Bug 1401594 - land NSS 6fb9c5396d52 UPGRADE_NSS_RELEASE, r=me
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Wed, 04 Oct 2017 10:42:25 +0200
changeset 384488 2380614f82bfdcde3b0f3ae1f1e50fe13feb22a5
parent 384487 dc2311553356d83b36bb2bc5b27b2ff04f1db6b1
child 384489 6a21a19886ec08165b8ff3153f851df1fcb562a4
push id32629
push userkwierso@gmail.com
push dateWed, 04 Oct 2017 23:38:17 +0000
treeherdermozilla-central@dedd9a48da69 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1401594
milestone58.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 1401594 - land NSS 6fb9c5396d52 UPGRADE_NSS_RELEASE, r=me MozReview-Commit-ID: 8NmVvC1r7uS
security/nss/TAG-INFO
security/nss/automation/abi-check/previous-nss-release
security/nss/automation/buildbot-slave/build.sh
security/nss/automation/taskcluster/graph/src/extend.js
security/nss/cmd/certutil/certutil.c
security/nss/cmd/modutil/error.h
security/nss/cmd/modutil/modutil.c
security/nss/cmd/modutil/modutil.h
security/nss/cmd/modutil/pk11.c
security/nss/cmd/pk12util/pk12util.c
security/nss/coreconf/config.gypi
security/nss/coreconf/coreconf.dep
security/nss/fuzz/tls_socket.h
security/nss/gtests/ssl_gtest/manifest.mn
security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc
security/nss/gtests/ssl_gtest/ssl_gtest.gyp
security/nss/gtests/ssl_gtest/ssl_keylog_unittest.cc
security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
security/nss/gtests/ssl_gtest/tls_agent.cc
security/nss/gtests/ssl_gtest/tls_agent.h
security/nss/gtests/ssl_gtest/tls_connect.cc
security/nss/gtests/ssl_gtest/tls_connect.h
security/nss/gtests/ssl_gtest/tls_protect.h
security/nss/lib/freebl/Makefile
security/nss/lib/freebl/aes-x86.c
security/nss/lib/freebl/freebl.gyp
security/nss/lib/freebl/gcm-x86.c
security/nss/lib/freebl/gcm.c
security/nss/lib/freebl/gcm.h
security/nss/lib/freebl/manifest.mn
security/nss/lib/freebl/rijndael.c
security/nss/lib/freebl/rijndael.h
security/nss/lib/nss/nss.h
security/nss/lib/nss/nssoptions.c
security/nss/lib/pk11wrap/pk11obj.c
security/nss/lib/pkcs12/p12d.c
security/nss/lib/softoken/softkver.h
security/nss/lib/ssl/ssl3con.c
security/nss/lib/ssl/ssl3exthandle.c
security/nss/lib/ssl/sslimpl.h
security/nss/lib/ssl/sslinfo.c
security/nss/lib/ssl/sslsnce.c
security/nss/lib/ssl/sslsock.c
security/nss/lib/ssl/sslt.h
security/nss/lib/ssl/tls13con.c
security/nss/lib/util/nssb64d.c
security/nss/lib/util/nssutil.h
security/nss/tests/cert/cert.sh
security/nss/tests/common/init.sh
security/nss/tests/tools/TestOldCA.p12
security/nss/tests/tools/tools.sh
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-NSS_3_33_RTM
+6fb9c5396d52
--- a/security/nss/automation/abi-check/previous-nss-release
+++ b/security/nss/automation/abi-check/previous-nss-release
@@ -1,1 +1,1 @@
-NSS_3_32_BRANCH
+NSS_3_33_BRANCH
--- a/security/nss/automation/buildbot-slave/build.sh
+++ b/security/nss/automation/buildbot-slave/build.sh
@@ -231,21 +231,24 @@ check_abi()
     if [ $? -ne 0 ]; then
         echo "invalid tag in automation/abi-check/previous-nss-release"
         return 1
     fi
 
     BASE_NSPR=NSPR_$(head -1 ${HGDIR}/baseline/nss/automation/release/nspr-version.txt | cut -d . -f 1-2 | tr . _)_BRANCH
     hg clone -u "${BASE_NSPR}" "${HGDIR}/nspr" "${HGDIR}/baseline/nspr"
     if [ $? -ne 0 ]; then
-        echo "invalid tag ${BASE_NSPR} derived from ${BASE_NSS} automation/release/nspr-version.txt"
-        return 1
+        echo "nonexisting tag ${BASE_NSPR} derived from ${BASE_NSS} automation/release/nspr-version.txt"
+        # Assume that version hasn't been released yet, fall back to trunk
+        pushd "${HGDIR}/baseline/nspr"
+        hg update default
+        popd
     fi
 
-    print_log "######## building older NSPR/NSS ########"
+    print_log "######## building baseline NSPR/NSS ########"
     pushd ${HGDIR}/baseline/nss
 
     print_log "$ ${MAKE} ${NSS_BUILD_TARGET}"
     ${MAKE} ${NSS_BUILD_TARGET} 2>&1 | tee -a ${LOG_ALL}
     RET=$?
     print_result "NSS - build - ${BITS} bits - ${OPT}" ${RET} 0
     if [ ${RET} -ne 0 ]; then
         tail -100 ${LOG_ALL}
--- a/security/nss/automation/taskcluster/graph/src/extend.js
+++ b/security/nss/automation/taskcluster/graph/src/extend.js
@@ -258,18 +258,17 @@ async function scheduleMac(name, base, a
     env: {
       PATH: "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin",
       NSS_TASKCLUSTER_MAC: "1",
       DOMSUF: "localdomain",
       HOST: "localhost",
     },
     provisioner: "localprovisioner",
     workerType: "nss-macos-10-12",
-    platform: "mac",
-    tier: 3
+    platform: "mac"
   });
 
   // Build base definition.
   let build_base = merge({
     command: [
       MAC_CHECKOUT_CMD,
       ["bash", "-c",
        "nss/automation/taskcluster/scripts/build_gyp.sh", args]
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -3005,16 +3005,43 @@ certutil_main(int argc, char **argv, PRB
                                 certutil.options[opt_NewPasswordFile].arg);
         }
         if (rv != SECSuccess) {
             SECU_PrintError(progName, "Could not set password for the slot");
             goto shutdown;
         }
     }
 
+    /* if we are going to modify the cert database,
+     * make sure it's initialized */
+    if (certutil.commands[cmd_ModifyCertTrust].activated ||
+        certutil.commands[cmd_CreateAndAddCert].activated ||
+        certutil.commands[cmd_AddCert].activated ||
+        certutil.commands[cmd_AddEmailCert].activated) {
+        if (PK11_NeedUserInit(slot)) {
+            char *password = NULL;
+            /* fetch the password from the command line or the file
+             * if no password is supplied, initialize the password to NULL */
+            if (pwdata.source == PW_FROMFILE) {
+                password = SECU_FilePasswd(slot, PR_FALSE, pwdata.data);
+            } else if (pwdata.source == PW_PLAINTEXT) {
+                password = PL_strdup(pwdata.data);
+            }
+            rv = PK11_InitPin(slot, (char *)NULL, password ? password : "");
+            if (password) {
+                PORT_Memset(password, 0, PL_strlen(password));
+                PORT_Free(password);
+            }
+            if (rv != SECSuccess) {
+                SECU_PrintError(progName, "Could not set password for the slot");
+                goto shutdown;
+            }
+        }
+    }
+
     /* walk through the upgrade merge if necessary.
      * This option is more to test what some applications will want to do
      * to do an automatic upgrade. The --merge command is more useful for
      * the general case where 2 database need to be merged together.
      */
     if (certutil.commands[cmd_UpgradeMerge].activated) {
         if (*upgradeTokenName == 0) {
             upgradeTokenName = upgradeID;
--- a/security/nss/cmd/modutil/error.h
+++ b/security/nss/cmd/modutil/error.h
@@ -52,16 +52,17 @@ typedef enum {
     ENABLE_FAILED_ERR,
     UPDATE_MOD_FAILED_ERR,
     DEFAULT_FAILED_ERR,
     UNDEFAULT_FAILED_ERR,
     STDIN_READ_ERR,
     UNSPECIFIED_ERR,
     NOCERTDB_MISUSE_ERR,
     NSS_INITIALIZE_FAILED_ERR,
+    INITPW_FAILED_ERR,
 
     LAST_ERR /* must be last */
 } Error;
 #define SUCCESS NO_ERR
 
 /* !!! Should move this into its own .c and un-static it. */
 static char *errStrings[] = {
     "Operation completed successfully.\n",
@@ -105,17 +106,18 @@ static char *errStrings[] = {
     "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: NSS_Initialize() failed.\n"
+    "ERROR: NSS_Initialize() failed.\n",
+    "ERROR: Unable to set initial password on the database.\n"
 };
 
 typedef enum {
     FIPS_ENABLED_MSG = 0,
     FIPS_DISABLED_MSG,
     USING_DBDIR_MSG,
     CREATING_DB_MSG,
     ADD_MODULE_SUCCESS_MSG,
--- a/security/nss/cmd/modutil/modutil.c
+++ b/security/nss/cmd/modutil/modutil.c
@@ -860,17 +860,17 @@ main(int argc, char* argv[])
     switch (command) {
         case ADD_COMMAND:
             errcode = AddModule(moduleName, libFile, ciphers, mechanisms, secmodString);
             break;
         case CHANGEPW_COMMAND:
             errcode = ChangePW(tokenName, pwFile, newpwFile);
             break;
         case CREATE_COMMAND:
-            /* The work was already done in init_crypto() */
+            errcode = InitPW();
             break;
         case DEFAULT_COMMAND:
             errcode = SetDefaultModule(moduleName, slotName, mechanisms);
             break;
         case DELETE_COMMAND:
             errcode = DeleteModule(moduleName);
             break;
         case DISABLE_COMMAND:
--- a/security/nss/cmd/modutil/modutil.h
+++ b/security/nss/cmd/modutil/modutil.h
@@ -24,16 +24,17 @@
 Error LoadMechanismList(void);
 Error FipsMode(char *arg);
 Error ChkFipsMode(char *arg);
 Error AddModule(char *moduleName, char *libFile, char *ciphers,
                 char *mechanisms, char *modparms);
 Error DeleteModule(char *moduleName);
 Error ListModule(char *moduleName);
 Error ListModules();
+Error InitPW(void);
 Error ChangePW(char *tokenName, char *pwFile, char *newpwFile);
 Error EnableModule(char *moduleName, char *slotName, PRBool enable);
 Error RawAddModule(char *dbmodulespec, char *modulespec);
 Error RawListModule(char *modulespec);
 Error SetDefaultModule(char *moduleName, char *slotName, char *mechanisms);
 Error UnsetDefaultModule(char *moduleName, char *slotName, char *mechanisms);
 void out_of_memory(void);
 
--- a/security/nss/cmd/modutil/pk11.c
+++ b/security/nss/cmd/modutil/pk11.c
@@ -665,16 +665,49 @@ loser:
     if (module) {
         SECMOD_DestroyModule(module);
     }
     return rv;
 }
 
 /************************************************************************
  *
+ * I n i t P W
+ */
+Error
+InitPW(void)
+{
+    PK11SlotInfo *slot;
+    Error ret = UNSPECIFIED_ERR;
+
+    slot = PK11_GetInternalKeySlot();
+    if (!slot) {
+        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], "internal");
+        return NO_SUCH_TOKEN_ERR;
+    }
+
+    /* Set the initial password to empty */
+    if (PK11_NeedUserInit(slot)) {
+        if (PK11_InitPin(slot, NULL, "") != SECSuccess) {
+            PR_fprintf(PR_STDERR, errStrings[INITPW_FAILED_ERR]);
+            ret = INITPW_FAILED_ERR;
+            goto loser;
+        }
+    }
+
+    ret = SUCCESS;
+
+loser:
+    PK11_FreeSlot(slot);
+
+    return ret;
+}
+
+/************************************************************************
+ *
  * C h a n g e P W
  */
 Error
 ChangePW(char *tokenName, char *pwFile, char *newpwFile)
 {
     char *oldpw = NULL, *newpw = NULL, *newpw2 = NULL;
     PK11SlotInfo *slot;
     Error ret = UNSPECIFIED_ERR;
--- a/security/nss/cmd/pk12util/pk12util.c
+++ b/security/nss/cmd/pk12util/pk12util.c
@@ -18,16 +18,17 @@
 #include "secpkcs5.h"
 #include "certdb.h"
 
 #define PKCS12_IN_BUFFER_SIZE 200
 
 static char *progName;
 PRBool pk12_debugging = PR_FALSE;
 PRBool dumpRawFile;
+static PRBool pk12uForceUnicode;
 
 PRIntn pk12uErrno = 0;
 
 static void
 Usage(char *progName)
 {
 #define FPS PR_fprintf(PR_STDERR,
     FPS "Usage:	 %s -i importfile [-d certdir] [-P dbprefix] [-h tokenname]\n",
@@ -352,16 +353,17 @@ p12U_ReadPKCS12File(SECItem *uniPwp, cha
                     secuPWData *slotPw, secuPWData *p12FilePw)
 {
     SEC_PKCS12DecoderContext *p12dcx = NULL;
     p12uContext *p12cxt = NULL;
     SECItem *pwitem = NULL;
     SECItem p12file = { 0 };
     SECStatus rv = SECFailure;
     PRBool swapUnicode = PR_FALSE;
+    PRBool forceUnicode = pk12uForceUnicode;
     PRBool trypw;
     int error;
 
 #ifdef IS_LITTLE_ENDIAN
     swapUnicode = PR_TRUE;
 #endif
 
     p12cxt = p12u_InitContext(PR_TRUE, in_file);
@@ -419,23 +421,44 @@ p12U_ReadPKCS12File(SECItem *uniPwp, cha
         rv = SEC_PKCS12DecoderVerify(p12dcx);
         if (rv != SECSuccess) {
             if (uniPwp->len == 2) {
                 /* this is a null PW, try once more with a zero-length PW
                    instead of a null string */
                 SEC_PKCS12DecoderFinish(p12dcx);
                 uniPwp->len = 0;
                 trypw = PR_TRUE;
+            } else if (forceUnicode == pk12uForceUnicode) {
+                /* try again with a different password encoding */
+                forceUnicode = !pk12uForceUnicode;
+                rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE,
+                                   forceUnicode);
+                if (rv != SECSuccess) {
+                    SECU_PrintError(progName, "PKCS12 decoding failed to set option");
+                    pk12uErrno = PK12UERR_DECODEVERIFY;
+                    break;
+                }
+                SEC_PKCS12DecoderFinish(p12dcx);
+                trypw = PR_TRUE;
             } else {
                 SECU_PrintError(progName, "PKCS12 decode not verified");
                 pk12uErrno = PK12UERR_DECODEVERIFY;
                 break;
             }
         }
     } while (trypw == PR_TRUE);
+
+    /* revert the option setting */
+    if (forceUnicode != pk12uForceUnicode) {
+        rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE, pk12uForceUnicode);
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "PKCS12 decoding failed to set option");
+            pk12uErrno = PK12UERR_DECODEVERIFY;
+        }
+    }
 /* rv has been set at this point */
 
 done:
     if (rv != SECSuccess) {
         if (p12dcx != NULL) {
             SEC_PKCS12DecoderFinish(p12dcx);
             p12dcx = NULL;
         }
@@ -465,51 +488,84 @@ done:
  *  variables have been added for this purpose.
  */
 PRIntn
 P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot,
                         secuPWData *slotPw, secuPWData *p12FilePw)
 {
     SEC_PKCS12DecoderContext *p12dcx = NULL;
     SECItem uniPwitem = { 0 };
+    PRBool forceUnicode = pk12uForceUnicode;
+    PRBool trypw;
     SECStatus rv = SECFailure;
 
     rv = P12U_InitSlot(slot, slotPw);
     if (rv != SECSuccess) {
         SECU_PrintError(progName, "Failed to authenticate to \"%s\"",
                         PK11_GetSlotName(slot));
         pk12uErrno = PK12UERR_PK11GETSLOT;
         return rv;
     }
 
-    rv = SECFailure;
-    p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw);
+    do {
+        trypw = PR_FALSE; /* normally we do this once */
+        rv = SECFailure;
+        p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw);
+
+        if (p12dcx == NULL) {
+            goto loser;
+        }
 
-    if (p12dcx == NULL) {
-        goto loser;
-    }
+        /* make sure the bags are okey dokey -- nicknames correct, etc. */
+        rv = SEC_PKCS12DecoderValidateBags(p12dcx, P12U_NicknameCollisionCallback);
+        if (rv != SECSuccess) {
+            if (PORT_GetError() == SEC_ERROR_PKCS12_DUPLICATE_DATA) {
+                pk12uErrno = PK12UERR_CERTALREADYEXISTS;
+            } else {
+                pk12uErrno = PK12UERR_DECODEVALIBAGS;
+            }
+            SECU_PrintError(progName, "PKCS12 decode validate bags failed");
+            goto loser;
+        }
 
-    /* make sure the bags are okey dokey -- nicknames correct, etc. */
-    rv = SEC_PKCS12DecoderValidateBags(p12dcx, P12U_NicknameCollisionCallback);
-    if (rv != SECSuccess) {
-        if (PORT_GetError() == SEC_ERROR_PKCS12_DUPLICATE_DATA) {
-            pk12uErrno = PK12UERR_CERTALREADYEXISTS;
-        } else {
-            pk12uErrno = PK12UERR_DECODEVALIBAGS;
+        /* stuff 'em in */
+        if (forceUnicode != pk12uForceUnicode) {
+            rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE,
+                               forceUnicode);
+            if (rv != SECSuccess) {
+                SECU_PrintError(progName, "PKCS12 decode set option failed");
+                pk12uErrno = PK12UERR_DECODEIMPTBAGS;
+                goto loser;
+            }
         }
-        SECU_PrintError(progName, "PKCS12 decode validate bags failed");
-        goto loser;
-    }
+        rv = SEC_PKCS12DecoderImportBags(p12dcx);
+        if (rv != SECSuccess) {
+            if (PR_GetError() == SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY &&
+                forceUnicode == pk12uForceUnicode) {
+                /* try again with a different password encoding */
+                forceUnicode = !pk12uForceUnicode;
+                SEC_PKCS12DecoderFinish(p12dcx);
+                SECITEM_ZfreeItem(&uniPwitem, PR_FALSE);
+                trypw = PR_TRUE;
+            } else {
+                SECU_PrintError(progName, "PKCS12 decode import bags failed");
+                pk12uErrno = PK12UERR_DECODEIMPTBAGS;
+                goto loser;
+            }
+        }
+    } while (trypw);
 
-    /* stuff 'em in */
-    rv = SEC_PKCS12DecoderImportBags(p12dcx);
-    if (rv != SECSuccess) {
-        SECU_PrintError(progName, "PKCS12 decode import bags failed");
-        pk12uErrno = PK12UERR_DECODEIMPTBAGS;
-        goto loser;
+    /* revert the option setting */
+    if (forceUnicode != pk12uForceUnicode) {
+        rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE, pk12uForceUnicode);
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "PKCS12 decode set option failed");
+            pk12uErrno = PK12UERR_DECODEIMPTBAGS;
+            goto loser;
+        }
     }
 
     fprintf(stdout, "%s: PKCS12 IMPORT SUCCESSFUL\n", progName);
     rv = SECSuccess;
 
 loser:
     if (p12dcx) {
         SEC_PKCS12DecoderFinish(p12dcx);
@@ -942,16 +998,17 @@ main(int argc, char **argv)
     char *dbprefix = "";
     SECStatus rv;
     SECOidTag cipher =
         SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
     SECOidTag certCipher;
     int keyLen = 0;
     int certKeyLen = 0;
     secuCommand pk12util;
+    PRInt32 forceUnicode;
 
 #ifdef _CRTDBG_MAP_ALLOC
     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
 #endif
 
     pk12util.numCommands = 0;
     pk12util.commands = 0;
     pk12util.numOptions = sizeof(pk12util_options) / sizeof(secuCommandFlag);
@@ -973,16 +1030,24 @@ main(int argc, char **argv)
         Usage(progName);
     }
 
     if (pk12util.options[opt_Export].activated &&
         !pk12util.options[opt_Nickname].activated) {
         Usage(progName);
     }
 
+    rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode);
+    if (rv != SECSuccess) {
+        SECU_PrintError(progName,
+                        "Failed to get NSS_PKCS12_DECODE_FORCE_UNICODE option");
+        Usage(progName);
+    }
+    pk12uForceUnicode = forceUnicode;
+
     slotname = SECU_GetOptionArg(&pk12util, opt_TokenName);
 
     import_file = (pk12util.options[opt_List].activated) ? SECU_GetOptionArg(&pk12util, opt_List)
                                                          : SECU_GetOptionArg(&pk12util, opt_Import);
     export_file = SECU_GetOptionArg(&pk12util, opt_Export);
 
     if (pk12util.options[opt_P12FilePWFile].activated) {
         p12FilePw.source = PW_FROMFILE;
--- a/security/nss/coreconf/config.gypi
+++ b/security/nss/coreconf/config.gypi
@@ -168,17 +168,17 @@
         'msvs_settings': {
           'VCCLCompilerTool': {
             'PreprocessorDefinitions': [
               'NSS_X86',
             ],
           },
         },
       }],
