diff options
Diffstat (limited to 'security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc')
-rw-r--r-- | security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc | 274 |
1 files changed, 50 insertions, 224 deletions
diff --git a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc index a413caf2c..ce0e3ca8d 100644 --- a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc @@ -9,7 +9,6 @@ #include "secerr.h" #include "ssl.h" #include "sslerr.h" -#include "sslexp.h" #include "sslproto.h" extern "C" { @@ -247,7 +246,8 @@ TEST_P(TlsConnectGeneric, ConnectWithExpiredTicketAtServer) { : ssl_session_ticket_xtn; auto capture = std::make_shared<TlsExtensionCapture>(xtn); client_->SetPacketFilter(capture); - StartConnect(); + client_->StartConnect(); + server_->StartConnect(); client_->Handshake(); EXPECT_TRUE(capture->captured()); EXPECT_LT(0U, capture->extension().len()); @@ -355,7 +355,10 @@ TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceReuseKey) { // This test parses the ServerKeyExchange, which isn't in 1.3 TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceNewKey) { - server_->SetOption(SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE); + server_->EnsureTlsSetup(); + SECStatus rv = + SSL_OptionSet(server_->ssl_fd(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE); + EXPECT_EQ(SECSuccess, rv); auto i1 = std::make_shared<TlsInspectorRecordHandshakeMessage>( kTlsHandshakeServerKeyExchange); server_->SetPacketFilter(i1); @@ -366,7 +369,9 @@ TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceNewKey) { // Restart Reset(); - server_->SetOption(SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE); + server_->EnsureTlsSetup(); + rv = SSL_OptionSet(server_->ssl_fd(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE); + EXPECT_EQ(SECSuccess, rv); auto i2 = std::make_shared<TlsInspectorRecordHandshakeMessage>( kTlsHandshakeServerKeyExchange); server_->SetPacketFilter(i2); @@ -396,8 +401,7 @@ TEST_P(TlsConnectTls13, TestTls13ResumeDifferentGroup) { client_->ConfigNamedGroups(kFFDHEGroups); server_->ConfigNamedGroups(kFFDHEGroups); Connect(); - CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign, ssl_sig_none); } // We need to enable different cipher suites at different times in the following @@ -457,6 +461,36 @@ TEST_P(TlsConnectGeneric, TestResumeServerDifferentCipher) { CheckKeys(); } +class SelectedCipherSuiteReplacer : public TlsHandshakeFilter { + public: + SelectedCipherSuiteReplacer(uint16_t suite) : cipher_suite_(suite) {} + + protected: + PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) override { + if (header.handshake_type() != kTlsHandshakeServerHello) { + return KEEP; + } + + *output = input; + uint32_t temp = 0; + EXPECT_TRUE(input.Read(0, 2, &temp)); + // Cipher suite is after version(2) and random(32). + size_t pos = 34; + if (temp < SSL_LIBRARY_VERSION_TLS_1_3) { + // In old versions, we have to skip a session_id too. + EXPECT_TRUE(input.Read(pos, 1, &temp)); + pos += 1 + temp; + } + output->Write(pos, static_cast<uint32_t>(cipher_suite_), 2); + return CHANGE; + } + + private: + uint16_t cipher_suite_; +}; + // Test that the client doesn't tolerate the server picking a different cipher // suite for resumption. TEST_P(TlsConnectStream, TestResumptionOverrideCipher) { @@ -490,13 +524,16 @@ TEST_P(TlsConnectStream, TestResumptionOverrideCipher) { class SelectedVersionReplacer : public TlsHandshakeFilter { public: - SelectedVersionReplacer(uint16_t version) - : TlsHandshakeFilter({kTlsHandshakeServerHello}), version_(version) {} + SelectedVersionReplacer(uint16_t version) : version_(version) {} protected: PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) override { + if (header.handshake_type() != kTlsHandshakeServerHello) { + return KEEP; + } + *output = input; output->Write(0, static_cast<uint32_t>(version_), 2); return CHANGE; @@ -572,7 +609,7 @@ TEST_F(TlsConnectTest, TestTls13ResumptionTwice) { Connect(); SendReceive(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_none); // The filter will go away when we reset, so save the captured extension. DataBuffer initialTicket(c1->extension()); ASSERT_LT(0U, initialTicket.len()); @@ -590,7 +627,7 @@ TEST_F(TlsConnectTest, TestTls13ResumptionTwice) { Connect(); SendReceive(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_none); ASSERT_LT(0U, c2->extension().len()); ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd())); @@ -615,158 +652,18 @@ TEST_F(TlsConnectTest, TestTls13ResumptionDuplicateNST) { // Clear the session ticket keys to invalidate the old ticket. SSLInt_ClearSelfEncryptKey(); - SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0); - - SendReceive(); // Need to read so that we absorb the session tickets. - CheckKeys(); - - // Resume the connection. - Reset(); - ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); - ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); - ExpectResumption(RESUME_TICKET); - Connect(); - SendReceive(); -} - -// Check that the value captured in a NewSessionTicket message matches the value -// captured from a pre_shared_key extension. -void NstTicketMatchesPskIdentity(const DataBuffer& nst, const DataBuffer& psk) { - uint32_t len; - - size_t offset = 4 + 4; // Skip ticket_lifetime and ticket_age_add. - ASSERT_TRUE(nst.Read(offset, 1, &len)); - offset += 1 + len; // Skip ticket_nonce. - - ASSERT_TRUE(nst.Read(offset, 2, &len)); - offset += 2; // Skip the ticket length. - ASSERT_LE(offset + len, nst.len()); - DataBuffer nst_ticket(nst.data() + offset, static_cast<size_t>(len)); - - offset = 2; // Skip the identities length. - ASSERT_TRUE(psk.Read(offset, 2, &len)); - offset += 2; // Skip the identity length. - ASSERT_LE(offset + len, psk.len()); - DataBuffer psk_ticket(psk.data() + offset, static_cast<size_t>(len)); - - EXPECT_EQ(nst_ticket, psk_ticket); -} - -TEST_F(TlsConnectTest, TestTls13ResumptionDuplicateNSTWithToken) { - ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); - ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); - - auto nst_capture = std::make_shared<TlsInspectorRecordHandshakeMessage>( - ssl_hs_new_session_ticket); - server_->SetTlsRecordFilter(nst_capture); - Connect(); - - // Clear the session ticket keys to invalidate the old ticket. - SSLInt_ClearSelfEncryptKey(); - nst_capture->Reset(); - uint8_t token[] = {0x20, 0x20, 0xff, 0x00}; - EXPECT_EQ(SECSuccess, - SSL_SendSessionTicket(server_->ssl_fd(), token, sizeof(token))); + SSLInt_SendNewSessionTicket(server_->ssl_fd()); SendReceive(); // Need to read so that we absorb the session tickets. CheckKeys(); - EXPECT_LT(0U, nst_capture->buffer().len()); // Resume the connection. Reset(); ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); ExpectResumption(RESUME_TICKET); - - auto psk_capture = - std::make_shared<TlsExtensionCapture>(ssl_tls13_pre_shared_key_xtn); - client_->SetPacketFilter(psk_capture); Connect(); SendReceive(); - - NstTicketMatchesPskIdentity(nst_capture->buffer(), psk_capture->extension()); -} - -// Disable SSL_ENABLE_SESSION_TICKETS but ensure that tickets can still be sent -// by invoking SSL_SendSessionTicket directly (and that the ticket is usable). -TEST_F(TlsConnectTest, SendSessionTicketWithTicketsDisabled) { - ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); - ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); - - EXPECT_EQ(SECSuccess, SSL_OptionSet(server_->ssl_fd(), - SSL_ENABLE_SESSION_TICKETS, PR_FALSE)); - - auto nst_capture = std::make_shared<TlsInspectorRecordHandshakeMessage>( - ssl_hs_new_session_ticket); - server_->SetTlsRecordFilter(nst_capture); - Connect(); - - EXPECT_EQ(0U, nst_capture->buffer().len()) << "expect nothing captured yet"; - - EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0)); - EXPECT_LT(0U, nst_capture->buffer().len()) << "should capture now"; - - SendReceive(); // Ensure that the client reads the ticket. - - // Resume the connection. - Reset(); - ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); - ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); - ExpectResumption(RESUME_TICKET); - - auto psk_capture = - std::make_shared<TlsExtensionCapture>(ssl_tls13_pre_shared_key_xtn); - client_->SetPacketFilter(psk_capture); - Connect(); - SendReceive(); - - NstTicketMatchesPskIdentity(nst_capture->buffer(), psk_capture->extension()); -} - -// Test calling SSL_SendSessionTicket in inappropriate conditions. -TEST_F(TlsConnectTest, SendSessionTicketInappropriate) { - ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); - ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_2); - - EXPECT_EQ(SECFailure, SSL_SendSessionTicket(client_->ssl_fd(), NULL, 0)) - << "clients can't send tickets"; - EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); - - StartConnect(); - - EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0)) - << "no ticket before the handshake has started"; - EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); - Handshake(); - EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0)) - << "no special tickets in TLS 1.2"; - EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); -} - -TEST_F(TlsConnectTest, SendSessionTicketMassiveToken) { - ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); - ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); - Connect(); - // It should be safe to set length with a NULL token because the length should - // be checked before reading token. - EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0x1ffff)) - << "this is clearly too big"; - EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); - - static const uint8_t big_token[0xffff] = {1}; - EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), big_token, - sizeof(big_token))) - << "this is too big, but that's not immediately obvious"; - EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); -} - -TEST_F(TlsConnectDatagram13, SendSessionTicketDtls) { - ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); - ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); - Connect(); - EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0)) - << "no extra tickets in DTLS until we have Ack support"; - EXPECT_EQ(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION, PORT_GetError()); } TEST_F(TlsConnectTest, TestTls13ResumptionDowngrade) { @@ -822,84 +719,13 @@ TEST_F(TlsConnectTest, TestTls13ResumptionForcedDowngrade) { TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256)); filters.push_back( std::make_shared<SelectedVersionReplacer>(SSL_LIBRARY_VERSION_TLS_1_2)); - - // Drop a bunch of extensions so that we get past the SH processing. The - // version extension says TLS 1.3, which is counter to our goal, the others - // are not permitted in TLS 1.2 handshakes. - filters.push_back( - std::make_shared<TlsExtensionDropper>(ssl_tls13_supported_versions_xtn)); - filters.push_back( - std::make_shared<TlsExtensionDropper>(ssl_tls13_key_share_xtn)); - filters.push_back( - std::make_shared<TlsExtensionDropper>(ssl_tls13_pre_shared_key_xtn)); server_->SetPacketFilter(std::make_shared<ChainedPacketFilter>(filters)); - // The client here generates an unexpected_message alert when it receives an - // encrypted handshake message from the server (EncryptedExtension). The - // client expects to receive an unencrypted TLS 1.2 Certificate message. - // The server can't decrypt the alert. - client_->ExpectSendAlert(kTlsAlertUnexpectedMessage); + client_->ExpectSendAlert(kTlsAlertDecodeError); server_->ExpectSendAlert(kTlsAlertBadRecordMac); // Server can't read ConnectExpectFail(); - client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA); + client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); } -TEST_P(TlsConnectGeneric, ReConnectTicket) { - ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); - server_->EnableSingleCipher(ChooseOneCipher(version_)); - Connect(); - SendReceive(); - CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); - // Resume - Reset(); - ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); - ExpectResumption(RESUME_TICKET); - Connect(); - // Only the client knows this. - CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, - ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256); -} - -TEST_P(TlsConnectGenericPre13, ReConnectCache) { - ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID); - server_->EnableSingleCipher(ChooseOneCipher(version_)); - Connect(); - SendReceive(); - CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); - // Resume - Reset(); - ExpectResumption(RESUME_SESSIONID); - Connect(); - CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, - ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256); -} - -TEST_P(TlsConnectGeneric, ReConnectAgainTicket) { - ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); - server_->EnableSingleCipher(ChooseOneCipher(version_)); - Connect(); - SendReceive(); - CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); - // Resume - Reset(); - ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); - ExpectResumption(RESUME_TICKET); - Connect(); - // Only the client knows this. - CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, - ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256); - // Resume connection again - Reset(); - ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); - ExpectResumption(RESUME_TICKET, 2); - Connect(); - // Only the client knows this. - CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, - ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256); -} - } // namespace nss_test |