Bug 1386955 - land NSS a0a4e05dcdd5 UPGRADE_NSS_RELEASE, r=me
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Fri, 04 Aug 2017 14:13:06 +0200
changeset 373031 7185eea462e908246d15e6cf6c833e26929ac2d7
parent 373030 952b32c08bc7373bac4298865b9ff1f86604714d
child 373032 5f192263de3e033c3849729724dd388a24dca21e
push id32288
push userarchaeopteryx@coole-files.de
push dateSat, 05 Aug 2017 09:55:48 +0000
treeherdermozilla-central@933a04a91ce3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1386955
milestone57.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 1386955 - land NSS a0a4e05dcdd5 UPGRADE_NSS_RELEASE, r=me
old-configure.in
security/nss/TAG-INFO
security/nss/automation/abi-check/previous-nss-release
security/nss/automation/clang-format/run_clang_format.sh
security/nss/automation/release/nspr-version.txt
security/nss/cmd/lib/secutil.c
security/nss/cmd/modutil/error.h
security/nss/cmd/pp/pp.c
security/nss/cmd/tstclnt/tstclnt.c
security/nss/coreconf/coreconf.dep
security/nss/cpputil/tls_parser.h
security/nss/fuzz/config/clone_libfuzzer.sh
security/nss/gtests/certdb_gtest/alg1485_unittest.cc
security/nss/gtests/manifest.mn
security/nss/gtests/softoken_gtest/Makefile
security/nss/gtests/softoken_gtest/manifest.mn
security/nss/gtests/softoken_gtest/softoken_gtest.cc
security/nss/gtests/softoken_gtest/softoken_gtest.gyp
security/nss/gtests/ssl_gtest/manifest.mn
security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
security/nss/gtests/ssl_gtest/ssl_gtest.gyp
security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
security/nss/gtests/ssl_gtest/ssl_misc_unittest.cc
security/nss/gtests/ssl_gtest/tls_agent.cc
security/nss/gtests/ssl_gtest/tls_agent.h
security/nss/gtests/ssl_gtest/tls_connect.cc
security/nss/gtests/ssl_gtest/tls_filter.cc
security/nss/gtests/ssl_gtest/tls_filter.h
security/nss/lib/certdb/alg1485.c
security/nss/lib/freebl/config.mk
security/nss/lib/freebl/freebl.gyp
security/nss/lib/nss/nss.h
security/nss/lib/pki/pki3hack.c
security/nss/lib/softoken/pkcs11.c
security/nss/lib/softoken/sdb.c
security/nss/lib/softoken/softkver.h
security/nss/lib/ssl/SSLerrs.h
security/nss/lib/ssl/exports.gyp
security/nss/lib/ssl/manifest.mn
security/nss/lib/ssl/ssl.def
security/nss/lib/ssl/ssl.h
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3prot.h
security/nss/lib/ssl/sslerr.h
security/nss/lib/ssl/sslexp.h
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslsock.c
security/nss/lib/ssl/tls13con.c
security/nss/lib/ssl/tls13con.h
security/nss/lib/ssl/tls13exthandle.c
security/nss/lib/util/nssutil.h
security/nss/lib/util/secoid.c
security/nss/mach
security/nss/nss.gyp
security/nss/tests/gtests/gtests.sh
--- a/old-configure.in
+++ b/old-configure.in
@@ -1914,17 +1914,17 @@ dnl = If NSS was not detected in the sys
 dnl = use the one in the source tree (mozilla/security/nss)
 dnl ========================================================
 
 MOZ_ARG_WITH_BOOL(system-nss,
 [  --with-system-nss       Use system installed NSS],
     _USE_SYSTEM_NSS=1 )
 
 if test -n "$_USE_SYSTEM_NSS"; then