-      [ 'target_arch=="arm64" or target_arch=="aarch64" or target_arch=="sparc64"', {
+      [ 'target_arch=="arm64" or target_arch=="aarch64" or target_arch=="sparc64" or target_arch=="ppc64" or target_arch=="ppc64le" or target_arch=="s390x" or target_arch=="mips64"', {
         'defines': [
           'NSS_USE_64',
         ],
       }],
       [ 'target_arch=="x64"', {
         'defines': [
           'NSS_X64',
           'NSS_USE_64',
--- 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/fuzz/tls_socket.h
+++ b/security/nss/fuzz/tls_socket.h
@@ -5,16 +5,17 @@
 #ifndef tls_socket_h__
 #define tls_socket_h__
 
 #include "dummy_io.h"
 
 class DummyPrSocket : public DummyIOLayerMethods {
  public:
   DummyPrSocket(const uint8_t *buf, size_t len) : buf_(buf), len_(len) {}
+  virtual ~DummyPrSocket() {}
 
   int32_t Read(PRFileDesc *f, void *data, int32_t len) override;
   int32_t Write(PRFileDesc *f, const void *buf, int32_t length) override;
   int32_t Recv(PRFileDesc *f, void *buf, int32_t buflen, int32_t flags,
                PRIntervalTime to) override;
 
  private:
   const uint8_t *buf_;
--- a/security/nss/gtests/ssl_gtest/manifest.mn
+++ b/security/nss/gtests/ssl_gtest/manifest.mn
@@ -24,16 +24,17 @@ CPPSRCS = \
       ssl_ems_unittest.cc \
       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_keylog_unittest.cc \
       ssl_loopback_unittest.cc \
       ssl_misc_unittest.cc \
       ssl_record_unittest.cc \
       ssl_resumption_unittest.cc \
       ssl_renegotiation_unittest.cc \
       ssl_skip_unittest.cc \
       ssl_staticrsa_unittest.cc \
       ssl_v2_client_hello_unittest.cc \
--- a/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc
@@ -531,30 +531,32 @@ TEST_P(TlsConnectGenericPre13, MismatchD
   client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
 }
 
 TEST_P(TlsConnectTls13, ResumeFfdhe) {
   EnableOnlyDheCiphers();
   ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
   Connect();
   SendReceive();  // Need to read so that we absorb the session ticket.
-  CheckKeys(ssl_kea_dh, ssl_auth_rsa_sign);
+  CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign,
+            ssl_sig_rsa_pss_sha256);
 
   Reset();
   ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
   EnableOnlyDheCiphers();
   auto clientCapture =
       std::make_shared<TlsExtensionCapture>(ssl_tls13_pre_shared_key_xtn);
   client_->SetPacketFilter(clientCapture);
   auto serverCapture =
       std::make_shared<TlsExtensionCapture>(ssl_tls13_pre_shared_key_xtn);
   server_->SetPacketFilter(serverCapture);
   ExpectResumption(RESUME_TICKET);
   Connect();
-  CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign, ssl_sig_none);
+  CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign,
+            ssl_sig_rsa_pss_sha256);
   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) {}
--- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
+++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
@@ -25,16 +25,17 @@
         'ssl_ems_unittest.cc',
         '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_keylog_unittest.cc',
         'ssl_loopback_unittest.cc',
         'ssl_misc_unittest.cc',
         'ssl_record_unittest.cc',
         'ssl_resumption_unittest.cc',
         'ssl_renegotiation_unittest.cc',
         'ssl_skip_unittest.cc',
         'ssl_staticrsa_unittest.cc',
         'ssl_v2_client_hello_unittest.cc',
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/ssl_gtest/ssl_keylog_unittest.cc
@@ -0,0 +1,91 @@
+/* -*- 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 <cstdlib>
+#include <fstream>
+#include <sstream>
+
+#include "gtest_utils.h"
+#include "tls_connect.h"
+
+namespace nss_test {
+
+static const std::string keylog_file_path = "keylog.txt";
+
+class KeyLogFileTest : public TlsConnectGeneric {
+ public:
+  void SetUp() {
+    TlsConnectTestBase::SetUp();
+    remove(keylog_file_path.c_str());
+    std::ostringstream sstr;
+    sstr << "SSLKEYLOGFILE=" << keylog_file_path;
+    PR_SetEnv(sstr.str().c_str());
+  }
+
+  void CheckKeyLog() {
+    std::ifstream f(keylog_file_path);
+    std::map<std::string, size_t> labels;
+    std::string last_client_random;
+    for (std::string line; std::getline(f, line);) {
+      if (line[0] == '#') {
+        continue;
+      }
+
+      std::istringstream iss(line);
+      std::string label, client_random, secret;
+      iss >> label >> client_random >> secret;
+
+      ASSERT_EQ(1U, client_random.size());
+      ASSERT_TRUE(last_client_random.empty() ||
+                  last_client_random == client_random);
+      last_client_random = client_random;
+      labels[label]++;
+    }
+
+    if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
+      ASSERT_EQ(1U, labels["CLIENT_RANDOM"]);
+    } else {
+      ASSERT_EQ(1U, labels["CLIENT_EARLY_TRAFFIC_SECRET"]);
+      ASSERT_EQ(1U, labels["CLIENT_HANDSHAKE_TRAFFIC_SECRET"]);
+      ASSERT_EQ(1U, labels["SERVER_HANDSHAKE_TRAFFIC_SECRET"]);
+      ASSERT_EQ(1U, labels["CLIENT_TRAFFIC_SECRET_0"]);
+      ASSERT_EQ(1U, labels["SERVER_TRAFFIC_SECRET_0"]);
+      ASSERT_EQ(1U, labels["EXPORTER_SECRET"]);
+    }
+  }
+
+  void ConnectAndCheck() {
+    Connect();
+    CheckKeyLog();
+    _exit(0);
+  }
+};
+
+// Tests are run in a separate process to ensure that NSS is not initialized yet
+// and can process the SSLKEYLOGFILE environment variable.
+
+TEST_P(KeyLogFileTest, KeyLogFile) {
+  testing::GTEST_FLAG(death_test_style) = "threadsafe";
+
+  ASSERT_EXIT(ConnectAndCheck(), ::testing::ExitedWithCode(0), "");
+}
+
+INSTANTIATE_TEST_CASE_P(
+    KeyLogFileDTLS12, KeyLogFileTest,
+    ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram,
+                       TlsConnectTestBase::kTlsV11V12));
+INSTANTIATE_TEST_CASE_P(
+    KeyLogFileTLS12, KeyLogFileTest,
+    ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
+                       TlsConnectTestBase::kTlsV10ToV12));
+#ifndef NSS_DISABLE_TLS_1_3
+INSTANTIATE_TEST_CASE_P(
+    KeyLogFileTLS13, KeyLogFileTest,
+    ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
+                       TlsConnectTestBase::kTlsV13));
+#endif
+
+}  // namespace nss_test
--- a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
@@ -391,17 +391,18 @@ TEST_P(TlsConnectTls13, TestTls13ResumeD
   CheckKeys();
 
   Reset();
   ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
   ExpectResumption(RESUME_TICKET);
   client_->ConfigNamedGroups(kFFDHEGroups);
   server_->ConfigNamedGroups(kFFDHEGroups);
   Connect();
-  CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign, ssl_sig_none);
+  CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign,
+            ssl_sig_rsa_pss_sha256);
 }
 
 // We need to enable different cipher suites at different times in the following
 // tests.  Those cipher suites need to be suited to the version.
 static uint16_t ChooseOneCipher(uint16_t version) {
   if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
     return TLS_AES_128_GCM_SHA256;
   }
@@ -599,17 +600,17 @@ TEST_F(TlsConnectTest, TestTls13Resumpti
   ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
   ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
   ExpectResumption(RESUME_TICKET);
   auto c1 = std::make_shared<TlsExtensionCapture>(ssl_tls13_pre_shared_key_xtn);
   client_->SetPacketFilter(c1);
   Connect();
   SendReceive();
   CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign,
-            ssl_sig_none);
+            ssl_sig_rsa_pss_sha256);
   // The filter will go away when we reset, so save the captured extension.
   DataBuffer initialTicket(c1->extension());
   ASSERT_LT(0U, initialTicket.len());
 
   ScopedCERTCertificate cert1(SSL_PeerCertificate(client_->ssl_fd()));
   ASSERT_TRUE(!!cert1.get());
 
   Reset();
@@ -617,17 +618,17 @@ TEST_F(TlsConnectTest, TestTls13Resumpti
   ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
   ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
   auto c2 = std::make_shared<TlsExtensionCapture>(ssl_tls13_pre_shared_key_xtn);
   client_->SetPacketFilter(c2);
   ExpectResumption(RESUME_TICKET);
   Connect();
   SendReceive();
   CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign,
-            ssl_sig_none);
+            ssl_sig_rsa_pss_sha256);
   ASSERT_LT(0U, c2->extension().len());
 
   ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd()));
   ASSERT_TRUE(!!cert2.get());
 
   // Check that the cipher suite is reported the same on both sides, though in
   // TLS 1.3 resumption actually negotiates a different cipher suite.
   uint16_t resumed_suite;
@@ -718,9 +719,66 @@ TEST_F(TlsConnectTest, TestTls13Resumpti
 
   client_->ExpectSendAlert(kTlsAlertDecodeError);
   server_->ExpectSendAlert(kTlsAlertBadRecordMac);  // Server can't read
   ConnectExpectFail();
   client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
   server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
 }
 
+TEST_P(TlsConnectGeneric, ReConnectTicket) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+  server_->EnableSingleCipher(ChooseOneCipher(version_));
+  Connect();
+  SendReceive();
+  CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign,
+            ssl_sig_rsa_pss_sha256);
+  // Resume
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+  ExpectResumption(RESUME_TICKET);
+  Connect();
+  // Only the client knows this.
+  CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519,
+                      ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256);
+}
+
+TEST_P(TlsConnectGenericPre13, ReConnectCache) {
+  ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
+  server_->EnableSingleCipher(ChooseOneCipher(version_));
+  Connect();
+  SendReceive();
+  CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign,
+            ssl_sig_rsa_pss_sha256);
+  // Resume
+  Reset();
+  ExpectResumption(RESUME_SESSIONID);
+  Connect();
+  CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519,
+                      ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256);
+}
+
+TEST_P(TlsConnectGeneric, ReConnectAgainTicket) {
+  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+  server_->EnableSingleCipher(ChooseOneCipher(version_));
+  Connect();
+  SendReceive();
+  CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign,
+            ssl_sig_rsa_pss_sha256);
+  // Resume
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+  ExpectResumption(RESUME_TICKET);
+  Connect();
+  // Only the client knows this.
+  CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519,
+                      ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256);
+  // Resume connection again
+  Reset();
+  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+  ExpectResumption(RESUME_TICKET, 2);
+  Connect();
+  // Only the client knows this.
+  CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519,
+                      ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256);
+}
+
 }  // namespace nss_test
--- a/security/nss/gtests/ssl_gtest/tls_agent.cc
+++ b/security/nss/gtests/ssl_gtest/tls_agent.cc
@@ -490,16 +490,22 @@ void TlsAgent::CheckKEA(SSLKEAType kea_t
     }
   }
   if (kea_group != ssl_grp_ffdhe_custom) {
     EXPECT_EQ(kea_size, info_.keaKeyBits);
     EXPECT_EQ(kea_group, info_.keaGroup);
   }
 }
 
+void TlsAgent::CheckOriginalKEA(SSLNamedGroup kea_group) const {
+  if (kea_group != ssl_grp_ffdhe_custom) {
+    EXPECT_EQ(kea_group, info_.originalKeaGroup);
+  }
+}
+
 void TlsAgent::CheckAuthType(SSLAuthType auth_type,
                              SSLSignatureScheme sig_scheme) const {
   EXPECT_EQ(STATE_CONNECTED, state_);
   EXPECT_EQ(auth_type, info_.authType);
   EXPECT_EQ(server_key_bits_, info_.authKeyBits);
   if (expected_version_ < SSL_LIBRARY_VERSION_TLS_1_2) {
     switch (auth_type) {
       case ssl_auth_rsa_sign:
@@ -715,16 +721,18 @@ void TlsAgent::Connected() {
   LOG("Handshake success");
   CheckPreliminaryInfo();
   CheckCallbacks();
 
   SECStatus rv = SSL_GetChannelInfo(ssl_fd(), &info_, sizeof(info_));
   EXPECT_EQ(SECSuccess, rv);
   EXPECT_EQ(sizeof(info_), info_.length);
 
+  EXPECT_EQ(expect_resumption_, info_.resumed == PR_TRUE);
+
   // Preliminary values are exposed through callbacks during the handshake.
   // If either expected values were set or the callbacks were called, check
   // that the final values are correct.
   EXPECT_EQ(expected_version_, info_.protocolVersion);
   EXPECT_EQ(expected_cipher_suite_, info_.cipherSuite);
 
   rv = SSL_GetCipherSuiteInfo(info_.cipherSuite, &csinfo_, sizeof(csinfo_));
   EXPECT_EQ(SECSuccess, rv);
--- a/security/nss/gtests/ssl_gtest/tls_agent.h
+++ b/security/nss/gtests/ssl_gtest/tls_agent.h
@@ -90,16 +90,17 @@ class TlsAgent : public PollTarget {
     adapter_->SetPacketFilter(filter);
   }
 
   void DeletePacketFilter() { adapter_->SetPacketFilter(nullptr); }
 
   void StartConnect(PRFileDesc* model = nullptr);
   void CheckKEA(SSLKEAType kea_type, SSLNamedGroup group,
                 size_t kea_size = 0) const;
+  void CheckOriginalKEA(SSLNamedGroup kea_group) const;
   void CheckAuthType(SSLAuthType auth_type,
                      SSLSignatureScheme sig_scheme) const;
 
   void DisableAllCiphers();
   void EnableCiphersByAuthType(SSLAuthType authType);
   void EnableCiphersByKeyExchange(SSLKEAType kea);
   void EnableGroupsByKeyExchange(SSLKEAType kea);
   void EnableGroupsByAuthType(SSLAuthType authType);
--- a/security/nss/gtests/ssl_gtest/tls_connect.cc
+++ b/security/nss/gtests/ssl_gtest/tls_connect.cc
@@ -108,16 +108,17 @@ TlsConnectTestBase::TlsConnectTestBase(S
                                        uint16_t version)
     : variant_(variant),
       client_(new TlsAgent(TlsAgent::kClient, TlsAgent::CLIENT, variant_)),
       server_(new TlsAgent(TlsAgent::kServerRsa, TlsAgent::SERVER, variant_)),
       client_model_(nullptr),
       server_model_(nullptr),
       version_(version),
       expected_resumption_mode_(RESUME_NONE),
+      expected_resumptions_(0),
       session_ids_(),
       expect_extended_master_secret_(false),
       expect_early_data_accepted_(false),
       skip_version_checks_(false) {
   std::string v;
   if (variant_ == ssl_variant_datagram &&
       version_ == SSL_LIBRARY_VERSION_TLS_1_1) {
     v = "1.0";
@@ -215,22 +216,25 @@ void TlsConnectTestBase::Reset(const std
   if (skip_version_checks_) {
     client_->SkipVersionChecks();
     server_->SkipVersionChecks();
   }
 
   Init();
 }
 
-void TlsConnectTestBase::ExpectResumption(SessionResumptionMode expected) {
+void TlsConnectTestBase::ExpectResumption(SessionResumptionMode expected,
+                                          uint8_t num_resumptions) {
   expected_resumption_mode_ = expected;
   if (expected != RESUME_NONE) {
     client_->ExpectResumption();
     server_->ExpectResumption();
+    expected_resumptions_ = num_resumptions;
   }
+  EXPECT_EQ(expected_resumptions_ == 0, expected == RESUME_NONE);
 }
 
 void TlsConnectTestBase::EnsureTlsSetup() {
   EXPECT_TRUE(server_->EnsureTlsSetup(server_model_ ? server_model_->ssl_fd()
                                                     : nullptr));
   EXPECT_TRUE(client_->EnsureTlsSetup(client_model_ ? client_model_->ssl_fd()
                                                     : nullptr));
 }
@@ -310,20 +314,22 @@ void TlsConnectTestBase::CheckConnected(
   CheckResumption(expected_resumption_mode_);
   client_->CheckSecretsDestroyed();
   server_->CheckSecretsDestroyed();
 }
 
 void TlsConnectTestBase::CheckKeys(SSLKEAType kea_type, SSLNamedGroup kea_group,
                                    SSLAuthType auth_type,
                                    SSLSignatureScheme sig_scheme) const {
-  client_->CheckKEA(kea_type, kea_group);
-  server_->CheckKEA(kea_type, kea_group);
+  if (kea_group != ssl_grp_none) {
+    client_->CheckKEA(kea_type, kea_group);
+    server_->CheckKEA(kea_type, kea_group);
+  }
+  server_->CheckAuthType(auth_type, sig_scheme);
   client_->CheckAuthType(auth_type, sig_scheme);
-  server_->CheckAuthType(auth_type, sig_scheme);
 }
 
 void TlsConnectTestBase::CheckKeys(SSLKEAType kea_type,
                                    SSLAuthType auth_type) const {
   SSLNamedGroup group;
   switch (kea_type) {
     case ssl_kea_ecdh:
       group = ssl_grp_ec_curve25519;
@@ -368,16 +374,27 @@ void TlsConnectTestBase::CheckKeys(SSLKE
   }
   CheckKeys(kea_type, group, auth_type, scheme);
 }
 
 void TlsConnectTestBase::CheckKeys() const {
   CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
 }
 
+void TlsConnectTestBase::CheckKeysResumption(SSLKEAType kea_type,
+                                             SSLNamedGroup kea_group,
+                                             SSLNamedGroup original_kea_group,
+                                             SSLAuthType auth_type,
+                                             SSLSignatureScheme sig_scheme) {
+  CheckKeys(kea_type, kea_group, auth_type, sig_scheme);
+  EXPECT_TRUE(expected_resumption_mode_ != RESUME_NONE);
+  client_->CheckOriginalKEA(original_kea_group);
+  server_->CheckOriginalKEA(original_kea_group);
+}
+
 void TlsConnectTestBase::ConnectExpectFail() {
   server_->StartConnect();
   client_->StartConnect();
   Handshake();
   ASSERT_EQ(TlsAgent::STATE_ERROR, client_->state());
   ASSERT_EQ(TlsAgent::STATE_ERROR, server_->state());
 }
 
@@ -472,31 +489,31 @@ void TlsConnectTestBase::ConfigureSessio
     EXPECT_EQ(SECSuccess,
               SSL_SetSessionTicketKeyPair(pubKey.get(), privKey.get()));
   }
 }
 
 void TlsConnectTestBase::CheckResumption(SessionResumptionMode expected) {
   EXPECT_NE(RESUME_BOTH, expected);
 
-  int resume_count = expected ? 1 : 0;
-  int stateless_count = (expected & RESUME_TICKET) ? 1 : 0;
+  int resume_count = expected ? expected_resumptions_ : 0;
+  int stateless_count = (expected & RESUME_TICKET) ? expected_resumptions_ : 0;
 
   // Note: hch == server counter; hsh == client counter.
   SSL3Statistics* stats = SSL_GetStatistics();
   EXPECT_EQ(resume_count, stats->hch_sid_cache_hits);
   EXPECT_EQ(resume_count, stats->hsh_sid_cache_hits);
 
   EXPECT_EQ(stateless_count, stats->hch_sid_stateless_resumes);
   EXPECT_EQ(stateless_count, stats->hsh_sid_stateless_resumes);
 
   if (expected != RESUME_NONE) {
     if (client_->version() < SSL_LIBRARY_VERSION_TLS_1_3) {
       // Check that the last two session ids match.
-      ASSERT_EQ(2U, session_ids_.size());
+      ASSERT_EQ(1U + expected_resumptions_, session_ids_.size());
       EXPECT_EQ(session_ids_[session_ids_.size() - 1],
                 session_ids_[session_ids_.size() - 2]);
     } else {
       // TLS 1.3 only uses tickets.
       EXPECT_TRUE(expected & RESUME_TICKET);
     }
   }
 }
--- a/security/nss/gtests/ssl_gtest/tls_connect.h
+++ b/security/nss/gtests/ssl_gtest/tls_connect.h
@@ -76,25 +76,31 @@ class TlsConnectTestBase : public ::test
   void ConnectWithCipherSuite(uint16_t cipher_suite);
   // Check that the keys used in the handshake match expectations.
   void CheckKeys(SSLKEAType kea_type, SSLNamedGroup kea_group,
                  SSLAuthType auth_type, SSLSignatureScheme sig_scheme) const;
   // This version guesses some of the values.
   void CheckKeys(SSLKEAType kea_type, SSLAuthType auth_type) const;
   // This version assumes defaults.
   void CheckKeys() const;
+  // Check that keys on resumed sessions.
+  void CheckKeysResumption(SSLKEAType kea_type, SSLNamedGroup kea_group,
+                           SSLNamedGroup original_kea_group,
+                           SSLAuthType auth_type,
+                           SSLSignatureScheme sig_scheme);
   void CheckGroups(const DataBuffer& groups,
                    std::function<void(SSLNamedGroup)> check_group);
   void CheckShares(const DataBuffer& shares,
                    std::function<void(SSLNamedGroup)> check_group);
 
   void ConfigureVersion(uint16_t version);
   void SetExpectedVersion(uint16_t version);
   // Expect resumption of a particular type.
-  void ExpectResumption(SessionResumptionMode expected);
+  void ExpectResumption(SessionResumptionMode expected,
+                        uint8_t num_resumed = 1);
   void DisableAllCiphers();
   void EnableOnlyStaticRsaCiphers();
   void EnableOnlyDheCiphers();
   void EnableSomeEcdhCiphers();
   void EnableExtendedMasterSecret();
   void ConfigureSessionCache(SessionResumptionMode client,
                              SessionResumptionMode server);
   void EnableAlpn();
@@ -118,16 +124,17 @@ class TlsConnectTestBase : public ::test
  protected:
   SSLProtocolVariant variant_;
   std::shared_ptr<TlsAgent> client_;
   std::shared_ptr<TlsAgent> server_;
   std::unique_ptr<TlsAgent> client_model_;
   std::unique_ptr<TlsAgent> server_model_;
   uint16_t version_;
   SessionResumptionMode expected_resumption_mode_;
+  uint8_t expected_resumptions_;
   std::vector<std::vector<uint8_t>> session_ids_;
 
   // A simple value of "a", "b".  Note that the preferred value of "a" is placed
   // at the end, because the NSS API follows the now defunct NPN specification,
   // which places the preferred (and default) entry at the end of the list.
   // NSS will move this final entry to the front when used with ALPN.
   const uint8_t alpn_dummy_val_[4] = {0x01, 0x62, 0x01, 0x61};
 
--- a/security/nss/gtests/ssl_gtest/tls_protect.h
+++ b/security/nss/gtests/ssl_gtest/tls_protect.h
@@ -15,17 +15,17 @@
 #include "sslt.h"
 
 namespace nss_test {
 class TlsRecordHeader;
 
 class AeadCipher {
  public:
   AeadCipher(CK_MECHANISM_TYPE mech) : mech_(mech), key_(nullptr) {}
-  ~AeadCipher();
+  virtual ~AeadCipher();
 
   bool Init(PK11SymKey *key, const uint8_t *iv);
   virtual bool Aead(bool decrypt, uint64_t seq, const uint8_t *in, size_t inlen,
                     uint8_t *out, size_t *outlen, size_t maxlen) = 0;
 
  protected:
   void FormatNonce(uint64_t seq, uint8_t *nonce);
   bool AeadInner(bool decrypt, void *params, size_t param_length,
--- a/security/nss/lib/freebl/Makefile
+++ b/security/nss/lib/freebl/Makefile
@@ -105,17 +105,19 @@ endif
 ifdef FREEBL_PRELINK_COMMAND
 	DEFINES +=-DFREEBL_PRELINK_COMMAND=\"$(FREEBL_PRELINK_COMMAND)\"
 endif
 # NSS_X86 means the target is a 32-bits x86 CPU architecture
 # NSS_X64 means the target is a 64-bits 64 CPU architecture
 # NSS_X86_OR_X64 means the target is either x86 or x64
 ifeq (,$(filter-out i386 x386 x86 x86_64,$(CPU_ARCH)))
         DEFINES += -DNSS_X86_OR_X64
-        CFLAGS += -mpclmul -maes
+        EXTRA_SRCS += gcm-x86.c aes-x86.c
+$(OBJDIR)/gcm-x86.o: CFLAGS += -mpclmul -maes
+$(OBJDIR)/aes-x86.o: CFLAGS += -mpclmul -maes
 ifneq (,$(USE_64)$(USE_X32))
         DEFINES += -DNSS_X64
 else
         DEFINES += -DNSS_X86
 endif
 endif
 
 ifeq ($(OS_TARGET),OSF1)
new file mode 100644
--- /dev/null
+++ b/security/nss/lib/freebl/aes-x86.c
@@ -0,0 +1,157 @@
+/* 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/. */
+
+#ifdef FREEBL_NO_DEPEND
+#include "stubs.h"
+#endif
+#include "rijndael.h"
+#include "secerr.h"
+
+#include <wmmintrin.h> /* aes-ni */
+
+#define EXPAND_KEY128(k, rcon, res)                   \
+    tmp_key = _mm_aeskeygenassist_si128(k, rcon);     \
+    tmp_key = _mm_shuffle_epi32(tmp_key, 0xFF);       \
+    tmp = _mm_xor_si128(k, _mm_slli_si128(k, 4));     \
+    tmp = _mm_xor_si128(tmp, _mm_slli_si128(tmp, 4)); \
+    tmp = _mm_xor_si128(tmp, _mm_slli_si128(tmp, 4)); \
+    res = _mm_xor_si128(tmp, tmp_key)
+
+static void
+native_key_expansion128(AESContext *cx, const unsigned char *key)
+{
+    __m128i *keySchedule = cx->keySchedule;
+    pre_align __m128i tmp_key post_align;
+    pre_align __m128i tmp post_align;
+    keySchedule[0] = _mm_loadu_si128((__m128i *)key);
+    EXPAND_KEY128(keySchedule[0], 0x01, keySchedule[1]);
+    EXPAND_KEY128(keySchedule[1], 0x02, keySchedule[2]);
+    EXPAND_KEY128(keySchedule[2], 0x04, keySchedule[3]);
+    EXPAND_KEY128(keySchedule[3], 0x08, keySchedule[4]);
+    EXPAND_KEY128(keySchedule[4], 0x10, keySchedule[5]);
+    EXPAND_KEY128(keySchedule[5], 0x20, keySchedule[6]);
+    EXPAND_KEY128(keySchedule[6], 0x40, keySchedule[7]);
+    EXPAND_KEY128(keySchedule[7], 0x80, keySchedule[8]);
+    EXPAND_KEY128(keySchedule[8], 0x1B, keySchedule[9]);
+    EXPAND_KEY128(keySchedule[9], 0x36, keySchedule[10]);
+}
+
+#define EXPAND_KEY192_PART1(res, k0, kt, rcon)                                \
+    tmp2 = _mm_slli_si128(k0, 4);                                             \
+    tmp1 = _mm_xor_si128(k0, tmp2);                                           \
+    tmp2 = _mm_slli_si128(tmp2, 4);                                           \
+    tmp1 = _mm_xor_si128(_mm_xor_si128(tmp1, tmp2), _mm_slli_si128(tmp2, 4)); \
+    tmp2 = _mm_aeskeygenassist_si128(kt, rcon);                               \
+    res = _mm_xor_si128(tmp1, _mm_shuffle_epi32(tmp2, 0x55))
+
+#define EXPAND_KEY192_PART2(res, k1, k2)             \
+    tmp2 = _mm_xor_si128(k1, _mm_slli_si128(k1, 4)); \
+    res = _mm_xor_si128(tmp2, _mm_shuffle_epi32(k2, 0xFF))
+
+#define EXPAND_KEY192(k0, res1, res2, res3, carry, rcon1, rcon2)         \
+    EXPAND_KEY192_PART1(tmp3, k0, res1, rcon1);                          \
+    EXPAND_KEY192_PART2(carry, res1, tmp3);                              \
+    res1 = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(res1),       \
+                                           _mm_castsi128_pd(tmp3), 0));  \
+    res2 = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(tmp3),       \
+                                           _mm_castsi128_pd(carry), 1)); \
+    EXPAND_KEY192_PART1(res3, tmp3, carry, rcon2)
+
+static void
+native_key_expansion192(AESContext *cx, const unsigned char *key)
+{
+    __m128i *keySchedule = cx->keySchedule;
+    pre_align __m128i tmp1 post_align;
+    pre_align __m128i tmp2 post_align;
+    pre_align __m128i tmp3 post_align;
+    pre_align __m128i carry post_align;
+    keySchedule[0] = _mm_loadu_si128((__m128i *)key);
+    keySchedule[1] = _mm_loadu_si128((__m128i *)(key + 16));
+    EXPAND_KEY192(keySchedule[0], keySchedule[1], keySchedule[2],
+                  keySchedule[3], carry, 0x1, 0x2);
+    EXPAND_KEY192_PART2(keySchedule[4], carry, keySchedule[3]);
+    EXPAND_KEY192(keySchedule[3], keySchedule[4], keySchedule[5],
+                  keySchedule[6], carry, 0x4, 0x8);
+    EXPAND_KEY192_PART2(keySchedule[7], carry, keySchedule[6]);
+    EXPAND_KEY192(keySchedule[6], keySchedule[7], keySchedule[8],
+                  keySchedule[9], carry, 0x10, 0x20);
+    EXPAND_KEY192_PART2(keySchedule[10], carry, keySchedule[9]);
+    EXPAND_KEY192(keySchedule[9], keySchedule[10], keySchedule[11],
+                  keySchedule[12], carry, 0x40, 0x80);
+}
+
+#define EXPAND_KEY256_PART(res, rconx, k1x, k2x, X)                           \
+    tmp_key = _mm_shuffle_epi32(_mm_aeskeygenassist_si128(k2x, rconx), X);    \
+    tmp2 = _mm_slli_si128(k1x, 4);                                            \
+    tmp1 = _mm_xor_si128(k1x, tmp2);                                          \
+    tmp2 = _mm_slli_si128(tmp2, 4);                                           \
+    tmp1 = _mm_xor_si128(_mm_xor_si128(tmp1, tmp2), _mm_slli_si128(tmp2, 4)); \
+    res = _mm_xor_si128(tmp1, tmp_key);
+
+#define EXPAND_KEY256(res1, res2, k1, k2, rcon)   \
+    EXPAND_KEY256_PART(res1, rcon, k1, k2, 0xFF); \
+    EXPAND_KEY256_PART(res2, 0x00, k2, res1, 0xAA)
+
+static void
+native_key_expansion256(AESContext *cx, const unsigned char *key)
+{
+    __m128i *keySchedule = cx->keySchedule;
+    pre_align __m128i tmp_key post_align;
+    pre_align __m128i tmp1 post_align;
+    pre_align __m128i tmp2 post_align;
+    keySchedule[0] = _mm_loadu_si128((__m128i *)key);
+    keySchedule[1] = _mm_loadu_si128((__m128i *)(key + 16));
+    EXPAND_KEY256(keySchedule[2], keySchedule[3], keySchedule[0],
+                  keySchedule[1], 0x01);
+    EXPAND_KEY256(keySchedule[4], keySchedule[5], keySchedule[2],
+                  keySchedule[3], 0x02);
+    EXPAND_KEY256(keySchedule[6], keySchedule[7], keySchedule[4],
+                  keySchedule[5], 0x04);
+    EXPAND_KEY256(keySchedule[8], keySchedule[9], keySchedule[6],
+                  keySchedule[7], 0x08);
+    EXPAND_KEY256(keySchedule[10], keySchedule[11], keySchedule[8],
+                  keySchedule[9], 0x10);
+    EXPAND_KEY256(keySchedule[12], keySchedule[13], keySchedule[10],
+                  keySchedule[11], 0x20);
+    EXPAND_KEY256_PART(keySchedule[14], 0x40, keySchedule[12],
+                       keySchedule[13], 0xFF);
+}
+
+/*
+ * AES key expansion using aes-ni instructions.
+ */
+void
+rijndael_native_key_expansion(AESContext *cx, const unsigned char *key,
+                              unsigned int Nk)
+{
+    switch (Nk) {
+        case 4:
+            native_key_expansion128(cx, key);
+            return;
+        case 6:
+            native_key_expansion192(cx, key);
+            return;
+        case 8:
+            native_key_expansion256(cx, key);
+            return;
+        default:
+            /* This shouldn't happen (checked by the caller). */
+            return;
+    }
+}
+
+void
+rijndael_native_encryptBlock(AESContext *cx,
+                             unsigned char *output,
+                             const unsigned char *input)
+{
+    int i;
+    pre_align __m128i m post_align = _mm_loadu_si128((__m128i *)input);
+    m = _mm_xor_si128(m, cx->keySchedule[0]);
+    for (i = 1; i < cx->Nr; ++i) {
+        m = _mm_aesenc_si128(m, cx->keySchedule[i]);
+    }
+    m = _mm_aesenclast_si128(m, cx->keySchedule[cx->Nr]);
+    _mm_storeu_si128((__m128i *)output, m);
+}
--- a/security/nss/lib/freebl/freebl.gyp
+++ b/security/nss/lib/freebl/freebl.gyp
@@ -18,16 +18,47 @@
       'cflags': [
         '-mssse3'
       ],
       'cflags_mozilla': [
         '-mssse3'
       ]
     },
     {
+      'target_name': 'gcm-aes-x86_c_lib',
+      'type': 'static_library',
+      'sources': [
+        'gcm-x86.c', 'aes-x86.c'
+      ],
+      'dependencies': [
+        '<(DEPTH)/exports.gyp:nss_exports'
+      ],
+      # Enable isa option for pclmul and aes-ni; supported since gcc 4.4.
+      # This is only supported by x84/x64. It's not needed for Windows,
+      # unless clang-cl is used.
+      'cflags_mozilla': [
+        '-mpclmul', '-maes'
+      ],
+      'conditions': [
+        [ 'OS=="linux" or OS=="android" or OS=="dragonfly" or OS=="freebsd" or OS=="netbsd" or OS=="openbsd"', {
+          'cflags': [
+            '-mpclmul', '-maes'
+          ],
+        }],
+        # macOS build doesn't use cflags.
+        [ 'OS=="mac"', {
+          'xcode_settings': {
+            'OTHER_CFLAGS': [
+              '-mpclmul', '-maes'
+            ],
+          },
+        }]
+      ]
+    },
+    {
       'target_name': 'freebl',
       'type': 'static_library',
       'sources': [
         'loader.c'
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports'
       ]
@@ -40,16 +71,21 @@
       'type': 'static_library',
       'includes': [
         'freebl_base.gypi',
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
       ],
       'conditions': [
+        [ 'target_arch=="ia32" or target_arch=="x64"', {
+          'dependencies': [
+            'gcm-aes-x86_c_lib'
+          ],
+        }],
         [ 'OS=="linux"', {
           'defines!': [
             'FREEBL_NO_DEPEND',
             'FREEBL_LOWHASH',
             'USE_HW_AES',
             'INTEL_GCM',
           ],
           'conditions': [
@@ -71,16 +107,21 @@
       'type': 'shared_library',
       'includes': [
         'freebl_base.gypi',
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
       ],
       'conditions': [
+        [ 'target_arch=="ia32" or target_arch=="x64"', {
+          'dependencies': [
+            'gcm-aes-x86_c_lib'
+          ]
+        }],
         [ 'OS!="linux" and OS!="android"', {
           'conditions': [
             [ 'moz_fold_libs==0', {
               'dependencies': [
                 '<(DEPTH)/lib/util/util.gyp:nssutil3',
               ],
             }, {
               'libraries': [
@@ -149,37 +190,21 @@
       'SHLIB_SUFFIX=\"<(dll_suffix)\"',
       'SHLIB_PREFIX=\"<(dll_prefix)\"',
       'SHLIB_VERSION=\"3\"',
       'SOFTOKEN_SHLIB_VERSION=\"3\"',
       'RIJNDAEL_INCLUDE_TABLES',
       'MP_API_COMPATIBLE'
     ],
     'conditions': [
-      [ 'target_arch=="ia32" or target_arch=="x64"', {
-        'cflags_mozilla': [
-          '-mpclmul',
-          '-maes',
-        ],
-        'conditions': [
-          [ 'OS=="dragonfly" or OS=="freebsd" or OS=="netbsd" or OS=="openbsd"', {
-            'cflags': [
-              '-mpclmul',
-              '-maes',
-            ],
-          }],
-        ],
-      }],
       [ '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
@@ -263,24 +288,16 @@
             'defines': [
               'MP_IS_LITTLE_ENDIAN',
               'MP_ASSEMBLY_MULTIPLY',
               'MP_ASSEMBLY_SQUARE',
               'MP_ASSEMBLY_DIV_2DX1D',
               'MP_USE_UINT_DIGIT',
             ],
           }],
-          [ 'target_arch=="ia32" or target_arch=="x64"', {
-            'cflags': [
-              # enable isa option for pclmul am aes-ni; supported since gcc 4.4
-              # This is only support by x84/x64. It's not needed for Windows.
-              '-mpclmul',
-              '-maes',
-            ],
-          }],
           [ 'target_arch=="arm"', {
             'defines': [
               'MP_ASSEMBLY_MULTIPLY',
               'MP_ASSEMBLY_SQUARE',
               'MP_USE_UINT_DIGIT',
               'SHA_NO_LONG_LONG',
               'ARMHF',
             ],
new file mode 100644
--- /dev/null
+++ b/security/nss/lib/freebl/gcm-x86.c
@@ -0,0 +1,127 @@
+/* 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/. */
+
+#ifdef FREEBL_NO_DEPEND
+#include "stubs.h"
+#endif
+#include "gcm.h"
+#include "secerr.h"
+
+#include <wmmintrin.h> /* clmul */
+
+#define WRITE64(x, bytes)   \
+    (bytes)[0] = (x) >> 56; \
+    (bytes)[1] = (x) >> 48; \
+    (bytes)[2] = (x) >> 40; \
+    (bytes)[3] = (x) >> 32; \
+    (bytes)[4] = (x) >> 24; \
+    (bytes)[5] = (x) >> 16; \
+    (bytes)[6] = (x) >> 8;  \
+    (bytes)[7] = (x);
+
+SECStatus
+gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
+{
+    uint64_t tmp_out[2];
+    _mm_storeu_si128((__m128i *)tmp_out, ghash->x);
+    /* maxout must be larger than 16 byte (checked by the caller). */
+    WRITE64(tmp_out[0], outbuf + 8);
+    WRITE64(tmp_out[1], outbuf);
+    return SECSuccess;
+}
+
+SECStatus
+gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
+                unsigned int count)
+{
+    size_t i;
+    pre_align __m128i z_high post_align;
+    pre_align __m128i z_low post_align;
+    pre_align __m128i C post_align;
+    pre_align __m128i D post_align;
+    pre_align __m128i E post_align;
+    pre_align __m128i F post_align;
+    pre_align __m128i bin post_align;
+    pre_align __m128i Ci post_align;
+    pre_align __m128i tmp post_align;
+
+    for (i = 0; i < count; i++, buf += 16) {
+        bin = _mm_set_epi16(((uint16_t)buf[0] << 8) | buf[1],
+                            ((uint16_t)buf[2] << 8) | buf[3],
+                            ((uint16_t)buf[4] << 8) | buf[5],
+                            ((uint16_t)buf[6] << 8) | buf[7],
+                            ((uint16_t)buf[8] << 8) | buf[9],
+                            ((uint16_t)buf[10] << 8) | buf[11],
+                            ((uint16_t)buf[12] << 8) | buf[13],
+                            ((uint16_t)buf[14] << 8) | buf[15]);
+        Ci = _mm_xor_si128(bin, ghash->x);
+
+        /* Do binary mult ghash->X = Ci * ghash->H. */
+        C = _mm_clmulepi64_si128(Ci, ghash->h, 0x00);
+        D = _mm_clmulepi64_si128(Ci, ghash->h, 0x11);
+        E = _mm_clmulepi64_si128(Ci, ghash->h, 0x01);
+        F = _mm_clmulepi64_si128(Ci, ghash->h, 0x10);
+        tmp = _mm_xor_si128(E, F);
+        z_high = _mm_xor_si128(tmp, _mm_slli_si128(D, 8));
+        z_high = _mm_unpackhi_epi64(z_high, D);
+        z_low = _mm_xor_si128(_mm_slli_si128(tmp, 8), C);
+        z_low = _mm_unpackhi_epi64(_mm_slli_si128(C, 8), z_low);
+
+        /* Shift one to the left (multiply by x) as gcm spec is stupid. */
+        C = _mm_slli_si128(z_low, 8);
+        E = _mm_srli_epi64(C, 63);
+        D = _mm_slli_si128(z_high, 8);
+        F = _mm_srli_epi64(D, 63);
+        /* Carry over */
+        C = _mm_srli_si128(z_low, 8);
+        D = _mm_srli_epi64(C, 63);
+        z_low = _mm_or_si128(_mm_slli_epi64(z_low, 1), E);
+        z_high = _mm_or_si128(_mm_or_si128(_mm_slli_epi64(z_high, 1), F), D);
+
+        /* Reduce */
+        C = _mm_slli_si128(z_low, 8);
+        /* D = z_low << 127 */
+        D = _mm_slli_epi64(C, 63);
+        /* E = z_low << 126 */
+        E = _mm_slli_epi64(C, 62);
+        /* F = z_low << 121 */
+        F = _mm_slli_epi64(C, 57);
+        /* z_low ^= (z_low << 127) ^ (z_low << 126) ^ (z_low << 121); */
+        z_low = _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(z_low, D), E), F);
+        C = _mm_srli_si128(z_low, 8);
+        /* D = z_low >> 1 */
+        D = _mm_slli_epi64(C, 63);
+        D = _mm_or_si128(_mm_srli_epi64(z_low, 1), D);
+        /* E = z_low >> 2 */
+        E = _mm_slli_epi64(C, 62);
+        E = _mm_or_si128(_mm_srli_epi64(z_low, 2), E);
+        /* F = z_low >> 7 */
+        F = _mm_slli_epi64(C, 57);
+        F = _mm_or_si128(_mm_srli_epi64(z_low, 7), F);
+        /* ghash->x ^= z_low ^ (z_low >> 1) ^ (z_low >> 2) ^ (z_low >> 7); */
+        ghash->x = _mm_xor_si128(_mm_xor_si128(
+                                     _mm_xor_si128(_mm_xor_si128(z_high, z_low), D), E),
+                                 F);
+    }
+    return SECSuccess;
+}
+
+SECStatus
+gcm_HashInit_hw(gcmHashContext *ghash)
+{
+    ghash->ghash_mul = gcm_HashMult_hw;
+    ghash->x = _mm_setzero_si128();
+    /* MSVC requires __m64 to load epi64. */
+    ghash->h = _mm_set_epi32(ghash->h_high >> 32, (uint32_t)ghash->h_high,
+                             ghash->h_low >> 32, (uint32_t)ghash->h_low);
+    ghash->hw = PR_TRUE;
+    return SECSuccess;
+}
+
+SECStatus
+gcm_HashZeroX_hw(gcmHashContext *ghash)
+{
+    ghash->x = _mm_setzero_si128();
+    return SECSuccess;
+}
--- a/security/nss/lib/freebl/gcm.c
+++ b/security/nss/lib/freebl/gcm.c
@@ -12,28 +12,60 @@
 #include "gcm.h"
 #include "ctr.h"
 #include "secerr.h"
 #include "prtypes.h"
 #include "pkcs11t.h"
 
 #include <limits.h>
 
-#ifdef NSS_X86_OR_X64
-#include <wmmintrin.h> /* clmul */
-#endif
-
 /* Forward declarations */
+SECStatus gcm_HashInit_hw(gcmHashContext *ghash);
+SECStatus gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf);
 SECStatus gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
                           unsigned int count);
+SECStatus gcm_HashZeroX_hw(gcmHashContext *ghash);
 SECStatus gcm_HashMult_sftw(gcmHashContext *ghash, const unsigned char *buf,
                             unsigned int count);
 SECStatus gcm_HashMult_sftw32(gcmHashContext *ghash, const unsigned char *buf,
                               unsigned int count);
 
+/* Stub definitions for the above *_hw functions, which shouldn't be
+ * used unless NSS_X86_OR_X64 is defined */
+#ifndef NSS_X86_OR_X64
+SECStatus
+gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
+{
+    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+    return SECFailure;
+}
+
+SECStatus
+gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
+                unsigned int count)
+{
+    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+    return SECFailure;
+}
+
+SECStatus
+gcm_HashInit_hw(gcmHashContext *ghash)
+{
+    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+    return SECFailure;
+}
+
+SECStatus
+gcm_HashZeroX_hw(gcmHashContext *ghash)
+{
+    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+    return SECFailure;
+}
+#endif /* NSS_X86_OR_X64 */
+
 uint64_t
 get64(const unsigned char *bytes)
 {
     return ((uint64_t)bytes[0]) << 56 |
            ((uint64_t)bytes[1]) << 48 |
            ((uint64_t)bytes[2]) << 40 |
            ((uint64_t)bytes[3]) << 32 |
            ((uint64_t)bytes[4]) << 24 |
@@ -41,46 +73,38 @@ get64(const unsigned char *bytes)
            ((uint64_t)bytes[6]) << 8 |
            ((uint64_t)bytes[7]);
 }
 
 /* Initialize a gcmHashContext */
 SECStatus
 gcmHash_InitContext(gcmHashContext *ghash, const unsigned char *H, PRBool sw)
 {
+    SECStatus rv = SECSuccess;
+
     ghash->cLen = 0;
     ghash->bufLen = 0;
     PORT_Memset(ghash->counterBuf, 0, sizeof(ghash->counterBuf));
 
     ghash->h_low = get64(H + 8);
     ghash->h_high = get64(H);
     if (clmul_support() && !sw) {
-#ifdef NSS_X86_OR_X64
-        ghash->ghash_mul = gcm_HashMult_hw;
-        ghash->x = _mm_setzero_si128();
-        /* MSVC requires __m64 to load epi64. */
-        ghash->h = _mm_set_epi32(ghash->h_high >> 32, (uint32_t)ghash->h_high,
-                                 ghash->h_low >> 32, (uint32_t)ghash->h_low);
-        ghash->hw = PR_TRUE;
-#else
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-#endif /* NSS_X86_OR_X64 */
+        rv = gcm_HashInit_hw(ghash);
     } else {
 /* We fall back to the software implementation if we can't use / don't
          * want to use pclmul. */
 #ifdef HAVE_INT128_SUPPORT
         ghash->ghash_mul = gcm_HashMult_sftw;
 #else
         ghash->ghash_mul = gcm_HashMult_sftw32;
 #endif
         ghash->x_high = ghash->x_low = 0;
         ghash->hw = PR_FALSE;
     }
-    return SECSuccess;
+    return rv;
 }
 
 #ifdef HAVE_INT128_SUPPORT
 /* Binary multiplication x * y = r_high << 64 | r_low. */
 void
 bmul(uint64_t x, uint64_t y, uint64_t *r_high, uint64_t *r_low)
 {
     uint128_t x1, x2, x3, x4, x5;
@@ -278,112 +302,27 @@ gcm_HashMult_sftw32(gcmHashContext *ghas
                     (z_low_h << 63) ^ (z_low_h << 62) ^ (z_low_h << 57);
         ghash->x_high = z_high_h;
         ghash->x_low = z_high_l;
     }
     return SECSuccess;
 }
 #endif /* HAVE_INT128_SUPPORT */
 
-SECStatus
-gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
-                unsigned int count)
-{
-#ifdef NSS_X86_OR_X64
-    size_t i;
-    pre_align __m128i z_high post_align;
-    pre_align __m128i z_low post_align;
-    pre_align __m128i C post_align;
-    pre_align __m128i D post_align;
-    pre_align __m128i E post_align;
-    pre_align __m128i F post_align;
-    pre_align __m128i bin post_align;
-    pre_align __m128i Ci post_align;
-    pre_align __m128i tmp post_align;
-
-    for (i = 0; i < count; i++, buf += 16) {
-        bin = _mm_set_epi16(((uint16_t)buf[0] << 8) | buf[1],
-                            ((uint16_t)buf[2] << 8) | buf[3],
-                            ((uint16_t)buf[4] << 8) | buf[5],
-                            ((uint16_t)buf[6] << 8) | buf[7],
-                            ((uint16_t)buf[8] << 8) | buf[9],
-                            ((uint16_t)buf[10] << 8) | buf[11],
-                            ((uint16_t)buf[12] << 8) | buf[13],
-                            ((uint16_t)buf[14] << 8) | buf[15]);
-        Ci = _mm_xor_si128(bin, ghash->x);
-
-        /* Do binary mult ghash->X = Ci * ghash->H. */
-        C = _mm_clmulepi64_si128(Ci, ghash->h, 0x00);
-        D = _mm_clmulepi64_si128(Ci, ghash->h, 0x11);
-        E = _mm_clmulepi64_si128(Ci, ghash->h, 0x01);
-        F = _mm_clmulepi64_si128(Ci, ghash->h, 0x10);
-        tmp = _mm_xor_si128(E, F);
-        z_high = _mm_xor_si128(tmp, _mm_slli_si128(D, 8));
-        z_high = _mm_unpackhi_epi64(z_high, D);
-        z_low = _mm_xor_si128(_mm_slli_si128(tmp, 8), C);
-        z_low = _mm_unpackhi_epi64(_mm_slli_si128(C, 8), z_low);
-
-        /* Shift one to the left (multiply by x) as gcm spec is stupid. */
-        C = _mm_slli_si128(z_low, 8);
-        E = _mm_srli_epi64(C, 63);
-        D = _mm_slli_si128(z_high, 8);
-        F = _mm_srli_epi64(D, 63);
-        /* Carry over */
-        C = _mm_srli_si128(z_low, 8);
-        D = _mm_srli_epi64(C, 63);
-        z_low = _mm_or_si128(_mm_slli_epi64(z_low, 1), E);
-        z_high = _mm_or_si128(_mm_or_si128(_mm_slli_epi64(z_high, 1), F), D);
-
-        /* Reduce */
-        C = _mm_slli_si128(z_low, 8);
-        /* D = z_low << 127 */
-        D = _mm_slli_epi64(C, 63);
-        /* E = z_low << 126 */
-        E = _mm_slli_epi64(C, 62);
-        /* F = z_low << 121 */
-        F = _mm_slli_epi64(C, 57);
-        /* z_low ^= (z_low << 127) ^ (z_low << 126) ^ (z_low << 121); */
-        z_low = _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(z_low, D), E), F);
-        C = _mm_srli_si128(z_low, 8);
-        /* D = z_low >> 1 */
-        D = _mm_slli_epi64(C, 63);
-        D = _mm_or_si128(_mm_srli_epi64(z_low, 1), D);
-        /* E = z_low >> 2 */
-        E = _mm_slli_epi64(C, 62);
-        E = _mm_or_si128(_mm_srli_epi64(z_low, 2), E);
-        /* F = z_low >> 7 */
-        F = _mm_slli_epi64(C, 57);
-        F = _mm_or_si128(_mm_srli_epi64(z_low, 7), F);
-        /* ghash->x ^= z_low ^ (z_low >> 1) ^ (z_low >> 2) ^ (z_low >> 7); */
-        ghash->x = _mm_xor_si128(_mm_xor_si128(
-                                     _mm_xor_si128(_mm_xor_si128(z_high, z_low), D), E),
-                                 F);
-    }
-    return SECSuccess;
-#else
-    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-    return SECFailure;
-#endif /* NSS_X86_OR_X64 */
-}
-
 static SECStatus
 gcm_zeroX(gcmHashContext *ghash)
 {
+    SECStatus rv = SECSuccess;
+
     if (ghash->hw) {
-#ifdef NSS_X86_OR_X64
-        ghash->x = _mm_setzero_si128();
-        return SECSuccess;
-#else
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-#endif /* NSS_X86_OR_X64 */
+        rv = gcm_HashZeroX_hw(ghash);
     }
 
     ghash->x_high = ghash->x_low = 0;
-    return SECSuccess;
+    return rv;
 }
 
 /*
  * implement GCM GHASH using the freebl GHASH function. The gcm_HashMult
  * function always takes AES_BLOCK_SIZE lengths of data. gcmHash_Update will
  * format the data properly.
  */
 SECStatus
@@ -498,25 +437,20 @@ gcmHash_Final(gcmHashContext *ghash, uns
 
     rv = ghash->ghash_mul(ghash, ghash->counterBuf,
                           (GCM_HASH_LEN_LEN * 2) / AES_BLOCK_SIZE);
     if (rv != SECSuccess) {
         goto cleanup;
     }
 
     if (ghash->hw) {
-#ifdef NSS_X86_OR_X64
-        uint64_t tmp_out[2];
-        _mm_storeu_si128((__m128i *)tmp_out, ghash->x);
-        WRITE64(tmp_out[0], T + 8);
-        WRITE64(tmp_out[1], T);
-#else
-        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
-        return SECFailure;
-#endif /* NSS_X86_OR_X64 */
+        rv = gcm_HashWrite_hw(ghash, T);
+        if (rv != SECSuccess) {
+            goto cleanup;
+        }
     } else {
         WRITE64(ghash->x_low, T + 8);
         WRITE64(ghash->x_high, T);
     }
 
     if (maxout > AES_BLOCK_SIZE) {
         maxout = AES_BLOCK_SIZE;
     }
--- a/security/nss/lib/freebl/gcm.h
+++ b/security/nss/lib/freebl/gcm.h
@@ -4,17 +4,31 @@
 
 #ifndef GCM_H
 #define GCM_H 1
 
 #include "blapii.h"
 #include <stdint.h>
 
 #ifdef NSS_X86_OR_X64
+/* GCC <= 4.8 doesn't support including emmintrin.h without enabling SSE2 */
+#if !defined(__clang__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && \
+    (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
+#pragma GCC push_options
+#pragma GCC target("sse2")
+#undef NSS_DISABLE_SSE2
+#define NSS_DISABLE_SSE2 1
+#endif /* GCC <= 4.8 */
+
 #include <emmintrin.h> /* __m128i */
+
+#ifdef NSS_DISABLE_SSE2
+#undef NSS_DISABLE_SSE2
+#pragma GCC pop_options
+#endif /* NSS_DISABLE_SSE2 */
 #endif
 
 SEC_BEGIN_PROTOS
 
 #ifdef HAVE_INT128_SUPPORT
 typedef unsigned __int128 uint128_t;
 #endif
 
--- a/security/nss/lib/freebl/manifest.mn
+++ b/security/nss/lib/freebl/manifest.mn
@@ -175,25 +175,17 @@ ALL_HDRS =  \
 	sha_fast.h \
 	sha256.h \
 	shsign.h \
 	vis_proto.h \
 	seed.h \
 	$(NULL)
 
 
-ifdef AES_GEN_TBL
-DEFINES += -DRIJNDAEL_GENERATE_TABLES
-else
-ifdef AES_GEN_TBL_M
-DEFINES += -DRIJNDAEL_GENERATE_TABLES_MACRO
-else
 ifdef AES_GEN_VAL
 DEFINES += -DRIJNDAEL_GENERATE_VALUES
 else
 ifdef AES_GEN_VAL_M
 DEFINES += -DRIJNDAEL_GENERATE_VALUES_MACRO
 else
 DEFINES += -DRIJNDAEL_INCLUDE_TABLES
 endif
 endif
-endif
-endif
--- a/security/nss/lib/freebl/rijndael.c
+++ b/security/nss/lib/freebl/rijndael.c
@@ -22,26 +22,49 @@
 
 #ifdef USE_HW_AES
 #include "intel-aes.h"
 #endif
 #ifdef INTEL_GCM
 #include "intel-gcm.h"
 #endif /* INTEL_GCM */
 
+/* Forward declarations */
+void rijndael_native_key_expansion(AESContext *cx, const unsigned char *key,
+                                   unsigned int Nk);
+void rijndael_native_encryptBlock(AESContext *cx,
+                                  unsigned char *output,
+                                  const unsigned char *input);
+
+/* Stub definitions for the above rijndael_native_* functions, which
+ * shouldn't be used unless NSS_X86_OR_X64 is defined */
+#ifndef NSS_X86_OR_X64
+void
+rijndael_native_key_expansion(AESContext *cx, const unsigned char *key,
+                              unsigned int Nk)
+{
+    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+    PORT_Assert(0);
+}
+
+void
+rijndael_native_encryptBlock(AESContext *cx,
+                             unsigned char *output,
+                             const unsigned char *input)
+{
+    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+    PORT_Assert(0);
+}
+#endif /* NSS_X86_OR_X64 */
+
 /*
- * There are currently five ways to build this code, varying in performance
+ * There are currently three ways to build this code, varying in performance
  * and code size.
  *
  * RIJNDAEL_INCLUDE_TABLES         Include all tables from rijndael32.tab
- * RIJNDAEL_GENERATE_TABLES        Generate tables on first
- *                                 encryption/decryption, then store them;
- *                                 use the function gfm
- * RIJNDAEL_GENERATE_TABLES_MACRO  Same as above, but use macros to do
- *                                 the generation
  * RIJNDAEL_GENERATE_VALUES        Do not store tables, generate the table
  *                                 values "on-the-fly", using gfm
  * RIJNDAEL_GENERATE_VALUES_MACRO  Same as above, but use macros
  *
  * The default is RIJNDAEL_INCLUDE_TABLES.
  */
 
 /*
@@ -103,18 +126,17 @@
 
 /*
  * The function xtime, used for Galois field multiplication
  */
 #define XTIME(a) \
     ((a & 0x80) ? ((a << 1) ^ 0x1b) : (a << 1))
 
 /* Choose GFM method (macros or function) */
-#if defined(RIJNDAEL_GENERATE_TABLES_MACRO) || \
-    defined(RIJNDAEL_GENERATE_VALUES_MACRO)
+#if defined(RIJNDAEL_GENERATE_VALUES_MACRO)
 
 /*
  * Galois field GF(2**8) multipliers, in macro form
  */
 #define GFM01(a) \
     (a) /* a * 01 = a, the identity */
 #define GFM02(a) \
     (XTIME(a) & 0xff) /* a * 02 = xtime(a) */
@@ -128,17 +150,17 @@
     (GFM01(a) ^ GFM08(a)) /* a * 09 = a * (01 + 08) */
 #define GFM0B(a) \
     (GFM01(a) ^ GFM02(a) ^ GFM08(a)) /* a * 0B = a * (01 + 02 + 08) */
 #define GFM0D(a) \
     (GFM01(a) ^ GFM04(a) ^ GFM08(a)) /* a * 0D = a * (01 + 04 + 08) */
 #define GFM0E(a) \
     (GFM02(a) ^ GFM04(a) ^ GFM08(a)) /* a * 0E = a * (02 + 04 + 08) */
 
-#else /* RIJNDAEL_GENERATE_TABLES or RIJNDAEL_GENERATE_VALUES */
+#else /* RIJNDAEL_GENERATE_VALUES */
 
 /* GF_MULTIPLY
  *
  * multiply two bytes represented in GF(2**8), mod (x**4 + 1)
  */
 PRUint8
 gfm(PRUint8 a, PRUint8 b)
 {
@@ -239,108 +261,34 @@ gen_TInvXi(PRUint8 tx, PRUint8 i)
 #define TInv0(i) gen_TInvXi(0, i)
 #define TInv1(i) gen_TInvXi(1, i)
 #define TInv2(i) gen_TInvXi(2, i)
 #define TInv3(i) gen_TInvXi(3, i)
 #define IMXC0(b) G_IMXC0(b)
 #define IMXC1(b) G_IMXC1(b)
 #define IMXC2(b) G_IMXC2(b)
 #define IMXC3(b) G_IMXC3(b)
-#elif defined(RIJNDAEL_GENERATE_VALUES_MACRO)
+#else /* RIJNDAEL_GENERATE_VALUES_MACRO */
 /* generate values for the tables with macros */
 #define T0(i) G_T0(i)
 #define T1(i) G_T1(i)
 #define T2(i) G_T2(i)
 #define T3(i) G_T3(i)
 #define TInv0(i) G_TInv0(i)
 #define TInv1(i) G_TInv1(i)
 #define TInv2(i) G_TInv2(i)
 #define TInv3(i) G_TInv3(i)
 #define IMXC0(b) G_IMXC0(b)
 #define IMXC1(b) G_IMXC1(b)
 #define IMXC2(b) G_IMXC2(b)
 #define IMXC3(b) G_IMXC3(b)
-#else /* RIJNDAEL_GENERATE_TABLES or RIJNDAEL_GENERATE_TABLES_MACRO */
-/* Generate T and T**-1 table values and store, then index */
-/* The inverse mix column tables are still generated */
-#define T0(i) rijndaelTables->T0[i]
-#define T1(i) rijndaelTables->T1[i]
-#define T2(i) rijndaelTables->T2[i]
-#define T3(i) rijndaelTables->T3[i]
-#define TInv0(i) rijndaelTables->TInv0[i]
-#define TInv1(i) rijndaelTables->TInv1[i]
-#define TInv2(i) rijndaelTables->TInv2[i]
-#define TInv3(i) rijndaelTables->TInv3[i]
-#define IMXC0(b) G_IMXC0(b)
-#define IMXC1(b) G_IMXC1(b)
-#define IMXC2(b) G_IMXC2(b)
-#define IMXC3(b) G_IMXC3(b)
 #endif /* choose T-table indexing method */
 
 #endif /* not RIJNDAEL_INCLUDE_TABLES */
 
-#if defined(RIJNDAEL_GENERATE_TABLES) || \
-    defined(RIJNDAEL_GENERATE_TABLES_MACRO)
-
-/* Code to generate and store the tables */
-
-struct rijndael_tables_str {
-    PRUint32 T0[256];
-    PRUint32 T1[256];
-    PRUint32 T2[256];
-    PRUint32 T3[256];
-    PRUint32 TInv0[256];
-    PRUint32 TInv1[256];
-    PRUint32 TInv2[256];
-    PRUint32 TInv3[256];
-};
-
-static struct rijndael_tables_str *rijndaelTables = NULL;
-static PRCallOnceType coRTInit = { 0, 0, 0 };
-static PRStatus
-init_rijndael_tables(void)
-{
-    PRUint32 i;
-    PRUint8 si01, si02, si03, si04, si08, si09, si0B, si0D, si0E;
-    struct rijndael_tables_str *rts;
-    rts = (struct rijndael_tables_str *)
-        PORT_Alloc(sizeof(struct rijndael_tables_str));
-    if (!rts)
-        return PR_FAILURE;
-    for (i = 0; i < 256; i++) {
-        /* The forward values */
-        si01 = SBOX(i);
-        si02 = XTIME(si01);
-        si03 = si02 ^ si01;
-        rts->T0[i] = WORD4(si02, si01, si01, si03);
-        rts->T1[i] = WORD4(si03, si02, si01, si01);
-        rts->T2[i] = WORD4(si01, si03, si02, si01);
-        rts->T3[i] = WORD4(si01, si01, si03, si02);
-        /* The inverse values */
-        si01 = SINV(i);
-        si02 = XTIME(si01);
-        si04 = XTIME(si02);
-        si08 = XTIME(si04);
-        si03 = si02 ^ si01;
-        si09 = si08 ^ si01;
-        si0B = si08 ^ si03;
-        si0D = si09 ^ si04;
-        si0E = si08 ^ si04 ^ si02;
-        rts->TInv0[i] = WORD4(si0E, si09, si0D, si0B);
-        rts->TInv1[i] = WORD4(si0B, si0E, si09, si0D);
-        rts->TInv2[i] = WORD4(si0D, si0B, si0E, si09);
-        rts->TInv3[i] = WORD4(si09, si0D, si0B, si0E);
-    }
-    /* wait until all the values are in to set */
-    rijndaelTables = rts;
-    return PR_SUCCESS;
-}
-
-#endif /* code to generate tables */
-
 /**************************************************************************
  *
  * Stuff related to the Rijndael key schedule
  *
  *************************************************************************/
 
 #define SUBBYTE(w)                                \
     ((((PRUint32)SBOX((w >> 24) & 0xff)) << 24) | \
@@ -384,172 +332,16 @@ rijndael_key_expansion7(AESContext *cx, 
         if (i % Nk == 0)
             tmp = SUBBYTE(ROTBYTE(tmp)) ^ Rcon[i / Nk - 1];
         else if (i % Nk == 4)
             tmp = SUBBYTE(tmp);
         *pW = W[i - Nk] ^ tmp;
     }
 }
 
-#if defined(NSS_X86_OR_X64)
-#define EXPAND_KEY128(k, rcon, res)                   \
-    tmp_key = _mm_aeskeygenassist_si128(k, rcon);     \
-    tmp_key = _mm_shuffle_epi32(tmp_key, 0xFF);       \
-    tmp = _mm_xor_si128(k, _mm_slli_si128(k, 4));     \
-    tmp = _mm_xor_si128(tmp, _mm_slli_si128(tmp, 4)); \
-    tmp = _mm_xor_si128(tmp, _mm_slli_si128(tmp, 4)); \
-    res = _mm_xor_si128(tmp, tmp_key)
-
-static void
-native_key_expansion128(AESContext *cx, const unsigned char *key)
-{
-    __m128i *keySchedule = cx->keySchedule;
-    pre_align __m128i tmp_key post_align;
-    pre_align __m128i tmp post_align;
-    keySchedule[0] = _mm_loadu_si128((__m128i *)key);
-    EXPAND_KEY128(keySchedule[0], 0x01, keySchedule[1]);
-    EXPAND_KEY128(keySchedule[1], 0x02, keySchedule[2]);
-    EXPAND_KEY128(keySchedule[2], 0x04, keySchedule[3]);
-    EXPAND_KEY128(keySchedule[3], 0x08, keySchedule[4]);
-    EXPAND_KEY128(keySchedule[4], 0x10, keySchedule[5]);
-    EXPAND_KEY128(keySchedule[5], 0x20, keySchedule[6]);
-    EXPAND_KEY128(keySchedule[6], 0x40, keySchedule[7]);
-    EXPAND_KEY128(keySchedule[7], 0x80, keySchedule[8]);
-    EXPAND_KEY128(keySchedule[8], 0x1B, keySchedule[9]);
-    EXPAND_KEY128(keySchedule[9], 0x36, keySchedule[10]);
-}
-
-#define EXPAND_KEY192_PART1(res, k0, kt, rcon)                                \
-    tmp2 = _mm_slli_si128(k0, 4);                                             \
-    tmp1 = _mm_xor_si128(k0, tmp2);                                           \
-    tmp2 = _mm_slli_si128(tmp2, 4);                                           \
-    tmp1 = _mm_xor_si128(_mm_xor_si128(tmp1, tmp2), _mm_slli_si128(tmp2, 4)); \
-    tmp2 = _mm_aeskeygenassist_si128(kt, rcon);                               \
-    res = _mm_xor_si128(tmp1, _mm_shuffle_epi32(tmp2, 0x55))
-
-#define EXPAND_KEY192_PART2(res, k1, k2)             \
-    tmp2 = _mm_xor_si128(k1, _mm_slli_si128(k1, 4)); \
-    res = _mm_xor_si128(tmp2, _mm_shuffle_epi32(k2, 0xFF))
-
-#define EXPAND_KEY192(k0, res1, res2, res3, carry, rcon1, rcon2)         \
-    EXPAND_KEY192_PART1(tmp3, k0, res1, rcon1);                          \
-    EXPAND_KEY192_PART2(carry, res1, tmp3);                              \
-    res1 = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(res1),       \
-                                           _mm_castsi128_pd(tmp3), 0));  \
-    res2 = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(tmp3),       \
-                                           _mm_castsi128_pd(carry), 1)); \
-    EXPAND_KEY192_PART1(res3, tmp3, carry, rcon2)
-
-static void
-native_key_expansion192(AESContext *cx, const unsigned char *key)
-{
-    __m128i *keySchedule = cx->keySchedule;
-    pre_align __m128i tmp1 post_align;
-    pre_align __m128i tmp2 post_align;
-    pre_align __m128i tmp3 post_align;
-    pre_align __m128i carry post_align;
-    keySchedule[0] = _mm_loadu_si128((__m128i *)key);
-    keySchedule[1] = _mm_loadu_si128((__m128i *)(key + 16));
-    EXPAND_KEY192(keySchedule[0], keySchedule[1], keySchedule[2],
-                  keySchedule[3], carry, 0x1, 0x2);
-    EXPAND_KEY192_PART2(keySchedule[4], carry, keySchedule[3]);
-    EXPAND_KEY192(keySchedule[3], keySchedule[4], keySchedule[5],
-                  keySchedule[6], carry, 0x4, 0x8);
-    EXPAND_KEY192_PART2(keySchedule[7], carry, keySchedule[6]);
-    EXPAND_KEY192(keySchedule[6], keySchedule[7], keySchedule[8],
-                  keySchedule[9], carry, 0x10, 0x20);
-    EXPAND_KEY192_PART2(keySchedule[10], carry, keySchedule[9]);
-    EXPAND_KEY192(keySchedule[9], keySchedule[10], keySchedule[11],
-                  keySchedule[12], carry, 0x40, 0x80);
-}
-
-#define EXPAND_KEY256_PART(res, rconx, k1x, k2x, X)                           \
-    tmp_key = _mm_shuffle_epi32(_mm_aeskeygenassist_si128(k2x, rconx), X);    \
-    tmp2 = _mm_slli_si128(k1x, 4);                                            \
-    tmp1 = _mm_xor_si128(k1x, tmp2);                                          \
-    tmp2 = _mm_slli_si128(tmp2, 4);                                           \
-    tmp1 = _mm_xor_si128(_mm_xor_si128(tmp1, tmp2), _mm_slli_si128(tmp2, 4)); \
-    res = _mm_xor_si128(tmp1, tmp_key);
-
-#define EXPAND_KEY256(res1, res2, k1, k2, rcon)   \
-    EXPAND_KEY256_PART(res1, rcon, k1, k2, 0xFF); \
-    EXPAND_KEY256_PART(res2, 0x00, k2, res1, 0xAA)
-
-static void
-native_key_expansion256(AESContext *cx, const unsigned char *key)
-{
-    __m128i *keySchedule = cx->keySchedule;
-    pre_align __m128i tmp_key post_align;
-    pre_align __m128i tmp1 post_align;
-    pre_align __m128i tmp2 post_align;
-    keySchedule[0] = _mm_loadu_si128((__m128i *)key);
-    keySchedule[1] = _mm_loadu_si128((__m128i *)(key + 16));
-    EXPAND_KEY256(keySchedule[2], keySchedule[3], keySchedule[0],
-                  keySchedule[1], 0x01);
-    EXPAND_KEY256(keySchedule[4], keySchedule[5], keySchedule[2],
-                  keySchedule[3], 0x02);
-    EXPAND_KEY256(keySchedule[6], keySchedule[7], keySchedule[4],
-                  keySchedule[5], 0x04);
-    EXPAND_KEY256(keySchedule[8], keySchedule[9], keySchedule[6],
-                  keySchedule[7], 0x08);
-    EXPAND_KEY256(keySchedule[10], keySchedule[11], keySchedule[8],
-                  keySchedule[9], 0x10);
-    EXPAND_KEY256(keySchedule[12], keySchedule[13], keySchedule[10],
-                  keySchedule[11], 0x20);
-    EXPAND_KEY256_PART(keySchedule[14], 0x40, keySchedule[12],
-                       keySchedule[13], 0xFF);
-}
-
-#endif /* NSS_X86_OR_X64 */
-
-/*
- * AES key expansion using aes-ni instructions.
- */
-static void
-native_key_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk)
-{
-#ifdef NSS_X86_OR_X64
-    switch (Nk) {
-        case 4:
-            native_key_expansion128(cx, key);
-            return;
-        case 6:
-            native_key_expansion192(cx, key);
-            return;
-        case 8:
-            native_key_expansion256(cx, key);
-            return;
-        default:
-            /* This shouldn't happen. */
-            PORT_Assert(0);
-    }
-#else
-    PORT_Assert(0);
-#endif /* NSS_X86_OR_X64 */
-}
-
-static void
-native_encryptBlock(AESContext *cx,
-                    unsigned char *output,
-                    const unsigned char *input)
-{
-#ifdef NSS_X86_OR_X64
-    int i;
-    pre_align __m128i m post_align = _mm_loadu_si128((__m128i *)input);
-    m = _mm_xor_si128(m, cx->keySchedule[0]);
-    for (i = 1; i < cx->Nr; ++i) {
-        m = _mm_aesenc_si128(m, cx->keySchedule[i]);
-    }
-    m = _mm_aesenclast_si128(m, cx->keySchedule[cx->Nr]);
-    _mm_storeu_si128((__m128i *)output, m);
-#else
-    PORT_Assert(0);
-#endif /* NSS_X86_OR_X64 */
-}
-
 /* rijndael_key_expansion
  *
  * Generate the expanded key from the key input by the user.
  */
 static void
 rijndael_key_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk)
 {
     unsigned int i;
@@ -905,17 +697,17 @@ static SECStatus
 rijndael_encryptECB(AESContext *cx, unsigned char *output,
                     unsigned int *outputLen, unsigned int maxOutputLen,
                     const unsigned char *input, unsigned int inputLen)
 {
     AESBlockFunc *encryptor;
 
     if (aesni_support()) {
         /* Use hardware acceleration for normal AES parameters. */
-        encryptor = &native_encryptBlock;
+        encryptor = &rijndael_native_encryptBlock;
     } else {
         encryptor = &rijndael_encryptBlock128;
     }
     while (inputLen > 0) {
         (*encryptor)(cx, output, input);
         output += AES_BLOCK_SIZE;
         input += AES_BLOCK_SIZE;
         inputLen -= AES_BLOCK_SIZE;
@@ -1095,32 +887,23 @@ aes_InitContext(AESContext *cx, const un
         return SECFailure;
     }
 #ifdef USE_HW_AES
     if (use_hw_aes) {
         intel_aes_init(encrypt, keysize);
     } else
 #endif
     {
-
-#if defined(RIJNDAEL_GENERATE_TABLES) || \
-    defined(RIJNDAEL_GENERATE_TABLES_MACRO)
-        if (rijndaelTables == NULL) {
-            if (PR_CallOnce(&coRTInit, init_rijndael_tables) != PR_SUCCESS) {
-                return SECFailure;
-            }
-        }
-#endif
         /* Generate expanded key */
         if (encrypt) {
             if (use_hw_aes && (cx->mode == NSS_AES_GCM || cx->mode == NSS_AES ||
                                cx->mode == NSS_AES_CTR)) {
                 PORT_Assert(keysize == 16 || keysize == 24 || keysize == 32);
                 /* Prepare hardware key for normal AES parameters. */
-                native_key_expansion(cx, key, Nk);
+                rijndael_native_key_expansion(cx, key, Nk);
             } else {
                 rijndael_key_expansion(cx, key, Nk);
             }
         } else {
             rijndael_invkey_expansion(cx, key, Nk);
         }
     }
     cx->worker_cx = cx;
--- a/security/nss/lib/freebl/rijndael.h
+++ b/security/nss/lib/freebl/rijndael.h
@@ -3,18 +3,32 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef _RIJNDAEL_H_
 #define _RIJNDAEL_H_ 1
 
 #include "blapii.h"
 #include <stdint.h>
 
-#ifdef NSS_X86_OR_X64
-#include <wmmintrin.h> /* aes-ni */
+#if defined(NSS_X86_OR_X64)
+/* GCC <= 4.8 doesn't support including emmintrin.h without enabling SSE2 */
+#if !defined(__clang__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && \
+    (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
+#pragma GCC push_options
+#pragma GCC target("sse2")
+#undef NSS_DISABLE_SSE2
+#define NSS_DISABLE_SSE2 1
+#endif /* GCC <= 4.8 */
+
+#include <emmintrin.h> /* __m128i */
+
+#ifdef NSS_DISABLE_SSE2
+#undef NSS_DISABLE_SSE2
+#pragma GCC pop_options
+#endif /* NSS_DISABLE_SSE2 */
 #endif
 
 typedef void AESBlockFunc(AESContext *cx,
                           unsigned char *output,
                           const unsigned char *input);
 
 /* RIJNDAEL_NUM_ROUNDS
  *
--- 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.33" _NSS_CUSTOMIZED
+#define NSS_VERSION "3.34" _NSS_CUSTOMIZED " Beta"
 #define NSS_VMAJOR 3
-#define NSS_VMINOR 33
+#define NSS_VMINOR 34
 #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;
 
 /*
@@ -286,16 +286,25 @@ SECStatus NSS_UnregisterShutdown(NSS_Shu
 #define NSS_RSA_MIN_KEY_SIZE 0x001
 #define NSS_DH_MIN_KEY_SIZE 0x002
 #define NSS_DSA_MIN_KEY_SIZE 0x004
 #define NSS_TLS_VERSION_MIN_POLICY 0x008
 #define NSS_TLS_VERSION_MAX_POLICY 0x009
 #define NSS_DTLS_VERSION_MIN_POLICY 0x00a
 #define NSS_DTLS_VERSION_MAX_POLICY 0x00b
 
+/* Until NSS 3.30, the PKCS#12 implementation used BMPString encoding
+ * for all passwords.  This changed to use UTF-8 for non-PKCS#12 PBEs
+ * in NSS 3.31.
+ *
+ * For backward compatibility, this option reverts the behavior to the
+ * old NSS versions.  This option might be removed in the future NSS
+ * releases; don't rely on it. */
+#define __NSS_PKCS12_DECODE_FORCE_UNICODE 0x00c
+
 /*
  * Set and get global options for the NSS library.
  */
 SECStatus NSS_OptionSet(PRInt32 which, PRInt32 value);
 SECStatus NSS_OptionGet(PRInt32 which, PRInt32 *value);
 
 /*
  * Close the Cert, Key databases.
--- a/security/nss/lib/nss/nssoptions.c
+++ b/security/nss/lib/nss/nssoptions.c
@@ -18,26 +18,28 @@
 struct nssOps {
     PRInt32 rsaMinKeySize;
     PRInt32 dhMinKeySize;
     PRInt32 dsaMinKeySize;
     PRInt32 tlsVersionMinPolicy;
     PRInt32 tlsVersionMaxPolicy;
     PRInt32 dtlsVersionMinPolicy;
     PRInt32 dtlsVersionMaxPolicy;
+    PRInt32 pkcs12DecodeForceUnicode;
 };
 
 static struct nssOps nss_ops = {
     SSL_RSA_MIN_MODULUS_BITS,
     SSL_DH_MIN_P_BITS,
     SSL_DSA_MIN_P_BITS,
     1,      /* Set TLS min to less the the smallest legal SSL value */
     0xffff, /* set TLS max to more than the largest legal SSL value */
     1,
     0xffff,
+    PR_FALSE
 };
 
 SECStatus
 NSS_OptionSet(PRInt32 which, PRInt32 value)
 {
     SECStatus rv = SECSuccess;
 
     switch (which) {
@@ -57,16 +59,19 @@ NSS_OptionSet(PRInt32 which, PRInt32 val
             nss_ops.tlsVersionMaxPolicy = value;
             break;
         case NSS_DTLS_VERSION_MIN_POLICY:
             nss_ops.dtlsVersionMinPolicy = value;
             break;
         case NSS_DTLS_VERSION_MAX_POLICY:
             nss_ops.dtlsVersionMaxPolicy = value;
             break;
+        case __NSS_PKCS12_DECODE_FORCE_UNICODE:
+            nss_ops.pkcs12DecodeForceUnicode = value;
+            break;
         default:
             rv = SECFailure;
     }
 
     return rv;
 }
 
 SECStatus
@@ -91,14 +96,17 @@ NSS_OptionGet(PRInt32 which, PRInt32 *va
             *value = nss_ops.tlsVersionMaxPolicy;
             break;
         case NSS_DTLS_VERSION_MIN_POLICY:
             *value = nss_ops.dtlsVersionMinPolicy;
             break;
         case NSS_DTLS_VERSION_MAX_POLICY:
             *value = nss_ops.dtlsVersionMaxPolicy;
             break;
+        case __NSS_PKCS12_DECODE_FORCE_UNICODE:
+            *value = nss_ops.pkcs12DecodeForceUnicode;
+            break;
         default:
             rv = SECFailure;
     }
 
     return rv;
 }
--- a/security/nss/lib/pk11wrap/pk11obj.c
+++ b/security/nss/lib/pk11wrap/pk11obj.c
@@ -196,17 +196,16 @@ PK11_HasAttributeSet(PK11SlotInfo *slot,
 CK_RV
 PK11_GetAttributes(PLArenaPool *arena, PK11SlotInfo *slot,
                    CK_OBJECT_HANDLE obj, CK_ATTRIBUTE *attr, int count)
 {
     int i;
     /* make pedantic happy... note that it's only used arena != NULL */
     void *mark = NULL;
     CK_RV crv;
-    PORT_Assert(slot->session != CK_INVALID_SESSION);
     if (slot->session == CK_INVALID_SESSION)
         return CKR_SESSION_HANDLE_INVALID;
 
     /*
      * first get all the lengths of the parameters.
      */
     PK11_EnterSlotMonitor(slot);
     crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session, obj, attr, count);
--- a/security/nss/lib/pkcs12/p12d.c
+++ b/security/nss/lib/pkcs12/p12d.c
@@ -1,13 +1,14 @@
 /* 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 "nssrenam.h"
+#include "nss.h"
 #include "p12t.h"
 #include "p12.h"
 #include "plarena.h"
 #include "secitem.h"
 #include "secoid.h"
 #include "seccomon.h"
 #include "secport.h"
 #include "cert.h"
@@ -121,16 +122,17 @@ struct SEC_PKCS12DecoderContextStr {
     digestIOFn dRead, dWrite;
     void *dArg;
     PRBool dIsOpen; /* is the temp file created? */
 
     /* helper functions */
     SECKEYGetPasswordKey pwfn;
     void *pwfnarg;
     PRBool swapUnicodeBytes;
+    PRBool forceUnicode;
 
     /* import information */
     PRBool bagsVerified;
 
     /* buffer management for the default callbacks implementation */
     void *buffer;       /* storage area */
     PRInt32 filesize;   /* actual data size */
     PRInt32 allocated;  /* total buffer size allocated */
@@ -187,18 +189,28 @@ sec_pkcs12_decoder_get_decrypt_key(void 
     /* if no slot specified, use the internal key slot */
     if (p12dcx->slot) {
         slot = PK11_ReferenceSlot(p12dcx->slot);
     } else {
         slot = PK11_GetInternalKeySlot();
     }
 
     algorithm = SECOID_GetAlgorithmTag(algid);
-    if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm, p12dcx->pwitem))
-        return NULL;
+
+    if (p12dcx->forceUnicode) {
+        if (SECITEM_CopyItem(NULL, &pwitem, p12dcx->pwitem) != SECSuccess) {
+            PK11_FreeSlot(slot);
+            return NULL;
+        }
+    } else {
+        if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm, p12dcx->pwitem)) {
+            PK11_FreeSlot(slot);
+            return NULL;
+        }
+    }
 
     bulkKey = PK11_PBEKeyGen(slot, algid, &pwitem, PR_FALSE, p12dcx->wincx);
     /* some tokens can't generate PBE keys on their own, generate the
      * key in the internal slot, and let the Import code deal with it,
      * (if the slot can't generate PBEs, then we need to use the internal
      * slot anyway to unwrap). */
     if (!bulkKey && !PK11_IsInternal(slot)) {
         PK11_FreeSlot(slot);
@@ -1159,16 +1171,18 @@ p12u_DigestWrite(void *arg, unsigned cha
  */
 SEC_PKCS12DecoderContext *
 SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx,
                        digestOpenFn dOpen, digestCloseFn dClose,
                        digestIOFn dRead, digestIOFn dWrite, void *dArg)
 {
     SEC_PKCS12DecoderContext *p12dcx;
     PLArenaPool *arena;
+    PRInt32 forceUnicode = PR_FALSE;
+    SECStatus rv;
 
     arena = PORT_NewArena(2048); /* different size? */
     if (!arena) {
         return NULL; /* error is already set */
     }
 
     /* allocate the decoder context and set the state variables */
     p12dcx = PORT_ArenaZNew(arena, SEC_PKCS12DecoderContext);
@@ -1191,16 +1205,21 @@ SEC_PKCS12DecoderStart(SECItem *pwitem, 
                          : PK11_GetInternalKeySlot());
     p12dcx->wincx = wincx;
     p12dcx->tokenCAs = SECPKCS12TargetTokenNoCAs;
 #ifdef IS_LITTLE_ENDIAN
     p12dcx->swapUnicodeBytes = PR_TRUE;
 #else
     p12dcx->swapUnicodeBytes = PR_FALSE;
 #endif
+    rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode);
+    if (rv != SECSuccess) {
+        goto loser;
+    }
+    p12dcx->forceUnicode = forceUnicode;
     p12dcx->errorValue = 0;
     p12dcx->error = PR_FALSE;
 
     /* start the decoding of the PFX and set the notify proc
      * for the PFX item.
      */
     p12dcx->pfxA1Dcx = SEC_ASN1DecoderStart(p12dcx->arena, &p12dcx->pfx,
                                             sec_PKCS12PFXItemTemplate);
@@ -2423,17 +2442,17 @@ sec_pkcs12_add_cert(sec_PKCS12SafeBag *c
 }
 
 static SECItem *
 sec_pkcs12_get_public_value_and_type(SECKEYPublicKey *pubKey, KeyType *type);
 
 static SECStatus
 sec_pkcs12_add_key(sec_PKCS12SafeBag *key, SECKEYPublicKey *pubKey,
                    unsigned int keyUsage,
-                   SECItem *nickName, void *wincx)
+                   SECItem *nickName, PRBool forceUnicode, void *wincx)
 {
     SECStatus rv;
     SECItem *publicValue = NULL;
     KeyType keyType;
 
     /* We should always have values for "key" and "pubKey"
        so they can be dereferenced later. */
     if (!key || !pubKey) {
@@ -2461,19 +2480,31 @@ sec_pkcs12_add_key(sec_PKCS12SafeBag *ke
                                            keyUsage, wincx);
             break;
         case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: {
             SECItem pwitem = { 0 };
             SECAlgorithmID *algid =
                 &key->safeBagContent.pkcs8ShroudedKeyBag->algorithm;
             SECOidTag algorithm = SECOID_GetAlgorithmTag(algid);
 
-            if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm,
-                                            key->pwitem))
-                return SECFailure;
+            if (forceUnicode) {
+                if (SECITEM_CopyItem(NULL, &pwitem, key->pwitem) != SECSuccess) {
+                    key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
+                    key->problem = PR_TRUE;
+                    return SECFailure;
+                }
+            } else {
+                if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm,
+                                                key->pwitem)) {
+                    key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
+                    key->problem = PR_TRUE;
+                    return SECFailure;
+                }
+            }
+
             rv = PK11_ImportEncryptedPrivateKeyInfo(key->slot,
                                                     key->safeBagContent.pkcs8ShroudedKeyBag,
                                                     &pwitem, nickName, publicValue,
                                                     PR_TRUE, PR_TRUE, keyType, keyUsage,
                                                     wincx);
             if (pwitem.data) {
                 SECITEM_ZfreeItem(&pwitem, PR_FALSE);
             }
@@ -2918,17 +2949,18 @@ sec_pkcs12_get_public_value_and_type(SEC
     return pubValue;
 }
 
 /* This function takes two passes over the bags, installing them in the
  * desired slot.  The two passes are intended to mirror exactly the
  * two passes in sec_pkcs12_validate_bags.
  */
 static SECStatus
-sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, void *wincx)
+sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, PRBool forceUnicode,
+                        void *wincx)
 {
     sec_PKCS12SafeBag **keyList;
     int i;
     int failedKeys = 0;
 
     if (!safeBags) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
@@ -2971,17 +3003,18 @@ sec_pkcs12_install_bags(sec_PKCS12SafeBa
                 key->error = SEC_ERROR_BAD_NICKNAME;
                 key->problem = PR_TRUE;
                 rv = SECFailure;
             } else if (!pubKey) {
                 key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
                 key->problem = PR_TRUE;
                 rv = SECFailure;
             } else {
-                rv = sec_pkcs12_add_key(key, pubKey, keyUsage, nickName, wincx);
+                rv = sec_pkcs12_add_key(key, pubKey, keyUsage, nickName,
+                                        forceUnicode, wincx);
             }
             if (pubKey) {
                 SECKEY_DestroyPublicKey(pubKey);
                 pubKey = NULL;
             }
             if (nickName) {
                 SECITEM_FreeItem(nickName, PR_TRUE);
                 nickName = NULL;
@@ -3048,26 +3081,38 @@ sec_pkcs12_install_bags(sec_PKCS12SafeBa
     }
 
     return SECSuccess;
 }
 
 SECStatus
 SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx)
 {
+    PRBool forceUnicode = PR_FALSE;
+    SECStatus rv;
+
     if (!p12dcx || p12dcx->error) {
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return SECFailure;
     }
 
     if (!p12dcx->bagsVerified) {
         return SECFailure;
     }
 
-    return sec_pkcs12_install_bags(p12dcx->safeBags, p12dcx->wincx);
+    /* We need to check the option here as well as in
+     * SEC_PKCS12DecoderStart, because different PBE's could be used
+     * for PKCS #7 and PKCS #8 */
+    rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode);
+    if (rv != SECSuccess) {
+        return SECFailure;
+    }
+
+    return sec_pkcs12_install_bags(p12dcx->safeBags, forceUnicode,
+                                   p12dcx->wincx);
 }
 
 PRBool
 sec_pkcs12_bagHasKey(SEC_PKCS12DecoderContext *p12dcx, sec_PKCS12SafeBag *bag)
 {
     int i;
     SECItem *keyId;
     SECItem *certKeyId;
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -12,16 +12,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.33" SOFTOKEN_ECC_STRING
+#define SOFTOKEN_VERSION "3.34" SOFTOKEN_ECC_STRING " Beta"
 #define SOFTOKEN_VMAJOR 3
-#define SOFTOKEN_VMINOR 33
+#define SOFTOKEN_VMINOR 34
 #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/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -6049,45 +6049,24 @@ ssl3_SendRSAClientKeyExchange(sslSocket 
 
     /* wrap pre-master secret in server's public key. */
     rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, pms, &enc_pms);
     if (rv != SECSuccess) {
         ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
         goto loser;
     }
 
