| /* -*- 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 "secerr.h" |
| #include "ssl.h" |
| #include "sslerr.h" |
| #include "sslproto.h" |
| |
| extern "C" { |
| // This is not something that should make you happy. |
| #include "libssl_internals.h" |
| } |
| |
| #include "gtest_utils.h" |
| #include "nss_scoped_ptrs.h" |
| #include "tls_connect.h" |
| #include "tls_filter.h" |
| #include "tls_parser.h" |
| |
| namespace nss_test { |
| |
| TEST_P(TlsConnectGeneric, ServerAuthBigRsa) { |
| Reset(TlsAgent::kRsa2048); |
| Connect(); |
| CheckKeys(); |
| } |
| |
| TEST_P(TlsConnectGeneric, ServerAuthRsaChain) { |
| Reset("rsa_chain"); |
| Connect(); |
| CheckKeys(); |
| size_t chain_length; |
| EXPECT_TRUE(client_->GetPeerChainLength(&chain_length)); |
| 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(); |
| CheckKeys(); |
| size_t chain_length; |
| EXPECT_TRUE(client_->GetPeerChainLength(&chain_length)); |
| EXPECT_EQ(2UL, chain_length); |
| } |
| |
| TEST_P(TlsConnectGeneric, ServerAuthRsaCARsaPssChain) { |
| Reset("rsa_ca_rsa_pss_chain"); |
| Connect(); |
| CheckKeys(); |
| size_t chain_length; |
| EXPECT_TRUE(client_->GetPeerChainLength(&chain_length)); |
| 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); |
| Connect(); |
| CheckKeys(); |
| } |
| |
| class TlsCertificateRequestContextRecorder : public TlsHandshakeFilter { |
| public: |
| TlsCertificateRequestContextRecorder(const std::shared_ptr<TlsAgent>& a, |
| uint8_t handshake_type) |
| : TlsHandshakeFilter(a, {handshake_type}), buffer_(), filtered_(false) { |
| EnableDecryption(); |
| } |
| |
| bool filtered() const { return filtered_; } |
| const DataBuffer& buffer() const { return buffer_; } |
| |
| protected: |
| virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, |
| const DataBuffer& input, |
| DataBuffer* output) { |
| assert(1 < input.len()); |
| size_t len = input.data()[0]; |
| assert(len + 1 < input.len()); |
| buffer_.Assign(input.data() + 1, len); |
| filtered_ = true; |
| return KEEP; |
| } |
| |
| private: |
| DataBuffer buffer_; |
| bool filtered_; |
| }; |
| |
| // All stream only tests; DTLS isn't supported yet. |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuth) { |
| EnsureTlsSetup(); |
| auto capture_cert_req = MakeTlsFilter<TlsCertificateRequestContextRecorder>( |
| server_, kTlsHandshakeCertificateRequest); |
| auto capture_certificate = |
| MakeTlsFilter<TlsCertificateRequestContextRecorder>( |
| client_, kTlsHandshakeCertificate); |
| client_->SetupClientAuth(); |
| client_->SetOption(SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE); |
| size_t called = 0; |
| server_->SetAuthCertificateCallback( |
| [&called](TlsAgent*, PRBool, PRBool) -> SECStatus { |
| called++; |
| return SECSuccess; |
| }); |
| Connect(); |
| EXPECT_EQ(0U, called); |
| EXPECT_FALSE(capture_cert_req->filtered()); |
| EXPECT_FALSE(capture_certificate->filtered()); |
| // Send CertificateRequest. |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| // Need to do a round-trip so that the post-handshake message is |
| // handled on both client and server. |
| server_->SendData(50); |
| client_->ReadBytes(50); |
| client_->SendData(50); |
| server_->ReadBytes(50); |
| EXPECT_EQ(1U, called); |
| EXPECT_TRUE(capture_cert_req->filtered()); |
| EXPECT_TRUE(capture_certificate->filtered()); |
| // Check if a non-empty request context is generated and it is |
| // properly sent back. |
| EXPECT_LT(0U, capture_cert_req->buffer().len()); |
| EXPECT_EQ(capture_cert_req->buffer().len(), |
| capture_certificate->buffer().len()); |
| EXPECT_EQ(0, memcmp(capture_cert_req->buffer().data(), |
| capture_certificate->buffer().data(), |
| capture_cert_req->buffer().len())); |
| ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd())); |
| ASSERT_NE(nullptr, cert1.get()); |
| ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd())); |
| ASSERT_NE(nullptr, cert2.get()); |
| EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert)); |
| } |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthAfterResumption) { |
| ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); |
| ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); |
| Connect(); |
| |
| 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); |
| |
| client_->SetupClientAuth(); |
| client_->SetOption(SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE); |
| Connect(); |
| SendReceive(); |
| |
| size_t called = 0; |
| server_->SetAuthCertificateCallback( |
| [&called](TlsAgent*, PRBool, PRBool) -> SECStatus { |
| called++; |
| return SECSuccess; |
| }); |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| server_->SendData(50); |
| client_->ReadBytes(50); |
| client_->SendData(50); |
| server_->ReadBytes(50); |
| EXPECT_EQ(1U, called); |
| |
| ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd())); |
| ASSERT_NE(nullptr, cert1.get()); |
| ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd())); |
| ASSERT_NE(nullptr, cert2.get()); |
| EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert)); |
| } |
| |
| static SECStatus GetClientAuthDataHook(void* self, PRFileDesc* fd, |
| CERTDistNames* caNames, |
| CERTCertificate** clientCert, |
| SECKEYPrivateKey** clientKey) { |
| ScopedCERTCertificate cert; |
| ScopedSECKEYPrivateKey priv; |
| // use a different certificate than TlsAgent::kClient |
| if (!TlsAgent::LoadCertificate(TlsAgent::kRsa2048, &cert, &priv)) { |
| return SECFailure; |
| } |
| |
| *clientCert = cert.release(); |
| *clientKey = priv.release(); |
| return SECSuccess; |
| } |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthMultiple) { |
| client_->SetupClientAuth(); |
| EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), |
| SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); |
| size_t called = 0; |
| server_->SetAuthCertificateCallback( |
| [&called](TlsAgent*, PRBool, PRBool) -> SECStatus { |
| called++; |
| return SECSuccess; |
| }); |
| Connect(); |
| EXPECT_EQ(0U, called); |
| EXPECT_EQ(nullptr, SSL_PeerCertificate(server_->ssl_fd())); |
| // Send 1st CertificateRequest. |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| server_->SendData(50); |
| client_->ReadBytes(50); |
| client_->SendData(50); |
| server_->ReadBytes(50); |
| EXPECT_EQ(1U, called); |
| ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd())); |
| ASSERT_NE(nullptr, cert1.get()); |
| ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd())); |
| ASSERT_NE(nullptr, cert2.get()); |
| EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert)); |
| // Send 2nd CertificateRequest. |
| EXPECT_EQ(SECSuccess, SSL_GetClientAuthDataHook( |
| client_->ssl_fd(), GetClientAuthDataHook, nullptr)); |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| server_->SendData(50); |
| client_->ReadBytes(50); |
| client_->SendData(50); |
| server_->ReadBytes(50); |
| EXPECT_EQ(2U, called); |
| ScopedCERTCertificate cert3(SSL_PeerCertificate(server_->ssl_fd())); |
| ASSERT_NE(nullptr, cert3.get()); |
| ScopedCERTCertificate cert4(SSL_LocalCertificate(client_->ssl_fd())); |
| ASSERT_NE(nullptr, cert4.get()); |
| EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert4->derCert)); |
| EXPECT_FALSE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert1->derCert)); |
| } |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthConcurrent) { |
| client_->SetupClientAuth(); |
| EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), |
| SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); |
| Connect(); |
| // Send 1st CertificateRequest. |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| // Send 2nd CertificateRequest. |
| EXPECT_EQ(SECFailure, SSL_SendCertificateRequest(server_->ssl_fd())); |
| EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); |
| } |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthBeforeKeyUpdate) { |
| client_->SetupClientAuth(); |
| EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), |
| SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); |
| Connect(); |
| // Send CertificateRequest. |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| // Send KeyUpdate. |
| EXPECT_EQ(SECFailure, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE)); |
| EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); |
| } |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDuringClientKeyUpdate) { |
| client_->SetupClientAuth(); |
| EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), |
| SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); |
| Connect(); |
| CheckEpochs(3, 3); |
| // Send CertificateRequest from server. |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| // Send KeyUpdate from client. |
| EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_TRUE)); |
| server_->SendData(50); // server sends CertificateRequest |
| client_->SendData(50); // client sends KeyUpdate |
| server_->ReadBytes(50); // server receives KeyUpdate and defers response |
| CheckEpochs(4, 3); |
| client_->ReadBytes(50); // client receives CertificateRequest |
| client_->SendData( |
| 50); // client sends Certificate, CertificateVerify, Finished |
| server_->ReadBytes( |
| 50); // server receives Certificate, CertificateVerify, Finished |
| client_->CheckEpochs(3, 4); |
| server_->CheckEpochs(4, 4); |
| server_->SendData(50); // server sends KeyUpdate |
| client_->ReadBytes(50); // client receives KeyUpdate |
| client_->CheckEpochs(4, 4); |
| } |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthMissingExtension) { |
| client_->SetupClientAuth(); |
| Connect(); |
| // Send CertificateRequest, should fail due to missing |
| // post_handshake_auth extension. |
| EXPECT_EQ(SECFailure, SSL_SendCertificateRequest(server_->ssl_fd())); |
| EXPECT_EQ(SSL_ERROR_MISSING_POST_HANDSHAKE_AUTH_EXTENSION, PORT_GetError()); |
| } |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthAfterClientAuth) { |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(true); |
| EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), |
| SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); |
| size_t called = 0; |
| server_->SetAuthCertificateCallback( |
| [&called](TlsAgent*, PRBool, PRBool) -> SECStatus { |
| called++; |
| return SECSuccess; |
| }); |
| Connect(); |
| EXPECT_EQ(1U, called); |
| ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd())); |
| ASSERT_NE(nullptr, cert1.get()); |
| ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd())); |
| ASSERT_NE(nullptr, cert2.get()); |
| EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert)); |
| // Send CertificateRequest. |
| EXPECT_EQ(SECSuccess, SSL_GetClientAuthDataHook( |
| client_->ssl_fd(), GetClientAuthDataHook, nullptr)); |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| server_->SendData(50); |
| client_->ReadBytes(50); |
| client_->SendData(50); |
| server_->ReadBytes(50); |
| EXPECT_EQ(2U, called); |
| ScopedCERTCertificate cert3(SSL_PeerCertificate(server_->ssl_fd())); |
| ASSERT_NE(nullptr, cert3.get()); |
| ScopedCERTCertificate cert4(SSL_LocalCertificate(client_->ssl_fd())); |
| ASSERT_NE(nullptr, cert4.get()); |
| EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert4->derCert)); |
| EXPECT_FALSE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert1->derCert)); |
| } |
| |
| // Damages the request context in a CertificateRequest message. |
| // We don't modify a Certificate message instead, so that the client |
| // can compute CertificateVerify correctly. |
| class TlsDamageCertificateRequestContextFilter : public TlsHandshakeFilter { |
| public: |
| TlsDamageCertificateRequestContextFilter(const std::shared_ptr<TlsAgent>& a) |
| : TlsHandshakeFilter(a, {kTlsHandshakeCertificateRequest}) { |
| EnableDecryption(); |
| } |
| |
| protected: |
| virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, |
| const DataBuffer& input, |
| DataBuffer* output) { |
| *output = input; |
| assert(1 < output->len()); |
| // The request context has a 1 octet length. |
| output->data()[1] ^= 73; |
| return CHANGE; |
| } |
| }; |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthContextMismatch) { |
| EnsureTlsSetup(); |
| MakeTlsFilter<TlsDamageCertificateRequestContextFilter>(server_); |
| client_->SetupClientAuth(); |
| EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), |
| SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); |
| Connect(); |
| // Send CertificateRequest. |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| server_->SendData(50); |
| client_->ReadBytes(50); |
| client_->SendData(50); |
| server_->ExpectSendAlert(kTlsAlertIllegalParameter); |
| server_->ReadBytes(50); |
| EXPECT_EQ(SSL_ERROR_RX_MALFORMED_CERTIFICATE, PORT_GetError()); |
| server_->ExpectReadWriteError(); |
| server_->SendData(50); |
| client_->ExpectReceiveAlert(kTlsAlertIllegalParameter); |
| client_->ReadBytes(50); |
| EXPECT_EQ(SSL_ERROR_ILLEGAL_PARAMETER_ALERT, PORT_GetError()); |
| } |
| |
| // Replaces signature in a CertificateVerify message. |
| class TlsDamageSignatureFilter : public TlsHandshakeFilter { |
| public: |
| TlsDamageSignatureFilter(const std::shared_ptr<TlsAgent>& a) |
| : TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}) { |
| EnableDecryption(); |
| } |
| |
| protected: |
| virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, |
| const DataBuffer& input, |
| DataBuffer* output) { |
| *output = input; |
| assert(2 < output->len()); |
| // The signature follows a 2-octet signature scheme. |
| output->data()[2] ^= 73; |
| return CHANGE; |
| } |
| }; |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthBadSignature) { |
| EnsureTlsSetup(); |
| MakeTlsFilter<TlsDamageSignatureFilter>(client_); |
| client_->SetupClientAuth(); |
| EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), |
| SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); |
| Connect(); |
| // Send CertificateRequest. |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| server_->SendData(50); |
| client_->ReadBytes(50); |
| client_->SendData(50); |
| server_->ExpectSendAlert(kTlsAlertDecodeError); |
| server_->ReadBytes(50); |
| EXPECT_EQ(SSL_ERROR_RX_MALFORMED_CERT_VERIFY, PORT_GetError()); |
| } |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDecline) { |
| EnsureTlsSetup(); |
| auto capture_cert_req = MakeTlsFilter<TlsCertificateRequestContextRecorder>( |
| server_, kTlsHandshakeCertificateRequest); |
| auto capture_certificate = |
| MakeTlsFilter<TlsCertificateRequestContextRecorder>( |
| client_, kTlsHandshakeCertificate); |
| client_->SetupClientAuth(); |
| EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), |
| SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); |
| EXPECT_EQ(SECSuccess, |
| SSL_OptionSet(server_->ssl_fd(), SSL_REQUIRE_CERTIFICATE, |
| SSL_REQUIRE_ALWAYS)); |
| // Client to decline the certificate request. |
| EXPECT_EQ(SECSuccess, |
| SSL_GetClientAuthDataHook( |
| client_->ssl_fd(), |
| [](void*, PRFileDesc*, CERTDistNames*, CERTCertificate**, |
| SECKEYPrivateKey**) -> SECStatus { return SECFailure; }, |
| nullptr)); |
| size_t called = 0; |
| server_->SetAuthCertificateCallback( |
| [&called](TlsAgent*, PRBool, PRBool) -> SECStatus { |
| called++; |
| return SECSuccess; |
| }); |
| Connect(); |
| EXPECT_EQ(0U, called); |
| // Send CertificateRequest. |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| server_->SendData(50); // send Certificate Request |
| client_->ReadBytes(50); // read Certificate Request |
| client_->SendData(50); // send empty Certificate+Finished |
| server_->ExpectSendAlert(kTlsAlertCertificateRequired); |
| server_->ReadBytes(50); // read empty Certificate+Finished |
| server_->ExpectReadWriteError(); |
| server_->SendData(50); // send alert |
| // AuthCertificateCallback is not called, because the client sends |
| // an empty certificate_list. |
| EXPECT_EQ(0U, called); |
| EXPECT_TRUE(capture_cert_req->filtered()); |
| EXPECT_TRUE(capture_certificate->filtered()); |
| // Check if a non-empty request context is generated and it is |
| // properly sent back. |
| EXPECT_LT(0U, capture_cert_req->buffer().len()); |
| EXPECT_EQ(capture_cert_req->buffer().len(), |
| capture_certificate->buffer().len()); |
| EXPECT_EQ(0, memcmp(capture_cert_req->buffer().data(), |
| capture_certificate->buffer().data(), |
| capture_cert_req->buffer().len())); |
| } |
| |
| // Check if post-handshake auth still works when session tickets are enabled: |
| // https://bugzilla.mozilla.org/show_bug.cgi?id=1553443 |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthWithSessionTicketsEnabled) { |
| EnsureTlsSetup(); |
| client_->SetupClientAuth(); |
| EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), |
| SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); |
| EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), |
| SSL_ENABLE_SESSION_TICKETS, PR_TRUE)); |
| EXPECT_EQ(SECSuccess, SSL_OptionSet(server_->ssl_fd(), |
| SSL_ENABLE_SESSION_TICKETS, PR_TRUE)); |
| size_t called = 0; |
| server_->SetAuthCertificateCallback( |
| [&called](TlsAgent*, PRBool, PRBool) -> SECStatus { |
| called++; |
| return SECSuccess; |
| }); |
| Connect(); |
| EXPECT_EQ(0U, called); |
| // Send CertificateRequest. |
| EXPECT_EQ(SECSuccess, SSL_GetClientAuthDataHook( |
| client_->ssl_fd(), GetClientAuthDataHook, nullptr)); |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| server_->SendData(50); |
| client_->ReadBytes(50); |
| client_->SendData(50); |
| server_->ReadBytes(50); |
| EXPECT_EQ(1U, called); |
| ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd())); |
| ASSERT_NE(nullptr, cert1.get()); |
| ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd())); |
| ASSERT_NE(nullptr, cert2.get()); |
| EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert)); |
| } |
| |
| TEST_P(TlsConnectGenericPre13, ClientAuthRequiredRejected) { |
| server_->RequestClientAuth(true); |
| ConnectExpectAlert(server_, kTlsAlertBadCertificate); |
| client_->CheckErrorCode(SSL_ERROR_BAD_CERT_ALERT); |
| server_->CheckErrorCode(SSL_ERROR_NO_CERTIFICATE); |
| } |
| |
| // In TLS 1.3, the client will claim that the connection is done and then |
| // receive the alert afterwards. So drive the handshake manually. |
| TEST_P(TlsConnectTls13, ClientAuthRequiredRejected) { |
| server_->RequestClientAuth(true); |
| StartConnect(); |
| client_->Handshake(); // CH |
| server_->Handshake(); // SH.. (no resumption) |
| client_->Handshake(); // Next message |
| ASSERT_EQ(TlsAgent::STATE_CONNECTED, client_->state()); |
| ExpectAlert(server_, kTlsAlertCertificateRequired); |
| server_->Handshake(); // Alert |
| server_->CheckErrorCode(SSL_ERROR_NO_CERTIFICATE); |
| client_->Handshake(); // Receive Alert |
| client_->CheckErrorCode(SSL_ERROR_RX_CERTIFICATE_REQUIRED_ALERT); |
| } |
| |
| TEST_P(TlsConnectGeneric, ClientAuthRequestedRejected) { |
| server_->RequestClientAuth(false); |
| Connect(); |
| CheckKeys(); |
| } |
| |
| TEST_P(TlsConnectGeneric, ClientAuthEcdsa) { |
| Reset(TlsAgent::kServerEcdsa256); |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(true); |
| Connect(); |
| CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa); |
| } |
| |
| TEST_P(TlsConnectGeneric, ClientAuthWithEch) { |
| Reset(TlsAgent::kServerEcdsa256); |
| EnsureTlsSetup(); |
| SetupEch(client_, server_); |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(true); |
| Connect(); |
| CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa); |
| } |
| |
| TEST_P(TlsConnectGeneric, ClientAuthBigRsa) { |
| Reset(TlsAgent::kServerRsa, TlsAgent::kRsa2048); |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(true); |
| Connect(); |
| CheckKeys(); |
| } |
| |
| // Offset is the position in the captured buffer where the signature sits. |
| static void CheckSigScheme(std::shared_ptr<TlsHandshakeRecorder>& capture, |
| size_t offset, std::shared_ptr<TlsAgent>& peer, |
| uint16_t expected_scheme, size_t expected_size) { |
| EXPECT_LT(offset + 2U, capture->buffer().len()); |
| |
| uint32_t scheme = 0; |
| capture->buffer().Read(offset, 2, &scheme); |
| EXPECT_EQ(expected_scheme, static_cast<uint16_t>(scheme)); |
| |
| ScopedCERTCertificate remote_cert(SSL_PeerCertificate(peer->ssl_fd())); |
| ASSERT_NE(nullptr, remote_cert.get()); |
| ScopedSECKEYPublicKey remote_key(CERT_ExtractPublicKey(remote_cert.get())); |
| ASSERT_NE(nullptr, remote_key.get()); |
| EXPECT_EQ(expected_size, SECKEY_PublicKeyStrengthInBits(remote_key.get())); |
| } |
| |
| // The server should prefer SHA-256 by default, even for the small key size used |
| // in the default certificate. |
| TEST_P(TlsConnectTls12, ServerAuthCheckSigAlg) { |
| EnsureTlsSetup(); |
| auto capture_ske = MakeTlsFilter<TlsHandshakeRecorder>( |
| server_, kTlsHandshakeServerKeyExchange); |
| Connect(); |
| CheckKeys(); |
| |
| const DataBuffer& buffer = capture_ske->buffer(); |
| EXPECT_LT(3U, buffer.len()); |
| EXPECT_EQ(3U, buffer.data()[0]) << "curve_type == named_curve"; |
| uint32_t tmp; |
| EXPECT_TRUE(buffer.Read(1, 2, &tmp)) << "read NamedCurve"; |
| EXPECT_EQ(ssl_grp_ec_curve25519, tmp); |
| EXPECT_TRUE(buffer.Read(3, 1, &tmp)) << " read ECPoint"; |
| CheckSigScheme(capture_ske, 4 + tmp, client_, ssl_sig_rsa_pss_rsae_sha256, |
| 1024); |
| } |
| |
| TEST_P(TlsConnectTls12, ClientAuthCheckSigAlg) { |
| EnsureTlsSetup(); |
| auto capture_cert_verify = MakeTlsFilter<TlsHandshakeRecorder>( |
| client_, kTlsHandshakeCertificateVerify); |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(true); |
| Connect(); |
| CheckKeys(); |
| |
| CheckSigScheme(capture_cert_verify, 0, server_, ssl_sig_rsa_pkcs1_sha1, 1024); |
| } |
| |
| TEST_P(TlsConnectTls12, ClientAuthBigRsaCheckSigAlg) { |
| Reset(TlsAgent::kServerRsa, TlsAgent::kRsa2048); |
| auto capture_cert_verify = MakeTlsFilter<TlsHandshakeRecorder>( |
| client_, kTlsHandshakeCertificateVerify); |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(true); |
| Connect(); |
| CheckKeys(); |
| CheckSigScheme(capture_cert_verify, 0, server_, ssl_sig_rsa_pss_rsae_sha256, |
| 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) {} |
| |
| 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); |
| } |
| |
| TEST_P(TlsConnectTls13, ClientAuthPkcs1SignatureScheme) { |
| static const SSLSignatureScheme kSignatureScheme[] = { |
| ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pss_rsae_sha256}; |
| |
| Reset(TlsAgent::kServerRsa, "rsa"); |
| client_->SetSignatureSchemes(kSignatureScheme, |
| PR_ARRAY_SIZE(kSignatureScheme)); |
| server_->SetSignatureSchemes(kSignatureScheme, |
| PR_ARRAY_SIZE(kSignatureScheme)); |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(true); |
| |
| auto capture_cert_verify = MakeTlsFilter<TlsHandshakeRecorder>( |
| client_, kTlsHandshakeCertificateVerify); |
| capture_cert_verify->EnableDecryption(); |
| |
| Connect(); |
| CheckSigScheme(capture_cert_verify, 0, server_, ssl_sig_rsa_pss_rsae_sha256, |
| 1024); |
| } |
| |
| // Client should refuse to connect without a usable signature scheme. |
| TEST_P(TlsConnectTls13, ClientAuthPkcs1SignatureSchemeOnly) { |
| static const SSLSignatureScheme kSignatureScheme[] = { |
| ssl_sig_rsa_pkcs1_sha256}; |
| |
| Reset(TlsAgent::kServerRsa, "rsa"); |
| client_->SetSignatureSchemes(kSignatureScheme, |
| PR_ARRAY_SIZE(kSignatureScheme)); |
| client_->SetupClientAuth(); |
| client_->StartConnect(); |
| client_->Handshake(); |
| EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state()); |
| client_->CheckErrorCode(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM); |
| } |
| |
| // Though the client has a usable signature scheme, when a certificate is |
| // requested, it can't produce one. |
| TEST_P(TlsConnectTls13, ClientAuthPkcs1AndEcdsaScheme) { |
| static const SSLSignatureScheme kSignatureScheme[] = { |
| ssl_sig_rsa_pkcs1_sha256, ssl_sig_ecdsa_secp256r1_sha256}; |
| |
| Reset(TlsAgent::kServerRsa, "rsa"); |
| client_->SetSignatureSchemes(kSignatureScheme, |
| PR_ARRAY_SIZE(kSignatureScheme)); |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(true); |
| |
| ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); |
| server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); |
| client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| } |
| |
| class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter { |
| public: |
| TlsZeroCertificateRequestSigAlgsFilter(const std::shared_ptr<TlsAgent>& a) |
| : TlsHandshakeFilter(a, {kTlsHandshakeCertificateRequest}) {} |
| virtual PacketFilter::Action FilterHandshake( |
| const TlsHandshakeFilter::HandshakeHeader& header, |
| const DataBuffer& input, DataBuffer* output) { |
| TlsParser parser(input); |
| std::cerr << "Zeroing CertReq.supported_signature_algorithms" << std::endl; |
| |
| DataBuffer cert_types; |
| if (!parser.ReadVariable(&cert_types, 1)) { |
| ADD_FAILURE(); |
| return KEEP; |
| } |
| |
| if (!parser.SkipVariable(2)) { |
| ADD_FAILURE(); |
| return KEEP; |
| } |
| |
| DataBuffer cas; |
| if (!parser.ReadVariable(&cas, 2)) { |
| ADD_FAILURE(); |
| return KEEP; |
| } |
| |
| size_t idx = 0; |
| |
| // Write certificate types. |
| idx = output->Write(idx, cert_types.len(), 1); |
| idx = output->Write(idx, cert_types); |
| |
| // Write zero signature algorithms. |
| idx = output->Write(idx, 0U, 2); |
| |
| // Write certificate authorities. |
| idx = output->Write(idx, cas.len(), 2); |
| idx = output->Write(idx, cas); |
| |
| return CHANGE; |
| } |
| }; |
| |
| // Check that we send an alert when the server doesn't provide any |
| // supported_signature_algorithms in the CertificateRequest message. |
| TEST_P(TlsConnectTls12, ClientAuthNoSigAlgs) { |
| EnsureTlsSetup(); |
| MakeTlsFilter<TlsZeroCertificateRequestSigAlgsFilter>(server_); |
| auto capture_cert_verify = MakeTlsFilter<TlsHandshakeRecorder>( |
| client_, kTlsHandshakeCertificateVerify); |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(true); |
| |
| ConnectExpectAlert(client_, kTlsAlertHandshakeFailure); |
| |
| server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT); |
| client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); |
| } |
| |
| static SECStatus GetEcClientAuthDataHook(void* self, PRFileDesc* fd, |
| CERTDistNames* caNames, |
| CERTCertificate** clientCert, |
| SECKEYPrivateKey** clientKey) { |
| ScopedCERTCertificate cert; |
| ScopedSECKEYPrivateKey priv; |
| // use a different certificate than TlsAgent::kClient |
| if (!TlsAgent::LoadCertificate(TlsAgent::kServerEcdsa256, &cert, &priv)) { |
| return SECFailure; |
| } |
| |
| *clientCert = cert.release(); |
| *clientKey = priv.release(); |
| return SECSuccess; |
| } |
| |
| TEST_P(TlsConnectTls12Plus, ClientAuthDisjointSchemes) { |
| EnsureTlsSetup(); |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(true); |
| |
| SSLSignatureScheme server_scheme = ssl_sig_rsa_pss_rsae_sha256; |
| std::vector<SSLSignatureScheme> client_schemes{ |
| ssl_sig_rsa_pss_rsae_sha256, ssl_sig_ecdsa_secp256r1_sha256}; |
| SECStatus rv = |
| SSL_SignatureSchemePrefSet(server_->ssl_fd(), &server_scheme, 1); |
| EXPECT_EQ(SECSuccess, rv); |
| rv = SSL_SignatureSchemePrefSet( |
| client_->ssl_fd(), client_schemes.data(), |
| static_cast<unsigned int>(client_schemes.size())); |
| EXPECT_EQ(SECSuccess, rv); |
| |
| // Select an EC cert that's incompatible with server schemes. |
| EXPECT_EQ(SECSuccess, |
| SSL_GetClientAuthDataHook(client_->ssl_fd(), |
| GetEcClientAuthDataHook, nullptr)); |
| |
| StartConnect(); |
| client_->Handshake(); // CH |
| server_->Handshake(); // SH |
| client_->Handshake(); |
| if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { |
| ASSERT_EQ(TlsAgent::STATE_CONNECTED, client_->state()); |
| ExpectAlert(server_, kTlsAlertCertificateRequired); |
| server_->Handshake(); // Alert |
| server_->CheckErrorCode(SSL_ERROR_NO_CERTIFICATE); |
| client_->Handshake(); // Receive Alert |
| client_->CheckErrorCode(SSL_ERROR_RX_CERTIFICATE_REQUIRED_ALERT); |
| } else { |
| ASSERT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); |
| ExpectAlert(server_, kTlsAlertBadCertificate); |
| server_->Handshake(); // Alert |
| server_->CheckErrorCode(SSL_ERROR_NO_CERTIFICATE); |
| client_->Handshake(); // Receive Alert |
| client_->CheckErrorCode(SSL_ERROR_BAD_CERT_ALERT); |
| } |
| } |
| |
| TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDisjointSchemes) { |
| EnsureTlsSetup(); |
| SSLSignatureScheme server_scheme = ssl_sig_rsa_pss_rsae_sha256; |
| std::vector<SSLSignatureScheme> client_schemes{ |
| ssl_sig_rsa_pss_rsae_sha256, ssl_sig_ecdsa_secp256r1_sha256}; |
| SECStatus rv = |
| SSL_SignatureSchemePrefSet(server_->ssl_fd(), &server_scheme, 1); |
| EXPECT_EQ(SECSuccess, rv); |
| rv = SSL_SignatureSchemePrefSet( |
| client_->ssl_fd(), client_schemes.data(), |
| static_cast<unsigned int>(client_schemes.size())); |
| EXPECT_EQ(SECSuccess, rv); |
| |
| client_->SetupClientAuth(); |
| client_->SetOption(SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE); |
| |
| // Select an EC cert that's incompatible with server schemes. |
| EXPECT_EQ(SECSuccess, |
| SSL_GetClientAuthDataHook(client_->ssl_fd(), |
| GetEcClientAuthDataHook, nullptr)); |
| |
| Connect(); |
| |
| // Send CertificateRequest. |
| EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) |
| << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); |
| |
| // Need to do a round-trip so that the post-handshake message is |
| // handled on both client and server. |
| server_->SendData(50); |
| client_->ReadBytes(50); |
| client_->SendData(50); |
| server_->ReadBytes(50); |
| |
| ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd())); |
| ASSERT_EQ(nullptr, cert1.get()); |
| ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd())); |
| ASSERT_EQ(nullptr, cert2.get()); |
| } |
| |
| static const SSLSignatureScheme kSignatureSchemeEcdsaSha384[] = { |
| ssl_sig_ecdsa_secp384r1_sha384}; |
| static const SSLSignatureScheme kSignatureSchemeEcdsaSha256[] = { |
| ssl_sig_ecdsa_secp256r1_sha256}; |
| static const SSLSignatureScheme kSignatureSchemeRsaSha384[] = { |
| ssl_sig_rsa_pkcs1_sha384}; |
| static const SSLSignatureScheme kSignatureSchemeRsaSha256[] = { |
| ssl_sig_rsa_pkcs1_sha256}; |
| |
| static SSLNamedGroup NamedGroupForEcdsa384(uint16_t version) { |
| // NSS tries to match the group size to the symmetric cipher. In TLS 1.1 and |
| // 1.0, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA is the highest priority suite, so |
| // we use P-384. With TLS 1.2 on we pick AES-128 GCM so use x25519. |
| if (version <= SSL_LIBRARY_VERSION_TLS_1_1) { |
| return ssl_grp_ec_secp384r1; |
| } |
| return ssl_grp_ec_curve25519; |
| } |
| |
| // When signature algorithms match up, this should connect successfully; even |
| // for TLS 1.1 and 1.0, where they should be ignored. |
| TEST_P(TlsConnectGeneric, SignatureAlgorithmServerAuth) { |
| Reset(TlsAgent::kServerEcdsa384); |
| 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); |
| } |
| |
| // Here the client picks a single option, which should work in all versions. |
| // Defaults on the server include the first option. |
| TEST_P(TlsConnectGeneric, SignatureAlgorithmClientOnly) { |
| const SSLSignatureAndHashAlg clientAlgorithms[] = { |
| {ssl_hash_sha384, ssl_sign_ecdsa}, |
| {ssl_hash_sha384, ssl_sign_rsa}, // supported but unusable |
| {ssl_hash_md5, ssl_sign_ecdsa} // unsupported and ignored |
| }; |
| Reset(TlsAgent::kServerEcdsa384); |
| EnsureTlsSetup(); |
| // Use the old API for this function. |
| EXPECT_EQ(SECSuccess, |
| SSL_SignaturePrefSet(client_->ssl_fd(), clientAlgorithms, |
| PR_ARRAY_SIZE(clientAlgorithms))); |
| Connect(); |
| CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa, |
| ssl_sig_ecdsa_secp384r1_sha384); |
| } |
| |
| // Here the server picks a single option, which should work in all versions. |
| // Defaults on the client include the provided option. |
| TEST_P(TlsConnectGeneric, SignatureAlgorithmServerOnly) { |
| Reset(TlsAgent::kServerEcdsa384); |
| server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, |
| PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); |
| Connect(); |
| CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa, |
| ssl_sig_ecdsa_secp384r1_sha384); |
| } |
| |
| // In TLS 1.2, curve and hash aren't bound together. |
| TEST_P(TlsConnectTls12, SignatureSchemeCurveMismatch) { |
| Reset(TlsAgent::kServerEcdsa256); |
| 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(kSignatureSchemeEcdsaSha384, |
| PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); |
| ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); |
| server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); |
| client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| } |
| |
| // 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(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(kSignatureSchemeEcdsaSha384, |
| PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); |
| ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); |
| server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); |
| client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| } |
| |
| // 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(kSignatureSchemeRsaSha384, |
| PR_ARRAY_SIZE(kSignatureSchemeRsaSha384)); |
| server_->SetSignatureSchemes(kSignatureSchemeRsaSha256, |
| PR_ARRAY_SIZE(kSignatureSchemeRsaSha256)); |
| EnableOnlyStaticRsaCiphers(); |
| Connect(); |
| CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt); |
| } |
| |
| TEST_P(TlsConnectTls12Plus, SignatureAlgorithmNoOverlapEcdsa) { |
| Reset(TlsAgent::kServerEcdsa256); |
| 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); |
| } |
| |
| // Pre 1.2, a mismatch on signature algorithms shouldn't affect anything. |
| TEST_P(TlsConnectPre12, SignatureAlgorithmNoOverlapEcdsa) { |
| Reset(TlsAgent::kServerEcdsa256); |
| client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384, |
| PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384)); |
| server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha256, |
| PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha256)); |
| Connect(); |
| } |
| |
| // The signature_algorithms extension is mandatory in TLS 1.3. |
| TEST_P(TlsConnectTls13, SignatureAlgorithmDrop) { |
| MakeTlsFilter<TlsExtensionDropper>(client_, ssl_signature_algorithms_xtn); |
| ConnectExpectAlert(server_, kTlsAlertMissingExtension); |
| client_->CheckErrorCode(SSL_ERROR_MISSING_EXTENSION_ALERT); |
| server_->CheckErrorCode(SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION); |
| } |
| |
| // TLS 1.2 has trouble detecting this sort of modification: it uses SHA1 and |
| // only fails when the Finished is checked. |
| TEST_P(TlsConnectTls12, SignatureAlgorithmDrop) { |
| MakeTlsFilter<TlsExtensionDropper>(client_, ssl_signature_algorithms_xtn); |
| ConnectExpectAlert(server_, kTlsAlertDecryptError); |
| client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); |
| server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); |
| } |
| |
| TEST_P(TlsConnectTls13, UnsupportedSignatureSchemeAlert) { |
| EnsureTlsSetup(); |
| auto filter = |
| MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(server_, ssl_sig_none); |
| filter->EnableDecryption(); |
| |
| ConnectExpectAlert(client_, kTlsAlertIllegalParameter); |
| server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); |
| client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CERT_VERIFY); |
| } |
| |
| TEST_P(TlsConnectTls13, InconsistentSignatureSchemeAlert) { |
| EnsureTlsSetup(); |
| |
| // This won't work because we use an RSA cert by default. |
| auto filter = MakeTlsFilter<TlsReplaceSignatureSchemeFilter>( |
| server_, ssl_sig_ecdsa_secp256r1_sha256); |
| filter->EnableDecryption(); |
| |
| ConnectExpectAlert(client_, kTlsAlertIllegalParameter); |
| server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); |
| client_->CheckErrorCode(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM); |
| } |
| |
| TEST_P(TlsConnectTls12, RequestClientAuthWithSha384) { |
| server_->SetSignatureSchemes(kSignatureSchemeRsaSha384, |
| PR_ARRAY_SIZE(kSignatureSchemeRsaSha384)); |
| server_->RequestClientAuth(false); |
| Connect(); |
| } |
| |
| class BeforeFinished : public TlsRecordFilter { |
| private: |
| enum HandshakeState { BEFORE_CCS, AFTER_CCS, DONE }; |
| |
| public: |
| BeforeFinished(const std::shared_ptr<TlsAgent>& server, |
| const std::shared_ptr<TlsAgent>& client, |
| VoidFunction before_ccs, VoidFunction before_finished) |
| : TlsRecordFilter(server), |
| client_(client), |
| before_ccs_(before_ccs), |
| before_finished_(before_finished), |
| state_(BEFORE_CCS) {} |
| |
| protected: |
| virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, |
| const DataBuffer& body, |
| DataBuffer* out) { |
| switch (state_) { |
| case BEFORE_CCS: |
| // Awaken when we see the CCS. |
| if (header.content_type() == ssl_ct_change_cipher_spec) { |
| before_ccs_(); |
| |
| // Write the CCS out as a separate write, so that we can make |
| // progress. Ordinarily, libssl sends the CCS and Finished together, |
| // but that means that they both get processed together. |
| DataBuffer ccs; |
| header.Write(&ccs, 0, body); |
| agent()->SendDirect(ccs); |
| client_.lock()->Handshake(); |
| state_ = AFTER_CCS; |
| // Request that the original record be dropped by the filter. |
| return DROP; |
| } |
| break; |
| |
| case AFTER_CCS: |
| 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. |
| |
| before_finished_(); |
| state_ = DONE; |
| break; |
| |
| case DONE: |
| break; |
| } |
| return KEEP; |
| } |
| |
| private: |
| std::weak_ptr<TlsAgent> client_; |
| VoidFunction before_ccs_; |
| VoidFunction before_finished_; |
| HandshakeState state_; |
| }; |
| |
| // Running code after the client has started processing the encrypted part of |
| // the server's first flight, but before the Finished is processed is very hard |
| // in TLS 1.3. These encrypted messages are sent in a single encrypted blob. |
| // The following test uses DTLS to make it possible to force the client to |
| // process the handshake in pieces. |
| // |
| // The first encrypted message from the server is dropped, and the MTU is |
| // reduced to just below the original message size so that the server sends two |
| // messages. The Finished message is then processed separately. |
| class BeforeFinished13 : public PacketFilter { |
| private: |
| enum HandshakeState { |
| INIT, |
| BEFORE_FIRST_FRAGMENT, |
| BEFORE_SECOND_FRAGMENT, |
| DONE |
| }; |
| |
| public: |
| BeforeFinished13(const std::shared_ptr<TlsAgent>& server, |
| const std::shared_ptr<TlsAgent>& client, |
| VoidFunction before_finished) |
| : server_(server), |
| client_(client), |
| before_finished_(before_finished), |
| records_(0) {} |
| |
| protected: |
| virtual PacketFilter::Action Filter(const DataBuffer& input, |
| DataBuffer* output) { |
| switch (++records_) { |
| case 1: |
| // Packet 1 is the server's entire first flight. Drop it. |
| EXPECT_EQ(SECSuccess, |
| SSLInt_SetMTU(server_.lock()->ssl_fd(), input.len() - 1)); |
| return DROP; |
| |
| // Packet 2 is the first part of the server's retransmitted first |
| // flight. Keep that. |
| |
| case 3: |
| // Packet 3 is the second part of the server's retransmitted first |
| // flight. Before passing that on, make sure that the client processes |
| // packet 2, then call the before_finished_() callback. |
| client_.lock()->Handshake(); |
| before_finished_(); |
| break; |
| |
| default: |
| break; |
| } |
| return KEEP; |
| } |
| |
| private: |
| std::weak_ptr<TlsAgent> server_; |
| std::weak_ptr<TlsAgent> client_; |
| VoidFunction before_finished_; |
| size_t records_; |
| }; |
| |
| static SECStatus AuthCompleteBlock(TlsAgent*, PRBool, PRBool) { |
| return SECWouldBlock; |
| } |
| |
| // This test uses an AuthCertificateCallback that blocks. A filter is used to |
| // split the server's first flight into two pieces. Before the second piece is |
| // processed by the client, SSL_AuthCertificateComplete() is called. |
| TEST_F(TlsConnectDatagram13, AuthCompleteBeforeFinished) { |
| client_->SetAuthCertificateCallback(AuthCompleteBlock); |
| MakeTlsFilter<BeforeFinished13>(server_, client_, [this]() { |
| EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); |
| }); |
| Connect(); |
| } |
| |
| // 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_P(TlsConnectTls13, AuthCompleteAfterFinished) { |
| SetDeferredAuthCertificateCallback(client_, 0); // 0 = success. |
| Connect(); |
| } |
| |
| TEST_P(TlsConnectGenericPre13, ClientWriteBetweenCCSAndFinishedWithFalseStart) { |
| client_->EnableFalseStart(); |
| MakeTlsFilter<BeforeFinished>( |
| server_, client_, |
| [this]() { EXPECT_TRUE(client_->can_falsestart_hook_called()); }, |
| [this]() { |
| // Write something, which used to fail: bug 1235366. |
| client_->SendData(10); |
| }); |
| |
| Connect(); |
| server_->SendData(10); |
| Receive(10); |
| } |
| |
| TEST_P(TlsConnectGenericPre13, AuthCompleteBeforeFinishedWithFalseStart) { |
| client_->EnableFalseStart(); |
| client_->SetAuthCertificateCallback(AuthCompleteBlock); |
| MakeTlsFilter<BeforeFinished>( |
| server_, client_, |
| []() { |
| // Do nothing before CCS |
| }, |
| [this]() { |
| EXPECT_FALSE(client_->can_falsestart_hook_called()); |
| // AuthComplete before Finished still enables false start. |
| EXPECT_EQ(SECSuccess, |
| SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); |
| EXPECT_TRUE(client_->can_falsestart_hook_called()); |
| client_->SendData(10); |
| }); |
| |
| Connect(); |
| server_->SendData(10); |
| Receive(10); |
| } |
| |
| class EnforceNoActivity : public PacketFilter { |
| protected: |
| PacketFilter::Action Filter(const DataBuffer& input, |
| DataBuffer* output) override { |
| std::cerr << "Unexpected packet: " << input << std::endl; |
| EXPECT_TRUE(false) << "should not send anything"; |
| return KEEP; |
| } |
| }; |
| |
| // In this test, we want to make sure that the server completes its handshake, |
| // but the client does not. Because the AuthCertificate callback blocks and we |
| // never call SSL_AuthCertificateComplete(), the client should never report that |
| // it has completed the handshake. Manually call Handshake(), alternating sides |
| // between client and server, until the desired state is reached. |
| TEST_P(TlsConnectGenericPre13, AuthCompleteDelayed) { |
| client_->SetAuthCertificateCallback(AuthCompleteBlock); |
| |
| StartConnect(); |
| client_->Handshake(); // Send ClientHello |
| server_->Handshake(); // Send ServerHello |
| client_->Handshake(); // Send ClientKeyExchange and Finished |
| server_->Handshake(); // Send Finished |
| // The server should now report that it is connected |
| EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state()); |
| |
| // The client should send nothing from here on. |
| client_->SetFilter(std::make_shared<EnforceNoActivity>()); |
| client_->Handshake(); |
| EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); |
| |
| // This should allow the handshake to complete now. |
| EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); |
| client_->Handshake(); // Transition to connected |
| EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state()); |
| EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state()); |
| |
| // Remove filter before closing or the close_notify alert will trigger it. |
| client_->ClearFilter(); |
| } |
| |
| TEST_P(TlsConnectGenericPre13, AuthCompleteFailDelayed) { |
| client_->SetAuthCertificateCallback(AuthCompleteBlock); |
| |
| StartConnect(); |
| client_->Handshake(); // Send ClientHello |
| server_->Handshake(); // Send ServerHello |
| client_->Handshake(); // Send ClientKeyExchange and Finished |
| server_->Handshake(); // Send Finished |
| // The server should now report that it is connected |
| EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state()); |
| |
| // The client should send nothing from here on. |
| client_->SetFilter(std::make_shared<EnforceNoActivity>()); |
| client_->Handshake(); |
| EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); |
| |
| // Report failure. |
| client_->ClearFilter(); |
| client_->ExpectSendAlert(kTlsAlertBadCertificate); |
| EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), |
| SSL_ERROR_BAD_CERTIFICATE)); |
| client_->Handshake(); // Fail |
| EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state()); |
| } |
| |
| // TLS 1.3 handles a delayed AuthComplete callback differently since the |
| // shape of the handshake is different. |
| TEST_P(TlsConnectTls13, AuthCompleteDelayed) { |
| client_->SetAuthCertificateCallback(AuthCompleteBlock); |
| |
| StartConnect(); |
| client_->Handshake(); // Send ClientHello |
| server_->Handshake(); // Send ServerHello |
| EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); |
| EXPECT_EQ(TlsAgent::STATE_CONNECTING, server_->state()); |
| |
| // The client will send nothing until AuthCertificateComplete is called. |
| client_->SetFilter(std::make_shared<EnforceNoActivity>()); |
| client_->Handshake(); |
| EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); |
| |
| // This should allow the handshake to complete now. |
| client_->ClearFilter(); |
| EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); |
| client_->Handshake(); // Send Finished |
| server_->Handshake(); // Transition to connected and send NewSessionTicket |
| EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state()); |
| EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state()); |
| } |
| |
| TEST_P(TlsConnectTls13, AuthCompleteFailDelayed) { |
| client_->SetAuthCertificateCallback(AuthCompleteBlock); |
| |
| StartConnect(); |
| client_->Handshake(); // Send ClientHello |
| server_->Handshake(); // Send ServerHello |
| EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); |
| EXPECT_EQ(TlsAgent::STATE_CONNECTING, server_->state()); |
| |
| // The client will send nothing until AuthCertificateComplete is called. |
| client_->SetFilter(std::make_shared<EnforceNoActivity>()); |
| client_->Handshake(); |
| EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); |
| |
| // Report failure. |
| client_->ClearFilter(); |
| ExpectAlert(client_, kTlsAlertBadCertificate); |
| EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), |
| SSL_ERROR_BAD_CERTIFICATE)); |
| client_->Handshake(); // This should now fail. |
| server_->Handshake(); // Get the error. |
| EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state()); |
| EXPECT_EQ(TlsAgent::STATE_ERROR, server_->state()); |
| } |
| |
| static SECStatus AuthCompleteFail(TlsAgent*, PRBool, PRBool) { |
| PORT_SetError(SSL_ERROR_BAD_CERTIFICATE); |
| return SECFailure; |
| } |
| |
| TEST_P(TlsConnectGeneric, AuthFailImmediate) { |
| client_->SetAuthCertificateCallback(AuthCompleteFail); |
| |
| StartConnect(); |
| ConnectExpectAlert(client_, kTlsAlertBadCertificate); |
| client_->CheckErrorCode(SSL_ERROR_BAD_CERTIFICATE); |
| } |
| |
| static const SSLExtraServerCertData ServerCertDataRsaPkcs1Decrypt = { |
| ssl_auth_rsa_decrypt, nullptr, nullptr, nullptr, nullptr, nullptr}; |
| static const SSLExtraServerCertData ServerCertDataRsaPkcs1Sign = { |
| ssl_auth_rsa_sign, nullptr, nullptr, nullptr, nullptr, nullptr}; |
| static const SSLExtraServerCertData ServerCertDataRsaPss = { |
| ssl_auth_rsa_pss, nullptr, nullptr, nullptr, nullptr, nullptr}; |
| |
| // Test RSA cert with usage=[signature, encipherment]. |
| TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPkcs1SignAndKEX) { |
| Reset(TlsAgent::kServerRsa); |
| |
| 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_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss)); |
| |
| // 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_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false, |
| &ServerCertDataRsaPss)); |
| } |
| |
| // Test RSA cert with usage=[signature]. |
| TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPkcs1Sign) { |
| Reset(TlsAgent::kServerRsaSign); |
| |
| 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_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 should work. |
| EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false, |
| &ServerCertDataRsaPkcs1Sign)); |
| EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false, |
| &ServerCertDataRsaPss)); |
| } |
| |
| // Test RSA cert with usage=[encipherment]. |
| TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPkcs1KEX) { |
| Reset(TlsAgent::kServerRsaDecrypt); |
| |
| PRFileDesc* ssl_fd = agent_->ssl_fd(); |
| EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_decrypt)); |
| EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_sign)); |
| EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss)); |
| |
| // Configuring for only rsa_sign or rsa_pss should fail. |
| EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaDecrypt, false, |
| &ServerCertDataRsaPkcs1Sign)); |
| EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaDecrypt, false, |
| &ServerCertDataRsaPss)); |
| |
| // Configuring for only rsa_decrypt should work. |
| EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsaDecrypt, false, |
| &ServerCertDataRsaPkcs1Decrypt)); |
| } |
| |
| // Test configuring an RSA-PSS cert. |
| TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPss) { |
| Reset(TlsAgent::kServerRsaPss); |
| |
| PRFileDesc* ssl_fd = agent_->ssl_fd(); |
| EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_decrypt)); |
| EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_sign)); |
| EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss)); |
| |
| // Configuring for only rsa_sign or rsa_decrypt should fail. |
| EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaPss, false, |
| &ServerCertDataRsaPkcs1Sign)); |
| EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaPss, false, |
| &ServerCertDataRsaPkcs1Decrypt)); |
| |
| // Configuring for only rsa_pss should work. |
| EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsaPss, false, |
| &ServerCertDataRsaPss)); |
| } |
| |
| // A server should refuse to even start a handshake with |
| // misconfigured certificate and signature scheme. |
| TEST_P(TlsConnectTls12Plus, MisconfiguredCertScheme) { |
| Reset(TlsAgent::kServerDsa); |
| static const SSLSignatureScheme kScheme[] = {ssl_sig_ecdsa_secp256r1_sha256}; |
| server_->SetSignatureSchemes(kScheme, PR_ARRAY_SIZE(kScheme)); |
| ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); |
| if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) { |
| // TLS 1.2 disables cipher suites, which leads to a different error. |
| server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| } else { |
| server_->CheckErrorCode(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM); |
| } |
| client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| } |
| |
| // In TLS 1.2, disabling an EC group causes ECDSA to be invalid. |
| TEST_P(TlsConnectTls12, Tls12CertDisabledGroup) { |
| Reset(TlsAgent::kServerEcdsa256); |
| static const std::vector<SSLNamedGroup> k25519 = {ssl_grp_ec_curve25519}; |
| server_->ConfigNamedGroups(k25519); |
| ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); |
| server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| } |
| |
| // In TLS 1.3, ECDSA configuration only depends on the signature scheme. |
| TEST_P(TlsConnectTls13, Tls13CertDisabledGroup) { |
| Reset(TlsAgent::kServerEcdsa256); |
| static const std::vector<SSLNamedGroup> k25519 = {ssl_grp_ec_curve25519}; |
| server_->ConfigNamedGroups(k25519); |
| Connect(); |
| } |
| |
| // A client should refuse to even start a handshake with only DSA. |
| TEST_P(TlsConnectTls13, Tls13DsaOnlyClient) { |
| static const SSLSignatureScheme kDsa[] = {ssl_sig_dsa_sha256}; |
| client_->SetSignatureSchemes(kDsa, PR_ARRAY_SIZE(kDsa)); |
| client_->StartConnect(); |
| client_->Handshake(); |
| EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state()); |
| client_->CheckErrorCode(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM); |
| } |
| |
| TEST_P(TlsConnectTls13, Tls13DsaOnlyServer) { |
| Reset(TlsAgent::kServerDsa); |
| static const SSLSignatureScheme kDsa[] = {ssl_sig_dsa_sha256}; |
| server_->SetSignatureSchemes(kDsa, PR_ARRAY_SIZE(kDsa)); |
| ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); |
| server_->CheckErrorCode(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM); |
| client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| } |
| |
| TEST_P(TlsConnectTls13, Tls13Pkcs1OnlyClient) { |
| static const SSLSignatureScheme kPkcs1[] = {ssl_sig_rsa_pkcs1_sha256}; |
| client_->SetSignatureSchemes(kPkcs1, PR_ARRAY_SIZE(kPkcs1)); |
| client_->StartConnect(); |
| client_->Handshake(); |
| EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state()); |
| client_->CheckErrorCode(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM); |
| } |
| |
| TEST_P(TlsConnectTls13, Tls13Pkcs1OnlyServer) { |
| static const SSLSignatureScheme kPkcs1[] = {ssl_sig_rsa_pkcs1_sha256}; |
| server_->SetSignatureSchemes(kPkcs1, PR_ARRAY_SIZE(kPkcs1)); |
| ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); |
| server_->CheckErrorCode(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM); |
| client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| } |
| |
| TEST_P(TlsConnectTls13, Tls13DsaIsNotAdvertisedClient) { |
| EnsureTlsSetup(); |
| static const SSLSignatureScheme kSchemes[] = {ssl_sig_dsa_sha256, |
| ssl_sig_rsa_pss_rsae_sha256}; |
| client_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes)); |
| auto capture = |
| MakeTlsFilter<TlsExtensionCapture>(client_, ssl_signature_algorithms_xtn); |
| Connect(); |
| // We should only have the one signature algorithm advertised. |
| static const uint8_t kExpectedExt[] = {0, 2, ssl_sig_rsa_pss_rsae_sha256 >> 8, |
| ssl_sig_rsa_pss_rsae_sha256 & 0xff}; |
| ASSERT_EQ(DataBuffer(kExpectedExt, sizeof(kExpectedExt)), |
| capture->extension()); |
| } |
| |
| TEST_P(TlsConnectTls13, Tls13DsaIsNotAdvertisedServer) { |
| EnsureTlsSetup(); |
| static const SSLSignatureScheme kSchemes[] = {ssl_sig_dsa_sha256, |
| ssl_sig_rsa_pss_rsae_sha256}; |
| server_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes)); |
| auto capture = MakeTlsFilter<TlsExtensionCapture>( |
| server_, ssl_signature_algorithms_xtn, true); |
| capture->SetHandshakeTypes({kTlsHandshakeCertificateRequest}); |
| capture->EnableDecryption(); |
| server_->RequestClientAuth(false); // So we get a CertificateRequest. |
| Connect(); |
| // We should only have the one signature algorithm advertised. |
| static const uint8_t kExpectedExt[] = {0, 2, ssl_sig_rsa_pss_rsae_sha256 >> 8, |
| ssl_sig_rsa_pss_rsae_sha256 & 0xff}; |
| ASSERT_EQ(DataBuffer(kExpectedExt, sizeof(kExpectedExt)), |
| capture->extension()); |
| } |
| |
| TEST_P(TlsConnectTls13, Tls13RsaPkcs1IsAdvertisedClient) { |
| EnsureTlsSetup(); |
| static const SSLSignatureScheme kSchemes[] = {ssl_sig_rsa_pkcs1_sha256, |
| ssl_sig_rsa_pss_rsae_sha256}; |
| client_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes)); |
| auto capture = |
| MakeTlsFilter<TlsExtensionCapture>(client_, ssl_signature_algorithms_xtn); |
| Connect(); |
| // We should only have the one signature algorithm advertised. |
| static const uint8_t kExpectedExt[] = {0, |
| 4, |
| ssl_sig_rsa_pss_rsae_sha256 >> 8, |
| ssl_sig_rsa_pss_rsae_sha256 & 0xff, |
| ssl_sig_rsa_pkcs1_sha256 >> 8, |
| ssl_sig_rsa_pkcs1_sha256 & 0xff}; |
| ASSERT_EQ(DataBuffer(kExpectedExt, sizeof(kExpectedExt)), |
| capture->extension()); |
| } |
| |
| TEST_P(TlsConnectTls13, Tls13RsaPkcs1IsAdvertisedServer) { |
| EnsureTlsSetup(); |
| static const SSLSignatureScheme kSchemes[] = {ssl_sig_rsa_pkcs1_sha256, |
| ssl_sig_rsa_pss_rsae_sha256}; |
| server_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes)); |
| auto capture = MakeTlsFilter<TlsExtensionCapture>( |
| server_, ssl_signature_algorithms_xtn, true); |
| capture->SetHandshakeTypes({kTlsHandshakeCertificateRequest}); |
| capture->EnableDecryption(); |
| server_->RequestClientAuth(false); // So we get a CertificateRequest. |
| Connect(); |
| // We should only have the one signature algorithm advertised. |
| static const uint8_t kExpectedExt[] = {0, |
| 4, |
| ssl_sig_rsa_pss_rsae_sha256 >> 8, |
| ssl_sig_rsa_pss_rsae_sha256 & 0xff, |
| ssl_sig_rsa_pkcs1_sha256 >> 8, |
| ssl_sig_rsa_pkcs1_sha256 & 0xff}; |
| ASSERT_EQ(DataBuffer(kExpectedExt, sizeof(kExpectedExt)), |
| capture->extension()); |
| } |
| |
| // variant, version, certificate, auth type, signature scheme |
| typedef std::tuple<SSLProtocolVariant, uint16_t, std::string, SSLAuthType, |
| SSLSignatureScheme> |
| SignatureSchemeProfile; |
| |
| class TlsSignatureSchemeConfiguration |
| : public TlsConnectTestBase, |
| public ::testing::WithParamInterface<SignatureSchemeProfile> { |
| public: |
| TlsSignatureSchemeConfiguration() |
| : TlsConnectTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())), |
| certificate_(std::get<2>(GetParam())), |
| auth_type_(std::get<3>(GetParam())), |
| signature_scheme_(std::get<4>(GetParam())) {} |
| |
| protected: |
| void TestSignatureSchemeConfig(std::shared_ptr<TlsAgent>& configPeer) { |
| EnsureTlsSetup(); |
| configPeer->SetSignatureSchemes(&signature_scheme_, 1); |
| Connect(); |
| CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, auth_type_, |
| signature_scheme_); |
| } |
| |
| std::string certificate_; |
| SSLAuthType auth_type_; |
| SSLSignatureScheme signature_scheme_; |
| }; |
| |
| TEST_P(TlsSignatureSchemeConfiguration, SignatureSchemeConfigServer) { |
| Reset(certificate_); |
| TestSignatureSchemeConfig(server_); |
| } |
| |
| TEST_P(TlsSignatureSchemeConfiguration, SignatureSchemeConfigClient) { |
| Reset(certificate_); |
| auto capture = |
| MakeTlsFilter<TlsExtensionCapture>(client_, ssl_signature_algorithms_xtn); |
| TestSignatureSchemeConfig(client_); |
| |
| const DataBuffer& ext = capture->extension(); |
| ASSERT_EQ(2U + 2U, ext.len()); |
| uint32_t v = 0; |
| ASSERT_TRUE(ext.Read(0, 2, &v)); |
| EXPECT_EQ(2U, v); |
| ASSERT_TRUE(ext.Read(2, 2, &v)); |
| EXPECT_EQ(signature_scheme_, static_cast<SSLSignatureScheme>(v)); |
| } |
| |
| TEST_P(TlsSignatureSchemeConfiguration, SignatureSchemeConfigBoth) { |
| Reset(certificate_); |
| EnsureTlsSetup(); |
| client_->SetSignatureSchemes(&signature_scheme_, 1); |
| server_->SetSignatureSchemes(&signature_scheme_, 1); |
| Connect(); |
| CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, auth_type_, signature_scheme_); |
| } |
| |
| class Tls12CertificateRequestReplacer : public TlsHandshakeFilter { |
| public: |
| Tls12CertificateRequestReplacer(const std::shared_ptr<TlsAgent>& a, |
| SSLSignatureScheme scheme) |
| : TlsHandshakeFilter(a, {kTlsHandshakeCertificateRequest}), |
| scheme_(scheme) {} |
| |
| virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, |
| const DataBuffer& input, |
| DataBuffer* output) { |
| uint32_t offset = 0; |
| |
| if (header.handshake_type() != ssl_hs_certificate_request) { |
| return KEEP; |
| } |
| |
| *output = input; |
| |
| uint32_t types_len = 0; |
| if (!output->Read(offset, 1, &types_len)) { |
| ADD_FAILURE(); |
| return KEEP; |
| } |
| offset += 1 + types_len; |
| uint32_t scheme_len = 0; |
| if (!output->Read(offset, 2, &scheme_len)) { |
| ADD_FAILURE(); |
| return KEEP; |
| } |
| DataBuffer schemes; |
| schemes.Write(0, 2, 2); |
| schemes.Write(2, scheme_, 2); |
| output->Write(offset, 2, schemes.len()); |
| output->Splice(schemes, offset + 2, scheme_len); |
| |
| return CHANGE; |
| } |
| |
| private: |
| SSLSignatureScheme scheme_; |
| }; |
| |
| // |
| // Test how policy interacts with client auth connections |
| // |
| |
| // TLS/DTLS version algorithm policy |
| typedef std::tuple<SSLProtocolVariant, uint16_t, SECOidTag, PRUint32> |
| PolicySignatureSchemeProfile; |
| |
| // Only TLS 1.2 handles client auth schemes inside |
| // the certificate request packet, so our failure tests for |
| // those kinds of connections only occur here. |
| class TlsConnectAuthWithPolicyTls12 |
| : public TlsConnectTestBase, |
| public ::testing::WithParamInterface<PolicySignatureSchemeProfile> { |
| public: |
| TlsConnectAuthWithPolicyTls12() |
| : TlsConnectTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) { |
| alg_ = std::get<2>(GetParam()); |
| policy_ = std::get<3>(GetParam()); |
| // use the algorithm to select which single scheme to deploy |
| // We use these schemes to force servers sending schemes the client |
| // didn't advertise to make sure the client will still filter these |
| // by policy and detect that no valid schemes were presented, rather |
| // than sending an empty client auth message. |
| switch (alg_) { |
| case SEC_OID_SHA256: |
| case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: |
| scheme_ = ssl_sig_rsa_pss_pss_sha256; |
| break; |
| case SEC_OID_PKCS1_RSA_ENCRYPTION: |
| scheme_ = ssl_sig_rsa_pkcs1_sha256; |
| break; |
| case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
| scheme_ = ssl_sig_ecdsa_secp256r1_sha256; |
| break; |
| default: |
| ADD_FAILURE() << "need to update algorithm table in " |
| "TlsConnectAuthWithPolicyTls12"; |
| scheme_ = ssl_sig_none; |
| break; |
| } |
| } |
| |
| protected: |
| SECOidTag alg_; |
| PRUint32 policy_; |
| SSLSignatureScheme scheme_; |
| }; |
| |
| // Only TLS 1.2 and greater looks at schemes extensions on client auth |
| class TlsConnectAuthWithPolicyTls12Plus |
| : public TlsConnectTestBase, |
| public ::testing::WithParamInterface<PolicySignatureSchemeProfile> { |
| public: |
| TlsConnectAuthWithPolicyTls12Plus() |
| : TlsConnectTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) { |
| alg_ = std::get<2>(GetParam()); |
| policy_ = std::get<3>(GetParam()); |
| } |
| |
| protected: |
| SECOidTag alg_; |
| PRUint32 policy_; |
| }; |
| |
| // make sure we can turn single algorithms off by policy an still connect |
| // this is basically testing that we are properly filtering our schemes |
| // by policy before communicating them to the server, and that the |
| // server is respecting our choices |
| TEST_P(TlsConnectAuthWithPolicyTls12Plus, PolicySuccessTest) { |
| // in TLS 1.3, RSA PKCS1 is restricted. If we are also |
| // restricting RSA PSS by policy, we can't use the default |
| // RSA certificate as the server cert, switch to ECDSA |
| if ((version_ >= SSL_LIBRARY_VERSION_TLS_1_3) && |
| (alg_ == SEC_OID_PKCS1_RSA_PSS_SIGNATURE)) { |
| Reset(TlsAgent::kServerEcdsa256); |
| } |
| client_->SetPolicy(alg_, 0, policy_); // Disable policy for client |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(false); |
| Connect(); |
| } |
| |
| // make sure we fail if the server ignores our policy preference and |
| // requests client auth with a scheme we don't support |
| TEST_P(TlsConnectAuthWithPolicyTls12, PolicyFailureTest) { |
| client_->SetPolicy(alg_, 0, policy_); |
| client_->SetupClientAuth(); |
| server_->RequestClientAuth(false); |
| MakeTlsFilter<Tls12CertificateRequestReplacer>(server_, scheme_); |
| ConnectExpectAlert(client_, kTlsAlertHandshakeFailure); |
| client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); |
| server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| SignaturesWithPolicyFail, TlsConnectAuthWithPolicyTls12, |
| ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, |
| TlsConnectTestBase::kTlsV12, |
| ::testing::Values(SEC_OID_SHA256, |
| SEC_OID_PKCS1_RSA_PSS_SIGNATURE, |
| SEC_OID_PKCS1_RSA_ENCRYPTION, |
| SEC_OID_ANSIX962_EC_PUBLIC_KEY), |
| ::testing::Values(NSS_USE_ALG_IN_SSL_KX, |
| NSS_USE_ALG_IN_ANY_SIGNATURE))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| SignaturesWithPolicySuccess, TlsConnectAuthWithPolicyTls12Plus, |
| ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, |
| TlsConnectTestBase::kTlsV12Plus, |
| ::testing::Values(SEC_OID_SHA256, |
| SEC_OID_PKCS1_RSA_PSS_SIGNATURE, |
| SEC_OID_PKCS1_RSA_ENCRYPTION, |
| SEC_OID_ANSIX962_EC_PUBLIC_KEY), |
| ::testing::Values(NSS_USE_ALG_IN_SSL_KX, |
| NSS_USE_ALG_IN_ANY_SIGNATURE))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| SignatureSchemeRsa, TlsSignatureSchemeConfiguration, |
| ::testing::Combine( |
| TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV12, |
| ::testing::Values(TlsAgent::kServerRsaSign), |
| ::testing::Values(ssl_auth_rsa_sign), |
| ::testing::Values(ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pkcs1_sha384, |
| ssl_sig_rsa_pkcs1_sha512, ssl_sig_rsa_pss_rsae_sha256, |
| ssl_sig_rsa_pss_rsae_sha384))); |
| // RSASSA-PKCS1-v1_5 is not allowed to be used in TLS 1.3 |
| INSTANTIATE_TEST_SUITE_P( |
| SignatureSchemeRsaTls13, TlsSignatureSchemeConfiguration, |
| ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, |
| TlsConnectTestBase::kTlsV13, |
| ::testing::Values(TlsAgent::kServerRsaSign), |
| ::testing::Values(ssl_auth_rsa_sign), |
| ::testing::Values(ssl_sig_rsa_pss_rsae_sha256, |
| ssl_sig_rsa_pss_rsae_sha384))); |
| // PSS with SHA-512 needs a bigger key to work. |
| INSTANTIATE_TEST_SUITE_P( |
| SignatureSchemeBigRsa, TlsSignatureSchemeConfiguration, |
| ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, |
| TlsConnectTestBase::kTlsV12Plus, |
| ::testing::Values(TlsAgent::kRsa2048), |
| ::testing::Values(ssl_auth_rsa_sign), |
| ::testing::Values(ssl_sig_rsa_pss_rsae_sha512))); |
| INSTANTIATE_TEST_SUITE_P( |
| SignatureSchemeRsaSha1, TlsSignatureSchemeConfiguration, |
| ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, |
| TlsConnectTestBase::kTlsV12, |
| ::testing::Values(TlsAgent::kServerRsa), |
| ::testing::Values(ssl_auth_rsa_sign), |
| ::testing::Values(ssl_sig_rsa_pkcs1_sha1))); |
| INSTANTIATE_TEST_SUITE_P( |
| SignatureSchemeEcdsaP256, TlsSignatureSchemeConfiguration, |
| ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, |
| TlsConnectTestBase::kTlsV12Plus, |
| ::testing::Values(TlsAgent::kServerEcdsa256), |
| ::testing::Values(ssl_auth_ecdsa), |
| ::testing::Values(ssl_sig_ecdsa_secp256r1_sha256))); |
| INSTANTIATE_TEST_SUITE_P( |
| SignatureSchemeEcdsaP384, TlsSignatureSchemeConfiguration, |
| ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, |
| TlsConnectTestBase::kTlsV12Plus, |
| ::testing::Values(TlsAgent::kServerEcdsa384), |
| ::testing::Values(ssl_auth_ecdsa), |
| ::testing::Values(ssl_sig_ecdsa_secp384r1_sha384))); |
| INSTANTIATE_TEST_SUITE_P( |
| SignatureSchemeEcdsaP521, TlsSignatureSchemeConfiguration, |
| ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, |
| TlsConnectTestBase::kTlsV12Plus, |
| ::testing::Values(TlsAgent::kServerEcdsa521), |
| ::testing::Values(ssl_auth_ecdsa), |
| ::testing::Values(ssl_sig_ecdsa_secp521r1_sha512))); |
| INSTANTIATE_TEST_SUITE_P( |
| SignatureSchemeEcdsaSha1, TlsSignatureSchemeConfiguration, |
| ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, |
| TlsConnectTestBase::kTlsV12, |
| ::testing::Values(TlsAgent::kServerEcdsa256, |
| TlsAgent::kServerEcdsa384), |
| ::testing::Values(ssl_auth_ecdsa), |
| ::testing::Values(ssl_sig_ecdsa_sha1))); |
| } // namespace nss_test |