-    AM_PATH_NSS(3.32, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
+    AM_PATH_NSS(3.33, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
 fi
 
 if test -n "$MOZ_SYSTEM_NSS"; then
    NSS_LIBS="$NSS_LIBS -lcrmf"
 else
    NSS_CFLAGS="-I${DIST}/include/nss"
    case "${OS_ARCH}" in
         # Only few platforms have been tested with GYP
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3_32_RTM
+a0a4e05dcdd5
--- a/security/nss/automation/abi-check/previous-nss-release
+++ b/security/nss/automation/abi-check/previous-nss-release
@@ -1,1 +1,1 @@
-NSS_3_31_BRANCH
+NSS_3_32_BRANCH
--- a/security/nss/automation/clang-format/run_clang_format.sh
+++ b/security/nss/automation/clang-format/run_clang_format.sh
@@ -1,67 +1,68 @@
 #!/usr/bin/env bash
 
 if [[ $(id -u) -eq 0 ]]; then
     # Drop privileges by re-running this script.
     # Note: this mangles arguments, better to avoid running scripts as root.
     exec su worker -c "$0 $*"
 fi
 
+set -e
+
 # Apply clang-format on the provided folder and verify that this doesn't change any file.
 # If any file differs after formatting, the script eventually exits with 1.
 # Any differences between formatted and unformatted files is printed to stdout to give a hint what's wrong.
 
 # Includes a default set of directories NOT to clang-format on.
 blacklist=(
      "./automation" \
      "./coreconf" \
      "./doc" \
      "./pkg" \
      "./tests" \
      "./lib/libpkix" \
      "./lib/zlib" \
      "./lib/sqlite" \
      "./gtests/google_test" \
-     "./.hg" \
      "./out" \
 )
 
-top="$(dirname $0)/../.."
-cd "$top"
+top=$(cd "$(dirname $0)/../.."; pwd -P)
 
 if [ $# -gt 0 ]; then
     dirs=("$@")
 else
-    dirs=($(find . -maxdepth 2 -mindepth 1 -type d ! -path . \( ! -regex '.*/' \)))
+    cd "$top"
+    dirs=($(find . -maxdepth 2 -mindepth 1 -type d ! -path '*/.*' -print))
 fi
 
 format_folder()
 {
     for black in "${blacklist[@]}"; do
         if [[ "$1" == "$black"* ]]; then
             echo "skip $1"
             return 1
         fi
     done
     return 0
 }
 
 for dir in "${dirs[@]}"; do
-    if format_folder "$dir" ; then
+    if format_folder "$dir"; then
         c="${dir//[^\/]}"
         echo "formatting $dir ..."
-        depth=""
+        depth=()
         if [ "${#c}" == "1" ]; then
-            depth="-maxdepth 1"
+            depth+=(-maxdepth 1)
         fi
-        find "$dir" $depth -type f \( -name '*.[ch]' -o -name '*.cc' \) -exec clang-format -i {} \+
+        find "$dir" "${depth[@]}" -type f \( -name '*.[ch]' -o -name '*.cc' \) -exec clang-format -i {} \+
     fi
 done
 
 TMPFILE=$(mktemp /tmp/$(basename $0).XXXXXX)
-trap 'rm $TMPFILE' exit
-if (cd $(dirname $0); hg root >/dev/null 2>&1); then
+trap 'rm -f $TMPFILE' exit
+if [[ -d "$top/.hg" ]]; then
     hg diff --git "$top" | tee $TMPFILE
 else
     git -C "$top" diff | tee $TMPFILE
 fi
 [[ ! -s $TMPFILE ]]
--- a/security/nss/automation/release/nspr-version.txt
+++ b/security/nss/automation/release/nspr-version.txt
@@ -1,9 +1,9 @@
-4.16
+4.15
 
 # The first line of this file must contain the human readable NSPR
 # version number, which is the minimum required version of NSPR
 # that is supported by this version of NSS.
 #
 # This information is used by release automation,
 # when creating an NSS source archive.
 #
--- a/security/nss/cmd/lib/secutil.c
+++ b/security/nss/cmd/lib/secutil.c
@@ -986,17 +986,17 @@ secu_PrintUniversalString(FILE *out, con
     len = (int)(my.len / 4);
     tmp.data = (unsigned char *)PORT_Alloc(len);
     if (!tmp.data)
         goto loser;
     tmp.len = len;
     for (s = my.data, d = tmp.data; len > 0; len--) {
         PRUint32 bmpChar = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
         s += 4;
-        if (!isprint(bmpChar))
+        if (!isprint(bmpChar & 0xFF))
             goto loser;
         *d++ = (unsigned char)bmpChar;
     }
     secu_PrintRawString(out, &tmp, m, level);
     PORT_Free(tmp.data);
     return;
 
 loser:
--- a/security/nss/cmd/modutil/error.h
+++ b/security/nss/cmd/modutil/error.h
@@ -104,17 +104,17 @@ static char *errStrings[] = {
     "ERROR: Unable to authenticate to token \"%s\".\n",
     "ERROR: Slot \"%s\" not found.\n",
     "ERROR: Failed to %s slot \"%s\".\n",
     "ERROR: Failed to update module \"%s\".\n",
     "ERROR: Failed to change defaults.\n",
     "ERROR: Failed to change default.\n",
     "ERROR: Unable to read from standard input.\n",
     "ERROR: Unknown error occurred.\n",
-    "ERROR: -nocertdb option can only be used with the -jar command.\n"
+    "ERROR: -nocertdb option can only be used with the -jar command.\n",
     "ERROR: NSS_Initialize() failed.\n"
 };
 
 typedef enum {
     FIPS_ENABLED_MSG = 0,
     FIPS_DISABLED_MSG,
     USING_DBDIR_MSG,
     CREATING_DB_MSG,
--- a/security/nss/cmd/pp/pp.c
+++ b/security/nss/cmd/pp/pp.c
@@ -79,25 +79,29 @@ main(int argc, char **argv)
                 ascii = 1;
                 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);
+                    PORT_Free(typeTag);
+                    PL_DestroyOptState(optstate);
                     return -1;
                 }
                 break;
 
             case 'o':
                 outFile = fopen(optstate->value, "w");
                 if (!outFile) {
                     fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
                             progName, optstate->value);
+                    PORT_Free(typeTag);
+                    PL_DestroyOptState(optstate);
                     return -1;
                 }
                 break;
 
             case 't':
                 typeTag = strdup(optstate->value);
                 break;
 
--- a/security/nss/cmd/tstclnt/tstclnt.c
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -26,16 +26,17 @@
 
 #include "nspr.h"
 #include "prio.h"
 #include "prnetdb.h"
 #include "nss.h"
 #include "ocsp.h"
 #include "ssl.h"
 #include "sslproto.h"
+#include "sslexp.h"
 #include "pk11func.h"
 #include "secmod.h"
 #include "plgetopt.h"
 #include "plstr.h"
 
 #if defined(WIN32)
 #include <fcntl.h>
 #include <io.h>
@@ -246,16 +247,17 @@ PrintParameterUsage(void)
     fprintf(stderr, "%-20s Require the use of FFDHE supported groups [RFC7919]\n", "-H");
     fprintf(stderr, "%-20s Read from a file instead of stdin\n", "-A");
     fprintf(stderr, "%-20s Allow 0-RTT data (TLS 1.3 only)\n", "-Z");
     fprintf(stderr, "%-20s Disconnect and reconnect up to N times total\n", "-L");
     fprintf(stderr, "%-20s Comma separated list of enabled groups for TLS key exchange.\n"
                     "%-20s The following values are valid:\n"
                     "%-20s P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n",
             "-I", "", "");
+    fprintf(stderr, "%-20s Enable alternate content type for TLS 1.3 ServerHello\n", "-X alt-server-hello");
 }
 
 static void
 Usage(const char *progName)
 {
     PrintUsageHeader(progName);
     PrintParameterUsage();
     exit(1);
@@ -909,16 +911,17 @@ ServerCertAuth serverCertAuth;
 char *hs1SniHostName = NULL;
 char *hs2SniHostName = NULL;
 PRUint16 portno = 443;
 int override = 0;
 char *requestString = NULL;
 PRInt32 requestStringLen = 0;
 PRBool requestSent = PR_FALSE;
 PRBool enableZeroRtt = PR_FALSE;
+PRBool enableAltServerHello = PR_FALSE;
 
 static int
 writeBytesToServer(PRFileDesc *s, const char *buf, int nb)
 {
     SECStatus rv;
     const char *bufp = buf;
     PRPollDesc pollDesc;
 
@@ -1173,16 +1176,26 @@ run_client(void)
         rv = SSL_OptionSet(s, SSL_ENABLE_0RTT_DATA, PR_TRUE);
         if (rv != SECSuccess) {
             SECU_PrintError(progName, "error enabling 0-RTT");
             error = 1;
             goto done;
         }
     }
 
+    /* Alternate ServerHello content type (TLS 1.3 only) */
+    if (enableAltServerHello) {
+        rv = SSL_UseAltServerHelloType(s, PR_TRUE);
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "error enabling alternate ServerHello type");
+            error = 1;
+            goto done;
+        }
+    }
+
     /* require the use of fixed finite-field DH groups */
     if (requireDHNamedGroups) {
         rv = SSL_OptionSet(s, SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE);
         if (rv != SECSuccess) {
             SECU_PrintError(progName, "error in requiring the use of fixed finite-field DH groups");
             error = 1;
             goto done;
         }
@@ -1507,17 +1520,17 @@ main(int argc, char **argv)
         }
     }
 
     SSL_VersionRangeGetSupported(ssl_variant_stream, &enabledVersions);
 
     /* XXX: 'B' was used in the past but removed in 3.28,
      *      please leave some time before resuing it. */
     optstate = PL_CreateOptState(argc, argv,
-                                 "46A:CDFGHI:KL:M:OR:STUV:W:YZa:bc:d:fgh:m:n:op:qr:st:uvw:z");
+                                 "46A:CDFGHI:KL:M:OR:STUV:W:X:YZa:bc:d:fgh:m:n:op:qr:st:uvw:z");
     while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
         switch (optstate->option) {
             case '?':
             default:
                 Usage(progName);
                 break;
 
             case '4':
@@ -1613,16 +1626,23 @@ main(int argc, char **argv)
                 if (SECU_ParseSSLVersionRangeString(optstate->value,
                                                     enabledVersions, &enabledVersions) !=
                     SECSuccess) {
                     fprintf(stderr, "Bad version specified.\n");
                     Usage(progName);
                 }
                 break;
 
+            case 'X':
+                if (!strcmp(optstate->value, "alt-server-hello")) {
+                    enableAltServerHello = PR_TRUE;
+                } else {
+                    Usage(progName);
+                }
+                break;
             case 'Y':
                 PrintCipherUsage(progName);
                 exit(0);
                 break;
 
             case 'Z':
                 enableZeroRtt = PR_TRUE;
                 break;
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,8 +5,9 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
+
--- a/security/nss/cpputil/tls_parser.h
+++ b/security/nss/cpputil/tls_parser.h
@@ -19,16 +19,17 @@
 #include "sslt.h"
 
 namespace nss_test {
 
 const uint8_t kTlsChangeCipherSpecType = 20;
 const uint8_t kTlsAlertType = 21;
 const uint8_t kTlsHandshakeType = 22;
 const uint8_t kTlsApplicationDataType = 23;
+const uint8_t kTlsAltHandshakeType = 24;
 
 const uint8_t kTlsHandshakeClientHello = 1;
 const uint8_t kTlsHandshakeServerHello = 2;
 const uint8_t kTlsHandshakeNewSessionTicket = 4;
 const uint8_t kTlsHandshakeHelloRetryRequest = 6;
 const uint8_t kTlsHandshakeEncryptedExtensions = 8;
 const uint8_t kTlsHandshakeCertificate = 11;
 const uint8_t kTlsHandshakeServerKeyExchange = 12;
--- a/security/nss/fuzz/config/clone_libfuzzer.sh
+++ b/security/nss/fuzz/config/clone_libfuzzer.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-LIBFUZZER_REVISION=56bd1d43451cca4b6a11d3be316bb77ab159b09d
+LIBFUZZER_REVISION=6937e68f927b6aefe526fcb9db8953f497e6e74d
 
 d=$(dirname $0)
 $d/git-copy.sh https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer $LIBFUZZER_REVISION $d/../libFuzzer
--- a/security/nss/gtests/certdb_gtest/alg1485_unittest.cc
+++ b/security/nss/gtests/certdb_gtest/alg1485_unittest.cc
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdint.h>
 
 #include "gtest/gtest.h"
 
 #include "nss.h"
 #include "scoped_ptrs.h"
+#include "prprf.h"
 
 namespace nss_test {
 
 typedef struct AVATestValuesStr {
   std::string avaString;
   bool expectedResult;
 } AVATestValues;
 
@@ -84,9 +85,28 @@ TEST_P(Alg1485CompareTest, CompareAVAStr
   ASSERT_TRUE(a && b);
   EXPECT_EQ(param.expectedResult, CERT_CompareName(a.get(), b.get()));
 }
 
 INSTANTIATE_TEST_CASE_P(ParseAVAStrings, Alg1485ParseTest,
                         ::testing::ValuesIn(kAVATestStrings));
 INSTANTIATE_TEST_CASE_P(CompareAVAStrings, Alg1485CompareTest,
                         ::testing::ValuesIn(kAVACompareStrings));
+
+TEST_F(Alg1485Test, ShortOIDTest) {
+  // This is not a valid OID (too short). CERT_GetOidString should return 0.
+  unsigned char data[] = {0x05};
+  const SECItem oid = {siBuffer, data, sizeof(data)};
+  char* result = CERT_GetOidString(&oid);
+  EXPECT_EQ(result, nullptr);
 }
+
+TEST_F(Alg1485Test, BrokenOIDTest) {
+  // This is not a valid OID (first bit of last byte is not set).
+  // CERT_GetOidString should return 0.
+  unsigned char data[] = {0x81, 0x82, 0x83, 0x84};
+  const SECItem oid = {siBuffer, data, sizeof(data)};
+  char* result = CERT_GetOidString(&oid);
+  EXPECT_EQ(15U, strlen(result));
+  EXPECT_EQ(0, strncmp("OID.UNSUPPORTED", result, 15));
+  PR_smprintf_free(result);
+}
+}
--- a/security/nss/gtests/manifest.mn
+++ b/security/nss/gtests/manifest.mn
@@ -18,18 +18,19 @@ UTIL_SRCDIRS = \
 endif
 
 ifneq ($(NSS_BUILD_SOFTOKEN_ONLY),1)
 ifneq ($(NSS_BUILD_UTIL_ONLY),1)
 NSS_SRCDIRS = \
 	certdb_gtest \
 	certhigh_gtest \
 	pk11_gtest \
+	softoken_gtest \
 	ssl_gtest \
-        nss_bogo_shim \
+	nss_bogo_shim \
 	$(NULL)
 endif
 endif
 
 DIRS = \
 	$(LIB_SRCDIRS) \
 	$(UTIL_SRCDIRS) \
 	$(NSS_SRCDIRS) \
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/softoken_gtest/Makefile
@@ -0,0 +1,45 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY).   #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL)          #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL)       #
+#######################################################################
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL).      #
+#######################################################################
+
+include ../common/gtest.mk
+
+CFLAGS += -I$(CORE_DEPTH)/lib/util
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL)                              #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL)                           #
+#######################################################################
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL).                              #
+#######################################################################
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/softoken_gtest/manifest.mn
@@ -0,0 +1,25 @@
+# -*- makefile -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+CORE_DEPTH = ../..
+DEPTH      = ../..
+MODULE = nss
+
+CPPSRCS = \
+	softoken_gtest.cc \
+	$(NULL)
+
+INCLUDES += \
+	-I$(CORE_DEPTH)/gtests/google_test/gtest/include \
+	-I$(CORE_DEPTH)/cpputil \
+	$(NULL)
+
+REQUIRES = nspr gtest
+
+PROGRAM = softoken_gtest
+
+EXTRA_LIBS = \
+	$(DIST)/lib/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) \
+	$(DIST)/lib/$(LIB_PREFIX)gtestutil.$(LIB_SUFFIX) \
+	$(NULL)
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/softoken_gtest/softoken_gtest.cc
@@ -0,0 +1,125 @@
+#include <cstdlib>
+
+#include "nspr.h"
+#include "nss.h"
+#include "pk11pub.h"
+
+#include "scoped_ptrs.h"
+
+#define GTEST_HAS_RTTI 0
+#include "gtest/gtest.h"
+
+namespace nss_test {
+
+// Given a prefix, attempts to create a unique directory that the user can do
+// work in without impacting other tests. For example, if given the prefix
+// "scratch", a directory like "scratch05c17b25" will be created in the current
+// working directory (or the location specified by NSS_GTEST_WORKDIR, if
+// defined).
+// Upon destruction, the implementation will attempt to delete the directory.
+// However, no attempt is made to first remove files in the directory - the
+// user is responsible for this. If the directory is not empty, deleting it will
+// fail.
+// Statistically, it is technically possible to fail to create a unique
+// directory name, but this is extremely unlikely given the expected workload of
+// this implementation.
+class ScopedUniqueDirectory {
+ public:
+  explicit ScopedUniqueDirectory(const std::string& prefix);
+
+  // NB: the directory must be empty upon destruction
+  ~ScopedUniqueDirectory() { assert(rmdir(mPath.c_str()) == 0); }
+
+  const std::string& GetPath() { return mPath; }
+
+ private:
+  static const int RETRY_LIMIT = 5;
+  static void GenerateRandomName(/*in/out*/ std::string& prefix);
+  static bool TryMakingDirectory(/*in/out*/ std::string& prefix);
+
+  std::string mPath;
+};
+
+ScopedUniqueDirectory::ScopedUniqueDirectory(const std::string& prefix) {
+  std::string path;
+  const char* workingDirectory = PR_GetEnvSecure("NSS_GTEST_WORKDIR");
+  if (workingDirectory) {
+    path.assign(workingDirectory);
+  }
+  path.append(prefix);
+  for (int i = 0; i < RETRY_LIMIT; i++) {
+    std::string pathCopy(path);
+    // TryMakingDirectory will modify its input. If it fails, we want to throw
+    // away the modified result.
+    if (TryMakingDirectory(pathCopy)) {
+      mPath.assign(pathCopy);
+      break;
+    }
+  }
+  assert(mPath.length() > 0);
+}
+
+void ScopedUniqueDirectory::GenerateRandomName(std::string& prefix) {
+  std::stringstream ss;
+  ss << prefix;
+  // RAND_MAX is at least 32767.
+  ss << std::setfill('0') << std::setw(4) << std::hex << rand() << rand();
+  // This will overwrite the value of prefix. This is a little inefficient, but
+  // at least it makes the code simple.
+  ss >> prefix;
+}
+
+bool ScopedUniqueDirectory::TryMakingDirectory(std::string& prefix) {
+  GenerateRandomName(prefix);
+#if defined(_WIN32)
+  return _mkdir(prefix.c_str()) == 0;
+#else
+  return mkdir(prefix.c_str(), 0777) == 0;
+#endif
+}
+
+class SoftokenTest : public ::testing::Test {
+ protected:
+  SoftokenTest() : mNSSDBDir("SoftokenTest.d-") {}
+
+  virtual void SetUp() {
+    std::string nssInitArg("sql:");
+    nssInitArg.append(mNSSDBDir.GetPath());
+    ASSERT_EQ(SECSuccess, NSS_Initialize(nssInitArg.c_str(), "", "", SECMOD_DB,
+                                         NSS_INIT_NOROOTINIT));
+  }
+
+  virtual void TearDown() {
+    ASSERT_EQ(SECSuccess, NSS_Shutdown());
+    const std::string& nssDBDirPath = mNSSDBDir.GetPath();
+    ASSERT_EQ(0, unlink((nssDBDirPath + "/cert9.db").c_str()));
+    ASSERT_EQ(0, unlink((nssDBDirPath + "/key4.db").c_str()));
+    ASSERT_EQ(0, unlink((nssDBDirPath + "/pkcs11.txt").c_str()));
+  }
+
+  ScopedUniqueDirectory mNSSDBDir;
+};
+
+TEST_F(SoftokenTest, ResetSoftokenEmptyPassword) {
+  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+  ASSERT_TRUE(slot);
+  EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, nullptr));
+  EXPECT_EQ(SECSuccess, PK11_ResetToken(slot.get(), nullptr));
+  EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, nullptr));
+}
+
+TEST_F(SoftokenTest, ResetSoftokenNonEmptyPassword) {
+  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+  ASSERT_TRUE(slot);
+  EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password"));
+  EXPECT_EQ(SECSuccess, PK11_ResetToken(slot.get(), nullptr));
+  EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password2"));
+}
+
+}  // namespace nss_test
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/softoken_gtest/softoken_gtest.gyp
@@ -0,0 +1,51 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+{
+  'includes': [
+    '../../coreconf/config.gypi',
+    '../common/gtest.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'softoken_gtest',
+      'type': 'executable',
+      'sources': [
+        'softoken_gtest.cc',
+      ],
+      'dependencies': [
+        '<(DEPTH)/exports.gyp:nss_exports',
+        '<(DEPTH)/lib/util/util.gyp:nssutil3',
+        '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
+      ],
+      'conditions': [
+        [ 'test_build==1', {
+          'dependencies': [
+            '<(DEPTH)/lib/nss/nss.gyp:nss_static',
+            '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
+            '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
+            '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
+            '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
+            '<(DEPTH)/lib/base/base.gyp:nssb',
+            '<(DEPTH)/lib/dev/dev.gyp:nssdev',
+            '<(DEPTH)/lib/pki/pki.gyp:nsspki',
+            '<(DEPTH)/lib/ssl/ssl.gyp:ssl',
+          ],
+        }, {
+          'dependencies': [
+            '<(DEPTH)/lib/nss/nss.gyp:nss3',
+            '<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
+          ],
+        }],
+      ],
+    }
+  ],
+  'target_defaults': {
+    'include_dirs': [
+      '../../lib/util'
+    ]
+  },
+  'variables': {
+    'module': 'nss'
+  }
+}
--- a/security/nss/gtests/ssl_gtest/manifest.mn
+++ b/security/nss/gtests/ssl_gtest/manifest.mn
@@ -25,16 +25,17 @@ CPPSRCS = \
       ssl_exporter_unittest.cc \
       ssl_extension_unittest.cc \
       ssl_fragment_unittest.cc \
       ssl_fuzz_unittest.cc \
       ssl_gather_unittest.cc \
       ssl_gtest.cc \
       ssl_hrr_unittest.cc \
       ssl_loopback_unittest.cc \