-#ifdef NSS_ALLOW_SSLKEYLOGFILE
-    if (ssl_keylog_iob) {
+#ifdef TRACE
+    if (ssl_trace >= 100) {
         SECStatus extractRV = PK11_ExtractKeyValue(pms);
         if (extractRV == SECSuccess) {
             SECItem *keyData = PK11_GetKeyData(pms);
             if (keyData && keyData->data && keyData->len) {
-#ifdef TRACE
-                if (ssl_trace >= 100) {
-                    ssl_PrintBuf(ss, "Pre-Master Secret",
-                                 keyData->data, keyData->len);
-                }
-#endif
-                if (ssl_keylog_iob && enc_pms.len >= 8 && keyData->len == 48) {
-                    /* https://developer.mozilla.org/en/NSS_Key_Log_Format */
-
-                    /* There could be multiple, concurrent writers to the
-                     * keylog, so we have to do everything in a single call to
-                     * fwrite. */
-                    char buf[4 + 8 * 2 + 1 + 48 * 2 + 1];
-
-                    strcpy(buf, "RSA ");
-                    hexEncode(buf + 4, enc_pms.data, 8);
-                    buf[20] = ' ';
-                    hexEncode(buf + 21, keyData->data, 48);
-                    buf[sizeof(buf) - 1] = '\n';
-
-                    fwrite(buf, sizeof(buf), 1, ssl_keylog_iob);
-                    fflush(ssl_keylog_iob);
-                }
+                ssl_PrintBuf(ss, "Pre-Master Secret",
+                             keyData->data, keyData->len);
             }
         }
     }
 #endif
 
     rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
                                     isTLS ? enc_pms.len + 2
                                           : enc_pms.len);
