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:
parent
3a9f00c59b
commit
97e97bccab
105 changed files with 629 additions and 290 deletions
|
@ -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() };
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue