| /* -*- 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 <functional> |
| #include <memory> |
| #include "secerr.h" |
| #include "ssl.h" |
| #include "sslerr.h" |
| #include "sslproto.h" |
| |
| #include "gtest_utils.h" |
| #include "tls_connect.h" |
| |
| namespace nss_test { |
| |
| class Tls13PskTest : public TlsConnectTestBase, |
| public ::testing::WithParamInterface< |
| std::tuple<SSLProtocolVariant, uint16_t>> { |
| public: |
| Tls13PskTest() |
| : TlsConnectTestBase(std::get<0>(GetParam()), |
| SSL_LIBRARY_VERSION_TLS_1_3), |
| suite_(std::get<1>(GetParam())) {} |
| |
| void SetUp() override { |
| TlsConnectTestBase::SetUp(); |
| scoped_psk_.reset(GetPsk()); |
| ASSERT_TRUE(!!scoped_psk_); |
| } |
| |
| private: |
| PK11SymKey* GetPsk() { |
| ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); |
| if (!slot) { |
| ADD_FAILURE(); |
| return nullptr; |
| } |
| |
| SECItem psk_item; |
| psk_item.type = siBuffer; |
| psk_item.len = sizeof(kPskDummyVal_); |
| psk_item.data = const_cast<uint8_t*>(kPskDummyVal_); |
| |
| PK11SymKey* key = |
| PK11_ImportSymKey(slot.get(), CKM_HKDF_KEY_GEN, PK11_OriginUnwrap, |
| CKA_DERIVE, &psk_item, NULL); |
| if (!key) { |
| ADD_FAILURE(); |
| } |
| return key; |
| } |
| |
| protected: |
| ScopedPK11SymKey scoped_psk_; |
| const uint16_t suite_; |
| const uint8_t kPskDummyVal_[16] = {0x01, 0x02, 0x03, 0x04, 0x05, |
| 0x06, 0x07, 0x08, 0x09, 0x0a, |
| 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; |
| const std::string kPskDummyLabel_ = "NSS PSK GTEST label"; |
| const SSLHashType kPskHash_ = ssl_hash_sha384; |
| }; |
| |
| // TLS 1.3 PSK connection test. |
| TEST_P(Tls13PskTest, NormalExternal) { |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| Connect(); |
| SendReceive(); |
| CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); |
| client_->RemovePsk(kPskDummyLabel_); |
| server_->RemovePsk(kPskDummyLabel_); |
| |
| // Removing it again should fail. |
| EXPECT_EQ(SECFailure, SSL_RemoveExternalPsk(client_->ssl_fd(), |
| reinterpret_cast<const uint8_t*>( |
| kPskDummyLabel_.data()), |
| kPskDummyLabel_.length())); |
| EXPECT_EQ(SECFailure, SSL_RemoveExternalPsk(server_->ssl_fd(), |
| reinterpret_cast<const uint8_t*>( |
| kPskDummyLabel_.data()), |
| kPskDummyLabel_.length())); |
| } |
| |
| TEST_P(Tls13PskTest, KeyTooLarge) { |
| ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); |
| ASSERT_TRUE(!!slot); |
| ScopedPK11SymKey scoped_psk(PK11_KeyGen( |
| slot.get(), CKM_GENERIC_SECRET_KEY_GEN, nullptr, 128, nullptr)); |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| Connect(); |
| SendReceive(); |
| CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); |
| } |
| |
| // Attempt to use a PSK with the wrong PRF hash. |
| // "Clients MUST verify that...the server selected a cipher suite |
| // indicating a Hash associated with the PSK" |
| TEST_P(Tls13PskTest, ClientVerifyHashType) { |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| MakeTlsFilter<SelectedCipherSuiteReplacer>(server_, |
| TLS_CHACHA20_POLY1305_SHA256); |
| client_->ExpectSendAlert(kTlsAlertIllegalParameter); |
| if (variant_ == ssl_variant_stream) { |
| server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); |
| ConnectExpectFail(); |
| EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code()); |
| } else { |
| ConnectExpectFailOneSide(TlsAgent::CLIENT); |
| } |
| EXPECT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code()); |
| } |
| |
| // Different EPSKs (by label) on each endpoint. Expect cert auth. |
| TEST_P(Tls13PskTest, LabelMismatch) { |
| client_->AddPsk(scoped_psk_, std::string("foo"), kPskHash_); |
| server_->AddPsk(scoped_psk_, std::string("bar"), kPskHash_); |
| Connect(); |
| CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); |
| } |
| |
| SSLHelloRetryRequestAction RetryFirstHello( |
| PRBool firstHello, const PRUint8* clientToken, unsigned int clientTokenLen, |
| PRUint8* appToken, unsigned int* appTokenLen, unsigned int appTokenMax, |
| void* arg) { |
| auto* called = reinterpret_cast<size_t*>(arg); |
| ++*called; |
| EXPECT_EQ(0U, clientTokenLen); |
| EXPECT_EQ(*called, firstHello ? 1U : 2U); |
| return firstHello ? ssl_hello_retry_request : ssl_hello_retry_accept; |
| } |
| |
| // Test resumption PSK with HRR. |
| TEST_P(Tls13PskTest, ResPskRetryStateless) { |
| ConfigureSelfEncrypt(); |
| ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); |
| Connect(); |
| SendReceive(); // Need to read so that we absorb the session ticket. |
| CheckKeys(); |
| |
| Reset(); |
| StartConnect(); |
| size_t cb_called = 0; |
| EXPECT_EQ(SECSuccess, SSL_HelloRetryRequestCallback( |
| server_->ssl_fd(), RetryFirstHello, &cb_called)); |
| ExpectResumption(RESUME_TICKET); |
| Handshake(); |
| CheckConnected(); |
| EXPECT_EQ(2U, cb_called); |
| CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); |
| SendReceive(); |
| } |
| |
| // Test external PSK with HRR. |
| TEST_P(Tls13PskTest, ExtPskRetryStateless) { |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| size_t cb_called = 0; |
| EXPECT_EQ(SECSuccess, SSL_HelloRetryRequestCallback( |
| server_->ssl_fd(), RetryFirstHello, &cb_called)); |
| StartConnect(); |
| client_->Handshake(); |
| server_->Handshake(); |
| EXPECT_EQ(1U, cb_called); |
| auto replacement = std::make_shared<TlsAgent>( |
| server_->name(), TlsAgent::SERVER, server_->variant()); |
| server_ = replacement; |
| server_->SetVersionRange(version_, version_); |
| client_->SetPeer(server_); |
| server_->SetPeer(client_); |
| server_->AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| server_->ExpectPsk(); |
| server_->StartConnect(); |
| Handshake(); |
| CheckConnected(); |
| SendReceive(); |
| CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); |
| } |
| |
| // Server not configured with PSK and sends a certificate instead of |
| // a selected_identity. Client should attempt certificate authentication. |
| TEST_P(Tls13PskTest, ClientOnly) { |
| client_->AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| Connect(); |
| CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); |
| } |
| |
| // Set a PSK, remove psk_key_exchange_modes. |
| TEST_P(Tls13PskTest, DropKexModes) { |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| StartConnect(); |
| MakeTlsFilter<TlsExtensionDropper>(client_, |
| ssl_tls13_psk_key_exchange_modes_xtn); |
| ConnectExpectAlert(server_, kTlsAlertMissingExtension); |
| client_->CheckErrorCode(SSL_ERROR_MISSING_EXTENSION_ALERT); |
| server_->CheckErrorCode(SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES); |
| } |
| |
| // "Clients MUST verify that...a server "key_share" extension is present |
| // if required by the ClientHello "psk_key_exchange_modes" extension." |
| // As we don't support PSK without DH, it is always required. |
| TEST_P(Tls13PskTest, DropRequiredKeyShare) { |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| StartConnect(); |
| MakeTlsFilter<TlsExtensionDropper>(server_, ssl_tls13_key_share_xtn); |
| client_->ExpectSendAlert(kTlsAlertMissingExtension); |
| if (variant_ == ssl_variant_stream) { |
| server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); |
| ConnectExpectFail(); |
| } else { |
| ConnectExpectFailOneSide(TlsAgent::CLIENT); |
| } |
| client_->CheckErrorCode(SSL_ERROR_MISSING_KEY_SHARE); |
| } |
| |
| // "Clients MUST verify that...the server's selected_identity is |
| // within the range supplied by the client". We send one OfferedPsk. |
| TEST_P(Tls13PskTest, InvalidSelectedIdentity) { |
| static const uint8_t selected_identity[] = {0x00, 0x01}; |
| DataBuffer buf(selected_identity, sizeof(selected_identity)); |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| StartConnect(); |
| MakeTlsFilter<TlsExtensionReplacer>(server_, ssl_tls13_pre_shared_key_xtn, |
| buf); |
| client_->ExpectSendAlert(kTlsAlertIllegalParameter); |
| if (variant_ == ssl_variant_stream) { |
| server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); |
| ConnectExpectFail(); |
| } else { |
| ConnectExpectFailOneSide(TlsAgent::CLIENT); |
| } |
| client_->CheckErrorCode(SSL_ERROR_MALFORMED_PRE_SHARED_KEY); |
| } |
| |
| // Resume-eligible reconnect with an EPSK configured. |
| // Expect the EPSK to be used. |
| TEST_P(Tls13PskTest, PreferEpsk) { |
| ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); |
| Connect(); |
| SendReceive(); // Need to read so that we absorb the session ticket. |
| CheckKeys(); |
| |
| Reset(); |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| ExpectResumption(RESUME_NONE); |
| StartConnect(); |
| Handshake(); |
| CheckConnected(); |
| SendReceive(); |
| CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); |
| } |
| |
| // Enable resumption, but connect (initially) with an EPSK. |
| // Expect no session ticket. |
| TEST_P(Tls13PskTest, SuppressNewSessionTicket) { |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); |
| auto nst_capture = |
| MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_new_session_ticket); |
| nst_capture->EnableDecryption(); |
| Connect(); |
| SendReceive(); |
| CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); |
| EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), nullptr, 0)); |
| EXPECT_EQ(0U, nst_capture->buffer().len()); |
| if (variant_ == ssl_variant_stream) { |
| EXPECT_EQ(SSL_ERROR_FEATURE_DISABLED, PORT_GetError()); |
| } else { |
| EXPECT_EQ(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION, PORT_GetError()); |
| } |
| |
| Reset(); |
| ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| ExpectResumption(RESUME_NONE); |
| Connect(); |
| SendReceive(); |
| CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); |
| } |
| |
| TEST_P(Tls13PskTest, BadConfigValues) { |
| EXPECT_TRUE(client_->EnsureTlsSetup()); |
| std::vector<uint8_t> label{'L', 'A', 'B', 'E', 'L'}; |
| EXPECT_EQ(SECFailure, |
| SSL_AddExternalPsk(client_->ssl_fd(), nullptr, label.data(), |
| label.size(), kPskHash_)); |
| EXPECT_EQ(SECFailure, SSL_AddExternalPsk(client_->ssl_fd(), scoped_psk_.get(), |
| nullptr, label.size(), kPskHash_)); |
| |
| EXPECT_EQ(SECFailure, SSL_AddExternalPsk(client_->ssl_fd(), scoped_psk_.get(), |
| label.data(), 0, kPskHash_)); |
| EXPECT_EQ(SECSuccess, |
| SSL_AddExternalPsk(client_->ssl_fd(), scoped_psk_.get(), |
| label.data(), label.size(), ssl_hash_sha256)); |
| |
| EXPECT_EQ(SECFailure, |
| SSL_RemoveExternalPsk(client_->ssl_fd(), nullptr, label.size())); |
| |
| EXPECT_EQ(SECFailure, |
| SSL_RemoveExternalPsk(client_->ssl_fd(), label.data(), 0)); |
| |
| EXPECT_EQ(SECSuccess, SSL_RemoveExternalPsk(client_->ssl_fd(), label.data(), |
| label.size())); |
| } |
| |
| // If the server has an EPSK configured with a ciphersuite not supported |
| // by the client, it should use certificate authentication. |
| TEST_P(Tls13PskTest, FallbackUnsupportedCiphersuite) { |
| client_->AddPsk(scoped_psk_, kPskDummyLabel_, ssl_hash_sha256, |
| TLS_AES_128_GCM_SHA256); |
| server_->AddPsk(scoped_psk_, kPskDummyLabel_, ssl_hash_sha256, |
| TLS_CHACHA20_POLY1305_SHA256); |
| |
| client_->EnableSingleCipher(TLS_AES_128_GCM_SHA256); |
| Connect(); |
| SendReceive(); |
| CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); |
| } |
| |
| // That fallback should not occur if there is no cipher overlap. |
| TEST_P(Tls13PskTest, ExplicitSuiteNoOverlap) { |
| client_->AddPsk(scoped_psk_, kPskDummyLabel_, ssl_hash_sha256, |
| TLS_AES_128_GCM_SHA256); |
| server_->AddPsk(scoped_psk_, kPskDummyLabel_, ssl_hash_sha256, |
| TLS_CHACHA20_POLY1305_SHA256); |
| |
| client_->EnableSingleCipher(TLS_AES_128_GCM_SHA256); |
| server_->EnableSingleCipher(TLS_CHACHA20_POLY1305_SHA256); |
| ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); |
| server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| } |
| |
| TEST_P(Tls13PskTest, SuppressHandshakeCertReq) { |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| server_->SetOption(SSL_REQUEST_CERTIFICATE, PR_TRUE); |
| server_->SetOption(SSL_REQUIRE_CERTIFICATE, PR_TRUE); |
| const std::set<uint8_t> hs_types = {ssl_hs_certificate, |
| ssl_hs_certificate_request}; |
| auto cr_cert_capture = MakeTlsFilter<TlsHandshakeRecorder>(server_, hs_types); |
| cr_cert_capture->EnableDecryption(); |
| |
| Connect(); |
| SendReceive(); |
| CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); |
| EXPECT_EQ(0U, cr_cert_capture->buffer().len()); |
| } |
| |
| TEST_P(Tls13PskTest, DisallowClientConfigWithoutServerCert) { |
| AddPsk(scoped_psk_, kPskDummyLabel_, kPskHash_); |
| server_->SetOption(SSL_REQUEST_CERTIFICATE, PR_TRUE); |
| server_->SetOption(SSL_REQUIRE_CERTIFICATE, PR_TRUE); |
| const std::set<uint8_t> hs_types = {ssl_hs_certificate, |
| ssl_hs_certificate_request}; |
| auto cr_cert_capture = MakeTlsFilter<TlsHandshakeRecorder>(server_, hs_types); |
| cr_cert_capture->EnableDecryption(); |
| |
| EXPECT_EQ(SECSuccess, SSLInt_RemoveServerCertificates(server_->ssl_fd())); |
| |
| ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); |
| server_->CheckErrorCode(SSL_ERROR_NO_CERTIFICATE); |
| client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); |
| EXPECT_EQ(0U, cr_cert_capture->buffer().len()); |
| } |
| |
| TEST_F(TlsConnectStreamTls13, ClientRejectHandshakeCertReq) { |
| // Stream only, as the filter doesn't support DTLS 1.3 yet. |
| ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); |
| ASSERT_TRUE(!!slot); |
| ScopedPK11SymKey scoped_psk(PK11_KeyGen( |
| slot.get(), CKM_GENERIC_SECRET_KEY_GEN, nullptr, 32, nullptr)); |
| AddPsk(scoped_psk, std::string("foo"), ssl_hash_sha256); |
| // Inject a CR after EE. This would be legal if not for ssl_auth_psk. |
| auto filter = MakeTlsFilter<TlsEncryptedHandshakeMessageReplacer>( |
| server_, kTlsHandshakeFinished, kTlsHandshakeCertificateRequest); |
| filter->EnableDecryption(); |
| |
| ExpectAlert(client_, kTlsAlertUnexpectedMessage); |
| ConnectExpectFail(); |
| client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST); |
| server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT); |
| } |
| |
| TEST_F(TlsConnectStreamTls13, RejectPha) { |
| // Stream only, as the filter doesn't support DTLS 1.3 yet. |
| ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); |
| ASSERT_TRUE(!!slot); |
| ScopedPK11SymKey scoped_psk(PK11_KeyGen( |
| slot.get(), CKM_GENERIC_SECRET_KEY_GEN, nullptr, 32, nullptr)); |
| AddPsk(scoped_psk, std::string("foo"), ssl_hash_sha256); |
| server_->SetOption(SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE); |
| auto kuToCr = MakeTlsFilter<TlsEncryptedHandshakeMessageReplacer>( |
| server_, kTlsHandshakeKeyUpdate, kTlsHandshakeCertificateRequest); |
| kuToCr->EnableDecryption(); |
| Connect(); |
| |
| // Make sure the direct path is blocked. |
| EXPECT_EQ(SECFailure, SSL_SendCertificateRequest(server_->ssl_fd())); |
| EXPECT_EQ(SSL_ERROR_FEATURE_DISABLED, PORT_GetError()); |
| |
| // Inject a PHA CR. Since this is not allowed, send KeyUpdate |
| // and change the message type. |
| EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE)); |
| ExpectAlert(client_, kTlsAlertUnexpectedMessage); |
| client_->Handshake(); // Eat the CR. |
| server_->Handshake(); |
| client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST); |
| server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT); |
| } |
| |
| class Tls13PskTestWithCiphers : public Tls13PskTest {}; |
| |
| TEST_P(Tls13PskTestWithCiphers, 0RttCiphers) { |
| RolloverAntiReplay(); |
| AddPsk(scoped_psk_, kPskDummyLabel_, tls13_GetHashForCipherSuite(suite_), |
| suite_); |
| StartConnect(); |
| client_->Set0RttEnabled(true); |
| server_->Set0RttEnabled(true); |
| ZeroRttSendReceive(true, true); |
| Handshake(); |
| ExpectEarlyDataAccepted(true); |
| CheckConnected(); |
| SendReceive(); |
| CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_psk, ssl_sig_none); |
| } |
| |
| TEST_P(Tls13PskTestWithCiphers, 0RttMaxEarlyData) { |
| EnsureTlsSetup(); |
| RolloverAntiReplay(); |
| const char* big_message = "0123456789abcdef"; |
| const size_t short_size = strlen(big_message) - 1; |
| const PRInt32 short_length = static_cast<PRInt32>(short_size); |
| |
| // Set up the PSK |
| EXPECT_EQ(SECSuccess, |
| SSL_AddExternalPsk0Rtt( |
| client_->ssl_fd(), scoped_psk_.get(), |
| reinterpret_cast<const uint8_t*>(kPskDummyLabel_.data()), |
| kPskDummyLabel_.length(), tls13_GetHashForCipherSuite(suite_), |
| suite_, short_length)); |
| EXPECT_EQ(SECSuccess, |
| SSL_AddExternalPsk0Rtt( |
| server_->ssl_fd(), scoped_psk_.get(), |
| reinterpret_cast<const uint8_t*>(kPskDummyLabel_.data()), |
| kPskDummyLabel_.length(), tls13_GetHashForCipherSuite(suite_), |
| suite_, short_length)); |
| client_->ExpectPsk(); |
| server_->ExpectPsk(); |
| client_->expected_cipher_suite(suite_); |
| server_->expected_cipher_suite(suite_); |
| StartConnect(); |
| client_->Set0RttEnabled(true); |
| server_->Set0RttEnabled(true); |
| client_->Handshake(); |
| CheckEarlyDataLimit(client_, short_size); |
| |
| PRInt32 sent; |
| // Writing more than the limit will succeed in TLS, but fail in DTLS. |
| if (variant_ == ssl_variant_stream) { |
| sent = PR_Write(client_->ssl_fd(), big_message, |
| static_cast<PRInt32>(strlen(big_message))); |
| } else { |
| sent = PR_Write(client_->ssl_fd(), big_message, |
| static_cast<PRInt32>(strlen(big_message))); |
| EXPECT_GE(0, sent); |
| EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); |
| |
| // Try an exact-sized write now. |
| sent = PR_Write(client_->ssl_fd(), big_message, short_length); |
| } |
| EXPECT_EQ(short_length, sent); |
| |
| // Even a single octet write should now fail. |
| sent = PR_Write(client_->ssl_fd(), big_message, 1); |
| EXPECT_GE(0, sent); |
| EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); |
| |
| // Process the ClientHello and read 0-RTT. |
| server_->Handshake(); |
| CheckEarlyDataLimit(server_, short_size); |
| |
| std::vector<uint8_t> buf(short_size + 1); |
| PRInt32 read = PR_Read(server_->ssl_fd(), buf.data(), buf.capacity()); |
| EXPECT_EQ(short_length, read); |
| EXPECT_EQ(0, memcmp(big_message, buf.data(), short_size)); |
| |
| // Second read fails. |
| read = PR_Read(server_->ssl_fd(), buf.data(), buf.capacity()); |
| EXPECT_EQ(SECFailure, read); |
| EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); |
| |
| Handshake(); |
| ExpectEarlyDataAccepted(true); |
| CheckConnected(); |
| SendReceive(); |
| } |
| |
| static const uint16_t k0RttCipherDefs[] = {TLS_CHACHA20_POLY1305_SHA256, |
| TLS_AES_128_GCM_SHA256, |
| TLS_AES_256_GCM_SHA384}; |
| |
| static const uint16_t kDefaultSuite[] = {TLS_CHACHA20_POLY1305_SHA256}; |
| |
| INSTANTIATE_TEST_SUITE_P( |
| Tls13PskTest, Tls13PskTest, |
| ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, |
| ::testing::ValuesIn(kDefaultSuite))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| Tls13PskTestWithCiphers, Tls13PskTestWithCiphers, |
| ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, |
| ::testing::ValuesIn(k0RttCipherDefs))); |
| |
| } // namespace nss_test |