@@ -6925,16 +6904,18 @@ ssl3_HandleServerHelloPart2(sslSocket *s
                 errCode = SSL_ERROR_MISSING_EXTENDED_MASTER_SECRET;
                 goto alert_loser;
             }
 
             ss->sec.authType = sid->authType;
             ss->sec.authKeyBits = sid->authKeyBits;
             ss->sec.keaType = sid->keaType;
             ss->sec.keaKeyBits = sid->keaKeyBits;
+            ss->sec.originalKeaGroup = ssl_LookupNamedGroup(sid->keaGroup);
+            ss->sec.signatureScheme = sid->sigScheme;
 
             if (sid->u.ssl3.keys.msIsWrapped) {
                 PK11SlotInfo *slot;
                 PK11SymKey *wrapKey; /* wrapping key */
                 CK_FLAGS keyFlags = 0;
 
                 /* unwrap master secret */
                 slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
@@ -7935,16 +7916,17 @@ ssl3_NewSessionID(sslSocket *ss, PRBool 
     }
     sid->peerID = (ss->peerID == NULL) ? NULL : PORT_Strdup(ss->peerID);
     sid->urlSvrName = (ss->url == NULL) ? NULL : PORT_Strdup(ss->url);
     sid->addr = ss->sec.ci.peer;
     sid->port = ss->sec.ci.port;
     sid->references = 1;
     sid->cached = never_cached;
     sid->version = ss->version;
+    sid->sigScheme = ssl_sig_none;
 
     sid->u.ssl3.keys.resumable = PR_TRUE;
     sid->u.ssl3.policy = SSL_ALLOWED;
     sid->u.ssl3.clientWriteKey = NULL;
     sid->u.ssl3.serverWriteKey = NULL;
     sid->u.ssl3.keys.extendedMasterSecretUsed = PR_FALSE;
 
     if (is_server) {
@@ -8908,16 +8890,18 @@ compression_found:
             if (ss->statelessResume)
                 SSL_AtomicIncrementLong(&ssl3stats.hch_sid_stateless_resumes);
             ss->ssl3.hs.isResuming = PR_TRUE;
 
             ss->sec.authType = sid->authType;
             ss->sec.authKeyBits = sid->authKeyBits;
             ss->sec.keaType = sid->keaType;
             ss->sec.keaKeyBits = sid->keaKeyBits;
+            ss->sec.originalKeaGroup = ssl_LookupNamedGroup(sid->keaGroup);
+            ss->sec.signatureScheme = sid->sigScheme;
 
             ss->sec.localCert =
                 CERT_DupCertificate(ss->sec.serverCert->serverCert);
 
             /* Copy cached name in to pending spec */
             if (sid != NULL &&
                 sid->version > SSL_LIBRARY_VERSION_3_0 &&
                 sid->u.ssl3.srvName.len && sid->u.ssl3.srvName.data) {
@@ -8979,16 +8963,17 @@ compression_found:
         } while (0);
 
     if (haveSpecWriteLock) {
         ssl_ReleaseSpecWriteLock(ss);
         haveSpecWriteLock = PR_FALSE;
     }
 
     if (sid) { /* we had a sid, but it's no longer valid, free it */
+        ss->statelessResume = PR_FALSE;
         SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok);
         ss->sec.uncache(sid);
         ssl_FreeSID(sid);
         sid = NULL;
     }
     SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_misses);
 
     /* We only send a session ticket extension if the client supports
@@ -11155,74 +11140,77 @@ ssl3_SendNextProto(sslSocket *ss)
     }
     rv = ssl3_AppendHandshakeVariable(ss, padding, padding_len, 1);
     if (rv != SECSuccess) {
         return rv; /* error code set by AppendHandshake */
     }
     return rv;
 }
 
