diff options
Diffstat (limited to 'security/nss/gtests/ssl_gtest')
39 files changed, 1729 insertions, 325 deletions
diff --git a/security/nss/gtests/ssl_gtest/manifest.mn b/security/nss/gtests/ssl_gtest/manifest.mn index 8547e56d1..7f4ee7953 100644 --- a/security/nss/gtests/ssl_gtest/manifest.mn +++ b/security/nss/gtests/ssl_gtest/manifest.mn @@ -52,6 +52,7 @@ CPPSRCS = \ tls_hkdf_unittest.cc \ tls_filter.cc \ tls_protect.cc \ + tls_esni_unittest.cc \ $(NULL) INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \ diff --git a/security/nss/gtests/ssl_gtest/rsa8193.h b/security/nss/gtests/ssl_gtest/rsa8193.h index 626516389..1ac8503bc 100644 --- a/security/nss/gtests/ssl_gtest/rsa8193.h +++ b/security/nss/gtests/ssl_gtest/rsa8193.h @@ -206,4 +206,4 @@ static const uint8_t rsa8193[] = { 0x13, 0x34, 0x9d, 0x34, 0xb8, 0xef, 0x13, 0x3a, 0x20, 0xf5, 0x74, 0x02, 0x70, 0x3b, 0x41, 0x60, 0x1f, 0x5e, 0x76, 0x0a, 0xb1, 0x17, 0xd5, 0xcf, 0x79, 0xef, 0xf7, 0xab, 0xe7, 0xd6, 0x0f, 0xad, 0x85, 0x2c, 0x52, 0x67, - 0xb5, 0xa0, 0x4a, 0xfd, 0xaf};
\ No newline at end of file + 0xb5, 0xa0, 0x4a, 0xfd, 0xaf}; diff --git a/security/nss/gtests/ssl_gtest/selfencrypt_unittest.cc b/security/nss/gtests/ssl_gtest/selfencrypt_unittest.cc index 4bae9dec9..0c62c4cac 100644 --- a/security/nss/gtests/ssl_gtest/selfencrypt_unittest.cc +++ b/security/nss/gtests/ssl_gtest/selfencrypt_unittest.cc @@ -19,7 +19,7 @@ extern "C" { #include "databuffer.h" #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" namespace nss_test { diff --git a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc index 28fdc6631..07eadfbd1 100644 --- a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc @@ -16,7 +16,7 @@ extern "C" { } #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" diff --git a/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc index 6be3b61f8..c3455d130 100644 --- a/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc @@ -34,7 +34,7 @@ const static uint8_t kCannedTls13ClientHello[] = { 0xc2, 0xb3, 0xc6, 0x80, 0x72, 0x86, 0x08, 0x86, 0x8f, 0x52, 0xc5, 0xcb, 0xbf, 0x2a, 0xb5, 0x59, 0x64, 0xcc, 0x0c, 0x49, 0x95, 0x36, 0xe4, 0xd9, 0x2f, 0xd4, 0x24, 0x66, 0x71, 0x6f, 0x5d, 0x70, 0xe2, 0xa0, 0xea, 0x26, - 0x00, 0x2b, 0x00, 0x03, 0x02, 0x7f, kD13, 0x00, 0x0d, 0x00, 0x20, 0x00, + 0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x1e, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02, 0x03, 0x08, 0x04, 0x08, 0x05, 0x08, 0x06, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x04, 0x02, 0x05, 0x02, 0x06, 0x02, 0x02, 0x02}; @@ -64,8 +64,8 @@ TEST_P(TlsAgentTestClient13, CannedHello) { auto sh = MakeCannedTls13ServerHello(); MakeHandshakeMessage(kTlsHandshakeServerHello, sh.data(), sh.len(), &server_hello); - MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, - server_hello.data(), server_hello.len(), &buffer); + MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello.data(), + server_hello.len(), &buffer); ProcessMessage(buffer, TlsAgent::STATE_CONNECTING); } @@ -79,8 +79,8 @@ TEST_P(TlsAgentTestClient13, EncryptedExtensionsInClear) { &encrypted_extensions, 1); server_hello.Append(encrypted_extensions); DataBuffer buffer; - MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, - server_hello.data(), server_hello.len(), &buffer); + MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello.data(), + server_hello.len(), &buffer); EnsureInit(); ExpectAlert(kTlsAlertUnexpectedMessage); ProcessMessage(buffer, TlsAgent::STATE_ERROR, @@ -97,11 +97,11 @@ TEST_F(TlsAgentStreamTestClient, EncryptedExtensionsInClearTwoPieces) { &encrypted_extensions, 1); server_hello.Append(encrypted_extensions); DataBuffer buffer; - MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, - server_hello.data(), kFirstFragmentSize, &buffer); + MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello.data(), + kFirstFragmentSize, &buffer); DataBuffer buffer2; - MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, + MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello.data() + kFirstFragmentSize, server_hello.len() - kFirstFragmentSize, &buffer2); @@ -129,11 +129,11 @@ TEST_F(TlsAgentDgramTestClient, EncryptedExtensionsInClearTwoPieces) { &encrypted_extensions, 1); server_hello_frag2.Append(encrypted_extensions); DataBuffer buffer; - MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, + MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello_frag1.data(), server_hello_frag1.len(), &buffer); DataBuffer buffer2; - MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, + MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello_frag2.data(), server_hello_frag2.len(), &buffer2, 1); EnsureInit(); @@ -150,7 +150,7 @@ TEST_F(TlsAgentDgramTestClient, AckWithBogusLengthField) { // Length doesn't match const uint8_t ackBuf[] = {0x00, 0x08, 0x00}; DataBuffer record; - MakeRecord(variant_, kTlsAckType, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf, + MakeRecord(variant_, ssl_ct_ack, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf, sizeof(ackBuf), &record, 0); agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3, SSL_LIBRARY_VERSION_TLS_1_3); @@ -164,7 +164,7 @@ TEST_F(TlsAgentDgramTestClient, AckWithNonEvenLength) { // Length isn't a multiple of 8 const uint8_t ackBuf[] = {0x00, 0x01, 0x00}; DataBuffer record; - MakeRecord(variant_, kTlsAckType, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf, + MakeRecord(variant_, ssl_ct_ack, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf, sizeof(ackBuf), &record, 0); agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3, SSL_LIBRARY_VERSION_TLS_1_3); @@ -196,7 +196,7 @@ TEST_F(TlsAgentStreamTestClient, Set0RttOptionThenRead) { agent_->StartConnect(); agent_->Set0RttEnabled(true); DataBuffer buffer; - MakeRecord(kTlsApplicationDataType, SSL_LIBRARY_VERSION_TLS_1_3, + MakeRecord(ssl_ct_application_data, SSL_LIBRARY_VERSION_TLS_1_3, reinterpret_cast<const uint8_t *>(k0RttData), strlen(k0RttData), &buffer); ExpectAlert(kTlsAlertUnexpectedMessage); @@ -214,10 +214,10 @@ TEST_F(TlsAgentStreamTestServer, Set0RttOptionClientHelloThenRead) { agent_->StartConnect(); agent_->Set0RttEnabled(true); DataBuffer buffer; - MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, + MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, kCannedTls13ClientHello, sizeof(kCannedTls13ClientHello), &buffer); ProcessMessage(buffer, TlsAgent::STATE_CONNECTING); - MakeRecord(kTlsApplicationDataType, SSL_LIBRARY_VERSION_TLS_1_3, + MakeRecord(ssl_ct_application_data, SSL_LIBRARY_VERSION_TLS_1_3, reinterpret_cast<const uint8_t *>(k0RttData), strlen(k0RttData), &buffer); ExpectAlert(kTlsAlertBadRecordMac); diff --git a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc index e2a30e6bc..3a52ac20c 100644 --- a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc @@ -15,7 +15,7 @@ extern "C" { } #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" @@ -37,6 +37,50 @@ TEST_P(TlsConnectGeneric, ServerAuthRsaChain) { EXPECT_EQ(2UL, chain_length); } +TEST_P(TlsConnectTls12Plus, ServerAuthRsaPss) { + static const SSLSignatureScheme kSignatureSchemePss[] = { + ssl_sig_rsa_pss_pss_sha256}; + + Reset(TlsAgent::kServerRsaPss); + client_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); + server_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); + Connect(); + CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_pss, + ssl_sig_rsa_pss_pss_sha256); +} + +// PSS doesn't work with TLS 1.0 or 1.1 because we can't signal it. +TEST_P(TlsConnectPre12, ServerAuthRsaPssFails) { + static const SSLSignatureScheme kSignatureSchemePss[] = { + ssl_sig_rsa_pss_pss_sha256}; + + Reset(TlsAgent::kServerRsaPss); + client_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); + server_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); + ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); + server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); + client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); +} + +// Check that a PSS certificate with no parameters works. +TEST_P(TlsConnectTls12Plus, ServerAuthRsaPssNoParameters) { + static const SSLSignatureScheme kSignatureSchemePss[] = { + ssl_sig_rsa_pss_pss_sha256}; + + Reset("rsa_pss_noparam"); + client_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); + server_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); + Connect(); + CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_pss, + ssl_sig_rsa_pss_pss_sha256); +} + TEST_P(TlsConnectGeneric, ServerAuthRsaPssChain) { Reset("rsa_pss_chain"); Connect(); @@ -55,6 +99,76 @@ TEST_P(TlsConnectGeneric, ServerAuthRsaCARsaPssChain) { EXPECT_EQ(2UL, chain_length); } +TEST_P(TlsConnectGeneric, ServerAuthRejected) { + EnsureTlsSetup(); + client_->SetAuthCertificateCallback( + [](TlsAgent*, PRBool, PRBool) -> SECStatus { return SECFailure; }); + ConnectExpectAlert(client_, kTlsAlertBadCertificate); + client_->CheckErrorCode(SSL_ERROR_BAD_CERTIFICATE); + server_->CheckErrorCode(SSL_ERROR_BAD_CERT_ALERT); + EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state()); +} + +struct AuthCompleteArgs : public PollTarget { + AuthCompleteArgs(const std::shared_ptr<TlsAgent>& a, PRErrorCode c) + : agent(a), code(c) {} + + std::shared_ptr<TlsAgent> agent; + PRErrorCode code; +}; + +static void CallAuthComplete(PollTarget* target, Event event) { + EXPECT_EQ(TIMER_EVENT, event); + auto args = reinterpret_cast<AuthCompleteArgs*>(target); + std::cerr << args->agent->role_str() << ": call SSL_AuthCertificateComplete " + << (args->code ? PR_ErrorToName(args->code) : "no error") + << std::endl; + EXPECT_EQ(SECSuccess, + SSL_AuthCertificateComplete(args->agent->ssl_fd(), args->code)); + args->agent->Handshake(); // Make the TlsAgent aware of the error. + delete args; +} + +// Install an AuthCertificateCallback that blocks when called. Then +// SSL_AuthCertificateComplete is called on a very short timer. This allows any +// processing that might follow the callback to complete. +static void SetDeferredAuthCertificateCallback(std::shared_ptr<TlsAgent> agent, + PRErrorCode code) { + auto args = new AuthCompleteArgs(agent, code); + agent->SetAuthCertificateCallback( + [args](TlsAgent*, PRBool, PRBool) -> SECStatus { + // This can't be 0 or we race the message from the client to the server, + // and tests assume that we lose that race. + std::shared_ptr<Poller::Timer> timer_handle; + Poller::Instance()->SetTimer(1U, args, CallAuthComplete, &timer_handle); + return SECWouldBlock; + }); +} + +TEST_P(TlsConnectTls13, ServerAuthRejectAsync) { + SetDeferredAuthCertificateCallback(client_, SEC_ERROR_REVOKED_CERTIFICATE); + ConnectExpectAlert(client_, kTlsAlertCertificateRevoked); + // We only detect the error here when we attempt to handshake, so all the + // client learns is that the handshake has already failed. + client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILED); + server_->CheckErrorCode(SSL_ERROR_REVOKED_CERT_ALERT); +} + +// In TLS 1.2 and earlier, this will result in the client sending its Finished +// before learning that the server certificate is bad. That means that the +// server will believe that the handshake is complete. +TEST_P(TlsConnectGenericPre13, ServerAuthRejectAsync) { + SetDeferredAuthCertificateCallback(client_, SEC_ERROR_EXPIRED_CERTIFICATE); + client_->ExpectSendAlert(kTlsAlertCertificateExpired); + server_->ExpectReceiveAlert(kTlsAlertCertificateExpired); + ConnectExpectFailOneSide(TlsAgent::CLIENT); + client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILED); + + // The server might not receive the alert that the client sends, which would + // cause the test to fail when it cleans up. Reset expectations. + server_->ExpectReceiveAlert(kTlsAlertCloseNotify, kTlsAlertWarning); +} + TEST_P(TlsConnectGeneric, ClientAuth) { client_->SetupClientAuth(); server_->RequestClientAuth(true); @@ -153,6 +267,81 @@ TEST_P(TlsConnectTls12, ClientAuthBigRsaCheckSigAlg) { 2048); } +// Replaces the signature scheme in a CertificateVerify message. +class TlsReplaceSignatureSchemeFilter : public TlsHandshakeFilter { + public: + TlsReplaceSignatureSchemeFilter(const std::shared_ptr<TlsAgent>& a, + SSLSignatureScheme scheme) + : TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}), + scheme_(scheme) { + EnableDecryption(); + } + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) { + *output = input; + output->Write(0, scheme_, 2); + return CHANGE; + } + + private: + SSLSignatureScheme scheme_; +}; + +// Check if CertificateVerify signed with rsa_pss_rsae_* is properly +// rejected when the certificate is RSA-PSS. +// +// This only works under TLS 1.2, because PSS doesn't work with TLS +// 1.0 or TLS 1.1 and the TLS 1.3 1-RTT handshake is partially +// successful at the client side. +TEST_P(TlsConnectTls12, ClientAuthInconsistentRsaeSignatureScheme) { + static const SSLSignatureScheme kSignatureSchemePss[] = { + ssl_sig_rsa_pss_pss_sha256, ssl_sig_rsa_pss_rsae_sha256}; + + Reset(TlsAgent::kServerRsa, "rsa_pss"); + client_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); + server_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); + client_->SetupClientAuth(); + server_->RequestClientAuth(true); + + EnsureTlsSetup(); + + MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(client_, + ssl_sig_rsa_pss_rsae_sha256); + + ConnectExpectAlert(server_, kTlsAlertIllegalParameter); +} + +// Check if CertificateVerify signed with rsa_pss_pss_* is properly +// rejected when the certificate is RSA. +// +// This only works under TLS 1.2, because PSS doesn't work with TLS +// 1.0 or TLS 1.1 and the TLS 1.3 1-RTT handshake is partially +// successful at the client side. +TEST_P(TlsConnectTls12, ClientAuthInconsistentPssSignatureScheme) { + static const SSLSignatureScheme kSignatureSchemePss[] = { + ssl_sig_rsa_pss_rsae_sha256, ssl_sig_rsa_pss_pss_sha256}; + + Reset(TlsAgent::kServerRsa, "rsa"); + client_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); + server_->SetSignatureSchemes(kSignatureSchemePss, + PR_ARRAY_SIZE(kSignatureSchemePss)); + client_->SetupClientAuth(); + server_->RequestClientAuth(true); + + EnsureTlsSetup(); + + MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(client_, + ssl_sig_rsa_pss_pss_sha256); + + ConnectExpectAlert(server_, kTlsAlertIllegalParameter); +} + class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter { public: TlsZeroCertificateRequestSigAlgsFilter(const std::shared_ptr<TlsAgent>& a) @@ -197,9 +386,9 @@ class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter { } }; -// Check that we fall back to SHA-1 when the server doesn't provide any +// Check that we send an alert when the server doesn't provide any // supported_signature_algorithms in the CertificateRequest message. -TEST_P(TlsConnectTls12, ClientAuthNoSigAlgsFallback) { +TEST_P(TlsConnectTls12, ClientAuthNoSigAlgs) { EnsureTlsSetup(); MakeTlsFilter<TlsZeroCertificateRequestSigAlgsFilter>(server_); auto capture_cert_verify = MakeTlsFilter<TlsHandshakeRecorder>( @@ -207,24 +396,19 @@ TEST_P(TlsConnectTls12, ClientAuthNoSigAlgsFallback) { client_->SetupClientAuth(); server_->RequestClientAuth(true); - ConnectExpectAlert(server_, kTlsAlertDecryptError); - - // We're expecting a bad signature here because we tampered with a handshake - // message (CertReq). Previously, without the SHA-1 fallback, we would've - // seen a malformed record alert. - server_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE); - client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); + ConnectExpectAlert(client_, kTlsAlertHandshakeFailure); - CheckSigScheme(capture_cert_verify, 0, server_, ssl_sig_rsa_pkcs1_sha1, 1024); + server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT); + client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); } -static const SSLSignatureScheme SignatureSchemeEcdsaSha384[] = { +static const SSLSignatureScheme kSignatureSchemeEcdsaSha384[] = { ssl_sig_ecdsa_secp384r1_sha384}; -static const SSLSignatureScheme SignatureSchemeEcdsaSha256[] = { +static const SSLSignatureScheme kSignatureSchemeEcdsaSha256[] = { ssl_sig_ecdsa_secp256r1_sha256}; -static const SSLSignatureScheme SignatureSchemeRsaSha384[] = { +static const SSLSignatureScheme kSignatureSchemeRsaSha384[] = { ssl_sig_rsa_pkcs1_sha384}; -static const SSLSignatureScheme SignatureSchemeRsaSha256[] = { +static const SSLSignatureScheme kSignatureSchemeRsaSha256[] = { ssl_sig_rsa_pkcs1_sha256}; static SSLNamedGroup NamedGroupForEcdsa384(uint16_t version) { @@ -241,10 +425,10 @@ static SSLNamedGroup NamedGroupForEcdsa384(uint16_t version) { // for TLS 1.1 and 1.0, where they should be ignored. TEST_P(TlsConnectGeneric, SignatureAlgorithmServerAuth) { Reset(TlsAgent::kServerEcdsa384); - client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384, - PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384)); - server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384, - PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384)); + client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); + server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); Connect(); CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa, ssl_sig_ecdsa_secp384r1_sha384); @@ -273,8 +457,8 @@ TEST_P(TlsConnectGeneric, SignatureAlgorithmClientOnly) { // Defaults on the client include the provided option. TEST_P(TlsConnectGeneric, SignatureAlgorithmServerOnly) { Reset(TlsAgent::kServerEcdsa384); - server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384, - PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384)); + server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); Connect(); CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa, ssl_sig_ecdsa_secp384r1_sha384); @@ -283,16 +467,16 @@ TEST_P(TlsConnectGeneric, SignatureAlgorithmServerOnly) { // In TLS 1.2, curve and hash aren't bound together. TEST_P(TlsConnectTls12, SignatureSchemeCurveMismatch) { Reset(TlsAgent::kServerEcdsa256); - client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384, - PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384)); + client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); Connect(); } // In TLS 1.3, curve and hash are coupled. TEST_P(TlsConnectTls13, SignatureSchemeCurveMismatch) { Reset(TlsAgent::kServerEcdsa256); - client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384, - PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384)); + client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); @@ -301,16 +485,16 @@ TEST_P(TlsConnectTls13, SignatureSchemeCurveMismatch) { // Configuring a P-256 cert with only SHA-384 signatures is OK in TLS 1.2. TEST_P(TlsConnectTls12, SignatureSchemeBadConfig) { Reset(TlsAgent::kServerEcdsa256); // P-256 cert can't be used. - server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384, - PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384)); + server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); Connect(); } // A P-256 certificate in TLS 1.3 needs a SHA-256 signature scheme. TEST_P(TlsConnectTls13, SignatureSchemeBadConfig) { Reset(TlsAgent::kServerEcdsa256); // P-256 cert can't be used. - server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384, - PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384)); + server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); @@ -319,10 +503,10 @@ TEST_P(TlsConnectTls13, SignatureSchemeBadConfig) { // Where there is no overlap on signature schemes, we still connect successfully // if we aren't going to use a signature. TEST_P(TlsConnectGenericPre13, SignatureAlgorithmNoOverlapStaticRsa) { - client_->SetSignatureSchemes(SignatureSchemeRsaSha384, - PR_ARRAY_SIZE(SignatureSchemeRsaSha384)); - server_->SetSignatureSchemes(SignatureSchemeRsaSha256, - PR_ARRAY_SIZE(SignatureSchemeRsaSha256)); + client_->SetSignatureSchemes(kSignatureSchemeRsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeRsaSha384)); + server_->SetSignatureSchemes(kSignatureSchemeRsaSha256, + PR_ARRAY_SIZE(kSignatureSchemeRsaSha256)); EnableOnlyStaticRsaCiphers(); Connect(); CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt); @@ -330,10 +514,10 @@ TEST_P(TlsConnectGenericPre13, SignatureAlgorithmNoOverlapStaticRsa) { TEST_P(TlsConnectTls12Plus, SignatureAlgorithmNoOverlapEcdsa) { Reset(TlsAgent::kServerEcdsa256); - client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384, - PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384)); - server_->SetSignatureSchemes(SignatureSchemeEcdsaSha256, - PR_ARRAY_SIZE(SignatureSchemeEcdsaSha256)); + client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); + server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha256, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha256)); ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); @@ -342,10 +526,10 @@ TEST_P(TlsConnectTls12Plus, SignatureAlgorithmNoOverlapEcdsa) { // Pre 1.2, a mismatch on signature algorithms shouldn't affect anything. TEST_P(TlsConnectPre12, SignatureAlgorithmNoOverlapEcdsa) { Reset(TlsAgent::kServerEcdsa256); - client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384, - PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384)); - server_->SetSignatureSchemes(SignatureSchemeEcdsaSha256, - PR_ARRAY_SIZE(SignatureSchemeEcdsaSha256)); + client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); + server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha256, + PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha256)); Connect(); } @@ -366,29 +550,6 @@ TEST_P(TlsConnectTls12, SignatureAlgorithmDrop) { server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); } -// Replaces the signature scheme in a TLS 1.3 CertificateVerify message. -class TlsReplaceSignatureSchemeFilter : public TlsHandshakeFilter { - public: - TlsReplaceSignatureSchemeFilter(const std::shared_ptr<TlsAgent>& a, - SSLSignatureScheme scheme) - : TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}), - scheme_(scheme) { - EnableDecryption(); - } - - protected: - virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, - const DataBuffer& input, - DataBuffer* output) { - *output = input; - output->Write(0, scheme_, 2); - return CHANGE; - } - - private: - SSLSignatureScheme scheme_; -}; - TEST_P(TlsConnectTls13, UnsupportedSignatureSchemeAlert) { EnsureTlsSetup(); MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(server_, ssl_sig_none); @@ -411,8 +572,8 @@ TEST_P(TlsConnectTls13, InconsistentSignatureSchemeAlert) { } TEST_P(TlsConnectTls12Plus, RequestClientAuthWithSha384) { - server_->SetSignatureSchemes(SignatureSchemeRsaSha384, - PR_ARRAY_SIZE(SignatureSchemeRsaSha384)); + server_->SetSignatureSchemes(kSignatureSchemeRsaSha384, + PR_ARRAY_SIZE(kSignatureSchemeRsaSha384)); server_->RequestClientAuth(false); Connect(); } @@ -438,7 +599,7 @@ class BeforeFinished : public TlsRecordFilter { switch (state_) { case BEFORE_CCS: // Awaken when we see the CCS. - if (header.content_type() == kTlsChangeCipherSpecType) { + if (header.content_type() == ssl_ct_change_cipher_spec) { before_ccs_(); // Write the CCS out as a separate write, so that we can make @@ -455,7 +616,7 @@ class BeforeFinished : public TlsRecordFilter { break; case AFTER_CCS: - EXPECT_EQ(kTlsHandshakeType, header.content_type()); + EXPECT_EQ(ssl_ct_handshake, header.content_type()); // This could check that data contains a Finished message, but it's // encrypted, so that's too much extra work. @@ -552,25 +713,11 @@ TEST_F(TlsConnectDatagram13, AuthCompleteBeforeFinished) { Connect(); } -static void TriggerAuthComplete(PollTarget* target, Event event) { - std::cerr << "client: call SSL_AuthCertificateComplete" << std::endl; - EXPECT_EQ(TIMER_EVENT, event); - TlsAgent* client = static_cast<TlsAgent*>(target); - EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client->ssl_fd(), 0)); -} - // This test uses a simple AuthCertificateCallback. Due to the way that the // entire server flight is processed, the call to SSL_AuthCertificateComplete // will trigger after the Finished message is processed. TEST_F(TlsConnectDatagram13, AuthCompleteAfterFinished) { - client_->SetAuthCertificateCallback( - [this](TlsAgent*, PRBool, PRBool) -> SECStatus { - std::shared_ptr<Poller::Timer> timer_handle; - // This is really just to unroll the stack. - Poller::Instance()->SetTimer(1U, client_.get(), TriggerAuthComplete, - &timer_handle); - return SECWouldBlock; - }); + SetDeferredAuthCertificateCallback(client_, 0); // 0 = success. Connect(); } @@ -754,15 +901,15 @@ TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPkcs1SignAndKEX) { PRFileDesc* ssl_fd = agent_->ssl_fd(); EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_decrypt)); EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_sign)); - EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss)); + EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss)); - // Configuring for only rsa_sign, rsa_pss, or rsa_decrypt should work. + // Configuring for only rsa_sign or rsa_decrypt should work. EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false, &ServerCertDataRsaPkcs1Decrypt)); EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false, &ServerCertDataRsaPkcs1Sign)); - EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false, - &ServerCertDataRsaPss)); + EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false, + &ServerCertDataRsaPss)); } // Test RSA cert with usage=[signature]. @@ -772,17 +919,17 @@ TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPkcs1Sign) { PRFileDesc* ssl_fd = agent_->ssl_fd(); EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_decrypt)); EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_sign)); - EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss)); + EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss)); // Configuring for only rsa_decrypt should fail. EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false, &ServerCertDataRsaPkcs1Decrypt)); - // Configuring for only rsa_sign or rsa_pss should work. + // Configuring for only rsa_sign should work. EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false, &ServerCertDataRsaPkcs1Sign)); - EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false, - &ServerCertDataRsaPss)); + EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false, + &ServerCertDataRsaPss)); } // Test RSA cert with usage=[encipherment]. diff --git a/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc index ec289bdd6..194cbab47 100644 --- a/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc @@ -84,6 +84,18 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase { Reset(TlsAgent::kRsa2048); auth_type_ = ssl_auth_rsa_sign; break; + case ssl_sig_rsa_pss_pss_sha256: + Reset(TlsAgent::kServerRsaPss); + auth_type_ = ssl_auth_rsa_pss; + break; + case ssl_sig_rsa_pss_pss_sha384: + Reset("rsa_pss384"); + auth_type_ = ssl_auth_rsa_pss; + break; + case ssl_sig_rsa_pss_pss_sha512: + Reset("rsa_pss512"); + auth_type_ = ssl_auth_rsa_pss; + break; case ssl_sig_ecdsa_secp256r1_sha256: Reset(TlsAgent::kServerEcdsa256); auth_type_ = ssl_auth_ecdsa; @@ -270,7 +282,7 @@ TEST_P(TlsCipherSuiteTest, ReadLimit) { } else { epoch = 0; } - TlsAgentTestBase::MakeRecord(variant_, kTlsApplicationDataType, version_, + TlsAgentTestBase::MakeRecord(variant_, ssl_ct_application_data, version_, payload, sizeof(payload), &record, (epoch << 48) | record_limit()); client_->SendDirect(record); @@ -310,14 +322,13 @@ static const auto kDummyNamedGroupParams = ::testing::Values(ssl_grp_none); static const auto kDummySignatureSchemesParams = ::testing::Values(ssl_sig_none); -#ifndef NSS_DISABLE_TLS_1_3 static SSLSignatureScheme kSignatureSchemesParamsArr[] = { ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pkcs1_sha384, ssl_sig_rsa_pkcs1_sha512, ssl_sig_ecdsa_secp256r1_sha256, ssl_sig_ecdsa_secp384r1_sha384, ssl_sig_rsa_pss_rsae_sha256, ssl_sig_rsa_pss_rsae_sha384, ssl_sig_rsa_pss_rsae_sha512, -}; -#endif + ssl_sig_rsa_pss_pss_sha256, ssl_sig_rsa_pss_pss_sha384, + ssl_sig_rsa_pss_pss_sha512}; INSTANTIATE_CIPHER_TEST_P(RC4, Stream, V10ToV12, kDummyNamedGroupParams, kDummySignatureSchemesParams, @@ -372,6 +383,14 @@ INSTANTIATE_CIPHER_TEST_P( TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA); +INSTANTIATE_CIPHER_TEST_P( + TLS12SigSchemes, All, V12, ::testing::ValuesIn(kFasterDHEGroups), + ::testing::ValuesIn(kSignatureSchemesParamsArr), + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, + TLS_DHE_DSS_WITH_AES_256_CBC_SHA256); #ifndef NSS_DISABLE_TLS_1_3 INSTANTIATE_CIPHER_TEST_P(TLS13, All, V13, ::testing::ValuesIn(kFasterDHEGroups), diff --git a/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc index 5be62e506..68c789a38 100644 --- a/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc @@ -132,7 +132,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionEmptyWriterServer) { // Sending extensions that the client doesn't expect leads to extensions // appearing even if the client didn't send one, or in the wrong messages. client_->ExpectSendAlert(kTlsAlertUnsupportedExtension); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); } @@ -350,7 +350,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionUnsolicitedServer) { auto capture = MakeTlsFilter<TlsExtensionCapture>(server_, extension_code); client_->ExpectSendAlert(kTlsAlertUnsupportedExtension); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); EXPECT_TRUE(capture->captured()); @@ -401,7 +401,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionClientReject) { EXPECT_EQ(SECSuccess, rv); client_->ExpectSendAlert(kTlsAlertHandshakeFailure); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); } @@ -451,7 +451,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionClientRejectAlert) { EXPECT_EQ(SECSuccess, rv); client_->ExpectSendAlert(kCustomAlert); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); } diff --git a/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc index b8836d7fc..0723c9bee 100644 --- a/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc @@ -17,7 +17,7 @@ extern "C" { } #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" diff --git a/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc index b99461632..f1ccc2864 100644 --- a/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc @@ -13,7 +13,7 @@ #include "sslproto.h" #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" @@ -643,4 +643,43 @@ TEST_P(TlsConnectGenericPre13, InvalidDERSignatureFfdhe) { client_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); } +// Replace SignatureAndHashAlgorithm of a SKE. +class DHEServerKEXSigAlgReplacer : public TlsHandshakeFilter { + public: + DHEServerKEXSigAlgReplacer(const std::shared_ptr<TlsAgent>& server, + SSLSignatureScheme sig_scheme) + : TlsHandshakeFilter(server, {kTlsHandshakeServerKeyExchange}), + sig_scheme_(sig_scheme) {} + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) { + *output = input; + + uint32_t len; + uint32_t idx = 0; + EXPECT_TRUE(output->Read(idx, 2, &len)); + idx += 2 + len; + EXPECT_TRUE(output->Read(idx, 2, &len)); + idx += 2 + len; + EXPECT_TRUE(output->Read(idx, 2, &len)); + idx += 2 + len; + output->Write(idx, sig_scheme_, 2); + + return CHANGE; + } + + private: + SSLSignatureScheme sig_scheme_; +}; + +TEST_P(TlsConnectTls12, ConnectInconsistentSigAlgDHE) { + EnableOnlyDheCiphers(); + + MakeTlsFilter<DHEServerKEXSigAlgReplacer>(server_, + ssl_sig_ecdsa_secp256r1_sha256); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); +} + } // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc index e5b52ff06..f25efc77a 100644 --- a/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc @@ -14,7 +14,7 @@ extern "C" { } #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" @@ -123,7 +123,7 @@ class TlsDropDatagram13 : public TlsConnectDatagram13, void Init(const std::shared_ptr<TlsAgent>& agent) { records_ = std::make_shared<TlsRecordRecorder>(agent); - ack_ = std::make_shared<TlsRecordRecorder>(agent, content_ack); + ack_ = std::make_shared<TlsRecordRecorder>(agent, ssl_ct_ack); ack_->EnableDecryption(); drop_ = std::make_shared<SelectiveRecordDropFilter>(agent, 0, false); chain_ = std::make_shared<ChainedPacketFilter>( @@ -670,7 +670,7 @@ TEST_P(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) { ASSERT_NE(nullptr, spec.get()); ASSERT_EQ(2, spec->epoch()); ASSERT_TRUE(client_->SendEncryptedRecord(spec, 0x0002000000000002, - kTlsApplicationDataType, + ssl_ct_application_data, DataBuffer(buf, sizeof(buf)))); // Now have the server consume the bogus message. @@ -696,7 +696,7 @@ TEST_P(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) { ASSERT_NE(nullptr, spec.get()); ASSERT_EQ(2, spec->epoch()); ASSERT_TRUE(client_->SendEncryptedRecord(spec, 0x0002000000000002, - kTlsHandshakeType, + ssl_ct_handshake, DataBuffer(buf, sizeof(buf)))); server_->Handshake(); EXPECT_EQ(2UL, server_filters_.ack_->count()); @@ -899,7 +899,7 @@ class TlsReplaceFirstRecordWithJunk : public TlsRecordFilter { } replaced_ = true; TlsRecordHeader out_header(header.variant(), header.version(), - kTlsApplicationDataType, + ssl_ct_application_data, header.sequence_number()); static const uint8_t junk[] = {1, 2, 3, 4}; diff --git a/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc index 12c6e8516..f1cf1fabc 100644 --- a/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc @@ -17,7 +17,7 @@ extern "C" { } #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" diff --git a/security/nss/gtests/ssl_gtest/ssl_ems_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_ems_unittest.cc index dad6ca026..39b2d5873 100644 --- a/security/nss/gtests/ssl_gtest/ssl_ems_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_ems_unittest.cc @@ -10,7 +10,7 @@ #include "sslproto.h" #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" diff --git a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc index 6965e9ca7..5819af746 100644 --- a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc @@ -9,6 +9,9 @@ #include "sslerr.h" #include "sslproto.h" +// This is only to get DTLS_1_3_DRAFT_VERSION +#include "ssl3prot.h" + #include <memory> #include "tls_connect.h" @@ -41,28 +44,6 @@ class TlsExtensionTruncator : public TlsExtensionFilter { size_t length_; }; -class TlsExtensionDamager : public TlsExtensionFilter { - public: - TlsExtensionDamager(const std::shared_ptr<TlsAgent>& a, uint16_t extension, - size_t index) - : TlsExtensionFilter(a), extension_(extension), index_(index) {} - virtual PacketFilter::Action FilterExtension(uint16_t extension_type, - const DataBuffer& input, - DataBuffer* output) { - if (extension_type != extension_) { - return KEEP; - } - - *output = input; - output->data()[index_] += 73; // Increment selected for maximum damage - return CHANGE; - } - - private: - uint16_t extension_; - size_t index_; -}; - class TlsExtensionAppender : public TlsHandshakeFilter { public: TlsExtensionAppender(const std::shared_ptr<TlsAgent>& a, @@ -454,6 +435,25 @@ TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsOddLength) { client_, ssl_signature_algorithms_xtn, extension)); } +TEST_F(TlsExtensionTest13Stream, SignatureAlgorithmsPrecedingGarbage) { + // 31 unknown signature algorithms followed by sha-256, rsa + const uint8_t val[] = { + 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0x01}; + DataBuffer extension(val, sizeof(val)); + MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_signature_algorithms_xtn, + extension); + client_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertBadRecordMac); + ConnectExpectFail(); + client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); + server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); +} + TEST_P(TlsExtensionTestGeneric, NoSupportedGroups) { ClientHelloErrorTest( std::make_shared<TlsExtensionDropper>(client_, ssl_supported_groups_xtn), @@ -563,10 +563,10 @@ TEST_F(TlsExtensionTest13Stream, DropServerKeyShare) { EnsureTlsSetup(); MakeTlsFilter<TlsExtensionDropper>(server_, ssl_tls13_key_share_xtn); client_->ExpectSendAlert(kTlsAlertMissingExtension); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code()); - EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code()); + EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code()); } TEST_F(TlsExtensionTest13Stream, WrongServerKeyShare) { @@ -583,13 +583,12 @@ TEST_F(TlsExtensionTest13Stream, WrongServerKeyShare) { EnsureTlsSetup(); MakeTlsFilter<TlsExtensionReplacer>(server_, ssl_tls13_key_share_xtn, buf); client_->ExpectSendAlert(kTlsAlertIllegalParameter); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); EXPECT_EQ(SSL_ERROR_RX_MALFORMED_KEY_SHARE, client_->error_code()); - EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code()); + EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code()); } -// TODO(ekr@rtfm.com): This is the wrong error code. See bug 1307269. TEST_F(TlsExtensionTest13Stream, UnknownServerKeyShare) { const uint16_t wrong_group = 0xffff; @@ -603,11 +602,11 @@ TEST_F(TlsExtensionTest13Stream, UnknownServerKeyShare) { DataBuffer buf(key_share, sizeof(key_share)); EnsureTlsSetup(); MakeTlsFilter<TlsExtensionReplacer>(server_, ssl_tls13_key_share_xtn, buf); - client_->ExpectSendAlert(kTlsAlertMissingExtension); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + client_->ExpectSendAlert(kTlsAlertIllegalParameter); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); - EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code()); - EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code()); + EXPECT_EQ(SSL_ERROR_RX_MALFORMED_KEY_SHARE, client_->error_code()); + EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code()); } TEST_F(TlsExtensionTest13Stream, AddServerSignatureAlgorithmsOnResumption) { @@ -616,10 +615,10 @@ TEST_F(TlsExtensionTest13Stream, AddServerSignatureAlgorithmsOnResumption) { MakeTlsFilter<TlsExtensionInjector>(server_, ssl_signature_algorithms_xtn, empty); client_->ExpectSendAlert(kTlsAlertUnsupportedExtension); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); EXPECT_EQ(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, client_->error_code()); - EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code()); + EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code()); } struct PskIdentity { @@ -912,23 +911,32 @@ TEST_P(TlsExtensionTest13, RemoveTls13FromVersionListServerV12) { // 3. Server supports 1.2 and 1.3, client supports 1.2 and 1.3 // but advertises 1.2 (because we changed things). TEST_P(TlsExtensionTest13, RemoveTls13FromVersionListBothV12) { + client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE); client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, SSL_LIBRARY_VERSION_TLS_1_3); server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, SSL_LIBRARY_VERSION_TLS_1_3); -#ifndef TLS_1_3_DRAFT_VERSION - ExpectAlert(server_, kTlsAlertIllegalParameter); -#else - ExpectAlert(server_, kTlsAlertDecryptError); +// The downgrade check is disabled in DTLS 1.3, so all that happens when we +// tamper with the supported versions is that the Finished check fails. +#ifdef DTLS_1_3_DRAFT_VERSION + if (variant_ == ssl_variant_datagram) { + ExpectAlert(server_, kTlsAlertDecryptError); + } else #endif + { + ExpectAlert(client_, kTlsAlertIllegalParameter); + } ConnectWithReplacementVersionList(SSL_LIBRARY_VERSION_TLS_1_2); -#ifndef TLS_1_3_DRAFT_VERSION - client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); - server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); -#else - client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); - server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); +#ifdef DTLS_1_3_DRAFT_VERSION + if (variant_ == ssl_variant_datagram) { + client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); + server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); + } else #endif + { + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); + server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); + } } TEST_P(TlsExtensionTest13, HrrThenRemoveSignatureAlgorithms) { @@ -1017,7 +1025,7 @@ class TlsBogusExtensionTest13 : public TlsBogusExtensionTest { client_->ExpectSendAlert(alert); client_->Handshake(); if (variant_ == ssl_variant_stream) { - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); } server_->Handshake(); } diff --git a/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc index 92947c2c7..375281263 100644 --- a/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc @@ -10,7 +10,7 @@ #include "sslproto.h" #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" @@ -106,8 +106,8 @@ class RecordFragmenter : public PacketFilter { } // Just rewrite the sequence number (CCS only). - if (header.content_type() != kTlsHandshakeType) { - EXPECT_EQ(kTlsChangeCipherSpecType, header.content_type()); + if (header.content_type() != ssl_ct_handshake) { + EXPECT_EQ(ssl_ct_change_cipher_spec, header.content_type()); WriteRecord(header, record); continue; } diff --git a/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc index f0afc9118..f033b7843 100644 --- a/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc @@ -33,7 +33,7 @@ class TlsApplicationDataRecorder : public TlsRecordFilter { virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& input, DataBuffer* output) { - if (header.content_type() == kTlsApplicationDataType) { + if (header.content_type() == ssl_ct_application_data) { buffer_.Append(input); } diff --git a/security/nss/gtests/ssl_gtest/ssl_gather_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_gather_unittest.cc index f47b2f445..745432951 100644 --- a/security/nss/gtests/ssl_gtest/ssl_gather_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_gather_unittest.cc @@ -15,6 +15,7 @@ class GatherV2ClientHelloTest : public TlsConnectTestBase { void ConnectExpectMalformedClientHello(const DataBuffer &data) { EnsureTlsSetup(); + server_->SetOption(SSL_ENABLE_V2_COMPATIBLE_HELLO, PR_TRUE); server_->ExpectSendAlert(kTlsAlertIllegalParameter); client_->SendDirect(data); server_->StartConnect(); diff --git a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp index 17677713d..be1c4ea32 100644 --- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp +++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp @@ -51,6 +51,7 @@ 'tls_connect.cc', 'tls_filter.cc', 'tls_hkdf_unittest.cc', + 'tls_esni_unittest.cc', 'tls_protect.cc' ], 'dependencies': [ diff --git a/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc index 77b335e86..27bc03654 100644 --- a/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc @@ -9,11 +9,11 @@ #include "sslerr.h" #include "sslproto.h" -// This is internal, just to get TLS_1_3_DRAFT_VERSION. +// This is internal, just to get DTLS_1_3_DRAFT_VERSION. #include "ssl3prot.h" #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" @@ -76,7 +76,7 @@ class CorrectMessageSeqAfterHrrFilter : public TlsRecordFilter { PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& record, size_t* offset, DataBuffer* output) { - if (filtered_packets() > 0 || header.content_type() != content_handshake) { + if (filtered_packets() > 0 || header.content_type() != ssl_ct_handshake) { return KEEP; } @@ -718,6 +718,86 @@ TEST_F(TlsConnectStreamTls13, RetryStatelessDamageSecondClientHello) { client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); } +// Stream because SSL_SendSessionTicket only supports that. +TEST_F(TlsConnectStreamTls13, SecondClientHelloSendSameTicket) { + // This simulates the scenario described at: + // https://bugzilla.mozilla.org/show_bug.cgi?id=1481271#c7 + // + // Here two connections are interleaved. Tickets are issued on one + // connection. A HelloRetryRequest is triggered on the second connection, + // meaning that there are two ClientHellos. We need to check that both + // ClientHellos have the same ticket, even if a new ticket is issued on the + // other connection in the meantime. + // + // Connection 1: <handshake> + // Connection 1: S->C: NST=X + // Connection 2: C->S: CH [PSK_ID=X] + // Connection 1: S->C: NST=Y + // Connection 2: S->C: HRR + // Connection 2: C->S: CH [PSK_ID=Y] + + // Connection 1, send a ticket after handshake is complete. + ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET); + + Connect(); + + // Set this token so that RetryHelloWithToken() will check that this + // is the token that it receives in the HelloRetryRequest callback. + EXPECT_EQ(SECSuccess, + SSL_SendSessionTicket(server_->ssl_fd(), kApplicationToken, + sizeof(kApplicationToken))); + SendReceive(50); + + // Connection 2, trigger HRR. + auto client2 = + std::make_shared<TlsAgent>(client_->name(), TlsAgent::CLIENT, variant_); + auto server2 = + std::make_shared<TlsAgent>(server_->name(), TlsAgent::SERVER, variant_); + + client2->SetPeer(server2); + server2->SetPeer(client2); + + client_.swap(client2); + server_.swap(server2); + + ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET); + + ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); + + client_->StartConnect(); + server_->StartConnect(); + + size_t cb_called = 0; + EXPECT_EQ(SECSuccess, + SSL_HelloRetryRequestCallback(server_->ssl_fd(), + RetryHelloWithToken, &cb_called)); + client_->Handshake(); // Send ClientHello. + server_->Handshake(); // Process ClientHello, send HelloRetryRequest. + + EXPECT_EQ(1U, cb_called) << "callback should be called once here"; + + // Connection 1, send another ticket. + client_.swap(client2); + server_.swap(server2); + + // If the client uses this token, RetryHelloWithToken() will fail the test. + const uint8_t kAnotherApplicationToken[] = {0x92, 0x44, 0x01}; + EXPECT_EQ(SECSuccess, + SSL_SendSessionTicket(server_->ssl_fd(), kAnotherApplicationToken, + sizeof(kAnotherApplicationToken))); + SendReceive(60); + + // Connection 2, continue the handshake. + // The client should use kApplicationToken, not kAnotherApplicationToken. + client_.swap(client2); + server_.swap(server2); + + client_->Handshake(); + server_->Handshake(); + + EXPECT_EQ(2U, cb_called) << "callback should be called twice here"; +} + // Read the cipher suite from the HRR and disable it on the identified agent. static void DisableSuiteFromHrr( std::shared_ptr<TlsAgent>& agent, @@ -844,10 +924,10 @@ TEST_F(TlsConnectStreamTls13, RetryWithDifferentCipherSuite) { TLS_CHACHA20_POLY1305_SHA256); client_->ExpectSendAlert(kTlsAlertIllegalParameter); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); EXPECT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code()); - EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code()); + EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code()); } // This tests that the second attempt at sending a ClientHello (after receiving @@ -1007,14 +1087,17 @@ class HelloRetryRequestAgentTest : public TlsAgentTestClient { // Now the supported version. i = hrr_data.Write(i, ssl_tls13_supported_versions_xtn, 2); i = hrr_data.Write(i, 2, 2); - i = hrr_data.Write(i, 0x7f00 | TLS_1_3_DRAFT_VERSION, 2); + i = hrr_data.Write(i, (variant_ == ssl_variant_datagram) + ? (0x7f00 | DTLS_1_3_DRAFT_VERSION) + : SSL_LIBRARY_VERSION_TLS_1_3, + 2); if (len) { hrr_data.Write(i, body, len); } DataBuffer hrr; MakeHandshakeMessage(kTlsHandshakeServerHello, hrr_data.data(), hrr_data.len(), &hrr, seq_num); - MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, hrr.data(), + MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, hrr.data(), hrr.len(), hrr_record, seq_num); } diff --git a/security/nss/gtests/ssl_gtest/ssl_keyupdate_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_keyupdate_unittest.cc index d03775c25..d6ac99a58 100644 --- a/security/nss/gtests/ssl_gtest/ssl_keyupdate_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_keyupdate_unittest.cc @@ -15,7 +15,7 @@ extern "C" { } #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" diff --git a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc index 5adbd9dc7..12c2496a6 100644 --- a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc @@ -18,7 +18,7 @@ extern "C" { } #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" @@ -65,7 +65,7 @@ class TlsAlertRecorder : public TlsRecordFilter { if (level_ != 255) { // Already captured. return KEEP; } - if (header.content_type() != kTlsAlertType) { + if (header.content_type() != ssl_ct_alert) { return KEEP; } @@ -130,7 +130,7 @@ TEST_P(TlsConnectTls13, CaptureAlertClient) { client_->Handshake(); if (variant_ == ssl_variant_stream) { // DTLS just drops the alert it can't decrypt. - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); } server_->Handshake(); EXPECT_EQ(kTlsAlertFatal, alert_recorder->level()); @@ -320,6 +320,53 @@ TEST_F(TlsConnectStreamTls13, DropRecordClient) { SendReceive(); } +// Check that a server can use 0.5 RTT if client authentication isn't enabled. +TEST_P(TlsConnectTls13, WriteBeforeClientFinished) { + EnsureTlsSetup(); + StartConnect(); + client_->Handshake(); // ClientHello + server_->Handshake(); // ServerHello + + server_->SendData(10); + client_->ReadBytes(10); // Client should emit the Finished as a side-effect. + server_->Handshake(); // Server consumes the Finished. + CheckConnected(); +} + +// We don't allow 0.5 RTT if client authentication is requested. +TEST_P(TlsConnectTls13, WriteBeforeClientFinishedClientAuth) { + client_->SetupClientAuth(); + server_->RequestClientAuth(false); + StartConnect(); + client_->Handshake(); // ClientHello + server_->Handshake(); // ServerHello + + static const uint8_t data[] = {1, 2, 3}; + EXPECT_GT(0, PR_Write(server_->ssl_fd(), data, sizeof(data))); + EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); + + Handshake(); + CheckConnected(); + SendReceive(); +} + +// 0.5 RTT should fail with client authentication required. +TEST_P(TlsConnectTls13, WriteBeforeClientFinishedClientAuthRequired) { + client_->SetupClientAuth(); + server_->RequestClientAuth(true); + StartConnect(); + client_->Handshake(); // ClientHello + server_->Handshake(); // ServerHello + + static const uint8_t data[] = {1, 2, 3}; + EXPECT_GT(0, PR_Write(server_->ssl_fd(), data, sizeof(data))); + EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); + + Handshake(); + CheckConnected(); + SendReceive(); +} + // The next two tests takes advantage of the fact that we // automatically read the first 1024 bytes, so if // we provide 1200 bytes, they overrun the read buffer @@ -426,13 +473,15 @@ class TlsPreCCSHeaderInjector : public TlsRecordFilter { virtual PacketFilter::Action FilterRecord( const TlsRecordHeader& record_header, const DataBuffer& input, size_t* offset, DataBuffer* output) override { - if (record_header.content_type() != kTlsChangeCipherSpecType) return KEEP; + if (record_header.content_type() != ssl_ct_change_cipher_spec) { + return KEEP; + } std::cerr << "Injecting Finished header before CCS\n"; const uint8_t hhdr[] = {kTlsHandshakeFinished, 0x00, 0x00, 0x0c}; DataBuffer hhdr_buf(hhdr, sizeof(hhdr)); TlsRecordHeader nhdr(record_header.variant(), record_header.version(), - kTlsHandshakeType, 0); + ssl_ct_handshake, 0); *offset = nhdr.Write(output, *offset, hhdr_buf); *offset = record_header.Write(output, *offset, input); return CHANGE; @@ -477,6 +526,26 @@ TEST_P(TlsConnectTls13, AlertWrongLevel) { client_->WaitForErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT, 2000); } +TEST_P(TlsConnectTls13, UnknownRecord) { + static const uint8_t kUknownRecord[] = { + 0xff, SSL_LIBRARY_VERSION_TLS_1_2 >> 8, + SSL_LIBRARY_VERSION_TLS_1_2 & 0xff, 0, 0}; + + Connect(); + if (variant_ == ssl_variant_stream) { + // DTLS just drops the record with an invalid type. + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); + } + client_->SendDirect(DataBuffer(kUknownRecord, sizeof(kUknownRecord))); + server_->ExpectReadWriteError(); + server_->ReadBytes(); + if (variant_ == ssl_variant_stream) { + EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code()); + } else { + EXPECT_EQ(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE, server_->error_code()); + } +} + TEST_F(TlsConnectStreamTls13, Tls13FailedWriteSecondFlight) { EnsureTlsSetup(); StartConnect(); @@ -539,6 +608,126 @@ TEST_F(TlsConnectTest, OneNRecordSplitting) { EXPECT_EQ(ExpectedCbcLen(20), records->record(2).buffer.len()); } +// We can't test for randomness easily here, but we can test that we don't +// produce a zero value, or produce the same value twice. There are 5 values +// here: two ClientHello.random, two ServerHello.random, and one zero value. +// Matrix them and fail if any are the same. +TEST_P(TlsConnectGeneric, CheckRandoms) { + ConfigureSessionCache(RESUME_NONE, RESUME_NONE); + + static const size_t random_len = 32; + uint8_t crandom1[random_len], srandom1[random_len]; + uint8_t z[random_len] = {0}; + + auto ch = MakeTlsFilter<TlsHandshakeRecorder>(client_, ssl_hs_client_hello); + auto sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello); + Connect(); + ASSERT_TRUE(ch->buffer().len() > (random_len + 2)); + ASSERT_TRUE(sh->buffer().len() > (random_len + 2)); + memcpy(crandom1, ch->buffer().data() + 2, random_len); + memcpy(srandom1, sh->buffer().data() + 2, random_len); + EXPECT_NE(0, memcmp(crandom1, srandom1, random_len)); + EXPECT_NE(0, memcmp(crandom1, z, random_len)); + EXPECT_NE(0, memcmp(srandom1, z, random_len)); + + Reset(); + ch = MakeTlsFilter<TlsHandshakeRecorder>(client_, ssl_hs_client_hello); + sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello); + Connect(); + ASSERT_TRUE(ch->buffer().len() > (random_len + 2)); + ASSERT_TRUE(sh->buffer().len() > (random_len + 2)); + const uint8_t* crandom2 = ch->buffer().data() + 2; + const uint8_t* srandom2 = sh->buffer().data() + 2; + + EXPECT_NE(0, memcmp(crandom2, srandom2, random_len)); + EXPECT_NE(0, memcmp(crandom2, z, random_len)); + EXPECT_NE(0, memcmp(srandom2, z, random_len)); + + EXPECT_NE(0, memcmp(crandom1, crandom2, random_len)); + EXPECT_NE(0, memcmp(crandom1, srandom2, random_len)); + EXPECT_NE(0, memcmp(srandom1, crandom2, random_len)); + EXPECT_NE(0, memcmp(srandom1, srandom2, random_len)); +} + +void FailOnCloseNotify(const PRFileDesc* fd, void* arg, const SSLAlert* alert) { + ADD_FAILURE() << "received alert " << alert->description; +} + +void CheckCloseNotify(const PRFileDesc* fd, void* arg, const SSLAlert* alert) { + *reinterpret_cast<bool*>(arg) = true; + EXPECT_EQ(close_notify, alert->description); + EXPECT_EQ(alert_warning, alert->level); +} + +TEST_P(TlsConnectGeneric, ShutdownOneSide) { + Connect(); + + // Setup to check alerts. + EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(server_->ssl_fd(), + FailOnCloseNotify, nullptr)); + EXPECT_EQ(SECSuccess, SSL_AlertReceivedCallback(client_->ssl_fd(), + FailOnCloseNotify, nullptr)); + + bool client_sent = false; + EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(client_->ssl_fd(), + CheckCloseNotify, &client_sent)); + bool server_received = false; + EXPECT_EQ(SECSuccess, + SSL_AlertReceivedCallback(server_->ssl_fd(), CheckCloseNotify, + &server_received)); + EXPECT_EQ(PR_SUCCESS, PR_Shutdown(client_->ssl_fd(), PR_SHUTDOWN_SEND)); + + // Make sure that the server reads out the close_notify. + uint8_t buf[10]; + EXPECT_EQ(0, PR_Read(server_->ssl_fd(), buf, sizeof(buf))); + + // Reading and writing should still work in the one open direction. + EXPECT_TRUE(client_sent); + EXPECT_TRUE(server_received); + server_->SendData(10, 10); + client_->ReadBytes(10); + + // Now close the other side and do the same checks. + bool server_sent = false; + EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(server_->ssl_fd(), + CheckCloseNotify, &server_sent)); + bool client_received = false; + EXPECT_EQ(SECSuccess, + SSL_AlertReceivedCallback(client_->ssl_fd(), CheckCloseNotify, + &client_received)); + EXPECT_EQ(PR_SUCCESS, PR_Shutdown(server_->ssl_fd(), PR_SHUTDOWN_SEND)); + + EXPECT_EQ(0, PR_Read(client_->ssl_fd(), buf, sizeof(buf))); + EXPECT_TRUE(server_sent); + EXPECT_TRUE(client_received); +} + +TEST_P(TlsConnectGeneric, ShutdownOneSideThenCloseTcp) { + Connect(); + + bool client_sent = false; + EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(client_->ssl_fd(), + CheckCloseNotify, &client_sent)); + bool server_received = false; + EXPECT_EQ(SECSuccess, + SSL_AlertReceivedCallback(server_->ssl_fd(), CheckCloseNotify, + &server_received)); + EXPECT_EQ(PR_SUCCESS, PR_Shutdown(client_->ssl_fd(), PR_SHUTDOWN_SEND)); + + // Make sure that the server reads out the close_notify. + uint8_t buf[10]; + EXPECT_EQ(0, PR_Read(server_->ssl_fd(), buf, sizeof(buf))); + + // Now simulate the underlying connection closing. + client_->adapter()->Reset(); + + // Now close the other side and see that things don't explode. + EXPECT_EQ(PR_SUCCESS, PR_Shutdown(server_->ssl_fd(), PR_SHUTDOWN_SEND)); + + EXPECT_GT(0, PR_Read(client_->ssl_fd(), buf, sizeof(buf))); + EXPECT_EQ(PR_NOT_CONNECTED_ERROR, PR_GetError()); +} + INSTANTIATE_TEST_CASE_P( GenericStream, TlsConnectGeneric, ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream, diff --git a/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc index 53b11c61a..f1e85e898 100644 --- a/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc @@ -111,7 +111,7 @@ class RecordReplacer : public TlsRecordFilter { PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& data, DataBuffer* changed) override { - EXPECT_EQ(kTlsApplicationDataType, header.content_type()); + EXPECT_EQ(ssl_ct_application_data, header.content_type()); changed->Allocate(size_); for (size_t i = 0; i < size_; ++i) { diff --git a/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc index 00651aec5..0a54ae1a8 100644 --- a/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc @@ -10,7 +10,7 @@ #include "sslproto.h" #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" @@ -34,7 +34,7 @@ class TlsRecordMaximum : public TlsRecordFilter { DataBuffer* output) override { std::cerr << "max: " << record << std::endl; // Ignore unprotected packets. - if (header.content_type() != kTlsApplicationDataType) { + if (header.content_type() != ssl_ct_application_data) { return KEEP; } @@ -187,7 +187,7 @@ class TlsRecordExpander : public TlsRecordFilter { virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& data, DataBuffer* changed) { - if (header.content_type() != kTlsApplicationDataType) { + if (header.content_type() != ssl_ct_application_data) { return KEEP; } changed->Allocate(data.len() + expansion_); @@ -252,7 +252,7 @@ class TlsRecordPadder : public TlsRecordFilter { PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& record, size_t* offset, DataBuffer* output) override { - if (header.content_type() != kTlsApplicationDataType) { + if (header.content_type() != ssl_ct_application_data) { return KEEP; } @@ -262,7 +262,7 @@ class TlsRecordPadder : public TlsRecordFilter { return KEEP; } - if (inner_content_type != kTlsApplicationDataType) { + if (inner_content_type != ssl_ct_application_data) { return KEEP; } diff --git a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc index 2cc98a327..264bde67f 100644 --- a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc @@ -18,7 +18,8 @@ extern "C" { } #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" +#include "scoped_ptrs_ssl.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" @@ -171,21 +172,143 @@ TEST_P(TlsConnectGenericResumption, ConnectResumeClientNoneServerBoth) { SendReceive(); } -TEST_P(TlsConnectGenericPre13, ConnectResumeWithHigherVersion) { +TEST_P(TlsConnectGenericPre13, ResumeWithHigherVersionTls13) { + uint16_t lower_version = version_; + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + Connect(); + SendReceive(); + CheckKeys(); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + EnsureTlsSetup(); + auto psk_ext = std::make_shared<TlsExtensionCapture>( + client_, ssl_tls13_pre_shared_key_xtn); + auto ticket_ext = + std::make_shared<TlsExtensionCapture>(client_, ssl_session_ticket_xtn); + client_->SetFilter(std::make_shared<ChainedPacketFilter>( + ChainedPacketFilterInit({psk_ext, ticket_ext}))); + SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_3); + client_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3); + server_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3); + ExpectResumption(RESUME_NONE); + Connect(); + + // The client shouldn't have sent a PSK, though it will send a ticket. + EXPECT_FALSE(psk_ext->captured()); + EXPECT_TRUE(ticket_ext->captured()); +} + +class CaptureSessionId : public TlsHandshakeFilter { + public: + CaptureSessionId(const std::shared_ptr<TlsAgent>& a) + : TlsHandshakeFilter( + a, {kTlsHandshakeClientHello, kTlsHandshakeServerHello}), + sid_() {} + + const DataBuffer& sid() const { return sid_; } + + protected: + PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) override { + // The session_id is in the same place in both Hello messages: + size_t offset = 2 + 32; // Version(2) + Random(32) + uint32_t len = 0; + EXPECT_TRUE(input.Read(offset, 1, &len)); + offset++; + if (input.len() < offset + len) { + ADD_FAILURE() << "session_id overflows the Hello message"; + return KEEP; + } + sid_.Assign(input.data() + offset, len); + return KEEP; + } + + private: + DataBuffer sid_; +}; + +// Attempting to resume from TLS 1.2 when 1.3 is possible should not result in +// resumption, though it will appear to be TLS 1.3 compatibility mode if the +// server uses a session ID. +TEST_P(TlsConnectGenericPre13, ResumeWithHigherVersionTls13SessionId) { + uint16_t lower_version = version_; ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID); - ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_1); - SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_1); + auto original_sid = MakeTlsFilter<CaptureSessionId>(server_); + Connect(); + CheckKeys(); + EXPECT_EQ(32U, original_sid->sid().len()); + + // The client should now attempt to resume with the session ID from the last + // connection. This looks like compatibility mode, we just want to ensure + // that we get TLS 1.3 rather than 1.2 (and no resumption). + Reset(); + auto client_sid = MakeTlsFilter<CaptureSessionId>(client_); + auto server_sid = MakeTlsFilter<CaptureSessionId>(server_); + ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID); + SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_3); + client_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3); + server_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3); + ExpectResumption(RESUME_NONE); + + Connect(); + SendReceive(); + + EXPECT_EQ(client_sid->sid(), original_sid->sid()); + if (variant_ == ssl_variant_stream) { + EXPECT_EQ(client_sid->sid(), server_sid->sid()); + } else { + // DTLS servers don't echo the session ID. + EXPECT_EQ(0U, server_sid->sid().len()); + } +} + +TEST_P(TlsConnectPre12, ResumeWithHigherVersionTls12) { + uint16_t lower_version = version_; + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); Connect(); Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); EnsureTlsSetup(); - SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_2); - client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1, - SSL_LIBRARY_VERSION_TLS_1_2); - server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1, - SSL_LIBRARY_VERSION_TLS_1_2); + SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_3); + client_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3); + server_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3); + ExpectResumption(RESUME_NONE); + Connect(); +} + +TEST_P(TlsConnectGenericPre13, ResumeWithLowerVersionFromTls13) { + uint16_t original_version = version_; + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); + Connect(); + SendReceive(); + CheckKeys(); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ConfigureVersion(original_version); ExpectResumption(RESUME_NONE); Connect(); + SendReceive(); +} + +TEST_P(TlsConnectPre12, ResumeWithLowerVersionFromTls12) { + uint16_t original_version = version_; + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_2); + Connect(); + SendReceive(); + CheckKeys(); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ConfigureVersion(original_version); + ExpectResumption(RESUME_NONE); + Connect(); + SendReceive(); } TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicketForget) { @@ -276,8 +399,13 @@ TEST_P(TlsConnectGeneric, ConnectResumeCorruptTicket) { ASSERT_NE(nullptr, hmac_key); SSLInt_SetSelfEncryptMacKey(hmac_key); ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); - ConnectExpectAlert(server_, illegal_parameter); - server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + ExpectResumption(RESUME_NONE); + Connect(); + } else { + ConnectExpectAlert(server_, illegal_parameter); + server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); + } } // This callback switches out the "server" cert used on the server with @@ -394,6 +522,64 @@ TEST_P(TlsConnectTls13, TestTls13ResumeDifferentGroup) { ssl_sig_rsa_pss_rsae_sha256); } +// Verify that TLS 1.3 server doesn't request certificate in the main +// handshake, after resumption. +TEST_P(TlsConnectTls13, TestTls13ResumeNoCertificateRequest) { + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); + client_->SetupClientAuth(); + server_->RequestClientAuth(true); + Connect(); + SendReceive(); // Need to read so that we absorb the session ticket. + ScopedCERTCertificate cert1(SSL_LocalCertificate(client_->ssl_fd())); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); + ExpectResumption(RESUME_TICKET); + server_->RequestClientAuth(false); + auto cr_capture = + MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_certificate_request); + cr_capture->EnableDecryption(); + Connect(); + SendReceive(); + EXPECT_EQ(0U, cr_capture->buffer().len()) << "expect nothing captured yet"; + + // Sanity check whether the client certificate matches the one + // decrypted from ticket. + ScopedCERTCertificate cert2(SSL_PeerCertificate(server_->ssl_fd())); + EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert)); +} + +// Here we test that 0.5 RTT is available at the server when resuming, even if +// configured to request a client certificate. The resumed handshake relies on +// the authentication from the original handshake, so no certificate is +// requested this time around. The server can write before the handshake +// completes because the PSK binder is sufficient authentication for the client. +TEST_P(TlsConnectTls13, WriteBeforeHandshakeCompleteOnResumption) { + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); + client_->SetupClientAuth(); + server_->RequestClientAuth(true); + Connect(); + SendReceive(); // Absorb the session ticket. + ScopedCERTCertificate cert1(SSL_LocalCertificate(client_->ssl_fd())); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); + ExpectResumption(RESUME_TICKET); + server_->RequestClientAuth(false); + StartConnect(); + client_->Handshake(); // ClientHello + server_->Handshake(); // ServerHello + + server_->SendData(10); + client_->ReadBytes(10); // Client should emit the Finished as a side-effect. + server_->Handshake(); // Server consumes the Finished. + CheckConnected(); + + // Check whether the client certificate matches the one from the ticket. + ScopedCERTCertificate cert2(SSL_PeerCertificate(server_->ssl_fd())); + EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert)); +} + // We need to enable different cipher suites at different times in the following // tests. Those cipher suites need to be suited to the version. static uint16_t ChooseOneCipher(uint16_t version) { @@ -467,7 +653,7 @@ TEST_P(TlsConnectStream, TestResumptionOverrideCipher) { if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { client_->ExpectSendAlert(kTlsAlertIllegalParameter); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); } else { ExpectAlert(client_, kTlsAlertHandshakeFailure); } @@ -476,7 +662,7 @@ TEST_P(TlsConnectStream, TestResumptionOverrideCipher) { if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { // The reason this test is stream only: the server is unable to decrypt // the alert that the client sends, see bug 1304603. - server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); + server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE); } else { server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT); } @@ -760,6 +946,36 @@ TEST_F(TlsConnectDatagram13, SendSessionTicketDtls) { EXPECT_EQ(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION, PORT_GetError()); } +TEST_F(TlsConnectStreamTls13, ExternalResumptionUseSecondTicket) { + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); + + struct ResumptionTicketState { + std::vector<uint8_t> ticket; + size_t invoked = 0; + } ticket_state; + auto cb = [](PRFileDesc* fd, const PRUint8* ticket, unsigned int ticket_len, + void* arg) -> SECStatus { + auto state = reinterpret_cast<ResumptionTicketState*>(arg); + state->ticket.assign(ticket, ticket + ticket_len); + state->invoked++; + return SECSuccess; + }; + SSL_SetResumptionTokenCallback(client_->ssl_fd(), cb, &ticket_state); + + Connect(); + EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), nullptr, 0)); + SendReceive(); + EXPECT_EQ(2U, ticket_state.invoked); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + client_->SetResumptionToken(ticket_state.ticket); + ExpectResumption(RESUME_TICKET); + Connect(); + SendReceive(); +} + TEST_F(TlsConnectTest, TestTls13ResumptionDowngrade) { ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); @@ -830,10 +1046,10 @@ TEST_F(TlsConnectTest, TestTls13ResumptionForcedDowngrade) { // client expects to receive an unencrypted TLS 1.2 Certificate message. // The server can't decrypt the alert. client_->ExpectSendAlert(kTlsAlertUnexpectedMessage); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); // Server can't read + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); // Server can't read ConnectExpectFail(); client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA); - server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); + server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE); } TEST_P(TlsConnectGenericResumption, ReConnectTicket) { @@ -908,6 +1124,36 @@ void CheckGetInfoResult(uint32_t alpnSize, uint32_t earlyDataSize, EXPECT_EQ(0, memcmp("a", token->alpnSelection, token->alpnSelectionLen)); ASSERT_EQ(earlyDataSize, token->maxEarlyDataSize); + + ASSERT_LT(ssl_TimeUsec(), token->expirationTime); +} + +// The client should generate a new, randomized session_id +// when resuming using an external token. +TEST_P(TlsConnectGenericResumptionToken, CheckSessionId) { + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + auto original_sid = MakeTlsFilter<CaptureSessionId>(client_); + Connect(); + SendReceive(); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ExpectResumption(RESUME_TICKET); + + StartConnect(); + ASSERT_TRUE(client_->MaybeSetResumptionToken()); + auto resumed_sid = MakeTlsFilter<CaptureSessionId>(client_); + + Handshake(); + CheckConnected(); + SendReceive(); + + if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) { + EXPECT_NE(resumed_sid->sid(), original_sid->sid()); + EXPECT_EQ(32U, resumed_sid->sid().len()); + } else { + EXPECT_EQ(0U, resumed_sid->sid().len()); + } } TEST_P(TlsConnectGenericResumptionToken, ConnectResumeGetInfo) { @@ -1026,4 +1272,34 @@ TEST_P(TlsConnectGenericResumption, ConnectResumeClientAuth) { SendReceive(); } +TEST_F(TlsConnectStreamTls13, ExternalTokenAfterHrr) { + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + Connect(); + SendReceive(); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ExpectResumption(RESUME_TICKET); + + static const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp384r1, + ssl_grp_ec_secp521r1}; + server_->ConfigNamedGroups(groups); + + StartConnect(); + ASSERT_TRUE(client_->MaybeSetResumptionToken()); + + client_->Handshake(); // Send ClientHello. + server_->Handshake(); // Process ClientHello, send HelloRetryRequest. + + auto& token = client_->GetResumptionToken(); + SECStatus rv = + SSL_SetResumptionToken(client_->ssl_fd(), token.data(), token.size()); + ASSERT_EQ(SECFailure, rv); + ASSERT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + Handshake(); + CheckConnected(); + SendReceive(); +} + } // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc index 9ef19653b..3ed42e86b 100644 --- a/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc @@ -32,7 +32,7 @@ class TlsHandshakeSkipFilter : public TlsRecordFilter { virtual PacketFilter::Action FilterRecord( const TlsRecordHeader& record_header, const DataBuffer& input, DataBuffer* output) { - if (record_header.content_type() != kTlsHandshakeType) { + if (record_header.content_type() != ssl_ct_handshake) { return KEEP; } diff --git a/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc index ff4091b9a..abddaa5b6 100644 --- a/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc @@ -17,7 +17,7 @@ extern "C" { } #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" diff --git a/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc index 42f1065f6..ecb63d476 100644 --- a/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc @@ -82,7 +82,7 @@ class Tls13CompatTest : public TlsConnectStreamTls13 { // Only the second record can be a CCS. bool expected_match = expected && (i == 1); EXPECT_EQ(expected_match, - kTlsChangeCipherSpecType == + ssl_ct_change_cipher_spec == records_->record(i).header.content_type()); } } @@ -299,15 +299,15 @@ TEST_F(TlsConnectTest, TLS13NonCompatModeSessionID) { MakeTlsFilter<TlsSessionIDInjectFilter>(server_); client_->ExpectSendAlert(kTlsAlertIllegalParameter); - server_->ExpectSendAlert(kTlsAlertBadRecordMac); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); - server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); + server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE); } static const uint8_t kCannedCcs[] = { - kTlsChangeCipherSpecType, + ssl_ct_change_cipher_spec, SSL_LIBRARY_VERSION_TLS_1_2 >> 8, SSL_LIBRARY_VERSION_TLS_1_2 & 0xff, 0, @@ -362,6 +362,19 @@ TEST_F(TlsConnectStreamTls13, ChangeCipherSpecBeforeClientHello12) { client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT); } +TEST_F(TlsConnectStreamTls13, ChangeCipherSpecAfterFinished13) { + EnsureTlsSetup(); + ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); + Connect(); + SendReceive(10); + // Client sends CCS after the handshake. + client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs))); + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); + server_->ExpectReadWriteError(); + server_->ReadBytes(); + EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code()); +} + TEST_F(TlsConnectDatagram13, CompatModeDtlsClient) { EnsureTlsSetup(); client_->SetOption(SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE); @@ -370,14 +383,14 @@ TEST_F(TlsConnectDatagram13, CompatModeDtlsClient) { Connect(); ASSERT_EQ(2U, client_records->count()); // CH, Fin - EXPECT_EQ(kTlsHandshakeType, client_records->record(0).header.content_type()); - EXPECT_EQ(kTlsApplicationDataType, + EXPECT_EQ(ssl_ct_handshake, client_records->record(0).header.content_type()); + EXPECT_EQ(ssl_ct_application_data, client_records->record(1).header.content_type()); ASSERT_EQ(6U, server_records->count()); // SH, EE, CT, CV, Fin, Ack - EXPECT_EQ(kTlsHandshakeType, server_records->record(0).header.content_type()); + EXPECT_EQ(ssl_ct_handshake, server_records->record(0).header.content_type()); for (size_t i = 1; i < server_records->count(); ++i) { - EXPECT_EQ(kTlsApplicationDataType, + EXPECT_EQ(ssl_ct_application_data, server_records->record(i).header.content_type()); } } @@ -422,12 +435,12 @@ TEST_F(TlsConnectDatagram13, CompatModeDtlsServer) { client_->Handshake(); ASSERT_EQ(1U, client_records->count()); - EXPECT_EQ(kTlsHandshakeType, client_records->record(0).header.content_type()); + EXPECT_EQ(ssl_ct_handshake, client_records->record(0).header.content_type()); ASSERT_EQ(5U, server_records->count()); // SH, EE, CT, CV, Fin - EXPECT_EQ(kTlsHandshakeType, server_records->record(0).header.content_type()); + EXPECT_EQ(ssl_ct_handshake, server_records->record(0).header.content_type()); for (size_t i = 1; i < server_records->count(); ++i) { - EXPECT_EQ(kTlsApplicationDataType, + EXPECT_EQ(ssl_ct_application_data, server_records->record(i).header.content_type()); } diff --git a/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc index 100595732..cafbcce68 100644 --- a/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc @@ -151,6 +151,7 @@ class SSLv2ClientHelloTestF : public TlsConnectTestBase { void SetUp() override { TlsConnectTestBase::SetUp(); filter_ = MakeTlsFilter<SSLv2ClientHelloFilter>(client_, version_); + server_->SetOption(SSL_ENABLE_V2_COMPATIBLE_HELLO, PR_TRUE); } void SetExpectedVersion(uint16_t version) { @@ -197,6 +198,27 @@ TEST_P(SSLv2ClientHelloTest, Connect) { Connect(); } +TEST_P(SSLv2ClientHelloTest, ConnectDisabled) { + server_->SetOption(SSL_ENABLE_V2_COMPATIBLE_HELLO, PR_FALSE); + SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA); + + StartConnect(); + client_->Handshake(); // Send the modified ClientHello. + server_->Handshake(); // Read some. + // The problem here is that the v2 ClientHello puts the version where the v3 + // ClientHello puts a version number. So the version number (0x0301+) appears + // to be a length and server blocks waiting for that much data. + EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); + + // This is usually what happens with v2-compatible: the server hangs. + // But to be certain, feed in more data to see if an error comes out. + uint8_t zeros[SSL_LIBRARY_VERSION_TLS_1_2] = {0}; + client_->SendDirect(DataBuffer(zeros, sizeof(zeros))); + ExpectAlert(server_, kTlsAlertIllegalParameter); + server_->Handshake(); + client_->Handshake(); +} + // Sending a v2 ClientHello after a no-op v3 record must fail. TEST_P(SSLv2ClientHelloTest, ConnectAfterEmptyV3Record) { DataBuffer buffer; @@ -328,6 +350,30 @@ TEST_P(SSLv2ClientHelloTest, RequireSafeRenegotiationWithSCSV) { Connect(); } +TEST_P(SSLv2ClientHelloTest, CheckServerRandom) { + ConfigureSessionCache(RESUME_NONE, RESUME_NONE); + SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA); + + static const size_t random_len = 32; + uint8_t srandom1[random_len]; + uint8_t z[random_len] = {0}; + + auto sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello); + Connect(); + ASSERT_TRUE(sh->buffer().len() > (random_len + 2)); + memcpy(srandom1, sh->buffer().data() + 2, random_len); + EXPECT_NE(0, memcmp(srandom1, z, random_len)); + + Reset(); + sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello); + Connect(); + ASSERT_TRUE(sh->buffer().len() > (random_len + 2)); + const uint8_t* srandom2 = sh->buffer().data() + 2; + + EXPECT_NE(0, memcmp(srandom2, z, random_len)); + EXPECT_NE(0, memcmp(srandom1, srandom2, random_len)); +} + // Connect to the server with TLS 1.1, signalling that this is a fallback from // a higher version. As the server doesn't support anything higher than TLS 1.1 // it must accept the connection. diff --git a/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc index 4e9099561..ffc0893e9 100644 --- a/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc @@ -11,7 +11,7 @@ #include "sslproto.h" #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" @@ -48,7 +48,6 @@ TEST_P(TlsConnectGeneric, ServerNegotiateTls12) { SSL_LIBRARY_VERSION_TLS_1_2); Connect(); } -#ifndef TLS_1_3_DRAFT_VERSION // Test the ServerRandom version hack from // [draft-ietf-tls-tls13-11 Section 6.3.1.1]. @@ -56,71 +55,116 @@ TEST_P(TlsConnectGeneric, ServerNegotiateTls12) { // two validate that we can also detect fallback using the // SSL_SetDowngradeCheckVersion() API. TEST_F(TlsConnectTest, TestDowngradeDetectionToTls11) { + client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE); MakeTlsFilter<TlsClientHelloVersionSetter>(client_, SSL_LIBRARY_VERSION_TLS_1_1); - ConnectExpectFail(); - ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code()); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); + server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); } -/* Attempt to negotiate the bogus DTLS 1.1 version. */ +// Attempt to negotiate the bogus DTLS 1.1 version. TEST_F(DtlsConnectTest, TestDtlsVersion11) { MakeTlsFilter<TlsClientHelloVersionSetter>(client_, ((~0x0101) & 0xffff)); - ConnectExpectFail(); + ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); // It's kind of surprising that SSL_ERROR_NO_CYPHER_OVERLAP is // what is returned here, but this is deliberate in ssl3_HandleAlert(). - EXPECT_EQ(SSL_ERROR_NO_CYPHER_OVERLAP, client_->error_code()); - EXPECT_EQ(SSL_ERROR_UNSUPPORTED_VERSION, server_->error_code()); + client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); + server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION); } -// Disabled as long as we have draft version. TEST_F(TlsConnectTest, TestDowngradeDetectionToTls12) { - EnsureTlsSetup(); - MakeTlsFilter<TlsClientHelloVersionSetter>(client_, - SSL_LIBRARY_VERSION_TLS_1_2); + client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE); + MakeTlsFilter<TlsExtensionDropper>(client_, ssl_tls13_supported_versions_xtn); client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, SSL_LIBRARY_VERSION_TLS_1_3); server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, SSL_LIBRARY_VERSION_TLS_1_3); - ConnectExpectFail(); - ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code()); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); + server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); +} + +// Disabling downgrade checks will be caught when the Finished MAC check fails. +TEST_F(TlsConnectTest, TestDisableDowngradeDetection) { + client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_FALSE); + MakeTlsFilter<TlsExtensionDropper>(client_, ssl_tls13_supported_versions_xtn); + client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_3); + server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_3); + ConnectExpectAlert(server_, kTlsAlertDecryptError); + client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); + server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); } // TLS 1.1 clients do not check the random values, so we should // instead get a handshake failure alert from the server. TEST_F(TlsConnectTest, TestDowngradeDetectionToTls10) { + // Setting the option here has no effect. + client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE); MakeTlsFilter<TlsClientHelloVersionSetter>(client_, SSL_LIBRARY_VERSION_TLS_1_0); client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, SSL_LIBRARY_VERSION_TLS_1_1); server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, SSL_LIBRARY_VERSION_TLS_1_2); - ConnectExpectFail(); - ASSERT_EQ(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE, server_->error_code()); - ASSERT_EQ(SSL_ERROR_DECRYPT_ERROR_ALERT, client_->error_code()); + ConnectExpectAlert(server_, kTlsAlertDecryptError); + server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); + client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); } TEST_F(TlsConnectTest, TestFallbackFromTls12) { - EnsureTlsSetup(); + client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE); client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_2); client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1, SSL_LIBRARY_VERSION_TLS_1_1); server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1, SSL_LIBRARY_VERSION_TLS_1_2); - ConnectExpectFail(); - ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code()); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); + server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); +} + +static SECStatus AllowFalseStart(PRFileDesc* fd, void* arg, + PRBool* can_false_start) { + bool* false_start_attempted = reinterpret_cast<bool*>(arg); + *false_start_attempted = true; + *can_false_start = PR_TRUE; + return SECSuccess; +} + +// If we disable the downgrade check, the sentinel is still generated, and we +// disable false start instead. +TEST_F(TlsConnectTest, DisableFalseStartOnFallback) { + // Don't call client_->EnableFalseStart(), because that sets the client up for + // success, and we want false start to fail. + client_->SetOption(SSL_ENABLE_FALSE_START, PR_TRUE); + bool false_start_attempted = false; + EXPECT_EQ(SECSuccess, + SSL_SetCanFalseStartCallback(client_->ssl_fd(), AllowFalseStart, + &false_start_attempted)); + + client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_3); + client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_2); + server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_3); + Connect(); + EXPECT_FALSE(false_start_attempted); } TEST_F(TlsConnectTest, TestFallbackFromTls13) { - EnsureTlsSetup(); + client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE); client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_3); client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, SSL_LIBRARY_VERSION_TLS_1_2); server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1, SSL_LIBRARY_VERSION_TLS_1_3); - ConnectExpectFail(); - ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code()); + ConnectExpectAlert(client_, kTlsAlertIllegalParameter); + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); + server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); } -#endif TEST_P(TlsConnectGeneric, TestFallbackSCSVVersionMatch) { client_->SetOption(SSL_ENABLE_FALLBACK_SCSV, PR_TRUE); @@ -132,6 +176,7 @@ TEST_P(TlsConnectGenericPre13, TestFallbackSCSVVersionMismatch) { server_->SetVersionRange(version_, version_ + 1); ConnectExpectAlert(server_, kTlsAlertInappropriateFallback); client_->CheckErrorCode(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT); + server_->CheckErrorCode(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT); } // The TLS v1.3 spec section C.4 states that 'Implementations MUST NOT send or @@ -158,7 +203,7 @@ TEST_P(TlsConnectGeneric, AlertBeforeServerHello) { static const uint8_t kWarningAlert[] = {kTlsAlertWarning, kTlsAlertUnrecognizedName}; DataBuffer alert; - TlsAgentTestBase::MakeRecord(variant_, kTlsAlertType, + TlsAgentTestBase::MakeRecord(variant_, ssl_ct_alert, SSL_LIBRARY_VERSION_TLS_1_0, kWarningAlert, PR_ARRAY_SIZE(kWarningAlert), &alert); client_->adapter()->PacketReceived(alert); diff --git a/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc index 09d7801e9..a75dbb7aa 100644 --- a/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc @@ -12,7 +12,7 @@ #include "sslproto.h" #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" diff --git a/security/nss/gtests/ssl_gtest/test_io.cc b/security/nss/gtests/ssl_gtest/test_io.cc index d76b3526c..6d792c520 100644 --- a/security/nss/gtests/ssl_gtest/test_io.cc +++ b/security/nss/gtests/ssl_gtest/test_io.cc @@ -31,6 +31,20 @@ ScopedPRFileDesc DummyPrSocket::CreateFD() { return DummyIOLayerMethods::CreateFD(test_fd_identity, this); } +void DummyPrSocket::Reset() { + auto p = peer_.lock(); + peer_.reset(); + if (p) { + p->peer_.reset(); + p->Reset(); + } + while (!input_.empty()) { + input_.pop(); + } + filter_ = nullptr; + write_error_ = 0; +} + void DummyPrSocket::PacketReceived(const DataBuffer &packet) { input_.push(Packet(packet)); } @@ -42,6 +56,12 @@ int32_t DummyPrSocket::Read(PRFileDesc *f, void *data, int32_t len) { return -1; } + auto dst = peer_.lock(); + if (!dst) { + PR_SetError(PR_NOT_CONNECTED_ERROR, 0); + return -1; + } + if (input_.empty()) { LOGV("Read --> wouldblock " << len); PR_SetError(PR_WOULD_BLOCK_ERROR, 0); @@ -74,6 +94,12 @@ int32_t DummyPrSocket::Recv(PRFileDesc *f, void *buf, int32_t buflen, return Read(f, buf, buflen); } + auto dst = peer_.lock(); + if (!dst) { + PR_SetError(PR_NOT_CONNECTED_ERROR, 0); + return -1; + } + if (input_.empty()) { PR_SetError(PR_WOULD_BLOCK_ERROR, 0); return -1; @@ -101,7 +127,7 @@ int32_t DummyPrSocket::Write(PRFileDesc *f, const void *buf, int32_t length) { auto dst = peer_.lock(); if (!dst) { - PR_SetError(PR_IO_ERROR, 0); + PR_SetError(PR_NOT_CONNECTED_ERROR, 0); return -1; } diff --git a/security/nss/gtests/ssl_gtest/test_io.h b/security/nss/gtests/ssl_gtest/test_io.h index 8327373ce..062ae86c8 100644 --- a/security/nss/gtests/ssl_gtest/test_io.h +++ b/security/nss/gtests/ssl_gtest/test_io.h @@ -17,7 +17,7 @@ #include "databuffer.h" #include "dummy_io.h" #include "prio.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "sslt.h" namespace nss_test { diff --git a/security/nss/gtests/ssl_gtest/tls_agent.cc b/security/nss/gtests/ssl_gtest/tls_agent.cc index 9bed1ce1b..fb66196b5 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.cc +++ b/security/nss/gtests/ssl_gtest/tls_agent.cc @@ -15,6 +15,9 @@ #include "tls_filter.h" #include "tls_parser.h" +// This is an internal header, used to get DTLS_1_3_DRAFT_VERSION. +#include "ssl3prot.h" + extern "C" { // This is not something that should make you happy. #include "libssl_internals.h" @@ -23,7 +26,7 @@ extern "C" { #define GTEST_HAS_RTTI 0 #include "gtest/gtest.h" #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" extern std::string g_working_dir_path; @@ -53,7 +56,7 @@ static const uint8_t kCannedTls13ServerHello[] = { 0x00, 0x1d, 0x00, 0x20, 0xc2, 0xcf, 0x23, 0x17, 0x64, 0x23, 0x03, 0xf0, 0xfb, 0x45, 0x98, 0x26, 0xd1, 0x65, 0x24, 0xa1, 0x6c, 0xa9, 0x80, 0x8f, 0x2c, 0xac, 0x0a, 0xea, 0x53, 0x3a, 0xcb, 0xe3, 0x08, - 0x84, 0xae, 0x19, 0x00, 0x2b, 0x00, 0x02, 0x7f, kD13}; + 0x84, 0xae, 0x19, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04}; TlsAgent::TlsAgent(const std::string& nm, Role rl, SSLProtocolVariant var) : name_(nm), @@ -226,6 +229,7 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc* modelSocket) { bool TlsAgent::MaybeSetResumptionToken() { if (!resumption_token_.empty()) { + LOG("setting external resumption token"); SECStatus rv = SSL_SetResumptionToken(ssl_fd(), resumption_token_.data(), resumption_token_.size()); @@ -583,6 +587,7 @@ void TlsAgent::CheckAuthType(SSLAuthType auth, // switch statement because default label is different. switch (auth) { case ssl_auth_rsa_sign: + case ssl_auth_rsa_pss: EXPECT_EQ(ssl_auth_rsa_decrypt, csinfo_.authAlgorithm) << "authAlgorithm for RSA is always decrypt"; break; @@ -934,8 +939,8 @@ void TlsAgent::SendRecordDirect(const TlsRecord& record) { SendDirect(buf); } -static bool ErrorIsNonFatal(PRErrorCode code) { - return code == PR_WOULD_BLOCK_ERROR || code == SSL_ERROR_RX_SHORT_DTLS_READ; +static bool ErrorIsFatal(PRErrorCode code) { + return code != PR_WOULD_BLOCK_ERROR && code != SSL_ERROR_RX_SHORT_DTLS_READ; } void TlsAgent::SendData(size_t bytes, size_t blocksize) { @@ -975,7 +980,7 @@ bool TlsAgent::SendEncryptedRecord(const std::shared_ptr<TlsCipherSpec>& spec, LOGV("Encrypting " << buf.len() << " bytes"); // Ensure that we are doing TLS 1.3. EXPECT_GE(expected_version_, SSL_LIBRARY_VERSION_TLS_1_3); - TlsRecordHeader header(variant_, expected_version_, kTlsApplicationDataType, + TlsRecordHeader header(variant_, expected_version_, ssl_ct_application_data, seq); DataBuffer padded = buf; padded.Write(padded.len(), ct, 1); @@ -994,28 +999,39 @@ bool TlsAgent::SendEncryptedRecord(const std::shared_ptr<TlsCipherSpec>& spec, void TlsAgent::ReadBytes(size_t amount) { uint8_t block[16384]; - int32_t rv = PR_Read(ssl_fd(), block, (std::min)(amount, sizeof(block))); - LOGV("ReadBytes " << rv); - int32_t err; + size_t remaining = amount; + while (remaining > 0) { + int32_t rv = PR_Read(ssl_fd(), block, (std::min)(amount, sizeof(block))); + LOGV("ReadBytes " << rv); - if (rv >= 0) { - size_t count = static_cast<size_t>(rv); - for (size_t i = 0; i < count; ++i) { - ASSERT_EQ(recv_ctr_ & 0xff, block[i]); - recv_ctr_++; - } - } else { - err = PR_GetError(); - LOG("Read error " << PORT_ErrorToName(err) << ": " - << PORT_ErrorToString(err)); - if (err != PR_WOULD_BLOCK_ERROR && expect_readwrite_error_) { - error_code_ = err; - expect_readwrite_error_ = false; + if (rv > 0) { + size_t count = static_cast<size_t>(rv); + for (size_t i = 0; i < count; ++i) { + ASSERT_EQ(recv_ctr_ & 0xff, block[i]); + recv_ctr_++; + } + remaining -= rv; + } else { + PRErrorCode err = 0; + if (rv < 0) { + err = PR_GetError(); + LOG("Read error " << PORT_ErrorToName(err) << ": " + << PORT_ErrorToString(err)); + if (err != PR_WOULD_BLOCK_ERROR && expect_readwrite_error_) { + error_code_ = err; + expect_readwrite_error_ = false; + } + } + if (err != 0 && ErrorIsFatal(err)) { + // If we hit a fatal error, we're done. + remaining = 0; + } + break; } } // If closed, then don't bother waiting around. - if (rv > 0 || (rv < 0 && ErrorIsNonFatal(err))) { + if (remaining) { LOGV("Re-arming"); Poller::Instance()->Wait(READABLE_EVENT, adapter_, this, &TlsAgent::ReadableCallback); @@ -1104,7 +1120,7 @@ void TlsAgentTestBase::MakeRecord(SSLProtocolVariant variant, uint8_t type, if (variant == ssl_variant_stream) { index = out->Write(index, version, 2); } else if (version >= SSL_LIBRARY_VERSION_TLS_1_3 && - type == kTlsApplicationDataType) { + type == ssl_ct_application_data) { uint32_t epoch = (sequence_number >> 48) & 0x3; uint32_t seqno = sequence_number & ((1ULL << 30) - 1); index = out->Write(index, (epoch << 30) | seqno, 4); @@ -1157,10 +1173,10 @@ void TlsAgentTestBase::MakeTrivialHandshakeRecord(uint8_t hs_type, size_t hs_len, DataBuffer* out) { size_t index = 0; - index = out->Write(index, kTlsHandshakeType, 1); // Content Type - index = out->Write(index, 3, 1); // Version high - index = out->Write(index, 1, 1); // Version low - index = out->Write(index, 4 + hs_len, 2); // Length + index = out->Write(index, ssl_ct_handshake, 1); // Content Type + index = out->Write(index, 3, 1); // Version high + index = out->Write(index, 1, 1); // Version low + index = out->Write(index, 4 + hs_len, 2); // Length index = out->Write(index, hs_type, 1); // Handshake record type. index = out->Write(index, hs_len, 3); // Handshake length @@ -1173,6 +1189,11 @@ DataBuffer TlsAgentTestBase::MakeCannedTls13ServerHello() { DataBuffer sh(kCannedTls13ServerHello, sizeof(kCannedTls13ServerHello)); if (variant_ == ssl_variant_datagram) { sh.Write(0, SSL_LIBRARY_VERSION_DTLS_1_2_WIRE, 2); + // The version should be at the end. + uint32_t v; + EXPECT_TRUE(sh.Read(sh.len() - 2, 2, &v)); + EXPECT_EQ(static_cast<uint32_t>(SSL_LIBRARY_VERSION_TLS_1_3), v); + sh.Write(sh.len() - 2, 0x7f00 | DTLS_1_3_DRAFT_VERSION, 2); } return sh; } diff --git a/security/nss/gtests/ssl_gtest/tls_agent.h b/security/nss/gtests/ssl_gtest/tls_agent.h index a93d0c6ee..020221868 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.h +++ b/security/nss/gtests/ssl_gtest/tls_agent.h @@ -10,9 +10,6 @@ #include "prio.h" #include "ssl.h" -// This is an internal header, used to get TLS_1_3_DRAFT_VERSION. -#include "ssl3prot.h" - #include <functional> #include <iostream> @@ -20,7 +17,8 @@ #define GTEST_HAS_RTTI 0 #include "gtest/gtest.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" +#include "scoped_ptrs_ssl.h" extern bool g_ssl_gtest_verbose; @@ -60,8 +58,6 @@ typedef std::function<int32_t(TlsAgent* agent, const SECItem* srvNameArr, PRUint32 srvNameArrSize)> SniCallbackFunction; -static const uint8_t kD13 = TLS_1_3_DRAFT_VERSION; - class TlsAgent : public PollTarget { public: enum Role { CLIENT, SERVER }; diff --git a/security/nss/gtests/ssl_gtest/tls_connect.cc b/security/nss/gtests/ssl_gtest/tls_connect.cc index 68f6d21e9..c48ae38ec 100644 --- a/security/nss/gtests/ssl_gtest/tls_connect.cc +++ b/security/nss/gtests/ssl_gtest/tls_connect.cc @@ -14,7 +14,7 @@ extern "C" { #include "databuffer.h" #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" #include "sslproto.h" extern std::string g_working_dir_path; @@ -559,13 +559,15 @@ void TlsConnectTestBase::CheckResumption(SessionResumptionMode expected) { EXPECT_EQ(stateless_count, stats->hsh_sid_stateless_resumes); if (expected != RESUME_NONE) { - if (client_->version() < SSL_LIBRARY_VERSION_TLS_1_3) { + if (client_->version() < SSL_LIBRARY_VERSION_TLS_1_3 && + client_->GetResumptionToken().size() == 0) { // Check that the last two session ids match. ASSERT_EQ(1U + expected_resumptions_, session_ids_.size()); EXPECT_EQ(session_ids_[session_ids_.size() - 1], session_ids_[session_ids_.size() - 2]); } else { - // TLS 1.3 only uses tickets. + // We've either chosen TLS 1.3 or are using an external resumption token, + // both of which only use tickets. EXPECT_TRUE(expected & RESUME_TICKET); } } diff --git a/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc b/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc new file mode 100644 index 000000000..3c860a0b2 --- /dev/null +++ b/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc @@ -0,0 +1,470 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <ctime> + +#include "secerr.h" +#include "ssl.h" + +#include "gtest_utils.h" +#include "tls_agent.h" +#include "tls_connect.h" + +namespace nss_test { + +static const char* kDummySni("dummy.invalid"); + +std::vector<uint16_t> kDefaultSuites = {TLS_AES_256_GCM_SHA384, + TLS_AES_128_GCM_SHA256}; +std::vector<uint16_t> kChaChaSuite = {TLS_CHACHA20_POLY1305_SHA256}; +std::vector<uint16_t> kBogusSuites = {0}; +std::vector<uint16_t> kTls12Suites = { + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256}; + +static void NamedGroup2ECParams(SSLNamedGroup group, SECItem* params) { + auto groupDef = ssl_LookupNamedGroup(group); + ASSERT_NE(nullptr, groupDef); + + auto oidData = SECOID_FindOIDByTag(groupDef->oidTag); + ASSERT_NE(nullptr, oidData); + ASSERT_NE(nullptr, + SECITEM_AllocItem(nullptr, params, (2 + oidData->oid.len))); + + /* + * params->data needs to contain the ASN encoding of an object ID (OID) + * representing the named curve. The actual OID is in + * oidData->oid.data so we simply prepend 0x06 and OID length + */ + params->data[0] = SEC_ASN1_OBJECT_ID; + params->data[1] = oidData->oid.len; + memcpy(params->data + 2, oidData->oid.data, oidData->oid.len); +} + +/* Checksum is a 4-byte array. */ +static void UpdateEsniKeysChecksum(DataBuffer* buf) { + SECStatus rv; + PRUint8 sha256[32]; + + /* Stomp the checksum. */ + PORT_Memset(buf->data() + 2, 0, 4); + + rv = PK11_HashBuf(ssl3_HashTypeToOID(ssl_hash_sha256), sha256, buf->data(), + buf->len()); + ASSERT_EQ(SECSuccess, rv); + buf->Write(2, sha256, 4); +} + +static void GenerateEsniKey(time_t windowStart, SSLNamedGroup group, + std::vector<uint16_t>& cipher_suites, + DataBuffer* record, + ScopedSECKEYPublicKey* pubKey = nullptr, + ScopedSECKEYPrivateKey* privKey = nullptr) { + SECKEYECParams ecParams = {siBuffer, NULL, 0}; + NamedGroup2ECParams(group, &ecParams); + + SECKEYPublicKey* pub = nullptr; + SECKEYPrivateKey* priv = SECKEY_CreateECPrivateKey(&ecParams, &pub, nullptr); + ASSERT_NE(nullptr, priv); + SECITEM_FreeItem(&ecParams, PR_FALSE); + PRUint8 encoded[1024]; + unsigned int encoded_len; + + SECStatus rv = SSL_EncodeESNIKeys( + &cipher_suites[0], cipher_suites.size(), group, pub, 100, windowStart, + windowStart + 10, encoded, &encoded_len, sizeof(encoded)); + ASSERT_EQ(SECSuccess, rv); + ASSERT_GT(encoded_len, 0U); + + if (pubKey) { + pubKey->reset(pub); + } else { + SECKEY_DestroyPublicKey(pub); + } + if (privKey) { + privKey->reset(priv); + } else { + SECKEY_DestroyPrivateKey(priv); + } + record->Truncate(0); + record->Write(0, encoded, encoded_len); +} + +static void SetupEsni(const std::shared_ptr<TlsAgent>& client, + const std::shared_ptr<TlsAgent>& server, + SSLNamedGroup group = ssl_grp_ec_curve25519) { + ScopedSECKEYPublicKey pub; + ScopedSECKEYPrivateKey priv; + DataBuffer record; + + GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record, + &pub, &priv); + SECStatus rv = SSL_SetESNIKeyPair(server->ssl_fd(), priv.get(), record.data(), + record.len()); + ASSERT_EQ(SECSuccess, rv); + + rv = SSL_EnableESNI(client->ssl_fd(), record.data(), record.len(), kDummySni); + ASSERT_EQ(SECSuccess, rv); +} + +static void CheckSniExtension(const DataBuffer& data) { + TlsParser parser(data.data(), data.len()); + uint32_t tmp; + ASSERT_TRUE(parser.Read(&tmp, 2)); + ASSERT_EQ(parser.remaining(), tmp); + ASSERT_TRUE(parser.Read(&tmp, 1)); + ASSERT_EQ(0U, tmp); /* sni_nametype_hostname */ + DataBuffer name; + ASSERT_TRUE(parser.ReadVariable(&name, 2)); + ASSERT_EQ(0U, parser.remaining()); + DataBuffer expected(reinterpret_cast<const uint8_t*>(kDummySni), + strlen(kDummySni)); + ASSERT_EQ(expected, name); +} + +static void ClientInstallEsni(std::shared_ptr<TlsAgent>& agent, + const DataBuffer& record, PRErrorCode err = 0) { + SECStatus rv = + SSL_EnableESNI(agent->ssl_fd(), record.data(), record.len(), kDummySni); + if (err == 0) { + ASSERT_EQ(SECSuccess, rv); + } else { + ASSERT_EQ(SECFailure, rv); + ASSERT_EQ(err, PORT_GetError()); + } +} + +TEST_P(TlsAgentTestClient13, EsniInstall) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record); + ClientInstallEsni(agent_, record); +} + +// The next set of tests fail at setup time. +TEST_P(TlsAgentTestClient13, EsniInvalidHash) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record); + record.data()[2]++; + ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS); +} + +TEST_P(TlsAgentTestClient13, EsniInvalidVersion) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record); + record.Write(0, 0xffff, 2); + ClientInstallEsni(agent_, record, SSL_ERROR_UNSUPPORTED_VERSION); +} + +TEST_P(TlsAgentTestClient13, EsniShort) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record); + record.Truncate(record.len() - 1); + UpdateEsniKeysChecksum(&record); + ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS); +} + +TEST_P(TlsAgentTestClient13, EsniLong) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record); + record.Write(record.len(), 1, 1); + UpdateEsniKeysChecksum(&record); + ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS); +} + +TEST_P(TlsAgentTestClient13, EsniExtensionMismatch) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record); + record.Write(record.len() - 1, 1, 1); + UpdateEsniKeysChecksum(&record); + ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS); +} + +// The following tests fail by ignoring the Esni block. +TEST_P(TlsAgentTestClient13, EsniUnknownGroup) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record); + record.Write(8, 0xffff, 2); // Fake group + UpdateEsniKeysChecksum(&record); + ClientInstallEsni(agent_, record, 0); + auto filter = + MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn); + agent_->Handshake(); + ASSERT_EQ(TlsAgent::STATE_CONNECTING, agent_->state()); + ASSERT_TRUE(!filter->captured()); +} + +TEST_P(TlsAgentTestClient13, EsniUnknownCS) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kBogusSuites, &record); + ClientInstallEsni(agent_, record, 0); + auto filter = + MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn); + agent_->Handshake(); + ASSERT_EQ(TlsAgent::STATE_CONNECTING, agent_->state()); + ASSERT_TRUE(!filter->captured()); +} + +TEST_P(TlsAgentTestClient13, EsniInvalidCS) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kTls12Suites, &record); + UpdateEsniKeysChecksum(&record); + ClientInstallEsni(agent_, record, 0); + auto filter = + MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn); + agent_->Handshake(); + ASSERT_EQ(TlsAgent::STATE_CONNECTING, agent_->state()); + ASSERT_TRUE(!filter->captured()); +} + +TEST_P(TlsAgentTestClient13, EsniNotReady) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0) + 1000, ssl_grp_ec_curve25519, kDefaultSuites, + &record); + ClientInstallEsni(agent_, record, 0); + auto filter = + MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn); + agent_->Handshake(); + ASSERT_TRUE(!filter->captured()); +} + +TEST_P(TlsAgentTestClient13, EsniExpired) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0) - 1000, ssl_grp_ec_curve25519, kDefaultSuites, + &record); + ClientInstallEsni(agent_, record, 0); + auto filter = + MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn); + agent_->Handshake(); + ASSERT_TRUE(!filter->captured()); +} + +TEST_P(TlsAgentTestClient13, NoSniSoNoEsni) { + EnsureInit(); + DataBuffer record; + GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record); + SSL_SetURL(agent_->ssl_fd(), ""); + ClientInstallEsni(agent_, record, 0); + auto filter = + MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn); + agent_->Handshake(); + ASSERT_TRUE(!filter->captured()); +} + +static int32_t SniCallback(TlsAgent* agent, const SECItem* srvNameAddr, + PRUint32 srvNameArrSize) { + EXPECT_EQ(1U, srvNameArrSize); + SECItem expected = { + siBuffer, reinterpret_cast<unsigned char*>(const_cast<char*>("server")), + 6}; + EXPECT_TRUE(!SECITEM_CompareItem(&expected, &srvNameAddr[0])); + return SECSuccess; +} + +TEST_P(TlsConnectTls13, ConnectEsni) { + EnsureTlsSetup(); + SetupEsni(client_, server_); + auto cFilterSni = + MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn); + auto cFilterEsni = + MakeTlsFilter<TlsExtensionCapture>(client_, ssl_tls13_encrypted_sni_xtn); + client_->SetFilter(std::make_shared<ChainedPacketFilter>( + ChainedPacketFilterInit({cFilterSni, cFilterEsni}))); + auto sfilter = + MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn); + sfilter->EnableDecryption(); + server_->SetSniCallback(SniCallback); + Connect(); + CheckSniExtension(cFilterSni->extension()); + ASSERT_TRUE(cFilterEsni->captured()); + // Check that our most preferred suite got chosen. + uint32_t suite; + ASSERT_TRUE(cFilterEsni->extension().Read(0, 2, &suite)); + ASSERT_EQ(TLS_AES_128_GCM_SHA256, static_cast<PRUint16>(suite)); + ASSERT_TRUE(!sfilter->captured()); +} + +TEST_P(TlsConnectTls13, ConnectEsniHrr) { + EnsureTlsSetup(); + const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp384r1}; + server_->ConfigNamedGroups(groups); + SetupEsni(client_, server_); + auto hrr_capture = MakeTlsFilter<TlsHandshakeRecorder>( + server_, kTlsHandshakeHelloRetryRequest); + auto filter = + MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn); + auto cfilter = + MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn); + server_->SetSniCallback(SniCallback); + Connect(); + CheckSniExtension(cfilter->extension()); + EXPECT_NE(0UL, hrr_capture->buffer().len()); +} + +TEST_P(TlsConnectTls13, ConnectEsniNoDummy) { + EnsureTlsSetup(); + ScopedSECKEYPublicKey pub; + ScopedSECKEYPrivateKey priv; + DataBuffer record; + + GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record, + &pub, &priv); + SECStatus rv = SSL_SetESNIKeyPair(server_->ssl_fd(), priv.get(), + record.data(), record.len()); + ASSERT_EQ(SECSuccess, rv); + rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), ""); + ASSERT_EQ(SECSuccess, rv); + + auto cfilter = + MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn); + auto sfilter = + MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn); + server_->SetSniCallback(SniCallback); + Connect(); + ASSERT_TRUE(!cfilter->captured()); + ASSERT_TRUE(!sfilter->captured()); +} + +TEST_P(TlsConnectTls13, ConnectEsniNullDummy) { + EnsureTlsSetup(); + ScopedSECKEYPublicKey pub; + ScopedSECKEYPrivateKey priv; + DataBuffer record; + + GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record, + &pub, &priv); + SECStatus rv = SSL_SetESNIKeyPair(server_->ssl_fd(), priv.get(), + record.data(), record.len()); + ASSERT_EQ(SECSuccess, rv); + rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), nullptr); + ASSERT_EQ(SECSuccess, rv); + + auto cfilter = + MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn); + auto sfilter = + MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn); + server_->SetSniCallback(SniCallback); + Connect(); + ASSERT_TRUE(!cfilter->captured()); + ASSERT_TRUE(!sfilter->captured()); +} + +/* Tell the client that it supports AES but the server that it supports ChaCha + */ +TEST_P(TlsConnectTls13, ConnectEsniCSMismatch) { + EnsureTlsSetup(); + ScopedSECKEYPublicKey pub; + ScopedSECKEYPrivateKey priv; + DataBuffer record; + + GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record, + &pub, &priv); + PRUint8 encoded[1024]; + unsigned int encoded_len; + + SECStatus rv = SSL_EncodeESNIKeys( + &kChaChaSuite[0], kChaChaSuite.size(), ssl_grp_ec_curve25519, pub.get(), + 100, time(0), time(0) + 10, encoded, &encoded_len, sizeof(encoded)); + rv = SSL_SetESNIKeyPair(server_->ssl_fd(), priv.get(), encoded, encoded_len); + ASSERT_EQ(SECSuccess, rv); + rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), ""); + ASSERT_EQ(SECSuccess, rv); + ConnectExpectAlert(server_, illegal_parameter); + server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); +} + +TEST_P(TlsConnectTls13, ConnectEsniP256) { + EnsureTlsSetup(); + SetupEsni(client_, server_, ssl_grp_ec_secp256r1); + auto cfilter = + MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn); + auto sfilter = + MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn); + server_->SetSniCallback(SniCallback); + Connect(); + CheckSniExtension(cfilter->extension()); + ASSERT_TRUE(!sfilter->captured()); +} + +TEST_P(TlsConnectTls13, ConnectMismatchedEsniKeys) { + EnsureTlsSetup(); + SetupEsni(client_, server_); + // Now install a new set of keys on the client, so we have a mismatch. + DataBuffer record; + GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record); + ClientInstallEsni(client_, record, 0); + ConnectExpectAlert(server_, illegal_parameter); + server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); +} + +TEST_P(TlsConnectTls13, ConnectDamagedEsniExtensionCH) { + EnsureTlsSetup(); + SetupEsni(client_, server_); + auto filter = MakeTlsFilter<TlsExtensionDamager>( + client_, ssl_tls13_encrypted_sni_xtn, 50); // in the ciphertext + ConnectExpectAlert(server_, illegal_parameter); + server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); +} + +TEST_P(TlsConnectTls13, ConnectRemoveEsniExtensionEE) { + EnsureTlsSetup(); + SetupEsni(client_, server_); + auto filter = + MakeTlsFilter<TlsExtensionDropper>(server_, ssl_tls13_encrypted_sni_xtn); + filter->EnableDecryption(); + ConnectExpectAlert(client_, missing_extension); + client_->CheckErrorCode(SSL_ERROR_MISSING_ESNI_EXTENSION); +} + +TEST_P(TlsConnectTls13, ConnectShortEsniExtensionEE) { + EnsureTlsSetup(); + SetupEsni(client_, server_); + DataBuffer shortNonce; + auto filter = MakeTlsFilter<TlsExtensionReplacer>( + server_, ssl_tls13_encrypted_sni_xtn, shortNonce); + filter->EnableDecryption(); + ConnectExpectAlert(client_, illegal_parameter); + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_ESNI_EXTENSION); +} + +TEST_P(TlsConnectTls13, ConnectBogusEsniExtensionEE) { + EnsureTlsSetup(); + SetupEsni(client_, server_); + const uint8_t bogusNonceBuf[16] = {0}; + DataBuffer bogusNonce(bogusNonceBuf, sizeof(bogusNonceBuf)); + auto filter = MakeTlsFilter<TlsExtensionReplacer>( + server_, ssl_tls13_encrypted_sni_xtn, bogusNonce); + filter->EnableDecryption(); + ConnectExpectAlert(client_, illegal_parameter); + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_ESNI_EXTENSION); +} + +// ESNI is a commitment to doing TLS 1.3 or above. +// The TLS 1.2 server ignores ESNI and processes the dummy SNI. +// The client then aborts when it sees the server did TLS 1.2. +TEST_P(TlsConnectTls13, EsniButTLS12Server) { + EnsureTlsSetup(); + SetupEsni(client_, server_); + client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_3); + server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_2); + ConnectExpectAlert(client_, kTlsAlertProtocolVersion); + client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION); + server_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT); + ASSERT_FALSE(SSLInt_ExtensionNegotiated(server_->ssl_fd(), + ssl_tls13_encrypted_sni_xtn)); +} +} diff --git a/security/nss/gtests/ssl_gtest/tls_filter.cc b/security/nss/gtests/ssl_gtest/tls_filter.cc index aa03cba70..25ad606fc 100644 --- a/security/nss/gtests/ssl_gtest/tls_filter.cc +++ b/security/nss/gtests/ssl_gtest/tls_filter.cc @@ -131,7 +131,7 @@ PacketFilter::Action TlsRecordFilter::Filter(const DataBuffer& input, // spec to another active cipher spec (KeyUpdate for instance) AND writes // are consolidated across that change, this code could use the wrong // sequence numbers when re-encrypting records with the old keys. - if (header.content_type() == kTlsApplicationDataType) { + if (header.content_type() == ssl_ct_application_data) { in_sequence_number_ = (std::max)(in_sequence_number_, header.sequence_number() + 1); } @@ -194,7 +194,7 @@ PacketFilter::Action TlsRecordFilter::FilterRecord( uint64_t seq_num; if (header.is_dtls() || !cipher_spec_ || - header.content_type() != kTlsApplicationDataType) { + header.content_type() != ssl_ct_application_data) { seq_num = header.sequence_number(); } else { seq_num = out_sequence_number_++; @@ -277,7 +277,7 @@ bool TlsRecordHeader::Parse(bool is_dtls13, uint64_t seqno, TlsParser* parser, #ifndef UNSAFE_FUZZER_MODE // Deal with the 7 octet header. - if (content_type_ == kTlsApplicationDataType) { + if (content_type_ == ssl_ct_application_data) { uint32_t tmp; if (!parser->Read(&tmp, 4)) { return false; @@ -298,7 +298,7 @@ bool TlsRecordHeader::Parse(bool is_dtls13, uint64_t seqno, TlsParser* parser, } // Need to use the low 5 bits of the first octet too. tmp |= (content_type_ & 0x1f) << 8; - content_type_ = kTlsApplicationDataType; + content_type_ = ssl_ct_application_data; sequence_number_ = ParseSequenceNumber(seqno, tmp, 12, 1); if (!parser->ReadFromMark(&header_, parser->consumed() - mark, mark)) { @@ -308,9 +308,9 @@ bool TlsRecordHeader::Parse(bool is_dtls13, uint64_t seqno, TlsParser* parser, } // The full 13 octet header can only be used for a few types. - EXPECT_TRUE(content_type_ == kTlsAlertType || - content_type_ == kTlsHandshakeType || - content_type_ == kTlsAckType); + EXPECT_TRUE(content_type_ == ssl_ct_alert || + content_type_ == ssl_ct_handshake || + content_type_ == ssl_ct_ack); #endif } @@ -347,7 +347,7 @@ size_t TlsRecordHeader::WriteHeader(DataBuffer* buffer, size_t offset, size_t body_len) const { offset = buffer->Write(offset, content_type_, 1); if (is_dtls() && version_ >= SSL_LIBRARY_VERSION_TLS_1_3 && - content_type() == kTlsApplicationDataType) { + content_type() == ssl_ct_application_data) { // application_data records in TLS 1.3 have a different header format. // Always use the long header here for simplicity. uint32_t e = (sequence_number_ >> 48) & 0x3; @@ -377,7 +377,7 @@ bool TlsRecordFilter::Unprotect(const TlsRecordHeader& header, const DataBuffer& ciphertext, uint8_t* inner_content_type, DataBuffer* plaintext) { - if (!cipher_spec_ || header.content_type() != kTlsApplicationDataType) { + if (!cipher_spec_ || header.content_type() != ssl_ct_application_data) { *inner_content_type = header.content_type(); *plaintext = ciphertext; return true; @@ -411,7 +411,7 @@ bool TlsRecordFilter::Protect(const TlsRecordHeader& header, uint8_t inner_content_type, const DataBuffer& plaintext, DataBuffer* ciphertext, size_t padding) { - if (!cipher_spec_ || header.content_type() != kTlsApplicationDataType) { + if (!cipher_spec_ || header.content_type() != ssl_ct_application_data) { *ciphertext = plaintext; return true; } @@ -453,8 +453,7 @@ PacketFilter::Action TlsHandshakeFilter::FilterRecord( const TlsRecordHeader& record_header, const DataBuffer& input, DataBuffer* output) { // Check that the first byte is as requested. - if ((record_header.content_type() != kTlsHandshakeType) && - (record_header.content_type() != kTlsAltHandshakeType)) { + if (record_header.content_type() != ssl_ct_handshake) { return KEEP; } @@ -879,6 +878,17 @@ PacketFilter::Action TlsExtensionDropper::FilterExtension( return KEEP; } +PacketFilter::Action TlsExtensionDamager::FilterExtension( + uint16_t extension_type, const DataBuffer& input, DataBuffer* output) { + if (extension_type != extension_) { + return KEEP; + } + + *output = input; + output->data()[index_] += 73; // Increment selected for maximum damage + return CHANGE; +} + PacketFilter::Action TlsExtensionInjector::FilterHandshake( const HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) { diff --git a/security/nss/gtests/ssl_gtest/tls_filter.h b/security/nss/gtests/ssl_gtest/tls_filter.h index effda4aa0..2b6e88645 100644 --- a/security/nss/gtests/ssl_gtest/tls_filter.h +++ b/security/nss/gtests/ssl_gtest/tls_filter.h @@ -172,20 +172,19 @@ inline std::ostream& operator<<(std::ostream& stream, hdr.WriteStream(stream); stream << ' '; switch (hdr.content_type()) { - case kTlsChangeCipherSpecType: + case ssl_ct_change_cipher_spec: stream << "CCS"; break; - case kTlsAlertType: + case ssl_ct_alert: stream << "Alert"; break; - case kTlsHandshakeType: - case kTlsAltHandshakeType: + case ssl_ct_handshake: stream << "Handshake"; break; - case kTlsApplicationDataType: + case ssl_ct_application_data: stream << "Data"; break; - case kTlsAckType: + case ssl_ct_ack: stream << "ACK"; break; default: @@ -301,7 +300,7 @@ class TlsRecordRecorder : public TlsRecordFilter { TlsRecordRecorder(const std::shared_ptr<TlsAgent>& a) : TlsRecordFilter(a), filter_(false), - ct_(content_handshake), // dummy (<optional> is C++14) + ct_(ssl_ct_handshake), // dummy (<optional> is C++14) records_() {} virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& input, @@ -466,6 +465,20 @@ class TlsExtensionInjector : public TlsHandshakeFilter { const DataBuffer data_; }; +class TlsExtensionDamager : public TlsExtensionFilter { + public: + TlsExtensionDamager(const std::shared_ptr<TlsAgent>& a, uint16_t extension, + size_t index) + : TlsExtensionFilter(a), extension_(extension), index_(index) {} + virtual PacketFilter::Action FilterExtension(uint16_t extension_type, + const DataBuffer& input, + DataBuffer* output); + + private: + uint16_t extension_; + size_t index_; +}; + typedef std::function<void(void)> VoidFunction; class AfterRecordN : public TlsRecordFilter { diff --git a/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc b/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc index 45f6cf2bd..004da3b1c 100644 --- a/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc +++ b/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc @@ -11,7 +11,7 @@ #include "databuffer.h" #include "gtest_utils.h" -#include "scoped_ptrs.h" +#include "nss_scoped_ptrs.h" namespace nss_test { @@ -60,9 +60,11 @@ const std::string kHashName[] = {"None", "MD5", "SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"}; static void ImportKey(ScopedPK11SymKey* to, const DataBuffer& key, - PK11SlotInfo* slot) { + SSLHashType hash_type, PK11SlotInfo* slot) { + ASSERT_LT(hash_type, sizeof(kHashLength)); + ASSERT_LE(kHashLength[hash_type], key.len()); SECItem key_item = {siBuffer, const_cast<uint8_t*>(key.data()), - static_cast<unsigned int>(key.len())}; + static_cast<unsigned int>(kHashLength[hash_type])}; PK11SymKey* inner = PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, PK11_OriginUnwrap, @@ -106,8 +108,8 @@ class TlsHkdfTest : public ::testing::Test, } void SetUp() { - ImportKey(&k1_, kKey1, slot_.get()); - ImportKey(&k2_, kKey2, slot_.get()); + ImportKey(&k1_, kKey1, hash_type_, slot_.get()); + ImportKey(&k2_, kKey2, hash_type_, slot_.get()); } void VerifyKey(const ScopedPK11SymKey& key, const DataBuffer& expected) { @@ -183,9 +185,9 @@ TEST_P(TlsHkdfTest, HkdfKey1Only) { {/* ssl_hash_md5 */}, {/* ssl_hash_sha1 */}, {/* ssl_hash_sha224 */}, - {0x11, 0x87, 0x38, 0x28, 0xa9, 0x19, 0x78, 0x11, 0x33, 0x91, 0x24, - 0xb5, 0x8a, 0x1b, 0xb0, 0x9f, 0x7f, 0x0d, 0x8d, 0xbb, 0x10, 0xf4, - 0x9c, 0x54, 0xbd, 0x1f, 0xd8, 0x85, 0xcd, 0x15, 0x30, 0x33}, + {0x41, 0x6c, 0x53, 0x92, 0xb9, 0xf3, 0x6d, 0xf1, 0x88, 0xe9, 0x0e, + 0xb1, 0x4d, 0x17, 0xbf, 0x0d, 0xa1, 0x90, 0xbf, 0xdb, 0x7f, 0x1f, + 0x49, 0x56, 0xe6, 0xe5, 0x66, 0xa5, 0x69, 0xc8, 0xb1, 0x5c}, {0x51, 0xb1, 0xd5, 0xb4, 0x59, 0x79, 0x79, 0x08, 0x4a, 0x15, 0xb2, 0xdb, 0x84, 0xd3, 0xd6, 0xbc, 0xfc, 0x93, 0x45, 0xd9, 0xdc, 0x74, 0xda, 0x1a, 0x57, 0xc2, 0x76, 0x9f, 0x3f, 0x83, 0x45, 0x2f, 0xf6, 0xf3, 0x56, 0x1f, @@ -201,11 +203,9 @@ TEST_P(TlsHkdfTest, HkdfKey2Only) { {/* ssl_hash_md5 */}, {/* ssl_hash_sha1 */}, {/* ssl_hash_sha224 */}, - { - 0x2f, 0x5f, 0x78, 0xd0, 0xa4, 0xc4, 0x36, 0xee, 0x6c, 0x8a, 0x4e, - 0xf9, 0xd0, 0x43, 0x81, 0x02, 0x13, 0xfd, 0x47, 0x83, 0x63, 0x3a, - 0xd2, 0xe1, 0x40, 0x6d, 0x2d, 0x98, 0x00, 0xfd, 0xc1, 0x87, - }, + {0x16, 0xaf, 0x00, 0x54, 0x3a, 0x56, 0xc8, 0x26, 0xa2, 0xa7, 0xfc, + 0xb6, 0x34, 0x66, 0x8a, 0xfd, 0x36, 0xdc, 0x8e, 0xce, 0xc4, 0xd2, + 0x6c, 0x7a, 0xdc, 0xe3, 0x70, 0x36, 0x3d, 0x60, 0xfa, 0x0b}, {0x7b, 0x40, 0xf9, 0xef, 0x91, 0xff, 0xc9, 0xd1, 0x29, 0x24, 0x5c, 0xbf, 0xf8, 0x82, 0x76, 0x68, 0xae, 0x4b, 0x63, 0xe8, 0x03, 0xdd, 0x39, 0xa8, 0xd4, 0x6a, 0xf6, 0xe5, 0xec, 0xea, 0xf8, 0x7d, 0x91, 0x71, 0x81, 0xf1, @@ -221,11 +221,9 @@ TEST_P(TlsHkdfTest, HkdfKey1Key2) { {/* ssl_hash_md5 */}, {/* ssl_hash_sha1 */}, {/* ssl_hash_sha224 */}, - { - 0x79, 0x53, 0xb8, 0xdd, 0x6b, 0x98, 0xce, 0x00, 0xb7, 0xdc, 0xe8, - 0x03, 0x70, 0x8c, 0xe3, 0xac, 0x06, 0x8b, 0x22, 0xfd, 0x0e, 0x34, - 0x48, 0xe6, 0xe5, 0xe0, 0x8a, 0xd6, 0x16, 0x18, 0xe5, 0x48, - }, + {0xa5, 0x68, 0x02, 0x5a, 0x95, 0xc9, 0x7f, 0x55, 0x38, 0xbc, 0xf7, + 0x97, 0xcc, 0x0f, 0xd5, 0xf6, 0xa8, 0x8d, 0x15, 0xbc, 0x0e, 0x85, + 0x74, 0x70, 0x3c, 0xa3, 0x65, 0xbd, 0x76, 0xcf, 0x9f, 0xd3}, {0x01, 0x93, 0xc0, 0x07, 0x3f, 0x6a, 0x83, 0x0e, 0x2e, 0x4f, 0xb2, 0x58, 0xe4, 0x00, 0x08, 0x5c, 0x68, 0x9c, 0x37, 0x32, 0x00, 0x37, 0xff, 0xc3, 0x1c, 0x5b, 0x98, 0x0b, 0x02, 0x92, 0x3f, 0xfd, 0x73, 0x5a, 0x6f, 0x2a, @@ -241,9 +239,9 @@ TEST_P(TlsHkdfTest, HkdfExpandLabel) { {/* ssl_hash_md5 */}, {/* ssl_hash_sha1 */}, {/* ssl_hash_sha224 */}, - {0xc6, 0xdd, 0x6e, 0xc4, 0x76, 0xb8, 0x55, 0xf2, 0xa4, 0xfc, 0x59, - 0x04, 0xa4, 0x90, 0xdc, 0xa7, 0xa7, 0x0d, 0x94, 0x8f, 0xc2, 0xdc, - 0x15, 0x6d, 0x48, 0x93, 0x9d, 0x05, 0xbb, 0x9a, 0xbc, 0xc1}, + {0x3e, 0x4e, 0x6e, 0xd0, 0xbc, 0xc4, 0xf4, 0xff, 0xf0, 0xf5, 0x69, + 0xd0, 0x6c, 0x1e, 0x0e, 0x10, 0x32, 0xaa, 0xd7, 0xa3, 0xef, 0xf6, + 0xa8, 0x65, 0x8e, 0xbe, 0xee, 0xc7, 0x1f, 0x01, 0x6d, 0x3c}, {0x41, 0xea, 0x77, 0x09, 0x8c, 0x90, 0x04, 0x10, 0xec, 0xbc, 0x37, 0xd8, 0x5b, 0x54, 0xcd, 0x7b, 0x08, 0x15, 0x13, 0x20, 0xed, 0x1e, 0x3f, 0x54, 0x74, 0xf7, 0x8b, 0x06, 0x38, 0x28, 0x06, 0x37, 0x75, 0x23, 0xa2, 0xb7, |