Bug 1283376 - Land NSS_3_26_BETA2 r=franziskus
authorTim Taubert <ttaubert@mozilla.com>
Tue, 12 Jul 2016 12:34:33 +0200
changeset 304636 d0da4f67c418464fa6daccf5c9cb2f08a9527e4a
parent 304635 940674ad1be3c211cc10d18666e3e4705e301f32
child 304637 00d2b3e1dde15ae2e42e2902f91b0a6d1141d001
push id79377
push userttaubert@mozilla.com
push dateTue, 12 Jul 2016 10:44:41 +0000
treeherdermozilla-inbound@d0da4f67c418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfranziskus
bugs1283376
milestone50.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 1283376 - Land NSS_3_26_BETA2 r=franziskus
security/nss/.taskcluster.yml
security/nss/TAG-INFO
security/nss/automation/taskcluster/graph/build.js
security/nss/automation/taskcluster/graph/linux/build32-debug.yml
security/nss/automation/taskcluster/graph/linux/build32-opt.yml
security/nss/automation/taskcluster/graph/linux/build64-asan.yml
security/nss/automation/taskcluster/graph/linux/build64-debug.yml
security/nss/automation/taskcluster/graph/linux/build64-lsan.yml
security/nss/automation/taskcluster/graph/linux/build64-opt.yml
security/nss/automation/taskcluster/graph/tests/memleak.yml
security/nss/automation/taskcluster/graph/tests/ocsp.yml
security/nss/automation/taskcluster/graph/tests/pkits.yml
security/nss/automation/taskcluster/graph/tests/pkix.yml
security/nss/automation/taskcluster/graph/tools/_build_base.yml
security/nss/automation/taskcluster/graph/tools/clang-format.yml
security/nss/automation/taskcluster/graph/tools/scan-build.yml
security/nss/automation/taskcluster/graph/windows/build64-debug.yml
security/nss/automation/taskcluster/graph/windows/build64-opt.yml
security/nss/automation/taskcluster/scripts/run_scan_build.sh
security/nss/cmd/bltest/blapitest.c
security/nss/cmd/crlutil/crlutil.c
security/nss/cmd/dbtest/dbtest.c
security/nss/cmd/ecperf/ecperf.c
security/nss/cmd/httpserv/httpserv.c
security/nss/cmd/p7content/p7content.c
security/nss/cmd/p7env/p7env.c
security/nss/cmd/p7sign/p7sign.c
security/nss/cmd/p7verify/p7verify.c
security/nss/cmd/pp/pp.c
security/nss/cmd/selfserv/selfserv.c
security/nss/cmd/signtool/certgen.c
security/nss/cmd/signtool/sign.c
security/nss/cmd/signtool/verify.c
security/nss/cmd/smimetools/cmsutil.c
security/nss/cmd/tstclnt/tstclnt.c
security/nss/coreconf/coreconf.dep
security/nss/coverage/cov.sh
security/nss/coverage/report.sh
security/nss/external_tests/ssl_gtest/libssl_internals.c
security/nss/external_tests/ssl_gtest/ssl_dhe_unittest.cc
security/nss/external_tests/ssl_gtest/tls_agent.cc
security/nss/lib/freebl/ecl/ecl_gf.c
security/nss/lib/freebl/ecl/ecp_256.c
security/nss/lib/freebl/lowhash_vector.c
security/nss/lib/freebl/mpi/mpi.c
security/nss/lib/freebl/mpi/mplogic.c
security/nss/lib/freebl/pqg.c
security/nss/lib/freebl/rawhash.c
security/nss/lib/freebl/rsa.c
security/nss/lib/jar/jar.c
security/nss/lib/jar/jarver.c
security/nss/lib/pk11wrap/pk11skey.c
security/nss/lib/ssl/derive.c
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ecc.c
security/nss/lib/ssl/ssl3ext.c
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslsock.c
security/nss/lib/ssl/ssltrace.c
security/nss/lib/ssl/tls13con.c
security/nss/tests/ssl/ssl.sh
--- a/security/nss/.taskcluster.yml
+++ b/security/nss/.taskcluster.yml
@@ -57,16 +57,17 @@ tasks:
         - "tc-treeherder.v2.{{project}}.{{revision}}.{{pushlog_id}}"
 
       payload:
         image: "ttaubert/nss-ci:0.0.17"
 
         env:
           TC_OWNER: {{owner}}
           TC_SOURCE: {{{source}}}
+          TC_PROJECT: {{project}}
           NSS_PUSHLOG_ID: '{{pushlog_id}}'
           NSS_HEAD_REPOSITORY: '{{{url}}}'
           NSS_HEAD_REVISION: '{{revision}}'
 
         maxRunTime: 1800
 
         command:
           - bash
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3.26_BETA1
+NSS_3.26_BETA2
--- a/security/nss/automation/taskcluster/graph/build.js
+++ b/security/nss/automation/taskcluster/graph/build.js
@@ -7,16 +7,17 @@ var path = require("path");
 var merge = require("merge");
 var yaml = require("js-yaml");
 var slugid = require("slugid");
 var flatmap = require("flatmap");
 
 // Default values for debugging.
 var TC_OWNER = process.env.TC_OWNER || "{{tc_owner}}";
 var TC_SOURCE = process.env.TC_SOURCE || "{{tc_source}}";