-/* called from ssl3_SendFinished
+/* called from ssl3_SendFinished and tls13_DeriveSecret.
  *
  * This function is simply a debugging aid and therefore does not return a
  * SECStatus. */
-static void
-ssl3_RecordKeyLog(sslSocket *ss)
+void
+ssl3_RecordKeyLog(sslSocket *ss, const char *label, PK11SymKey *secret)
 {
 #ifdef NSS_ALLOW_SSLKEYLOGFILE
     SECStatus rv;
     SECItem *keyData;
-    char buf[14 /* "CLIENT_RANDOM " */ +
-             SSL3_RANDOM_LENGTH * 2 /* client_random */ +
-             1 /* " " */ +
-             48 * 2 /* master secret */ +
-             1 /* new line */];
-    unsigned int j;
+    /* Longest label is "CLIENT_HANDSHAKE_TRAFFIC_SECRET", master secret is 48
+     * bytes which happens to be the largest in TLS 1.3 as well (SHA384).
+     * Maximum line length: "CLIENT_HANDSHAKE_TRAFFIC_SECRET" (31) + " " (1) +
+     * client_random (32*2) + " " (1) +
+     * traffic_secret (48*2) + "\n" (1) = 194. */
+    char buf[200];
+    unsigned int offset, len;
 
     PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
 
     if (!ssl_keylog_iob)
         return;
 
-    rv = PK11_ExtractKeyValue(ss->ssl3.cwSpec->master_secret);
+    rv = PK11_ExtractKeyValue(secret);
     if (rv != SECSuccess)
         return;
 
-    ssl_GetSpecReadLock(ss);
-
     /* keyData does not need to be freed. */
-    keyData = PK11_GetKeyData(ss->ssl3.cwSpec->master_secret);
-    if (!keyData || !keyData->data || keyData->len != 48) {
-        ssl_ReleaseSpecReadLock(ss);
+    keyData = PK11_GetKeyData(secret);
+    if (!keyData || !keyData->data)
         return;
-    }
+
+    len = strlen(label) + 1 +          /* label + space */
+          SSL3_RANDOM_LENGTH * 2 + 1 + /* client random (hex) + space */
+          keyData->len * 2 + 1;        /* secret (hex) + newline */
+    PORT_Assert(len <= sizeof(buf));
+    if (len > sizeof(buf))
+        return;
 
     /* https://developer.mozilla.org/en/NSS_Key_Log_Format */
 
     /* There could be multiple, concurrent writers to the
      * keylog, so we have to do everything in a single call to
      * fwrite. */
 
-    memcpy(buf, "CLIENT_RANDOM ", 14);
-    j = 14;
-    hexEncode(buf + j, ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
-    j += SSL3_RANDOM_LENGTH * 2;
-    buf[j++] = ' ';
-    hexEncode(buf + j, keyData->data, 48);
-    j += 48 * 2;
-    buf[j++] = '\n';
-
-    PORT_Assert(j == sizeof(buf));
-
-    ssl_ReleaseSpecReadLock(ss);
-
-    if (fwrite(buf, sizeof(buf), 1, ssl_keylog_iob) != 1)
-        return;
-    fflush(ssl_keylog_iob);
-    return;
+    strcpy(buf, label);
+    offset = strlen(label);
+    buf[offset++] += ' ';
+    hexEncode(buf + offset, ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
+    offset += SSL3_RANDOM_LENGTH * 2;
+    buf[offset++] = ' ';
+    hexEncode(buf + offset, keyData->data, keyData->len);
+    offset += keyData->len * 2;
+    buf[offset++] = '\n';
+
+    PORT_Assert(offset == len);
+
+    PZ_Lock(ssl_keylog_lock);
+    if (fwrite(buf, len, 1, ssl_keylog_iob) == 1)
+        fflush(ssl_keylog_iob);
+    PZ_Unlock(ssl_keylog_lock);
 #endif
 }
 
 /* called from ssl3_SendClientSecondRound
  *             ssl3_HandleClientHello
  *             ssl3_HandleFinished
  */
 static SECStatus
@@ -11279,17 +11267,17 @@ ssl3_SendFinished(sslSocket *ss, PRInt32
         if (rv != SECSuccess)
             goto fail; /* err set by AppendHandshake. */
     }
     rv = ssl3_FlushHandshake(ss, flags);
     if (rv != SECSuccess) {
         goto fail; /* error code set by ssl3_FlushHandshake */
     }
 
-    ssl3_RecordKeyLog(ss);
+    ssl3_RecordKeyLog(ss, "CLIENT_RANDOM", ss->ssl3.cwSpec->master_secret);
 
     return SECSuccess;
 
 fail:
     return rv;
 }
 
 /* wrap the master secret, and put it into the SID.
@@ -11549,16 +11537,22 @@ ssl3_FillInCachedSID(sslSocket *ss, sslS
     sid->u.ssl3.cipherSuite = ss->ssl3.hs.cipher_suite;
     sid->u.ssl3.compression = ss->ssl3.hs.compression;
     sid->u.ssl3.policy = ss->ssl3.policy;
     sid->version = ss->version;
     sid->authType = ss->sec.authType;
     sid->authKeyBits = ss->sec.authKeyBits;
     sid->keaType = ss->sec.keaType;
     sid->keaKeyBits = ss->sec.keaKeyBits;
+    if (ss->sec.keaGroup) {
+        sid->keaGroup = ss->sec.keaGroup->name;
+    } else {
+        sid->keaGroup = ssl_grp_none;
+    }
+    sid->sigScheme = ss->sec.signatureScheme;
     sid->lastAccessTime = sid->creationTime = ssl_Time();
     sid->expirationTime = sid->creationTime + ssl3_sid_timeout;
     sid->localCert = CERT_DupCertificate(ss->sec.localCert);
     if (ss->sec.isServer) {
         sid->namedCurve = ss->sec.serverCert->namedCurve;
     }
 
     if (ss->xtnData.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT &&
--- a/security/nss/lib/ssl/ssl3exthandle.c
+++ b/security/nss/lib/ssl/ssl3exthandle.c
@@ -797,17 +797,17 @@ ssl3_ClientHandleStatusRequestXtn(const 
     }
 
     /* Keep track of negotiated extensions. */
     xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
     return SECSuccess;
 }
 
 PRUint32 ssl_ticket_lifetime = 2 * 24 * 60 * 60; /* 2 days in seconds */
