Bug 1317947 - land NSS 0x6c26f0cd19ba, r=me
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Wed, 23 Nov 2016 06:01:07 +0100
changeset 323912 ecb49ac1035745fe2c0efc76ec7c65096a34ab89
parent 323911 1846a78b62ff79f695c81c741cb1f15c9c2cda28
child 323913 fb3d024cb5e2e16afac36a72e1eae47a8c855d11
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersme
bugs1317947
milestone53.0a1
Bug 1317947 - land NSS 0x6c26f0cd19ba, r=me
security/nss/TAG-INFO
security/nss/automation/taskcluster/graph/src/extend.js
security/nss/automation/taskcluster/graph/src/queue.js
security/nss/automation/taskcluster/graph/src/try_syntax.js
security/nss/build.sh
security/nss/cmd/selfserv/selfserv.c
security/nss/cmd/shlibsign/shlibsign.c
security/nss/coreconf/config.gypi
security/nss/coreconf/coreconf.dep
security/nss/coreconf/sanitizers.py
security/nss/fuzz/cert_target.cc
security/nss/fuzz/fuzz.gyp
security/nss/fuzz/quickder_targets.cc
security/nss/fuzz/registry.h
security/nss/fuzz/spki_target.cc
security/nss/gtests/common/scoped_ptrs.h
security/nss/gtests/ssl_gtest/databuffer.h
security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc
security/nss/gtests/ssl_gtest/tls_agent.cc
security/nss/lib/freebl/freebl.gyp
security/nss/lib/nss/nss.h
security/nss/lib/softoken/softkver.h
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3ecc.c
security/nss/lib/ssl/tls13con.c
security/nss/lib/ssl/tls13exthandle.c
security/nss/lib/util/nssutil.h
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-86638bd12ab0
+6c26f0cd19ba
--- a/security/nss/automation/taskcluster/graph/src/extend.js
+++ b/security/nss/automation/taskcluster/graph/src/extend.js
@@ -327,16 +327,31 @@ async function scheduleFuzzing() {
         "cert nss/fuzz/corpus/cert -max_total_time=300"
     ],
     // Need a privileged docker container to remove this.
     env: {ASAN_OPTIONS: "detect_leaks=0"},
     symbol: "SCert",
     kind: "test"
   }));
 
+  queue.scheduleTask(merge(base, {
+    parent: task_build,
+    name: "SPKI",
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/fuzz.sh " +
+        "spki nss/fuzz/corpus/spki -max_total_time=300"
+    ],
+    // Need a privileged docker container to remove this.
+    env: {ASAN_OPTIONS: "detect_leaks=0"},
+    symbol: "SPKI",
+    kind: "test"
+  }));
+
   return queue.submit();
 }
 
 /*****************************************************************************/
 
 async function scheduleTestBuilds() {
   let base = {
     platform: "linux64",
--- a/security/nss/automation/taskcluster/graph/src/queue.js
+++ b/security/nss/automation/taskcluster/graph/src/queue.js
@@ -10,17 +10,17 @@ import * as image_builder from "./image_
 
 let maps = [];
 let filters = [];
 
 let tasks = new Map();
 let image_tasks = new Map();
 
 let queue = new taskcluster.Queue({
-  baseUrl: "http://taskcluster/queue/v1/"
+  baseUrl: "http://taskcluster/queue/v1"
 });
 
 function fromNow(hours) {
   let d = new Date();
   d.setHours(d.getHours() + (hours|0));
   return d.toJSON();
 }
 
--- a/security/nss/automation/taskcluster/graph/src/try_syntax.js
+++ b/security/nss/automation/taskcluster/graph/src/try_syntax.js
@@ -30,17 +30,17 @@ function parseOptions(opts) {
   if (platforms.length == 0 && opts.platform != "none") {
     platforms = allPlatforms;
   }
 
   // Parse unit tests.
   let aliases = {"gtests": "gtest"};
   let allUnitTests = ["bogo", "crmf", "chains", "cipher", "db", "ec", "fips",
                       "gtest", "lowhash", "merge", "sdr", "smime", "tools",
-                      "ssl", "mpi", "scert"];
+                      "ssl", "mpi", "scert", "spki"];
   let unittests = intersect(opts.unittests.split(/\s*,\s*/).map(t => {
     return aliases[t] || t;
   }), allUnitTests);
 
   // If the given value is "all" run all tests.
   // If it's nonsense then don't run any tests.
   if (opts.unittests == "all") {
     unittests = allUnitTests;
--- a/security/nss/build.sh
+++ b/security/nss/build.sh
@@ -9,16 +9,17 @@ set -e
 source $(dirname $0)/coreconf/nspr.sh
 
 # Usage info
 show_help() {
 cat << EOF
 
 Usage: ${0##*/} [-hcgv] [-j <n>] [--test] [--fuzz] [--scan-build[=output]]
                 [-m32] [--opt|-o] [--asan] [--ubsan] [--sancov[=edge|bb|func]]
+                [--pprof] [--msan]
 
 This script builds NSS with gyp and ninja.
 
 This build system is still under development.  It does not yet support all
 the features or platforms that NSS supports.
 
 NSS build tool options:
 
@@ -30,35 +31,37 @@ NSS build tool options:
     -m32          do a 32-bit build on a 64-bit system
     --test        ignore map files and export everything we have
     --fuzz        enable fuzzing mode. this always enables test builds
     --scan-build  run the build with scan-build (scan-build has to be in the path)
                   --scan-build=/out/path sets the output path for scan-build
     --opt|-o      do an opt build
     --asan        do an asan build
     --ubsan       do an ubsan build
+    --msan        do an msan build
     --sancov      do sanitize coverage builds
                   --sancov=func sets coverage to function level for example
+    --pprof       build with gperftool support
 EOF
 }
 
 if [ -n "$CCC" ] && [ -z "$CXX" ]; then
     export CXX="$CCC"
 fi
 
 opt_build=0
 build_64=0
 clean=0
 rebuild_gyp=0
 target=Debug
 verbose=0
 fuzz=0
 
 # parse parameters to store in config
-params=$(echo "$*" | perl -pe 's/-c|-v|-g|-j [0-9]*|-h//g' | perl -pe 's/^[ \t]*//')
+params=$(echo "$*" | perl -pe 's/-c|-v|-g|-j [0-9]*|-h//g' | perl -pe 's/^\s*(.*?)\s*$/\1/')
 params=$(echo "$params $CC $CCC" | tr " " "\n" | perl -pe '/^\s*$/d')
 params=$(echo "${params[*]}" | sort)
 
 cwd=$(cd $(dirname $0); pwd -P)
 dist_dir="$cwd/../dist"
 
 # try to guess sensible defaults
 arch=$(python "$cwd/coreconf/detect_host_arch.py")
@@ -96,16 +99,18 @@ while [ $# -gt 0 ]; do
         --scan-build) scanbuild=(scan-build) ;;
         --scan-build=?*) scanbuild=(scan-build -o "${1#*=}") ;;
         --opt|-o) opt_build=1 ;;
         -m32|--m32) build_64=0 ;;
         --asan) gyp_params+=(-Duse_asan=1); nspr_sanitizer asan ;;
         --ubsan) gyp_params+=(-Duse_ubsan=1); nspr_sanitizer ubsan ;;
         --sancov) gyp_params+=(-Duse_sancov=edge); nspr_sanitizer sancov edge ;;
         --sancov=?*) gyp_params+=(-Duse_sancov="${1#*=}"); nspr_sanitizer sancov "${1#*=}" ;;
