/* -*- 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 "ssl.h" #include "ssl3prot.h" #include "sslerr.h" #include "sslproto.h" // This is only to get DTLS_1_3_DRAFT_VERSION #include "ssl3prot.h" #include #include "tls_connect.h" #include "tls_filter.h" #include "tls_parser.h" namespace nss_test { class Dtls13LegacyCookieInjector : public TlsHandshakeFilter { public: Dtls13LegacyCookieInjector(const std::shared_ptr& a) : TlsHandshakeFilter(a, {kTlsHandshakeClientHello}) {} virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) { const uint8_t cookie_bytes[] = {0x03, 0x0A, 0x0B, 0x0C}; uint32_t offset = 2 /* version */ + 32 /* random */; if (agent()->variant() != ssl_variant_datagram) { ADD_FAILURE(); return KEEP; } if (header.handshake_type() != ssl_hs_client_hello) { return KEEP; } DataBuffer cookie(cookie_bytes, sizeof(cookie_bytes)); *output = input; // Add the SID length (if any) to locate the cookie. uint32_t sid_len = 0; if (!output->Read(offset, 1, &sid_len)) { ADD_FAILURE(); return KEEP; } offset += 1 + sid_len; output->Splice(cookie, offset, 1); return CHANGE; } private: DataBuffer cookie_; }; class TlsExtensionTruncator : public TlsExtensionFilter { public: TlsExtensionTruncator(const std::shared_ptr& a, uint16_t extension, size_t length) : TlsExtensionFilter(a), extension_(extension), length_(length) {} virtual PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer& input, DataBuffer* output) { if (extension_type != extension_) { return KEEP; } if (input.len() <= length_) { return KEEP; } output->Assign(input.data(), length_); return CHANGE; } private: uint16_t extension_; size_t length_; }; class TlsExtensionTestBase : public TlsConnectTestBase { protected: TlsExtensionTestBase(SSLProtocolVariant variant, uint16_t version) : TlsConnectTestBase(variant, version) {} void ClientHelloErrorTest(std::shared_ptr filter, uint8_t desc = kTlsAlertDecodeError) { client_->SetFilter(filter); ConnectExpectAlert(server_, desc); } void ServerHelloErrorTest(std::shared_ptr filter, uint8_t desc = kTlsAlertDecodeError) { server_->SetFilter(filter); ConnectExpectAlert(client_, desc); } static void InitSimpleSni(DataBuffer* extension) { const char* name = "host.name"; const size_t namelen = PL_strlen(name); extension->Allocate(namelen + 5); extension->Write(0, namelen + 3, 2); extension->Write(2, static_cast(0), 1); // 0 == hostname extension->Write(3, namelen, 2); extension->Write(5, reinterpret_cast(name), namelen); } void HrrThenRemoveExtensionsTest(SSLExtensionType type, PRInt32 client_error, PRInt32 server_error) { static const std::vector client_groups = { ssl_grp_ec_secp384r1, ssl_grp_ec_curve25519}; static const std::vector server_groups = { ssl_grp_ec_curve25519, ssl_grp_ec_secp384r1}; client_->ConfigNamedGroups(client_groups); server_->ConfigNamedGroups(server_groups); EnsureTlsSetup(); StartConnect(); client_->Handshake(); // Send ClientHello server_->Handshake(); // Send HRR. MakeTlsFilter(client_, type); Handshake(); client_->CheckErrorCode(client_error); server_->CheckErrorCode(server_error); } }; class TlsExtensionTestDtls : public TlsExtensionTestBase, public ::testing::WithParamInterface { public: TlsExtensionTestDtls() : TlsExtensionTestBase(ssl_variant_datagram, GetParam()) {} }; class TlsExtensionTest12Plus : public TlsExtensionTestBase, public ::testing::WithParamInterface< std::tuple> { public: TlsExtensionTest12Plus() : TlsExtensionTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) { } }; class TlsExtensionTest12 : public TlsExtensionTestBase, public ::testing::WithParamInterface< std::tuple> { public: TlsExtensionTest12() : TlsExtensionTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) { } }; class TlsExtensionTest13 : public TlsExtensionTestBase, public ::testing::WithParamInterface { public: TlsExtensionTest13() : TlsExtensionTestBase(GetParam(), SSL_LIBRARY_VERSION_TLS_1_3) {} void ConnectWithBogusVersionList(const uint8_t* buf, size_t len) { DataBuffer versions_buf(buf, len); MakeTlsFilter( client_, ssl_tls13_supported_versions_xtn, versions_buf); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); } void ConnectWithReplacementVersionList(uint16_t version) { // Convert the version encoding for DTLS, if needed. if (variant_ == ssl_variant_datagram) { switch (version) { case SSL_LIBRARY_VERSION_TLS_1_3: #ifdef DTLS_1_3_DRAFT_VERSION version = 0x7f00 | DTLS_1_3_DRAFT_VERSION; #else version = SSL_LIBRARY_VERSION_DTLS_1_3_WIRE; #endif break; case SSL_LIBRARY_VERSION_TLS_1_2: version = SSL_LIBRARY_VERSION_DTLS_1_2_WIRE; break; case SSL_LIBRARY_VERSION_TLS_1_1: /* TLS_1_1 maps to DTLS_1_0, see sslproto.h. */ version = SSL_LIBRARY_VERSION_DTLS_1_0_WIRE; break; default: PORT_Assert(0); } } DataBuffer versions_buf; size_t index = versions_buf.Write(0, 2, 1); versions_buf.Write(index, version, 2); MakeTlsFilter( client_, ssl_tls13_supported_versions_xtn, versions_buf); ConnectExpectFail(); } }; class TlsExtensionTest13Stream : public TlsExtensionTestBase { public: TlsExtensionTest13Stream() : TlsExtensionTestBase(ssl_variant_stream, SSL_LIBRARY_VERSION_TLS_1_3) {} }; class TlsExtensionTestGeneric : public TlsExtensionTestBase, public ::testing::WithParamInterface< std::tuple> { public: TlsExtensionTestGeneric() : TlsExtensionTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) { } }; class TlsExtensionTestPre13 : public TlsExtensionTestBase, public ::testing::WithParamInterface< std::tuple> { public: TlsExtensionTestPre13() : TlsExtensionTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) { } }; TEST_P(TlsExtensionTestGeneric, DamageSniLength) { ClientHelloErrorTest( std::make_shared(client_, ssl_server_name_xtn, 1)); } TEST_P(TlsExtensionTestGeneric, DamageSniHostLength) { ClientHelloErrorTest( std::make_shared(client_, ssl_server_name_xtn, 4)); } TEST_P(TlsExtensionTestGeneric, TruncateSni) { ClientHelloErrorTest( std::make_shared(client_, ssl_server_name_xtn, 7)); } // A valid extension that appears twice will be reported as unsupported. TEST_P(TlsExtensionTestGeneric, RepeatSni) { DataBuffer extension; InitSimpleSni(&extension); ClientHelloErrorTest(std::make_shared( client_, ssl_server_name_xtn, extension), kTlsAlertIllegalParameter); } // An SNI entry with zero length is considered invalid (strangely, not if it is // the last entry, which is probably a bug). TEST_P(TlsExtensionTestGeneric, BadSni) { DataBuffer simple; InitSimpleSni(&simple); DataBuffer extension; extension.Allocate(simple.len() + 3); extension.Write(0, static_cast(0), 3); extension.Write(3, simple); ClientHelloErrorTest(std::make_shared( client_, ssl_server_name_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, EmptySni) { DataBuffer extension; extension.Allocate(2); extension.Write(0, static_cast(0), 2); ClientHelloErrorTest(std::make_shared( client_, ssl_server_name_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, EmptyAlpnExtension) { EnableAlpn(); DataBuffer extension; ClientHelloErrorTest(std::make_shared( client_, ssl_app_layer_protocol_xtn, extension), kTlsAlertIllegalParameter); } // An empty ALPN isn't considered bad, though it does lead to there being no // protocol for the server to select. TEST_P(TlsExtensionTestGeneric, EmptyAlpnList) { EnableAlpn(); const uint8_t val[] = {0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_app_layer_protocol_xtn, extension), kTlsAlertNoApplicationProtocol); } TEST_P(TlsExtensionTestGeneric, OneByteAlpn) { EnableAlpn(); ClientHelloErrorTest(std::make_shared( client_, ssl_app_layer_protocol_xtn, 1)); } TEST_P(TlsExtensionTestGeneric, AlpnMissingValue) { EnableAlpn(); // This will leave the length of the second entry, but no value. ClientHelloErrorTest(std::make_shared( client_, ssl_app_layer_protocol_xtn, 5)); } TEST_P(TlsExtensionTestGeneric, AlpnZeroLength) { EnableAlpn(); const uint8_t val[] = {0x00, 0x03, 0x01, 0x61, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, AlpnLengthOverflow) { EnableAlpn(); const uint8_t val[] = {0x00, 0x03, 0x01, 0x61, 0x01}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, AlpnMismatch) { const uint8_t client_alpn[] = {0x01, 0x61}; client_->EnableAlpn(client_alpn, sizeof(client_alpn)); const uint8_t server_alpn[] = {0x02, 0x61, 0x62}; server_->EnableAlpn(server_alpn, sizeof(server_alpn)); ClientHelloErrorTest(nullptr, kTlsAlertNoApplicationProtocol); client_->CheckErrorCode(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL); } TEST_P(TlsExtensionTestGeneric, AlpnDisabledServer) { const uint8_t client_alpn[] = {0x01, 0x61}; client_->EnableAlpn(client_alpn, sizeof(client_alpn)); server_->EnableAlpn(nullptr, 0); ClientHelloErrorTest(nullptr, kTlsAlertUnsupportedExtension); } TEST_P(TlsConnectGeneric, AlpnDisabled) { server_->EnableAlpn(nullptr, 0); Connect(); SSLNextProtoState state; uint8_t buf[255] = {0}; unsigned int buf_len = 3; EXPECT_EQ(SECSuccess, SSL_GetNextProto(client_->ssl_fd(), &state, buf, &buf_len, sizeof(buf))); EXPECT_EQ(SSL_NEXT_PROTO_NO_SUPPORT, state); EXPECT_EQ(0U, buf_len); } // Many of these tests fail in TLS 1.3 because the extension is encrypted, which // prevents modification of the value from the ServerHello. TEST_P(TlsExtensionTestPre13, AlpnReturnedEmptyList) { EnableAlpn(); const uint8_t val[] = {0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedEmptyName) { EnableAlpn(); const uint8_t val[] = {0x00, 0x01, 0x00}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedListTrailingData) { EnableAlpn(); const uint8_t val[] = {0x00, 0x02, 0x01, 0x61, 0x00}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedExtraEntry) { EnableAlpn(); const uint8_t val[] = {0x00, 0x04, 0x01, 0x61, 0x01, 0x62}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedBadListLength) { EnableAlpn(); const uint8_t val[] = {0x00, 0x99, 0x01, 0x61, 0x00}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedBadNameLength) { EnableAlpn(); const uint8_t val[] = {0x00, 0x02, 0x99, 0x61}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedUnknownName) { EnableAlpn(); const uint8_t val[] = {0x00, 0x02, 0x01, 0x67}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( server_, ssl_app_layer_protocol_xtn, extension), kTlsAlertIllegalParameter); } TEST_P(TlsExtensionTestDtls, SrtpShort) { EnableSrtp(); ClientHelloErrorTest( std::make_shared(client_, ssl_use_srtp_xtn, 3)); } TEST_P(TlsExtensionTestDtls, SrtpOdd) { EnableSrtp(); const uint8_t val[] = {0x00, 0x01, 0xff, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_use_srtp_xtn, extension)); } TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsBadLength) { const uint8_t val[] = {0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_signature_algorithms_xtn, extension)); } TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsTrailingData) { // make sure the test uses an algorithm that is legal for // tls 1.3 (or tls 1.3 will throw a handshake failure alert // instead of a decode error alert) const uint8_t val[] = {0x00, 0x02, 0x08, 0x09, 0x00}; // sha-256, rsa-pss-pss DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_signature_algorithms_xtn, extension)); } TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsEmpty) { const uint8_t val[] = {0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_signature_algorithms_xtn, extension), kTlsAlertHandshakeFailure); } TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsNoOverlap) { const uint8_t val[] = {0x00, 0x02, 0xff, 0xff}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_signature_algorithms_xtn, extension), kTlsAlertHandshakeFailure); } TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsOddLength) { const uint8_t val[] = {0x00, 0x01, 0x04}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_signature_algorithms_xtn, extension)); } TEST_F(TlsExtensionTest13Stream, SignatureAlgorithmsPrecedingGarbage) { // 31 unknown signature algorithms followed by sha-256, rsa-pss 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, 0x08, 0x04}; DataBuffer extension(val, sizeof(val)); MakeTlsFilter(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(client_, ssl_supported_groups_xtn), version_ < SSL_LIBRARY_VERSION_TLS_1_3 ? kTlsAlertDecryptError : kTlsAlertMissingExtension); } TEST_P(TlsExtensionTestGeneric, SupportedCurvesShort) { const uint8_t val[] = {0x00, 0x01, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_elliptic_curves_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, SupportedCurvesBadLength) { const uint8_t val[] = {0x09, 0x99, 0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_elliptic_curves_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, SupportedCurvesTrailingData) { const uint8_t val[] = {0x00, 0x02, 0x00, 0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_elliptic_curves_xtn, extension)); } TEST_P(TlsExtensionTest12, SupportedCurvesDisableX25519) { // Disable session resumption. ConfigureSessionCache(RESUME_NONE, RESUME_NONE); // Ensure that we can enable its use in the key exchange. SECStatus rv = NSS_SetAlgorithmPolicy(SEC_OID_CURVE25519, NSS_USE_ALG_IN_SSL_KX, 0); ASSERT_EQ(SECSuccess, rv); rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, 0); ASSERT_EQ(SECSuccess, rv); auto capture1 = MakeTlsFilter(client_, ssl_elliptic_curves_xtn); Connect(); EXPECT_TRUE(capture1->captured()); const DataBuffer& ext1 = capture1->extension(); uint32_t count; ASSERT_TRUE(ext1.Read(0, 2, &count)); // Whether or not we've seen x25519 offered in this handshake. bool seen1_x25519 = false; for (size_t offset = 2; offset <= count; offset++) { uint32_t val; ASSERT_TRUE(ext1.Read(offset, 2, &val)); if (val == ssl_grp_ec_curve25519) { seen1_x25519 = true; break; } } ASSERT_TRUE(seen1_x25519); // Ensure that we can disable its use in the key exchange. rv = NSS_SetAlgorithmPolicy(SEC_OID_CURVE25519, 0, NSS_USE_ALG_IN_SSL_KX); ASSERT_EQ(SECSuccess, rv); rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, 0); ASSERT_EQ(SECSuccess, rv); // Clean up after the last run. Reset(); auto capture2 = MakeTlsFilter(client_, ssl_elliptic_curves_xtn); Connect(); EXPECT_TRUE(capture2->captured()); const DataBuffer& ext2 = capture2->extension(); ASSERT_TRUE(ext2.Read(0, 2, &count)); // Whether or not we've seen x25519 offered in this handshake. bool seen2_x25519 = false; for (size_t offset = 2; offset <= count; offset++) { uint32_t val; ASSERT_TRUE(ext2.Read(offset, 2, &val)); if (val == ssl_grp_ec_curve25519) { seen2_x25519 = true; break; } } ASSERT_FALSE(seen2_x25519); } TEST_P(TlsExtensionTestPre13, SupportedPointsEmpty) { const uint8_t val[] = {0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_ec_point_formats_xtn, extension)); } TEST_P(TlsExtensionTestPre13, SupportedPointsBadLength) { const uint8_t val[] = {0x99, 0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_ec_point_formats_xtn, extension)); } TEST_P(TlsExtensionTestPre13, SupportedPointsTrailingData) { const uint8_t val[] = {0x01, 0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_ec_point_formats_xtn, extension)); } TEST_P(TlsExtensionTestPre13, SupportedPointsCompressed) { const uint8_t val[] = {0x01, 0x02}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_ec_point_formats_xtn, extension), kTlsAlertIllegalParameter); } TEST_P(TlsExtensionTestPre13, SupportedPointsUndefined) { const uint8_t val[] = {0x01, 0xAA}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_ec_point_formats_xtn, extension), kTlsAlertIllegalParameter); } TEST_P(TlsExtensionTestPre13, RenegotiationInfoBadLength) { const uint8_t val[] = {0x99}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_renegotiation_info_xtn, extension)); } TEST_P(TlsExtensionTestPre13, RenegotiationInfoMismatch) { const uint8_t val[] = {0x01, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_renegotiation_info_xtn, extension)); } // The extension has to contain a length. TEST_P(TlsExtensionTestPre13, RenegotiationInfoExtensionEmpty) { DataBuffer extension; ClientHelloErrorTest(std::make_shared( client_, ssl_renegotiation_info_xtn, extension)); } // This only works on TLS 1.2, since it relies on static RSA; otherwise libssl // picks the wrong cipher suite. TEST_P(TlsExtensionTest12, SignatureAlgorithmConfiguration) { const SSLSignatureScheme schemes[] = {ssl_sig_rsa_pss_rsae_sha512, ssl_sig_rsa_pss_rsae_sha384}; auto capture = MakeTlsFilter(client_, ssl_signature_algorithms_xtn); client_->SetSignatureSchemes(schemes, PR_ARRAY_SIZE(schemes)); EnableOnlyStaticRsaCiphers(); Connect(); const DataBuffer& ext = capture->extension(); EXPECT_EQ(2 + PR_ARRAY_SIZE(schemes) * 2, ext.len()); for (size_t i = 0, cursor = 2; i < PR_ARRAY_SIZE(schemes) && cursor < ext.len(); ++i) { uint32_t v = 0; EXPECT_TRUE(ext.Read(cursor, 2, &v)); cursor += 2; EXPECT_EQ(schemes[i], static_cast(v)); } } // This only works on TLS 1.2, since it relies on DSA. TEST_P(TlsExtensionTest12, SignatureAlgorithmDisableDSA) { const std::vector schemes = { ssl_sig_dsa_sha1, ssl_sig_dsa_sha256, ssl_sig_dsa_sha384, ssl_sig_dsa_sha512, ssl_sig_rsa_pss_rsae_sha256}; // Connect with DSA enabled by policy. SECStatus rv = NSS_SetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, NSS_USE_ALG_IN_SSL_KX, 0); ASSERT_EQ(SECSuccess, rv); rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, 0); ASSERT_EQ(SECSuccess, rv); Reset(TlsAgent::kServerDsa); auto capture1 = MakeTlsFilter(client_, ssl_signature_algorithms_xtn); client_->SetSignatureSchemes(schemes.data(), schemes.size()); Connect(); // Check if all the signature algorithms are advertised. EXPECT_TRUE(capture1->captured()); const DataBuffer& ext1 = capture1->extension(); EXPECT_EQ(2U + 2U * schemes.size(), ext1.len()); // Connect with DSA disabled by policy. rv = NSS_SetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, 0, NSS_USE_ALG_IN_SSL_KX); ASSERT_EQ(SECSuccess, rv); rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, 0); ASSERT_EQ(SECSuccess, rv); Reset(TlsAgent::kServerDsa); auto capture2 = MakeTlsFilter(client_, ssl_signature_algorithms_xtn); client_->SetSignatureSchemes(schemes.data(), schemes.size()); ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); // Check if no DSA algorithms are advertised. EXPECT_TRUE(capture2->captured()); const DataBuffer& ext2 = capture2->extension(); EXPECT_EQ(2U + 2U, ext2.len()); uint32_t v = 0; EXPECT_TRUE(ext2.Read(2, 2, &v)); EXPECT_EQ(ssl_sig_rsa_pss_rsae_sha256, v); } // Temporary test to verify that we choke on an empty ClientKeyShare. // This test will fail when we implement HelloRetryRequest. TEST_P(TlsExtensionTest13, EmptyClientKeyShare) { ClientHelloErrorTest(std::make_shared( client_, ssl_tls13_key_share_xtn, 2), kTlsAlertHandshakeFailure); } // These tests only work in stream mode because the client sends a // cleartext alert which causes a MAC error on the server. With // stream this causes handshake failure but with datagram, the // packet gets dropped. TEST_F(TlsExtensionTest13Stream, DropServerKeyShare) { EnsureTlsSetup(); MakeTlsFilter(server_, ssl_tls13_key_share_xtn); client_->ExpectSendAlert(kTlsAlertMissingExtension); server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code()); EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code()); } TEST_F(TlsExtensionTest13Stream, WrongServerKeyShare) { const uint16_t wrong_group = ssl_grp_ec_secp384r1; static const uint8_t key_share[] = { wrong_group >> 8, wrong_group & 0xff, // Group we didn't offer. 0x00, 0x02, // length = 2 0x01, 0x02}; DataBuffer buf(key_share, sizeof(key_share)); EnsureTlsSetup(); MakeTlsFilter(server_, ssl_tls13_key_share_xtn, buf); client_->ExpectSendAlert(kTlsAlertIllegalParameter); server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); 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, UnknownServerKeyShare) { const uint16_t wrong_group = 0xffff; static const uint8_t key_share[] = { wrong_group >> 8, wrong_group & 0xff, // Group we didn't offer. 0x00, 0x02, // length = 2 0x01, 0x02}; DataBuffer buf(key_share, sizeof(key_share)); EnsureTlsSetup(); MakeTlsFilter(server_, ssl_tls13_key_share_xtn, buf); client_->ExpectSendAlert(kTlsAlertIllegalParameter); server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); 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) { SetupForResume(); DataBuffer empty; MakeTlsFilter(server_, ssl_signature_algorithms_xtn, empty); client_->ExpectSendAlert(kTlsAlertIllegalParameter); server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFail(); EXPECT_EQ(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, client_->error_code()); EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code()); } struct PskIdentity { DataBuffer identity; uint32_t obfuscated_ticket_age; }; class TlsPreSharedKeyReplacer; typedef std::function TlsPreSharedKeyReplacerFunc; class TlsPreSharedKeyReplacer : public TlsExtensionFilter { public: TlsPreSharedKeyReplacer(const std::shared_ptr& a, TlsPreSharedKeyReplacerFunc function) : TlsExtensionFilter(a), identities_(), binders_(), function_(function) {} static size_t CopyAndMaybeReplace(TlsParser* parser, size_t size, const std::unique_ptr& replace, size_t index, DataBuffer* output) { DataBuffer tmp; bool ret = parser->ReadVariable(&tmp, size); EXPECT_EQ(true, ret); if (!ret) return 0; if (replace) { tmp = *replace; } return WriteVariable(output, index, tmp, size); } PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer& input, DataBuffer* output) { if (extension_type != ssl_tls13_pre_shared_key_xtn) { return KEEP; } if (!Decode(input)) { return KEEP; } // Call the function. function_(this); Encode(output); return CHANGE; } std::vector identities_; std::vector binders_; private: bool Decode(const DataBuffer& input) { std::unique_ptr parser(new TlsParser(input)); DataBuffer identities; if (!parser->ReadVariable(&identities, 2)) { ADD_FAILURE(); return false; } DataBuffer binders; if (!parser->ReadVariable(&binders, 2)) { ADD_FAILURE(); return false; } EXPECT_EQ(0UL, parser->remaining()); // Now parse the inner sections. parser.reset(new TlsParser(identities)); while (parser->remaining()) { PskIdentity identity; if (!parser->ReadVariable(&identity.identity, 2)) { ADD_FAILURE(); return false; } if (!parser->Read(&identity.obfuscated_ticket_age, 4)) { ADD_FAILURE(); return false; } identities_.push_back(identity); } parser.reset(new TlsParser(binders)); while (parser->remaining()) { DataBuffer binder; if (!parser->ReadVariable(&binder, 1)) { ADD_FAILURE(); return false; } binders_.push_back(binder); } return true; } void Encode(DataBuffer* output) { DataBuffer identities; size_t index = 0; for (auto id : identities_) { index = WriteVariable(&identities, index, id.identity, 2); index = identities.Write(index, id.obfuscated_ticket_age, 4); } DataBuffer binders; index = 0; for (auto binder : binders_) { index = WriteVariable(&binders, index, binder, 1); } output->Truncate(0); index = 0; index = WriteVariable(output, index, identities, 2); index = WriteVariable(output, index, binders, 2); } TlsPreSharedKeyReplacerFunc function_; }; TEST_F(TlsExtensionTest13Stream, ResumeEmptyPskLabel) { SetupForResume(); MakeTlsFilter( client_, [](TlsPreSharedKeyReplacer* r) { r->identities_[0].identity.Truncate(0); }); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); } // Flip the first byte of the binder. TEST_F(TlsExtensionTest13Stream, ResumeIncorrectBinderValue) { SetupForResume(); MakeTlsFilter( client_, [](TlsPreSharedKeyReplacer* r) { r->binders_[0].Write(0, r->binders_[0].data()[0] ^ 0xff, 1); }); ConnectExpectAlert(server_, kTlsAlertDecryptError); client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); } // Do the same with an External PSK. TEST_P(TlsConnectTls13, TestTls13PskInvalidBinderValue) { ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); ASSERT_TRUE(!!slot); ScopedPK11SymKey key( PK11_KeyGen(slot.get(), CKM_HKDF_KEY_GEN, nullptr, 16, nullptr)); ASSERT_TRUE(!!key); AddPsk(key, std::string("foo"), ssl_hash_sha256); StartConnect(); ASSERT_TRUE(client_->MaybeSetResumptionToken()); MakeTlsFilter( client_, [](TlsPreSharedKeyReplacer* r) { r->binders_[0].Write(0, r->binders_[0].data()[0] ^ 0xff, 1); }); ConnectExpectAlert(server_, kTlsAlertDecryptError); client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); } // Extend the binder by one. TEST_F(TlsExtensionTest13Stream, ResumeIncorrectBinderLength) { SetupForResume(); MakeTlsFilter( client_, [](TlsPreSharedKeyReplacer* r) { r->binders_[0].Write(r->binders_[0].len(), 0xff, 1); }); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); } // Binders must be at least 32 bytes. TEST_F(TlsExtensionTest13Stream, ResumeBinderTooShort) { SetupForResume(); MakeTlsFilter( client_, [](TlsPreSharedKeyReplacer* r) { r->binders_[0].Truncate(31); }); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); } // Duplicate the identity and binder. This will fail with an error // processing the binder (because we extended the identity list.) TEST_F(TlsExtensionTest13Stream, ResumeTwoPsks) { SetupForResume(); MakeTlsFilter( client_, [](TlsPreSharedKeyReplacer* r) { r->identities_.push_back(r->identities_[0]); r->binders_.push_back(r->binders_[0]); }); ConnectExpectAlert(server_, kTlsAlertDecryptError); client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); } // The next two tests have mismatches in the number of identities // and binders. This generates an illegal parameter alert. TEST_F(TlsExtensionTest13Stream, ResumeTwoIdentitiesOneBinder) { SetupForResume(); MakeTlsFilter( client_, [](TlsPreSharedKeyReplacer* r) { r->identities_.push_back(r->identities_[0]); }); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); } TEST_F(TlsExtensionTest13Stream, ResumeOneIdentityTwoBinders) { SetupForResume(); MakeTlsFilter( client_, [](TlsPreSharedKeyReplacer* r) { r->binders_.push_back(r->binders_[0]); }); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); } TEST_F(TlsExtensionTest13Stream, ResumePskExtensionNotLast) { SetupForResume(); const uint8_t empty_buf[] = {0}; DataBuffer empty(empty_buf, 0); // Inject an unused extension after the PSK extension. MakeTlsFilter(client_, kTlsHandshakeClientHello, 0xffff, empty); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); } TEST_F(TlsExtensionTest13Stream, ResumeNoKeModes) { SetupForResume(); DataBuffer empty; MakeTlsFilter(client_, ssl_tls13_psk_key_exchange_modes_xtn); ConnectExpectAlert(server_, kTlsAlertMissingExtension); client_->CheckErrorCode(SSL_ERROR_MISSING_EXTENSION_ALERT); server_->CheckErrorCode(SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES); } // The following test contains valid but unacceptable PreSharedKey // modes and therefore produces non-resumption followed by MAC // errors. TEST_F(TlsExtensionTest13Stream, ResumeBogusKeModes) { SetupForResume(); const static uint8_t ke_modes[] = {1, // Length kTls13PskKe}; DataBuffer modes(ke_modes, sizeof(ke_modes)); MakeTlsFilter( client_, ssl_tls13_psk_key_exchange_modes_xtn, modes); client_->ExpectSendAlert(kTlsAlertBadRecordMac); server_->ExpectSendAlert(kTlsAlertBadRecordMac); ConnectExpectFail(); client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); } TEST_P(TlsExtensionTest13, NoKeModesIfResumptionOff) { ConfigureSessionCache(RESUME_NONE, RESUME_NONE); auto capture = MakeTlsFilter( client_, ssl_tls13_psk_key_exchange_modes_xtn); Connect(); EXPECT_FALSE(capture->captured()); } // In these tests, we downgrade to TLS 1.2, causing the // server to negotiate TLS 1.2. // 1. Both sides only support TLS 1.3, so we get a cipher version // error. TEST_P(TlsExtensionTest13, RemoveTls13FromVersionList) { ExpectAlert(server_, kTlsAlertProtocolVersion); ConnectWithReplacementVersionList(SSL_LIBRARY_VERSION_TLS_1_2); client_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT); server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION); } // 2. Server supports 1.2 and 1.3, client supports 1.2, so we // can't negotiate any ciphers. TEST_P(TlsExtensionTest13, RemoveTls13FromVersionListServerV12) { server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, SSL_LIBRARY_VERSION_TLS_1_3); ExpectAlert(server_, kTlsAlertHandshakeFailure); ConnectWithReplacementVersionList(SSL_LIBRARY_VERSION_TLS_1_2); client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); } // 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); // 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); #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) { ExpectAlert(server_, kTlsAlertMissingExtension); HrrThenRemoveExtensionsTest(ssl_signature_algorithms_xtn, SSL_ERROR_MISSING_EXTENSION_ALERT, SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION); } TEST_P(TlsExtensionTest13, HrrThenRemoveKeyShare) { ExpectAlert(server_, kTlsAlertIllegalParameter); HrrThenRemoveExtensionsTest(ssl_tls13_key_share_xtn, SSL_ERROR_ILLEGAL_PARAMETER_ALERT, SSL_ERROR_BAD_2ND_CLIENT_HELLO); } TEST_P(TlsExtensionTest13, HrrThenRemoveSupportedGroups) { ExpectAlert(server_, kTlsAlertMissingExtension); HrrThenRemoveExtensionsTest(ssl_supported_groups_xtn, SSL_ERROR_MISSING_EXTENSION_ALERT, SSL_ERROR_MISSING_SUPPORTED_GROUPS_EXTENSION); } TEST_P(TlsExtensionTest13, EmptyVersionList) { static const uint8_t kExt[] = {0x00, 0x00}; ConnectWithBogusVersionList(kExt, sizeof(kExt)); } TEST_P(TlsExtensionTest13, OddVersionList) { static const uint8_t kExt[] = {0x00, 0x01, 0x00}; ConnectWithBogusVersionList(kExt, sizeof(kExt)); } TEST_P(TlsExtensionTest13, SignatureAlgorithmsInvalidTls13) { // testing the case where we ask for a invalid parameter for tls13 const uint8_t val[] = {0x00, 0x02, 0x04, 0x01}; // sha-256, rsa-pkcs1 DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( client_, ssl_signature_algorithms_xtn, extension), kTlsAlertHandshakeFailure); } // Use the stream version number for TLS 1.3 (0x0304) in DTLS. TEST_F(TlsConnectDatagram13, TlsVersionInDtls) { static const uint8_t kExt[] = {0x02, 0x03, 0x04}; DataBuffer versions_buf(kExt, sizeof(kExt)); MakeTlsFilter(client_, ssl_tls13_supported_versions_xtn, versions_buf); ConnectExpectAlert(server_, kTlsAlertProtocolVersion); client_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT); server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION); } // TODO: this only tests extensions in server messages. The client can extend // Certificate messages, which is not checked here. class TlsBogusExtensionTest : public TlsConnectTestBase, public ::testing::WithParamInterface< std::tuple> { public: TlsBogusExtensionTest() : TlsConnectTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) {} protected: virtual void ConnectAndFail(uint8_t message) = 0; void AddFilter(uint8_t message, uint16_t extension) { static uint8_t empty_buf[1] = {0}; DataBuffer empty(empty_buf, 0); auto filter = MakeTlsFilter(server_, message, extension, empty); if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { filter->EnableDecryption(); } } void Run(uint8_t message, uint16_t extension = 0xff) { EnsureTlsSetup(); AddFilter(message, extension); ConnectAndFail(message); } }; class TlsBogusExtensionTestPre13 : public TlsBogusExtensionTest { protected: void ConnectAndFail(uint8_t) override { ConnectExpectAlert(client_, kTlsAlertUnsupportedExtension); } }; class TlsBogusExtensionTest13 : public TlsBogusExtensionTest { protected: void ConnectAndFail(uint8_t message) override { if (message != kTlsHandshakeServerHello) { ConnectExpectAlert(client_, kTlsAlertUnsupportedExtension); return; } FailWithAlert(kTlsAlertUnsupportedExtension); } void FailWithAlert(uint8_t alert) { StartConnect(); client_->Handshake(); // ClientHello server_->Handshake(); // ServerHello client_->ExpectSendAlert(alert); client_->Handshake(); if (variant_ == ssl_variant_stream) { server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); } server_->Handshake(); } }; TEST_P(TlsBogusExtensionTestPre13, AddBogusExtensionServerHello) { Run(kTlsHandshakeServerHello); } TEST_P(TlsBogusExtensionTest13, AddBogusExtensionServerHello) { Run(kTlsHandshakeServerHello); } TEST_P(TlsBogusExtensionTest13, AddBogusExtensionEncryptedExtensions) { Run(kTlsHandshakeEncryptedExtensions); } TEST_P(TlsBogusExtensionTest13, AddBogusExtensionCertificate) { Run(kTlsHandshakeCertificate); } // It's perfectly valid to set unknown extensions in CertificateRequest. TEST_P(TlsBogusExtensionTest13, AddBogusExtensionCertificateRequest) { server_->RequestClientAuth(false); AddFilter(kTlsHandshakeCertificateRequest, 0xff); ConnectExpectAlert(client_, kTlsAlertDecryptError); client_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE); } TEST_P(TlsBogusExtensionTest13, AddBogusExtensionHelloRetryRequest) { static const std::vector groups = {ssl_grp_ec_secp384r1}; server_->ConfigNamedGroups(groups); Run(kTlsHandshakeHelloRetryRequest); } // NewSessionTicket allows unknown extensions AND it isn't protected by the // Finished. So adding an unknown extension doesn't cause an error. TEST_P(TlsBogusExtensionTest13, AddBogusExtensionNewSessionTicket) { ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); AddFilter(kTlsHandshakeNewSessionTicket, 0xff); Connect(); SendReceive(); CheckKeys(); Reset(); ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); ExpectResumption(RESUME_TICKET); Connect(); SendReceive(); } class TlsDisallowedExtensionTest13 : public TlsBogusExtensionTest { protected: void ConnectAndFail(uint8_t message) override { ConnectExpectAlert(client_, kTlsAlertIllegalParameter); } }; TEST_P(TlsDisallowedExtensionTest13, AddVersionExtensionEncryptedExtensions) { Run(kTlsHandshakeEncryptedExtensions, ssl_tls13_supported_versions_xtn); } TEST_P(TlsDisallowedExtensionTest13, AddVersionExtensionCertificate) { Run(kTlsHandshakeCertificate, ssl_tls13_supported_versions_xtn); } TEST_P(TlsDisallowedExtensionTest13, AddVersionExtensionCertificateRequest) { server_->RequestClientAuth(false); Run(kTlsHandshakeCertificateRequest, ssl_tls13_supported_versions_xtn); } /* For unadvertised disallowed extensions an unsupported_extension alert is * thrown since NSS checks for unadvertised extensions before its disallowed * extension check. */ class TlsDisallowedUnadvertisedExtensionTest13 : public TlsBogusExtensionTest { protected: void ConnectAndFail(uint8_t message) override { uint8_t alert = kTlsAlertUnsupportedExtension; if (message == kTlsHandshakeCertificateRequest) { alert = kTlsAlertIllegalParameter; } ConnectExpectAlert(client_, alert); } }; TEST_P(TlsDisallowedUnadvertisedExtensionTest13, AddPSKExtensionEncryptedExtensions) { Run(kTlsHandshakeEncryptedExtensions, ssl_tls13_pre_shared_key_xtn); } TEST_P(TlsDisallowedUnadvertisedExtensionTest13, AddPSKExtensionCertificate) { Run(kTlsHandshakeCertificate, ssl_tls13_pre_shared_key_xtn); } TEST_P(TlsDisallowedUnadvertisedExtensionTest13, AddPSKExtensionCertificateRequest) { server_->RequestClientAuth(false); Run(kTlsHandshakeCertificateRequest, ssl_tls13_pre_shared_key_xtn); } TEST_P(TlsConnectStream, IncludePadding) { EnsureTlsSetup(); SSL_EnableTls13GreaseEch(client_->ssl_fd(), PR_FALSE); // Don't GREASE // This needs to be long enough to push a TLS 1.0 ClientHello over 255, but // short enough not to push a TLS 1.3 ClientHello over 511. static const char* long_name = "chickenchickenchickenchickenchickenchickenchickenchicken." "chickenchickenchickenchickenchickenchickenchickenchicken." "chickenchickenchickenchickenchicken."; SECStatus rv = SSL_SetURL(client_->ssl_fd(), long_name); EXPECT_EQ(SECSuccess, rv); auto capture = MakeTlsFilter(client_, ssl_padding_xtn); client_->StartConnect(); client_->Handshake(); EXPECT_TRUE(capture->captured()); } TEST_F(TlsConnectDatagram13, Dtls13RejectLegacyCookie) { EnsureTlsSetup(); MakeTlsFilter(client_); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); } TEST_P(TlsConnectGeneric, ClientHelloExtensionPermutation) { EnsureTlsSetup(); PR_ASSERT(SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_CH_EXTENSION_PERMUTATION, PR_TRUE) == SECSuccess); Connect(); } TEST_F(TlsConnectStreamTls13, ClientHelloExtensionPermutationWithPSK) { EnsureTlsSetup(); ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); const uint8_t kPskDummyVal_[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; SECItem psk_item; psk_item.type = siBuffer; psk_item.len = sizeof(kPskDummyVal_); psk_item.data = const_cast(kPskDummyVal_); PK11SymKey* key = PK11_ImportSymKey(slot.get(), CKM_HKDF_KEY_GEN, PK11_OriginUnwrap, CKA_DERIVE, &psk_item, NULL); ScopedPK11SymKey scoped_psk_(key); const std::string kPskDummyLabel_ = "NSS PSK GTEST label"; const SSLHashType kPskHash_ = ssl_hash_sha384; AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); PR_ASSERT(SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_CH_EXTENSION_PERMUTATION, PR_TRUE) == SECSuccess); Connect(); SendReceive(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); } /* This test checks that the ClientHello extension order is actually permuted * if ss->opt.chXtnPermutation is set. It is asserted that at least one out of * 10 extension orders differs from the others. * * This is a probabilistic test: The default TLS 1.3 ClientHello contains 8 * extensions, leading to a 1/8! probability for any extension order and the * same probability for two drawn extension orders to coincide. * Since all sequences are compared against each other this leads to a false * positive rate of (1/8!)^(n^2-n). * To achieve a spurious failure rate << 1/2^64, we compare n=10 drawn orders. * * This test assures that randomisation is happening but does not check quality * of the used Fisher-Yates shuffle. */ TEST_F(TlsConnectStreamTls13, ClientHelloExtensionPermutationProbabilisticTest) { std::vector> orders; /* Capture the extension order of 10 ClientHello messages. */ for (size_t i = 0; i < 10; i++) { client_->StartConnect(); /* Enable ClientHello extension permutation. */ ASSERT_TRUE(SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_CH_EXTENSION_PERMUTATION, PR_TRUE) == SECSuccess); /* Capture extension order filter. */ auto filter = MakeTlsFilter( client_, kTlsHandshakeClientHello); /* Send ClientHello. */ client_->Handshake(); /* Remember extension order. */ orders.push_back(filter->order); /* Reset client / server state. */ Reset(); } /* Check for extension order inequality. */ size_t inequal = 0; for (auto& outerOrders : orders) { for (auto& innerOrders : orders) { if (outerOrders != innerOrders) { inequal++; } } } ASSERT_TRUE(inequal >= 1); } // The certificate_authorities xtn can be included in a ClientHello [RFC 8446, // Section 4.2] TEST_F(TlsConnectStreamTls13, ClientHelloCertAuthXtnToleration) { EnsureTlsSetup(); uint8_t bodyBuf[3] = {0x00, 0x01, 0xff}; DataBuffer body(bodyBuf, sizeof(bodyBuf)); auto ch = MakeTlsFilter( client_, kTlsHandshakeClientHello, ssl_tls13_certificate_authorities_xtn, body); // The Connection will fail because the added extension isn't in the client's // transcript not because the extension is unsupported (Bug 1815167). server_->ExpectSendAlert(bad_record_mac); client_->ExpectSendAlert(bad_record_mac); ConnectExpectFail(); server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); } INSTANTIATE_TEST_SUITE_P( ExtensionStream, TlsExtensionTestGeneric, ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream, TlsConnectTestBase::kTlsVAll)); INSTANTIATE_TEST_SUITE_P( ExtensionDatagram, TlsExtensionTestGeneric, ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram, TlsConnectTestBase::kTlsV11Plus)); INSTANTIATE_TEST_SUITE_P(ExtensionDatagramOnly, TlsExtensionTestDtls, TlsConnectTestBase::kTlsV11Plus); INSTANTIATE_TEST_SUITE_P(ExtensionTls12, TlsExtensionTest12, ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV12)); INSTANTIATE_TEST_SUITE_P(ExtensionTls12Plus, TlsExtensionTest12Plus, ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV12Plus)); INSTANTIATE_TEST_SUITE_P( ExtensionPre13Stream, TlsExtensionTestPre13, ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream, TlsConnectTestBase::kTlsV10ToV12)); INSTANTIATE_TEST_SUITE_P(ExtensionPre13Datagram, TlsExtensionTestPre13, ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV11V12)); INSTANTIATE_TEST_SUITE_P(ExtensionTls13, TlsExtensionTest13, TlsConnectTestBase::kTlsVariantsAll); INSTANTIATE_TEST_SUITE_P( BogusExtensionStream, TlsBogusExtensionTestPre13, ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream, TlsConnectTestBase::kTlsV10ToV12)); INSTANTIATE_TEST_SUITE_P( BogusExtensionDatagram, TlsBogusExtensionTestPre13, ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram, TlsConnectTestBase::kTlsV11V12)); INSTANTIATE_TEST_SUITE_P(BogusExtension13, TlsBogusExtensionTest13, ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV13)); INSTANTIATE_TEST_SUITE_P(DisallowedExtension13, TlsDisallowedExtensionTest13, ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV13)); INSTANTIATE_TEST_SUITE_P(DisallowedUnadvertisedExtension13, TlsDisallowedUnadvertisedExtensionTest13, ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV13)); } // namespace nss_test