+var TC_PROJECT = process.env.TC_PROJECT || "{{tc_project}}";
 var NSS_PUSHLOG_ID = process.env.NSS_PUSHLOG_ID || "{{nss_pushlog_id}}";
 var NSS_HEAD_REPOSITORY = process.env.NSS_HEAD_REPOSITORY || "{{nss_head_repo}}";
 var NSS_HEAD_REVISION = process.env.NSS_HEAD_REVISION || "{{nss_head_rev}}";
 
 // Register custom YAML types.
 var YAML_SCHEMA = yaml.Schema.create([
   // Point in time at $now + x hours.
   new yaml.Type('!from_now', {
@@ -61,18 +62,18 @@ function parseYamlFile(file, fallback) {
 
 // Add base information to the given task.
 function decorateTask(task) {
   // Assign random task id.
   task.taskId = slugid.v4();
 
   // TreeHerder routes.
   task.task.routes = [
-    "tc-treeherder-stage.v2.nss." + NSS_HEAD_REVISION + "." + NSS_PUSHLOG_ID,
-    "tc-treeherder.v2.nss." + NSS_HEAD_REVISION + "." + NSS_PUSHLOG_ID
+    "tc-treeherder-stage.v2." + TC_PROJECT + "." + NSS_HEAD_REVISION + "." + NSS_PUSHLOG_ID,
+    "tc-treeherder.v2." + TC_PROJECT + "." + NSS_HEAD_REVISION + "." + NSS_PUSHLOG_ID
   ];
 }
 
 // Generate all tasks for a given build.
 function generateBuildTasks(platform, file) {
   var dir = path.join(__dirname, "./" + platform);
 
   // Parse base definitions.
--- a/security/nss/automation/taskcluster/graph/linux/build32-debug.yml
+++ b/security/nss/automation/taskcluster/graph/linux/build32-debug.yml
@@ -22,19 +22,16 @@
     - cipher
     - crmf
     - db
     - ec
     - fips
     - gtests
     - lowhash
     - merge
-    - ocsp
-    - pkits
-    - pkix
     - sdr
     - smime
     - ssl
     - tools
 
 - task:
     metadata:
       name: "Linux 32 (debug, no TLS 1.3)"
@@ -118,23 +115,23 @@
         collection:
           debug: true
         groupSymbol: Builds
         groupName: Various builds
         symbol: gcc-6.1
 
 - task:
     metadata:
-      name: "Linux 32 (debug, NO_PKCS11_BYPASS=1)"
-      description: "Linux 32 (debug, NO_PKCS11_BYPASS=1)"
+      name: "Linux 32 (debug, NSS_NO_PKCS11_BYPASS=1)"
+      description: "Linux 32 (debug, NSS_NO_PKCS11_BYPASS=1)"
 
     payload:
       env:
+        NSS_NO_PKCS11_BYPASS: 1
         NSS_ENABLE_TLS_1_3: 1
-        NO_PKCS11_BYPASS: 1
 
     extra:
       treeherder:
         build:
           platform: linux32
         machine:
           platform: linux32
         collection:
--- a/security/nss/automation/taskcluster/graph/linux/build32-opt.yml
+++ b/security/nss/automation/taskcluster/graph/linux/build32-opt.yml
@@ -23,19 +23,16 @@
     - cipher
     - crmf
     - db
     - ec
     - fips
     - gtests
     - lowhash
     - merge
-    - ocsp
-    - pkits
-    - pkix
     - sdr
     - smime
     - ssl
     - tools
 
 - task:
     metadata:
       name: "Linux 32 (opt, no TLS 1.3)"
@@ -126,23 +123,23 @@
         collection:
           opt: true
         groupSymbol: Builds
         groupName: Various builds
         symbol: gcc-6.1
 
 - task:
     metadata:
-      name: "Linux 32 (opt, NO_PKCS11_BYPASS=1)"
-      description: "Linux 32 (opt, NO_PKCS11_BYPASS=1)"
+      name: "Linux 32 (opt, NSS_NO_PKCS11_BYPASS=1)"
+      description: "Linux 32 (opt, NSS_NO_PKCS11_BYPASS=1)"
 
     payload:
       env:
+        NSS_NO_PKCS11_BYPASS: 1
         NSS_ENABLE_TLS_1_3: 1
-        NO_PKCS11_BYPASS: 1
         BUILD_OPT: 1
 
     extra:
       treeherder:
         build:
           platform: linux32
         machine:
           platform: linux32
--- a/security/nss/automation/taskcluster/graph/linux/build64-asan.yml
+++ b/security/nss/automation/taskcluster/graph/linux/build64-asan.yml
@@ -26,15 +26,12 @@
     - cipher
     - crmf
     - db
     - ec
     - fips
     - gtests
     - lowhash
     - merge
-    - ocsp
-    - pkits
-    - pkix
     - sdr
     - smime
     - ssl
     - tools
--- a/security/nss/automation/taskcluster/graph/linux/build64-debug.yml
+++ b/security/nss/automation/taskcluster/graph/linux/build64-debug.yml
@@ -24,19 +24,16 @@
     - crmf
     - db
     - ec
     - fips
     - gtests
     - lowhash
     - memleak
     - merge
-    - ocsp
-    - pkits
-    - pkix
     - sdr
     - smime
     - ssl
     - tools
 
 - task:
     metadata:
       name: "Linux 64 (debug, no TLS 1.3)"
@@ -127,23 +124,23 @@
         collection:
           debug: true
         groupSymbol: Builds
         groupName: Various builds
         symbol: gcc-6.1
 
 - task:
     metadata:
-      name: "Linux 64 (debug, NO_PKCS11_BYPASS=1)"
-      description: "Linux 64 (debug, NO_PKCS11_BYPASS=1)"
+      name: "Linux 64 (debug, NSS_NO_PKCS11_BYPASS=1)"
+      description: "Linux 64 (debug, NSS_NO_PKCS11_BYPASS=1)"
 
     payload:
       env:
+        NSS_NO_PKCS11_BYPASS: 1
         NSS_ENABLE_TLS_1_3: 1
-        NO_PKCS11_BYPASS: 1
         USE_64: 1
 
     extra:
       treeherder:
         build:
           platform: linux64
         machine:
           platform: linux64
--- a/security/nss/automation/taskcluster/graph/linux/build64-lsan.yml
+++ b/security/nss/automation/taskcluster/graph/linux/build64-lsan.yml
@@ -20,16 +20,19 @@
         build:
           platform: linux64
         machine:
           platform: linux64
         collection:
           lsan: true
 
   tests:
+    - chains
     - cipher
+    - db
     - ec
     - gtests
     - lowhash
     - merge
-    - ocsp
-    - pkits
     - sdr
+    - smime
+    - ssl
+    - tools
--- a/security/nss/automation/taskcluster/graph/linux/build64-opt.yml
+++ b/security/nss/automation/taskcluster/graph/linux/build64-opt.yml
@@ -24,19 +24,16 @@
     - cipher
     - crmf
     - db
     - ec
     - fips
     - gtests
     - lowhash
     - merge
-    - ocsp
-    - pkits
-    - pkix
     - sdr
     - smime
     - ssl
     - tools
 
 - task:
     metadata:
       name: "Linux 64 (opt, no TLS 1.3)"
@@ -131,23 +128,23 @@
         collection:
           opt: true
         groupSymbol: Builds
         groupName: Various builds
         symbol: gcc-6.1
 
 - task:
     metadata:
-      name: "Linux 64 (opt, NO_PKCS11_BYPASS=1)"
-      description: "Linux 64 (opt, NO_PKCS11_BYPASS=1)"
+      name: "Linux 64 (opt, NSS_NO_PKCS11_BYPASS=1)"
+      description: "Linux 64 (opt, NSS_NO_PKCS11_BYPASS=1)"
 
     payload:
       env:
+        NSS_NO_PKCS11_BYPASS: 1
         NSS_ENABLE_TLS_1_3: 1
-        NO_PKCS11_BYPASS: 1
         BUILD_OPT: 1
         USE_64: 1
 
     extra:
       treeherder:
         build:
           platform: linux64
         machine:
--- a/security/nss/automation/taskcluster/graph/tests/memleak.yml
+++ b/security/nss/automation/taskcluster/graph/tests/memleak.yml
@@ -1,27 +1,11 @@
 ---
 - task:
     metadata:
-      name: "MemLeak tests (ocsp)"
-      description: "MemLeak tests (ocsp)"
-
-    payload:
-      env:
-        NSS_MEMLEAK_TESTS: ocsp
-        NSS_TESTS: memleak
-
-    extra:
-      treeherder:
-        symbol: ocsp
-        collection:
-          memleak: true
-
-- task:
-    metadata:
       name: "MemLeak tests (ssl_server, standard)"
       description: "MemLeak tests (ssl_server, standard)"
 
     payload:
       env:
         NSS_MEMLEAK_TESTS: ssl_server
         NSS_CYCLES: standard
         NSS_TESTS: memleak
deleted file mode 100644
--- a/security/nss/automation/taskcluster/graph/tests/ocsp.yml
+++ /dev/null
@@ -1,13 +0,0 @@
----
-- task:
-    metadata:
-      name: OCSP tests
-      description: OCSP tests
-
-    payload:
-      env:
-        NSS_TESTS: ocsp
-
-    extra:
-      treeherder:
-        symbol: OCSP
deleted file mode 100644
--- a/security/nss/automation/taskcluster/graph/tests/pkits.yml
+++ /dev/null
@@ -1,13 +0,0 @@
----
-- task:
-    metadata:
-      name: NIST PKITS tests
-      description: NIST PKITS tests
-
-    payload:
-      env:
-        NSS_TESTS: pkits
-
-    extra:
-      treeherder:
-        symbol: PKITS
deleted file mode 100644
--- a/security/nss/automation/taskcluster/graph/tests/pkix.yml
+++ /dev/null
@@ -1,13 +0,0 @@
----
-- task:
-    metadata:
-      name: libpkix tests
-      description: libpkix tests
-
-    payload:
-      env:
-        NSS_TESTS: libpkix
-
-    extra:
-      treeherder:
-        symbol: PKIX
new file mode 100644
--- /dev/null
+++ b/security/nss/automation/taskcluster/graph/tools/_build_base.yml
@@ -0,0 +1,28 @@
+---
+reruns: 0
+
+task:
+  created: !from_now 0
+  deadline: !from_now 24
+  provisionerId: aws-provisioner-v1
+  workerType: hg-worker
+  schedulerId: task-graph-scheduler
+
+  metadata:
+    owner: !env TC_OWNER
+    source: !env TC_SOURCE
+
+  payload:
+    maxRunTime: 3600
+    image: ttaubert/nss-ci:0.0.17
+
+    env:
+      NSS_HEAD_REPOSITORY: !env NSS_HEAD_REPOSITORY
+      NSS_HEAD_REVISION: !env NSS_HEAD_REVISION
+
+  extra:
+    treeherder:
+      build:
+        platform: nss-tools
+      machine:
+        platform: nss-tools
--- a/security/nss/automation/taskcluster/graph/tools/clang-format.yml
+++ b/security/nss/automation/taskcluster/graph/tools/clang-format.yml
@@ -1,35 +1,15 @@
 ---
-- reruns: 0
-  task:
-    created: !from_now 0
-    deadline: !from_now 24
-    provisionerId: aws-provisioner-v1
-    workerType: hg-worker
-    schedulerId: task-graph-scheduler
-
+- task:
     metadata:
-      owner: !env TC_OWNER
-      source: !env TC_SOURCE
       name: clang-format-3.8
       description: clang-format-3.8
 
     payload:
-      maxRunTime: 3600
-      image: ttaubert/nss-ci:0.0.17
-
       command:
         - "/bin/bash"
         - "-c"
         - "bin/checkout.sh && nss/automation/taskcluster/scripts/run_clang_format.sh nss/lib/ssl"
 
-      env:
-        NSS_HEAD_REPOSITORY: !env NSS_HEAD_REPOSITORY
-        NSS_HEAD_REVISION: !env NSS_HEAD_REVISION
-
     extra:
       treeherder:
-        build:
-          platform: nss-tools
-        machine:
-          platform: nss-tools
         symbol: clang-format-3.8
new file mode 100644
--- /dev/null
+++ b/security/nss/automation/taskcluster/graph/tools/scan-build.yml
@@ -0,0 +1,27 @@
+---
+- task:
+    metadata:
+      name: scan-build-3.8
+      description: scan-build-3.8
+
+    payload:
+      artifacts:
+        public:
+          type: directory
+          path: /home/worker/artifacts
+          expires: !from_now 24
+
+      command:
+        - "/bin/bash"
+        - "-c"
+        - "bin/checkout.sh && nss/automation/taskcluster/scripts/run_scan_build.sh"
+
+      env:
+        GCC_VERSION: clang
+        GXX_VERSION: clang++
+        NSS_ENABLE_TLS_1_3: 1
+        USE_64: 1
+
+    extra:
+      treeherder:
+        symbol: scan-build-3.8
--- a/security/nss/automation/taskcluster/graph/windows/build64-debug.yml
+++ b/security/nss/automation/taskcluster/graph/windows/build64-debug.yml
@@ -22,19 +22,16 @@
     - cipher
     - crmf
     - db
     - ec
     - fips
     - gtests
     - lowhash
     - merge
-    - ocsp
-    - pkits
-    - pkix
     - sdr
     - smime
     - tools
 
 - task:
     metadata:
       name: "Windows 2012 64 (debug, no TLS 1.3)"
       description: "Windows 2012 64 (debug, no TLS 1.3)"
@@ -52,23 +49,23 @@
         collection:
           debug: true
         groupSymbol: Builds
         groupName: Various builds
         symbol: noTLSv1.3
 
 - task:
     metadata:
-      name: "Windows 2012 64 (debug, NO_PKCS11_BYPASS=1)"
-      description: "Windows 2012 64 (debug, NO_PKCS11_BYPASS=1)"
+      name: "Windows 2012 64 (debug, NSS_NO_PKCS11_BYPASS=1)"
+      description: "Windows 2012 64 (debug, NSS_NO_PKCS11_BYPASS=1)"
 
     payload:
       env:
+        NSS_NO_PKCS11_BYPASS: 1
         NSS_ENABLE_TLS_1_3: 1
-        NO_PKCS11_BYPASS: 1
         USE_64: 1
 
     extra:
       treeherder:
         build:
           platform: windows2012-64
         machine:
           platform: windows2012-64
--- a/security/nss/automation/taskcluster/graph/windows/build64-opt.yml
+++ b/security/nss/automation/taskcluster/graph/windows/build64-opt.yml
@@ -23,19 +23,16 @@
     - cipher
     - crmf
     - db
     - ec
     - fips
     - gtests
     - lowhash
     - merge
-    - ocsp
-    - pkits
-    - pkix
     - sdr
     - smime
     - tools
 
 - task:
     metadata:
       name: "Windows 2012 64 (opt, no TLS 1.3)"
       description: "Windows 2012 64 (opt, no TLS 1.3)"
@@ -54,23 +51,23 @@
         collection:
           opt: true
         groupSymbol: Builds
         groupName: Various builds
         symbol: noTLSv1.3
 
 - task:
     metadata:
-      name: "Windows 2012 64 (opt, NO_PKCS11_BYPASS=1)"
-      description: "Windows 2012 64 (opt, NO_PKCS11_BYPASS=1)"
+      name: "Windows 2012 64 (opt, NSS_NO_PKCS11_BYPASS=1)"
+      description: "Windows 2012 64 (opt, NSS_NO_PKCS11_BYPASS=1)"
 
     payload:
       env:
+        NSS_NO_PKCS11_BYPASS: 1
         NSS_ENABLE_TLS_1_3: 1
-        NO_PKCS11_BYPASS: 1
         BUILD_OPT: 1
         USE_64: 1
 
     extra:
       treeherder:
         build:
           platform: windows2012-64
         machine:
new file mode 100755
--- /dev/null
+++ b/security/nss/automation/taskcluster/scripts/run_scan_build.sh
@@ -0,0 +1,42 @@
+#!/usr/bin/env bash
+
+set -v -e -x
+
+if [ $(id -u) = 0 ]; then
+    source $(dirname $0)/tools.sh
+
+    # Set compiler.
+    switch_compilers
+
+    # Drop privileges by re-running this script.
+    exec su worker $0 $@
+fi
+
+# Clone NSPR if needed.
+if [ ! -d "nspr" ]; then
+    hg clone https://hg.mozilla.org/projects/nspr
+fi
+
+# Build.
+cd nss && make nss_build_all
+
+# we run scan-build on these folders
+declare -a scan=("lib/ssl" "lib/freebl")
+
+for i in "${scan[@]}"
+do
+   echo "cleaning $i ..."
+   find "$i" -name "*.OBJ" | xargs rm -fr
+done
+
+# run scan-build
+scan-build -o /home/worker/artifacts/ make nss_build_all && cd ..
+
+# print errors we found
+set +v +x
+for i in "${scan[@]}"
+do
+   n=$(grep -Rn "${i#*/}/" /home/worker/artifacts/*/index.html | wc -l)
+   # TODO: print FAILED/PASSED and set exit code for folders we expect to be clean
+   echo "$(date '+%T') WARNING - TEST-UNEXPECTED-FAIL: $i contains $n scan-build errors"
+done
--- a/security/nss/cmd/bltest/blapitest.c
+++ b/security/nss/cmd/bltest/blapitest.c
@@ -3293,16 +3293,19 @@ blapi_selftest(bltestCipherMode *modes, 
 }
 
 SECStatus
 dump_file(bltestCipherMode mode, char *filename)
 {
     bltestIO keydata;
     PLArenaPool *arena = NULL;
     arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
+    if (!arena) {
+        return SECFailure;
+    }
     if (mode == bltestRSA || mode == bltestRSA_PSS || mode == bltestRSA_OAEP) {
         RSAPrivateKey *key;
         load_file_data(arena, &keydata, filename, bltestBase64Encoded);
         key = rsakey_from_filedata(arena, &keydata.buf);
         dump_rsakey(key);
     } else if (mode == bltestDSA) {
 #if 0
     PQGParams *pqg;
--- a/security/nss/cmd/crlutil/crlutil.c
+++ b/security/nss/cmd/crlutil/crlutil.c
@@ -451,21 +451,25 @@ CreateModifiedCRLCopy(PLArenaPool *arena
      * by "update <time>" command from crl generation script */
     rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now());
     if (rv != SECSuccess) {
         SECU_PrintError(progName, "fail to encode current time\n");
         goto loser;
     }
 
     signCrl->arena = arena;
+    signCrl->referenceCount = 1;
 
 loser:
     if (crlDER.data) {
         SECITEM_FreeItem(&crlDER, PR_FALSE);
     }
+    if (modArena && (!modCrl || modCrl->arena != modArena)) {
+        PORT_FreeArena(modArena, PR_FALSE);
+    }
     if (modCrl)
         SEC_DestroyCrl(modCrl);
     if (rv != SECSuccess && signCrl) {
         SEC_DestroyCrl(signCrl);
         signCrl = NULL;
     }
     return signCrl;
 }
--- a/security/nss/cmd/dbtest/dbtest.c
+++ b/security/nss/cmd/dbtest/dbtest.c
@@ -115,23 +115,28 @@ main(int argc, char **argv)
                 userPassword = PORT_Strdup(optstate->value);
                 break;
 
             case 'd':
                 dbDir = PORT_Strdup(optstate->value);
                 break;
         }
     }
+    PL_DestroyOptState(optstate);
     if (optstatus == PL_OPT_BAD)
         Usage(progName);
 
-    if (!dbDir) {
-        dbDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
+    if (dbDir) {
+        char *tmp = dbDir;
+        dbDir = SECU_ConfigDirectory(tmp);
+        PORT_Free(tmp);
+    } else {
+        /* Look in $SSL_DIR */
+        dbDir = SECU_ConfigDirectory(SECU_DefaultSSLDir());
     }
-    dbDir = SECU_ConfigDirectory(dbDir);
     PR_fprintf(PR_STDERR, "dbdir selected is %s\n\n", dbDir);
 
     if (dbDir[0] == '\0') {
         PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
         ret = DIR_DOESNT_EXIST_ERR;
         goto loser;
     }
 
@@ -157,16 +162,17 @@ main(int argc, char **argv)
                 } else if (PR_Access(dbString, PR_ACCESS_READ_OK) != PR_SUCCESS) {
                     PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
                                dbString);
                 } else if (!(flags & NSS_INIT_READONLY) &&
                            PR_Access(dbString, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
                     PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
                                dbString);
                 }
+                PR_smprintf_free(dbString);
             }
         }
     }
 
     rv = NSS_Initialize(SECU_ConfigDirectory(dbDir), dbprefix, dbprefix,
                         secmodName, flags);
     if (rv != SECSuccess) {
         SECU_PrintPRandOSError(progName);
--- a/security/nss/cmd/ecperf/ecperf.c
+++ b/security/nss/cmd/ecperf/ecperf.c
@@ -280,39 +280,45 @@ M_TimeOperation(void (*threadFunc)(void 
  */
 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;
     }
 
-    if (SECITEM_AllocItem(arena, item, tmp / 2) == NULL) {
+    item = SECITEM_AllocItem(arena, item, tmp / 2);
+    if (item == NULL) {
         return NULL;
     }
 
     while (str[i]) {
-        if ((str[i] >= '0') && (str[i] <= '9'))
+        if ((str[i] >= '0') && (str[i] <= '9')) {
             tmp = str[i] - '0';
-        else if ((str[i] >= 'a') && (str[i] <= 'f'))
+        } else if ((str[i] >= 'a') && (str[i] <= 'f')) {
             tmp = str[i] - 'a' + 10;
-        else if ((str[i] >= 'A') && (str[i] <= 'F'))
+        } else if ((str[i] >= 'A') && (str[i] <= 'F')) {
             tmp = str[i] - 'A' + 10;
-        else
+        } 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++;
     }
@@ -569,16 +575,17 @@ ectest_curve_freebl(ECCurveName curve, i
     PLArenaPool *arena;
 
     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     if (!arena) {
         return SECFailure;
     }
 
     if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
+        PORT_FreeArena(arena, PR_FALSE);
         return SECFailure;
     }
 
     ecParams.name = curve;
     ecParams.type = ec_params_named;
     ecParams.curveOID.data = NULL;
     ecParams.curveOID.len = 0;
     ecParams.curve.seed.data = NULL;
--- a/security/nss/cmd/httpserv/httpserv.c
+++ b/security/nss/cmd/httpserv/httpserv.c
@@ -635,16 +635,17 @@ handle_connection(
 
             iovs[numIOVs].iov_base = (char *)outHeader;
             iovs[numIOVs].iov_len = (sizeof(outHeader)) - 1;
             numIOVs++;
 
             if (isOcspRequest && caRevoInfos) {
                 CERTOCSPRequest *request = NULL;
                 PRBool failThisRequest = PR_FALSE;
+                PLArenaPool *arena = NULL;
 
                 if (ocspMethodsAllowed == ocspGetOnly && postData.len) {
                     failThisRequest = PR_TRUE;
                 } else if (ocspMethodsAllowed == ocspPostOnly && getData) {
                     failThisRequest = PR_TRUE;
                 } else if (ocspMethodsAllowed == ocspRandomGetFailure && getData) {
                     if (!(rand() % 2)) {
                         failThisRequest = PR_TRUE;
@@ -655,22 +656,27 @@ handle_connection(
                     PR_Write(ssl_sock, outBadRequestHeader, strlen(outBadRequestHeader));
                     break;
                 }
                 /* get is base64, post is binary.
                  * If we have base64, convert into the (empty) postData array.
                  */
                 if (getData) {
                     if (urldecode_base64chars_inplace(getData) == SECSuccess) {
-                        NSSBase64_DecodeBuffer(NULL, &postData, getData, strlen(getData));
+                        /* The code below can handle a NULL arena */
+                        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+                        NSSBase64_DecodeBuffer(arena, &postData, getData, strlen(getData));
                     }
                 }
                 if (postData.len) {
                     request = CERT_DecodeOCSPRequest(&postData);
                 }
+                if (arena) {
+                    PORT_FreeArena(arena, PR_FALSE);
+                }
                 if (!request || !request->tbsRequest ||
                     !request->tbsRequest->requestList ||
                     !request->tbsRequest->requestList[0]) {
                     PORT_Sprintf(msgBuf, "Cannot decode OCSP request.\r\n");
 
                     iovs[numIOVs].iov_base = msgBuf;
                     iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
                     numIOVs++;
@@ -770,16 +776,17 @@ handle_connection(
                             iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
                             numIOVs++;
                         } else {
                             PR_Write(ssl_sock, outOcspHeader, strlen(outOcspHeader));
                             PR_Write(ssl_sock, ocspResponse->data, ocspResponse->len);
                             PORT_FreeArena(arena, PR_FALSE);
                         }
                     }
+                    CERT_DestroyOCSPRequest(request);
                     break;
                 }
             } else if (local_file_fd) {
                 PRInt32 bytes;
                 int errLen;
                 bytes = PR_TransmitFile(ssl_sock, local_file_fd, outHeader,
                                         sizeof outHeader - 1,
                                         PR_TRANSMITFILE_KEEP_OPEN,
@@ -1362,16 +1369,17 @@ main(int argc, char **argv)
                 if (rv != SECSuccess) {
                     fprintf(stderr, "unable to read crl file %s\n",
                             revoInfo->crlFilename);
                     exit(1);
                 }
                 revoInfo->crl =
                     CERT_DecodeDERCrlWithFlags(NULL, &crlDER, SEC_CRL_TYPE,
                                                CRL_DECODE_DEFAULT_OPTIONS);
+                SECITEM_FreeItem(&crlDER, PR_FALSE);
                 if (!revoInfo->crl) {
                     fprintf(stderr, "unable to decode crl file %s\n",
                             revoInfo->crlFilename);
                     exit(1);
                 }
                 if (CERT_CompareName(&revoInfo->crl->crl.name,
                                      &revoInfo->cert->subject) != SECEqual) {
                     fprintf(stderr, "CRL %s doesn't match cert identified by preceding nickname %s\n",
--- a/security/nss/cmd/p7content/p7content.c
+++ b/security/nss/cmd/p7content/p7content.c
@@ -150,16 +150,17 @@ DecodeAndPrintFile(FILE *out, PRFileDesc
         }
     } else {
         fprintf(out, "Content was not signed.\n");
     }
 
     fprintf(out, "There were%s certs or crls included.\n",
             SEC_PKCS7ContainsCertsOrCrls(cinfo) ? "" : " no");
 
+    SECITEM_FreeItem(&derdata, PR_FALSE);
     SEC_PKCS7DestroyContentInfo(cinfo);
     return 0;
 }
 
 /*
  * Print the contents of a PKCS7 message, indicating signatures, etc.
  */
 
@@ -167,16 +168,17 @@ int
 main(int argc, char **argv)
 {
     char *progName;
     FILE *outFile;
     PRFileDesc *inFile;
     PLOptState *optstate;
     PLOptStatus status;
     SECStatus rv;
+    int error = 0;
 
     progName = strrchr(argv[0], '/');
     progName = progName ? progName + 1 : argv[0];
 
     inFile = NULL;
     outFile = NULL;
 
     /*
@@ -189,26 +191,28 @@ main(int argc, char **argv)
                 SECU_ConfigDirectory(optstate->value);
                 break;
 
             case 'i':
                 inFile = PR_Open(optstate->value, PR_RDONLY, 0);
                 if (!inFile) {
                     fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
                             progName, optstate->value);
-                    return -1;
+                    error = -1;
+                    goto done;
                 }
                 break;
 
             case 'o':
                 outFile = fopen(optstate->value, "w");
                 if (!outFile) {
                     fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
                             progName, optstate->value);
-                    return -1;
+                    error = -1;
+                    goto done;
                 }
                 break;
 
             case 'p':
                 pwdata.source = PW_PLAINTEXT;
                 pwdata.data = PORT_Strdup(optstate->value);
                 break;
 
@@ -217,37 +221,49 @@ main(int argc, char **argv)
                 pwdata.data = PORT_Strdup(optstate->value);
                 break;
 
             default:
                 Usage(progName);
                 break;
         }
     }
+    PL_DestroyOptState(optstate);
+
     if (status == PL_OPT_BAD)
         Usage(progName);
 
     if (!inFile)
         inFile = PR_STDIN;
     if (!outFile)
         outFile = stdout;
 
     /* Call the initialization routines */
     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
     rv = NSS_Init(SECU_ConfigDirectory(NULL));
     if (rv != SECSuccess) {
         SECU_PrintPRandOSError(progName);
-        return -1;
+        error = -1;
+        goto done;
     }
 
     PK11_SetPasswordFunc(SECU_GetModulePassword);
 
     if (DecodeAndPrintFile(outFile, inFile, progName)) {
         SECU_PrintError(progName, "problem decoding data");
-        return -1;
+        error = -1;
+        goto done;
+    }
+
+done:
+    if (inFile && inFile != PR_STDIN) {
+        PR_Close(inFile);
+    }
+    if (outFile && outFile != stdout) {
+        fclose(outFile);
     }
 
     if (NSS_Shutdown() != SECSuccess) {
-        exit(1);
+        error = -1;
     }
 
-    return 0;
+    return error;
 }
--- a/security/nss/cmd/p7env/p7env.c
+++ b/security/nss/cmd/p7env/p7env.c
@@ -185,22 +185,23 @@ main(int argc, char **argv)
                     rcpt->next = PORT_Alloc(sizeof(struct recipient));
                     rcpt = rcpt->next;
                 }
                 if (rcpt == NULL) {
                     fprintf(stderr, "%s: unable to allocate recipient struct\n",
                             progName);
                     return -1;
                 }
-                rcpt->nickname = strdup(optstate->value);
+                rcpt->nickname = PORT_Strdup(optstate->value);
                 rcpt->cert = NULL;
                 rcpt->next = NULL;
                 break;
         }
     }
+    PL_DestroyOptState(optstate);
 
     if (!recipients)
         Usage(progName);
 
     if (!inFile)
         inFile = stdin;
     if (!outFile)
         outFile = stdout;
@@ -230,10 +231,31 @@ main(int argc, char **argv)
         }
     }
 
     if (EncryptFile(outFile, inFile, recipients, progName)) {
         SECU_PrintError(progName, "problem encrypting data");
         return -1;
     }
 
+    /* free certs */
+    for (rcpt = recipients; rcpt != NULL; ) {
+        struct recipient *next = rcpt->next;
+        CERT_DestroyCertificate(rcpt->cert);
+        PORT_Free(rcpt->nickname);
+        PORT_Free(rcpt);
+        rcpt = next;
+    }
+
+    if (inFile && inFile != stdin) {
+        fclose(inFile);
+    }
+    if (outFile && outFile != stdout) {
+        fclose(outFile);
+    }
+
+    if (NSS_Shutdown() != SECSuccess) {
+        SECU_PrintError(progName, "NSS shutdown:");
+        return -1;
+    }
+
     return 0;
 }
--- a/security/nss/cmd/p7sign/p7sign.c
+++ b/security/nss/cmd/p7sign/p7sign.c
@@ -127,16 +127,17 @@ SignFile(FILE *outFile, PRFileDesc *inFi
     if (rv != SECSuccess) {
         SEC_PKCS7DestroyContentInfo(cinfo);
         return -1;
     }
 
     rv = SEC_PKCS7Encode(cinfo, SignOut, outFile, NULL,
                          NULL, &pwdata);
 
+    SECITEM_FreeItem(&data2sign, PR_FALSE);
     SEC_PKCS7DestroyContentInfo(cinfo);
 
     if (rv != SECSuccess)
         return -1;
 
     return 0;
 }
 
@@ -207,16 +208,17 @@ main(int argc, char **argv)
                 break;
 
             case 'f':
                 pwdata.source = PW_FROMFILE;
                 pwdata.data = PORT_Strdup(optstate->value);
                 break;
         }
     }
+    PL_DestroyOptState(optstate);
 
     if (!keyName)
         Usage(progName);
 
     if (!inFile)
         inFile = PR_STDIN;
     if (!outFile)
         outFile = stdout;
--- a/security/nss/cmd/p7verify/p7verify.c
+++ b/security/nss/cmd/p7verify/p7verify.c
@@ -166,16 +166,17 @@ HashDecodeAndVerify(FILE *out, FILE *con
     fprintf(out, "Signature is ");
     if (SEC_PKCS7VerifyDetachedSignature(cinfo, usage, &digest, digestType,
                                          PR_FALSE))
         fprintf(out, "valid.\n");
     else
         fprintf(out, "invalid (Reason: %s).\n",
                 SECU_Strerror(PORT_GetError()));
 
+    SECITEM_FreeItem(&derdata, PR_FALSE);
     SEC_PKCS7DestroyContentInfo(cinfo);
     return 0;
 }
 
 int
 main(int argc, char **argv)
 {
     char *progName;
@@ -240,16 +241,17 @@ main(int argc, char **argv)
                 usageType = atoi(strdup(optstate->value));
                 if (usageType < certUsageSSLClient || usageType > certUsageAnyCA)
                     return -1;
                 certUsage = (SECCertUsage)usageType;
                 break;
             }
         }
     }
+    PL_DestroyOptState(optstate);
 
     if (!contentFile)
         Usage(progName);
     if (!signatureFile)
         Usage(progName);
     if (!outFile)
         outFile = stdout;
 
@@ -262,14 +264,20 @@ main(int argc, char **argv)
     }
 
     if (HashDecodeAndVerify(outFile, contentFile, signatureFile,
                             certUsage, progName)) {
         SECU_PrintError(progName, "problem decoding/verifying signature");
         return -1;
     }
 
+    fclose(contentFile);
+    PR_Close(signatureFile);
+    if (outFile && outFile != stdout) {
+        fclose(outFile);
+    }
+
     if (NSS_Shutdown() != SECSuccess) {
         exit(1);
     }
 
     return 0;
 }
--- a/security/nss/cmd/pp/pp.c
+++ b/security/nss/cmd/pp/pp.c
@@ -172,16 +172,18 @@ main(int argc, char **argv)
         rv = SECU_PrintDERName(outFile, &data, "Name", 0);
     } else {
         fprintf(stderr, "%s: don't know how to print out '%s' files\n",
                 progName, typeTag);
         SECU_PrintAny(outFile, &data, "File contains", 0);
         return -1;
     }
 
