1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:17:44 +00:00

Everywhere: Make ByteBuffer::{create_*,copy}() OOM-safe

This commit is contained in:
Ali Mohammad Pur 2021-09-06 03:29:52 +04:30 committed by Andreas Kling
parent 3a9f00c59b
commit 97e97bccab
105 changed files with 629 additions and 290 deletions

View file

@ -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() };

View file

@ -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();

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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));

View file

@ -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