diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2021-09-06 03:29:52 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-09-06 01:53:26 +0200 |
commit | 97e97bccab085823d1365cb54142fd8c41dbcd8c (patch) | |
tree | 9008687dbcdfb6f36f6dc6372aa382b15b9d36c8 /Userland/Libraries/LibTLS | |
parent | 3a9f00c59bad7735970c72cb940d08161fda09b0 (diff) | |
download | serenity-97e97bccab085823d1365cb54142fd8c41dbcd8c.zip |
Everywhere: Make ByteBuffer::{create_*,copy}() OOM-safe
Diffstat (limited to 'Userland/Libraries/LibTLS')
-rw-r--r-- | Userland/Libraries/LibTLS/Handshake.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibTLS/HandshakeClient.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibTLS/HandshakeServer.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibTLS/Record.cpp | 54 | ||||
-rw-r--r-- | Userland/Libraries/LibTLS/Socket.cpp | 17 | ||||
-rw-r--r-- | Userland/Libraries/LibTLS/TLSPacketBuilder.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibTLS/TLSv12.cpp | 4 |
7 files changed, 98 insertions, 24 deletions
diff --git a/Userland/Libraries/LibTLS/Handshake.cpp b/Userland/Libraries/LibTLS/Handshake.cpp index 7f6361f595..df45a157ed 100644 --- a/Userland/Libraries/LibTLS/Handshake.cpp +++ b/Userland/Libraries/LibTLS/Handshake.cpp @@ -151,7 +151,7 @@ ByteBuffer TLSv12::build_handshake_finished() u8 out[verify_data_length]; auto outbuffer = Bytes { out, verify_data_length }; - auto dummy = ByteBuffer::create_zeroed(0); + ByteBuffer dummy; auto digest = m_context.handshake_hash.digest(); auto hashbuf = ReadonlyBytes { digest.immutable_data(), m_context.handshake_hash.digest_size() }; diff --git a/Userland/Libraries/LibTLS/HandshakeClient.cpp b/Userland/Libraries/LibTLS/HandshakeClient.cpp index f88f52e873..462a4a72fa 100644 --- a/Userland/Libraries/LibTLS/HandshakeClient.cpp +++ b/Userland/Libraries/LibTLS/HandshakeClient.cpp @@ -192,7 +192,12 @@ void TLSv12::build_rsa_pre_master_secret(PacketBuilder& builder) *(u16*)random_bytes = AK::convert_between_host_and_network_endian((u16)Version::V12); } - m_context.premaster_key = ByteBuffer::copy(random_bytes, bytes); + auto premaster_key_result = ByteBuffer::copy(random_bytes, bytes); + if (!premaster_key_result.has_value()) { + dbgln("RSA premaster key generation failed, not enough memory"); + return; + } + m_context.premaster_key = premaster_key_result.release_value(); const auto& certificate_option = verify_chain_and_get_matching_certificate(m_context.extensions.SNI); // if the SNI is empty, we'll make a special case and match *a* leaf certificate. if (!certificate_option.has_value()) { @@ -239,11 +244,21 @@ void TLSv12::build_dhe_rsa_pre_master_secret(PacketBuilder& builder) auto dh_random = Crypto::NumberTheory::random_number(0, dh_p); auto dh_Yc = Crypto::NumberTheory::ModularPower(dh_g, dh_random, dh_p); - auto dh_Yc_bytes = ByteBuffer::create_uninitialized(dh_key_size); + auto dh_Yc_bytes_result = ByteBuffer::create_uninitialized(dh_key_size); + if (!dh_Yc_bytes_result.has_value()) { + dbgln("Failed to build DHE_RSA premaster secret: not enough memory"); + return; + } + auto dh_Yc_bytes = dh_Yc_bytes_result.release_value(); dh_Yc.export_data(dh_Yc_bytes); auto premaster_key = Crypto::NumberTheory::ModularPower(dh_Ys, dh_random, dh_p); - m_context.premaster_key = ByteBuffer::create_uninitialized(dh_key_size); + auto premaster_key_result = ByteBuffer::create_uninitialized(dh_key_size); + if (!premaster_key_result.has_value()) { + dbgln("Failed to build DHE_RSA premaster secret: not enough memory"); + return; + } + m_context.premaster_key = premaster_key_result.release_value(); premaster_key.export_data(m_context.premaster_key, true); dh.p.clear(); diff --git a/Userland/Libraries/LibTLS/HandshakeServer.cpp b/Userland/Libraries/LibTLS/HandshakeServer.cpp index c3c3e3672a..def2a9f5c2 100644 --- a/Userland/Libraries/LibTLS/HandshakeServer.cpp +++ b/Userland/Libraries/LibTLS/HandshakeServer.cpp @@ -240,15 +240,30 @@ ssize_t TLSv12::handle_dhe_rsa_server_key_exchange(ReadonlyBytes buffer) { auto dh_p_length = AK::convert_between_host_and_network_endian(ByteReader::load16(buffer.offset_pointer(3))); auto dh_p = buffer.slice(5, dh_p_length); - m_context.server_diffie_hellman_params.p = ByteBuffer::copy(dh_p.data(), dh_p.size()); + auto p_result = ByteBuffer::copy(dh_p); + if (!p_result.has_value()) { + dbgln("dhe_rsa_server_key_exchange failed: Not enough memory"); + return 0; + } + m_context.server_diffie_hellman_params.p = p_result.release_value(); auto dh_g_length = AK::convert_between_host_and_network_endian(ByteReader::load16(buffer.offset_pointer(5 + dh_p_length))); auto dh_g = buffer.slice(7 + dh_p_length, dh_g_length); - m_context.server_diffie_hellman_params.g = ByteBuffer::copy(dh_g.data(), dh_g.size()); + auto g_result = ByteBuffer::copy(dh_g); + if (!g_result.has_value()) { + dbgln("dhe_rsa_server_key_exchange failed: Not enough memory"); + return 0; + } + m_context.server_diffie_hellman_params.g = g_result.release_value(); auto dh_Ys_length = AK::convert_between_host_and_network_endian(ByteReader::load16(buffer.offset_pointer(7 + dh_p_length + dh_g_length))); auto dh_Ys = buffer.slice(9 + dh_p_length + dh_g_length, dh_Ys_length); - m_context.server_diffie_hellman_params.Ys = ByteBuffer::copy(dh_Ys.data(), dh_Ys.size()); + auto Ys_result = ByteBuffer::copy(dh_Ys); + if (!Ys_result.has_value()) { + dbgln("dhe_rsa_server_key_exchange failed: Not enough memory"); + return 0; + } + m_context.server_diffie_hellman_params.Ys = Ys_result.release_value(); if constexpr (TLS_DEBUG) { dbgln("dh_p: {:hex-dump}", dh_p); diff --git a/Userland/Libraries/LibTLS/Record.cpp b/Userland/Libraries/LibTLS/Record.cpp index 53bb06b531..dc541fa238 100644 --- a/Userland/Libraries/LibTLS/Record.cpp +++ b/Userland/Libraries/LibTLS/Record.cpp @@ -97,7 +97,12 @@ void TLSv12::update_packet(ByteBuffer& packet) if (m_context.crypto.created == 1) { // `buffer' will continue to be encrypted - auto buffer = ByteBuffer::create_uninitialized(length); + auto buffer_result = ByteBuffer::create_uninitialized(length); + if (!buffer_result.has_value()) { + dbgln("LibTLS: Failed to allocate enough memory"); + VERIFY_NOT_REACHED(); + } + auto buffer = buffer_result.release_value(); size_t buffer_position = 0; auto iv_size = iv_length(); @@ -112,7 +117,12 @@ void TLSv12::update_packet(ByteBuffer& packet) [&](Crypto::Cipher::AESCipher::GCMMode& gcm) { VERIFY(is_aead()); // We need enough space for a header, the data, a tag, and the IV - ct = ByteBuffer::create_uninitialized(length + header_size + iv_size + 16); + auto ct_buffer_result = ByteBuffer::create_uninitialized(length + header_size + iv_size + 16); + if (!ct_buffer_result.has_value()) { + dbgln("LibTLS: Failed to allocate enough memory for the ciphertext"); + VERIFY_NOT_REACHED(); + } + ct = ct_buffer_result.release_value(); // copy the header over ct.overwrite(0, packet.data(), header_size - 2); @@ -161,7 +171,12 @@ void TLSv12::update_packet(ByteBuffer& packet) [&](Crypto::Cipher::AESCipher::CBCMode& cbc) { VERIFY(!is_aead()); // We need enough space for a header, iv_length bytes of IV and whatever the packet contains - ct = ByteBuffer::create_uninitialized(length + header_size + iv_size); + auto ct_buffer_result = ByteBuffer::create_uninitialized(length + header_size + iv_size); + if (!ct_buffer_result.has_value()) { + dbgln("LibTLS: Failed to allocate enough memory for the ciphertext"); + VERIFY_NOT_REACHED(); + } + ct = ct_buffer_result.release_value(); // copy the header over ct.overwrite(0, packet.data(), header_size - 2); @@ -179,7 +194,12 @@ void TLSv12::update_packet(ByteBuffer& packet) VERIFY(buffer_position == buffer.size()); - auto iv = ByteBuffer::create_uninitialized(iv_size); + auto iv_buffer_result = ByteBuffer::create_uninitialized(iv_size); + if (!iv_buffer_result.has_value()) { + dbgln("LibTLS: Failed to allocate memory for IV"); + VERIFY_NOT_REACHED(); + } + auto iv = iv_buffer_result.release_value(); fill_with_random(iv.data(), iv.size()); // write it into the ciphertext portion of the message @@ -266,14 +286,18 @@ ByteBuffer TLSv12::hmac_message(const ReadonlyBytes& buf, const Optional<Readonl hmac.update(buf2.value()); } auto digest = hmac.digest(); - auto mac = ByteBuffer::copy(digest.immutable_data(), digest.data_length()); + auto mac_result = ByteBuffer::copy(digest.immutable_data(), digest.data_length()); + if (!mac_result.has_value()) { + dbgln("Failed to calculate message HMAC: Not enough memory"); + return {}; + } if constexpr (TLS_DEBUG) { dbgln("HMAC of the block for sequence number {}", sequence_number); - print_buffer(mac); + print_buffer(*mac_result); } - return mac; + return mac_result.release_value(); } ssize_t TLSv12::handle_message(ReadonlyBytes buffer) @@ -336,7 +360,13 @@ ssize_t TLSv12::handle_message(ReadonlyBytes buffer) auto packet_length = length - iv_length() - 16; auto payload = plain; - decrypted = ByteBuffer::create_uninitialized(packet_length); + auto decrypted_result = ByteBuffer::create_uninitialized(packet_length); + if (!decrypted_result.has_value()) { + dbgln("Failed to allocate memory for the packet"); + return_value = Error::DecryptionFailed; + return; + } + decrypted = decrypted_result.release_value(); // AEAD AAD (13) // Seq. no (8) @@ -394,7 +424,13 @@ ssize_t TLSv12::handle_message(ReadonlyBytes buffer) VERIFY(!is_aead()); auto iv_size = iv_length(); - decrypted = cbc.create_aligned_buffer(length - iv_size); + auto decrypted_result = cbc.create_aligned_buffer(length - iv_size); + if (!decrypted_result.has_value()) { + dbgln("Failed to allocate memory for the packet"); + return_value = Error::DecryptionFailed; + return; + } + decrypted = decrypted_result.release_value(); auto iv = buffer.slice(header_size, iv_size); Bytes decrypted_span = decrypted; diff --git a/Userland/Libraries/LibTLS/Socket.cpp b/Userland/Libraries/LibTLS/Socket.cpp index 536b52bf7e..7f3528ecad 100644 --- a/Userland/Libraries/LibTLS/Socket.cpp +++ b/Userland/Libraries/LibTLS/Socket.cpp @@ -15,9 +15,8 @@ namespace TLS { Optional<ByteBuffer> TLSv12::read() { if (m_context.application_buffer.size()) { - auto buf = m_context.application_buffer.slice(0, m_context.application_buffer.size()); - m_context.application_buffer.clear(); - return buf; + auto buf = move(m_context.application_buffer); + return { move(buf) }; } return {}; } @@ -47,10 +46,18 @@ String TLSv12::read_line(size_t max_size) if (offset > max_size) return {}; - auto buffer = ByteBuffer::copy(start, offset); + auto buffer_result = ByteBuffer::copy(start, offset); + if (!buffer_result.has_value()) { + dbgln("TLS: Failed to read line, not enough memory"); + dbgln("max_size < offset: {} < {} (size = {})", max_size, offset, m_context.application_buffer.size()); + dbgln("-> {:32hex-dump}", ReadonlyBytes { start, offset }); + return {}; + } + + String line { bit_cast<char const*>(start), offset, Chomp }; m_context.application_buffer = m_context.application_buffer.slice(offset + 1, m_context.application_buffer.size() - offset - 1); - return String::copy(buffer, Chomp); + return line; } bool TLSv12::write(ReadonlyBytes buffer) diff --git a/Userland/Libraries/LibTLS/TLSPacketBuilder.h b/Userland/Libraries/LibTLS/TLSPacketBuilder.h index 955caa0492..d2d3bffa32 100644 --- a/Userland/Libraries/LibTLS/TLSPacketBuilder.h +++ b/Userland/Libraries/LibTLS/TLSPacketBuilder.h @@ -36,7 +36,8 @@ public: PacketBuilder(MessageType type, Version version, size_t size_hint = 0xfdf) { - m_packet_data = ByteBuffer::create_uninitialized(size_hint + 16); + // FIXME: Handle possible OOM situation. + m_packet_data = ByteBuffer::create_uninitialized(size_hint + 16).release_value(); m_current_length = 5; m_packet_data[0] = (u8)type; ByteReader::store(m_packet_data.offset_pointer(1), AK::convert_between_host_and_network_endian((u16)version)); diff --git a/Userland/Libraries/LibTLS/TLSv12.cpp b/Userland/Libraries/LibTLS/TLSv12.cpp index 8c5273e557..8f31933d9c 100644 --- a/Userland/Libraries/LibTLS/TLSv12.cpp +++ b/Userland/Libraries/LibTLS/TLSv12.cpp @@ -35,7 +35,7 @@ void TLSv12::consume(ReadonlyBytes record) dbgln_if(TLS_DEBUG, "Consuming {} bytes", record.size()); - if (!m_context.message_buffer.try_append(record.data(), record.size())) { + if (!m_context.message_buffer.try_append(record)) { dbgln("Not enough space in message buffer, dropping the record"); return; } @@ -306,7 +306,7 @@ TLSv12::TLSv12(Core::Object* parent, Options options) { m_context.options = move(options); m_context.is_server = false; - m_context.tls_buffer = ByteBuffer::create_uninitialized(0); + m_context.tls_buffer = {}; #ifdef SOCK_NONBLOCK int fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); #else |