+    PORT_Free(typeTag);
+
     if (inFile != PR_STDIN)
         PR_Close(inFile);
     PORT_Free(der.data);
     if (rv) {
         fprintf(stderr, "%s: problem converting data (%s)\n",
                 progName, SECU_Strerror(PORT_GetError()));
     }
     if (NSS_Shutdown() != SECSuccess) {
--- a/security/nss/cmd/selfserv/selfserv.c
+++ b/security/nss/cmd/selfserv/selfserv.c
@@ -689,17 +689,17 @@ launch_threads(
         slot->c = c;
         slot->startFunc = startFunc;
         slot->prThread = PR_CreateThread(PR_USER_THREAD,
                                          thread_wrapper, slot, PR_PRIORITY_NORMAL,
                                          (PR_TRUE ==
                                           local)
                                              ? PR_LOCAL_THREAD
                                              : PR_GLOBAL_THREAD,
-                                         PR_UNJOINABLE_THREAD, 0);
+                                         PR_JOINABLE_THREAD, 0);
         if (slot->prThread == NULL) {
             printf("selfserv: Failed to launch thread!\n");
             slot->state = rs_idle;
             rv = SECFailure;
             break;
         }
 
         ++threadCount;
@@ -718,23 +718,34 @@ launch_threads(
     if (name) {               \
         PZ_DestroyLock(name); \
         name = NULL;          \
     }
 
 void
 terminateWorkerThreads(void)
 {
-    VLOG(("selfserv: server_thead: waiting on stopping"));
+    int i;
+
+    VLOG(("selfserv: server_thread: waiting on stopping"));
     PZ_Lock(qLock);
     PZ_NotifyAllCondVar(jobQNotEmptyCv);
-    while (threadCount > 0) {
-        PZ_WaitCondVar(threadCountChangeCv, PR_INTERVAL_NO_TIMEOUT);
+    PZ_Unlock(qLock);
+
+    /* Wait for worker threads to terminate. */
+    for (i = 0; i < maxThreads; ++i) {
+        perThread *slot = threads + i;
+        if (slot->prThread) {
+            PR_JoinThread(slot->prThread);
+        }
     }
+
     /* The worker threads empty the jobQ before they terminate. */
+    PZ_Lock(qLock);
+    PORT_Assert(threadCount == 0);
     PORT_Assert(PR_CLIST_IS_EMPTY(&jobQ));
     PZ_Unlock(qLock);
 
     DESTROY_CONDVAR(jobQNotEmptyCv);
     DESTROY_CONDVAR(freeListNotEmptyCv);
     DESTROY_CONDVAR(threadCountChangeCv);
 
     PR_DestroyLock(lastLoadedCrlLock);
@@ -831,16 +842,17 @@ PRBool hasSidCache = PR_FALSE;
 PRBool disableStepDown = PR_FALSE;
 PRBool bypassPKCS11 = PR_FALSE;
 PRBool disableLocking = PR_FALSE;
 PRBool testbypass = PR_FALSE;
 PRBool enableSessionTickets = PR_FALSE;
 PRBool enableCompression = PR_FALSE;
 PRBool failedToNegotiateName = PR_FALSE;
 PRBool enableExtendedMasterSecret = PR_FALSE;
+PRBool zeroRTT = PR_FALSE;
 
 static char *virtServerNameArray[MAX_VIRT_SERVER_NAME_ARRAY_INDEX];
 static int virtServerNameIndex = 1;
 
 static const char stopCmd[] = { "GET /stop " };
 static const char getCmd[] = { "GET " };
 static const char EOFmsg[] = { "EOF\r\n\r\n\r\n" };
 static const char outHeader[] = {
@@ -1837,16 +1849,19 @@ handshakeCallback(PRFileDesc *fd, void *
 {
     const char *handshakeName = (const char *)client_data;
     if (handshakeName && !failedToNegotiateName) {
         SECItem *hostInfo = SSL_GetNegotiatedHostInfo(fd);
         if (!hostInfo || PORT_Strncmp(handshakeName, (char *)hostInfo->data,
                                       hostInfo->len)) {
             failedToNegotiateName = PR_TRUE;
         }
+        if (hostInfo) {
+            SECITEM_FreeItem(hostInfo, PR_TRUE);
+        }
     }
 }
 
 void
 server_main(
     PRFileDesc *listen_sock,
     int requestCert,
     SECKEYPrivateKey **privKey,
@@ -1982,16 +1997,26 @@ server_main(
 
     if (NoReuse) {
         rv = SSL_OptionSet(model_sock, SSL_NO_CACHE, 1);
         if (rv < 0) {
             errExit("SSL_OptionSet SSL_NO_CACHE");
         }
     }
 
+    if (zeroRTT) {
+        if (enabledVersions.max < SSL_LIBRARY_VERSION_TLS_1_3) {
+            errExit("You tried enabling 0RTT without enabling TLS 1.3!");
+        }
+        rv = SSL_OptionSet(model_sock, SSL_ENABLE_0RTT_DATA, PR_TRUE);
+        if (rv != SECSuccess) {
+            errExit("error enabling 0RTT ");
+        }
+    }
+
     /* This cipher is not on by default. The Acceptance test
      * would like it to be. Turn this cipher on.
      */
 
     secStatus = SSL_CipherPrefSetDefault(TLS_RSA_WITH_NULL_MD5, PR_TRUE);
     if (secStatus != SECSuccess) {
         errExit("SSL_CipherPrefSetDefault:TLS_RSA_WITH_NULL_MD5");
     }
@@ -2234,17 +2259,17 @@ main(int argc, char **argv)
 
     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
     SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
 
     /* please keep this list of options in ASCII collating sequence.
     ** numbers, then capital letters, then lower case, alphabetical.
     */
     optstate = PL_CreateOptState(argc, argv,
-                                 "2:A:BC:DEGH:L:M:NP:RS:T:U:V:W:Ya:bc:d:e:f:g:hi:jk:lmn:op:qrst:uvw:xyz");
+                                 "2:A:BC:DEGH:L:M:NP:RS:T:U:V:W:YZa:bc:d:e:f:g:hi:jk:lmn:op:qrst:uvw:xyz");
     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
         ++optionsFound;
         switch (optstate->option) {
             case '2':
                 fileName = optstate->value;
                 break;
 
             case 'A':
@@ -2457,16 +2482,20 @@ main(int argc, char **argv)
             case 'y':
                 debugCache = PR_TRUE;
                 break;
 
             case 'z':
                 enableCompression = PR_TRUE;
                 break;
 
+            case 'Z':
+                zeroRTT = PR_TRUE;
+                break;
+
             default:
             case '?':
                 fprintf(stderr, "Unrecognized or bad option specified.\n");
                 fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
                 exit(4);
                 break;
         }
     }
@@ -2874,16 +2903,19 @@ cleanup:
     if (certPrefix && certPrefix != emptyString) {
         PORT_Free(certPrefix);
     }
 #ifndef NSS_DISABLE_ECC
     if (ecNickName) {
         PORT_Free(ecNickName);
     }
 #endif
+    if (dsaNickName) {
+        PORT_Free(dsaNickName);
+    }
 
     if (hasSidCache) {
         SSL_ShutdownServerSessionIDCache();
     }
     if (certStatusArena) {
         PORT_FreeArena(certStatusArena, PR_FALSE);
     }
     if (NSS_Shutdown() != SECSuccess) {
--- a/security/nss/cmd/signtool/certgen.c
+++ b/security/nss/cmd/signtool/certgen.c
@@ -343,16 +343,18 @@ GenerateSelfSignedObjectSigningCert(char
     if (ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) {
         FatalError("Unable to change trust on generated certificate");
     }
 
     /* !!! Free memory ? !!! */
     PK11_FreeSlot(slot);
     SECKEY_DestroyPrivateKey(privk);
     SECKEY_DestroyPublicKey(pubk);
+    CERT_DestroyCertificate(temp_cert);
+    CERT_DestroyCertificateRequest(req);
 
     return cert;
 }
 
 /**************************************************************************
  *
  * C h a n g e T r u s t A t t r i b u t e s
  */
@@ -382,16 +384,17 @@ ChangeTrustAttributes(CERTCertDBHandle *
 
     if (CERT_ChangeCertTrust(db, cert, trust)) {
         PR_fprintf(errorFD, "unable to modify trust attributes for cert %s\n",
                    cert->nickname ? cert->nickname : "");
         errorCount++;
         return SECFailure;
     }
 
+    PORT_Free(trust);
     return SECSuccess;
 }
 
 /*************************************************************************
  *
  * s e t _ c e r t _ t y p e
  */
 static SECStatus
@@ -622,16 +625,17 @@ make_cert(CERTCertificateRequest *req, u
     if (validity == NULL) {
         PR_fprintf(errorFD, "%s: error creating certificate validity\n",
                    PROGRAM_NAME);
         errorCount++;
         exit(ERRX);
     }
 
     cert = CERT_CreateCertificate(serial, ca_subject, validity, req);
+    CERT_DestroyValidity(validity);
 
     if (cert == NULL) {
         /* should probably be more precise here */
         PR_fprintf(errorFD, "%s: error while generating certificate\n",
                    PROGRAM_NAME);
         errorCount++;
         exit(ERRX);
     }
@@ -645,17 +649,17 @@ make_cert(CERTCertificateRequest *req, u
  */
 static void
 output_ca_cert(CERTCertificate *cert, CERTCertDBHandle *db)
 {
     FILE *out;
 
     SECItem *encodedCertChain;
     SEC_PKCS7ContentInfo *certChain;
-    char *filename;
+    char *filename, *certData;
 
     /* the raw */
 
     filename = PORT_ZAlloc(strlen(DEFAULT_X509_BASENAME) + 8);
     if (!filename)
         out_of_memory();
 
     sprintf(filename, "%s.raw", DEFAULT_X509_BASENAME);
@@ -690,20 +694,20 @@ output_ca_cert(CERTCertificate *cert, CE
     sprintf(filename, "%s.cacert", DEFAULT_X509_BASENAME);
     if ((out = fopen(filename, "wb")) == NULL) {
         PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME,
                    filename);
         errorCount++;
         return;
     }
 
-    fprintf(out, "%s\n%s\n%s\n",
-            NS_CERT_HEADER,
-            BTOA_DataToAscii(cert->derCert.data, cert->derCert.len),
-            NS_CERT_TRAILER);
+    certData = BTOA_DataToAscii(cert->derCert.data, cert->derCert.len);
+    fprintf(out, "%s\n%s\n%s\n", NS_CERT_HEADER, certData, NS_CERT_TRAILER);
+    PORT_Free(certData);
 
+    PORT_Free(filename);
     fclose(out);
 
     if (verbosity >= 0) {
         PR_fprintf(outputFD, "Exported certificate to %s.raw and %s.cacert.\n",
                    DEFAULT_X509_BASENAME, DEFAULT_X509_BASENAME);
     }
 }
--- a/security/nss/cmd/signtool/sign.c
+++ b/security/nss/cmd/signtool/sign.c
@@ -438,16 +438,17 @@ manifesto_xpi_fn(char *relpath, char *ba
  *  Called by pointer from manifesto(), once for
  *  each file within the directory.
  *
  */
 static int
 manifesto_fn(char *relpath, char *basedir, char *reldir, char *filename, void *arg)
 {
     int use_js;
+    char *md5, *sha1;
 
     JAR_Digest dig;
     char fullname[FNSIZE];
 
     if (verbosity >= 0) {
         PR_fprintf(outputFD, "--> %s\n", relpath);
     }
 
@@ -489,21 +490,25 @@ manifesto_fn(char *relpath, char *basedi
         if (metafile)
             add_meta(mf, relpath);
     }
 
     JAR_digest_file(fullname, &dig);
 
     if (optimize == 0) {
         fprintf(mf, "Digest-Algorithms: MD5 SHA1\n");
-        fprintf(mf, "MD5-Digest: %s\n", BTOA_DataToAscii(dig.md5,
-                                                         MD5_LENGTH));
+
+        md5 = BTOA_DataToAscii(dig.md5, MD5_LENGTH);
+        fprintf(mf, "MD5-Digest: %s\n", md5);
+        PORT_Free(md5);
     }
 
-    fprintf(mf, "SHA1-Digest: %s\n", BTOA_DataToAscii(dig.sha1, SHA1_LENGTH));
+    sha1 = BTOA_DataToAscii(dig.sha1, SHA1_LENGTH);
+    fprintf(mf, "SHA1-Digest: %s\n", sha1);
+    PORT_Free(sha1);
 
     if (!use_js) {
         JzipAdd(fullname, relpath, zipfile, compression_level);
     }
 
     return 0;
 }
 
@@ -669,16 +674,17 @@ SignFile(FILE *outFile, FILE *inFile, CE
 static int
 generate_SF_file(char *manifile, char *who)
 {
     FILE *sf;
     FILE *mf;
     long r1, r2, r3;
     char whofile[FNSIZE];
     char *buf, *name = NULL;
+    char *md5, *sha1;
     JAR_Digest dig;
     int line = 0;
 
     strcpy(whofile, who);
 
     if ((mf = fopen(manifile, "rb")) == NULL) {
         perror(manifile);
         exit(ERRX);
@@ -751,22 +757,25 @@ generate_SF_file(char *manifile, char *w
             fprintf(sf, "\n");
             fprintf(sf, "%s", name);
         }
 
         calculate_MD5_range(mf, r1, r2, &dig);
 
         if (optimize == 0) {
             fprintf(sf, "Digest-Algorithms: MD5 SHA1\n");
-            fprintf(sf, "MD5-Digest: %s\n",
-                    BTOA_DataToAscii(dig.md5, MD5_LENGTH));
+
+            md5 = BTOA_DataToAscii(dig.md5, MD5_LENGTH);
+            fprintf(sf, "MD5-Digest: %s\n", md5);
+            PORT_Free(md5);
         }
 
-        fprintf(sf, "SHA1-Digest: %s\n",
-                BTOA_DataToAscii(dig.sha1, SHA1_LENGTH));
+        sha1 = BTOA_DataToAscii(dig.sha1, SHA1_LENGTH);
+        fprintf(sf, "SHA1-Digest: %s\n", sha1);
+        PORT_Free(sha1);
 
         /* restore normalcy after changing offset position */
         fseek(mf, r3, SEEK_SET);
     }
 
     PORT_Free(buf);
     PORT_Free(name);
 
--- a/security/nss/cmd/signtool/verify.c
+++ b/security/nss/cmd/signtool/verify.c
@@ -226,16 +226,18 @@ verify_global(JAR *jar)
                                        : "match");
                     }
 
                     if (globaldig == NULL && verbosity >= 0) {
                         PR_fprintf(outputFD,
                                    "global metadigest is not available, strange.\n");
                     }
 
+                    PORT_Free(md5_digest);
+                    PORT_Free(sha1_digest);
                     fclose(fp);
                 }
             }
         }
     }
 
     JAR_find_end(ctx);
 
--- a/security/nss/cmd/smimetools/cmsutil.c
+++ b/security/nss/cmd/smimetools/cmsutil.c
@@ -1246,17 +1246,17 @@ main(int argc, char **argv)
                     decodeOptions.content.len = 0;
                 }
 
                 break;
             case 'd':
                 SECU_ConfigDirectory(optstate->value);
                 break;
             case 'e':
-                envFileName = strdup(optstate->value);
+                envFileName = PORT_Strdup(optstate->value);
                 encryptOptions.envFile = PR_Open(envFileName, PR_RDONLY, 00660);
                 break;
 
             case 'h':
                 if (mode != DECODE) {
                     fprintf(stderr,
                             "%s: option -h only supported with option -D.\n",
                             progName);
@@ -1374,19 +1374,16 @@ main(int argc, char **argv)
         Usage(progName);
 
     if (mode != CERTSONLY && !batch) {
         rv = SECU_FileToItem(&input, inFile);
         if (rv != SECSuccess) {
             SECU_PrintError(progName, "unable to read infile");
             exit(1);
         }
-        if (inFile != PR_STDIN) {
-            PR_Close(inFile);
-        }
     }
     if (cms_verbose) {
         fprintf(stderr, "received commands\n");
     }
 
     /* Call the NSS initialization routines */
     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
     rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL));
@@ -1456,19 +1453,16 @@ main(int argc, char **argv)
             if (!batch) {
                 cmsg = decode(outFile, &input, &decodeOptions);
                 if (!cmsg) {
                     SECU_PrintError(progName, "problem decoding");
                     exitstatus = 1;
                 }
             } else {
                 exitstatus = doBatchDecode(outFile, inFile, &decodeOptions);
-                if (inFile != PR_STDIN) {
-                    PR_Close(inFile);
-                }
             }
             break;
         case SIGN: /* -S */
             signOptions.options = &options;
             cmsg = signed_data(&signOptions);
             if (!cmsg) {
                 SECU_PrintError(progName, "problem signing");
                 exitstatus = 1;
@@ -1606,16 +1600,26 @@ main(int argc, char **argv)
         }
         PORT_FreeArena(arena, PR_FALSE);
     }
     if (cmsg)
         NSS_CMSMessage_Destroy(cmsg);
     if (outFile != stdout)
         fclose(outFile);
 
+    if (inFile != PR_STDIN) {
+        PR_Close(inFile);
+    }
+    if (envFileName) {
+        PORT_Free(envFileName);
+    }
+    if (encryptOptions.envFile) {
+        PR_Close(encryptOptions.envFile);
+    }
+
     SECITEM_FreeItem(&decodeOptions.content, PR_FALSE);
     SECITEM_FreeItem(&envmsg, PR_FALSE);
     SECITEM_FreeItem(&input, PR_FALSE);
     if (NSS_Shutdown() != SECSuccess) {
         SECU_PrintError(progName, "NSS_Shutdown failed");
         exitstatus = 1;
     }
     PR_Cleanup();
--- a/security/nss/cmd/tstclnt/tstclnt.c
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -889,17 +889,17 @@ restartHandshakeAfterServerCertIfNeeded(
     }
 
     return rv;
 }
 
 int
 main(int argc, char **argv)
 {
-    PRFileDesc *s;
+    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;
@@ -1205,104 +1205,111 @@ main(int argc, char **argv)
         /* Lookup host */
         PRAddrInfo *addrInfo;
         void *enumPtr = NULL;
 
         addrInfo = PR_GetAddrInfoByName(host, PR_AF_UNSPEC,
                                         PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME);
         if (!addrInfo) {
             SECU_PrintError(progName, "error looking up host");
-            return 1;
+            error = 1;
+            goto done;
         }
         for (;;) {
             enumPtr = PR_EnumerateAddrInfo(enumPtr, addrInfo, portno, &addr);
             if (enumPtr == NULL)
                 break;
             if (addr.raw.family == PR_AF_INET && allowIPv4)
                 break;
             if (addr.raw.family == PR_AF_INET6 && allowIPv6)
                 break;
         }
         PR_FreeAddrInfo(addrInfo);
         if (enumPtr == NULL) {
             SECU_PrintError(progName, "error looking up host address");
-            return 1;
+            error = 1;
+            goto done;
         }
     }
 
     printHostNameAndAddr(host, &addr);
 
+    if (!certDir) {
+        certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
+        certDir = SECU_ConfigDirectory(certDir);
+    } else {
+        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);
             if (s == NULL) {
                 SECU_PrintError(progName, "Failed to create a TCP socket");
+                error = 1;
+                goto done;
             }
             opt.option = PR_SockOpt_Nonblocking;
             opt.value.non_blocking = PR_FALSE;
             prStatus = PR_SetSocketOption(s, &opt);
             if (prStatus != PR_SUCCESS) {
-                PR_Close(s);
                 SECU_PrintError(progName,
                                 "Failed to set blocking socket option");
-                return 1;
+                error = 1;
+                goto done;
             }
             if (pingTimeoutSeconds >= 0) {
                 timeoutInterval = PR_SecondsToInterval(pingTimeoutSeconds);
             }
             prStatus = PR_Connect(s, &addr, timeoutInterval);
             if (prStatus == PR_SUCCESS) {
                 PR_Shutdown(s, PR_SHUTDOWN_BOTH);
-                PR_Close(s);
-                PR_Cleanup();
-                return 0;
+                goto done;
             }
             err = PR_GetError();
             if ((err != PR_CONNECT_REFUSED_ERROR) &&
                 (err != PR_CONNECT_RESET_ERROR)) {
                 SECU_PrintError(progName, "TCP Connection failed");
-                return 1;
+                error = 1;
+                goto done;
             }
             PR_Close(s);
+            s = NULL;
             PR_Sleep(PR_MillisecondsToInterval(WAIT_INTERVAL));
         } while (++iter < max_attempts);
         SECU_PrintError(progName,
                         "Client timed out while waiting for connection to server");
-        return 1;
+        error = 1;
+        goto done;
     }
 
     /* open the cert DB, the key DB, and the secmod DB. */