+      ssl_misc_unittest.cc \
       ssl_record_unittest.cc \
       ssl_resumption_unittest.cc \
       ssl_skip_unittest.cc \
       ssl_staticrsa_unittest.cc \
       ssl_v2_client_hello_unittest.cc \
       ssl_version_unittest.cc \
       ssl_versionpolicy_unittest.cc \
       selfencrypt_unittest.cc \
--- a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "secerr.h"
 #include "ssl.h"
 #include "sslerr.h"
+#include "sslexp.h"
 #include "sslproto.h"
 
 extern "C" {
 // This is not something that should make you happy.
 #include "libssl_internals.h"
 }
 
 #include "gtest_utils.h"
--- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
+++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
@@ -26,16 +26,17 @@
         'ssl_exporter_unittest.cc',
         'ssl_extension_unittest.cc',
         'ssl_fuzz_unittest.cc',
         'ssl_fragment_unittest.cc',
         'ssl_gather_unittest.cc',
         'ssl_gtest.cc',
         'ssl_hrr_unittest.cc',
         'ssl_loopback_unittest.cc',
+        'ssl_misc_unittest.cc',
         'ssl_record_unittest.cc',
         'ssl_resumption_unittest.cc',
         'ssl_skip_unittest.cc',
         'ssl_staticrsa_unittest.cc',
         'ssl_v2_client_hello_unittest.cc',
         'ssl_version_unittest.cc',
         'ssl_versionpolicy_unittest.cc',
         'test_io.cc',