+        --pprof) gyp_params+=(-Duse_pprof=1) ;;
+        --msan) gyp_params+=(-Duse_msan=1); nspr_sanitizer msan ;;
         *) show_help; exit ;;
     esac
     shift
 done
 
 if [ "$opt_build" = "1" ]; then
     target=Release
     nspr_opt+=(--disable-debug --enable-optimize)
--- a/security/nss/cmd/selfserv/selfserv.c
+++ b/security/nss/cmd/selfserv/selfserv.c
@@ -1251,17 +1251,17 @@ handle_connection(
     int newln = 0; /* # of consecutive newlns */
     int firstTime = 1;
     int reqLen;
     int rv;
     int numIOVs;
     PRSocketOptionData opt;
     PRIOVec iovs[16];
     char msgBuf[160];
-    char buf[10240];
+    char buf[10240] = { 0 };
     char fileName[513];
     char proto[128];
     PRDescIdentity aboveLayer = PR_INVALID_IO_LAYER;
 
     pBuf = buf;
     bufRem = sizeof buf;
 
     VLOG(("selfserv: handle_connection: starting"));
--- a/security/nss/cmd/shlibsign/shlibsign.c
+++ b/security/nss/cmd/shlibsign/shlibsign.c
@@ -702,17 +702,17 @@ getSlotList(CK_FUNCTION_LIST_PTR pFuncti
 }
 
 int
 main(int argc, char **argv)
 {
     PLOptState *optstate;
     char *program_name;
     char *libname = NULL;
-    PRLibrary *lib;
+    PRLibrary *lib = NULL;
     PRFileDesc *fd;
     PRStatus rv = PR_SUCCESS;
     const char *input_file = NULL; /* read/create encrypted data from here */
     char *output_file = NULL;      /* write new encrypted data here */
     int bytesRead;
     int bytesWritten;
     unsigned char file_buf[512];
     int count = 0;
@@ -865,34 +865,50 @@ main(int argc, char **argv)
         return 1;
     }
 
     /* Get the platform-dependent library name of the
      * NSS cryptographic module.
      */
     libname = PR_GetLibraryName(NULL, "softokn3");
     assert(libname != NULL);
+    if (!libname) {
+        PR_fprintf(PR_STDERR, "getting softokn3 failed");
+        goto cleanup;
+    }
     lib = PR_LoadLibrary(libname);
     assert(lib != NULL);
+    if (!lib) {
+        PR_fprintf(PR_STDERR, "loading softokn3 failed");
+        goto cleanup;
+    }
     PR_FreeLibraryName(libname);
 
     if (FIPSMODE) {
         /* FIPSMODE == FC_GetFunctionList */
         /* library path must be set to an already signed softokn3/freebl */
         pC_GetFunctionList = (CK_C_GetFunctionList)
             PR_FindFunctionSymbol(lib, "FC_GetFunctionList");
     } else {
         /* NON FIPS mode  == C_GetFunctionList */
         pC_GetFunctionList = (CK_C_GetFunctionList)
             PR_FindFunctionSymbol(lib, "C_GetFunctionList");
     }
     assert(pC_GetFunctionList != NULL);
+    if (!pC_GetFunctionList) {
+        PR_fprintf(PR_STDERR, "getting function list failed");
+        goto cleanup;
+    }
 
     crv = (*pC_GetFunctionList)(&pFunctionList);
     assert(crv == CKR_OK);
+    if (crv != CKR_OK) {
+        PR_fprintf(PR_STDERR, "loading function list failed");
+        goto cleanup;
+    }
 
     if (configDir) {
         if (!dbPrefix) {
             dbPrefix = PL_strdup("");
         }
         crv = softokn_Init(pFunctionList, configDir, dbPrefix);
         if (crv != CKR_OK) {
             logIt("Failed to use provided database directory "
@@ -1299,17 +1315,17 @@ cleanup:
     }
 #ifdef USES_LINKS
     if (link_file) { /* allocated by mkoutput function */
         PL_strfree(link_file);
     }
 #endif
 
     disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
-    if (!disableUnload) {
+    if (!disableUnload && lib) {
         PR_UnloadLibrary(lib);
     }
     PR_Cleanup();
 
     if (crv != CKR_OK)
         return crv;
 
     return (successful) ? 0 : 1;
--- a/security/nss/coreconf/config.gypi
+++ b/security/nss/coreconf/config.gypi
@@ -88,20 +88,22 @@
     'disable_libpkix%': 1,
     'disable_werror%': 0,
     'mozilla_client%': 0,
     'moz_fold_libs%': 0,
     'moz_folded_library_name%': '',
     'ssl_enable_zlib%': 1,
     'use_asan%': 0,
     'use_ubsan%': 0,
+    'use_msan%': 0,
     'use_sancov%': 0,
     'test_build%': 0,
     'fuzz%': 0,
     'sign_libs%': 1,
+    'use_pprof%': 0,
     'nss_public_dist_dir%': '<(nss_dist_dir)/public',
     'nss_private_dist_dir%': '<(nss_dist_dir)/private',
   },
   'target_defaults': {
     # Settings specific to targets should go here.
     # This is mostly for linking to libraries.
     'variables': {
       'mapfile%': '',
@@ -266,16 +268,19 @@
               [ 'target_arch=="ia32"', {
                 'cflags': ['-m32'],
                 'ldflags': ['-m32'],
               }],
               [ 'target_arch=="x64"', {
                 'cflags': ['-m64'],
                 'ldflags': ['-m64'],
               }],
+              [ 'use_pprof==1' , {
+                'ldflags': [ '-lprofiler' ],
+              }],
             ],
           }],
           [ 'disable_werror==0 and (OS=="linux" or OS=="mac")', {
             'cflags': [
               '<!@(<(python) <(DEPTH)/coreconf/werror.py)',
             ],
           }],
           [ 'fuzz==1', {
@@ -318,16 +323,31 @@
             'ldflags!': ['<@(no_ldflags)'],
             'xcode_settings': {
               'OTHER_CFLAGS': ['<@(ubsan_flags)'],
               'OTHER_LDFLAGS!': ['<@(no_ldflags)'],
               # See comment above.
               'LIBRARY_SEARCH_PATHS': ['/usr/lib <(ubsan_flags)'],
             },
           }],
+          [ 'use_msan==1', {
+            'variables': {
+              'msan_flags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py msan)',
+              'no_ldflags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py ld)',
+            },
+            'cflags': ['<@(msan_flags)'],
+            'ldflags': ['<@(msan_flags)'],
+            'ldflags!': ['<@(no_ldflags)'],
+            'xcode_settings': {
+              'OTHER_CFLAGS': ['<@(msan_flags)'],
+              'OTHER_LDFLAGS!': ['<@(no_ldflags)'],
+              # See comment above.
+              'LIBRARY_SEARCH_PATHS': ['/usr/lib <(msan_flags)'],
+            },
+          }],
           [ 'use_sancov!=0', {
             'variables': {
               'sancov_flags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py sancov <(use_sancov))',
               'no_ldflags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py ld)',
             },
             'cflags': ['<@(sancov_flags)'],
             'ldflags': ['<@(sancov_flags)'],
             'ldflags!': ['<@(no_ldflags)'],
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/security/nss/coreconf/sanitizers.py
+++ b/security/nss/coreconf/sanitizers.py
@@ -1,32 +1,36 @@
 #!/usr/bin/env python2
 
 from __future__ import print_function
 import sys
 
 def main():
     if len(sys.argv) < 2:
-        raise Exception('Specify either "ld", asan", "sancov" or "ubsan" as argument.')
+        raise Exception('Specify either "ld", asan", "msan", "sancov" or "ubsan" as argument.')
 
     sanitizer = sys.argv[1]
     if sanitizer == "ubsan":
         print('-fsanitize=undefined -fno-sanitize-recover=undefined ', end='')
         return
     if sanitizer == "asan":
         print('-fsanitize=address ', end='')
         print('-fno-omit-frame-pointer -fno-optimize-sibling-calls ', end='')
         return
+    if sanitizer == "msan":
+        print('-fsanitize=memory -fsanitize-memory-track-origins ', end='')
+        print('-fno-omit-frame-pointer -fno-optimize-sibling-calls ', end='')
+        return
     if sanitizer == "sancov":
         if len(sys.argv) < 3:
             raise Exception('sancov requires another argument (edge|bb|func).')
         print('-fsanitize-coverage='+sys.argv[2]+' ', end='')
         return
 
     # We have to remove this from the ld flags when building asan.
     if sanitizer == "ld":
         print('-Wl,-z,defs ', end='')
         return
 
-    raise Exception('Specify either "ld", asan", "sancov" or "ubsan" as argument.')
+    raise Exception('Specify either "ld", asan", "msan", "sancov" or "ubsan" as argument.')
 
 if __name__ == '__main__':
     main()
deleted file mode 100644
--- a/security/nss/fuzz/cert_target.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <stdint.h>
-
-#include "cert.h"
-
-#include "registry.h"
-
-extern "C" int cert_fuzzing_target(const uint8_t *Data, size_t Size) {
-  PORTCheapArenaPool pool;
-  PORT_InitCheapArena(&pool, DER_DEFAULT_CHUNKSIZE);
-
-  CERTCertificate cert;
-  SECItem data = {siBuffer, (unsigned char *)Data, (unsigned int)Size};
-  SEC_QuickDERDecodeItem(&pool.arena, &cert, SEC_SignedCertificateTemplate,
-                         &data);
-
-  PORT_DestroyCheapArena(&pool);
-  return 0;
-}
-
-REGISTER_FUZZING_TARGET("cert", cert_fuzzing_target, 3072, "Certificate Import")
--- a/security/nss/fuzz/fuzz.gyp
+++ b/security/nss/fuzz/fuzz.gyp
@@ -6,20 +6,19 @@
     '../coreconf/config.gypi',
     '../cmd/platlibs.gypi'
   ],
   'targets': [
     {
       'target_name': 'nssfuzz',
       'type': 'executable',
       'sources': [
-        'cert_target.cc',
+        'nssfuzz.cc',
         'pkcs8_target.cc',
-        'spki_target.cc',
-        'nssfuzz.cc',
+        'quickder_targets.cc',
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/fuzz/libFuzzer/libFuzzer.gyp:libFuzzer'
       ]
     }
   ],
   'target_defaults': {
new file mode 100644
--- /dev/null
+++ b/security/nss/fuzz/quickder_targets.cc
@@ -0,0 +1,36 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdint.h>
+
+#include "cert.h"
+
+#include "registry.h"
+
+void QuickDERDecode(void *dst, const SEC_ASN1Template *tpl, const uint8_t *buf,
+                    size_t len) {
+  PORTCheapArenaPool pool;
+  SECItem data = {siBuffer, const_cast<unsigned char *>(buf),
+                  static_cast<unsigned int>(len)};
+
+  PORT_InitCheapArena(&pool, DER_DEFAULT_CHUNKSIZE);
+  (void)SEC_QuickDERDecodeItem(&pool.arena, dst, tpl, &data);
+  PORT_DestroyCheapArena(&pool);
+}
+
+extern "C" int cert_fuzzing_target(const uint8_t *Data, size_t Size) {
+  CERTCertificate cert;
+  QuickDERDecode(&cert, SEC_SignedCertificateTemplate, Data, Size);
+  return 0;
+}
+
+REGISTER_FUZZING_TARGET("cert", cert_fuzzing_target, 3072, "Certificate Import")
+
+extern "C" int spki_fuzzing_target(const uint8_t *Data, size_t Size) {
+  CERTSubjectPublicKeyInfo spki;
+  QuickDERDecode(&spki, CERT_SubjectPublicKeyInfoTemplate, Data, Size);
+  return 0;
+}
+
+REGISTER_FUZZING_TARGET("spki", spki_fuzzing_target, 1024, "SPKI Import")
--- a/security/nss/fuzz/registry.h
+++ b/security/nss/fuzz/registry.h
@@ -58,14 +58,14 @@ class Registry {
     return GetInstance().targets_[name];
   }
 
   Registry() {}
 
   std::map<std::string, TargetData> targets_;
 };
 
-#define REGISTER_FUZZING_TARGET(name, func, max_len, desc)           \
-  static void __attribute__((constructor)) RegisterFuzzingTarget() { \
-    Registry::Add(name, func, max_len, desc);                        \
+#define REGISTER_FUZZING_TARGET(name, func, max_len, desc)     \
+  static void __attribute__((constructor)) Register_##func() { \
+    Registry::Add(name, func, max_len, desc);                  \
   }
 
 #endif  // registry_h__
deleted file mode 100644
--- a/security/nss/fuzz/spki_target.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <assert.h>
-#include <stdint.h>
-#include <memory>
-
-#include "keyhi.h"
-#include "pk11pub.h"
-
-#include "registry.h"
-#include "shared.h"
-
-extern "C" int spki_fuzzing_target(const uint8_t *Data, size_t Size) {
-  SECItem data = {siBuffer, (unsigned char *)Data, (unsigned int)Size};
-
-  static std::unique_ptr<NSSDatabase> db(new NSSDatabase());
-  assert(db != nullptr);
-
-  CERTSubjectPublicKeyInfo *spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&data);
-
-  if (spki) {
-    SECKEYPublicKey *key = SECKEY_ExtractPublicKey(spki);
-    SECKEY_DestroyPublicKey(key);
-  }
-
-  SECKEY_DestroySubjectPublicKeyInfo(spki);
-
-  return 0;
-}
-
-REGISTER_FUZZING_TARGET("spki", spki_fuzzing_target, 1024, "SPKI Import")
--- a/security/nss/gtests/common/scoped_ptrs.h
+++ b/security/nss/gtests/common/scoped_ptrs.h
@@ -14,16 +14,17 @@
 
 namespace nss_test {
 
 struct ScopedDelete {
   void operator()(CERTCertificate* cert) { CERT_DestroyCertificate(cert); }
   void operator()(CERTCertificateList* list) {
     CERT_DestroyCertificateList(list);
   }
+  void operator()(CERTCertList* list) { CERT_DestroyCertList(list); }
   void operator()(CERTSubjectPublicKeyInfo* spki) {
     SECKEY_DestroySubjectPublicKeyInfo(spki);
   }
   void operator()(PK11SlotInfo* slot) { PK11_FreeSlot(slot); }
   void operator()(PK11SymKey* key) { PK11_FreeSymKey(key); }
   void operator()(SECAlgorithmID* id) { SECOID_DestroyAlgorithmID(id, true); }
   void operator()(SECItem* item) { SECITEM_FreeItem(item, true); }
   void operator()(SECKEYPublicKey* key) { SECKEY_DestroyPublicKey(key); }
@@ -39,16 +40,17 @@ struct ScopedMaybeDelete {
     }
   }
 };
 
 #define SCOPED(x) typedef std::unique_ptr<x, ScopedMaybeDelete<x> > Scoped##x
 
 SCOPED(CERTCertificate);
 SCOPED(CERTCertificateList);
+SCOPED(CERTCertList);
 SCOPED(CERTSubjectPublicKeyInfo);
 SCOPED(PK11SlotInfo);
 SCOPED(PK11SymKey);
 SCOPED(SECAlgorithmID);
 SCOPED(SECItem);
 SCOPED(SECKEYPublicKey);
 SCOPED(SECKEYPrivateKey);
 
--- a/security/nss/gtests/ssl_gtest/databuffer.h
+++ b/security/nss/gtests/ssl_gtest/databuffer.h
@@ -131,17 +131,17 @@ class DataBuffer {
     len_ = index + ins_len + tail_len;
     data_ = new uint8_t[len_ ? len_ : 1];
 
     // The head of the old.
     if (old_value) {
       Write(0, old_value, std::min(old_len, index));
     }
     // Maybe a gap.
-    if (index > old_len) {
+    if (old_value && index > old_len) {
       memset(old_value + index, 0, index - old_len);
     }
     // The new.
     Write(index, ins, ins_len);
     // The tail of the old.
     if (tail_len > 0) {
       Write(index + ins_len, old_value + index + remove, tail_len);
     }
--- a/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc
@@ -541,9 +541,69 @@ TEST_P(TlsConnectTls13, ResumeFfdhe) {
   server_->SetPacketFilter(serverCapture);
   ExpectResumption(RESUME_TICKET);
   Connect();
   CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign, ssl_sig_none);
   ASSERT_LT(0UL, clientCapture->extension().len());
   ASSERT_LT(0UL, serverCapture->extension().len());
 }
 
+class TlsDheSkeChangeSignature : public TlsHandshakeFilter {
+ public:
+  TlsDheSkeChangeSignature(uint16_t version, const uint8_t* data, size_t len)
+      : version_(version), data_(data), len_(len) {}
+
+ protected:
+  virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
+                                               const DataBuffer& input,
+                                               DataBuffer* output) {
+    if (header.handshake_type() != kTlsHandshakeServerKeyExchange) {
+      return KEEP;
+    }
+
+    TlsParser parser(input);
+    EXPECT_TRUE(parser.SkipVariable(2));  // dh_p
+    EXPECT_TRUE(parser.SkipVariable(2));  // dh_g
+    EXPECT_TRUE(parser.SkipVariable(2));  // dh_Ys
+
+    // Copy DH params to output.
+    size_t offset = output->Write(0, input.data(), parser.consumed());
+
+    if (version_ == SSL_LIBRARY_VERSION_TLS_1_2) {
+      // Write signature algorithm.
+      offset = output->Write(offset, ssl_sig_dsa_sha256, 2);
+    }
+
+    // Write new signature.
+    offset = output->Write(offset, len_, 2);
+    offset = output->Write(offset, data_, len_);
+
+    return CHANGE;
+  }
+
+ private:
+  uint16_t version_;
+  const uint8_t* data_;
+  size_t len_;
+};
+
+TEST_P(TlsConnectGenericPre13, InvalidDERSignatureFfdhe) {
+  const uint8_t kBogusDheSignature[] = {
+      0x30, 0x69, 0x3c, 0x02, 0x1c, 0x7d, 0x0b, 0x2f, 0x64, 0x00, 0x27,
+      0xae, 0xcf, 0x1e, 0x28, 0x08, 0x6a, 0x7f, 0xb1, 0xbd, 0x78, 0xb5,
+      0x3b, 0x8c, 0x8f, 0x59, 0xed, 0x8f, 0xee, 0x78, 0xeb, 0x2c, 0xe9,
+      0x02, 0x1c, 0x6d, 0x7f, 0x3c, 0x0f, 0xf4, 0x44, 0x35, 0x0b, 0xb2,
+      0x6d, 0xdc, 0xb8, 0x21, 0x87, 0xdd, 0x0d, 0xb9, 0x46, 0x09, 0x3e,
+      0xef, 0x81, 0x5b, 0x37, 0x09, 0x39, 0xeb};
+
+  Reset(TlsAgent::kServerDsa);
+
+  const std::vector<SSLNamedGroup> client_groups = {ssl_grp_ffdhe_2048};
+  client_->ConfigNamedGroups(client_groups);
+
+  server_->SetPacketFilter(new TlsDheSkeChangeSignature(
+      version_, kBogusDheSignature, sizeof(kBogusDheSignature)));
+
+  ConnectExpectFail();
+  client_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+}
+
 }  // namespace nss_test
--- a/security/nss/gtests/ssl_gtest/tls_agent.cc
+++ b/security/nss/gtests/ssl_gtest/tls_agent.cc
@@ -145,16 +145,20 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc
   if (rv != SECSuccess) return false;
 
   if (role_ == SERVER) {
     EXPECT_TRUE(ConfigServerCert(name_, true));
 
     rv = SSL_SNISocketConfigHook(ssl_fd_, SniHook, this);
     EXPECT_EQ(SECSuccess, rv);
     if (rv != SECSuccess) return false;
+
+    ScopedCERTCertList anchors(CERT_NewCertList());
+    rv = SSL_SetTrustAnchors(ssl_fd_, anchors.get());
+    if (rv != SECSuccess) return false;
   } else {
     rv = SSL_SetURL(ssl_fd_, "server");
     EXPECT_EQ(SECSuccess, rv);
     if (rv != SECSuccess) return false;
   }
 
   rv = SSL_AuthCertificateHook(ssl_fd_, AuthCertificateHook, this);
   EXPECT_EQ(SECSuccess, rv);
--- a/security/nss/lib/freebl/freebl.gyp
+++ b/security/nss/lib/freebl/freebl.gyp
@@ -368,16 +368,20 @@
           }],
           [ 'target_arch=="x64"', {
             'defines': [
               'MP_IS_LITTLE_ENDIAN',
               'NSS_BEVAND_ARCFOUR',
               'MPI_AMD64',
               'MP_ASSEMBLY_MULTIPLY',
               'NSS_USE_COMBA',
+            ],
+          }],
+          [ 'target_arch=="x64" and use_msan==0', {
+            'defines': [
               'USE_HW_AES',
               'INTEL_GCM',
             ],
           }],
           [ 'target_arch=="ia32"', {
             'defines': [
               'MP_IS_LITTLE_ENDIAN',
               'MP_ASSEMBLY_MULTIPLY',
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -17,19 +17,19 @@
 
 /*
  * NSS's major version, minor version, patch level, build number, and whether
  * this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define NSS_VERSION "3.29" _NSS_CUSTOMIZED " Beta"
+#define NSS_VERSION "3.28" _NSS_CUSTOMIZED " Beta"
 #define NSS_VMAJOR 3
-#define NSS_VMINOR 29
+#define NSS_VMINOR 28
 #define NSS_VPATCH 0
 #define NSS_VBUILD 0
 #define NSS_BETA PR_TRUE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -16,16 +16,16 @@
 
 /*
  * Softoken's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
  */
-#define SOFTOKEN_VERSION "3.29" SOFTOKEN_ECC_STRING " Beta"
+#define SOFTOKEN_VERSION "3.28" SOFTOKEN_ECC_STRING " Beta"
 #define SOFTOKEN_VMAJOR 3
-#define SOFTOKEN_VMINOR 29
+#define SOFTOKEN_VMINOR 28
 #define SOFTOKEN_VPATCH 0
 #define SOFTOKEN_VBUILD 0
 #define SOFTOKEN_BETA PR_TRUE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -1249,17 +1249,17 @@ done:
 
 /* Called from ssl3_HandleServerKeyExchange, ssl3_HandleCertificateVerify */
 SECStatus
 ssl3_VerifySignedHashes(sslSocket *ss, SSLSignatureScheme scheme, SSL3Hashes *hash,
                         SECItem *buf)
 {
     SECKEYPublicKey *key;
     SECItem *signature = NULL;
-    SECStatus rv;
+    SECStatus rv = SECFailure;
     SECItem hashItem;
     SECOidTag encAlg;
     SECOidTag hashAlg;
     void *pwArg = ss->pkcs11PinArg;
     PRBool isRsaPssScheme = ssl_IsRsaPssSignatureScheme(scheme);
 
     PRINT_BUF(60, (NULL, "check signed hashes",
                    buf->data, buf->len));
@@ -1292,17 +1292,17 @@ ssl3_VerifySignedHashes(sslSocket *ss, S
                 hashItem.len = hash->len;
             }
             /* Allow DER encoded DSA signatures in SSL 3.0 */
             if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0 ||
                 buf->len != SECKEY_SignatureLen(key)) {
                 signature = DSAU_DecodeDerSigToLen(buf, SECKEY_SignatureLen(key));
                 if (!signature) {
                     PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
-                    return SECFailure;
+                    goto loser;
                 }
                 buf = signature;
             }
             if (scheme == ssl_sig_none) {
                 scheme = ssl_sig_dsa_sha1;
             }
             break;
 
@@ -1323,19 +1323,18 @@ ssl3_VerifySignedHashes(sslSocket *ss, S
                 hashItem.len = hash->len;
             }
             if (scheme == ssl_sig_none) {
                 scheme = ssl_sig_ecdsa_sha1;
             }
             break;
 
         default:
-            SECKEY_DestroyPublicKey(key);
             PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
-            return SECFailure;
+            goto loser;
     }
 
     PRINT_BUF(60, (NULL, "hash(es) to be verified",
                    hashItem.data, hashItem.len));
 
     if (isRsaPssScheme ||
         hashAlg == SEC_OID_UNKNOWN ||
         SECKEY_GetPublicKeyType(key) == dsaKey) {
@@ -1360,30 +1359,32 @@ ssl3_VerifySignedHashes(sslSocket *ss, S
             mech = CKM_RSA_PKCS_PSS;
         }
 
         rv = PK11_VerifyWithMechanism(key, mech, params, buf, &hashItem, pwArg);
     } else {
         rv = VFY_VerifyDigestDirect(&hashItem, key, buf, encAlg, hashAlg,
                                     pwArg);
     }
-    SECKEY_DestroyPublicKey(key);
     if (signature) {
         SECITEM_FreeItem(signature, PR_TRUE);
     }
-#ifdef UNSAFE_FUZZER_MODE
-    rv = SECSuccess;
-    PORT_SetError(0);
-#endif
     if (rv != SECSuccess) {
         ssl_MapLowLevelError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
     }
     if (!ss->sec.isServer) {
         ss->sec.signatureScheme = scheme;
     }
+
+loser:
+    SECKEY_DestroyPublicKey(key);
+#ifdef UNSAFE_FUZZER_MODE
+    rv = SECSuccess;
+    PORT_SetError(0);
+#endif
     return rv;
 }
 
 /* Caller must set hiLevel error code. */
 /* Called from ssl3_ComputeDHKeyHash
  * which are called from ssl3_HandleServerKeyExchange.
  *
  * hashAlg: ssl_hash_none indicates the pre-1.2, MD5/SHA1 combination hash.
@@ -6499,24 +6500,23 @@ ssl3_SendCertificateVerify(sslSocket *ss
     }
     if (ss->ssl3.hs.hashType == handshake_hash_record &&
         hashAlg != ssl3_GetSuitePrfHash(ss)) {
         rv = ssl3_ComputeHandshakeHash(ss->ssl3.hs.messages.buf,
                                        ss->ssl3.hs.messages.len,
                                        hashAlg, &hashes);
         if (rv != SECSuccess) {
             ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
-            goto done;
         }
     } else {
         rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0);
     }
     ssl_ReleaseSpecReadLock(ss);
     if (rv != SECSuccess) {
-        goto done; /* err code was set by ssl3_ComputeHandshakeHashes */
+        goto done; /* err code was set by ssl3_ComputeHandshakeHash(es) */
     }
 
     isTLS12 = (PRBool)(ss->version == SSL_LIBRARY_VERSION_TLS_1_2);
     PORT_Assert(ss->version <= SSL_LIBRARY_VERSION_TLS_1_2);
 
     rv = ssl3_SignHashes(ss, &hashes, privKey, &buf);
     if (rv == SECSuccess && !ss->sec.isServer) {
         /* Remember the info about the slot that did the signing.
@@ -9448,20 +9448,17 @@ ssl3_SendDHServerKeyExchange(sslSocket *
         goto loser;
     }
 
     certPrivateKey = ss->sec.serverCert->serverKeyPair->privKey;
     rv = ssl3_SignHashes(ss, &hashes, certPrivateKey, &signed_hash);
     if (rv != SECSuccess) {
         goto loser; /* ssl3_SignHashes has set err. */
     }
