Bug 1432177 - land NSS 1b20549e1075 UPGRADE_NSS_RELEASE, r=me
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Mon, 29 Jan 2018 12:28:20 +0100
changeset 401218 ed6f573553e71ba4d7c0454a105e332c5cde2525
parent 401217 f7400dab78d50ab6735e28d81cca4c1f5a0eba77
child 401219 df9df2ef6538b8068c57d0c091ef4d6dedb15f47
push id33339
push userebalazs@mozilla.com
push dateMon, 29 Jan 2018 16:32:15 +0000
treeherdermozilla-central@c0f08b020685 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1432177
milestone60.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 1432177 - land NSS 1b20549e1075 UPGRADE_NSS_RELEASE, r=me
security/nss/TAG-INFO
security/nss/automation/abi-check/expected-report-libssl3.so.txt
security/nss/automation/buildbot-slave/build.sh
security/nss/automation/saw/poly1305-hacl.saw
security/nss/automation/saw/poly1305.cry
security/nss/automation/saw/poly1305.saw
security/nss/automation/taskcluster/docker/setup.sh
security/nss/automation/taskcluster/graph/src/extend.js
security/nss/automation/taskcluster/graph/src/try_syntax.js
security/nss/automation/taskcluster/scripts/check_abi.sh
security/nss/automation/taskcluster/scripts/run_scan_build.sh
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/ssl_0rtt_unittest.cc
security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
security/nss/gtests/ssl_gtest/tls_agent.cc
security/nss/gtests/ssl_gtest/tls_agent.h
security/nss/gtests/ssl_gtest/tls_connect.cc
security/nss/gtests/ssl_gtest/tls_connect.h
security/nss/lib/freebl/Makefile
security/nss/lib/freebl/lowhash_vector.c
security/nss/lib/freebl/stubs.c
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3exthandle.c
security/nss/lib/ssl/sslexp.h
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslnonce.c
security/nss/lib/ssl/sslsock.c
security/nss/lib/ssl/tls13con.c
security/nss/tests/interop/interop.sh
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-10f7e0179b18
+1b20549e1075
--- a/security/nss/automation/abi-check/expected-report-libssl3.so.txt
+++ b/security/nss/automation/abi-check/expected-report-libssl3.so.txt
@@ -1,20 +1,20 @@
-Functions changes summary: 0 Removed, 1 Changed (2 filtered out), 0 Added function
-Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
 
 1 function with some indirect sub-type change:
 
-  [C]'function SECStatus SSL_GetChannelInfo(SSLChannelInfo*, PRUintn)' at sslinfo.c:12:1 has some indirect sub-type changes:
-    parameter 1 of type 'SSLChannelInfo*' has sub-type changes:
+  [C]'function SECStatus SSL_GetChannelInfo(PRFileDesc*, SSLChannelInfo*, PRUintn)' at sslinfo.c:12:1 has some indirect sub-type changes:
+    parameter 2 of type 'SSLChannelInfo*' has sub-type changes:
       in pointed to type 'typedef SSLChannelInfo' at sslt.h:318:1:
         underlying type 'struct SSLChannelInfoStr' at sslt.h:259:1 changed:
+          type size hasn't changed
           1 data member change:
            type of 'SSLSignatureScheme SSLChannelInfoStr::signatureScheme' changed:
-             underlying type 'enum __anonymous_enum__' changed:
+             underlying type 'enum __anonymous_enum__' at sslt.h:115:1 changed:
+               type size hasn't changed
                3 enumerator deletions:
                  '__anonymous_enum__::ssl_sig_rsa_pss_sha256' value '2052'
                  '__anonymous_enum__::ssl_sig_rsa_pss_sha384' value '2053'
                  '__anonymous_enum__::ssl_sig_rsa_pss_sha512' value '2054'
 
                6 enumerator insertions:
                  '__anonymous_enum__::ssl_sig_rsa_pss_rsae_sha256' value '2052'
                  '__anonymous_enum__::ssl_sig_rsa_pss_rsae_sha384' value '2053'
