Bug 1420060 - land NSS 04fc9a90997b UPGRADE_NSS_RELEASE, r=me
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Tue, 19 Dec 2017 15:26:12 +0100
changeset 396836 ba3a2c41b4b95871804244df48b2e4a70a831167
parent 396835 8a16779be2fb34e3046c84a426117620a5288715
child 396837 56b3aab1d763d41b4672b06cc1034f6f5895357d
push id98378
push userfranziskuskiefer@gmail.com
push dateTue, 19 Dec 2017 14:26:43 +0000
treeherdermozilla-inbound@ba3a2c41b4b9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1420060
milestone59.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 1420060 - land NSS 04fc9a90997b UPGRADE_NSS_RELEASE, r=me MozReview-Commit-ID: 5VMV4wtzMKA
security/manager/ssl/RootHashes.inc
security/manager/tools/KnownRootHashes.json
security/nss/TAG-INFO
security/nss/automation/abi-check/expected-report-libnspr4.so.txt
security/nss/automation/abi-check/expected-report-libssl3.so.txt
security/nss/automation/buildbot-slave/build.sh
security/nss/automation/release/nspr-version.txt
security/nss/automation/taskcluster/docker-hacl/Dockerfile
security/nss/automation/taskcluster/docker-hacl/license.txt
security/nss/automation/taskcluster/docker-hacl/setup-user.sh
security/nss/automation/taskcluster/docker-hacl/setup.sh
security/nss/automation/taskcluster/graph/src/extend.js
security/nss/automation/taskcluster/graph/src/image_builder.js
security/nss/automation/taskcluster/scripts/run_hacl.sh
security/nss/cmd/certutil/certutil.c
security/nss/cmd/tstclnt/tstclnt.c
security/nss/coreconf/coreconf.dep
security/nss/gtests/ssl_gtest/libssl_internals.c
security/nss/gtests/ssl_gtest/libssl_internals.h
security/nss/gtests/ssl_gtest/manifest.mn
security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc
security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc
security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc
security/nss/gtests/ssl_gtest/ssl_gtest.gyp
security/nss/gtests/ssl_gtest/ssl_keylog_unittest.cc
security/nss/gtests/ssl_gtest/ssl_keyupdate_unittest.cc
security/nss/gtests/ssl_gtest/tls_connect.cc
security/nss/gtests/ssl_gtest/tls_connect.h
security/nss/lib/dbm/src/h_page.c
security/nss/lib/dev/devutil.c
security/nss/lib/freebl/Makefile
security/nss/lib/freebl/chacha20poly1305.c
security/nss/lib/freebl/freebl_base.gypi
security/nss/lib/freebl/verified/Hacl_Chacha20.c
security/nss/lib/freebl/verified/Hacl_Chacha20.h
security/nss/lib/freebl/verified/Hacl_Poly1305_64.c
security/nss/lib/freebl/verified/Hacl_Poly1305_64.h
security/nss/lib/freebl/verified/kremlib.h
security/nss/lib/freebl/verified/specs/Spec.CTR.fst
security/nss/lib/freebl/verified/specs/Spec.Chacha20.fst
security/nss/lib/freebl/verified/specs/Spec.Curve25519.fst
security/nss/lib/freebl/verified/specs/Spec.Poly1305.fst
security/nss/lib/softoken/legacydb/lgattr.c
security/nss/lib/softoken/legacydb/pcertdb.c
security/nss/lib/ssl/SSLerrs.h
security/nss/lib/ssl/dtls13con.c
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3encode.c
security/nss/lib/ssl/ssl3encode.h
security/nss/lib/ssl/ssl3ext.c
security/nss/lib/ssl/ssl3exthandle.c
security/nss/lib/ssl/sslerr.h
security/nss/lib/ssl/sslexp.h
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslsecur.c
security/nss/lib/ssl/sslsock.c
security/nss/lib/ssl/sslspec.c
security/nss/lib/ssl/tls13con.c
security/nss/lib/ssl/tls13con.h
security/nss/lib/util/utilpars.c
security/nss/tests/all.sh
security/nss/tests/cert/cert.sh
security/nss/tests/merge/merge.sh
security/nss/tests/ssl/ssl.sh
--- a/security/manager/ssl/RootHashes.inc
+++ b/security/manager/ssl/RootHashes.inc
@@ -47,16 +47,22 @@ static const struct CertAuthorityHash RO
   },
   {
     /* DST_Root_CA_X3 */
     { 0x06, 0x87, 0x26, 0x03, 0x31, 0xA7, 0x24, 0x03, 0xD9, 0x09, 0xF1, 0x05, 0xE6, 0x9B, 0xCF, 0x0D,
       0x32, 0xE1, 0xBD, 0x24, 0x93, 0xFF, 0xC6, 0xD9, 0x20, 0x6D, 0x11, 0xBC, 0xD6, 0x77, 0x07, 0x39 },
       52 /* Bin Number */
   },
   {
+    /* TrustCor_RootCert_CA_2 */
+    { 0x07, 0x53, 0xE9, 0x40, 0x37, 0x8C, 0x1B, 0xD5, 0xE3, 0x83, 0x6E, 0x39, 0x5D, 0xAE, 0xA5, 0xCB,
+      0x83, 0x9E, 0x50, 0x46, 0xF1, 0xBD, 0x0E, 0xAE, 0x19, 0x51, 0xCF, 0x10, 0xFE, 0xC7, 0xC9, 0x65 },
+      191 /* Bin Number */
+  },
+  {
     /* AddTrust_Public_CA_Root */
     { 0x07, 0x91, 0xCA, 0x07, 0x49, 0xB2, 0x07, 0x82, 0xAA, 0xD3, 0xC7, 0xD7, 0xBD, 0x0C, 0xDF, 0xC9,
       0x48, 0x58, 0x35, 0x84, 0x3E, 0xB2, 0xD7, 0x99, 0x60, 0x09, 0xCE, 0x43, 0xAB, 0x6C, 0x69, 0x27 },
       16 /* Bin Number */
   },
   {
     /* OU_Equifax_Secure_Certificate_Authority_O_Equifax_C_US */
     { 0x08, 0x29, 0x7A, 0x40, 0x47, 0xDB, 0xA2, 0x36, 0x80, 0xC7, 0x31, 0xDB, 0x6E, 0x31, 0x76, 0x53,
@@ -161,16 +167,22 @@ static const struct CertAuthorityHash RO
   },
   {
     /* Swisscom_Root_CA_1 */
     { 0x21, 0xDB, 0x20, 0x12, 0x36, 0x60, 0xBB, 0x2E, 0xD4, 0x18, 0x20, 0x5D, 0xA1, 0x1E, 0xE7, 0xA8,
       0x5A, 0x65, 0xE2, 0xBC, 0x6E, 0x55, 0xB5, 0xAF, 0x7E, 0x78, 0x99, 0xC8, 0xA2, 0x66, 0xD9, 0x2E },
       47 /* Bin Number */
   },
   {
+    /* SSL_com_EV_Root_Certification_Authority_ECC */
+    { 0x22, 0xA2, 0xC1, 0xF7, 0xBD, 0xED, 0x70, 0x4C, 0xC1, 0xE7, 0x01, 0xB5, 0xF4, 0x08, 0xC3, 0x10,
+      0x88, 0x0F, 0xE9, 0x56, 0xB5, 0xDE, 0x2A, 0x4A, 0x44, 0xF9, 0x9C, 0x87, 0x3A, 0x25, 0xA7, 0xC8 },
+      196 /* Bin Number */
+  },
+  {
     /* VeriSign_Universal_Root_Certification_Authority */
     { 0x23, 0x99, 0x56, 0x11, 0x27, 0xA5, 0x71, 0x25, 0xDE, 0x8C, 0xEF, 0xEA, 0x61, 0x0D, 0xDF, 0x2F,
       0xA0, 0x78, 0xB5, 0xC8, 0x06, 0x7F, 0x4E, 0x82, 0x82, 0x90, 0xBF, 0xB8, 0x60, 0xE8, 0x4B, 0x3C },
       90 /* Bin Number */
   },
   {
     /* Izenpe_com */
     { 0x25, 0x30, 0xCC, 0x8E, 0x98, 0x32, 0x15, 0x02, 0xBA, 0xD9, 0x6F, 0x9B, 0x1F, 0xBA, 0x1B, 0x09,
@@ -197,16 +209,22 @@ static const struct CertAuthorityHash RO
   },
   {
     /* OU_ApplicationCA_O_Japanese_Government_C_JP */
     { 0x2D, 0x47, 0x43, 0x7D, 0xE1, 0x79, 0x51, 0x21, 0x5A, 0x12, 0xF3, 0xC5, 0x8E, 0x51, 0xC7, 0x29,
       0xA5, 0x80, 0x26, 0xEF, 0x1F, 0xCC, 0x0A, 0x5F, 0xB3, 0xD9, 0xDC, 0x01, 0x2F, 0x60, 0x0D, 0x19 },
       85 /* Bin Number */
   },
   {
+    /* SSL_com_EV_Root_Certification_Authority_RSA_R2 */
+    { 0x2E, 0x7B, 0xF1, 0x6C, 0xC2, 0x24, 0x85, 0xA7, 0xBB, 0xE2, 0xAA, 0x86, 0x96, 0x75, 0x07, 0x61,
+      0xB0, 0xAE, 0x39, 0xBE, 0x3B, 0x2F, 0xE9, 0xD0, 0xCC, 0x6D, 0x4E, 0xF7, 0x34, 0x91, 0x42, 0x5C },
+      195 /* Bin Number */
+  },
+  {
     /* IdenTrust_Public_Sector_Root_CA_1 */
     { 0x30, 0xD0, 0x89, 0x5A, 0x9A, 0x44, 0x8A, 0x26, 0x20, 0x91, 0x63, 0x55, 0x22, 0xD1, 0xF5, 0x20,
       0x10, 0xB5, 0x86, 0x7A, 0xCA, 0xE1, 0x2C, 0x78, 0xEF, 0x95, 0x8F, 0xD4, 0xF4, 0x38, 0x9F, 0x2F },
       162 /* Bin Number */
   },
   {
     /* DigiCert_Global_Root_G3 */
     { 0x31, 0xAD, 0x66, 0x48, 0xF8, 0x10, 0x41, 0x38, 0xC7, 0x38, 0xF3, 0x9E, 0xA4, 0x32, 0x01, 0x33,
@@ -215,16 +233,22 @@ static const struct CertAuthorityHash RO
   },
   {
     /* Microsec_e_Szigno_Root_CA */
     { 0x32, 0x7A, 0x3D, 0x76, 0x1A, 0xBA, 0xDE, 0xA0, 0x34, 0xEB, 0x99, 0x84, 0x06, 0x27, 0x5C, 0xB1,
       0xA4, 0x77, 0x6E, 0xFD, 0xAE, 0x2F, 0xDF, 0x6D, 0x01, 0x68, 0xEA, 0x1C, 0x4F, 0x55, 0x67, 0xD0 },
       70 /* Bin Number */
   },
   {
+    /* SSL_com_Root_Certification_Authority_ECC */
+    { 0x34, 0x17, 0xBB, 0x06, 0xCC, 0x60, 0x07, 0xDA, 0x1B, 0x96, 0x1C, 0x92, 0x0B, 0x8A, 0xB4, 0xCE,
+      0x3F, 0xAD, 0x82, 0x0E, 0x4A, 0xA3, 0x0B, 0x9A, 0xCB, 0xC4, 0xA7, 0x4E, 0xBD, 0xCE, 0xBC, 0x65 },
+      194 /* Bin Number */
+  },
+  {
     /* EBG_Elektronik_Sertifika_Hizmet_Sa_lay_c_s_ */
     { 0x35, 0xAE, 0x5B, 0xDD, 0xD8, 0xF7, 0xAE, 0x63, 0x5C, 0xFF, 0xBA, 0x56, 0x82, 0xA8, 0xF0, 0x0B,
       0x95, 0xF4, 0x84, 0x62, 0xC7, 0x10, 0x8E, 0xE9, 0xA0, 0xE5, 0x29, 0x2B, 0x07, 0x4A, 0xAF, 0xB2 },
       82 /* Bin Number */
   },
   {
     /* GeoTrust_Primary_Certification_Authority */
     { 0x37, 0xD5, 0x10, 0x06, 0xC5, 0x12, 0xEA, 0xAB, 0x62, 0x64, 0x21, 0xF1, 0xEC, 0x8C, 0x92, 0x01,
@@ -401,16 +425,22 @@ static const struct CertAuthorityHash RO
   },
   {
     /* TWCA_Global_Root_CA */
     { 0x59, 0x76, 0x90, 0x07, 0xF7, 0x68, 0x5D, 0x0F, 0xCD, 0x50, 0x87, 0x2F, 0x9F, 0x95, 0xD5, 0x75,
       0x5A, 0x5B, 0x2B, 0x45, 0x7D, 0x81, 0xF3, 0x69, 0x2B, 0x61, 0x0A, 0x98, 0x67, 0x2F, 0x0E, 0x1B },
       139 /* Bin Number */
   },
   {
+    /* TrustCor_ECA_1 */
+    { 0x5A, 0x88, 0x5D, 0xB1, 0x9C, 0x01, 0xD9, 0x12, 0xC5, 0x75, 0x93, 0x88, 0x93, 0x8C, 0xAF, 0xBB,
+      0xDF, 0x03, 0x1A, 0xB2, 0xD4, 0x8E, 0x91, 0xEE, 0x15, 0x58, 0x9B, 0x42, 0x97, 0x1D, 0x03, 0x9C },
+      192 /* Bin Number */
+  },
+  {
     /* Certum_Trusted_Network_CA */
     { 0x5C, 0x58, 0x46, 0x8D, 0x55, 0xF5, 0x8E, 0x49, 0x7E, 0x74, 0x39, 0x82, 0xD2, 0xB5, 0x00, 0x10,
       0xB6, 0xD1, 0x65, 0x37, 0x4A, 0xCF, 0x83, 0xA7, 0xD4, 0xA3, 0x2D, 0xB7, 0x68, 0xC4, 0x40, 0x8E },
       113 /* Bin Number */
   },
   {
     /* CFCA_EV_ROOT */
     { 0x5C, 0xC3, 0xD7, 0x8E, 0x4E, 0x1D, 0x5E, 0x45, 0x54, 0x7A, 0x04, 0xE6, 0x87, 0x3E, 0x64, 0xF9,
@@ -575,16 +605,22 @@ static const struct CertAuthorityHash RO
   },
   {
     /* OU_VeriSign_Trust_Network_OU___c__1998_VeriSign__Inc____For_authorized_use_only__OU_Class_3_Public_Primary_Certification_Authority___G2_O__VeriSign__Inc___C_US */
     { 0x83, 0xCE, 0x3C, 0x12, 0x29, 0x68, 0x8A, 0x59, 0x3D, 0x48, 0x5F, 0x81, 0x97, 0x3C, 0x0F, 0x91,
       0x95, 0x43, 0x1E, 0xDA, 0x37, 0xCC, 0x5E, 0x36, 0x43, 0x0E, 0x79, 0xC7, 0xA8, 0x88, 0x63, 0x8B },
       5 /* Bin Number */
   },
   {
+    /* SSL_com_Root_Certification_Authority_RSA */
+    { 0x85, 0x66, 0x6A, 0x56, 0x2E, 0xE0, 0xBE, 0x5C, 0xE9, 0x25, 0xC1, 0xD8, 0x89, 0x0A, 0x6F, 0x76,
+      0xA8, 0x7E, 0xC1, 0x6D, 0x4D, 0x7D, 0x5F, 0x29, 0xEA, 0x74, 0x19, 0xCF, 0x20, 0x12, 0x3B, 0x69 },
+      193 /* Bin Number */
+  },
+  {
     /* QuoVadis_Root_CA_2 */
     { 0x85, 0xA0, 0xDD, 0x7D, 0xD7, 0x20, 0xAD, 0xB7, 0xFF, 0x05, 0xF8, 0x3D, 0x54, 0x2B, 0x20, 0x9D,
       0xC7, 0xFF, 0x45, 0x28, 0xF7, 0xD6, 0x77, 0xB1, 0x83, 0x89, 0xFE, 0xA5, 0xE5, 0xC4, 0x9E, 0x86 },
       32 /* Bin Number */
   },
   {
     /* UTN___DATACorp_SGC */
     { 0x85, 0xFB, 0x2F, 0x91, 0xDD, 0x12, 0x27, 0x5A, 0x01, 0x45, 0xB6, 0x36, 0x53, 0x4F, 0x84, 0x02,
@@ -857,16 +893,22 @@ static const struct CertAuthorityHash RO
   },
   {
     /* TWCA_Root_Certification_Authority */
     { 0xBF, 0xD8, 0x8F, 0xE1, 0x10, 0x1C, 0x41, 0xAE, 0x3E, 0x80, 0x1B, 0xF8, 0xBE, 0x56, 0x35, 0x0E,
       0xE9, 0xBA, 0xD1, 0xA6, 0xB9, 0xBD, 0x51, 0x5E, 0xDC, 0x5C, 0x6D, 0x5B, 0x87, 0x11, 0xAC, 0x44 },
       117 /* Bin Number */
   },
   {
+    /* GDCA_TrustAUTH_R5_ROOT */
+    { 0xBF, 0xFF, 0x8F, 0xD0, 0x44, 0x33, 0x48, 0x7D, 0x6A, 0x8A, 0xA6, 0x0C, 0x1A, 0x29, 0x76, 0x7A,
+      0x9F, 0xC2, 0xBB, 0xB0, 0x5E, 0x42, 0x0F, 0x71, 0x3A, 0x13, 0xB9, 0x92, 0x89, 0x1D, 0x38, 0x93 },
+      189 /* Bin Number */
+  },
+  {
     /* OU_ePKI_Root_Certification_Authority_O__Chunghwa_Telecom_Co___Ltd___C_TW */
     { 0xC0, 0xA6, 0xF4, 0xDC, 0x63, 0xA2, 0x4B, 0xFD, 0xCF, 0x54, 0xEF, 0x2A, 0x6A, 0x08, 0x2A, 0x0A,
       0x72, 0xDE, 0x35, 0x80, 0x3E, 0x2F, 0xF5, 0xFF, 0x52, 0x7A, 0xE5, 0xD8, 0x72, 0x06, 0xDF, 0xD5 },
       78 /* Bin Number */
   },
   {
     /* OU_Trustis_FPS_Root_CA_O_Trustis_Limited_C_GB */
     { 0xC1, 0xB4, 0x82, 0x99, 0xAB, 0xA5, 0x20, 0x8F, 0xE9, 0x63, 0x0A, 0xCE, 0x55, 0xCA, 0x68, 0xA0,
@@ -929,16 +971,22 @@ static const struct CertAuthorityHash RO
   },
   {
     /* Equifax_Secure_eBusiness_CA_1 */
     { 0xCF, 0x56, 0xFF, 0x46, 0xA4, 0xA1, 0x86, 0x10, 0x9D, 0xD9, 0x65, 0x84, 0xB5, 0xEE, 0xB5, 0x8A,
       0x51, 0x0C, 0x42, 0x75, 0xB0, 0xE5, 0xF9, 0x4F, 0x40, 0xBB, 0xAE, 0x86, 0x5E, 0x19, 0xF6, 0x73 },
       13 /* Bin Number */
   },
   {
+    /* TrustCor_RootCert_CA_1 */
+    { 0xD4, 0x0E, 0x9C, 0x86, 0xCD, 0x8F, 0xE4, 0x68, 0xC1, 0x77, 0x69, 0x59, 0xF4, 0x9E, 0xA7, 0x74,
+      0xFA, 0x54, 0x86, 0x84, 0xB6, 0xC4, 0x06, 0xF3, 0x90, 0x92, 0x61, 0xF4, 0xDC, 0xE2, 0x57, 0x5C },
+      190 /* Bin Number */
+  },
+  {
     /* Staat_der_Nederlanden_Root_CA */
     { 0xD4, 0x1D, 0x82, 0x9E, 0x8C, 0x16, 0x59, 0x82, 0x2A, 0xF9, 0x3F, 0xCE, 0x62, 0xBF, 0xFC, 0xDE,
       0x26, 0x4F, 0xC8, 0x4E, 0x8B, 0x95, 0x0C, 0x5F, 0xF2, 0x75, 0xD0, 0x52, 0x35, 0x46, 0x95, 0xA3 },
       36 /* Bin Number */
   },
   {
     /* Certification_Authority_of_WoSign_G2 */
     { 0xD4, 0x87, 0xA5, 0x6F, 0x83, 0xB0, 0x74, 0x82, 0xE8, 0x5E, 0x96, 0x33, 0x94, 0xC1, 0xEC, 0xC2,
--- a/security/manager/tools/KnownRootHashes.json
+++ b/security/manager/tools/KnownRootHashes.json
@@ -943,12 +943,52 @@
       "label": "LuxTrust_Global_Root_2",
       "binNumber": 187,
       "sha256Fingerprint": "VEVfcSnCCxRHxBj5lxaPJMWPxQI79dpb4utuHdiQLtU="
     },
     {
       "label": "TUBITAK_Kamu_SM_SSL_Kok_Sertifikasi___Surum_1",
       "binNumber": 188,
       "sha256Fingerprint": "Ru3DaJBG1TpFP7MQSrgNyuxliyZg6hYp3X6GeZBkhxY="
+    },
+    {
+      "label": "GDCA_TrustAUTH_R5_ROOT",
+      "binNumber": 189,
+      "sha256Fingerprint": "v/+P0EQzSH1qiqYMGil2ep/Cu7BeQg9xOhO5kokdOJM="
+    },
+    {
+      "label": "TrustCor_RootCert_CA_1",
+      "binNumber": 190,
+      "sha256Fingerprint": "1A6chs2P5GjBd2lZ9J6ndPpUhoS2xAbzkJJh9NziV1w="
+    },
+    {
+      "label": "TrustCor_RootCert_CA_2",
+      "binNumber": 191,
+      "sha256Fingerprint": "B1PpQDeMG9Xjg245Xa6ly4OeUEbxvQ6uGVHPEP7HyWU="
+    },
+    {
+      "label": "TrustCor_ECA_1",
+      "binNumber": 192,
+      "sha256Fingerprint": "WohdsZwB2RLFdZOIk4yvu98DGrLUjpHuFVibQpcdA5w="
+    },
+    {
+      "label": "SSL_com_Root_Certification_Authority_RSA",
+      "binNumber": 193,
+      "sha256Fingerprint": "hWZqVi7gvlzpJcHYiQpvdqh+wW1NfV8p6nQZzyASO2k="
+    },
+    {
+      "label": "SSL_com_Root_Certification_Authority_ECC",
+      "binNumber": 194,
+      "sha256Fingerprint": "NBe7BsxgB9oblhySC4q0zj+tgg5Kowuay8SnTr3OvGU="
+    },
+    {
+      "label": "SSL_com_EV_Root_Certification_Authority_RSA_R2",
+      "binNumber": 195,
+      "sha256Fingerprint": "LnvxbMIkhae74qqGlnUHYbCuOb47L+nQzG1O9zSRQlw="
+    },
+    {
+      "label": "SSL_com_EV_Root_Certification_Authority_ECC",
+      "binNumber": 196,
+      "sha256Fingerprint": "IqLB973tcEzB5wG19AjDEIgP6Va13ipKRPmchzolp8g="
     }
   ],
-  "maxBin": 188
+  "maxBin": 196
 }
\ No newline at end of file
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-ceb8b9290b35
+04fc9a90997b
--- a/security/nss/automation/abi-check/expected-report-libnspr4.so.txt
+++ b/security/nss/automation/abi-check/expected-report-libnspr4.so.txt
@@ -0,0 +1,8 @@
+Functions changes summary: 1 Removed, 0 Changed, 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+1 Removed function:
+
+  'function void PR_EXPERIMENTAL_ONLY_IN_4_17_GetOverlappedIOHandle(void**)'    {PR_EXPERIMENTAL_ONLY_IN_4_17_GetOverlappedIOHandle}
+
+
--- a/security/nss/automation/abi-check/expected-report-libssl3.so.txt
+++ b/security/nss/automation/abi-check/expected-report-libssl3.so.txt
@@ -0,0 +1,3 @@
+Functions changes summary: 0 Removed, 0 Changed (5 filtered out), 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
--- a/security/nss/automation/buildbot-slave/build.sh
+++ b/security/nss/automation/buildbot-slave/build.sh
@@ -266,25 +266,28 @@ check_abi()
         if [ ! -f ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt ]; then
             touch ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt
         fi
         abidiff --hd1 $PREVDIST/public/ --hd2 $NEWDIST/public \
             $PREVDIST/*/lib/$SO $NEWDIST/*/lib/$SO \
             > ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt
         if [ $? -ne 0 ]; then
             ABI_PROBLEM_FOUND=1
+            print_log "FAILED to run abidiff {$PREVDIST , $NEWDIST} for $SO, or failed writing to ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt"
         fi
         if [ ! -f ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt ]; then
             ABI_PROBLEM_FOUND=1
+            print_log "FAILED to access report file: ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt"
         fi
 
         diff -wB -u ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt \
                 ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt >> ${ABI_REPORT}
         if [ ! -f ${ABI_REPORT} ]; then
             ABI_PROBLEM_FOUND=1
+            print_log "FAILED to compare exepcted and new report: ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt"
         fi
     done
 
     if [ -s ${ABI_REPORT} ]; then
         print_log "FAILED: there are new unexpected ABI changes"
         cat ${ABI_REPORT}
         return 1
     elif [ $ABI_PROBLEM_FOUND -ne 0 ]; then
--- a/security/nss/automation/release/nspr-version.txt
+++ b/security/nss/automation/release/nspr-version.txt
@@ -1,9 +1,9 @@
-4.17
+4.18
 
 # The first line of this file must contain the human readable NSPR
 # version number, which is the minimum required version of NSPR
 # that is supported by this version of NSS.
 #
 # This information is used by release automation,
 # when creating an NSS source archive.
 #
--- a/security/nss/automation/taskcluster/docker-hacl/Dockerfile
+++ b/security/nss/automation/taskcluster/docker-hacl/Dockerfile
@@ -4,64 +4,27 @@ MAINTAINER Franziskus Kiefer <franziskus
 # Based on the HACL* image from Benjamin Beurdouche and
 # the original F* formula with Daniel Fabian
 
 # Pinned versions of HACL* (F* and KreMLin are pinned as submodules)
 ENV haclrepo https://github.com/mitls/hacl-star.git
 
 # Define versions of dependencies
 ENV opamv 4.04.2
-ENV haclversion daa7e159f0adf252b5e6962967bc0f27dbac243b
+ENV haclversion dcd48329d535727dbde93877b124c5ec4a7a2b20
 
 # Install required packages and set versions
-RUN apt-get -qq update
-RUN apt-get install --yes sudo libssl-dev libsqlite3-dev g++-5 gcc-5 m4 make opam pkg-config python libgmp3-dev cmake curl libtool-bin autoconf wget
-RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 200
-RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 200
+ADD setup.sh /tmp/setup.sh
+RUN bash /tmp/setup.sh
 
-# Create user
+# Create user, add scripts.
 RUN useradd -ms /bin/bash worker
-RUN echo "worker ALL=(ALL:ALL) NOPASSWD:ALL" >> /etc/sudoers
 WORKDIR /home/worker
-
-# Add build and test scripts.
 ADD bin /home/worker/bin
 RUN chmod +x /home/worker/bin/*
 USER worker
 
-# Prepare build (OCaml packages)
+# Build F*, HACL*, verify. Install a few more dependencies.
 ENV OPAMYES true
-RUN opam init
-RUN echo ". /home/worker/.opam/opam-init/init.sh > /dev/null 2> /dev/null || true" >> .bashrc
-RUN opam switch -v ${opamv}
-RUN opam install ocamlfind batteries sqlite3 fileutils yojson ppx_deriving_yojson zarith pprint menhir ulex process fix wasm stdint
-
-# Get the HACL* code
-RUN git clone ${haclrepo} hacl-star
-RUN git -C hacl-star checkout ${haclversion}
-
-# Prepare submodules, and build, verify, test, and extract c code
-# This caches the extracted c code (pins the HACL* version). All we need to do
-# on CI now is comparing the code in this docker image with the one in NSS.
-RUN opam config exec -- make -C hacl-star prepare -j$(nproc)
 ENV PATH "/home/worker/hacl-star/dependencies/z3/bin:$PATH"
-RUN make -C hacl-star verify-nss -j$(nproc)
-RUN make -C hacl-star -f Makefile.build snapshots/nss -j$(nproc)
-RUN KOPTS="-funroll-loops 5" make -C hacl-star/code/curve25519 test -j$(nproc)
-RUN make -C hacl-star/code/salsa-family test -j$(nproc)
-
-# Get clang-format-3.9
-RUN curl -LO http://releases.llvm.org/3.9.1/clang+llvm-3.9.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz
-RUN curl -LO http://releases.llvm.org/3.9.1/clang+llvm-3.9.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz.sig
-# Verify the signature.
-RUN gpg --keyserver pool.sks-keyservers.net --recv-keys B6C8F98282B944E3B0D5C2530FC3042E345AD05D
-RUN gpg --verify *.tar.xz.sig
-# Install into /usr/local/.
-RUN sudo tar xJvf *.tar.xz -C /usr/local --strip-components=1
-# Cleanup.
-RUN rm *.tar.xz*
-
-# Cleanup
-RUN rm -rf ~/.ccache ~/.cache
-RUN rm -rf /home/worker/hacl-star/dependencies
-RUN sudo apt-get autoremove -y
-RUN sudo apt-get clean
-RUN sudo apt-get autoclean
+ADD setup-user.sh /tmp/setup-user.sh
+ADD license.txt /tmp/license.txt
+RUN bash /tmp/setup-user.sh
new file mode 100644
--- /dev/null
+++ b/security/nss/automation/taskcluster/docker-hacl/license.txt
@@ -0,0 +1,15 @@
+/* Copyright 2016-2017 INRIA and Microsoft Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
new file mode 100644
--- /dev/null
+++ b/security/nss/automation/taskcluster/docker-hacl/setup-user.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+# Prepare build (OCaml packages)
+opam init
+echo ". /home/worker/.opam/opam-init/init.sh > /dev/null 2> /dev/null || true" >> .bashrc
+opam switch -v ${opamv}
+opam install ocamlfind batteries sqlite3 fileutils yojson ppx_deriving_yojson zarith pprint menhir ulex process fix wasm stdint
+
+# Get the HACL* code
+git clone ${haclrepo} hacl-star
+git -C hacl-star checkout ${haclversion}
+
+# Prepare submodules, and build, verify, test, and extract c code
+# This caches the extracted c code (pins the HACL* version). All we need to do
+# on CI now is comparing the code in this docker image with the one in NSS.
+opam config exec -- make -C hacl-star prepare -j$(nproc)
+make -C hacl-star verify-nss -j$(nproc)
+make -C hacl-star -f Makefile.build snapshots/nss -j$(nproc)
+KOPTS="-funroll-loops 5" make -C hacl-star/code/curve25519 test -j$(nproc)
+make -C hacl-star/code/salsa-family test -j$(nproc)
+make -C hacl-star/code/poly1305 test -j$(nproc)
+
+# Cleanup.
+rm -rf ~/.ccache ~/.cache
new file mode 100644
--- /dev/null
+++ b/security/nss/automation/taskcluster/docker-hacl/setup.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+# Update packages.
+export DEBIAN_FRONTEND=noninteractive
+apt-get -qq update
+apt-get install --yes libssl-dev libsqlite3-dev g++-5 gcc-5 m4 make opam pkg-config python libgmp3-dev cmake curl libtool-bin autoconf wget locales
+update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 200
+update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 200
+
+# Get clang-format-3.9
+curl -LO http://releases.llvm.org/3.9.1/clang+llvm-3.9.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz
+curl -LO http://releases.llvm.org/3.9.1/clang+llvm-3.9.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz.sig
+# Verify the signature.
+gpg --keyserver pool.sks-keyservers.net --recv-keys B6C8F98282B944E3B0D5C2530FC3042E345AD05D
+gpg --verify *.tar.xz.sig
+# Install into /usr/local/.
+tar xJvf *.tar.xz -C /usr/local --strip-components=1
+# Cleanup.
+rm *.tar.xz*
+
+locale-gen en_US.UTF-8
+dpkg-reconfigure locales
+
+# Cleanup.
+rm -rf ~/.ccache ~/.cache
+apt-get autoremove -y
+apt-get clean
+apt-get autoclean
--- a/security/nss/automation/taskcluster/graph/src/extend.js
+++ b/security/nss/automation/taskcluster/graph/src/extend.js
@@ -154,16 +154,28 @@ export default async function main() {
     collection: "make",
     command: [
        "/bin/bash",
        "-c",
        "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh"
     ],
   });
 
+  await scheduleLinux("Linux 64 (opt, make)", {
+    env: {USE_64: "1", BUILD_OPT: "1"},
+    platform: "linux64",
+    image: LINUX_IMAGE,
+    collection: "make",
+    command: [
+       "/bin/bash",
+       "-c",
+       "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh"
+    ],
+  });
+
   await scheduleLinux("Linux 32 (debug, make)", {
     platform: "linux32",
     image: LINUX_IMAGE,
     collection: "make",
     command: [
        "/bin/bash",
        "-c",
        "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh"
--- a/security/nss/automation/taskcluster/graph/src/image_builder.js
+++ b/security/nss/automation/taskcluster/graph/src/image_builder.js
@@ -49,12 +49,13 @@ export async function buildTask({name, p
     },
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/build_image.sh"
     ],
     platform: "nss-decision",
     features: ["dind"],
+    maxRunTime: 7200,
     kind: "build",
     symbol: "I"
   };
 }
--- a/security/nss/automation/taskcluster/scripts/run_hacl.sh
+++ b/security/nss/automation/taskcluster/scripts/run_hacl.sh
@@ -7,16 +7,25 @@ if [[ $(id -u) -eq 0 ]]; then
 fi
 
 set -e -x -v
 
 # The docker image this is running in has the HACL* and NSS sources.
 # The extracted C code from HACL* is already generated and the HACL* tests were
 # successfully executed.
 
+# Verify Poly1305 (doesn't work in docker image build)
+make verify -C ~/hacl-star/code/poly1305 -j$(nproc)
+
+# Add license header to specs
+spec_files=($(find ~/hacl-star/specs -type f -name '*.fst'))
+for f in "${spec_files[@]}"; do
+    cat /tmp/license.txt "$f" > /tmp/tmpfile && mv /tmp/tmpfile "$f"
+done
+
 # Format the extracted C code.
 cd ~/hacl-star/snapshots/nss
 cp ~/nss/.clang-format .
 find . -type f -name '*.[ch]' -exec clang-format -i {} \+
 
 # These diff commands will return 1 if there are differences and stop the script.
 files=($(find ~/nss/lib/freebl/verified/ -type f -name '*.[ch]'))
 for f in "${files[@]}"; do
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -648,43 +648,43 @@ ListCerts(CERTCertDBHandle *handle, char
         return SECSuccess;
     }
     rv = listCerts(handle, nickname, email, slot, raw, ascii,
                    extensionOID, outfile, pwdata);
     return rv;
 }
 
 static SECStatus
-DeleteCert(CERTCertDBHandle *handle, char *name)
+DeleteCert(CERTCertDBHandle *handle, char *name, void *pwdata)
 {
     SECStatus rv;
     CERTCertificate *cert;
 
-    cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
+    cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
     if (!cert) {
         SECU_PrintError(progName, "could not find certificate named \"%s\"",
                         name);
         return SECFailure;
     }
 
     rv = SEC_DeletePermCertificate(cert);
     CERT_DestroyCertificate(cert);
     if (rv) {
         SECU_PrintError(progName, "unable to delete certificate");
     }
     return rv;
 }
 
 static SECStatus
-RenameCert(CERTCertDBHandle *handle, char *name, char *newName)
+RenameCert(CERTCertDBHandle *handle, char *name, char *newName, void *pwdata)
 {
     SECStatus rv;
     CERTCertificate *cert;
 
-    cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
+    cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
     if (!cert) {
         SECU_PrintError(progName, "could not find certificate named \"%s\"",
                         name);
         return SECFailure;
     }
 
     rv = __PK11_SetCertificateNickname(cert, newName);
     CERT_DestroyCertificate(cert);
@@ -3329,22 +3329,22 @@ certutil_main(int argc, char **argv, PRB
     }
     /*  List modules (-U)  */
     if (certutil.commands[cmd_ListModules].activated) {
         rv = ListModules();
         goto shutdown;
     }
     /*  Delete cert (-D)  */
     if (certutil.commands[cmd_DeleteCert].activated) {
-        rv = DeleteCert(certHandle, name);
+        rv = DeleteCert(certHandle, name, &pwdata);
         goto shutdown;
     }
     /*  Rename cert (--rename)  */
     if (certutil.commands[cmd_Rename].activated) {
-        rv = RenameCert(certHandle, name, newName);
+        rv = RenameCert(certHandle, name, newName, &pwdata);
         goto shutdown;
     }
     /*  Delete key (-F)  */
     if (certutil.commands[cmd_DeleteKey].activated) {
         rv = DeleteKey(name, &pwdata);
         goto shutdown;
     }
     /*  Modify trust attribute for cert (-M)  */
--- a/security/nss/cmd/tstclnt/tstclnt.c
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -91,16 +91,17 @@ int ssl3CipherSuites[] = {
     0
 };
 
 unsigned long __cmp_umuls;
 PRBool verbose;
 int dumpServerChain = 0;
 int renegotiationsToDo = 0;
 int renegotiationsDone = 0;
+PRBool initializedServerSessionCache = PR_FALSE;
 
 static char *progName;
 
 secuPWData pwdata = { PW_NONE, 0 };
 
 SSLNamedGroup *enabledGroups = NULL;
 unsigned int enabledGroupsCount = 0;
 
@@ -174,17 +175,17 @@ static void
 PrintUsageHeader(const char *progName)
 {
     fprintf(stderr,
             "Usage:  %s -h host [-a 1st_hs_name ] [-a 2nd_hs_name ] [-p port]\n"
             "[-D | -d certdir] [-C] [-b | -R root-module] \n"
             "[-n nickname] [-Bafosvx] [-c ciphers] [-Y] [-Z]\n"
             "[-V [min-version]:[max-version]] [-K] [-T] [-U]\n"
             "[-r N] [-w passwd] [-W pwfile] [-q [-t seconds]] [-I groups]\n"
-            "[-A requestfile] [-L totalconnections]\n"
+            "[-A requestfile] [-L totalconnections] [-P {client,server}] [-Q]\n"
             "\n",
             progName);
 }
 
 static void
 PrintParameterUsage(void)
 {
     fprintf(stderr, "%-20s Send different SNI name. 1st_hs_name - at first\n"
@@ -198,17 +199,17 @@ PrintParameterUsage(void)
             "%-20s Directory with cert database (default is ~/.netscape)\n",
             "-d certdir");
     fprintf(stderr, "%-20s Run without a cert database\n", "-D");
     fprintf(stderr, "%-20s Load the default \"builtins\" root CA module\n", "-b");
     fprintf(stderr, "%-20s Load the given root CA module\n", "-R");
     fprintf(stderr, "%-20s Print certificate chain information\n", "-C");
     fprintf(stderr, "%-20s (use -C twice to print more certificate details)\n", "");
     fprintf(stderr, "%-20s (use -C three times to include PEM format certificate dumps)\n", "");
-    fprintf(stderr, "%-20s Nickname of key and cert for client auth\n",
+    fprintf(stderr, "%-20s Nickname of key and cert\n",
             "-n nickname");
     fprintf(stderr,
             "%-20s Restricts the set of enabled SSL/TLS protocols versions.\n"
             "%-20s All versions are enabled by default.\n"
             "%-20s Possible values for min/max: ssl3 tls1.0 tls1.1 tls1.2 tls1.3\n"
             "%-20s Example: \"-V ssl3:\" enables SSL 3 and newer.\n",
             "-V [min]:[max]", "", "", "");
     fprintf(stderr, "%-20s Send TLS_FALLBACK_SCSV\n", "-K");
@@ -248,16 +249,18 @@ PrintParameterUsage(void)
     fprintf(stderr, "%-20s Read from a file instead of stdin\n", "-A");
     fprintf(stderr, "%-20s Allow 0-RTT data (TLS 1.3 only)\n", "-Z");
     fprintf(stderr, "%-20s Disconnect and reconnect up to N times total\n", "-L");
     fprintf(stderr, "%-20s Comma separated list of enabled groups for TLS key exchange.\n"
                     "%-20s The following values are valid:\n"
                     "%-20s P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n",
             "-I", "", "");
     fprintf(stderr, "%-20s Enable alternative TLS 1.3 handshake\n", "-X alt-server-hello");
+    fprintf(stderr, "%-20s Use DTLS\n", "-P {client, server}");
+    fprintf(stderr, "%-20s Exit after handshake\n", "-Q");
 }
 
 static void
 Usage(const char *progName)
 {
     PrintUsageHeader(progName);
     PrintParameterUsage();
     exit(1);
@@ -912,16 +915,21 @@ char *hs1SniHostName = NULL;
 char *hs2SniHostName = NULL;
 PRUint16 portno = 443;
 int override = 0;
 char *requestString = NULL;
 PRInt32 requestStringLen = 0;
 PRBool requestSent = PR_FALSE;
 PRBool enableZeroRtt = PR_FALSE;
 PRBool enableAltServerHello = PR_FALSE;
+PRBool useDTLS = PR_FALSE;
+PRBool actAsServer = PR_FALSE;
+PRBool stopAfterHandshake = PR_FALSE;
+PRBool requestToExit = PR_FALSE;
+char *versionString = NULL;
 
 static int
 writeBytesToServer(PRFileDesc *s, const char *buf, int nb)
 {
     SECStatus rv;
     const char *bufp = buf;
     PRPollDesc pollDesc;
 
@@ -994,73 +1002,203 @@ handshakeCallback(PRFileDesc *fd, void *
         if (rv != SECSuccess)
             return;
 
         if (!info.earlyDataAccepted) {
             FPRINTF(stderr, "Early data rejected. Re-sending\n");
             writeBytesToServer(fd, requestString, requestStringLen);
         }
     }
+    if (stopAfterHandshake) {
+        requestToExit = PR_TRUE;
+    }
 }
 
 #define REQUEST_WAITING (requestString && !requestSent)
 
+static SECStatus
+installServerCertificate(PRFileDesc *s, char *nickname)
+{
+    CERTCertificate *cert;
+    SECKEYPrivateKey *privKey = NULL;
+
+    if (!nickname) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    cert = PK11_FindCertFromNickname(nickname, &pwdata);
+    if (cert == NULL) {
+        return SECFailure;
+    }
+
+    privKey = PK11_FindKeyByAnyCert(cert, &pwdata);
+    if (privKey == NULL) {
+        return SECFailure;
+    }
+    if (SSL_ConfigServerCert(s, cert, privKey, NULL, 0) != SECSuccess) {
+        return SECFailure;
+    }
+    SECKEY_DestroyPrivateKey(privKey);
+    CERT_DestroyCertificate(cert);
+
+    return SECSuccess;
+}
+
+static SECStatus
+bindToClient(PRFileDesc *s)
+{
+    PRStatus status;
+    status = PR_Bind(s, &addr);
+    if (status != PR_SUCCESS) {
+        return SECFailure;
+    }
+
+    for (;;) {
+        /* Bind the remote address on first packet. This must happen
+         * before we SSL-ize the socket because we need to get the
+         * peer's address before SSLizing. Recvfrom gives us that
+         * while not consuming any data. */
+        unsigned char tmp;
+        PRNetAddr remote;
+        int nb;
+
+        nb = PR_RecvFrom(s, &tmp, 1, PR_MSG_PEEK,
+                         &remote, PR_INTERVAL_NO_TIMEOUT);
+        if (nb != 1)
+            continue;
+
+        status = PR_Connect(s, &remote, PR_INTERVAL_NO_TIMEOUT);
+        if (status != PR_SUCCESS) {
+            SECU_PrintError(progName, "server bind to remote end failed");
+            return SECFailure;
+        }
+        return SECSuccess;
+    }
+
+    /* Unreachable. */
+}
+
+static SECStatus
+connectToServer(PRFileDesc *s, PRPollDesc *pollset)
+{
+    PRStatus status;
+    PRInt32 filesReady;
+
+    status = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT);
+    if (status != PR_SUCCESS) {
+        if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
+            if (verbose)
+                SECU_PrintError(progName, "connect");
+            milliPause(50 * multiplier);
+            pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+            pollset[SSOCK_FD].out_flags = 0;
+            pollset[SSOCK_FD].fd = s;
+            while (1) {
+                FPRINTF(stderr,
+                        "%s: about to call PR_Poll for connect completion!\n",
+                        progName);
+                filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
+                if (filesReady < 0) {
+                    SECU_PrintError(progName, "unable to connect (poll)");
+                    return SECFailure;
+                }
+                FPRINTF(stderr,
+                        "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
+                        progName, pollset[SSOCK_FD].out_flags);
+                if (filesReady == 0) { /* shouldn't happen! */
+                    SECU_PrintError(progName, "%s: PR_Poll returned zero!\n");
+                    return SECFailure;
+                }
+                status = PR_GetConnectStatus(pollset);
+                if (status == PR_SUCCESS) {
+                    break;
+                }
+                if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
+                    SECU_PrintError(progName, "unable to connect (poll)");
+                    return SECFailure;
+                }
+                SECU_PrintError(progName, "poll");
+                milliPause(50 * multiplier);
+            }
+        } else {
+            SECU_PrintError(progName, "unable to connect");
+            return SECFailure;
+        }
+    }
+
+    return SECSuccess;
+}
+
 static int
-run_client(void)
+run(void)
 {
     int headerSeparatorPtrnId = 0;
     int error = 0;
     SECStatus rv;
     PRStatus status;
     PRInt32 filesReady;
     int npds;
     PRFileDesc *s = NULL;
     PRFileDesc *std_out;
     PRPollDesc pollset[2];
     PRBool wrStarted = PR_FALSE;
 
     requestSent = PR_FALSE;
 
     /* Create socket */
-    s = PR_OpenTCPSocket(addr.raw.family);
+    if (useDTLS) {
+        s = PR_OpenUDPSocket(addr.raw.family);
+    } else {
+        s = PR_OpenTCPSocket(addr.raw.family);
+    }
+
     if (s == NULL) {
         SECU_PrintError(progName, "error creating socket");
         error = 1;
         goto done;
     }
 
+    if (actAsServer) {
+        if (bindToClient(s) != SECSuccess) {
+            return 1;
+        }
+    }
     opt.option = PR_SockOpt_Nonblocking;
     opt.value.non_blocking = PR_TRUE; /* default */
     if (serverCertAuth.testFreshStatusFromSideChannel) {
         opt.value.non_blocking = PR_FALSE;
     }
     status = PR_SetSocketOption(s, &opt);
     if (status != PR_SUCCESS) {
         SECU_PrintError(progName, "error setting socket options");
         error = 1;
         goto done;
     }
 
-    s = SSL_ImportFD(NULL, s);
+    if (useDTLS) {
+        s = DTLS_ImportFD(NULL, s);
+    } else {
+        s = SSL_ImportFD(NULL, s);
+    }
     if (s == NULL) {
         SECU_PrintError(progName, "error importing socket");
         error = 1;
         goto done;
     }
-
     SSL_SetPKCS11PinArg(s, &pwdata);
 
     rv = SSL_OptionSet(s, SSL_SECURITY, 1);
     if (rv != SECSuccess) {
         SECU_PrintError(progName, "error enabling socket");
         error = 1;
         goto done;
     }
 
-    rv = SSL_OptionSet(s, SSL_HANDSHAKE_AS_CLIENT, 1);
+    rv = SSL_OptionSet(s, actAsServer ? SSL_HANDSHAKE_AS_SERVER : SSL_HANDSHAKE_AS_CLIENT, 1);
     if (rv != SECSuccess) {
         SECU_PrintError(progName, "error enabling client handshake");
         error = 1;
         goto done;
     }
 
     /* all SSL3 cipher suites are enabled by default. */
     if (cipherString) {
@@ -1220,74 +1358,59 @@ run_client(void)
     }
 
     serverCertAuth.dbHandle = CERT_GetDefaultCertDB();
 
     SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth);
     if (override) {
         SSL_BadCertHook(s, ownBadCertHandler, NULL);
     }
-    SSL_GetClientAuthDataHook(s, own_GetClientAuthData, (void *)nickname);
+    if (actAsServer) {
+        rv = installServerCertificate(s, nickname);
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "error installing server cert");
+            return 1;
+        }
+        rv = SSL_ConfigServerSessionIDCache(1024, 0, 0, ".");
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "error configuring session cache");
+            return 1;
+        }
+        initializedServerSessionCache = PR_TRUE;
+    } else {
+        SSL_GetClientAuthDataHook(s, own_GetClientAuthData, (void *)nickname);
+    }
     SSL_HandshakeCallback(s, handshakeCallback, hs2SniHostName);
     if (hs1SniHostName) {
         SSL_SetURL(s, hs1SniHostName);
     } else {
         SSL_SetURL(s, host);
     }
 
-    /* Try to connect to the server */
-    status = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT);
-    if (status != PR_SUCCESS) {
-        if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
-            if (verbose)
-                SECU_PrintError(progName, "connect");
-            milliPause(50 * multiplier);
-            pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
-            pollset[SSOCK_FD].out_flags = 0;
-            pollset[SSOCK_FD].fd = s;
-            while (1) {
-                FPRINTF(stderr,
-                        "%s: about to call PR_Poll for connect completion!\n",
-                        progName);
-                filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
-                if (filesReady < 0) {
-                    SECU_PrintError(progName, "unable to connect (poll)");
-                    error = 1;
-                    goto done;
-                }
-                FPRINTF(stderr,
-                        "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
-                        progName, pollset[SSOCK_FD].out_flags);
-                if (filesReady == 0) { /* shouldn't happen! */
-                    FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
-                    error = 1;
-                    goto done;
-                }
-                status = PR_GetConnectStatus(pollset);
-                if (status == PR_SUCCESS) {
-                    break;
-                }
-                if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
-                    SECU_PrintError(progName, "unable to connect (poll)");
-                    error = 1;
-                    goto done;
-                }
-                SECU_PrintError(progName, "poll");
-                milliPause(50 * multiplier);
-            }
-        } else {
-            SECU_PrintError(progName, "unable to connect");
+    if (actAsServer) {
+        rv = SSL_ResetHandshake(s, PR_TRUE /* server */);
+        if (rv != SECSuccess) {
+            return 1;
+        }
+    } else {
+        /* Try to connect to the server */
+        rv = connectToServer(s, pollset);
+        if (rv != SECSuccess) {
+            ;
             error = 1;
             goto done;
         }
     }
 
     pollset[SSOCK_FD].fd = s;
-    pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT |
-                                 (clientSpeaksFirst ? 0 : PR_POLL_READ);
+    pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT;
+    if (!actAsServer)
+        pollset[SSOCK_FD].in_flags |= (clientSpeaksFirst ? 0 : PR_POLL_READ);
+    else
+        pollset[SSOCK_FD].in_flags |= PR_POLL_READ;
     pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput);
     if (!REQUEST_WAITING) {
         pollset[STDIN_FD].in_flags = PR_POLL_READ;
         npds = 2;
     } else {
         npds = 1;
     }
     std_out = PR_GetSpecialFD(PR_StandardOutput);
