瀏覽代碼

LibTLS: Implement the `extended_master_secret` TLS extension

Michiel Visser 1 年之前
父節點
當前提交
e785172290

+ 10 - 0
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();

+ 19 - 6
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) {

+ 3 - 0
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;

+ 2 - 0
Userland/Libraries/LibTLS/TLSv12.h

@@ -181,6 +181,7 @@ struct Options {
     OPTION_WITH_DEFAULTS(Function<void(AlertDescription)>, alert_handler, [](auto) {})
     OPTION_WITH_DEFAULTS(Function<void()>, finish_callback, [] {})
     OPTION_WITH_DEFAULTS(Function<Vector<Certificate>()>, certificate_provider, [] { return Vector<Certificate> {}; })
+    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 };