summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibTLS
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2021-09-06 03:29:52 +0430
committerAndreas Kling <kling@serenityos.org>2021-09-06 01:53:26 +0200
commit97e97bccab085823d1365cb54142fd8c41dbcd8c (patch)
tree9008687dbcdfb6f36f6dc6372aa382b15b9d36c8 /Userland/Libraries/LibTLS
parent3a9f00c59bad7735970c72cb940d08161fda09b0 (diff)
downloadserenity-97e97bccab085823d1365cb54142fd8c41dbcd8c.zip
Everywhere: Make ByteBuffer::{create_*,copy}() OOM-safe
Diffstat (limited to 'Userland/Libraries/LibTLS')
-rw-r--r--Userland/Libraries/LibTLS/Handshake.cpp2
-rw-r--r--Userland/Libraries/LibTLS/HandshakeClient.cpp21
-rw-r--r--Userland/Libraries/LibTLS/HandshakeServer.cpp21
-rw-r--r--Userland/Libraries/LibTLS/Record.cpp54
-rw-r--r--Userland/Libraries/LibTLS/Socket.cpp17
-rw-r--r--Userland/Libraries/LibTLS/TLSPacketBuilder.h3
-rw-r--r--Userland/Libraries/LibTLS/TLSv12.cpp4
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