--- a/security/nss/automation/buildbot-slave/build.sh
+++ b/security/nss/automation/buildbot-slave/build.sh
@@ -207,17 +207,17 @@ test_nss()
 	OUTPUTFILE=${LOG_TMP}
     fi
 
     cat ${LOG_TMP} >> ${LOG_ALL}
     tail -n2 ${HGDIR}/tests_results/security/*.1/results.html | grep END_OF_TEST >> ${LOG_ALL}
     RET=$?
 
     print_log "######## details of detected failures (if any) ########"
-    grep -B50 FAILED ${OUTPUTFILE}
+    grep -B50 -w FAILED ${OUTPUTFILE}
     [ $? -eq 1 ] || RET=1
 
     print_result "NSS - tests - ${BITS} bits - ${OPT}" ${RET} 0
     return ${RET}
 }
 
 check_abi()
 {
@@ -263,18 +263,23 @@ check_abi()
     NEWDIST=${HGDIR}/dist
     ALL_SOs="libfreebl3.so libfreeblpriv3.so libnspr4.so libnss3.so libnssckbi.so libnssdbm3.so libnsssysinit.so libnssutil3.so libplc4.so libplds4.so libsmime3.so libsoftokn3.so libssl3.so"
     for SO in ${ALL_SOs}; do
         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-temp$SO.txt
+        RET=$?
+        cat ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt \
+            | grep -v "^Functions changes summary:" \
+            | grep -v "^Variables changes summary:" \
             > ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt
-        RET=$?
+        rm -f ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt
         ABIDIFF_ERROR=$((($RET & 0x01) != 0))
         ABIDIFF_USAGE_ERROR=$((($RET & 0x02) != 0))
         ABIDIFF_ABI_CHANGE=$((($RET & 0x04) != 0))
         ABIDIFF_ABI_INCOMPATIBLE_CHANGE=$((($RET & 0x08) != 0))
         ABIDIFF_UNKNOWN_BIT_SET=$((($RET & 0xf0) != 0))
 
         # If abidiff reports an error, or a usage error, or if it sets a result
         # bit value this script doesn't know yet about, we'll report failure.
new file mode 100644
--- /dev/null
+++ b/security/nss/automation/saw/poly1305-hacl.saw
@@ -0,0 +1,38 @@
+// 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/.
+
+import "poly1305.cry" as poly1305;
+
+print "Proving Poly1305 spec...";
+prove_print abc {{ poly1305::allTestsPass }};
+
+print "Loading LLVM bitcode...";
+m <- llvm_load_module "../../../dist/Debug/lib/libfreeblpriv3.so.bc";
+
+let SpecPoly1305 n = do {
+  llvm_ptr "output" (llvm_array 16 (llvm_int 8));
+  output <- llvm_var "*output" (llvm_array 16 (llvm_int 8));
+
+  llvm_ptr "input" (llvm_array n (llvm_int 8));
+  input <- llvm_var "*input" (llvm_array n (llvm_int 8));
+
+  llvm_var "len1" (llvm_int 64);
+  llvm_ptr "k1" (llvm_array 32 (llvm_int 8));
+  k1 <- llvm_var "*k1" (llvm_array 32 (llvm_int 8));
+
+  llvm_assert_eq "*input" {{ zero : [n][8] }};
+  llvm_assert_eq "len1" {{ `n : [64] }};
+
+  llvm_assert_eq "*k1" {{ zero : [32][8] }};
+
+  let res = {{ poly1305::Poly1305 input (take`{16} k1) (drop`{16} k1) }};
+  llvm_ensure_eq "*output" {{ res }};
+
+  llvm_verify_tactic abc;
+};
+
+print "Proving equality for a single block...";
+// This is currently disabled as it takes way too long. We need to help Z3
+// prove this before we can enable it on Taskcluster.
+//time (llvm_verify m "Hacl_Poly1305_64_crypto_onetimeauth" [] (SpecPoly1305 16));
new file mode 100644
--- /dev/null
+++ b/security/nss/automation/saw/poly1305.cry
@@ -0,0 +1,336 @@
+/* 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/. */
+
+/* This file provides a spec of the Poly1305 one-time authenticator.
+ * See <https://tools.ietf.org/html/rfc7539> for details. */
+
+module poly1305 where
+
+P : [136]
+P = 2^^130 - 5
+
+Poly1305 : {n} (fin n) => [n][8] -> [16][8] -> [16][8] -> [16][8]
+Poly1305 msg r s = reverse (groupBy (drop ((rounds ! 0) + s')))
+  where
+    rounds = [zero] # [ Poly1305_block acc r' b | b <- blocks | acc <- rounds ]
+    r' = zero # (Poly1305_clamp (join (reverse r)))
+    s' = zero # (join (reverse s))
+    blocks = Poly1305_split msg
+
+private
+  // 0x0f - for r[3], r[7], r[11], r[15]
+  // 0xfc - for r[4], r[8], r[12]
+  Poly1305_clamp r = r && 0x0ffffffc0ffffffc0ffffffc0fffffff
+
+  // Poly1305_block : ((acc + msg) * r) % P
+  Poly1305_block : [136] -> [136] -> [136] -> [136]
+  Poly1305_block acc r msg = drop (prod % (zero # P))
+    where
+      acc' : [137]
+      // Add the current block to the accumulator.
+      acc' = (zero # acc) + (zero # msg)
+      prod : [273]
+      // Multiply the new accumulator value by r.
+      prod = ((zero : [137]) # r) * ((zero : [136]) # acc')
+
+  Poly1305_split : {n, nb, nf} (fin n, nf == n / 16, nb == (n + 15) / 16) => [n][8] -> [nb][136]
+  Poly1305_split msg = take ((h1 : [nf][136]) # h2)
+    where
+      // Split all full 16-byte blocks and append 0x01, then convert to LE.
+      h1 = [ join (reverse (b # [0x01])) | b <- groupBy`{16} (take msg)]
+      // Pad the remaining bytes (if any) and convert to LE.
+      h2 = [join (reverse ((drop`{nf * 16} msg) # [0x01] # zero))]
+
+/* -------------------------------------------------------------------------- */
+/* -- Tests ----------------------------------------------------------------- */
+
+private
+  // https://tools.ietf.org/html/rfc7539#section-2.5.2
+  rval1 = [0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33,
+           0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8]
+  sval1 = [0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd,
+           0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b]
+  text1 = [0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72,
+           0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f,
+           0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65,
+           0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f,
+           0x75, 0x70]
+
+  rfctest01 = Poly1305 text1 rval1 sval1
+      == [0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6,
+          0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9]
+
+  // https://tools.ietf.org/html/rfc7539#appendix-A.3
+  // Test Vector #1
+  rval2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  sval2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  text2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+  rfctest02 = Poly1305 text2 rval2 sval2
+      == [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+  // https://tools.ietf.org/html/rfc7539#appendix-A.3
+  // Test Vector #2
+  rval3 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  sval3 = [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70,
+           0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e]
+  text3 = [0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
+           0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
+           0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
+           0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
+           0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
+           0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
+           0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
+           0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
+           0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
+           0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
+           0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
+           0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
+           0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+           0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
+           0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
+           0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
+           0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+           0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
+           0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+           0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
+           0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
+           0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
+           0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
+           0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
+           0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
+           0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
+           0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+           0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
+           0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
+           0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
+           0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
+           0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
+           0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
+           0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
+           0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
+           0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
+           0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
+           0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
+           0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
+           0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
+           0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
+           0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
+           0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
+           0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
+           0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
+           0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
+           0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f]
+
+  rfctest03 = Poly1305 text3 rval3 sval3
+      == [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70,
+          0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e]
+
+  // https://tools.ietf.org/html/rfc7539#appendix-A.3
+  // Test Vector #3
+  rval4 = [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70,
+           0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e]
+  sval4 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  text4 = [0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
+           0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
+           0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
+           0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
+           0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
+           0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
+           0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
+           0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
+           0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
+           0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
+           0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
+           0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
+           0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+           0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
+           0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
+           0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
+           0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+           0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
+           0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+           0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
+           0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
+           0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
+           0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
+           0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
+           0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
+           0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
+           0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+           0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
+           0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
+           0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
+           0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
+           0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
+           0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
+           0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
+           0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
+           0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
+           0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
+           0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
+           0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
+           0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
+           0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
+           0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
+           0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
+           0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
+           0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
+           0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
+           0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f]
+
+  rfctest04 = Poly1305 text4 rval4 sval4
+      == [0xf3, 0x47, 0x7e, 0x7c, 0xd9, 0x54, 0x17, 0xaf,
+          0x89, 0xa6, 0xb8, 0x79, 0x4c, 0x31, 0x0c, 0xf0]
+
+  // https://tools.ietf.org/html/rfc7539#appendix-A.3
+  // Test Vector #4
+  rval5 = [0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a,
+           0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0]
+  sval5 = [0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09,
+           0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0]
+  text5 = [0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72,
+           0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61,
+           0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+           0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f,
+           0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20,
+           0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64,
+           0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20,
+           0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+           0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c,
+           0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77,
+           0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+           0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65,
+           0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+           0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20,
+           0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75,
+           0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e]
+
+  rfctest05 = Poly1305 text5 rval5 sval5
+      == [0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61,
+          0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62]
+
+  // https://tools.ietf.org/html/rfc7539#appendix-A.3
+  // Test Vector #5
+  rval6 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  sval6 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  text6 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
+
+  rfctest06 = Poly1305 text6 rval6 sval6
+      == [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+  // https://tools.ietf.org/html/rfc7539#appendix-A.3
+  // Test Vector #6
+  rval7 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  sval7 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
+  text7 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+  rfctest07 = Poly1305 text7 rval7 sval7
+      == [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+  // https://tools.ietf.org/html/rfc7539#appendix-A.3
+  // Test Vector #7
+  rval8 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  sval8 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  text8 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+           0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+           0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+  rfctest08 = Poly1305 text8 rval8 sval8
+      == [0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+  // https://tools.ietf.org/html/rfc7539#appendix-A.3
+  // Test Vector #8
+  rval9 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  sval9 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  text9 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+           0xfb, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+           0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+           0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+           0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01]
+
+  rfctest09 = Poly1305 text9 rval9 sval9
+      == [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+  // https://tools.ietf.org/html/rfc7539#appendix-A.3
+  // Test Vector #9
+  rval10 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  sval10 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  text10 = [0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
+
+  rfctest10 = Poly1305 text10 rval10 sval10
+      == [0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+          0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
+
+  // https://tools.ietf.org/html/rfc7539#appendix-A.3
+  // Test Vector #10
+  rval11 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  sval11 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  text11 = [0xe3, 0x35, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0xb9,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x33, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0x79, 0xcd,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+  rfctest11 = Poly1305 text11 rval11 sval11
+      == [0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+  // https://tools.ietf.org/html/rfc7539#appendix-A.3
+  // Test Vector #11
+  rval12 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  sval12 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+  text12 = [0xe3, 0x35, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0xb9,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x33, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0x79, 0xcd,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+  rfctest12 = Poly1305 text12 rval12 sval12
+      == [0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+
+property allTestsPass =
+  ([ // Full RFC test vectors
+     rfctest01, rfctest02, rfctest03, rfctest04,
+     rfctest05, rfctest06, rfctest07, rfctest08,
+     rfctest09, rfctest10, rfctest11, rfctest12
+   ] : [_]Bit) == ~zero // All test bits should equal one
new file mode 100644
--- /dev/null
+++ b/security/nss/automation/saw/poly1305.saw
@@ -0,0 +1,47 @@
+// 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/.
+
+import "poly1305.cry" as poly1305;
+
+print "Proving Poly1305 spec...";
+prove_print abc {{ poly1305::allTestsPass }};
+
+print "Loading LLVM bitcode...";
+m <- llvm_load_module "../../../dist/Debug/lib/libfreeblpriv3.so.bc";
+
+let SpecPoly1305 n = do {
+  llvm_ptr "out" (llvm_array 16 (llvm_int 8));
+  out <- llvm_var "*out" (llvm_array 16 (llvm_int 8));
+
+  llvm_ptr "ad" (llvm_array 16 (llvm_int 8));
+  ad <- llvm_var "*ad" (llvm_array 16 (llvm_int 8));
+
+  adLen <- llvm_var "adLen" (llvm_int 32);
+
+  llvm_ptr "ciphertext" (llvm_array n (llvm_int 8));
+  ciphertext <- llvm_var "*ciphertext" (llvm_array n (llvm_int 8));
+
+  ciphertextLen <- llvm_var "ciphertextLen" (llvm_int 32);
+
+  llvm_ptr "key" (llvm_array 32 (llvm_int 8));
+  key <- llvm_var "*key" (llvm_array 32 (llvm_int 8));
+
+  llvm_assert_eq "*ad" {{ zero : [16][8] }};
+  llvm_assert_eq "adLen" {{ 16 : [32] }};
+
+  llvm_assert_eq "*ciphertext" {{ zero : [n][8] }};
+  llvm_assert_eq "ciphertextLen" {{ `n : [32] }};
+
+  llvm_assert_eq "*key" {{ zero : [32][8] }};
+
+  let res = {{ poly1305::Poly1305 (ad # ciphertext # [16, 0, 0, 0, 0, 0, 0, 0] # [`n, 0, 0, 0, 0, 0, 0, 0]) (take`{16} key) (drop`{16} key) }};
+  llvm_ensure_eq "*out" {{ res }};
+
+  llvm_verify_tactic abc;
+};
+
+print "Proving equality for a single block...";
+// This is currently disabled as it takes way too long. We need to help Z3
+// prove this before we can enable it on Taskcluster.
+//time (llvm_verify m "Poly1305Do" [] (SpecPoly1305 16));
--- a/security/nss/automation/taskcluster/docker/setup.sh
+++ b/security/nss/automation/taskcluster/docker/setup.sh
@@ -7,16 +7,17 @@ export DEBIAN_FRONTEND=noninteractive
 apt-get -y update && apt-get -y upgrade
 
 # Need this to add keys for PPAs below.
 apt-get install -y --no-install-recommends apt-utils
 
 apt_packages=()
 apt_packages+=('build-essential')
 apt_packages+=('ca-certificates')
+apt_packages+=('clang-5.0')
 apt_packages+=('curl')
 apt_packages+=('npm')
 apt_packages+=('git')
 apt_packages+=('golang-1.6')
 apt_packages+=('libxml2-utils')
 apt_packages+=('locales')
 apt_packages+=('ninja-build')
 apt_packages+=('pkg-config')
@@ -42,26 +43,27 @@ apt_packages+=('g++-6-multilib')
 apt_packages+=('g++-4.8-multilib')
 apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 60C317803A41BA51845E371A1E9377A2BA9EF27F
 echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" > /etc/apt/sources.list.d/toolchain.list
 
 # Install packages.
 apt-get -y update
 apt-get install -y --no-install-recommends ${apt_packages[@]}
 
-# Download clang.
-curl -LO https://releases.llvm.org/4.0.0/clang+llvm-4.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
-curl -LO https://releases.llvm.org/4.0.0/clang+llvm-4.0.0-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*
+# Latest version of abigail-tools
+apt-get install -y libxml2-dev autoconf libelf-dev libdw-dev libtool
+git clone git://sourceware.org/git/libabigail.git
+cd ./libabigail
+autoreconf -fi
+./configure --prefix=/usr --disable-static --disable-apidoc --disable-manual
+make
+make install
+cd ..
+apt-get remove -y libxml2-dev autoconf libtool
+rm -rf libabigail
 
 # Install latest Rust (stable).
 su worker -c "curl https://sh.rustup.rs -sSf | sh -s -- -y"
 
 locale-gen en_US.UTF-8
 dpkg-reconfigure locales
 
 # Cleanup.
--- a/security/nss/automation/taskcluster/graph/src/extend.js
+++ b/security/nss/automation/taskcluster/graph/src/extend.js
@@ -187,18 +187,18 @@ export default async function main() {
     ],
   });
 
   await scheduleLinux("Linux 64 (ASan, debug)", {
     env: {
       UBSAN_OPTIONS: "print_stacktrace=1",
       NSS_DISABLE_ARENA_FREE_LIST: "1",
       NSS_DISABLE_UNLOAD: "1",
-      CC: "clang",
-      CCC: "clang++",
+      CC: "clang-5.0",
+      CCC: "clang++-5.0",
     },
     platform: "linux64",
     collection: "asan",
     image: LINUX_IMAGE,
     features: ["allowPtrace"],
   }, "--ubsan --asan");
 
   await scheduleLinux("Linux 64 (FIPS opt)", {
@@ -418,22 +418,22 @@ async function scheduleLinux(name, base,
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/run_tests.sh"
     ]
   }));
 
   // Extra builds.
   let extra_base = merge({group: "Builds"}, build_base);
   queue.scheduleTask(merge(extra_base, {
-    name: `${name} w/ clang-4.0`,
+    name: `${name} w/ clang-5.0`,
     env: {
-      CC: "clang",
-      CCC: "clang++",
+      CC: "clang-5.0",
+      CCC: "clang++-5.0",
     },
-    symbol: "clang-4.0"
+    symbol: "clang-5.0"
   }));
 
   queue.scheduleTask(merge(extra_base, {
     name: `${name} w/ gcc-4.4`,
     image: LINUX_GCC44_IMAGE,
     env: {
       USE_64: "1",
       CC: "gcc-4.4",
@@ -946,35 +946,47 @@ function scheduleTests(task_build, task_
 /*****************************************************************************/
 
 async function scheduleTools() {
   let base = {
     platform: "nss-tools",
     kind: "test"
   };
 
+  //ABI check task
+  queue.scheduleTask(merge(base, {
+    symbol: "abi",
+    name: "abi",
+    image: LINUX_IMAGE,
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/check_abi.sh"
+    ],
+  }));
+
   queue.scheduleTask(merge(base, {
     symbol: "clang-format-3.9",
     name: "clang-format-3.9",
     image: LINUX_CLANG39_IMAGE,
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/clang-format/run_clang_format.sh"
     ]
   }));
 
   queue.scheduleTask(merge(base, {
-    symbol: "scan-build-4.0",
-    name: "scan-build-4.0",
+    symbol: "scan-build-5.0",
+    name: "scan-build-5.0",
     image: LINUX_IMAGE,
     env: {
       USE_64: "1",
-      CC: "clang",
-      CCC: "clang++",
+      CC: "clang-5.0",
+      CCC: "clang++-5.0",
     },
     artifacts: {
       public: {
         expires: 24 * 7,
         type: "directory",
         path: "/home/worker/artifacts"
       }
     },
@@ -1042,10 +1054,23 @@ async function scheduleTools() {
     image: SAW_IMAGE,
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/run_saw.sh chacha20"
     ]
   }));
 
+  queue.scheduleTask(merge(base, {
+    parent: task_saw,
+    symbol: "Poly1305",
+    group: "SAW",
+    name: "poly1305.saw",
+    image: SAW_IMAGE,
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/run_saw.sh poly1305"
+    ]
+  }));
+
   return queue.submit();
 }
--- a/security/nss/automation/taskcluster/graph/src/try_syntax.js
+++ b/security/nss/automation/taskcluster/graph/src/try_syntax.js
@@ -46,17 +46,17 @@ function parseOptions(opts) {
   // If it's nonsense then don't run any tests.
   if (opts.unittests == "all") {
     unittests = allUnitTests;
   } else if (unittests.length == 0) {
     unittests = [];
   }
 
   // Parse tools.
-  let allTools = ["clang-format", "scan-build", "hacl", "saw"];
+  let allTools = ["clang-format", "scan-build", "hacl", "saw", "abi"];
   let tools = intersect(opts.tools.split(/\s*,\s*/), allTools);
 
   // If the given value is "all" run all tools.
   // If it's nonsense then don't run any tools.
   if (opts.tools == "all") {
     tools = allTools;
   } else if (tools.length == 0) {
     tools = [];
new file mode 100755
--- /dev/null
+++ b/security/nss/automation/taskcluster/scripts/check_abi.sh
@@ -0,0 +1,172 @@
+#! /bin/bash
+
+set_env()
+{
+  cd /home/worker
+  HGDIR=/home/worker
+  OUTPUTDIR=$(pwd)$(echo "/output")
+  DATE=$(date "+TB [%Y-%m-%d %H:%M:%S]")
+
+  if [ ! -d "${OUTPUTDIR}" ]; then
+    echo "Creating output dir"
+    mkdir "${OUTPUTDIR}"
+  fi
+
+  if [ ! -d "nspr" ]; then
+    for i in 0 2 5; do
+      sleep $i
+      hg clone -r "default" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/nspr" && break
+      rm -rf nspr
+    done
+  fi
+
+  cd nss
+  ./build.sh -v -c
+  cd ..
+}
+
+check_abi()
+{
+  set_env
+  set +e #reverses set -e from build.sh to allow possible hg clone failures
+  if [[ "$1" != --nobuild ]]; then # Start nobuild block
+
+    echo "######## NSS ABI CHECK ########"
+    echo "######## creating temporary HG clones ########"
+
+    rm -rf ${HGDIR}/baseline
+    mkdir ${HGDIR}/baseline
+    BASE_NSS=`cat ${HGDIR}/nss/automation/abi-check/previous-nss-release`  #Reads the version number of the last release from the respective file
+    NSS_CLONE_RESULT=0
+    for i in 0 2 5; do
+        sleep $i
+        hg clone -u "${BASE_NSS}" "https://hg.mozilla.org/projects/nss" "${HGDIR}/baseline/nss"
+        if [ $? -eq 0 ]; then
+          NSS_CLONE_RESULT=0
+          break
+        fi
+        rm -rf "${HGDIR}/baseline/nss"
+        NSS_CLONE_RESULT=1
+    done
+    if [ ${NSS_CLONE_RESULT} -ne 0 ]; then
+      echo "invalid tag in automation/abi-check/previous-nss-release"
+      return 1
+    fi
+
+    BASE_NSPR=NSPR_$(head -1 ${HGDIR}/baseline/nss/automation/release/nspr-version.txt | cut -d . -f 1-2 | tr . _)_BRANCH
+    hg clone -u "${BASE_NSPR}" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/baseline/nspr"
+    NSPR_CLONE_RESULT=$?
+
+    if [ ${NSPR_CLONE_RESULT} -ne 0 ]; then
+      rm -rf "${HGDIR}/baseline/nspr"
+      for i in 0 2 5; do
+          sleep $i
+          hg clone -u "default" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/baseline/nspr" && break
+          rm -rf "${HGDIR}/baseline/nspr"
+      done
+      echo "Nonexisting tag ${BASE_NSPR} derived from ${BASE_NSS} automation/release/nspr-version.txt"
+      echo "Using default branch instead."
+    fi
+
+    echo "######## building baseline NSPR/NSS ########"
+    echo "${HGDIR}/baseline/nss/build.sh"
+    cd ${HGDIR}/baseline/nss
+    ./build.sh -v -c
+    cd ${HGDIR}
+  else  # Else nobuild block
+    echo "######## using existing baseline NSPR/NSS build ########"
+  fi # End nobuild block
+
+  set +e #reverses set -e from build.sh to allow abidiff failures
+
+  echo "######## Starting abidiff procedure ########"
+  abi_diff
+}
+
+#Slightly modified from builbot-slave/build.sh
+abi_diff()
+{
+  ABI_PROBLEM_FOUND=0
+  ABI_REPORT=${OUTPUTDIR}/abi-diff.txt
+  rm -f ${ABI_REPORT}
+  PREVDIST=${HGDIR}/baseline/dist
+  NEWDIST=${HGDIR}/dist
+  ALL_SOs="libfreebl3.so libfreeblpriv3.so libnspr4.so libnss3.so libnssckbi.so libnssdbm3.so libnsssysinit.so libnssutil3.so libplc4.so libplds4.so libsmime3.so libsoftokn3.so libssl3.so"
+  for SO in ${ALL_SOs}; do
+      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-temp$SO.txt
+      RET=$?
+      cat ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt \
+          | grep -v "^Functions changes summary:" \
+          | grep -v "^Variables changes summary:" \
+          > ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt
+      rm -f ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt
+
+      ABIDIFF_ERROR=$((($RET & 0x01) != 0))
+      ABIDIFF_USAGE_ERROR=$((($RET & 0x02) != 0))
+      ABIDIFF_ABI_CHANGE=$((($RET & 0x04) != 0))
+      ABIDIFF_ABI_INCOMPATIBLE_CHANGE=$((($RET & 0x08) != 0))
+      ABIDIFF_UNKNOWN_BIT_SET=$((($RET & 0xf0) != 0))
+
+      # If abidiff reports an error, or a usage error, or if it sets a result
+      # bit value this script doesn't know yet about, we'll report failure.
+      # For ABI changes, we don't yet report an error. We'll compare the
+      # result report with our whitelist. This allows us to silence changes
+      # that we're already aware of and have been declared acceptable.
+
+      REPORT_RET_AS_FAILURE=0
+      if [ $ABIDIFF_ERROR -ne 0 ]; then
+          echo "abidiff reported ABIDIFF_ERROR."
+          REPORT_RET_AS_FAILURE=1
+      fi
+      if [ $ABIDIFF_USAGE_ERROR -ne 0 ]; then
+          echo "abidiff reported ABIDIFF_USAGE_ERROR."
+          REPORT_RET_AS_FAILURE=1
+      fi
+      if [ $ABIDIFF_UNKNOWN_BIT_SET -ne 0 ]; then
+          echo "abidiff reported ABIDIFF_UNKNOWN_BIT_SET."
+          REPORT_RET_AS_FAILURE=1
+      fi
+
+      if [ $ABIDIFF_ABI_CHANGE -ne 0 ]; then
+          echo "Ignoring abidiff result ABI_CHANGE, instead we'll check for non-whitelisted differences."
+      fi
+      if [ $ABIDIFF_ABI_INCOMPATIBLE_CHANGE -ne 0 ]; then
+          echo "Ignoring abidiff result ABIDIFF_ABI_INCOMPATIBLE_CHANGE, instead we'll check for non-whitelisted differences."
+      fi
+
+      if [ $REPORT_RET_AS_FAILURE -ne 0 ]; then
+          ABI_PROBLEM_FOUND=1
+          echo "abidiff {$PREVDIST , $NEWDIST} for $SO FAILED with result $RET, 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
+          echo "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
+          echo "FAILED to compare exepcted and new report: ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt"
+      fi
+  done
+
+  if [ -s ${ABI_REPORT} ]; then
+      echo "FAILED: there are new unexpected ABI changes"
+      cat ${ABI_REPORT}
+      return 1
+  elif [ $ABI_PROBLEM_FOUND -ne 0 ]; then
+      echo "FAILED: failure executing the ABI checks"
+      cat ${ABI_REPORT}
+      return 1
+  fi
+
+  return 0
+}
+
+check_abi $1
--- a/security/nss/automation/taskcluster/scripts/run_scan_build.sh
+++ b/security/nss/automation/taskcluster/scripts/run_scan_build.sh
@@ -29,17 +29,17 @@ declare -A scan=( \
     )
 
 # remove .OBJ directories to force a rebuild of just the select few
 for i in "${!scan[@]}"; do
    find "$i" -name "*.OBJ" -exec rm -rf {} \+
 done
 
 # run scan-build (only building affected directories)
-scan-build -o /home/worker/artifacts --use-cc=$CC --use-c++=$CCC make nss_build_all && cd ..
+scan-build-5.0 -o /home/worker/artifacts --use-cc=$CC --use-c++=$CCC make nss_build_all && cd ..
 
 # print errors we found
 set +v +x
 STATUS=0
 for i in "${!scan[@]}"; do
    n=$(grep -Rn "$i" /home/worker/artifacts/*/report-*.html | wc -l)
    if [ $n -ne ${scan[$i]} ]; then
      STATUS=1
--- 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
@@ -327,20 +327,16 @@ const PRUint8 *SSLInt_CipherSpecToIv(con
 PRUint16 SSLInt_CipherSpecToEpoch(const ssl3CipherSpec *spec) {
   return spec->epoch;
 }
 
 void SSLInt_SetTicketLifetime(uint32_t lifetime) {
   ssl_ticket_lifetime = lifetime;
 }
 
-void SSLInt_SetMaxEarlyDataSize(uint32_t size) {
-  ssl_max_early_data_size = size;
-}
-
 SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size) {
   sslSocket *ss;
 
   ss = ssl_FindSocket(fd);
   if (!ss) {
     return SECFailure;
   }
 
--- a/security/nss/gtests/ssl_gtest/libssl_internals.h
+++ b/security/nss/gtests/ssl_gtest/libssl_internals.h
@@ -45,13 +45,12 @@ SECStatus SSLInt_GetEpochs(PRFileDesc *f
 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);
 void SSLInt_SetTicketLifetime(uint32_t lifetime);
-void SSLInt_SetMaxEarlyDataSize(uint32_t size);
 SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size);
 void SSLInt_RolloverAntiReplay(void);
 
 #endif  // ndef libssl_internals_h_
--- a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
@@ -454,20 +454,23 @@ static void CheckEarlyDataLimit(const st
   SSLPreliminaryChannelInfo preinfo;
   SECStatus rv =
       SSL_GetPreliminaryChannelInfo(agent->ssl_fd(), &preinfo, sizeof(preinfo));
   EXPECT_EQ(SECSuccess, rv);
   EXPECT_EQ(expected_size, static_cast<size_t>(preinfo.maxEarlyDataSize));
 }
 
 TEST_P(TlsConnectTls13, SendTooMuchEarlyData) {
+  EnsureTlsSetup();
   const char* big_message = "0123456789abcdef";
   const size_t short_size = strlen(big_message) - 1;
   const PRInt32 short_length = static_cast<PRInt32>(short_size);
-  SSLInt_SetMaxEarlyDataSize(static_cast<PRUint32>(short_size));
+  EXPECT_EQ(SECSuccess,
+            SSL_SetMaxEarlyDataSize(server_->ssl_fd(),
+                                    static_cast<PRUint32>(short_size)));
   SetupForZeroRtt();
 
   client_->Set0RttEnabled(true);
   server_->Set0RttEnabled(true);
   ExpectResumption(RESUME_TICKET);
 
   client_->Handshake();
   CheckEarlyDataLimit(client_, short_size);
@@ -509,18 +512,20 @@ TEST_P(TlsConnectTls13, SendTooMuchEarly
 
   Handshake();
   ExpectEarlyDataAccepted(true);
   CheckConnected();
   SendReceive();
 }
 
 TEST_P(TlsConnectTls13, ReceiveTooMuchEarlyData) {
+  EnsureTlsSetup();
+
   const size_t limit = 5;
-  SSLInt_SetMaxEarlyDataSize(limit);
+  EXPECT_EQ(SECSuccess, SSL_SetMaxEarlyDataSize(server_->ssl_fd(), limit));
   SetupForZeroRtt();
 
   client_->Set0RttEnabled(true);
   server_->Set0RttEnabled(true);
   ExpectResumption(RESUME_TICKET);
 
   client_->Handshake();  // Send ClientHello
   CheckEarlyDataLimit(client_, limit);
--- a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
@@ -1009,9 +1009,30 @@ TEST_P(TlsConnectTls13ResumptionToken, C
   Handshake();
   ExpectEarlyDataAccepted(true);
   CheckConnected();
   CheckAlpn("a");
 
   SendReceive();
 }
 
+// Resumption on sessions with client authentication only works with internal
+// caching.
+TEST_P(TlsConnectGenericResumption, ConnectResumeClientAuth) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+  client_->SetupClientAuth();
+  server_->RequestClientAuth(true);
+  Connect();
+  SendReceive();
+  EXPECT_FALSE(client_->resumption_callback_called());
+
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+  if (use_external_cache()) {
+    ExpectResumption(RESUME_NONE);
+  } else {
+    ExpectResumption(RESUME_TICKET);
+  }
+  Connect();
+  SendReceive();
+}
+
 }  // namespace nss_test
--- a/security/nss/gtests/ssl_gtest/tls_agent.cc
+++ b/security/nss/gtests/ssl_gtest/tls_agent.cc
@@ -61,16 +61,17 @@ TlsAgent::TlsAgent(const std::string& na
       can_falsestart_hook_called_(false),
       sni_hook_called_(false),
       auth_certificate_hook_called_(false),
       expected_received_alert_(kTlsAlertCloseNotify),
       expected_received_alert_level_(kTlsAlertWarning),
       expected_sent_alert_(kTlsAlertCloseNotify),
       expected_sent_alert_level_(kTlsAlertWarning),
       handshake_callback_called_(false),
+      resumption_callback_called_(false),
       error_code_(0),
       send_ctr_(0),
       recv_ctr_(0),
       expect_readwrite_error_(false),
       handshake_callback_(),
       auth_certificate_callback_(),
       sni_callback_(),
       skip_version_checks_(false),
@@ -178,16 +179,20 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc
 
     rv = SSL_SNISocketConfigHook(ssl_fd(), SniHook, this);
     EXPECT_EQ(SECSuccess, rv);
     if (rv != SECSuccess) return false;
 
     ScopedCERTCertList anchors(CERT_NewCertList());
     rv = SSL_SetTrustAnchors(ssl_fd(), anchors.get());
     if (rv != SECSuccess) return false;
+
+    rv = SSL_SetMaxEarlyDataSize(ssl_fd(), 1024);
+    EXPECT_EQ(SECSuccess, rv);
+    if (rv != SECSuccess) return false;
   } else {
     rv = SSL_SetURL(ssl_fd(), "server");
     EXPECT_EQ(SECSuccess, rv);
     if (rv != SECSuccess) return false;
   }
 
   rv = SSL_AuthCertificateHook(ssl_fd(), AuthCertificateHook, this);
   EXPECT_EQ(SECSuccess, rv);
@@ -415,16 +420,17 @@ SECStatus ResumptionTokenCallback(PRFile
                                   unsigned int len, void* ctx) {
   EXPECT_NE(nullptr, resumptionToken);
   if (!resumptionToken) {
     return SECFailure;
   }
 
   std::vector<uint8_t> new_token(resumptionToken, resumptionToken + len);
   reinterpret_cast<TlsAgent*>(ctx)->SetResumptionToken(new_token);
+  reinterpret_cast<TlsAgent*>(ctx)->SetResumptionCallbackCalled();
   return SECSuccess;
 }
 
 void TlsAgent::SetResumptionTokenCallback() {
   EXPECT_TRUE(EnsureTlsSetup());
   SECStatus rv =
       SSL_SetResumptionTokenCallback(ssl_fd(), ResumptionTokenCallback, this);
   EXPECT_EQ(SECSuccess, rv);
--- a/security/nss/gtests/ssl_gtest/tls_agent.h
+++ b/security/nss/gtests/ssl_gtest/tls_agent.h
@@ -174,16 +174,20 @@ class TlsAgent : public PollTarget {
     return resumption_token_;
   }
   void GetTokenInfo(ScopedSSLResumptionTokenInfo& token) {
     SECStatus rv = SSL_GetResumptionTokenInfo(
         resumption_token_.data(), resumption_token_.size(), token.get(),
         sizeof(SSLResumptionTokenInfo));
     ASSERT_EQ(SECSuccess, rv);
   }
+  void SetResumptionCallbackCalled() { resumption_callback_called_ = true; }
+  bool resumption_callback_called() const {
+    return resumption_callback_called_;
+  }
 
   const std::string& name() const { return name_; }
 
   Role role() const { return role_; }
   std::string role_str() const { return role_ == SERVER ? "server" : "client"; }
 
   SSLProtocolVariant variant() const { return variant_; }
 
@@ -391,16 +395,17 @@ class TlsAgent : public PollTarget {
   bool can_falsestart_hook_called_;
   bool sni_hook_called_;
   bool auth_certificate_hook_called_;
   uint8_t expected_received_alert_;
   uint8_t expected_received_alert_level_;
   uint8_t expected_sent_alert_;
   uint8_t expected_sent_alert_level_;
   bool handshake_callback_called_;
+  bool resumption_callback_called_;
   SSLChannelInfo info_;
   SSLCipherSuiteInfo csinfo_;
   SSLVersionRange vrange_;
   PRErrorCode error_code_;
   size_t send_ctr_;
   size_t recv_ctr_;
   bool expect_readwrite_error_;
   HandshakeCallbackFunction handshake_callback_;
--- a/security/nss/gtests/ssl_gtest/tls_connect.cc
+++ b/security/nss/gtests/ssl_gtest/tls_connect.cc
@@ -192,17 +192,16 @@ void TlsConnectTestBase::ClearServerCach
   SSLInt_ClearSelfEncryptKey();
   SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str());
 }
 
 void TlsConnectTestBase::SetUp() {
   SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str());
   SSLInt_ClearSelfEncryptKey();
   SSLInt_SetTicketLifetime(30);
-  SSLInt_SetMaxEarlyDataSize(1024);
   SSL_SetupAntiReplay(1 * PR_USEC_PER_SEC, 1, 3);
   ClearStats();
   Init();
 }
 
 void TlsConnectTestBase::TearDown() {
   client_ = nullptr;
   server_ = nullptr;
--- a/security/nss/gtests/ssl_gtest/tls_connect.h
+++ b/security/nss/gtests/ssl_gtest/tls_connect.h
@@ -220,16 +220,18 @@ class TlsConnectGenericResumption
 
   virtual void EnsureTlsSetup() {
     TlsConnectTestBase::EnsureTlsSetup();
     // Enable external resumption token cache.
     if (external_cache_) {
       client_->SetResumptionTokenCallback();
     }
   }
+
+  bool use_external_cache() const { return external_cache_; }
 };
 
 class TlsConnectTls13ResumptionToken
     : public TlsConnectTestBase,
       public ::testing::WithParamInterface<SSLProtocolVariant> {
  public:
   TlsConnectTls13ResumptionToken();
 
--- a/security/nss/lib/freebl/Makefile
+++ b/security/nss/lib/freebl/Makefile
@@ -522,17 +522,22 @@ ifndef NSS_DISABLE_CHACHAPOLY
 
         ifneq (1,$(CC_IS_GCC))
             EXTRA_SRCS += chacha20.c
             VERIFIED_SRCS += Hacl_Chacha20.c
         else
             EXTRA_SRCS += chacha20_vec.c
         endif
     else
-        EXTRA_SRCS += poly1305.c
+        ifeq ($(CPU_ARCH),aarch64)
+            EXTRA_SRCS += Hacl_Poly1305_64.c
+        else
+            EXTRA_SRCS += poly1305.c
+        endif
+
         EXTRA_SRCS += chacha20.c
         VERIFIED_SRCS += Hacl_Chacha20.c
     endif # x86_64
 endif # NSS_DISABLE_CHACHAPOLY
 
 ifeq (,$(filter-out i386 x386 x86 x86_64 aarch64,$(CPU_ARCH)))
     # All intel architectures get the 64 bit version
     # With custom uint128 if necessary (faster than generic 32 bit version).
--- a/security/nss/lib/freebl/lowhash_vector.c
+++ b/security/nss/lib/freebl/lowhash_vector.c
@@ -97,121 +97,128 @@ freebl_LoadDSO(void)
         }
         (void)dlclose(handle);
     }
     return PR_FAILURE;
 }
 
 static PRCallOnceType loadFreeBLOnce;
 
-static PRStatus
+static void
 freebl_RunLoaderOnce(void)
 {
     /* Don't have NSPR, so can use the real PR_CallOnce, implement a stripped
      * down version. */
     if (loadFreeBLOnce.initialized) {
-        return loadFreeBLOnce.status;
+        return;
     }
     if (__sync_lock_test_and_set(&loadFreeBLOnce.inProgress, 1) == 0) {
         loadFreeBLOnce.status = freebl_LoadDSO();
         loadFreeBLOnce.initialized = 1;
     } else {
         /* shouldn't have a lot of takers on the else clause, which is good
          * since we don't have condition variables yet.
          * 'initialized' only ever gets set (not cleared) so we don't
          * need the traditional locks. */
         while (!loadFreeBLOnce.initialized) {
             sleep(1); /* don't have condition variables, just give up the CPU */
         }
     }
+}
 
-    return loadFreeBLOnce.status;
+static const NSSLOWVector *
+freebl_InitVector(void)
+{
+    if (!vector) {
+        freebl_RunLoaderOnce();
+    }
+    return vector;
 }
 
 const FREEBLVector *
 FREEBL_GetVector(void)
 {
-    if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
-        return NULL;
-    }
-    if (vector) {
+    if (freebl_InitVector()) {
         return (vector->p_FREEBL_GetVector)();
     }
     return NULL;
 }
 
 NSSLOWInitContext *
 NSSLOW_Init(void)
 {
-    if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-        return NULL;
-    return (vector->p_NSSLOW_Init)();
+    if (freebl_InitVector()) {
+        return (vector->p_NSSLOW_Init)();
+    }
+    return NULL;
 }
 
 void
 NSSLOW_Shutdown(NSSLOWInitContext *context)
 {
-    if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-        return;
-    (vector->p_NSSLOW_Shutdown)(context);
+    if (freebl_InitVector()) {
+        (vector->p_NSSLOW_Shutdown)(context);
+    }
 }
 
 void
 NSSLOW_Reset(NSSLOWInitContext *context)
 {
-    if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-        return;
-    (vector->p_NSSLOW_Reset)(context);
+    if (freebl_InitVector()) {
+        (vector->p_NSSLOW_Reset)(context);
+    }
 }
 
 NSSLOWHASHContext *
 NSSLOWHASH_NewContext(
     NSSLOWInitContext *initContext,
     HASH_HashType hashType)
 {
-    if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-        return NULL;
-    return (vector->p_NSSLOWHASH_NewContext)(initContext, hashType);
+    if (freebl_InitVector()) {
+        return (vector->p_NSSLOWHASH_NewContext)(initContext, hashType);
+    }
+    return NULL;
 }
 
 void
 NSSLOWHASH_Begin(NSSLOWHASHContext *context)
 {
-    if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-        return;
-    (vector->p_NSSLOWHASH_Begin)(context);
+    if (freebl_InitVector()) {
+        (vector->p_NSSLOWHASH_Begin)(context);
+    }
 }
 
 void
 NSSLOWHASH_Update(NSSLOWHASHContext *context,
                   const unsigned char *buf,
                   unsigned int len)
 {
-    if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-        return;
-    (vector->p_NSSLOWHASH_Update)(context, buf, len);
+    if (freebl_InitVector()) {
+        (vector->p_NSSLOWHASH_Update)(context, buf, len);
+    }
 }
 
 void
 NSSLOWHASH_End(NSSLOWHASHContext *context,
                unsigned char *buf,
                unsigned int *ret, unsigned int len)
 {
-    if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-        return;
-    (vector->p_NSSLOWHASH_End)(context, buf, ret, len);
+    if (freebl_InitVector()) {
+        (vector->p_NSSLOWHASH_End)(context, buf, ret, len);
+    }
 }
 
 void
 NSSLOWHASH_Destroy(NSSLOWHASHContext *context)
 {
-    if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-        return;
-    (vector->p_NSSLOWHASH_Destroy)(context);
+    if (freebl_InitVector()) {
+        (vector->p_NSSLOWHASH_Destroy)(context);
+    }
 }
 
 unsigned int
 NSSLOWHASH_Length(NSSLOWHASHContext *context)
 {
-    if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
-        return -1;
-    return (vector->p_NSSLOWHASH_Length)(context);
+    if (freebl_InitVector()) {
+        return (vector->p_NSSLOWHASH_Length)(context);
+    }
+    return -1;
 }
--- a/security/nss/lib/freebl/stubs.c
+++ b/security/nss/lib/freebl/stubs.c
@@ -31,16 +31,17 @@
 #include <prinrval.h>
 #include <prtime.h>
 #include <prcvar.h>
 #include <secasn1.h>
 #include <secdig.h>
 #include <secport.h>
 #include <secitem.h>
 #include <blapi.h>
+#include <assert.h>
 #include <private/pprio.h>
 
 /* Android API < 21 doesn't define RTLD_NOLOAD */
 #ifndef RTLD_NOLOAD
 #define RTLD_NOLOAD 0
 #endif
 
 #define FREEBL_NO_WEAK 1
@@ -247,17 +248,22 @@ PORT_ZAllocAligned_stub(size_t bytes, si
 
     /* Always allocate a non-zero amount of bytes */
     *mem = malloc(len);
     if (!*mem) {
         return NULL;
     }
 
     memset(*mem, 0, len);
-    return (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x);
+
+    /* We're pretty sure this is non-zero, but let's assure scan-build too. */
+    void *ret = (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x);
+    assert(ret);
+
+    return ret;
 }
 
 extern void *
 PORT_ZAllocAlignedOffset_stub(size_t size, size_t alignment, size_t offset)
 {
     STUB_SAFE_CALL3(PORT_ZAllocAlignedOffset_Util, size, alignment, offset);
     if (offset > size) {
         return NULL;
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -4267,28 +4267,28 @@ ssl3_ComputeHandshakeHashes(sslSocket *s
         unsigned char stackBuf[1024];
         unsigned char *stateBuf = NULL;
 
         h = ss->ssl3.hs.sha;
         stateBuf = PK11_SaveContextAlloc(h, stackBuf,
                                          sizeof(stackBuf), &stateLen);
         if (stateBuf == NULL) {
             ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
+            rv = SECFailure;
             goto tls12_loser;
         }
         rv |= PK11_DigestFinal(h, hashes->u.raw, &hashes->len,
                                sizeof(hashes->u.raw));
         if (rv != SECSuccess) {
             ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
             rv = SECFailure;
             goto tls12_loser;
         }
 
         hashes->hashAlg = ssl3_GetSuitePrfHash(ss);
-        rv = SECSuccess;
 
     tls12_loser:
         if (stateBuf) {
             if (PK11_RestoreContext(h, stateBuf, stateLen) != SECSuccess) {
                 ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
                 rv = SECFailure;
             }
             if (stateBuf != stackBuf) {
@@ -4310,24 +4310,26 @@ ssl3_ComputeHandshakeHashes(sslSocket *s
         unsigned char shaStackBuf[512];
         const int md5Pad = ssl_GetMacDefByAlg(ssl_mac_md5)->pad_size;
         const int shaPad = ssl_GetMacDefByAlg(ssl_mac_sha)->pad_size;
 
         md5StateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.md5, md5StackBuf,
                                             sizeof md5StackBuf, &md5StateLen);
         if (md5StateBuf == NULL) {
             ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
+            rv = SECFailure;
             goto loser;
         }
         md5 = ss->ssl3.hs.md5;
 
         shaStateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.sha, shaStackBuf,
                                             sizeof shaStackBuf, &shaStateLen);
         if (shaStateBuf == NULL) {
             ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+            rv = SECFailure;
             goto loser;
         }
         sha = ss->ssl3.hs.sha;
 
         if (!isTLS) {
             /* compute hashes for SSL3. */
             unsigned char s[4];
 
@@ -4413,17 +4415,16 @@ ssl3_ComputeHandshakeHashes(sslSocket *s
             ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
             rv = SECFailure;
             goto loser;
         }
 
         PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH));
 
         hashes->len = MD5_LENGTH + SHA1_LENGTH;
-        rv = SECSuccess;
 
     loser:
         if (md5StateBuf) {
             if (PK11_RestoreContext(ss->ssl3.hs.md5, md5StateBuf, md5StateLen) !=
                 SECSuccess) {
                 ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
                 rv = SECFailure;
             }
--- a/security/nss/lib/ssl/ssl3exthandle.c
+++ b/security/nss/lib/ssl/ssl3exthandle.c
@@ -816,17 +816,17 @@ ssl3_EncodeSessionTicket(sslSocket *ss, 
                 ss->xtnData.nextProto.len == 0);
     alpnSelection = &ss->xtnData.nextProto;
     PORT_Assert(alpnSelection->len < 256);
     rv = sslBuffer_AppendVariable(&plaintext, alpnSelection->data,
                                   alpnSelection->len, 1);
     if (rv != SECSuccess)
         goto loser;
 
-    rv = sslBuffer_AppendNumber(&plaintext, ssl_max_early_data_size, 4);
+    rv = sslBuffer_AppendNumber(&plaintext, ss->opt.maxEarlyDataSize, 4);
     if (rv != SECSuccess)
         goto loser;
 
     /*
      * We store this in the ticket:
      *    ticket_age_baseline = 1rtt - ticket_age_add
      *
      * When the client resumes, it will provide:
--- a/security/nss/lib/ssl/sslexp.h
+++ b/security/nss/lib/ssl/sslexp.h
@@ -439,15 +439,23 @@ typedef SECStatus(PR_CALLBACK *SSLResump
  *   of length |len|.
  */
 #define SSL_SetResumptionToken(fd, token, len)                              \
     SSL_EXPERIMENTAL_API(                                                   \
         "SSL_SetResumptionToken",                                           \
         (PRFileDesc * _fd, const PRUint8 *_token, const unsigned int _len), \
         (fd, token, len))
 
+/* TLS 1.3 allows a server to set a limit on the number of bytes of early data
+ * that can be received. This allows that limit to be set. This function has no
+ * effect on a client. */
+#define SSL_SetMaxEarlyDataSize(fd, size)                    \
+    SSL_EXPERIMENTAL_API("SSL_SetMaxEarlyDataSize",          \
+                         (PRFileDesc * _fd, PRUint32 _size), \
+                         (fd, size))
+
 /* Deprecated experimental APIs */
 
 #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
@@ -228,16 +228,17 @@ typedef struct {
 /* MAX_SIGNATURE_SCHEMES allows for all the values we support. */
 #define MAX_SIGNATURE_SCHEMES 15
 
 typedef struct sslOptionsStr {
     /* If SSL_SetNextProtoNego has been called, then this contains the
      * list of supported protocols. */
     SECItem nextProtoNego;
 
+    PRUint32 maxEarlyDataSize;
     unsigned int useSecurity : 1;
     unsigned int useSocks : 1;
     unsigned int requestCertificate : 1;
     unsigned int requireCertificate : 2;
     unsigned int handshakeAsClient : 1;
     unsigned int handshakeAsServer : 1;
     unsigned int noCache : 1;
     unsigned int fdx : 1;
@@ -1064,17 +1065,16 @@ typedef struct sslSelfEncryptKeysStr ssl
 
 extern char ssl_debug;
 extern char ssl_trace;
 extern FILE *ssl_trace_iob;
 extern FILE *ssl_keylog_iob;
 extern PZLock *ssl_keylog_lock;
 extern PRUint32 ssl3_sid_timeout;
 extern PRUint32 ssl_ticket_lifetime;
-extern PRUint32 ssl_max_early_data_size;
 
 extern const char *const ssl3_cipherName[];
 
 extern sslSessionIDLookupFunc ssl_sid_lookup;
 
 extern const sslNamedGroupDef ssl_named_groups[];
 
 /************************************************************************/
@@ -1696,17 +1696,17 @@ SECStatus SSLExp_SetResumptionTokenCallb
 SECStatus SSLExp_SetResumptionToken(PRFileDesc *fd, const PRUint8 *token,
                                     unsigned int len);
 
 SECStatus SSLExp_GetResumptionTokenInfo(const PRUint8 *tokenData, unsigned int tokenLen,
                                         SSLResumptionTokenInfo *token, unsigned int version);
 
 SECStatus SSLExp_DestroyResumptionTokenInfo(SSLResumptionTokenInfo *token);
 
-#define SSLResumptionTokenVersion 1
+#define SSLResumptionTokenVersion 2
 
 SEC_END_PROTOS
 
 #if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
 #define SSL_GETPID getpid
 #elif defined(WIN32)
 extern int __cdecl _getpid(void);
 #define SSL_GETPID _getpid
--- a/security/nss/lib/ssl/sslnonce.c
+++ b/security/nss/lib/ssl/sslnonce.c
@@ -418,17 +418,20 @@ ReadVariableFromBuffer(sslReader *reader
 {
     if (sslRead_ReadVariable(reader, lenBytes, readerBuffer) != SECSuccess) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
     if (readerBuffer->len) {
         SECItem tempItem = { siBuffer, (unsigned char *)readerBuffer->buf,
                              readerBuffer->len };
-        SECITEM_CopyItem(NULL, dest, &tempItem);
+        SECStatus rv = SECITEM_CopyItem(NULL, dest, &tempItem);
+        if (rv != SECSuccess) {
+            return rv;
+        }
     }
     return SECSuccess;
 }
 
 /* Fill sid with the values from the encoded resumption token.
  * sid has to be allocated.
  * We don't care about locks here as this cache entry is externally stored.
  */
@@ -516,27 +519,29 @@ ssl_DecodeResumptionToken(sslSessionID *
         SECITEM_CopyItem(NULL, &sid->peerCertStatus.items[0], &tempItem);
     }
 
     if (sslRead_ReadVariable(&reader, 1, &readerBuffer) != SECSuccess) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
     if (readerBuffer.len) {
+        PORT_Assert(readerBuffer.buf);
         sid->peerID = PORT_Strdup((const char *)readerBuffer.buf);
     }
 
     if (sslRead_ReadVariable(&reader, 1, &readerBuffer) != SECSuccess) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
     if (readerBuffer.len) {
         if (sid->urlSvrName) {
             PORT_Free((void *)sid->urlSvrName);
         }
+        PORT_Assert(readerBuffer.buf);
         sid->urlSvrName = PORT_Strdup((const char *)readerBuffer.buf);
     }
 
     if (sslRead_ReadVariable(&reader, 3, &readerBuffer) != SECSuccess) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
     if (readerBuffer.len) {
@@ -600,16 +605,17 @@ ssl_DecodeResumptionToken(sslSessionID *
     }
     sid->u.ssl3.sessionIDLength = (PRUint8)tmpInt;
 
     if (sslRead_ReadVariable(&reader, 1, &readerBuffer) != SECSuccess) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
     if (readerBuffer.len) {
+        PORT_Assert(readerBuffer.buf);
         PORT_Memcpy(sid->u.ssl3.sessionID, readerBuffer.buf, readerBuffer.len);
     }
 
     if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) {
         return SECFailure;
     }
     sid->u.ssl3.cipherSuite = (PRUint16)tmpInt;
     if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
@@ -621,16 +627,17 @@ ssl_DecodeResumptionToken(sslSessionID *
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
     PORT_Assert(readerBuffer.len == WRAPPED_MASTER_SECRET_SIZE);
     if (readerBuffer.len != WRAPPED_MASTER_SECRET_SIZE) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
+    PORT_Assert(readerBuffer.buf);
     PORT_Memcpy(sid->u.ssl3.keys.wrapped_master_secret, readerBuffer.buf,
                 readerBuffer.len);
 
     if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
         return SECFailure;
     }
     sid->u.ssl3.keys.wrapped_master_secret_len = (PRUint8)tmpInt;
     if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
@@ -655,37 +662,20 @@ ssl_DecodeResumptionToken(sslSessionID *
         return SECFailure;
     }
     sid->u.ssl3.masterWrapIndex = (PRUint32)tmpInt;
     if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) {
         return SECFailure;
     }
     sid->u.ssl3.masterWrapSeries = (PRUint16)tmpInt;
 
-    if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) {
-        return SECFailure;
-    }
-    sid->u.ssl3.clAuthModuleID = (unsigned long)tmpInt;
-    if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) {
-        return SECFailure;
-    }
-    sid->u.ssl3.clAuthSlotID = (unsigned long)tmpInt;
-    if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) {
-        return SECFailure;
-    }
-    sid->u.ssl3.clAuthSeries = (PRUint16)tmpInt;
-
     if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
         return SECFailure;
     }
     sid->u.ssl3.masterValid = (char)tmpInt;
-    if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
-        return SECFailure;
-    }
-    sid->u.ssl3.clAuthValid = (char)tmpInt;
 
     if (ReadVariableFromBuffer(&reader, &readerBuffer, 1,
                                &sid->u.ssl3.srvName) != SECSuccess) {
         return SECFailure;
     }
     if (ReadVariableFromBuffer(&reader, &readerBuffer, 2,
                                &sid->u.ssl3.signedCertTimestamps) != SECSuccess) {
         return SECFailure;
@@ -753,18 +743,18 @@ ssl_IsResumptionTokenValid(sslSocket *ss
 /* Encode a session ticket into a byte array that can be handed out to a cache.
  * Needed memory in encodedToken has to be allocated according to
  * *encodedTokenLen. */
 static SECStatus
 ssl_EncodeResumptionToken(sslSessionID *sid, sslBuffer *encodedTokenBuf)
 {
     PORT_Assert(encodedTokenBuf);
     PORT_Assert(sid);
-    if (!sid->u.ssl3.locked.sessionTicket.ticket.len || !encodedTokenBuf ||
-        !sid || !sid->u.ssl3.keys.resumable || !sid->urlSvrName) {
+    if (!sid || !sid->u.ssl3.locked.sessionTicket.ticket.len ||
+        !encodedTokenBuf || !sid->u.ssl3.keys.resumable || !sid->urlSvrName) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
     /* Encoding format:
      * 0-byte: version
      * Integers are encoded according to their length.
      * SECItems are prepended with a 64-bit length field followed by the bytes.
@@ -1017,42 +1007,21 @@ ssl_EncodeResumptionToken(sslSessionID *
         return SECFailure;
     }
     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterWrapSeries, 2);
     if (rv != SECSuccess) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
-    rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.clAuthModuleID, 8);
-    if (rv != SECSuccess) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-    rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.clAuthSlotID, 8);
-    if (rv != SECSuccess) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-    rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.clAuthSeries, 2);
-    if (rv != SECSuccess) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
-
     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterValid, 1);
     if (rv != SECSuccess) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
-    rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.clAuthValid, 1);
-    if (rv != SECSuccess) {
-        PORT_SetError(SEC_ERROR_INVALID_ARGS);
-        return SECFailure;
-    }
 
     rv = sslBuffer_AppendVariable(encodedTokenBuf, sid->u.ssl3.srvName.data,
                                   sid->u.ssl3.srvName.len, 1);
     if (rv != SECSuccess) {
         return SECFailure;
     }
     rv = sslBuffer_AppendVariable(encodedTokenBuf,
                                   sid->u.ssl3.signedCertTimestamps.data,
@@ -1097,16 +1066,21 @@ ssl_CacheExternalToken(sslSocket *ss)
                 sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime,
                 sid->cached));
 
     /* This is only available for stateless resumption. */
     if (sid->u.ssl3.locked.sessionTicket.ticket.data == NULL) {
         return;
     }
 
+    /* Don't export token if the session used client authentication. */
+    if (sid->u.ssl3.clAuthValid) {
+        return;
+    }
+
     if (!sid->creationTime) {
         sid->lastAccessTime = sid->creationTime = ssl_TimeUsec();
     }
     if (!sid->expirationTime) {
         sid->expirationTime = sid->creationTime + ssl3_sid_timeout;
     }
 
     sslBuffer encodedToken = SSL_BUFFER_EMPTY;
@@ -1155,20 +1129,22 @@ ssl_UncacheSessionID(sslSocket *ss)
 {
     if (ss->opt.noCache) {
         return;
     }
 
     sslSecurityInfo *sec = &ss->sec;
     PORT_Assert(sec);
 
-    if (sec->isServer) {
-        ssl_ServerUncacheSessionID(sec->ci.sid);
-    } else if (!ss->resumptionTokenCallback) {
-        LockAndUncacheSID(sec->ci.sid);
+    if (sec->ci.sid) {
+        if (sec->isServer) {
+            ssl_ServerUncacheSessionID(sec->ci.sid);
+        } else if (!ss->resumptionTokenCallback) {
+            LockAndUncacheSID(sec->ci.sid);
+        }
     }
 }
 
 /* wipe out the entire client session cache. */
 void
 SSL_ClearSessionCache(void)
 {
     LOCK_CACHE;
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -48,44 +48,45 @@ static const sslSocketOps ssl_secure_ops
                                              ssl_DefGetpeername,
                                              ssl_DefGetsockname
 };
 
 /*
 ** default settings for socket enables
 */
 static sslOptions ssl_defaults = {
-    { siBuffer, NULL, 0 }, /* nextProtoNego */
-    PR_TRUE,               /* useSecurity        */
-    PR_FALSE,              /* useSocks           */
-    PR_FALSE,              /* requestCertificate */
-    2,                     /* requireCertificate */
-    PR_FALSE,              /* handshakeAsClient  */
-    PR_FALSE,              /* handshakeAsServer  */
-    PR_FALSE,              /* noCache            */
-    PR_FALSE,              /* fdx                */
-    PR_TRUE,               /* detectRollBack     */
-    PR_FALSE,              /* noLocks            */
-    PR_FALSE,              /* enableSessionTickets */
-    PR_FALSE,              /* enableDeflate      */
-    2,                     /* enableRenegotiation (default: requires extension) */
-    PR_FALSE,              /* requireSafeNegotiation */
-    PR_FALSE,              /* enableFalseStart   */
-    PR_TRUE,               /* cbcRandomIV        */
-    PR_FALSE,              /* enableOCSPStapling */
-    PR_FALSE,              /* enableNPN          */
-    PR_TRUE,               /* enableALPN         */
-    PR_TRUE,               /* reuseServerECDHEKey */
-    PR_FALSE,              /* enableFallbackSCSV */
-    PR_TRUE,               /* enableServerDhe */
-    PR_FALSE,              /* enableExtendedMS    */
-    PR_FALSE,              /* enableSignedCertTimestamps */
-    PR_FALSE,              /* requireDHENamedGroups */
-    PR_FALSE,              /* enable0RttData */
-    PR_FALSE               /* enableTls13CompatMode */
+    .nextProtoNego = { siBuffer, NULL, 0 },
+    .maxEarlyDataSize = 1 << 16,
+    .useSecurity = PR_TRUE,
+    .useSocks = PR_FALSE,
+    .requestCertificate = PR_FALSE,
+    .requireCertificate = SSL_REQUIRE_FIRST_HANDSHAKE,
+    .handshakeAsClient = PR_FALSE,
+    .handshakeAsServer = PR_FALSE,
+    .noCache = PR_FALSE,
+    .fdx = PR_FALSE,
+    .detectRollBack = PR_TRUE,
+    .noLocks = PR_FALSE,
+    .enableSessionTickets = PR_FALSE,
+    .enableDeflate = PR_FALSE,
+    .enableRenegotiation = SSL_RENEGOTIATE_REQUIRES_XTN,
+    .requireSafeNegotiation = PR_FALSE,
+    .enableFalseStart = PR_FALSE,
+    .cbcRandomIV = PR_TRUE,
+    .enableOCSPStapling = PR_FALSE,
+    .enableNPN = PR_FALSE,
+    .enableALPN = PR_TRUE,
+    .reuseServerECDHEKey = PR_TRUE,
+    .enableFallbackSCSV = PR_FALSE,
+    .enableServerDhe = PR_TRUE,
+    .enableExtendedMS = PR_FALSE,
+    .enableSignedCertTimestamps = PR_FALSE,
+    .requireDHENamedGroups = PR_FALSE,
+    .enable0RttData = PR_FALSE,
+    .enableTls13CompatMode = PR_FALSE
 };
 
 /*
  * default range of enabled SSL/TLS protocols
  */
 static SSLVersionRange versions_defaults_stream = {
     SSL_LIBRARY_VERSION_TLS_1_0,
     SSL_LIBRARY_VERSION_TLS_1_2
@@ -1247,16 +1248,28 @@ SSL_OptionSetDefault(PRInt32 which, PRIn
 
         default:
             PORT_SetError(SEC_ERROR_INVALID_ARGS);
             return SECFailure;
     }
     return SECSuccess;
 }
 
+SECStatus
+SSLExp_SetMaxEarlyDataSize(PRFileDesc *fd, PRUint32 size)
+{
+    sslSocket *ss = ssl_FindSocket(fd);
+    if (!ss) {
+        return SECFailure; /* Error code already set. */
+    }
+
+    ss->opt.maxEarlyDataSize = size;
+    return SECSuccess;
+}
+
 /* function tells us if the cipher suite is one that we no longer support. */
 static PRBool
 ssl_IsRemovedCipherSuite(PRInt32 suite)
 {
     switch (suite) {
         case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
         case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
         case SSL_FORTEZZA_DMS_WITH_RC4_128_SHA:
@@ -3927,16 +3940,17 @@ struct {
     void *function;
 } ssl_experimental_functions[] = {
 #ifndef SSL_DISABLE_EXPERIMENTAL_API
     EXP(GetExtensionSupport),
     EXP(HelloRetryRequestCallback),
     EXP(InstallExtensionHooks),
     EXP(KeyUpdate),
     EXP(SendSessionTicket),
+    EXP(SetMaxEarlyDataSize),
     EXP(SetupAntiReplay),
     EXP(SetResumptionTokenCallback),
     EXP(SetResumptionToken),
     EXP(GetResumptionTokenInfo),
     EXP(DestroyResumptionTokenInfo),
 #endif
     { "", NULL }
 };
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -4412,18 +4412,16 @@ tls13_SendClientSecondRound(sslSocket *s
  *       uint32 ticket_lifetime;
  *       uint32 ticket_age_add;
  *       opaque ticket_nonce<1..255>;
  *       opaque ticket<1..2^16-1>;
  *       TicketExtension extensions<0..2^16-2>;
  *   } NewSessionTicket;
  */
 
-PRUint32 ssl_max_early_data_size = (2 << 16); /* Arbitrary limit. */
-
 static SECStatus
 tls13_SendNewSessionTicket(sslSocket *ss, const PRUint8 *appToken,
                            unsigned int appTokenLen)
 {
     PRUint16 message_length;
     PK11SymKey *secret;
     SECItem ticket_data = { 0, NULL, 0 };
     SECStatus rv;
@@ -4515,17 +4513,17 @@ tls13_SendNewSessionTicket(sslSocket *ss
         if (rv != SECSuccess)
             goto loser;
 
         /* Length */
         rv = ssl3_AppendHandshakeNumber(ss, 4, 2);
         if (rv != SECSuccess)
             goto loser;
 
-        rv = ssl3_AppendHandshakeNumber(ss, ssl_max_early_data_size, 4);
+        rv = ssl3_AppendHandshakeNumber(ss, ss->opt.maxEarlyDataSize, 4);
         if (rv != SECSuccess)
             goto loser;
     }
 
     SECITEM_FreeItem(&ticket_data, PR_FALSE);
     return SECSuccess;
 
 loser:
--- a/security/nss/tests/interop/interop.sh
+++ b/security/nss/tests/interop/interop.sh
@@ -52,17 +52,22 @@ interop_cleanup()
 interop_run()
 {
   test_name=$1
   client=$2
   server=$3
 
   (cd "$INTEROP";
    cargo run -- --client "$client" --server "$server" --rootdir "$BORING"/ssl/test/runner/ --test-cases cases.json) 2>interop-${test_name}.errors | tee interop-${test_name}.log
-  html_msg "${PIPESTATUS[0]}" 0 "Interop" "Run successfully"
+  RESULT=${PIPESTATUS[0]}
+  html_msg "${RESULT}" 0 "Interop" "Run successfully"
+  if [ $RESULT -ne 0 ]; then
+    cat interop-${test_name}.errors
+    cat interop-${test_name}.log
+  fi
   grep -i 'FAILED\|Assertion failure' interop-${test_name}.errors
   html_msg $? 1 "Interop" "No failures"
 }
 
 cd "$(dirname "$0")"
 SOURCE_DIR="$PWD"/../..
 interop_init
 NSS_SHIM="$BINDIR"/nss_bogo_shim