From e785172290f90aaa9821568c22e743cc8109b5b2 Mon Sep 17 00:00:00 2001 From: Michiel Visser Date: Sat, 25 Nov 2023 00:27:45 +0100 Subject: [PATCH] LibTLS: Implement the `extended_master_secret` TLS extension --- Userland/Libraries/LibTLS/Handshake.cpp | 10 ++++++++ Userland/Libraries/LibTLS/HandshakeClient.cpp | 25 ++++++++++++++----- Userland/Libraries/LibTLS/HandshakeServer.cpp | 3 +++ Userland/Libraries/LibTLS/TLSv12.h | 2 ++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/Userland/Libraries/LibTLS/Handshake.cpp b/Userland/Libraries/LibTLS/Handshake.cpp index 20b70f6e79..c9cea5ba5f 100644 --- a/Userland/Libraries/LibTLS/Handshake.cpp +++ b/Userland/Libraries/LibTLS/Handshake.cpp @@ -75,6 +75,7 @@ ByteBuffer TLSv12::build_hello() auto elliptic_curves_length = 2 * m_context.options.elliptic_curves.size(); auto supported_ec_point_formats_length = m_context.options.supported_ec_point_formats.size(); bool supports_elliptic_curves = elliptic_curves_length && supported_ec_point_formats_length; + bool enable_extended_master_secret = m_context.options.enable_extended_master_secret; // signature_algorithms: 2b extension ID, 2b extension length, 2b vector length, 2xN signatures and hashes extension_length += 2 + 2 + 2 + 2 * m_context.options.supported_signature_algorithms.size(); @@ -86,6 +87,9 @@ ByteBuffer TLSv12::build_hello() if (supports_elliptic_curves) extension_length += 6 + elliptic_curves_length + 5 + supported_ec_point_formats_length; + if (enable_extended_master_secret) + extension_length += 4; + builder.append((u16)extension_length); if (sni_length) { @@ -130,6 +134,12 @@ ByteBuffer TLSv12::build_hello() builder.append((u8)format); } + if (enable_extended_master_secret) { + // extended_master_secret extension + builder.append((u16)ExtensionType::EXTENDED_MASTER_SECRET); + builder.append((u16)0); + } + if (alpn_length) { // TODO VERIFY_NOT_REACHED(); diff --git a/Userland/Libraries/LibTLS/HandshakeClient.cpp b/Userland/Libraries/LibTLS/HandshakeClient.cpp index bd6133b14a..1092aa5d53 100644 --- a/Userland/Libraries/LibTLS/HandshakeClient.cpp +++ b/Userland/Libraries/LibTLS/HandshakeClient.cpp @@ -126,12 +126,25 @@ bool TLSv12::compute_master_secret_from_pre_master_secret(size_t length) return false; } - pseudorandom_function( - m_context.master_key, - m_context.premaster_key, - (u8 const*)"master secret", 13, - ReadonlyBytes { m_context.local_random, sizeof(m_context.local_random) }, - ReadonlyBytes { m_context.remote_random, sizeof(m_context.remote_random) }); + if (m_context.extensions.extended_master_secret) { + Crypto::Hash::Manager handshake_hash_copy = m_context.handshake_hash.copy(); + auto digest = handshake_hash_copy.digest(); + auto session_hash = ReadonlyBytes { digest.immutable_data(), handshake_hash_copy.digest_size() }; + + pseudorandom_function( + m_context.master_key, + m_context.premaster_key, + (u8 const*)"extended master secret", 22, + session_hash, + {}); + } else { + pseudorandom_function( + m_context.master_key, + m_context.premaster_key, + (u8 const*)"master secret", 13, + ReadonlyBytes { m_context.local_random, sizeof(m_context.local_random) }, + ReadonlyBytes { m_context.remote_random, sizeof(m_context.remote_random) }); + } m_context.premaster_key.clear(); if constexpr (TLS_DEBUG) { diff --git a/Userland/Libraries/LibTLS/HandshakeServer.cpp b/Userland/Libraries/LibTLS/HandshakeServer.cpp index bef53c92d2..9ba4acc4e7 100644 --- a/Userland/Libraries/LibTLS/HandshakeServer.cpp +++ b/Userland/Libraries/LibTLS/HandshakeServer.cpp @@ -189,6 +189,9 @@ ssize_t TLSv12::handle_server_hello(ReadonlyBytes buffer, WritePacketStage& writ // uncompressed points. Therefore, this extension can be safely ignored as it should always inform us // that the server supports uncompressed points. res += extension_length; + } else if (extension_type == ExtensionType::EXTENDED_MASTER_SECRET) { + m_context.extensions.extended_master_secret = true; + res += extension_length; } else { dbgln("Encountered unknown extension {} with length {}", enum_to_string(extension_type), extension_length); res += extension_length; diff --git a/Userland/Libraries/LibTLS/TLSv12.h b/Userland/Libraries/LibTLS/TLSv12.h index ecc81c2ecb..a869ea4c55 100644 --- a/Userland/Libraries/LibTLS/TLSv12.h +++ b/Userland/Libraries/LibTLS/TLSv12.h @@ -181,6 +181,7 @@ struct Options { OPTION_WITH_DEFAULTS(Function, alert_handler, [](auto) {}) OPTION_WITH_DEFAULTS(Function, finish_callback, [] {}) OPTION_WITH_DEFAULTS(Function()>, certificate_provider, [] { return Vector {}; }) + OPTION_WITH_DEFAULTS(bool, enable_extended_master_secret, true) #undef OPTION_WITH_DEFAULTS }; @@ -232,6 +233,7 @@ struct Context { struct { // Server Name Indicator DeprecatedString SNI; // I hate your existence + bool extended_master_secret { false }; } extensions; u8 request_client_certificate { 0 };