-    if (!certDir) {
-        certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
-        certDir = SECU_ConfigDirectory(certDir);
-    } else {
-        char *certDirTmp = certDir;
-        certDir = SECU_ConfigDirectory(certDirTmp);
-        PORT_Free(certDirTmp);
-    }
-
     if (openDB) {
         rv = NSS_Init(certDir);
         if (rv != SECSuccess) {
             SECU_PrintError(progName, "unable to open cert database");
-            return 1;
+            error = 1;
+            goto done;
         }
     } else {
         rv = NSS_NoDB_Init(NULL);
         if (rv != SECSuccess) {
             SECU_PrintError(progName, "failed to initialize NSS");
-            return 1;
+            error = 1;
+            goto done;
         }
     }
 
     if (loadDefaultRootCAs) {
         SECMOD_AddNewModule("Builtins",
                             DLL_PREFIX "nssckbi." DLL_SUFFIX, 0, 0);
     } else if (rootModule) {
         SECMOD_AddNewModule("Builtins", rootModule, 0, 0);
@@ -1319,43 +1326,47 @@ main(int argc, char **argv)
         /* 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");
-        return 1;
+        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");
-        return 1;
+        error = 1;
+        goto done;
     }
 
     rv = SSL_OptionSet(s, SSL_SECURITY, 1);
     if (rv != SECSuccess) {
         SECU_PrintError(progName, "error enabling socket");
-        return 1;
+        error = 1;
+        goto done;
     }
 
     rv = SSL_OptionSet(s, SSL_HANDSHAKE_AS_CLIENT, 1);
     if (rv != SECSuccess) {
         SECU_PrintError(progName, "error enabling client handshake");
-        return 1;
+        error = 1;
+        goto done;
     }
 
     /* all SSL3 cipher suites are enabled by default. */
     if (cipherString) {
         char *cstringSaved = cipherString;
         int ndx;
 
         while (0 != (ndx = *cipherString++)) {
@@ -1394,93 +1405,104 @@ main(int argc, char **argv)
             }
         }
         PORT_Free(cstringSaved);
     }
 
     rv = SSL_VersionRangeSet(s, &enabledVersions);
     if (rv != SECSuccess) {
         SECU_PrintError(progName, "error setting SSL/TLS version range ");
-        return 1;
+        error = 1;
+        goto done;
     }
 
     /* enable PKCS11 bypass */
     rv = SSL_OptionSet(s, SSL_BYPASS_PKCS11, bypassPKCS11);
     if (rv != SECSuccess) {
         SECU_PrintError(progName, "error enabling PKCS11 bypass");
-        return 1;
+        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");
-        return 1;
+        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");
-        return 1;
+        error = 1;
+        goto done;
     }
 
     /* enable compression. */
     rv = SSL_OptionSet(s, SSL_ENABLE_DEFLATE, enableCompression);
     if (rv != SECSuccess) {
         SECU_PrintError(progName, "error enabling compression");
-        return 1;
+        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");
-        return 1;
+        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");
-            return 1;
+            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)");
-        return 1;
+        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");
-            return 1;
+            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 enabling extended master secret");
-            return 1;
+            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");
-        return 1;
+        error = 1;
+        goto done;
     }
 
     SSL_SetPKCS11PinArg(s, &pwdata);
 
     serverCertAuth.dbHandle = CERT_GetDefaultCertDB();
 
     SSL_AuthCertificateHook(s, ownAuthCertificate, &serverCertAuth);
     if (override) {
@@ -1506,39 +1528,43 @@ main(int argc, char **argv)
             pollset[SSOCK_FD].fd = s;
             while (1) {
                 FPRINTF(stderr,
                         "%s: about to call PR_Poll for connect completion!\n",
                         progName);
                 filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
                 if (filesReady < 0) {
                     SECU_PrintError(progName, "unable to connect (poll)");
-                    return 1;
+                    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);
-                    return 1;
+                    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)");
-                    return 1;
+                    error = 1;
+                    goto done;
                 }
                 SECU_PrintError(progName, "poll");
                 milliPause(50 * multiplier);
             }
         } else {
             SECU_PrintError(progName, "unable to connect");
-            return 1;
+            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;
@@ -1606,17 +1632,18 @@ main(int argc, char **argv)
         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);