@@ -1327,19 +1450,21 @@ run_client(void)
         error = serverCertAuth.sideChannelRevocationTestResultCode;
         goto done;
     }
 
     /*
     ** Select on stdin and on the socket. Write data from stdin to
     ** socket, read data from socket and write to stdout.
     */
+    requestToExit = PR_FALSE;
     FPRINTF(stderr, "%s: ready...\n", progName);
-    while ((pollset[SSOCK_FD].in_flags | pollset[STDIN_FD].in_flags) ||
-           REQUEST_WAITING) {
+    while (!requestToExit &&
+           ((pollset[SSOCK_FD].in_flags | pollset[STDIN_FD].in_flags) ||
+            REQUEST_WAITING)) {
         char buf[4000]; /* buffer for stdin */
         int nb;         /* num bytes read from stdin. */
 
         rv = restartHandshakeAfterServerCertIfNeeded(s, &serverCertAuth,
                                                      override);
         if (rv != SECSuccess) {
             error = EXIT_CODE_HANDSHAKE_FAILED;
             SECU_PrintError(progName, "authentication of server cert failed");
@@ -1515,22 +1640,20 @@ main(int argc, char **argv)
     tmp = PR_GetEnvSecure("NSS_DEBUG_TIMEOUT");
     if (tmp && tmp[0]) {
         int sec = PORT_Atoi(tmp);
         if (sec > 0) {
             maxInterval = PR_SecondsToInterval(sec);
         }
     }
 
-    SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
-
     /* XXX: 'B' was used in the past but removed in 3.28,
      *      please leave some time before resuing it. */
     optstate = PL_CreateOptState(argc, argv,
-                                 "46A:CDFGHI:KL:M:OR:STUV:W:X:YZa:bc:d:fgh:m:n:op:qr:st:uvw:z");
+                                 "46A:CDFGHI:KL:M:OP:QR:STUV:W:X:YZa:bc:d:fgh:m:n:op:qr:st:uvw:z");
     while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
         switch (optstate->option) {
             case '?':
             default:
                 Usage(progName);
                 break;
 
             case '4':
@@ -1601,16 +1724,31 @@ main(int argc, char **argv)
                     case 0:
                     default:
                         serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
                         serverCertAuth.allowCRLSideChannelData = PR_TRUE;
                         break;
                 };
                 break;
 
+            case 'P':
+                useDTLS = PR_TRUE;
+                if (!strcmp(optstate->value, "server")) {
+                    actAsServer = 1;
+                } else {
+                    if (strcmp(optstate->value, "client")) {
+                        Usage(progName);
+                    }
+                }
+                break;
+
+            case 'Q':
+                stopAfterHandshake = PR_TRUE;
+                break;
+
             case 'R':
                 rootModule = PORT_Strdup(optstate->value);
                 break;
 
             case 'S':
                 skipProtoHeader = PR_TRUE;
                 break;
 
@@ -1618,22 +1756,17 @@ main(int argc, char **argv)
                 enableCertStatus = 1;
                 break;
 
             case 'U':
                 enableSignedCertTimestamps = 1;
                 break;
 
             case 'V':
-                if (SECU_ParseSSLVersionRangeString(optstate->value,
-                                                    enabledVersions, &enabledVersions) !=
-                    SECSuccess) {
-                    fprintf(stderr, "Bad version specified.\n");
-                    Usage(progName);
-                }
+                versionString = PORT_Strdup(optstate->value);
                 break;
 
             case 'X':
                 if (!strcmp(optstate->value, "alt-server-hello")) {
                     enableAltServerHello = PR_TRUE;
                 } else {
                     Usage(progName);
                 }
@@ -1742,18 +1875,29 @@ main(int argc, char **argv)
                 if (rv != SECSuccess) {
                     PL_DestroyOptState(optstate);
                     fprintf(stderr, "Bad group specified.\n");
                     Usage(progName);
                 }
                 break;
         }
     }
