author | Kevin Jacobs <kjacobs@mozilla.com> |
Mon, 10 Aug 2020 17:59:40 +0000 | |
changeset 544133 | 4462bac0fc59f25feab3764f9e2b9226dc2d22d2 |
parent 544132 | 60059f7d5c464eb10d7979cefb4d151bf50b5abf |
child 544134 | 837f7946e5fbdad679fe7dd96391bdd71da7465f |
push id | 37688 |
push user | apavel@mozilla.com |
push date | Tue, 11 Aug 2020 03:16:35 +0000 |
treeherder | mozilla-central@3bfe3b28bf50 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jcj |
bugs | 1655105, 1625791, 1651564, 1588941, 1656981, 65537, 12629, 29431, 30332, 1656429 |
milestone | 81.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1,1 +1,1 @@ -afa38fb2f0b5 \ No newline at end of file +c06f22733446 \ No newline at end of file
--- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -5,9 +5,8 @@ /* * A dummy header file that is a dependency for all the object files. * Used to force a full recompilation of NSS in Mozilla's Tinderbox * depend builds. See comments in rules.mk. */ #error "Do not include this header file." -
--- a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc @@ -206,16 +206,116 @@ TEST_P(TlsConnectTls13, ZeroRttOptionsSe server_->Set0RttEnabled(true); ExpectResumption(RESUME_TICKET); ZeroRttSendReceive(false, false); Handshake(); CheckConnected(); SendReceive(); } +// Make sure that a session ticket sent well after the original handshake +// can be used for 0-RTT. +// Stream because DTLS doesn't support SSL_SendSessionTicket. +TEST_F(TlsConnectStreamTls13, ZeroRttUsingLateTicket) { + // Use a small-ish anti-replay window. + ResetAntiReplay(100 * PR_USEC_PER_MSEC); + RolloverAntiReplay(); + + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); + server_->Set0RttEnabled(true); + Connect(); + CheckKeys(); + + // Now move time forward 30s and send a ticket. + AdvanceTime(30 * PR_USEC_PER_SEC); + EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0)); + SendReceive(); + Reset(); + StartConnect(); + + client_->Set0RttEnabled(true); + server_->Set0RttEnabled(true); + ExpectResumption(RESUME_TICKET); + ZeroRttSendReceive(true, true); + Handshake(); + ExpectEarlyDataAccepted(true); + CheckConnected(); + SendReceive(); +} + +// Check that post-handshake authentication with a long RTT doesn't +// make things worse. +TEST_F(TlsConnectStreamTls13, ZeroRttUsingLateTicketPha) { + // Use a small-ish anti-replay window. + ResetAntiReplay(100 * PR_USEC_PER_MSEC); + RolloverAntiReplay(); + + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); + server_->Set0RttEnabled(true); + client_->SetupClientAuth(); + client_->SetOption(SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE); + Connect(); + CheckKeys(); + + // Add post-handshake authentication, with some added delays. + AdvanceTime(10 * PR_USEC_PER_SEC); + EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())); + AdvanceTime(10 * PR_USEC_PER_SEC); + server_->SendData(50); + client_->ReadBytes(50); + client_->SendData(50); + server_->ReadBytes(50); + + AdvanceTime(10 * PR_USEC_PER_SEC); + EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0)); + server_->SendData(100); + client_->ReadBytes(100); + Reset(); + StartConnect(); + + client_->Set0RttEnabled(true); + server_->Set0RttEnabled(true); + ExpectResumption(RESUME_TICKET); + ZeroRttSendReceive(true, true); + Handshake(); + ExpectEarlyDataAccepted(true); + CheckConnected(); + SendReceive(); +} + +// Same, but with client authentication on the first connection. +TEST_F(TlsConnectStreamTls13, ZeroRttUsingLateTicketClientAuth) { + // Use a small-ish anti-replay window. + ResetAntiReplay(100 * PR_USEC_PER_MSEC); + RolloverAntiReplay(); + + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); + client_->SetupClientAuth(); + server_->RequestClientAuth(true); + server_->Set0RttEnabled(true); + Connect(); + CheckKeys(); + + // Now move time forward 30s and send a ticket. + AdvanceTime(30 * PR_USEC_PER_SEC); + EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0)); + SendReceive(); + Reset(); + StartConnect(); + + client_->Set0RttEnabled(true); + server_->Set0RttEnabled(true); + ExpectResumption(RESUME_TICKET); + ZeroRttSendReceive(true, true); + Handshake(); + ExpectEarlyDataAccepted(true); + CheckConnected(); + SendReceive(); +} + TEST_P(TlsConnectTls13, ZeroRttServerForgetTicket) { SetupForZeroRtt(); client_->Set0RttEnabled(true); server_->Set0RttEnabled(true); ClearServerCache(); ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); ExpectResumption(RESUME_NONE); ZeroRttSendReceive(true, false);
--- a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc @@ -910,16 +910,114 @@ TEST_P(TlsConnectTls12, ClientAuthNoSigA 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};
--- a/security/nss/gtests/ssl_gtest/tls_connect.cc +++ b/security/nss/gtests/ssl_gtest/tls_connect.cc @@ -102,17 +102,17 @@ std::string VersionString(uint16_t versi default: std::cerr << "Invalid version: " << version << std::endl; EXPECT_TRUE(false); return ""; } } // The default anti-replay window for tests. Tests that rely on a different -// value call SSL_InitAntiReplay directly. +// value call ResetAntiReplay directly. static PRTime kAntiReplayWindow = 100 * PR_USEC_PER_SEC; TlsConnectTestBase::TlsConnectTestBase(SSLProtocolVariant variant, uint16_t version) : variant_(variant), client_(new TlsAgent(TlsAgent::kClient, TlsAgent::CLIENT, variant_)), server_(new TlsAgent(TlsAgent::kServerRsa, TlsAgent::SERVER, variant_)), client_model_(nullptr),
--- a/security/nss/lib/freebl/Makefile +++ b/security/nss/lib/freebl/Makefile @@ -229,27 +229,33 @@ ifeq ($(USE_N32),1) ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3 endif DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE DEFINES += -DMP_USE_UINT_DIGIT endif endif ifeq ($(OS_TARGET),Darwin) -ifeq ($(CPU_ARCH),x86) +ifeq ($(CPU_ARCH),x86_64) + ASFILES = mpi_amd64_common.s + DEFINES += -DMPI_AMD64 -DMP_IS_LITTLE_ENDIAN + DEFINES += -DMP_ASSEMBLY_MULTIPLY -DNSS_USE_COMBA + MPI_SRCS += mpi_amd64.c mp_comba.c +else ifeq ($(CPU_ARCH),x86) ASFILES = mpi_sse2.s DEFINES += -DMP_USE_UINT_DIGIT DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE DEFINES += -DMP_ASSEMBLY_DIV_2DX1D endif endif # Darwin ifeq ($(OS_TARGET),Linux) ifeq ($(CPU_ARCH),x86_64) - ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s + # Lower case s on mpi_amd64_common due to make implicit rules. + ASFILES = arcfour-amd64-gas.s mpi_amd64_common.s ASFLAGS += -fPIC -Wa,--noexecstack DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY DEFINES += -DNSS_USE_COMBA DEFINES += -DMP_IS_LITTLE_ENDIAN # DEFINES += -DMPI_AMD64_ADD # comment the next four lines to turn off Intel HW acceleration. DEFINES += -DUSE_HW_AES -DINTEL_GCM ASFILES += intel-aes.s intel-gcm.s @@ -479,17 +485,17 @@ else ifdef NS_USE_GCC LD = gcc AS = gcc ASFLAGS = -x assembler-with-cpp endif ifeq ($(USE_64),1) # Solaris for AMD64 ifdef NS_USE_GCC - ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s + ASFILES = arcfour-amd64-gas.s mpi_amd64_common.s ASFLAGS += -march=opteron -m64 -fPIC MPI_SRCS += mp_comba.c # comment the next four lines to turn off Intel HW acceleration ASFILES += intel-gcm.s EXTRA_SRCS += intel-gcm-wrap.c INTEL_GCM = 1 DEFINES += -DINTEL_GCM else
--- a/security/nss/lib/freebl/freebl_base.gypi +++ b/security/nss/lib/freebl/freebl_base.gypi @@ -63,17 +63,17 @@ ], 'conditions': [ [ 'OS=="linux" or OS=="android"', { 'conditions': [ [ 'target_arch=="x64"', { 'sources': [ 'arcfour-amd64-gas.s', 'mpi/mpi_amd64.c', - 'mpi/mpi_amd64_gas.s', + 'mpi/mpi_amd64_common.S', 'mpi/mp_comba.c', ], 'conditions': [ [ 'cc_is_clang==1 and fuzz!=1 and coverage!=1', { 'cflags': [ '-no-integrated-as', ], 'cflags_mozilla': [ @@ -197,16 +197,28 @@ 'mpi/mpi_sse2.s', ], 'defines': [ 'MP_USE_UINT_DIGIT', 'MP_ASSEMBLY_MULTIPLY', 'MP_ASSEMBLY_SQUARE', 'MP_ASSEMBLY_DIV_2DX1D', ], + }, 'target_arch=="x64"', { + 'sources': [ + 'mpi/mpi_amd64.c', + 'mpi/mpi_amd64_common.S', + 'mpi/mp_comba.c', + ], + 'defines': [ + 'MP_IS_LITTLE_ENDIAN', + 'MPI_AMD64', + 'MP_ASSEMBLY_MULTIPLY', + 'NSS_USE_COMBA', + ], }], ], }], ], 'ldflags': [ '-Wl,-Bsymbolic' ], }
rename from security/nss/lib/freebl/mpi/mpi_amd64_gas.s rename to security/nss/lib/freebl/mpi/mpi_amd64_common.S --- a/security/nss/lib/freebl/mpi/mpi_amd64_gas.s +++ b/security/nss/lib/freebl/mpi/mpi_amd64_common.S @@ -13,17 +13,25 @@ # r = a * digit, r and a are vectors of length len # returns the carry digit # r and a are 64 bit aligned. # # uint64_t # s_mpv_mul_set_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit) # -.text; .align 16; .globl s_mpv_mul_set_vec64; .type s_mpv_mul_set_vec64, @function; s_mpv_mul_set_vec64: +.text; .align 16; .globl s_mpv_mul_set_vec64; + +#ifdef DARWIN +#define s_mpv_mul_set_vec64 _s_mpv_mul_set_vec64 +.private_extern s_mpv_mul_set_vec64 +s_mpv_mul_set_vec64: +#else +.type s_mpv_mul_set_vec64, @function; s_mpv_mul_set_vec64: +#endif xorq %rax, %rax # if (len == 0) return (0) testq %rdx, %rdx jz .L17 movq %rdx, %r8 # Use r8 for len; %rdx is used by mul xorq %r9, %r9 # cy = 0 @@ -164,34 +172,44 @@ decq %r8 jz .L17 .L17: movq %r9, %rax ret +#ifndef DARWIN .size s_mpv_mul_set_vec64, .-s_mpv_mul_set_vec64 +#endif # ------------------------------------------------------------------------ # # Implementation of s_mpv_mul_add_vec which exploits # the 64X64->128 bit unsigned multiply instruction. # # ------------------------------------------------------------------------ # r += a * digit, r and a are vectors of length len # returns the carry digit # r and a are 64 bit aligned. # # uint64_t # s_mpv_mul_add_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit) # -.text; .align 16; .globl s_mpv_mul_add_vec64; .type s_mpv_mul_add_vec64, @function; s_mpv_mul_add_vec64: +.text; .align 16; .globl s_mpv_mul_add_vec64; + +#ifdef DARWIN +#define s_mpv_mul_add_vec64 _s_mpv_mul_add_vec64 +.private_extern s_mpv_mul_add_vec64 +s_mpv_mul_add_vec64: +#else +.type s_mpv_mul_add_vec64, @function; s_mpv_mul_add_vec64: +#endif xorq %rax, %rax # if (len == 0) return (0) testq %rdx, %rdx jz .L27 movq %rdx, %r8 # Use r8 for len; %rdx is used by mul xorq %r9, %r9 # cy = 0 @@ -376,14 +394,16 @@ movq %rdx, %r9 # cy = hi(p) decq %r8 jz .L27 .L27: movq %r9, %rax ret - + +#ifndef DARWIN .size s_mpv_mul_add_vec64, .-s_mpv_mul_add_vec64 # Magic indicating no need for an executable stack .section .note.GNU-stack, "", @progbits .previous +#endif
--- a/security/nss/lib/pki/tdcache.c +++ b/security/nss/lib/pki/tdcache.c @@ -69,17 +69,17 @@ log_cert_ref(const char *msg, NSSCertifi /* XXX * Locking is not handled well at all. A single, global lock with sub-locks * in the collection types. Cleanup needed. */ /* should it live in its own arena? */ struct nssTDCertificateCacheStr { - PZLock *lock; + PZLock *lock; /* Must not be held when calling nssSlot_IsTokenPresent. See bug 1625791. */ NSSArena *arena; nssHash *issuerAndSN; nssHash *subject; nssHash *nickname; nssHash *email; }; struct cache_entry_str { @@ -708,16 +708,24 @@ add_cert_to_cache( NSSArena *arena = NULL; nssList *subjectList = NULL; PRStatus nssrv; PRUint32 added = 0; cache_entry *ce; NSSCertificate *rvCert = NULL; NSSUTF8 *certNickname = nssCertificate_GetNickname(cert, NULL); + /* Set cc->trust and cc->nssCertificate before taking td->cache->lock. + * Otherwise, the sorter in add_subject_entry may eventually call + * nssSlot_IsTokenPresent, which must not occur while the cache lock + * is held. See bugs 1625791 and 1651564 for details. */ + if (cert->type == NSSCertificateType_PKIX) { + (void)STAN_GetCERTCertificate(cert); + } + PZ_Lock(td->cache->lock); /* If it exists in the issuer/serial hash, it's already in all */ ce = (cache_entry *)nssHash_Lookup(td->cache->issuerAndSN, cert); if (ce) { ce->hits++; ce->lastHit = PR_Now(); rvCert = nssCertificate_AddRef(ce->entry.cert); #ifdef DEBUG_CACHE
--- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -7648,51 +7648,52 @@ ssl3_CompleteHandleCertificateRequest(ss case SECWouldBlock: /* getClientAuthData has put up a dialog box. */ ssl3_SetAlwaysBlock(ss); break; /* not an error */ case SECSuccess: /* check what the callback function returned */ if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) { /* we are missing either the key or cert */ - if (ss->ssl3.clientCertificate) { - /* got a cert, but no key - free it */ - CERT_DestroyCertificate(ss->ssl3.clientCertificate); - ss->ssl3.clientCertificate = NULL; - } - if (ss->ssl3.clientPrivateKey) { - /* got a key, but no cert - free it */ - SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); - ss->ssl3.clientPrivateKey = NULL; - } goto send_no_certificate; } /* Setting ssl3.clientCertChain non-NULL will cause * ssl3_HandleServerHelloDone to call SendCertificate. */ ss->ssl3.clientCertChain = CERT_CertChainFromCert( ss->ssl3.clientCertificate, certUsageSSLClient, PR_FALSE); if (ss->ssl3.clientCertChain == NULL) { - CERT_DestroyCertificate(ss->ssl3.clientCertificate); - ss->ssl3.clientCertificate = NULL; - SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); - ss->ssl3.clientPrivateKey = NULL; goto send_no_certificate; } if (ss->ssl3.hs.hashType == handshake_hash_record || ss->ssl3.hs.hashType == handshake_hash_single) { rv = ssl_PickClientSignatureScheme(ss, signatureSchemes, signatureSchemeCount); + if (rv != SECSuccess) { + /* This should only happen if our schemes changed or + * if an RSA-PSS cert was selected, but the token + * does not support PSS schemes. */ + goto send_no_certificate; + } } break; /* not an error */ case SECFailure: default: send_no_certificate: + CERT_DestroyCertificate(ss->ssl3.clientCertificate); + SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); + ss->ssl3.clientCertificate = NULL; + ss->ssl3.clientPrivateKey = NULL; + if (ss->ssl3.clientCertChain) { + CERT_DestroyCertificateList(ss->ssl3.clientCertChain); + ss->ssl3.clientCertChain = NULL; + } + if (ss->version > SSL_LIBRARY_VERSION_3_0) { ss->ssl3.sendEmptyCert = PR_TRUE; } else { (void)SSL3_SendAlert(ss, alert_warning, no_certificate); } rv = SECSuccess; break; }
--- a/security/nss/lib/ssl/ssl3exthandle.c +++ b/security/nss/lib/ssl/ssl3exthandle.c @@ -791,17 +791,17 @@ ssl3_EncodeSessionTicket(sslSocket *ss, * * We calculate the client's estimate of this as: * ticket_create + ticket_age_baseline + obfuscated_age * = ticket_create + 1rtt + ticket_age_client * * This is compared to the expected time, which should differ only as a * result of clock errors or errors in the RTT estimate. */ - ticketAgeBaseline = (ssl_Time(ss) - ss->ssl3.hs.serverHelloTime) / PR_USEC_PER_MSEC; + ticketAgeBaseline = ss->ssl3.hs.rttEstimate / PR_USEC_PER_MSEC; ticketAgeBaseline -= ticket->ticket_age_add; rv = sslBuffer_AppendNumber(&plaintext, ticketAgeBaseline, 4); if (rv != SECSuccess) goto loser; /* Application token */ rv = sslBuffer_AppendVariable(&plaintext, appToken, appTokenLen, 2); if (rv != SECSuccess)
--- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -708,28 +708,34 @@ typedef struct SSL3HandshakeStateStr { ssl3CipherSuite zeroRttSuite; /* The cipher suite we used for 0-RTT. */ PRCList bufferedEarlyData; /* Buffered TLS 1.3 early data * on server.*/ PRBool helloRetry; /* True if HelloRetryRequest has been sent * or received. */ PRBool receivedCcs; /* A server received ChangeCipherSpec * before the handshake started. */ PRBool clientCertRequested; /* True if CertificateRequest received. */ + PRBool endOfFlight; /* Processed a full flight (DTLS 1.3). */ ssl3KEADef kea_def_mutable; /* Used to hold the writable kea_def * we use for TLS 1.3 */ - PRTime serverHelloTime; /* Time the ServerHello flight was sent. */ PRUint16 ticketNonce; /* A counter we use for tickets. */ SECItem fakeSid; /* ... (server) the SID the client used. */ - PRBool endOfFlight; /* Processed a full flight (DTLS 1.3). */ + + /* rttEstimate is used to guess the round trip time between server and client. + * When the server sends ServerHello it sets this to the current time. + * Only after it receives a message from the client's second flight does it + * set the value to something resembling an RTT estimate. */ + PRTime rttEstimate; /* The following lists contain DTLSHandshakeRecordEntry */ PRCList dtlsSentHandshake; /* Used to map records to handshake fragments. */ PRCList dtlsRcvdHandshake; /* Handshake records we have received * used to generate ACKs. */ - PRCList psks; /* A list of PSKs, resumption and/or external. */ + + PRCList psks; /* A list of PSKs, resumption and/or external. */ } SSL3HandshakeState; #define SSL_ASSERT_HASHES_EMPTY(ss) \ do { \ PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_unknown); \ PORT_Assert(ss->ssl3.hs.messages.len == 0); \ } while (0)
--- a/security/nss/lib/ssl/tls13con.c +++ b/security/nss/lib/ssl/tls13con.c @@ -2861,17 +2861,19 @@ tls13_SendServerHelloSequence(sslSocket } if (tls13_ShouldRequestClientAuth(ss)) { TLS13_SET_HS_STATE(ss, wait_client_cert); } else { TLS13_SET_HS_STATE(ss, wait_finished); } } - ss->ssl3.hs.serverHelloTime = ssl_Time(ss); + /* Here we set a baseline value for our RTT estimation. + * This value is updated when we get a response from the client. */ + ss->ssl3.hs.rttEstimate = ssl_Time(ss); return SECSuccess; } SECStatus tls13_HandleServerHelloPart2(sslSocket *ss) { SECStatus rv; sslSessionID *sid = ss->sec.ci.sid; @@ -3246,31 +3248,37 @@ tls13_HandleCertificate(sslSocket *ss, P } else { rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, wait_client_cert); } } else { rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, wait_cert_request, wait_server_cert); } - if (rv != SECSuccess) - return SECFailure; + if (rv != SECSuccess) { + return SECFailure; + } /* We can ignore any other cleartext from the client. */ if (ss->sec.isServer && IS_DTLS(ss)) { ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyClearText); dtls_ReceivedFirstMessageInFlight(ss); } if (ss->firstHsDone) { rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_certificate, b, length); if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } + } else if (ss->sec.isServer) { + /* Our first shot an getting an RTT estimate. If the client took extra + * time to fetch a certificate, this will be bad, but we can't do much + * about that. */ + ss->ssl3.hs.rttEstimate = ssl_Time(ss) - ss->ssl3.hs.rttEstimate; } /* Process the context string */ rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length); if (rv != SECSuccess) return SECFailure; if (ss->ssl3.clientCertRequested) { @@ -4768,16 +4776,21 @@ tls13_ServerHandleFinished(sslSocket *ss if (!tls13_ShouldRequestClientAuth(ss)) { /* Receiving this message might be the first sign we have that * early data is over, so pretend we received EOED. */ rv = tls13_MaybeHandleSuppressedEndOfEarlyData(ss); if (rv != SECSuccess) { return SECFailure; /* Code already set. */ } + + if (!tls13_IsPostHandshake(ss)) { + /* Finalize the RTT estimate. */ + ss->ssl3.hs.rttEstimate = ssl_Time(ss) - ss->ssl3.hs.rttEstimate; + } } rv = tls13_CommonHandleFinished(ss, ss->firstHsDone ? ss->ssl3.hs.clientTrafficSecret : ss->ssl3.hs.clientHsTrafficSecret, b, length); if (rv != SECSuccess) { return SECFailure; }
--- a/security/nss/lib/ssl/tls13replay.c +++ b/security/nss/lib/ssl/tls13replay.c @@ -51,18 +51,17 @@ tls13_ReleaseAntiReplayContext(SSLAntiRe } PK11_FreeSymKey(ctx->key); ctx->key = NULL; sslBloom_Destroy(&ctx->filters[0]); sslBloom_Destroy(&ctx->filters[1]); PORT_Free(ctx); } -/* Clear the current state and free any resources we allocated. The signature - * here is odd to allow this to be called during shutdown. */ +/* Clear the current state and free any resources we allocated. */ SECStatus SSLExp_ReleaseAntiReplayContext(SSLAntiReplayContext *ctx) { tls13_ReleaseAntiReplayContext(ctx); return SECSuccess; } SSLAntiReplayContext *