-            return 1;
+            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) {
@@ -1733,18 +1760,23 @@ done:
     if (nickname) {
         PORT_Free(nickname);
     }
     if (pwdata.data) {
         PORT_Free(pwdata.data);
     }
     PORT_Free(host);
 
-    PR_Close(s);
-    SSL_ClearSessionCache();
-    if (NSS_Shutdown() != SECSuccess) {
-        exit(1);
+    if (s) {
+        PR_Close(s);
+    }
+
+    if (NSS_IsInitialized()) {
+        SSL_ClearSessionCache();
+        if (NSS_Shutdown() != SECSuccess) {
+            error = 1;
+        }
     }
 
     FPRINTF(stderr, "tstclnt: exiting with return code %d\n", error);
     PR_Cleanup();
     return error;
 }
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
deleted file mode 100755
--- a/security/nss/coverage/cov.sh
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/bin/bash
-#
-# 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/.
-
-OS=`uname -s`
-ARCH=`uname -p`
-SCRIPT_DIR=`pwd`
-DATE=`date +%Y%m%d`
-
-if [ $# -ne 1 ]; then
-    echo "Usage: $0 [securitytip|securityjes5]"
-    exit 1
-fi
-
-BRANCH="$1"
-
-if [ "${BRANCH}" != "securitytip" -a "${BRANCH}" != "securityjes5" ]; then
-    echo "Usage: $0 [securitytip|securityjes5]"
-    exit 1
-fi
-
-COV_DIR="/share/builds/mccrel3/security/coverage"
-BRANCH_DIR="${COV_DIR}/${BRANCH}"
-DATE_DIR="${BRANCH_DIR}/${DATE}-${ARCH}"
-CVS_DIR="${DATE_DIR}/cvs_mozilla"
-TCOV_DIR="${DATE_DIR}/tcov_mozilla"
-
-CVS_CHECKOUT_BRANCH="cvs_checkout_${BRANCH}"
-
-export HOST=`hostname`
-export DOMSUF=red.iplanet.com
-
-export NSS_ECC_MORE_THAN_SUITE_B=1
-export IOPR_HOSTADDR_LIST="dochinups.red.iplanet.com"
-export NSS_AIA_PATH="/share/builds/mccrel3/security/aia_certs"
-export NSS_AIA_HTTP="http://cindercone.red.iplanet.com/share/builds/mccrel3/security/aia_certs"
-
-export USE_TCOV=1
-export SUN_PROFDATA_DIR="${DATE_DIR}"
-export SUN_PROFDATA="tcov_data"
-
-if [ "${OS}" != "SunOS" ]; then
-    echo "OS not supported"
-    exit 1
-fi
-
-case "${ARCH}" in 
-"sparc")
-    export PATH="/usr/dist/share/sunstudio_sparc,v12.0/SUNWspro/prod/bin:/usr/sfw/bin:/usr/bin:/usr/ccs/bin:/usr/ucb:/tools/ns/bin:/usr/local/bin"
-    ;;
-"i386")
-    export PATH="/usr/dist/share/sunstudio_i386,v12.0/SUNWspro/bin:/usr/sfw/bin:/usr/bin:/usr/ccs/bin:/usr/ucb:/tools/ns/bin:/usr/local/bin"
-    ;;
-*)
-    echo "Platform not supported"
-    exit 1
-    ;;
-esac
-
-cvs_checkout_securitytip()
-{
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A mozilla/nsprpub
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A mozilla/dbm
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A mozilla/security/dbm
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A mozilla/security/coreconf
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A mozilla/security/nss
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A mozilla/security/jss
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A -r NSS_3_11_1_RTM mozilla/security/nss/lib/freebl/ecl/ecl-curve.h
-}
-
-cvs_checkout_securityjes5()
-{
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A -r NSPR_4_6_BRANCH mozilla/nsprpub
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A -r NSS_3_11_BRANCH mozilla/dbm
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A -r NSS_3_11_BRANCH mozilla/security/dbm
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A -r NSS_3_11_BRANCH mozilla/security/coreconf
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A -r NSS_3_11_BRANCH mozilla/security/nss
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A -r JSS_4_2_BRANCH mozilla/security/jss
-    cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -A -r NSS_3_11_1_RTM mozilla/security/nss/lib/freebl/ecl/ecl-curve.h
-}
-
-cvs_checkout()
-{
-    rm -rf "${DATE_DIR}"
-    mkdir -p "${CVS_DIR}"
-    cd "${CVS_DIR}"
-
-    ${CVS_CHECKOUT_BRANCH}
-}
-
-run_build()
-{
-    cd "${CVS_DIR}/mozilla/security/nss"
-    gmake nss_build_all
-}
-
-run_tests()
-{
-    cd "${CVS_DIR}/mozilla/security/nss/tests"
-    ./all.sh
-}
-
-process_results()
-{
-    rm -rf "${TCOV_DIR}"
-    mkdir -p "${TCOV_DIR}"
-
-    cat "${SUN_PROFDATA_DIR}/${SUN_PROFDATA}/tcovd" | grep SRCFILE | grep "${CVS_DIR}/.*.c$" | sed "s:[^/]*\(.*\):\1:" | sort -u |
-    while read line
-    do
-	DIR=`echo "${line}" | sed "s:${CVS_DIR}/\(.*\)/.*:\1:"`
-	FILE=`echo "${line}" | sed "s:.*/\(.*\):\1:"`
-
-	mkdir -p "${TCOV_DIR}/${DIR}"
-	tcov -o "${TCOV_DIR}/${DIR}/$FILE" -x "${SUN_PROFDATA}" $line >/dev/null 2>&1
-    done
-}
-
-cvs_checkout
-run_build
-run_tests
-process_results
-
-cd "${SCRIPT_DIR}"
-./report.sh "${BRANCH}" "${DATE}" "${ARCH}"  
-
-exit 0
-
deleted file mode 100755
--- a/security/nss/coverage/report.sh
+++ /dev/null
@@ -1,206 +0,0 @@
-#!/bin/bash
-#
-# 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/.
-
-OS=`uname -s`
-ARCH=`uname -p`
-SCRIPT_DIR=`pwd`
-DATE=`date +%Y-%m-%d`
-
-if [ $# -lt 1 -o $# -gt 3 ]; then
-    echo "Usage: $0 [securitytip|securityjes5] <date> <architecture>"
-    exit 1
-fi
-
-BRANCH="$1"
-
-if [ "${BRANCH}" != "securitytip" -a "${BRANCH}" != "securityjes5" ]; then
-    echo "Usage: $0 [securitytip|securityjes5] <date> <architecture>"
-    exit 1
-fi
-
-if [ $# -ge 2 ]; then
-    DATE=$2
-fi
-
-if [ $# -ge 3 ]; then
-    ARCH=$3
-fi
-
-HEADER="Code Coverage - NSS - ${BRANCH} - ${OS}/${ARCH} - ${DATE}"
-
-COV_DIR="/share/builds/mccrel3/security/coverage"
-BRANCH_DIR="${COV_DIR}/${BRANCH}"
-DATE_DIR="${BRANCH_DIR}/${DATE}-${ARCH}"
-CVS_DIR="${DATE_DIR}/cvs_mozilla"
-TCOV_DIR="${DATE_DIR}/tcov_mozilla"
-OUTPUT="${DATE_DIR}/nss.html"
-
-LIB_PATH="/mozilla/security/nss/lib"
-CVS_PATH="${CVS_DIR}${LIB_PATH}"
-TCOV_PATH="${TCOV_DIR}${LIB_PATH}"
-
-MIN_GREEN=70
-MIN_YELLOW=40
-
-print_header()
-{
-    echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final\">" 
-    echo "<HTML><HEAD><TITLE>${HEADER}</TITLE></HEAD><BODY>" 
-    echo "<TABLE ALIGN=\"CENTER\" WIDTH=\"100%\">"
-    echo "<TR><TH BGCOLOR=\"GREY\"><H2>${HEADER}</H2></TH></TR>"
-    echo "</TABLE><BR>"
-}
-
-print_footer()
-{
-    echo "</BODY></HTML>"
-}
-
-print_notes()
-{
-    echo "<TABLE ALIGN=\"CENTER\" WIDTH=\"100%\">"
-    echo "<TR ALIGN=\"CENTER\" BGCOLOR=\"LIGHTGREY\"><TD><A HREF=\"http://wikihome.sfbay.sun.com/jes-security/Wiki.jsp?page=Code_Coverage_Test_Execution\">Test Execution Notes</A></TD></TR>"
-    echo "</TABLE><BR>"
-}
-
-print_legend()
-{
-    echo "<TABLE ALIGN=\"CENTER\" WIDTH=\"100%\">"
-    echo "<TR ALIGN=\"CENTER\" BGCOLOR=\"GREY\"><TH>Legend</TH></TR>"
-    echo "<TR ALIGN=\"CENTER\" BGCOLOR=\"LIGHTGREEN\"><TD>${MIN_GREEN}% - 100% of blocks tested</TD></TR>"
-    echo "<TR ALIGN=\"CENTER\" BGCOLOR=\"YELLOW\"><TD>${MIN_YELLOW}% - ${MIN_GREEN}% of blocks tested</TD></TR>"
-    echo "<TR ALIGN=\"CENTER\" BGCOLOR=\"ORANGE\"><TD>0% - ${MIN_YELLOW}% of blocks tested</TD></TR>"
-    echo "<TR ALIGN=\"CENTER\" BGCOLOR=\"RED\"><TD>File not tested (these files are not included into statistics)</TD></TR>"
-    echo "</TABLE>"
-}
-
-set_color()
-{
-    if [ ${PERCENT_INT} -le ${MIN_YELLOW} ]; then
-        bgcolor="ORANGE"
-    elif [ ${PERCENT_INT} -le ${MIN_GREEN} ]; then
-        bgcolor="YELLOW"
-    else
-        bgcolor="LIGHTGREEN"
-    fi    
-}
-
-create_table()
-{
-    echo "<TABLE ALIGN=\"CENTER\" WIDTH=\"100%\">"
-    echo "<TR><TH BGCOLOR=\"GREY\" COLSPAN=\"2\">${DIR}</TH></TR>"
-    echo "<TR BGCOLOR=\"DARKGREY\"><TH WIDTH=\"50%\">File</TH>"
-    echo "<TH>Tested blocks (Tested blocks/Total blocks/Total lines)</TR>"
-}
-
-close_table()
-{
-    if [ "${LASTDIR}" != "" ]; then
-        if [ ${DFILES} -gt 0 ]; then
-            if [ ${DBLOCKS_TOTAL} -eq 0 ]; then
-                PERCENT_INT=0
-            else
-                PERCENT_INT=`expr ${DBLOCKS_EXEC} \* 100 \/ ${DBLOCKS_TOTAL}`
-            fi
-            set_color
-
-            echo "<TR><TH BGCOLOR=\"${bgcolor}\" COLSPAN=\"2\">Total: ${PERCENT_INT}% (${DBLOCKS_EXEC}/${DBLOCKS_TOTAL})</TH></TR>"
-        else
-            echo "<TR><TH BGCOLOR=\"RED\" COLSPAN=\"2\">Total: Not tested</TH></TR>"
-        fi
-        echo "</TABLE><BR>"
-    fi
-}
-
-print_line()
-{
-    LINES_TOTAL=`wc -l "${file}" | /usr/bin/awk '{print $1}'`
-
-    if [ -r "${TCOV_PATH}/${DIR}/${FILE}" ]; then
-        BLOCKS_EXEC=`cat "${TCOV_PATH}/${DIR}/${FILE}" | grep "Basic blocks executed" | /usr/bin/awk '{print $1}'`
-        BLOCKS_TOTAL=`cat "${TCOV_PATH}/${DIR}/${FILE}" | grep "Basic blocks in this file" | /usr/bin/awk '{print $1}'`
-
-        DBLOCKS_EXEC=`expr ${DBLOCKS_EXEC} + ${BLOCKS_EXEC}`
-        DBLOCKS_TOTAL=`expr ${DBLOCKS_TOTAL} + ${BLOCKS_TOTAL}`
-        TBLOCKS_EXEC=`expr ${TBLOCKS_EXEC} + ${BLOCKS_EXEC}`
-        TBLOCKS_TOTAL=`expr ${TBLOCKS_TOTAL} + ${BLOCKS_TOTAL}`
-
-        TFILES=`expr ${TFILES} + 1`
-        DFILES=`expr ${DFILES} + 1`
-
-        PERCENT_EXEC=`cat "${TCOV_PATH}/${DIR}/${FILE}" | grep "Percent of the file executed" | /usr/bin/awk '{print $1}'`
-        PERCENT_INT=`echo ${PERCENT_EXEC} | cut -d. -f1`
-        set_color
-
-        echo "<TR><TD BGCOLOR=\"LIGHTGREY\"><A HREF=\"${TCOV_PATH}/${DIR}/${FILE}\">${FILE}</A></TD>"
-        echo "<TD BGCOLOR=\"${bgcolor}\">${PERCENT_EXEC}% (${BLOCKS_EXEC}/${BLOCKS_TOTAL}/${LINES_TOTAL})</TD></TR>"
-    else
-        echo "<TR><TD BGCOLOR=\"LIGHTGREY\"><A HREF=\"${file}\">${FILE}</A></TD>"
-        echo "<TD BGCOLOR=\"RED\">Not tested (0/?/${LINES_TOTAL})</TD></TR>"
-    fi
-}
-
-print_total()
-{
-    echo "<TABLE ALIGN=\"CENTER\" WIDTH=\"100%\">"
-    if [ ${TFILES} -gt 0 ]; then
-        if [ ${TBLOCKS_TOTAL} -eq 0 ]; then
-            PERCENT_INT=0
-        else
-            PERCENT_INT=`expr ${TBLOCKS_EXEC} \* 100 \/ ${TBLOCKS_TOTAL}`
-        fi
-        set_color
-
-        echo "<TR><TH BGCOLOR=\"${bgcolor}\"><H2>Total: ${PERCENT_INT}% (${TBLOCKS_EXEC}/${TBLOCKS_TOTAL})</H2></TH></TR>"
-    else
-        echo "<TR><TH BGCOLOR=\"RED\"><H2>Total: Not tested</H2></TH></TR>"
-    fi
-    echo "</TABLE><BR>"
-}
-
-process_cmd()
-{
-    LASTDIR=""
-    TBLOCKS_EXEC=0
-    TBLOCKS_TOTAL=0
-    TFILES=0
-
-    for dir in `find "${CVS_PATH}" -type d | sort`
-    do
-        DIR=`echo "${dir}" | sed "s:^${CVS_PATH}/::"`
-        for file in `ls -1 ${dir}/*.c 2> /dev/null`
-        do 
-            if [ "${DIR}" != "${LASTDIR}" ]; then
-                close_table
-                create_table 
-
-                LASTDIR="${DIR}";
-                DBLOCKS_EXEC=0
-                DBLOCKS_TOTAL=0
-                DFILES=0
-            fi
-
-            FILE=`echo "${file}" | sed "s:^.*/\(.*.c\):\1:"`
-            print_line
-        done
-    done
-
-    close_table
-    print_total
-}
-
-report()
-{
-    print_header > "${OUTPUT}"
-    print_notes >> "${OUTPUT}"
-    process_cmd >> "${OUTPUT}"
-    print_legend >> "${OUTPUT}"
-    print_footer >> "${OUTPUT}"
-}
-
-report
-
-exit 0
--- a/security/nss/external_tests/ssl_gtest/libssl_internals.c
+++ b/security/nss/external_tests/ssl_gtest/libssl_internals.c
@@ -179,25 +179,26 @@ PRBool sslint_DamageTrafficSecret(PRFile
   sslSocket *ss = ssl_FindSocket(fd);
   if (!ss) {
     return PR_FALSE;
   }
   if (!slot) {
     return PR_FALSE;
   }
   keyPtr = (PK11SymKey **)((char *)&ss->ssl3.hs + offset);
-  if (!keyPtr)
+  if (!*keyPtr) {
     return PR_FALSE;
+  }
   PK11_FreeSymKey(*keyPtr);
-  *keyPtr = PK11_ImportSymKey(slot,
-                              CKM_NSS_HKDF_SHA256, PK11_OriginUnwrap,
+  *keyPtr = PK11_ImportSymKey(slot, CKM_NSS_HKDF_SHA256, PK11_OriginUnwrap,
                               CKA_DERIVE, &key_item, NULL);
   PK11_FreeSlot(slot);
-  if (!*keyPtr)
+  if (!*keyPtr) {
     return PR_FALSE;
+  }
 
   return PR_TRUE;
 }
 
 
 PRBool SSLInt_DamageHsTrafficSecret(PRFileDesc *fd)
 {
   return sslint_DamageTrafficSecret(
--- a/security/nss/external_tests/ssl_gtest/ssl_dhe_unittest.cc
+++ b/security/nss/external_tests/ssl_gtest/ssl_dhe_unittest.cc
@@ -5,47 +5,157 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "secerr.h"
 #include "ssl.h"
 #include "sslerr.h"
 #include "sslproto.h"
 #include <memory>
 #include <functional>
+#include <set>
 
 #include "scoped_ptrs.h"
 #include "tls_parser.h"
 #include "tls_filter.h"
 #include "tls_connect.h"
 #include "gtest_utils.h"
 
 namespace nss_test {
 
 TEST_P(TlsConnectGeneric, ConnectDhe) {
   EnableOnlyDheCiphers();
   Connect();
   CheckKeys(ssl_kea_dh, ssl_auth_rsa_sign);
 }
 
+// Track groups and make sure that there are no duplicates.
+class CheckDuplicateGroup {
+ public:
+  void AddAndCheckGroup(uint16_t group) {
+    EXPECT_EQ(groups_.end(), groups_.find(group))
+        << "Group " << group << " should not be duplicated";
+    groups_.insert(group);
+  }
+
+ private:
+  std::set<uint16_t> groups_;
+};
+
+// Check the group of each of the supported groups
+static void CheckGroups(const DataBuffer& groups,
+                        std::function<void(uint16_t)> check_group) {
+  CheckDuplicateGroup group_set;
+  uint32_t tmp;
+  EXPECT_TRUE(groups.Read(0, 2, &tmp));
+  EXPECT_EQ(groups.len() - 2, static_cast<size_t>(tmp));
+  for (size_t i = 2; i < groups.len(); i += 2) {
+    EXPECT_TRUE(groups.Read(i, 2, &tmp));
+    uint16_t group = static_cast<uint16_t>(tmp);
+    group_set.AddAndCheckGroup(group);
+    check_group(group);
+  }
+}
+
+// Check the group of each of the shares
+static void CheckShares(const DataBuffer& shares,
+                        std::function<void(uint16_t)> check_group) {
+  CheckDuplicateGroup group_set;
+  uint32_t tmp;
+  EXPECT_TRUE(shares.Read(0, 2, &tmp));
+  EXPECT_EQ(shares.len() - 2, static_cast<size_t>(tmp));
+  size_t i;
+  for(i = 2; i < shares.len(); i += 4 + tmp) {
+    ASSERT_TRUE(shares.Read(i, 2, &tmp));
+    uint16_t group = static_cast<uint16_t>(tmp);
+    group_set.AddAndCheckGroup(group);
+    check_group(group);
+    ASSERT_TRUE(shares.Read(i + 2, 2, &tmp));
+  }
+  EXPECT_EQ(shares.len(), i);
+}
+
+#ifdef NSS_ENABLE_TLS_1_3
+TEST_P(TlsConnectTls13, SharesForBothEcdheAndDhe) {
+  EnsureTlsSetup();
+  client_->DisableAllCiphers();
+  client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
+  client_->EnableCiphersByKeyExchange(ssl_kea_dh);
+
+  auto groups_capture = new TlsExtensionCapture(ssl_supported_groups_xtn);
+  auto shares_capture = new TlsExtensionCapture(ssl_tls13_key_share_xtn);
+  std::vector<PacketFilter*> captures;
+  captures.push_back(groups_capture);
+  captures.push_back(shares_capture);
+  client_->SetPacketFilter(new ChainedPacketFilter(captures));
+
+  Connect();
+
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+
+  bool ec, dh;
+  auto track_group_type = [&ec, &dh](uint16_t group) {
+    if ((group & 0xff00U) == 0x100U) {
+      dh = true;
+    } else {
+      ec = true;
+    }
+  };
+  CheckGroups(groups_capture->extension(), track_group_type);
+  CheckShares(shares_capture->extension(), track_group_type);
+  EXPECT_TRUE(ec) << "Should include an EC group and share";
+  EXPECT_TRUE(dh) << "Should include an FFDHE group and share";
+}
+
+TEST_P(TlsConnectTls13, NoDheOnEcdheConnections) {
+  EnsureTlsSetup();
+  client_->DisableAllCiphers();
+  client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
+
+  auto groups_capture = new TlsExtensionCapture(ssl_supported_groups_xtn);
+  auto shares_capture = new TlsExtensionCapture(ssl_tls13_key_share_xtn);
+  std::vector<PacketFilter*> captures;
+  captures.push_back(groups_capture);
+  captures.push_back(shares_capture);
+  client_->SetPacketFilter(new ChainedPacketFilter(captures));
+
+  Connect();
+
+  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
+  auto is_ecc = [](uint16_t group) {
+                EXPECT_NE(0x100U, group & 0xff00U);
+  };
+  CheckGroups(groups_capture->extension(), is_ecc);
+  CheckShares(shares_capture->extension(), is_ecc);
+}
+#endif
+
 TEST_P(TlsConnectGeneric, ConnectFfdheClient) {
   EnableOnlyDheCiphers();
   EXPECT_EQ(SECSuccess,
             SSL_OptionSet(client_->ssl_fd(),
                           SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE));
-  auto clientCapture = new TlsExtensionCapture(ssl_supported_groups_xtn);
-  client_->SetPacketFilter(clientCapture);
+  auto groups_capture = new TlsExtensionCapture(ssl_supported_groups_xtn);
+  auto shares_capture = new TlsExtensionCapture(ssl_tls13_key_share_xtn);
+  std::vector<PacketFilter*> captures;
+  captures.push_back(groups_capture);
+  captures.push_back(shares_capture);
+  client_->SetPacketFilter(new ChainedPacketFilter(captures));
 
   Connect();
 
   CheckKeys(ssl_kea_dh, ssl_auth_rsa_sign);
-
-  // Extension value: length + FFDHE 2048 group identifier.
-  const uint8_t val[] = { 0x00, 0x02, 0x01, 0x00 };
-  DataBuffer expected_groups(val, sizeof(val));
-  EXPECT_EQ(expected_groups, clientCapture->extension());
+  auto is_ffdhe_2048 = [](uint16_t group) {
+    EXPECT_EQ(0x100U, group);
+  };
+  CheckGroups(groups_capture->extension(), is_ffdhe_2048);
+  if (version_ == SSL_LIBRARY_VERSION_TLS_1_3) {
+    CheckShares(shares_capture->extension(), is_ffdhe_2048);
+  } else {
+    EXPECT_EQ(0U, shares_capture->extension().len());
+  }
 }
 
 // Requiring the FFDHE extension on the server alone means that clients won't be
 // able to connect using a DHE suite.  They should still connect in TLS 1.3,
 // because the client automatically sends the supported groups extension.
 TEST_P(TlsConnectGenericPre13, ConnectFfdheServer) {
   EnableOnlyDheCiphers();
   EXPECT_EQ(SECSuccess,
@@ -407,39 +517,30 @@ TEST_P(TlsConnectGenericPre13, WeakDHGro
             SSL_OptionSet(client_->ssl_fd(),
                           SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE));
   EXPECT_EQ(SECSuccess,
             SSL_EnableWeakDHEPrimeGroup(server_->ssl_fd(), PR_TRUE));
 
   Connect();
 }
 
-#ifdef NSS_ENABLE_TLS_1_3
-
-// In the absence of HelloRetryRequest, enabling only the 3072-bit group causes
-// the TLS 1.3 handshake to fail because the client will only add the 2048-bit
-// group to its ClientHello.
-TEST_P(TlsConnectTls13, DisableFfdhe2048) {
+TEST_P(TlsConnectGeneric, Ffdhe3072) {
   EnableOnlyDheCiphers();
   static const SSLDHEGroupType groups[] = { ssl_ff_dhe_3072_group };
   EXPECT_EQ(SECSuccess,
             SSL_DHEGroupPrefSet(client_->ssl_fd(), groups,
                                 PR_ARRAY_SIZE(groups)));
   EXPECT_EQ(SECSuccess,
             SSL_DHEGroupPrefSet(server_->ssl_fd(), groups,
                                 PR_ARRAY_SIZE(groups)));
-  EXPECT_EQ(SECSuccess,
-            SSL_OptionSet(server_->ssl_fd(),
-                          SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE));
 
-  ConnectExpectFail();
+  Connect();
+}
 
-  server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
-  client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
-}
+#ifdef NSS_ENABLE_TLS_1_3
 
 TEST_P(TlsConnectTls13, ResumeFfdhe) {
   EnableOnlyDheCiphers();
   ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
   Connect();
   SendReceive(); // Need to read so that we absorb the session ticket.
   CheckKeys(ssl_kea_dh, ssl_auth_rsa_sign);
 
--- a/security/nss/external_tests/ssl_gtest/tls_agent.cc
+++ b/security/nss/external_tests/ssl_gtest/tls_agent.cc
@@ -182,16 +182,18 @@ bool TlsAgent::GetClientAuthCredentials(
   return true;
 }
 
 SECStatus TlsAgent::GetClientAuthDataHook(void* self, PRFileDesc* fd,
                                           CERTDistNames* caNames,
                                           CERTCertificate** cert,
                                           SECKEYPrivateKey** privKey) {
   TlsAgent* agent = reinterpret_cast<TlsAgent*>(self);
+  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;
 }
 
 
 void TlsAgent::RequestClientAuth(bool requireAuth) {
--- a/security/nss/lib/freebl/ecl/ecl_gf.c
+++ b/security/nss/lib/freebl/ecl/ecl_gf.c
@@ -798,16 +798,17 @@ ec_GFp_sub_5(const mp_int *a, const mp_i
 	 	b2 = MP_DIGIT(&meth->irr,2);
 		b1 = MP_DIGIT(&meth->irr,1);
 		b0 = MP_DIGIT(&meth->irr,0);
                 borrow = 0;
 		MP_ADD_CARRY(b0, r0, r0, borrow);
 		MP_ADD_CARRY(b1, r1, r1, borrow);
 		MP_ADD_CARRY(b2, r2, r2, borrow);
 		MP_ADD_CARRY(b3, r3, r3, borrow);
+		MP_ADD_CARRY(b4, r4, r4, borrow);
 	}
 	MP_CHECKOK(s_mp_pad(r, 5));
 	MP_DIGIT(r, 4) = r4;
 	MP_DIGIT(r, 3) = r3;
 	MP_DIGIT(r, 2) = r2;
 	MP_DIGIT(r, 1) = r1;
 	MP_DIGIT(r, 0) = r0;
 	MP_SIGN(r) = MP_ZPOS;
@@ -875,16 +876,17 @@ ec_GFp_sub_6(const mp_int *a, const mp_i
 		b1 = MP_DIGIT(&meth->irr,1);
 		b0 = MP_DIGIT(&meth->irr,0);
                 borrow = 0;
 		MP_ADD_CARRY(b0, r0, r0, borrow);
 		MP_ADD_CARRY(b1, r1, r1, borrow);
 		MP_ADD_CARRY(b2, r2, r2, borrow);
 		MP_ADD_CARRY(b3, r3, r3, borrow);
 		MP_ADD_CARRY(b4, r4, r4, borrow);
+		MP_ADD_CARRY(b5, r5, r5, borrow);
 	}
 
 	MP_CHECKOK(s_mp_pad(r, 6));
 	MP_DIGIT(r, 5) = r5;
 	MP_DIGIT(r, 4) = r4;
 	MP_DIGIT(r, 3) = r3;
 	MP_DIGIT(r, 2) = r2;
 	MP_DIGIT(r, 1) = r1;
--- a/security/nss/lib/freebl/ecl/ecp_256.c
+++ b/security/nss/lib/freebl/ecl/ecp_256.c
@@ -69,98 +69,107 @@ ec_GFp_nistp256_mod(const mp_int *a, mp_
 
 		/* sum 1 */
                 carry = 0;
 		MP_ADD_CARRY(r3, a11, r3, carry);
 		MP_ADD_CARRY(r4, a12, r4, carry);
 		MP_ADD_CARRY(r5, a13, r5, carry);
 		MP_ADD_CARRY(r6, a14, r6, carry);
 		MP_ADD_CARRY(r7, a15, r7, carry);
-		r8 = carry; carry = 0;
+		r8 = carry;
+		carry = 0;
 		MP_ADD_CARRY(r3, a11, r3, carry);
 		MP_ADD_CARRY(r4, a12, r4, carry);
 		MP_ADD_CARRY(r5, a13, r5, carry);
 		MP_ADD_CARRY(r6, a14, r6, carry);
 		MP_ADD_CARRY(r7, a15, r7, carry);
-		r8 += carry; carry = 0;
+		r8 += carry;
+		carry = 0;
 		/* sum 2 */
 		MP_ADD_CARRY(r3, a12, r3, carry);
 		MP_ADD_CARRY(r4, a13, r4, carry);
 		MP_ADD_CARRY(r5, a14, r5, carry);
 		MP_ADD_CARRY(r6, a15, r6, carry);
 		MP_ADD_CARRY(r7,   0, r7, carry);
-		r8 += carry; carry = 0;
+		r8 += carry;
+		carry = 0;
 		/* combine last bottom of sum 3 with second sum 2 */
 		MP_ADD_CARRY(r0, a8,  r0, carry);
 		MP_ADD_CARRY(r1, a9,  r1, carry);
 		MP_ADD_CARRY(r2, a10, r2, carry);
 		MP_ADD_CARRY(r3, a12, r3, carry);
 		MP_ADD_CARRY(r4, a13, r4, carry);
 		MP_ADD_CARRY(r5, a14, r5, carry);
 		MP_ADD_CARRY(r6, a15, r6, carry);
 		MP_ADD_CARRY(r7, a15, r7, carry); /* from sum 3 */
-		r8 += carry; carry = 0;
+		r8 += carry;
+		carry = 0;
 		/* sum 3 (rest of it)*/
 		MP_ADD_CARRY(r6, a14, r6, carry);
 		MP_ADD_CARRY(r7,   0, r7, carry);
-		r8 += carry; carry = 0;
+		r8 += carry;
+		carry = 0;
 		/* sum 4 (rest of it)*/
 		MP_ADD_CARRY(r0, a9,  r0, carry);
 		MP_ADD_CARRY(r1, a10, r1, carry);
 		MP_ADD_CARRY(r2, a11, r2, carry);
 		MP_ADD_CARRY(r3, a13, r3, carry);
 		MP_ADD_CARRY(r4, a14, r4, carry);
 		MP_ADD_CARRY(r5, a15, r5, carry);
 		MP_ADD_CARRY(r6, a13, r6, carry);
 		MP_ADD_CARRY(r7, a8,  r7, carry);
-		r8 += carry; carry = 0;
+		r8 += carry;
+		carry = 0;
 		/* diff 5 */
 		MP_SUB_BORROW(r0, a11, r0, carry);
 		MP_SUB_BORROW(r1, a12, r1, carry);
 		MP_SUB_BORROW(r2, a13, r2, carry);
 		MP_SUB_BORROW(r3,   0, r3, carry);
 		MP_SUB_BORROW(r4,   0, r4, carry);
 		MP_SUB_BORROW(r5,   0, r5, carry);
 		MP_SUB_BORROW(r6, a8,  r6, carry);
 		MP_SUB_BORROW(r7, a10, r7, carry);
-		r8 -= carry; carry = 0;
+		r8 -= carry;
+		carry = 0;
 		/* diff 6 */
 		MP_SUB_BORROW(r0, a12, r0, carry);
 		MP_SUB_BORROW(r1, a13, r1, carry);
 		MP_SUB_BORROW(r2, a14, r2, carry);
 		MP_SUB_BORROW(r3, a15, r3, carry);
 		MP_SUB_BORROW(r4,   0, r4, carry);
 		MP_SUB_BORROW(r5,   0, r5, carry);
 		MP_SUB_BORROW(r6, a9,  r6, carry);
 		MP_SUB_BORROW(r7, a11, r7, carry);
-		r8 -= carry; carry = 0;
+		r8 -= carry;
+		carry = 0;
 		/* diff 7 */
 		MP_SUB_BORROW(r0, a13, r0, carry);
 		MP_SUB_BORROW(r1, a14, r1, carry);
 		MP_SUB_BORROW(r2, a15, r2, carry);
 		MP_SUB_BORROW(r3, a8,  r3, carry);
 		MP_SUB_BORROW(r4, a9,  r4, carry);
 		MP_SUB_BORROW(r5, a10, r5, carry);
 		MP_SUB_BORROW(r6, 0,   r6, carry);
 		MP_SUB_BORROW(r7, a12, r7, carry);
-		r8 -= carry; carry = 0;
+		r8 -= carry;
+		carry = 0;
 		/* diff 8 */
 		MP_SUB_BORROW(r0, a14, r0, carry);
 		MP_SUB_BORROW(r1, a15, r1, carry);
 		MP_SUB_BORROW(r2, 0,   r2, carry);
 		MP_SUB_BORROW(r3, a9,  r3, carry);
 		MP_SUB_BORROW(r4, a10, r4, carry);
 		MP_SUB_BORROW(r5, a11, r5, carry);
 		MP_SUB_BORROW(r6, 0,   r6, carry);
 		MP_SUB_BORROW(r7, a13, r7, carry);
 		r8 -= carry;
 
 		/* reduce the overflows */
 		while (r8 > 0) {
-			mp_digit r8_d = r8; carry = 0;
+			mp_digit r8_d = r8;
 			carry = 0;
 			MP_ADD_CARRY(r0, r8_d,         r0, carry);
 			MP_ADD_CARRY(r1, 0,            r1, carry);
 			MP_ADD_CARRY(r2, 0,            r2, carry);
 			MP_ADD_CARRY(r3, 0-r8_d,       r3, carry);
 			MP_ADD_CARRY(r4, MP_DIGIT_MAX, r4, carry);
 			MP_ADD_CARRY(r5, MP_DIGIT_MAX, r5, carry);
 			MP_ADD_CARRY(r6, 0-(r8_d+1),   r6, carry);
@@ -228,45 +237,44 @@ ec_GFp_nistp256_mod(const mp_int *a, mp_
 		a4h = a4 >> 32;
 		r3 = MP_DIGIT(a,3);
 		r2 = MP_DIGIT(a,2);
 		r1 = MP_DIGIT(a,1);
 		r0 = MP_DIGIT(a,0);
 
 		/* sum 1 */
                 carry = 0;
+		MP_ADD_CARRY(r1, a5h << 32, r1, carry);
+		MP_ADD_CARRY(r2, a6,        r2, carry);
+		MP_ADD_CARRY(r3, a7,        r3, carry);
+		r4 = carry;
 		carry = 0;
 		MP_ADD_CARRY(r1, a5h << 32, r1, carry);
 		MP_ADD_CARRY(r2, a6,        r2, carry);
 		MP_ADD_CARRY(r3, a7,        r3, carry);
-		r4 = carry; carry = 0;
-		carry = 0;
-		MP_ADD_CARRY(r1, a5h << 32, r1, carry);
-		MP_ADD_CARRY(r2, a6,        r2, carry);
-		MP_ADD_CARRY(r3, a7,        r3, carry);
-		r4 += carry; carry = 0;
+		r4 += carry;
 		/* sum 2 */
 		carry = 0;
 		MP_ADD_CARRY(r1, a6l,       r1, carry);
 		MP_ADD_CARRY(r2, a6h | a7l, r2, carry);
 		MP_ADD_CARRY(r3, a7h,       r3, carry);
-		r4 += carry; carry = 0;
+		r4 += carry;
 		carry = 0;
 		MP_ADD_CARRY(r1, a6l,       r1, carry);
 		MP_ADD_CARRY(r2, a6h | a7l, r2, carry);
 		MP_ADD_CARRY(r3, a7h,       r3, carry);
-		r4 += carry; carry = 0;
+		r4 += carry;
 
 		/* sum 3 */
 		carry = 0;
 		MP_ADD_CARRY(r0, a4,        r0, carry);
 		MP_ADD_CARRY(r1, a5l >> 32, r1, carry);
 		MP_ADD_CARRY(r2, 0,         r2, carry);
 		MP_ADD_CARRY(r3, a7,        r3, carry);
-		r4 += carry; carry = 0;
+		r4 += carry;
 		/* sum 4 */
 		carry = 0;
 		MP_ADD_CARRY(r0, a4h | a5l,     r0, carry);
 		MP_ADD_CARRY(r1, a5h|(a6h<<32), r1, carry);
 		MP_ADD_CARRY(r2, a7,            r2, carry);
 		MP_ADD_CARRY(r3, a6h | a4l,     r3, carry);
 		r4 += carry;
 		/* diff 5 */
@@ -298,17 +306,16 @@ ec_GFp_nistp256_mod(const mp_int *a, mp_
 		MP_SUB_BORROW(r3, a6h<<32,      r3, carry);
 		r4 -= carry;
 
 		/* reduce the overflows */
 		while (r4 > 0) {
 			mp_digit r4_long = r4;
 			mp_digit r4l = (r4_long << 32);
                         carry = 0;
-			carry = 0;
 			MP_ADD_CARRY(r0, r4_long,      r0, carry);
 			MP_ADD_CARRY(r1, 0-r4l,        r1, carry);
 			MP_ADD_CARRY(r2, MP_DIGIT_MAX, r2, carry);
 			MP_ADD_CARRY(r3, r4l-r4_long-1,r3, carry);
 			r4 = carry;
 		}
 
 		/* reduce the underflows */
--- a/security/nss/lib/freebl/lowhash_vector.c
+++ b/security/nss/lib/freebl/lowhash_vector.c
@@ -125,19 +125,23 @@ freebl_RunLoaderOnce( void )
 	}
   }
 
   return loadFreeBLOnce.status;
 }
 
 const FREEBLVector *FREEBL_GetVector(void)
 {
-  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
+  if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
       return NULL;
-  return (vector->p_FREEBL_GetVector)();
+  }
+  if (vector) {
+      return (vector->p_FREEBL_GetVector)();
+  }
+  return NULL;
 }
 
 NSSLOWInitContext *NSSLOW_Init(void) 
 {
   if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
       return NULL;
   return (vector->p_NSSLOW_Init)();
 }
--- a/security/nss/lib/freebl/mpi/mpi.c
+++ b/security/nss/lib/freebl/mpi/mpi.c
@@ -520,17 +520,17 @@ mp_err mp_mul_2(const mp_int *a, mp_int 
   single digit d.  Respects the sign of its divisor (single digits are
   unsigned anyway).
  */
 
 mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r)
 {
   mp_err   res;
   mp_int   qp;
-  mp_digit rem;
+  mp_digit rem = 0;
   int      pow;
 
   ARGCHK(a != NULL, MP_BADARG);
 
   if(d == 0)
     return MP_RANGE;
 
   /* Shortcut for powers of two ... */
@@ -556,18 +556,19 @@ mp_err mp_div_d(const mp_int *a, mp_digi
   if((res = mp_init_copy(&qp, a)) != MP_OKAY)
     return res;
 
   res = s_mp_div_d(&qp, d, &rem);
 
   if(s_mp_cmp_d(&qp, 0) == 0)
     SIGN(q) = ZPOS;
 
-  if(r)
+  if(r) {
     *r = rem;
+  }
 
   if(q)
     s_mp_exch(&qp, q);
 
   mp_clear(&qp);
   return res;
 
 } /* end mp_div_d() */
@@ -3285,17 +3286,17 @@ CLEANUP:
   single digit d.  If r is null, the remainder will be discarded.
  */
 
 mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r)
 {
 #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
   mp_word   w = 0, q;
 #else
-  mp_digit  w, q;
+  mp_digit  w = 0, q;
 #endif
   int       ix;
   mp_err    res;
   mp_int    quot;
   mp_int    rem;
 
   if(d == 0)
     return MP_RANGE;
@@ -3373,18 +3374,19 @@ mp_err   s_mp_div_d(mp_int *mp, mp_digit
 #if !defined(MP_ASSEMBLY_DIV_2DX1D)
     if (norm)
       w >>= norm;
 #endif
   }
 #endif
 
   /* Deliver the remainder, if desired */
-  if(r)
+  if(r) {
     *r = (mp_digit)w;
+  }
 
   s_mp_clamp(&quot);
   mp_exch(&quot, mp);
 CLEANUP:
   mp_clear(&quot);
   mp_clear(&rem);
 
   return res;
--- a/security/nss/lib/freebl/mpi/mplogic.c
+++ b/security/nss/lib/freebl/mpi/mplogic.c
@@ -405,17 +405,16 @@ mp_err mpl_get_bits(const mp_int *a, mp_
  */
 mp_size mpl_significant_bits(const mp_int *a)
 {
   mp_size bits = 0;
   int    ix;
 
   ARGCHK(a != NULL, MP_BADARG);
 
-  ix = MP_USED(a);
   for (ix = MP_USED(a); ix > 0; ) {
     mp_digit d;
     d = MP_DIGIT(a, --ix);
     if (d) {
       while (d) {
 	++bits;
 	d >>= 1;
       }
--- a/security/nss/lib/freebl/pqg.c
+++ b/security/nss/lib/freebl/pqg.c
@@ -171,19 +171,23 @@ getNextHash(HASH_HashType hashtype)
     }
     return hashtype;
 }
 
 static unsigned int
 HASH_ResultLen(HASH_HashType type)
 {
     const SECHashObject *hash_obj = HASH_GetRawHashObject(type);
+    PORT_Assert(hash_obj != NULL);
     if (hash_obj == NULL) {
-	return 0;
+        /* type is always a valid HashType. Thus a null hash_obj must be a bug */
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return 0;
     }
+    PORT_Assert(hash_obj->length != 0);
     return hash_obj->length;
 }
 
 static SECStatus
 HASH_HashBuf(HASH_HashType type, unsigned char *dest,
 	     const unsigned char *src, PRUint32 src_len)
 {
     const SECHashObject *hash_obj = HASH_GetRawHashObject(type);
--- a/security/nss/lib/freebl/rawhash.c
+++ b/security/nss/lib/freebl/rawhash.c
@@ -148,14 +148,14 @@ const SECHashObject SECRawHashObjects[] 
     (void (*)(void *, unsigned char *, unsigned int *,
 	      unsigned int)) SHA224_EndRaw
   },
 };
 
 const SECHashObject *
 HASH_GetRawHashObject(HASH_HashType hashType)
 {
-    if (hashType < HASH_AlgNULL || hashType >= HASH_AlgTOTAL) {
+    if (hashType <= HASH_AlgNULL || hashType >= HASH_AlgTOTAL) {
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	return NULL;
     }
     return &SECRawHashObjects[hashType];
 }
--- a/security/nss/lib/freebl/rsa.c
+++ b/security/nss/lib/freebl/rsa.c
@@ -548,17 +548,16 @@ rsa_get_primes_from_exponents(mp_int *e,
 	    /* we now have a candidate for the second prime */
 	    CHECK_MPI_OK(mp_add_d(&phi, 1, &tmp));
 	    
 	    /* check to make sure it is prime */
 	    err = rsa_is_prime(&tmp);
 	    if (err != MP_OKAY) {
 		if (err == MP_NO) {
 		    /* No, then we still have the wrong phi */
-		    err = MP_OKAY;
         	    continue;
 		}
 		goto cleanup;
 	    }
 	    /*
 	     * It is possible that we have the wrong phi if 
 	     * k_guess*(q_guess-1) = k*(q-1) (k and q-1 have swapped factors).
 	     * since our q_quess is prime, however. We have found a valid
@@ -1254,17 +1253,18 @@ get_blinding_params(RSAPrivateKey *key, 
 	    /* put the blinding parameter values into cache */
 	    CHECK_MPI_OK( mp_init( &bp->f) );
 	    CHECK_MPI_OK( mp_init( &bp->g) );
 	    CHECK_MPI_OK( mp_copy( f, &bp->f) );
 	    CHECK_MPI_OK( mp_copy( g, &bp->g) );
 
 	    /* Put this at head of queue of usable params. */
 	    PZ_Lock(blindingParamsList.lock);
-	    holdingLock = PR_TRUE;
+            holdingLock = PR_TRUE;
+            (void)holdingLock;
 	    /* initialize RSABlindingParamsStr */
 	    bp->counter = RSA_BLINDING_PARAMS_MAX_REUSE;
 	    bp->next    = rsabp->bp;
 	    rsabp->bp   = bp;
 	    bpUnlinked  = NULL;
 	    /* In case there're threads waiting for new blinding value
 	     * just notify them the value is ready
 	     */
@@ -1280,16 +1280,17 @@ get_blinding_params(RSAPrivateKey *key, 
 	 * actively having parameters generated for them.
 	 * So, we need to wait here and not eat up CPU until some 
 	 * change happens. 
 	 */
 	blindingParamsList.waitCount++;
 	PR_WaitCondVar( blindingParamsList.cVar, PR_INTERVAL_NO_TIMEOUT );
 	PZ_Unlock(blindingParamsList.lock); 
 	holdingLock = PR_FALSE;
+        (void)holdingLock;
     } while (1);
 
 cleanup:
     /* It is possible to reach this after the lock is already released.  */
     if (bpUnlinked) {
 	if (!holdingLock) {
 	    PZ_Lock(blindingParamsList.lock);
 	    holdingLock = PR_TRUE;
@@ -1299,17 +1300,16 @@ cleanup:
 	mp_clear( &bp->g );
 	bp->counter = 0;
     	/* Must put the unlinked bp back on the free list */
 	bp->next    = rsabp->free;
 	rsabp->free = bp;
     }
     if (holdingLock) {
 	PZ_Unlock(blindingParamsList.lock);
-	holdingLock = PR_FALSE;
     }
     if (err) {
 	MP_TO_SEC_ERROR(err);
     }
     return SECFailure;
 }
 
 /*
--- a/security/nss/lib/jar/jar.c
+++ b/security/nss/lib/jar/jar.c
@@ -75,16 +75,18 @@ JAR_destroy(JAR *jar)
         return;
 
     if (jar->fp)
         JAR_FCLOSE((PRFileDesc *)jar->fp);
     if (jar->url)
         PORT_Free(jar->url);
     if (jar->filename)
         PORT_Free(jar->filename);
+    if (jar->globalmeta)
+        PORT_Free(jar->globalmeta);
 
     /* Free the linked list elements */
     jar_destroy_list(jar->manifest);
     ZZ_DestroyList(jar->manifest);
     jar_destroy_list(jar->hashes);
     ZZ_DestroyList(jar->hashes);
     jar_destroy_list(jar->phy);
     ZZ_DestroyList(jar->phy);
--- a/security/nss/lib/jar/jarver.c
+++ b/security/nss/lib/jar/jarver.c
@@ -334,27 +334,30 @@ jar_parse_any(JAR *jar, int type, JAR_Si
             ADDITEM(jar->metainfo, jarTypeMeta,
                     /* pathname */ NULL, met, sizeof(JAR_Metainfo));
         }
 
         /* For SF files, this metadata may be the digests
            of the MF file, still in the "met" structure. */
 
         if (type == jarTypeSF) {
-            if (!PORT_Strcasecmp(line, "MD5-Digest"))
+            if (!PORT_Strcasecmp(line, "MD5-Digest")) {
                 sf_md5 = (char *)met->info;
-
-            if (!PORT_Strcasecmp(line, "SHA1-Digest") ||
-                !PORT_Strcasecmp(line, "SHA-Digest"))
+            } else if (!PORT_Strcasecmp(line, "SHA1-Digest") ||
+                       !PORT_Strcasecmp(line, "SHA-Digest")) {
                 sf_sha1 = (char *)met->info;
+            } else {
+                PORT_Free(met->info);
+                met->info = NULL;
+            }
         }
 
         if (type != jarTypeMF) {
             PORT_Free(met->header);
-            if (type != jarTypeSF) {
+            if ((type != jarTypeSF || !jar->globalmeta) && met->info) {
                 PORT_Free(met->info);
             }
             PORT_Free(met);
         }
     }
 
     if (type == jarTypeSF && jar->globalmeta) {
         /* this is a SF file which may contain a digest of the manifest.mf's
@@ -364,34 +367,38 @@ jar_parse_any(JAR *jar, int type, JAR_Si
         JAR_Digest *glob = jar->globalmeta;
 
         if (sf_md5) {
             unsigned int md5_length;
             unsigned char *md5_digest;
 
             md5_digest = ATOB_AsciiToData(sf_md5, &md5_length);
             PORT_Assert(md5_length == MD5_LENGTH);
+            PORT_Free(sf_md5);
 
             if (md5_length != MD5_LENGTH)
                 return JAR_ERR_CORRUPT;
 
             match = PORT_Memcmp(md5_digest, glob->md5, MD5_LENGTH);
+            PORT_Free(md5_digest);
         }
 
         if (sf_sha1 && match == 0) {
             unsigned int sha1_length;
             unsigned char *sha1_digest;
 
             sha1_digest = ATOB_AsciiToData(sf_sha1, &sha1_length);
             PORT_Assert(sha1_length == SHA1_LENGTH);
+            PORT_Free(sf_sha1);
 
             if (sha1_length != SHA1_LENGTH)
                 return JAR_ERR_CORRUPT;
 
             match = PORT_Memcmp(sha1_digest, glob->sha1, SHA1_LENGTH);
+            PORT_Free(sha1_digest);
         }
 
         if (match != 0) {
             /* global digest doesn't match, SF file therefore invalid */
             jar->valid = JAR_ERR_METADATA;
             return JAR_ERR_METADATA;
         }
     }
@@ -505,30 +512,32 @@ jar_parse_any(JAR *jar, int type, JAR_Si
             binary_digest = ATOB_AsciiToData(x_md5, &binary_length);
             PORT_Assert(binary_length == MD5_LENGTH);
             if (binary_length != MD5_LENGTH) {
                 PORT_Free(dig);
                 return JAR_ERR_CORRUPT;
             }
             memcpy(dig->md5, binary_digest, MD5_LENGTH);
             dig->md5_status = jarHashPresent;
+            PORT_Free(binary_digest);
         }
 
         if (*x_sha) {
             unsigned int binary_length;
             unsigned char *binary_digest;
 
             binary_digest = ATOB_AsciiToData(x_sha, &binary_length);
             PORT_Assert(binary_length == SHA1_LENGTH);
             if (binary_length != SHA1_LENGTH) {
                 PORT_Free(dig);
                 return JAR_ERR_CORRUPT;
             }
             memcpy(dig->sha1, binary_digest, SHA1_LENGTH);
             dig->sha1_status = jarHashPresent;
+            PORT_Free(binary_digest);
         }
 
         PORT_Assert(type == jarTypeMF || type == jarTypeSF);
         if (type == jarTypeMF) {
             ADDITEM(jar->hashes, jarTypeMF, x_name, dig, sizeof(JAR_Digest));
         } else if (type == jarTypeSF) {
             ADDITEM(signer->sf, jarTypeSF, x_name, dig, sizeof(JAR_Digest));
         } else {
--- a/security/nss/lib/pk11wrap/pk11skey.c
+++ b/security/nss/lib/pk11wrap/pk11skey.c
@@ -1783,38 +1783,27 @@ loser:
     return NULL;
 }
 
 /*
  * This Generates a wrapping key based on a privateKey, publicKey, and two
  * random numbers. For Mail usage RandomB should be NULL. In the Sender's
  * case RandomA is generate, outherwize it is passed.
  */
-static unsigned char *rb_email = NULL;
-
 PK11SymKey *
 PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, 
    PRBool isSender, SECItem *randomA, SECItem *randomB, 
     CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
 			CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx)
 {
     PK11SlotInfo *slot = privKey->pkcs11Slot;
     CK_MECHANISM mechanism;
     PK11SymKey *symKey;
     CK_RV crv;
 
-
-    if (rb_email == NULL) {
-	rb_email = PORT_ZAlloc(128);
-	if (rb_email == NULL) {
-	    return NULL;
-	}
-	rb_email[127] = 1;
-    }
-
     /* get our key Structure */
     symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx);
     if (symKey == NULL) {
 	return NULL;
     }
 
     symKey->origin = PK11_OriginDerive;
 
@@ -1824,21 +1813,23 @@ PK11_PubDerive(SECKEYPrivateKey *privKey
     case rsaOaepKey:
     case nullKey:
 	PORT_SetError(SEC_ERROR_BAD_KEY);
 	break;
     case dsaKey:
     case keaKey:
     case fortezzaKey:
 	{
+	    static unsigned char rb_email[128] = { 0 };
 	    CK_KEA_DERIVE_PARAMS param;
 	    param.isSender = (CK_BBOOL) isSender;
 	    param.ulRandomLen = randomA->len;
 	    param.pRandomA = randomA->data;
 	    param.pRandomB = rb_email;
+	    param.pRandomB[127] = 1;
 	    if (randomB)
 		 param.pRandomB = randomB->data;
 	    if (pubKey->keyType == fortezzaKey) {
 		param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len;
 		param.pPublicData = pubKey->u.fortezza.KEAKey.data;
 	    } else {
 		/* assert type == keaKey */
 		/* XXX change to match key key types */
--- a/security/nss/lib/ssl/derive.c
+++ b/security/nss/lib/ssl/derive.c
@@ -371,17 +371,16 @@ ssl3_KeyAndMacDeriveBypass(
         /*
         ** server_write_key[CipherSpec.key_material]
         ** final_server_write_key = PRF(server_write_key,
         **                              "server write key",
         **                              client_random + server_random);
         */
         secret.data = &key_block[i];
         secret.len = effKeySize;
-        i += effKeySize;
         keyblk.data = key_block2;
         keyblk.len = keySize;
         status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS);
         if (status != SECSuccess) {
             goto key_and_mac_derive_fail;
         }
         buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item,
                     "TLS Export Server Write Key");
@@ -599,17 +598,17 @@ SSL_CanBypass(CERTCertificate *cert, SEC
 #ifdef NO_PKCS11_BYPASS
     if (!pcanbypass) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
     *pcanbypass = PR_FALSE;
     return SECSuccess;
 #else
-    SECStatus rv;
+    SECStatus rv = SECFailure;
     int i;
     PRUint16 suite;
     PK11SymKey *pms = NULL;
     SECKEYPublicKey *srvPubkey = NULL;
     KeyType privKeytype;
     PK11SlotInfo *slot = NULL;
     SECItem param;
     CK_VERSION version;
@@ -628,17 +627,16 @@ SSL_CanBypass(CERTCertificate *cert, SEC
         return SECFailure;
     }
 
     srvPubkey = CERT_ExtractPublicKey(cert);
     if (!srvPubkey)
         return SECFailure;
 
     *pcanbypass = PR_TRUE;
-    rv = SECFailure;
 
     /* determine which KEAs to test */
     /* 0 (TLS_NULL_WITH_NULL_NULL) is used as a list terminator because
      * SSL3 and TLS specs forbid negotiating that cipher suite number.
      */
     for (i = 0; i < nsuites && (suite = *ciphersuites++) != 0; i++) {
         /* skip cipher suites NSS doesn't support */
         if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess)
@@ -682,17 +680,16 @@ SSL_CanBypass(CERTCertificate *cert, SEC
         } else {
             isTLS = PR_TRUE;
             protocolmask ^= SSL_CBP_TLS1_0;
         }
 
         if (privKeytype == rsaKey && testrsa_export) {
             if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) {
                 *pcanbypass = PR_FALSE;
-                rv = SECSuccess;
                 break;
             } else
                 testrsa = PR_TRUE;
         }
         for (; privKeytype == rsaKey && testrsa;) {
             /* TLS_RSA */
             unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
             unsigned int outLen = 0;
@@ -808,17 +805,17 @@ SSL_CanBypass(CERTCertificate *cert, SEC
                 keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL);
                 if (!keapriv || !keapub) {
                     if (keapriv)
                         SECKEY_DestroyPrivateKey(keapriv);
                     if (keapub)
                         SECKEY_DestroyPublicKey(keapub);
                     PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
                     rv = SECFailure;
-                    break;
+                    goto done;
                 }
             } else {
                 /* TLS_ECDH_ECDSA */
                 keapub = srvPubkey;
                 keapriv = srvPrivkey;
                 pecParams = &srvPubkey->u.ec.DEREncodedParams;
             }
 
@@ -827,17 +824,17 @@ SSL_CanBypass(CERTCertificate *cert, SEC
             cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL);
             if (!cpriv || !cpub) {
                 if (testecdhe) {
                     SECKEY_DestroyPrivateKey(keapriv);
                     SECKEY_DestroyPublicKey(keapub);
                 }
                 PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
                 rv = SECFailure;
-                break;
+                goto done;
             }
             /* now do the server side */
             /* determine the PMS using client's public value */
             target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH
                            : CKM_SSL3_MASTER_KEY_DERIVE_DH;
             pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL,
                                         CKM_ECDH1_DERIVE,
                                         target,
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -1488,16 +1488,17 @@ ssl3_ComputeDHKeyHash(sslSocket *ss, SSL
     PRUint8 *hashBuf;
     PRUint8 *pBuf;
     SECStatus rv = SECSuccess;
     unsigned int bufLen;
     PRUint8 buf[2 * SSL3_RANDOM_LENGTH + 2 + 4096 / 8 + 2 + 4096 / 8];
 
     PORT_Assert(dh_p.data);
     PORT_Assert(dh_g.data);
+    PORT_Assert(dh_Ys.data);
 
     bufLen = 2 * SSL3_RANDOM_LENGTH +
              2 + dh_p.len +
              2 + dh_g.len +
              2 + (padY ? dh_p.len : dh_Ys.len);
     if (bufLen <= sizeof buf) {
         hashBuf = buf;
     } else {
@@ -5134,17 +5135,17 @@ SECStatus
 ssl3_ConsumeSignatureAndHashAlgorithm(sslSocket *ss,
                                       SSL3Opaque **b,
                                       PRUint32 *length,
                                       SSLSignatureAndHashAlg *out)
 {
     PRUint8 bytes[2];
     SECStatus rv;
 
-    rv = ssl3_ConsumeHandshake(ss, bytes, sizeof(bytes), b, length);
+    rv = ssl3_ConsumeHandshake(ss, &bytes[0], sizeof(bytes), b, length);
     if (rv != SECSuccess) {
         return rv;
     }
 
     out->hashAlg = (SSLHashType)bytes[0];
     out->sigAlg = (SSLSignType)bytes[1];
     if (!ssl3_IsSupportedSignatureAlgorithm(out)) {
         PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
@@ -10550,30 +10551,36 @@ ssl3_HandleCertificateVerify(sslSocket *
         }
         rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
             ss, &sigAndHash, ss->sec.peerCert);
         if (rv != SECSuccess) {
             errCode = PORT_GetError();
             desc = decrypt_error;
             goto alert_loser;
         }
+
+        if (hashes->u.pointer_to_hash_input.data) {
 #ifndef NO_PKCS11_BYPASS
-        if (ss->opt.bypassPKCS11) {
-            rv = ssl3_ComputeBypassHandshakeHash(hashes->u.pointer_to_hash_input.data,
-                                                 hashes->u.pointer_to_hash_input.len,
-                                                 sigAndHash.hashAlg,
-                                                 &localHashes);
-        } else
+            if (ss->opt.bypassPKCS11 && hashes->u.pointer_to_hash_input.data) {
+                rv = ssl3_ComputeBypassHandshakeHash(hashes->u.pointer_to_hash_input.data,
+                                                     hashes->u.pointer_to_hash_input.len,
+                                                     sigAndHash.hashAlg,
+                                                     &localHashes);
+            } else
 #endif
-        {
-            rv = ssl3_ComputePkcs11HandshakeHash(hashes->u.pointer_to_hash_input.data,
-                                                 hashes->u.pointer_to_hash_input.len,
-                                                 sigAndHash.hashAlg,
-                                                 &localHashes);
-        }
+            {
+                rv = ssl3_ComputePkcs11HandshakeHash(hashes->u.pointer_to_hash_input.data,
+                                                     hashes->u.pointer_to_hash_input.len,
+                                                     sigAndHash.hashAlg,
+                                                     &localHashes);
+            }
+        } else {
+            rv = SECFailure;
+        }
+
         if (rv == SECSuccess) {
             hashesForVerify = &localHashes;
         } else {
             errCode = SSL_ERROR_DIGEST_FAILURE;
             desc = decrypt_error;
             goto alert_loser;
         }
     }
@@ -11044,30 +11051,32 @@ ssl3_HandleClientKeyExchange(sslSocket *
 
 /* This is TLS's equivalent of sending a no_certificate alert. */
 SECStatus
 ssl3_SendEmptyCertificate(sslSocket *ss)
 {
     SECStatus rv;
     unsigned int len = 0;
     PRBool isTLS13 = PR_FALSE;
+    const SECItem *context;
 
     if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
-        len = ss->ssl3.hs.certReqContextLen + 1;
+        PORT_Assert(ss->ssl3.hs.certificateRequest);
+        context = &ss->ssl3.hs.certificateRequest->context;
+        len = context->len + 1;
         isTLS13 = PR_TRUE;
     }
 
     rv = ssl3_AppendHandshakeHeader(ss, certificate, len + 3);
     if (rv != SECSuccess) {
         return rv;
     }
 
     if (isTLS13) {
-        rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.hs.certReqContext,
-                                          ss->ssl3.hs.certReqContextLen, 1);
+        rv = ssl3_AppendHandshakeVariable(ss, context->data, context->len, 1);
         if (rv != SECSuccess) {
             return rv;
         }
     }
 
     return ssl3_AppendHandshakeNumber(ss, 0, 3);
 }
 
@@ -11239,16 +11248,17 @@ ssl3_SendCertificate(sslSocket *ss)
     CERTCertificateList *certChain;
     int certChainLen = 0;
     int i;
 #ifdef NISCC_TEST
     SECItem fakeCert;
     int ndex = -1;
 #endif
     PRBool isTLS13 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
+    SECItem context = { siBuffer, NULL, 0 };
     unsigned int contextLen = 0;
 
     SSL_TRC(3, ("%d: SSL3[%d]: send certificate handshake",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
@@ -11265,19 +11275,21 @@ ssl3_SendCertificate(sslSocket *ss)
         ss->sec.localCert = CERT_DupCertificate(ss->ssl3.clientCertificate);
     }
 
 #ifdef NISCC_TEST
     rv = get_fake_cert(&fakeCert, &ndex);
 #endif
 
     if (isTLS13) {
-        contextLen = 1; /* Length of the context */
+        contextLen = 1; /* Size of the context length */
         if (!ss->sec.isServer) {
-            contextLen += ss->ssl3.hs.certReqContextLen;
+            PORT_Assert(ss->ssl3.hs.certificateRequest);
+            context = ss->ssl3.hs.certificateRequest->context;
+            contextLen += context.len;
         }
     }
     if (certChain) {
         for (i = 0; i < certChain->len; i++) {
 #ifdef NISCC_TEST
             if (fakeCert.len > 0 && i == ndex) {
                 certChainLen += fakeCert.len + 3;
             } else {
@@ -11291,23 +11303,18 @@ ssl3_SendCertificate(sslSocket *ss)
 
     rv = ssl3_AppendHandshakeHeader(ss, certificate,
                                     contextLen + certChainLen + 3);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
 
     if (isTLS13) {
-        if (ss->sec.isServer) {
-            rv = ssl3_AppendHandshakeNumber(ss, 0, 1);
-        } else {
-            rv = ssl3_AppendHandshakeVariable(ss,
-                                              ss->ssl3.hs.certReqContext,
-                                              ss->ssl3.hs.certReqContextLen, 1);
-        }
+        rv = ssl3_AppendHandshakeVariable(ss, context.data,
+                                          context.len, 1);
         if (rv != SECSuccess) {
             return rv; /* err set by AppendHandshake. */
         }
     }
 
     rv = ssl3_AppendHandshakeNumber(ss, certChainLen, 3);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
@@ -13688,17 +13695,17 @@ ssl3_InitState(sslSocket *ss)
     ss->ssl3.hs.clientHelloHash = NULL;
     PR_INIT_CLIST(&ss->ssl3.hs.remoteKeyShares);
     ss->ssl3.hs.currentSecret = NULL;
     ss->ssl3.hs.resumptionPsk = NULL;
     ss->ssl3.hs.resumptionContext = nullItem;
     ss->ssl3.hs.dheSecret = NULL;
     ss->ssl3.hs.trafficSecret = NULL;
     ss->ssl3.hs.hsTrafficSecret = NULL;
-    ss->ssl3.hs.certReqContextLen = 0;
+    ss->ssl3.hs.certificateRequest = NULL;
     PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs);
 
     PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space);
     ss->ssl3.hs.messages.buf = NULL;
     ss->ssl3.hs.messages.space = 0;
 
     ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
     PORT_Memset(&ss->ssl3.hs.newSessionTicket, 0,
@@ -14020,16 +14027,21 @@ ssl3_DestroySSL3Info(sslSocket *ss)
     }
 
     /* free the SSL3Buffer (msg_body) */
     PORT_Free(ss->ssl3.hs.msg_body.buf);
 
     SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE);
     SECITEM_FreeItem(&ss->ssl3.hs.srvVirtName, PR_FALSE);
 
+    if (ss->ssl3.hs.certificateRequest) {
+        PORT_FreeArena(ss->ssl3.hs.certificateRequest->arena, PR_FALSE);
+        ss->ssl3.hs.certificateRequest = NULL;
+    }
+
     /* free up the CipherSpecs */
     ssl3_DestroyCipherSpec(&ss->ssl3.specs[0], PR_TRUE /*freeSrvName*/);
     ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE /*freeSrvName*/);
 
     /* Destroy the DTLS data */
     if (IS_DTLS(ss)) {
         dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
         if (ss->ssl3.hs.recvdFragments.buf) {
--- a/security/nss/lib/ssl/ssl3ecc.c
+++ b/security/nss/lib/ssl/ssl3ecc.c
@@ -960,32 +960,38 @@ ssl_IsSuiteEnabled(sslSocket *ss, const 
         PORT_Assert(rv == SECSuccess); /* else is coding error */
         if (rv == SECSuccess && enabled)
             return PR_TRUE;
     }
     return PR_FALSE;
 }
 
 /* Ask: is ANY ECC cipher suite enabled on this socket? */
-static PRBool
+PRBool
 ssl_IsECCEnabled(sslSocket *ss)
 {
     PK11SlotInfo *slot;
 
     /* make sure we can do ECC */
     slot = PK11_GetBestSlot(CKM_ECDH1_DERIVE, ss->pkcs11PinArg);
     if (!slot) {
         return PR_FALSE;
     }
     PK11_FreeSlot(slot);
 
     /* make sure an ECC cipher is enabled */
     return ssl_IsSuiteEnabled(ss, ssl_all_ec_suites);
 }
 
+PRBool
+ssl_IsDHEEnabled(sslSocket *ss)
+{
+    return ssl_IsSuiteEnabled(ss, ssl_dhe_suites);
+}
+
 /* This function already presumes we can do ECC, ssl_IsECCEnabled must be
  * called before this function. It looks to see if we have a token which
  * is capable of doing smaller than SuiteB curves. If the token can, we
  * presume the token can do the whole SSL suite of curves. If it can't we
  * presume the token that allowed ECC to be enabled can only do suite B
  * curves. */
 PRBool
 ssl_SuiteBOnly(sslSocket *ss)
@@ -1019,17 +1025,17 @@ ssl_SendSupportedGroupsXtn(sslSocket *ss
     if (!ss)
         return 0;
 
     ec = ssl_IsECCEnabled(ss);
     /* We only send FF supported groups if we require DH named groups or if TLS
      * 1.3 is a possibility. */
     if (ss->opt.requireDHENamedGroups ||
         ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3) {
-        ff = ssl_IsSuiteEnabled(ss, ssl_dhe_suites);
+        ff = ssl_IsDHEEnabled(ss);
     }
     if (!ec && !ff) {
         return 0;
     }
 
     PORT_Assert(sizeof(enabledGroups) > ssl_named_group_count * 2);
     for (i = 0; i < ssl_named_group_count; ++i) {
         if (ssl_named_groups[i].type == group_type_ec && !ec) {
--- a/security/nss/lib/ssl/ssl3ext.c
+++ b/security/nss/lib/ssl/ssl3ext.c
@@ -1167,17 +1167,17 @@ ssl3_EncodeSessionTicket(sslSocket *ss, 
     const unsigned char *aes_key = NULL;
     const unsigned char *mac_key = NULL;
     PRUint32 aes_key_length;
     PRUint32 mac_key_length;
     PRUint64 aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS];
     AESContext *aes_ctx;
     const SECHashObject *hashObj = NULL;
     PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
-    HMACContext *hmac_ctx;
+    HMACContext *hmac_ctx = NULL;
 #endif
     CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
     PK11Context *aes_ctx_pkcs11;
     CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC;
     PK11Context *hmac_ctx_pkcs11 = NULL;
     unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
     unsigned int computed_mac_length;
     unsigned char iv[AES_BLOCK_SIZE];
@@ -1480,26 +1480,29 @@ ssl3_EncodeSessionTicket(sslSocket *ss, 
 /* Compute MAC. */
 #ifndef NO_PKCS11_BYPASS
     if (ss->opt.bypassPKCS11) {
         PORT_Assert(mac_key);
 
         hmac_ctx = (HMACContext *)hmac_ctx_buf;
         hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
         if (HMAC_Init(hmac_ctx, hashObj, mac_key,
-                      mac_key_length, PR_FALSE) != SECSuccess)
+                      mac_key_length, PR_FALSE) != SECSuccess) {
             goto loser;
+        }
 
         HMAC_Begin(hmac_ctx);
         HMAC_Update(hmac_ctx, key_name, SESS_TICKET_KEY_NAME_LEN);
         HMAC_Update(hmac_ctx, iv, sizeof(iv));
         HMAC_Update(hmac_ctx, (unsigned char *)length_buf, 2);
         HMAC_Update(hmac_ctx, ciphertext.data, ciphertext.len);
-        HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
-                    sizeof(computed_mac));
+        if (HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
+                        sizeof(computed_mac)) != SECSuccess) {
+            goto loser;
+        }
     } else
 #endif
     {
         SECItem macParam;
         PORT_Assert(mac_key_pkcs11);
         macParam.data = NULL;
         macParam.len = 0;
         hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech,
@@ -1563,22 +1566,30 @@ ssl3_EncodeSessionTicket(sslSocket *ss, 
     if (rv != SECSuccess)
         goto loser;
 
     /* Give ownership of memory to caller. */
     *ticket_data = ticket_buf;
     ticket_buf.data = NULL;
 
 loser:
-    if (hmac_ctx_pkcs11)
+#ifndef NO_PKCS11_BYPASS
+    if (hmac_ctx) {
+        HMAC_Destroy(hmac_ctx, PR_FALSE);
+    }
+#endif
+    if (hmac_ctx_pkcs11) {
         PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
-    if (plaintext_item.data)
+    }
+    if (plaintext_item.data) {
         SECITEM_FreeItem(&plaintext_item, PR_FALSE);
-    if (ciphertext.data)
+    }
+    if (ciphertext.data) {
         SECITEM_FreeItem(&ciphertext, PR_FALSE);
+    }
     if (ticket_buf.data) {
         SECITEM_FreeItem(&ticket_buf, PR_FALSE);
     }
 
     return rv;
 }
 
 /* When a client receives a SessionTicket extension a NewSessionTicket
@@ -1694,19 +1705,22 @@ ssl3_ProcessSessionTicketCommon(sslSocke
         hmac_ctx = (HMACContext *)hmac_ctx_buf;
         hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
         if (HMAC_Init(hmac_ctx, hashObj, mac_key,
                       sizeof(session_ticket_mac_key), PR_FALSE) != SECSuccess)
             goto no_ticket;
         HMAC_Begin(hmac_ctx);
         HMAC_Update(hmac_ctx, extension_data.data,
                     extension_data.len - TLS_EX_SESS_TICKET_MAC_LENGTH);
-        if (HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
-                        sizeof(computed_mac)) != SECSuccess)
+        rv = HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
+                         sizeof(computed_mac));
+        HMAC_Destroy(hmac_ctx, PR_FALSE);
+        if (rv != SECSuccess) {
             goto no_ticket;
+        }
     } else
 #endif
     {
         SECItem macParam;
         PORT_Assert(mac_key_pkcs11);
         macParam.data = NULL;
         macParam.len = 0;
         hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech,
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -888,16 +888,24 @@ typedef struct {
 
 typedef enum {
     handshake_hash_unknown = 0,
     handshake_hash_combo = 1,  /* The MD5/SHA-1 combination */
     handshake_hash_single = 2, /* A single hash */
     handshake_hash_record
 } SSL3HandshakeHashType;
 
+/* This holds state for TLS 1.3 CertificateRequest handling. */
+typedef struct TLS13CertificateRequestStr {
+    PLArenaPool *arena;
+    SECItem context;
+    SECItem algorithms;
+    CERTDistNames ca_list;
+} TLS13CertificateRequest;
+
 /*
 ** This is the "hs" member of the "ssl3" struct.
 ** This entire struct is protected by ssl3HandshakeLock
 */
 typedef struct SSL3HandshakeStateStr {
     SSL3Random server_random;
     SSL3Random client_random;
     SSL3WaitState ws; /* May also contain SSL3WaitState | 0x80 for TLS 1.3 */
@@ -997,38 +1005,36 @@ typedef struct SSL3HandshakeStateStr {
     PRUint32 rtTimeoutMs;          /* The length of the current timeout
                                     * used for backoff (in ms) */
     PRUint32 rtRetries;            /* The retry counter */
     SECItem srvVirtName;           /* for server: name that was negotiated
                           * with a client. For client - is
                           * always set to NULL.*/
 
     /* This group of values is used for TLS 1.3 and above */
-    PK11Context *clientHelloHash;      /* The client hello hash state, used
+    PK11Context *clientHelloHash;   /* The client hello hash state, used
                                         * by the server for 0-RTT. */
-    PRCList remoteKeyShares;           /* The other side's public keys */
-    PK11SymKey *currentSecret;         /* The secret down the "left hand side"
+    PRCList remoteKeyShares;        /* The other side's public keys */
+    PK11SymKey *currentSecret;      /* The secret down the "left hand side"
                                         * of the TLS 1.3 key schedule. */
-    PK11SymKey *resumptionPsk;         /* The resumption PSK. */
-    SECItem resumptionContext;         /* The resumption context. */
-    PK11SymKey *dheSecret;             /* The (EC)DHE shared secret. */
-    PK11SymKey *earlyTrafficSecret;    /* The secret we use for 0-RTT. */
-    PK11SymKey *hsTrafficSecret;       /* The handshake traffic secret. */
-    PK11SymKey *trafficSecret;         /* The source key to use to generate
+    PK11SymKey *resumptionPsk;      /* The resumption PSK. */
+    SECItem resumptionContext;      /* The resumption context. */
+    PK11SymKey *dheSecret;          /* The (EC)DHE shared secret. */
+    PK11SymKey *earlyTrafficSecret; /* The secret we use for 0-RTT. */
+    PK11SymKey *hsTrafficSecret;    /* The handshake traffic secret. */
+    PK11SymKey *trafficSecret;      /* The source key to use to generate
                                         * traffic keys */
-    unsigned char certReqContext[255]; /* Ties CertificateRequest
-                                        * to Certificate */
-    PRUint8 certReqContextLen;         /* Length of the context
-                                        * cannot be greater than 255. */
-    ssl3CipherSuite origCipherSuite;   /* The cipher suite from the original
+    /* The certificate request from the server. */
+    TLS13CertificateRequest *certificateRequest;
+    ssl3CipherSuite origCipherSuite; /* The cipher suite from the original
                                         * connection if we are resuming. */
-    PRCList cipherSpecs;               /* The cipher specs in the sequence they
+    PRCList cipherSpecs;             /* The cipher specs in the sequence they
                                         * will be applied. */
-    PRBool doing0Rtt;                  /* Are we doing a 0-RTT handshake? */
-    PRCList bufferedEarlyData;         /* Buffered TLS 1.3 early data
+    PRBool doing0Rtt;                /* Are we doing a 0-RTT handshake? */
+    PRCList bufferedEarlyData;       /* Buffered TLS 1.3 early data
                                         * on server.*/
 } SSL3HandshakeState;
 
 /*
 ** This is the "ssl3" struct, as in "ss->ssl3".
 ** note:
 ** usually,   crSpec == cwSpec and prSpec == pwSpec.
 ** Sometimes, crSpec == pwSpec and prSpec == cwSpec.
@@ -1732,17 +1738,18 @@ extern SECStatus ssl_CreateDHEKeyPair(co
                                       sslEphemeralKeyPair **keyPair);
 extern PRBool ssl_IsValidDHEShare(const SECItem *dh_p, const SECItem *dh_Ys);
 extern SECStatus ssl_ValidateDHENamedGroup(sslSocket *ss,
                                            const SECItem *dh_p,
                                            const SECItem *dh_g,
                                            const namedGroupDef **groupDef,
                                            const ssl3DHParams **dhParams);
 
-extern PRBool ssl3_IsECCEnabled(sslSocket *ss);
+extern PRBool ssl_IsECCEnabled(sslSocket *ss);
+extern PRBool ssl_IsDHEEnabled(sslSocket *ss);
 
 /* Macro for finding a curve equivalent in strength to RSA key's */
 /* clang-format off */
 #define SSL_RSASTRENGTH_TO_ECSTRENGTH(s)                                       \
         ((s <= 1024) ? 160                                                     \
                      : ((s <= 2048) ? 224                                      \
                                     : ((s <= 3072) ? 256                       \
                                                    : ((s <= 7168) ? 384        \
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -255,17 +255,20 @@ ssl_DupSocket(sslSocket *os)
 
     ss = ssl_NewSocket((PRBool)(!os->opt.noLocks), os->protocolVariant);
     if (!ss) {
         return NULL;
     }
 
     ss->opt = os->opt;
     ss->opt.useSocks = PR_FALSE;
-    SECITEM_CopyItem(NULL, &ss->opt.nextProtoNego, &os->opt.nextProtoNego);
+    rv = SECITEM_CopyItem(NULL, &ss->opt.nextProtoNego, &os->opt.nextProtoNego);
+    if (rv != SECSuccess) {
+        goto loser;
+    }
     ss->vrange = os->vrange;
 
     ss->peerID = !os->peerID ? NULL : PORT_Strdup(os->peerID);
     ss->url = !os->url ? NULL : PORT_Strdup(os->url);
 
     ss->ops = os->ops;
     ss->rTimeout = os->rTimeout;
     ss->wTimeout = os->wTimeout;
--- a/security/nss/lib/ssl/ssltrace.c
+++ b/security/nss/lib/ssl/ssltrace.c
@@ -43,16 +43,22 @@ ssl_PrintBuf(sslSocket *ss, const char *
     char *ap;
 
     if (ss) {
         SSL_TRACE(("%d: SSL[%d]: %s [Len: %d]", SSL_GETPID(), ss->fd,
                    msg, len));
     } else {
         SSL_TRACE(("%d: SSL: %s [Len: %d]", SSL_GETPID(), msg, len));
     }
+
+    if (!cp) {
+        SSL_TRACE(("   <NULL>"));
+        return;
+    }
+
     memset(buf, ' ', sizeof buf);
     bp = buf;
     ap = buf + 50;
     while (--len >= 0) {
         unsigned char ch = *cp++;
         *bp++ = hex[(ch >> 4) & 0xf];
         *bp++ = hex[ch & 0xf];
         *bp++ = ' ';
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -309,56 +309,77 @@ tls13_GetHmacMechanism(sslSocket *ss)
             return CKM_SHA384_HMAC;
         default:
             PORT_Assert(0);
     }
     return CKM_SHA256_HMAC;
 }
 
 /*
- * Called from ssl3_SendClientHello
+ * Generate shares for ECDHE and FFDHE.  This picks the first enabled group of
+ * the requisite type and creates a share for that.
+ *
+ * Called from ssl3_SendClientHello.
  */
 SECStatus
 tls13_SetupClientHello(sslSocket *ss)
 {
+    unsigned int i;
+    PRBool ecNeeded = ssl_IsECCEnabled(ss);
     /* This does FFDHE always only while we don't have HelloRetryRequest
      * support.  FFDHE is too much of a burden for normal requests.  We really
      * only want it when EC suites are disabled. */
-    static const NamedGroup groups_to_try[] = { ec_secp256r1, ffdhe_2048 };
-    unsigned int i;
+    PRBool ffNeeded = ssl_IsDHEEnabled(ss);
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
 
-    for (i = 0; i < PR_ARRAY_SIZE(groups_to_try); ++i) {
+    for (i = 0; i < ssl_named_group_count; ++i) {
         SECStatus rv;
-        sslEphemeralKeyPair *keyPair;
-        const namedGroupDef *groupDef = ssl_LookupNamedGroup(groups_to_try[i]);
+        sslEphemeralKeyPair *keyPair = NULL;
+        const namedGroupDef *groupDef = &ssl_named_groups[i];
+        const ssl3DHParams *params;
         if (!ssl_NamedGroupEnabled(ss, groupDef)) {
             continue;
         }
         switch (groupDef->type) {
             case group_type_ec:
+                if (!ecNeeded) {
+                    continue;
+                }
                 rv = ssl_CreateECDHEphemeralKeyPair(groupDef, &keyPair);
+                if (rv != SECSuccess) {
+                    return SECFailure;
+                }
+                ecNeeded = PR_FALSE;
                 break;
-            case group_type_ff: {
-                const ssl3DHParams *params = ssl_GetDHEParams(groupDef);
+            case group_type_ff:
+                if (!ffNeeded) {
+                    continue;
+                }
+                params = ssl_GetDHEParams(groupDef);
                 PORT_Assert(params->name != ffdhe_custom);
                 rv = ssl_CreateDHEKeyPair(groupDef, params, &keyPair);
+                if (rv != SECSuccess) {
+                    return SECFailure;
+                }
+                ffNeeded = PR_FALSE;
                 break;
-            }
         }
-        if (rv != SECSuccess)
-            return rv;
 
         PR_APPEND_LINK(&keyPair->link, &ss->ephemeralKeyPairs);
     }
+
     PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
+    /* We don't permit all groups of a given type to be disabled, so this should
+     * never reach this point wanting for a share of either type. */
+    PORT_Assert(!ecNeeded);
+    PORT_Assert(!ffNeeded);
 
     return SECSuccess;
 }
 
 static SECStatus
 tls13_ImportDHEKeyShare(sslSocket *ss, SECKEYPublicKey *peerKey,
                         SSL3Opaque *b, PRUint32 length,
                         SECKEYPublicKey *pubKey)
@@ -1178,16 +1199,18 @@ tls13_HandleClientKeyShare(sslSocket *ss
     if (rv != SECSuccess) {
         return SECFailure; /* Error code set already. */
     }
 
     rv = tls13_HandleKeyShare(ss, peerShare, keyPair->keys);
     return rv; /* Error code set already. */
 }
 
+static const unsigned char tls13_certreq_context[] = { 0 };
+
 /*
  *     [draft-ietf-tls-tls13-11] Section 6.3.3.2
  *
  *     opaque DistinguishedName<1..2^16-1>;
  *
  *     struct {
  *         opaque certificate_extension_oid<1..2^8-1>;
  *         opaque certificate_extension_values<0..2^16-1>;
@@ -1212,36 +1235,32 @@ tls13_SendCertificateRequest(sslSocket *
     int i;
     PRUint8 sigAlgs[MAX_SIGNATURE_ALGORITHMS * 2];
     unsigned int sigAlgsLength = 0;
     int length;
 
     SSL_TRC(3, ("%d: TLS13[%d]: begin send certificate_request",
                 SSL_GETPID(), ss->fd));
 
-    /* Fixed context value. */
-    ss->ssl3.hs.certReqContext[0] = 0;
-    ss->ssl3.hs.certReqContextLen = 1;
-
     rv = ssl3_EncodeCertificateRequestSigAlgs(ss, sigAlgs, sizeof(sigAlgs),
                                               &sigAlgsLength);
     if (rv != SECSuccess) {
         return rv;
     }
 
     ssl3_GetCertificateRequestCAs(ss, &calen, &names, &nnames);
-    length = 1 + ss->ssl3.hs.certReqContextLen +
+    length = 1 + sizeof(tls13_certreq_context) +
              2 + sigAlgsLength + 2 + calen + 2;
 
     rv = ssl3_AppendHandshakeHeader(ss, certificate_request, length);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
-    rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.hs.certReqContext,
-                                      ss->ssl3.hs.certReqContextLen, 1);
+    rv = ssl3_AppendHandshakeVariable(ss, tls13_certreq_context,
+                                      sizeof(tls13_certreq_context), 1);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
     rv = ssl3_AppendHandshakeVariable(ss, sigAlgs, sigAlgsLength, 2);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
     rv = ssl3_AppendHandshakeNumber(ss, calen, 2);
@@ -1261,85 +1280,96 @@ tls13_SendCertificateRequest(sslSocket *
 
     return SECSuccess;
 }
 
 static SECStatus
 tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
     SECStatus rv;
+    TLS13CertificateRequest *certRequest = NULL;
     SECItem context = { siBuffer, NULL, 0 };
     SECItem algorithms = { siBuffer, NULL, 0 };
     PLArenaPool *arena;
-    CERTDistNames ca_list;
     PRInt32 extensionsLength;
 
     SSL_TRC(3, ("%d: TLS13[%d]: handle certificate_request sequence",
                 SSL_GETPID(), ss->fd));
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     /* Client */
-    rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, wait_cert_request);
+    rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST,
+                              wait_cert_request);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     PORT_Assert(ss->ssl3.clientCertChain == NULL);
     PORT_Assert(ss->ssl3.clientCertificate == NULL);
     PORT_Assert(ss->ssl3.clientPrivateKey == NULL);
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length);
-    if (rv != SECSuccess)
-        return SECFailure;
-    PORT_Assert(sizeof(ss->ssl3.hs.certReqContext) == 255);
-    PORT_Memcpy(ss->ssl3.hs.certReqContext, context.data, context.len);
-    ss->ssl3.hs.certReqContextLen = context.len;
-
-    rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &b, &length);
-    if (rv != SECSuccess)
-        return SECFailure;
-
-    if (algorithms.len == 0 || (algorithms.len & 1) != 0) {
-        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST,
-                    illegal_parameter);
-        return SECFailure;
-    }
-
-    arena = ca_list.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    PORT_Assert(ss->ssl3.hs.certificateRequest == NULL);
+
+    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     if (!arena) {
         FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
         return SECFailure;
     }
 
-    rv = ssl3_ParseCertificateRequestCAs(ss, &b, &length, arena, &ca_list);
+    rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length);
+    if (rv != SECSuccess)
+        goto loser;
+    if (context.len == 0) {
+        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST,
+                    illegal_parameter);
+        goto loser;
+    }
+
+    rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &b, &length);
     if (rv != SECSuccess)
-        goto loser; /* alert sent below */
+        goto loser;
+    if (algorithms.len == 0 || (algorithms.len & 1) != 0) {
+        FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST,
+                    illegal_parameter);
+        goto loser;
+    }
+
+    certRequest = PORT_ArenaZNew(arena, TLS13CertificateRequest);
+    if (!certRequest)
+        goto loser;
+    certRequest->arena = arena;
+    certRequest->ca_list.arena = arena;
+
+    rv = ssl3_ParseCertificateRequestCAs(ss, &b, &length, arena,
+                                         &certRequest->ca_list);
+    if (rv != SECSuccess)
+        goto loser; /* alert already sent */
 
     /* Verify that the extensions length is correct. */
     extensionsLength = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
     if (extensionsLength < 0) {
-        goto loser; /* alert sent below */
+        goto loser; /* alert already sent */
     }
     if (extensionsLength != length) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST,
                     illegal_parameter);
         goto loser;
     }
 
+    rv = SECITEM_CopyItem(arena, &certRequest->context, &context);
+    if (rv != SECSuccess)
+        goto loser;
+    rv = SECITEM_CopyItem(arena, &certRequest->algorithms, &algorithms);
+    if (rv != SECSuccess)
+        goto loser;
+
     TLS13_SET_HS_STATE(ss, wait_server_cert);
-
-    rv = ssl3_CompleteHandleCertificateRequest(ss, &algorithms, &ca_list);
-    if (rv != SECSuccess) {
-        FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
-        goto loser;
-    }
-
-    PORT_FreeArena(arena, PR_FALSE);
+    ss->ssl3.hs.certificateRequest = certRequest;
+
     return SECSuccess;
 
 loser:
     PORT_FreeArena(arena, PR_FALSE);
     return SECFailure;
 }
 
 /* Called from:  ssl3_HandleClientHello */
@@ -1688,27 +1718,31 @@ tls13_HandleCertificate(sslSocket *ss, S
     if (!ss->sec.isServer) {
         if (context.len) {
             /* The server's context string MUST be empty */
             FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE,
                         illegal_parameter);
             return SECFailure;
         }
     } else {
-        if (!context.len || context.len != ss->ssl3.hs.certReqContextLen ||
-            (NSS_SecureMemcmp(ss->ssl3.hs.certReqContext,
+        if (context.len != sizeof(tls13_certreq_context) ||
+            (NSS_SecureMemcmp(tls13_certreq_context,
                               context.data, context.len) != 0)) {
             FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE,
                         illegal_parameter);
             return SECFailure;
         }
         context.len = 0; /* Belt and suspenders. Zero out the context. */
     }
 
-    return ssl3_CompleteHandleCertificate(ss, b, length);
+    rv = ssl3_CompleteHandleCertificate(ss, b, length);
+    if (rv != SECSuccess)
+        return rv;
+
+    return SECSuccess;
 }
 
 /* Called from tls13_CompleteHandleHandshakeMessage() when it has deciphered a complete
  * ssl3 CertificateStatus message.
  * Caller must hold Handshake and RecvBuf locks.
  */
 static SECStatus
 tls13_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
@@ -2551,16 +2585,29 @@ tls13_HandleCertificateVerify(sslSocket 
 
     rv = ssl3_VerifySignedHashes(&tbsHash, ss->sec.peerCert, &signed_hash,
                                  PR_TRUE, ss->pkcs11PinArg);
     if (rv != SECSuccess) {
         FATAL_ERROR(ss, PORT_GetError(), decrypt_error);
         return SECFailure;
     }
 
+    /* Request a client certificate now if one was requested. */
+    if (ss->ssl3.hs.certificateRequest) {
+        TLS13CertificateRequest *req = ss->ssl3.hs.certificateRequest;
+
+        PORT_Assert(!ss->sec.isServer);
+        rv = ssl3_CompleteHandleCertificateRequest(ss, &req->algorithms,
+                                                   &req->ca_list);
+        if (rv != SECSuccess) {
+            FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+            return rv;
+        }
+    }
+
     TLS13_SET_HS_STATE(ss, wait_finished);
 
     return SECSuccess;
 }
 
 static SECStatus
 tls13_ComputeFinished(sslSocket *ss, PK11SymKey *baseKey,
                       const TLS13CombinedHash *hashes,
@@ -2857,19 +2904,19 @@ tls13_SendClientSecondRound(sslSocket *s
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     sendClientCert = !ss->ssl3.sendEmptyCert &&
                      ss->ssl3.clientCertChain != NULL &&
                      ss->ssl3.clientPrivateKey != NULL;
 
-    /* Defer client authentication sending if we are still
-     * waiting for server authentication. See the long block
-     * comment in ssl3_SendClientSecondRound for more detail.
+    /* Defer client authentication sending if we are still waiting for server
+     * authentication.  This avoids unnecessary disclosure of client credentials
+     * to an unauthenticated server.
      */
     if (ss->ssl3.hs.restartTarget) {
         PR_NOT_REACHED("unexpected ss->ssl3.hs.restartTarget");
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
     if (ss->ssl3.hs.authCertificatePending) {
         SSL_TRC(3, ("%d: TLS13[%p]: deferring ssl3_SendClientSecondRound because"
@@ -2901,16 +2948,20 @@ tls13_SendClientSecondRound(sslSocket *s
             goto loser; /* error code is set. */
         }
     } else if (sendClientCert) {
         rv = ssl3_SendCertificate(ss);
         if (rv != SECSuccess) {
             goto loser; /* error code is set. */
         }
     }
+    if (ss->ssl3.hs.certificateRequest) {
+        PORT_FreeArena(ss->ssl3.hs.certificateRequest->arena, PR_FALSE);
+        ss->ssl3.hs.certificateRequest = NULL;
+    }
 
     if (sendClientCert) {
         rv = tls13_SendCertificateVerify(ss, ss->ssl3.clientPrivateKey);
         SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
         ss->ssl3.clientPrivateKey = NULL;
         if (rv != SECSuccess) {
             goto loser; /* err is set. */
         }
--- a/security/nss/tests/ssl/ssl.sh
+++ b/security/nss/tests/ssl/ssl.sh
@@ -602,20 +602,20 @@ ssl_stress()
           fi
 
           if [ "`uname -n`" = "sjsu" ] ; then
               echo "debugging disapering selfserv... ps -ef | grep selfserv"
               ps -ef | grep selfserv
           fi
 
           echo "strsclnt -q -p ${PORT} -d ${P_R_CLIENTDIR} ${CLIENT_OPTIONS} -w nss $cparam \\"
-          echo "         $verbose ${HOSTADDR}"
+          echo "         -V ssl3:tls1.2 $verbose ${HOSTADDR}"
           echo "strsclnt started at `date`"
           ${PROFTOOL} ${BINDIR}/strsclnt -q -p ${PORT} -d ${P_R_CLIENTDIR} ${CLIENT_OPTIONS} -w nss $cparam \
-                   $verbose ${HOSTADDR}
+                   -V ssl3:tls1.2 $verbose ${HOSTADDR}
           ret=$?
           echo "strsclnt completed at `date`"
           html_msg $ret $value \
                    "${testname}" \
                    "produced a returncode of $ret, expected is $value. "
           if [ "`uname -n`" = "sjsu" ] ; then
               echo "debugging disapering selfserv... ps -ef | grep selfserv"
               ps -ef | grep selfserv