+    PL_DestroyOptState(optstate);
 
-    PL_DestroyOptState(optstate);
+    SSL_VersionRangeGetSupported(useDTLS ? ssl_variant_datagram : ssl_variant_stream, &enabledVersions);
+
+    if (versionString) {
+        if (SECU_ParseSSLVersionRangeString(versionString,
+                                            enabledVersions, &enabledVersions) !=
+            SECSuccess) {
+            fprintf(stderr, "Bad version specified.\n");
+            Usage(progName);
+        }
+        PORT_Free(versionString);
+    }
 
     if (optstatus == PL_OPT_BAD) {
         Usage(progName);
     }
 
     if (!host || !portno) {
         fprintf(stderr, "%s: parameters -h and -p are mandatory\n", progName);
         Usage(progName);
@@ -1773,28 +1917,29 @@ main(int argc, char **argv)
     if (rootModule && loadDefaultRootCAs) {
         fprintf(stderr, "%s: Cannot combine parameters -b and -R\n", progName);
         exit(1);
     }
 
     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
 
     PK11_SetPasswordFunc(SECU_GetModulePassword);
-
+    memset(&addr, 0, sizeof(addr));
     status = PR_StringToNetAddr(host, &addr);
     if (status == PR_SUCCESS) {
         addr.inet.port = PR_htons(portno);
     } else {
         /* Lookup host */
         PRAddrInfo *addrInfo;
         void *enumPtr = NULL;
 
         addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC,
                                         PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME);
         if (!addrInfo) {
+            fprintf(stderr, "HOSTNAME=%s\n", host);
             SECU_PrintError(progName, "error looking up host");
             error = 1;
             goto done;
         }
         for (;;) {
             enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, portno, &addr);
             if (enumPtr == NULL)
                 break;
@@ -1899,17 +2044,17 @@ main(int argc, char **argv)
 
     /* all SSL3 cipher suites are enabled by default. */
     if (cipherString) {
         /* disable all the ciphers, then enable the ones we want. */
         disableAllSSLCiphers();
     }
 
     while (numConnections--) {
-        error = run_client();
+        error = run();
         if (error) {
             goto done;
         }
     }
 
 done:
     if (s) {
         PR_Close(s);
@@ -1930,16 +2075,22 @@ done:
     PORT_Free(host);
     PORT_Free(requestString);
 
     if (enabledGroups) {
         PORT_Free(enabledGroups);
     }
     if (NSS_IsInitialized()) {
         SSL_ClearSessionCache();
+        if (initializedServerSessionCache) {
+            if (SSL_ShutdownServerSessionIDCache() != SECSuccess) {
+                error = 1;
+            }
+        }
+
         if (NSS_Shutdown() != SECSuccess) {
             error = 1;
         }
     }
 
     FPRINTF(stderr, "tstclnt: exiting with return code %d\n", error);
     PR_Cleanup();
     return error;
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,8 +5,9 @@
 
 /*
  * 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/libssl_internals.c
+++ b/security/nss/gtests/ssl_gtest/libssl_internals.c
@@ -357,8 +357,22 @@ SECStatus SSLInt_SetSocketMaxEarlyDataSi
   ssl_ReleaseSpecWriteLock(ss);
 
   return SECSuccess;
 }
 
 void SSLInt_RolloverAntiReplay(void) {
   tls13_AntiReplayRollover(ssl_TimeUsec());
 }
+
+SECStatus SSLInt_GetEpochs(PRFileDesc *fd, PRUint16 *readEpoch,
+                           PRUint16 *writeEpoch) {
+  sslSocket *ss = ssl_FindSocket(fd);
+  if (!ss || !readEpoch || !writeEpoch) {
+    return SECFailure;
+  }
+
+  ssl_GetSpecReadLock(ss);
+  *readEpoch = ss->ssl3.crSpec->epoch;
+  *writeEpoch = ss->ssl3.cwSpec->epoch;
+  ssl_ReleaseSpecReadLock(ss);
+  return SECSuccess;
+}
--- a/security/nss/gtests/ssl_gtest/libssl_internals.h
+++ b/security/nss/gtests/ssl_gtest/libssl_internals.h
@@ -34,16 +34,18 @@ PRBool SSLInt_DamageServerHsTrafficSecre
 PRBool SSLInt_DamageEarlyTrafficSecret(PRFileDesc *fd);
 SECStatus SSLInt_Set0RttAlpn(PRFileDesc *fd, PRUint8 *data, unsigned int len);
 PRBool SSLInt_HasCertWithAuthType(PRFileDesc *fd, SSLAuthType authType);
 PRBool SSLInt_SendAlert(PRFileDesc *fd, uint8_t level, uint8_t type);
 SECStatus SSLInt_AdvanceWriteSeqNum(PRFileDesc *fd, PRUint64 to);
 SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to);
 SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra);
 SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group);
+SECStatus SSLInt_GetEpochs(PRFileDesc *fd, PRUint16 *readEpoch,
+                           PRUint16 *writeEpoch);
 
 SECStatus SSLInt_SetCipherSpecChangeFunc(PRFileDesc *fd,
                                          sslCipherSpecChangedFunc func,
                                          void *arg);
 PRUint16 SSLInt_CipherSpecToEpoch(const ssl3CipherSpec *spec);
 PK11SymKey *SSLInt_CipherSpecToKey(const ssl3CipherSpec *spec);
 SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(const ssl3CipherSpec *spec);
 const PRUint8 *SSLInt_CipherSpecToIv(const ssl3CipherSpec *spec);
--- a/security/nss/gtests/ssl_gtest/manifest.mn
+++ b/security/nss/gtests/ssl_gtest/manifest.mn
@@ -27,16 +27,17 @@ CPPSRCS = \
       ssl_exporter_unittest.cc \
       ssl_extension_unittest.cc \
       ssl_fragment_unittest.cc \
       ssl_fuzz_unittest.cc \
       ssl_gather_unittest.cc \
       ssl_gtest.cc \
       ssl_hrr_unittest.cc \
       ssl_keylog_unittest.cc \
+      ssl_keyupdate_unittest.cc \
       ssl_loopback_unittest.cc \
       ssl_misc_unittest.cc \
       ssl_record_unittest.cc \
       ssl_resumption_unittest.cc \
       ssl_renegotiation_unittest.cc \
       ssl_skip_unittest.cc \
       ssl_staticrsa_unittest.cc \
       ssl_tls13compat_unittest.cc \
--- a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
@@ -607,23 +607,17 @@ TEST_P(TlsConnectTls13, ZeroRttOrdering)
   // server: delivery of early data, handshake callback, delivery of 1-RTT.
   size_t step = 0;
   server_->SetHandshakeCallback([&step](TlsAgent*) {
     EXPECT_EQ(1U, step);
     ++step;
   });
 
   std::vector<uint8_t> buf(10);
-  // The first read here blocks because there isn't any 0-RTT to deliver so it
-  // processes everything.  When the EndOfEarlyData message is read, it stalls
-  // out of the loop.  The second read should return the early data.
   PRInt32 read = PR_Read(server_->ssl_fd(), buf.data(), buf.size());
-  EXPECT_GT(0, read);
-  EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
-  read = PR_Read(server_->ssl_fd(), buf.data(), buf.size());
   ASSERT_EQ(static_cast<PRInt32>(early_data.size()), read);
   buf.resize(read);
   EXPECT_EQ(early_data, buf);
   EXPECT_EQ(0U, step);
   ++step;
 
   // The third read should be after the handshake callback and should return the
   // data that was sent after the handshake completed.
--- a/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc
@@ -230,58 +230,64 @@ TEST_P(TlsCipherSuiteTest, ResumeCipherS
 
   Reset();
   ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
   EnableSingleCipher();
   ExpectResumption(RESUME_TICKET);
   ConnectAndCheckCipherSuite();
 }
 
-// This only works for stream ciphers because we modify the sequence number -
-// which is included explicitly in the DTLS record header - and that trips a
-// different error code.  Note that the message that the client sends would not
-// decrypt (the nonce/IV wouldn't match), but the record limit is hit before
-// attempting to decrypt a record.
 TEST_P(TlsCipherSuiteTest, ReadLimit) {
   SetupCertificate();
   EnableSingleCipher();
   ConnectAndCheckCipherSuite();
-  EXPECT_EQ(SECSuccess,
-            SSLInt_AdvanceWriteSeqNum(client_->ssl_fd(), last_safe_write()));
-  EXPECT_EQ(SECSuccess,
-            SSLInt_AdvanceReadSeqNum(server_->ssl_fd(), last_safe_write()));
+  if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
+    uint64_t last = last_safe_write();
+    EXPECT_EQ(SECSuccess, SSLInt_AdvanceWriteSeqNum(client_->ssl_fd(), last));
+    EXPECT_EQ(SECSuccess, SSLInt_AdvanceReadSeqNum(server_->ssl_fd(), last));
 
-  client_->SendData(10, 10);
-  server_->ReadBytes();  // This should be OK.
+    client_->SendData(10, 10);
+    server_->ReadBytes();  // This should be OK.
+  } else {
+    // In TLS 1.3, reading or writing triggers a KeyUpdate.  That would mean
+    // that the sequence numbers would reset and we wouldn't hit the limit.  So
+    // we move the sequence number to one less than the limit directly and don't
+    // test sending and receiving just before the limit.
+    uint64_t last = record_limit() - 1;
+    EXPECT_EQ(SECSuccess, SSLInt_AdvanceReadSeqNum(server_->ssl_fd(), last));
+  }
 
-  // The payload needs to be big enough to pass for encrypted.  In the extreme
-  // case (TLS 1.3), this means 1 for payload, 1 for content type and 16 for
-  // authentication tag.
-  static const uint8_t payload[18] = {6};
+  // The payload needs to be big enough to pass for encrypted.  The code checks
+  // the limit before it tries to decrypt.
+  static const uint8_t payload[32] = {6};
   DataBuffer record;
   uint64_t epoch;
   if (variant_ == ssl_variant_datagram) {
     if (version_ == SSL_LIBRARY_VERSION_TLS_1_3) {
       epoch = 3;  // Application traffic keys.
     } else {
       epoch = 1;
     }
   } else {
     epoch = 0;
   }
   TlsAgentTestBase::MakeRecord(variant_, kTlsApplicationDataType, version_,
                                payload, sizeof(payload), &record,
                                (epoch << 48) | record_limit());
-  server_->adapter()->PacketReceived(record);
+  client_->SendDirect(record);
   server_->ExpectReadWriteError();
   server_->ReadBytes();
   EXPECT_EQ(SSL_ERROR_TOO_MANY_RECORDS, server_->error_code());
 }
 
 TEST_P(TlsCipherSuiteTest, WriteLimit) {
+  // This asserts in TLS 1.3 because we expect an automatic update.
+  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+    return;
+  }
   SetupCertificate();
   EnableSingleCipher();
   ConnectAndCheckCipherSuite();
   EXPECT_EQ(SECSuccess,
             SSLInt_AdvanceWriteSeqNum(client_->ssl_fd(), last_safe_write()));
   client_->SendData(10, 10);
   client_->ExpectReadWriteError();
   client_->SendData(10, 10);
--- a/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc
@@ -72,17 +72,17 @@ static const uint16_t kManyExtensions[] 
 // The list here includes all extensions we expect to use (SSL_MAX_EXTENSIONS),
 // plus the deprecated values (see sslt.h), and two extra dummy values.
 PR_STATIC_ASSERT((SSL_MAX_EXTENSIONS + 5) == PR_ARRAY_SIZE(kManyExtensions));
 
 void InstallManyWriters(std::shared_ptr<TlsAgent> agent,
                         SSLExtensionWriter writer, size_t *installed = nullptr,
                         size_t *called = nullptr) {
   for (size_t i = 0; i < PR_ARRAY_SIZE(kManyExtensions); ++i) {
-    SSLExtensionSupport support;
+    SSLExtensionSupport support = ssl_ext_none;
     SECStatus rv = SSL_GetExtensionSupport(kManyExtensions[i], &support);
     ASSERT_EQ(SECSuccess, rv) << "SSL_GetExtensionSupport cannot fail";
 
     rv = SSL_InstallExtensionHooks(agent->ssl_fd(), kManyExtensions[i], writer,
                                    called, NoopExtensionHandler, nullptr);
     if (support == ssl_ext_native_only) {
       EXPECT_EQ(SECFailure, rv);
       EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
--- a/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc
@@ -347,16 +347,19 @@ TEST_F(TlsDropDatagram13, DropSecondHalf
 // After that we let all the ACKs through and allow the handshake to complete
 // without further interference.
 //
 // This allows us to test that ranges of handshake messages are sent correctly
 // even when there are overlapping acknowledgments; that ACKs with duplicate or
 // overlapping message ranges are handled properly; and that extra
 // retransmissions are handled properly.
 class TlsFragmentationAndRecoveryTest : public TlsDropDatagram13 {
+ public:
+  TlsFragmentationAndRecoveryTest() : cert_len_(0) {}
+
  protected:
   void RunTest(size_t dropped_half) {
     FirstFlightDropCertificate();
 
     SecondAttemptDropHalf(dropped_half);
     size_t dropped_half_size = server_record_len(dropped_half);
     size_t second_flight_count = server_filters_.records_->count();
 
--- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
+++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
@@ -28,16 +28,17 @@
         'ssl_exporter_unittest.cc',
         'ssl_extension_unittest.cc',
         'ssl_fuzz_unittest.cc',
         'ssl_fragment_unittest.cc',
         'ssl_gather_unittest.cc',
         'ssl_gtest.cc',
         'ssl_hrr_unittest.cc',
         'ssl_keylog_unittest.cc',
+        'ssl_keyupdate_unittest.cc',
         'ssl_loopback_unittest.cc',
         'ssl_misc_unittest.cc',
         'ssl_record_unittest.cc',
         'ssl_resumption_unittest.cc',
         'ssl_renegotiation_unittest.cc',
         'ssl_skip_unittest.cc',
         'ssl_staticrsa_unittest.cc',
         'ssl_tls13compat_unittest.cc',
--- a/security/nss/gtests/ssl_gtest/ssl_keylog_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_keylog_unittest.cc
@@ -1,70 +1,94 @@
 /* -*- 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/. */
 
+#ifdef NSS_ALLOW_SSLKEYLOGFILE
+
 #include <cstdlib>
 #include <fstream>
 #include <sstream>
 
 #include "gtest_utils.h"
 #include "tls_connect.h"
 
 namespace nss_test {
 
 static const std::string keylog_file_path = "keylog.txt";
+static const std::string keylog_env = "SSLKEYLOGFILE=" + keylog_file_path;
 
 class KeyLogFileTest : public TlsConnectGeneric {
  public:
   void SetUp() {
     TlsConnectTestBase::SetUp();
     // Remove previous results (if any).
     (void)remove(keylog_file_path.c_str());
-    std::ostringstream sstr;
-    sstr << "SSLKEYLOGFILE=" << keylog_file_path;
-    PR_SetEnv(sstr.str().c_str());
+    PR_SetEnv(keylog_env.c_str());
   }
 
   void CheckKeyLog() {
     std::ifstream f(keylog_file_path);
     std::map<std::string, size_t> labels;
-    std::string last_client_random;
+    std::set<std::string> client_randoms;
     for (std::string line; std::getline(f, line);) {
       if (line[0] == '#') {
         continue;
       }
 
       std::istringstream iss(line);
       std::string label, client_random, secret;
       iss >> label >> client_random >> secret;
 
-      ASSERT_EQ(1U, client_random.size());
-      ASSERT_TRUE(last_client_random.empty() ||
-                  last_client_random == client_random);
-      last_client_random = client_random;
+      ASSERT_EQ(64U, client_random.size());
+      client_randoms.insert(client_random);
       labels[label]++;
     }
 
     if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
-      ASSERT_EQ(1U, labels["CLIENT_RANDOM"]);
+      ASSERT_EQ(1U, client_randoms.size());
     } else {
-      ASSERT_EQ(1U, labels["CLIENT_EARLY_TRAFFIC_SECRET"]);
-      ASSERT_EQ(1U, labels["CLIENT_HANDSHAKE_TRAFFIC_SECRET"]);
-      ASSERT_EQ(1U, labels["SERVER_HANDSHAKE_TRAFFIC_SECRET"]);
-      ASSERT_EQ(1U, labels["CLIENT_TRAFFIC_SECRET_0"]);
-      ASSERT_EQ(1U, labels["SERVER_TRAFFIC_SECRET_0"]);
-      ASSERT_EQ(1U, labels["EXPORTER_SECRET"]);
+      /* two handshakes for 0-RTT */
+      ASSERT_EQ(2U, client_randoms.size());
+    }
+
+    // Every entry occurs twice (one log from server, one from client).
+    if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
+      ASSERT_EQ(2U, labels["CLIENT_RANDOM"]);
+    } else {
+      ASSERT_EQ(2U, labels["CLIENT_EARLY_TRAFFIC_SECRET"]);
+      ASSERT_EQ(2U, labels["EARLY_EXPORTER_SECRET"]);
+      ASSERT_EQ(4U, labels["CLIENT_HANDSHAKE_TRAFFIC_SECRET"]);
+      ASSERT_EQ(4U, labels["SERVER_HANDSHAKE_TRAFFIC_SECRET"]);
+      ASSERT_EQ(4U, labels["CLIENT_TRAFFIC_SECRET_0"]);
+      ASSERT_EQ(4U, labels["SERVER_TRAFFIC_SECRET_0"]);
+      ASSERT_EQ(4U, labels["EXPORTER_SECRET"]);
     }
   }
 
   void ConnectAndCheck() {
-    Connect();
+    // This is a child process, ensure that error messages immediately
+    // propagate or else it will not be visible.
+    ::testing::GTEST_FLAG(throw_on_failure) = true;
+
+    if (version_ == SSL_LIBRARY_VERSION_TLS_1_3) {
+      SetupForZeroRtt();
+      client_->Set0RttEnabled(true);
+      server_->Set0RttEnabled(true);
+      ExpectResumption(RESUME_TICKET);
+      ZeroRttSendReceive(true, true);
+      Handshake();
+      ExpectEarlyDataAccepted(true);
+      CheckConnected();
+      SendReceive();
+    } else {
+      Connect();
+    }
     CheckKeyLog();
     _exit(0);
   }
 };
 
 // Tests are run in a separate process to ensure that NSS is not initialized yet
 // and can process the SSLKEYLOGFILE environment variable.
 
@@ -85,8 +109,10 @@ INSTANTIATE_TEST_CASE_P(
 #ifndef NSS_DISABLE_TLS_1_3
 INSTANTIATE_TEST_CASE_P(
     KeyLogFileTLS13, KeyLogFileTest,
     ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
                        TlsConnectTestBase::kTlsV13));
 #endif
 
 }  // namespace nss_test
