Bug 1317947 - land NSS 0x5b7a40ced8c5, r=me
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Wed, 16 Nov 2016 14:06:23 +0100
changeset 322832 f296d03423848da45f1839b946b103047834b459
parent 322831 3cbb93f5768e0e5ac470d3bb29cea58fe2f45df3
child 322833 9611f0e821c2fe892e5a42002c71f94b2662cd70
push id30961
push userkwierso@gmail.com
push dateThu, 17 Nov 2016 01:08:03 +0000
treeherdermozilla-central@c27117f67fa3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1317947
milestone53.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 1317947 - land NSS 0x5b7a40ced8c5, r=me
security/nss/Makefile
security/nss/TAG-INFO
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/run_tests.sh
security/nss/build.sh
security/nss/cmd/certutil/certutil.c
security/nss/cmd/ecperf/ecperf.c
security/nss/cmd/ecperf/ecperf.gyp
security/nss/cmd/fbectest/fbectest.c
security/nss/cmd/fbectest/fbectest.gyp
security/nss/cmd/lib/exports.gyp
security/nss/cmd/lib/secutil.c
security/nss/cmd/lib/secutil.h
security/nss/cmd/modutil/modutil.gyp
security/nss/cmd/mpitests/mpi-test.c
security/nss/cmd/mpitests/mpitests.gyp
security/nss/cmd/mpitests/test-info.c
security/nss/cmd/pk11ectest/testvecs.h
security/nss/cmd/tstclnt/tstclnt.c
security/nss/coreconf/check_cc_clang.py
security/nss/coreconf/config.gypi
security/nss/coreconf/coreconf.dep
security/nss/coreconf/detect_host_arch.py
security/nss/coreconf/nspr.sh
security/nss/coreconf/pkg_config.py
security/nss/coreconf/sanitizers.py
security/nss/coreconf/shlibsign.py
security/nss/coreconf/werror.py
security/nss/exports.gyp
security/nss/fuzz/Makefile
security/nss/fuzz/cert_target.cc
security/nss/fuzz/clone_libfuzzer.sh
security/nss/fuzz/common.mk
security/nss/fuzz/fuzz.gyp
security/nss/fuzz/libFuzzer/Makefile
security/nss/fuzz/libFuzzer/config.mk
security/nss/fuzz/libFuzzer/libFuzzer.gyp
security/nss/fuzz/libFuzzer/manifest.mn
security/nss/fuzz/manifest.mn
security/nss/fuzz/nssfuzz.cc
security/nss/fuzz/nssfuzz/Makefile
security/nss/fuzz/nssfuzz/cert_target.cc
security/nss/fuzz/nssfuzz/manifest.mn
security/nss/fuzz/nssfuzz/nssfuzz.cc
security/nss/fuzz/nssfuzz/pkcs8_target.cc
security/nss/fuzz/nssfuzz/registry.h
security/nss/fuzz/nssfuzz/shared.h
security/nss/fuzz/nssfuzz/spki_target.cc
security/nss/fuzz/pkcs8_target.cc
security/nss/fuzz/registry.h
security/nss/fuzz/shared.h
security/nss/fuzz/spki_target.cc
security/nss/gtests/common/scoped_ptrs.h
security/nss/gtests/der_gtest/der_gtest.gyp
security/nss/gtests/freebl_gtest/freebl_gtest.gyp
security/nss/gtests/freebl_gtest/mpi_unittest.cc
security/nss/gtests/nss_bogo_shim/config.json
security/nss/gtests/ssl_gtest/databuffer.h
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_agent_unittest.cc
security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc
security/nss/gtests/ssl_gtest/ssl_cert_ext_unittest.cc
security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc
security/nss/gtests/ssl_gtest/ssl_exporter_unittest.cc
security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc
security/nss/gtests/ssl_gtest/ssl_gtest.gyp
security/nss/gtests/ssl_gtest/ssl_hrr_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/gtests/ssl_gtest/tls_filter.cc
security/nss/gtests/ssl_gtest/tls_filter.h
security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc
security/nss/lib/base/exports.gyp
security/nss/lib/certdb/exports.gyp
security/nss/lib/certhigh/exports.gyp
security/nss/lib/ckfw/builtins/exports.gyp
security/nss/lib/ckfw/exports.gyp
security/nss/lib/crmf/crmf.gyp
security/nss/lib/crmf/exports.gyp
security/nss/lib/cryptohi/exports.gyp
security/nss/lib/dbm/include/exports.gyp
security/nss/lib/dev/exports.gyp
security/nss/lib/freebl/exports.gyp
security/nss/lib/freebl/freebl.gyp
security/nss/lib/freebl/mpi/mpi-test.c
security/nss/lib/freebl/mpi/mpi.c
security/nss/lib/freebl/mpi/mpi.h
security/nss/lib/freebl/mpi/test-arrays.txt
security/nss/lib/freebl/mpi/test-info.c
security/nss/lib/jar/exports.gyp
security/nss/lib/libpkix/include/exports.gyp
security/nss/lib/libpkix/pkix/certsel/exports.gyp
security/nss/lib/libpkix/pkix/checker/exports.gyp
security/nss/lib/libpkix/pkix/crlsel/exports.gyp
security/nss/lib/libpkix/pkix/params/exports.gyp
security/nss/lib/libpkix/pkix/results/exports.gyp
security/nss/lib/libpkix/pkix/store/exports.gyp
security/nss/lib/libpkix/pkix/top/exports.gyp
security/nss/lib/libpkix/pkix/util/exports.gyp
security/nss/lib/libpkix/pkix_pl_nss/module/exports.gyp
security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp
security/nss/lib/libpkix/pkix_pl_nss/system/exports.gyp
security/nss/lib/nss/exports.gyp
security/nss/lib/nss/nss.h
security/nss/lib/pk11wrap/exports.gyp
security/nss/lib/pkcs12/exports.gyp
security/nss/lib/pkcs7/exports.gyp
security/nss/lib/pki/exports.gyp
security/nss/lib/smime/exports.gyp
security/nss/lib/softoken/exports.gyp
security/nss/lib/softoken/softkver.h
security/nss/lib/sqlite/exports.gyp
security/nss/lib/ssl/SSLerrs.h
security/nss/lib/ssl/dtlscon.c
security/nss/lib/ssl/exports.gyp
security/nss/lib/ssl/ssl.def
security/nss/lib/ssl/ssl.h
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ext.c
security/nss/lib/ssl/ssl3ext.h
security/nss/lib/ssl/ssl3exthandle.c
security/nss/lib/ssl/ssl3prot.h
security/nss/lib/ssl/sslcert.c
security/nss/lib/ssl/sslerr.h
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslinfo.c
security/nss/lib/ssl/sslsock.c
security/nss/lib/ssl/sslt.h
security/nss/lib/ssl/tls13con.c
security/nss/lib/ssl/tls13con.h
security/nss/lib/ssl/tls13exthandle.c
security/nss/lib/ssl/tls13exthandle.h
security/nss/lib/ssl/tls13hkdf.c
security/nss/lib/util/exports.gyp
security/nss/lib/util/nssutil.h
security/nss/lib/zlib/exports.gyp
security/nss/manifest.mn
security/nss/nss.gyp
security/nss/tests/bogo/bogo.sh
security/nss/tests/common/init.sh
security/nss/tests/mpi/mpi.sh
security/nss/tests/run.sh
security/nss/tests/ssl_gtests/ssl_gtests.sh
--- a/security/nss/Makefile
+++ b/security/nss/Makefile
@@ -41,17 +41,17 @@ include $(CORE_DEPTH)/coreconf/rules.mk
 #######################################################################
 
 
 
 #######################################################################
 # (7) Execute "local" rules. (OPTIONAL).                              #
 #######################################################################
 
-nss_build_all: build_nspr all
+nss_build_all: build_nspr all latest
 
 nss_clean_all: clobber_nspr clobber
 
 NSPR_CONFIG_STATUS = $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME)/config.status
 NSPR_CONFIGURE = $(CORE_DEPTH)/../nspr/configure
 
 #
 # Translate coreconf build options to NSPR configure options.
@@ -158,8 +158,11 @@ build_docs:
 clean_docs:
 	$(MAKE) -C $(CORE_DEPTH)/doc clean
 
 nss_RelEng_bld: import all
 
 package:
 	$(MAKE) -C pkg publish
 
+latest:
+	echo $(OBJDIR_NAME) > $(CORE_DEPTH)/../dist/latest
+
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-5d2424d699a0
+5b7a40ced8c5
--- a/security/nss/automation/taskcluster/docker/setup.sh
+++ b/security/nss/automation/taskcluster/docker/setup.sh
@@ -20,16 +20,19 @@ apt_packages+=('ninja-build')
 apt_packages+=('pkg-config')
 apt_packages+=('zlib1g-dev')
 
 # 32-bit builds
 apt_packages+=('lib32z1-dev')
 apt_packages+=('gcc-multilib')
 apt_packages+=('g++-multilib')
 
+# ct-verif and sanitizers
+apt_packages+=('valgrind')
+
 # Latest Mercurial.
 apt_packages+=('mercurial')
 apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 41BD8711B1F0EC2B0D85B91CF59CE3A8323293EE
 echo "deb http://ppa.launchpad.net/mercurial-ppa/releases/ubuntu xenial main" > /etc/apt/sources.list.d/mercurial.list
 
 # gcc 4.8 and 6
 apt_packages+=('g++-6')
 apt_packages+=('g++-4.8')
--- a/security/nss/automation/taskcluster/graph/src/extend.js
+++ b/security/nss/automation/taskcluster/graph/src/extend.js
@@ -12,17 +12,18 @@ const WINDOWS_CHECKOUT_CMD =
     "(sleep 2; hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss) || " +
     "(sleep 5; hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss)\"";
 
 /*****************************************************************************/
 
 queue.filter(task => {
   if (task.group == "Builds") {
     // Remove extra builds on {A,UB}San and ARM.
-    if (task.collection == "asan" || task.collection == "arm-debug") {
+    if (task.collection == "asan" || task.collection == "arm-debug" ||
+        task.collection == "gyp-asan") {
       return false;
     }
 
     // Remove extra builds w/o libpkix for non-linux64-debug.
     if (task.symbol == "noLibpkix" &&
         (task.platform != "linux64" || task.collection != "debug")) {
       return false;
     }
@@ -36,43 +37,44 @@ queue.filter(task => {
 
     // No BoGo tests on ARM.
     if (task.collection == "arm-debug") {
       return false;
     }
   }
 
   // GYP builds with -Ddisable_libpkix=1 by default.
-  if (task.collection == "gyp" && task.tests == "chains") {
+  if ((task.collection == "gyp" || task.collection == "gyp-asan") &&
+      task.tests == "chains") {
     return false;
   }
 
   return true;
 });
 
 queue.map(task => {
-  if (task.collection == "asan") {
+  if (task.collection == "asan" || task.collection == "gyp-asan") {
     // CRMF and FIPS tests still leak, unfortunately.
     if (task.tests == "crmf" || task.tests == "fips") {
       task.env.ASAN_OPTIONS = "detect_leaks=0";
     }
-
-    // SSL(standard) runs on ASan take some time.
-    if (task.tests == "ssl" && task.cycle == "standard") {
-      task.maxRunTime = 7200;
-    }
   }
 
   if (task.collection == "arm-debug") {
     // These tests take quite some time on our poor ARM devices.
     if (task.tests == "chains" || (task.tests == "ssl" && task.cycle == "standard")) {
       task.maxRunTime = 14400;
     }
   }
 
+  // Windows is slow.
+  if (task.platform == "windows2012-64" && task.tests == "chains") {
+    task.maxRunTime = 7200;
+  }
+
   // Enable TLS 1.3 for every task.
   task.env = task.env || {};
   task.env.NSS_ENABLE_TLS_1_3 = "1";
 
   return task;
 });
 
 /*****************************************************************************/
@@ -109,16 +111,35 @@ export default async function main() {
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/build_gyp.sh"
     ],
     platform: "linux64",
     collection: "gyp",
     image: LINUX_IMAGE
   });
 
+  await scheduleLinux("Linux 64 (debug, gyp, asan, ubsan)", {
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/build_gyp.sh -g -v --ubsan --asan"
+    ],
+    env: {
+      ASAN_OPTIONS: "detect_odr_violation=0", // bug 1316276
+      UBSAN_OPTIONS: "print_stacktrace=1",
+      NSS_DISABLE_ARENA_FREE_LIST: "1",
+      NSS_DISABLE_UNLOAD: "1",
+      CC: "clang",
+      CCC: "clang++"
+    },
+    platform: "linux64",
+    collection: "gyp-asan",
+    image: LINUX_IMAGE
+  });
+
   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++",
       USE_UBSAN: "1",
@@ -135,16 +156,18 @@ export default async function main() {
   });
 
   await scheduleWindows("Windows 2012 64 (debug)", {
     collection: "debug"
   });
 
   await scheduleFuzzing();
 
+  await scheduleTestBuilds();
+
   await scheduleTools();
 
   await scheduleLinux("Linux 32 (ARM, debug)", {
     image: "franziskus/nss-arm-ci",
     provisioner: "localprovisioner",
     collection: "arm-debug",
     workerType: "nss-rpi",
     platform: "linux32",
@@ -236,17 +259,18 @@ async function scheduleLinux(name, base)
   return queue.submit();
 }
 
 /*****************************************************************************/
 
 async function scheduleFuzzing() {
   let base = {
     env: {
-      ASAN_OPTIONS: "allocator_may_return_null=1",
+       // bug 1316276
+      ASAN_OPTIONS: "allocator_may_return_null=1:detect_odr_violation=0",
       UBSAN_OPTIONS: "print_stacktrace=1",
       CC: "clang",
       CCC: "clang++"
     },
     platform: "linux64",
     collection: "fuzz",
     image: LINUX_IMAGE
   };
@@ -291,16 +315,68 @@ async function scheduleFuzzing() {
     kind: "test"
   }));
 
   return queue.submit();
 }
 
 /*****************************************************************************/
 
+async function scheduleTestBuilds() {
+  let base = {
+    platform: "linux64",
+    collection: "gyp",
+    group: "Test",
+    image: LINUX_IMAGE
+  };
+
+  // Build base definition.
+  let build = merge({
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && " +
+      "nss/automation/taskcluster/scripts/build_gyp.sh -g -v --test"
+    ],
+    artifacts: {
+      public: {
+        expires: 24 * 7,
+        type: "directory",
+        path: "/home/worker/artifacts"
+      }
+    },
+    kind: "build",
+    symbol: "B",
+    name: "Linux 64 (debug, gyp, test)"
+  }, base);
+
+  // The task that builds NSPR+NSS.
+  let task_build = queue.scheduleTask(build);
+
+  // Schedule tests.
+  queue.scheduleTask(merge(base, {
+    parent: task_build,
+    name: "mpi",
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/run_tests.sh"
+    ],
+    tests: "mpi",
+    cycle: "standard",
+    symbol: "mpi",
+    kind: "test"
+  }));
+
+  return queue.submit();
+}
+
+
+/*****************************************************************************/
+
 async function scheduleWindows(name, base) {
   base = merge(base, {
     workerType: "nss-win2012r2",
     platform: "windows2012-64",
     env: {
       PATH: "c:\\mozilla-build\\python;c:\\mozilla-build\\msys\\local\\bin;" +
             "c:\\mozilla-build\\7zip;c:\\mozilla-build\\info-zip;" +
             "c:\\mozilla-build\\python\\Scripts;c:\\mozilla-build\\yasm;" +
--- a/security/nss/automation/taskcluster/graph/src/try_syntax.js
+++ b/security/nss/automation/taskcluster/graph/src/try_syntax.js
@@ -18,29 +18,29 @@ function parseOptions(opts) {
 
   // If the given value is nonsense default to debug and opt builds.
   if (builds.length == 0) {
     builds = ["d", "o"];
   }
 
   // Parse platforms.
   let allPlatforms = ["linux", "linux64", "linux64-asan", "win64", "arm",
-                      "linux64-gyp", "linux64-fuzz"];
+                      "linux64-gyp", "linux64-gyp-asan", "linux64-fuzz"];
   let platforms = intersect(opts.platform.split(/\s*,\s*/), allPlatforms);
 
   // If the given value is nonsense or "none" default to all platforms.
   if (platforms.length == 0 && opts.platform != "none") {
     platforms = allPlatforms;
   }
 
   // Parse unit tests.
   let aliases = {"gtests": "gtest"};
   let allUnitTests = ["bogo", "crmf", "chains", "cipher", "db", "ec", "fips",
                       "gtest", "lowhash", "merge", "sdr", "smime", "tools",
-                      "ssl"];
+                      "ssl", "mpi"];
   let unittests = intersect(opts.unittests.split(/\s*,\s*/).map(t => {
     return aliases[t] || t;
   }), allUnitTests);
 
   // If the given value is "all" run all tests.
   // If it's nonsense then don't run any tests.
   if (opts.unittests == "all") {
     unittests = allUnitTests;
@@ -77,16 +77,20 @@ function filter(opts) {
       return opts.tools.some(tool => {
         return task.symbol.toLowerCase().startsWith(tool);
       });
     }
 
     // Filter unit tests.
     if (task.tests) {
       let found = opts.unittests.some(test => {
+        // TODO: think of something more intelligent here.
+        if (task.symbol.toLowerCase().startsWith("mpi") && test == "mpi") {
+          return true;
+        }
         return (task.group || task.symbol).toLowerCase().startsWith(test);
       });
 
       if (!found) {
         return false;
       }
     }
 
@@ -99,30 +103,33 @@ function filter(opts) {
 
     // Filter by platform.
     let found = opts.platforms.some(platform => {
       let aliases = {
         "linux": "linux32",
         "linux64-asan": "linux64",
         "linux64-fuzz": "linux64",
         "linux64-gyp": "linux64",
+        "linux64-gyp-asan": "linux64",
         "win64": "windows2012-64",
         "arm": "linux32"
       };
 
       // Check the platform name.
       let keep = (task.platform == (aliases[platform] || platform));
 
       // Additional checks.
       if (platform == "linux64-asan") {
         keep &= coll("asan");
       } else if (platform == "arm") {
         keep &= coll("arm-opt") || coll("arm-debug");
       } else if (platform == "linux64-gyp") {
         keep &= coll("gyp");
+      } else if (platform == "linux64-gyp-asan") {
+        keep &= coll("gyp-asan");
       } else if (platform == "linux64-fuzz") {
         keep &= coll("fuzz");
       } else {
         keep &= coll("opt") || coll("debug");
       }
 
       return keep;
     });
--- a/security/nss/automation/taskcluster/scripts/run_tests.sh
+++ b/security/nss/automation/taskcluster/scripts/run_tests.sh
@@ -9,9 +9,9 @@ if [ $(id -u) = 0 ]; then
     # Drop privileges by re-running this script.
     exec su worker $0
 fi
 
 # Fetch artifact if needed.
 fetch_dist
 
 # Run tests.
-cd nss/tests && ./run.sh
+cd nss/tests && ./all.sh
--- a/security/nss/build.sh
+++ b/security/nss/build.sh
@@ -1,22 +1,24 @@
 #!/bin/bash
 # This script builds NSS with gyp and ninja.
 #
 # This build system is still under development.  It does not yet support all
 # the features or platforms that NSS supports.
 
 set -e
 
+source $(dirname $0)/coreconf/nspr.sh
+
 # Usage info
 show_help() {
 cat << EOF
 
 Usage: ${0##*/} [-hcgv] [-j <n>] [--test] [--fuzz] [--scan-build[=output]]
-                [-m32] [--opt|-o]
+                [-m32] [--opt|-o] [--asan] [--ubsan] [--sancov[=edge|bb|func]]
 
 This script builds NSS with gyp and ninja.
 
 This build system is still under development.  It does not yet support all
 the features or platforms that NSS supports.
 
 NSS build tool options:
 
@@ -26,112 +28,155 @@ NSS build tool options:
     -j <n>        run at most <n> concurrent jobs
     -v            verbose build
     -m32          do a 32-bit build on a 64-bit system
     --test        ignore map files and export everything we have
     --fuzz        enable fuzzing mode. this always enables test builds
     --scan-build  run the build with scan-build (scan-build has to be in the path)
                   --scan-build=/out/path sets the output path for scan-build
     --opt|-o      do an opt build
+    --asan        do an asan build
+    --ubsan       do an ubsan build
+    --sancov      do sanitize coverage builds
+                  --sancov=func sets coverage to function level for example
 EOF
 }
 
 if [ -n "$CCC" ] && [ -z "$CXX" ]; then
     export CXX="$CCC"
 fi
 
 opt_build=0
 build_64=0
 clean=0
 rebuild_gyp=0
 target=Debug
+params=$(echo "$* $CC $CCC" | tr " " "\n")
+verbose=0
+
+cwd=$(cd $(dirname $0); pwd -P)
+dist_dir="$cwd/../dist"
+
+cwd=$(cd $(dirname $0); pwd -P)
+dist_dir="$cwd/../dist"
 
 # try to guess sensible defaults
-arch=$(uname -m)
-if [ "$arch" = "x86_64" -o "$arch" = "aarch64" ]; then
+arch=$(python "$cwd/coreconf/detect_host_arch.py")
+if [ "$arch" = "x64" -o "$arch" = "aarch64" ]; then
     build_64=1
 fi
 
 gyp_params=()
 ninja_params=()
 scanbuild=()
-nspr_env=()
+
+enable_fuzz()
+{
+    nspr_sanitizer asan
+    nspr_sanitizer ubsan
+    nspr_sanitizer sancov edge
+    gyp_params+=(-Duse_asan=1)
+    gyp_params+=(-Duse_ubsan=1)
+    gyp_params+=(-Duse_sancov=edge)
+
+    # Adding debug symbols even for opt builds.
+    nspr_opt+=(--enable-debug-symbols)
+
+    # Clone libFuzzer repository.
+    $cwd/fuzz/clone_libfuzzer.sh &>/dev/null
+}
 
 # parse command line arguments
 while [ $# -gt 0 ]; do
     case $1 in
         -c) clean=1 ;;
         -g) rebuild_gyp=1 ;;
         -j) ninja_params+=(-j "$2"); shift ;;
-        -v) ninja_params+=(-v) ;;
+        -v) ninja_params+=(-v); verbose=1 ;;
         --test) gyp_params+=(-Dtest_build=1) ;;
-        --fuzz) gyp_params+=(-Dtest_build=1 -Dfuzz=1) ;;
+        --fuzz) gyp_params+=(-Dtest_build=1 -Dfuzz=1); enable_fuzz ;;
         --scan-build) scanbuild=(scan-build) ;;
         --scan-build=?*) scanbuild=(scan-build -o "${1#*=}") ;;
-        --opt|-o) opt_build=1; nspr_env+=(BUILD_OPT=1) ;;
+        --opt|-o) opt_build=1 ;;
         -m32|--m32) build_64=0 ;;
+        --asan) gyp_params+=(-Duse_asan=1); nspr_sanitizer asan ;;
+        --ubsan) gyp_params+=(-Duse_ubsan=1); nspr_sanitizer ubsan ;;
+        --sancov) gyp_params+=(-Duse_sancov=edge); nspr_sanitizer sancov edge ;;
+        --sancov=?*) gyp_params+=(-Duse_sancov="${1#*=}"); nspr_sanitizer sancov "${1#*=}" ;;
         *) show_help; exit ;;
     esac
     shift
 done
 
 if [ "$opt_build" = "1" ]; then
     target=Release
+    nspr_opt+=(--disable-debug --enable-optimize)
 else
     target=Debug
 fi
 if [ "$build_64" == "1" ]; then
-    target="${target}_x64"
-    nspr_env+=(USE_64=1)
+    nspr_opt+=(--enable-64bit)
 else
     gyp_params+=(-Dtarget_arch=ia32)
+    nspr_opt+=(--enable-x32)
+fi
+
+# check if we have to rebuild gyp
+if [ "$params" != "$(cat $cwd/out/config 2>/dev/null)" -o "$rebuild_gyp" == 1 -o "$clean" == 1 ]; then
+    rebuild_gyp=1
+    rm -rf "$cwd/../nspr/$target" # force NSPR to rebuild
 fi
 
 # set paths
-cwd=$(cd $(dirname $0); pwd -P)
-dist_dir="$cwd/../dist"
 target_dir="$cwd/out/$target"
 
 # get the realpath of $dist_dir
 dist_dir=$(mkdir -p $dist_dir; cd $dist_dir; pwd -P)
 
-# save the chosen target
-echo $target > $dist_dir/latest
-
 # get object directory
 obj_dir="$dist_dir/$target"
 gyp_params+=(-Dnss_dist_dir=$dist_dir)
 gyp_params+=(-Dnss_dist_obj_dir=$obj_dir)
+gyp_params+=(-Dnspr_lib_dir=$obj_dir/lib)
+gyp_params+=(-Dnspr_include_dir=$obj_dir/include/nspr)
 
 # -c = clean first
 if [ "$clean" = 1 ]; then
     rm -rf "$cwd/out"
     rm -rf "$cwd/../nspr/$target"
+    rm -rf "$dist_dir"
 fi
 
-# figure out the scan-build string
+# save the chosen target
+mkdir -p $dist_dir
+echo $target > $dist_dir/latest
+
+# pass on CC and CCC
 if [ "${#scanbuild[@]}" -gt 0 ]; then
     if [ -n "$CC" ]; then
        scanbuild+=(--use-cc="$CC")
     fi
     if [ -n "$CCC" ]; then
        scanbuild+=(--use-c++="$CCC")
     fi
  fi
 
 # These steps can take a while, so don't overdo them.
 # Force a redo with -g.
 if [ "$rebuild_gyp" = 1 -o ! -d "$target_dir" ]; then
-    # Build NSPR.
-    make "${nspr_env[@]}" -C "$cwd" NSS_GYP_PREFIX=$obj_dir install_nspr
+    build_nspr $verbose
 
     # Run gyp.
-    PKG_CONFIG_PATH="$obj_dir/lib/pkgconfig" \
-        "${scanbuild[@]}" gyp -f ninja "${gyp_params[@]}" --depth="$cwd" \
-          --generator-output="." "$cwd/nss.gyp"
+    [ $verbose = 1 ] && set -v -x
+    "${scanbuild[@]}" gyp -f ninja "${gyp_params[@]}" --depth="$cwd" \
+      --generator-output="." "$cwd/nss.gyp"
+    [ $verbose = 1 ] && set +v +x
+
+    # Store used parameters for next run.
+    echo "$params" > "$cwd/out/config"
 fi
 
 # Run ninja.
 if which ninja >/dev/null 2>&1; then
     ninja=(ninja)
 elif which ninja-build >/dev/null 2>&1; then
     ninja=(ninja-build)
 else
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -199,16 +199,17 @@ CertReq(SECKEYPrivateKey *privk, SECKEYP
     if (!arena) {
         SECU_PrintError(progName, "out of memory");
         return SECFailure;
     }
 
     /* Create info about public key */
     spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
     if (!spki) {
+        PORT_FreeArena(arena, PR_FALSE);
         SECU_PrintError(progName, "unable to create subject public key");
         return SECFailure;
     }
 
     /* Change cert type to RSA-PSS, if desired. */
     if (pssCertificate) {
         spki->algorithm.parameters.data = NULL;
         rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
--- a/security/nss/cmd/ecperf/ecperf.c
+++ b/security/nss/cmd/ecperf/ecperf.c
@@ -4,16 +4,17 @@
 
 #include "blapi.h"
 #include "ec.h"
 #include "ecl-curve.h"
 #include "prprf.h"
 #include "basicutil.h"
 #include "pkcs11.h"
 #include "nspr.h"
+#include "secutil.h"
 #include <stdio.h>
 
 #define __PASTE(x, y) x##y
 
 /*
  * Get the NSS specific PKCS #11 function names.
  */
 #undef CK_PKCS11_FUNCTION_INFO
@@ -88,18 +89,16 @@ static SECOidTag ecCurve_oid_map[] = {
     SEC_OID_UNKNOWN, /* ECCurve_WTLS_9 */
     SEC_OID_CURVE25519,
     SEC_OID_UNKNOWN /* ECCurve_pastLastCurve */
 };
 
 typedef SECStatus (*op_func)(void *, void *, void *);
 typedef SECStatus (*pk11_op_func)(CK_SESSION_HANDLE, void *, void *, void *);
 
-typedef SECItem SECKEYECParams;
-
 typedef struct ThreadDataStr {
     op_func op;
     void *p1;
     void *p2;
     void *p3;
     int iters;
     PRLock *lock;
     int count;
@@ -287,70 +286,16 @@ M_TimeOperation(void (*threadFunc)(void 
     if (usepkcs11) {                                                              \
         printf("Testing %s using pkcs11 implementation...\n", name_c);            \
         rv = ectest_curve_pkcs11(name_v, iterations, numThreads);                 \
         if (rv != SECSuccess)                                                     \
             goto cleanup;                                                         \
         printf("... okay.\n");                                                    \
     }
 
-/*
- * Initializes a SECItem from a hexadecimal string
- *
- * Warning: This function ignores leading 00's, so any leading 00's
- * in the hexadecimal string must be optional.
- */
-static SECItem *
-hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
-{
-    int i = 0;
-    int byteval = 0;
-    int tmp = PORT_Strlen(str);
-
-    PORT_Assert(arena);
-    PORT_Assert(item);
-
-    if ((tmp % 2) != 0) {
-        return NULL;
-    }
-
-    /* skip leading 00's unless the hex string is "00" */
-    while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
-        str += 2;
-        tmp -= 2;
-    }
-
-    item = SECITEM_AllocItem(arena, item, tmp / 2);
-    if (item == NULL) {
-        return NULL;
-    }
-
-    while (str[i]) {
-        if ((str[i] >= '0') && (str[i] <= '9')) {
-            tmp = str[i] - '0';
-        } else if ((str[i] >= 'a') && (str[i] <= 'f')) {
-            tmp = str[i] - 'a' + 10;
-        } else if ((str[i] >= 'A') && (str[i] <= 'F')) {
-            tmp = str[i] - 'A' + 10;
-        } else {
-            /* item is in arena and gets freed by the caller */
-            return NULL;
-        }
-
-        byteval = byteval * 16 + tmp;
-        if ((i % 2) != 0) {
-            item->data[i / 2] = byteval;
-            byteval = 0;
-        }
-        i++;
-    }
-
-    return item;
-}
-
 #define PK11_SETATTRS(x, id, v, l) \
     (x)->type = (id);              \
     (x)->pValue = (v);             \
     (x)->ulValueLen = (l);
 
 SECStatus
 PKCS11_Derive(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey,
               CK_MECHANISM *pMech, int *dummy)
@@ -617,26 +562,26 @@ ectest_curve_freebl(ECCurveName curve, i
     ecParams.curve.seed.data = NULL;
     ecParams.curve.seed.len = 0;
     ecParams.DEREncoding.data = NULL;
     ecParams.DEREncoding.len = 0;
     ecParams.pointSize = ecCurve_map[curve]->pointSize;
 
     ecParams.fieldID.size = ecCurve_map[curve]->size;
     ecParams.fieldID.type = fieldType;
-    hexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
-    hexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
-    hexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
+    SECU_HexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
+    SECU_HexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
+    SECU_HexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
     genenc[0] = '0';
     genenc[1] = '4';
     genenc[2] = '\0';
     strcat(genenc, ecCurve_map[curve]->genx);
     strcat(genenc, ecCurve_map[curve]->geny);
-    hexString2SECItem(arena, &ecParams.base, genenc);
-    hexString2SECItem(arena, &ecParams.order, ecCurve_map[curve]->order);
+    SECU_HexString2SECItem(arena, &ecParams.base, genenc);
+    SECU_HexString2SECItem(arena, &ecParams.order, ecCurve_map[curve]->order);
     ecParams.cofactor = ecCurve_map[curve]->cofactor;
 
     PORT_Memset(digestData, 0xa5, sizeof(digestData));
     digest.data = digestData;
     digest.len = sizeof(digestData);
     sig.data = sigData;
     sig.len = sizeof(sigData);
 
--- a/security/nss/cmd/ecperf/ecperf.gyp
+++ b/security/nss/cmd/ecperf/ecperf.gyp
@@ -17,17 +17,17 @@
         '<(DEPTH)/exports.gyp:dbm_exports',
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3'
       ]
     }
   ],
   'target_defaults': {
     'include_dirs': [
-      '../../nss/lib/softoken'
+      '<(DEPTH)/lib/softoken',
     ],
     'defines': [
       'NSS_USE_STATIC_LIBS'
     ]
   },
   'variables': {
     'module': 'nss',
     'use_static_libs': 1
--- a/security/nss/cmd/fbectest/fbectest.c
+++ b/security/nss/cmd/fbectest/fbectest.c
@@ -4,16 +4,17 @@
 
 #include "blapi.h"
 #include "ec.h"
 #include "ecl-curve.h"
 #include "prprf.h"
 #include "basicutil.h"
 #include "secder.h"
 #include "secitem.h"
+#include "secutil.h"
 #include "nspr.h"
 #include <stdio.h>
 
 typedef struct {
     ECCurveName curve;
     int iterations;
     char *privhex;
     char *our_pubhex;
@@ -27,62 +28,16 @@ typedef struct {
     ECCurveName curve;
     char *point;
     char *name;
     ECFieldType fieldType;
 } ECDH_BAD;
 
 #include "testvecs.h"
 
-/*
- * Initializes a SECItem from a hexadecimal string
- *
- */
-static SECItem *
-hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
-{
-    int i = 0;
-    int byteval = 0;
-    int tmp = PORT_Strlen(str);
-
-    PORT_Assert(arena);
-    PORT_Assert(item);
-
-    if ((tmp % 2) != 0) {
-        return NULL;
-    }
-
-    item = SECITEM_AllocItem(arena, item, tmp / 2);
-    if (item == NULL) {
-        return NULL;
-    }
-
-    while (str[i]) {
-        if ((str[i] >= '0') && (str[i] <= '9')) {
-            tmp = str[i] - '0';
-        } else if ((str[i] >= 'a') && (str[i] <= 'f')) {
-            tmp = str[i] - 'a' + 10;
-        } else if ((str[i] >= 'A') && (str[i] <= 'F')) {
-            tmp = str[i] - 'A' + 10;
-        } else {
-            /* item is in arena and gets freed by the caller */
-            return NULL;
-        }
-
-        byteval = byteval * 16 + tmp;
-        if ((i % 2) != 0) {
-            item->data[i / 2] = byteval;
-            byteval = 0;
-        }
-        i++;
-    }
-
-    return item;
-}
-
 void
 printBuf(const SECItem *item)
 {
     int i;
     if (!item || !item->len) {
         printf("(null)\n");
         return;
     }
@@ -138,47 +93,47 @@ ectest_ecdh_kat(ECDH_KAT *kat)
     char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
     int i;
 
     rv = init_params(&ecParams, curve, &arena, kat->fieldType);
     if (rv != SECSuccess) {
         return rv;
     }
 
-    hexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
-    hexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
-    hexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
+    SECU_HexString2SECItem(arena, &ecParams.fieldID.u.prime, ecCurve_map[curve]->irr);
+    SECU_HexString2SECItem(arena, &ecParams.curve.a, ecCurve_map[curve]->curvea);
+    SECU_HexString2SECItem(arena, &ecParams.curve.b, ecCurve_map[curve]->curveb);
     genenc[0] = '0';
     genenc[1] = '4';
     genenc[2] = '\0';
     PORT_Assert(PR_ARRAY_SIZE(genenc) >= PORT_Strlen(ecCurve_map[curve]->genx));
     PORT_Assert(PR_ARRAY_SIZE(genenc) >= PORT_Strlen(ecCurve_map[curve]->geny));
     strcat(genenc, ecCurve_map[curve]->genx);
     strcat(genenc, ecCurve_map[curve]->geny);
-    hexString2SECItem(arena, &ecParams.base, genenc);
-    hexString2SECItem(arena, &ecParams.order, ecCurve_map[curve]->order);
+    SECU_HexString2SECItem(arena, &ecParams.base, genenc);
+    SECU_HexString2SECItem(arena, &ecParams.order, ecCurve_map[curve]->order);
 
     if (kat->our_pubhex) {
-        hexString2SECItem(arena, &answer, kat->our_pubhex);
+        SECU_HexString2SECItem(arena, &answer, kat->our_pubhex);
     }
-    hexString2SECItem(arena, &seed, kat->privhex);
+    SECU_HexString2SECItem(arena, &seed, kat->privhex);
     rv = EC_NewKeyFromSeed(&ecParams, &ecPriv, seed.data, seed.len);
     if (rv != SECSuccess) {
         rv = SECFailure;
         goto cleanup;
     }
     if (kat->our_pubhex) {
         if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) {
             rv = SECFailure;
             goto cleanup;
         }
     }
 
-    hexString2SECItem(arena, &theirKey, kat->their_pubhex);
-    hexString2SECItem(arena, &answer2, kat->common_key);
+    SECU_HexString2SECItem(arena, &theirKey, kat->their_pubhex);
+    SECU_HexString2SECItem(arena, &answer2, kat->common_key);
 
     rv = EC_ValidatePublicKey(&ecParams, &theirKey);
     if (rv != SECSuccess) {
         printf("EC_ValidatePublicKey failed\n");
         goto cleanup;
     }
 
     for (i = 0; i < kat->iterations; ++i) {
@@ -226,17 +181,17 @@ ectest_validate_point(ECDH_BAD *bad)
     SECStatus rv = SECFailure;
     PLArenaPool *arena = NULL;
 
     rv = init_params(&ecParams, bad->curve, &arena, bad->fieldType);
     if (rv != SECSuccess) {
         return rv;
     }
 
-    hexString2SECItem(arena, &point, bad->point);
+    SECU_HexString2SECItem(arena, &point, bad->point);
     rv = EC_ValidatePublicKey(&ecParams, &point);
 
     PORT_FreeArena(arena, PR_FALSE);
     return rv;
 }
 
 void
 printUsage(char *prog)
--- a/security/nss/cmd/fbectest/fbectest.gyp
+++ b/security/nss/cmd/fbectest/fbectest.gyp
@@ -16,17 +16,17 @@
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3'
       ]
     }
   ],
   'target_defaults': {
     'include_dirs': [
-      '../../nss/lib/softoken'
+      '<(DEPTH)/lib/softoken',
     ],
     'defines': [
       'NSS_USE_STATIC_LIBS'
     ]
   },
   'variables': {
     'module': 'nss',
     'use_static_libs': 1
--- a/security/nss/cmd/lib/exports.gyp
+++ b/security/nss/cmd/lib/exports.gyp
@@ -11,17 +11,17 @@
       'type': 'none',
       'copies': [
         {
           'files': [
             'basicutil.h',
             'pk11table.h',
             'secutil.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/cmd/lib/secutil.c
+++ b/security/nss/cmd/lib/secutil.c
@@ -3827,8 +3827,51 @@ SECU_ParseSSLVersionRangeString(const ch
 
     if (vrange->min > vrange->max) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
     return SECSuccess;
 }
+
+SECItem *
+SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
+{
+    int i = 0;
+    int byteval = 0;
+    int tmp = PORT_Strlen(str);
+
+    PORT_Assert(arena);
+    PORT_Assert(item);
+
+    if ((tmp % 2) != 0) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return NULL;
+    }
+
+    item = SECITEM_AllocItem(arena, item, tmp / 2);
+    if (item == NULL) {
+        return NULL;
+    }
+
+    while (str[i]) {
+        if ((str[i] >= '0') && (str[i] <= '9')) {
+            tmp = str[i] - '0';
+        } else if ((str[i] >= 'a') && (str[i] <= 'f')) {
+            tmp = str[i] - 'a' + 10;
+        } else if ((str[i] >= 'A') && (str[i] <= 'F')) {
+            tmp = str[i] - 'A' + 10;
+        } else {
+            /* item is in arena and gets freed by the caller */
+            return NULL;
+        }
+
+        byteval = byteval * 16 + tmp;
+        if ((i % 2) != 0) {
+            item->data[i / 2] = byteval;
+            byteval = 0;
+        }
+        i++;
+    }
+
+    return item;
+}
--- a/security/nss/cmd/lib/secutil.h
+++ b/security/nss/cmd/lib/secutil.h
@@ -317,22 +317,22 @@ extern SECOidTag SECU_StringToSignatureA
 extern SECStatus SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl,
                                PRFileDesc *outFile, PRBool ascii, char *url);
 
 /*
 ** DER sign a single block of data using private key encryption and the
 ** MD5 hashing algorithm. This routine first computes a digital signature
 ** using SEC_SignData, then wraps it with an CERTSignedData and then der
 ** encodes the result.
-**	"arena" is the memory arena to use to allocate data from
-**      "sd" returned CERTSignedData
-** 	"result" the final der encoded data (memory is allocated)
-** 	"buf" the input data to sign
-** 	"len" the amount of data to sign
-** 	"pk" the private key to encrypt with
+**     "arena" is the memory arena to use to allocate data from
+**     "sd" returned CERTSignedData
+**     "result" the final der encoded data (memory is allocated)
+**     "buf" the input data to sign
+**     "len" the amount of data to sign
+**     "pk" the private key to encrypt with
 */
 extern SECStatus SECU_DerSignDataCRL(PLArenaPool *arena, CERTSignedData *sd,
                                      unsigned char *buf, int len,
                                      SECKEYPrivateKey *pk, SECOidTag algID);
 
 typedef enum {
     noKeyFound = 1,
     noSignatureMatch = 2,
@@ -397,16 +397,21 @@ SECU_SECItemHexStringToBinary(SECItem *s
  * the caller must provide the desired default values for the min/max values,
  * by providing defaultVersionRange (which can be obtained from libssl by
  * calling SSL_VersionRangeGetSupported).
  */
 SECStatus
 SECU_ParseSSLVersionRangeString(const char *input,
                                 const SSLVersionRange defaultVersionRange,
                                 SSLVersionRange *vrange);
+/*
+** Read a hex string into a SecItem.
+*/
+extern SECItem *SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item,
+                                       const char *str);
 
 /*
  *
  *  Error messaging
  *
  */
 
 void printflags(char *trusts, unsigned int flags);
--- a/security/nss/cmd/modutil/modutil.gyp
+++ b/security/nss/cmd/modutil/modutil.gyp
@@ -24,18 +24,18 @@
         '<(DEPTH)/exports.gyp:dbm_exports',
         '<(DEPTH)/lib/jar/jar.gyp:jar',
         '<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib'
       ]
     }
   ],
   'target_defaults': {
     'include_dirs': [
-      '<(nss_dist_dir)/private/nss',
-      '<(nss_dist_dir)/private/dbm'
+      '<(nss_private_dist_dir)/nss',
+      '<(nss_private_dist_dir)/dbm'
     ],
     'defines': [
       'NSPR20',
       'YY_NO_UNPUT',
       'YY_NO_INPUT'
     ]
   },
   'variables': {
rename from security/nss/lib/freebl/mpi/mpi-test.c
rename to security/nss/cmd/mpitests/mpi-test.c
new file mode 100644
--- /dev/null
+++ b/security/nss/cmd/mpitests/mpitests.gyp
@@ -0,0 +1,30 @@
+# 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/.
+{
+  'includes': [
+    '../../coreconf/config.gypi',
+    '../../cmd/platlibs.gypi'
+  ],
+  'targets': [
+    {
+      'target_name': 'mpi_tests',
+      'type': 'executable',
+      'sources': [
+        'mpi-test.c',
+      ],
+      'dependencies': [
+        '<(DEPTH)/lib/freebl/freebl.gyp:<(freebl_name)',
+      ]
+    }
+  ],
+  'target_defaults': {
+    'include_dirs': [
+      '<(DEPTH)/lib/freebl/mpi',
+      '<(DEPTH)/lib/util',
+    ]
+  },
+  'variables': {
+    'module': 'nss'
+  }
+}
new file mode 100644
--- /dev/null
+++ b/security/nss/cmd/mpitests/test-info.c
@@ -0,0 +1,157 @@
+/*
+ *  test-info.c
+ *
+ *  Arbitrary precision integer arithmetic library
+ *
+ * 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/. */
+
+/* Table mapping test suite names to index numbers */
+const int g_count = 41;
+const char *g_names[] = {
+    "list",              /* print out a list of the available test suites */
+    "copy",              /* test assignment of mp-int structures          */
+    "exchange",          /* test exchange of mp-int structures            */
+    "zero",              /* test zeroing of an mp-int                     */
+    "set",               /* test setting an mp-int to a small constant    */
+    "absolute-value",    /* test the absolute value function              */
+    "negate",            /* test the arithmetic negation function         */
+    "add-digit",         /* test digit addition                           */
+    "add",               /* test full addition                            */
+    "subtract-digit",    /* test digit subtraction                        */
+    "subtract",          /* test full subtraction                         */
+    "multiply-digit",    /* test digit multiplication                     */
+    "multiply",          /* test full multiplication                      */
+    "square",            /* test full squaring function                   */
+    "divide-digit",      /* test digit division                           */
+    "divide-2",          /* test division by two                          */
+    "divide-2d",         /* test division & remainder by 2^d              */
+    "divide",            /* test full division                            */
+    "expt-digit",        /* test digit exponentiation                     */
+    "expt",              /* test full exponentiation                      */
+    "expt-2",            /* test power-of-two exponentiation              */
+    "modulo-digit",      /* test digit modular reduction                  */
+    "modulo",            /* test full modular reduction                   */
+    "mod-add",           /* test modular addition                         */
+    "mod-subtract",      /* test modular subtraction                      */
+    "mod-multiply",      /* test modular multiplication                   */
+    "mod-square",        /* test modular squaring function                */
+    "mod-expt",          /* test full modular exponentiation              */
+    "mod-expt-digit",    /* test digit modular exponentiation             */
+    "mod-inverse",       /* test modular inverse function                 */
+    "compare-digit",     /* test digit comparison function                */
+    "compare-zero",      /* test zero comparison function                 */
+    "compare",           /* test general signed comparison                */
+    "compare-magnitude", /* test general magnitude comparison             */
+    "parity",            /* test parity comparison functions              */
+    "gcd",               /* test greatest common divisor functions        */
+    "lcm",               /* test least common multiple function           */
+    "conversion",        /* test general radix conversion facilities      */
+    "binary",            /* test raw output format                        */
+    "pprime",            /* test probabilistic primality tester           */
+    "fermat"             /* test Fermat pseudoprimality tester            */
+};
+
+/* Test function prototypes */
+int test_list(void);
+int test_copy(void);
+int test_exch(void);
+int test_zero(void);
+int test_set(void);
+int test_abs(void);
+int test_neg(void);
+int test_add_d(void);
+int test_add(void);
+int test_sub_d(void);
+int test_sub(void);
+int test_mul_d(void);
+int test_mul(void);
+int test_sqr(void);
+int test_div_d(void);
+int test_div_2(void);
+int test_div_2d(void);
+int test_div(void);
+int test_expt_d(void);
+int test_expt(void);
+int test_2expt(void);
+int test_mod_d(void);
+int test_mod(void);
+int test_addmod(void);
+int test_submod(void);
+int test_mulmod(void);
+int test_sqrmod(void);
+int test_exptmod(void);
+int test_exptmod_d(void);
+int test_invmod(void);
+int test_cmp_d(void);
+int test_cmp_z(void);
+int test_cmp(void);
+int test_cmp_mag(void);
+int test_parity(void);
+int test_gcd(void);
+int test_lcm(void);
+int test_convert(void);
+int test_raw(void);
+int test_pprime(void);
+int test_fermat(void);
+
+/* Table mapping index numbers to functions */
+int (*g_tests[])(void) = {
+    test_list, test_copy, test_exch, test_zero,
+    test_set, test_abs, test_neg, test_add_d,
+    test_add, test_sub_d, test_sub, test_mul_d,
+    test_mul, test_sqr, test_div_d, test_div_2,
+    test_div_2d, test_div, test_expt_d, test_expt,
+    test_2expt, test_mod_d, test_mod,
+    test_addmod, test_submod, test_mulmod, test_sqrmod,
+    test_exptmod, test_exptmod_d, test_invmod, test_cmp_d,
+    test_cmp_z, test_cmp, test_cmp_mag, test_parity,
+    test_gcd, test_lcm, test_convert, test_raw,
+    test_pprime, test_fermat
+};
+
+/* Table mapping index numbers to descriptions */
+const char *g_descs[] = {
+    "print out a list of the available test suites",
+    "test assignment of mp-int structures",
+    "test exchange of mp-int structures",
+    "test zeroing of an mp-int",
+    "test setting an mp-int to a small constant",
+    "test the absolute value function",
+    "test the arithmetic negation function",
+    "test digit addition",
+    "test full addition",
+    "test digit subtraction",
+    "test full subtraction",
+    "test digit multiplication",
+    "test full multiplication",
+    "test full squaring function",
+    "test digit division",
+    "test division by two",
+    "test division & remainder by 2^d",
+    "test full division",
+    "test digit exponentiation",
+    "test full exponentiation",
+    "test power-of-two exponentiation",
+    "test digit modular reduction",
+    "test full modular reduction",
+    "test modular addition",
+    "test modular subtraction",
+    "test modular multiplication",
+    "test modular squaring function",
+    "test full modular exponentiation",
+    "test digit modular exponentiation",
+    "test modular inverse function",
+    "test digit comparison function",
+    "test zero comparison function",
+    "test general signed comparison",
+    "test general magnitude comparison",
+    "test parity comparison functions",
+    "test greatest common divisor functions",
+    "test least common multiple function",
+    "test general radix conversion facilities",
+    "test raw output format",
+    "test probabilistic primality tester",
+    "test Fermat pseudoprimality tester"
+};
deleted file mode 100644
--- a/security/nss/cmd/pk11ectest/testvecs.h
+++ /dev/null
@@ -1,818 +0,0 @@
-static ECDH_KAT ecdh_testvecs[] = {
-    { ECCurve_NIST_P256, 1,
-      "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534",
-      "04ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b23028af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141",
-      "04700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
-      "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b",
-      "curve: P256 vector: 0", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5",
-      "04119f2f047902782ab0c9e27a54aff5eb9b964829ca99c06b02ddba95b0a3f6d08f52b726664cac366fc98ac7a012b2682cbd962e5acb544671d41b9445704d1d",
-      "04809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7aeb29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3",
-      "057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67",
-      "curve: P256 vector: 1", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "1accfaf1b97712b85a6f54b148985a1bdc4c9bec0bd258cad4b3d603f49f32c8",
-      "04d9f2b79c172845bfdb560bbb01447ca5ecc0470a09513b6126902c6b4f8d1051f815ef5ec32128d3487834764678702e64e164ff7315185e23aff5facd96d7bc",
-      "04a2339c12d4a03c33546de533268b4ad667debf458b464d77443636440ee7fec3ef48a3ab26e20220bcda2c1851076839dae88eae962869a497bf73cb66faf536",
-      "2d457b78b4614132477618a5b077965ec90730a8c81a1c75d6d4ec68005d67ec",
-      "curve: P256 vector: 2", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "207c43a79bfee03db6f4b944f53d2fb76cc49ef1c9c4d34d51b6c65c4db6932d",
-      "0424277c33f450462dcb3d4801d57b9ced05188f16c28eda873258048cd1607e0dc4789753e2b1f63b32ff014ec42cd6a69fac81dfe6d0d6fd4af372ae27c46f88",
-      "04df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4",
-      "96441259534b80f6aee3d287a6bb17b5094dd4277d9e294f8fe73e48bf2a0024",
-      "curve: P256 vector: 3", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "59137e38152350b195c9718d39673d519838055ad908dd4757152fd8255c09bf",
-      "04a8c5fdce8b62c5ada598f141adb3b26cf254c280b2857a63d2ad783a73115f6b806e1aafec4af80a0d786b3de45375b517a7e5b51ffb2c356537c9e6ef227d4a",
-      "0441192d2813e79561e6a1d6f53c8bc1a433a199c835e141b05a74a97b0faeb9221af98cc45e98a7e041b01cf35f462b7562281351c8ebf3ffa02e33a0722a1328",
-      "19d44c8d63e8e8dd12c22a87b8cd4ece27acdde04dbf47f7f27537a6999a8e62",
-      "curve: P256 vector: 4", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "f5f8e0174610a661277979b58ce5c90fee6c9b3bb346a90a7196255e40b132ef",
-      "047b861dcd2844a5a8363f6b8ef8d493640f55879217189d80326aad9480dfc149c4675b45eeb306405f6c33c38bc69eb2bdec9b75ad5af4706aab84543b9cc63a",
-      "0433e82092a0f1fb38f5649d5867fba28b503172b7035574bf8e5b7100a3052792f2cf6b601e0a05945e335550bf648d782f46186c772c0f20d3cd0d6b8ca14b2f",
-      "664e45d5bba4ac931cd65d52017e4be9b19a515f669bea4703542a2c525cd3d3",
-      "curve: P256 vector: 5", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "3b589af7db03459c23068b64f63f28d3c3c6bc25b5bf76ac05f35482888b5190",
-      "049fb38e2d58ea1baf7622e96720101cae3cde4ba6c1e9fa26d9b1de0899102863d5561b900406edf50802dd7d73e89395f8aed72fba0e1d1b61fe1d22302260f0",
-      "046a9e0c3f916e4e315c91147be571686d90464e8bf981d34a90b6353bca6eeba740f9bead39c2f2bcc2602f75b8a73ec7bdffcbcead159d0174c6c4d3c5357f05",
-      "ca342daa50dc09d61be7c196c85e60a80c5cb04931746820be548cdde055679d",
-      "curve: P256 vector: 6", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "d8bf929a20ea7436b2461b541a11c80e61d826c0a4c9d322b31dd54e7f58b9c8",
-      "0420f07631e4a6512a89ad487c4e9d63039e579cb0d7a556cb9e661cd59c1e7fa46de91846b3eee8a5ec09c2ab1f41e21bd83620ccdd1bdce3ab7ea6e02dd274f5",
-      "04a9c0acade55c2a73ead1a86fb0a9713223c82475791cd0e210b046412ce224bbf6de0afa20e93e078467c053d241903edad734c6b403ba758c2b5ff04c9d4229",
-      "35aa9b52536a461bfde4e85fc756be928c7de97923f0416c7a3ac8f88b3d4489",
-      "curve: P256 vector: 7", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "0f9883ba0ef32ee75ded0d8bda39a5146a29f1f2507b3bd458dbea0b2bb05b4d",
-      "04abb61b423be5d6c26e21c605832c9142dc1dfe5a5fff28726737936e6fbf516d733d2513ef58beab202090586fac91bf0fee31e80ab33473ab23a2d89e58fad6",
-      "0494e94f16a98255fff2b9ac0c9598aac35487b3232d3231bd93b7db7df36f9eb9d8049a43579cfa90b8093a94416cbefbf93386f15b3f6e190b6e3455fedfe69a",
-      "605c16178a9bc875dcbff54d63fe00df699c03e8a888e9e94dfbab90b25f39b4",
-      "curve: P256 vector: 8", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "2beedb04b05c6988f6a67500bb813faf2cae0d580c9253b6339e4a3337bb6c08",
-      "043d63e429cb5fa895a9247129bf4e48e89f35d7b11de8158efeb3e106a2a873950cae9e477ef41e7c8c1064379bb7b554ddcbcae79f9814281f1e50f0403c61f3",
-      "04e099bf2a4d557460b5544430bbf6da11004d127cb5d67f64ab07c94fcdf5274fd9c50dbe70d714edb5e221f4e020610eeb6270517e688ca64fb0e98c7ef8c1c5",
-      "f96e40a1b72840854bb62bc13c40cc2795e373d4e715980b261476835a092e0b",
-      "curve: P256 vector: 9", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "77c15dcf44610e41696bab758943eff1409333e4d5a11bbe72c8f6c395e9f848",
-      "04ad5d13c3db508ddcd38457e5991434a251bed49cf5ddcb59cdee73865f138c9f62cec1e70588aa4fdfc7b9a09daa678081c04e1208b9d662b8a2214bf8e81a21",
-      "04f75a5fe56bda34f3c1396296626ef012dc07e4825838778a645c8248cff0165833bbdf1b1772d8059df568b061f3f1122f28a8d819167c97be448e3dc3fb0c3c",
-      "8388fa79c4babdca02a8e8a34f9e43554976e420a4ad273c81b26e4228e9d3a3",
-      "curve: P256 vector: 10", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "42a83b985011d12303db1a800f2610f74aa71cdf19c67d54ce6c9ed951e9093e",
-      "04ab48caa61ea35f13f8ed07ffa6a13e8db224dfecfae1a7df8b1bb6ebaf0cb97d1274530ca2c385a3218bddfbcbf0b4024c9badd5243bff834ebff24a8618dccb",
-      "042db4540d50230756158abf61d9835712b6486c74312183ccefcaef2797b7674d62f57f314e3f3495dc4e099012f5e0ba71770f9660a1eada54104cdfde77243e",
-      "72877cea33ccc4715038d4bcbdfe0e43f42a9e2c0c3b017fc2370f4b9acbda4a",
-      "curve: P256 vector: 11", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "ceed35507b5c93ead5989119b9ba342cfe38e6e638ba6eea343a55475de2800b",
-      "049a8cd9bd72e71752df91440f77c547509a84df98114e7de4f26cdb39234a625dd07cfc84c8e144fab2839f5189bb1d7c88631d579bbc58012ed9a2327da52f62",
-      "04cd94fc9497e8990750309e9a8534fd114b0a6e54da89c4796101897041d14ecbc3def4b5fe04faee0a11932229fff563637bfdee0e79c6deeaf449f85401c5c4",
-      "e4e7408d85ff0e0e9c838003f28cdbd5247cdce31f32f62494b70e5f1bc36307",
-      "curve: P256 vector: 12", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "43e0e9d95af4dc36483cdd1968d2b7eeb8611fcce77f3a4e7d059ae43e509604",
-      "04f989cf8ee956a82e7ebd9881cdbfb2fd946189b08db53559bc8cfdd48071eb145eff28f1a18a616b04b7d337868679f6dd84f9a7b3d7b6f8af276c19611a541d",
-      "0415b9e467af4d290c417402e040426fe4cf236bae72baa392ed89780dfccdb471cdf4e9170fb904302b8fd93a820ba8cc7ed4efd3a6f2d6b05b80b2ff2aee4e77",
-      "ed56bcf695b734142c24ecb1fc1bb64d08f175eb243a31f37b3d9bb4407f3b96",
-      "curve: P256 vector: 13", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "b2f3600df3368ef8a0bb85ab22f41fc0e5f4fdd54be8167a5c3cd4b08db04903",
-      "0469c627625b36a429c398b45c38677cb35d8beb1cf78a571e40e99fe4eac1cd4e81690112b0a88f20f7136b28d7d47e5fbc2ada3c8edd87589bc19ec9590637bd",
-      "0449c503ba6c4fa605182e186b5e81113f075bc11dcfd51c932fb21e951eee2fa18af706ff0922d87b3f0c5e4e31d8b259aeb260a9269643ed520a13bb25da5924",
-      "bc5c7055089fc9d6c89f83c1ea1ada879d9934b2ea28fcf4e4a7e984b28ad2cf",
-      "curve: P256 vector: 14", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "4002534307f8b62a9bf67ff641ddc60fef593b17c3341239e95bdb3e579bfdc8",
-      "045fe964671315a18aa68a2a6e3dd1fde7e23b8ce7181471cfac43c99e1ae80262d5827be282e62c84de531b963884ba832db5d6b2c3a256f0e604fe7e6b8a7f72",
-      "0419b38de39fdd2f70f7091631a4f75d1993740ba9429162c2a45312401636b29c09aed7232b28e060941741b6828bcdfa2bc49cc844f3773611504f82a390a5ae",
-      "9a4e8e657f6b0e097f47954a63c75d74fcba71a30d83651e3e5a91aa7ccd8343",
-      "curve: P256 vector: 15", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "4dfa12defc60319021b681b3ff84a10a511958c850939ed45635934ba4979147",
-      "04c9b2b8496f1440bd4a2d1e52752fd372835b364885e154a7dac49295f281ec7cfbe6b926a8a4de26ccc83b802b1212400754be25d9f3eeaf008b09870ae76321",
-      "042c91c61f33adfe9311c942fdbff6ba47020feff416b7bb63cec13faf9b0999546cab31b06419e5221fca014fb84ec870622a1b12bab5ae43682aa7ea73ea08d0",
-      "3ca1fc7ad858fb1a6aba232542f3e2a749ffc7203a2374a3f3d3267f1fc97b78",
-      "curve: P256 vector: 16", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "1331f6d874a4ed3bc4a2c6e9c74331d3039796314beee3b7152fcdba5556304e",
-      "0459e1e101521046ad9cf1d082e9d2ec7dd22530cce064991f1e55c5bcf5fcb591482f4f673176c8fdaa0bb6e59b15a3e47454e3a04297d3863c9338d98add1f37",
-      "04a28a2edf58025668f724aaf83a50956b7ac1cfbbff79b08c3bf87dfd2828d767dfa7bfffd4c766b86abeaf5c99b6e50cb9ccc9d9d00b7ffc7804b0491b67bc03",
-      "1aaabe7ee6e4a6fa732291202433a237df1b49bc53866bfbe00db96a0f58224f",
-      "curve: P256 vector: 17", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "dd5e9f70ae740073ca0204df60763fb6036c45709bf4a7bb4e671412fad65da3",
-      "0430b9db2e2e977bcdc98cb87dd736cbd8e78552121925cf16e1933657c2fb23146a45028800b81291bce5c2e1fed7ded650620ebbe6050c6f3a7f0dfb4673ab5c",
-      "04a2ef857a081f9d6eb206a81c4cf78a802bdf598ae380c8886ecd85fdc1ed7644563c4c20419f07bc17d0539fade1855e34839515b892c0f5d26561f97fa04d1a",
-      "430e6a4fba4449d700d2733e557f66a3bf3d50517c1271b1ddae1161b7ac798c",
-      "curve: P256 vector: 18", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "5ae026cfc060d55600717e55b8a12e116d1d0df34af831979057607c2d9c2f76",
-      "0446c9ebd1a4a3c8c0b6d572b5dcfba12467603208a9cb5d2acfbb733c40cf639146c913a27d044185d38b467ace011e04d4d9bbbb8cb9ae25fa92aaf15a595e86",
-      "04ccd8a2d86bc92f2e01bce4d6922cf7fe1626aed044685e95e2eebd464505f01fe9ddd583a9635a667777d5b8a8f31b0f79eba12c75023410b54b8567dddc0f38",
-      "1ce9e6740529499f98d1f1d71329147a33df1d05e4765b539b11cf615d6974d3",
-      "curve: P256 vector: 19", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "b601ac425d5dbf9e1735c5e2d5bdb79ca98b3d5be4a2cfd6f2273f150e064d9d",
-      "047c9e950841d26c8dde8994398b8f5d475a022bc63de7773fcf8d552e01f1ba0acc42b9885c9b3bee0f8d8c57d3a8f6355016c019c4062fa22cff2f209b5cc2e1",
-      "04c188ffc8947f7301fb7b53e36746097c2134bf9cc981ba74b4e9c4361f595e4ebf7d2f2056e72421ef393f0c0f2b0e00130e3cac4abbcc00286168e85ec55051",
-      "4690e3743c07d643f1bc183636ab2a9cb936a60a802113c49bb1b3f2d0661660",
-      "curve: P256 vector: 20", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "fefb1dda1845312b5fce6b81b2be205af2f3a274f5a212f66c0d9fc33d7ae535",
-      "0438b54db85500cb20c61056edd3d88b6a9dc26780a047f213a6e1b900f76596eb6387e4e5781571e4eb8ae62991a33b5dc33301c5bc7e125d53794a39160d8fd0",
-      "04317e1020ff53fccef18bf47bb7f2dd7707fb7b7a7578e04f35b3beed222a0eb609420ce5a19d77c6fe1ee587e6a49fbaf8f280e8df033d75403302e5a27db2ae",
-      "30c2261bd0004e61feda2c16aa5e21ffa8d7e7f7dbf6ec379a43b48e4b36aeb0",
-      "curve: P256 vector: 21", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "334ae0c4693d23935a7e8e043ebbde21e168a7cba3fa507c9be41d7681e049ce",
-      "043f2bf1589abf3047bf3e54ac9a95379bff95f8f55405f64eca36a7eebe8ffca75212a94e66c5ae9a8991872f66a72723d80ec5b2e925745c456f5371943b3a06",
-      "0445fb02b2ceb9d7c79d9c2fa93e9c7967c2fa4df5789f9640b24264b1e524fcb15c6e8ecf1f7d3023893b7b1ca1e4d178972ee2a230757ddc564ffe37f5c5a321",
-      "2adae4a138a239dcd93c243a3803c3e4cf96e37fe14e6a9b717be9599959b11c",
-      "curve: P256 vector: 22", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "2c4bde40214fcc3bfc47d4cf434b629acbe9157f8fd0282540331de7942cf09d",
-      "0429c0807f10cbc42fb45c9989da50681eead716daa7b9e91fd32e062f5eb92ca0ff1d6d1955d7376b2da24fe1163a271659136341bc2eb1195fc706dc62e7f34d",
-      "04a19ef7bff98ada781842fbfc51a47aff39b5935a1c7d9625c8d323d511c92de6e9c184df75c955e02e02e400ffe45f78f339e1afe6d056fb3245f4700ce606ef",
-      "2e277ec30f5ea07d6ce513149b9479b96e07f4b6913b1b5c11305c1444a1bc0b",
-      "curve: P256 vector: 23", ec_field_GFp },
-
-    { ECCurve_NIST_P256, 1,
-      "85a268f9d7772f990c36b42b0a331adc92b5941de0b862d5d89a347cbf8faab0",
-      "049cf4b98581ca1779453cc816ff28b4100af56cf1bf2e5bc312d83b6b1b21d3337a5504fcac5231a0d12d658218284868229c844a04a3450d6c7381abe080bf3b",
-      "04356c5a444c049a52fee0adeb7e5d82ae5aa83030bfff31bbf8ce2096cf161c4b57d128de8b2a57a094d1a001e572173f96e8866ae352bf29cddaf92fc85b2f92",
-      "1e51373bd2c6044c129c436e742a55be2a668a85ae08441b6756445df5493857",
-      "curve: P256 vector: 24", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "3cc3122a68f0d95027ad38c067916ba0eb8c38894d22e1b15618b6818a661774ad463b205da88cf699ab4d43c9cf98a1",
-      "049803807f2f6d2fd966cdd0290bd410c0190352fbec7ff6247de1302df86f25d34fe4a97bef60cff548355c015dbb3e5"
-      "fba26ca69ec2f5b5d9dad20cc9da711383a9dbe34ea3fa5a2af75b46502629ad54dd8b7d73a8abb06a3a3be47d650cc99",
-      "04a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e764592efda27fe7513272734466b400091adbf2d68c58e0c5006"
-      "6ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b661efedf243451915ed0905a32b060992b468c64766fc8437a",
-      "5f9d29dc5e31a163060356213669c8ce132e22f57c9a04f40ba7fcead493b457e5621e766c40a2e3d4d6a04b25e533f1",
-      "curve: P384 vector: 0", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "92860c21bde06165f8e900c687f8ef0a05d14f290b3f07d8b3a8cc6404366e5d5119cd6d03fb12dc58e89f13df9cd783",
-      "04ea4018f5a307c379180bf6a62fd2ceceebeeb7d4df063a66fb838aa35243419791f7e2c9d4803c9319aa0eb03c416b"
-      "6668835a91484f05ef028284df6436fb88ffebabcdd69ab0133e6735a1bcfb37203d10d340a8328a7b68770ca75878a1a6",
-      "0430f43fcf2b6b00de53f624f1543090681839717d53c7c955d1d69efaf0349b7363acb447240101cbb3af6641ce4b88e0"
-      "25e46c0c54f0162a77efcc27b6ea792002ae2ba82714299c860857a68153ab62e525ec0530d81b5aa15897981e858757",
-      "a23742a2c267d7425fda94b93f93bbcc24791ac51cd8fd501a238d40812f4cbfc59aac9520d758cf789c76300c69d2ff",
-      "curve: P384 vector: 1", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "12cf6a223a72352543830f3f18530d5cb37f26880a0b294482c8a8ef8afad09aa78b7dc2f2789a78c66af5d1cc553853",
-      "04fcfcea085e8cf74d0dced1620ba8423694f903a219bbf901b0b59d6ac81baad316a242ba32bde85cb248119b852fab6"
-      "6972e3c68c7ab402c5836f2a16ed451a33120a7750a6039f3ff15388ee622b7065f7122bf6d51aefbc29b37b03404581b",
-      "041aefbfa2c6c8c855a1a216774550b79a24cda37607bb1f7cc906650ee4b3816d68f6a9c75da6e4242cebfb6652f65180"
-      "419d28b723ebadb7658fcebb9ad9b7adea674f1da3dc6b6397b55da0f61a3eddacb4acdb14441cb214b04a0844c02fa3",
-      "3d2e640f350805eed1ff43b40a72b2abed0a518bcebe8f2d15b111b6773223da3c3489121db173d414b5bd5ad7153435",
-      "curve: P384 vector: 2", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "8dd48063a3a058c334b5cc7a4ce07d02e5ee6d8f1f3c51a1600962cbab462690ae3cd974fb39e40b0e843daa0fd32de1",
-      "04e38c9846248123c3421861ea4d32669a7b5c3c08376ad28104399494c84ff5efa3894adb2c6cbe8c3c913ef2eec5bd3"
-      "c9fa84024a1028796df84021f7b6c9d02f0f4bd1a612a03cbf75a0beea43fef8ae84b48c60172aadf09c1ad016d0bf3ce",
-      "048bc089326ec55b9cf59b34f0eb754d93596ca290fcb3444c83d4de3a5607037ec397683f8cef07eab2fe357eae36c44"
-      "9d9d16ce8ac85b3f1e94568521aae534e67139e310ec72693526aa2e927b5b322c95a1a033c229cb6770c957cd3148dd7",
-      "6a42cfc392aba0bfd3d17b7ccf062b91fc09bbf3417612d02a90bdde62ae40c54bb2e56e167d6b70db670097eb8db854",
-      "curve: P384 vector: 3", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "84ece6cc3429309bd5b23e959793ed2b111ec5cb43b6c18085fcaea9efa0685d98a6262ee0d330ee250bc8a67d0e733f",
-      "043222063a2997b302ee60ee1961108ff4c7acf1c0ef1d5fb0d164b84bce71c431705cb9aea9a45f5d73806655a058bee"
-      "3e61fa9e7fbe7cd43abf99596a3d3a039e99fa9dc93b0bdd9cad81966d17eeaf557068afa7c78466bb5b22032d1100fa6",
-      "04eb952e2d9ac0c20c6cc48fb225c2ad154f53c8750b003fd3b4ed8ed1dc0defac61bcdde02a2bcfee7067d75d342ed2b"
-      "0f1828205baece82d1b267d0d7ff2f9c9e15b69a72df47058a97f3891005d1fb38858f5603de840e591dfa4f6e7d489e1",
-      "ce7ba454d4412729a32bb833a2d1fd2ae612d4667c3a900e069214818613447df8c611de66da200db7c375cf913e4405",
-      "curve: P384 vector: 4", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "68fce2121dc3a1e37b10f1dde309f9e2e18fac47cd1770951451c3484cdb77cb136d00e731260597cc2859601c01a25b",
-      "04868be0e694841830e424d913d8e7d86b84ee1021d82b0ecf523f09fe89a76c0c95c49f2dfbcf829c1e39709d55efbb"
-      "3b9195eb183675b40fd92f51f37713317e4a9b4f715c8ab22e0773b1bc71d3a219f05b8116074658ee86b52e36f3897116",
-      "04441d029e244eb7168d647d4df50db5f4e4974ab3fdaf022aff058b3695d0b8c814cc88da6285dc6df1ac55c55388500"
-      "3e8025ac23a41d4b1ea2aa46c50c6e479946b59b6d76497cd9249977e0bfe4a6262622f13d42a3c43d66bdbb30403c345",
-      "ba69f0acdf3e1ca95caaac4ecaf475bbe51b54777efce01ca381f45370e486fe87f9f419b150c61e329a286d1aa265ec",
-      "curve: P384 vector: 5", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "b1764c54897e7aae6de9e7751f2f37de849291f88f0f91093155b858d1cc32a3a87980f706b86cc83f927bdfdbeae0bd",
-      "04c371222feaa6770c6f3ea3e0dac9740def4fcf821378b7f91ff937c21e0470f70f3a31d5c6b2912195f10926942b48ae"
-      "047d6b4d765123563f81116bc665b7b8cc6207830d805fd84da7cb805a65baa7c12fd592d1b5b5e3e65d9672a9ef7662",
-      "043d4e6bf08a73404accc1629873468e4269e82d90d832e58ad72142639b5a056ad8d35c66c60e8149fac0c797bceb7c2"
-      "f9b0308dc7f0e6d29f8c277acbc65a21e5adb83d11e6873bc0a07fda0997f482504602f59e10bc5cb476b83d0a4f75e71",
-      "1a6688ee1d6e59865d8e3ada37781d36bb0c2717eef92e61964d3927cb765c2965ea80f7f63e58c322ba0397faeaf62b",
-      "curve: P384 vector: 6", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "f0f7a96e70d98fd5a30ad6406cf56eb5b72a510e9f192f50e1f84524dbf3d2439f7287bb36f5aa912a79deaab4adea82",
-      "0499c8c41cb1ab5e0854a346e4b08a537c1706a61553387c8d94943ab15196d40dbaa55b8210a77a5d00915f2c4ea69e"
-      "ab5531065bdcf17bfb3cb55a02e41a57c7f694c383ad289f900fbd656c2233a93c92e933e7a26f54cbb56f0ad875c51bb0",
-      "04f5f6bef1d110da03be0017eac760cc34b24d092f736f237bc7054b3865312a813bcb62d297fb10a4f7abf54708fe2d3d"
-      "06fdf8d7dc032f4e10010bf19cbf6159321252ff415fb91920d438f24e67e60c2eb0463204679fa356af44cea9c9ebf5",
-      "d06a568bf2336b90cbac325161be7695eacb2295f599500d787f072612aca313ee5d874f807ddef6c1f023fe2b6e7cd0",
-      "curve: P384 vector: 7", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "9efb87ddc61d43c482ba66e1b143aef678fbd0d1bebc2000941fabe677fe5b706bf78fce36d100b17cc787ead74bbca2",
-      "044c34efee8f0c95565d2065d1bbac2a2dd25ae964320eb6bccedc5f3a9b42a881a1afca1bb6b880584fa27b01c193cd9"
-      "2d8fb01dbf7cd0a3868c26b951f393c3c56c2858cee901f7793ff5d271925d13a41f8e52409f4eba1990f33acb0bac669",
-      "047cdec77e0737ea37c67b89b7137fe38818010f4464438ee4d1d35a0c488cad3fde2f37d00885d36d3b795b9f93d23a6"
-      "728c42ee8d6027c56cf979ba4c229fdb01d234944f8ac433650112c3cf0f02844e888a3569dfef7828a8a884589aa055e",
-      "bb3b1eda9c6560d82ff5bee403339f1e80342338a991344853b56b24f109a4d94b92f654f0425edd4c205903d7586104",
-      "curve: P384 vector: 8", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "d787a57fde22ec656a0a525cf3c738b30d73af61e743ea90893ecb2d7b622add2f94ee25c2171467afb093f3f84d0018",
-      "04171546923b87b2cbbad664f01ce932bf09d6a6118168678446bfa9f0938608cb4667a98f4ec8ac1462285c2508f7486"
-      "2fa41cb4db68ae71f1f8a3e8939dc52c2dec61a83c983beb2a02baf29ec49278088882ed0cf56c74b5c173b552ccf63cf",
-      "048eeea3a319c8df99fbc29cb55f243a720d95509515ee5cc587a5c5ae22fbbd009e626db3e911def0b99a4f7ae304b1b"
-      "a73877dc94db9adddc0d9a4b24e8976c22d73c844370e1ee857f8d1b129a3bd5f63f40caf3bd0533e38a5f5777074ff9e",
-      "1e97b60add7cb35c7403dd884c0a75795b7683fff8b49f9d8672a8206bfdcf0a106b8768f983258c74167422e44e4d14",
-      "curve: P384 vector: 9", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "83d70f7b164d9f4c227c767046b20eb34dfc778f5387e32e834b1e6daec20edb8ca5bb4192093f543b68e6aeb7ce788b",
-      "0457cd770f3bbcbe0c78c770eab0b169bc45e139f86378ffae1c2b16966727c2f2eb724572b8f3eb228d130db4ff862c"
-      "637ec5c8813b685558d83e924f14bc719f6eb7ae0cbb2c474227c5bda88637a4f26c64817929af999592da6f787490332f",
-      "04a721f6a2d4527411834b13d4d3a33c29beb83ab7682465c6cbaf6624aca6ea58c30eb0f29dd842886695400d7254f20f"
-      "14ba6e26355109ad35129366d5e3a640ae798505a7fa55a96a36b5dad33de00474f6670f522214dd7952140ab0a7eb68",
-      "1023478840e54775bfc69293a3cf97f5bc914726455c66538eb5623e218feef7df4befa23e09d77145ad577db32b41f9",
-      "curve: P384 vector: 10", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "8f558e05818b88ed383d5fca962e53413db1a0e4637eda194f761944cbea114ab9d5da175a7d57882550b0e432f395a9",
-      "049a2f57f4867ce753d72b0d95195df6f96c1fae934f602efd7b6a54582f556cfa539d89005ca2edac08ad9b72dd1f60b"
-      "ad9b94ee82da9cc601f346044998ba387aee56404dc6ecc8ab2b590443319d0b2b6176f9d0eac2d44678ed561607d09a9",
-      "04d882a8505c2d5cb9b8851fc676677bb0087681ad53faceba1738286b45827561e7da37b880276c656cfc38b32ade847"
-      "e34b314bdc134575654573cffaf40445da2e6aaf987f7e913cd4c3091523058984a25d8f21da8326192456c6a0fa5f60c",
-      "6ad6b9dc8a6cf0d3691c501cbb967867f6e4bbb764b60dbff8fcff3ed42dbba39d63cf325b4b4078858495ddee75f954",
-      "curve: P384 vector: 11", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "0f5dee0affa7bbf239d5dff32987ebb7cf84fcceed643e1d3c62d0b3352aec23b6e5ac7fa4105c8cb26126ad2d1892cb",
-      "0423346bdfbc9d7c7c736e02bdf607671ff6082fdd27334a8bc75f3b23681ebe614d0597dd614fae58677c835a9f0b273"
-      "b82ba36290d2f94db41479eb45ab4eaf67928a2315138d59eecc9b5285dfddd6714f77557216ea44cc6fc119d8243efaf",
-      "04815c9d773dbf5fb6a1b86799966247f4006a23c92e68c55e9eaa998b17d8832dd4d84d927d831d4f68dac67c6488219f"
-      "e79269948b2611484560fd490feec887cb55ef99a4b524880fa7499d6a07283aae2afa33feab97deca40bc606c4d8764",
-      "cc9e063566d46b357b3fcae21827377331e5e290a36e60cd7c39102b828ae0b918dc5a02216b07fe6f1958d834e42437",
-      "curve: P384 vector: 12", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "037b633b5b8ba857c0fc85656868232e2febf59578718391b81da8541a00bfe53c30ae04151847f27499f8d7abad8cf4",
-      "048878ac8a947f7d5cb2b47aad24fbb8210d86126585399a2871f84aa9c5fde3074ae540c6bf82275ca822d0feb862bc7"
-      "4632f5cd2f900c2711c32f8930728eb647d31edd8d650f9654e7d33e5ed1b475489d08daa30d8cbcba6bfc3b60d9b5a37",
-      "041c0eeda7a2be000c5bdcda0478aed4db733d2a9e341224379123ad847030f29e3b168fa18e89a3c0fba2a6ce1c28fc3"
-      "bec8c1c83c118c4dbea94271869f2d868eb65e8b44e21e6f14b0f4d9b38c068daefa27114255b9a41d084cc4a1ad85456",
-      "deff7f03bd09865baf945e73edff6d5122c03fb561db87dec8662e09bed4340b28a9efe118337bb7d3d4f7f568635ff9",
-      "curve: P384 vector: 13", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "e3d07106bedcc096e7d91630ffd3094df2c7859db8d7edbb2e37b4ac47f429a637d06a67d2fba33838764ef203464991",
-      "04e74a1a2b85f1cbf8dbbdf050cf1aff8acb02fda2fb6591f9d3cfe4e79d0ae938a9c1483e7b75f8db24505d65065cdb1"
-      "81773ee591822f7abaa856a1a60bc0a5203548dbd1cb5025466eff8481bd07614eaa04a16c3db76905913e972a5b6b59d",
-      "04c95c185e256bf997f30b311548ae7f768a38dee43eeeef43083f3077be70e2bf39ac1d4daf360c514c8c6be623443d1"
-      "a3e63a663eaf75d8a765ab2b9a35513d7933fa5e26420a5244550ec6c3b6f033b96db2aca3d6ac6aab052ce929595aea5",
-      "c8b1038f735ad3bb3e4637c3e47eab487637911a6b7950a4e461948329d3923b969e5db663675623611a457fcda35a71",
-      "curve: P384 vector: 14", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "f3f9b0c65a49a506632c8a45b10f66b5316f9eeb06fae218f2da62333f99905117b141c760e8974efc4af10570635791",
-      "04a4ad77aa7d86e5361118a6b921710c820721210712f4c347985fdee58aa4effa1e28be80a17b120b139f96300f89b4"
-      "9b1ddf22e07e03f1560d8f45a480094560dba9fae7f9531130c1b57ebb95982496524f31d3797793396fa823f22bdb4328",
-      "043497238a7e6ad166df2dac039aa4dac8d17aa925e7c7631eb3b56e3aaa1c545fcd54d2e5985807910fb202b1fc191d2a"
-      "a49e5c487dcc7aa40a8f234c979446040d9174e3ad357d404d7765183195aed3f913641b90c81a306ebf0d8913861316",
-      "d337eaa32b9f716b8747b005b97a553c59dab0c51df41a2d49039cdae705aa75c7b9e7bc0b6a0e8c578c902bc4fff23e",
-      "curve: P384 vector: 15", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "59fce7fad7de28bac0230690c95710c720e528f9a4e54d3a6a8cd5fc5c5f21637031ce1c5b4e3d39647d8dcb9b794664",
-      "049c43bf971edf09402876ee742095381f78b1bd3aa39b5132af75dbfe7e98bd78bde10fe2e903c2b6379e1deee175a1b"
-      "0a6c58ecea5a477bb01bd543b339f1cc49f1371a2cda4d46eb4e53e250597942351a99665a122ffea9bde0636c375daf2",
-      "0490a34737d45b1aa65f74e0bd0659bc118f8e4b774b761944ffa6573c6df4f41dec0d11b697abd934d390871d4b453240"
-      "9b590719bb3307c149a7817be355d684893a307764b512eeffe07cb699edb5a6ffbf8d6032e6c79d5e93e94212c2aa4e",
-      "32d292b695a4488e42a7b7922e1ae537d76a3d21a0b2e36875f60e9f6d3e8779c2afb3a413b9dd79ae18e70b47d337c1",
-      "curve: P384 vector: 16", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "3e49fbf950a424c5d80228dc4bc35e9f6c6c0c1d04440998da0a609a877575dbe437d6a5cedaa2ddd2a1a17fd112aded",
-      "045a949594228b1a3d6f599eb3db0d06070fbc551c657b58234ba164ce3fe415fa5f3eb823c08dc29b8c341219c77b6b3"
-      "d2baad447c8c290cfed25edd9031c41d0b76921457327f42db31122b81f337bbf0b1039ec830ce9061a3761953c75e4a8",
-      "04dda546acfc8f903d11e2e3920669636d44b2068aeb66ff07aa266f0030e1535b0ed0203cb8a460ac990f1394faf22f1"
-      "d15bbb2597913035faadf413476f4c70f7279769a40c986f470c427b4ee4962abdf8173bbad81874772925fd32f0b159f",
-      "1220e7e6cad7b25df98e5bbdcc6c0b65ca6c2a50c5ff6c41dca71e475646fd489615979ca92fb4389aeadefde79a24f1",
-      "curve: P384 vector: 17", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "50ccc1f7076e92f4638e85f2db98e0b483e6e2204c92bdd440a6deea04e37a07c6e72791c190ad4e4e86e01efba84269",
-      "04756c07df0ce32c839dac9fb4733c9c28b70113a676a7057c38d223f22a3a9095a8d564653af528e04c7e1824be4a651"
-      "217c2ce6962cbd2a2e066297b39d57dd9bb4680f0191d390f70b4e461419b2972ce68ad46127fdda6c39195774ea86df3",
-      "04788be2336c52f4454d63ee944b1e49bfb619a08371048e6da92e584eae70bde1f171c4df378bd1f3c0ab03048a237802"
-      "4673ebd8db604eaf41711748bab2968a23ca4476ce144e728247f08af752929157b5830f1e26067466bdfa8b65145a33",
-      "793bb9cd22a93cf468faf804a38d12b78cb12189ec679ddd2e9aa21fa9a5a0b049ab16a23574fe04c1c3c02343b91beb",
-      "curve: P384 vector: 18", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "06f132b71f74d87bf99857e1e4350a594e5fe35533b888552ceccbc0d8923c902e36141d7691e28631b8bc9bafe5e064",
-      "042a3cc6b8ff5cde926e7e3a189a1bd029c9b586351af8838f4f201cb8f4b70ef3b0da06d352c80fc26baf8f42b784459"
-      "ebf9985960176da6d23c7452a2954ffcbbcb24249b43019a2a023e0b3dabd461f19ad3e775c364f3f11ad49f3099400d3",
-      "04d09bb822eb99e38060954747c82bb3278cf96bbf36fece3400f4c873838a40c135eb3babb9293bd1001bf3ecdee7bf2"
-      "6d416db6e1b87bbb7427788a3b6c7a7ab2c165b1e366f9608df512037584f213a648d47f16ac326e19aae972f63fd76c9",
-      "012d191cf7404a523678c6fc075de8285b243720a903047708bb33e501e0dbee5bcc40d7c3ef6c6da39ea24d830da1e8",
-      "curve: P384 vector: 19", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "12048ebb4331ec19a1e23f1a2c773b664ccfe90a28bfb846fc12f81dff44b7443c77647164bf1e9e67fd2c07a6766241",
-      "04bc18836bc7a9fdf54b5352f37d7528ab8fa8ec544a8c6180511cbfdd49cce377c39e34c031b5240dc9980503ed2f26"
-      "2c8086cbe338191080f0b7a16c7afc4c7b0326f9ac66f58552ef4bb9d24de3429ed5d3277ed58fcf48f2b5f61326bec6c6",
-      "0413741262ede5861dad71063dfd204b91ea1d3b7c631df68eb949969527d79a1dc59295ef7d2bca6743e8cd77b04d1"
-      "b580baaeadc7e19d74a8a04451a135f1be1b02fe299f9dc00bfdf201e83d995c6950bcc1cb89d6f7b30bf54656b9a4da586",
-      "ad0fd3ddffe8884b9263f3c15fe1f07f2a5a22ffdc7e967085eea45f0cd959f20f18f522763e28bcc925e496a52dda98",
-      "curve: P384 vector: 20", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "34d61a699ca576169fcdc0cc7e44e4e1221db0fe63d16850c8104029f7d48449714b9884328cae189978754ab460b486",
-      "04867f81104ccd6b163a7902b670ef406042cb0cce7dcdc63d1dfc91b2c40e3cdf7595834bf9eceb79849f1636fc8462f"
-      "c9d4bde8e875ec49697d258d1d59465f8431c6f5531e1c59e9f9ebe3cf164a8d9ce10a12f1979283a959bad244dd83863",
-      "049e22cbc18657f516a864b37b783348b66f1aa9626cd631f4fa1bd32ad88cf11db52057c660860d39d11fbf024fabd44"
-      "46b0d53c79681c28116df71e9cee74fd56c8b7f04b39f1198cc72284e98be9562e35926fb4f48a9fbecafe729309e8b6f",
-      "dc4ca392dc15e20185f2c6a8ea5ec31dfc96f56153a47394b3072b13d0015f5d4ae13beb3bed54d65848f9b8383e6c95",
-      "curve: P384 vector: 21", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "dc60fa8736d702135ff16aab992bb88eac397f5972456c72ec447374d0d8ce61153831bfc86ad5a6eb5b60bfb96a862c",
-      "04b69beede85d0f829fec1b893ccb9c3e052ff692e13b974537bc5b0f9feaf7b22e84f03231629b24866bdb4b8cf9089"
-      "1466f85e2bfcaba2843285b0e14ebc07ef7dafff8b424416fee647b59897b619f20eed95a632e6a4206bf7da429c04c560",
-      "042db5da5f940eaa884f4db5ec2139b0469f38e4e6fbbcc52df15c0f7cf7fcb1808c749764b6be85d2fdc5b16f58ad5d"
-      "c022e8b02dcf33e1b5a083849545f84ad5e43f77cb71546dbbac0d11bdb2ee202e9d3872e8d028c08990746c5e1dde9989",
-      "d765b208112d2b9ed5ad10c4046e2e3b0dbf57c469329519e239ac28b25c7d852bf757d5de0ee271cadd021d86cfd347",
-      "curve: P384 vector: 22", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "6fa6a1c704730987aa634b0516a826aba8c6d6411d3a4c89772d7a62610256a2e2f289f5c3440b0ec1e70fa339e251ce",
-      "0453de1fc1328e8de14aecab29ad8a40d6b13768f86f7d298433d20fec791f86f8bc73f358098b256a298bb488de257bf"
-      "4ac28944fd27f17b82946c04c66c41f0053d3692f275da55cd8739a95bd8cd3af2f96e4de959ea8344d8945375905858b",
-      "04329647baa354224eb4414829c5368c82d7893b39804e08cbb2180f459befc4b347a389a70c91a23bd9d30c83be5295d"
-      "3cc8f61923fad2aa8e505d6cfa126b9fabd5af9dce290b75660ef06d1caa73681d06089c33bc4246b3aa30dbcd2435b12",
-      "d3778850aeb58804fbe9dfe6f38b9fa8e20c2ca4e0dec335aafceca0333e3f2490b53c0c1a14a831ba37c4b9d74be0f2",
-      "curve: P384 vector: 23", ec_field_GFp },
-
-    { ECCurve_NIST_P384, 1,
-      "74ad8386c1cb2ca0fcdeb31e0869bb3f48c036afe2ef110ca302bc8b910f621c9fcc54cec32bb89ec7caa84c7b8e54a8",
-      "0427a3e83cfb9d5122e73129d801615857da7cc089cccc9c54ab3032a19e0a0a9f677346e37f08a0b3ed8da6e5dd69106"
-      "38d60e44aa5e0fd30c918456796af37f0e41957901645e5c596c6d989f5859b03a0bd7d1f4e77936fff3c74d204e5388e",
-      "0429d8a36d22200a75b7aea1bb47cdfcb1b7fd66de967041434728ab5d533a060df732130600fe6f75852a871fb2938e3"
-      "9e19b53db528395de897a45108967715eb8cb55c3fcbf23379372c0873a058d57544b102ecce722b2ccabb1a603774fd5",
-      "81e1e71575bb4505498de097350186430a6242fa6c57b85a5f984a23371123d2d1424eefbf804258392bc723e4ef1e35",
-      "curve: P384 vector: 24", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "017eecc07ab4b329068fba65e56a1f8890aa935e57134ae0ffcce802735151f4eac6564f6ee9974c5e6887a1fefee5743"
-      "ae2241bfeb95d5ce31ddcb6f9edb4d6fc47",
-      "0400602f9d0cf9e526b29e22381c203c48a886c2b0673033366314f1ffbcba240ba42f4ef38a76174635f91e6b4ed3427"
-      "5eb01c8467d05ca80315bf1a7bbd945f550a501b7c85f26f5d4b2d7355cf6b02117659943762b6d1db5ab4f1dbc44ce7b2"
-      "946eb6c7de342962893fd387d1b73d7a8672d1f236961170b7eb3579953ee5cdc88cd2d",
-      "0400685a48e86c79f0f0875f7bc18d25eb5fc8c0b07e5da4f4370f3a9490340854334b1e1b87fa395464c60626124a4e70"
-      "d0f785601d37c09870ebf176666877a2046d01ba52c56fc8776d9e8f5db4f0cc27636d0b741bbe05400697942e80b739884"
-      "a83bde99e0f6716939e632bc8986fa18dccd443a348b6c3e522497955a4f3c302f676",
-      "005fc70477c3e63bc3954bd0df3ea0d1f41ee21746ed95fc5e1fdf90930d5e136672d72cc770742d1711c3c3a4c334a0ad9"
-      "759436a4d3c5bf6e74b9578fac148c831",
-      "curve: P521 vector: 0", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "00816f19c1fb10ef94d4a1d81c156ec3d1de08b66761f03f06ee4bb9dcebbbfe1eaa1ed49a6a990838d8ed318c14d74cc"
-      "872f95d05d07ad50f621ceb620cd905cfb8",
-      "0400d45615ed5d37fde699610a62cd43ba76bedd8f85ed31005fe00d6450fbbd101291abd96d4945a8b57bc73b3fe9f46"
-      "71105309ec9b6879d0551d930dac8ba45d25501425332844e592b440c0027972ad1526431c06732df19cd46a242172d4d"
-      "d67c2c8c99dfc22e49949a56cf90c6473635ce82f25b33682fb19bc33bd910ed8ce3a7fa",
-      "0401df277c152108349bc34d539ee0cf06b24f5d3500677b4445453ccc21409453aafb8a72a0be9ebe54d12270aa51b3a"
-      "b7f316aa5e74a951c5e53f74cd95fc29aee7a013d52f33a9f3c14384d1587fa8abe7aed74bc33749ad9c570b471776422c"
-      "7d4505d9b0a96b3bfac041e4c6a6990ae7f700e5b4a6640229112deafa0cd8bb0d089b0",
-      "000b3920ac830ade812c8f96805da2236e002acbbf13596a9ab254d44d0e91b6255ebf1229f366fb5a05c5884ef46032c2"
-      "6d42189273ca4efa4c3db6bd12a6853759",
-      "curve: P521 vector: 1", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "012f2e0c6d9e9d117ceb9723bced02eb3d4eebf5feeaf8ee0113ccd8057b13ddd416e0b74280c2d0ba8ed291c443bc1b14"
-      "1caf8afb3a71f97f57c225c03e1e4d42b0",
-      "0400717fcb3d4a40d103871ede044dc803db508aaa4ae74b70b9fb8d8dfd84bfecfad17871879698c292d2fd5e17b4f9343"
-      "636c531a4fac68a35a93665546b9a87867900f3d96a8637036993ab5d244500fff9d2772112826f6436603d3eb234a44d5c"
-      "4e5c577234679c4f9df725ee5b9118f23d8a58d0cc01096daf70e8dfec0128bdc2e8",
-      "040092db3142564d27a5f0006f819908fba1b85038a5bc2509906a497daac67fd7aee0fc2daba4e4334eeaef0e0019204b4"
-      "71cd88024f82115d8149cc0cf4f7ce1a4d5016bad0623f517b158d9881841d2571efbad63f85cbe2e581960c5d670601a67"
-      "60272675a548996217e4ab2b8ebce31d71fca63fcc3c08e91c1d8edd91cf6fe845f8",
-      "006b380a6e95679277cfee4e8353bf96ef2a1ebdd060749f2f046fe571053740bbcc9a0b55790bc9ab56c3208aa05ddf746"
-      "a10a3ad694daae00d980d944aabc6a08f",
-      "curve: P521 vector: 2", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "00e548a79d8b05f923b9825d11b656f222e8cb98b0f89de1d317184dc5a698f7c71161ee7dc11cd31f4f4f8ae3a981e1a3e7"
-      "8bdebb97d7c204b9261b4ef92e0918e0",
-      "04000ce800217ed243dd10a79ad73df578aa8a3f9194af528cd1094bbfee27a3b5481ad5862c8876c0c3f91294c0ab3aa806"
-      "d9020cbaa2ed72b7fecdc5a09a6dad6f3201543c9ab45b12469232918e21d5a351f9a4b9cbf9efb2afcc402fa9b31650bec2d6"
-      "41a05c440d35331c0893d11fb13151335988b303341301a73dc5f61d574e67d9",
-      "0400fdd40d9e9d974027cb3bae682162eac1328ad61bc4353c45bf5afe76bf607d2894c8cce23695d920f2464fda4773d4693b"
-      "e4b3773584691bdb0329b7f4c86cc2990034ceac6a3fef1c3e1c494bfe8d872b183832219a7e14da414d4e3474573671ec19b03"
-      "3be831b915435905925b44947c592959945b4eb7c951c3b9c8cf52530ba23",
-      "00fbbcd0b8d05331fef6086f22a6cce4d35724ab7a2f49dd8458d0bfd57a0b8b70f246c17c4468c076874b0dff7a0336823b19e"
-      "98bf1cec05e4beffb0591f97713c6",
-      "curve: P521 vector: 3", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "01c8aae94bb10b8ca4f7be577b4fb32bb2381032c4942c24fc2d753e7cc5e47b483389d9f3b956d20ee9001b1eef9f23545f72"
-      "c5602140046839e963313c3decc864",
-      "040106a14e2ee8ff970aa8ab0c79b97a33bba2958e070b75b94736b77bbe3f777324fa52872771aa88a63a9e8490c3378df4dc"
-      "760cd14d62be700779dd1a4377943656002366ce3941e0b284b1aa81215d0d3b9778fce23c8cd1e4ed6fa0abf62156c91d4b3eb"
-      "55999c3471bed275e9e60e5aa9d690d310bfb15c9c5bbd6f5e9eb39682b74",
-      "040098d99dee0816550e84dbfced7e88137fddcf581a725a455021115fe49f8dc3cf233cd9ea0e6f039dc7919da973cdceaca20"
-      "5da39e0bd98c8062536c47f258f44b500cd225c8797371be0c4297d2b457740100c774141d8f214c23b61aa2b6cd4806b9b70722"
-      "aa4965fb622f42b7391e27e5ec21c5679c5b06b59127372997d421adc1e",
-      "0145cfa38f25943516c96a5fd4bfebb2f645d10520117aa51971eff442808a23b4e23c187e639ff928c3725fbd1c0c2ad0d4aeb2"
-      "07bc1a6fb6cb6d467888dc044b3c",
-      "curve: P521 vector: 4", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "009b0af137c9696c75b7e6df7b73156bb2d45f482e5a4217324f478b10ceb76af09724cf86afa316e7f89918d31d54824a5c33"
-      "107a483c15c15b96edc661340b1c0e",
-      "0400748cdbb875d35f4bccb62abe20e82d32e4c14dc2feb5b87da2d0ccb11c9b6d4b7737b6c46f0dfb4d896e2db92fcf53cdbb"
-      "ae2a404c0babd564ad7adeac6273efa301984acab8d8f173323de0bb60274b228871609373bb22a17287e9dec7495873abc09a"
-      "8915b54c8455c8e02f654f602e23a2bbd7a9ebb74f3009bd65ecc650814cc0",
-      "04007ae115adaaf041691ab6b7fb8c921f99d8ed32d283d67084e80b9ad9c40c56cd98389fb0a849d9ecf7268c297b6f934061"
-      "19f40e32b5773ed25a28a9a85c4a758801a28e004e37eeaefe1f4dbb71f1878696141af3a10a9691c4ed93487214643b761fa4b"
-      "0fbeeb247cf6d3fba7a60697536ad03f49b80a9d1cb079673654977c5fa94",
-      "005c5721e96c273319fd60ecc46b5962f698e974b429f28fe6962f4ac656be2eb8674c4aafc037eab48ece612953b1e8d86101"
-      "6b6ad0c79805784c67f73ada96f351",
-      "curve: P521 vector: 5", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "01e48faacee6dec83ffcde944cf6bdf4ce4bae72747888ebafee455b1e91584971efb49127976a52f4142952f7c207ec0265f2b"
-      "718cf3ead96ea4f62c752e4f7acd3",
-      "04010eb1b4d9172bcc23f4f20cc9560fc54928c3f34ea61c00391dc766c76ed9fa608449377d1e4fadd1236025417330b4b91086"
-      "704ace3e4e6484c606e2a943478c860149413864069825ee1d0828da9f4a97713005e9bd1adbc3b38c5b946900721a960fe96ad2c"
-      "1b3a44fe3de9156136d44cb17cbc2415729bb782e16bfe2deb3069e43",
-      "04012588115e6f7f7bdcfdf57f03b169b479758baafdaf569d04135987b2ce6164c02a57685eb5276b5dae6295d3fe90620f38b55"
-      "35c6d2260c173e61eb888ca92020301542c169cf97c2596fe2ddd848a222e367c5f7e6267ebc1bcd9ab5dcf49158f1a48e4af29a89"
-      "7b7e6a82091c2db874d8e7abf0f58064691344154f396dbaed188b6",
-      "01736d9717429b4f412e903febe2f9e0fffd81355d6ce2c06ff3f66a3be15ceec6e65e308347593f00d7f33591da4043c30763d72"
-      "749f72cdceebe825e4b34ecd570",
-      "curve: P521 vector: 6", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "00c29aa223ea8d64b4a1eda27f39d3bc98ea0148dd98c1cbe595f8fd2bfbde119c9e017a50f5d1fc121c08c1cef31b75885955"
-      "6eb3e0e042d8dd6aaac57a05ca61e3",
-      "04001511c848ef60d5419a98d10204db0fe58224124370061bcfa4e9249d50618c56bf3722471b259f38263bb7b280d23caf2a"
-      "1ee8737f9371cdb2732cdc958369930c01d461681ae6d8c49b4c5f4d6016143fb1bd7491573e3ed0e6c48b82e821644f87f82f0"
-      "e5f08fd16f1f98fa17586200ab02ed8c627b35c3f27617ec5fd92f456203f",
-      "040169491d55bd09049fdf4c2a53a660480fee4c03a0538675d1cd09b5bba78dac48543ef118a1173b3fbf8b20e39ce0e6b8"
-      "90a163c50f9645b3d21d1cbb3b60a6fff40083494b2eba76910fed33c761804515011fab50e3b377abd8a8a045d886d2238d2"
-      "c268ac1b6ec88bd71b7ba78e2c33c152e4bf7da5d565e4acbecf5e92c7ad662bb",
-      "018f2ae9476c771726a77780208dedfefa205488996b18fecc50bfd4c132753f5766b2cd744afa9918606de2e016effc63622"
-      "e9029e76dc6e3f0c69f7aeced565c2c",
-      "curve: P521 vector: 7", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "0028692be2bf5c4b48939846fb3d5bce74654bb2646e15f8389e23708a1afadf561511ea0d9957d0b53453819d60fba8f65a1"
-      "8f7b29df021b1bb01cd163293acc3cc",
-      "0401cfdc10c799f5c79cb6930a65fba351748e07567993e5e410ef4cacc4cd8a25784991eb4674e41050f930c7190ac812b92"
-      "45f48a7973b658daf408822fe5b85f6680180d9ddfc9af77b9c4a6f02a834db15e535e0b3845b2cce30388301b51cecbe32763"
-      "07ef439b5c9e6a72dc2d94d879bc395052dbb4a5787d06efb280210fb8be037",
-      "04008415f5bbd0eee387d6c09d0ef8acaf29c66db45d6ba101860ae45d3c60e1e0e3f7247a4626a60fdd404965c3566c79f644"
-      "9e856ce0bf94619f97da8da24bd2cfb600fdd7c59c58c361bc50a7a5d0d36f723b17c4f2ad2b03c24d42dc50f74a8c465a0afc"
-      "4683f10fab84652dfe9e928c2626b5456453e1573ff60be1507467d431fbb2",
-      "0105a346988b92ed8c7a25ce4d79d21bc86cfcc7f99c6cd19dbb4a39f48ab943b79e4f0647348da0b80bd864b85c6b8d92536"
-      "d6aa544dc7537a00c858f8b66319e25",
-      "curve: P521 vector: 8", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "01194d1ee613f5366cbc44b504d21a0cf6715e209cd358f2dd5f3e71cc0d67d0e964168c42a084ebda746f9863a86bacffc81"
-      "9f1edf1b8c727ccfb3047240a57c435",
-      "04016bd15c8a58d366f7f2b2f298cc87b7485e9ee70d11d12448b8377c0a82c7626f67aff7f97be7a3546bf417eeeddf75a93"
-      "c130191c84108042ea2fca17fd3f80d1401560502d04b74fce1743aab477a9d1eac93e5226981fdb97a7478ce4ce566ff72439"
-      "31284fad850b0c2bcae0ddd2d97790160c1a2e77c3ed6c95ecc44b89e2637fc",
-      "0401c721eea805a5cba29f34ba5758775be0cf6160e6c08723f5ab17bf96a1ff2bd9427961a4f34b07fc0b14ca4b2bf6845de"
-      "bd5a869f124ebfa7aa72fe565050b7f1800b6e89eb0e1dcf181236f7c548fd1a8c16b258b52c1a9bfd3fe8f22841b26763265"
-      "f074c4ccf2d634ae97b701956f67a11006c52d97197d92f585f5748bc2672eeb",
-      "004531b3d2c6cd12f21604c8610e6723dbf4daf80b5a459d6ba5814397d1c1f7a21d7c114be964e27376aaebe3a7bc3d6af7"
-      "a7f8c7befb611afe487ff032921f750f",
-      "curve: P521 vector: 9", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "01fd90e3e416e98aa3f2b6afa7f3bf368e451ad9ca5bd54b5b14aee2ed6723dde5181f5085b68169b09fbec721372ccf6b"
-      "284713f9a6356b8d560a8ff78ca3737c88",
-      "0401ebea1b10d3e3b971b7efb69fc878de11c7f472e4e4d384c31b8d6288d8071517acade9b39796c7af5163bcf71aeda7"
-      "77533f382c6cf0a4d9bbb938c85f44b78037016b0e3e19c2996b2cbd1ff64730e7ca90edca1984f9b2951333535e5748baa"
-      "34a99f61ff4d5f812079e0f01e87789f34efdad8098015ee74a4f846dd190d16dc6e1",
-      "0401c35823e440a9363ab98d9fc7a7bc0c0532dc7977a79165599bf1a9cc64c00fb387b42cca365286e8430360bfad3643"
-      "bc31354eda50dc936c329ecdb60905c40fcb00d9e7f433531e44df4f6d514201cbaabb06badd6783e01111726d815531d23"
-      "3c5cdb722893ffbb2027259d594de77438809738120c6f783934f926c3fb69b40c409",
-      "0100c8935969077bae0ba89ef0df8161d975ec5870ac811ae7e65ca5394efba4f0633d41bf79ea5e5b9496bbd7aae000b05"
-      "94baa82ef8f244e6984ae87ae1ed124b7",
-      "curve: P521 vector: 10", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "009012ecfdadc85ced630afea534cdc8e9d1ab8be5f3753dcf5f2b09b40eda66fc6858549bc36e6f8df55998cfa9a0703a"
-      "ecf6c42799c245011064f530c09db98369",
-      "0400234e32be0a907131d2d128a6477e0caceb86f02479745e0fe245cb332de631c078871160482eeef584e274df7fa412c"
-      "ea3e1e91f71ecba8781d9205d48386341ad01cf86455b09b1c005cffba8d76289a3759628c874beea462f51f30bd581e380"
-      "3134307dedbb771b3334ee15be2e242cd79c3407d2f58935456c6941dd9b6d155a46",
-      "0400093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918ec6619b9931955d5a89d4d74adf10"
-      "46bb362192f2ef6bd3e3d2d04dd1f87054a00aa3fb2448335f694e3cda4ae0cc71b1b2f2a206fa802d7262f19983c44674f"
-      "e15327acaac1fa40424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf",
-      "017f36af19303841d13a389d95ec0b801c7f9a679a823146c75c17bc44256e9ad422a4f8b31f14647b2c7d317b933f7c294"
-      "6c4b8abd1d56d620fab1b5ff1a3adc71f",
-      "curve: P521 vector: 11", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "01b5ff847f8eff20b88cfad42c06e58c3742f2f8f1fdfd64b539ba48c25926926bd5e332b45649c0b184f77255e9d58fe8"
-      "afa1a6d968e2cb1d4637777120c765c128",
-      "0401de3dc9263bc8c4969dc684be0eec54befd9a9f3dba194d8658a789341bf0d78d84da6735227cafaf093519516911975"
-      "73c8c360a11e5285712b8bbdf5ac91b977c00812de58cd095ec2e5a9b247eb3ed41d8bef6aeace194a7a05b65aa5d289fbc9"
-      "b1770ec84bb6be0c2c64cc37c1d54a7f5d71377a9adbe20f26f6f2b544a821ea831",
-      "040083192ed0b1cb31f75817794937f66ad91cf74552cd510cedb9fd641310422af5d09f221cad249ee814d16dd7ac84ded"
-      "9eacdc28340fcfc9c0c06abe30a2fc28cd8002212ed868c9ba0fb2c91e2c39ba93996a3e4ebf45f2852d0928c48930e875c"
-      "c7b428d0e7f3f4d503e5d60c68cb49b13c2480cd486bed9200caddaddfe4ff8e3562",
-      "00062f9fc29ae1a68b2ee0dcf956cbd38c88ae5f645eaa546b00ebe87a7260bf724be20d34b9d02076655c933d056b21e30"
-      "4c24ddb1dedf1dd76de611fc4a2340336",
-      "curve: P521 vector: 12", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "011a6347d4e801c91923488354cc533e7e35fddf81ff0fb7f56bb0726e0c29ee5dcdc5f394ba54cf57269048aab6e055895c"
-      "8da24b8b0639a742314390cc04190ed6",
-      "0400fe30267f33ba5cdefc25cbb3c9320dad9ccb1d7d376644620ca4fadee5626a3cede25ad254624def727a7048f7145f761"
-      "62aa98042f9b123b2076f8e8cf59b3fdf001145dc6631953b6e2945e94301d6cbb098fe4b04f7ee9b09411df104dc82d7d79e"
-      "c46a01ed0f2d3e7db6eb680694bdeb107c1078aec6cabd9ebee3d342fe7e54df",
-      "0401a89b636a93e5d2ba6c2292bf23033a84f06a3ac1220ea71e806afbe097a804cc67e9baa514cfb6c12c9194be30212bf7a"
-      "ae7fdf6d376c212f0554e656463ffab7e0182efcaf70fc412d336602e014da47256a0b606f2addcce8053bf817ac8656bb4e4"
-      "2f14c8cbf2a68f488ab35dcdf64056271dee1f606a440ba4bd4e5a11b8b8e54f",
-      "0128ab09bfec5406799e610f772ba17e892249fa8e0e7b18a04b9197034b250b48294f1867fb9641518f92766066a07a8b917"
-      "b0e76879e1011e51ccbd9f540c54d4f",
-      "curve: P521 vector: 13", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "0022b6d2a22d71dfaa811d2d9f9f31fbed27f2e1f3d239538ddf3e4cc8c39a330266db25b7bc0a9704f17bde7f3592bf5f1f2d"
-      "4b56013aacc3d8d1bc02f00d3146cc",
-      "0400ba38cfbf9fd2518a3f61d43549e7a6a6d28b2be57ffd3e0faceb636b34ed17e044a9f249dae8fc132e937e2d9349cd2ed7"
-      "7bb1049ceb692a2ec5b17ad61502a64c001ec91d3058573fa6c0564a02a1a010160c313bc7c73510dc983e5461682b5be00dbc"
-      "e7e2c682ad73f29ca822cdc111f68fabe33a7b384a648342c3cdb9f050bcdb",
-      "04017200b3f16a68cbaed2bf78ba8cddfb6cffac262bba00fbc25f9dc72a07ce59372904899f364c44cb264c097b647d4412be"
-      "e3e519892d534d9129f8a28f7500fee700baba8d672a4f4a3b63de48b96f56e18df5d68f7d70d5109833f43770d6732e06b39ad"
-      "60d93e5b43db8789f1ec0aba47286a39ea584235acea757dbf13d53b58364",
-      "0101e462e9d9159968f6440e956f11dcf2227ae4aea81667122b6af9239a291eb5d6cf5a4087f358525fcacfa46bb2db01a75a"
-      "f1ba519b2d31da33eda87a9d565748",
-      "curve: P521 vector: 14", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "005bacfff268acf6553c3c583b464ea36a1d35e2b257a5d49eb3419d5a095087c2fb4d15cf5bf5af816d0f3ff7586490ccd3ddc1"
-      "a98b39ce63749c6288ce0dbdac7d",
-      "040036e488da7581472a9d8e628c58d6ad727311b7e6a3f6ae33a8544f34b09280249020be7196916fafd90e2ec54b66b5468d23"
-      "61b99b56fa00d7ac37abb8c6f16653011edb9fb8adb6a43f4f5f5fdc1421c9fe04fc8ba46c9b66334e3af927c8befb4307104f299"
-      "acec4e30f812d9345c9720d19869dbfffd4ca3e7d2713eb5fc3f42615",
-      "04004efd5dbd2f979e3831ce98f82355d6ca14a5757842875882990ab85ab9b7352dd6b9b2f4ea9a1e95c3880d65d1f3602f9ca6"
-      "53dc346fac858658d75626f4d4fb080061cf15dbdaa7f31589c98400373da284506d70c89f074ed262a9e28140796b7236c2eef99"
-      "016085e71552ff488c72b7339fefb7915c38459cb20ab85aec4e45052",
-      "0141d6a4b719ab67eaf04a92c0a41e2dda78f4354fb90bdc35202cc7699b9b04d49616f82255debf7bbec045ae58f982a66905fc"
-      "fae69d689785e38c868eb4a27e7b",
-      "curve: P521 vector: 15", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "008e2c93c5423876223a637cad367c8589da69a2d0fc68612f31923ae50219df2452e7cc92615b67f17b57ffd2f52b19154bb40"
-      "d7715336420fde2e89fee244f59dc",
-      "0400fa3b35118d6c422570f724a26f90b2833b19239174cea081c53133f64db60d6940ea1261299c04c1f4587cdb0c4c39616"
-      "479c1bb0c146799a118032dcf98f899c00069f040229006151fa32b51f679c8816f7c17506b403809dc77cd58a2aec430d94d"
-      "13b6c916de99f355aa45fcfbc6853d686c71be496a067d24bfaea4818fc51f75",
-      "040129891de0cf3cf82e8c2cf1bf90bb296fe00ab08ca45bb7892e0e227a504fdd05d2381a4448b68adff9c4153c87eacb783"
-      "30d8bd52515f9f9a0b58e85f446bb4e10009edd679696d3d1d0ef327f200383253f6413683d9e4fcc87bb35f112c2f110098d"
-      "15e5701d7ceee416291ff5fed85e687f727388b9afe26a4f6feed560b218e6bb",
-      "00345e26e0abb1aac12b75f3a9cf41efe1c336396dffa4a067a4c2cfeb878c68b2b045faa4e5b4e6fa4678f5b603c351903b1"
-      "4bf9a6a70c439257199a640890b61d1",
-      "curve: P521 vector: 16", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "0004d49d39d40d8111bf16d28c5936554326b197353eebbcf47545393bc8d3aaf98f14f5be7074bfb38e6cc97b989754074da"
-      "ddb3045f4e4ce745669fdb3ec0d5fa8",
-      "04012ec226d050ce07c79b3df4d0f0891f9f7adf462e8c98dbc1a2a14f5e53a3f5ad894433587cc429a8be9ea1d84fa33b180"
-      "3690dae04da7218d30026157fc995cf52004837dfbf3426f57b5c793269130abb9a38f618532211931154db4eeb9aede88e57"
-      "290f842ea0f2ea9a5f74c6203a3920fe4e305f6118f676b154e1d75b9cb5eb88",
-      "0401a3c20240e59f5b7a3e17c275d2314ba1741210ad58b71036f8c83cc1f6b0f409dfdd9113e94b67ec39c3291426c23ffc"
-      "c447054670d2908ff8fe67dc2306034c5c01d2825bfd3af8b1e13205780c137fe938f84fde40188e61ea02cead81badfdb425"
-      "c29f7d7fb0324debadc10bbb93de68f62c35069268283f5265865db57a79f7bf7",
-      "006fe9de6fb8e672e7fd150fdc5e617fabb0d43906354ccfd224757c7276f7a1010091b17ed072074f8d10a5ec971eb35a5c"
-      "b7076603b7bc38d432cbc059f80f9488",
-      "curve: P521 vector: 17", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "011a5d1cc79cd2bf73ea106f0e60a5ace220813b53e27b739864334a07c03367efda7a4619fa6eef3a9746492283b3c445610"
-      "a023a9cc49bf4591140384fca5c8bb5",
-      "0400eb07c7332eedb7d3036059d35f7d2288d4377d5f42337ad3964079fb120ccd4c8bd384b585621055217023acd9a94fcb3"
-      "b965bfb394675e788ade41a1de73e620c00491a835de2e6e7deb7e090f4a11f2c460c0b1f3d5e94ee8d751014dc720784fd3b"
-      "54500c86ebaef18429f09e8e876d5d1538968a030d7715dde99f0d8f06e29d59",
-      "04007e2d138f2832e345ae8ff65957e40e5ec7163f016bdf6d24a2243daa631d878a4a16783990c722382130f9e51f0c1bd6"
-      "ff5ac96780e48b68f5dec95f42e6144bb500b0de5c896791f52886b0f09913e26e78dd0b69798fc4df6d95e3ca708ecbcbcce1c1895f"
-      "5561bbabaae372e9e67e6e1a3be60e19b470cdf673ec1fc393d3426e20",
-      "01e4e759ecedce1013baf73e6fcc0b92451d03bdd50489b78871c333114990c9ba6a9b2fc7b1a2d9a1794c1b60d9279af6f"
-      "146f0bbfb0683140403bfa4ccdb524a29",
-      "curve: P521 vector: 18", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "010c908caf1be74c616b625fc8c1f514446a6aec83b5937141d6afbb0a8c7666a7746fa1f7a6664a2123e8cdf6cd8bf836c5"
-      "6d3c0ebdcc980e43a186f938f3a78ae7",
-      "040031890f4c7abec3f723362285d77d2636f876817db3bbc88b01e773597b969ff6f013ea470c854ab4a7739004eb8cbea6"
-      "9b82ddf36acadd406871798ecb2ac3aa7f00d8b429ae3250266b9643c0c765a60dc10155bc2531cf8627296f4978b6640a9e"
-      "600e19d0037d58503fa80799546a814d7478a550aa90e5ebeb052527faaeae5d08",
-      "0400118c36022209b1af8ebad1a12b566fc48744576e1199fe80de1cdf851cdf03e5b9091a8f7e079e83b7f827259b691d0"
-      "c22ee29d6bdf73ec7bbfd746f2cd97a357d00da5ff4904548a342e2e7ba6a1f4ee5f840411a96cf63e6fe622f22c13e614e"
-      "0a847c11a1ab3f1d12cc850c32e095614ca8f7e2721477b486e9ff40372977c3f65c",
-      "0163c9191d651039a5fe985a0eea1eba018a40ab1937fcd2b61220820ee8f2302e9799f6edfc3f5174f369d672d377ea895"
-      "4a8d0c8b851e81a56fda95212a6578f0e",
-      "curve: P521 vector: 19", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "01b37d6b7288de671360425d3e5ac1ccb21815079d8d73431e9b74a6f0e7ae004a357575b11ad66642ce8b775593eba9d98"
-      "bf25c75ef0b4d3a2098bbc641f59a2b77",
-      "0400189a5ee34de7e35aefeaeef9220c18071b4c29a4c3bd9d954458bd3e82a7a34da34cff5579b8101c065b1f2f527cf45"
-      "81501e28ef5671873e65267733d003520af01eb4bc50a7b4d4599d7e3fa773ddb9eb252c9b3422872e544bdf75c7bf60f51"
-      "66ddc11eb08fa7c30822dabaee373ab468eb2d922e484e2a527fff2ebb804b7d9a37",
-      "0401780edff1ca1c03cfbe593edc6c049bcb2860294a92c355489d9afb2e702075ade1c953895a456230a0cde905de4a3f"
-      "38573dbfcccd67ad6e7e93f0b5581e926a5d00a5481962c9162962e7f0ebdec936935d0eaa813e8226d40d7f6119bfd940"
-      "602380c86721e61db1830f51e139f210000bcec0d8edd39e54d73a9a129f95cd5fa979",
-      "015d613e267a36342e0d125cdad643d80d97ed0600afb9e6b9545c9e64a98cc6da7c5aaa3a8da0bdd9dd3b97e9788218a8"
-      "0abafc106ef065c8f1c4e1119ef58d298b",
-      "curve: P521 vector: 20", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "00f2661ac762f60c5fff23be5d969ccd4ec6f98e4e72618d12bdcdb9b4102162333788c0bae59f91cdfc172c7a1681ee44d9"
-      "6ab2135a6e5f3415ebbcd55165b1afb0",
-      "0400a8e25a6902d687b4787cdc94c364ac7cecc5c495483ed363dc0aa95ee2bd739c4c4d46b17006c728b076350d7d7e54c"
-      "6822f52f47162a25109aaaba690cab696ec0168d2f08fe19e4dc9ee7a195b03c9f7fe6676f9f520b6270557504e72ca4394"
-      "a2c6918625e15ac0c51b8f95cd560123653fb8e8ee6db961e2c4c62cc54e92e2a2a9",
-      "04016dacffa183e5303083a334f765de724ec5ec9402026d4797884a9828a0d321a8cfac74ab737fe20a7d6befcfc73b6a3"
-      "5c1c7b01d373e31abc192d48a4241a35803011e5327cac22d305e7156e559176e19bee7e4f2f59e86f1a9d0b6603b6a7df"
-      "1069bde6387feb71587b8ffce5b266e1bae86de29378a34e5c74b6724c4d40a719923",
-      "014d6082a3b5ced1ab8ca265a8106f302146c4acb8c30bb14a4c991e3c82a9731288bdb91e0e85bda313912d06384fc44"
-      "f2153fb13506fa9cf43c9aab5750988c943",
-      "curve: P521 vector: 21", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "00f430ca1261f09681a9282e9e970a9234227b1d5e58d558c3cc6eff44d1bdf53de16ad5ee2b18b92d62fc79586116b0e"
-      "fc15f79340fb7eaf5ce6c44341dcf8dde27",
-      "04006c1d9b5eca87de1fb871a0a32f807c725adccde9b3967453a71347d608f0c030cd09e338cdecbf4a02015bc8a6e8"
-      "d3e2595fe773ffc2fc4e4a55d0b1a2cc00323b01141b2109e7f4981c952aa818a2b9f6f5c41feccdb7a7a45b9b4b6729"
-      "37771b008cae5f934dfe3fed10d383ab1f38769c92ce88d9be5414817ecb073a31ab368ccb",
-      "0400a091421d3703e3b341e9f1e7d58f8cf7bdbd1798d001967b801d1cec27e605c580b2387c1cb464f55ce7ac803341"
-      "02ab03cfb86d88af76c9f4129c01bedd3bbfc4008c9c577a8e6fc446815e9d40baa66025f15dae285f19eb668ee60ae9"
-      "c98e7ecdbf2b2a68e22928059f67db188007161d3ecf397e0883f0c4eb7eaf7827a62205cc",
-      "0020c00747cb8d492fd497e0fec54644bf027d418ab686381f109712a99cabe328b9743d2225836f9ad66e5d7fed1de2"
-      "47e0da92f60d5b31f9e47672e57f710598f4",
-      "curve: P521 vector: 22", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "005dc33aeda03c2eb233014ee468dff753b72f73b00991043ea353828ae69d4cd0fadeda7bb278b535d7c57406ff2e6e"
-      "473a5a4ff98e90f90d6dadd25100e8d85666",
-      "0400c825ba307373cec8dd2498eef82e21fd9862168dbfeb83593980ca9f82875333899fe94f137daf1c4189eb502937"
-      "c3a367ea7951ed8b0f3377fcdf2922021d46a5016b8a2540d5e65493888bc337249e67c0a68774f3e8d81e3b4574a012"
-      "5165f0bd58b8af9de74b35832539f95c3cd9f1b759408560aa6851ae3ac7555347b0d3b13b",
-      "04004f38816681771289ce0cb83a5e29a1ab06fc91f786994b23708ff08a08a0f675b809ae99e9f9967eb1a49f196057"
-      "d69e50d6dedb4dd2d9a81c02bdcc8f7f518460009efb244c8b91087de1eed766500f0e81530752d469256ef79f6b965d"
-      "8a2232a0c2dbc4e8e1d09214bab38485be6e357c4200d073b52f04e4a16fc6f5247187aecb",
-      "00c2bfafcd7fbd3e2fd1c750fdea61e70bd4787a7e68468c574ee99ebc47eedef064e8944a73bcb7913dbab5d93dca6"
-      "60d216c553622362794f7a2acc71022bdb16f",
-      "curve: P521 vector: 23", ec_field_GFp },
-
-    { ECCurve_NIST_P521, 1,
-      "00df14b1f1432a7b0fb053965fd8643afee26b2451ecb6a8a53a655d5fbe16e4c64ce8647225eb11e7fdcb23627471"
-      "dffc5c2523bd2ae89957cba3a57a23933e5a78",
-      "04004e8583bbbb2ecd93f0714c332dff5ab3bc6396e62f3c560229664329baa5138c3bb1c36428abd4e23d17fcb7"
-      "a2cfcc224b2e734c8941f6f121722d7b6b9415457601cf0874f204b0363f020864672fadbf87c8811eb147758b254b"
-      "74b14fae742159f0f671a018212bbf25b8519e126d4cad778cfff50d288fd39ceb0cac635b175ec0",
-      "0401a32099b02c0bd85371f60b0dd20890e6c7af048c8179890fda308b359dbbc2b7a832bb8c6526c4af99a7ea3f0"
-      "b3cb96ae1eb7684132795c478ad6f962e4a6f446d017627357b39e9d7632a1370b3e93c1afb5c851b910eb4ead0c9"
-      "d387df67cde85003e0e427552f1cd09059aad0262e235cce5fba8cedc4fdc1463da76dcd4b6d1a46",
-      "01aaf24e5d47e4080c18c55ea35581cd8da30f1a079565045d2008d51b12d0abb4411cda7a0785b15d149ed301a36"
-      "97062f42da237aa7f07e0af3fd00eb1800d9c41",
-      "curve: P521 vector: 24", ec_field_GFp },
-
-    { ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL, 0 }
-};
-
-static ECDH_KAT nonnist_testvecs[] = {
-    { ECCurve25519, 1,
-      "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
-      NULL,
-      "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c",
-      "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552",
-      "curve: 25519 vector: 0", ec_field_plain },
-    { ECCurve25519, 1,
-      "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d",
-      NULL,
-      "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493",
-      "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957",
-      "curve: 25519 vector: 1", ec_field_plain },
-    { ECCurve25519, 1,
-      "0900000000000000000000000000000000000000000000000000000000000000",
-      NULL,
-      "0900000000000000000000000000000000000000000000000000000000000000",
-      "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079",
-      "curve: 25519 vector: 2", ec_field_plain },
-    { ECCurve25519, 1000,
-      "0900000000000000000000000000000000000000000000000000000000000000",
-      NULL,
-      "0900000000000000000000000000000000000000000000000000000000000000",
-      "684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51",
-      "curve: 25519 vector: 1000 iterations", ec_field_plain },
-#ifdef NSS_ENABLE_EXPENSIVE_TESTS
-    /* This test is disabled by default because it takes a very long time
-       * to run. */
-    { ECCurve25519, 1000000,
-      "0900000000000000000000000000000000000000000000000000000000000000",
-      NULL,
-      "0900000000000000000000000000000000000000000000000000000000000000",
-      "7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424",
-      "curve: 25519 vector: 1000000 iterations", ec_field_plain },
-#endif
-    { ECCurve25519, 1,
-      "174a56a75017c029e0861044d3c57c291823cf477ae6e21065cc121578bfa893",
-      NULL,
-      "7bd8396462a5788951caf3d3a28cb0904e4d081e62e6ac2d9da7152eb1310f30",
-      "28c09f6be3666a6ab3bf8f5b03eec14e95505e32726ae887053ce6a2061a9656",
-      "curve: 25519 custom vector 1", ec_field_plain },
-    { ECCurve25519, 1,
-      "577a2a7fcdacd4ccf7d7f81ba93ec83ae4bda32bec00ff7d59c294b69404f688",
-      NULL,
-      "a43b5491cbd9273abf694115f383fabe3bdc5f2baa30d2e00e43b6937a75cc5d",
-      "4aed703c32552576ca0b30a3fab53242e1eea29ddec993219d3c2b3c3e59b735",
-      "curve: 25519 custom vector 1", ec_field_plain },
-
-    { ECCurve_pastLastCurve, 0, NULL, NULL, NULL, NULL, NULL, 0 }
-};
-
-static ECDH_BAD nonnist_testvecs_bad_values[] = {
-    { ECCurve25519, "00", "curve: 25519 vector: 0 bad point", ec_field_plain },
-    { ECCurve25519,
-      "0100000000000000000000000000000000000000000000000000000000000000",
-      "curve: 25519 vector: 1 bad point", ec_field_plain },
-    { ECCurve25519,
-      "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b8",
-      "curve: 25519 vector: 2 bad point", ec_field_plain },
-    { ECCurve25519,
-      "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157",
-      "curve: 25519 vector: 3 bad point", ec_field_plain },
-    { ECCurve25519,
-      "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
-      "curve: 25519 vector: 4 bad point", ec_field_plain },
-    { ECCurve25519,
-      "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
-      "curve: 25519 vector: 5 bad point", ec_field_plain },
-    { ECCurve25519,
-      "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
-      "curve: 25519 vector: 6 bad point", ec_field_plain },
-    { ECCurve25519,
-      "cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880",
-      "curve: 25519 vector: 7 bad point", ec_field_plain },
-    { ECCurve25519,
-      "4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7",
-      "curve: 25519 vector: 8 bad point", ec_field_plain },
-    { ECCurve25519,
-      "d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-      "curve: 25519 vector: 9 bad point", ec_field_plain },
-    { ECCurve25519,
-      "daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-      "curve: 25519 vector: 10 bad point", ec_field_plain },
-    { ECCurve25519,
-      "dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-      "curve: 25519 vector: 11 bad point", ec_field_plain },
-
-    { ECCurve_pastLastCurve, 0, NULL, 0 }
-};
--- a/security/nss/cmd/tstclnt/tstclnt.c
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -184,19 +184,20 @@ handshakeCallback(PRFileDesc *fd, void *
 }
 
 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]\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",
+            "[-r N] [-w passwd] [-W pwfile] [-q [-t seconds]] [-I groups]\n"
+            "[-A requestfile] [-L totalconnections]",
             progName);
 }
 
 static void
 PrintParameterUsage(void)
 {
     fprintf(stderr, "%-20s Send different SNI name. 1st_hs_name - at first\n"
                     "%-20s handshake, 2nd_hs_name - at second handshake.\n"
@@ -253,20 +254,23 @@ PrintParameterUsage(void)
     fprintf(stderr, "%-20s Print cipher values allowed for parameter -c and exit\n", "-Y");
     fprintf(stderr, "%-20s Enforce using an IPv4 destination address\n", "-4");
     fprintf(stderr, "%-20s Enforce using an IPv6 destination address\n", "-6");
     fprintf(stderr, "%-20s (Options -4 and -6 cannot be combined.)\n", "");
     fprintf(stderr, "%-20s Enable the extended master secret extension [RFC7627]\n", "-G");
     fprintf(stderr, "%-20s Require the use of FFDHE supported groups "
                     "[I-D.ietf-tls-negotiated-ff-dhe]\n",
             "-H");
+    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",
-            "-G", "", "");
+            "-I", "", "");
 }
 
 static void
 Usage(const char *progName)
 {
     PrintUsageHeader(progName);
     PrintParameterUsage();
     exit(1);
@@ -885,64 +889,581 @@ restartHandshakeAfterServerCertIfNeeded(
 
     if (SSL_AuthCertificateComplete(fd, error) != SECSuccess) {
         rv = SECFailure;
     }
 
     return rv;
 }
 
-int
-main(int argc, char **argv)
+char *host = NULL;
+char *nickname = NULL;
+char *cipherString = NULL;
+int multiplier = 0;
+SSLVersionRange enabledVersions;
+int disableLocking = 0;
+int enableSessionTickets = 0;
+int enableCompression = 0;
+int enableFalseStart = 0;
+int enableCertStatus = 0;
+int enableSignedCertTimestamps = 0;
+int forceFallbackSCSV = 0;
+int enableExtendedMasterSecret = 0;
+PRBool requireDHNamedGroups = 0;
+PRSocketOptionData opt;
+PRNetAddr addr;
+PRBool allowIPv4 = PR_TRUE;
+PRBool allowIPv6 = PR_TRUE;
+PRBool pingServerFirst = PR_FALSE;
+int pingTimeoutSeconds = -1;
+PRBool clientSpeaksFirst = PR_FALSE;
+PRBool skipProtoHeader = PR_FALSE;
+ServerCertAuth serverCertAuth;
+char *hs1SniHostName = NULL;
+char *hs2SniHostName = NULL;
+PRUint16 portno = 443;
+int override = 0;
+char *requestString = NULL;
+PRInt32 requestStringLen = 0;
+PRBool enableZeroRtt = PR_FALSE;
+
+static int
+writeBytesToServer(PRFileDesc *s, PRPollDesc *pollset, const char *buf, int nb)
 {
-    PRFileDesc *s = NULL;
-    PRFileDesc *std_out;
-    char *host = NULL;
-    char *certDir = NULL;
-    char *nickname = NULL;
-    char *cipherString = NULL;
-    char *tmp;
-    int multiplier = 0;
+    SECStatus rv;
+    const char *bufp = buf;
+
+    FPRINTF(stderr, "%s: Writing %d bytes to server\n",
+            progName, nb);
+    do {
+        PRInt32 cc = PR_Send(s, bufp, nb, 0, maxInterval);
+        if (cc < 0) {
+            PRErrorCode err = PR_GetError();
+            if (err != PR_WOULD_BLOCK_ERROR) {
+                SECU_PrintError(progName,
+                                "write to SSL socket failed");
+                return 254;
+            }
+            cc = 0;
+        }
+        bufp += cc;
+        nb -= cc;
+        if (nb <= 0)
+            break;
+
+        rv = restartHandshakeAfterServerCertIfNeeded(s,
+                                                     &serverCertAuth, override);
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "authentication of server cert failed");
+            return EXIT_CODE_HANDSHAKE_FAILED;
+        }
+
+        pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+        pollset[SSOCK_FD].out_flags = 0;
+        FPRINTF(stderr,
+                "%s: about to call PR_Poll on writable socket !\n",
+                progName);
+        cc = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
+        if (cc < 0) {
+            SECU_PrintError(progName,
+                            "PR_Poll failed");
+            return -1;
+        }
+        FPRINTF(stderr,
+                "%s: PR_Poll returned with writable socket !\n",
+                progName);
+    } while (1);
+
+    return 0;
+}
+
+static int
+run_client(void)
+{
+    int headerSeparatorPtrnId = 0;
+    int error = 0;
     SECStatus rv;
     PRStatus status;
     PRInt32 filesReady;
     int npds;
-    int override = 0;
-    SSLVersionRange enabledVersions;
-    int disableLocking = 0;
-    int enableSessionTickets = 0;
-    int enableCompression = 0;
-    int enableFalseStart = 0;
-    int enableCertStatus = 0;
-    int enableSignedCertTimestamps = 0;
-    int forceFallbackSCSV = 0;
-    int enableExtendedMasterSecret = 0;
-    PRBool requireDHNamedGroups = 0;
-    PRSocketOptionData opt;
-    PRNetAddr addr;
+    PRFileDesc *s = NULL;
+    PRFileDesc *std_out;
     PRPollDesc pollset[2];
-    PRBool allowIPv4 = PR_TRUE;
-    PRBool allowIPv6 = PR_TRUE;
-    PRBool pingServerFirst = PR_FALSE;
-    int pingTimeoutSeconds = -1;
-    PRBool clientSpeaksFirst = PR_FALSE;
     PRBool wrStarted = PR_FALSE;
-    PRBool skipProtoHeader = PR_FALSE;
-    ServerCertAuth serverCertAuth;
-    int headerSeparatorPtrnId = 0;
-    int error = 0;
-    PRUint16 portno = 443;
-    char *hs1SniHostName = NULL;
-    char *hs2SniHostName = NULL;
+    char *requestStringInt = requestString;
+
+    /* Create socket */
+    s = PR_OpenTCPSocket(addr.raw.family);
+    if (s == NULL) {
+        SECU_PrintError(progName, "error creating socket");
+        error = 1;
+        goto done;
+    }
+
+    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 (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);
+    if (rv != SECSuccess) {
+        SECU_PrintError(progName, "error enabling client handshake");
+        error = 1;
+        goto done;
+    }
+
+    /* all SSL3 cipher suites are enabled by default. */
+    if (cipherString) {
+        char *cstringSaved = cipherString;
+        int ndx;
+
+        while (0 != (ndx = *cipherString++)) {
+            int cipher = 0;
+
+            if (ndx == ':') {
+                int ctmp = 0;
+
+                HEXCHAR_TO_INT(*cipherString, ctmp)
+                cipher |= (ctmp << 12);
+                cipherString++;
+                HEXCHAR_TO_INT(*cipherString, ctmp)
+                cipher |= (ctmp << 8);
+                cipherString++;
+                HEXCHAR_TO_INT(*cipherString, ctmp)
+                cipher |= (ctmp << 4);
+                cipherString++;
+                HEXCHAR_TO_INT(*cipherString, ctmp)
+                cipher |= ctmp;
+                cipherString++;
+            } else {
+                if (!isalpha(ndx))
+                    Usage(progName);
+                ndx = tolower(ndx) - 'a';
+                if (ndx < PR_ARRAY_SIZE(ssl3CipherSuites)) {
+                    cipher = ssl3CipherSuites[ndx];
+                }
+            }
+            if (cipher > 0) {
+                SECStatus status;
+                status = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED);
+                if (status != SECSuccess)
+                    SECU_PrintError(progName, "SSL_CipherPrefSet()");
+            } else {
+                Usage(progName);
+            }
+        }
+        PORT_Free(cstringSaved);
+    }
+
+    rv = SSL_VersionRangeSet(s, &enabledVersions);
+    if (rv != SECSuccess) {
+        SECU_PrintError(progName, "error setting SSL/TLS version range ");
+        error = 1;
+        goto done;
+    }
+
+    /* disable SSL socket locking */
+    rv = SSL_OptionSet(s, SSL_NO_LOCKS, disableLocking);
+    if (rv != SECSuccess) {
+        SECU_PrintError(progName, "error disabling SSL socket locking");
+        error = 1;
+        goto done;
+    }
+
+    /* enable Session Ticket extension. */
+    rv = SSL_OptionSet(s, SSL_ENABLE_SESSION_TICKETS, enableSessionTickets);
+    if (rv != SECSuccess) {
+        SECU_PrintError(progName, "error enabling Session Ticket extension");
+        error = 1;
+        goto done;
+    }
+
+    /* enable compression. */
+    rv = SSL_OptionSet(s, SSL_ENABLE_DEFLATE, enableCompression);
+    if (rv != SECSuccess) {
+        SECU_PrintError(progName, "error enabling compression");
+        error = 1;
+        goto done;
+    }
+
+    /* enable false start. */
+    rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START, enableFalseStart);
+    if (rv != SECSuccess) {
+        SECU_PrintError(progName, "error enabling false start");
+        error = 1;
+        goto done;
+    }
+
+    if (forceFallbackSCSV) {
+        rv = SSL_OptionSet(s, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "error forcing fallback scsv");
+            error = 1;
+            goto done;
+        }
+    }
+
+    /* enable cert status (OCSP stapling). */
+    rv = SSL_OptionSet(s, SSL_ENABLE_OCSP_STAPLING, enableCertStatus);
+    if (rv != SECSuccess) {
+        SECU_PrintError(progName, "error enabling cert status (OCSP stapling)");
+        error = 1;
+        goto done;
+    }
+
+    /* enable extended master secret mode */
+    if (enableExtendedMasterSecret) {
+        rv = SSL_OptionSet(s, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE);
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "error enabling extended master secret");
+            error = 1;
+            goto done;
+        }
+    }
+
+    /* enable 0-RTT (TLS 1.3 only) */
+    if (enableZeroRtt) {
+        rv = SSL_OptionSet(s, SSL_ENABLE_0RTT_DATA, PR_TRUE);
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "error enabling 0-RTT");
+            error = 1;
+            goto done;
+        }
+    }
+
+    /* require the use of fixed finite-field DH groups */
+    if (requireDHNamedGroups) {
+        rv = SSL_OptionSet(s, SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE);
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "error in requiring the use of fixed finite-field DH groups");
+            error = 1;
+            goto done;
+        }
+    }
+
+    /* enable Signed Certificate Timestamps. */
+    rv = SSL_OptionSet(s, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
+                       enableSignedCertTimestamps);
+    if (rv != SECSuccess) {
+        SECU_PrintError(progName, "error enabling signed cert timestamps");
+        error = 1;
+        goto done;
+    }
+
+    if (enabledGroups) {
+        rv = SSL_NamedGroupConfig(s, enabledGroups, enabledGroupsCount);
+        if (rv < 0) {
+            SECU_PrintError(progName, "SSL_NamedGroupConfig failed");
+            error = 1;
+            goto done;
+        }
+    }
+
+    serverCertAuth.dbHandle = CERT_GetDefaultCertDB();
+
+    SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth);
+    if (override) {
+        SSL_BadCertHook(s, ownBadCertHandler, NULL);
+    }
+    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");
+            error = 1;
+            goto done;
+        }
+    }
+
+    pollset[SSOCK_FD].fd = s;
+    pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT |
+                                 (clientSpeaksFirst ? 0 : PR_POLL_READ);
+    pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput);
+    if (!requestStringInt) {
+        pollset[STDIN_FD].in_flags = PR_POLL_READ;
+        npds = 2;
+    } else {
+        npds = 1;
+    }
+    std_out = PR_GetSpecialFD(PR_StandardOutput);
+
+#if defined(WIN32) || defined(OS2)
+    /* PR_Poll cannot be used with stdin on Windows or OS/2.  (sigh).
+    ** But use of PR_Poll and non-blocking sockets is a major feature
+    ** of this program.  So, we simulate a pollable stdin with a
+    ** TCP socket pair and a  thread that reads stdin and writes to
+    ** that socket pair.
+    */
+    {
+        PRFileDesc *fds[2];
+        PRThread *thread;
+
+        int nspr_rv = PR_NewTCPSocketPair(fds);
+        if (nspr_rv != PR_SUCCESS) {
+            SECU_PrintError(progName, "PR_NewTCPSocketPair failed");
+            error = 1;
+            goto done;
+        }
+        pollset[STDIN_FD].fd = fds[1];
+
+        thread = PR_CreateThread(PR_USER_THREAD, thread_main, fds[0],
+                                 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+                                 PR_UNJOINABLE_THREAD, 0);
+        if (!thread) {
+            SECU_PrintError(progName, "PR_CreateThread failed");
+            error = 1;
+            goto done;
+        }
+    }
+#endif
+
+    if (serverCertAuth.testFreshStatusFromSideChannel) {
+        SSL_ForceHandshake(s);
+        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.
+    */
+    FPRINTF(stderr, "%s: ready...\n", progName);
+    while ((pollset[SSOCK_FD].in_flags | pollset[STDIN_FD].in_flags) ||
+           requestStringInt) {
+        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");
+            goto done;
+        }
+
+        pollset[SSOCK_FD].out_flags = 0;
+        pollset[STDIN_FD].out_flags = 0;
+
+        FPRINTF(stderr, "%s: about to call PR_Poll !\n", progName);
+        filesReady = PR_Poll(pollset, npds, PR_INTERVAL_NO_TIMEOUT);
+        if (filesReady < 0) {
+            SECU_PrintError(progName, "select failed");
+            error = 1;
+            goto done;
+        }
+        if (filesReady == 0) { /* shouldn't happen! */
+            FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
+            error = 1;
+            goto done;
+        }
+        FPRINTF(stderr, "%s: PR_Poll returned!\n", progName);
+        if (pollset[STDIN_FD].in_flags) {
+            FPRINTF(stderr,
+                    "%s: PR_Poll returned 0x%02x for stdin out_flags.\n",
+                    progName, pollset[STDIN_FD].out_flags);
+        }
+        if (pollset[SSOCK_FD].in_flags) {
+            FPRINTF(stderr,
+                    "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
+                    progName, pollset[SSOCK_FD].out_flags);
+        }
+        if (requestStringInt) {
+            error = writeBytesToServer(s, pollset,
+                                       requestStringInt, requestStringLen);
+            if (error) {
+                goto done;
+            }
+            requestStringInt = NULL;
+            pollset[SSOCK_FD].in_flags = PR_POLL_READ;
+        }
+        if (pollset[STDIN_FD].out_flags & PR_POLL_READ) {
+            /* Read from stdin and write to socket */
+            nb = PR_Read(pollset[STDIN_FD].fd, buf, sizeof(buf));
+            FPRINTF(stderr, "%s: stdin read %d bytes\n", progName, nb);
+            if (nb < 0) {
+                if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+                    SECU_PrintError(progName, "read from stdin failed");
+                    error = 1;
+                    break;
+                }
+            } else if (nb == 0) {
+                /* EOF on stdin, stop polling stdin for read. */
+                pollset[STDIN_FD].in_flags = 0;
+            } else {
+                error = writeBytesToServer(s, pollset, buf, nb);
+                if (error) {
+                    goto done;
+                }
+                pollset[SSOCK_FD].in_flags = PR_POLL_READ;
+            }
+        }
+
+        if (pollset[SSOCK_FD].in_flags) {
+            FPRINTF(stderr,
+                    "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
+                    progName, pollset[SSOCK_FD].out_flags);
+        }
+        if ((pollset[SSOCK_FD].out_flags & PR_POLL_READ) ||
+            (pollset[SSOCK_FD].out_flags & PR_POLL_ERR)
+#ifdef PR_POLL_HUP
+            || (pollset[SSOCK_FD].out_flags & PR_POLL_HUP)
+#endif
+                ) {
+            /* Read from socket and write to stdout */
+            nb = PR_Recv(pollset[SSOCK_FD].fd, buf, sizeof buf, 0, maxInterval);
+            FPRINTF(stderr, "%s: Read from server %d bytes\n", progName, nb);
+            if (nb < 0) {
+                if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+                    SECU_PrintError(progName, "read from socket failed");
+                    error = 1;
+                    goto done;
+                }
+            } else if (nb == 0) {
+                /* EOF from socket... stop polling socket for read */
+                pollset[SSOCK_FD].in_flags = 0;
+            } else {
+                if (skipProtoHeader != PR_TRUE || wrStarted == PR_TRUE) {
+                    PR_Write(std_out, buf, nb);
+                } else {
+                    separateReqHeader(std_out, buf, nb, &wrStarted,
+                                      &headerSeparatorPtrnId);
+                }
+                if (verbose)
+                    fputs("\n\n", stderr);
+            }
+        }
+        milliPause(50 * multiplier);
+    }
+
+done:
+    if (s) {
+        PR_Close(s);
+    }
+
+    return error;
+}
+
+PRInt32
+ReadFile(const char *filename, char **data)
+{
+    char *ret = NULL;
+    char buf[8192];
+    unsigned int len = 0;
+    PRStatus rv;
+
+    PRFileDesc *fd = PR_Open(filename, PR_RDONLY, 0);
+    if (!fd)
+        return -1;
+
+    for (;;) {
+        rv = PR_Read(fd, buf, sizeof(buf));
+        if (rv < 0) {
+            PR_Free(ret);
+            return rv;
+        }
+
+        if (!rv)
+            break;
+
+        ret = PR_Realloc(ret, len + rv);
+        if (!ret) {
+            return -1;
+        }
+        PORT_Memcpy(ret + len, buf, rv);
+        len += rv;
+    }
+
+    *data = ret;
+    return len;
+}
+
+int
+main(int argc, char **argv)
+{
     PLOptState *optstate;
     PLOptStatus optstatus;
+    PRStatus status;
     PRStatus prStatus;
+    int error = 0;
+    char *tmp;
+    SECStatus rv;
+    char *certDir = NULL;
     PRBool openDB = PR_TRUE;
     PRBool loadDefaultRootCAs = PR_FALSE;
     char *rootModule = NULL;
+    int numConnections = 1;
+    PRFileDesc *s = NULL;
 
     serverCertAuth.shouldPause = PR_TRUE;
     serverCertAuth.isPaused = PR_FALSE;
     serverCertAuth.dbHandle = NULL;
     serverCertAuth.testFreshStatusFromSideChannel = PR_FALSE;
     serverCertAuth.sideChannelRevocationTestResultCode = EXIT_CODE_HANDSHAKE_FAILED;
     serverCertAuth.requireDataForIntermediates = PR_FALSE;
     serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
@@ -961,17 +1482,17 @@ main(int argc, char **argv)
         }
     }
 
     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,
-                                 "46CDFGHI:KM:OR:STUV:W:Ya:bc:d:fgh:m:n:op:qr:st:uvw:z");
+                                 "46A:CDFGHI:KL:M:OR:STUV:WYZa: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':
@@ -980,16 +1501,24 @@ main(int argc, char **argv)
                     Usage(progName);
                 break;
             case '6':
                 allowIPv4 = PR_FALSE;
                 if (!allowIPv6)
                     Usage(progName);
                 break;
 
+            case 'A':
+                requestStringLen = ReadFile(optstate->value, &requestString);
+                if (requestStringLen < 0) {
+                    fprintf(stderr, "Couldn't read file %s\n", optstate->value);
+                    exit(1);
+                }
+                break;
+
             case 'C':
                 ++dumpServerChain;
                 break;
 
             case 'D':
                 openDB = PR_FALSE;
                 break;
 
@@ -1012,16 +1541,20 @@ main(int argc, char **argv)
             case 'O':
                 serverCertAuth.shouldPause = PR_FALSE;
                 break;
 
             case 'K':
                 forceFallbackSCSV = PR_TRUE;
                 break;
 
+            case 'L':
+                numConnections = atoi(optstate->value);
+                break;
+
             case 'M':
                 switch (atoi(optstate->value)) {
                     case 1:
                         serverCertAuth.allowOCSPSideChannelData = PR_TRUE;
                         serverCertAuth.allowCRLSideChannelData = PR_FALSE;
                         break;
                     case 2:
                         serverCertAuth.allowOCSPSideChannelData = PR_FALSE;
@@ -1059,16 +1592,20 @@ main(int argc, char **argv)
                 }
                 break;
 
             case 'Y':
                 PrintCipherUsage(progName);
                 exit(0);
                 break;
 
+            case 'Z':
+                enableZeroRtt = PR_TRUE;
+                break;
+
             case 'a':
                 if (!hs1SniHostName) {
                     hs1SniHostName = PORT_Strdup(optstate->value);
                 } else if (!hs2SniHostName) {
                     hs2SniHostName = PORT_Strdup(optstate->value);
                 } else {
                     Usage(progName);
                 }
@@ -1237,16 +1774,17 @@ main(int argc, char **argv)
         char *certDirTmp = certDir;
         certDir = SECU_ConfigDirectory(certDirTmp);
         PORT_Free(certDirTmp);
     }
 
     if (pingServerFirst) {
         int iter = 0;
         PRErrorCode err;
+
         int max_attempts = MAX_WAIT_FOR_SERVER;
         if (pingTimeoutSeconds >= 0) {
             /* If caller requested a timeout, let's try just twice. */
             max_attempts = 2;
         }
         do {
             PRIntervalTime timeoutInterval = PR_INTERVAL_NO_TIMEOUT;
             s = PR_OpenTCPSocket(addr.raw.family);
@@ -1314,462 +1852,46 @@ 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();
     }
 
-    /* Create socket */
-    s = PR_OpenTCPSocket(addr.raw.family);
-    if (s == NULL) {
-        SECU_PrintError(progName, "error creating socket");
-        error = 1;
-        goto done;
-    }
-
-    opt.option = PR_SockOpt_Nonblocking;
-    opt.value.non_blocking = PR_TRUE; /* default */
-    if (serverCertAuth.testFreshStatusFromSideChannel) {
-        opt.value.non_blocking = PR_FALSE;
-    }
-    PR_SetSocketOption(s, &opt);
-    /*PR_SetSocketOption(PR_GetSpecialFD(PR_StandardInput), &opt);*/
-
-    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);
-    if (rv != SECSuccess) {
-        SECU_PrintError(progName, "error enabling client handshake");
-        error = 1;
-        goto done;
-    }
-
-    /* all SSL3 cipher suites are enabled by default. */
-    if (cipherString) {
-        char *cstringSaved = cipherString;
-        int ndx;
-
-        while (0 != (ndx = *cipherString++)) {
-            int cipher = 0;
-
-            if (ndx == ':') {
-                int ctmp = 0;
-
-                HEXCHAR_TO_INT(*cipherString, ctmp)
-                cipher |= (ctmp << 12);
-                cipherString++;
-                HEXCHAR_TO_INT(*cipherString, ctmp)
-                cipher |= (ctmp << 8);
-                cipherString++;
-                HEXCHAR_TO_INT(*cipherString, ctmp)
-                cipher |= (ctmp << 4);
-                cipherString++;
-                HEXCHAR_TO_INT(*cipherString, ctmp)
-                cipher |= ctmp;
-                cipherString++;
-            } else {
-                if (!isalpha(ndx))
-                    Usage(progName);
-                ndx = tolower(ndx) - 'a';
-                if (ndx < PR_ARRAY_SIZE(ssl3CipherSuites)) {
-                    cipher = ssl3CipherSuites[ndx];
-                }
-            }
-            if (cipher > 0) {
-                SECStatus status;
-                status = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED);
-                if (status != SECSuccess)
-                    SECU_PrintError(progName, "SSL_CipherPrefSet()");
-            } else {
-                Usage(progName);
-            }
-        }
-        PORT_Free(cstringSaved);
-    }
-
-    rv = SSL_VersionRangeSet(s, &enabledVersions);
-    if (rv != SECSuccess) {
-        SECU_PrintError(progName, "error setting SSL/TLS version range ");
-        error = 1;
-        goto done;
-    }
-
-    /* disable SSL socket locking */
-    rv = SSL_OptionSet(s, SSL_NO_LOCKS, disableLocking);
-    if (rv != SECSuccess) {
-        SECU_PrintError(progName, "error disabling SSL socket locking");
-        error = 1;
-        goto done;
-    }
-
-    /* enable Session Ticket extension. */
-    rv = SSL_OptionSet(s, SSL_ENABLE_SESSION_TICKETS, enableSessionTickets);
-    if (rv != SECSuccess) {
-        SECU_PrintError(progName, "error enabling Session Ticket extension");
-        error = 1;
-        goto done;
-    }
-
-    /* enable compression. */
-    rv = SSL_OptionSet(s, SSL_ENABLE_DEFLATE, enableCompression);
-    if (rv != SECSuccess) {
-        SECU_PrintError(progName, "error enabling compression");
-        error = 1;
-        goto done;
-    }
-
-    /* enable false start. */
-    rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START, enableFalseStart);
-    if (rv != SECSuccess) {
-        SECU_PrintError(progName, "error enabling false start");
-        error = 1;
-        goto done;
-    }
-
-    if (forceFallbackSCSV) {
-        rv = SSL_OptionSet(s, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
-        if (rv != SECSuccess) {
-            SECU_PrintError(progName, "error forcing fallback scsv");
-            error = 1;
-            goto done;
-        }
-    }
-
-    /* enable cert status (OCSP stapling). */
-    rv = SSL_OptionSet(s, SSL_ENABLE_OCSP_STAPLING, enableCertStatus);
-    if (rv != SECSuccess) {
-        SECU_PrintError(progName, "error enabling cert status (OCSP stapling)");
-        error = 1;
-        goto done;
-    }
-
-    /* enable extended master secret mode */
-    if (enableExtendedMasterSecret) {
-        rv = SSL_OptionSet(s, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE);
-        if (rv != SECSuccess) {
-            SECU_PrintError(progName, "error enabling extended master secret");
-            error = 1;
-            goto done;
-        }
-    }
-
-    /* require the use of fixed finite-field DH groups */
-    if (requireDHNamedGroups) {
-        rv = SSL_OptionSet(s, SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE);
-        if (rv != SECSuccess) {
-            SECU_PrintError(progName, "error in requiring the use of fixed finite-field DH groups");
-            error = 1;
-            goto done;
-        }
-    }
-
-    /* enable Signed Certificate Timestamps. */
-    rv = SSL_OptionSet(s, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
-                       enableSignedCertTimestamps);
-    if (rv != SECSuccess) {
-        SECU_PrintError(progName, "error enabling signed cert timestamps");
-        error = 1;
-        goto done;
-    }
-
-    if (enabledGroups) {
-        rv = SSL_NamedGroupConfig(s, enabledGroups, enabledGroupsCount);
-        if (rv < 0) {
-            SECU_PrintError(progName, "SSL_NamedGroupConfig failed");
-            error = 1;
+    while (numConnections--) {
+        error = run_client();
+        if (error) {
             goto done;
         }
     }
 
-    serverCertAuth.dbHandle = CERT_GetDefaultCertDB();
-
-    SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth);
-    if (override) {
-        SSL_BadCertHook(s, ownBadCertHandler, NULL);
-    }
-    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");
-            error = 1;
-            goto done;
-        }
-    }
-
-    pollset[SSOCK_FD].fd = s;
-    pollset[SSOCK_FD].in_flags = PR_POLL_EXCEPT |
-                                 (clientSpeaksFirst ? 0 : PR_POLL_READ);
-    pollset[STDIN_FD].fd = PR_GetSpecialFD(PR_StandardInput);
-    pollset[STDIN_FD].in_flags = PR_POLL_READ;
-    npds = 2;
-    std_out = PR_GetSpecialFD(PR_StandardOutput);
-
-#if defined(WIN32) || defined(OS2)
-    /* PR_Poll cannot be used with stdin on Windows or OS/2.  (sigh).
-    ** But use of PR_Poll and non-blocking sockets is a major feature
-    ** of this program.  So, we simulate a pollable stdin with a
-    ** TCP socket pair and a  thread that reads stdin and writes to
-    ** that socket pair.
-    */
-    {
-        PRFileDesc *fds[2];
-        PRThread *thread;
-
-        int nspr_rv = PR_NewTCPSocketPair(fds);
-        if (nspr_rv != PR_SUCCESS) {
-            SECU_PrintError(progName, "PR_NewTCPSocketPair failed");
-            error = 1;
-            goto done;
-        }
-        pollset[STDIN_FD].fd = fds[1];
-
-        thread = PR_CreateThread(PR_USER_THREAD, thread_main, fds[0],
-                                 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
-                                 PR_UNJOINABLE_THREAD, 0);
-        if (!thread) {
-            SECU_PrintError(progName, "PR_CreateThread failed");
-            error = 1;
-            goto done;
-        }
-    }
-#endif
-
-    if (serverCertAuth.testFreshStatusFromSideChannel) {
-        SSL_ForceHandshake(s);
-        error = serverCertAuth.sideChannelRevocationTestResultCode;
-        goto done;
+done:
+    if (s) {
+        PR_Close(s);
     }
 
-    /*
-    ** Select on stdin and on the socket. Write data from stdin to
-    ** socket, read data from socket and write to stdout.
-    */
-    FPRINTF(stderr, "%s: ready...\n", progName);
-
-    while (pollset[SSOCK_FD].in_flags | pollset[STDIN_FD].in_flags) {
-        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");
-            goto done;
-        }
-
-        pollset[SSOCK_FD].out_flags = 0;
-        pollset[STDIN_FD].out_flags = 0;
-
-        FPRINTF(stderr, "%s: about to call PR_Poll !\n", progName);
-        filesReady = PR_Poll(pollset, npds, PR_INTERVAL_NO_TIMEOUT);
-        if (filesReady < 0) {
-            SECU_PrintError(progName, "select failed");
-            error = 1;
-            goto done;
-        }
-        if (filesReady == 0) { /* shouldn't happen! */
-            FPRINTF(stderr, "%s: PR_Poll returned zero!\n", progName);
-            error = 1;
-            goto done;
-        }
-        FPRINTF(stderr, "%s: PR_Poll returned!\n", progName);
-        if (pollset[STDIN_FD].in_flags) {
-            FPRINTF(stderr,
-                    "%s: PR_Poll returned 0x%02x for stdin out_flags.\n",
-                    progName, pollset[STDIN_FD].out_flags);
-        }
-        if (pollset[SSOCK_FD].in_flags) {
-            FPRINTF(stderr,
-                    "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
-                    progName, pollset[SSOCK_FD].out_flags);
-        }
-        if (pollset[STDIN_FD].out_flags & PR_POLL_READ) {
-            /* Read from stdin and write to socket */
-            nb = PR_Read(pollset[STDIN_FD].fd, buf, sizeof(buf));
-            FPRINTF(stderr, "%s: stdin read %d bytes\n", progName, nb);
-            if (nb < 0) {
-                if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
-                    SECU_PrintError(progName, "read from stdin failed");
-                    error = 1;
-                    break;
-                }
-            } else if (nb == 0) {
-                /* EOF on stdin, stop polling stdin for read. */
-                pollset[STDIN_FD].in_flags = 0;
-            } else {
-                char *bufp = buf;
-                FPRINTF(stderr, "%s: Writing %d bytes to server\n",
-                        progName, nb);
-                do {
-                    PRInt32 cc = PR_Send(s, bufp, nb, 0, maxInterval);
-                    if (cc < 0) {
-                        PRErrorCode err = PR_GetError();
-                        if (err != PR_WOULD_BLOCK_ERROR) {
-                            SECU_PrintError(progName,
-                                            "write to SSL socket failed");
-                            error = 254;
-                            goto done;
-                        }
-                        cc = 0;
-                    }
-                    bufp += cc;
-                    nb -= cc;
-                    if (nb <= 0)
-                        break;
-
-                    rv = restartHandshakeAfterServerCertIfNeeded(s,
-                                                                 &serverCertAuth, override);
-                    if (rv != SECSuccess) {
-                        error = EXIT_CODE_HANDSHAKE_FAILED;
-                        SECU_PrintError(progName, "authentication of server cert failed");
-                        goto done;
-                    }
-
-                    pollset[SSOCK_FD].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
-                    pollset[SSOCK_FD].out_flags = 0;
-                    FPRINTF(stderr,
-                            "%s: about to call PR_Poll on writable socket !\n",
-                            progName);
-                    cc = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
-                    if (cc < 0) {
-                        SECU_PrintError(progName,
-                                        "PR_Poll failed");
-                        error = 1;
-                        goto done;
-                    }
-                    FPRINTF(stderr,
-                            "%s: PR_Poll returned with writable socket !\n",
-                            progName);
-                } while (1);
-                pollset[SSOCK_FD].in_flags = PR_POLL_READ;
-            }
-        }
-
-        if (pollset[SSOCK_FD].in_flags) {
-            FPRINTF(stderr,
-                    "%s: PR_Poll returned 0x%02x for socket out_flags.\n",
-                    progName, pollset[SSOCK_FD].out_flags);
-        }
-        if ((pollset[SSOCK_FD].out_flags & PR_POLL_READ) ||
-            (pollset[SSOCK_FD].out_flags & PR_POLL_ERR)
-#ifdef PR_POLL_HUP
-            || (pollset[SSOCK_FD].out_flags & PR_POLL_HUP)
-#endif
-                ) {
-            /* Read from socket and write to stdout */
-            nb = PR_Recv(pollset[SSOCK_FD].fd, buf, sizeof buf, 0, maxInterval);
-            FPRINTF(stderr, "%s: Read from server %d bytes\n", progName, nb);
-            if (nb < 0) {
-                if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
-                    SECU_PrintError(progName, "read from socket failed");
-                    error = 1;
-                    goto done;
-                }
-            } else if (nb == 0) {
-                /* EOF from socket... stop polling socket for read */
-                pollset[SSOCK_FD].in_flags = 0;
-            } else {
-                if (skipProtoHeader != PR_TRUE || wrStarted == PR_TRUE) {
-                    PR_Write(std_out, buf, nb);
-                } else {
-                    separateReqHeader(std_out, buf, nb, &wrStarted,
-                                      &headerSeparatorPtrnId);
-                }
-                if (verbose)
-                    fputs("\n\n", stderr);
-            }
-        }
-        milliPause(50 * multiplier);
-    }
-
-done:
     if (hs1SniHostName) {
         PORT_Free(hs1SniHostName);
     }
     if (hs2SniHostName) {
         PORT_Free(hs2SniHostName);
     }
     if (nickname) {
         PORT_Free(nickname);
     }
     if (pwdata.data) {
         PORT_Free(pwdata.data);
     }
     PORT_Free(host);
+    PORT_Free(requestString);
 
-    if (s) {
-        PR_Close(s);
-    }
     if (enabledGroups) {
         PORT_Free(enabledGroups);
     }
-
     if (NSS_IsInitialized()) {
         SSL_ClearSessionCache();
         if (NSS_Shutdown() != SECSuccess) {
             error = 1;
         }
     }
 
     FPRINTF(stderr, "tstclnt: exiting with return code %d\n", error);
--- a/security/nss/coreconf/check_cc_clang.py
+++ b/security/nss/coreconf/check_cc_clang.py
@@ -1,12 +1,20 @@
 #!/usr/bin/env python
 
 import os
 import subprocess
+import sys
 
 def main():
-    cc = os.environ.get('CC', 'cc')
-    cc_is_clang = 'clang' in subprocess.check_output([cc, '--version'])
-    print int(cc_is_clang)
+    if sys.platform == 'win32':
+        print 0
+    else:
+        cc = os.environ.get('CC', 'cc')
+        try:
+            cc_is_clang = 'clang' in subprocess.check_output([cc, '--version'])
+        except OSError:
+            # We probably just don't have CC/cc.
+            cc_is_clang = False
+        print int(cc_is_clang)
 
 if __name__ == '__main__':
     main()
--- a/security/nss/coreconf/config.gypi
+++ b/security/nss/coreconf/config.gypi
@@ -22,32 +22,27 @@
         }, {
           # Default architecture we're building for is the architecture we're
           # building on.
           'target_arch%': '<(host_arch)',
         }],
         ['OS=="win"', {
           'use_system_zlib%': 0,
           'nspr_libs%': ['nspr4.lib', 'plc4.lib', 'plds4.lib'],
-          #XXX: gyp breaks if these are empty!
-          'nspr_lib_dir%': ' ',
-          'nspr_include_dir%': ' ',
           'zlib_libs%': [],
           #TODO
           'moz_debug_flags%': '',
           'dll_prefix': '',
           'dll_suffix': 'dll',
         }, {
           'nspr_libs%': ['-lplds4', '-lplc4', '-lnspr4'],
-          'nspr_lib_dir%': '<!(<(python) <(DEPTH)/coreconf/pkg_config.py . --libs nspr)',
-          'nspr_include_dir%': '<!(<(python) <(DEPTH)/coreconf/pkg_config.py . --cflags nspr)',
           'use_system_zlib%': 1,
         }],
         ['OS=="linux" or OS=="android"', {
-          'zlib_libs%': ['<!@(<(python) <(DEPTH)/coreconf/pkg_config.py raw --libs zlib)'],
+          'zlib_libs%': ['-lz'],
           'moz_debug_flags%': '-gdwarf-2',
           'optimize_flags%': '-O2',
           'dll_prefix': 'lib',
           'dll_suffix': 'so',
         }],
         ['OS=="linux"', {
           'freebl_name': 'freeblpriv3',
         }, {
@@ -92,18 +87,23 @@
     'disable_dbm%': 0,
     'disable_libpkix%': 1,
     'disable_werror%': 0,
     'mozilla_client%': 0,
     'moz_fold_libs%': 0,
     'moz_folded_library_name%': '',
     'ssl_enable_zlib%': 1,
     'use_asan%': 0,
+    'use_ubsan%': 0,
+    'use_sancov%': 0,
     'test_build%': 0,
     'fuzz%': 0,
+    'sign_libs%': 1,
+    'nss_public_dist_dir%': '<(nss_dist_dir)/public',
+    'nss_private_dist_dir%': '<(nss_dist_dir)/private',
   },
   'target_defaults': {
     # Settings specific to targets should go here.
     # This is mostly for linking to libraries.
     'variables': {
       'mapfile%': '',
       'test_build%': 0,
     },
@@ -213,17 +213,17 @@
             'SubSystem': '2',
           },
         },
       }],
     ],
     'default_configuration': 'Debug',
     'configurations': {
       # Common settings for Debug+Release should go here.
-      'Common_Base': {
+      'Common': {
         'abstract': 1,
         'defines': [
           'NSS_NO_INIT_SUPPORT',
           'USE_UTIL_DIRECTLY',
           'NO_NSPR_10_SUPPORT',
           'SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES',
         ],
         'msvs_configuration_attributes': {
@@ -253,40 +253,95 @@
               'XP_UNIX',
               '_REENTRANT',
             ],
             'cflags': [
               '-fPIC',
               '-pipe',
               '-ffunction-sections',
               '-fdata-sections',
-              '<(moz_debug_flags)',
             ],
             'cflags_cc': [
               '-std=c++0x',
             ],
             'conditions': [
-
               [ 'target_arch=="ia32"', {
                 'cflags': ['-m32'],
                 'ldflags': ['-m32'],
               }],
               [ 'target_arch=="x64"', {
                 'cflags': ['-m64'],
                 'ldflags': ['-m64'],
               }],
             ],
           }],
           [ 'disable_werror==0 and (OS=="linux" or OS=="mac")', {
             'cflags': [
               '<!@(<(python) <(DEPTH)/coreconf/werror.py)',
             ],
           }],
           [ 'fuzz==1', {
-            'cflags': ['-Wno-unused-function']
+            'cflags': [
+              '-Wno-unused-function',
+            ]
+          }],
+          [ 'use_asan==1 or use_ubsan==1', {
+            'cflags': ['-O1'],
+            'xcode_settings': {
+              'GCC_OPTIMIZATION_LEVEL': '1', # -O1
+            }
+          }],
+          [ 'use_asan==1', {
+            'variables': {
+              'asan_flags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py asan)',
+              'no_ldflags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py ld)',
+            },
+            'cflags': ['<@(asan_flags)'],
+            'ldflags': ['<@(asan_flags)'],
+            'ldflags!': ['<@(no_ldflags)'],
+            'xcode_settings': {
+              'OTHER_CFLAGS': ['<@(asan_flags)'],
+              'OTHER_LDFLAGS!': ['<@(no_ldflags)'],
+              # We want to pass -fsanitize=... to our final link call,
+              # but not to libtool. OTHER_LDFLAGS is passed to both.
+              # To trick GYP into doing what we want, we'll piggyback on
+              # LIBRARY_SEARCH_PATHS, producing "-L/usr/lib -fsanitize=...".
+              # The -L/usr/lib is redundant but innocuous: it's a default path.
+              'LIBRARY_SEARCH_PATHS': ['/usr/lib <(asan_flags)'],
+            },
+          }],
+          [ 'use_ubsan==1', {
+            'variables': {
+              'ubsan_flags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py ubsan)',
+              'no_ldflags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py ld)',
+            },
+            'cflags': ['<@(ubsan_flags)'],
+            'ldflags': ['<@(ubsan_flags)'],
+            'ldflags!': ['<@(no_ldflags)'],
+            'xcode_settings': {
+              'OTHER_CFLAGS': ['<@(ubsan_flags)'],
+              'OTHER_LDFLAGS!': ['<@(no_ldflags)'],
+              # See comment above.
+              'LIBRARY_SEARCH_PATHS': ['/usr/lib <(ubsan_flags)'],
+            },
+          }],
+          [ 'use_sancov!=0', {
+            'variables': {
+              'sancov_flags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py sancov <(use_sancov))',
+              'no_ldflags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py ld)',
+            },
+            'cflags': ['<@(sancov_flags)'],
+            'ldflags': ['<@(sancov_flags)'],
+            'ldflags!': ['<@(no_ldflags)'],
+            'xcode_settings': {
+              'OTHER_CFLAGS': ['<@(sancov_flags)'],
+              'OTHER_LDFLAGS!': ['<@(no_ldflags)'],
+              # See comment above.
+              'LIBRARY_SEARCH_PATHS': ['/usr/lib <(sancov_flags)'],
+            },
           }],
           [ 'OS=="android" and mozilla_client==0', {
             'defines': [
               'NO_SYSINFO',
               'NO_FORK_CHECK',
               'ANDROID',
             ],
           }],
@@ -322,89 +377,96 @@
               '-w44267', # Disable C4267: conversion from 'size_t' to 'type', possible loss of data
               '-w44244', # Disable C4244: conversion from 'type1' to 'type2', possible loss of data
               '-w44018', # Disable C4018: 'expression' : signed/unsigned mismatch
               '-w44312', # Disable C4312: 'type cast': conversion from 'type1' to 'type2' of greater size
             ],
             'conditions': [
               [ 'disable_werror==0', {
                 'cflags': ['-WX']
-              }]
+              }],
+              [ 'target_arch=="ia32"', {
+                'msvs_configuration_platform': 'Win32',
+                'msvs_settings': {
+                  'VCLinkerTool': {
+                    'MinimumRequiredVersion': '5.01',  # XP.
+                    'TargetMachine': '1',
+                    'ImageHasSafeExceptionHandlers': 'false',
+                  },
+                  'VCCLCompilerTool': {
+                    'PreprocessorDefinitions': [
+                      'WIN32',
+                    ],
+                  },
+                },
+
+              }],
+              [ 'target_arch=="x64"', {
+                'msvs_configuration_platform': 'x64',
+                'msvs_settings': {
+                  'VCLinkerTool': {
+                    'TargetMachine': '17', # x86-64
+                  },
+                  'VCCLCompilerTool': {
+                    'PreprocessorDefinitions': [
+                      'WIN64',
+                      '_AMD64_',
+                    ],
+                  },
+                },
+              }],
             ],
           }],
           [ 'disable_dbm==1', {
             'defines': [
               'NSS_DISABLE_DBM',
             ],
           }],
           [ 'disable_libpkix==1', {
             'defines': [
               'NSS_DISABLE_LIBPKIX',
             ],
           }],
         ],
       },
-      # Common settings for x86 should go here.
-      'x86_Base': {
-        'abstract': 1,
-        'msvs_settings': {
-          'VCLinkerTool': {
-            'MinimumRequiredVersion': '5.01',  # XP.
-            'TargetMachine': '1',
-          },
-          'VCCLCompilerTool': {
-            'PreprocessorDefinitions': [
-              'WIN32',
+      # Common settings for debug should go here.
+      'Debug': {
+        'inherit_from': ['Common'],
+        'conditions': [
+          [ 'OS=="linux" or OS=="android"', {
+            'cflags': [
+              '-g',
+              '<(moz_debug_flags)',
             ],
-          },
-        },
-        'msvs_configuration_platform': 'Win32',
-      },
-      # Common settings for x86-64 should go here.
-      'x64_Base': {
-        'abstract': 1,
-        'msvs_configuration_platform': 'x64',
-        'msvs_settings': {
-          'VCLinkerTool': {
-            'TargetMachine': '17', # x86-64
-          },
-          'VCCLCompilerTool': {
-            'PreprocessorDefinitions': [
-              'WIN64',
-              '_AMD64_',
-            ],
-          },
-        },
-      },
-      # Common settings for debug should go here.
-      'Debug_Base': {
-        'abstract': 1,
+          }]
+        ],
         #TODO: DEBUG_$USER
         'defines': ['DEBUG'],
         'xcode_settings': {
           'COPY_PHASE_STRIP': 'NO',
           'GCC_OPTIMIZATION_LEVEL': '0',
+          'GCC_GENERATE_DEBUGGING_SYMBOLS': 'YES',
         },
         'msvs_settings': {
           'VCCLCompilerTool': {
             'Optimization': '0',
             'BasicRuntimeChecks': '3',
             'RuntimeLibrary': '2', # /MD
           },
           'VCLinkerTool': {
             'LinkIncremental': '1',
           },
           'VCResourceCompilerTool': {
             'PreprocessorDefinitions': ['DEBUG'],
           },
         },
       },
-      # Common settings for release should go here.n
-      'Release_Base': {
-        'abstract': 1,
+      # Common settings for release should go here.
+      'Release': {
+        'inherit_from': ['Common'],
         'defines': [
           'NDEBUG',
         ],
         'xcode_settings': {
           'DEAD_CODE_STRIPPING': 'YES',  # -Wl,-dead_strip
           'GCC_OPTIMIZATION_LEVEL': '2', # -O2
         },
         'msvs_settings': {
@@ -412,34 +474,30 @@
             'Optimization': '2', # /Os
             'RuntimeLibrary': '2', # /MD
           },
           'VCLinkerTool': {
             'LinkIncremental': '1',
           },
         },
       },
-      #
-      # Concrete configurations
-      #
-      # These configurations shouldn't have anything in them, it should
-      # all be derived from the _Base configurations above.
-      'Debug': {
-        'inherit_from': ['Common_Base', 'x86_Base', 'Debug_Base'],
-      },
-      'Release': {
-        'inherit_from': ['Common_Base', 'x86_Base', 'Release_Base'],
-      },
-      # The gyp ninja backend requires these.
-      'Debug_x64': {
-        'inherit_from': ['Common_Base', 'x64_Base', 'Debug_Base'],
-      },
-      'Release_x64': {
-        'inherit_from': ['Common_Base', 'x64_Base', 'Release_Base'],
-      },
+      'conditions': [
+        [ 'OS=="win"', {
+          # The gyp ninja backend requires these.
+          # TODO: either we should support building both 32/64-bit as
+          # configurations from the same gyp build, or we should fix
+          # upstream gyp to not require these.
+          'Debug_x64': {
+            'inherit_from': ['Debug'],
+          },
+          'Release_x64': {
+            'inherit_from': ['Release'],
+          },
+        }],
+      ],
     },
   },
   'conditions': [
     [ 'OS=="linux" or OS=="android"', {
       'variables': {
         'process_map_file': ['/bin/sh', '-c', '/bin/grep -v ";-" >(mapfile) | sed -e "s,;+,," -e "s; DATA ;;" -e "s,;;,," -e "s,;.*,;," > >@(_outputs)'],
       },
     }],
--- 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/coreconf/detect_host_arch.py
+++ b/security/nss/coreconf/detect_host_arch.py
@@ -1,33 +1,25 @@
 #!/usr/bin/env python
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-"""Outputs host CPU architecture in format recognized by gyp."""
+#
+# 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/.
+
+from __future__ import print_function
+
+import fnmatch
 import platform
-import re
 
-def HostArch():
-  """Returns the host architecture with a predictable string."""
-  host_arch = platform.machine().lower()
-  # Convert machine type to format recognized by gyp.
-  if re.match(r'i.86', host_arch) or host_arch == 'i86pc':
-    host_arch = 'ia32'
-  elif host_arch in ['x86_64', 'amd64']:
-    host_arch = 'x64'
-  elif host_arch.startswith('arm'):
-    host_arch = 'arm'
-  elif host_arch.startswith('mips'):
-    host_arch = 'mips'
-  # platform.machine is based on running kernel. It's possible to use 64-bit
-  # kernel with 32-bit userland, e.g. to give linker slightly more memory.
-  # Distinguish between different userland bitness by querying
-  # the python binary.
-  if host_arch == 'x64' and platform.architecture()[0] == '32bit':
-    host_arch = 'ia32'
-  return host_arch
-def DoMain(_):
-  """Hook to be called from gyp without starting a separate python
-  interpreter."""
-  return HostArch()
+def main():
+    host_arch = platform.machine().lower()
+    if host_arch in ('amd64', 'x86_64'):
+        host_arch = 'x64'
+    elif fnmatch.fnmatch(host_arch, 'i?86') or host_arch == 'i86pc':
+        host_arch = 'x64'
+    elif host_arch.startswith('arm'):
+        host_arch = 'arm'
+    elif host_arch.startswith('mips'):
+        host_arch = 'mips'
+    print(host_arch)
+
 if __name__ == '__main__':
-  print DoMain([])
+    main()
new file mode 100644
--- /dev/null
+++ b/security/nss/coreconf/nspr.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# This script builds NSPR for NSS.
+#
+# This build system is still under development.  It does not yet support all
+# the features or platforms that the regular NSPR build supports.
+
+# variables
+nspr_opt=()
+nspr_cflags=
+nspr_cxxflags=
+nspr_ldflags=
+
+nspr_sanitizer()
+{
+    nspr_cflags="$nspr_cflags $(python $cwd/coreconf/sanitizers.py $1 $2)"
+    nspr_cxxflags="$nspr_cxxflags $(python $cwd/coreconf/sanitizers.py $1 $2)"
+    nspr_ldflags="$nspr_ldflags $(python $cwd/coreconf/sanitizers.py $1 $2)"
+}
+
+verbose()
+{
+    CFLAGS=$nspr_cflags CXXFLAGS=$nspr_cxxflags LDFLAGS=$nspr_ldflags \
+      CC=$CC CXX=$CCC ../configure "${nspr_opt[@]}" --prefix="$obj_dir"
+    make -C "$cwd/../nspr/$target"
+    make -C "$cwd/../nspr/$target" install
+}
+
+silent()
+{
+    echo "[1/3] configure NSPR ..."
+    CFLAGS=$nspr_cflags CXXFLAGS=$nspr_cxxflags LDFLAGS=$nspr_ldflags \
+      CC=$CC CXX=$CCC ../configure "${nspr_opt[@]}" --prefix="$obj_dir" 1> /dev/null
+    echo "[2/3] make NSPR ..."
+    make -C "$cwd/../nspr/$target" 1> /dev/null
+    echo "[3/3] install NSPR ..."
+    make -C "$cwd/../nspr/$target" install 1> /dev/null
+}
+
+build_nspr()
+{
+    mkdir -p "$cwd/../nspr/$target"
+    cd "$cwd/../nspr/$target"
+    if [ "$1" == 1 ]; then
+        verbose
+    else
+        silent
+    fi
+}
deleted file mode 100644
--- a/security/nss/coreconf/pkg_config.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python
-#
-# 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 os
-import subprocess
-import sys
-
-def main():
-    is_raw = sys.argv[1] == 'raw'
-    stdout = None if is_raw else subprocess.PIPE
-
-    if sys.argv[2] == '--libs':
-        part_prefix = '-L'
-    elif sys.argv[2] == '--cflags':
-        part_prefix = '-I'
-    else:
-        raise Exception('Specify either --libs or --cflags as the second argument.')
-
-    try:
-        process = subprocess.Popen(['pkg-config'] + sys.argv[2:], stdout=stdout, stderr=open(os.devnull, 'wb'))
-
-    except OSError:
-        # pkg-config is probably not installed
-        return
-
-    if is_raw:
-        process.wait()
-        return
-
-    for part in process.communicate()[0].strip().split():
-        if part.startswith(part_prefix):
-            print os.path.realpath(os.path.join(part[2:], sys.argv[1]))
-            return
-
-if __name__ == '__main__':
-    main()
new file mode 100644
--- /dev/null
+++ b/security/nss/coreconf/sanitizers.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python2
+
+from __future__ import print_function
+import sys
+
+def main():
+    if len(sys.argv) < 2:
+        raise Exception('Specify either "ld", asan", "sancov" or "ubsan" as argument.')
+
+    sanitizer = sys.argv[1]
+    if sanitizer == "ubsan":
+        print('-fsanitize=undefined -fno-sanitize-recover=undefined ', end='')
+        return
+    if sanitizer == "asan":
+        print('-fsanitize=address ', end='')
+        print('-fno-omit-frame-pointer -fno-optimize-sibling-calls ', end='')
+        return
+    if sanitizer == "sancov":
+        if len(sys.argv) < 3:
+            raise Exception('sancov requires another argument (edge|bb|func).')
+        print('-fsanitize-coverage='+sys.argv[2]+' ', end='')
+        return
+
+    # We have to remove this from the ld flags when building asan.
+    if sanitizer == "ld":
+        print('-Wl,-z,defs ', end='')
+        return
+
+    raise Exception('Specify either "ld", asan", "sancov" or "ubsan" as argument.')
+
+if __name__ == '__main__':
+    main()
--- a/security/nss/coreconf/shlibsign.py
+++ b/security/nss/coreconf/shlibsign.py
@@ -1,9 +1,9 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
 #
 # 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 os
 import subprocess
 import sys
@@ -13,15 +13,18 @@ def main():
         if os.path.isfile(lib_file):
             sign(lib_file)
 
 def sign(lib_file):
     ld_lib_path = os.path.realpath(os.path.join(lib_file, '..'))
     bin_path = os.path.realpath(os.path.join(ld_lib_path, '../bin'))
 
     env = os.environ.copy()
-    env['LD_LIBRARY_PATH'] = env['DYLD_LIBRARY_PATH'] = ld_lib_path
+    if sys.platform == 'win32':
+        env['PATH'] = os.pathsep.join((env['PATH'], ld_lib_path))
+    else:
+        env['LD_LIBRARY_PATH'] = env['DYLD_LIBRARY_PATH'] = ld_lib_path
 
     dev_null = open(os.devnull, 'wb')
-    subprocess.Popen([os.path.join(bin_path, 'shlibsign'), '-v', '-i', lib_file], env=env, stdout=dev_null, stderr=dev_null).wait()
+    subprocess.check_call([os.path.join(bin_path, 'shlibsign'), '-v', '-i', lib_file], env=env, stdout=dev_null, stderr=dev_null)
 
 if __name__ == '__main__':
     main()
--- a/security/nss/coreconf/werror.py
+++ b/security/nss/coreconf/werror.py
@@ -1,17 +1,21 @@
 #!/usr/bin/env python
 
 import os
 import subprocess
 
 def main():
     cc = os.environ.get('CC', 'cc')
     sink = open(os.devnull, 'wb')
-    cc_is_clang = 'clang' in subprocess.check_output([cc, '--version'], stderr=sink)
+    try:
+        cc_is_clang = 'clang' in subprocess.check_output([cc, '--version'], stderr=sink)
+    except OSError:
+        # We probably just don't have CC/cc.
+        return
 
     def warning_supported(warning):
         return subprocess.call([cc, '-x', 'c', '-E', '-Werror',
                                 '-W%s' % warning, os.devnull], stdout=sink, stderr=sink) == 0
     def can_enable():
         # This would be a problem
         if not warning_supported('all'):
             return False
--- a/security/nss/exports.gyp
+++ b/security/nss/exports.gyp
@@ -6,17 +6,17 @@
     'coreconf/config.gypi'
   ],
   'targets': [
     {
       'target_name': 'nss_exports',
       'type': 'none',
       'direct_dependent_settings': {
         'include_dirs': [
-          '<(nss_dist_dir)/public/nss'
+          '<(nss_public_dist_dir)/nss'
         ]
       },
       'dependencies': [
         'cmd/lib/exports.gyp:cmd_lib_exports',
         'lib/base/exports.gyp:lib_base_exports',
         'lib/certdb/exports.gyp:lib_certdb_exports',
         'lib/certhigh/exports.gyp:lib_certhigh_exports',
         'lib/ckfw/builtins/exports.gyp:lib_ckfw_builtins_exports',
@@ -59,17 +59,17 @@
     },
     {
       'target_name': 'dbm_exports',
       'type': 'none',
       'conditions': [
         ['disable_dbm==0', {
           'direct_dependent_settings': {
             'include_dirs': [
-              '<(nss_dist_dir)/public/dbm'
+              '<(nss_public_dist_dir)/dbm'
             ]
           },
           'dependencies': [
             'lib/dbm/include/exports.gyp:lib_dbm_include_exports'
           ],
         }],
       ],
     }
deleted file mode 100644
--- a/security/nss/fuzz/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-#! gmake
-#
-# 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/.
-
-#######################################################################
-# (1) Include initial platform-independent assignments (MANDATORY).   #
-#######################################################################
-
-include manifest.mn
-
-#######################################################################
-# (2) Include "global" configuration information. (OPTIONAL)          #
-#######################################################################
-
-include $(CORE_DEPTH)/coreconf/config.mk
-
-#######################################################################
-# (3) Include "component" configuration information. (OPTIONAL)       #
-#######################################################################
-
-
-#######################################################################
-# (4) Include "local" platform-dependent assignments (OPTIONAL).      #
-#######################################################################
-
-
-#######################################################################
-# (5) Execute "global" rules. (OPTIONAL)                              #
-#######################################################################
-
-include $(CORE_DEPTH)/coreconf/rules.mk
-
-#######################################################################
-# (6) Execute "component" rules. (OPTIONAL)                           #
-#######################################################################
-
-
-#######################################################################
-# (7) Execute "local" rules. (OPTIONAL).                              #
-#######################################################################
new file mode 100644
--- /dev/null
+++ b/security/nss/fuzz/cert_target.cc
@@ -0,0 +1,26 @@
+/* -*- 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 <stdint.h>
+
+#include "cert.h"
+
+#include "registry.h"
+
+extern "C" int cert_fuzzing_target(const uint8_t *Data, size_t Size) {
+  PORTCheapArenaPool pool;
+  PORT_InitCheapArena(&pool, DER_DEFAULT_CHUNKSIZE);
+
+  CERTCertificate cert;
+  SECItem data = {siBuffer, (unsigned char *)Data, (unsigned int)Size};
+  SEC_QuickDERDecodeItem(&pool.arena, &cert, SEC_SignedCertificateTemplate,
+                         &data);
+
+  PORT_DestroyCheapArena(&pool);
+  return 0;
+}
+
+REGISTER_FUZZING_TARGET("cert", cert_fuzzing_target, 3072, "Certificate Import")
--- a/security/nss/fuzz/clone_libfuzzer.sh
+++ b/security/nss/fuzz/clone_libfuzzer.sh
@@ -1,9 +1,9 @@
 #!/bin/sh
 
 cd $(dirname $0)
 mkdir tmp/
 git clone -q https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer tmp/
-mv tmp/.git libFuzzer
+mv tmp/.git libFuzzer/
 rm -fr tmp
 cd libFuzzer
 git reset --hard 4333f2ca71eb7951fcafcdcb111012fbe25c5e7e
deleted file mode 100644
--- a/security/nss/fuzz/common.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-#! gmake
-#
-# 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/.
-
-MKPROG = $(CCC)
-MKSHLIB = $(CCC) $(DSO_LDOPTS) $(DARWIN_SDK_SHLIBFLAGS)
-
-CXXFLAGS += -std=c++11
new file mode 100644
--- /dev/null
+++ b/security/nss/fuzz/fuzz.gyp
@@ -0,0 +1,33 @@
+# 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/.
+{
+  'includes': [
+    '../coreconf/config.gypi',
+    '../cmd/platlibs.gypi'
+  ],
+  'targets': [
+    {
+      'target_name': 'nssfuzz',
+      'type': 'executable',
+      'sources': [
+        'cert_target.cc',
+        'pkcs8_target.cc',
+        'spki_target.cc',
+        'nssfuzz.cc',
+      ],
+      'dependencies': [
+        '<(DEPTH)/exports.gyp:nss_exports',
+        '<(DEPTH)/fuzz/libFuzzer/libFuzzer.gyp:libFuzzer'
+      ]
+    }
+  ],
+  'target_defaults': {
+    'include_dirs': [
+      'libFuzzer',
+    ],
+  },
+  'variables': {
+    'module': 'nss',
+  }
+}
deleted file mode 100644
--- a/security/nss/fuzz/libFuzzer/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-#! gmake
-#
-# 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/.
-
-#######################################################################
-# (1) Include initial platform-independent assignments (MANDATORY).   #
-#######################################################################
-
-include manifest.mn
-
-#######################################################################
-# (2) Include "global" configuration information. (OPTIONAL)          #
-#######################################################################
-
-include $(CORE_DEPTH)/coreconf/config.mk
-
-#######################################################################
-# (3) Include "component" configuration information. (OPTIONAL)       #
-#######################################################################
-
-include config.mk
-
-include ../common.mk
-
-#######################################################################
-# (4) Include "local" platform-dependent assignments (OPTIONAL).      #
-#######################################################################
-
-
-#######################################################################
-# (5) Execute "global" rules. (OPTIONAL)                              #
-#######################################################################
-
-include $(CORE_DEPTH)/coreconf/rules.mk
-
-#######################################################################
-# (6) Execute "component" rules. (OPTIONAL)                           #
-#######################################################################
-
-
-#######################################################################
-# (7) Execute "local" rules. (OPTIONAL).                              #
-#######################################################################
deleted file mode 100644
--- a/security/nss/fuzz/libFuzzer/config.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# 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/.
-
-# According to the LLVM docs, LibFuzzer isn't supposed to be built with any
-# sanitizer flags and in fact, building it with ASan coverage currently causes
-# Clang 3.9+ to crash, so we filter out all sanitizer-related flags here.
-CXXFLAGS := $(filter-out -fsanitize%,$(CXXFLAGS))
-CFLAGS := $(filter-out -fsanitize%,$(CFLAGS))
-LDFLAGS := $(filter-out -fsanitize%,$(LDFLAGS))
-DARWIN_SDK_SHLIBFLAGS := $(filter-out -fsanitize%,$(DARWIN_SDK_SHLIBFLAGS))
-
-CXXFLAGS += -g -O2
new file mode 100644
--- /dev/null
+++ b/security/nss/fuzz/libFuzzer/libFuzzer.gyp
@@ -0,0 +1,43 @@
+# 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/.
+{
+  'includes': [
+    '../../coreconf/config.gypi'
+  ],
+  'targets': [
+    {
+      'target_name': 'libFuzzer',
+      'type': 'static_library',
+      'sources': [
+        'FuzzerCrossOver.cpp',
+        'FuzzerDriver.cpp',
+        'FuzzerExtFunctionsDlsym.cpp',
+        'FuzzerExtFunctionsWeak.cpp',
+        'FuzzerIO.cpp',
+        'FuzzerLoop.cpp',
+        'FuzzerMutate.cpp',
+        'FuzzerSHA1.cpp',
+        'FuzzerTracePC.cpp',
+        'FuzzerTraceState.cpp',
+        'FuzzerUtil.cpp',
+        'FuzzerUtilDarwin.cpp',
+        'FuzzerUtilLinux.cpp',
+      ],
+      'cflags': [
+        '-O2',
+      ],
+      'cflags/': [
+        ['exclude', '-fsanitize='],
+        ['exclude', '-fsanitize-'],
+      ],
+      'xcode_settings': {
+        'GCC_OPTIMIZATION_LEVEL': '2', # -O2
+        'OTHER_CFLAGS/': [
+          ['exclude', '-fsanitize='],
+          ['exclude', '-fsanitize-'],
+        ],
+      },
+    }
+  ],
+}
deleted file mode 100644
--- a/security/nss/fuzz/libFuzzer/manifest.mn
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# 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/.
-CORE_DEPTH = ../..
-DEPTH      = ../..
-MODULE = nss
-
-CPPSRCS = \
-      FuzzerCrossOver.cpp \
-      FuzzerDriver.cpp \
-      FuzzerExtFunctionsDlsym.cpp \
-      FuzzerExtFunctionsWeak.cpp \
-      FuzzerIO.cpp \
-      FuzzerLoop.cpp \
-      FuzzerMutate.cpp \
-      FuzzerSHA1.cpp \
-      FuzzerTracePC.cpp \
-      FuzzerTraceState.cpp \
-      FuzzerUtil.cpp \
-      FuzzerUtilDarwin.cpp \
-      FuzzerUtilLinux.cpp \
-      $(NULL)
-
-LIBRARY_NAME = Fuzzer
-LIBRARY_VERSION = 1
deleted file mode 100644
--- a/security/nss/fuzz/manifest.mn
+++ /dev/null
@@ -1,8 +0,0 @@
-# 
-# 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/.
-CORE_DEPTH = ..
-DEPTH      = ..
-
-DIRS = libFuzzer nssfuzz
rename from security/nss/fuzz/nssfuzz/nssfuzz.cc
rename to security/nss/fuzz/nssfuzz.cc
deleted file mode 100644
--- a/security/nss/fuzz/nssfuzz/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-#! gmake
-#
-# 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/.
-
-#######################################################################
-# (1) Include initial platform-independent assignments (MANDATORY).   #
-#######################################################################
-
-include manifest.mn
-
-#######################################################################
-# (2) Include "global" configuration information. (OPTIONAL)          #
-#######################################################################
-
-include $(CORE_DEPTH)/coreconf/config.mk
-
-#######################################################################
-# (3) Include "component" configuration information. (OPTIONAL)       #
-#######################################################################
-
-include $(CORE_DEPTH)/cmd/platlibs.mk
-
-include ../common.mk
-
-#######################################################################
-# (4) Include "local" platform-dependent assignments (OPTIONAL).      #
-#######################################################################
-
-
-#######################################################################
-# (5) Execute "global" rules. (OPTIONAL)                              #
-#######################################################################
-
-include $(CORE_DEPTH)/coreconf/rules.mk
-
-#######################################################################
-# (6) Execute "component" rules. (OPTIONAL)                           #
-#######################################################################
-
-
-#######################################################################
-# (7) Execute "local" rules. (OPTIONAL).                              #
-#######################################################################
deleted file mode 100644
--- a/security/nss/fuzz/nssfuzz/cert_target.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- 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 <assert.h>
-#include <stdint.h>
-#include <memory>
-
-#include "cert.h"
-
-#include "registry.h"
-#include "shared.h"
-
-extern "C" int cert_fuzzing_target(const uint8_t *Data, size_t Size) {
-  SECItem data = {siBuffer, (unsigned char *)Data, (unsigned int)Size};
-
-  static std::unique_ptr<NSSDatabase> db(new NSSDatabase());
-  assert(db != nullptr);
-
-  static CERTCertDBHandle *certDB = CERT_GetDefaultCertDB();
-  assert(certDB != NULL);
-
-  CERTCertificate *cert =
-      CERT_NewTempCertificate(certDB, &data, nullptr, false, true);
-
-  if (cert) {
-    CERT_DestroyCertificate(cert);
-  }
-
-  return 0;
-}
-
-REGISTER_FUZZING_TARGET("cert", cert_fuzzing_target, 3072, "Certificate Import")
deleted file mode 100644
--- a/security/nss/fuzz/nssfuzz/manifest.mn
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# 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/.
-CORE_DEPTH = ../..
-DEPTH      = ../..
-MODULE = nss
-
-CPPSRCS = \
-      cert_target.cc \
-      pkcs8_target.cc \
-      spki_target.cc \
-      nssfuzz.cc \
-      $(NULL)
-
-INCLUDES += -I$(CORE_DEPTH)/fuzz/libFuzzer
-
-REQUIRES = nspr nss
-
-PROGRAM = nssfuzz
-
-EXTRA_LIBS = $(DIST)/lib/$(LIB_PREFIX)Fuzzer.$(LIB_SUFFIX)
-
-USE_STATIC_LIBS = 1
rename from security/nss/fuzz/nssfuzz/pkcs8_target.cc
rename to security/nss/fuzz/pkcs8_target.cc
rename from security/nss/fuzz/nssfuzz/registry.h
rename to security/nss/fuzz/registry.h
rename from security/nss/fuzz/nssfuzz/shared.h
rename to security/nss/fuzz/shared.h
rename from security/nss/fuzz/nssfuzz/spki_target.cc
rename to security/nss/fuzz/spki_target.cc
--- a/security/nss/gtests/common/scoped_ptrs.h
+++ b/security/nss/gtests/common/scoped_ptrs.h
@@ -11,16 +11,19 @@
 #include "cert.h"
 #include "keyhi.h"
 #include "pk11pub.h"
 
 namespace nss_test {
 
 struct ScopedDelete {
   void operator()(CERTCertificate* cert) { CERT_DestroyCertificate(cert); }
+  void operator()(CERTCertificateList* list) {
+    CERT_DestroyCertificateList(list);
+  }
   void operator()(CERTSubjectPublicKeyInfo* spki) {
     SECKEY_DestroySubjectPublicKeyInfo(spki);
   }
   void operator()(PK11SlotInfo* slot) { PK11_FreeSlot(slot); }
   void operator()(PK11SymKey* key) { PK11_FreeSymKey(key); }
   void operator()(SECAlgorithmID* id) { SECOID_DestroyAlgorithmID(id, true); }
   void operator()(SECItem* item) { SECITEM_FreeItem(item, true); }
   void operator()(SECKEYPublicKey* key) { SECKEY_DestroyPublicKey(key); }
@@ -35,16 +38,17 @@ struct ScopedMaybeDelete {
       del(ptr);
     }
   }
 };
 
 #define SCOPED(x) typedef std::unique_ptr<x, ScopedMaybeDelete<x> > Scoped##x
 
 SCOPED(CERTCertificate);
+SCOPED(CERTCertificateList);
 SCOPED(CERTSubjectPublicKeyInfo);
 SCOPED(PK11SlotInfo);
 SCOPED(PK11SymKey);
 SCOPED(SECAlgorithmID);
 SCOPED(SECItem);
 SCOPED(SECKEYPublicKey);
 SCOPED(SECKEYPrivateKey);
 
--- a/security/nss/gtests/der_gtest/der_gtest.gyp
+++ b/security/nss/gtests/der_gtest/der_gtest.gyp
@@ -7,16 +7,17 @@
     '../common/gtest.gypi',
   ],
   'targets': [
     {
       'target_name': 'der_gtest',
       'type': 'executable',
       'sources': [
         'der_getint_unittest.cc',
+        'der_private_key_import_unittest.cc',
         '<(DEPTH)/gtests/common/gtests.cc'
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
       ]
     }
   ],
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/freebl_gtest/freebl_gtest.gyp
@@ -0,0 +1,37 @@
+# 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/.
+{
+  'includes': [
+    '../../coreconf/config.gypi',
+    '../common/gtest.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'freebl_gtest',
+      'type': 'executable',
+      'sources': [
+        'mpi_unittest.cc',
+        '<(DEPTH)/gtests/common/gtests.cc'
+      ],
+      'dependencies': [
+        '<(DEPTH)/exports.gyp:nss_exports',
+        '<(DEPTH)/lib/freebl/freebl.gyp:<(freebl_name)',
+        '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
+      ],
+      'defines': [
+        'CT_VERIF',
+      ],
+    }
+  ],
+  'target_defaults': {
+    'include_dirs': [
+      '<(DEPTH)/gtests/google_test/gtest/include',
+      '<(DEPTH)/gtests/common',
+      '<(DEPTH)/lib/freebl/mpi',
+    ]
+  },
+  'variables': {
+    'module': 'nss'
+  }
+}
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/freebl_gtest/mpi_unittest.cc
@@ -0,0 +1,83 @@
+// 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 "secdert.h"
+#include "secitem.h"
+#include "secport.h"
+
+#include "gtest/gtest.h"
+
+#include <stdint.h>
+#include <string.h>
+#include <string>
+
+#include "mpi.h"
+namespace nss_test {
+
+class MPITest : public ::testing::Test {
+ protected:
+  void TestCmp(const std::string a_string, const std::string b_string,
+               int result) {
+    mp_int a, b, c;
+    MP_DIGITS(&a) = 0;
+    MP_DIGITS(&b) = 0;
+    MP_DIGITS(&c) = 0;
+    ASSERT_EQ(MP_OKAY, mp_init(&a));
+    ASSERT_EQ(MP_OKAY, mp_init(&b));
+
+    mp_read_radix(&a, a_string.c_str(), 16);
+    mp_read_radix(&b, b_string.c_str(), 16);
+    EXPECT_EQ(result, mp_cmp(&a, &b));
+  }
+};
+
+TEST_F(MPITest, MpiCmp01Test) { TestCmp("0", "1", -1); }
+TEST_F(MPITest, MpiCmp10Test) { TestCmp("1", "0", 1); }
+TEST_F(MPITest, MpiCmp00Test) { TestCmp("0", "0", 0); }
+TEST_F(MPITest, MpiCmp11Test) { TestCmp("1", "1", 0); }
+
+TEST_F(MPITest, MpiCmpConstTest) {
+  mp_int a, b, c;
+  MP_DIGITS(&a) = 0;
+  MP_DIGITS(&b) = 0;
+  MP_DIGITS(&c) = 0;
+  ASSERT_EQ(MP_OKAY, mp_init(&a));
+  ASSERT_EQ(MP_OKAY, mp_init(&b));
+  ASSERT_EQ(MP_OKAY, mp_init(&c));
+
+  mp_read_radix(&a, const_cast<char *>("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"), 16);
+  mp_read_radix(&b, const_cast<char *>("FF0FFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"), 16);
+  mp_read_radix(&c, const_cast<char *>("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550"), 16);
+
+  mp_taint(&b);
+  mp_taint(&c);
+
+  uint32_t runs = 5000000;
+  uint32_t time_b = 0, time_c = 0;
+  for (uint32_t i = 0; i < runs; ++i) {
+    struct timespec start, end;
+    clock_gettime(CLOCK_MONOTONIC, &start);
+    int r = mp_cmp(&a, &b);
+    clock_gettime(CLOCK_MONOTONIC, &end);
+    unsigned long long used = end.tv_sec * 1000000000L + end.tv_nsec;
+    used -= (unsigned long long)start.tv_sec * 1000000000L + start.tv_nsec;
+    time_b += used;
+    ASSERT_EQ(1, r);
+  }
+  printf("time b: %u\n", time_b / runs);
+
+  for (uint32_t i = 0; i < runs; ++i) {
+    struct timespec start, end;
+    clock_gettime(CLOCK_MONOTONIC, &start);
+    int r = mp_cmp(&a, &c);
+    clock_gettime(CLOCK_MONOTONIC, &end);
+    unsigned long long used = end.tv_sec * 1000000000L + end.tv_nsec;
+    used -= (unsigned long long)start.tv_sec * 1000000000L + start.tv_nsec;
+    time_c += used;
+    ASSERT_EQ(1, r);
+  }
+  printf("time c: %u\n", time_c / runs);
+}
+
+}  // nss_test
--- a/security/nss/gtests/nss_bogo_shim/config.json
+++ b/security/nss/gtests/nss_bogo_shim/config.json
@@ -1,10 +1,24 @@
 {
     "DisabledTests": {
+        "### These tests break whenever we rev versions, so just leave them here for easy uncommenting":"",
+        "#*TLS13*":"(NSS=18, BoGo=16)",
+        "#*HelloRetryRequest*":"(NSS=18, BoGo=16)",
+        "#*KeyShare*":"(NSS=18, BoGo=16)",
+        "#*EncryptedExtensions*":"(NSS=18, BoGo=16)",
+        "#*ServerHelloSignatureAlgorithms*":"(NSS=18, BoGo=16)",
+        "#*SecondClientHello*":"(NSS=18, BoGo=16)",
+        "#*IgnoreClientVersionOrder*":"(NSS=18, BoGo=16)",
+        "Resume-Server-BinderWrongLength":"Alert disagreement (Bug 1317633)",
+        "Resume-Server-NoPSKBinder":"Alert disagreement (Bug 1317633)",
+        "CheckRecordVersion-TLS*":"Bug 1317634",
+        "GREASE-Server-TLS13":"BoringSSL GREASEs without a flag, but we ignore it",
+        "TLS13-ExpectNoSessionTicketOnBadKEMode-Server":"Bug in NSS. Don't send ticket when not permitted by KE modes (Bug 1317635)",
+        "Resume-Server-InvalidPSKBinder":"(Bogo incorrectly expects 'illegal_parameter')",
         "FallbackSCSV-VersionMatch":"Draft version mismatch (NSS=15, BoGo=14)",
         "*KeyUpdate*":"KeyUpdate Unimplemented",
         "ClientAuth-NoFallback-TLS13":"Disagreement about alerts. Bug 1294975",
         "ClientAuth-SHA1-Fallback":"Disagreement about alerts. Bug 1294975",
         "SendWarningAlerts-TLS13":"NSS needs to trigger on warning alerts",
         "NoSupportedCurves":"This tests a non-spec behavior for TLS 1.2 and expects the wrong alert for TLS 1.3",
         "SendEmptyRecords":"Tests a non-spec behavior in BoGo where it chokes on too many empty records",
         "LargePlaintext":"NSS needs to check for over-long records. Bug 1294978",
--- a/security/nss/gtests/ssl_gtest/databuffer.h
+++ b/security/nss/gtests/ssl_gtest/databuffer.h
@@ -23,17 +23,17 @@ extern bool g_ssl_gtest_verbose;
 namespace nss_test {
 
 class DataBuffer {
  public:
   DataBuffer() : data_(nullptr), len_(0) {}
   DataBuffer(const uint8_t* data, size_t len) : data_(nullptr), len_(0) {
     Assign(data, len);
   }
-  explicit DataBuffer(const DataBuffer& other) : data_(nullptr), len_(0) {
+  DataBuffer(const DataBuffer& other) : data_(nullptr), len_(0) {
     Assign(other);
   }
   ~DataBuffer() { delete[] data_; }
 
   DataBuffer& operator=(const DataBuffer& other) {
     if (&other != this) {
       Assign(other);
     }
--- a/security/nss/gtests/ssl_gtest/libssl_internals.c
+++ b/security/nss/gtests/ssl_gtest/libssl_internals.c
@@ -89,16 +89,32 @@ PRInt32 SSLInt_CountTls13CipherSpecs(PRF
 
   for (cur_p = PR_NEXT_LINK(&ss->ssl3.hs.cipherSpecs);
        cur_p != &ss->ssl3.hs.cipherSpecs; cur_p = PR_NEXT_LINK(cur_p)) {
     ++ct;
   }
   return ct;
 }
 
+void SSLInt_PrintTls13CipherSpecs(PRFileDesc *fd) {
+  PRCList *cur_p;
+
+  sslSocket *ss = ssl_FindSocket(fd);
+  if (!ss) {
+    return;
+  }
+
+  fprintf(stderr, "Cipher specs\n");
+  for (cur_p = PR_NEXT_LINK(&ss->ssl3.hs.cipherSpecs);
+       cur_p != &ss->ssl3.hs.cipherSpecs; cur_p = PR_NEXT_LINK(cur_p)) {
+    ssl3CipherSpec *spec = (ssl3CipherSpec *)cur_p;
+    fprintf(stderr, "  %s\n", spec->phase);
+  }
+}
+
 /* Force a timer expiry by backdating when the timer was started.
  * We could set the remaining time to 0 but then backoff would not
  * work properly if we decide to test it. */
 void SSLInt_ForceTimerExpiry(PRFileDesc *fd) {
   sslSocket *ss = ssl_FindSocket(fd);
   if (!ss) {
     return;
   }
@@ -117,17 +133,17 @@ void SSLInt_ForceTimerExpiry(PRFileDesc 
 
 PRBool SSLInt_CheckSecretsDestroyed(PRFileDesc *fd) {
   sslSocket *ss = ssl_FindSocket(fd);
   if (!ss) {
     return PR_FALSE;
   }
 
   CHECK_SECRET(currentSecret);
-  CHECK_SECRET(resumptionPsk);
+  CHECK_SECRET(resumptionMasterSecret);
   CHECK_SECRET(dheSecret);
   CHECK_SECRET(clientEarlyTrafficSecret);
   CHECK_SECRET(clientHsTrafficSecret);
   CHECK_SECRET(serverHsTrafficSecret);
 
   return PR_TRUE;
 }
 
--- a/security/nss/gtests/ssl_gtest/libssl_internals.h
+++ b/security/nss/gtests/ssl_gtest/libssl_internals.h
@@ -17,16 +17,17 @@ SECStatus SSLInt_IncrementClientHandshak
 
 SECStatus SSLInt_UpdateSSLv2ClientRandom(PRFileDesc *fd, uint8_t *rnd,
                                          size_t rnd_len, uint8_t *msg,
                                          size_t msg_len);
 
 PRBool SSLInt_ExtensionNegotiated(PRFileDesc *fd, PRUint16 ext);
 void SSLInt_ClearSessionTicketKey();
 PRInt32 SSLInt_CountTls13CipherSpecs(PRFileDesc *fd);
+void SSLInt_PrintTls13CipherSpecs(PRFileDesc *fd);
 void SSLInt_ForceTimerExpiry(PRFileDesc *fd);
 SECStatus SSLInt_SetMTU(PRFileDesc *fd, PRUint16 mtu);
 PRBool SSLInt_CheckSecretsDestroyed(PRFileDesc *fd);
 PRBool SSLInt_DamageClientHsTrafficSecret(PRFileDesc *fd);
 PRBool SSLInt_DamageServerHsTrafficSecret(PRFileDesc *fd);
 PRBool SSLInt_DamageEarlyTrafficSecret(PRFileDesc *fd);
 SECStatus SSLInt_Set0RttAlpn(PRFileDesc *fd, PRUint8 *data, unsigned int len);
 PRBool SSLInt_HasCertWithAuthType(PRFileDesc *fd, SSLAuthType authType);
--- a/security/nss/gtests/ssl_gtest/manifest.mn
+++ b/security/nss/gtests/ssl_gtest/manifest.mn
@@ -17,16 +17,17 @@ CPPSRCS = \
       ssl_auth_unittest.cc \
       ssl_cert_ext_unittest.cc \
       ssl_ciphersuite_unittest.cc \
       ssl_damage_unittest.cc \
       ssl_dhe_unittest.cc \
       ssl_drop_unittest.cc \
       ssl_ecdh_unittest.cc \
       ssl_ems_unittest.cc \
+      ssl_exporter_unittest.cc \
       ssl_extension_unittest.cc \
       ssl_fuzz_unittest.cc \
       ssl_gtest.cc \
       ssl_hrr_unittest.cc \
       ssl_loopback_unittest.cc \
       ssl_record_unittest.cc \
       ssl_resumption_unittest.cc \
       ssl_skip_unittest.cc \
--- a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
@@ -195,22 +195,9 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRtt
     return false;
   });
   Handshake();
   CheckConnected();
   SendReceive();
   CheckAlpn("b");
 }
 
-TEST_F(TlsConnectTest, DamageSecretHandleZeroRttClientFinished) {
-  SetupForZeroRtt();
-  client_->Set0RttEnabled(true);
-  server_->Set0RttEnabled(true);
-  client_->SetPacketFilter(new AfterRecordN(
-      client_, server_,
-      0,  // ClientHello.
-      [this]() { SSLInt_DamageEarlyTrafficSecret(server_->ssl_fd()); }));
-  ConnectExpectFail();
-  client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
-  server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
-}
-
 }  // namespace nss_test
--- a/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc
@@ -39,26 +39,23 @@ const static uint8_t kCannedTls13ClientH
     0xbf, 0x2a, 0xb5, 0x59, 0x64, 0xcc, 0x0c, 0x49, 0x95, 0x36, 0xe4, 0xd9,
     0x2f, 0xd4, 0x24, 0x66, 0x71, 0x6f, 0x5d, 0x70, 0xe2, 0xa0, 0xea, 0x26,
     0x00, 0x2b, 0x00, 0x03, 0x02, 0x7f, kD13, 0x00, 0x0d, 0x00, 0x20, 0x00,
     0x1e, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02, 0x03, 0x08, 0x04, 0x08,
     0x05, 0x08, 0x06, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x04,
     0x02, 0x05, 0x02, 0x06, 0x02, 0x02, 0x02};
 
 const static uint8_t kCannedTls13ServerHello[] = {
-    0x7f, kD13, 0x21, 0x12, 0xa7, 0xa7, 0x0d, 0x85, 0x8b, 0xb8, 0x0c, 0xbb,
-    0xdc, 0xa6, 0xfd, 0x97, 0xfe, 0x31, 0x26, 0x49, 0x2d, 0xa8, 0x6c, 0x7b,
-    0x65, 0x30, 0x71, 0x00, 0x31, 0x03, 0x2b, 0x94, 0xe2, 0x16, 0x13, 0x01,
-    0x00, 0x4d, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x28, 0x00, 0x45, 0x00, 0x17,
-    0x00, 0x41, 0x04, 0x10, 0x97, 0x3d, 0x7a, 0xcf, 0xa2, 0x34, 0xe3, 0x69,
-    0xc4, 0xdd, 0x1e, 0xf2, 0xd6, 0xc0, 0x9a, 0x3e, 0xf5, 0x41, 0xf3, 0x03,
-    0x23, 0x94, 0xd2, 0x31, 0x85, 0xb7, 0xae, 0x5d, 0xfa, 0xc6, 0x9a, 0xd0,
-    0xa5, 0x44, 0xa3, 0x3a, 0xe0, 0xbb, 0x61, 0xaa, 0x0a, 0x6f, 0xe8, 0xaf,
-    0xdf, 0x86, 0xd8, 0x48, 0x36, 0x9c, 0x19, 0x70, 0x55, 0x84, 0xb0, 0x1c,
-    0x8d, 0xfc, 0x6e, 0xd8, 0x86, 0xc3, 0x95};
+    0x7f, kD13, 0x9c, 0xbc, 0x14, 0x9b, 0x0e, 0x2e, 0xfa, 0x0d, 0xf3, 0xf0,
+    0x5c, 0x70, 0x7a, 0xe0, 0xd1, 0x9b, 0x3e, 0x5a, 0x44, 0x6b, 0xdf, 0xe5,
+    0xc2, 0x28, 0x64, 0xf7, 0x00, 0xc1, 0x9c, 0x08, 0x76, 0x08, 0x13, 0x01,
+    0x00, 0x28, 0x00, 0x28, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0xc2, 0xcf,
+    0x23, 0x17, 0x64, 0x23, 0x03, 0xf0, 0xfb, 0x45, 0x98, 0x26, 0xd1, 0x65,
+    0x24, 0xa1, 0x6c, 0xa9, 0x80, 0x8f, 0x2c, 0xac, 0x0a, 0xea, 0x53, 0x3a,
+    0xcb, 0xe3, 0x08, 0x84, 0xae, 0x19};
 static const char *k0RttData = "ABCDEF";
 
 TEST_P(TlsAgentTest, EarlyFinished) {
   DataBuffer buffer;
   MakeTrivialHandshakeRecord(kTlsHandshakeFinished, 0, &buffer);
   ProcessMessage(buffer, TlsAgent::STATE_ERROR,
                  SSL_ERROR_RX_UNEXPECTED_FINISHED);
 }
--- a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc
@@ -23,16 +23,25 @@ extern "C" {
 namespace nss_test {
 
 TEST_P(TlsConnectGeneric, ServerAuthBigRsa) {
   Reset(TlsAgent::kRsa2048);
   Connect();
   CheckKeys();
 }
 
+TEST_P(TlsConnectGeneric, ServerAuthRsaChain) {
+  Reset(TlsAgent::kServerRsaChain);
+  Connect();
+  CheckKeys();
+  size_t chain_length;
+  EXPECT_TRUE(client_->GetPeerChainLength(&chain_length));
+  EXPECT_EQ(2UL, chain_length);
+}
+
 TEST_P(TlsConnectGeneric, ClientAuth) {
   client_->SetupClientAuth();
   server_->RequestClientAuth(true);
   Connect();
   CheckKeys();
 }
 
 // In TLS 1.3, the client sends its cert rejection on the
--- a/security/nss/gtests/ssl_gtest/ssl_cert_ext_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_cert_ext_unittest.cc
@@ -18,112 +18,112 @@ namespace nss_test {
 
 // Tests for Certificate Transparency (RFC 6962)
 // These don't work with TLS 1.3: see bug 1252745.
 
 // Helper class - stores signed certificate timestamps as provided
 // by the relevant callbacks on the client.
 class SignedCertificateTimestampsExtractor {
  public:
-  SignedCertificateTimestampsExtractor(TlsAgent* client) {
-    client->SetAuthCertificateCallback(
+  SignedCertificateTimestampsExtractor(TlsAgent* client) : client_(client) {
+    client_->SetAuthCertificateCallback(
         [&](TlsAgent* agent, bool checksig, bool isServer) -> SECStatus {
           const SECItem* scts = SSL_PeerSignedCertTimestamps(agent->ssl_fd());
           EXPECT_TRUE(scts);
           if (!scts) {
             return SECFailure;
           }
           auth_timestamps_.reset(new DataBuffer(scts->data, scts->len));
           return SECSuccess;
         });
-    client->SetHandshakeCallback([&](TlsAgent* agent) {
+    client_->SetHandshakeCallback([&](TlsAgent* agent) {
       const SECItem* scts = SSL_PeerSignedCertTimestamps(agent->ssl_fd());
       ASSERT_TRUE(scts);
       handshake_timestamps_.reset(new DataBuffer(scts->data, scts->len));
     });
   }
 
   void assertTimestamps(const DataBuffer& timestamps) {
     EXPECT_TRUE(auth_timestamps_);
     EXPECT_EQ(timestamps, *auth_timestamps_);
 
     EXPECT_TRUE(handshake_timestamps_);
     EXPECT_EQ(timestamps, *handshake_timestamps_);
+
+    const SECItem* current = SSL_PeerSignedCertTimestamps(client_->ssl_fd());
+    EXPECT_EQ(timestamps, DataBuffer(current->data, current->len));
   }
 
  private:
+  TlsAgent* client_;
   std::unique_ptr<DataBuffer> auth_timestamps_;
   std::unique_ptr<DataBuffer> handshake_timestamps_;
 };
 
 static const uint8_t kSctValue[] = {0x01, 0x23, 0x45, 0x67, 0x89};
 static const SECItem kSctItem = {siBuffer, const_cast<uint8_t*>(kSctValue),
                                  sizeof(kSctValue)};
 static const DataBuffer kSctBuffer(kSctValue, sizeof(kSctValue));
 
 // Test timestamps extraction during a successful handshake.
-TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsHandshake) {
+TEST_P(TlsConnectGeneric, SignedCertificateTimestampsHandshake) {
   EnsureTlsSetup();
   EXPECT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(server_->ssl_fd(),
                                                     &kSctItem, ssl_kea_rsa));
   EXPECT_EQ(SECSuccess,
             SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
                           PR_TRUE));
   SignedCertificateTimestampsExtractor timestamps_extractor(client_);
 
   Connect();
 
   timestamps_extractor.assertTimestamps(kSctBuffer);
-  const SECItem* c_timestamps = SSL_PeerSignedCertTimestamps(client_->ssl_fd());
-  EXPECT_EQ(SECEqual, SECITEM_CompareItem(&kSctItem, c_timestamps));
 }
 
-TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsConfig) {
+TEST_P(TlsConnectGeneric, SignedCertificateTimestampsConfig) {
   static const SSLExtraServerCertData kExtraData = {ssl_auth_rsa_sign, nullptr,
                                                     nullptr, &kSctItem};
 
   EnsureTlsSetup();
   EXPECT_TRUE(
       server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraData));
   EXPECT_EQ(SECSuccess,
             SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
                           PR_TRUE));
   SignedCertificateTimestampsExtractor timestamps_extractor(client_);
 
   Connect();
 
   timestamps_extractor.assertTimestamps(kSctBuffer);
-  const SECItem* c_timestamps = SSL_PeerSignedCertTimestamps(client_->ssl_fd());
-  EXPECT_EQ(SECEqual, SECITEM_CompareItem(&kSctItem, c_timestamps));
 }
 
 // Test SSL_PeerSignedCertTimestamps returning zero-length SECItem
 // when the client / the server / both have not enabled the feature.
-TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsInactiveClient) {
+TEST_P(TlsConnectGeneric, SignedCertificateTimestampsInactiveClient) {
   EnsureTlsSetup();
   EXPECT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(server_->ssl_fd(),
                                                     &kSctItem, ssl_kea_rsa));
   SignedCertificateTimestampsExtractor timestamps_extractor(client_);
 
   Connect();
   timestamps_extractor.assertTimestamps(DataBuffer());
 }
 
-TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsInactiveServer) {
+TEST_P(TlsConnectGeneric, SignedCertificateTimestampsInactiveServer) {
   EnsureTlsSetup();
   EXPECT_EQ(SECSuccess,
             SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
                           PR_TRUE));
   SignedCertificateTimestampsExtractor timestamps_extractor(client_);
 
   Connect();
   timestamps_extractor.assertTimestamps(DataBuffer());
 }
 
-TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsInactiveBoth) {
+TEST_P(TlsConnectGeneric, SignedCertificateTimestampsInactiveBoth) {
   EnsureTlsSetup();
   SignedCertificateTimestampsExtractor timestamps_extractor(client_);
 
   Connect();
   timestamps_extractor.assertTimestamps(DataBuffer());
 }
 
 // Check that the given agent doesn't have an OCSP response for its peer.
--- a/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc
@@ -282,17 +282,17 @@ TEST_P(TlsKeyExchangeTest13, Curve25519P
   client_->ConfigNamedGroups(client_groups);
   server_->ConfigNamedGroups(server_groups);
 
   Connect();
 
   CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign,
             ssl_sig_rsa_pss_sha256);
   const std::vector<SSLNamedGroup> shares = {ssl_grp_ec_secp256r1};
-  CheckKEXDetails(client_groups, shares, false);
+  CheckKEXDetails(client_groups, shares);
 }
 
 TEST_P(TlsKeyExchangeTest13, Curve25519P256EqualPriorityServer13) {
   EnsureKeyShareSetup();
 
   // The client sends a 25519 key share while the server prefers P256.
   // We have to accept 25519 without retry.
   const std::vector<SSLNamedGroup> client_groups = {ssl_grp_ec_curve25519,
@@ -302,17 +302,17 @@ TEST_P(TlsKeyExchangeTest13, Curve25519P
   client_->ConfigNamedGroups(client_groups);
   server_->ConfigNamedGroups(server_groups);
 
   Connect();
 
   CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign,
             ssl_sig_rsa_pss_sha256);
   const std::vector<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
-  CheckKEXDetails(client_groups, shares, false);
+  CheckKEXDetails(client_groups, shares);
 }
 
 TEST_P(TlsKeyExchangeTest13, EqualPriorityTestRetryECServer13) {
   EnsureKeyShareSetup();
 
   // The client sends a 25519 key share while the server prefers P256.
   // The server prefers P-384 over x25519, so it must not consider P-256 and
   // x25519 to be equivalent. It will therefore request a P-256 share
@@ -324,17 +324,17 @@ TEST_P(TlsKeyExchangeTest13, EqualPriori
   client_->ConfigNamedGroups(client_groups);
   server_->ConfigNamedGroups(server_groups);
 
   Connect();
 
   CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign,
             ssl_sig_rsa_pss_sha256);
   const std::vector<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
-  CheckKEXDetails(client_groups, shares, true);
+  CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1);
 }
 
 TEST_P(TlsKeyExchangeTest13, NotEqualPriorityWithIntermediateGroup13) {
   EnsureKeyShareSetup();
 
   // The client sends a 25519 key share while the server prefers P256.
   // The server prefers ffdhe_2048 over x25519, so it must not consider the
   // P-256 and x25519 to be equivalent. It will therefore request a P-256 share
@@ -346,17 +346,17 @@ TEST_P(TlsKeyExchangeTest13, NotEqualPri
   client_->ConfigNamedGroups(client_groups);
   server_->ConfigNamedGroups(server_groups);
 
   Connect();
 
   CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign,
             ssl_sig_rsa_pss_sha256);
   const std::vector<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
-  CheckKEXDetails(client_groups, shares, true);
+  CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1);
 }
 
 TEST_P(TlsKeyExchangeTest13,
        NotEqualPriorityWithUnsupportedFFIntermediateGroup13) {
   EnsureKeyShareSetup();
 
   // As in the previous test, the server prefers ffdhe_2048. Thus, even though
   // the client doesn't support this group, the server must not regard x25519 as
@@ -368,17 +368,17 @@ TEST_P(TlsKeyExchangeTest13,
   client_->ConfigNamedGroups(client_groups);
   server_->ConfigNamedGroups(server_groups);
 
   Connect();
 
   CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign,
             ssl_sig_rsa_pss_sha256);
   const std::vector<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
-  CheckKEXDetails(client_groups, shares, true);
+  CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1);
 }
 
 TEST_P(TlsKeyExchangeTest13,
        NotEqualPriorityWithUnsupportedECIntermediateGroup13) {
   EnsureKeyShareSetup();
 
   // As in the previous test, the server prefers P-384. Thus, even though
   // the client doesn't support this group, the server must not regard x25519 as
@@ -390,17 +390,17 @@ TEST_P(TlsKeyExchangeTest13,
   client_->ConfigNamedGroups(client_groups);
   server_->ConfigNamedGroups(server_groups);
 
   Connect();
 
   CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign,
             ssl_sig_rsa_pss_sha256);
   const std::vector<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
-  CheckKEXDetails(client_groups, shares, true);
+  CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1);
 }
 
 TEST_P(TlsKeyExchangeTest13, EqualPriority13) {
   EnsureKeyShareSetup();
 
   // The client sends a 25519 key share while the server prefers P256.
   // We have to accept 25519 without retry because it's considered equivalent to
   // P256 by the server.
@@ -410,17 +410,17 @@ TEST_P(TlsKeyExchangeTest13, EqualPriori
                                                     ssl_grp_ec_curve25519};
   client_->ConfigNamedGroups(client_groups);
   server_->ConfigNamedGroups(server_groups);
 
   Connect();
 
   CheckKeys();
   const std::vector<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
-  CheckKEXDetails(client_groups, shares, false);
+  CheckKEXDetails(client_groups, shares);
 }
 #endif
 
 TEST_P(TlsConnectGeneric, P256ClientAndCurve25519Server) {
   EnsureTlsSetup();
   client_->DisableAllCiphers();
   client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
 
@@ -453,17 +453,17 @@ TEST_P(TlsKeyExchangeTest13, MultipleCli
 
   Connect();
 
   // The server would accept 25519 but its preferred group (P256) has to win.
   CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign,
             ssl_sig_rsa_pss_sha256);
   const std::vector<SSLNamedGroup> shares = {ssl_grp_ec_curve25519,
                                              ssl_grp_ec_secp256r1};
-  CheckKEXDetails(client_groups, shares, false);
+  CheckKEXDetails(client_groups, shares);
 }
 
 // Replace the point in the client key exchange message with an empty one
 class ECCClientKEXFilter : public TlsHandshakeFilter {
  public:
   ECCClientKEXFilter() {}
 
  protected:
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/ssl_gtest/ssl_exporter_unittest.cc
@@ -0,0 +1,122 @@
+/* -*- 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 "ssl.h"
+
+#include "gtest_utils.h"
+#include "tls_connect.h"
+
+namespace nss_test {
+
+static const char* kExporterLabel = "EXPORTER-duck";
+static const uint8_t kExporterContext[] = {0x12, 0x34, 0x56};
+
+static void ExportAndCompare(TlsAgent* client, TlsAgent* server, bool context) {
+  static const size_t exporter_len = 10;
+  uint8_t client_value[exporter_len] = {0};
+  EXPECT_EQ(SECSuccess,
+            SSL_ExportKeyingMaterial(
+                client->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
+                context ? PR_TRUE : PR_FALSE, kExporterContext,
+                sizeof(kExporterContext), client_value, sizeof(client_value)));
+  uint8_t server_value[exporter_len] = {0xff};
+  EXPECT_EQ(SECSuccess,
+            SSL_ExportKeyingMaterial(
+                server->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
+                context ? PR_TRUE : PR_FALSE, kExporterContext,
+                sizeof(kExporterContext), server_value, sizeof(server_value)));
+  EXPECT_EQ(0, memcmp(client_value, server_value, sizeof(client_value)));
+}
+
+TEST_P(TlsConnectGeneric, ExporterBasic) {
+  EnsureTlsSetup();
+  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+    server_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
+  } else {
+    server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
+  }
+  Connect();
+  CheckKeys();
+  ExportAndCompare(client_, server_, false);
+}
+
+TEST_P(TlsConnectGeneric, ExporterContext) {
+  EnsureTlsSetup();
+  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+    server_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
+  } else {
+    server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
+  }
+  Connect();
+  CheckKeys();
+  ExportAndCompare(client_, server_, true);
+}
+
+// Bug 1312976 - SHA-384 doesn't work in 1.2 right now.
+TEST_P(TlsConnectTls13, ExporterSha384) {
+  EnsureTlsSetup();
+  client_->EnableSingleCipher(TLS_AES_256_GCM_SHA384);
+  Connect();
+  CheckKeys();
+  ExportAndCompare(client_, server_, false);
+}
+
+TEST_P(TlsConnectTls13, ExporterContextEmptyIsSameAsNone) {
+  EnsureTlsSetup();
+  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+    server_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
+  } else {
+    server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
+  }
+  Connect();
+  CheckKeys();
+  ExportAndCompare(client_, server_, false);
+}
+
+// This has a weird signature so that it can be passed to the SNI callback.
+int32_t RegularExporterShouldFail(TlsAgent* agent, const SECItem* srvNameArr,
+                                  PRUint32 srvNameArrSize) {
+  uint8_t val[10];
+  EXPECT_EQ(SECFailure, SSL_ExportKeyingMaterial(
+                            agent->ssl_fd(), kExporterLabel,
+                            strlen(kExporterLabel), PR_TRUE, kExporterContext,
+                            sizeof(kExporterContext), val, sizeof(val)))
+      << "regular exporter should fail";
+  return 0;
+}
+
+TEST_P(TlsConnectTls13, EarlyExporter) {
+  SetupForZeroRtt();
+  client_->Set0RttEnabled(true);
+  server_->Set0RttEnabled(true);
+  ExpectResumption(RESUME_TICKET);
+
+  client_->Handshake();  // Send ClientHello.
+  uint8_t client_value[10] = {0};
+  RegularExporterShouldFail(client_, nullptr, 0);
+  EXPECT_EQ(SECSuccess,
+            SSL_ExportEarlyKeyingMaterial(
+                client_->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
+                kExporterContext, sizeof(kExporterContext), client_value,
+                sizeof(client_value)));
+
+  server_->SetSniCallback(RegularExporterShouldFail);
+  server_->Handshake();  // Handle ClientHello.
+  uint8_t server_value[10] = {0};
+  EXPECT_EQ(SECSuccess,
+            SSL_ExportEarlyKeyingMaterial(
+                server_->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
+                kExporterContext, sizeof(kExporterContext), server_value,
+                sizeof(server_value)));
+  EXPECT_EQ(0, memcmp(client_value, server_value, sizeof(client_value)));
+
+  Handshake();
+  ExpectEarlyDataAccepted(true);
+  CheckConnected();
+  SendReceive();
+}
+
+}  // namespace nss_test
--- a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc
@@ -109,16 +109,61 @@ class TlsExtensionInjector : public TlsH
     return CHANGE;
   }
 
  private:
   const uint16_t extension_;
   const DataBuffer data_;
 };
 
+class TlsExtensionAppender : public TlsHandshakeFilter {
+ public:
+  TlsExtensionAppender(uint16_t ext, DataBuffer& data)
+      : extension_(ext), data_(data) {}
+
+  virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
+                                               const DataBuffer& input,
+                                               DataBuffer* output) {
+    size_t offset;
+    TlsParser parser(input);
+    if (header.handshake_type() == kTlsHandshakeClientHello) {
+      if (!TlsExtensionFilter::FindClientHelloExtensions(&parser, header)) {
+        return KEEP;
+      }
+    } else if (header.handshake_type() == kTlsHandshakeServerHello) {
+      if (!TlsExtensionFilter::FindServerHelloExtensions(&parser)) {
+        return KEEP;
+      }
+    } else {
+      return KEEP;
+    }
+    offset = parser.consumed();
+    *output = input;
+
+    uint32_t ext_len;
+    if (!parser.Read(&ext_len, 2)) {
+      ADD_FAILURE();
+      return KEEP;
+    }
+
+    ext_len += 4 + data_.len();
+    output->Write(offset, ext_len, 2);
+
+    offset = output->len();
+    offset = output->Write(offset, extension_, 2);
+    WriteVariable(output, offset, data_, 2);
+
+    return CHANGE;
+  }
+
+ private:
+  const uint16_t extension_;
+  const DataBuffer data_;
+};
+
 class TlsExtensionTestBase : public TlsConnectTestBase {
  protected:
   TlsExtensionTestBase(Mode mode, uint16_t version)
       : TlsConnectTestBase(mode, version) {}
   TlsExtensionTestBase(const std::string& mode, uint16_t version)
       : TlsConnectTestBase(mode, version) {}
 
   void ClientHelloErrorTest(PacketFilter* filter,
@@ -576,187 +621,282 @@ TEST_F(TlsExtensionTest13Stream, Unknown
   EnsureTlsSetup();
   server_->SetPacketFilter(
       new TlsExtensionReplacer(ssl_tls13_key_share_xtn, buf));
   ConnectExpectFail();
   EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code());
   EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
 }
 
-TEST_F(TlsExtensionTest13Stream, DropServerSignatureAlgorithms) {
-  EnsureTlsSetup();
-  server_->SetPacketFilter(
-      new TlsExtensionDropper(ssl_signature_algorithms_xtn));
-  ConnectExpectFail();
-  EXPECT_EQ(SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION,
-            client_->error_code());
-  EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
-}
-
-TEST_F(TlsExtensionTest13Stream, NonEmptySignatureAlgorithms) {
-  EnsureTlsSetup();
-  DataBuffer sig_algs;
-  size_t index = 0;
-  index = sig_algs.Write(index, 2, 2);
-  index = sig_algs.Write(index, ssl_sig_rsa_pss_sha256, 2);
-  server_->SetPacketFilter(
-      new TlsExtensionReplacer(ssl_signature_algorithms_xtn, sig_algs));
-  ConnectExpectFail();
-  EXPECT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
-  EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
-}
-
 TEST_F(TlsExtensionTest13Stream, AddServerSignatureAlgorithmsOnResumption) {
   SetupForResume();
   DataBuffer empty;
   server_->SetPacketFilter(
       new TlsExtensionInjector(ssl_signature_algorithms_xtn, empty));
   ConnectExpectFail();
-  EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_EXTENSION, client_->error_code());
+  EXPECT_EQ(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, client_->error_code());
   EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
 }
 
+struct PskIdentity {
+  DataBuffer identity;
+  uint32_t obfuscated_ticket_age;
+};
+
+class TlsPreSharedKeyReplacer;
+
+typedef std::function<void(TlsPreSharedKeyReplacer*)>
+    TlsPreSharedKeyReplacerFunc;
+
 class TlsPreSharedKeyReplacer : public TlsExtensionFilter {
  public:
-  TlsPreSharedKeyReplacer(const uint8_t* psk, size_t psk_len,
-                          const uint8_t* ke_modes, size_t ke_modes_len,
-                          const uint8_t* auth_modes, size_t auth_modes_len) {
-    if (psk) {
-      psk_.reset(new DataBuffer(psk, psk_len));
-    }
-    if (ke_modes) {
-      ke_modes_.reset(new DataBuffer(ke_modes, ke_modes_len));
-    }
-    if (auth_modes) {
-      auth_modes_.reset(new DataBuffer(auth_modes, auth_modes_len));
-    }
-  }
+  TlsPreSharedKeyReplacer(TlsPreSharedKeyReplacerFunc function)
+      : identities_(), binders_(), function_(function) {}
 
   static size_t CopyAndMaybeReplace(TlsParser* parser, size_t size,
                                     const std::unique_ptr<DataBuffer>& replace,
                                     size_t index, DataBuffer* output) {
     DataBuffer tmp;
     bool ret = parser->ReadVariable(&tmp, size);
     EXPECT_EQ(true, ret);
     if (!ret) return 0;
     if (replace) {
       tmp = *replace;
     }
 
     return WriteVariable(output, index, tmp, size);
-    ;
   }
 
   PacketFilter::Action FilterExtension(uint16_t extension_type,
                                        const DataBuffer& input,
                                        DataBuffer* output) {
     if (extension_type != ssl_tls13_pre_shared_key_xtn) {
       return KEEP;
     }
 
-    TlsParser parser(input);
-    uint32_t len;                 // Length of the overall vector.
-    if (!parser.Read(&len, 2)) {  // We only allow one entry.
-      return DROP;
-    }
-    EXPECT_EQ(parser.remaining(), len);
-    if (len != parser.remaining()) {
-      return DROP;
-    }
-    DataBuffer buf;
-    size_t index = 0;
-    index = CopyAndMaybeReplace(&parser, 1, ke_modes_, index, &buf);
-    if (!index) {
-      return DROP;
+    if (!Decode(input)) {
+      return KEEP;
     }
 
-    index = CopyAndMaybeReplace(&parser, 1, auth_modes_, index, &buf);
-    if (!index) {
-      return DROP;
-    }
+    // Call the function.
+    function_(this);
 
-    index = CopyAndMaybeReplace(&parser, 2, psk_, index, &buf);
-    if (!index) {
-      return DROP;
-    }
-
-    output->Truncate(0);
-    WriteVariable(output, 0, buf, 2);
+    Encode(output);
 
     return CHANGE;
   }
 
+  std::vector<PskIdentity> identities_;
+  std::vector<DataBuffer> binders_;
+
  private:
-  std::unique_ptr<DataBuffer> psk_;
-  std::unique_ptr<DataBuffer> ke_modes_;
-  std::unique_ptr<DataBuffer> auth_modes_;
+  bool Decode(const DataBuffer& input) {
+    std::unique_ptr<TlsParser> parser(new TlsParser(input));
+    DataBuffer identities;
+
+    if (!parser->ReadVariable(&identities, 2)) {
+      ADD_FAILURE();
+      return false;
+    }
+
+    DataBuffer binders;
+    if (!parser->ReadVariable(&binders, 2)) {
+      ADD_FAILURE();
+      return false;
+    }
+    EXPECT_EQ(0UL, parser->remaining());
+
+    // Now parse the inner sections.
+    parser.reset(new TlsParser(identities));
+    while (parser->remaining()) {
+      PskIdentity identity;
+
+      if (!parser->ReadVariable(&identity.identity, 2)) {
+        ADD_FAILURE();
+        return false;
+      }
+
+      if (!parser->Read(&identity.obfuscated_ticket_age, 4)) {
+        ADD_FAILURE();
+        return false;
+      }
+
+      identities_.push_back(identity);
+    }
+
+    parser.reset(new TlsParser(binders));
+    while (parser->remaining()) {
+      DataBuffer binder;
+
+      if (!parser->ReadVariable(&binder, 1)) {
+        ADD_FAILURE();
+        return false;
+      }
+
+      binders_.push_back(binder);
+    }
+
+    return true;
+  }
+
+  void Encode(DataBuffer* output) {
+    DataBuffer identities;
+    size_t index = 0;
+    for (auto id : identities_) {
+      index = WriteVariable(&identities, index, id.identity, 2);
+      index = identities.Write(index, id.obfuscated_ticket_age, 4);
+    }
+
+    DataBuffer binders;
+    index = 0;
+    for (auto binder : binders_) {
+      index = WriteVariable(&binders, index, binder, 1);
+    }
+
+    output->Truncate(0);
+    index = 0;
+    index = WriteVariable(output, index, identities, 2);
+    index = WriteVariable(output, index, binders, 2);
+  }
+
+  TlsPreSharedKeyReplacerFunc function_;
 };
 
-// The following three tests produce bogus (ill-formatted) PreSharedKey
-// extensions so generate errors.
 TEST_F(TlsExtensionTest13Stream, ResumeEmptyPskLabel) {
   SetupForResume();
-  const static uint8_t psk[1] = {0};
+
+  client_->SetPacketFilter(new TlsPreSharedKeyReplacer([](
+      TlsPreSharedKeyReplacer* r) { r->identities_[0].identity.Truncate(0); }));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+}
+
+// Flip the first byte of the binder.
+TEST_F(TlsExtensionTest13Stream, ResumeIncorrectBinderValue) {
+  SetupForResume();
+
+  client_->SetPacketFilter(
+      new TlsPreSharedKeyReplacer([](TlsPreSharedKeyReplacer* r) {
+        r->binders_[0].Write(0, r->binders_[0].data()[0] ^ 0xff, 1);
+      }));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+}
+
+// Extend the binder by one.
+TEST_F(TlsExtensionTest13Stream, ResumeIncorrectBinderLength) {
+  SetupForResume();
+
+  client_->SetPacketFilter(
+      new TlsPreSharedKeyReplacer([](TlsPreSharedKeyReplacer* r) {
+        r->binders_[0].Write(r->binders_[0].len(), 0xff, 1);
+      }));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+}
+
+// Binders must be at least 32 bytes.
+TEST_F(TlsExtensionTest13Stream, ResumeBinderTooShort) {
+  SetupForResume();
+
+  client_->SetPacketFilter(new TlsPreSharedKeyReplacer(
+      [](TlsPreSharedKeyReplacer* r) { r->binders_[0].Truncate(31); }));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+}
 
-  DataBuffer empty;
+// Duplicate the identity and binder. This will fail with an error
+// processing the binder (because we extended the identity list.)
+TEST_F(TlsExtensionTest13Stream, ResumeTwoPsks) {
+  SetupForResume();
+
+  client_->SetPacketFilter(
+      new TlsPreSharedKeyReplacer([](TlsPreSharedKeyReplacer* r) {
+        r->identities_.push_back(r->identities_[0]);
+        r->binders_.push_back(r->binders_[0]);
+      }));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+}
+
+// The next two tests have mismatches in the number of identities
+// and binders. This generates an illegal parameter alert.
+TEST_F(TlsExtensionTest13Stream, ResumeTwoIdentitiesOneBinder) {
+  SetupForResume();
+
   client_->SetPacketFilter(
-      new TlsPreSharedKeyReplacer(&psk[0], 0, nullptr, 0, nullptr, 0));
+      new TlsPreSharedKeyReplacer([](TlsPreSharedKeyReplacer* r) {
+        r->identities_.push_back(r->identities_[0]);
+      }));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+}
+
+TEST_F(TlsExtensionTest13Stream, ResumeOneIdentityTwoBinders) {
+  SetupForResume();
+
+  client_->SetPacketFilter(new TlsPreSharedKeyReplacer([](
+      TlsPreSharedKeyReplacer* r) { r->binders_.push_back(r->binders_[0]); }));
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+}
+
+TEST_F(TlsExtensionTest13Stream, ResumePskExtensionNotLast) {
+  SetupForResume();
+
+  const uint8_t empty_buf[] = {0};
+  DataBuffer empty(empty_buf, 0);
+  client_->SetPacketFilter(
+      // Inject an unused extension.
+      new TlsExtensionAppender(0xffff, empty));
   ConnectExpectFail();
   client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
   server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
 }
 
 TEST_F(TlsExtensionTest13Stream, ResumeNoKeModes) {
   SetupForResume();
-  const static uint8_t ke_modes[1] = {0};
-
-  DataBuffer empty;
-  client_->SetPacketFilter(
-      new TlsPreSharedKeyReplacer(nullptr, 0, &ke_modes[0], 0, nullptr, 0));
-  ConnectExpectFail();
-  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
-  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
-}
-
-TEST_F(TlsExtensionTest13Stream, ResumeNoAuthModes) {
-  SetupForResume();
-  const static uint8_t auth_modes[1] = {0};
 
   DataBuffer empty;
   client_->SetPacketFilter(
-      new TlsPreSharedKeyReplacer(nullptr, 0, nullptr, 0, &auth_modes[0], 0));
+      new TlsExtensionDropper(ssl_tls13_psk_key_exchange_modes_xtn));
   ConnectExpectFail();
-  client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
-  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+  client_->CheckErrorCode(SSL_ERROR_MISSING_EXTENSION_ALERT);
+  server_->CheckErrorCode(SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES);
 }
 
-// The following two tests are valid but unacceptable PreSharedKey
-// modes and therefore produce non-resumption followed by MAC errors.
+// The following test contains valid but unacceptable PreSharedKey
+// modes and therefore produces non-resumption followed by MAC
+// errors.
 TEST_F(TlsExtensionTest13Stream, ResumeBogusKeModes) {
   SetupForResume();
-  const static uint8_t ke_modes = kTls13PskKe;
+  const static uint8_t ke_modes[] = {1,  // Length
+                                     kTls13PskKe};
 
-  DataBuffer empty;
+  DataBuffer modes(ke_modes, sizeof(ke_modes));
   client_->SetPacketFilter(
-      new TlsPreSharedKeyReplacer(nullptr, 0, &ke_modes, 1, nullptr, 0));
+      new TlsExtensionReplacer(ssl_tls13_psk_key_exchange_modes_xtn, modes));
   ConnectExpectFail();
   client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
   server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
 }
 
-TEST_F(TlsExtensionTest13Stream, ResumeBogusAuthModes) {
-  SetupForResume();
-  const static uint8_t auth_modes = kTls13PskSignAuth;
-
-  DataBuffer empty;
-  client_->SetPacketFilter(
-      new TlsPreSharedKeyReplacer(nullptr, 0, nullptr, 0, &auth_modes, 1));
-  ConnectExpectFail();
-  client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
-  server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
+TEST_P(TlsExtensionTest13, NoKeModesIfResumptionOff) {
+  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
+  auto capture = new TlsExtensionCapture(ssl_tls13_psk_key_exchange_modes_xtn);
+  client_->SetPacketFilter(capture);
+  Connect();
+  EXPECT_FALSE(capture->captured());
 }
 
 // In these tests, we downgrade to TLS 1.2, causing the
 // server to negotiate TLS 1.2.
 // 1. Both sides only support TLS 1.3, so we get a cipher version
 //    error.
 TEST_P(TlsExtensionTest13, RemoveTls13FromVersionList) {
   ConnectWithReplacementVersionList(SSL_LIBRARY_VERSION_TLS_1_2);
--- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
+++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
@@ -17,16 +17,17 @@
         'ssl_auth_unittest.cc',
         'ssl_cert_ext_unittest.cc',
         'ssl_ciphersuite_unittest.cc',
         'ssl_damage_unittest.cc',
         'ssl_dhe_unittest.cc',
         'ssl_drop_unittest.cc',
         'ssl_ecdh_unittest.cc',
         'ssl_ems_unittest.cc',
+        'ssl_exporter_unittest.cc',
         'ssl_extension_unittest.cc',
         'ssl_fuzz_unittest.cc',
         'ssl_gtest.cc',
         'ssl_hrr_unittest.cc',
         'ssl_loopback_unittest.cc',
         'ssl_record_unittest.cc',
         'ssl_resumption_unittest.cc',
         'ssl_skip_unittest.cc',
@@ -56,19 +57,16 @@
         '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
         '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap',
         '<(DEPTH)/lib/softoken/softoken.gyp:softokn',
         '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
         '<(DEPTH)/lib/pki/pki.gyp:nsspki',
         '<(DEPTH)/lib/dev/dev.gyp:nssdev',
         '<(DEPTH)/lib/base/base.gyp:nssb',
         '<(DEPTH)/lib/freebl/freebl.gyp:<(freebl_name)',
-        '<(DEPTH)/lib/nss/nss.gyp:nss_static',
-        '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap',
-        '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
         '<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib'
       ],
       'conditions': [
         [ 'disable_dbm==0', {
           'dependencies': [
             '<(DEPTH)/lib/dbm/src/src.gyp:dbm',
           ],
         }],
@@ -91,17 +89,13 @@
     }
   ],
   'target_defaults': {
     'include_dirs': [
       '../../gtests/google_test/gtest/include',
       '../../gtests/common',
       '../../lib/ssl'
     ],
-    'defines': [
-      'NSS_USE_STATIC_LIBS'
-    ]
   },
   'variables': {
     'module': 'nss',
-    'use_static_libs': 1
   }
 }
--- a/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc
@@ -34,17 +34,17 @@ TEST_P(TlsConnectTls13, HelloRetryReques
   ExpectResumption(RESUME_TICKET);
 
   // Send first ClientHello and send 0-RTT data
   auto capture_early_data = new TlsExtensionCapture(ssl_tls13_early_data_xtn);
   client_->SetPacketFilter(capture_early_data);
   client_->Handshake();
   EXPECT_EQ(k0RttDataLen, PR_Write(client_->ssl_fd(), k0RttData,
                                    k0RttDataLen));  // 0-RTT write.
-  EXPECT_LT(0U, capture_early_data->extension().len());
+  EXPECT_TRUE(capture_early_data->captured());
 
   // Send the HelloRetryRequest
   auto hrr_capture =
       new TlsInspectorRecordHandshakeMessage(kTlsHandshakeHelloRetryRequest);
   server_->SetPacketFilter(hrr_capture);
   server_->Handshake();
   EXPECT_LT(0U, hrr_capture->buffer().len());
 
@@ -57,17 +57,17 @@ TEST_P(TlsConnectTls13, HelloRetryReques
   capture_early_data = new TlsExtensionCapture(ssl_tls13_early_data_xtn);
   client_->SetPacketFilter(capture_early_data);
 
   // Complete the handshake successfully
   Handshake();
   ExpectEarlyDataAccepted(false);  // The server should reject 0-RTT
   CheckConnected();
   SendReceive();
-  EXPECT_EQ(0U, capture_early_data->extension().len());
+  EXPECT_FALSE(capture_early_data->captured());
 }
 
 class KeyShareReplayer : public TlsExtensionFilter {
  public:
   KeyShareReplayer() {}
 
   virtual PacketFilter::Action FilterExtension(uint16_t extension_type,
                                                const DataBuffer& input,
@@ -124,34 +124,34 @@ TEST_P(TlsKeyExchange13, ConnectEcdhePre
   static const std::vector<SSLNamedGroup> server_groups = {
       ssl_grp_ec_curve25519, ssl_grp_ec_secp384r1};
   client_->ConfigNamedGroups(client_groups);
   server_->ConfigNamedGroups(server_groups);
   Connect();
   CheckKeys();
   static const std::vector<SSLNamedGroup> expectedShares = {
       ssl_grp_ec_secp384r1};
-  CheckKEXDetails(client_groups, expectedShares, true /* expect_hrr */);
+  CheckKEXDetails(client_groups, expectedShares, ssl_grp_ec_curve25519);
 }
 
 // This should work, but not use HRR because the key share for x25519 was
 // pre-generated by the client.
 TEST_P(TlsKeyExchange13, ConnectEcdhePreferenceMismatchHrrExtraShares) {
   EnsureKeyShareSetup();
   static const std::vector<SSLNamedGroup> client_groups = {
       ssl_grp_ec_secp384r1, ssl_grp_ec_curve25519};
   static const std::vector<SSLNamedGroup> server_groups = {
       ssl_grp_ec_curve25519, ssl_grp_ec_secp384r1};
   client_->ConfigNamedGroups(client_groups);
   server_->ConfigNamedGroups(server_groups);
   EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1));
 
   Connect();
   CheckKeys();
-  CheckKEXDetails(client_groups, client_groups, false /* expect_hrr */);
+  CheckKEXDetails(client_groups, client_groups);
 }
 
 TEST_F(TlsConnectTest, Select12AfterHelloRetryRequest) {
   EnsureTlsSetup();
   client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                            SSL_LIBRARY_VERSION_TLS_1_3);
   server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                            SSL_LIBRARY_VERSION_TLS_1_3);
@@ -235,17 +235,17 @@ TEST_P(HelloRetryRequestAgentTest, SendS
   ProcessMessage(hrr, TlsAgent::STATE_ERROR,
                  SSL_ERROR_RX_UNEXPECTED_HELLO_RETRY_REQUEST);
 }
 
 // Here the client receives a HelloRetryRequest with a group that they already
 // provided a share for.
 TEST_P(HelloRetryRequestAgentTest, HandleBogusHelloRetryRequest) {
   DataBuffer hrr;
-  MakeGroupHrr(ssl_grp_ec_secp256r1, &hrr);
+  MakeGroupHrr(ssl_grp_ec_curve25519, &hrr);
   ProcessMessage(hrr, TlsAgent::STATE_ERROR,
                  SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST);
 }
 
 TEST_P(HelloRetryRequestAgentTest, HandleNoopHelloRetryRequest) {
   DataBuffer hrr;
   MakeCannedHrr(nullptr, 0U, &hrr);
   ProcessMessage(hrr, TlsAgent::STATE_ERROR,
--- a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
@@ -328,17 +328,17 @@ static uint16_t ChooseOneCipher(uint16_t
   if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
     return TLS_AES_128_GCM_SHA256;
   }
   return TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
 }
 
 static uint16_t ChooseAnotherCipher(uint16_t version) {
   if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-    return TLS_CHACHA20_POLY1305_SHA256;
+    return TLS_AES_256_GCM_SHA384;
   }
   return TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
 }
 
 // Test that we don't resume when we can't negotiate the same cipher.
 TEST_P(TlsConnectGeneric, TestResumeClientDifferentCipher) {
   ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
   client_->EnableSingleCipher(ChooseOneCipher(version_));
--- a/security/nss/gtests/ssl_gtest/tls_agent.cc
+++ b/security/nss/gtests/ssl_gtest/tls_agent.cc
@@ -30,16 +30,17 @@ namespace nss_test {
 const char* TlsAgent::states[] = {"INIT", "CONNECTING", "CONNECTED", "ERROR"};
 
 const std::string TlsAgent::kClient = "client";    // both sign and encrypt
 const std::string TlsAgent::kRsa2048 = "rsa2048";  // bigger
 const std::string TlsAgent::kServerRsa = "rsa";    // both sign and encrypt
 const std::string TlsAgent::kServerRsaSign = "rsa_sign";
 const std::string TlsAgent::kServerRsaPss = "rsa_pss";
 const std::string TlsAgent::kServerRsaDecrypt = "rsa_decrypt";
+const std::string TlsAgent::kServerRsaChain = "rsa_chain";
 const std::string TlsAgent::kServerEcdsa256 = "ecdsa256";
 const std::string TlsAgent::kServerEcdsa384 = "ecdsa384";
 const std::string TlsAgent::kServerEcdsa521 = "ecdsa521";
 const std::string TlsAgent::kServerEcdhRsa = "ecdh_rsa";
 const std::string TlsAgent::kServerEcdhEcdsa = "ecdh_ecdsa";
 const std::string TlsAgent::kServerDsa = "dsa";
 
 TlsAgent::TlsAgent(const std::string& name, Role role, Mode mode)
@@ -196,16 +197,33 @@ SECStatus TlsAgent::GetClientAuthDataHoo
   ScopedCERTCertificate peerCert(SSL_PeerCertificate(agent->ssl_fd()));
   EXPECT_TRUE(peerCert) << "Client should be able to see the server cert";
   if (agent->GetClientAuthCredentials(cert, privKey)) {
     return SECSuccess;
   }
   return SECFailure;
 }
 
+bool TlsAgent::GetPeerChainLength(size_t* count) {
+  CERTCertList* chain = SSL_PeerCertificateChain(ssl_fd_);
+  if (!chain) return false;
+  *count = 0;
+
+  for (PRCList* cursor = PR_NEXT_LINK(&chain->list); cursor != &chain->list;
+       cursor = PR_NEXT_LINK(cursor)) {
+    CERTCertListNode* node = (CERTCertListNode*)cursor;
+    std::cerr << node->cert->subjectName << std::endl;
+    ++(*count);
+  }
+
+  CERT_DestroyCertList(chain);
+
+  return true;
+}
+
 void TlsAgent::RequestClientAuth(bool requireAuth) {
   EXPECT_TRUE(EnsureTlsSetup());
   ASSERT_EQ(SERVER, role_);
 
   EXPECT_EQ(SECSuccess,
             SSL_OptionSet(ssl_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE));
   EXPECT_EQ(SECSuccess, SSL_OptionSet(ssl_fd_, SSL_REQUIRE_CERTIFICATE,
                                       requireAuth ? PR_TRUE : PR_FALSE));
@@ -624,17 +642,21 @@ void TlsAgent::Connected() {
   rv = SSL_GetCipherSuiteInfo(info_.cipherSuite, &csinfo_, sizeof(csinfo_));
   EXPECT_EQ(SECSuccess, rv);
   EXPECT_EQ(sizeof(csinfo_), csinfo_.length);
 
   if (expected_version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
     PRInt32 cipherSuites = SSLInt_CountTls13CipherSpecs(ssl_fd_);
     // We use one ciphersuite in each direction, plus one that's kept around
     // by DTLS for retransmission.
-    EXPECT_EQ(((mode_ == DGRAM) && (role_ == CLIENT)) ? 3 : 2, cipherSuites);
+    PRInt32 expected = ((mode_ == DGRAM) && (role_ == CLIENT)) ? 3 : 2;
+    EXPECT_EQ(expected, cipherSuites);
+    if (expected != cipherSuites) {
+      SSLInt_PrintTls13CipherSpecs(ssl_fd_);
+    }
   }
 
   SetState(STATE_CONNECTED);
 }
 
 void TlsAgent::EnableExtendedMasterSecret() {
   ASSERT_TRUE(EnsureTlsSetup());
 
@@ -854,17 +876,18 @@ void TlsAgentTestBase::Init(const std::s
   agent_->StartConnect();
 }
 
 void TlsAgentTestBase::EnsureInit() {
   if (!agent_) {
     Init();
   }
   const std::vector<SSLNamedGroup> groups = {
-      ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, ssl_grp_ffdhe_2048};
+      ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1,
+      ssl_grp_ffdhe_2048};
   agent_->ConfigNamedGroups(groups);
 }
 
 void TlsAgentTestBase::ProcessMessage(const DataBuffer& buffer,
                                       TlsAgent::State expected_state,
                                       int32_t error_code) {
   std::cerr << "Process message: " << buffer << std::endl;
   EnsureInit();
--- a/security/nss/gtests/ssl_gtest/tls_agent.h
+++ b/security/nss/gtests/ssl_gtest/tls_agent.h
@@ -57,16 +57,17 @@ class TlsAgent : public PollTarget {
   enum State { STATE_INIT, STATE_CONNECTING, STATE_CONNECTED, STATE_ERROR };
 
   static const std::string kClient;     // the client key is sign only
   static const std::string kRsa2048;    // bigger sign and encrypt for either
   static const std::string kServerRsa;  // both sign and encrypt
   static const std::string kServerRsaSign;
   static const std::string kServerRsaPss;
   static const std::string kServerRsaDecrypt;
+  static const std::string kServerRsaChain;  // A cert that requires a chain.
   static const std::string kServerEcdsa256;
   static const std::string kServerEcdsa384;
   static const std::string kServerEcdsa521;
   static const std::string kServerEcdhEcdsa;
   static const std::string kServerEcdhRsa;
   static const std::string kServerDsa;
 
   TlsAgent(const std::string& name, Role role, Mode mode);
@@ -103,16 +104,17 @@ class TlsAgent : public PollTarget {
 
   void Handshake();
   // Marks the internal state as CONNECTING in anticipation of renegotiation.
   void PrepareForRenegotiate();
   // Prepares for renegotiation, then actually triggers it.
   void StartRenegotiate();
   bool ConfigServerCert(const std::string& name, bool updateKeyBits = false,
                         const SSLExtraServerCertData* serverCertData = nullptr);
+  bool ConfigServerCertWithChain(const std::string& name);
   bool EnsureTlsSetup(PRFileDesc* modelSocket = nullptr);
 
   void SetupClientAuth();
   void RequestClientAuth(bool requireAuth);
   bool GetClientAuthCredentials(CERTCertificate** cert,
                                 SECKEYPrivateKey** priv) const;
 
   void ConfigureSessionCache(SessionResumptionMode mode);
@@ -146,16 +148,17 @@ class TlsAgent : public PollTarget {
   void CheckExtendedMasterSecret(bool expected);
   void CheckEarlyDataAccepted(bool expected);
   void DisableRollbackDetection();
   void EnableCompression();
   void SetDowngradeCheckVersion(uint16_t version);
   void CheckSecretsDestroyed();
   void ConfigNamedGroups(const std::vector<SSLNamedGroup>& groups);
   void DisableECDHEServerKeyReuse();
+  bool GetPeerChainLength(size_t* count);
 
   const std::string& name() const { return name_; }
 
   Role role() const { return role_; }
   std::string role_str() const { return role_ == SERVER ? "server" : "client"; }
 
   State state() const { return state_; }
 
--- a/security/nss/gtests/ssl_gtest/tls_connect.cc
+++ b/security/nss/gtests/ssl_gtest/tls_connect.cc
@@ -613,19 +613,21 @@ TlsConnectTls12Plus::TlsConnectTls12Plus
 
 TlsConnectTls13::TlsConnectTls13()
     : TlsConnectTestBase(GetParam(), SSL_LIBRARY_VERSION_TLS_1_3) {}
 
 void TlsKeyExchangeTest::EnsureKeyShareSetup() {
   EnsureTlsSetup();
   groups_capture_ = new TlsExtensionCapture(ssl_supported_groups_xtn);
   shares_capture_ = new TlsExtensionCapture(ssl_tls13_key_share_xtn);
+  shares_capture2_ = new TlsExtensionCapture(ssl_tls13_key_share_xtn, true);
   std::vector<PacketFilter*> captures;
   captures.push_back(groups_capture_);
   captures.push_back(shares_capture_);
+  captures.push_back(shares_capture2_);
   client_->SetPacketFilter(new ChainedPacketFilter(captures));
   capture_hrr_ =
       new TlsInspectorRecordHandshakeMessage(kTlsHandshakeHelloRetryRequest);
   server_->SetPacketFilter(capture_hrr_);
 }
 
 void TlsKeyExchangeTest::ConfigNamedGroups(
     const std::vector<SSLNamedGroup>& groups) {
@@ -678,9 +680,29 @@ void TlsKeyExchangeTest::CheckKEXDetails
     EXPECT_EQ(expected_shares, shares);
   } else {
     EXPECT_EQ(0U, shares_capture_->extension().len());
   }
 
   EXPECT_EQ(expect_hrr, capture_hrr_->buffer().len() != 0);
 }
 
+void TlsKeyExchangeTest::CheckKEXDetails(
+    const std::vector<SSLNamedGroup>& expected_groups,
+    const std::vector<SSLNamedGroup>& expected_shares) {
+  CheckKEXDetails(expected_groups, expected_shares, false);
+}
+
+void TlsKeyExchangeTest::CheckKEXDetails(
+    const std::vector<SSLNamedGroup>& expected_groups,
+    const std::vector<SSLNamedGroup>& expected_shares,
+    SSLNamedGroup expected_share2) {
+  CheckKEXDetails(expected_groups, expected_shares, true);
+
+  for (auto it : expected_shares) {
+    EXPECT_NE(expected_share2, it);
+  }
+  std::vector<SSLNamedGroup> expected_shares2 = {expected_share2};
+  std::vector<SSLNamedGroup> shares =
+      GetShareDetails(shares_capture2_->extension());
+  EXPECT_EQ(expected_shares2, shares);
+}
 }  // namespace nss_test
--- a/security/nss/gtests/ssl_gtest/tls_connect.h
+++ b/security/nss/gtests/ssl_gtest/tls_connect.h
@@ -242,25 +242,33 @@ class TlsConnectDatagram13 : public TlsC
 
 // A variant that is used only with Pre13.
 class TlsConnectGenericPre13 : public TlsConnectGeneric {};
 
 class TlsKeyExchangeTest : public TlsConnectGeneric {
  protected:
   TlsExtensionCapture* groups_capture_;
   TlsExtensionCapture* shares_capture_;
+  TlsExtensionCapture* shares_capture2_;
   TlsInspectorRecordHandshakeMessage* capture_hrr_;
 
   void EnsureKeyShareSetup();
   void ConfigNamedGroups(const std::vector<SSLNamedGroup>& groups);
   std::vector<SSLNamedGroup> GetGroupDetails(const DataBuffer& ext);
   std::vector<SSLNamedGroup> GetShareDetails(const DataBuffer& ext);
   void CheckKEXDetails(const std::vector<SSLNamedGroup>& expectedGroups,
+                       const std::vector<SSLNamedGroup>& expectedShares);
+  void CheckKEXDetails(const std::vector<SSLNamedGroup>& expectedGroups,
                        const std::vector<SSLNamedGroup>& expectedShares,
-                       bool expect_hrr = false);
+                       SSLNamedGroup expectedShare2);
+
+ private:
+  void CheckKEXDetails(const std::vector<SSLNamedGroup>& expectedGroups,
+                       const std::vector<SSLNamedGroup>& expectedShares,
+                       bool expect_hrr);
 };
 
 class TlsKeyExchangeTest13 : public TlsKeyExchangeTest {};
 class TlsKeyExchangeTestPre13 : public TlsKeyExchangeTest {};
 
 }  // namespace nss_test
 
 #endif
--- a/security/nss/gtests/ssl_gtest/tls_filter.cc
+++ b/security/nss/gtests/ssl_gtest/tls_filter.cc
@@ -426,18 +426,19 @@ PacketFilter::Action TlsExtensionFilter:
     output->Write(length_offset, newlen, 2);
     return CHANGE;
   }
   return KEEP;
 }
 
 PacketFilter::Action TlsExtensionCapture::FilterExtension(
     uint16_t extension_type, const DataBuffer& input, DataBuffer* output) {
-  if (extension_type == extension_ && data_.len() == 0) {
+  if (extension_type == extension_ && (last_ || !captured_)) {
     data_.Assign(input);
+    captured_ = true;
   }
   return KEEP;
 }
 
 PacketFilter::Action TlsExtensionReplacer::FilterExtension(
     uint16_t extension_type, const DataBuffer& input, DataBuffer* output) {
   if (extension_type != extension_) {
     return KEEP;
--- a/security/nss/gtests/ssl_gtest/tls_filter.h
+++ b/security/nss/gtests/ssl_gtest/tls_filter.h
@@ -229,27 +229,31 @@ class TlsExtensionFilter : public TlsHan
  private:
   PacketFilter::Action FilterExtensions(TlsParser* parser,
                                         const DataBuffer& input,
                                         DataBuffer* output);
 };
 
 class TlsExtensionCapture : public TlsExtensionFilter {
  public:
-  TlsExtensionCapture(uint16_t ext) : extension_(ext), data_() {}
+  TlsExtensionCapture(uint16_t ext, bool last = false)
+      : extension_(ext), captured_(false), last_(last), data_() {}
 
   const DataBuffer& extension() const { return data_; }
+  bool captured() const { return captured_; }
 
  protected:
   PacketFilter::Action FilterExtension(uint16_t extension_type,
                                        const DataBuffer& input,
                                        DataBuffer* output) override;
 
  private:
   const uint16_t extension_;
+  bool captured_;
+  bool last_;
   DataBuffer data_;
 };
 
 class TlsExtensionReplacer : public TlsExtensionFilter {
  public:
   TlsExtensionReplacer(uint16_t extension, const DataBuffer& data)
       : extension_(extension), data_(data) {}
   PacketFilter::Action FilterExtension(uint16_t extension_type,
--- a/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc
@@ -236,26 +236,26 @@ TEST_P(TlsHkdfTest, HkdfKey1Key2) {
 }
 
 TEST_P(TlsHkdfTest, HkdfExpandLabel) {
   const uint8_t tv[][48] = {
       {/* ssl_hash_none   */},
       {/* ssl_hash_md5    */},
       {/* ssl_hash_sha1   */},
       {/* ssl_hash_sha224 */},
-      {0x66, 0x8a, 0x55, 0x1a, 0xef, 0x33, 0x7b, 0x45, 0x26, 0xa6, 0x36,
-       0xb1, 0xe0, 0x23, 0x48, 0x24, 0x6f, 0x34, 0xa5, 0x57, 0x11, 0x4a,
-       0xb5, 0x64, 0xc4, 0x5c, 0x69, 0xb4, 0x0f, 0xc8, 0x12, 0xa5},
-      {0x99, 0x98, 0xde, 0xbf, 0x82, 0x8d, 0xf6, 0x55, 0xa1, 0xcf, 0xa8, 0xbe,
-       0x12, 0x06, 0x5c, 0x8e, 0x65, 0xec, 0x80, 0xa1, 0x33, 0xed, 0x61, 0x06,
-       0x09, 0xc6, 0x5c, 0x08, 0xcf, 0xc9, 0x91, 0x39, 0xbe, 0xce, 0x4e, 0x4a,
-       0x9b, 0x67, 0x36, 0x50, 0x89, 0x98, 0x59, 0x1c, 0x5d, 0x6e, 0x9c, 0x7d}};
+      {0x34, 0x7c, 0x67, 0x80, 0xff, 0x0b, 0xba, 0xd7, 0x1c, 0x28, 0x3b,
+       0x16, 0xeb, 0x2f, 0x9c, 0xf6, 0x2d, 0x24, 0xe6, 0xcd, 0xb6, 0x13,
+       0xd5, 0x17, 0x76, 0x54, 0x8c, 0xb0, 0x7d, 0xcd, 0xe7, 0x4c},
+      {0x4b, 0x1e, 0x5e, 0xc1, 0x49, 0x30, 0x78, 0xea, 0x35, 0xbd, 0x3f, 0x01,
+       0x04, 0xe6, 0x1a, 0xea, 0x14, 0xcc, 0x18, 0x2a, 0xd1, 0xc4, 0x76, 0x21,
+       0xc4, 0x64, 0xc0, 0x4e, 0x4b, 0x36, 0x16, 0x05, 0x6f, 0x04, 0xab, 0xe9,
+       0x43, 0xb1, 0x2d, 0xa8, 0xa7, 0x17, 0x9a, 0x5f, 0x09, 0x91, 0x7d, 0x1f}};
 
   const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]);
-  HkdfExpandLabel(&k1_, hash_type_, kSessionHash, kHashLength[hash_type_] * 2,
+  HkdfExpandLabel(&k1_, hash_type_, kSessionHash, kHashLength[hash_type_],
                   kLabelMasterSecret, strlen(kLabelMasterSecret),
                   expected_data);
 }
 
 static const SSLHashType kHashTypes[] = {ssl_hash_sha256, ssl_hash_sha384};
 INSTANTIATE_TEST_CASE_P(AllHashFuncs, TlsHkdfTest,
                         ::testing::ValuesIn(kHashTypes));
 
--- a/security/nss/lib/base/exports.gyp
+++ b/security/nss/lib/base/exports.gyp
@@ -10,24 +10,24 @@
       'target_name': 'lib_base_exports',
       'type': 'none',
       'copies': [
         {
           'files': [
             'nssbase.h',
             'nssbaset.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'base.h',
             'baset.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/certdb/exports.gyp
+++ b/security/nss/lib/certdb/exports.gyp
@@ -11,26 +11,26 @@
       'type': 'none',
       'copies': [
         {
           'files': [
             'cert.h',
             'certdb.h',
             'certt.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'certi.h',
             'certxutl.h',
             'genname.h',
             'xconst.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/certhigh/exports.gyp
+++ b/security/nss/lib/certhigh/exports.gyp
@@ -10,24 +10,24 @@
       'target_name': 'lib_certhigh_exports',
       'type': 'none',
       'copies': [
         {
           'files': [
             'ocsp.h',
             'ocspt.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'ocspi.h',
             'ocspti.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/ckfw/builtins/exports.gyp
+++ b/security/nss/lib/ckfw/builtins/exports.gyp
@@ -9,17 +9,17 @@
     {
       'target_name': 'lib_ckfw_builtins_exports',
       'type': 'none',
       'copies': [
         {
           'files': [
             'nssckbi.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/ckfw/exports.gyp
+++ b/security/nss/lib/ckfw/exports.gyp
@@ -17,28 +17,28 @@
             'nssckft.h',
             'nssckfw.h',
             'nssckfwc.h',
             'nssckfwt.h',
             'nssckg.h',
             'nssckmdt.h',
             'nssckt.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'ck.h',
             'ckfw.h',
             'ckfwm.h',
             'ckfwtm.h',
             'ckmd.h',
             'ckt.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/crmf/crmf.gyp
+++ b/security/nss/lib/crmf/crmf.gyp
@@ -25,15 +25,19 @@
         'crmftmpl.c',
         'encutil.c',
         'respcli.c',
         'respcmn.c',
         'servget.c'
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports'
-      ]
+      ],
+      'variables': {
+        # This is purely for the use of the Mozilla build system.
+        'no_expand_libs': 1,
+      },
     }
   ],
   'variables': {
     'module': 'nss'
   }
-}
\ No newline at end of file
+}
--- a/security/nss/lib/crmf/exports.gyp
+++ b/security/nss/lib/crmf/exports.gyp
@@ -12,26 +12,26 @@
       'copies': [
         {
           'files': [
             'cmmf.h',
             'cmmft.h',
             'crmf.h',
             'crmft.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'cmmfi.h',
             'cmmfit.h',
             'crmfi.h',
             'crmfit.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/cryptohi/exports.gyp
+++ b/security/nss/lib/cryptohi/exports.gyp
@@ -18,20 +18,20 @@
             'cryptohi.h',
             'cryptoht.h',
             'key.h',
             'keyhi.h',
             'keyt.h',
             'keythi.h',
             'sechash.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'keyi.h',
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
 }
--- a/security/nss/lib/dbm/include/exports.gyp
+++ b/security/nss/lib/dbm/include/exports.gyp
@@ -11,28 +11,28 @@
       'type': 'none',
       'copies': [
         {
           'files': [
             'mcom_db.h',
             'ncompat.h',
             'winfile.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'extern.h',
             'hash.h',
             'hsearch.h',
             'page.h',
             'queue.h',
             'search.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'dbm'
   }
 }
--- a/security/nss/lib/dev/exports.gyp
+++ b/security/nss/lib/dev/exports.gyp
@@ -15,17 +15,17 @@
             'ckhelper.h',
             'dev.h',
             'devm.h',
             'devt.h',
             'devtm.h',
             'nssdev.h',
             'nssdevt.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/freebl/exports.gyp
+++ b/security/nss/lib/freebl/exports.gyp
@@ -18,31 +18,31 @@
           ],
           'conditions': [
             [ 'OS=="linux"', {
               'files': [
                 'nsslowhash.h',
               ],
             }],
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'alghmac.h',
             'blapi.h',
             'chacha20poly1305.h',
             'ec.h',
             'ecl/ecl-curve.h',
             'ecl/ecl.h',
             'hmacct.h',
             'secmpi.h',
             'secrng.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/freebl/freebl.gyp
+++ b/security/nss/lib/freebl/freebl.gyp
@@ -42,17 +42,16 @@
         'arcfive.c',
         'arcfour.c',
         'camellia.c',
         'chacha20poly1305.c',
         'ctr.c',
         'cts.c',
         'des.c',
         'desblapi.c',
-        'det_rng.c',
         'dh.c',
         'drbg.c',
         'dsa.c',
         'ec.c',
         'ecdecode.c',
         'ecl/ec_naf.c',
         'ecl/ecl.c',
         'ecl/ecl_curve.c',
@@ -99,16 +98,19 @@
             'nsslowhash.c',
             'stubs.c',
           ],
           'conditions': [
             [ 'test_build==1', {
               'dependencies': [
                 '<(DEPTH)/lib/util/util.gyp:nssutil3',
               ],
+              'defines': [
+                'CT_VERIF',
+              ],
             }],
             [ 'target_arch=="x64"', {
               'sources': [
                 'arcfour-amd64-gas.s',
                 'intel-aes.s',
                 'intel-gcm.s',
                 'mpi/mpi_amd64.c',
                 'mpi/mpi_amd64_gas.s',
@@ -210,16 +212,19 @@
               'sources': [
                 'chacha20.c',
                 'poly1305.c',
               ],
             }],
           ],
         }],
         [ 'fuzz==1', {
+          'sources': [
+            'det_rng.c',
+          ],
           'defines': [
             'UNSAFE_FUZZER_MODE',
           ],
         }],
         [ 'OS=="mac"', {
           'conditions': [
             [ 'target_arch=="ia32"', {
               'sources': [
@@ -284,57 +289,54 @@
       'SHLIB_SUFFIX=\"<(dll_suffix)\"',
       'SHLIB_PREFIX=\"<(dll_prefix)\"',
       'SHLIB_VERSION=\"3\"',
       'SOFTOKEN_SHLIB_VERSION=\"3\"',
       'RIJNDAEL_INCLUDE_TABLES',
       'MP_API_COMPATIBLE'
     ],
     'conditions': [
-      [ 'OS=="win"', {
-        'configurations': {
-          'x86_Base': {
-            'msvs_settings': {
-              'VCCLCompilerTool': {
-                #TODO: -Ox optimize flags
-                'PreprocessorDefinitions': [
-                  'NSS_X86_OR_X64',
-                  'NSS_X86',
-                  'MP_ASSEMBLY_MULTIPLY',
-                  'MP_ASSEMBLY_SQUARE',
-                  'MP_ASSEMBLY_DIV_2DX1D',
-                  'MP_USE_UINT_DIGIT',
-                  'MP_NO_MP_WORD',
-                  'USE_HW_AES',
-                  'INTEL_GCM',
-                ],
-              },
-            },
-          },
-          'x64_Base': {
-            'msvs_settings': {
-              'VCCLCompilerTool': {
-                #TODO: -Ox optimize flags
-                'PreprocessorDefinitions': [
-                  'NSS_USE_64',
-                  'NSS_X86_OR_X64',
-                  'NSS_X64',
-                  'MP_IS_LITTLE_ENDIAN',
-                  'NSS_BEVAND_ARCFOUR',
-                  'MPI_AMD64',
-                  'MP_ASSEMBLY_MULTIPLY',
-                  'NSS_USE_COMBA',
-                  'USE_HW_AES',
-                  'INTEL_GCM',
-                ],
-              },
-            },
+      [ 'OS=="win" and target_arch=="ia32"', {
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            #TODO: -Ox optimize flags
+            'PreprocessorDefinitions': [
+              'NSS_X86_OR_X64',
+              'NSS_X86',
+              'MP_ASSEMBLY_MULTIPLY',
+              'MP_ASSEMBLY_SQUARE',
+              'MP_ASSEMBLY_DIV_2DX1D',
+              'MP_USE_UINT_DIGIT',
+              'MP_NO_MP_WORD',
+              'USE_HW_AES',
+              'INTEL_GCM',
+            ],
           },
         },
-      }, {
+      }],
+      [ 'OS=="win" and target_arch=="x64"', {
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            #TODO: -Ox optimize flags
+            'PreprocessorDefinitions': [
+              'NSS_USE_64',
+              'NSS_X86_OR_X64',
+              'NSS_X64',
+              'MP_IS_LITTLE_ENDIAN',
+              'NSS_BEVAND_ARCFOUR',
+              'MPI_AMD64',
+              'MP_ASSEMBLY_MULTIPLY',
+              'NSS_USE_COMBA',
+              'USE_HW_AES',
+              'INTEL_GCM',
+            ],
+          },
+        },
+      }],
+      [ 'OS!="win"', {
         'conditions': [
           [ 'target_arch=="x64"', {
             'defines': [
               'NSS_USE_64',
               'NSS_X86_OR_X64',
               'NSS_X64',
               # The Makefile does version-tests on GCC, but we're not doing that here.
               'HAVE_INT128_SUPPORT',
@@ -387,18 +389,14 @@
               'MP_ASSEMBLY_MULTIPLY',
               'MP_ASSEMBLY_SQUARE',
               'MP_USE_UINT_DIGIT',
               'SHA_NO_LONG_LONG',
             ],
           }],
         ],
       }],
-      [ 'OS=="mac"', {
-      }],
-      [ 'OS=="win"', {
-      }],
     ],
   },
   'variables': {
     'module': 'nss',
   }
 }
--- a/security/nss/lib/freebl/mpi/mpi.c
+++ b/security/nss/lib/freebl/mpi/mpi.c
@@ -32,16 +32,20 @@
   log_r(n) = log_2(n) * log_r(2)
 
   This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
   which are the output bases supported.
  */
 #include "logtab.h"
 #endif
 
+#ifdef CT_VERIF
+#include <valgrind/memcheck.h>
+#endif
+
 /* {{{ Constant strings */
 
 /* Constant strings returned by mp_strerror() */
 static const char *mp_err_string[] = {
     "unknown result code",     /* say what?            */
     "boolean true",            /* MP_OKAY, MP_YES      */
     "boolean false",           /* MP_NO                */
     "out of memory",           /* MP_MEM               */
@@ -77,16 +81,36 @@ mp_set_prec(mp_size prec)
         s_mp_defprec = MP_DEFPREC;
     else
         s_mp_defprec = prec;
 
 } /* end mp_set_prec() */
 
 /* }}} */
 
+#ifdef CT_VERIF
+void
+mp_taint(mp_int *mp)
+{
+    size_t i;
+    for (i = 0; i < mp->used; ++i) {
+        VALGRIND_MAKE_MEM_UNDEFINED(&(mp->dp[i]), sizeof(mp_digit));
+    }
+}
+
+void
+mp_untaint(mp_int *mp)
+{
+    size_t i;
+    for (i = 0; i < mp->used; ++i) {
+        VALGRIND_MAKE_MEM_DEFINED(&(mp->dp[i]), sizeof(mp_digit));
+    }
+}
+#endif
+
 /*------------------------------------------------------------------------*/
 /* {{{ mp_init(mp) */
 
 /*
   mp_init(mp)
 
   Initialize a new zero-valued mp_int.  Returns MP_OKAY if successful,
   MP_MEM if memory could not be allocated for the structure.
--- a/security/nss/lib/freebl/mpi/mpi.h
+++ b/security/nss/lib/freebl/mpi/mpi.h
@@ -7,16 +7,19 @@
  * 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 _H_MPI_
 #define _H_MPI_
 
 #include "mpi-config.h"
 
+#include "seccomon.h"
+SEC_BEGIN_PROTOS
+
 #if MP_DEBUG
 #undef MP_IOFUNC
 #define MP_IOFUNC 1
 #endif
 
 #if MP_IOFUNC
 #include <stdio.h>
 #include <ctype.h>
@@ -268,17 +271,16 @@ void freebl_cpuid(unsigned long op, unsi
 
 #define MP_CHECKOK(x)          \
     if (MP_OKAY > (res = (x))) \
     goto CLEANUP
 #define MP_CHECKERR(x)         \
     if (MP_OKAY > (res = (x))) \
     goto CLEANUP
 
-#if defined(MP_API_COMPATIBLE)
 #define NEG MP_NEG
 #define ZPOS MP_ZPOS
 #define DIGIT_MAX MP_DIGIT_MAX
 #define DIGIT_BIT MP_DIGIT_BIT
 #define DIGIT_FMT MP_DIGIT_FMT
 #define RADIX MP_RADIX
 #define MAX_RADIX MP_MAX_RADIX
 #define SIGN(MP) MP_SIGN(MP)
@@ -295,11 +297,17 @@ void freebl_cpuid(unsigned long op, unsi
         }               \
     }
 #elif MP_ARGCHK == 2
 #include <assert.h>
 #define ARGCHK(X, Y) assert(X)
 #else
 #define ARGCHK(X, Y) /*  */
 #endif
-#endif /* defined MP_API_COMPATIBLE */
+
+#ifdef CT_VERIF
+void mp_taint(mp_int *mp);
+void mp_untaint(mp_int *mp);
+#endif
+
+SEC_END_PROTOS
 
 #endif /* end _H_MPI_ */
--- a/security/nss/lib/freebl/mpi/test-arrays.txt
+++ b/security/nss/lib/freebl/mpi/test-arrays.txt
@@ -28,17 +28,16 @@ multiply:test_mul:test full multiplicati
 square:test_sqr:test full squaring function
 divide-digit:test_div_d:test digit division
 divide-2:test_div_2:test division by two
 divide-2d:test_div_2d:test division & remainder by 2^d
 divide:test_div:test full division
 expt-digit:test_expt_d:test digit exponentiation
 expt:test_expt:test full exponentiation
 expt-2:test_2expt:test power-of-two exponentiation
-square-root:test_sqrt:test integer square root function
 modulo-digit:test_mod_d:test digit modular reduction
 modulo:test_mod:test full modular reduction
 mod-add:test_addmod:test modular addition
 mod-subtract:test_submod:test modular subtraction
 mod-multiply:test_mulmod:test modular multiplication
 mod-square:test_sqrmod:test modular squaring function
 mod-expt:test_exptmod:test full modular exponentiation
 mod-expt-digit:test_exptmod_d:test digit modular exponentiation
deleted file mode 100644
--- a/security/nss/lib/freebl/mpi/test-info.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- *  test-info.c
- *
- *  Arbitrary precision integer arithmetic library
- *
- * 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/. */
-
-/* Table mapping test suite names to index numbers */
-const int g_count = 42;
-const char *g_names[] = {
-    "list",              /* print out a list of the available test suites */
-    "copy",              /* test assignment of mp-int structures          */
-    "exchange",          /* test exchange of mp-int structures            */
-    "zero",              /* test zeroing of an mp-int                     */
-    "set",               /* test setting an mp-int to a small constant    */
-    "absolute-value",    /* test the absolute value function              */
-    "negate",            /* test the arithmetic negation function         */
-    "add-digit",         /* test digit addition                           */
-    "add",               /* test full addition                            */
-    "subtract-digit",    /* test digit subtraction                        */
-    "subtract",          /* test full subtraction                         */
-    "multiply-digit",    /* test digit multiplication                     */
-    "multiply",          /* test full multiplication                      */
-    "square",            /* test full squaring function                   */
-    "divide-digit",      /* test digit division                           */
-    "divide-2",          /* test division by two                          */
-    "divide-2d",         /* test division & remainder by 2^d              */
-    "divide",            /* test full division                            */
-    "expt-digit",        /* test digit exponentiation                     */
-    "expt",              /* test full exponentiation                      */
-    "expt-2",            /* test power-of-two exponentiation              */
-    "square-root",       /* test integer square root function             */
-    "modulo-digit",      /* test digit modular reduction                  */
-    "modulo",            /* test full modular reduction                   */
-    "mod-add",           /* test modular addition                         */
-    "mod-subtract",      /* test modular subtraction                      */
-    "mod-multiply",      /* test modular multiplication                   */
-    "mod-square",        /* test modular squaring function                */
-    "mod-expt",          /* test full modular exponentiation              */
-    "mod-expt-digit",    /* test digit modular exponentiation             */
-    "mod-inverse",       /* test modular inverse function                 */
-    "compare-digit",     /* test digit comparison function                */
-    "compare-zero",      /* test zero comparison function                 */
-    "compare",           /* test general signed comparison                */
-    "compare-magnitude", /* test general magnitude comparison             */
-    "parity",            /* test parity comparison functions              */
-    "gcd",               /* test greatest common divisor functions        */
-    "lcm",               /* test least common multiple function           */
-    "conversion",        /* test general radix conversion facilities      */
-    "binary",            /* test raw output format                        */
-    "pprime",            /* test probabilistic primality tester           */
-    "fermat"             /* test Fermat pseudoprimality tester            */
-};
-
-/* Test function prototypes */
-int test_list(void);
-int test_copy(void);
-int test_exch(void);
-int test_zero(void);
-int test_set(void);
-int test_abs(void);
-int test_neg(void);
-int test_add_d(void);
-int test_add(void);
-int test_sub_d(void);
-int test_sub(void);
-int test_mul_d(void);
-int test_mul(void);
-int test_sqr(void);
-int test_div_d(void);
-int test_div_2(void);
-int test_div_2d(void);
-int test_div(void);
-int test_expt_d(void);
-int test_expt(void);
-int test_2expt(void);
-int test_sqrt(void);
-int test_mod_d(void);
-int test_mod(void);
-int test_addmod(void);
-int test_submod(void);
-int test_mulmod(void);
-int test_sqrmod(void);
-int test_exptmod(void);
-int test_exptmod_d(void);
-int test_invmod(void);
-int test_cmp_d(void);
-int test_cmp_z(void);
-int test_cmp(void);
-int test_cmp_mag(void);
-int test_parity(void);
-int test_gcd(void);
-int test_lcm(void);
-int test_convert(void);
-int test_raw(void);
-int test_pprime(void);
-int test_fermat(void);
-
-/* Table mapping index numbers to functions */
-int (*g_tests[])(void) = {
-    test_list, test_copy, test_exch, test_zero,
-    test_set, test_abs, test_neg, test_add_d,
-    test_add, test_sub_d, test_sub, test_mul_d,
-    test_mul, test_sqr, test_div_d, test_div_2,
-    test_div_2d, test_div, test_expt_d, test_expt,
-    test_2expt, test_sqrt, test_mod_d, test_mod,
-    test_addmod, test_submod, test_mulmod, test_sqrmod,
-    test_exptmod, test_exptmod_d, test_invmod, test_cmp_d,
-    test_cmp_z, test_cmp, test_cmp_mag, test_parity,
-    test_gcd, test_lcm, test_convert, test_raw,
-    test_pprime, test_fermat
-};
-
-/* Table mapping index numbers to descriptions */
-const char *g_descs[] = {
-    "print out a list of the available test suites",
-    "test assignment of mp-int structures",
-    "test exchange of mp-int structures",
-    "test zeroing of an mp-int",
-    "test setting an mp-int to a small constant",
-    "test the absolute value function",
-    "test the arithmetic negation function",
-    "test digit addition",
-    "test full addition",
-    "test digit subtraction",
-    "test full subtraction",
-    "test digit multiplication",
-    "test full multiplication",
-    "test full squaring function",
-    "test digit division",
-    "test division by two",
-    "test division & remainder by 2^d",
-    "test full division",
-    "test digit exponentiation",
-    "test full exponentiation",
-    "test power-of-two exponentiation",
-    "test integer square root function",
-    "test digit modular reduction",
-    "test full modular reduction",
-    "test modular addition",
-    "test modular subtraction",
-    "test modular multiplication",
-    "test modular squaring function",
-    "test full modular exponentiation",
-    "test digit modular exponentiation",
-    "test modular inverse function",
-    "test digit comparison function",
-    "test zero comparison function",
-    "test general signed comparison",
-    "test general magnitude comparison",
-    "test parity comparison functions",
-    "test greatest common divisor functions",
-    "test least common multiple function",
-    "test general radix conversion facilities",
-    "test raw output format",
-    "test probabilistic primality tester",
-    "test Fermat pseudoprimality tester"
-};
--- a/security/nss/lib/jar/exports.gyp
+++ b/security/nss/lib/jar/exports.gyp
@@ -11,17 +11,17 @@
       'type': 'none',
       'copies': [
         {
           'files': [
             'jar-ds.h',
             'jar.h',
             'jarfile.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/include/exports.gyp
+++ b/security/nss/lib/libpkix/include/exports.gyp
@@ -22,17 +22,17 @@
             'pkix_pl_pki.h',
             'pkix_pl_system.h',
             'pkix_results.h',
             'pkix_revchecker.h',
             'pkix_sample_modules.h',
             'pkix_util.h',
             'pkixt.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/pkix/certsel/exports.gyp
+++ b/security/nss/lib/libpkix/pkix/certsel/exports.gyp
@@ -10,17 +10,17 @@
       'target_name': 'lib_libpkix_pkix_certsel_exports',
       'type': 'none',
       'copies': [
         {
           'files': [
             'pkix_certselector.h',
             'pkix_comcertselparams.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/pkix/checker/exports.gyp
+++ b/security/nss/lib/libpkix/pkix/checker/exports.gyp
@@ -21,17 +21,17 @@
             'pkix_nameconstraintschecker.h',
             'pkix_ocspchecker.h',
             'pkix_policychecker.h',
             'pkix_revocationchecker.h',
             'pkix_revocationmethod.h',
             'pkix_signaturechecker.h',
             'pkix_targetcertchecker.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/pkix/crlsel/exports.gyp
+++ b/security/nss/lib/libpkix/pkix/crlsel/exports.gyp
@@ -10,17 +10,17 @@
       'target_name': 'lib_libpkix_pkix_crlsel_exports',
       'type': 'none',
       'copies': [
         {
           'files': [
             'pkix_comcrlselparams.h',
             'pkix_crlselector.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/pkix/params/exports.gyp
+++ b/security/nss/lib/libpkix/pkix/params/exports.gyp
@@ -12,17 +12,17 @@
       'copies': [
         {
           'files': [
             'pkix_procparams.h',
             'pkix_resourcelimits.h',
             'pkix_trustanchor.h',
             'pkix_valparams.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/pkix/results/exports.gyp
+++ b/security/nss/lib/libpkix/pkix/results/exports.gyp
@@ -12,17 +12,17 @@
       'copies': [
         {
           'files': [
             'pkix_buildresult.h',
             'pkix_policynode.h',
             'pkix_valresult.h',
             'pkix_verifynode.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/pkix/store/exports.gyp
+++ b/security/nss/lib/libpkix/pkix/store/exports.gyp
@@ -9,17 +9,17 @@
     {
       'target_name': 'lib_libpkix_pkix_store_exports',
       'type': 'none',
       'copies': [
         {
           'files': [
             'pkix_store.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/pkix/top/exports.gyp
+++ b/security/nss/lib/libpkix/pkix/top/exports.gyp
@@ -11,17 +11,17 @@
       'type': 'none',
       'copies': [
         {
           'files': [
             'pkix_build.h',
             'pkix_lifecycle.h',
             'pkix_validate.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/pkix/util/exports.gyp
+++ b/security/nss/lib/libpkix/pkix/util/exports.gyp
@@ -12,17 +12,17 @@
       'copies': [
         {
           'files': [
             'pkix_error.h',
             'pkix_list.h',
             'pkix_logger.h',
             'pkix_tools.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/pkix_pl_nss/module/exports.gyp
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/exports.gyp
@@ -20,17 +20,17 @@
             'pkix_pl_ldapdefaultclient.h',
             'pkix_pl_ldaprequest.h',
             'pkix_pl_ldapresponse.h',
             'pkix_pl_ldapt.h',
             'pkix_pl_nsscontext.h',
             'pkix_pl_pk11certstore.h',
             'pkix_pl_socket.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/exports.gyp
@@ -25,17 +25,17 @@
             'pkix_pl_infoaccess.h',
             'pkix_pl_nameconstraints.h',
             'pkix_pl_ocspcertid.h',
             'pkix_pl_ocsprequest.h',
             'pkix_pl_ocspresponse.h',
             'pkix_pl_publickey.h',
             'pkix_pl_x500name.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/libpkix/pkix_pl_nss/system/exports.gyp
+++ b/security/nss/lib/libpkix/pkix_pl_nss/system/exports.gyp
@@ -21,17 +21,17 @@
             'pkix_pl_monitorlock.h',
             'pkix_pl_mutex.h',
             'pkix_pl_object.h',
             'pkix_pl_oid.h',
             'pkix_pl_primhash.h',
             'pkix_pl_rwlock.h',
             'pkix_pl_string.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/nss/exports.gyp
+++ b/security/nss/lib/nss/exports.gyp
@@ -9,24 +9,24 @@
     {
       'target_name': 'lib_nss_exports',
       'type': 'none',
       'copies': [
         {
           'files': [
             'nss.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'nssoptions.h',
             'nssrenam.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -17,19 +17,19 @@
 
 /*
  * NSS's major version, minor version, patch level, build number, and whether
  * this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define NSS_VERSION "3.28" _NSS_CUSTOMIZED " Beta"
+#define NSS_VERSION "3.29" _NSS_CUSTOMIZED " Beta"
 #define NSS_VMAJOR 3
-#define NSS_VMINOR 28
+#define NSS_VMINOR 29
 #define NSS_VPATCH 0
 #define NSS_VBUILD 0
 #define NSS_BETA PR_TRUE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
--- a/security/nss/lib/pk11wrap/exports.gyp
+++ b/security/nss/lib/pk11wrap/exports.gyp
@@ -16,24 +16,24 @@
             'pk11pqg.h',
             'pk11priv.h',
             'pk11pub.h',
             'pk11sdr.h',
             'secmod.h',
             'secmodt.h',
             'secpkcs5.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'dev3hack.h',
             'secmodi.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/pkcs12/exports.gyp
+++ b/security/nss/lib/pkcs12/exports.gyp
@@ -13,17 +13,17 @@
         {
           'files': [
             'p12.h',
             'p12plcy.h',
             'p12t.h',
             'pkcs12.h',
             'pkcs12t.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/pkcs7/exports.gyp
+++ b/security/nss/lib/pkcs7/exports.gyp
@@ -11,23 +11,23 @@
       'type': 'none',
       'copies': [
         {
           'files': [
             'pkcs7t.h',
             'secmime.h',
             'secpkcs7.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'p7local.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/pki/exports.gyp
+++ b/security/nss/lib/pki/exports.gyp
@@ -16,17 +16,17 @@
             'nsspkit.h',
             'pki.h',
             'pki3hack.h',
             'pkim.h',
             'pkistore.h',
             'pkit.h',
             'pkitm.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/smime/exports.gyp
+++ b/security/nss/lib/smime/exports.gyp
@@ -12,23 +12,23 @@
       'copies': [
         {
           'files': [
             'cms.h',
             'cmsreclist.h',
             'cmst.h',
             'smime.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'cmslocal.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/softoken/exports.gyp
+++ b/security/nss/lib/softoken/exports.gyp
@@ -10,29 +10,29 @@
       'target_name': 'lib_softoken_exports',
       'type': 'none',
       'copies': [
         {
           'files': [
             'lowkeyi.h',
             'lowkeyti.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         },
         {
           'files': [
             'lgglue.h',
             'pkcs11ni.h',
             'sdb.h',
             'sftkdbt.h',
             'softkver.h',
             'softoken.h',
             'softoknt.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -16,16 +16,16 @@
 
 /*
  * Softoken's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define SOFTOKEN_VERSION "3.28" SOFTOKEN_ECC_STRING " Beta"
+#define SOFTOKEN_VERSION "3.29" SOFTOKEN_ECC_STRING " Beta"
 #define SOFTOKEN_VMAJOR 3
-#define SOFTOKEN_VMINOR 28
+#define SOFTOKEN_VMINOR 29
 #define SOFTOKEN_VPATCH 0
 #define SOFTOKEN_VBUILD 0
 #define SOFTOKEN_BETA PR_TRUE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/sqlite/exports.gyp
+++ b/security/nss/lib/sqlite/exports.gyp
@@ -9,17 +9,17 @@
     {
       'target_name': 'lib_sqlite_exports',
       'type': 'none',
       'copies': [
         {
           'files': [
             'sqlite3.h'
           ],
-          'destination': '<(nss_dist_dir)/private/<(module)'
+          'destination': '<(nss_private_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/ssl/SSLerrs.h
+++ b/security/nss/lib/ssl/SSLerrs.h
@@ -494,8 +494,14 @@ ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_RETRY_
 ER3(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST, (SSL_ERROR_BASE + 155),
     "SSL received a malformed Hello Retry Request handshake message.")
 
 ER3(SSL_ERROR_BAD_2ND_CLIENT_HELLO, (SSL_ERROR_BASE + 156),
     "SSL received a second Client Hello message without a usable key share.")
 
 ER3(SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION, (SSL_ERROR_BASE + 157),
     "SSL expected a signature algorithms extension.")
+
+ER3(SSL_ERROR_MALFORMED_PSK_KEY_EXCHANGE_MODES, (SSL_ERROR_BASE + 158),
+    "SSL received a malformed PSK key exchange modes extension.")
+
+ER3(SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES, (SSL_ERROR_BASE + 159),
+    "SSL expected a missing PSK key exchange modes extension.")
--- a/security/nss/lib/ssl/dtlscon.c
+++ b/security/nss/lib/ssl/dtlscon.c
@@ -797,64 +797,16 @@ dtls_SendSavedWriteData(sslSocket *ss)
     /* Update the largest message sent so we can adjust the MTU
      * estimate if necessary */
     if (sent > ss->ssl3.hs.maxMessageSent)
         ss->ssl3.hs.maxMessageSent = sent;
 
     return SECSuccess;
 }
 
-/* Compress, MAC, encrypt a DTLS record. Allows specification of
- * the epoch using epoch value. If use_epoch is PR_TRUE then
- * we use the provided epoch. If use_epoch is PR_FALSE then
- * whatever the current value is in effect is used.
- *
- * Called from ssl3_SendRecord()
- */
-SECStatus
-dtls_CompressMACEncryptRecord(sslSocket *ss,
-                              ssl3CipherSpec *cwSpec,
-                              SSL3ContentType type,
-                              const SSL3Opaque *pIn,
-                              PRUint32 contentLen,
-                              sslBuffer *wrBuf)
-{
-    SECStatus rv = SECFailure;
-
-    ssl_GetSpecReadLock(ss); /********************************/
-
-    /* The reason for this switch-hitting code is that we might have
-     * a flight of records spanning an epoch boundary, e.g.,
-     *
-     * ClientKeyExchange (epoch = 0)
-     * ChangeCipherSpec (epoch = 0)
-     * Finished (epoch = 1)
-     *
-     * Thus, each record needs a different cipher spec. The information
-     * about which epoch to use is carried with the record.
-     */
-    if (!cwSpec) {
-        cwSpec = ss->ssl3.cwSpec;
-    } else {
-        PORT_Assert(type == content_handshake ||
-                    type == content_change_cipher_spec);
-    }
-
-    if (cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-        rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
-                                           PR_FALSE, type, pIn, contentLen,
-                                           wrBuf);
-    } else {
-        rv = tls13_ProtectRecord(ss, cwSpec, type, pIn, contentLen, wrBuf);
-    }
-    ssl_ReleaseSpecReadLock(ss); /************************************/
-
-    return rv;
-}
-
 static SECStatus
 dtls_StartTimer(sslSocket *ss, PRUint32 time, DTLSTimerCb cb)
 {
     PORT_Assert(ss->ssl3.hs.rtTimerCb == NULL);
 
     ss->ssl3.hs.rtRetries = 0;
     ss->ssl3.hs.rtTimerStarted = PR_IntervalNow();
     ss->ssl3.hs.rtTimeoutMs = time;
--- a/security/nss/lib/ssl/exports.gyp
+++ b/security/nss/lib/ssl/exports.gyp
@@ -13,17 +13,17 @@
         {
           'files': [
             'preenc.h',
             'ssl.h',
             'sslerr.h',
             'sslproto.h',
             'sslt.h'
           ],
-          'destination': '<(nss_dist_dir)/public/<(module)'
+          'destination': '<(nss_public_dist_dir)/<(module)'
         }
       ]
     }
   ],
   'variables': {
     'module': 'nss'
   }
 }
--- a/security/nss/lib/ssl/ssl.def
+++ b/security/nss/lib/ssl/ssl.def
@@ -215,8 +215,14 @@ SSL_NamedGroupConfig;
 ;+NSS_3.28 {    # NSS 3.28 release
 ;+    global:
 SSL_SendAdditionalKeyShares;
 SSL_SignatureSchemePrefSet;
 SSL_SignatureSchemePrefGet;
 ;+    local:
 ;+*;
 ;+};
+;+NSS_3.29 {    # NSS 3.29 release
+;+    global:
+SSL_ExportEarlyKeyingMaterial;
+;+    local:
+;+*;
+;+};
--- a/security/nss/lib/ssl/ssl.h
+++ b/security/nss/lib/ssl/ssl.h
@@ -1211,16 +1211,26 @@ SSL_IMPORT SECStatus SSL_ExportKeyingMat
                                               const char *label,
                                               unsigned int labelLen,
                                               PRBool hasContext,
                                               const unsigned char *context,
                                               unsigned int contextLen,
                                               unsigned char *out,
                                               unsigned int outLen);
 
+/* Early exporters are used if 0-RTT is enabled.  This is TLS 1.3 only.  Note
+ * that in TLS 1.3, an empty context is equivalent to an absent context. */
+SSL_IMPORT SECStatus SSL_ExportEarlyKeyingMaterial(PRFileDesc *fd,
+                                                   const char *label,
+                                                   unsigned int labelLen,
+                                                   const unsigned char *context,
+                                                   unsigned int contextLen,
+                                                   unsigned char *out,
+                                                   unsigned int outLen);
+
 /*
 ** Return a new reference to the certificate that was most recently sent
 ** to the peer on this SSL/TLS connection, or NULL if none has been sent.
 */
 SSL_IMPORT CERTCertificate *SSL_LocalCertificate(PRFileDesc *fd);
 
 #define SSL_CBP_SSL3 0x0001   /* (deprecated) */
 #define SSL_CBP_TLS1_0 0x0002 /* (deprecated) */
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -40,24 +40,22 @@
 
 #ifndef PK11_SETATTRS
 #define PK11_SETATTRS(x, id, v, l) \
     (x)->type = (id);              \
     (x)->pValue = (v);             \
     (x)->ulValueLen = (l);
 #endif
 
-static SECStatus ssl3_AuthCertificate(sslSocket *ss);
-static void ssl3_CleanupPeerCerts(sslSocket *ss);
 static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
                                        PK11SlotInfo *serverKeySlot);
 static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms);
 static SECStatus ssl3_DeriveConnectionKeys(sslSocket *ss);
 static SECStatus ssl3_HandshakeFailure(sslSocket *ss);
-
+static SECStatus ssl3_SendCertificate(sslSocket *ss);
 static SECStatus ssl3_SendCertificateRequest(sslSocket *ss);
 static SECStatus ssl3_SendNextProto(sslSocket *ss);
 static SECStatus ssl3_SendFinished(sslSocket *ss, PRInt32 flags);
 static SECStatus ssl3_SendServerHelloDone(sslSocket *ss);
 static SECStatus ssl3_SendServerKeyExchange(sslSocket *ss);
 static SECStatus ssl3_HandleClientHelloPart2(sslSocket *ss,
                                              SECItem *suites,
                                              SECItem *comps,
@@ -2409,110 +2407,94 @@ ssl3_CompressMACEncryptRecord(ssl3Cipher
                               PRUint32 contentLen,
                               sslBuffer *wrBuf)
 {
     const ssl3BulkCipherDef *cipher_def;
     SECStatus rv;
     PRUint32 macLen = 0;
     PRUint32 fragLen;
     PRUint32 p1Len, p2Len, oddLen = 0;
-    PRUint16 headerLen;
     unsigned int ivLen = 0;
-    int cipherBytes = 0;
     unsigned char pseudoHeader[13];
     unsigned int pseudoHeaderLen;
-    PRUint8 *b;
 
     cipher_def = cwSpec->cipher_def;
-    headerLen = isDTLS ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH;
-
-    PORT_Assert(cipher_def->max_records <= RECORD_SEQ_MAX);
-    if ((cwSpec->write_seq_num & RECORD_SEQ_MAX) >= cipher_def->max_records) {
-        SSL_TRC(3, ("%d: SSL[-]: write sequence number at limit 0x%0llx",
-                    SSL_GETPID(), cwSpec->write_seq_num));
-        PORT_SetError(SSL_ERROR_TOO_MANY_RECORDS);
-        return SECFailure;
-    }
 
     if (cipher_def->type == type_block &&
         cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
         /* Prepend the per-record explicit IV using technique 2b from
          * RFC 4346 section 6.2.3.2: The IV is a cryptographically
          * strong random number XORed with the CBC residue from the previous
          * record.
          */
         ivLen = cipher_def->iv_size;
-        if (ivLen > wrBuf->space - headerLen) {
+        if (ivLen > wrBuf->space) {
             PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
             return SECFailure;
         }
-        rv = PK11_GenerateRandom(wrBuf->buf + headerLen, ivLen);
+        rv = PK11_GenerateRandom(wrBuf->buf, ivLen);
         if (rv != SECSuccess) {
             ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
             return rv;
         }
         rv = cwSpec->encode(cwSpec->encodeContext,
-                            wrBuf->buf + headerLen,
-                            &cipherBytes, /* output and actual outLen */
-                            ivLen,        /* max outlen */
-                            wrBuf->buf + headerLen,
-                            ivLen); /* input and inputLen*/
-        if (rv != SECSuccess || cipherBytes != ivLen) {
+                            wrBuf->buf,         /* output */
+                            (int *)&wrBuf->len, /* outlen */
+                            ivLen,              /* max outlen */
+                            wrBuf->buf,         /* input */
+                            ivLen);             /* input len */
+        if (rv != SECSuccess || wrBuf->len != ivLen) {
             PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
             return SECFailure;
         }
     }
 
     if (cwSpec->compressor) {
         int outlen;
-        rv = cwSpec->compressor(
-            cwSpec->compressContext,
-            wrBuf->buf + headerLen + ivLen, &outlen,
-            wrBuf->space - headerLen - ivLen, pIn, contentLen);
+        rv = cwSpec->compressor(cwSpec->compressContext, wrBuf->buf + ivLen,
+                                &outlen, wrBuf->space - ivLen, pIn, contentLen);
         if (rv != SECSuccess)
             return rv;
-        pIn = wrBuf->buf + headerLen + ivLen;
+        pIn = wrBuf->buf + ivLen;
         contentLen = outlen;
     }
 
     pseudoHeaderLen = ssl3_BuildRecordPseudoHeader(
         pseudoHeader, cwSpec->write_seq_num, type,
         cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->version,
         isDTLS, contentLen);
     PORT_Assert(pseudoHeaderLen <= sizeof(pseudoHeader));
     if (cipher_def->type == type_aead) {
         const int nonceLen = cipher_def->explicit_nonce_size;
         const int tagLen = cipher_def->tag_size;
 
-        if (headerLen + nonceLen + contentLen + tagLen > wrBuf->space) {
+        if (nonceLen + contentLen + tagLen > wrBuf->space) {
             PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
             return SECFailure;
         }
 
-        cipherBytes = contentLen;
         rv = cwSpec->aead(
             isServer ? &cwSpec->server : &cwSpec->client,
-            PR_FALSE,                 /* do encrypt */
-            wrBuf->buf + headerLen,   /* output  */
-            &cipherBytes,             /* out len */
-            wrBuf->space - headerLen, /* max out */
-            pIn, contentLen,          /* input   */
+            PR_FALSE,           /* do encrypt */
+            wrBuf->buf,         /* output  */
+            (int *)&wrBuf->len, /* out len */
+            wrBuf->space,       /* max out */
+            pIn, contentLen,    /* input   */
             pseudoHeader, pseudoHeaderLen);
         if (rv != SECSuccess) {
             PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
             return SECFailure;
         }
     } else {
         /*
          * Add the MAC
          */
-        rv = ssl3_ComputeRecordMAC(cwSpec, isServer,
-                                   pseudoHeader, pseudoHeaderLen, pIn, contentLen,
-                                   wrBuf->buf + headerLen + ivLen + contentLen,
-                                   &macLen);
+        rv = ssl3_ComputeRecordMAC(cwSpec, isServer, pseudoHeader,
+                                   pseudoHeaderLen, pIn, contentLen,
+                                   wrBuf->buf + ivLen + contentLen, &macLen);
         if (rv != SECSuccess) {
             ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
             return SECFailure;
         }
         p1Len = contentLen;
         p2Len = macLen;
         fragLen = contentLen + macLen; /* needs to be encrypted */
         PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);
@@ -2528,90 +2510,127 @@ ssl3_CompressMACEncryptRecord(ssl3Cipher
 
             oddLen = contentLen % cipher_def->block_size;
             /* Assume blockSize is a power of two */
             padding_length = cipher_def->block_size - 1 - ((fragLen) & (cipher_def->block_size - 1));
             fragLen += padding_length + 1;
             PORT_Assert((fragLen % cipher_def->block_size) == 0);
 
             /* Pad according to TLS rules (also acceptable to SSL3). */
-            pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1];
+            pBuf = &wrBuf->buf[ivLen + fragLen - 1];
             for (i = padding_length + 1; i > 0; --i) {
                 *pBuf-- = padding_length;
             }
             /* now, if contentLen is not a multiple of block size, fix it */
             p2Len = fragLen - p1Len;
         }
         if (p1Len < 256) {
             oddLen = p1Len;
             p1Len = 0;
         } else {
             p1Len -= oddLen;
         }
         if (oddLen) {
             p2Len += oddLen;
             PORT_Assert((cipher_def->block_size < 2) ||
                         (p2Len % cipher_def->block_size) == 0);
-            memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len,
-                    oddLen);
+            memmove(wrBuf->buf + ivLen + p1Len, pIn + p1Len, oddLen);
         }
         if (p1Len > 0) {
             int cipherBytesPart1 = -1;
             rv = cwSpec->encode(cwSpec->encodeContext,
-                                wrBuf->buf + headerLen + ivLen, /* output */
-                                &cipherBytesPart1,              /* actual outlen */
-                                p1Len,                          /* max outlen */
+                                wrBuf->buf + ivLen, /* output */
+                                &cipherBytesPart1,  /* actual outlen */
+                                p1Len,              /* max outlen */
                                 pIn,
                                 p1Len); /* input, and inputlen */
             PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int)p1Len);
             if (rv != SECSuccess || cipherBytesPart1 != (int)p1Len) {
                 PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
                 return SECFailure;
             }
-            cipherBytes += cipherBytesPart1;
+            wrBuf->len += cipherBytesPart1;
         }
         if (p2Len > 0) {
             int cipherBytesPart2 = -1;
             rv = cwSpec->encode(cwSpec->encodeContext,
-                                wrBuf->buf + headerLen + ivLen + p1Len,
+                                wrBuf->buf + ivLen + p1Len,
                                 &cipherBytesPart2, /* output and actual outLen */
                                 p2Len,             /* max outlen */
-                                wrBuf->buf + headerLen + ivLen + p1Len,
+                                wrBuf->buf + ivLen + p1Len,
                                 p2Len); /* input and inputLen*/
             PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int)p2Len);
             if (rv != SECSuccess || cipherBytesPart2 != (int)p2Len) {
                 PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
                 return SECFailure;
             }
-            cipherBytes += cipherBytesPart2;
-        }
-    }
-
-    PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024);
-
-    wrBuf->len = cipherBytes + headerLen;
-    b = &wrBuf->buf[0];
-    b = ssl_EncodeUintX(type, 1, b);
-    if (isDTLS) {
-        SSL3ProtocolVersion version;
-
-        version = dtls_TLSVersionToDTLSVersion(cwSpec->version);
-        b = ssl_EncodeUintX(version, 2, b);
-        b = ssl_EncodeUintX(cwSpec->write_seq_num, 8, b);
+            wrBuf->len += cipherBytesPart2;
+        }
+    }
+
+    return SECSuccess;
+}
+
+SECStatus
+ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec,
+                  PRBool capRecordVersion, SSL3ContentType type,
+                  const SSL3Opaque *pIn, PRUint32 contentLen, sslBuffer *wrBuf)
+{
+    const ssl3BulkCipherDef *cipher_def = cwSpec->cipher_def;
+    PRUint16 headerLen = IS_DTLS(ss) ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH;
+    sslBuffer protBuf = { wrBuf->buf + headerLen, 0, wrBuf->space - headerLen };
+    SSL3ProtocolVersion version = cwSpec->version;
+    PRBool isTLS13;
+    SECStatus rv;
+
+    PORT_Assert(cipher_def->max_records <= RECORD_SEQ_MAX);
+    if ((cwSpec->write_seq_num & RECORD_SEQ_MAX) >= cipher_def->max_records) {
+        SSL_TRC(3, ("%d: SSL[-]: write sequence number at limit 0x%0llx",
+                    SSL_GETPID(), cwSpec->write_seq_num));
+        PORT_SetError(SSL_ERROR_TOO_MANY_RECORDS);
+        return SECFailure;
+    }
+
+    isTLS13 = (PRBool)(cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+
+    if (isTLS13) {
+        rv = tls13_ProtectRecord(ss, cwSpec, type, pIn, contentLen, &protBuf);
     } else {
-        SSL3ProtocolVersion version = cwSpec->version;
-
-        if (capRecordVersion || version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+        rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer,
+                                           IS_DTLS(ss), capRecordVersion, type,
+                                           pIn, contentLen, &protBuf);
+    }
+    if (rv != SECSuccess) {
+        return SECFailure; /* error was set */
+    }
+
+    PORT_Assert(protBuf.len <= MAX_FRAGMENT_LENGTH + (isTLS13 ? 256 : 1024));
+    wrBuf->len = protBuf.len + headerLen;
+
+    if (isTLS13 && cipher_def->calg != ssl_calg_null) {
+        wrBuf->buf[0] = content_application_data;
+    } else {
+        wrBuf->buf[0] = type;
+    }
+
+    if (IS_DTLS(ss)) {
+        version = isTLS13 ? SSL_LIBRARY_VERSION_TLS_1_1 : version;
+        version = dtls_TLSVersionToDTLSVersion(version);
+
+        (void)ssl_EncodeUintX(version, 2, &wrBuf->buf[1]);
+        (void)ssl_EncodeUintX(cwSpec->write_seq_num, 8, &wrBuf->buf[3]);
+        (void)ssl_EncodeUintX(protBuf.len, 2, &wrBuf->buf[11]);
+    } else {
+        if (capRecordVersion || isTLS13) {
             version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version);
         }
 
-        b = ssl_EncodeUintX(version, 2, b);
-    }
-    (void)ssl_EncodeUintX(cipherBytes, 2, b);
-
+        (void)ssl_EncodeUintX(version, 2, &wrBuf->buf[1]);
+        (void)ssl_EncodeUintX(protBuf.len, 2, &wrBuf->buf[3]);
+    }
     ++cwSpec->write_seq_num;
 
     return SECSuccess;
 }
 
 /* Process the plain text before sending it.
  * Returns the number of bytes of plaintext that were successfully sent
  *  plus the number of bytes of plaintext that were copied into the
@@ -2728,65 +2747,48 @@ ssl3_SendRecord(sslSocket *ss,
                 SSL_DBG(("%d: SSL3[%d]: SendRecord, tried to get %d bytes",
                          SSL_GETPID(), ss->fd, spaceNeeded));
                 goto spec_locked_loser; /* sslBuffer_Grow set error code. */
             }
         }
 
         if (numRecords == 2) {
             sslBuffer secondRecord;
-            rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
-                                               ss->sec.isServer, IS_DTLS(ss),
-                                               capRecordVersion, type, pIn,
-                                               1, wrBuf);
+            rv = ssl_ProtectRecord(ss, ss->ssl3.cwSpec, capRecordVersion, type,
+                                   pIn, 1, wrBuf);
             if (rv != SECSuccess)
                 goto spec_locked_loser;
 
             PRINT_BUF(50, (ss, "send (encrypted) record data [1/2]:",
                            wrBuf->buf, wrBuf->len));
 
             secondRecord.buf = wrBuf->buf + wrBuf->len;
             secondRecord.len = 0;
             secondRecord.space = wrBuf->space - wrBuf->len;
 
-            rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
-                                               ss->sec.isServer, IS_DTLS(ss),
-                                               capRecordVersion, type,
-                                               pIn + 1,
-                                               contentLen - 1,
-                                               &secondRecord);
+            rv = ssl_ProtectRecord(ss, ss->ssl3.cwSpec, capRecordVersion, type,
+                                   pIn + 1, contentLen - 1, &secondRecord);
             if (rv == SECSuccess) {
                 PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:",
                                secondRecord.buf, secondRecord.len));
                 wrBuf->len += secondRecord.len;
             }
         } else {
-            if (!IS_DTLS(ss)) {
+            if (cwSpec) {
                 /* cwSpec can only be set for retransmissions of DTLS handshake
                  * messages. */
-                PORT_Assert(!cwSpec);
-                if (ss->ssl3.cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_3) {
-                    rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
-                                                       ss->sec.isServer,
-                                                       PR_FALSE,
-                                                       capRecordVersion,
-                                                       type, pIn,
-                                                       contentLen, wrBuf);
-                } else {
-                    rv = tls13_ProtectRecord(ss, ss->ssl3.cwSpec, type, pIn,
-                                             contentLen, wrBuf);
-                }
+                PORT_Assert(IS_DTLS(ss) &&
+                            (type == content_handshake ||
+                             type == content_change_cipher_spec));
             } else {
-                /* TLS <= 1.2 and TLS 1.3 cases are both handled in
-                 * dtls_CompressMACEncryptRecord. */
-                rv = dtls_CompressMACEncryptRecord(ss, cwSpec,
-                                                   type, pIn,
-                                                   contentLen, wrBuf);
-            }
-
+                cwSpec = ss->ssl3.cwSpec;
+            }
+
+            rv = ssl_ProtectRecord(ss, cwSpec, !IS_DTLS(ss) && capRecordVersion,
+                                   type, pIn, contentLen, wrBuf);
             if (rv == SECSuccess) {
                 PRINT_BUF(50, (ss, "send (encrypted) record data:",
                                wrBuf->buf, wrBuf->len));
             }
         }
 
     spec_locked_loser:
         ssl_ReleaseSpecReadLock(ss); /************************************/
@@ -3025,27 +3027,19 @@ ssl3_FlushHandshakeMessages(sslSocket *s
 }
 
 /*
  * Called from ssl3_HandleAlert and from ssl3_HandleCertificate when
  * the remote client sends a negative response to our certificate request.
  * Returns SECFailure if the application has required client auth.
  *         SECSuccess otherwise.
  */
-static SECStatus
+SECStatus
 ssl3_HandleNoCertificate(sslSocket *ss)
 {
-    if (ss->sec.peerCert != NULL) {
-        if (ss->sec.peerKey != NULL) {
-            SECKEY_DestroyPublicKey(ss->sec.peerKey);
-            ss->sec.peerKey = NULL;
-        }
-        CERT_DestroyCertificate(ss->sec.peerCert);
-        ss->sec.peerCert = NULL;
-    }
     ssl3_CleanupPeerCerts(ss);
 
     /* If the server has required client-auth blindly but doesn't
      * actually look at the certificate it won't know that no
      * certificate was presented so we shutdown the socket to ensure
      * an error.  We only do this if we haven't already completed the
      * first handshake because if we're redoing the handshake we
      * know the server is paying attention to the certificate.
@@ -3150,17 +3144,17 @@ static SECStatus
 ssl3_HandshakeFailure(sslSocket *ss)
 {
     (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
     PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
                                    : SSL_ERROR_BAD_SERVER);
     return SECFailure;
 }
 
-static void
+void
 ssl3_SendAlertForCertError(sslSocket *ss, PRErrorCode errCode)
 {
     SSL3AlertDescription desc = bad_certificate;
     PRBool isTLS = ss->version >= SSL_LIBRARY_VERSION_3_1_TLS;
 
     switch (errCode) {
         case SEC_ERROR_LIBRARY_FAILURE:
             desc = unsupported_certificate;
@@ -3979,18 +3973,19 @@ loser:
     if (symKey)
         PK11_FreeSymKey(symKey);
     ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
     return SECFailure;
 }
 
 /* ssl3_InitHandshakeHashes creates handshake hash contexts and hashes in
  * buffered messages in ss->ssl3.hs.messages. Called from
- * ssl3_NegotiateCipherSuite() and ssl3_HandleServerHello. */
-static SECStatus
+ * ssl3_NegotiateCipherSuite(), tls13_HandleClientHelloPart2(),
+ * and ssl3_HandleServerHello. */
+SECStatus
 ssl3_InitHandshakeHashes(sslSocket *ss)
 {
     SSL_TRC(30, ("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_unknown);
     if (ss->version == SSL_LIBRARY_VERSION_TLS_1_2) {
         ss->ssl3.hs.hashType = handshake_hash_record;
     } else {
@@ -4965,16 +4960,17 @@ ssl3_SendClientHello(sslSocket *ss, sslC
     int num_suites;
     int actual_count = 0;
     PRBool isTLS = PR_FALSE;
     PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE;
     PRInt32 total_exten_len = 0;
     unsigned paddingExtensionLen;
     unsigned numCompressionMethods;
     PRUint16 version;
+    PRInt32 flags;
 
     SSL_TRC(3, ("%d: SSL3[%d]: send %s ClientHello handshake", SSL_GETPID(),
                 ss->fd, ssl_ClientHelloTypeName(type)));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     /* shouldn't get here if SSL3 is disabled, but ... */
@@ -5204,20 +5200,19 @@ ssl3_SendClientHello(sslSocket *ss, sslC
     if (sid->u.ssl3.lock) {
         PR_RWLock_Rlock(sid->u.ssl3.lock);
     }
 
     if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3 &&
         type == client_hello_initial) {
         rv = tls13_SetupClientHello(ss);
         if (rv != SECSuccess) {
-            return rv;
-        }
-    }
-
+            return SECFailure;
+        }
+    }
     if (isTLS || (ss->firstHsDone && ss->peerRequestedProtection)) {
         PRUint32 maxBytes = 65535; /* 2^16 - 1 */
         PRInt32 extLen;
 
         extLen = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, maxBytes, NULL);
         if (extLen < 0) {
             if (sid->u.ssl3.lock) {
                 PR_RWLock_Unlock(sid->u.ssl3.lock);
@@ -5448,26 +5443,26 @@ ssl3_SendClientHello(sslSocket *ss, sslC
         rv = ssl3_AppendHandshakeNumber(ss, maxBytes, 2);
         if (rv != SECSuccess) {
             if (sid->u.ssl3.lock) {
                 PR_RWLock_Unlock(sid->u.ssl3.lock);
             }
             return rv; /* err set by AppendHandshake. */
         }
 
-        extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, maxBytes, NULL);
+        extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
         if (extLen < 0) {
             if (sid->u.ssl3.lock) {
                 PR_RWLock_Unlock(sid->u.ssl3.lock);
             }
             return SECFailure;
         }
         maxBytes -= extLen;
 
-        extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
+        extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, maxBytes, NULL);
         if (extLen < 0) {
             if (sid->u.ssl3.lock) {
                 PR_RWLock_Unlock(sid->u.ssl3.lock);
             }
             return SECFailure;
         }
         maxBytes -= extLen;
 
@@ -5484,48 +5479,32 @@ ssl3_SendClientHello(sslSocket *ss, sslC
 
     if (ss->ssl3.hs.sendingSCSV) {
         /* Since we sent the SCSV, pretend we sent empty RI extension. */
         TLSExtensionData *xtnData = &ss->xtnData;
         xtnData->advertised[xtnData->numAdvertised++] =
             ssl_renegotiation_info_xtn;
     }
 
+    flags = 0;
+    if (!ss->firstHsDone && !IS_DTLS(ss)) {
+        flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION;
+    }
+    rv = ssl3_FlushHandshake(ss, flags);
+    if (rv != SECSuccess) {
+        return rv; /* error code set by ssl3_FlushHandshake */
+    }
+
     if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
         rv = tls13_MaybeDo0RTTHandshake(ss);
         if (rv != SECSuccess) {
             return SECFailure; /* error code set already. */
         }
     }
 
-    /* On TLS (but not DTLS), if we sent 0-RTT, then we will have data in the
-     * pending buffer. This just pushes a little of that out.  If we didn't do
-     * that, we wouldn't send a ClientHello the first time and applications
-     * would have to push SSL_ForceHandshake() twice. This should go away once
-     * we have Finished stuffed in the ClientHello. */
-    if (!IS_DTLS(ss) && ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) {
-        int sent;
-
-        PORT_Assert(version >= SSL_LIBRARY_VERSION_TLS_1_3);
-        PORT_Assert(ss->pendingBuf.len);
-        sent = ssl_SendSavedWriteData(ss);
-        if (sent < 0) {
-            return SECFailure;
-        }
-    } else {
-        PRInt32 flags = 0;
-        if (!ss->firstHsDone && !IS_DTLS(ss)) {
-            flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION;
-        }
-        rv = ssl3_FlushHandshake(ss, flags);
-        if (rv != SECSuccess) {
-            return rv; /* error code set by ssl3_FlushHandshake */
-        }
-    }
-
     ss->ssl3.hs.ws = wait_server_hello;
     return SECSuccess;
 }
 
 /* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered a
  * complete ssl3 Hello Request.
  * Caller must hold Handshake and RecvBuf locks.
  */
@@ -6822,17 +6801,16 @@ ssl3_HandleServerHello(sslSocket *ss, SS
 
     return SECSuccess;
 
 alert_loser:
     (void)SSL3_SendAlert(ss, alert_fatal, desc);
 
 loser:
     /* Clean up the temporary pointer to the handshake buffer. */
-    ss->xtnData.signedCertTimestamps.data = NULL;
     ss->xtnData.signedCertTimestamps.len = 0;
     ssl_MapLowLevelError(errCode);
     return SECFailure;
 }
 
 static SECStatus
 ssl3_HandleServerHelloPart2(sslSocket *ss, const SECItem *sidBytes,
                             int *retErrCode)
@@ -7021,24 +6999,22 @@ ssl3_HandleServerHelloPart2(sslSocket *s
     if (sidBytes->len > 0) {
         PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes->data, sidBytes->len);
     }
 
     sid->u.ssl3.keys.extendedMasterSecretUsed =
         ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn);
 
     /* Copy Signed Certificate Timestamps, if any. */
-    if (ss->xtnData.signedCertTimestamps.data) {
+    if (ss->xtnData.signedCertTimestamps.len) {
         rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.signedCertTimestamps,
                               &ss->xtnData.signedCertTimestamps);
+        ss->xtnData.signedCertTimestamps.len = 0;
         if (rv != SECSuccess)
             goto loser;
-        /* Clean up the temporary pointer to the handshake buffer. */
-        ss->xtnData.signedCertTimestamps.data = NULL;
-        ss->xtnData.signedCertTimestamps.len = 0;
     }
 
     ss->ssl3.hs.isResuming = PR_FALSE;
     if (ss->ssl3.hs.kea_def->authKeyType != ssl_auth_null) {
         /* All current cipher suites other than those with ssl_auth_null (i.e.,
          * (EC)DH_anon_* suites) require a certificate, so use that signal. */
         ss->ssl3.hs.ws = wait_server_cert;
     } else {
@@ -7386,17 +7362,19 @@ ssl_ParseSignatureSchemes(const sslSocke
             return SECFailure;
         }
         if (ssl_IsSupportedSignatureScheme((SSLSignatureScheme)tmp)) {
             schemes[numSchemes++] = (SSLSignatureScheme)tmp;
         }
     }
 
     if (!numSchemes) {
-        PORT_Free(schemes);
+        if (!arena) {
+            PORT_Free(schemes);
+        }
         schemes = NULL;
     }
 
     *schemesOut = schemes;
     *numSchemesOut = numSchemes;
     return SECSuccess;
 }
 
@@ -10346,17 +10324,17 @@ loser:
     return SECFailure;
 }
 #endif
 
 /*
  * Used by both client and server.
  * Called from HandleServerHelloDone and from SendServerHelloSequence.
  */
-SECStatus
+static SECStatus
 ssl3_SendCertificate(sslSocket *ss)
 {
     SECStatus rv;
     CERTCertificateList *certChain;
     int certChainLen = 0;
     int i;
 #ifdef NISCC_TEST
     SECItem fakeCert;
@@ -10502,29 +10480,38 @@ ssl3_SendCertificateStatus(sslSocket *ss
         return rv; /* err set by AppendHandshake. */
 
     return SECSuccess;
 }
 
 /* This is used to delete the CA certificates in the peer certificate chain
  * from the cert database after they've been validated.
  */
-static void
+void
 ssl3_CleanupPeerCerts(sslSocket *ss)
 {
     PLArenaPool *arena = ss->ssl3.peerCertArena;
     ssl3CertNode *certs = (ssl3CertNode *)ss->ssl3.peerCertChain;
 
     for (; certs; certs = certs->next) {
         CERT_DestroyCertificate(certs->cert);
     }
     if (arena)
         PORT_FreeArena(arena, PR_FALSE);
     ss->ssl3.peerCertArena = NULL;
     ss->ssl3.peerCertChain = NULL;
+
+    if (ss->sec.peerCert != NULL) {
+        if (ss->sec.peerKey) {
+            SECKEY_DestroyPublicKey(ss->sec.peerKey);
+            ss->sec.peerKey = NULL;
+        }
+        CERT_DestroyCertificate(ss->sec.peerCert);
+        ss->sec.peerCert = NULL;
+    }
 }
 
 /* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered
  * a complete ssl3 CertificateStatus message.
  * Caller must hold Handshake and RecvBuf locks.
  */
 static SECStatus
 ssl3_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
@@ -10623,25 +10610,16 @@ ssl3_CompleteHandleCertificate(sslSocket
     PRInt32 size;
     SECStatus rv;
     PRBool isServer = ss->sec.isServer;
     PRBool isTLS;
     SSL3AlertDescription desc;
     int errCode = SSL_ERROR_RX_MALFORMED_CERTIFICATE;
     SECItem certItem;
 
-    if (ss->sec.peerCert != NULL) {
-        if (ss->sec.peerKey) {
-            SECKEY_DestroyPublicKey(ss->sec.peerKey);
-            ss->sec.peerKey = NULL;
-        }
-        CERT_DestroyCertificate(ss->sec.peerCert);
-        ss->sec.peerCert = NULL;
-    }
-
     ssl3_CleanupPeerCerts(ss);
     isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
 
     /* It is reported that some TLS client sends a Certificate message
     ** with a zero-length message body.  We'll treat that case like a
     ** normal no_certificates message to maximize interoperability.
     */
     if (length) {
@@ -10781,17 +10759,17 @@ decode_loser:
 alert_loser:
     (void)SSL3_SendAlert(ss, alert_fatal, desc);
 
 loser:
     (void)ssl_MapLowLevelError(errCode);
     return SECFailure;
 }
 
-static SECStatus
+SECStatus
 ssl3_AuthCertificate(sslSocket *ss)
 {
     SECStatus rv;
     PRBool isServer = ss->sec.isServer;
     int errCode;
 
     ss->ssl3.hs.authCertificatePending = PR_FALSE;
 
@@ -11673,18 +11651,17 @@ ssl3_HandleHandshakeMessage(sslSocket *s
                 computeHashes = PR_TRUE;
             }
         }
     } else {
         if (type == certificate_verify) {
             computeHashes = TLS13_IN_HS_STATE(ss, wait_cert_verify);
         } else if (type == finished) {
             computeHashes =
-                TLS13_IN_HS_STATE(ss, wait_cert_request, wait_finished,
-                                  wait_0rtt_finished);
+                TLS13_IN_HS_STATE(ss, wait_cert_request, wait_finished);
         }
     }
 
     ssl_GetSpecReadLock(ss); /************************************/
     if (computeHashes) {
         SSL3Sender sender = (SSL3Sender)0;
         ssl3CipherSpec *rSpec = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 ? ss->ssl3.crSpec
                                                                            : ss->ssl3.prSpec;
@@ -12498,17 +12475,17 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Cip
 {
     SECStatus rv;
     PRBool isTLS;
     sslSequenceNumber seq_num = 0;
     ssl3CipherSpec *crSpec;
     SSL3ContentType rType;
     sslBuffer *plaintext;
     sslBuffer temp_buf;
-    SSL3AlertDescription alert;
+    SSL3AlertDescription alert = internal_error;
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
 
     if (!ss->ssl3.initialized) {
         ssl_GetSSL3HandshakeLock(ss);
         rv = ssl3_InitState(ss);
         ssl_ReleaseSSL3HandshakeLock(ss);
         if (rv != SECSuccess) {
             return rv; /* ssl3_InitState has set the error code. */
@@ -12826,17 +12803,16 @@ ssl3_InitCipherSpec(ssl3CipherSpec *spec
 **
 ** This function should perhaps acquire and release the SpecWriteLock.
 **
 **
 */
 SECStatus
 ssl3_InitState(sslSocket *ss)
 {
-    SECItem nullItem = { siBuffer, NULL, 0 };
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     if (ss->ssl3.initialized)
         return SECSuccess; /* Function should be idempotent */
 
     ss->ssl3.policy = SSL_ALLOWED;
 
     ssl_InitSecState(&ss->sec);
@@ -12860,21 +12836,20 @@ ssl3_InitState(sslSocket *ss)
         ss->ssl3.hs.recvMessageSeq = 0;
         ss->ssl3.hs.rtTimeoutMs = DTLS_RETRANSMIT_INITIAL_MS;
         ss->ssl3.hs.rtRetries = 0;
         ss->ssl3.hs.recvdHighWater = -1;
         PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight);
         dtls_SetMTU(ss, 0); /* Set the MTU to the highest plateau */
     }
 
-    ss->ssl3.hs.clientHelloHash = NULL;
     ss->ssl3.hs.currentSecret = NULL;
-    ss->ssl3.hs.resumptionPsk = NULL;
-    ss->ssl3.hs.resumptionContext = nullItem;
+    ss->ssl3.hs.resumptionMasterSecret = NULL;
     ss->ssl3.hs.dheSecret = NULL;
+    ss->ssl3.hs.pskBinderKey = NULL;
     ss->ssl3.hs.clientEarlyTrafficSecret = NULL;
     ss->ssl3.hs.clientHsTrafficSecret = NULL;
     ss->ssl3.hs.serverHsTrafficSecret = NULL;
     ss->ssl3.hs.clientTrafficSecret = NULL;
     ss->ssl3.hs.serverTrafficSecret = NULL;
     ss->ssl3.hs.certificateRequest = NULL;
     PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs);
 
@@ -13231,43 +13206,42 @@ ssl3_DestroySSL3Info(sslSocket *ss)
             PORT_Free(ss->ssl3.hs.recvdFragments.buf);
         }
     }
 
     /* Destroy remote extensions */
     ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions);
     ssl3_ResetExtensionData(&ss->xtnData);
 
-    /* Destroy the stored hash. */
-    if (ss->ssl3.hs.clientHelloHash) {
-        PK11_DestroyContext(ss->ssl3.hs.clientHelloHash, PR_TRUE);
-    }
-
     /* Destroy TLS 1.3 cipher specs */
     tls13_DestroyCipherSpecs(&ss->ssl3.hs.cipherSpecs);
 
     /* Destroy TLS 1.3 keys */
     if (ss->ssl3.hs.currentSecret)
         PK11_FreeSymKey(ss->ssl3.hs.currentSecret);
-    if (ss->ssl3.hs.resumptionPsk)
-        PK11_FreeSymKey(ss->ssl3.hs.resumptionPsk);
+    if (ss->ssl3.hs.resumptionMasterSecret)
+        PK11_FreeSymKey(ss->ssl3.hs.resumptionMasterSecret);
     if (ss->ssl3.hs.dheSecret)
         PK11_FreeSymKey(ss->ssl3.hs.dheSecret);
-    if (ss->ssl3.hs.resumptionContext.data)
-        SECITEM_FreeItem(&ss->ssl3.hs.resumptionContext, PR_FALSE);
+    if (ss->ssl3.hs.pskBinderKey)
+        PK11_FreeSymKey(ss->ssl3.hs.pskBinderKey);
     if (ss->ssl3.hs.clientEarlyTrafficSecret)
         PK11_FreeSymKey(ss->ssl3.hs.clientEarlyTrafficSecret);
     if (ss->ssl3.hs.clientHsTrafficSecret)
         PK11_FreeSymKey(ss->ssl3.hs.clientHsTrafficSecret);
     if (ss->ssl3.hs.serverHsTrafficSecret)
         PK11_FreeSymKey(ss->ssl3.hs.serverHsTrafficSecret);
     if (ss->ssl3.hs.clientTrafficSecret)
         PK11_FreeSymKey(ss->ssl3.hs.clientTrafficSecret);
     if (ss->ssl3.hs.serverTrafficSecret)
         PK11_FreeSymKey(ss->ssl3.hs.serverTrafficSecret);
+    if (ss->ssl3.hs.earlyExporterSecret)
+        PK11_FreeSymKey(ss->ssl3.hs.earlyExporterSecret);
+    if (ss->ssl3.hs.exporterSecret)
+        PK11_FreeSymKey(ss->ssl3.hs.exporterSecret);
 
     ss->ssl3.hs.zeroRttState = ssl_0rtt_none;
     /* Destroy TLS 1.3 buffered early data. */
     tls13_DestroyEarlyData(&ss->ssl3.hs.bufferedEarlyData);
 
     ss->ssl3.initialized = PR_FALSE;
 
     SECITEM_FreeItem(&ss->xtnData.nextProto, PR_FALSE);
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -32,16 +32,18 @@ static const ssl3ExtensionHandler client
     { ssl_use_srtp_xtn, &ssl3_ServerHandleUseSRTPXtn },
     { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn },
     { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn },
     { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
     { ssl_signed_cert_timestamp_xtn, &ssl3_ServerHandleSignedCertTimestampXtn },
     { ssl_tls13_key_share_xtn, &tls13_ServerHandleKeyShareXtn },
     { ssl_tls13_pre_shared_key_xtn, &tls13_ServerHandlePreSharedKeyXtn },
     { ssl_tls13_early_data_xtn, &tls13_ServerHandleEarlyDataXtn },
+    { ssl_tls13_psk_key_exchange_modes_xtn,
+      &tls13_ServerHandlePskKeyExchangeModesXtn },
     { -1, NULL }
 };
 
 /* These two tables are used by the client, to handle server hello
  * extensions. */
 static const ssl3ExtensionHandler serverHelloHandlersTLS[] = {
     { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
     /* TODO: add a handler for ssl_ec_point_formats_xtn */
@@ -51,17 +53,16 @@ static const ssl3ExtensionHandler server
     { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
     { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn },
     { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
     { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
     { ssl_signed_cert_timestamp_xtn, &ssl3_ClientHandleSignedCertTimestampXtn },
     { ssl_tls13_key_share_xtn, &tls13_ClientHandleKeyShareXtn },
     { ssl_tls13_pre_shared_key_xtn, &tls13_ClientHandlePreSharedKeyXtn },
     { ssl_tls13_early_data_xtn, &tls13_ClientHandleEarlyDataXtn },
-    { ssl_signature_algorithms_xtn, &tls13_ClientHandleSigAlgsXtn },
     { -1, NULL }
 };
 
 static const ssl3ExtensionHandler helloRetryRequestHandlers[] = {
     { ssl_tls13_key_share_xtn, tls13_ClientHandleKeyShareXtnHrr },
     { ssl_tls13_cookie_xtn, tls13_ClientHandleHrrCookie },
     { -1, NULL }
 };
@@ -72,16 +73,23 @@ static const ssl3ExtensionHandler server
 };
 
 static const ssl3ExtensionHandler newSessionTicketHandlers[] = {
     { ssl_tls13_ticket_early_data_info_xtn,
       &tls13_ClientHandleTicketEarlyDataInfoXtn },
     { -1, NULL }
 };
 
+/* This table is used by the client to handle server certificates in TLS 1.3 */
+static const ssl3ExtensionHandler serverCertificateHandlers[] = {
+    { ssl_signed_cert_timestamp_xtn, &ssl3_ClientHandleSignedCertTimestampXtn },
+    { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
+    { -1, NULL }
+};
+
 /* Tables of functions to format TLS hello extensions, one function per
  * extension.
  * These static tables are for the formatting of client hello extensions.
  * The server's table of hello senders is dynamic, in the socket struct,
  * and sender functions are registered there.
  * NB: the order of these extensions can have an impact on compatibility. Some
  * servers (e.g. Tomcat) will terminate the connection if the last extension in
  * the client hello is empty (for example, the extended master secret
@@ -96,25 +104,28 @@ static const ssl3HelloExtensionSender cl
       { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
       { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
       { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn },
       { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn },
       { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn },
       { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
       { ssl_signed_cert_timestamp_xtn, &ssl3_ClientSendSignedCertTimestampXtn },
       { ssl_tls13_key_share_xtn, &tls13_ClientSendKeyShareXtn },
-      { ssl_tls13_pre_shared_key_xtn, &tls13_ClientSendPreSharedKeyXtn },
       { ssl_tls13_early_data_xtn, &tls13_ClientSendEarlyDataXtn },
       /* Some servers (e.g. WebSphere Application Server 7.0 and Tomcat) will
        * time out or terminate the connection if the last extension in the
        * client hello is empty. They are not intolerant of TLS 1.2, so list
        * signature_algorithms at the end. See bug 1243641. */
       { ssl_tls13_supported_versions_xtn, &tls13_ClientSendSupportedVersionsXtn },
       { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
-      { ssl_tls13_cookie_xtn, &tls13_ClientSendHrrCookieXtn }
+      { ssl_tls13_cookie_xtn, &tls13_ClientSendHrrCookieXtn },
+      { ssl_tls13_psk_key_exchange_modes_xtn,
+        &tls13_ClientSendPskKeyExchangeModesXtn },
+      /* The pre_shared_key extension MUST be last. */
+      { ssl_tls13_pre_shared_key_xtn, &tls13_ClientSendPreSharedKeyXtn },
       /* any extra entries will appear as { 0, NULL }    */
     };
 
 static const ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = {
     { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }
     /* any extra entries will appear as { 0, NULL }    */
 };
 
@@ -166,16 +177,18 @@ ssl3_ParseExtensions(sslSocket *ss, SSL3
         PRCList *cursor;
 
         /* Get the extension's type field */
         extension_type = ssl3_ConsumeHandshakeNumber(ss, 2, b, length);
         if (extension_type < 0) { /* failure to decode extension_type */
             return SECFailure;    /* alert already sent */
         }
 
+        SSL_TRC(10, ("%d: SSL3[%d]: parsing extension %d",
+                     SSL_GETPID(), ss->fd, extension_type));
         /* Check whether an extension has been sent multiple times. */
         for (cursor = PR_NEXT_LINK(&ss->ssl3.hs.remoteExtensions);
              cursor != &ss->ssl3.hs.remoteExtensions;
              cursor = PR_NEXT_LINK(cursor)) {
             if (((TLSExtension *)cursor)->type == extension_type) {
                 (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
                 PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION);
                 return SECFailure;
@@ -252,16 +265,20 @@ ssl3_HandleParsedExtensions(sslSocket *s
         /* fall through */
         case server_hello:
             if (ss->version > SSL_LIBRARY_VERSION_3_0) {
                 handlers = serverHelloHandlersTLS;
             } else {
                 handlers = serverHelloHandlersSSL3;
             }
             break;
+        case certificate:
+            PORT_Assert(!ss->sec.isServer);
+            handlers = serverCertificateHandlers;
+            break;
         default:
             PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
             PORT_Assert(0);
             return SECFailure;
     }
 
     for (cursor = PR_NEXT_LINK(&ss->ssl3.hs.remoteExtensions);
          cursor != &ss->ssl3.hs.remoteExtensions;
@@ -286,16 +303,27 @@ ssl3_HandleParsedExtensions(sslSocket *s
                 /* Skip extensions not used in TLS 1.3 */
                 continue;
             }
             tls13_FatalError(ss, SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION,
                              unsupported_extension);
             return SECFailure;
         }
 
+        /* Special check for this being the last extension if it's
+         * PreSharedKey */
+        if (ss->sec.isServer && isTLS13 &&
+            (extension->type == ssl_tls13_pre_shared_key_xtn) &&
+            (PR_NEXT_LINK(cursor) != &ss->ssl3.hs.remoteExtensions)) {
+            tls13_FatalError(ss,
+                             SSL_ERROR_RX_MALFORMED_CLIENT_HELLO,
+                             illegal_parameter);
+            return SECFailure;
+        }
+
         /* find extension_type in table of Hello Extension Handlers */
         for (handler = handlers; handler->ex_type >= 0; handler++) {
             /* if found, call this handler */
             if (handler->ex_type == extension->type) {
                 SECStatus rv;
 
                 rv = (*handler->ex_handler)(ss, &ss->xtnData,
                                             (PRUint16)extension->type,
@@ -345,22 +373,23 @@ ssl3_RegisterExtensionSender(const sslSo
     int i;
     ssl3HelloExtensionSender *sender;
     if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
         sender = &xtnData->serverHelloSenders[0];
     } else {
         if (tls13_ExtensionAllowed(ex_type, server_hello)) {
             PORT_Assert(!tls13_ExtensionAllowed(ex_type, encrypted_extensions));
             sender = &xtnData->serverHelloSenders[0];
+        } else if (tls13_ExtensionAllowed(ex_type, certificate)) {
+            sender = &xtnData->certificateSenders[0];
         } else {
             PORT_Assert(tls13_ExtensionAllowed(ex_type, encrypted_extensions));
             sender = &xtnData->encryptedExtensionsSenders[0];
         }
     }
-
     for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) {
         if (!sender->ex_sender) {
             sender->ex_type = ex_type;
             sender->ex_sender = cb;
             return SECSuccess;
         }
         /* detect duplicate senders */
         PORT_Assert(sender->ex_type != ex_type);
--- a/security/nss/lib/ssl/ssl3ext.h
+++ b/security/nss/lib/ssl/ssl3ext.h
@@ -41,31 +41,30 @@ typedef struct {
     PRInt32 ex_type;
     ssl3ExtensionHandlerFunc ex_handler;
 } ssl3ExtensionHandler;
 
 struct TLSExtensionDataStr {
     /* registered callbacks that send server hello extensions */
     ssl3HelloExtensionSender serverHelloSenders[SSL_MAX_EXTENSIONS];
     ssl3HelloExtensionSender encryptedExtensionsSenders[SSL_MAX_EXTENSIONS];
+    ssl3HelloExtensionSender certificateSenders[SSL_MAX_EXTENSIONS];
 
     /* Keep track of the extensions that are negotiated. */
     PRUint16 numAdvertised;
     PRUint16 numNegotiated;
     PRUint16 advertised[SSL_MAX_EXTENSIONS];
     PRUint16 negotiated[SSL_MAX_EXTENSIONS];
 
     /* SessionTicket Extension related data. */
     PRBool ticketTimestampVerified;
     PRBool emptySessionTicket;
     PRBool sentSessionTicketInClientHello;
     SECItem psk_ke_modes;
-    SECItem psk_auth_modes;
-    PRUint32 ticket_age_add;
-    PRBool ticket_age_add_found;
+    PRUint32 max_early_data_size;
 
     /* SNI Extension related data
      * Names data is not coppied from the input buffer. It can not be
      * used outside the scope where input buffer is defined and that
      * is beyond ssl3_HandleClientHello function. */
     SECItem *sniNameArr;
     PRUint32 sniNameArrSize;
 
@@ -92,17 +91,19 @@ struct TLSExtensionDataStr {
     /* In a client: if the server supports Next Protocol Negotiation, then
      * this is the protocol that was negotiated.
      */
     SECItem nextProto;
     SSLNextProtoState nextProtoState;
 
     PRUint16 dtlsSRTPCipherSuite; /* 0 if not selected */
 
-    PRCList remoteKeyShares; /* The other side's public keys (TLS 1.3) */
+    SECItem pskBinder;                /* The PSK binder for the first PSK (TLS 1.3) */
+    unsigned long pskBinderPrefixLen; /* The length of the binder input. */
+    PRCList remoteKeyShares;          /* The other side's public keys (TLS 1.3) */
 };
 
 typedef struct TLSExtensionStr {
     PRCList link;  /* The linked list link */
     PRUint16 type; /* Extension type */
     SECItem data;  /* Pointers into the handshake data. */
 } TLSExtension;
 
--- a/security/nss/lib/ssl/ssl3exthandle.c
+++ b/security/nss/lib/ssl/ssl3exthandle.c
@@ -2421,28 +2421,27 @@ ssl3_ServerSendSignedCertTimestampXtn(co
         return 0;
     }
     if (append) {
         SECStatus rv;
         /* extension_type */
         rv = ssl3_ExtAppendHandshakeNumber(ss,
                                            ssl_signed_cert_timestamp_xtn,
                                            2);
-        if (rv != SECSuccess)
-            goto loser;
+        if (rv != SECSuccess) {
+            return -1;
+        }
         /* extension_data */
         rv = ssl3_ExtAppendHandshakeVariable(ss, scts->data, scts->len, 2);
-        if (rv != SECSuccess)
-            goto loser;
+        if (rv != SECSuccess) {
+            return -1;
+        }
     }
 
     return extension_length;
-
-loser:
-    return -1;
 }
 
 SECStatus
 ssl3_ServerHandleSignedCertTimestampXtn(const sslSocket *ss,
                                         TLSExtensionData *xtnData,
                                         PRUint16 ex_type,
                                         SECItem *data)
 {
--- a/security/nss/lib/ssl/ssl3prot.h
+++ b/security/nss/lib/ssl/ssl3prot.h
@@ -13,17 +13,17 @@
 typedef PRUint8 SSL3Opaque;
 
 typedef PRUint16 SSL3ProtocolVersion;
 /* version numbers are defined in sslproto.h */
 
 /* The TLS 1.3 draft version. Used to avoid negotiating
  * between incompatible pre-standard TLS 1.3 drafts.
  * TODO(ekr@rtfm.com): Remove when TLS 1.3 is published. */
-#define TLS_1_3_DRAFT_VERSION 16
+#define TLS_1_3_DRAFT_VERSION 18
 
 typedef PRUint16 ssl3CipherSuite;
 /* The cipher suites are defined in sslproto.h */
 
 #define MAX_CERT_TYPES 10
 #define MAX_COMPRESSION_METHODS 10
 #define MAX_MAC_LENGTH 64
 #define MAX_PADDING_LENGTH 64
@@ -283,30 +283,26 @@ typedef struct {
 /* SessionTicket extension related data structures. */
 
 /* NewSessionTicket handshake message. */
 typedef struct {
     PRUint32 received_timestamp;
     PRUint32 ticket_lifetime_hint;
     PRUint32 flags;
     PRUint32 ticket_age_add;
+    PRUint32 max_early_data_size;
     SECItem ticket;
 } NewSessionTicket;
 
 typedef enum {
     tls13_psk_ke = 0,
     tls13_psk_dh_ke = 1
 } TLS13PskKEModes;
 
 typedef enum {
-    tls13_psk_auth = 0,
-    tls13_psk_sign_auth = 1
-} TLS13PskAuthModes;
-
-typedef enum {
     CLIENT_AUTH_ANONYMOUS = 0,
     CLIENT_AUTH_CERTIFICATE = 1
 } ClientAuthenticationType;
 
 typedef struct {
     ClientAuthenticationType client_auth_type;
     union {
         SSL3Opaque *certificate_list;
--- a/security/nss/lib/ssl/sslcert.c
+++ b/security/nss/lib/ssl/sslcert.c
@@ -269,17 +269,17 @@ ssl_PopulateOCSPResponses(sslServerCert 
 
 static SECStatus
 ssl_PopulateSignedCertTimestamps(sslServerCert *sc,
                                  const SECItem *signedCertTimestamps)
 {
     if (sc->signedCertTimestamps.len) {
         SECITEM_FreeItem(&sc->signedCertTimestamps, PR_FALSE);
     }
-    if (signedCertTimestamps) {
+    if (signedCertTimestamps && signedCertTimestamps->len) {
         return SECITEM_CopyItem(NULL, &sc->signedCertTimestamps,
                                 signedCertTimestamps);
     }
     return SECSuccess;
 }
 
 static SECStatus
 ssl_ConfigCert(sslSocket *ss, CERTCertificate *cert,
--- a/security/nss/lib/ssl/sslerr.h
+++ b/security/nss/lib/ssl/sslerr.h
@@ -237,15 +237,17 @@ typedef enum {
     SSL_ERROR_MISSING_ALPN_EXTENSION = (SSL_ERROR_BASE + 150),
     SSL_ERROR_RX_UNEXPECTED_EXTENSION = (SSL_ERROR_BASE + 151),
     SSL_ERROR_MISSING_SUPPORTED_GROUPS_EXTENSION = (SSL_ERROR_BASE + 152),
     SSL_ERROR_TOO_MANY_RECORDS = (SSL_ERROR_BASE + 153),
     SSL_ERROR_RX_UNEXPECTED_HELLO_RETRY_REQUEST = (SSL_ERROR_BASE + 154),
     SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST = (SSL_ERROR_BASE + 155),
     SSL_ERROR_BAD_2ND_CLIENT_HELLO = (SSL_ERROR_BASE + 156),
     SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION = (SSL_ERROR_BASE + 157),
+    SSL_ERROR_MALFORMED_PSK_KEY_EXCHANGE_MODES = (SSL_ERROR_BASE + 158),
+    SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES = (SSL_ERROR_BASE + 159),
     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_ */