-#define TLS_EX_SESS_TICKET_VERSION (0x0105)
+#define TLS_EX_SESS_TICKET_VERSION (0x0106)
 
 /*
  * Called from ssl3_SendNewSessionTicket, tls13_SendNewSessionTicket
  */
 SECStatus
 ssl3_EncodeSessionTicket(sslSocket *ss,
                          const NewSessionTicket *ticket,
                          SECItem *ticket_data)
@@ -877,16 +877,17 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
     alpnSelection = &ss->xtnData.nextProto;
 
     plaintext_length =
         sizeof(PRUint16)                       /* ticket version */
         + sizeof(SSL3ProtocolVersion)          /* ssl_version */
         + sizeof(ssl3CipherSuite)              /* ciphersuite */
         + 1                                    /* compression */
         + 10                                   /* cipher spec parameters */
+        + 8                                    /* kea group and sig scheme */
         + 1                                    /* certType arguments */
         + 1                                    /* SessionTicket.ms_is_wrapped */
         + 4                                    /* msWrapMech */
         + 2                                    /* master_secret.length */
         + ms_item.len                          /* master_secret */
         + 1                                    /* client_auth_type */
         + cert_length                          /* cert */
         + 2 + srvName->len                     /* name len + length field */
@@ -932,16 +933,29 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
     if (rv != SECSuccess)
         goto loser;
     rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaType, 1);
     if (rv != SECSuccess)
         goto loser;
     rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaKeyBits, 4);
     if (rv != SECSuccess)
         goto loser;