+
+#endif  // NSS_ALLOW_SSLKEYLOGFILE
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/ssl_gtest/ssl_keyupdate_unittest.cc
@@ -0,0 +1,178 @@
+/* -*- 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 "scoped_ptrs.h"
+#include "tls_connect.h"
+#include "tls_filter.h"
+#include "tls_parser.h"
+
+namespace nss_test {
+
+// All stream only tests; DTLS isn't supported yet.
+
+TEST_F(TlsConnectTest, KeyUpdateClient) {
+  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  Connect();
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_FALSE));
+  SendReceive(50);
+  SendReceive(60);
+  CheckEpochs(4, 3);
+}
+
+TEST_F(TlsConnectTest, KeyUpdateClientRequestUpdate) {
+  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  Connect();
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_TRUE));
+  // SendReceive() only gives each peer one chance to read.  This isn't enough
+  // when the read on one side generates another handshake message.  A second
+  // read gives each peer an extra chance to consume the KeyUpdate.
+  SendReceive(50);
+  SendReceive(60);  // Cumulative count.
+  CheckEpochs(4, 4);
+}
+
+TEST_F(TlsConnectTest, KeyUpdateServer) {
+  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  Connect();
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), PR_FALSE));
+  SendReceive(50);
+  SendReceive(60);
+  CheckEpochs(3, 4);
+}
+
+TEST_F(TlsConnectTest, KeyUpdateServerRequestUpdate) {
+  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  Connect();
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE));
+  SendReceive(50);
+  SendReceive(60);
+  CheckEpochs(4, 4);
+}
+
+TEST_F(TlsConnectTest, KeyUpdateConsecutiveRequests) {
+  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  Connect();
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE));
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE));
+  SendReceive(50);
+  SendReceive(60);
+  // The server should have updated twice, but the client should have declined
+  // to respond to the second request from the server, since it doesn't send
+  // anything in between those two requests.
+  CheckEpochs(4, 5);
+}
+
+// Check that a local update can be immediately followed by a remotely triggered
+// update even if there is no use of the keys.
+TEST_F(TlsConnectTest, KeyUpdateLocalUpdateThenConsecutiveRequests) {
+  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  Connect();
+  // This should trigger an update on the client.
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_FALSE));
+  // The client should update for the first request.
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE));
+  // ...but not the second.
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE));
+  SendReceive(50);
+  SendReceive(60);
+  // Both should have updated twice.
+  CheckEpochs(5, 5);
+}
+
+TEST_F(TlsConnectTest, KeyUpdateMultiple) {
+  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  Connect();
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), PR_FALSE));
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE));
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), PR_FALSE));
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_FALSE));
+  SendReceive(50);
+  SendReceive(60);
+  CheckEpochs(5, 6);
+}
+
+// Both ask the other for an update, and both should react.
+TEST_F(TlsConnectTest, KeyUpdateBothRequest) {
+  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  Connect();
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_TRUE));
+  EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE));
+  SendReceive(50);
+  SendReceive(60);
+  CheckEpochs(5, 5);
+}
+
+// If the sequence number exceeds the number of writes before an automatic
+// update (currently 3/4 of the max records for the cipher suite), then the
+// stack should send an update automatically (but not request one).
+TEST_F(TlsConnectTest, KeyUpdateAutomaticOnWrite) {
+  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  ConnectWithCipherSuite(TLS_AES_128_GCM_SHA256);
+
+  // Set this to one below the write threshold.
+  uint64_t threshold = (0x5aULL << 28) * 3 / 4;
+  EXPECT_EQ(SECSuccess,
+            SSLInt_AdvanceWriteSeqNum(client_->ssl_fd(), threshold));
+  EXPECT_EQ(SECSuccess, SSLInt_AdvanceReadSeqNum(server_->ssl_fd(), threshold));
+
+  // This should be OK.
+  client_->SendData(10);
+  server_->ReadBytes();
+
+  // This should cause the client to update.
+  client_->SendData(10);
+  server_->ReadBytes();
+
+  SendReceive(100);
+  CheckEpochs(4, 3);
+}
+
+// If the sequence number exceeds a certain number of reads (currently 7/8 of
+// the max records for the cipher suite), then the stack should send AND request
+// an update automatically.  However, the sender (client) will be above its
+// automatic update threshold, so the KeyUpdate - that it sends with the old
+// cipher spec - will exceed the receiver (server) automatic update threshold.
+// The receiver gets a packet with a sequence number over its automatic read
+// update threshold.  Even though the sender has updated, the code that checks
+// the sequence numbers at the receiver doesn't know this and it will request an
+// update.  This causes two updates: one from the sender (without requesting a
+// response) and one from the receiver (which does request a response).
+TEST_F(TlsConnectTest, KeyUpdateAutomaticOnRead) {
+  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+  ConnectWithCipherSuite(TLS_AES_128_GCM_SHA256);
+
+  // Move to right at the read threshold.  Unlike the write test, we can't send
+  // packets because that would cause the client to update, which would spoil
+  // the test.
+  uint64_t threshold = ((0x5aULL << 28) * 7 / 8) + 1;
+  EXPECT_EQ(SECSuccess,
+            SSLInt_AdvanceWriteSeqNum(client_->ssl_fd(), threshold));
+  EXPECT_EQ(SECSuccess, SSLInt_AdvanceReadSeqNum(server_->ssl_fd(), threshold));
+
+  // This should cause the client to update, but not early enough to prevent the
+  // server from updating also.
+  client_->SendData(10);
+  server_->ReadBytes();
+
+  // Need two SendReceive() calls to ensure that the update that the server
+  // requested is properly generated and consumed.
+  SendReceive(70);
+  SendReceive(80);
+  CheckEpochs(5, 4);
+}
+
+}  // namespace nss_test
--- a/security/nss/gtests/ssl_gtest/tls_connect.cc
+++ b/security/nss/gtests/ssl_gtest/tls_connect.cc
@@ -160,16 +160,32 @@ void TlsConnectTestBase::CheckShares(
     SSLNamedGroup group = static_cast<SSLNamedGroup>(tmp);
     group_set.AddAndCheckGroup(group);
     check_group(group);
     ASSERT_TRUE(shares.Read(i + 2, 2, &tmp));
   }
   EXPECT_EQ(shares.len(), i);
 }
 
+void TlsConnectTestBase::CheckEpochs(uint16_t client_epoch,
+                                     uint16_t server_epoch) const {
+  uint16_t read_epoch = 0;
+  uint16_t write_epoch = 0;
+
+  EXPECT_EQ(SECSuccess,
+            SSLInt_GetEpochs(client_->ssl_fd(), &read_epoch, &write_epoch));
+  EXPECT_EQ(server_epoch, read_epoch) << "client read epoch";
+  EXPECT_EQ(client_epoch, write_epoch) << "client write epoch";
+
+  EXPECT_EQ(SECSuccess,
+            SSLInt_GetEpochs(server_->ssl_fd(), &read_epoch, &write_epoch));
+  EXPECT_EQ(client_epoch, read_epoch) << "server read epoch";
+  EXPECT_EQ(server_epoch, write_epoch) << "server write epoch";
+}
+
 void TlsConnectTestBase::ClearStats() {
   // Clear statistics.
   SSL3Statistics* stats = SSL_GetStatistics();
   memset(stats, 0, sizeof(*stats));
 }
 
 void TlsConnectTestBase::ClearServerCache() {
   SSL_ShutdownServerSessionIDCache();
@@ -588,20 +604,22 @@ void TlsConnectTestBase::EnableSrtp() {
   server_->EnableSrtp();
 }
 
 void TlsConnectTestBase::CheckSrtp() const {
   client_->CheckSrtp();
   server_->CheckSrtp();
 }
 
-void TlsConnectTestBase::SendReceive() {
-  client_->SendData(50);
-  server_->SendData(50);
-  Receive(50);
+void TlsConnectTestBase::SendReceive(size_t total) {
+  ASSERT_GT(total, client_->received_bytes());
+  ASSERT_GT(total, server_->received_bytes());
+  client_->SendData(total - server_->received_bytes());
+  server_->SendData(total - client_->received_bytes());
+  Receive(total);  // Receive() is cumulative
 }
 
 // Do a first connection so we can do 0-RTT on the second one.
 void TlsConnectTestBase::SetupForZeroRtt() {
   // If we don't do this, then all 0-RTT attempts will be rejected.
   SSLInt_RolloverAntiReplay();
 
   ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
--- a/security/nss/gtests/ssl_gtest/tls_connect.h
+++ b/security/nss/gtests/ssl_gtest/tls_connect.h
@@ -89,16 +89,17 @@ class TlsConnectTestBase : public ::test
   void CheckKeysResumption(SSLKEAType kea_type, SSLNamedGroup kea_group,
                            SSLNamedGroup original_kea_group,
                            SSLAuthType auth_type,
                            SSLSignatureScheme sig_scheme);
   void CheckGroups(const DataBuffer& groups,
                    std::function<void(SSLNamedGroup)> check_group);
   void CheckShares(const DataBuffer& shares,
                    std::function<void(SSLNamedGroup)> check_group);
+  void CheckEpochs(uint16_t client_epoch, uint16_t server_epoch) const;
 
   void ConfigureVersion(uint16_t version);
   void SetExpectedVersion(uint16_t version);
   // Expect resumption of a particular type.
   void ExpectResumption(SessionResumptionMode expected,
                         uint8_t num_resumed = 1);
   void DisableAllCiphers();
   void EnableOnlyStaticRsaCiphers();
@@ -109,17 +110,17 @@ class TlsConnectTestBase : public ::test
   void ConfigureSessionCache(SessionResumptionMode client,
                              SessionResumptionMode server);
   void EnableAlpn();
   void EnableAlpn(const uint8_t* val, size_t len);
   void EnsureModelSockets();
   void CheckAlpn(const std::string& val);
   void EnableSrtp();
   void CheckSrtp() const;
-  void SendReceive();
+  void SendReceive(size_t total = 50);
   void SetupForZeroRtt();
   void SetupForResume();
   void ZeroRttSendReceive(
       bool expect_writable, bool expect_readable,
       std::function<bool()> post_clienthello_check = nullptr);
   void Receive(size_t amount);
   void ExpectExtendedMasterSecret(bool expected);
   void ExpectEarlyDataAccepted(bool expected);
--- a/security/nss/lib/dbm/src/h_page.c
+++ b/security/nss/lib/dbm/src/h_page.c
@@ -421,16 +421,19 @@ ugly_split(HTAB *hashp, uint32 obucket, 
 
     bufp = old_bufp;
     ino = (uint16 *)old_bufp->page;
     np = (uint16 *)new_bufp->page;
     op = (uint16 *)old_bufp->page;
     last_bfp = NULL;
     scopyto = (uint16)copyto; /* ANSI */
 
