diff --git a/Userland/Libraries/LibTLS/HandshakeClient.cpp b/Userland/Libraries/LibTLS/HandshakeClient.cpp index cc4e0271b0..d1a96908b8 100644 --- a/Userland/Libraries/LibTLS/HandshakeClient.cpp +++ b/Userland/Libraries/LibTLS/HandshakeClient.cpp @@ -179,6 +179,7 @@ void TLSv12::build_rsa_pre_master_secret(PacketBuilder& builder) } m_context.premaster_key = premaster_key_result.release_value(); + // RFC5246 section 7.4.2: The sender's certificate MUST come first in the list. auto& certificate = m_context.certificates.first(); if constexpr (TLS_DEBUG) { dbgln("PreMaster secret"); diff --git a/Userland/Libraries/LibTLS/HandshakeServer.cpp b/Userland/Libraries/LibTLS/HandshakeServer.cpp index 92ca783706..8696ece782 100644 --- a/Userland/Libraries/LibTLS/HandshakeServer.cpp +++ b/Userland/Libraries/LibTLS/HandshakeServer.cpp @@ -359,6 +359,7 @@ ssize_t TLSv12::verify_rsa_server_key_exchange(ReadonlyBytes server_key_info_buf dbgln("verify_rsa_server_key_exchange failed: Attempting to verify signature without certificates"); return (i8)Error::NotSafe; } + // RFC5246 section 7.4.2: The sender's certificate MUST come first in the list. auto certificate_public_key = m_context.certificates.first().public_key; Crypto::PK::RSAPrivateKey dummy_private_key; auto rsa = Crypto::PK::RSA(certificate_public_key, dummy_private_key); diff --git a/Userland/Libraries/LibTLS/TLSv12.cpp b/Userland/Libraries/LibTLS/TLSv12.cpp index ab95df9e1c..1cff1fe03f 100644 --- a/Userland/Libraries/LibTLS/TLSv12.cpp +++ b/Userland/Libraries/LibTLS/TLSv12.cpp @@ -233,6 +233,12 @@ bool Context::verify_chain(StringView host) const return false; } + // RFC5246 section 7.4.2: The sender's certificate MUST come first in the list. Each following certificate + // MUST directly certify the one preceding it. Because certificate validation requires that root keys be + // distributed independently, the self-signed certificate that specifies the root certificate authority MAY be + // omitted from the chain, under the assumption that the remote end must already possess it in order to validate + // it in any case. + if (!host.is_empty()) { auto first_certificate = local_chain->first(); auto subject_matches = certificate_subject_matches_host(first_certificate, host);