--- a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
@@ -1,20 +1,22 @@
 /* -*- 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 <functional>
 #include <memory>
+#include <vector>
 #include "secerr.h"
 #include "ssl.h"
 #include "sslerr.h"
 #include "sslproto.h"
+#include "ssl3prot.h"
 
 extern "C" {
 // This is not something that should make you happy.
 #include "libssl_internals.h"
 }
 
 #include "gtest_utils.h"
 #include "scoped_ptrs.h"
@@ -318,16 +320,52 @@ TEST_F(TlsConnectStreamTls13, Tls13Faile
 TEST_F(TlsConnectStreamTls13, NegotiateShortHeaders) {
   client_->SetShortHeadersEnabled();
   server_->SetShortHeadersEnabled();
   client_->ExpectShortHeaders();
   server_->ExpectShortHeaders();
   Connect();
 }
 
+TEST_F(TlsConnectStreamTls13, ClientAltHandshakeType) {
+  client_->SetAltHandshakeTypeEnabled();
+  auto filter = std::make_shared<TlsHeaderRecorder>();
+  server_->SetPacketFilter(filter);
+  Connect();
+  ASSERT_EQ(kTlsHandshakeType, filter->header(0)->content_type());
+}
+
+TEST_F(TlsConnectStreamTls13, ServerAltHandshakeType) {
+  server_->SetAltHandshakeTypeEnabled();
+  auto filter = std::make_shared<TlsHeaderRecorder>();
+  server_->SetPacketFilter(filter);
+  Connect();
+  ASSERT_EQ(kTlsHandshakeType, filter->header(0)->content_type());
+}
+
+TEST_F(TlsConnectStreamTls13, BothAltHandshakeType) {
+  client_->SetAltHandshakeTypeEnabled();
+  server_->SetAltHandshakeTypeEnabled();
+  auto header_filter = std::make_shared<TlsHeaderRecorder>();
+  auto sh_filter = std::make_shared<TlsInspectorRecordHandshakeMessage>(
+      kTlsHandshakeServerHello);
+  std::vector<std::shared_ptr<PacketFilter>> filters = {header_filter,
+                                                        sh_filter};
+  auto chained = std::make_shared<ChainedPacketFilter>(filters);
+  server_->SetPacketFilter(chained);
+  header_filter->SetAgent(server_.get());
+  header_filter->EnableDecryption();
+  Connect();
+  ASSERT_EQ(kTlsAltHandshakeType, header_filter->header(0)->content_type());
+  ASSERT_EQ(kTlsHandshakeType, header_filter->header(1)->content_type());
+  uint32_t ver;
+  ASSERT_TRUE(sh_filter->buffer().Read(0, 2, &ver));
+  ASSERT_EQ((uint32_t)(0x7a00 | TLS_1_3_DRAFT_VERSION), ver);
+}
+
 INSTANTIATE_TEST_CASE_P(
     GenericStream, TlsConnectGeneric,
     ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
                        TlsConnectTestBase::kTlsVAll));
 INSTANTIATE_TEST_CASE_P(
     GenericDatagram, TlsConnectGeneric,
     ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram,
                        TlsConnectTestBase::kTlsV11Plus));
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/ssl_gtest/ssl_misc_unittest.cc
@@ -0,0 +1,20 @@
+/* -*- 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 "sslexp.h"
+
+#include "gtest_utils.h"
+
+namespace nss_test {
+
+class MiscTest : public ::testing::Test {};
+
+TEST_F(MiscTest, NonExistentExperimentalAPI) {
+  EXPECT_EQ(nullptr, SSL_GetExperimentalAPI("blah"));
+  EXPECT_EQ(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API, PORT_GetError());
+}
+
+}  // namespace nss_test
--- a/security/nss/gtests/ssl_gtest/tls_agent.cc
+++ b/security/nss/gtests/ssl_gtest/tls_agent.cc
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "tls_agent.h"
 #include "databuffer.h"
 #include "keyhi.h"
 #include "pk11func.h"
 #include "ssl.h"
 #include "sslerr.h"
+#include "sslexp.h"
 #include "sslproto.h"
 #include "tls_parser.h"
 
 extern "C" {
 // This is not something that should make you happy.
 #include "libssl_internals.h"
 }
 
@@ -409,16 +410,23 @@ void TlsAgent::SetFallbackSCSVEnabled(bo
 
 void TlsAgent::SetShortHeadersEnabled() {
   EXPECT_TRUE(EnsureTlsSetup());
 
   SECStatus rv = SSLInt_EnableShortHeaders(ssl_fd());
   EXPECT_EQ(SECSuccess, rv);
 }
 
+void TlsAgent::SetAltHandshakeTypeEnabled() {
+  EXPECT_TRUE(EnsureTlsSetup());
+
+  SECStatus rv = SSL_UseAltServerHelloType(ssl_fd(), true);
+  EXPECT_EQ(SECSuccess, rv);
+}
+
 void TlsAgent::SetVersionRange(uint16_t minver, uint16_t maxver) {
   vrange_.min = minver;
   vrange_.max = maxver;
 
   if (ssl_fd()) {
     SECStatus rv = SSL_VersionRangeSet(ssl_fd(), &vrange_);
     EXPECT_EQ(SECSuccess, rv);
   }
--- a/security/nss/gtests/ssl_gtest/tls_agent.h
+++ b/security/nss/gtests/ssl_gtest/tls_agent.h
@@ -122,16 +122,17 @@ class TlsAgent : public PollTarget {
   void RequestClientAuth(bool requireAuth);
 
   void ConfigureSessionCache(SessionResumptionMode mode);
   void SetSessionTicketsEnabled(bool en);
   void SetSessionCacheEnabled(bool en);
   void Set0RttEnabled(bool en);
   void SetFallbackSCSVEnabled(bool en);
   void SetShortHeadersEnabled();
+  void SetAltHandshakeTypeEnabled();
   void SetVersionRange(uint16_t minver, uint16_t maxver);
   void GetVersionRange(uint16_t* minver, uint16_t* maxver);
   void CheckPreliminaryInfo();
   void ResetPreliminaryInfo();
   void SetExpectedVersion(uint16_t version);
   void SetServerKeyBits(uint16_t bits);
   void ExpectReadWriteError();
   void EnableFalseStart();
--- a/security/nss/gtests/ssl_gtest/tls_connect.cc
+++ b/security/nss/gtests/ssl_gtest/tls_connect.cc
@@ -1,15 +1,16 @@
 /* -*- 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 "tls_connect.h"
+#include "sslexp.h"
 extern "C" {
 #include "libssl_internals.h"
 }
 
 #include <iostream>
 
 #include "databuffer.h"
 #include "gtest_utils.h"
--- a/security/nss/gtests/ssl_gtest/tls_filter.cc
+++ b/security/nss/gtests/ssl_gtest/tls_filter.cc
@@ -222,17 +222,18 @@ bool TlsRecordFilter::Protect(const TlsR
   padded.Write(padded.len(), inner_content_type, 1);
   return cipher_spec_->Protect(header, padded, ciphertext);
 }
 
 PacketFilter::Action TlsHandshakeFilter::FilterRecord(
     const TlsRecordHeader& record_header, const DataBuffer& input,
     DataBuffer* output) {
   // Check that the first byte is as requested.
-  if (record_header.content_type() != kTlsHandshakeType) {
+  if ((record_header.content_type() != kTlsHandshakeType) &&
+      (record_header.content_type() != kTlsAltHandshakeType)) {
     return KEEP;
   }
 
   bool changed = false;
   size_t offset = 0U;
   output->Allocate(input.len());  // Preallocate a little.
 
   TlsParser parser(input);
@@ -364,25 +365,40 @@ PacketFilter::Action TlsInspectorReplace
 
 PacketFilter::Action TlsConversationRecorder::FilterRecord(
     const TlsRecordHeader& header, const DataBuffer& input,
     DataBuffer* output) {
   buffer_.Append(input);
   return KEEP;
 }
 
+PacketFilter::Action TlsHeaderRecorder::FilterRecord(
+    const TlsRecordHeader& header, const DataBuffer& input,
+    DataBuffer* output) {
+  headers_.push_back(header);
+  return KEEP;
+}
+
+const TlsRecordHeader* TlsHeaderRecorder::header(size_t index) {
+  if (index > headers_.size() + 1) {
+    return nullptr;
+  }
+  return &headers_[index];
+}
+
 PacketFilter::Action ChainedPacketFilter::Filter(const DataBuffer& input,
                                                  DataBuffer* output) {
   DataBuffer in(input);
   bool changed = false;
   for (auto it = filters_.begin(); it != filters_.end(); ++it) {
     PacketFilter::Action action = (*it)->Filter(in, output);
     if (action == DROP) {
       return DROP;
     }
+
     if (action == CHANGE) {
       in = *output;
       changed = true;
     }
   }
   return changed ? CHANGE : KEEP;
 }
 
--- a/security/nss/gtests/ssl_gtest/tls_filter.h
+++ b/security/nss/gtests/ssl_gtest/tls_filter.h
@@ -128,16 +128,17 @@ inline std::ostream& operator<<(std::ost
   switch (hdr.content_type()) {
     case kTlsChangeCipherSpecType:
       stream << "CCS";
       break;
     case kTlsAlertType:
       stream << "Alert";
       break;
     case kTlsHandshakeType:
+    case kTlsAltHandshakeType:
       stream << "Handshake";
       break;
     case kTlsApplicationDataType:
       stream << "Data";
       break;
     default:
       stream << '<' << hdr.content_type() << '>';
       break;
@@ -225,17 +226,29 @@ class TlsConversationRecorder : public T
  public:
   TlsConversationRecorder(DataBuffer& buffer) : buffer_(buffer) {}
 
   virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
                                             const DataBuffer& input,
                                             DataBuffer* output);
 
  private:
-  DataBuffer& buffer_;
+  DataBuffer buffer_;
+};
+
+// Make a copy of the records
+class TlsHeaderRecorder : public TlsRecordFilter {
+ public:
+  virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
+                                            const DataBuffer& input,
+                                            DataBuffer* output);
+  const TlsRecordHeader* header(size_t index);
+
+ private:
+  std::vector<TlsRecordHeader> headers_;
 };
 
 // Runs multiple packet filters in series.
 class ChainedPacketFilter : public PacketFilter {
  public:
   ChainedPacketFilter() {}
   ChainedPacketFilter(const std::vector<std::shared_ptr<PacketFilter>> filters)
       : filters_(filters.begin(), filters.end()) {}
--- a/security/nss/lib/certdb/alg1485.c
+++ b/security/nss/lib/certdb/alg1485.c
@@ -698,24 +698,29 @@ CERT_GetOidString(const SECItem* oid)
 
 #define MAX_OID_LEN 1024 /* bytes */
 
     if (oid->len > MAX_OID_LEN) {
         PORT_SetError(SEC_ERROR_INPUT_LEN);
         return NULL;
     }
 
+    /* If the OID has length 1, we bail. */
+    if (oid->len < 2) {
+        return NULL;
+    }
+
     /* first will point to the next sequence of bytes to decode */
     first = (PRUint8*)oid->data;
     /* stop points to one past the legitimate data */
     stop = &first[oid->len];
 
     /*
-   * Check for our pseudo-encoded single-digit OIDs
-   */
+     * Check for our pseudo-encoded single-digit OIDs
+     */
     if ((*first == 0x80) && (2 == oid->len)) {
         /* Funky encoding.  The second byte is the number */
         rvString = PR_smprintf("%lu", (PRUint32)first[1]);
         if (!rvString) {
             PORT_SetError(SEC_ERROR_NO_MEMORY);
         }
         return rvString;
     }