+    if (ino[0] < 1) {
+        return DATABASE_CORRUPTED_ERROR;
+    }
     n = ino[0] - 1;
     while (n < ino[0]) {
 
         /* this function goes nuts sometimes and never returns.
          * I havent found the problem yet but I need a solution
          * so if we loop too often we assume a database curruption error
          * :LJM
          */
@@ -458,17 +461,23 @@ ugly_split(HTAB *hashp, uint32 obucket, 
             ino = (uint16 *)cino;
             last_bfp = ret.nextp;
         } else if (ino[n + 1] == OVFLPAGE) {
             ov_addr = ino[n];
             /*
              * Fix up the old page -- the extra 2 are the fields
              * which contained the overflow information.
              */
+            if (ino[0] < (moved + 2)) {
+                return DATABASE_CORRUPTED_ERROR;
+            }
             ino[0] -= (moved + 2);
+            if (scopyto < sizeof(uint16) * (ino[0] + 3)) {
+                return DATABASE_CORRUPTED_ERROR;
+            }
             FREESPACE(ino) =
                 scopyto - sizeof(uint16) * (ino[0] + 3);
             OFFSET(ino) = scopyto;
 
             bufp = __get_buf(hashp, ov_addr, bufp, 0);
             if (!bufp)
                 return (-1);
 
@@ -481,18 +490,24 @@ ugly_split(HTAB *hashp, uint32 obucket, 
                 __free_ovflpage(hashp, last_bfp);
             last_bfp = bufp;
         }
         /* Move regular sized pairs of there are any */
         off = hashp->BSIZE;
         for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
             cino = (char *)ino;
             key.data = (uint8 *)cino + ino[n];
+            if (off < ino[n]) {
+                return DATABASE_CORRUPTED_ERROR;
+            }
             key.size = off - ino[n];
             val.data = (uint8 *)cino + ino[n + 1];
+            if (ino[n] < ino[n + 1]) {
+                return DATABASE_CORRUPTED_ERROR;
+            }
             val.size = ino[n] - ino[n + 1];
             off = ino[n + 1];
 
             if (__call_hash(hashp, (char *)key.data, key.size) == obucket) {
                 /* Keep on old page */
                 if (PAIRFITS(op, (&key), (&val)))
                     putpair((char *)op, &key, &val);
                 else {
--- a/security/nss/lib/dev/devutil.c
+++ b/security/nss/lib/dev/devutil.c
@@ -27,25 +27,31 @@ nssCryptokiObject_Create(
     slot = nssToken_GetSlot(t);
     status = nssCKObject_GetAttributes(h, cert_template, 2,
                                        NULL, session, slot);
     nssSlot_Destroy(slot);
     if (status != PR_SUCCESS) {
         /* a failure here indicates a device error */
         return (nssCryptokiObject *)NULL;
     }
+    if (cert_template[0].ulValueLen == 0) {
+        nss_ZFreeIf(cert_template[1].pValue);
+        return (nssCryptokiObject *)NULL;
+    }
     object = nss_ZNEW(NULL, nssCryptokiObject);
     if (!object) {
+        nss_ZFreeIf(cert_template[0].pValue);
+        nss_ZFreeIf(cert_template[1].pValue);
         return (nssCryptokiObject *)NULL;
     }
     object->handle = h;
     object->token = nssToken_AddRef(t);
     isTokenObject = (CK_BBOOL *)cert_template[0].pValue;
     object->isTokenObject = *isTokenObject;
-    nss_ZFreeIf(isTokenObject);
+    nss_ZFreeIf(cert_template[0].pValue);
     NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[1], object->label);
     return object;
 }
 
 NSS_IMPLEMENT void
 nssCryptokiObject_Destroy(
     nssCryptokiObject *object)
 {
--- a/security/nss/lib/freebl/Makefile
+++ b/security/nss/lib/freebl/Makefile
@@ -487,18 +487,16 @@ else
  	ifndef NS_USE_GCC
  	   MPCPU_SRCS =
  	   ASFILES += mpcpucache_x86.s
  	endif
     endif
 endif # Solaris for non-sparc family CPUs
 endif # target == SunO
 
-# poly1305-donna-x64-sse2-incremental-source.c requires __int128 support
-# in GCC 4.6.0.
 ifdef USE_64
     ifdef CC_IS_CLANG
             HAVE_INT128_SUPPORT = 1
             DEFINES += -DHAVE_INT128_SUPPORT
     else ifeq (1,$(CC_IS_GCC))
         ifneq (,$(filter 4.6 4.7 4.8 4.9,$(word 1,$(GCC_VERSION)).$(word 2,$(GCC_VERSION))))
             HAVE_INT128_SUPPORT = 1
             DEFINES += -DHAVE_INT128_SUPPORT
@@ -512,17 +510,17 @@ endif
 
 ifndef HAVE_INT128_SUPPORT
     DEFINES += -DKRML_NOUINT128
 endif
 
 ifndef NSS_DISABLE_CHACHAPOLY
     ifeq ($(CPU_ARCH),x86_64)
         ifdef HAVE_INT128_SUPPORT
-            EXTRA_SRCS += poly1305-donna-x64-sse2-incremental-source.c
+            EXTRA_SRCS += Hacl_Poly1305_64.c
         else
             EXTRA_SRCS += poly1305.c
         endif
 
         ifneq (1,$(CC_IS_GCC))
             EXTRA_SRCS += chacha20.c
             VERIFIED_SRCS += Hacl_Chacha20.c
         else
--- a/security/nss/lib/freebl/chacha20poly1305.c
+++ b/security/nss/lib/freebl/chacha20poly1305.c
@@ -9,24 +9,71 @@
 #include <string.h>
 #include <stdio.h>
 
 #include "seccomon.h"
 #include "secerr.h"
 #include "blapit.h"
 
 #ifndef NSS_DISABLE_CHACHAPOLY
+#if defined(HAVE_INT128_SUPPORT) && (defined(NSS_X86_OR_X64) || defined(__aarch64__))
+#include "verified/Hacl_Poly1305_64.h"
+#else
 #include "poly1305.h"
+#endif
 #include "chacha20.h"
 #include "chacha20poly1305.h"
 #endif
 
 /* Poly1305Do writes the Poly1305 authenticator of the given additional data
  * and ciphertext to |out|. */
 #ifndef NSS_DISABLE_CHACHAPOLY
+
+#if defined(HAVE_INT128_SUPPORT) && (defined(NSS_X86_OR_X64) || defined(__aarch64__))
+
+static void
+Poly1305PadUpdate(Hacl_Impl_Poly1305_64_State_poly1305_state state, unsigned char *block, const unsigned char *p, const unsigned int pLen)
+{
+    unsigned int pRemLen = pLen % 16;
+    Hacl_Poly1305_64_update(state, (uint8_t *)p, (pLen / 16));
+    if (pRemLen > 0) {
+        memcpy(block, p + (pLen - pRemLen), pRemLen);
+        Hacl_Poly1305_64_update(state, block, 1);
+    }
+}
+
+static void
+Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen,
+           const unsigned char *ciphertext, unsigned int ciphertextLen,
+           const unsigned char key[32])
+{
+    uint64_t tmp1[6U] = { 0U };
+    Hacl_Impl_Poly1305_64_State_poly1305_state state = Hacl_Poly1305_64_mk_state(tmp1, tmp1 + 3);
+
+    unsigned char block[16] = { 0 };
+    Hacl_Poly1305_64_init(state, (uint8_t *)key);
+
+    Poly1305PadUpdate(state, block, ad, adLen);
+    memset(block, 0, 16);
+    Poly1305PadUpdate(state, block, ciphertext, ciphertextLen);
+
+    unsigned int i;
+    unsigned int j;
+    for (i = 0, j = adLen; i < 8; i++, j >>= 8) {
+        block[i] = j;
+    }
+    for (i = 8, j = ciphertextLen; i < 16; i++, j >>= 8) {
+        block[i] = j;
+    }
+
+    Hacl_Poly1305_64_update(state, block, 1);
+    Hacl_Poly1305_64_finish(state, out, (uint8_t *)(key + 16));
+}
+#else
+
 static void
 Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen,
            const unsigned char *ciphertext, unsigned int ciphertextLen,
            const unsigned char key[32])
 {
     poly1305_state state;
     unsigned int j;
     unsigned char lengthBytes[8];
@@ -51,17 +98,19 @@ Poly1305Do(unsigned char *out, const uns
     j = ciphertextLen;
     for (i = 0; i < sizeof(lengthBytes); i++) {
         lengthBytes[i] = j;
         j >>= 8;
     }
     Poly1305Update(&state, lengthBytes, sizeof(lengthBytes));
     Poly1305Finish(&state, out);
 }
-#endif
+
+#endif /* HAVE_INT128_SUPPORT */
+#endif /* NSS_DISABLE_CHACHAPOLY */
 
 SECStatus
 ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx,
                              const unsigned char *key, unsigned int keyLen,
                              unsigned int tagLen)
 {
 #ifdef NSS_DISABLE_CHACHAPOLY
     return SECFailure;
--- a/security/nss/lib/freebl/freebl_base.gypi
+++ b/security/nss/lib/freebl/freebl_base.gypi
@@ -140,23 +140,45 @@
     }, {
       'sources': [
         # All other architectures get the generic 32 bit implementation (slow!)
         'ecl/curve25519_32.c',
       ],
     }],
     [ 'disable_chachapoly==0', {
       'conditions': [
-        [ 'OS!="win" and target_arch=="x64"', {
-          'sources': [
-            'chacha20_vec.c',
-            'poly1305-donna-x64-sse2-incremental-source.c',
+        [ 'OS!="win"', {
+          'conditions': [
+            [ 'target_arch=="x64"', {
+              'sources': [
+                'chacha20_vec.c',
+                'verified/Hacl_Poly1305_64.c',
+              ],
+            }, {
+              # !Windows & !x64
+              'conditions': [
+                [ 'target_arch=="arm64" or target_arch=="aarch64"', {
+                  'sources': [
+                    'chacha20.c',
+                    'verified/Hacl_Chacha20.c',
+                    'verified/Hacl_Poly1305_64.c',
+                  ],
+                }, {
+                  # !Windows & !x64 & !arm64 & !aarch64
+                  'sources': [
+                    'chacha20.c',
+                    'verified/Hacl_Chacha20.c',
+                    'poly1305.c',
+                  ],
+                }],
+              ],
+            }],
           ],
         }, {
-          # not x64
+          # Windows
           'sources': [
             'chacha20.c',
             'verified/Hacl_Chacha20.c',
             'poly1305.c',
           ],
         }],
       ],
     }],
--- a/security/nss/lib/freebl/verified/Hacl_Chacha20.c
+++ b/security/nss/lib/freebl/verified/Hacl_Chacha20.c
@@ -37,32 +37,16 @@ Hacl_Lib_LoadStore32_uint32s_to_le_bytes
 
 inline static uint32_t
 Hacl_Impl_Chacha20_rotate_left(uint32_t a, uint32_t s)
 {
     return a << s | a >> ((uint32_t)32U - s);
 }
 
 inline static void
-Hacl_Impl_Chacha20_setup(uint32_t *st, uint8_t *k, uint8_t *n1, uint32_t c)
-{
-    uint32_t *stcst = st;
-    uint32_t *stk = st + (uint32_t)4U;
-    uint32_t *stc = st + (uint32_t)12U;
-    uint32_t *stn = st + (uint32_t)13U;
-    stcst[0U] = (uint32_t)0x61707865U;
-    stcst[1U] = (uint32_t)0x3320646eU;
-    stcst[2U] = (uint32_t)0x79622d32U;
-    stcst[3U] = (uint32_t)0x6b206574U;
-    Hacl_Lib_LoadStore32_uint32s_from_le_bytes(stk, k, (uint32_t)8U);
-    stc[0U] = c;
-    Hacl_Lib_LoadStore32_uint32s_from_le_bytes(stn, n1, (uint32_t)3U);
-}
-
-inline static void
 Hacl_Impl_Chacha20_quarter_round(uint32_t *st, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
 {
     uint32_t sa = st[a];
     uint32_t sb0 = st[b];
     st[a] = sa + sb0;
     uint32_t sd = st[d];
     uint32_t sa10 = st[a];
     uint32_t sda = sd ^ sa10;
@@ -141,17 +125,27 @@ Hacl_Impl_Chacha20_chacha20_block(uint8_
     uint32_t st_[16U] = { 0U };
     Hacl_Impl_Chacha20_chacha20_core(st_, st, ctr);
     Hacl_Lib_LoadStore32_uint32s_to_le_bytes(stream_block, st_, (uint32_t)16U);
 }
 
 inline static void
 Hacl_Impl_Chacha20_init(uint32_t *st, uint8_t *k, uint8_t *n1)
 {
-    Hacl_Impl_Chacha20_setup(st, k, n1, (uint32_t)0U);
+    uint32_t *stcst = st;
+    uint32_t *stk = st + (uint32_t)4U;
+    uint32_t *stc = st + (uint32_t)12U;
+    uint32_t *stn = st + (uint32_t)13U;
+    stcst[0U] = (uint32_t)0x61707865U;
+    stcst[1U] = (uint32_t)0x3320646eU;
+    stcst[2U] = (uint32_t)0x79622d32U;
+    stcst[3U] = (uint32_t)0x6b206574U;
+    Hacl_Lib_LoadStore32_uint32s_from_le_bytes(stk, k, (uint32_t)8U);
+    stc[0U] = (uint32_t)0U;
+    Hacl_Lib_LoadStore32_uint32s_from_le_bytes(stn, n1, (uint32_t)3U);
 }
 
 static void
 Hacl_Impl_Chacha20_update(uint8_t *output, uint8_t *plain, uint32_t *st, uint32_t ctr)
 {
     uint32_t b[48U] = { 0U };
     uint32_t *k = b;
     uint32_t *ib = b + (uint32_t)16U;
@@ -183,21 +177,21 @@ Hacl_Impl_Chacha20_update_last(
         output[i] = xi ^ yi;
     }
 }
 
 static void
 Hacl_Impl_Chacha20_chacha20_counter_mode_blocks(
     uint8_t *output,
     uint8_t *plain,
-    uint32_t len,
+    uint32_t num_blocks,
     uint32_t *st,
     uint32_t ctr)
 {
-    for (uint32_t i = (uint32_t)0U; i < len; i = i + (uint32_t)1U) {
+    for (uint32_t i = (uint32_t)0U; i < num_blocks; i = i + (uint32_t)1U) {
         uint8_t *b = plain + (uint32_t)64U * i;
         uint8_t *o = output + (uint32_t)64U * i;
         Hacl_Impl_Chacha20_update(o, b, st, ctr + i);
     }
 }
 
 static void
 Hacl_Impl_Chacha20_chacha20_counter_mode(
@@ -237,16 +231,37 @@ void
 Hacl_Chacha20_chacha20_key_block(uint8_t *block, uint8_t *k, uint8_t *n1, uint32_t ctr)
 {
     uint32_t buf[16U] = { 0U };
     uint32_t *st = buf;
     Hacl_Impl_Chacha20_init(st, k, n1);
     Hacl_Impl_Chacha20_chacha20_block(block, st, ctr);
 }
 
+/*
+  This function implements Chacha20
+
+  val chacha20 :
+  output:uint8_p ->
+  plain:uint8_p{ disjoint output plain } ->
+  len:uint32_t{ v len = length output /\ v len = length plain } ->
+  key:uint8_p{ length key = 32 } ->
+  nonce:uint8_p{ length nonce = 12 } ->
+  ctr:uint32_t{ v ctr + length plain / 64 < pow2 32 } ->
+  Stack unit
+    (requires
+      fun h -> live h output /\ live h plain /\ live h nonce /\ live h key)
+    (ensures
+      fun h0 _ h1 ->
+        live h1 output /\ live h0 plain /\ modifies_1 output h0 h1 /\
+        live h0 nonce /\
+        live h0 key /\
+        h1.[ output ] ==
+        chacha20_encrypt_bytes h0.[ key ] h0.[ nonce ] (v ctr) h0.[ plain ])
+*/
 void
 Hacl_Chacha20_chacha20(
     uint8_t *output,
     uint8_t *plain,
     uint32_t len,
     uint8_t *k,
     uint8_t *n1,
     uint32_t ctr)
--- a/security/nss/lib/freebl/verified/Hacl_Chacha20.h
+++ b/security/nss/lib/freebl/verified/Hacl_Chacha20.h
@@ -44,16 +44,37 @@ typedef void *Hacl_Impl_Chacha20_log_t;
 typedef uint32_t Hacl_Lib_Create_h32;
 
 typedef uint8_t *Hacl_Chacha20_uint8_p;
 
 typedef uint32_t Hacl_Chacha20_uint32_t;
 
 void Hacl_Chacha20_chacha20_key_block(uint8_t *block, uint8_t *k, uint8_t *n1, uint32_t ctr);
 
+/*
+  This function implements Chacha20
+
+  val chacha20 :
+  output:uint8_p ->
+  plain:uint8_p{ disjoint output plain } ->
+  len:uint32_t{ v len = length output /\ v len = length plain } ->
+  key:uint8_p{ length key = 32 } ->
+  nonce:uint8_p{ length nonce = 12 } ->
+  ctr:uint32_t{ v ctr + length plain / 64 < pow2 32 } ->
+  Stack unit
+    (requires
+      fun h -> live h output /\ live h plain /\ live h nonce /\ live h key)
+    (ensures
+      fun h0 _ h1 ->
+        live h1 output /\ live h0 plain /\ modifies_1 output h0 h1 /\
+        live h0 nonce /\
+        live h0 key /\
+        h1.[ output ] ==
+        chacha20_encrypt_bytes h0.[ key ] h0.[ nonce ] (v ctr) h0.[ plain ])
+*/
 void
 Hacl_Chacha20_chacha20(
     uint8_t *output,
     uint8_t *plain,
     uint32_t len,
     uint8_t *k,
     uint8_t *n1,
     uint32_t ctr);
new file mode 100644
--- /dev/null
+++ b/security/nss/lib/freebl/verified/Hacl_Poly1305_64.c
@@ -0,0 +1,485 @@
+/* Copyright 2016-2017 INRIA and Microsoft Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Hacl_Poly1305_64.h"
+
+inline static void
+Hacl_Bignum_Modulo_reduce(uint64_t *b)
+{
+    uint64_t b0 = b[0U];
+    b[0U] = (b0 << (uint32_t)4U) + (b0 << (uint32_t)2U);
+}
+
+inline static void
+Hacl_Bignum_Modulo_carry_top(uint64_t *b)
+{
+    uint64_t b2 = b[2U];
+    uint64_t b0 = b[0U];
+    uint64_t b2_42 = b2 >> (uint32_t)42U;
+    b[2U] = b2 & (uint64_t)0x3ffffffffffU;
+    b[0U] = (b2_42 << (uint32_t)2U) + b2_42 + b0;
+}
+
+inline static void
+Hacl_Bignum_Modulo_carry_top_wide(FStar_UInt128_t *b)
+{
+    FStar_UInt128_t b2 = b[2U];
+    FStar_UInt128_t b0 = b[0U];
+    FStar_UInt128_t
+        b2_ = FStar_UInt128_logand(b2, FStar_UInt128_uint64_to_uint128((uint64_t)0x3ffffffffffU));
+    uint64_t b2_42 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b2, (uint32_t)42U));
+    FStar_UInt128_t
+        b0_ = FStar_UInt128_add(b0, FStar_UInt128_uint64_to_uint128((b2_42 << (uint32_t)2U) + b2_42));
+    b[2U] = b2_;
+    b[0U] = b0_;
+}
+
+inline static void
+Hacl_Bignum_Fproduct_copy_from_wide_(uint64_t *output, FStar_UInt128_t *input)
+{
+    for (uint32_t i = (uint32_t)0U; i < (uint32_t)3U; i = i + (uint32_t)1U) {
+        FStar_UInt128_t xi = input[i];
+        output[i] = FStar_UInt128_uint128_to_uint64(xi);
+    }
+}
+
+inline static void
+Hacl_Bignum_Fproduct_sum_scalar_multiplication_(
+    FStar_UInt128_t *output,
+    uint64_t *input,
+    uint64_t s)
+{
+    for (uint32_t i = (uint32_t)0U; i < (uint32_t)3U; i = i + (uint32_t)1U) {
+        FStar_UInt128_t xi = output[i];
+        uint64_t yi = input[i];
+        output[i] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s));
+    }
+}
+
+inline static void
+Hacl_Bignum_Fproduct_carry_wide_(FStar_UInt128_t *tmp)
+{
+    for (uint32_t i = (uint32_t)0U; i < (uint32_t)2U; i = i + (uint32_t)1U) {
+        uint32_t ctr = i;
+        FStar_UInt128_t tctr = tmp[ctr];
+        FStar_UInt128_t tctrp1 = tmp[ctr + (uint32_t)1U];
+        uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0xfffffffffffU;
+        FStar_UInt128_t c = FStar_UInt128_shift_right(tctr, (uint32_t)44U);
+        tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0);
+        tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c);
+    }
+}
+
+inline static void
+Hacl_Bignum_Fproduct_carry_limb_(uint64_t *tmp)
+{
+    for (uint32_t i = (uint32_t)0U; i < (uint32_t)2U; i = i + (uint32_t)1U) {
+        uint32_t ctr = i;
+        uint64_t tctr = tmp[ctr];
+        uint64_t tctrp1 = tmp[ctr + (uint32_t)1U];
+        uint64_t r0 = tctr & (uint64_t)0xfffffffffffU;
+        uint64_t c = tctr >> (uint32_t)44U;
+        tmp[ctr] = r0;
+        tmp[ctr + (uint32_t)1U] = tctrp1 + c;
+    }
+}
+
+inline static void
+Hacl_Bignum_Fmul_shift_reduce(uint64_t *output)
+{
+    uint64_t tmp = output[2U];
+    for (uint32_t i = (uint32_t)0U; i < (uint32_t)2U; i = i + (uint32_t)1U) {
+        uint32_t ctr = (uint32_t)3U - i - (uint32_t)1U;
+        uint64_t z = output[ctr - (uint32_t)1U];
+        output[ctr] = z;
+    }
+    output[0U] = tmp;
+    Hacl_Bignum_Modulo_reduce(output);
+}
+
+static void
+Hacl_Bignum_Fmul_mul_shift_reduce_(FStar_UInt128_t *output, uint64_t *input, uint64_t *input2)
+{
+    for (uint32_t i = (uint32_t)0U; i < (uint32_t)2U; i = i + (uint32_t)1U) {
+        uint64_t input2i = input2[i];
+        Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i);
+        Hacl_Bignum_Fmul_shift_reduce(input);
+    }
+    uint32_t i = (uint32_t)2U;
+    uint64_t input2i = input2[i];
+    Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i);
+}
+
+inline static void
+Hacl_Bignum_Fmul_fmul(uint64_t *output, uint64_t *input, uint64_t *input2)
+{
+    uint64_t tmp[3U] = { 0U };
+    memcpy(tmp, input, (uint32_t)3U * sizeof input[0U]);
+    KRML_CHECK_SIZE(FStar_UInt128_uint64_to_uint128((uint64_t)0U), (uint32_t)3U);
+    FStar_UInt128_t t[3U];
+    for (uint32_t _i = 0U; _i < (uint32_t)3U; ++_i)
+        t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U);
+    Hacl_Bignum_Fmul_mul_shift_reduce_(t, tmp, input2);
+    Hacl_Bignum_Fproduct_carry_wide_(t);
+    Hacl_Bignum_Modulo_carry_top_wide(t);
+    Hacl_Bignum_Fproduct_copy_from_wide_(output, t);
+    uint64_t i0 = output[0U];
+    uint64_t i1 = output[1U];
+    uint64_t i0_ = i0 & (uint64_t)0xfffffffffffU;
+    uint64_t i1_ = i1 + (i0 >> (uint32_t)44U);
+    output[0U] = i0_;
+    output[1U] = i1_;
+}
+
+inline static void
+Hacl_Bignum_AddAndMultiply_add_and_multiply(uint64_t *acc, uint64_t *block, uint64_t *r)
+{
+    for (uint32_t i = (uint32_t)0U; i < (uint32_t)3U; i = i + (uint32_t)1U) {
+        uint64_t xi = acc[i];
+        uint64_t yi = block[i];
+        acc[i] = xi + yi;
+    }
+    Hacl_Bignum_Fmul_fmul(acc, acc, r);
+}
+
+inline static void
+Hacl_Impl_Poly1305_64_poly1305_update(
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *m)
+{
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut0 = st;
+    uint64_t *h = scrut0.h;
+    uint64_t *acc = h;
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
+    uint64_t *r = scrut.r;
+    uint64_t *r3 = r;
+    uint64_t tmp[3U] = { 0U };
+    FStar_UInt128_t m0 = load128_le(m);
+    uint64_t r0 = FStar_UInt128_uint128_to_uint64(m0) & (uint64_t)0xfffffffffffU;
+    uint64_t
+        r1 =
+            FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(m0, (uint32_t)44U)) & (uint64_t)0xfffffffffffU;
+    uint64_t r2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(m0, (uint32_t)88U));
+    tmp[0U] = r0;
+    tmp[1U] = r1;
+    tmp[2U] = r2;
+    uint64_t b2 = tmp[2U];
+    uint64_t b2_ = (uint64_t)0x10000000000U | b2;
+    tmp[2U] = b2_;
+    Hacl_Bignum_AddAndMultiply_add_and_multiply(acc, tmp, r3);
+}
+
+inline static void
+Hacl_Impl_Poly1305_64_poly1305_process_last_block_(
+    uint8_t *block,
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *m,
+    uint64_t rem_)
+{
+    uint64_t tmp[3U] = { 0U };
+    FStar_UInt128_t m0 = load128_le(block);
+    uint64_t r0 = FStar_UInt128_uint128_to_uint64(m0) & (uint64_t)0xfffffffffffU;
+    uint64_t
+        r1 =
+            FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(m0, (uint32_t)44U)) & (uint64_t)0xfffffffffffU;
+    uint64_t r2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(m0, (uint32_t)88U));
+    tmp[0U] = r0;
+    tmp[1U] = r1;
+    tmp[2U] = r2;
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut0 = st;
+    uint64_t *h = scrut0.h;
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
+    uint64_t *r = scrut.r;
+    Hacl_Bignum_AddAndMultiply_add_and_multiply(h, tmp, r);
+}
+
+inline static void
+Hacl_Impl_Poly1305_64_poly1305_process_last_block(
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *m,
+    uint64_t rem_)
+{
+    uint8_t zero1 = (uint8_t)0U;
+    KRML_CHECK_SIZE(zero1, (uint32_t)16U);
+    uint8_t block[16U];
+    for (uint32_t _i = 0U; _i < (uint32_t)16U; ++_i)
+        block[_i] = zero1;
+    uint32_t i0 = (uint32_t)rem_;
+    uint32_t i = (uint32_t)rem_;
+    memcpy(block, m, i * sizeof m[0U]);
+    block[i0] = (uint8_t)1U;
+    Hacl_Impl_Poly1305_64_poly1305_process_last_block_(block, st, m, rem_);
+}
+
+static void
+Hacl_Impl_Poly1305_64_poly1305_last_pass(uint64_t *acc)
+{
+    Hacl_Bignum_Fproduct_carry_limb_(acc);
+    Hacl_Bignum_Modulo_carry_top(acc);
+    uint64_t a0 = acc[0U];
+    uint64_t a10 = acc[1U];
+    uint64_t a20 = acc[2U];
+    uint64_t a0_ = a0 & (uint64_t)0xfffffffffffU;
+    uint64_t r0 = a0 >> (uint32_t)44U;
+    uint64_t a1_ = (a10 + r0) & (uint64_t)0xfffffffffffU;
+    uint64_t r1 = (a10 + r0) >> (uint32_t)44U;
+    uint64_t a2_ = a20 + r1;
+    acc[0U] = a0_;
+    acc[1U] = a1_;
+    acc[2U] = a2_;
+    Hacl_Bignum_Modulo_carry_top(acc);
+    uint64_t i0 = acc[0U];
+    uint64_t i1 = acc[1U];
+    uint64_t i0_ = i0 & (uint64_t)0xfffffffffffU;
+    uint64_t i1_ = i1 + (i0 >> (uint32_t)44U);
+    acc[0U] = i0_;
+    acc[1U] = i1_;
+    uint64_t a00 = acc[0U];
+    uint64_t a1 = acc[1U];
+    uint64_t a2 = acc[2U];
+    uint64_t mask0 = FStar_UInt64_gte_mask(a00, (uint64_t)0xffffffffffbU);
+    uint64_t mask1 = FStar_UInt64_eq_mask(a1, (uint64_t)0xfffffffffffU);
+    uint64_t mask2 = FStar_UInt64_eq_mask(a2, (uint64_t)0x3ffffffffffU);
+    uint64_t mask = (mask0 & mask1) & mask2;
+    uint64_t a0_0 = a00 - ((uint64_t)0xffffffffffbU & mask);
+    uint64_t a1_0 = a1 - ((uint64_t)0xfffffffffffU & mask);
+    uint64_t a2_0 = a2 - ((uint64_t)0x3ffffffffffU & mask);
+    acc[0U] = a0_0;
+    acc[1U] = a1_0;
+    acc[2U] = a2_0;
+}
+
+static Hacl_Impl_Poly1305_64_State_poly1305_state
+Hacl_Impl_Poly1305_64_mk_state(uint64_t *r, uint64_t *h)
+{
+    return ((Hacl_Impl_Poly1305_64_State_poly1305_state){.r = r, .h = h });
+}
+
+static void
+Hacl_Standalone_Poly1305_64_poly1305_blocks(
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *m,
+    uint64_t len1)
+{
+    if (!(len1 == (uint64_t)0U)) {
+        uint8_t *block = m;
+        uint8_t *tail1 = m + (uint32_t)16U;
+        Hacl_Impl_Poly1305_64_poly1305_update(st, block);
+        uint64_t len2 = len1 - (uint64_t)1U;
+        Hacl_Standalone_Poly1305_64_poly1305_blocks(st, tail1, len2);
+    }
+}
+
+static void
+Hacl_Standalone_Poly1305_64_poly1305_partial(
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *input,
+    uint64_t len1,
+    uint8_t *kr)
+{
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
+    uint64_t *r = scrut.r;
+    uint64_t *x0 = r;
+    FStar_UInt128_t k1 = load128_le(kr);
+    FStar_UInt128_t
+        k_clamped =
+            FStar_UInt128_logand(k1,
+                                 FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0ffffffcU),
+                                                                              (uint32_t)64U),
+                                                     FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0fffffffU)));
+    uint64_t r0 = FStar_UInt128_uint128_to_uint64(k_clamped) & (uint64_t)0xfffffffffffU;
+    uint64_t
+        r1 =
+            FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)44U)) & (uint64_t)0xfffffffffffU;
+    uint64_t
+        r2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)88U));
+    x0[0U] = r0;
+    x0[1U] = r1;
+    x0[2U] = r2;
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut0 = st;
+    uint64_t *h = scrut0.h;
+    uint64_t *x00 = h;
+    x00[0U] = (uint64_t)0U;
+    x00[1U] = (uint64_t)0U;
+    x00[2U] = (uint64_t)0U;
+    Hacl_Standalone_Poly1305_64_poly1305_blocks(st, input, len1);
+}
+
+static void
+Hacl_Standalone_Poly1305_64_poly1305_complete(
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *m,
+    uint64_t len1,
+    uint8_t *k1)
+{
+    uint8_t *kr = k1;
+    uint64_t len16 = len1 >> (uint32_t)4U;
+    uint64_t rem16 = len1 & (uint64_t)0xfU;
+    uint8_t *part_input = m;
+    uint8_t *last_block = m + (uint32_t)((uint64_t)16U * len16);
+    Hacl_Standalone_Poly1305_64_poly1305_partial(st, part_input, len16, kr);
+    if (!(rem16 == (uint64_t)0U))
+        Hacl_Impl_Poly1305_64_poly1305_process_last_block(st, last_block, rem16);
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
+    uint64_t *h = scrut.h;
+    uint64_t *acc = h;
+    Hacl_Impl_Poly1305_64_poly1305_last_pass(acc);
+}
+
+static void
+Hacl_Standalone_Poly1305_64_crypto_onetimeauth_(
+    uint8_t *output,
+    uint8_t *input,
+    uint64_t len1,
+    uint8_t *k1)
+{
+    uint64_t buf[6U] = { 0U };
+    uint64_t *r = buf;
+    uint64_t *h = buf + (uint32_t)3U;
+    Hacl_Impl_Poly1305_64_State_poly1305_state st = Hacl_Impl_Poly1305_64_mk_state(r, h);
+    uint8_t *key_s = k1 + (uint32_t)16U;
+    Hacl_Standalone_Poly1305_64_poly1305_complete(st, input, len1, k1);
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
+    uint64_t *h3 = scrut.h;
+    uint64_t *acc = h3;
+    FStar_UInt128_t k_ = load128_le(key_s);
+    uint64_t h0 = acc[0U];
+    uint64_t h1 = acc[1U];
+    uint64_t h2 = acc[2U];
+    FStar_UInt128_t
+        acc_ =
+            FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128(h2
+                                                                                             << (uint32_t)24U |
+                                                                                         h1 >> (uint32_t)20U),
+                                                         (uint32_t)64U),
+                                FStar_UInt128_uint64_to_uint128(h1 << (uint32_t)44U | h0));
+    FStar_UInt128_t mac_ = FStar_UInt128_add_mod(acc_, k_);
+    store128_le(output, mac_);
+}
+
+static void
+Hacl_Standalone_Poly1305_64_crypto_onetimeauth(
+    uint8_t *output,
+    uint8_t *input,
+    uint64_t len1,
+    uint8_t *k1)
+{
+    Hacl_Standalone_Poly1305_64_crypto_onetimeauth_(output, input, len1, k1);
+}
+
+Hacl_Impl_Poly1305_64_State_poly1305_state
+Hacl_Poly1305_64_mk_state(uint64_t *r, uint64_t *acc)
+{
+    return Hacl_Impl_Poly1305_64_mk_state(r, acc);
+}
+
+void
+Hacl_Poly1305_64_init(Hacl_Impl_Poly1305_64_State_poly1305_state st, uint8_t *k1)
+{
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
+    uint64_t *r = scrut.r;
+    uint64_t *x0 = r;
+    FStar_UInt128_t k10 = load128_le(k1);
+    FStar_UInt128_t
+        k_clamped =
+            FStar_UInt128_logand(k10,
+                                 FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0ffffffcU),
+                                                                              (uint32_t)64U),
+                                                     FStar_UInt128_uint64_to_uint128((uint64_t)0x0ffffffc0fffffffU)));
+    uint64_t r0 = FStar_UInt128_uint128_to_uint64(k_clamped) & (uint64_t)0xfffffffffffU;
+    uint64_t
+        r1 =
+            FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)44U)) & (uint64_t)0xfffffffffffU;
+    uint64_t
+        r2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(k_clamped, (uint32_t)88U));
+    x0[0U] = r0;
+    x0[1U] = r1;
+    x0[2U] = r2;
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut0 = st;
+    uint64_t *h = scrut0.h;
+    uint64_t *x00 = h;
+    x00[0U] = (uint64_t)0U;
+    x00[1U] = (uint64_t)0U;
+    x00[2U] = (uint64_t)0U;
+}
+
+void
+Hacl_Poly1305_64_update_block(Hacl_Impl_Poly1305_64_State_poly1305_state st, uint8_t *m)
+{
+    Hacl_Impl_Poly1305_64_poly1305_update(st, m);
+}
+
+void
+Hacl_Poly1305_64_update(
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *m,
+    uint32_t num_blocks)
+{
+    if (!(num_blocks == (uint32_t)0U)) {
+        uint8_t *block = m;
+        uint8_t *m_ = m + (uint32_t)16U;
+        uint32_t n1 = num_blocks - (uint32_t)1U;
+        Hacl_Poly1305_64_update_block(st, block);
+        Hacl_Poly1305_64_update(st, m_, n1);
+    }
+}
+
+void
+Hacl_Poly1305_64_update_last(
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *m,
+    uint32_t len1)
+{
+    if (!((uint64_t)len1 == (uint64_t)0U))
+        Hacl_Impl_Poly1305_64_poly1305_process_last_block(st, m, (uint64_t)len1);
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
+    uint64_t *h = scrut.h;
+    uint64_t *acc = h;
+    Hacl_Impl_Poly1305_64_poly1305_last_pass(acc);
+}
+
+void
+Hacl_Poly1305_64_finish(
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *mac,
+    uint8_t *k1)
+{
+    Hacl_Impl_Poly1305_64_State_poly1305_state scrut = st;
+    uint64_t *h = scrut.h;
+    uint64_t *acc = h;
+    FStar_UInt128_t k_ = load128_le(k1);
+    uint64_t h0 = acc[0U];
+    uint64_t h1 = acc[1U];
+    uint64_t h2 = acc[2U];
+    FStar_UInt128_t
+        acc_ =
+            FStar_UInt128_logor(FStar_UInt128_shift_left(FStar_UInt128_uint64_to_uint128(h2
+                                                                                             << (uint32_t)24U |
+                                                                                         h1 >> (uint32_t)20U),
+                                                         (uint32_t)64U),
+                                FStar_UInt128_uint64_to_uint128(h1 << (uint32_t)44U | h0));
+    FStar_UInt128_t mac_ = FStar_UInt128_add_mod(acc_, k_);
+    store128_le(mac, mac_);
+}
+
+void
+Hacl_Poly1305_64_crypto_onetimeauth(
+    uint8_t *output,
+    uint8_t *input,
+    uint64_t len1,
+    uint8_t *k1)
+{
+    Hacl_Standalone_Poly1305_64_crypto_onetimeauth(output, input, len1, k1);
+}
new file mode 100644
--- /dev/null
+++ b/security/nss/lib/freebl/verified/Hacl_Poly1305_64.h
@@ -0,0 +1,99 @@
+/* Copyright 2016-2017 INRIA and Microsoft Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "kremlib.h"
+#ifndef __Hacl_Poly1305_64_H
+#define __Hacl_Poly1305_64_H
+
+typedef uint64_t Hacl_Bignum_Constants_limb;
+
+typedef FStar_UInt128_t Hacl_Bignum_Constants_wide;
+
+typedef FStar_UInt128_t Hacl_Bignum_Wide_t;
+
+typedef uint64_t Hacl_Bignum_Limb_t;
+
+typedef void *Hacl_Impl_Poly1305_64_State_log_t;
+
+typedef uint8_t *Hacl_Impl_Poly1305_64_State_uint8_p;
+
+typedef uint64_t *Hacl_Impl_Poly1305_64_State_bigint;
+
+typedef void *Hacl_Impl_Poly1305_64_State_seqelem;
+
+typedef uint64_t *Hacl_Impl_Poly1305_64_State_elemB;
+
+typedef uint8_t *Hacl_Impl_Poly1305_64_State_wordB;
+
+typedef uint8_t *Hacl_Impl_Poly1305_64_State_wordB_16;
+
+typedef struct
+{
+    uint64_t *r;
+    uint64_t *h;
+} Hacl_Impl_Poly1305_64_State_poly1305_state;
+
+typedef void *Hacl_Impl_Poly1305_64_log_t;
+
+typedef uint64_t *Hacl_Impl_Poly1305_64_bigint;
+
+typedef uint8_t *Hacl_Impl_Poly1305_64_uint8_p;
+
+typedef uint64_t *Hacl_Impl_Poly1305_64_elemB;
+
+typedef uint8_t *Hacl_Impl_Poly1305_64_wordB;
+
+typedef uint8_t *Hacl_Impl_Poly1305_64_wordB_16;
+
+typedef uint8_t *Hacl_Poly1305_64_uint8_p;
+
+typedef uint64_t Hacl_Poly1305_64_uint64_t;
+
+typedef uint8_t *Hacl_Poly1305_64_key;
+
+typedef Hacl_Impl_Poly1305_64_State_poly1305_state Hacl_Poly1305_64_state;
+
+Hacl_Impl_Poly1305_64_State_poly1305_state
+Hacl_Poly1305_64_mk_state(uint64_t *r, uint64_t *acc);
+
+void Hacl_Poly1305_64_init(Hacl_Impl_Poly1305_64_State_poly1305_state st, uint8_t *k1);
+
+void Hacl_Poly1305_64_update_block(Hacl_Impl_Poly1305_64_State_poly1305_state st, uint8_t *m);
+
+void
+Hacl_Poly1305_64_update(
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *m,
+    uint32_t num_blocks);
+
+void
+Hacl_Poly1305_64_update_last(
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *m,
+    uint32_t len1);
+
+void
+Hacl_Poly1305_64_finish(
+    Hacl_Impl_Poly1305_64_State_poly1305_state st,
+    uint8_t *mac,
+    uint8_t *k1);
+
+void
+Hacl_Poly1305_64_crypto_onetimeauth(
+    uint8_t *output,
+    uint8_t *input,
+    uint64_t len1,
+    uint8_t *k1);
+#endif
--- a/security/nss/lib/freebl/verified/kremlib.h
+++ b/security/nss/lib/freebl/verified/kremlib.h
@@ -202,29 +202,29 @@ typedef const char *Prims_string;
 #define le32toh(x) OSSwapLittleToHostInt32(x)
 #define htobe32(x) OSSwapHostToBigInt32(x)
 #define be32toh(x) OSSwapBigToHostInt32(x)
 
 /* ... for Solaris */
 #elif defined(__sun__)
 #include <sys/byteorder.h>
 #define htole64(x) LE_64(x)
-#define le64toh(x) LE_IN64(x)
+#define le64toh(x) LE_64(x)
 #define htobe64(x) BE_64(x)
-#define be64toh(x) BE_IN64(x)
+#define be64toh(x) BE_64(x)
 
 #define htole16(x) LE_16(x)
-#define le16toh(x) LE_IN16(x)
+#define le16toh(x) LE_16(x)
 #define htobe16(x) BE_16(x)
-#define be16toh(x) BE_IN16(x)
+#define be16toh(x) BE_16(x)
 
 #define htole32(x) LE_32(x)
-#define le32toh(x) LE_IN32(x)
+#define le32toh(x) LE_32(x)
 #define htobe32(x) BE_32(x)
-#define be32toh(x) BE_IN32(x)
+#define be32toh(x) BE_32(x)
 
 /* ... for the BSDs */
 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
 #include <sys/endian.h>
 #elif defined(__OpenBSD__)
 #include <endian.h>
 
 /* ... for Windows (MSVC)... not targeting XBOX 360! */
--- a/security/nss/lib/freebl/verified/specs/Spec.CTR.fst
+++ b/security/nss/lib/freebl/verified/specs/Spec.CTR.fst
@@ -1,8 +1,23 @@
+/* Copyright 2016-2017 INRIA and Microsoft Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 module Spec.CTR
 
 module ST = FStar.HyperStack.ST
 
 open FStar.Mul
 open FStar.Seq
 open Spec.Lib
 
--- a/security/nss/lib/freebl/verified/specs/Spec.Chacha20.fst
+++ b/security/nss/lib/freebl/verified/specs/Spec.Chacha20.fst
@@ -1,8 +1,23 @@
+/* Copyright 2016-2017 INRIA and Microsoft Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 module Spec.Chacha20
 
 module ST = FStar.HyperStack.ST
 
 open FStar.Mul
 open FStar.Seq
 open FStar.UInt32
 open FStar.Endianness
new file mode 100644
--- /dev/null
+++ b/security/nss/lib/freebl/verified/specs/Spec.Curve25519.fst
@@ -0,0 +1,168 @@
+/* Copyright 2016-2017 INRIA and Microsoft Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module Spec.Curve25519
+
+module ST = FStar.HyperStack.ST
+
+open FStar.Mul
+open FStar.Seq
+open FStar.UInt8
+open FStar.Endianness
+open Spec.Lib
+open Spec.Curve25519.Lemmas
+
+#reset-options "--initial_fuel 0 --max_fuel 0 --z3rlimit 20"
+
+(* Field types and parameters *)
+let prime = pow2 255 - 19
+type elem : Type0 = e:int{e >= 0 /\ e < prime}
+let fadd e1 e2 = (e1 + e2) % prime
+let fsub e1 e2 = (e1 - e2) % prime
+let fmul e1 e2 = (e1 * e2) % prime
+let zero : elem = 0
+let one  : elem = 1
+let ( +@ ) = fadd
+let ( *@ ) = fmul
+
+(** Exponentiation *)
+let rec ( ** ) (e:elem) (n:pos) : Tot elem (decreases n) =
+  if n = 1 then e
+  else
+    if n % 2 = 0 then op_Star_Star (e `fmul` e) (n / 2)
+    else e `fmul` (op_Star_Star (e `fmul` e) ((n-1)/2))
+
+(* Type aliases *)
+type scalar = lbytes 32
+type serialized_point = lbytes 32
+type proj_point = | Proj: x:elem -> z:elem -> proj_point
+
+let decodeScalar25519 (k:scalar) =
+  let k   = k.[0] <- (k.[0] &^ 248uy)          in
+  let k   = k.[31] <- ((k.[31] &^ 127uy) |^ 64uy) in k
+
+let decodePoint (u:serialized_point) =
+  (little_endian u % pow2 255) % prime
+
+let add_and_double qx nq nqp1 =
+  let x_1 = qx in
+  let x_2, z_2 = nq.x, nq.z in
+  let x_3, z_3 = nqp1.x, nqp1.z in
+  let a  = x_2 `fadd` z_2 in
+  let aa = a**2 in
+  let b  = x_2 `fsub` z_2 in
+  let bb = b**2 in
+  let e = aa `fsub` bb in
+  let c = x_3 `fadd` z_3 in
+  let d = x_3 `fsub` z_3 in
+  let da = d `fmul` a in
+  let cb = c `fmul` b in
+  let x_3 = (da `fadd` cb)**2 in
+  let z_3 = x_1 `fmul` ((da `fsub` cb)**2) in
+  let x_2 = aa `fmul` bb in
+  let z_2 = e `fmul` (aa `fadd` (121665 `fmul` e)) in
+  Proj x_2 z_2, Proj x_3 z_3
+
+let ith_bit (k:scalar) (i:nat{i < 256}) =
+  let q = i / 8 in let r = i % 8 in
+  (v (k.[q]) / pow2 r) % 2
+
+let rec montgomery_ladder_ (init:elem) x xp1 (k:scalar) (ctr:nat{ctr<=256})
+  : Tot proj_point (decreases ctr) =
+  if ctr = 0 then x
+  else (
+    let ctr' = ctr - 1 in
+    let (x', xp1') =
+      if ith_bit k ctr' = 1 then (
+        let nqp2, nqp1 = add_and_double init xp1 x in
+        nqp1, nqp2
+      ) else add_and_double init x xp1 in
+    montgomery_ladder_ init x' xp1' k ctr'
+  )
+
+let montgomery_ladder (init:elem) (k:scalar) : Tot proj_point =
+  montgomery_ladder_ init (Proj one zero) (Proj init one) k 256
+
+let encodePoint (p:proj_point) : Tot serialized_point =
+  let p = p.x `fmul` (p.z ** (prime - 2)) in
+  little_bytes 32ul p
+
+let scalarmult (k:scalar) (u:serialized_point) : Tot serialized_point =
+  let k = decodeScalar25519 k in
+  let u = decodePoint u in
+  let res = montgomery_ladder u k in
+  encodePoint res
+
+
+(* ********************* *)
+(* RFC 7748 Test Vectors *)
+(* ********************* *)
+
+let scalar1 = [
+  0xa5uy; 0x46uy; 0xe3uy; 0x6buy; 0xf0uy; 0x52uy; 0x7cuy; 0x9duy;
+  0x3buy; 0x16uy; 0x15uy; 0x4buy; 0x82uy; 0x46uy; 0x5euy; 0xdduy;
+  0x62uy; 0x14uy; 0x4cuy; 0x0auy; 0xc1uy; 0xfcuy; 0x5auy; 0x18uy;
+  0x50uy; 0x6auy; 0x22uy; 0x44uy; 0xbauy; 0x44uy; 0x9auy; 0xc4uy
+]
+
+let scalar2 = [
+  0x4buy; 0x66uy; 0xe9uy; 0xd4uy; 0xd1uy; 0xb4uy; 0x67uy; 0x3cuy;
+  0x5auy; 0xd2uy; 0x26uy; 0x91uy; 0x95uy; 0x7duy; 0x6auy; 0xf5uy;
+  0xc1uy; 0x1buy; 0x64uy; 0x21uy; 0xe0uy; 0xeauy; 0x01uy; 0xd4uy;
+  0x2cuy; 0xa4uy; 0x16uy; 0x9euy; 0x79uy; 0x18uy; 0xbauy; 0x0duy
+]
+
+let input1 = [
+  0xe6uy; 0xdbuy; 0x68uy; 0x67uy; 0x58uy; 0x30uy; 0x30uy; 0xdbuy;
+  0x35uy; 0x94uy; 0xc1uy; 0xa4uy; 0x24uy; 0xb1uy; 0x5fuy; 0x7cuy;
+  0x72uy; 0x66uy; 0x24uy; 0xecuy; 0x26uy; 0xb3uy; 0x35uy; 0x3buy;
+  0x10uy; 0xa9uy; 0x03uy; 0xa6uy; 0xd0uy; 0xabuy; 0x1cuy; 0x4cuy
+]
+
+let input2 = [
+  0xe5uy; 0x21uy; 0x0fuy; 0x12uy; 0x78uy; 0x68uy; 0x11uy; 0xd3uy;
+  0xf4uy; 0xb7uy; 0x95uy; 0x9duy; 0x05uy; 0x38uy; 0xaeuy; 0x2cuy;
+  0x31uy; 0xdbuy; 0xe7uy; 0x10uy; 0x6fuy; 0xc0uy; 0x3cuy; 0x3euy;
+  0xfcuy; 0x4cuy; 0xd5uy; 0x49uy; 0xc7uy; 0x15uy; 0xa4uy; 0x93uy
+]
+
+let expected1 = [
+  0xc3uy; 0xdauy; 0x55uy; 0x37uy; 0x9duy; 0xe9uy; 0xc6uy; 0x90uy;
+  0x8euy; 0x94uy; 0xeauy; 0x4duy; 0xf2uy; 0x8duy; 0x08uy; 0x4fuy;
+  0x32uy; 0xecuy; 0xcfuy; 0x03uy; 0x49uy; 0x1cuy; 0x71uy; 0xf7uy;
+  0x54uy; 0xb4uy; 0x07uy; 0x55uy; 0x77uy; 0xa2uy; 0x85uy; 0x52uy
+]
+let expected2 = [
+  0x95uy; 0xcbuy; 0xdeuy; 0x94uy; 0x76uy; 0xe8uy; 0x90uy; 0x7duy;
+  0x7auy; 0xaduy; 0xe4uy; 0x5cuy; 0xb4uy; 0xb8uy; 0x73uy; 0xf8uy;
+  0x8buy; 0x59uy; 0x5auy; 0x68uy; 0x79uy; 0x9fuy; 0xa1uy; 0x52uy;
+  0xe6uy; 0xf8uy; 0xf7uy; 0x64uy; 0x7auy; 0xacuy; 0x79uy; 0x57uy
+]
+
+let test () =
+  assert_norm(List.Tot.length scalar1 = 32);
+  assert_norm(List.Tot.length scalar2 = 32);
+  assert_norm(List.Tot.length input1 = 32);
+  assert_norm(List.Tot.length input2 = 32);
+  assert_norm(List.Tot.length expected1 = 32);
+  assert_norm(List.Tot.length expected2 = 32);
+  let scalar1 = createL scalar1 in
+  let scalar2 = createL scalar2 in
+  let input1 = createL input1 in
+  let input2 = createL input2 in
+  let expected1 = createL expected1 in
+  let expected2 = createL expected2 in
+  scalarmult scalar1 input1 = expected1
+  && scalarmult scalar2 input2 = expected2
new file mode 100644
--- /dev/null
+++ b/security/nss/lib/freebl/verified/specs/Spec.Poly1305.fst
@@ -0,0 +1,107 @@
+/* Copyright 2016-2017 INRIA and Microsoft Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module Spec.Poly1305
+
+module ST = FStar.HyperStack.ST
+
+open FStar.Math.Lib
+open FStar.Mul
+open FStar.Seq
+open FStar.UInt8
+open FStar.Endianness
+open Spec.Poly1305.Lemmas
+
+#set-options "--initial_fuel 0 --max_fuel 0 --initial_ifuel 0 --max_ifuel 0"
+
+(* Field types and parameters *)
+let prime = pow2 130 - 5
+type elem = e:int{e >= 0 /\ e < prime}
+let fadd (e1:elem) (e2:elem) = (e1 + e2) % prime
+let fmul (e1:elem) (e2:elem) = (e1 * e2) % prime
+let zero : elem = 0
+let one  : elem = 1
+let op_Plus_At = fadd
+let op_Star_At = fmul
+(* Type aliases *)
+let op_Amp_Bar = UInt.logand #128
+type word = w:bytes{length w <= 16}
+type word_16 = w:bytes{length w = 16}
+type tag = word_16
+type key = lbytes 32
+type text = seq word
+
+(* Specification code *)
+let encode (w:word) =
+  (pow2 (8 * length w)) `fadd` (little_endian w)
+
+let rec poly (txt:text) (r:e:elem) : Tot elem (decreases (length txt)) =
+  if length txt = 0 then zero
+  else
+    let a = poly (Seq.tail txt) r in
+    let n = encode (Seq.head txt) in
+    (n `fadd` a) `fmul` r
+
+let encode_r (rb:word_16) =
+  (little_endian rb) &| 0x0ffffffc0ffffffc0ffffffc0fffffff
+
+let finish (a:elem) (s:word_16) : Tot tag =
+  let n = (a + little_endian s) % pow2 128 in
+  little_bytes 16ul n
+
+let rec encode_bytes (txt:bytes) : Tot text (decreases (length txt)) =
+  if length txt = 0 then createEmpty
+  else
+    let w, txt = split txt (min (length txt) 16) in
+    append_last (encode_bytes txt) w
+
+let poly1305 (msg:bytes) (k:key) : Tot tag =
+  let text = encode_bytes msg in
+  let r = encode_r (slice k 0 16) in
+  let s = slice k 16 32 in
+  finish (poly text r) s
+
+
+(* ********************* *)
+(* RFC 7539 Test Vectors *)
+(* ********************* *)
+
+#reset-options "--initial_fuel 0 --max_fuel 0 --z3rlimit 20"
+
+unfold let msg = [
+  0x43uy; 0x72uy; 0x79uy; 0x70uy; 0x74uy; 0x6fuy; 0x67uy; 0x72uy;
+  0x61uy; 0x70uy; 0x68uy; 0x69uy; 0x63uy; 0x20uy; 0x46uy; 0x6fuy;
+  0x72uy; 0x75uy; 0x6duy; 0x20uy; 0x52uy; 0x65uy; 0x73uy; 0x65uy;
+  0x61uy; 0x72uy; 0x63uy; 0x68uy; 0x20uy; 0x47uy; 0x72uy; 0x6fuy;
+  0x75uy; 0x70uy ]
+
+unfold let k = [
+  0x85uy; 0xd6uy; 0xbeuy; 0x78uy; 0x57uy; 0x55uy; 0x6duy; 0x33uy;
+  0x7fuy; 0x44uy; 0x52uy; 0xfeuy; 0x42uy; 0xd5uy; 0x06uy; 0xa8uy;
+  0x01uy; 0x03uy; 0x80uy; 0x8auy; 0xfbuy; 0x0duy; 0xb2uy; 0xfduy;
+  0x4auy; 0xbfuy; 0xf6uy; 0xafuy; 0x41uy; 0x49uy; 0xf5uy; 0x1buy ]
+
+unfold let expected = [
+  0xa8uy; 0x06uy; 0x1duy; 0xc1uy; 0x30uy; 0x51uy; 0x36uy; 0xc6uy;
+  0xc2uy; 0x2buy; 0x8buy; 0xafuy; 0x0cuy; 0x01uy; 0x27uy; 0xa9uy ]
+
+let test () : Tot bool =
+  assert_norm(List.Tot.length msg      = 34);
+  assert_norm(List.Tot.length k        = 32);
+  assert_norm(List.Tot.length expected = 16);
+  let msg      = createL msg in
+  let k        = createL k   in
+  let expected = createL expected in
+  poly1305 msg k = expected
--- a/security/nss/lib/softoken/legacydb/lgattr.c
+++ b/security/nss/lib/softoken/legacydb/lgattr.c
@@ -128,17 +128,17 @@ lg_CopyAttribute(CK_ATTRIBUTE *attr, CK_
     if (attr->pValue == NULL) {
         attr->ulValueLen = len;
         return CKR_OK;
     }
     if (attr->ulValueLen < len) {
         attr->ulValueLen = (CK_ULONG)-1;
         return CKR_BUFFER_TOO_SMALL;
     }
-    if (value != NULL) {
+    if (len > 0 && value != NULL) {
         PORT_Memcpy(attr->pValue, value, len);
     }
     attr->ulValueLen = len;
     return CKR_OK;
 }
 
 static CK_RV
 lg_CopyAttributeSigned(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type,
--- a/security/nss/lib/softoken/legacydb/pcertdb.c
+++ b/security/nss/lib/softoken/legacydb/pcertdb.c
@@ -1849,30 +1849,34 @@ DecodeDBSMimeEntry(certDBEntrySMime *ent
         if (entry->smimeOptions.data == NULL) {
             PORT_SetError(SEC_ERROR_NO_MEMORY);
             goto loser;
         }
         PORT_Memcpy(entry->smimeOptions.data,
                     &dbentry->data[DB_SMIME_ENTRY_HEADER_LEN +
                                    entry->subjectName.len],
                     entry->smimeOptions.len);
+    } else {
+        entry->smimeOptions.data = NULL;
     }
     if (entry->optionsDate.len) {
         entry->optionsDate.data =
             (unsigned char *)PORT_ArenaAlloc(entry->common.arena,
                                              entry->optionsDate.len);
         if (entry->optionsDate.data == NULL) {
             PORT_SetError(SEC_ERROR_NO_MEMORY);
             goto loser;
         }
         PORT_Memcpy(entry->optionsDate.data,
                     &dbentry->data[DB_SMIME_ENTRY_HEADER_LEN +
                                    entry->subjectName.len +
                                    entry->smimeOptions.len],
                     entry->optionsDate.len);
+    } else {
+        entry->optionsDate.data = NULL;
     }
 
     /* both options and options date must either exist or not exist */
     if (((entry->optionsDate.len == 0) ||
          (entry->smimeOptions.len == 0)) &&
         entry->smimeOptions.len != entry->optionsDate.len) {
         PORT_SetError(SEC_ERROR_BAD_DATABASE);
         goto loser;
@@ -2009,35 +2013,35 @@ loser:
 /*
  * Read a SMIME entry
  */
 certDBEntrySMime *
 nsslowcert_ReadDBSMimeEntry(NSSLOWCERTCertDBHandle *handle, char *emailAddr)
 {
     PLArenaPool *arena = NULL;
     PLArenaPool *tmparena = NULL;
-    certDBEntrySMime *entry;
+    certDBEntrySMime *entry = NULL;
     SECItem dbkey;
     SECItem dbentry;
     SECStatus rv;
 
     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     if (arena == NULL) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         goto loser;
     }
 
     tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     if (tmparena == NULL) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         goto loser;
     }
 
-    entry = (certDBEntrySMime *)PORT_ArenaAlloc(arena,
-                                                sizeof(certDBEntrySMime));
+    entry = (certDBEntrySMime *)PORT_ArenaZAlloc(arena,
+                                                 sizeof(certDBEntrySMime));
     if (entry == NULL) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         goto loser;
     }
     entry->common.arena = arena;
     entry->common.type = certDBEntryTypeSMimeProfile;
 
     rv = EncodeDBSMimeKey(emailAddr, tmparena, &dbkey);
--- a/security/nss/lib/ssl/SSLerrs.h
+++ b/security/nss/lib/ssl/SSLerrs.h
@@ -526,8 +526,17 @@ ER3(SSL_ERROR_APPLICATION_ABORT, (SSL_ER
 ER3(SSL_ERROR_APP_CALLBACK_ERROR, (SSL_ERROR_BASE + 166),
     "An application callback produced an invalid response.")
 
 ER3(SSL_ERROR_NO_TIMERS_ERROR, (SSL_ERROR_BASE + 167),
     "No timers are currently running.")
 
 ER3(SSL_ERROR_MISSING_COOKIE_EXTENSION, (SSL_ERROR_BASE + 168),
     "A second ClientHello was received without a cookie extension.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_KEY_UPDATE, (SSL_ERROR_BASE + 169),
+    "SSL received an unexpected key update message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_KEY_UPDATE, (SSL_ERROR_BASE + 170),
+    "SSL received a malformed key update message.")
+
+ER3(SSL_ERROR_TOO_MANY_KEY_UPDATES, (SSL_ERROR_BASE + 171),
+    "SSL attempted too many key updates.")
--- a/security/nss/lib/ssl/dtls13con.c
+++ b/security/nss/lib/ssl/dtls13con.c
@@ -73,17 +73,17 @@ dtls13_RememberFragment(sslSocket *ss,
     PR_APPEND_LINK(&entry->link, list);
 
     return SECSuccess;
 }
 
 SECStatus
 dtls13_SendAck(sslSocket *ss)
 {
-    sslBuffer buf = { NULL, 0, 0 };
+    sslBuffer buf = SSL_BUFFER_EMPTY;
     SECStatus rv = SECSuccess;
     PRCList *cursor;
     PRInt32 sent;
 
     SSL_TRC(10, ("%d: SSL3[%d]: Sending ACK",
                  SSL_GETPID(), ss->fd));
 
     for (cursor = PR_LIST_HEAD(&ss->ssl3.hs.dtlsRcvdHandshake);
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -2200,16 +2200,18 @@ ssl_ProtectRecord(sslSocket *ss, ssl3Cip
                                          SSL_BUFFER_SPACE(wrBuf) - headerLen);
     PRBool isTLS13;
     SECStatus rv;
 
     PORT_Assert(cwSpec->direction == CipherSpecWrite);
     PORT_Assert(SSL_BUFFER_LEN(wrBuf) == 0);
     PORT_Assert(cwSpec->cipherDef->max_records <= RECORD_SEQ_MAX);
     if (cwSpec->seqNum >= cwSpec->cipherDef->max_records) {
+        /* We should have automatically updated before here in TLS 1.3. */
+        PORT_Assert(cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_3);
         SSL_TRC(3, ("%d: SSL[-]: write sequence number at limit 0x%0llx",
                     SSL_GETPID(), cwSpec->seqNum));
         PORT_SetError(SSL_ERROR_TOO_MANY_RECORDS);
         return SECFailure;
     }
 
     isTLS13 = (PRBool)(cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_3);
 
@@ -8607,17 +8609,17 @@ loser:
     return SECFailure;
 }
 
 /*
  * ssl3_HandleV2ClientHello is used when a V2 formatted hello comes
  * in asking to use the V3 handshake.
  */
 SECStatus
-ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length,
+ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, unsigned int length,
                          PRUint8 padding)
 {
     sslSessionID *sid = NULL;
     unsigned char *suites;
     unsigned char *random;
     SSL3ProtocolVersion version;
     SECStatus rv;
     unsigned int i;
deleted file mode 100644
--- a/security/nss/lib/ssl/ssl3encode.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is PRIVATE to SSL.
- *
- * 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 "prnetdb.h"
-#include "seccomon.h"
-#include "secerr.h"
-#include "ssl3encode.h"
-
-SECStatus
-ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes)
-{
-    if (bytes > item->len) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
-    PORT_Memcpy(item->data, buf, bytes);
-    item->data += bytes;
-    item->len -= bytes;
-    return SECSuccess;
-}
-
-SECStatus
-ssl3_AppendNumberToItem(SECItem *item, PRUint64 num, PRInt32 lenSize)
-{
-    SECStatus rv;
-    PRUint8 b[sizeof(num)];
-
-    ssl_EncodeUintX(num, lenSize, b);
-    rv = ssl3_AppendToItem(item, &b[0], lenSize);
-    return rv;
-}
-
-SECStatus
-ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes)
-{
-    if (bytes > item->len) {
-        PORT_SetError(SEC_ERROR_BAD_DATA);
-        return SECFailure;
-    }
-
-    *buf = item->data;
-    item->data += bytes;
-    item->len -= bytes;
-    return SECSuccess;
-}
-
-SECStatus
-ssl3_ConsumeNumberFromItem(SECItem *item, PRUint32 *num, PRUint32 bytes)
-{
-    unsigned int i;
-
-    if (bytes > item->len || bytes > sizeof(*num)) {
-        PORT_SetError(SEC_ERROR_BAD_DATA);
-        return SECFailure;
-    }
-
-    *num = 0;
-    for (i = 0; i < bytes; i++) {
-        *num = (*num << 8) + item->data[i];
-    }
-
-    item->data += bytes;
-    item->len -= bytes;
-
-    return SECSuccess;
-}
-
-/* Helper function to encode an unsigned integer into a buffer. */
-PRUint8 *
-ssl_EncodeUintX(PRUint64 value, unsigned int bytes, PRUint8 *to)
-{
-    PRUint64 encoded;
-
-    PORT_Assert(bytes > 0 && bytes <= sizeof(encoded));
-
-    encoded = PR_htonll(value);
-    memcpy(to, ((unsigned char *)(&encoded)) + (sizeof(encoded) - bytes), bytes);
-    return to + bytes;
-}
deleted file mode 100644
--- a/security/nss/lib/ssl/ssl3encode.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is PRIVATE to SSL.
- *
- * 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/. */
-
-#ifndef __ssl3encode_h_
-#define __ssl3encode_h_
-
-#include "seccomon.h"
-
-/* All of these functions modify the underlying SECItem, and so should
- * be performed on a shallow copy.*/
-SECStatus ssl3_AppendToItem(SECItem *item,
-                            const unsigned char *buf, PRUint32 bytes);
-SECStatus ssl3_AppendNumberToItem(SECItem *item,
-                                  PRUint64 num, PRInt32 lenSize);
-SECStatus ssl3_ConsumeFromItem(SECItem *item,
-                               unsigned char **buf, PRUint32 bytes);
-SECStatus ssl3_ConsumeNumberFromItem(SECItem *item,
-                                     PRUint32 *num, PRUint32 bytes);
-PRUint8 *ssl_EncodeUintX(PRUint64 value, unsigned int bytes, PRUint8 *to);
-
-#endif
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -614,17 +614,17 @@ ssl3_RegisterExtensionSender(const sslSo
     PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
     return SECFailure;
 }
 
 static SECStatus
 ssl_CallCustomExtensionSenders(sslSocket *ss, sslBuffer *buf,
                                SSLHandshakeType message)
 {
-    sslBuffer tail = { NULL, 0, 0 };
+    sslBuffer tail = SSL_BUFFER_EMPTY;
     SECStatus rv;
     PRCList *cursor;
 
     /* Save any extensions that want to be last. */
     if (ss->xtnData.lastXtnOffset) {
         rv = sslBuffer_Append(&tail, buf->buf + ss->xtnData.lastXtnOffset,
                               buf->len - ss->xtnData.lastXtnOffset);
         if (rv != SECSuccess) {
--- a/security/nss/lib/ssl/ssl3exthandle.c
+++ b/security/nss/lib/ssl/ssl3exthandle.c
@@ -660,17 +660,17 @@ PRUint32 ssl_ticket_lifetime = 2 * 24 * 
  * Called from ssl3_SendNewSessionTicket, tls13_SendNewSessionTicket
  */
 SECStatus
 ssl3_EncodeSessionTicket(sslSocket *ss, const NewSessionTicket *ticket,
                          const PRUint8 *appToken, unsigned int appTokenLen,
                          PK11SymKey *secret, SECItem *ticket_data)
 {
     SECStatus rv;
-    sslBuffer plaintext = { NULL, 0, 0 };
+    sslBuffer plaintext = SSL_BUFFER_EMPTY;
     SECItem ticket_buf = { 0, NULL, 0 };
     sslSessionID sid;
     unsigned char wrapped_ms[SSL3_MASTER_SECRET_LENGTH];
     SECItem ms_item = { 0, NULL, 0 };
     PRTime now;
     SECItem *srvName = NULL;
     CK_MECHANISM_TYPE msWrapMech;
     SECItem *alpnSelection = NULL;
--- a/security/nss/lib/ssl/sslerr.h
+++ b/security/nss/lib/ssl/sslerr.h
@@ -252,15 +252,18 @@ typedef enum {
 
     SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API = (SSL_ERROR_BASE + 164),
 
     SSL_ERROR_APPLICATION_ABORT = (SSL_ERROR_BASE + 165),
     SSL_ERROR_APP_CALLBACK_ERROR = (SSL_ERROR_BASE + 166),
     SSL_ERROR_NO_TIMERS_FOUND = (SSL_ERROR_BASE + 167),
     SSL_ERROR_MISSING_COOKIE_EXTENSION = (SSL_ERROR_BASE + 168),
 
+    SSL_ERROR_RX_UNEXPECTED_KEY_UPDATE = (SSL_ERROR_BASE + 169),
+    SSL_ERROR_RX_MALFORMED_KEY_UPDATE = (SSL_ERROR_BASE + 170),
+    SSL_ERROR_TOO_MANY_KEY_UPDATES = (SSL_ERROR_BASE + 171),
     SSL_ERROR_END_OF_LIST   /* let the c compiler determine the value of this. */
 } SSLErrorCodes;
 #endif /* NO_SECURITY_ERROR_ENUM */
 
 /* clang-format on */
 
 #endif /* __SSL_ERR_H_ */
--- a/security/nss/lib/ssl/sslexp.h
+++ b/security/nss/lib/ssl/sslexp.h
@@ -335,14 +335,24 @@ typedef SSLHelloRetryRequestAction(PR_CA
     void *arg);
 
 #define SSL_HelloRetryRequestCallback(fd, cb, arg)                       \
     SSL_EXPERIMENTAL_API("SSL_HelloRetryRequestCallback",                \
                          (PRFileDesc * _fd,                              \
                           SSLHelloRetryRequestCallback _cb, void *_arg), \
                          (fd, cb, arg))
 
+/* Update traffic keys (TLS 1.3 only).
+ *
+ * The |requestUpdate| flag determines whether to request an update from the
+ * remote peer.
+ */
+#define SSL_KeyUpdate(fd, requestUpdate)                            \
+    SSL_EXPERIMENTAL_API("SSL_KeyUpdate",                           \
+                         (PRFileDesc * _fd, PRBool _requestUpdate), \
+                         (fd, requestUpdate))
+
 #define SSL_UseAltServerHelloType(fd, enable) \
     SSL_DEPRECATED_EXPERIMENTAL_API
 
 SEC_END_PROTOS
 
 #endif /* __sslexp_h_ */
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -721,16 +721,20 @@ struct ssl3StateStr {
     ** The following Specs and Spec pointers must be protected using the
     ** Spec Lock.
     */
     ssl3CipherSpec *crSpec; /* current read spec. */
     ssl3CipherSpec *prSpec; /* pending read spec. */
     ssl3CipherSpec *cwSpec; /* current write spec. */
     ssl3CipherSpec *pwSpec; /* pending write spec. */
 
+    /* This is true after the peer requests a key update; false after a key
+     * update is initiated locally. */
+    PRBool peerRequestedKeyUpdate;
+
     /* Internal callback for when we do a cipher suite change. Used for
      * debugging in TLS 1.3. This can only be set by non-public functions. */
     sslCipherSpecChangedFunc changedCipherSpecFunc;
     void *changedCipherSpecArg;
 
     CERTCertificate *clientCertificate;   /* used by client */
     SECKEYPrivateKey *clientPrivateKey;   /* used by client */
     CERTCertificateList *clientCertChain; /* used by client */
@@ -1368,17 +1372,17 @@ extern SECStatus SSL3_SendAlert(sslSocke
 extern SECStatus ssl3_DecodeError(sslSocket *ss);
 
 extern SECStatus ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error);
 
 /*
  * for dealing with SSL 3.0 clients sending SSL 2.0 format hellos
  */
 extern SECStatus ssl3_HandleV2ClientHello(
-    sslSocket *ss, unsigned char *buffer, int length, PRUint8 padding);
+    sslSocket *ss, unsigned char *buffer, unsigned int length, PRUint8 padding);
 
 SECStatus ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type);
 
 /*
  * input into the SSL3 machinery from the actualy network reading code
  */
 SECStatus ssl3_HandleRecord(
     sslSocket *ss, SSL3Ciphertext *cipher, sslBuffer *out);
--- a/security/nss/lib/ssl/sslsecur.c
+++ b/security/nss/lib/ssl/sslsecur.c
@@ -757,16 +757,65 @@ ssl_SecureShutdown(sslSocket *ss, int ns
 
     ss->shutdownHow |= sslHow;
 
     return rv;
 }
 
 /************************************************************************/
 
+static SECStatus
+tls13_CheckKeyUpdate(sslSocket *ss, CipherSpecDirection dir)
+{
+    PRBool keyUpdate;
+    ssl3CipherSpec *spec;
+    sslSequenceNumber seqNum;
+    sslSequenceNumber margin;
+    SECStatus rv;
+
+    /* Bug 1413368: enable for DTLS */
+    if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 || IS_DTLS(ss)) {
+        return SECSuccess;
+    }
+
+    /* If both sides update at the same number, then this will cause two updates
+     * to happen at once. The problem is that the KeyUpdate itself consumes a
+     * sequence number, and that will trigger the reading side to request an
+     * update.
+     *
+     * If we have the writing side update first, the writer will be the one that
+     * drives the update.  An update by the writer doesn't need a response, so
+     * it is more efficient overall.  The margins here are pretty arbitrary, but
+     * having the write margin larger reduces the number of times that a
+     * KeyUpdate is sent by a reader. */
+    ssl_GetSpecReadLock(ss);
+    if (dir == CipherSpecRead) {
+        spec = ss->ssl3.crSpec;
+        margin = spec->cipherDef->max_records / 8;
+    } else {
+        spec = ss->ssl3.cwSpec;
+        margin = spec->cipherDef->max_records / 4;
+    }
+    seqNum = spec->seqNum;
+    keyUpdate = seqNum > spec->cipherDef->max_records - margin;
+    ssl_ReleaseSpecReadLock(ss);
+    if (!keyUpdate) {
+        return SECSuccess;
+    }
+
+    SSL_TRC(5, ("%d: SSL[%d]: automatic key update at %llx for %s cipher spec",
+                SSL_GETPID(), ss->fd, seqNum,
+                (dir == CipherSpecRead) ? "read" : "write"));
+    ssl_GetSSL3HandshakeLock(ss);
+    rv = tls13_SendKeyUpdate(ss, (dir == CipherSpecRead) ? update_requested : update_not_requested,
+                             dir == CipherSpecWrite /* buffer */);
+    ssl_ReleaseSSL3HandshakeLock(ss);
+    return rv;
+}
+
 int
 ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
 {
     int rv = 0;
 
     if (ss->shutdownHow & ssl_SHUTDOWN_RCV) {
         PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
         return PR_FAILURE;
@@ -796,18 +845,27 @@ ssl_SecureRecv(sslSocket *ss, unsigned c
 
     /* If any of these is non-zero, the initial handshake is not done. */
     if (!ss->firstHsDone) {
         ssl_Get1stHandshakeLock(ss);
         if (ss->handshake) {
             rv = ssl_Do1stHandshake(ss);
         }
         ssl_Release1stHandshakeLock(ss);
+    } else {
+        if (tls13_CheckKeyUpdate(ss, CipherSpecRead) != SECSuccess) {
+            rv = PR_FAILURE;
+        }
     }
     if (rv < 0) {
+        if (PORT_GetError() == PR_WOULD_BLOCK_ERROR &&
+            !PR_CLIST_IS_EMPTY(&ss->ssl3.hs.bufferedEarlyData)) {
+            PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+            return tls13_Read0RttData(ss, buf, len);
+        }
         return rv;
     }
 
     if (len == 0)
         return 0;
 
     rv = DoRecv(ss, (unsigned char *)buf, len, flags);
     SSL_TRC(2, ("%d: SSL[%d]: recving %d bytes securely (errno=%d)",
@@ -879,21 +937,29 @@ ssl_SecureSend(sslSocket *ss, const unsi
             allowEarlySend = ss->ssl3.hs.canFalseStart || zeroRtt;
             ssl_ReleaseSSL3HandshakeLock(ss);
         }
         if (!allowEarlySend && ss->handshake) {
             rv = ssl_Do1stHandshake(ss);
         }
         ssl_Release1stHandshakeLock(ss);
     }
+
     if (rv < 0) {
         ss->writerThread = NULL;
         goto done;
     }
 
+    if (ss->firstHsDone) {
+        if (tls13_CheckKeyUpdate(ss, CipherSpecWrite) != SECSuccess) {
+            rv = PR_FAILURE;
+            goto done;
+        }
+    }
+
     if (zeroRtt) {
         /* There's a limit to the number of early data octets we can send.
          *
          * Note that taking this lock doesn't prevent the cipher specs from
          * being changed out between here and when records are ultimately
          * encrypted.  The only effect of that is to occasionally do an
          * unnecessary short write when data is identified as 0-RTT here but
          * 1-RTT later.
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -102,17 +102,16 @@ static SSLVersionRange versions_defaults
     (variant == ssl_variant_stream ? NSS_TLS_VERSION_MIN_POLICY : NSS_DTLS_VERSION_MIN_POLICY)
 #define VERSIONS_POLICY_MAX(variant) \
     (variant == ssl_variant_stream ? NSS_TLS_VERSION_MAX_POLICY : NSS_DTLS_VERSION_MAX_POLICY)
 
 sslSessionIDLookupFunc ssl_sid_lookup;
 sslSessionIDCacheFunc ssl_sid_cache;
 sslSessionIDUncacheFunc ssl_sid_uncache;
 
-static PRBool ssl_inited = PR_FALSE;
 static PRDescIdentity ssl_layer_id;
 
 PRBool locksEverDisabled; /* implicitly PR_FALSE */
 PRBool ssl_force_locks;   /* implicitly PR_FALSE */
 int ssl_lock_readers = 1; /* default true. */
 char ssl_debug;
 char ssl_trace;
 FILE *ssl_trace_iob;
@@ -3457,35 +3456,32 @@ ssl_SetupIOMethods(void)
 
 static PRCallOnceType initIoLayerOnce;
 
 static PRStatus
 ssl_InitIOLayer(void)
 {
     ssl_layer_id = PR_GetUniqueIdentity("SSL");
     ssl_SetupIOMethods();
-    ssl_inited = PR_TRUE;
     return PR_SUCCESS;
 }
 
 static PRStatus
 ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack, PRDescIdentity id)
 {
     PRFileDesc *layer = NULL;
     PRStatus status;
 
-    if (!ssl_inited) {
-        status = PR_CallOnce(&initIoLayerOnce, &ssl_InitIOLayer);
-        if (status != PR_SUCCESS)
-            goto loser;
+    status = PR_CallOnce(&initIoLayerOnce, &ssl_InitIOLayer);
+    if (status != PR_SUCCESS) {
+        goto loser;
     }
-
-    if (ns == NULL)
+    if (ns == NULL) {
         goto loser;
-
+    }
     layer = PR_CreateIOLayerStub(ssl_layer_id, &combined_methods);
     if (layer == NULL)
         goto loser;
     layer->secret = (PRFilePrivate *)ns;
 
     /* Here, "stack" points to the PRFileDesc on the top of the stack.
     ** "layer" points to a new FD that is to be inserted into the stack.
     ** If layer is being pushed onto the top of the stack, then
@@ -3929,16 +3925,17 @@ SSL_CanBypass(CERTCertificate *cert, SEC
 struct {
     const char *const name;
     void *function;
 } ssl_experimental_functions[] = {
 #ifndef SSL_DISABLE_EXPERIMENTAL_API
     EXP(GetExtensionSupport),
     EXP(HelloRetryRequestCallback),
     EXP(InstallExtensionHooks),
+    EXP(KeyUpdate),
     EXP(SendSessionTicket),
     EXP(SetupAntiReplay),
 #endif
     { "", NULL }
 };
 #undef EXP
 #undef PUB
 
--- a/security/nss/lib/ssl/sslspec.c
+++ b/security/nss/lib/ssl/sslspec.c
@@ -247,17 +247,18 @@ ssl_CipherSpecRelease(ssl3CipherSpec *sp
         ssl_FreeCipherSpec(spec);
     }
 }
 
 void
 ssl_DestroyCipherSpecs(PRCList *list)
 {
     while (!PR_CLIST_IS_EMPTY(list)) {
-        ssl_FreeCipherSpec((ssl3CipherSpec *)PR_LIST_TAIL(list));
+        ssl3CipherSpec *spec = (ssl3CipherSpec *)PR_LIST_TAIL(list);
+        ssl_FreeCipherSpec(spec);
     }
 }
 
 void
 ssl_CipherSpecReleaseByEpoch(sslSocket *ss, CipherSpecDirection dir,
                              DTLSEpoch epoch)
 {
     ssl3CipherSpec *spec;
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -19,17 +19,17 @@
 #include "sslerr.h"
 #include "ssl3exthandle.h"
 #include "tls13hkdf.h"
 #include "tls13con.h"
 #include "tls13err.h"
 #include "tls13exthandle.h"
 #include "tls13hashstate.h"
 
-static SECStatus tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type,
+static SECStatus tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch,
                                      CipherSpecDirection install,
                                      PRBool deleteSecret);
 static SECStatus tls13_AESGCM(
     ssl3KeyMaterial *keys,
     PRBool doDecrypt,
     unsigned char *out, int *outlen, int maxout,
     const unsigned char *in, int inlen,
     const unsigned char *additionalData, int additionalDataLen);
@@ -120,23 +120,19 @@ const char kHkdfLabelResumption[] = "res
 const char kHkdfPurposeKey[] = "key";
 const char kHkdfPurposeIv[] = "iv";
 
 const char keylogLabelClientEarlyTrafficSecret[] = "CLIENT_EARLY_TRAFFIC_SECRET";
 const char keylogLabelClientHsTrafficSecret[] = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
 const char keylogLabelServerHsTrafficSecret[] = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
 const char keylogLabelClientTrafficSecret[] = "CLIENT_TRAFFIC_SECRET_0";
 const char keylogLabelServerTrafficSecret[] = "SERVER_TRAFFIC_SECRET_0";
+const char keylogLabelEarlyExporterSecret[] = "EARLY_EXPORTER_SECRET";
 const char keylogLabelExporterSecret[] = "EXPORTER_SECRET";
 
-#define TRAFFIC_SECRET(ss, dir, name) ((ss->sec.isServer ^            \
-                                        (dir == CipherSpecWrite))     \
-                                           ? ss->ssl3.hs.client##name \
-                                           : ss->ssl3.hs.server##name)
-
 /* Belt and suspenders in case we ever add a TLS 1.4. */
 PR_STATIC_ASSERT(SSL_LIBRARY_VERSION_MAX_SUPPORTED <=
                  SSL_LIBRARY_VERSION_TLS_1_3);
 
 /* Use this instead of FATAL_ERROR when no alert shall be sent. */
 #define LOG_ERROR(ss, prError)                                                     \
     do {                                                                           \
         SSL_TRC(3, ("%d: TLS13[%d]: fatal error %d in %s (%s:%d)",                 \
@@ -576,16 +572,249 @@ tls13_HandleKeyShare(sslSocket *ss,
 
 loser:
     PORT_DestroyCheapArena(&arena);
     errorCode = PORT_GetError(); /* don't overwrite the error code */
     tls13_FatalError(ss, errorCode, illegal_parameter);
     return SECFailure;
 }
 
+static PRBool
+tls13_UseServerSecret(sslSocket *ss, CipherSpecDirection direction)
+{
+    return ss->sec.isServer == (direction == CipherSpecWrite);
+}
+
+static PK11SymKey **
+tls13_TrafficSecretRef(sslSocket *ss, CipherSpecDirection direction)
+{
+    if (tls13_UseServerSecret(ss, direction)) {
+        return &ss->ssl3.hs.serverTrafficSecret;
+    }
+    return &ss->ssl3.hs.clientTrafficSecret;
+}
+
+SECStatus
+tls13_UpdateTrafficKeys(sslSocket *ss, CipherSpecDirection direction)
+{
+    PK11SymKey **secret;
+    PK11SymKey *updatedSecret;
+    PRUint16 epoch;
+    SECStatus rv;
+
+    secret = tls13_TrafficSecretRef(ss, direction);
+    rv = tls13_HkdfExpandLabel(*secret, tls13_GetHash(ss),
+                               NULL, 0,
+                               kHkdfLabelApplicationTrafficSecret,
+                               strlen(kHkdfLabelApplicationTrafficSecret),
+                               tls13_GetHmacMechanism(ss),
+                               tls13_GetHashSize(ss),
+                               &updatedSecret);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+
+    PK11_FreeSymKey(*secret);
+    *secret = updatedSecret;
+
+    ssl_GetSpecReadLock(ss);
+    if (direction == CipherSpecRead) {
+        epoch = ss->ssl3.crSpec->epoch;
+    } else {
+        epoch = ss->ssl3.cwSpec->epoch;
+    }
+    ssl_ReleaseSpecReadLock(ss);
+
+    if (epoch == PR_UINT16_MAX) {
+        /* Good chance that this is an overflow from too many updates. */
+        FATAL_ERROR(ss, SSL_ERROR_TOO_MANY_KEY_UPDATES, internal_error);
+        return SECFailure;
+    }
+    ++epoch;
+
+    rv = tls13_SetCipherSpec(ss, epoch, direction, PR_FALSE);
+    if (rv != SECSuccess) {
+        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+        return SECFailure;
+    }
+
+    return SECSuccess;
+}
+
+SECStatus
+tls13_SendKeyUpdate(sslSocket *ss, tls13KeyUpdateRequest request, PRBool buffer)
+{
+    SECStatus rv;
+
+    SSL_TRC(3, ("%d: TLS13[%d]: %s send key update, response %s",
+                SSL_GETPID(), ss->fd, SSL_ROLE(ss),
+                (request == update_requested) ? "requested"
+                                              : "not requested"));
+
+    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+    if (!ss->firstHsDone) {
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return SECFailure;
+    }
+
+    rv = TLS13_CHECK_HS_STATE(ss, SEC_ERROR_LIBRARY_FAILURE,
+                              idle_handshake);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+
+    /* Not supported. */
+    if (IS_DTLS(ss)) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    ssl_GetXmitBufLock(ss);
+    rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_key_update, 1);
+    if (rv != SECSuccess) {
+        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+        goto loser;
+    }
+    rv = ssl3_AppendHandshakeNumber(ss, request, 1);
+    if (rv != SECSuccess) {
+        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+        goto loser;
+    }
+
+    /* If we have been asked to buffer, then do so.  This allows us to coalesce
+     * a KeyUpdate with a pending write. */
+    rv = ssl3_FlushHandshake(ss, buffer ? ssl_SEND_FLAG_FORCE_INTO_BUFFER : 0);
+    if (rv != SECSuccess) {
+        goto loser; /* error code set by ssl3_FlushHandshake */
+    }
+    ssl_ReleaseXmitBufLock(ss);
+
+    rv = tls13_UpdateTrafficKeys(ss, CipherSpecWrite);
+    if (rv != SECSuccess) {
+        goto loser; /* error code set by tls13_UpdateTrafficKeys */
+    }
+
+    return SECSuccess;
+
+loser:
+    ssl_ReleaseXmitBufLock(ss);
+    return SECFailure;
+}
+
+SECStatus
+SSLExp_KeyUpdate(PRFileDesc *fd, PRBool requestUpdate)
+{
+    SECStatus rv;
+    sslSocket *ss = ssl_FindSocket(fd);
+    if (!ss) {
+        return SECFailure;
+    }
+
+    if (!ss->firstHsDone) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    rv = TLS13_CHECK_HS_STATE(ss, SEC_ERROR_INVALID_ARGS,
+                              idle_handshake);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+
+    ssl_GetSSL3HandshakeLock(ss);
+    rv = tls13_SendKeyUpdate(ss, requestUpdate ? update_requested : update_not_requested,
+                             PR_FALSE /* don't buffer */);
+
+    /* Remember that we are the ones that initiated this KeyUpdate. */
+    if (rv == SECSuccess) {
+        ss->ssl3.peerRequestedKeyUpdate = PR_FALSE;
+    }
+    ssl_ReleaseSSL3HandshakeLock(ss);
+    return rv;
+}
+
+/*
+ * enum {
+ *     update_not_requested(0), update_requested(1), (255)
+ * } KeyUpdateRequest;
+ *
+ * struct {
+ *     KeyUpdateRequest request_update;
+ * } KeyUpdate;
+ */
+static SECStatus
+tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsigned int length)
+{
+    SECStatus rv;
+    PRUint32 update;
+
+    SSL_TRC(3, ("%d: TLS13[%d]: %s handle key update",
+                SSL_GETPID(), ss->fd, SSL_ROLE(ss)));
+
+    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
+    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+    PORT_Assert(ss->firstHsDone);
+    if (!ss->firstHsDone) {
+        FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_KEY_UPDATE, unexpected_message);
+        return SECFailure;
+    }
+
+    rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_KEY_UPDATE,
+                              idle_handshake);
+    if (rv != SECSuccess) {
+        /* We should never be idle_handshake prior to firstHsDone. */
+        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+        return SECFailure;
+    }
+
+    rv = ssl3_ConsumeHandshakeNumber(ss, &update, 1, &b, &length);
+    if (rv != SECSuccess) {
+        return SECFailure; /* Error code set already. */
+    }
+    if (length != 0) {
+        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_KEY_UPDATE, decode_error);
+        return SECFailure;
+    }
+    if (!(update == update_requested ||
+          update == update_not_requested)) {
+        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_KEY_UPDATE, decode_error);
+        return SECFailure;
+    }
+
+    rv = tls13_UpdateTrafficKeys(ss, CipherSpecRead);
+    if (rv != SECSuccess) {
+        return SECFailure; /* Error code set by tls13_UpdateTrafficKeys. */
+    }
+
+    if (update == update_requested) {
+        PRBool sendUpdate;
+        if (ss->ssl3.peerRequestedKeyUpdate) {
+            /* Only send an update if we have sent with the current spec.  This
+             * prevents us from being forced to crank forward pointlessly. */
+            ssl_GetSpecReadLock(ss);
+            sendUpdate = ss->ssl3.cwSpec->seqNum > 0;
+            ssl_ReleaseSpecReadLock(ss);
+        } else {
+            sendUpdate = PR_TRUE;
+        }
+        if (sendUpdate) {
+            /* Respond immediately (don't buffer). */
+            rv = tls13_SendKeyUpdate(ss, update_not_requested, PR_FALSE);
+            if (rv != SECSuccess) {
+                return SECFailure; /* Error already set. */
+            }
+        }
+        ss->ssl3.peerRequestedKeyUpdate = PR_TRUE;
+    }
+
+    return SECSuccess;
+}
+
 SECStatus
 tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length)
 {
     if (ss->sec.isServer && ss->ssl3.hs.zeroRttIgnore != ssl_0rtt_ignore_none) {
         SSL_TRC(3, ("%d: TLS13[%d]: %s successfully decrypted handshake after"
                     "failed 0-RTT",
                     SSL_GETPID(), ss->fd));
         ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_none;
@@ -613,16 +842,19 @@ tls13_HandlePostHelloHandshakeMessage(ss
                 return tls13_ServerHandleFinished(ss, b, length);
             } else {
                 return tls13_ClientHandleFinished(ss, b, length);
             }
 
         case ssl_hs_end_of_early_data:
             return tls13_HandleEndOfEarlyData(ss, b, length);
 
+        case ssl_hs_key_update:
+            return tls13_HandleKeyUpdate(ss, b, length);
+
         default:
             FATAL_ERROR(ss, SSL_ERROR_RX_UNKNOWN_HANDSHAKE, unexpected_message);
             return SECFailure;
     }
 
     PORT_Assert(0); /* Unreached */
     return SECFailure;
 }
@@ -762,30 +994,48 @@ tls13_ComputeEarlySecrets(sslSocket *ss)
 
         rv = tls13_DeriveSecretNullHash(ss, ss->ssl3.hs.currentSecret,
                                         kHkdfLabelPskBinderKey,
                                         strlen(kHkdfLabelPskBinderKey),
                                         &ss->ssl3.hs.pskBinderKey);
         if (rv != SECSuccess) {
             return SECFailure;
         }
-
-        rv = tls13_DeriveSecretNullHash(ss, ss->ssl3.hs.currentSecret,
-                                        kHkdfLabelEarlyExporterSecret,
-                                        strlen(kHkdfLabelEarlyExporterSecret),
-                                        &ss->ssl3.hs.earlyExporterSecret);
-        if (rv != SECSuccess) {
-            return SECFailure;
-        }
     }
     PORT_Assert(!ss->ssl3.hs.resumptionMasterSecret);
 
     return SECSuccess;
 }
 
+/* This derives the early traffic and early exporter secrets. */
+static SECStatus
+tls13_DeriveEarlySecrets(sslSocket *ss)
+{
+    SECStatus rv;
+
+    rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
+                                kHkdfLabelClient,
+                                kHkdfLabelEarlyTrafficSecret,
+                                keylogLabelClientEarlyTrafficSecret,
+                                &ss->ssl3.hs.clientEarlyTrafficSecret);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+
+    rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
+                                NULL, kHkdfLabelEarlyExporterSecret,
+                                keylogLabelEarlyExporterSecret,
+                                &ss->ssl3.hs.earlyExporterSecret);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+
+    return SECSuccess;
+}
+
 static SECStatus
 tls13_ComputeHandshakeSecrets(sslSocket *ss)
 {
     SECStatus rv;
     PK11SymKey *derivedSecret = NULL;
     PK11SymKey *newSecret = NULL;
 
     SSL_TRC(5, ("%d: TLS13[%d]: compute handshake secrets (%s)",
@@ -1592,21 +1842,17 @@ tls13_HandleClientHelloPart2(sslSocket *
             return SECFailure;
         }
     }
     /* Take ownership of the session. */
     ss->sec.ci.sid = sid;
     sid = NULL;
 
     if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
-        rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
-                                    kHkdfLabelClient,
-                                    kHkdfLabelEarlyTrafficSecret,
-                                    keylogLabelClientEarlyTrafficSecret,
-                                    &ss->ssl3.hs.clientEarlyTrafficSecret);
+        rv = tls13_DeriveEarlySecrets(ss);
         if (rv != SECSuccess) {
             FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
             return SECFailure;
         }
     }
 
     ssl_GetXmitBufLock(ss);
     rv = tls13_SendServerHelloSequence(ss);
@@ -2213,18 +2459,17 @@ tls13_SendServerHelloSequence(sslSocket 
         return SECFailure;
     }
 
     if (IS_DTLS(ss)) {
         /* We need this for reading ACKs. */
         ssl_CipherSpecAddRef(ss->ssl3.crSpec);
     }
     if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
-        rv = tls13_SetCipherSpec(ss,
-                                 TrafficKeyEarlyApplicationData,
+        rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData,
                                  CipherSpecRead, PR_TRUE);
         if (rv != SECSuccess) {
             LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
             return SECFailure;
         }
         TLS13_SET_HS_STATE(ss, wait_end_of_early_data);
     } else {
         PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_none ||
@@ -2818,17 +3063,17 @@ tls13_DeriveSecretNullHash(sslSocket *ss
     rv = tls13_ComputeHash(ss, &hashes, buf, 0);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     return tls13_DeriveSecret(ss, key, label, labelLen, &hashes, dest);
 }
 
-/* Convenience wrapper that lets us supply a separate previx and suffix. */
+/* Convenience wrapper that lets us supply a separate prefix and suffix. */
 static SECStatus
 tls13_DeriveSecretWrap(sslSocket *ss, PK11SymKey *key,
                        const char *prefix,
                        const char *suffix,
                        const char *keylogLabel,
                        PK11SymKey **dest)
 {
     SECStatus rv;
@@ -2879,43 +3124,40 @@ tls13_DeriveTrafficKeys(sslSocket *ss, s
     size_t keySize = spec->cipherDef->key_size;
     size_t ivSize = spec->cipherDef->iv_size +
                     spec->cipherDef->explicit_nonce_size; /* This isn't always going to
                                                            * work, but it does for
                                                            * AES-GCM */
     CK_MECHANISM_TYPE bulkAlgorithm = ssl3_Alg2Mech(spec->cipherDef->calg);
     PK11SymKey **prkp = NULL;
     PK11SymKey *prk = NULL;
-    PRBool clientKey;
+    PRBool clientSecret;
     SECStatus rv;
     /* These labels are just used for debugging. */
     static const char kHkdfPhaseEarlyApplicationDataKeys[] = "early application data";
     static const char kHkdfPhaseHandshakeKeys[] = "handshake data";
     static const char kHkdfPhaseApplicationDataKeys[] = "application data";
 
-    if (ss->sec.isServer ^ (spec->direction == CipherSpecWrite)) {
-        clientKey = PR_TRUE;
-    } else {
-        clientKey = PR_FALSE;
-    }
-
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
+    clientSecret = !tls13_UseServerSecret(ss, spec->direction);
     switch (type) {
         case TrafficKeyEarlyApplicationData:
-            PORT_Assert(clientKey);
+            PORT_Assert(clientSecret);
             prkp = &ss->ssl3.hs.clientEarlyTrafficSecret;
             spec->phase = kHkdfPhaseEarlyApplicationDataKeys;
             break;
         case TrafficKeyHandshake:
-            prkp = clientKey ? &ss->ssl3.hs.clientHsTrafficSecret : &ss->ssl3.hs.serverHsTrafficSecret;
+            prkp = clientSecret ? &ss->ssl3.hs.clientHsTrafficSecret
+                                : &ss->ssl3.hs.serverHsTrafficSecret;
             spec->phase = kHkdfPhaseHandshakeKeys;
             break;
         case TrafficKeyApplicationData:
-            prkp = clientKey ? &ss->ssl3.hs.clientTrafficSecret : &ss->ssl3.hs.serverTrafficSecret;
+            prkp = clientSecret ? &ss->ssl3.hs.clientTrafficSecret
+                                : &ss->ssl3.hs.serverTrafficSecret;
             spec->phase = kHkdfPhaseApplicationDataKeys;
             break;
         default:
             LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
             PORT_Assert(0);
             return SECFailure;
     }
     PORT_Assert(prkp != NULL);
@@ -3042,21 +3284,26 @@ tls13_SetAlertCipherSpec(sslSocket *ss)
                              CipherSpecWrite, PR_FALSE);
     if (rv != SECSuccess) {
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
     return SECSuccess;
 }
 
-/* Install a new cipher spec for this direction. */
+/* Install a new cipher spec for this direction.
+ *
+ * During the handshake, the values for |epoch| take values from the
+ * TrafficKeyType enum.  Afterwards, key update increments them.
+ */
 static SECStatus
-tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type,
+tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch,
                     CipherSpecDirection direction, PRBool deleteSecret)
 {
+    TrafficKeyType type;
     SECStatus rv;
     ssl3CipherSpec *spec = NULL;
     ssl3CipherSpec **specp;
 
     /* Flush out old handshake data. */
     ssl_GetXmitBufLock(ss);
     rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
     ssl_ReleaseXmitBufLock(ss);
@@ -3064,56 +3311,54 @@ tls13_SetCipherSpec(sslSocket *ss, Traff
         return SECFailure;
     }
 
     /* Create the new spec. */
     spec = ssl_CreateCipherSpec(ss, direction);
     if (!spec) {
         return SECFailure;
     }
-
-    specp = (direction == CipherSpecRead) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec;
-
-    /* We use the epoch for cipher suite identification, so increment
-     * it in both TLS and DTLS. */
-    if ((*specp)->epoch == PR_UINT16_MAX) {
-        return SECFailure;
-    }
-    spec->epoch = (PRUint16)type;
+    spec->epoch = epoch;
     spec->seqNum = 0;
     if (IS_DTLS(ss)) {
         dtls_InitRecvdRecords(&spec->recvdRecords);
     }
 
     /* This depends on spec having a valid direction and epoch. */
     rv = tls13_SetupPendingCipherSpec(ss, spec);
     if (rv != SECSuccess) {
-        return SECFailure;
-    }
-
+        goto loser;
+    }
+
+    type = (TrafficKeyType)PR_MIN(TrafficKeyApplicationData, epoch);
     rv = tls13_DeriveTrafficKeys(ss, spec, type, deleteSecret);
     if (rv != SECSuccess) {
-        return SECFailure;
+        goto loser;
     }
 
     /* Now that we've set almost everything up, finally cut over. */
+    specp = (direction == CipherSpecRead) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec;
     ssl_GetSpecWriteLock(ss);
     ssl_CipherSpecRelease(*specp); /* May delete old cipher. */
     *specp = spec;                 /* Overwrite. */
     ssl_ReleaseSpecWriteLock(ss);
 
     SSL_TRC(3, ("%d: TLS13[%d]: %s installed key for epoch=%d (%s) dir=%s",
                 SSL_GETPID(), ss->fd, SSL_ROLE(ss), spec->epoch,
                 spec->phase, SPEC_DIR(spec)));
 
     if (ss->ssl3.changedCipherSpecFunc) {
         ss->ssl3.changedCipherSpecFunc(ss->ssl3.changedCipherSpecArg,
                                        direction == CipherSpecWrite, spec);
     }
     return SECSuccess;
+
+loser:
+    ssl_CipherSpecRelease(spec);
+    return SECFailure;
 }
 
 SECStatus
 tls13_ComputeHandshakeHashes(sslSocket *ss, SSL3Hashes *hashes)
 {
     SECStatus rv;
     PK11Context *ctx = NULL;
 
@@ -3929,17 +4174,17 @@ tls13_ServerHandleFinished(sslSocket *ss
     }
 
     if (!ss->opt.requestCertificate &&
         (ss->ssl3.hs.zeroRttState != ssl_0rtt_done)) {
         dtls_ReceivedFirstMessageInFlight(ss);
     }
 
     rv = tls13_SetCipherSpec(ss, TrafficKeyApplicationData,
-                             CipherSpecRead, PR_TRUE);
+                             CipherSpecRead, PR_FALSE);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
         return SECFailure;
     }
 
     if (IS_DTLS(ss)) {
         ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, TrafficKeyClearText);
         /* We need to keep the handshake cipher spec so we can
@@ -4136,17 +4381,17 @@ tls13_SendClientSecondRound(sslSocket *s
         if (sendAlert != no_alert) {
             FATAL_ERROR(ss, PORT_GetError(), sendAlert);
         } else {
             LOG_ERROR(ss, PORT_GetError());
         }
         return SECFailure;
     }
     rv = tls13_SetCipherSpec(ss, TrafficKeyApplicationData,
-                             CipherSpecWrite, PR_TRUE);
+                             CipherSpecWrite, PR_FALSE);
     if (rv != SECSuccess) {
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
 
     rv = tls13_ComputeFinalSecrets(ss);
     if (rv != SECSuccess) {
         return SECFailure;
@@ -4837,21 +5082,17 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss
         if (rv != SECSuccess) {
             return SECFailure;
         }
     }
 
     /* Cipher suite already set in tls13_SetupClientHello. */
     ss->ssl3.hs.preliminaryInfo = 0;
 
-    rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
-                                kHkdfLabelClient,
-                                kHkdfLabelEarlyTrafficSecret,
-                                keylogLabelClientEarlyTrafficSecret,
-                                &ss->ssl3.hs.clientEarlyTrafficSecret);
+    rv = tls13_DeriveEarlySecrets(ss);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     /* Save cwSpec in case we get a HelloRetryRequest and have to send another
      * ClientHello. */
     ssl_CipherSpecAddRef(ss->ssl3.cwSpec);
 
@@ -4987,21 +5228,21 @@ tls13_EncodeDraftVersion(SSL3ProtocolVer
         return 0x7f00 | TLS_1_3_DRAFT_VERSION;
     }
 #endif
     return (PRUint16)version;
 }
 
 /* Pick the highest version we support that is also advertised. */
 SECStatus
-tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supported_versions)
+tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supportedVersions)
 {
     PRUint16 version;
-    /* Make a copy so we're nondestructive*/
-    SECItem data = supported_versions->data;
+    /* Make a copy so we're nondestructive. */
+    SECItem data = supportedVersions->data;
     SECItem versions;
     SECStatus rv;
 
     rv = ssl3_ConsumeHandshakeVariable(ss, &versions, 1,
                                        &data.data, &data.len);
     if (rv != SECSuccess) {
         return SECFailure;
     }
--- a/security/nss/lib/ssl/tls13con.h
+++ b/security/nss/lib/ssl/tls13con.h
@@ -13,16 +13,21 @@
 #include "sslspec.h"
 
 typedef enum {
     tls13_extension_allowed,
     tls13_extension_disallowed,
     tls13_extension_unknown
 } tls13ExtensionStatus;
 
+typedef enum {
+    update_not_requested = 0,
+    update_requested = 1
+} tls13KeyUpdateRequest;
+
 #define TLS13_MAX_FINISHED_SIZE 64
 
 SECStatus tls13_UnprotectRecord(
     sslSocket *ss, ssl3CipherSpec *spec,
     SSL3Ciphertext *cText, sslBuffer *plaintext,
     SSL3AlertDescription *alert);
 
 #if defined(WIN32)
@@ -96,19 +101,22 @@ PRInt32 tls13_Read0RttData(sslSocket *ss
 SECStatus tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf);
 PRBool tls13_ClientAllow0Rtt(const sslSocket *ss, const sslSessionID *sid);
 PRUint16 tls13_EncodeDraftVersion(SSL3ProtocolVersion version);
 SECStatus tls13_NegotiateVersion(sslSocket *ss,
                                  const TLSExtension *supported_versions);
 
 PRBool tls13_IsReplay(const sslSocket *ss, const sslSessionID *sid);
 void tls13_AntiReplayRollover(PRTime now);
+
 SECStatus SSLExp_SetupAntiReplay(PRTime window, unsigned int k,
                                  unsigned int bits);
 
 SECStatus SSLExp_HelloRetryRequestCallback(PRFileDesc *fd,
                                            SSLHelloRetryRequestCallback cb,
                                            void *arg);
-SECStatus SSLExp_UseAltHandshakeType(PRFileDesc *fd, PRBool enable);
+SECStatus tls13_SendKeyUpdate(sslSocket *ss, tls13KeyUpdateRequest request,
+                              PRBool buffer);
+SECStatus SSLExp_KeyUpdate(PRFileDesc *fd, PRBool requestUpdate);
 PRBool tls13_MaybeTls13(sslSocket *ss);
 void tls13_SetSpecRecordVersion(sslSocket *ss, ssl3CipherSpec *spec);
 
 #endif /* __tls13con_h_ */
--- a/security/nss/lib/util/utilpars.c
+++ b/security/nss/lib/util/utilpars.c
@@ -1105,22 +1105,18 @@ NSSUTIL_MkNSSString(char **slotStrings, 
 #define SECMOD_DB "secmod.db"
 const char *
 _NSSUTIL_EvaluateConfigDir(const char *configdir,
                            NSSDBType *pdbType, char **appName)
 {
     NSSDBType dbType;
     PRBool checkEnvDefaultDB = PR_FALSE;
     *appName = NULL;
-/* force the default */
-#ifdef NSS_DISABLE_DBM
+    /* force the default */
     dbType = NSS_DB_TYPE_SQL;
-#else
-    dbType = NSS_DB_TYPE_LEGACY;
-#endif
     if (configdir == NULL) {
         checkEnvDefaultDB = PR_TRUE;
     } else if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS) - 1) == 0) {
         char *cdir;
         dbType = NSS_DB_TYPE_MULTIACCESS;
 
         *appName = PORT_Strdup(configdir + sizeof(MULTIACCESS) - 1);
         if (*appName == NULL) {
--- a/security/nss/tests/all.sh
+++ b/security/nss/tests/all.sh
@@ -106,16 +106,18 @@
 RUN_FIPS=""
 
 ############################## run_tests ###############################
 # run test suites defined in TESTS variable, skip scripts defined in
 # TESTS_SKIP variable
 ########################################################################
 run_tests()
 {
+    echo "Running test cycle: ${TEST_MODE} ----------------------"
+    echo "List of tests that will be executed: ${TESTS}"
     for TEST in ${TESTS}
     do
         # NOTE: the spaces are important. If you don't include
         # the spaces, then turning off ssl_gtests will also turn off ssl
         # tests.
         echo " ${TESTS_SKIP} " | grep " ${TEST} " > /dev/null
         if [ $? -eq 0 ]; then
             continue
@@ -167,18 +169,19 @@ run_cycle_pkix()
     export NSS_ENABLE_PKIX_VERIFY
 
     TESTS="${ALL_TESTS}"
     TESTS_SKIP="cipher dbtests sdr crmf smime merge multinit"
 
     NSS_SSL_TESTS=`echo "${NSS_SSL_TESTS}" | sed -e "s/normal//g" -e "s/fips//g" -e "s/_//g"`
     export -n NSS_SSL_RUN
 
-    # use the default format
+    # use the default format. (unset for the shell, export -n for binaries)
     export -n NSS_DEFAULT_DB_TYPE
+    unset NSS_DEFAULT_DB_TYPE
 
     run_tests
 }
 
 ######################### run_cycle_upgrade_db #########################
 # upgrades certificate database to shareable format and run test suites
 # with those databases
 ########################################################################
--- a/security/nss/tests/cert/cert.sh
+++ b/security/nss/tests/cert/cert.sh
@@ -509,21 +509,21 @@ cert_all_CA()
 	rm $CLIENT_CADIR/dsaroot.cert $SERVER_CADIR/dsaroot.cert
 #	dsaroot.cert in $CLIENT_CADIR and in $SERVER_CADIR is one of the last 
 #	in the chain
 
 #
 #       Create RSA-PSS version of TestCA
 	ALL_CU_SUBJECT="CN=NSS Test CA (RSA-PSS), O=BOGUS NSS, L=Mountain View, ST=California, C=US"
 	cert_rsa_pss_CA $CADIR TestCA-rsa-pss -x "CTu,CTu,CTu" ${D_CA} "1" SHA256
-	rm $CLIENT_CADIR/rsapssroot.cert $SERVER_CADIR/rsapssroot.cert
+	rm $CADIR/rsapssroot.cert
 
 	ALL_CU_SUBJECT="CN=NSS Test CA (RSA-PSS-SHA1), O=BOGUS NSS, L=Mountain View, ST=California, C=US"
 	cert_rsa_pss_CA $CADIR TestCA-rsa-pss-sha1 -x "CTu,CTu,CTu" ${D_CA} "1" SHA1
-	rm $CLIENT_CADIR/rsapssroot.cert $SERVER_CADIR/rsapssroot.cert
+	rm $CADIR/rsapssroot.cert
 
 #
 #       Create EC version of TestCA
 	CA_CURVE="secp521r1"
 	ALL_CU_SUBJECT="CN=NSS Test CA (ECC), O=BOGUS NSS, L=Mountain View, ST=California, C=US"
 	cert_ec_CA $CADIR TestCA-ec -x "CTu,CTu,CTu" ${D_CA} "1" ${CA_CURVE}
 #
 #       Create EC versions of the intermediate CA certs
--- a/security/nss/tests/merge/merge.sh
+++ b/security/nss/tests/merge/merge.sh
@@ -93,17 +93,17 @@ merge_init()
   CONFLICT1DIR=conflict1
   CONFLICT2DIR=conflict2
   mkdir ${CONFLICT1DIR}
   mkdir ${CONFLICT2DIR}
   # in the upgrade mode (dbm->sql), make sure our test databases
   # are dbm databases.
   if [ "${TEST_MODE}" = "UPGRADE_DB" ]; then
 	save=${NSS_DEFAULT_DB_TYPE}
-	NSS_DEFAULT_DB_TYPE= ; export NSS_DEFAULT_DB_TYPE
+	NSS_DEFAULT_DB_TYPE=dbm ; export NSS_DEFAULT_DB_TYPE
   fi
 
   certutil -N -d ${CONFLICT1DIR} -f ${R_PWFILE}
   certutil -N -d ${CONFLICT2DIR} -f ${R_PWFILE}
   certutil -A -n Alice -t ,, -i ${R_CADIR}/TestUser41.cert -d ${CONFLICT1DIR}
   # modify CONFLICTDIR potentially corrupting the database
   certutil -A -n "Alice #1" -t C,, -i ${R_CADIR}/TestUser42.cert -d ${CONFLICT1DIR} -f ${R_PWFILE}
   certutil -M -n "Alice #1" -t ,, -d ${CONFLICT1DIR} -f ${R_PWFILE}
--- a/security/nss/tests/ssl/ssl.sh
+++ b/security/nss/tests/ssl/ssl.sh
@@ -59,19 +59,19 @@ ssl_init()
   PORT=${PORT-8443}
   # Avoid port conflicts when multiple tests are running on the same machine.
   if [ -n "$NSS_TASKCLUSTER_MAC" ]; then
     cwd=$(cd $(dirname $0); pwd -P)
     padd=$(echo $cwd | cut -d "/" -f4 | sed 's/[^0-9]//g')
     PORT=$(($PORT + $padd))
   fi
   NSS_SSL_TESTS=${NSS_SSL_TESTS:-normal_normal}
-  nss_ssl_run="stapling signed_cert_timestamps cov auth stress"
+  nss_ssl_run="stapling signed_cert_timestamps cov auth stress dtls"
   NSS_SSL_RUN=${NSS_SSL_RUN:-$nss_ssl_run}
-
+  
   # Test case files
   SSLCOV=${QADIR}/ssl/sslcov.txt
   SSLAUTH=${QADIR}/ssl/sslauth.txt
   SSLSTRESS=${QADIR}/ssl/sslstress.txt
   SSLPOLICY=${QADIR}/ssl/sslpolicy.txt
   REQUEST_FILE=${QADIR}/ssl/sslreq.dat
 
   #temparary files
@@ -1092,16 +1092,57 @@ ssl_crl_cache()
     SERV_ARG="${SERV_ARG}_-r"
     rm -f ${SSLAUTH_TMP}
     grep -- " $SERV_ARG " ${SSLAUTH} | grep -v "^#" | grep -v none | grep -v bogus  > ${SSLAUTH_TMP}
   done
   TEMPFILES=${SSLAUTH_TMP}
   html "</TABLE><BR>"
 }
 
+############################ ssl_dtls ###################################
+# local shell function to test tstclnt acting as client and server for DTLS
+#########################################################################
+ssl_dtls()
+{
+  #verbose="-v"
+  html_head "SSL DTLS $NORM_EXT - server $SERVER_MODE/client $CLIENT_MODE"
+
+    testname="ssl_dtls"
+    value=0
+
+    if [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] ; then
+        echo "$SCRIPTNAME: skipping  $testname (non-FIPS only)"
+        return 0
+    fi
+
+    echo "${testname}"
+
+    echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${P_R_SERVERDIR} $verbose ${SERVER_OPTIONS} \\"
+    echo "        -U -V tls1.1:tls1.2 -P server -Q < ${REQUEST_FILE} &"
+
+    ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f ${SERVER_OPTIONS} \
+                -d ${P_R_SERVERDIR} $verbose -U -V tls1.1:tls1.2 -P server -n ${HOSTADDR} -w nss < ${REQUEST_FILE} 2>&1 &
+
+    PID=$!
+    
+    sleep 1
+    
+    echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f -d ${P_R_CLIENTDIR} $verbose ${CLIENT_OPTIONS} \\"
+    echo "        -U -V tls1.1:tls1.2 -P client -Q < ${REQUEST_FILE}"
+    ${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -f ${CLIENT_OPTIONS} \
+            -d ${P_R_CLIENTDIR} $verbose -U -V tls1.1:tls1.2 -P client -Q < ${REQUEST_FILE} 2>&1 
+    ret=$?
+    html_msg $ret $value "${testname}" \
+             "produced a returncode of $ret, expected is $value"
+
+    kill ${PID}
+    
+  html "</TABLE><BR>"
+}
+
 
 ############################## ssl_cleanup #############################
 # local shell function to finish this script (no exit since it might be
 # sourced)
 ########################################################################
 ssl_cleanup()
 {
   rm $SERVERPID 2>/dev/null
@@ -1129,16 +1170,19 @@ ssl_run()
             ssl_cov
             ;;
         "auth")
             ssl_auth
             ;;
         "stress")
             ssl_stress
             ;;
+        "dtls")
+            ssl_dtls
+            ;;
          esac
     done
 }
 
 ############################ ssl_run_all ###############################
 # local shell function to run both standard and extended ssl tests
 ########################################################################
 ssl_run_all()