Bug 1655105 - land NSS c06f22733446 UPGRADE_NSS_RELEASE, r=jcj
authorKevin Jacobs <kjacobs@mozilla.com>
Mon, 10 Aug 2020 17:59:40 +0000
changeset 544133 4462bac0fc59f25feab3764f9e2b9226dc2d22d2
parent 544132 60059f7d5c464eb10d7979cefb4d151bf50b5abf
child 544134 837f7946e5fbdad679fe7dd96391bdd71da7465f
push id37688
push userapavel@mozilla.com
push dateTue, 11 Aug 2020 03:16:35 +0000
treeherdermozilla-central@3bfe3b28bf50 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjcj
bugs1655105, 1625791, 1651564, 1588941, 1656981, 65537, 12629, 29431, 30332, 1656429
milestone81.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
Bug 1655105 - land NSS c06f22733446 UPGRADE_NSS_RELEASE, r=jcj 2020-08-07 Kevin Jacobs <kjacobs@mozilla.com> * lib/pki/tdcache.c: Bug 1625791 - Call STAN_GetCERTCertificate to load CERTCertificate trust before caching. r=jcj,keeler When caching certificates, `td->cache->lock` must not be held when taking `slot->isPresentLock`. `add_cert_to_cache` holds then former when calling the sort function in `add_subject_entry`, which will [[ https://searchfox.org/mozilla-central/rev/a3b25e347e2c22207c4b369b99 246e4aebf861a7/security/nss/lib/pki/certificate.c#266 | call ]] `STAN_GetCERTCertificate` -> `fill_CERTCertificateFields` when `cc->nssCertificate` [[ https://searchfox.org/mozilla-central/rev/a3 b25e347e2c22207c4b369b99246e4aebf861a7/security/nss/lib/pki/pki3hack .c#923 | is NULL ]]. There are two problems with this: # `fill_CERTCertificateFields` may end up locking `slot->isPresentLock` (bad ordering, bug 1651564) # The above may happen followed by another attempt to lock `td->cache->lock`(deadlock, this bug). By calling `STAN_GetCERTCertificate` prior to the first lock of `td->cache->lock`, we can prevent the problematic call to `fill_CERTCertificateFields` later on, because `cc->nssCertificate` will already be filled. [c06f22733446] [tip] * gtests/ssl_gtest/ssl_auth_unittest.cc, lib/ssl/ssl3con.c: Bug 1588941 - Send empty client cert msg when signature scheme selection fails. r=mt `ssl3_CompleteHandleCertificateRequest` does essentially two things: 1) Calls the `getClientAuthData` hook for certificate selection, and 2) calls `ssl_PickClientSignatureScheme` to select an appropriate signature scheme when a cert is selected. If the first function returns SECFailure, we default to sending an empty certificate message. If the latter fails, however, this bubbles up as a [[ https://searchfox.org/mozilla-central/rev/56bb74e a8e04bdac57c33cbe9b54d889b9262ade/security/nss/lib/ssl/tls13con.c#26 70 | fatal error ]] (and an assertion failure) on the connection. Importantly, the signature scheme selection can fail for reasons that should not be considered fatal - notably when an RSA-PSS cert is selected, but the token on which the key resides does not actually support PSS. This patch treats the failure to find a usable signature scheme as a "no certificate" response, rather than killing the connection entirely. [41ecb7fe5546] * lib/freebl/Makefile, lib/freebl/freebl_base.gypi, lib/freebl/mpi/mpi_amd64_common.S, lib/freebl/mpi/mpi_amd64_gas.s: Bug 1656981 - Use 64x64->128 multiply and MP_COMBA on x86_64 Mac. r=mt This patch makes two MPI changes for MacOS: 1. Rename `mpi_amd64_gas.s` to `mpi_amd64_common.S` and add defines for macho64, allowing Intel Macs to take advantage of the 64x64->128 multiply code. 2. Define and use `NSS_USE_COMBA` on Intel Macs. Performance results with `rsaperf -n none -p 10 -e -x 65537` (default 2048-bit key): Before: `12629.12 operations/s. one operation every 79 microseconds` With 64x64->128 assembly: `29431.65 operations/s. one operation every 33 microseconds` With MP_COMBA and 64x64->128 assembly: `30332.99 operations/s. one operation every 32 microseconds` [330bdab498a3] * lib/ssl/sslimpl.h: Bug 1656429 - Clang-format fixup, r=bustage [07083076fc92] 2020-08-05 Martin Thomson <mt@lowentropy.net> * gtests/ssl_gtest/ssl_0rtt_unittest.cc, gtests/ssl_gtest/tls_connect.cc, lib/ssl/ssl3exthandle.c, lib/ssl/sslimpl.h, lib/ssl/tls13con.c, lib/ssl/tls13replay.c: Bug 1656429 - Correct RTT estimate used in anti-replay, r=kjacobs This was never a security problem, but the more time that passes between the handshake and sending a ticket, the more likely we are to reject 0-RTT. Eventually, 0-RTT only works if it is delayed in the network by a surprising amount. [b4a1c57eb569] Differential Revision: https://phabricator.services.mozilla.com/D86454
security/nss/TAG-INFO
security/nss/coreconf/coreconf.dep
security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc
security/nss/gtests/ssl_gtest/tls_connect.cc
security/nss/lib/freebl/Makefile
security/nss/lib/freebl/freebl_base.gypi
security/nss/lib/freebl/mpi/mpi_amd64_common.S
security/nss/lib/freebl/mpi/mpi_amd64_gas.s
security/nss/lib/pki/tdcache.c
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3exthandle.c
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/tls13con.c
security/nss/lib/ssl/tls13replay.c
--- 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 *