@@ -723,16 +728,20 @@ CERT_GetOidString(const SECItem* oid)
     for (; first < stop; first = last + 1) {
         unsigned int bytesBeforeLast;
 
         for (last = first; last < stop; last++) {
             if (0 == (*last & 0x80)) {
                 break;
             }
         }
+        /* There's no first bit set, so this isn't valid. Bail.*/
+        if (last == stop) {
+            goto unsupported;
+        }
         bytesBeforeLast = (unsigned int)(last - first);
         if (bytesBeforeLast <= 3U) { /* 0-28 bit number */
             PRUint32 n = 0;
             PRUint32 c;
 
 #define CGET(i, m)    \
     c = last[-i] & m; \
     n |= c << (7 * i)
@@ -743,22 +752,22 @@ CERT_GetOidString(const SECItem* oid)
         if (!n)     \
         goto unsupported /* fall-through */
 
             switch (bytesBeforeLast) {
                 CASE(3, 0x7f);
                 CASE(2, 0x7f);
                 CASE(1, 0x7f);
                 case 0:
-                    n |=
-                        last[0] & 0x7f;
+                    n |= last[0] & 0x7f;
                     break;
             }
-            if (last[0] & 0x80)
+            if (last[0] & 0x80) {
                 goto unsupported;
+            }
 
             if (!rvString) {
                 /* This is the first number.. decompose it */
                 PRUint32 one = PR_MIN(n / 40, 2); /* never > 2 */
                 PRUint32 two = n - (one * 40);
 
                 rvString = PR_smprintf("OID.%lu.%lu", one, two);
             } else {
--- a/security/nss/lib/freebl/config.mk
+++ b/security/nss/lib/freebl/config.mk
@@ -85,13 +85,18 @@ EXTRA_SHARED_LIBS += \
 	-L$(NSSUTIL_LIB_DIR) \
 	-lnssutil3 \
 	-L$(NSPR_LIB_DIR) \
 	-lnspr4 \
 	$(NULL)
 endif
 endif
 
+ifeq ($(OS_ARCH), Linux)
+CFLAGS += -std=gnu99
+endif
+
 ifeq ($(OS_ARCH), Darwin)
+CFLAGS += -std=gnu99
 EXTRA_SHARED_LIBS += -dylib_file @executable_path/libplc4.dylib:$(DIST)/lib/libplc4.dylib -dylib_file @executable_path/libplds4.dylib:$(DIST)/lib/libplds4.dylib
 endif
 
 endif
--- a/security/nss/lib/freebl/freebl.gyp
+++ b/security/nss/lib/freebl/freebl.gyp
@@ -161,16 +161,17 @@
       }],
       [ 'OS=="mac"', {
         'xcode_settings': {
           # I'm not sure since when this is supported.
           # But I hope that doesn't matter. We also assume this is x86/x64.
           'OTHER_CFLAGS': [
             '-mpclmul',
             '-maes',
+            '-std=gnu99',
           ],
         },
       }],
       [ 'OS=="win" and target_arch=="ia32"', {
         'msvs_settings': {
           'VCCLCompilerTool': {
             #TODO: -Ox optimize flags
             'PreprocessorDefinitions': [
@@ -227,16 +228,19 @@
           }],
         ],
       }],
       [ 'OS=="linux"', {
         'defines': [
           'FREEBL_LOWHASH',
           'FREEBL_NO_DEPEND',
         ],
+        'cflags': [
+          '-std=gnu99',
+        ],
       }],
       [ 'OS=="linux" or OS=="android"', {
         'conditions': [
           [ 'target_arch=="x64"', {
             'defines': [
               'MP_IS_LITTLE_ENDIAN',
               'NSS_BEVAND_ARCFOUR',
               'MPI_AMD64',
--- a/security/nss/lib/nss/nss.h
+++ b/security/nss/lib/nss/nss.h
@@ -17,22 +17,22 @@
 
 /*
  * 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.32" _NSS_CUSTOMIZED
+#define NSS_VERSION "3.33" _NSS_CUSTOMIZED " Beta"
 #define NSS_VMAJOR 3
-#define NSS_VMINOR 32
+#define NSS_VMINOR 33
 #define NSS_VPATCH 0
 #define NSS_VBUILD 0
-#define NSS_BETA PR_FALSE
+#define NSS_BETA PR_TRUE
 
 #ifndef RC_INVOKED
 
 #include "seccomon.h"
 
 typedef struct NSSInitParametersStr NSSInitParameters;
 
 /*
--- a/security/nss/lib/pki/pki3hack.c
+++ b/security/nss/lib/pki/pki3hack.c
@@ -175,26 +175,28 @@ STAN_AddModuleToDefaultTrustDomain(
 NSS_IMPLEMENT SECStatus
 STAN_RemoveModuleFromDefaultTrustDomain(
     SECMODModule *module)
 {
     NSSToken *token;
     NSSTrustDomain *td;
     int i;
     td = STAN_GetDefaultTrustDomain();
-    NSSRWLock_LockWrite(td->tokensLock);
     for (i = 0; i < module->slotCount; i++) {
         token = PK11Slot_GetNSSToken(module->slots[i]);
         if (token) {
             nssToken_NotifyCertsNotVisible(token);
+            NSSRWLock_LockWrite(td->tokensLock);
             nssList_Remove(td->tokenList, token);
+            NSSRWLock_UnlockWrite(td->tokensLock);
             PK11Slot_SetNSSToken(module->slots[i], NULL);
             nssToken_Destroy(token);
         }
     }
+    NSSRWLock_LockWrite(td->tokensLock);
     nssListIterator_Destroy(td->tokens);
     td->tokens = nssList_CreateIterator(td->tokenList);
     NSSRWLock_UnlockWrite(td->tokensLock);
     return SECSuccess;
 }
 
 NSS_IMPLEMENT PRStatus
 STAN_Shutdown()
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -3561,17 +3561,16 @@ sftk_MechAllowsOperation(CK_MECHANISM_TY
 
 /* NSC_InitToken initializes a token. */
 CK_RV
 NSC_InitToken(CK_SLOT_ID slotID, CK_CHAR_PTR pPin,
               CK_ULONG ulPinLen, CK_CHAR_PTR pLabel)
 {
     SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
     SFTKDBHandle *handle;
-    SFTKDBHandle *certHandle;
     SECStatus rv;
     unsigned int i;
     SFTKObject *object;
 
     CHECK_FORK();
 
     if (slot == NULL)
         return CKR_SLOT_ID_INVALID;
@@ -3609,29 +3608,26 @@ NSC_InitToken(CK_SLOT_ID slotID, CK_CHAR
 
     /* then clear out the key database */
     handle = sftk_getKeyDB(slot);
     if (handle == NULL) {
         return CKR_TOKEN_WRITE_PROTECTED;
     }
 
     rv = sftkdb_ResetKeyDB(handle);
+    /* clear the password */
+    sftkdb_ClearPassword(handle);
+    /* update slot->needLogin (should be true now since no password is set) */
+    sftk_checkNeedLogin(slot, handle);
     sftk_freeDB(handle);
     if (rv != SECSuccess) {
         return CKR_DEVICE_ERROR;
     }
 
-    /* finally  mark all the user certs as non-user certs */
-    certHandle = sftk_getCertDB(slot);
-    if (certHandle == NULL)
-        return CKR_OK;
-
-    sftk_freeDB(certHandle);
-
-    return CKR_OK; /*is this the right function for not implemented*/
+    return CKR_OK;
 }
 
 /* NSC_InitPIN initializes the normal user's PIN. */
 CK_RV
 NSC_InitPIN(CK_SESSION_HANDLE hSession,
             CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
 {
     SFTKSession *sp = NULL;
--- a/security/nss/lib/softoken/sdb.c
+++ b/security/nss/lib/softoken/sdb.c
@@ -1595,17 +1595,17 @@ loser:
     if (sqlDB) {
         sdb_closeDBLocal(sdb_p, sqlDB);
     }
     UNLOCK_SQLITE()
 
     return error;
 }
 
-static const char RESET_CMD[] = "DROP TABLE IF EXISTS %s;";
+static const char RESET_CMD[] = "DELETE FROM %s;";
 CK_RV
 sdb_Reset(SDB *sdb)
 {
     SDBPrivate *sdb_p = sdb->private;
     sqlite3 *sqlDB = NULL;
     char *newStr;
     int sqlerr = SQLITE_OK;
     CK_RV error = CKR_OK;
@@ -1616,27 +1616,29 @@ sdb_Reset(SDB *sdb)
     }
 
     LOCK_SQLITE()
     error = sdb_openDBLocal(sdb_p, &sqlDB, NULL);
     if (error != CKR_OK) {
         goto loser;
     }
 
-    /* delete the key table */
-    newStr = sqlite3_mprintf(RESET_CMD, sdb_p->table);
-    if (newStr == NULL) {
-        error = CKR_HOST_MEMORY;
-        goto loser;
+    if (tableExists(sqlDB, sdb_p->table)) {
+        /* delete the contents of the key table */
+        newStr = sqlite3_mprintf(RESET_CMD, sdb_p->table);
+        if (newStr == NULL) {
+            error = CKR_HOST_MEMORY;
+            goto loser;
+        }
+        sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
+        sqlite3_free(newStr);
+
+        if (sqlerr != SQLITE_OK)
+            goto loser;
     }
-    sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL);
-    sqlite3_free(newStr);
-
-    if (sqlerr != SQLITE_OK)
-        goto loser;
 
     /* delete the password entry table */
     sqlerr = sqlite3_exec(sqlDB, "DROP TABLE IF EXISTS metaData;",
                           NULL, 0, NULL);
 
 loser:
     /* fix up the error if necessary */
     if (error == CKR_OK) {
@@ -1861,40 +1863,39 @@ sdb_init(char *dbname, char *table, sdbD
 
     /* access to network filesystems are significantly slower than local ones
      * for database operations. In those cases we need to create a cached copy
      * of the database in a temporary location on the local disk. SQLITE
      * already provides a way to create a temporary table and initialize it,
      * so we use it for the cache (see sdb_buildCache for how it's done).*/
 
     /*
-      * we decide whether or not to use the cache based on the following input.
-      *
-      * NSS_SDB_USE_CACHE environment variable is non-existant or set to
-      *   anything other than "no" or "yes" ("auto", for instance).
-      *   This is the normal case. NSS will measure the performance of access
-      *   to the temp database versus the access to the users passed in
-      *   database location. If the temp database location is "significantly"
-      *   faster we will use the cache.
-      *
-      * NSS_SDB_USE_CACHE environment variable is set to "no": cache will not
-      *   be used.
-      *
-      * NSS_SDB_USE_CACHE environment variable is set to "yes": cache will
-      *   always be used.
-      *
-      * It is expected that most applications would use the "auto" selection,
-      * the environment variable is primarily to simplify testing, and to
-      * correct potential corner cases where  */
+     * we decide whether or not to use the cache based on the following input.
+     *
+     * NSS_SDB_USE_CACHE environment variable is set to anything other than
+     *   "yes" or "no" (for instance, "auto"): NSS will measure the performance
+     *   of access to the temp database versus the access to the user's
+     *   passed-in database location. If the temp database location is
+     *   "significantly" faster we will use the cache.
+     *
+     * NSS_SDB_USE_CACHE environment variable is nonexistent or set to "no":
+     *   cache will not be used.
+     *
+     * NSS_SDB_USE_CACHE environment variable is set to "yes": cache will
+     *   always be used.
+     *
+     * It is expected that most applications will not need this feature, and
+     * thus it is disabled by default.
+     */
 
     env = PR_GetEnvSecure("NSS_SDB_USE_CACHE");
 
-    if (env && PORT_Strcasecmp(env, "no") == 0) {
+    if (!env || PORT_Strcasecmp(env, "no") == 0) {
         enableCache = PR_FALSE;
-    } else if (env && PORT_Strcasecmp(env, "yes") == 0) {
+    } else if (PORT_Strcasecmp(env, "yes") == 0) {
         enableCache = PR_TRUE;
     } else {
         char *tempDir = NULL;
         PRUint32 tempOps = 0;
         /*
          *  Use PR_Access to determine how expensive it
          * is to check for the existance of a local file compared to the same
          * check in the temp directory. If the temp directory is faster, cache
@@ -2030,20 +2031,21 @@ s_open(const char *directory, const char
 #endif
 
     /* how long does it take to test for a non-existant file in our working
      * directory? Allows us to test if we may be on a network file system */
     accessOps = 1;
     {
         char *env;
         env = PR_GetEnvSecure("NSS_SDB_USE_CACHE");
-        /* If the environment variable is set to yes or no, sdb_init() will
-         * ignore the value of accessOps, and we can skip the measuring.*/
-        if (!env || ((PORT_Strcasecmp(env, "no") != 0) &&
-                     (PORT_Strcasecmp(env, "yes") != 0))) {
+        /* If the environment variable is undefined or set to yes or no,
+         * sdb_init() will ignore the value of accessOps, and we can skip the
+         * measuring.*/
+        if (env && PORT_Strcasecmp(env, "no") != 0 &&
+            PORT_Strcasecmp(env, "yes") != 0) {
             accessOps = sdb_measureAccess(directory);
         }
     }
 
     /*
      * open the cert data base
      */
     if (certdb) {
--- 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.32" SOFTOKEN_ECC_STRING
+#define SOFTOKEN_VERSION "3.33" SOFTOKEN_ECC_STRING " Beta"
 #define SOFTOKEN_VMAJOR 3
-#define SOFTOKEN_VMINOR 32
+#define SOFTOKEN_VMINOR 33
 #define SOFTOKEN_VPATCH 0
 #define SOFTOKEN_VBUILD 0
-#define SOFTOKEN_BETA PR_FALSE
+#define SOFTOKEN_BETA PR_TRUE
 
 #endif /* _SOFTKVER_H_ */
--- a/security/nss/lib/ssl/SSLerrs.h
+++ b/security/nss/lib/ssl/SSLerrs.h
@@ -506,8 +506,17 @@ ER3(SSL_ERROR_MALFORMED_PSK_KEY_EXCHANGE
 ER3(SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES, (SSL_ERROR_BASE + 159),
     "SSL expected a PSK key exchange modes extension.")
 
 ER3(SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA, (SSL_ERROR_BASE + 160),
     "SSL got a pre-TLS 1.3 version even though we sent early data.")
 
 ER3(SSL_ERROR_TOO_MUCH_EARLY_DATA, (SSL_ERROR_BASE + 161),
     "SSL received more early data than permitted.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_END_OF_EARLY_DATA, (SSL_ERROR_BASE + 162),
+    "SSL received an unexpected End of Early Data message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_END_OF_EARLY_DATA, (SSL_ERROR_BASE + 163),
+    "SSL received a malformed End of Early Data message.")
+
+ER3(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API, (SSL_ERROR_BASE + 164),
+    "An experimental API was called, but not supported.")
--- a/security/nss/lib/ssl/exports.gyp
+++ b/security/nss/lib/ssl/exports.gyp
@@ -10,16 +10,17 @@
       'target_name': 'lib_ssl_exports',
       'type': 'none',
       'copies': [
         {
           'files': [
             'preenc.h',
             'ssl.h',
             'sslerr.h',
+            'sslexp.h',
             'sslproto.h',
             'sslt.h'
           ],
           'destination': '<(nss_public_dist_dir)/<(module)'
         }
       ]
     }
   ],
--- a/security/nss/lib/ssl/manifest.mn
+++ b/security/nss/lib/ssl/manifest.mn
@@ -5,16 +5,17 @@
 CORE_DEPTH = ../..
 
 # DEFINES = -DTRACE
 
 EXPORTS = \
         ssl.h \
         sslt.h \
         sslerr.h \
+        sslexp.h \
         sslproto.h \
         preenc.h \
         $(NULL)
 
 MODULE = nss
 MAPFILE = $(OBJDIR)/ssl.def
 
 CSRCS = \
--- a/security/nss/lib/ssl/ssl.def
+++ b/security/nss/lib/ssl/ssl.def
@@ -229,8 +229,14 @@ SSL_SetSessionTicketKeyPair;
 ;+};
 ;+NSS_3.30.0.1 { # Additional symbols for NSS 3.30 release
 ;+    global:
 SSL_AlertReceivedCallback;
 SSL_AlertSentCallback;
 ;+    local:
 ;+*;
 ;+};
+;+NSS_3.33 {    # NSS 3.33 release
+;+    global:
+SSL_GetExperimentalAPI;
+;+    local:
+;+*;
+;+};
--- a/security/nss/lib/ssl/ssl.h
+++ b/security/nss/lib/ssl/ssl.h
@@ -1369,11 +1369,18 @@ extern const char *NSSSSL_GetVersion(voi
  * return SECSuccess (normally), but that does not mean that the application
  * should continue using the connection. If the application passes a non-zero
  * value for second argument (error), or if SSL_AuthCertificateComplete returns
  * anything other than SECSuccess, then the application should close the
  * connection.
  */
 SSL_IMPORT SECStatus SSL_AuthCertificateComplete(PRFileDesc *fd,
                                                  PRErrorCode error);
+
+/*
+ * This is used to access experimental APIs.  Don't call this directly.  This is
+ * used to enable the experimental APIs that are defined in "sslexp.h".
+ */
+SSL_IMPORT void *SSL_GetExperimentalAPI(const char *name);
+
 SEC_END_PROTOS
 
 #endif /* __ssl_h_ */
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -1085,17 +1085,18 @@ ssl_ClientReadVersion(sslSocket *ss, PRU
     }
 
 #ifdef TLS_1_3_DRAFT_VERSION
     if (temp == SSL_LIBRARY_VERSION_TLS_1_3) {
         (void)SSL3_SendAlert(ss, alert_fatal, protocol_version);
         PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
         return SECFailure;
     }
-    if (temp == tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3)) {
+    if (temp == tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3) || (ss->opt.enableAltHandshaketype &&
+                                                                          (temp == tls13_EncodeAltDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3)))) {
         v = SSL_LIBRARY_VERSION_TLS_1_3;
     } else {
         v = (SSL3ProtocolVersion)temp;
     }
 #else
     v = (SSL3ProtocolVersion)temp;
 #endif
 
@@ -2972,30 +2973,36 @@ ssl3_FlushHandshake(sslSocket *ss, PRInt
  */
 static SECStatus
 ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
 {
     static const PRInt32 allowedFlags = ssl_SEND_FLAG_FORCE_INTO_BUFFER |
                                         ssl_SEND_FLAG_CAP_RECORD_VERSION;
     PRInt32 count = -1;
     SECStatus rv;
+    SSL3ContentType ct = content_handshake;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
     PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 
     if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
         return SECSuccess;
 
     /* only these flags are allowed */
     PORT_Assert(!(flags & ~allowedFlags));
     if ((flags & ~allowedFlags) != 0) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
-    count = ssl3_SendRecord(ss, NULL, content_handshake,
+    /* Maybe send the first message with alt handshake type. */
+    if (ss->ssl3.hs.altHandshakeType) {
+        ct = content_alt_handshake;
+        ss->ssl3.hs.altHandshakeType = PR_FALSE;
+    }
+    count = ssl3_SendRecord(ss, NULL, ct,
                             ss->sec.ci.sendBuf.buf,
                             ss->sec.ci.sendBuf.len, flags);
     if (count < 0) {
         int err = PORT_GetError();
         PORT_Assert(err != PR_WOULD_BLOCK_ERROR);
         if (err == PR_WOULD_BLOCK_ERROR) {
             PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         }
@@ -9316,17 +9323,17 @@ ssl3_SendServerHello(sslSocket *ss)
     rv = ssl3_AppendHandshakeHeader(ss, server_hello, length);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
 
     if (IS_DTLS(ss) && ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
         version = dtls_TLSVersionToDTLSVersion(ss->version);
     } else {
-        version = tls13_EncodeDraftVersion(ss->version);
+        version = ss->ssl3.hs.altHandshakeType ? tls13_EncodeAltDraftVersion(ss->version) : tls13_EncodeDraftVersion(ss->version);
     }
 
     rv = ssl3_AppendHandshakeNumber(ss, version, 2);
     if (rv != SECSuccess) {
         return rv; /* err set by AppendHandshake. */
     }
     /* Random already generated in ssl3_HandleClientHello */
     rv = ssl3_AppendHandshake(
@@ -9747,23 +9754,22 @@ ssl3_HandleCertificateVerify(sslSocket *
         if (rv != SECSuccess) {
             errCode = PORT_GetError();
             desc = decrypt_error;
             goto alert_loser;
         }
 
         hashAlg = ssl_SignatureSchemeToHashType(sigScheme);
 
-        if (hashes->u.pointer_to_hash_input.data) {
-            rv = ssl3_ComputeHandshakeHash(hashes->u.pointer_to_hash_input.data,
-                                           hashes->u.pointer_to_hash_input.len,
-                                           hashAlg, &localHashes);
-        } else {
-            rv = SECFailure;
-        }
+        /* Read from the message buffer, but we need to use only up to the end
+         * of the previous handshake message. The length of the transcript up to
+         * that point is saved in |hashes->u.transcriptLen|. */
+        rv = ssl3_ComputeHandshakeHash(ss->ssl3.hs.messages.buf,
+                                       hashes->u.transcriptLen,
+                                       hashAlg, &localHashes);
 
         if (rv == SECSuccess) {
             hashesForVerify = &localHashes;
         } else {
             errCode = SSL_ERROR_DIGEST_FAILURE;
             desc = decrypt_error;
             goto alert_loser;
         }
@@ -11653,25 +11659,25 @@ ssl3_HandleHandshakeMessage(sslSocket *s
                  * ssl3_HandleCertificateVerify, which will tell us which
                  * hash function we must use.
                  *
                  * (ssl3_HandleCertificateVerify cannot simply look at the
                  * buffer length itself, because at the time we reach it,
                  * additional handshake messages will have been added to the
                  * buffer, e.g. the certificate_verify message itself.)
                  *
-                 * Therefore, we use SSL3Hashes.u.pointer_to_hash_input
-                 * to signal the current state of the buffer.
+                 * Therefore, we use SSL3Hashes.u.transcriptLen to save how much
+                 * data there is and read directly from ss->ssl3.hs.messages
+                 * when calculating the hashes.
                  *
                  * ssl3_HandleCertificateVerify will detect
                  *     hashType == handshake_hash_record
                  * and use that information to calculate the hash.
                  */
-                hashes.u.pointer_to_hash_input.data = ss->ssl3.hs.messages.buf;
-                hashes.u.pointer_to_hash_input.len = ss->ssl3.hs.messages.len;
+                hashes.u.transcriptLen = ss->ssl3.hs.messages.len;
                 hashesPtr = &hashes;
             } else {
                 computeHashes = PR_TRUE;
             }
         }
     } else {
         if (type == certificate_verify) {
             computeHashes = TLS13_IN_HS_STATE(ss, wait_cert_verify);
@@ -12724,16 +12730,24 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Cip
 /* It's a record that must be handled by ssl itself, not the application.
     */
 process_it:
     /* XXX  Get the xmit lock here.  Odds are very high that we'll be xmiting
      * data ang getting the xmit lock here prevents deadlocks.
      */
     ssl_GetSSL3HandshakeLock(ss);
 
+    /* Special case: allow alt content type for TLS 1.3 ServerHello. */
+    if ((rType == content_alt_handshake) &&
+        (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3) &&
+        (ss->ssl3.hs.ws == wait_server_hello) &&
+        (ss->opt.enableAltHandshaketype) &&
+        (!IS_DTLS(ss))) {
+        rType = content_handshake;
+    }
     /* All the functions called in this switch MUST set error code if
     ** they return SECFailure or SECWouldBlock.
     */
     switch (rType) {
         case content_change_cipher_spec:
             rv = ssl3_HandleChangeCipherSpecs(ss, databuf);
             break;
         case content_alert:
--- a/security/nss/lib/ssl/ssl3prot.h
+++ b/security/nss/lib/ssl/ssl3prot.h
@@ -36,17 +36,18 @@ typedef PRUint16 ssl3CipherSuite;
 #define DTLS_RECORD_HEADER_LENGTH 13
 
 #define MAX_FRAGMENT_LENGTH 16384
 
 typedef enum {
     content_change_cipher_spec = 20,
     content_alert = 21,
     content_handshake = 22,
-    content_application_data = 23
+    content_application_data = 23,
+    content_alt_handshake = 24
 } SSL3ContentType;
 
 typedef struct {
     SSL3ContentType type;
     SSL3ProtocolVersion version;
     PRUint16 length;
     SECItem fragment;
 } SSL3Plaintext;
@@ -230,17 +231,17 @@ typedef struct {
  * which, if |hashAlg==ssl_hash_none| is also a SSL3HashesIndividually
  * struct. */
 typedef struct {
     unsigned int len;
     SSLHashType hashAlg;
     union {
         PRUint8 raw[64];
         SSL3HashesIndividually s;
-        SECItem pointer_to_hash_input;
+        unsigned int transcriptLen;
     } u;
 } SSL3Hashes;
 
 typedef struct {
     union {
         PRUint8 anonymous;
         SSL3Hashes certified;
     } u;
--- a/security/nss/lib/ssl/sslerr.h
+++ b/security/nss/lib/ssl/sslerr.h
@@ -241,15 +241,20 @@ typedef enum {
     SSL_ERROR_RX_UNEXPECTED_HELLO_RETRY_REQUEST = (SSL_ERROR_BASE + 154),
     SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST = (SSL_ERROR_BASE + 155),
     SSL_ERROR_BAD_2ND_CLIENT_HELLO = (SSL_ERROR_BASE + 156),
     SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION = (SSL_ERROR_BASE + 157),
     SSL_ERROR_MALFORMED_PSK_KEY_EXCHANGE_MODES = (SSL_ERROR_BASE + 158),
     SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES = (SSL_ERROR_BASE + 159),
     SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA = (SSL_ERROR_BASE + 160),
     SSL_ERROR_TOO_MUCH_EARLY_DATA = (SSL_ERROR_BASE + 161),
+    SSL_ERROR_RX_UNEXPECTED_END_OF_EARLY_DATA = (SSL_ERROR_BASE + 162),
+    SSL_ERROR_RX_MALFORMED_END_OF_EARLY_DATA = (SSL_ERROR_BASE + 163),
+
+    SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API = (SSL_ERROR_BASE + 164),
+
     SSL_ERROR_END_OF_LIST   /* let the c compiler determine the value of this. */
 } SSLErrorCodes;
 #endif /* NO_SECURITY_ERROR_ENUM */
 
 /* clang-format on */
 
 #endif /* __SSL_ERR_H_ */
new file mode 100644
--- /dev/null
+++ b/security/nss/lib/ssl/sslexp.h
@@ -0,0 +1,37 @@
+/*
+ * This file contains prototypes for experimental SSL functions.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __sslexp_h_
+#define __sslexp_h_
+
+#include "ssl.h"
+#include "sslerr.h"
+
+SEC_BEGIN_PROTOS
+
+/* The functions in this header file are not guaranteed to remain available in
+ * future NSS versions. Code that uses these functions needs to safeguard
+ * against the function not being available. */
+
+#define SSL_EXPERIMENTAL_API(name, arglist, args)                   \
+    (SSL_GetExperimentalAPI(name)                                   \
+         ? ((SECStatus(*) arglist)SSL_GetExperimentalAPI(name))args \
+         : SECFailure)
+
+/* Allow the ServerHello to be record type 24. Experiment to test:
+ * https://github.com/tlswg/tls13-spec/pull/1051
+ * This will either become part of the standard or be disabled
+ * after we have tested it.
+ */
+#define SSL_UseAltServerHelloType(fd, enable)                \
+    SSL_EXPERIMENTAL_API("SSL_UseAltServerHelloType",        \
+                         (PRFileDesc * _fd, PRBool _enable), \
+                         (fd, enable))
+
+SEC_END_PROTOS
+
+#endif /* __sslexp_h_ */
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -293,16 +293,17 @@ typedef struct sslOptionsStr {
     unsigned int reuseServerECDHEKey : 1;
     unsigned int enableFallbackSCSV : 1;
     unsigned int enableServerDhe : 1;
     unsigned int enableExtendedMS : 1;
     unsigned int enableSignedCertTimestamps : 1;
     unsigned int requireDHENamedGroups : 1;
     unsigned int enable0RttData : 1;
     unsigned int enableShortHeaders : 1;
+    unsigned int enableAltHandshaketype : 1;
 } sslOptions;
 
 typedef enum { sslHandshakingUndetermined = 0,
                sslHandshakingAsClient,
                sslHandshakingAsServer
 } sslHandshakingType;
 
 #define SSL_LOCK_RANK_SPEC 255
@@ -878,16 +879,17 @@ typedef struct SSL3HandshakeStateStr {
     ssl3CipherSuite zeroRttSuite;   /* The cipher suite we used for 0-RTT. */
     PRCList bufferedEarlyData;      /* Buffered TLS 1.3 early data
                                      * on server.*/
     PRBool helloRetry;              /* True if HelloRetryRequest has been sent
                                      * or received. */
     ssl3KEADef kea_def_mutable;     /* Used to hold the writable kea_def
                                      * we use for TLS 1.3 */
     PRBool shortHeaders;            /* Assigned if we are doing short headers. */
+    PRBool altHandshakeType;        /* Assigned if we are doing the wrapped handshake. */
 } SSL3HandshakeState;
 
 /*
 ** This is the "ssl3" struct, as in "ss->ssl3".
 ** note:
 ** usually,   crSpec == cwSpec and prSpec == pwSpec.
 ** Sometimes, crSpec == pwSpec and prSpec == cwSpec.
 ** But there are never more than 2 actual specs.
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -6,16 +6,17 @@
  *
  * 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 "seccomon.h"
 #include "cert.h"
 #include "keyhi.h"
 #include "ssl.h"
+#include "sslexp.h"
 #include "sslimpl.h"
 #include "sslproto.h"
 #include "nspr.h"
 #include "private/pprio.h"
 #include "nss.h"
 #include "pk11pqg.h"
 
 static const sslSocketOps ssl_default_ops = { /* No SSL. */
@@ -75,20 +76,21 @@ static sslOptions ssl_defaults = {
     PR_TRUE,               /* reuseServerECDHEKey */
     PR_FALSE,              /* enableFallbackSCSV */
     PR_TRUE,               /* enableServerDhe */
     PR_FALSE,              /* enableExtendedMS    */
     PR_FALSE,              /* enableSignedCertTimestamps */
     PR_FALSE,              /* requireDHENamedGroups */
     PR_FALSE,              /* enable0RttData */
 #ifdef NSS_ENABLE_TLS13_SHORT_HEADERS
-    PR_TRUE /* enableShortHeaders */
+    PR_TRUE, /* enableShortHeaders */
 #else
-    PR_FALSE /* enableShortHeaders */
+    PR_FALSE, /* enableShortHeaders */
 #endif
+    PR_FALSE /* enableAltHandshaketype */
 };
 
 /*
  * default range of enabled SSL/TLS protocols
  */
 static SSLVersionRange versions_defaults_stream = {
     SSL_LIBRARY_VERSION_TLS_1_0,
     SSL_LIBRARY_VERSION_TLS_1_2
@@ -2209,17 +2211,17 @@ ssl3_GetEffectiveVersionPolicy(SSLProtoc
         minPolicy > maxPolicy) {
         return SECFailure;
     }
     effectivePolicy->min = PR_MAX(effectivePolicy->min, minPolicy);
     effectivePolicy->max = PR_MIN(effectivePolicy->max, maxPolicy);
     return SECSuccess;
 }
 
-/* 
+/*
  * Assumes that rangeParam values are within the supported boundaries,
  * but should contain all potentially allowed versions, even if they contain
  * conflicting versions.
  * Will return the overlap, or a NONE range if system policy is invalid.
  */
 static SECStatus
 ssl3_CreateOverlapWithPolicy(SSLProtocolVariant protocolVariant,
                              SSLVersionRange *input,
@@ -3835,8 +3837,53 @@ SSL_CanBypass(CERTCertificate *cert, SEC
 {
     if (!pcanbypass) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
     *pcanbypass = PR_FALSE;
     return SECSuccess;
 }
+
+/* Functions that are truly experimental use EXP, functions that are no longer
+ * experimental use PUB.
+ *
+ * When initially defining a new API, add that API here using the EXP() macro
+ * and name the function with a SSLExp_ prefix.  Define the experimental API as
+ * a macro in sslexp.h using the SSL_EXPERIMENTAL_API() macro defined there.
+ *
+ * Once an API is stable and proven, move the macro definition in sslexp.h to a
+ * proper function declaration in ssl.h.  Keeping the function in this list
+ * ensures that code built against the release that contained the experimental
+ * API will continue to work; use PUB() to reference the public function.
+ */
+#define EXP(n)                \
+    {                         \
+        "SSL_" #n, SSLExp_##n \
+    }
+#define PUB(n)             \
+    {                      \
+        "SSL_" #n, SSL_##n \
+    }
+struct {
+    const char *const name;
+    void *function;
+} ssl_experimental_functions[] = {
+#ifndef SSL_DISABLE_EXPERIMENTAL_API
+    EXP(UseAltServerHelloType),
+#endif
+    { "", NULL }
+};
+#undef EXP
+#undef PUB
+
+void *
+SSL_GetExperimentalAPI(const char *name)
+{
+    unsigned int i;
+    for (i = 0; i < PR_ARRAY_SIZE(ssl_experimental_functions); ++i) {
+        if (strcmp(name, ssl_experimental_functions[i].name) == 0) {
+            return ssl_experimental_functions[i].function;
+        }
+    }
+    PORT_SetError(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API);
+    return NULL;
+}
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -4470,16 +4470,27 @@ tls13_EncodeDraftVersion(SSL3ProtocolVer
 #ifdef TLS_1_3_DRAFT_VERSION
     if (version == SSL_LIBRARY_VERSION_TLS_1_3) {
         return 0x7f00 | TLS_1_3_DRAFT_VERSION;
     }
 #endif
     return (PRUint16)version;
 }
 
+PRUint16
+tls13_EncodeAltDraftVersion(SSL3ProtocolVersion version)
+{
+#ifdef TLS_1_3_DRAFT_VERSION
+    if (version == SSL_LIBRARY_VERSION_TLS_1_3) {
+        return 0x7a00 | TLS_1_3_DRAFT_VERSION;
+    }
+#endif
+    return (PRUint16)version;
+}
+
 /* Pick the highest version we support that is also advertised. */
 SECStatus
 tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supported_versions)
 {
     PRUint16 version;
     /* Make a copy so we're nondestructive*/
     SECItem data = supported_versions->data;
     SECItem versions;
@@ -4491,23 +4502,48 @@ tls13_NegotiateVersion(sslSocket *ss, co
         return SECFailure;
     }
     if (data.len || !versions.len || (versions.len & 1)) {
         FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
         return SECFailure;
     }
     for (version = ss->vrange.max; version >= ss->vrange.min; --version) {
         PRUint16 wire = tls13_EncodeDraftVersion(version);
+        PRUint16 alt_wire = tls13_EncodeAltDraftVersion(version);
         unsigned long offset;
 
         for (offset = 0; offset < versions.len; offset += 2) {
             PRUint16 supported =
                 (versions.data[offset] << 8) | versions.data[offset + 1];
             if (supported == wire) {
                 ss->version = version;
                 return SECSuccess;
             }
+            if (ss->opt.enableAltHandshaketype && !IS_DTLS(ss) &&
+                supported == alt_wire) {
+                ss->version = version;
+                ss->ssl3.hs.altHandshakeType = PR_TRUE;
+                return SECSuccess;
+            }
         }
     }
 
     FATAL_ERROR(ss, SSL_ERROR_UNSUPPORTED_VERSION, protocol_version);
     return SECFailure;
 }
+
+SECStatus
+SSLExp_UseAltServerHelloType(PRFileDesc *fd, PRBool enable)
+{
+    sslSocket *ss;
+
+    ss = ssl_FindSocket(fd);
+    if (!ss) {
+        SSL_DBG(("%d: SSL[%d]: bad socket in SSLExp_UseAltServerHelloType",
+                 SSL_GETPID(), fd));
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    ss->opt.enableAltHandshaketype = enable;
+
+    return SECSuccess;
+}
--- a/security/nss/lib/ssl/tls13con.h
+++ b/security/nss/lib/ssl/tls13con.h
@@ -76,14 +76,15 @@ SECStatus tls13_ProtectRecord(sslSocket 
                               const PRUint8 *pIn,
                               PRUint32 contentLen,
                               sslBuffer *wrBuf);
 PRInt32 tls13_Read0RttData(sslSocket *ss, void *buf, PRInt32 len);
 SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss);
 SECStatus tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf);
 PRBool tls13_ClientAllow0Rtt(const sslSocket *ss, const sslSessionID *sid);
 PRUint16 tls13_EncodeDraftVersion(SSL3ProtocolVersion version);
-PRUint16 tls13_DecodeDraftVersion(PRUint16 version);
+PRUint16 tls13_EncodeAltDraftVersion(SSL3ProtocolVersion version);
 SECStatus tls13_NegotiateVersion(sslSocket *ss,
                                  const TLSExtension *supported_versions);
 SECStatus tls13_SendNewSessionTicket(sslSocket *ss);
+SECStatus SSLExp_UseAltServerHelloType(PRFileDesc *fd, PRBool enable);
 
 #endif /* __tls13con_h_ */
--- a/security/nss/lib/ssl/tls13exthandle.c
+++ b/security/nss/lib/ssl/tls13exthandle.c
@@ -891,16 +891,20 @@ tls13_ClientSendSupportedVersionsXtn(con
     SSL_TRC(3, ("%d: TLS13[%d]: send supported_versions extension",
                 SSL_GETPID(), ss->fd));
 
     /* Extension type, extension len fiels, vector len field,
      * length of the values. */
     extensions_len = 2 + 2 + 1 +
                      2 * (ss->vrange.max - ss->vrange.min + 1);
 
+    if (ss->opt.enableAltHandshaketype && !IS_DTLS(ss)) {
+        extensions_len += 2;
+    }
+
     if (maxBytes < (PRUint32)extensions_len) {
         PORT_Assert(0);
         return 0;
     }
 
     if (append) {
         rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_supported_versions_xtn, 2);
         if (rv != SECSuccess)
@@ -909,16 +913,25 @@ tls13_ClientSendSupportedVersionsXtn(con
         rv = ssl3_ExtAppendHandshakeNumber(ss, extensions_len - 4, 2);
         if (rv != SECSuccess)
             return -1;
 
         rv = ssl3_ExtAppendHandshakeNumber(ss, extensions_len - 5, 1);
         if (rv != SECSuccess)
             return -1;
 
+        if (ss->opt.enableAltHandshaketype && !IS_DTLS(ss)) {
+            rv = ssl3_ExtAppendHandshakeNumber(
+                ss, tls13_EncodeAltDraftVersion(
+                        SSL_LIBRARY_VERSION_TLS_1_3),
+                2);
+            if (rv != SECSuccess)
+                return -1;
+        }
+
         for (version = ss->vrange.max; version >= ss->vrange.min; --version) {
             rv = ssl3_ExtAppendHandshakeNumber(
                 ss, tls13_EncodeDraftVersion(version), 2);
             if (rv != SECSuccess)
                 return -1;
         }
 
         xtnData->advertised[xtnData->numAdvertised++] =
--- a/security/nss/lib/util/nssutil.h
+++ b/security/nss/lib/util/nssutil.h
@@ -14,22 +14,22 @@
 
 /*
  * 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.32"
+#define NSSUTIL_VERSION "3.33 Beta"
 #define NSSUTIL_VMAJOR 3
-#define NSSUTIL_VMINOR 32
+#define NSSUTIL_VMINOR 33
 #define NSSUTIL_VPATCH 0
 #define NSSUTIL_VBUILD 0
-#define NSSUTIL_BETA PR_FALSE
+#define NSSUTIL_BETA PR_TRUE
 
 SEC_BEGIN_PROTOS
 
 /*
  * Returns a const string of the UTIL library version.
  */
 extern const char *NSSUTIL_GetVersion(void);
 
--- a/security/nss/lib/util/secoid.c
+++ b/security/nss/lib/util/secoid.c
@@ -1836,23 +1836,21 @@ secoid_HashDynamicOiddata(const SECOidDa
  * cheaper to rehash the table when it changes than it is to do the loop
  * each time.
  */
 static SECOidData *
 secoid_FindDynamic(const SECItem *key)
 {
     SECOidData *ret = NULL;
 
+    NSSRWLock_LockRead(dynOidLock);
     if (dynOidHash) {
-        NSSRWLock_LockRead(dynOidLock);
-        if (dynOidHash) { /* must check it again with lock held. */
-            ret = (SECOidData *)PL_HashTableLookup(dynOidHash, key);
-        }
-        NSSRWLock_UnlockRead(dynOidLock);
+        ret = (SECOidData *)PL_HashTableLookup(dynOidHash, key);
     }
+    NSSRWLock_UnlockRead(dynOidLock);
     if (ret == NULL) {
         PORT_SetError(SEC_ERROR_UNRECOGNIZED_OID);
     }
     return ret;
 }
 
 static dynXOid *
 secoid_FindDynamicByTag(SECOidTag tagnum)
@@ -1861,24 +1859,22 @@ secoid_FindDynamicByTag(SECOidTag tagnum
     int tagNumDiff;
 
     if (tagnum < SEC_OID_TOTAL) {
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return NULL;
     }
     tagNumDiff = tagnum - SEC_OID_TOTAL;
 
-    if (dynOidTable) {
-        NSSRWLock_LockRead(dynOidLock);
-        if (dynOidTable != NULL && /* must check it again with lock held. */
-            tagNumDiff < dynOidEntriesUsed) {
-            dxo = dynOidTable[tagNumDiff];
-        }
-        NSSRWLock_UnlockRead(dynOidLock);
+    NSSRWLock_LockRead(dynOidLock);
+    if (dynOidTable != NULL &&
+        tagNumDiff < dynOidEntriesUsed) {
+        dxo = dynOidTable[tagNumDiff];
     }
+    NSSRWLock_UnlockRead(dynOidLock);
     if (dxo == NULL) {
         PORT_SetError(SEC_ERROR_UNRECOGNIZED_OID);
     }
     return dxo;
 }
 
 /*
  * This routine is thread safe now.
--- a/security/nss/mach
+++ b/security/nss/mach
@@ -15,22 +15,26 @@ import os
 import platform
 from hashlib import sha256
 
 cwd = os.path.dirname(os.path.abspath(__file__))
 
 
 class cfAction(argparse.Action):
     docker_command = ["docker"]
+    restorecon = None
 
     def __call__(self, parser, args, values, option_string=None):
         if "noroot" not in values:
             self.setDockerCommand()
         else:
             values.remove("noroot")
+        files = [os.path.join('/home/worker/nss',
+                              os.path.relpath(os.path.abspath(x), start=cwd))
+                     for x in values]
 
         # First check if we can run docker.
         try:
             with open(os.devnull, "w") as f:
                 subprocess.check_call(
                     self.docker_command + ["images"], stdout=f)
         except:
             print("Please install docker and start the docker daemon.")
@@ -50,20 +54,22 @@ class cfAction(argparse.Action):
             ]
             with open(os.devnull, "w") as f:
                 subprocess.check_call(command, stdout=f)
         except:
             print("I have to build the docker image first.")
             self.buildImage(docker_image, cf_docker_folder)
 
         command = self.docker_command + [
-            'run', '-v', cwd + ':/home/worker/nss', '--rm', '-ti', docker_image
+                'run', '-v', cwd + ':/home/worker/nss:Z', '--rm', '-ti', docker_image
         ]
         # The clang format script returns 1 if something's to do. We don't care.
-        subprocess.call(command + values)
+        subprocess.call(command + files)
+        if self.restorecon is not None:
+            subprocess.call([self.restorecon, '-R', cwd])
 
     def filesChanged(self, path):
         hash = sha256()
         for dirname, dirnames, files in os.walk(path):
             for file in files:
                 with open(os.path.join(dirname, file), "rb") as f:
                     hash.update(f.read())
         chk_file = cwd + "/.chk"
@@ -82,16 +88,18 @@ class cfAction(argparse.Action):
         command = self.docker_command + [
             "build", "-t", docker_image, cf_docker_folder
         ]
         subprocess.check_call(command)
         return
 
     def setDockerCommand(self):
         if platform.system() == "Linux":
+            from distutils.spawn import find_executable
+            self.restorecon = find_executable('restorecon')
             self.docker_command = ["sudo"] + self.docker_command
 
 
 class buildAction(argparse.Action):
     def __call__(self, parser, args, values, option_string=None):
         cwd = os.path.dirname(os.path.abspath(__file__))
         subprocess.check_call([cwd + "/build.sh"] + values)
 
@@ -109,16 +117,23 @@ class testAction(argparse.Action):
         }
         command = cwd + "/tests/all.sh"
         subprocess.check_call(command, env=env)
 
     def __call__(self, parser, args, values, option_string=None):
         self.runTest(values)
 
 
+class commandsAction(argparse.Action):
+    commands = []
+    def __call__(self, parser, args, values, option_string=None):
+        for c in commandsAction.commands:
+            print(c)
+
+
 def parse_arguments():
     parser = argparse.ArgumentParser(
         description='NSS helper script. ' +
         'Make sure to separate sub-command arguments with --.')
     subparsers = parser.add_subparsers()
 
     parser_build = subparsers.add_parser(
         'build', help='All arguments are passed to build.sh')
@@ -138,16 +153,26 @@ def parse_arguments():
         'tests', help='Run tests through tests/all.sh.')
     tests = [
         "cipher", "lowhash", "chains", "cert", "dbtests", "tools", "fips",
         "sdr", "crmf", "smime", "ssl", "ocsp", "merge", "pkits", "ec",
         "gtests", "ssl_gtests"
     ]
     parser_test.add_argument(
         'test', choices=tests, help="Available tests", action=testAction)
+
+    parser_commands = subparsers.add_parser(
+        'mach-commands',
+        help="list commands")
+    parser_commands.add_argument(
+        'mach-commands',
+        nargs='*',
+        action=commandsAction)
+
+    commandsAction.commands = [c for c in subparsers.choices]
     return parser.parse_args()
 
 
 def main():
     parse_arguments()
 
 
 if __name__ == '__main__':
--- a/security/nss/nss.gyp
+++ b/security/nss/nss.gyp
@@ -163,16 +163,17 @@
             'cmd/tstclnt/tstclnt.gyp:tstclnt',
             'cmd/vfychain/vfychain.gyp:vfychain',
             'cmd/vfyserv/vfyserv.gyp:vfyserv',
             'gtests/certhigh_gtest/certhigh_gtest.gyp:certhigh_gtest',
             'gtests/der_gtest/der_gtest.gyp:der_gtest',
             'gtests/certdb_gtest/certdb_gtest.gyp:certdb_gtest',
             'gtests/freebl_gtest/freebl_gtest.gyp:prng_gtest',
             'gtests/pk11_gtest/pk11_gtest.gyp:pk11_gtest',
+            'gtests/softoken_gtest/softoken_gtest.gyp:softoken_gtest',
             'gtests/ssl_gtest/ssl_gtest.gyp:ssl_gtest',
             'gtests/util_gtest/util_gtest.gyp:util_gtest',
             'gtests/nss_bogo_shim/nss_bogo_shim.gyp:nss_bogo_shim',
           ],
           'conditions': [
             [ 'OS=="linux"', {
               'dependencies': [
                 'cmd/lowhashtest/lowhashtest.gyp:lowhashtest',
--- a/security/nss/tests/gtests/gtests.sh
+++ b/security/nss/tests/gtests/gtests.sh
@@ -78,13 +78,13 @@ gtest_start()
 gtest_cleanup()
 {
   html "</TABLE><BR>"
   cd ${QADIR}
   . common/cleanup.sh
 }
 
 ################## main #################################################
-GTESTS="prng_gtest certhigh_gtest certdb_gtest der_gtest pk11_gtest util_gtest freebl_gtest"
+GTESTS="prng_gtest certhigh_gtest certdb_gtest der_gtest pk11_gtest util_gtest freebl_gtest softoken_gtest"
 SOURCE_DIR="$PWD"/../..
 gtest_init $0
 gtest_start
 gtest_cleanup