-    if (signed_hash.data == NULL) {
-        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
+
     length = 2 + pubKey->u.dh.prime.len +
              2 + pubKey->u.dh.base.len +
              2 + pubKey->u.dh.prime.len +
              2 + signed_hash.len;
 
     if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
         length += 2;
     }
@@ -13189,16 +13186,19 @@ ssl3_DestroySSL3Info(sslSocket *ss)
 
     if (ss->ssl3.peerCertArena != NULL)
         ssl3_CleanupPeerCerts(ss);
 
     if (ss->ssl3.clientCertChain != NULL) {
         CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
         ss->ssl3.clientCertChain = NULL;
     }
+    if (ss->ssl3.ca_list) {
+        CERT_FreeDistNames(ss->ssl3.ca_list);
+    }
 
     /* clean up handshake */
     if (ss->ssl3.hs.md5) {
         PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
     }
     if (ss->ssl3.hs.sha) {
         PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE);
     }
--- a/security/nss/lib/ssl/ssl3ecc.c
+++ b/security/nss/lib/ssl/ssl3ecc.c
@@ -678,17 +678,17 @@ loser:
 
 SECStatus
 ssl3_SendECDHServerKeyExchange(sslSocket *ss)
 {
     SECStatus rv = SECFailure;
     int length;
     PRBool isTLS12;
     SECItem signed_hash = { siBuffer, NULL, 0 };
-    SSLHashType hashAlg = ssl_hash_none;
+    SSLHashType hashAlg;
     SSL3Hashes hashes;
 
     SECItem ec_params = { siBuffer, NULL, 0 };
     unsigned char paramBuf[3];
     const sslNamedGroupDef *ecGroup;
     sslEphemeralKeyPair *keyPair;
     SECKEYPublicKey *pubKey;
 
@@ -746,21 +746,16 @@ ssl3_SendECDHServerKeyExchange(sslSocket
 
     isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
 
     rv = ssl3_SignHashes(ss, &hashes,
                          ss->sec.serverCert->serverKeyPair->privKey, &signed_hash);
     if (rv != SECSuccess) {
         goto loser; /* ssl3_SignHashes has set err. */
     }
-    if (signed_hash.data == NULL) {
-        /* how can this happen and rv == SECSuccess ?? */
-        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
-        goto loser;
-    }
 
     length = ec_params.len +
              1 + pubKey->u.ec.publicValue.len +
              (isTLS12 ? 2 : 0) + 2 + signed_hash.len;
 
     rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
     if (rv != SECSuccess) {
         goto loser; /* err set by AppendHandshake. */
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -380,16 +380,17 @@ SSL_SendAdditionalKeyShares(PRFileDesc *
  * the requisite type and creates a share for that.
  *
  * Called from ssl3_SendClientHello.
  */
 SECStatus
 tls13_SetupClientHello(sslSocket *ss)
 {
     unsigned int i;
+    SSL3Statistics *ssl3stats = SSL_GetStatistics();
     NewSessionTicket *session_ticket = NULL;
     sslSessionID *sid = ss->sec.ci.sid;
     unsigned int numShares = 0;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
     PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
 
@@ -430,25 +431,32 @@ tls13_SetupClientHello(sslSocket *ss)
              session_ticket->received_timestamp >
          ssl_Time())) {
         ss->statelessResume = PR_TRUE;
     }
 
     if (ss->statelessResume) {
         SECStatus rv;
 
+        PORT_Assert(ss->sec.ci.sid);
         rv = tls13_RecoverWrappedSharedSecret(ss, ss->sec.ci.sid);
         if (rv != SECSuccess) {
             FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+            SSL_AtomicIncrementLong(&ssl3stats->sch_sid_cache_not_ok);
+            ss->sec.uncache(ss->sec.ci.sid);
+            ssl_FreeSID(ss->sec.ci.sid);
+            ss->sec.ci.sid = NULL;
             return SECFailure;
         }
 
         rv = ssl3_SetCipherSuite(ss, ss->sec.ci.sid->u.ssl3.cipherSuite, PR_FALSE);
-        if (rv != SECSuccess)
+        if (rv != SECSuccess) {
+            FATAL_ERROR(ss, PORT_GetError(), internal_error);
             return SECFailure;
+        }
 
         rv = tls13_ComputeEarlySecrets(ss);
         if (rv != SECSuccess) {
             FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
             return SECFailure;
         }
     }
 
@@ -1329,16 +1337,17 @@ tls13_HandleClientHelloPart2(sslSocket *
                                 &ss->ssl3.hs.srvVirtName) != SECEqual) {
             FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO,
                         handshake_failure);
             goto loser;
         }
 
         rv = tls13_RecoverWrappedSharedSecret(ss, sid);
         if (rv != SECSuccess) {
+            SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
             FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
             goto loser;
         }
         tls13_RestoreCipherInfo(ss, sid);
 
         ss->sec.serverCert = ssl_FindServerCert(ss, &sid->certType);
         PORT_Assert(ss->sec.serverCert);
         ss->sec.localCert = CERT_DupCertificate(ss->sec.serverCert->serverCert);
@@ -1994,29 +2003,17 @@ tls13_HandleServerHelloPart2(sslSocket *
     }
 
     /* Now create a synthetic kea_def that we can tweak. */
     ss->ssl3.hs.kea_def_mutable = *ss->ssl3.hs.kea_def;
     ss->ssl3.hs.kea_def = &ss->ssl3.hs.kea_def_mutable;
 
     if (ss->statelessResume) {
         /* PSK */
-        PRBool cacheOK = PR_FALSE;
-        do {
-            ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk;
-
-            cacheOK = PR_TRUE;
-        } while (0);
-
-        if (!cacheOK) {
-            SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_cache_not_ok);
-            ss->sec.uncache(sid);
-            return SECFailure;
-        }
-
+        ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk;
         tls13_RestoreCipherInfo(ss, sid);
         if (sid->peerCert) {
             ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
         }
 
         SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_cache_hits);
         SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_stateless_resumes);
     } else {
--- a/security/nss/lib/ssl/tls13exthandle.c
+++ b/security/nss/lib/ssl/tls13exthandle.c
@@ -528,20 +528,18 @@ tls13_ClientSendPreSharedKeyXtn(const ss
         rv = ssl3_ExtAppendHandshakeVariable(ss,
                                              binder, binderLen, 1);
         if (rv != SECSuccess)
             goto loser;
 
         PRINT_BUF(50, (ss, "Sending PreSharedKey value",
                        session_ticket->ticket.data,
                        session_ticket->ticket.len));
+
         xtnData->sentSessionTicketInClientHello = PR_TRUE;
-        if (rv != SECSuccess)
-            goto loser;
-
         xtnData->advertised[xtnData->numAdvertised++] =
             ssl_tls13_pre_shared_key_xtn;
     }
     return extension_length;
 
 loser:
     xtnData->ticketTimestampVerified = PR_FALSE;
     return -1;
--- a/security/nss/lib/util/nssutil.h
+++ b/security/nss/lib/util/nssutil.h
@@ -14,19 +14,19 @@
 
 /*
  * NSS utilities's major version, minor version, patch level, build number,
  * and whether this is a beta release.
  *
  * The format of the version string should be
  *     "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
  */
-#define NSSUTIL_VERSION "3.29 Beta"
+#define NSSUTIL_VERSION "3.28 Beta"
 #define NSSUTIL_VMAJOR 3
-#define NSSUTIL_VMINOR 29
+#define NSSUTIL_VMINOR 28
 #define NSSUTIL_VPATCH 0
 #define NSSUTIL_VBUILD 0
 #define NSSUTIL_BETA PR_TRUE
 
 SEC_BEGIN_PROTOS
 
 /*
  * Returns a const string of the UTIL library version.