+    if (ss->sec.keaGroup) {
+        rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaGroup->name, 4);
+        if (rv != SECSuccess)
+            goto loser;
+    } else {
+        /* No kea group. Write 0 as invalid value. */
+        rv = ssl3_AppendNumberToItem(&plaintext, 0, 4);
+        if (rv != SECSuccess)
+            goto loser;
+    }
+    rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.signatureScheme, 4);
+    if (rv != SECSuccess)
+        goto loser;
 
     /* certificate type */
     PORT_Assert(SSL_CERT_IS(ss->sec.serverCert, ss->sec.authType));
     if (SSL_CERT_IS_EC(ss->sec.serverCert)) {
         const sslServerCert *cert = ss->sec.serverCert;
         PORT_Assert(cert->namedCurve);
         /* EC curves only use the second of the two bytes. */
         PORT_Assert(cert->namedCurve->name < 256);
@@ -1160,16 +1174,28 @@ ssl_ParseSessionTicket(sslSocket *ss, co
     }
     parsedTicket->keaType = (SSLKEAType)temp;
     rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 4, &buffer, &len);
     if (rv != SECSuccess) {
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
     parsedTicket->keaKeyBits = temp;
+    rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 4, &buffer, &len);
+    if (rv != SECSuccess) {
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return SECFailure;
+    }
+    parsedTicket->originalKeaGroup = temp;
+    rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 4, &buffer, &len);
+    if (rv != SECSuccess) {
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return SECFailure;
+    }
+    parsedTicket->signatureScheme = (SSLSignatureScheme)temp;
 
     /* Read the optional named curve. */
     rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 1, &buffer, &len);
     if (rv != SECSuccess) {
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
     if (parsedTicket->authType == ssl_auth_ecdsa ||
@@ -1314,17 +1340,19 @@ ssl_CreateSIDFromTicket(sslSocket *ss, c
     /* Copy over parameters. */
     sid->version = parsedTicket->ssl_version;
     sid->u.ssl3.cipherSuite = parsedTicket->cipher_suite;
     sid->u.ssl3.compression = parsedTicket->compression_method;
     sid->authType = parsedTicket->authType;
     sid->authKeyBits = parsedTicket->authKeyBits;
     sid->keaType = parsedTicket->keaType;
     sid->keaKeyBits = parsedTicket->keaKeyBits;
+    sid->keaGroup = parsedTicket->originalKeaGroup;
     sid->namedCurve = parsedTicket->namedCurve;
+    sid->sigScheme = parsedTicket->signatureScheme;
 
     rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.locked.sessionTicket.ticket,
                           rawTicket);
     if (rv != SECSuccess) {
         goto loser;
     }
     sid->u.ssl3.locked.sessionTicket.flags = parsedTicket->flags;
     sid->u.ssl3.locked.sessionTicket.max_early_data_size =
--- a/security/nss/lib/ssl/sslimpl.h
+++ b/security/nss/lib/ssl/sslimpl.h
@@ -548,16 +548,18 @@ struct sslSessionIDStr {
 
     PRUint32 creationTime;   /* seconds since Jan 1, 1970 */
     PRUint32 expirationTime; /* seconds since Jan 1, 1970 */
 
     SSLAuthType authType;
     PRUint32 authKeyBits;
     SSLKEAType keaType;
     PRUint32 keaKeyBits;
+    SSLNamedGroup keaGroup;
+    SSLSignatureScheme sigScheme;
 
     union {
         struct {
             /* values that are copied into the server's on-disk SID cache. */
             PRUint8 sessionIDLength;
             PRUint8 sessionID[SSL3_SESSIONID_BYTES];
 
             ssl3CipherSuite cipherSuite;
@@ -997,16 +999,18 @@ typedef struct SessionTicketStr {
     PRBool valid;
     SSL3ProtocolVersion ssl_version;
     ssl3CipherSuite cipher_suite;
     SSLCompressionMethod compression_method;
     SSLAuthType authType;
     PRUint32 authKeyBits;
     SSLKEAType keaType;
     PRUint32 keaKeyBits;
+    SSLNamedGroup originalKeaGroup;
+    SSLSignatureScheme signatureScheme;
     const sslNamedGroupDef *namedCurve; /* For certificate lookup. */
 
     /*
      * msWrapMech contains a meaningful value only if ms_is_wrapped is true.
      */
     PRUint8 ms_is_wrapped;
     CK_MECHANISM_TYPE msWrapMech;
     PRUint16 ms_length;
@@ -1063,16 +1067,17 @@ struct sslSecurityInfoStr {
     SECKEYPublicKey *peerKey;
 
     SSLAuthType authType;
     PRUint32 authKeyBits;
     SSLSignatureScheme signatureScheme;
     SSLKEAType keaType;
     PRUint32 keaKeyBits;
     const sslNamedGroupDef *keaGroup;
+    const sslNamedGroupDef *originalKeaGroup;
     /* The selected certificate (for servers only). */
     const sslServerCert *serverCert;
 
     /*
     ** Procs used for SID cache (nonce) management.
     ** Different implementations exist for clients/servers
     ** The lookup proc is only used for servers.  Baloney!
     */
@@ -1238,16 +1243,17 @@ struct sslSelfEncryptKeysStr {
     PK11SymKey *macKey;
 };
 typedef struct sslSelfEncryptKeysStr sslSelfEncryptKeys;
 
 extern char ssl_debug;
 extern char ssl_trace;
 extern FILE *ssl_trace_iob;
 extern FILE *ssl_keylog_iob;
+extern PZLock *ssl_keylog_lock;
 extern PRUint32 ssl3_sid_timeout;
 extern PRUint32 ssl_ticket_lifetime;
 extern PRUint32 ssl_max_early_data_size;
 
 extern const char *const ssl3_cipherName[];
 
 extern sslSessionIDLookupFunc ssl_sid_lookup;
 extern sslSessionIDCacheFunc ssl_sid_cache;
@@ -1874,16 +1880,19 @@ extern HASH_HashType
 ssl3_GetTls12HashType(sslSocket *ss);
 
 extern SECStatus
 ssl3_TLSPRFWithMasterSecret(sslSocket *ss, ssl3CipherSpec *spec,
                             const char *label, unsigned int labelLen,
                             const unsigned char *val, unsigned int valLen,
                             unsigned char *out, unsigned int outLen);
 
+extern void
+ssl3_RecordKeyLog(sslSocket *ss, const char *label, PK11SymKey *secret);
+
 PRBool ssl_AlpnTagAllowed(const sslSocket *ss, const SECItem *tag);
 
 #ifdef TRACE
 #define SSL_TRACE(msg) ssl_Trace msg
 #else
 #define SSL_TRACE(msg)
 #endif
 
--- a/security/nss/lib/ssl/sslinfo.c
+++ b/security/nss/lib/ssl/sslinfo.c
@@ -73,21 +73,32 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLCh
             if (rv != SECSuccess) {
                 return SECFailure; /* Error code already set. */
             }
             inf.symCipher = cinfo.symCipher;
             inf.macAlgorithm = cinfo.macAlgorithm;
             /* Get these fromm |ss->sec| because that is accurate
              * even with TLS 1.3 disaggregated cipher suites. */
             inf.keaType = ss->sec.keaType;
-            inf.keaGroup = ss->sec.keaGroup ? ss->sec.keaGroup->name : ssl_grp_none;
+            inf.originalKeaGroup = ss->sec.originalKeaGroup
+                                       ? ss->sec.originalKeaGroup->name
+                                       : ssl_grp_none;
+            inf.keaGroup = ss->sec.keaGroup
+                               ? ss->sec.keaGroup->name
+                               : ssl_grp_none;
             inf.keaKeyBits = ss->sec.keaKeyBits;
             inf.authType = ss->sec.authType;
             inf.authKeyBits = ss->sec.authKeyBits;
             inf.signatureScheme = ss->sec.signatureScheme;
+            /* If this is a resumed session, signatureScheme isn't set in ss->sec.
+             * Use the signature scheme from the previous handshake. */
+            if (inf.signatureScheme == ssl_sig_none && sid->sigScheme) {
+                inf.signatureScheme = sid->sigScheme;
+            }
+            inf.resumed = ss->statelessResume || ss->ssl3.hs.isResuming;
         }
         if (sid) {
             unsigned int sidLen;
 
             inf.creationTime = sid->creationTime;
             inf.lastAccessTime = sid->lastAccessTime;
             inf.expirationTime = sid->expirationTime;
             inf.extendedMasterSecretUsed =
--- a/security/nss/lib/ssl/sslsnce.c
+++ b/security/nss/lib/ssl/sslsnce.c
@@ -93,17 +93,19 @@ struct sidCacheEntryStr {
     /*  2 */ PRUint16 version;
     /*  1 */ PRUint8 valid;
     /*  1 */ PRUint8 sessionIDLength;
     /* 32 */ PRUint8 sessionID[SSL3_SESSIONID_BYTES];
     /*  2 */ PRUint16 authType;
     /*  2 */ PRUint16 authKeyBits;
     /*  2 */ PRUint16 keaType;
     /*  2 */ PRUint16 keaKeyBits;
-    /* 72  - common header total */
+    /*  4 */ PRUint32 signatureScheme;
+    /*  4 */ PRUint32 keaGroup;
+    /* 80  - common header total */
 
     union {
         struct {
             /*  2 */ ssl3CipherSuite cipherSuite;
             /*  2 */ PRUint16 compression; /* SSLCompressionMethod */
 
             /* 54 */ ssl3SidKeys keys; /* keys, wrapped as needed. */
 
@@ -111,17 +113,17 @@ struct sidCacheEntryStr {
             /*  4 */ PRInt32 certIndex;
             /*  4 */ PRInt32 srvNameIndex;
             /* 32 */ PRUint8 srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */
             /*  2 */ PRUint16 namedCurve;
 /*104 */} ssl3;
 
 /* force sizeof(sidCacheEntry) to be a multiple of cache line size */
 struct {
-    /*120 */ PRUint8 filler[120]; /* 72+120==192, a multiple of 16 */
+    /*112 */ PRUint8 filler[112]; /* 80+112==192, a multiple of 16 */
 } forceSize;
     } u;
 };
 typedef struct sidCacheEntryStr sidCacheEntry;
 
 /* The length of this struct is supposed to be a power of 2, e.g. 4KB */
 struct certCacheEntryStr {
     PRUint16 certLength;                     /*    2 */
@@ -427,16 +429,18 @@ ConvertFromSID(sidCacheEntry *to, sslSes
     to->addr = from->addr;
     to->creationTime = from->creationTime;
     to->lastAccessTime = from->lastAccessTime;
     to->expirationTime = from->expirationTime;
     to->authType = from->authType;
     to->authKeyBits = from->authKeyBits;
     to->keaType = from->keaType;
     to->keaKeyBits = from->keaKeyBits;
+    to->keaGroup = from->keaGroup;
+    to->signatureScheme = from->sigScheme;
 
     to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
     to->u.ssl3.compression = (PRUint16)from->u.ssl3.compression;
     to->u.ssl3.keys = from->u.ssl3.keys;
     to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
     to->sessionIDLength = from->u.ssl3.sessionIDLength;
     to->u.ssl3.certIndex = -1;
     to->u.ssl3.srvNameIndex = -1;
@@ -536,16 +540,18 @@ ConvertToSID(sidCacheEntry *from,
     to->expirationTime = from->expirationTime;
     to->cached = in_server_cache;
     to->addr = from->addr;
     to->references = 1;
     to->authType = from->authType;
     to->authKeyBits = from->authKeyBits;
     to->keaType = from->keaType;
     to->keaKeyBits = from->keaKeyBits;
+    to->keaGroup = from->keaGroup;
+    to->sigScheme = from->signatureScheme;
 
     return to;
 
 loser:
     if (to) {
         SECITEM_FreeItem(&to->u.ssl3.srvName, PR_FALSE);
         PORT_Free(to);
     }
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -119,16 +119,17 @@ PRBool locksEverDisabled; /* implicitly 
 PRBool ssl_force_locks;   /* implicitly PR_FALSE */
 int ssl_lock_readers = 1; /* default true. */
 char ssl_debug;
 char ssl_trace;
 FILE *ssl_trace_iob;
 
 #ifdef NSS_ALLOW_SSLKEYLOGFILE
 FILE *ssl_keylog_iob;
+PZLock *ssl_keylog_lock;
 #endif
 
 char lockStatus[] = "Locks are ENABLED.  ";
 #define LOCKSTATUS_OFFSET 10 /* offset of ENABLED */
 
 /* SRTP_NULL_HMAC_SHA1_80 and SRTP_NULL_HMAC_SHA1_32 are not implemented. */
 static const PRUint16 srtpCiphers[] = {
     SRTP_AES128_CM_HMAC_SHA1_80,
@@ -3539,16 +3540,22 @@ ssl_SetDefaultsFromEnvironment(void)
             if (!ssl_keylog_iob) {
                 SSL_TRACE(("SSL: failed to open key log file"));
             } else {
                 if (ftell(ssl_keylog_iob) == 0) {
                     fputs("# SSL/TLS secrets log file, generated by NSS\n",
                           ssl_keylog_iob);
                 }
                 SSL_TRACE(("SSL: logging SSL/TLS secrets to %s", ev));
+                ssl_keylog_lock = PR_NewLock();
+                if (!ssl_keylog_lock) {
+                    SSL_TRACE(("SSL: failed to create key log lock"));
+                    fclose(ssl_keylog_iob);
+                    ssl_keylog_iob = NULL;
+                }
             }
         }
 #endif
         ev = PR_GetEnvSecure("SSLFORCELOCKS");
         if (ev && ev[0] == '1') {
             ssl_force_locks = PR_TRUE;
             ssl_defaults.noLocks = 0;
             strcpy(lockStatus + LOCKSTATUS_OFFSET, "FORCED.  ");
--- a/security/nss/lib/ssl/sslt.h
+++ b/security/nss/lib/ssl/sslt.h
@@ -270,16 +270,24 @@ typedef struct SSLChannelInfoStr {
     /* These fields have the same meaning as in SSLCipherSuiteInfo. */
     SSLKEAType keaType;
     SSLNamedGroup keaGroup;
     SSLCipherAlgorithm symCipher;
     SSLMACAlgorithm macAlgorithm;
     SSLAuthType authType;
     SSLSignatureScheme signatureScheme;
 
+    /* The following fields were added in NSS 3.34. */
+    /* When the session was resumed this holds the key exchange group of the
+     * original handshake. */
+    SSLNamedGroup originalKeaGroup;
+    /* This field is PR_TRUE when the session is resumed and PR_FALSE
+     * otherwise. */
+    PRBool resumed;
+
     /* When adding new fields to this structure, please document the
      * NSS version in which they were added. */
 } SSLChannelInfo;
 
 /* Preliminary channel info */
 #define ssl_preinfo_version (1U << 0)
 #define ssl_preinfo_cipher_suite (1U << 1)
 #define ssl_preinfo_all (ssl_preinfo_version | ssl_preinfo_cipher_suite)
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -70,16 +70,17 @@ static SECStatus tls13_HandleCertificate
     sslSocket *ss, PRUint8 *b, PRUint32 length,
     SSL3Hashes *hashes);
 static SECStatus tls13_RecoverWrappedSharedSecret(sslSocket *ss,
                                                   sslSessionID *sid);
 static SECStatus
 tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key,
                    const char *prefix,
                    const char *suffix,
+                   const char *keylogLabel,
                    const SSL3Hashes *hashes,
                    PK11SymKey **dest);
 static SECStatus tls13_SendEndOfEarlyData(sslSocket *ss);
 static SECStatus tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey);
 static SECStatus tls13_ComputePskBinderHash(sslSocket *ss,
                                             unsigned long prefixLength,
                                             SSL3Hashes *hashes);
 static SECStatus tls13_VerifyFinished(sslSocket *ss, SSL3HandshakeType message,
@@ -115,16 +116,23 @@ const char kHkdfLabelEarlyExporterSecret
 const char kHkdfLabelHandshakeTrafficSecret[] = "handshake traffic secret";
 const char kHkdfLabelApplicationTrafficSecret[] = "application traffic secret";
 const char kHkdfLabelFinishedSecret[] = "finished";
 const char kHkdfLabelResumptionMasterSecret[] = "resumption master secret";
 const char kHkdfLabelExporterMasterSecret[] = "exporter master secret";
 const char kHkdfPurposeKey[] = "key";
 const char kHkdfPurposeIv[] = "iv";
 
+const char keylogLabelClientEarlyTrafficSecret[] = "CLIENT_EARLY_TRAFFIC_SECRET";
+const char keylogLabelClientHsTrafficSecret[] = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
+const char keylogLabelServerHsTrafficSecret[] = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
+const char keylogLabelClientTrafficSecret[] = "CLIENT_TRAFFIC_SECRET_0";
+const char keylogLabelServerTrafficSecret[] = "SERVER_TRAFFIC_SECRET_0";
+const char keylogLabelExporterSecret[] = "EXPORTER_SECRET";
+
 #define TRAFFIC_SECRET(ss, dir, name) ((ss->sec.isServer ^            \
                                         (dir == CipherSpecWrite))     \
                                            ? ss->ssl3.hs.client##name \
                                            : ss->ssl3.hs.server##name)
 
 const SSL3ProtocolVersion kTlsRecordVersion = SSL_LIBRARY_VERSION_TLS_1_0;
 const SSL3ProtocolVersion kDtlsRecordVersion = SSL_LIBRARY_VERSION_TLS_1_1;
 
@@ -752,24 +760,24 @@ tls13_ComputeEarlySecrets(sslSocket *ss)
                           hashes.u.raw, buf, 0);
         if (rv != SECSuccess) {
             FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
             return SECFailure;
         }
         hashes.len = tls13_GetHashSize(ss);
 
         rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
-                                NULL, kHkdfLabelPskBinderKey, &hashes,
+                                NULL, kHkdfLabelPskBinderKey, NULL, &hashes,
                                 &ss->ssl3.hs.pskBinderKey);
         if (rv != SECSuccess) {
             return SECFailure;
         }
 
         rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
-                                NULL, kHkdfLabelEarlyExporterSecret,
+                                NULL, kHkdfLabelEarlyExporterSecret, NULL,
                                 &hashes, &ss->ssl3.hs.earlyExporterSecret);
         if (rv != SECSuccess) {
             return SECFailure;
         }
     } else {
         PORT_Assert(!ss->ssl3.hs.resumptionMasterSecret);
     }
 
@@ -797,25 +805,29 @@ tls13_ComputeHandshakeSecrets(sslSocket 
     PK11_FreeSymKey(ss->ssl3.hs.dheSecret);
     ss->ssl3.hs.dheSecret = NULL;
     PK11_FreeSymKey(ss->ssl3.hs.currentSecret);
     ss->ssl3.hs.currentSecret = newSecret;
 
     /* Now compute |*HsTrafficSecret| */
     rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
                             kHkdfLabelClient,
-                            kHkdfLabelHandshakeTrafficSecret, NULL,
+                            kHkdfLabelHandshakeTrafficSecret,
+                            keylogLabelClientHsTrafficSecret,
+                            NULL,
                             &ss->ssl3.hs.clientHsTrafficSecret);
     if (rv != SECSuccess) {
         LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
         return rv;
     }
     rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
                             kHkdfLabelServer,
-                            kHkdfLabelHandshakeTrafficSecret, NULL,
+                            kHkdfLabelHandshakeTrafficSecret,
+                            keylogLabelServerHsTrafficSecret,
+                            NULL,
                             &ss->ssl3.hs.serverHsTrafficSecret);
     if (rv != SECSuccess) {
         LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
         return rv;
     }
 
     SSL_TRC(5, ("%d: TLS13[%d]: compute master secret (%s)",
                 SSL_GETPID(), ss->fd, SSL_ROLE(ss)));
@@ -840,33 +852,37 @@ tls13_ComputeHandshakeSecrets(sslSocket 
 static SECStatus
 tls13_ComputeApplicationSecrets(sslSocket *ss)
 {
     SECStatus rv;
 
     rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
                             kHkdfLabelClient,
                             kHkdfLabelApplicationTrafficSecret,
+                            keylogLabelClientTrafficSecret,
                             NULL,
                             &ss->ssl3.hs.clientTrafficSecret);
     if (rv != SECSuccess) {
         return SECFailure;
     }
     rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
                             kHkdfLabelServer,
                             kHkdfLabelApplicationTrafficSecret,
+                            keylogLabelServerTrafficSecret,
                             NULL,
                             &ss->ssl3.hs.serverTrafficSecret);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
                             NULL, kHkdfLabelExporterMasterSecret,
-                            NULL, &ss->ssl3.hs.exporterSecret);
+                            keylogLabelExporterSecret,
+                            NULL,
+                            &ss->ssl3.hs.exporterSecret);
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     return SECSuccess;
 }
 
 static SECStatus
@@ -875,17 +891,17 @@ tls13_ComputeFinalSecrets(sslSocket *ss)
     SECStatus rv;
     PK11SymKey *resumptionMasterSecret = NULL;
 
     PORT_Assert(!ss->ssl3.crSpec->master_secret);
     PORT_Assert(!ss->ssl3.cwSpec->master_secret);
 
     rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
                             NULL, kHkdfLabelResumptionMasterSecret,
-                            NULL, &resumptionMasterSecret);
+                            NULL, NULL, &resumptionMasterSecret);
     PK11_FreeSymKey(ss->ssl3.hs.currentSecret);
     ss->ssl3.hs.currentSecret = NULL;
     if (rv != SECSuccess) {
         return SECFailure;
     }
 
     /* This is pretty gross. TLS 1.3 uses a number of master secrets:
      * The master secret to generate the keys and then the resumption
@@ -904,16 +920,18 @@ static void
 tls13_RestoreCipherInfo(sslSocket *ss, sslSessionID *sid)
 {
     /* Set these to match the cached value.
      * TODO(ekr@rtfm.com): Make a version with the "true" values.
      * Bug 1256137.
      */
     ss->sec.authType = sid->authType;
     ss->sec.authKeyBits = sid->authKeyBits;
+    ss->sec.originalKeaGroup = ssl_LookupNamedGroup(sid->keaGroup);
+    ss->sec.signatureScheme = sid->sigScheme;
 }
 
 /* Check whether resumption-PSK is allowed. */
 static PRBool
 tls13_CanResume(sslSocket *ss, const sslSessionID *sid)
 {
     const sslServerCert *sc;
 
@@ -1427,16 +1445,17 @@ tls13_HandleClientHelloPart2(sslSocket *
     /* Take ownership of the session. */
     ss->sec.ci.sid = sid;
     sid = NULL;
 
     if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
         rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
                                 kHkdfLabelClient,
                                 kHkdfLabelEarlyTrafficSecret,
+                                keylogLabelClientEarlyTrafficSecret,
                                 NULL, /* Current running hash. */
                                 &ss->ssl3.hs.clientEarlyTrafficSecret);
         if (rv != SECSuccess) {
             FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
             return SECFailure;
         }
     }
 
@@ -2538,16 +2557,17 @@ loser:
  *    Derive-Secret(Secret, Label, Messages) =
  *       HKDF-Expand-Label(Secret, Label,
  *                         Hash(Messages) + Hash(resumption_context), L))
  */
 static SECStatus
 tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key,
                    const char *prefix,
                    const char *suffix,
+                   const char *keylogLabel,
                    const SSL3Hashes *hashes,
                    PK11SymKey **dest)
 {
     SECStatus rv;
     SSL3Hashes hashesTmp;
     char buf[100];
     const char *label;
 
@@ -2580,16 +2600,19 @@ tls13_DeriveSecret(sslSocket *ss, PK11Sy
                                hashes->u.raw, hashes->len,
                                label, strlen(label),
                                tls13_GetHkdfMechanism(ss),
                                tls13_GetHashSize(ss), dest);
     if (rv != SECSuccess) {
         LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
+    if (keylogLabel) {
+        ssl3_RecordKeyLog(ss, keylogLabel, *dest);
+    }
     return SECSuccess;
 }
 
 /* Derive traffic keys for the next cipher spec in the queue. */
 static SECStatus
 tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec,
                         TrafficKeyType type,
                         CipherSpecDirection direction,
@@ -4346,16 +4369,17 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss
     }
 
     /* Cipher suite already set in tls13_SetupClientHello. */
     ss->ssl3.hs.preliminaryInfo = 0;
 
     rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
                             kHkdfLabelClient,
                             kHkdfLabelEarlyTrafficSecret,
+                            keylogLabelClientEarlyTrafficSecret,
                             NULL,
                             &ss->ssl3.hs.clientEarlyTrafficSecret);
     if (rv != SECSuccess)
         return SECFailure;
 
     rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData,
                              CipherSpecWrite, PR_TRUE);
     if (rv != SECSuccess) {
--- a/security/nss/lib/util/nssb64d.c
+++ b/security/nss/lib/util/nssb64d.c
@@ -244,17 +244,17 @@ pl_base64_decode_buffer(PLBase64Decoder 
 
         if (i < 4) {
             /* Didn't get enough for a complete token. */
             data->token_size = i;
             break;
         }
         i = 0;
 
-        PR_ASSERT((out - data->output_buffer + 3) <= data->output_buflen);
+        PR_ASSERT((PRUint32)(out - data->output_buffer + 3) <= data->output_buflen);
 
         /*
          * Assume we are not at the end; the following function only works
          * for an internal token (no trailing padding characters) but is
          * faster that way.  If it hits an invalid character (padding) it
          * will return an error; we break out of the loop and try again
          * calling the routine that will handle a final token.
          * Note that we intentionally do it this way rather than explicitly
--- 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.33"
+#define NSSUTIL_VERSION "3.34 Beta"
 #define NSSUTIL_VMAJOR 3
-#define NSSUTIL_VMINOR 33
+#define NSSUTIL_VMINOR 34
 #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/tests/cert/cert.sh
+++ b/security/nss/tests/cert/cert.sh
@@ -1941,32 +1941,42 @@ cert_test_distrust()
 cert_test_ocspresp()
 {
   echo "$SCRIPTNAME: OCSP response creation selftest"
   OR_ACTION="perform selftest"
   RETEXPECTED=0
   ocspr ${SERVER_CADIR} "serverCA" "chain-1-serverCA" -f "${R_PWFILE}" 2>&1
 }
 
+cert_test_implicit_db_init()
+{
+  echo "$SCRIPTNAME: test implicit database init"
+
+  CU_ACTION="Add cert with trust flags to db with implicit init"
+  mkdir ${IMPLICIT_INIT_DIR}
+  certu -A -n ca -t 'C,C,C' -d ${P_R_IMPLICIT_INIT_DIR} -i "${SERVER_CADIR}/serverCA.ca.cert"
+}
+
 ############################## cert_cleanup ############################
 # local shell function to finish this script (no exit since it might be
 # sourced)
 ########################################################################
 cert_cleanup()
 {
   cert_log "$SCRIPTNAME: finished $SCRIPTNAME"
   html "</TABLE><BR>"
   cd ${QADIR}
   . common/cleanup.sh
 }
 
 ################## main #################################################
 
 cert_init
 cert_all_CA
+cert_test_implicit_db_init
 cert_extended_ssl
 cert_ssl
 cert_smime_client
 if [[ -n "$NSS_TEST_ENABLE_FIPS" ]]; then
     cert_fips
 fi
 cert_eccurves
 cert_extensions
--- a/security/nss/tests/common/init.sh
+++ b/security/nss/tests/common/init.sh
@@ -63,16 +63,17 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOU
         DBPASSDIR=${HOSTDIR}/dbpass
         ECCURVES_DIR=${HOSTDIR}/eccurves
         DISTRUSTDIR=${HOSTDIR}/distrust
 
         SERVER_CADIR=${HOSTDIR}/serverCA
         CLIENT_CADIR=${HOSTDIR}/clientCA
         EXT_SERVERDIR=${HOSTDIR}/ext_server
         EXT_CLIENTDIR=${HOSTDIR}/ext_client
+        IMPLICIT_INIT_DIR=${HOSTDIR}/implicit_init
 
         IOPR_CADIR=${HOSTDIR}/CA_iopr
         IOPR_SSL_SERVERDIR=${HOSTDIR}/server_ssl_iopr
         IOPR_SSL_CLIENTDIR=${HOSTDIR}/client_ssl_iopr
         IOPR_OCSP_CLIENTDIR=${HOSTDIR}/client_ocsp_iopr
 
         CERT_EXTENSIONS_DIR=${HOSTDIR}/cert_extensions
         STAPLINGDIR=${HOSTDIR}/stapling
@@ -531,16 +532,17 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOU
     D_SERVER="Server.$version"
     D_CLIENT="Client.$version"
     D_NOLOGIN="NoLogin.$version"
     D_FIPS="FIPS.$version"
     D_DBPASS="DBPASS.$version"
     D_ECCURVES="ECCURVES.$version"
     D_EXT_SERVER="ExtendedServer.$version"
     D_EXT_CLIENT="ExtendedClient.$version"
+    D_IMPLICIT_INIT="ImplicitInit.$version"
     D_CERT_EXTENSTIONS="CertExtensions.$version"
     D_DISTRUST="Distrust.$version"
 
     # we need relative pathnames of these files abd directories, since our
     # tools can't handle the unix style absolut pathnames on cygnus
 
     R_CADIR=../CA
     R_SERVERDIR=../server
@@ -550,16 +552,17 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOU
     R_IOPR_SSL_CLIENTDIR=../client_ssl_iopr
     R_IOPR_OCSP_CLIENTDIR=../client_ocsp_iopr
     R_ALICEDIR=../alicedir
     R_BOBDIR=../bobdir
     R_DAVEDIR=../dave
     R_EVEDIR=../eve
     R_EXT_SERVERDIR=../ext_server
     R_EXT_CLIENTDIR=../ext_client
+    R_IMPLICIT_INIT_DIR=../implicit_init
     R_CERT_EXT=../cert_extensions
     R_STAPLINGDIR=../stapling
     R_NOLOGINDIR=../nologin
     R_SSLGTESTDIR=../ssl_gtests
     R_GTESTDIR=../gtests
 
     #
     # profiles are either paths or domains depending on the setting of
@@ -570,27 +573,29 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOU
     P_R_BOBDIR=${R_BOBDIR}
     P_R_DAVEDIR=${R_DAVEDIR}
     P_R_EVEDIR=${R_EVEDIR}
     P_R_SERVERDIR=${R_SERVERDIR}
     P_R_CLIENTDIR=${R_CLIENTDIR}
     P_R_NOLOGINDIR=${R_NOLOGINDIR}
     P_R_EXT_SERVERDIR=${R_EXT_SERVERDIR}
     P_R_EXT_CLIENTDIR=${R_EXT_CLIENTDIR}
+    P_R_IMPLICIT_INIT_DIR=${R_IMPLICIT_INIT_DIR}
     if [ -n "${MULTIACCESS_DBM}" ]; then
         P_R_CADIR="multiaccess:${D_CA}"
         P_R_ALICEDIR="multiaccess:${D_ALICE}"
         P_R_BOBDIR="multiaccess:${D_BOB}"
         P_R_DAVEDIR="multiaccess:${D_DAVE}"
         P_R_EVEDIR="multiaccess:${D_EVE}"
         P_R_SERVERDIR="multiaccess:${D_SERVER}"
         P_R_CLIENTDIR="multiaccess:${D_CLIENT}"
         P_R_NOLOGINDIR="multiaccess:${D_NOLOGIN}"
         P_R_EXT_SERVERDIR="multiaccess:${D_EXT_SERVER}"
         P_R_EXT_CLIENTDIR="multiaccess:${D_EXT_CLIENT}"
+        P_R_IMPLICIT_INIT_DIR="multiaccess:${D_IMPLICIT_INIT}"
     fi
 
     R_PWFILE=../tests.pw
     R_EMPTY_FILE=../tests_empty
     R_NOISE_FILE=../tests_noise
 
     R_FIPSPWFILE=../tests.fipspw
     R_FIPSBADPWFILE=../tests.fipsbadpw
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..40d5671b9dbc2df8a701df091ef5dbc568c10399
GIT binary patch
literal 2588
zc$~eKcTkhr8pglxODLh&P%hOVpl-+)5)^`f2vLd%N>ijGB^U|PQE8DTprBHeq7)S=
ziYP@oSSX?kDhLFnCQB0)j0!?vVRlD%XYQYO?)m4;^E=NubLKf`-g)6@2t>fq+^FsG
zCh^||K^`zaS|u7uN43Dw{|)EEbW|=(N33)6|Ggx@2O{$6h?^TQpPTP*h(d!KEDcFV
zq-^j+m=5{pBOnlhAfdgm;Ll@0el7s^!Sll?ZiFq8TO6{r#*4$En}S!I&&Z8R@uCIz
zQQYuoSYi|MhznZKg8hQrD1J(I6wgq+7%Z~M`NUCsE%)16D;>19#!JKKO@<H`-cU+5
zo`FG1mek`)MuxD0lpuZ=tb-@wi7-J^(_vHMHGj(g<4x$`mVd?oasdcBC=6_HK8Oy2
zK+jZ`#pzg|iJs<*o%%WzEZ3VSLaa*Xyz^^Di?8eneBVkO5xRLbMU?oxTJKTCz5c#I
z95oBm!R&PrkREES!0Fz1FH_?xK7aab2g@<GFf2{3b@|yV(%reTQEO2Jy?{qYIvrDR
z8Nbs;Qcp0GmcmWHw{gqwm8jOVR7lb#%&83ezMJA-Q!%)Z$dcJQZBkxlSLy!MB}TRR
z!6J*2nXi{z5ALVY1ee#a7GbxHq*{wxYXz7d6ACAH7*gWNR>|VN%>LSEGshWng=0FY
zT?<}QT5UzsaVsAW^o3>@7wrp*RVqIk#e)fwoy#4PT&qrX$-bz^v+mIEfUcl5s+dCv
z5CDsI!=#P0QLgbOVEoeFjhMi7BoYBZNLXwmS9$SG%?opHOb`gbLYqwZm*?N#46zxj
zALuQs?zAgU(V^axP5#jl7M=OyUaqa(ol;lPE><lfGkM(UW#dGBh-w7y`+2E36`hP5
zMR%N;9R6~WEBbRG{Sgm!O9{WzEb}eukARg1tV5hywF7VIP{)YCHxV$LB|xc2$vDd!
z8Qx^-B)Aswm8u|&xzqd~_NTa=FNsl-GcGcFPIV1S+BHulYRTjwRqklM?WxBAJguJL
z%#0S~!fJlpVGOG)K0P-wx^A!W=YnL}GK*n_i&^%iMW?>hqLwnU{XH}^hIBJ5vd9OH
zd<?X6S8J&Z*oWtYo{CzpU+87%980HHdW#5OP2-ZW^je2_vQe7Dcl#q=C)C@x;!R-X
zpQ)fE@Dd7QfDPaY1Oh>TB|rs^14e)$jQM4e#G{cCY15VV`oQaRTMBTEDB>T2u71=?
zn9h~)&k_LT)450+a3}2gb2pbDYz=Gvk^=Bnq{w9+wd``!7K8cIr8g!*dxRl~rxya1
zU_Nf%zkCo6EdSS=dm@nFcBBZdD*N`KG|~AhYGxp>@vdAX9obvdY=M(Vem|8Mn4MZ}
zpXZ&_>;FPu`5<(|A?k!&;ph)<CYMi7d;o#5OY9uDR31MTHX#GQTg}3LDm=;fpltmF
zR#yu%t;k!XO5W~dwPJK_J58j}jV>n5W0F^wuIJdS$da7)V^Y0@#@`XAiDzbMakVZu
zO-pghN*}GaAv0v`W74~;#{A0`rvq)pzvPJ2H3E}!_pQgnn%hS{_zQs5f!43Qw6x!7
z*__@T;8maCO*@(V{8ib!ilXM@-=9AVI~{9c@S{#*x--Z;$-aF>Bk_Uxcb#dzoTpNP
z-};Ha0T*8r?4p%TIVs^d^{wrXqx535YlhJ6mddLMxr2WD-AeA$WFH2xG%m@8dg<QF
zn5=DN))-D*q3AQn!D!=HcY~7ZA0y9|3442u)Jf4JP4%bxS{*oK3fY1k#lWx*8thNP
zFgl$JG9#%3@;b+bCKyr>T@z40`z5<Rd(y0IwL$H*bFf)#%i23*ukfJV3Op|^Kvy`8
z-SQs_q?^;PeZE!}vQr?n@<nKTSjwXWN~i7<O-E=wrb`ES(!MgiyXiXQNY9%bNRiew
zRKBgZaKTVjhT6B5BP7<Q!?(;)Tz(X!i;)nCxm((Ql!LuRH5ocU#N$EUyFxFkP;Bl<
z0<`Vw6&ykSsq&eo25?g0q~O;t!lRzE{8>^I;YVR@=Jp@o&s_S}(cAHWiY11KoXBfF
z!Nfhp#%M$=u@~(Z+h;4)04Ju0!=y)^*_d{?XWON^cV+vBLlXzOEF)_|I)Wk98=vJU
z=6hbKzw!;;3B@cDcOkmxYxCCzRTle{q_pLi?7rG8Hc5>SyqUZA@^yR~JJaraXF&}&
z`&b)3&g+wsmgJu0skT))W*m)`X&Tx-Q^l$t%&Zx08w+u*D)av#Z6zEXMC1<qquySB
z`#psKRWV>TS(U^3AfB0K?Cx%UKY*y&fjhLmTXgaq>2Ud|&bd#Am^NT!=TOE<j>B|!
zxm4X!u49F9w;xv}b@{GMu=fH*dclL;@o*}A0J%*yMdS!uu%0~DwfHdR1tElh%X;Np
zm8YgHz%V1rmHWnBW8PqhMp4kmUiuBsTpg1<^Y!^m)g1AmTG``p<f_$SMU@1zYp0GM
zGA;~Kw<)Ef`U;j7n`35@2*{S5=g61IFK$vwGWGAvn;Uj6gjy!JCm5%^k0OUKFx~DI
z^S*W3-eb=qIbf7RLu$m)*z%z7spGY4g=J6EYqwwP<2+!fIXV}AJ5Msce+I^qu9x_r
z!`Osf%M;;Txb3r^Lb;Cnd<>pyi|S$ZMj(sj3)3x!b#n~HCwf*dyL2=!ei~ToOpnzy
zI}3B}(mXxhK9y4mjC-2}bTr0Aei%Nhr7??tZ~GP-U*bcc3MDEKJWMYRTZI;n4(zaJ
zxFI8QhAankslE-@(-o^+R%+j*58l|x??z%hVE6jIF<Kpt#C3`DKBfp+7WHO-#5N)9
zGZ8mQ4@4&P^=&KyfY<7g6AkG(_SvpS?X_eg5QXyinm0CAbhh>;Ea~GHyC-MrG#1!h
zv7>ML;~ZwQMV|~F&rO!oZ_XOm5v%NRG(2yr*n4ZF;<?nPSbj`!F(ZXKi|*d&7C1)E
zi;{`{LU`+H(zcFCeW&>@w;fvvXRuG7{qG7h@UH>uz{(pf4c87K1SHD^ASGNI7OW+f
pR78?2toM{Up|N<{Z)Bv%V1DDdet*~Cvy9urY-uZ@&7uqde*(pUL-GIs
--- a/security/nss/tests/tools/tools.sh
+++ b/security/nss/tests/tools/tools.sh
@@ -97,16 +97,18 @@ tools_init()
   fi
 
   mkdir -p ${TOOLSDIR}
   mkdir -p ${COPYDIR}
   mkdir -p ${SIGNDIR}
   cp ${ALICEDIR}/* ${SIGNDIR}/
   mkdir -p ${TOOLSDIR}/html
   cp ${QADIR}/tools/sign*.html ${TOOLSDIR}/html
+  mkdir -p ${TOOLSDIR}/data
+  cp ${QADIR}/tools/TestOldCA.p12 ${TOOLSDIR}/data
 
   cd ${TOOLSDIR}
 }
 
 ########################## list_p12_file ###############################
 # List the key and cert in the specified p12 file
 ########################################################################
 list_p12_file()
@@ -412,27 +414,38 @@ tools_p12_export_list_import_with_defaul
   echo "$SCRIPTNAME: Listing Alice's pk12 EC file -----------------"
   echo "pk12util -l Alice-ec.p12 -w ${R_PWFILE}"
   ${BINDIR}/pk12util -l Alice-ec.p12 -w ${R_PWFILE} 2>&1
   ret=$?
   html_msg $ret 0 "Listing Alice's pk12 EC file (pk12util -l)"
   check_tmpfile
 }
 
+tools_p12_import_old_files()
+{
+  echo "$SCRIPTNAME: Importing CA cert & key created with NSS 3.21 --------------"
+  echo "pk12util -i TestOldCA.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}"
+  ${BINDIR}/pk12util -i ${TOOLSDIR}/data/TestOldCA.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE} 2>&1
+  ret=$?
+  html_msg $ret 0 "Importing CA cert & key created with NSS 3.21"
+  check_tmpfile
+}
+
 ############################## tools_p12 ###############################
 # local shell function to test basic functionality of pk12util
 ########################################################################
 tools_p12()
 {
   tools_p12_export_list_import_with_default_ciphers
   tools_p12_export_list_import_all_pkcs5v2_ciphers
   tools_p12_export_list_import_all_pkcs5pbe_ciphers
   tools_p12_export_list_import_all_pkcs12v2pbe_ciphers
   tools_p12_export_with_none_ciphers
   tools_p12_export_with_invalid_ciphers
+  tools_p12_import_old_files
 }
 
 ############################## tools_sign ##############################
 # local shell function pk12util uses a hardcoded tmp file, if this exists
 # and is owned by another user we don't get reasonable errormessages 
 ########################################################################
 check_tmpfile()
 {
@@ -492,27 +505,43 @@ SIGNSCRIPT
 
   echo "$SCRIPTNAME: Show who signed xpi ------------------------------"
   echo "signtool -w nojs.xpi -d ${P_R_SIGNDIR}"
   ${BINDIR}/signtool -w nojs.xpi -d ${P_R_SIGNDIR}
   html_msg $? 0 "Show who signed xpi (signtool -w)"
 
 }
 
+tools_modutil()
+{
+  echo "$SCRIPTNAME: Test if DB created by modutil -create is initialized"
+  mkdir -p ${R_TOOLSDIR}/moddir
+  # copied from modu function in cert.sh
+  # echo is used to press Enter expected by modutil
+  echo | ${BINDIR}/modutil -create -dbdir "${R_TOOLSDIR}/moddir" 2>&1
+  ret=$?
+  ${BINDIR}/certutil -S -s 'CN=TestUser' -d "${TOOLSDIR}/moddir" -n TestUser \
+	   -x -t ',,' -z "${R_NOISE_FILE}"
+  ret=$?
+  html_msg $ret 0 "Test if DB created by modutil -create is initialized"
+  check_tmpfile
+}
+
 ############################## tools_cleanup ###########################
 # local shell function to finish this script (no exit since it might be 
 # sourced)
 ########################################################################
 tools_cleanup()
 {
   html "</TABLE><BR>"
   cd ${QADIR}
   . common/cleanup.sh
 }
 
 ################## main #################################################
 
 tools_init
 tools_p12
 tools_sign
+tools_modutil
 tools_cleanup