diff --git a/.gitignore b/.gitignore
index 42f8cb6..a250c86 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,8 @@ SOURCES/cert8.db.xml
 SOURCES/cert9.db.xml
 SOURCES/key3.db.xml
 SOURCES/key4.db.xml
-SOURCES/nss-3.41.tar.gz
+SOURCES/nss-3.44.tar.gz
 SOURCES/nss-config.xml
+SOURCES/nss-softokn-cavs-1.0.tar.gz
 SOURCES/secmod.db.xml
 SOURCES/setup-nsssysinit.xml
diff --git a/.nss.metadata b/.nss.metadata
index 359f253..bd0ba0b 100644
--- a/.nss.metadata
+++ b/.nss.metadata
@@ -7,7 +7,8 @@ bd748cf6e1465a1bbe6e751b72ffc0076aff0b50 SOURCES/blank-secmod.db
 ea6705e15999bdc6365f05b3d66f9c1d49677f84 SOURCES/cert9.db.xml
 24c123810543ff0f6848647d6d910744e275fb01 SOURCES/key3.db.xml
 af51b16a56fda1f7525a0eed3ecbdcbb4133be0c SOURCES/key4.db.xml
-69c60e8d3190573dbcbc01f50e68e3ceb7d92522 SOURCES/nss-3.41.tar.gz
+44a83b1bf4efd27605177ecdbf217e579ae8c8ae SOURCES/nss-3.44.tar.gz
 2905c9b06e7e686c9e3c0b5736a218766d4ae4c2 SOURCES/nss-config.xml
+d8a7f044570732caf4ed06fd44a63b3e86ea2a16 SOURCES/nss-softokn-cavs-1.0.tar.gz
 ca9ebf79c1437169a02527c18b1e3909943c4be9 SOURCES/secmod.db.xml
 bcbe05281b38d843273f91ae3f9f19f70c7d97b3 SOURCES/setup-nsssysinit.xml
diff --git a/SOURCES/enable-fips-when-system-is-in-fips-mode.patch b/SOURCES/enable-fips-when-system-is-in-fips-mode.patch
deleted file mode 100644
index dde5dcb..0000000
--- a/SOURCES/enable-fips-when-system-is-in-fips-mode.patch
+++ /dev/null
@@ -1,79 +0,0 @@
-diff -up nss/lib/pk11wrap/pk11pars.c.852023_enable_fips_when_in_fips_mode nss/lib/pk11wrap/pk11pars.c
---- nss/lib/pk11wrap/pk11pars.c.852023_enable_fips_when_in_fips_mode	2018-03-05 16:58:32.000000000 +0100
-+++ nss/lib/pk11wrap/pk11pars.c	2018-03-09 17:24:39.815838810 +0100
-@@ -671,6 +671,10 @@ SECMOD_CreateModuleEx(const char *librar
- 
-     mod->internal = NSSUTIL_ArgHasFlag("flags", "internal", nssc);
-     mod->isFIPS = NSSUTIL_ArgHasFlag("flags", "FIPS", nssc);
-+    /* if the system FIPS mode is enabled, force FIPS to be on */
-+    if (SECMOD_GetSystemFIPSEnabled()) {
-+	mod->isFIPS = PR_TRUE;
-+    }
-     mod->isCritical = NSSUTIL_ArgHasFlag("flags", "critical", nssc);
-     slotParams = NSSUTIL_ArgGetParamValue("slotParams", nssc);
-     mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena, slotParams,
-diff -up nss/lib/pk11wrap/pk11util.c.852023_enable_fips_when_in_fips_mode nss/lib/pk11wrap/pk11util.c
---- nss/lib/pk11wrap/pk11util.c.852023_enable_fips_when_in_fips_mode	2018-03-05 16:58:32.000000000 +0100
-+++ nss/lib/pk11wrap/pk11util.c	2018-03-09 17:25:46.804347730 +0100
-@@ -95,6 +95,26 @@ SECMOD_Shutdown()
-     return SECSuccess;
- }
- 
-+int SECMOD_GetSystemFIPSEnabled(void) {
-+#ifdef LINUX
-+    FILE *f;
-+    char d;
-+    size_t size;
-+
-+    f = fopen("/proc/sys/crypto/fips_enabled", "r");
-+    if (!f)
-+        return 0;
-+
-+    size = fread(&d, 1, 1, f);
-+    fclose(f);
-+    if (size != 1)
-+        return 0;
-+    if (d == '1')
-+        return 1;
-+#endif
-+    return 0;
-+}
-+
- /*
-  * retrieve the internal module
-  */
-@@ -428,7 +448,7 @@ SECMOD_DeleteInternalModule(const char *
-     SECMODModuleList **mlpp;
-     SECStatus rv = SECFailure;
- 
--    if (pendingModule) {
-+    if (SECMOD_GetSystemFIPSEnabled() || pendingModule) {
-         PORT_SetError(SEC_ERROR_MODULE_STUCK);
-         return rv;
-     }
-@@ -963,7 +983,7 @@ SECMOD_CanDeleteInternalModule(void)
- #ifdef NSS_FIPS_DISABLED
-     return PR_FALSE;
- #else
--    return (PRBool)(pendingModule == NULL);
-+    return (PRBool) ((pendingModule == NULL) && !SECMOD_GetSystemFIPSEnabled());
- #endif
- }
- 
-diff -up nss/lib/pk11wrap/secmodi.h.852023_enable_fips_when_in_fips_mode nss/lib/pk11wrap/secmodi.h
---- nss/lib/pk11wrap/secmodi.h.852023_enable_fips_when_in_fips_mode	2018-03-05 16:58:32.000000000 +0100
-+++ nss/lib/pk11wrap/secmodi.h	2018-03-09 17:24:39.816838788 +0100
-@@ -115,6 +115,13 @@ PK11SymKey *pk11_TokenKeyGenWithFlagsAnd
- CK_MECHANISM_TYPE pk11_GetPBECryptoMechanism(SECAlgorithmID *algid,
-                                              SECItem **param, SECItem *pwd, PRBool faulty3DES);
- 
-+/* Get the state of the system FIPS mode */
-+/* NSS uses this to force FIPS mode if the system bit is on. Applications which
-+ * use the SECMOD_CanDeleteInteral() to check to see if they can switch to or
-+ * from FIPS mode will automatically be told that they can't swith out of FIPS
-+ * mode */
-+int SECMOD_GetSystemFIPSEnabled();
-+
- extern void pk11sdr_Init(void);
- extern void pk11sdr_Shutdown(void);
- 
diff --git a/SOURCES/nss-3.39-create-public-key-on-private-import.patch b/SOURCES/nss-3.39-create-public-key-on-private-import.patch
deleted file mode 100644
index c17a38a..0000000
--- a/SOURCES/nss-3.39-create-public-key-on-private-import.patch
+++ /dev/null
@@ -1,804 +0,0 @@
-# HG changeset patch
-# User Robert Relyea <rrelyea@redhat.com>
-# Date 1544226862 28800
-#      Fri Dec 07 15:54:22 2018 -0800
-# Node ID 521a5b2f10cc197b9349df033f9d3cca0b5226c5
-# Parent  5ac4d4904afae59149bb1fab49c3b21244a51a22
-try: -b do -u all - p all -t all
-
-diff --git a/cmd/manifest.mn b/cmd/manifest.mn
---- a/cmd/manifest.mn
-+++ b/cmd/manifest.mn
-@@ -51,16 +51,17 @@ NSS_SRCDIRS = \
-  ocspclnt  \
-  ocspresp \
-  oidcalc  \
-  p7content  \
-  p7env  \
-  p7sign  \
-  p7verify  \
-  pk12util \
-+ pk11import \
-  pk11ectest \
-  pk11gcmtest \
-  pk11mode \
-  pk1sign  \
-  pp  \
-  pwdecrypt \
-  rsaperf \
-  rsapoptst \
-diff --git a/cmd/pk11import/Makefile b/cmd/pk11import/Makefile
-new file mode 100644
---- /dev/null
-+++ b/cmd/pk11import/Makefile
-@@ -0,0 +1,43 @@
-+#! gmake
-+#
-+# This Source Code Form is subject to the terms of the Mozilla Public
-+# License, v. 2.0. If a copy of the MPL was not distributed with this
-+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-+
-+#######################################################################
-+# (1) Include initial platform-independent assignments (MANDATORY).   #
-+#######################################################################
-+
-+include manifest.mn
-+
-+#######################################################################
-+# (2) Include "global" configuration information. (OPTIONAL)          #
-+#######################################################################
-+
-+include $(CORE_DEPTH)/coreconf/config.mk
-+
-+#######################################################################
-+# (3) Include "component" configuration information. (OPTIONAL)       #
-+#######################################################################
-+
-+#######################################################################
-+# (4) Include "local" platform-dependent assignments (OPTIONAL).      #
-+#######################################################################
-+
-+include ../platlibs.mk
-+
-+#######################################################################
-+# (5) Execute "global" rules. (OPTIONAL)                              #
-+#######################################################################
-+
-+include $(CORE_DEPTH)/coreconf/rules.mk
-+
-+#######################################################################
-+# (6) Execute "component" rules. (OPTIONAL)                           #
-+#######################################################################
-+
-+#######################################################################
-+# (7) Execute "local" rules. (OPTIONAL).                              #
-+#######################################################################
-+
-+include ../platrules.mk
-diff --git a/cmd/pk11import/manifest.mn b/cmd/pk11import/manifest.mn
-new file mode 100644
---- /dev/null
-+++ b/cmd/pk11import/manifest.mn
-@@ -0,0 +1,15 @@
-+# This Source Code Form is subject to the terms of the Mozilla Public
-+# License, v. 2.0. If a copy of the MPL was not distributed with this
-+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-+
-+CORE_DEPTH = ../..
-+
-+MODULE = nss
-+
-+CSRCS = pk11import.c	\
-+	$(NULL)
-+
-+REQUIRES = seccmd
-+
-+PROGRAM = pk11import
-+
-diff --git a/cmd/pk11import/pk11import.c b/cmd/pk11import/pk11import.c
-new file mode 100644
---- /dev/null
-+++ b/cmd/pk11import/pk11import.c
-@@ -0,0 +1,410 @@
-+/* 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 "secutil.h"
-+#include "secmod.h"
-+#include "cert.h"
-+#include "secoid.h"
-+#include "nss.h"
-+#include "pk11pub.h"
-+#include "pk11pqg.h"
-+
-+/* NSPR 2.0 header files */
-+#include "prinit.h"
-+#include "prprf.h"
-+#include "prsystem.h"
-+#include "prmem.h"
-+/* Portable layer header files */
-+#include "plstr.h"
-+
-+SECOidData *
-+getCurveFromString(char *curve_name)
-+{
-+    SECOidTag tag = SEC_OID_SECG_EC_SECP256R1;
-+
-+    if (PORT_Strcasecmp(curve_name, "NISTP256") == 0) {
-+    } else if (PORT_Strcasecmp(curve_name, "NISTP384") == 0) {
-+        tag = SEC_OID_SECG_EC_SECP384R1;
-+    } else if (PORT_Strcasecmp(curve_name, "NISTP521") == 0) {
-+        tag = SEC_OID_SECG_EC_SECP521R1;
-+    } else if (PORT_Strcasecmp(curve_name, "Curve25519") == 0) {
-+        tag = SEC_OID_CURVE25519;
-+    }
-+    return SECOID_FindOIDByTag(tag);
-+}
-+
-+void
-+dumpItem(const char *label, const SECItem *item)
-+{
-+    int i;
-+    printf("%s = [%d bytes] {", label, item->len);
-+    for (i = 0; i < item->len; i++) {
-+        if ((i & 0xf) == 0)
-+            printf("\n    ");
-+        else
-+            printf(", ");
-+        printf("%02x", item->data[i]);
-+    }
-+    printf("};\n");
-+}
-+
-+SECStatus
-+handleEncryptedPrivateImportTest(char *progName, PK11SlotInfo *slot,
-+                                 char *testname, CK_MECHANISM_TYPE genMech, void *params, void *pwArgs)
-+{
-+    SECStatus rv = SECSuccess;
-+    SECItem privID = { 0 };
-+    SECItem pubID = { 0 };
-+    SECItem pubValue = { 0 };
-+    SECItem pbePwItem = { 0 };
-+    SECItem nickname = { 0 };
-+    SECItem token = { 0 };
-+    SECKEYPublicKey *pubKey = NULL;
-+    SECKEYPrivateKey *privKey = NULL;
-+    PK11GenericObject *objs = NULL;
-+    PK11GenericObject *obj = NULL;
-+    SECKEYEncryptedPrivateKeyInfo *epki = NULL;
-+    PRBool keyFound = 0;
-+    KeyType keyType;
-+
-+    fprintf(stderr, "Testing %s PrivateKeyImport ***********************\n",
-+            testname);
-+
-+    /* generate a temp key */
-+    privKey = PK11_GenerateKeyPair(slot, genMech, params, &pubKey,
-+                                   PR_FALSE, PR_TRUE, pwArgs);
-+    if (privKey == NULL) {
-+        SECU_PrintError(progName, "PK11_GenerateKeyPair Failed");
-+        goto cleanup;
-+    }
-+
-+    /* wrap the temp key */
-+    pbePwItem.data = (unsigned char *)"pw";
-+    pbePwItem.len = 2;
-+    epki = PK11_ExportEncryptedPrivKeyInfo(slot, SEC_OID_AES_256_CBC,
-+                                           &pbePwItem, privKey, 1, NULL);
-+    if (epki == NULL) {
-+        SECU_PrintError(progName, "PK11_ExportEncryptedPrivKeyInfo Failed");
-+        goto cleanup;
-+    }
-+
-+    /* Save the public value, which we will need on import */
-+    keyType = pubKey->keyType;
-+    switch (keyType) {
-+        case rsaKey:
-+            SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.rsa.modulus);
-+            break;
-+        case dhKey:
-+            SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.dh.publicValue);
-+            break;
-+        case dsaKey:
-+            SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.dsa.publicValue);
-+            break;
-+        case ecKey:
-+            SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.ec.publicValue);
-+            break;
-+        default:
-+            fprintf(stderr, "Unknown keytype = %d\n", keyType);
-+            goto cleanup;
-+    }
-+    dumpItem("pubValue", &pubValue);
-+
-+    /* when Asymetric keys represent session keys, those session keys are
-+     * destroyed when we destroy the Asymetric key representations */
-+    SECKEY_DestroyPublicKey(pubKey);
-+    pubKey = NULL;
-+    SECKEY_DestroyPrivateKey(privKey);
-+    privKey = NULL;
-+
-+    /* unwrap the temp key as a perm */
-+    nickname.data = (unsigned char *)"testKey";
-+    nickname.len = sizeof("testKey");
-+    rv = PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(slot, epki, &pbePwItem,
-+                                                        &nickname, &pubValue, PR_TRUE, PR_TRUE, keyType, 0, &privKey, NULL);
-+    if (rv != SECSuccess) {
-+        SECU_PrintError(progName, "PK11_ImportEncryptedPrivateKeyInfo Failed");
-+        goto cleanup;
-+    }
-+
-+    /* verify the public key exists */
-+    rv = PK11_ReadRawAttribute(PK11_TypePrivKey, privKey, CKA_ID, &privID);
-+    if (rv != SECSuccess) {
-+        SECU_PrintError(progName,
-+                        "Couldn't read CKA_ID from pub key, checking next key");
-+        goto cleanup;
-+    }
-+    dumpItem("privKey CKA_ID", &privID);
-+    objs = PK11_FindGenericObjects(slot, CKO_PUBLIC_KEY);
-+    for (obj = objs; obj; obj = PK11_GetNextGenericObject(obj)) {
-+        rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_ID, &pubID);
-+        if (rv != SECSuccess) {
-+            SECU_PrintError(progName,
-+                            "Couldn't read CKA_ID from pub key, checking next key");
-+            continue;
-+        }
-+        dumpItem("pubKey CKA_ID", &pubID);
-+        if (!SECITEM_ItemsAreEqual(&privID, &pubID)) {
-+            fprintf(stderr,
-+                    "CKA_ID does not match priv key, checking next key\n");
-+            SECITEM_FreeItem(&pubID, PR_FALSE);
-+            continue;
-+        }
-+        SECITEM_FreeItem(&pubID, PR_FALSE);
-+        rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_TOKEN, &token);
-+        if (rv == SECSuccess) {
-+            if (token.len == 1) {
-+                keyFound = token.data[0];
-+            }
-+            SECITEM_FreeItem(&token, PR_FALSE);
-+        }
-+        if (keyFound) {
-+            printf("matching public key found\n");
-+            break;
-+        }
-+        printf("Matching key was not a token key, checking next key\n");
-+    }
-+cleanup:
-+    if (objs) {
-+        PK11_DestroyGenericObjects(objs);
-+    }
-+    if (pubValue.data) {
-+        SECITEM_FreeItem(&pubValue, PR_FALSE);
-+    }
-+    if (privID.data) {
-+        SECITEM_FreeItem(&privID, PR_FALSE);
-+    }
-+    if (epki) {
-+        PORT_FreeArena(epki->arena, PR_TRUE);
-+    }
-+    if (pubKey) {
-+        SECKEY_DestroyPublicKey(pubKey);
-+    }
-+    if (privKey) {
-+        SECKEY_DestroyPrivateKey(privKey);
-+    }
-+    fprintf(stderr, "%s PrivateKeyImport %s ***********************\n",
-+            testname, keyFound ? "PASSED" : "FAILED");
-+    return keyFound ? SECSuccess : SECFailure;
-+}
-+
-+static const char *const usageInfo[] = {
-+    "pk11import - test PK11_PrivateKeyImport()"
-+    "Options:",
-+    " -d certdir            directory containing cert database",
-+    " -k keysize            size of the rsa, dh, and dsa key to test (default 1024)",
-+    " -C ecc_curve          ecc curve (default )",
-+    " -f pwFile             file to fetch the password from",
-+    " -p pwString           password",
-+    " -r                    skip rsa test",
-+    " -D                    skip dsa test",
-+    " -h                    skip dh test",
-+    " -e                    skip ec test",
-+};
-+static int nUsageInfo = sizeof(usageInfo) / sizeof(char *);
-+
-+static void
-+Usage(char *progName, FILE *outFile)
-+{
-+    int i;
-+    fprintf(outFile, "Usage:  %s [ commands ] options\n", progName);
-+    for (i = 0; i < nUsageInfo; i++)
-+        fprintf(outFile, "%s\n", usageInfo[i]);
-+    exit(-1);
-+}
-+
-+enum {
-+    opt_CertDir,
-+    opt_KeySize,
-+    opt_ECCurve,
-+    opt_PWFile,
-+    opt_PWString,
-+    opt_NoRSA,
-+    opt_NoDSA,
-+    opt_NoDH,
-+    opt_NoEC
-+};
-+
-+static secuCommandFlag options[] =
-+    {
-+      { /* opt_CertDir          */ 'd', PR_TRUE, 0, PR_FALSE },
-+      { /* opt_KeySize          */ 'k', PR_TRUE, 0, PR_FALSE },
-+      { /* opt_ECCurve          */ 'C', PR_TRUE, 0, PR_FALSE },
-+      { /* opt_PWFile           */ 'f', PR_TRUE, 0, PR_FALSE },
-+      { /* opt_PWString         */ 'p', PR_TRUE, 0, PR_FALSE },
-+      { /* opt_NORSA            */ 'r', PR_FALSE, 0, PR_FALSE },
-+      { /* opt_NoDSA            */ 'D', PR_FALSE, 0, PR_FALSE },
-+      { /* opt_NoDH             */ 'h', PR_FALSE, 0, PR_FALSE },
-+      { /* opt_NoEC             */ 'e', PR_FALSE, 0, PR_FALSE },
-+    };
-+
-+int
-+main(int argc, char **argv)
-+{
-+    char *progName;
-+    SECStatus rv;
-+    secuCommand args;
-+    PK11SlotInfo *slot = NULL;
-+    PRBool failed = PR_FALSE;
-+    secuPWData pwArgs = { PW_NONE, 0 };
-+    PRBool doRSA = PR_TRUE;
-+    PRBool doDSA = PR_TRUE;
-+    PRBool doDH = PR_FALSE; /* NSS currently can't export wrapped DH keys */
-+    PRBool doEC = PR_TRUE;
-+    PQGParams *pqgParams = NULL;
-+    int keySize;
-+
-+    args.numCommands = 0;
-+    args.numOptions = sizeof(options) / sizeof(secuCommandFlag);
-+    args.commands = NULL;
-+    args.options = options;
-+
-+#ifdef XP_PC
-+    progName = strrchr(argv[0], '\\');
-+#else
-+    progName = strrchr(argv[0], '/');
-+#endif
-+    progName = progName ? progName + 1 : argv[0];
-+
-+    rv = SECU_ParseCommandLine(argc, argv, progName, &args);
-+    if (SECSuccess != rv) {
-+        Usage(progName, stderr);
-+    }
-+
-+    /*  Set the certdb directory (default is ~/.netscape) */
-+    rv = NSS_InitReadWrite(SECU_ConfigDirectory(args.options[opt_CertDir].arg));
-+    if (rv != SECSuccess) {
-+        SECU_PrintPRandOSError(progName);
-+        return 255;
-+    }
-+    PK11_SetPasswordFunc(SECU_GetModulePassword);
-+
-+    /* below here, goto cleanup */
-+    SECU_RegisterDynamicOids();
-+
-+    /* handle the arguments */
-+    if (args.options[opt_PWFile].arg) {
-+        pwArgs.source = PW_FROMFILE;
-+        pwArgs.data = args.options[opt_PWFile].arg;
-+    }
-+    if (args.options[opt_PWString].arg) {
-+        pwArgs.source = PW_PLAINTEXT;
-+        pwArgs.data = args.options[opt_PWString].arg;
-+    }
-+    if (args.options[opt_NoRSA].activated) {
-+        doRSA = PR_FALSE;
-+    }
-+    if (args.options[opt_NoDSA].activated) {
-+        doDSA = PR_FALSE;
-+    }
-+    if (args.options[opt_NoDH].activated) {
-+        doDH = PR_FALSE;
-+    }
-+    if (args.options[opt_NoEC].activated) {
-+        doEC = PR_FALSE;
-+    }
-+
-+    slot = PK11_GetInternalKeySlot();
-+    if (slot == NULL) {
-+        SECU_PrintError(progName, "Couldn't find the internal key slot\n");
-+        return 255;
-+    }
-+    rv = PK11_Authenticate(slot, PR_TRUE, &pwArgs);
-+    if (rv != SECSuccess) {
-+        SECU_PrintError(progName, "Failed to log into slot");
-+        PK11_FreeSlot(slot);
-+        return 255;
-+    }
-+
-+    keySize = 1024;
-+    if (args.options[opt_KeySize].activated &&
-+        args.options[opt_KeySize].arg) {
-+        keySize = atoi(args.options[opt_KeySize].arg);
-+    }
-+
-+    if (doDSA || doDH) {
-+        PQGVerify *pqgVfy;
-+        rv = PK11_PQG_ParamGenV2(keySize, 0, keySize / 16, &pqgParams, &pqgVfy);
-+        if (rv == SECSuccess) {
-+            PK11_PQG_DestroyVerify(pqgVfy);
-+        } else {
-+            SECU_PrintError(progName,
-+                            "PK11_PQG_ParamGenV2 failed, can't test DH or DSA");
-+            doDSA = doDH = PR_FALSE;
-+            failed = PR_TRUE;
-+        }
-+    }
-+
-+    if (doRSA) {
-+        PK11RSAGenParams rsaParams;
-+        rsaParams.keySizeInBits = keySize;
-+        rsaParams.pe = 0x010001;
-+        rv = handleEncryptedPrivateImportTest(progName, slot, "RSA",
-+                                              CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams, &pwArgs);
-+        if (rv != SECSuccess) {
-+            fprintf(stderr, "RSA Import Failed!\n");
-+            failed = PR_TRUE;
-+        }
-+    }
-+    if (doDSA) {
-+        rv = handleEncryptedPrivateImportTest(progName, slot, "DSA",
-+                                              CKM_DSA_KEY_PAIR_GEN, pqgParams, &pwArgs);
-+        if (rv != SECSuccess) {
-+            fprintf(stderr, "DSA Import Failed!\n");
-+            failed = PR_TRUE;
-+        }
-+    }
-+    if (doDH) {
-+        SECKEYDHParams dhParams;
-+        dhParams.prime = pqgParams->prime;
-+        dhParams.base = pqgParams->base;
-+        rv = handleEncryptedPrivateImportTest(progName, slot, "DH",
-+                                              CKM_DH_PKCS_KEY_PAIR_GEN, &dhParams, &pwArgs);
-+        if (rv != SECSuccess) {
-+            fprintf(stderr, "DH Import Failed!\n");
-+            failed = PR_TRUE;
-+        }
-+    }
-+    if (doEC) {
-+        SECKEYECParams ecParams;
-+        SECOidData *curve = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
-+        if (args.options[opt_ECCurve].activated &&
-+            args.options[opt_ECCurve].arg) {
-+            curve = getCurveFromString(args.options[opt_ECCurve].arg);
-+        }
-+        ecParams.data = PORT_Alloc(curve->oid.len + 2);
-+        if (ecParams.data == NULL) {
-+            rv = SECFailure;
-+            goto ec_failed;
-+        }
-+        ecParams.data[0] = SEC_ASN1_OBJECT_ID;
-+        ecParams.data[1] = (unsigned char)curve->oid.len;
-+        PORT_Memcpy(&ecParams.data[2], curve->oid.data, curve->oid.len);
-+        ecParams.len = curve->oid.len + 2;
-+        rv = handleEncryptedPrivateImportTest(progName, slot, "ECC",
-+                                              CKM_EC_KEY_PAIR_GEN, &ecParams, &pwArgs);
-+        PORT_Free(ecParams.data);
-+    ec_failed:
-+        if (rv != SECSuccess) {
-+            fprintf(stderr, "ECC Import Failed!\n");
-+            failed = PR_TRUE;
-+        }
-+    }
-+
-+    if (pqgParams) {
-+        PK11_PQG_DestroyParams(pqgParams);
-+    }
-+
-+    if (slot) {
-+        PK11_FreeSlot(slot);
-+    }
-+
-+    rv = NSS_Shutdown();
-+    if (rv != SECSuccess) {
-+        fprintf(stderr, "Shutdown failed\n");
-+        SECU_PrintPRandOSError(progName);
-+        return 255;
-+    }
-+
-+    return failed ? 1 : 0;
-+}
-diff --git a/cmd/pk11import/pk11import.gyp b/cmd/pk11import/pk11import.gyp
-new file mode 100644
---- /dev/null
-+++ b/cmd/pk11import/pk11import.gyp
-@@ -0,0 +1,25 @@
-+# This Source Code Form is subject to the terms of the Mozilla Public
-+# License, v. 2.0. If a copy of the MPL was not distributed with this
-+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-+{
-+  'includes': [
-+    '../../coreconf/config.gypi',
-+    '../../cmd/platlibs.gypi'
-+  ],
-+  'targets': [
-+    {
-+      'target_name': 'pk11import',
-+      'type': 'executable',
-+      'sources': [
-+        'pk11import.c'
-+      ],
-+      'dependencies': [
-+        '<(DEPTH)/exports.gyp:dbm_exports',
-+        '<(DEPTH)/exports.gyp:nss_exports'
-+      ]
-+    }
-+  ],
-+  'variables': {
-+    'module': 'nss'
-+  }
-+}
-diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c
---- a/lib/pk11wrap/pk11akey.c
-+++ b/lib/pk11wrap/pk11akey.c
-@@ -1672,16 +1672,96 @@ PK11_MakeKEAPubKey(unsigned char *keyDat
-     rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.KEAKey, &pkData);
-     if (rv != SECSuccess) {
-         PORT_FreeArena(arena, PR_FALSE);
-         return NULL;
-     }
-     return pubk;
- }
- 
-+SECStatus
-+SECKEY_SetPublicValue(SECKEYPrivateKey *privKey, SECItem *publicValue)
-+{
-+    SECStatus rv;
-+    SECKEYPublicKey pubKey;
-+    PLArenaPool *arena;
-+    PK11SlotInfo *slot = privKey->pkcs11Slot;
-+    CK_OBJECT_HANDLE privKeyID = privKey->pkcs11ID;
-+
-+    pubKey.arena = NULL;
-+    pubKey.keyType = privKey->keyType;
-+    pubKey.pkcs11Slot = NULL;
-+    pubKey.pkcs11ID = CK_INVALID_HANDLE;
-+    /* can't use PORT_InitCheapArena here becase SECKEY_DestroyPublic is used
-+      * to free it, and it uses PORT_FreeArena which not only frees the 
-+      * underlying arena, it also frees the allocated arena struct. */
-+    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-+    pubKey.arena = arena;
-+    if (arena == NULL) {
-+        return SECFailure;
-+    }
-+    rv = SECFailure;
-+    switch (privKey->keyType) {
-+        default:
-+            /* error code already set to SECFailure */
-+            break;
-+        case rsaKey:
-+            pubKey.u.rsa.modulus = *publicValue;
-+            rv = PK11_ReadAttribute(slot, privKeyID, CKA_PUBLIC_EXPONENT,
-+                                    arena, &pubKey.u.rsa.publicExponent);
-+            break;
-+        case dsaKey:
-+            pubKey.u.dsa.publicValue = *publicValue;
-+            rv = PK11_ReadAttribute(slot, privKeyID, CKA_PRIME,
-+                                    arena, &pubKey.u.dsa.params.prime);
-+            if (rv != SECSuccess) {
-+                break;
-+            }
-+            rv = PK11_ReadAttribute(slot, privKeyID, CKA_SUBPRIME,
-+                                    arena, &pubKey.u.dsa.params.subPrime);
-+            if (rv != SECSuccess) {
-+                break;
-+            }
-+            rv = PK11_ReadAttribute(slot, privKeyID, CKA_BASE,
-+                                    arena, &pubKey.u.dsa.params.base);
-+            break;
-+        case dhKey:
-+            pubKey.u.dh.publicValue = *publicValue;
-+            rv = PK11_ReadAttribute(slot, privKeyID, CKA_PRIME,
-+                                    arena, &pubKey.u.dh.prime);
-+            if (rv != SECSuccess) {
-+                break;
-+            }
-+            rv = PK11_ReadAttribute(slot, privKeyID, CKA_BASE,
-+                                    arena, &pubKey.u.dh.base);
-+            break;
-+        case ecKey:
-+            pubKey.u.ec.publicValue = *publicValue;
-+            pubKey.u.ec.encoding = ECPoint_Undefined;
-+            pubKey.u.ec.size = 0;
-+            rv = PK11_ReadAttribute(slot, privKeyID, CKA_EC_PARAMS,
-+                                    arena, &pubKey.u.ec.DEREncodedParams);
-+            break;
-+    }
-+    if (rv == SECSuccess) {
-+        rv = PK11_ImportPublicKey(slot, &pubKey, PR_TRUE);
-+    }
-+    /* Even though pubKey is stored on the stack, we've allocated
-+     * some of it's data from the arena. SECKEY_DestroyPublicKey
-+     * destroys keys by freeing the arena, so this will clean up all
-+     * the data we allocated specifically for the key above. It will
-+     * also free any slot references which we may have picked up in
-+     * PK11_ImportPublicKey. It won't delete the underlying key if
-+     * its a Token/Permanent key (which it will be if
-+     * PK11_ImportPublicKey succeeds). */
-+    SECKEY_DestroyPublicKey(&pubKey);
-+
-+    return rv;
-+}
-+
- /*
-  * NOTE: This function doesn't return a SECKEYPrivateKey struct to represent
-  * the new private key object.  If it were to create a session object that
-  * could later be looked up by its nickname, it would leak a SECKEYPrivateKey.
-  * So isPerm must be true.
-  */
- SECStatus
- PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot,
-@@ -1797,22 +1877,16 @@ try_faulty_3des:
- 
-     PORT_Assert(usage != NULL);
-     PORT_Assert(usageCount != 0);
-     privKey = PK11_UnwrapPrivKey(slot, key, cryptoMechType,
-                                  crypto_param, &epki->encryptedData,
-                                  nickname, publicValue, isPerm, isPrivate,
-                                  key_type, usage, usageCount, wincx);
-     if (privKey) {
--        if (privk) {
--            *privk = privKey;
--        } else {
--            SECKEY_DestroyPrivateKey(privKey);
--        }
--        privKey = NULL;
-         rv = SECSuccess;
-         goto done;
-     }
- 
-     /* if we are unable to import the key and the pbeMechType is
-      * CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, then it is possible that
-      * the encrypted blob was created with a buggy key generation method
-      * which is described in the PKCS 12 implementation notes.  So we
-@@ -1832,16 +1906,35 @@ try_faulty_3des:
-         faulty3DES = PR_TRUE;
-         goto try_faulty_3des;
-     }
- 
-     /* key import really did fail */
-     rv = SECFailure;
- 
- done:
-+    if ((rv == SECSuccess) && isPerm) {
-+        /* If we are importing a token object,
-+         * create the corresponding public key.
-+         * If this fails, just continue as the target
-+         * token simply might not support persistant
-+         * public keys. Such tokens are usable, but
-+         * need to be authenticated before searching
-+         * for user certs. */
-+        (void)SECKEY_SetPublicValue(privKey, publicValue);
-+    }
-+
-+    if (privKey) {
-+        if (privk) {
-+            *privk = privKey;
-+        } else {
-+            SECKEY_DestroyPrivateKey(privKey);
-+        }
-+        privKey = NULL;
-+    }
-     if (crypto_param != NULL) {
-         SECITEM_ZfreeItem(crypto_param, PR_TRUE);
-     }
- 
-     if (key != NULL) {
-         PK11_FreeSymKey(key);
-     }
- 
-diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c
---- a/lib/softoken/pkcs11.c
-+++ b/lib/softoken/pkcs11.c
-@@ -1810,29 +1810,36 @@ sftk_GetPubKey(SFTKObject *object, CK_KE
-                  * Some curves are always pressumed to be non-DER.
-                  */
-                 if (pubKey->u.ec.publicValue.len == keyLen &&
-                     (pubKey->u.ec.ecParams.fieldID.type == ec_field_plain ||
-                      pubKey->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED)) {
-                     break; /* key was not DER encoded, no need to unwrap */
-                 }
- 
--                PORT_Assert(pubKey->u.ec.ecParams.name != ECCurve25519);
-+                /* The PKCS #11 spec says that the Params should be DER encoded. Even though the params from the
-+                 * Certificate aren't according the the ECCurve 25519 spec. We should accept this encoding.
-+                PORT_Assert(pubKey->u.ec.ecParams.name != ECCurve25519); */
- 
-                 /* handle the encoded case */
-                 if ((pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING) &&
-                     pubKey->u.ec.publicValue.len > keyLen) {
-                     SECItem publicValue;
-                     SECStatus rv;
- 
-                     rv = SEC_QuickDERDecodeItem(arena, &publicValue,
-                                                 SEC_ASN1_GET(SEC_OctetStringTemplate),
-                                                 &pubKey->u.ec.publicValue);
-                     /* nope, didn't decode correctly */
--                    if ((rv != SECSuccess) || (publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) || (publicValue.len != keyLen)) {
-+                    if ((rv != SECSuccess) || (publicValue.len != keyLen)) {
-+                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
-+                        break;
-+                    }
-+                    /* we don't handle compressed points except in the case of ECCurve25519 */
-+                    if ((pubKey->u.ec.ecParams.fieldID.type != ec_field_plain) && (publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED)) {
-                         crv = CKR_ATTRIBUTE_VALUE_INVALID;
-                         break;
-                     }
-                     /* replace our previous with the decoded key */
-                     pubKey->u.ec.publicValue = publicValue;
-                     break;
-                 }
-                 crv = CKR_ATTRIBUTE_VALUE_INVALID;
-diff --git a/nss.gyp b/nss.gyp
---- a/nss.gyp
-+++ b/nss.gyp
-@@ -159,16 +159,17 @@
-             'cmd/oidcalc/oidcalc.gyp:oidcalc',
-             'cmd/p7content/p7content.gyp:p7content',
-             'cmd/p7env/p7env.gyp:p7env',
-             'cmd/p7sign/p7sign.gyp:p7sign',
-             'cmd/p7verify/p7verify.gyp:p7verify',
-             'cmd/pk11ectest/pk11ectest.gyp:pk11ectest',
-             'cmd/pk11gcmtest/pk11gcmtest.gyp:pk11gcmtest',
-             'cmd/pk11mode/pk11mode.gyp:pk11mode',
-+            'cmd/pk11import/pk11import.gyp:pk11import',
-             'cmd/pk1sign/pk1sign.gyp:pk1sign',
-             'cmd/pp/pp.gyp:pp',
-             'cmd/rsaperf/rsaperf.gyp:rsaperf',
-             'cmd/rsapoptst/rsapoptst.gyp:rsapoptst',
-             'cmd/sdrtest/sdrtest.gyp:sdrtest',
-             'cmd/selfserv/selfserv.gyp:selfserv',
-             'cmd/shlibsign/mangle/mangle.gyp:mangle',
-             'cmd/strsclnt/strsclnt.gyp:strsclnt',
-diff --git a/tests/dbtests/dbtests.sh b/tests/dbtests/dbtests.sh
---- a/tests/dbtests/dbtests.sh
-+++ b/tests/dbtests/dbtests.sh
-@@ -247,16 +247,35 @@ dbtest_main()
-     # the old one should still be there...
-     ${BINDIR}/certutil -L -n bob -d ${CONFLICT_DIR}
-     ret=$?
-     if [ $ret -ne 0 ]; then
-       html_failed "Nicknane conflict test-setting nickname conflict incorrectly worked"
-     else
-       html_passed "Nicknane conflict test-setting nickname conflict was correctly rejected"
-     fi
--
-+    # import a token private key and make sure the corresponding public key is
-+    # created
-+    ${BINDIR}/pk11import -d ${CONFLICT_DIR} -f ${R_PWFILE}
-+    echo ${BINDIR}/pk11import -d ${CONFLICT_DIR} -f ${R_PWFILE}
-+    ret=$?
-+    if [ $ret -ne 0 ]; then
-+      html_failed "Importing Token Private Key does not create the corrresponding Public Key"
-+    else
-+      html_passed "Importing Token Private Key correctly creates the corrresponding Public Key"
-+    fi
-+    # import a token private key and make sure the corresponding public key is
-+    # created
-+    ${BINDIR}/pk11import -r -D -h -C Curve25519 -d ${CONFLICT_DIR} -f ${R_PWFILE}
-+    echo ${BINDIR}/pk11import -r -D -h -C Curve25519 -d ${CONFLICT_DIR} -f ${R_PWFILE}
-+    ret=$?
-+    if [ $ret -ne 0 ]; then
-+      html_failed "Importing ECC Curve 25519 Token Private Key does not create the corrresponding Public Key"
-+    else
-+      html_passed "Importing ECC Curve 25519 Token Private Key correctly creates the corrresponding Public Key"
-+    fi
- }
- 
- ################## main #################################################
- 
- dbtest_init 
- dbtest_main 2>&1
- dbtest_cleanup
diff --git a/SOURCES/nss-8-add-ipsec-usage-to-manpage.patch b/SOURCES/nss-8-add-ipsec-usage-to-manpage.patch
new file mode 100644
index 0000000..028ad4b
--- /dev/null
+++ b/SOURCES/nss-8-add-ipsec-usage-to-manpage.patch
@@ -0,0 +1,13 @@
+diff -up ./doc/certutil.xml.ipsec_doc ./doc/certutil.xml
+--- ./doc/certutil.xml.ipsec_doc	2019-05-10 14:14:18.000000000 -0700
++++ ./doc/certutil.xml	2019-06-05 16:49:44.229301383 -0700
+@@ -428,6 +428,9 @@ of the attribute codes:
+ 	<listitem>
+ <para><command>J</command> (as an object signer)</para>
+ 	</listitem>
++	<listitem>
++<para><command>I</command> (as an IPSEC user)</para>
++	</listitem>
+ 	</itemizedlist></listitem>
+       </varlistentry>
+ 
diff --git a/SOURCES/nss-8-fix-public-key-from-priv.patch b/SOURCES/nss-8-fix-public-key-from-priv.patch
new file mode 100644
index 0000000..1a3d1b4
--- /dev/null
+++ b/SOURCES/nss-8-fix-public-key-from-priv.patch
@@ -0,0 +1,571 @@
+diff -up ./gtests/pk11_gtest/pk11_import_unittest.cc.pub-priv-mech ./gtests/pk11_gtest/pk11_import_unittest.cc
+--- ./gtests/pk11_gtest/pk11_import_unittest.cc.pub-priv-mech	2019-05-10 14:14:18.000000000 -0700
++++ ./gtests/pk11_gtest/pk11_import_unittest.cc	2019-06-05 16:43:42.276498676 -0700
+@@ -78,17 +78,40 @@ class Pk11KeyImportTestBase : public ::t
+   CK_MECHANISM_TYPE mech_;
+ 
+  private:
++  SECItem GetPublicComponent(ScopedSECKEYPublicKey& pub_key) {
++    SECItem null = { siBuffer, NULL, 0};
++    switch(SECKEY_GetPublicKeyType(pub_key.get())) {
++    case rsaKey:
++    case rsaPssKey:
++    case rsaOaepKey:
++       return pub_key->u.rsa.modulus;
++    case keaKey:
++       return pub_key->u.kea.publicValue;
++    case dsaKey:
++       return pub_key->u.dsa.publicValue;
++    case dhKey:
++       return pub_key->u.dh.publicValue;
++    case ecKey:
++       return pub_key->u.ec.publicValue;
++    case fortezzaKey: /* depricated */
++    case nullKey:
++    /* didn't use default here so we can catch new key types at compile time */
++       break;
++    }
++    return null;
++  }
+   void CheckForPublicKey(const ScopedSECKEYPrivateKey& priv_key,
+                          const SECItem* expected_public) {
+     // Verify the public key exists.
+     StackSECItem priv_id;
++    KeyType type = SECKEY_GetPrivateKeyType(priv_key.get());
+     SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, priv_key.get(),
+                                          CKA_ID, &priv_id);
+     ASSERT_EQ(SECSuccess, rv) << "Couldn't read CKA_ID from private key: "
+                               << PORT_ErrorToName(PORT_GetError());
+ 
+     CK_ATTRIBUTE_TYPE value_type = CKA_VALUE;
+-    switch (SECKEY_GetPrivateKeyType(priv_key.get())) {
++    switch (type) {
+       case rsaKey:
+         value_type = CKA_MODULUS;
+         break;
+@@ -106,6 +129,8 @@ class Pk11KeyImportTestBase : public ::t
+         FAIL() << "unknown key type";
+     }
+ 
++    // Scan public key objects until we find one with the same CKA_ID as
++    // priv_key
+     std::unique_ptr<PK11GenericObject, PK11GenericObjectsDeleter> objs(
+         PK11_FindGenericObjects(slot_.get(), CKO_PUBLIC_KEY));
+     ASSERT_NE(nullptr, objs);
+@@ -128,20 +153,46 @@ class Pk11KeyImportTestBase : public ::t
+       ASSERT_EQ(1U, token.len);
+       ASSERT_NE(0, token.data[0]);
+ 
+-      StackSECItem value;
+-      rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, value_type, &value);
++      StackSECItem raw_value;
++      SECItem decoded_value;
++      rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, value_type, &raw_value);
+       ASSERT_EQ(SECSuccess, rv);
++      SECItem value = raw_value;
+ 
++      // Decode the EC_POINT and check the output against expected.
+       // CKA_EC_POINT isn't stable, see Bug 1520649.
++      ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
++      ASSERT_TRUE(arena);
+       if (value_type == CKA_EC_POINT) {
+-        continue;
+-      }
+ 
++        // If this fails due to the noted inconsistency, we may need to
++        // check the whole raw_value, or remove a leading UNCOMPRESSED_POINT tag
++        rv = SEC_QuickDERDecodeItem(arena.get(), &decoded_value,
++                                    SEC_ASN1_GET(SEC_OctetStringTemplate),
++                                    &raw_value);
++        ASSERT_EQ(SECSuccess, rv);
++        value = decoded_value;
++      }
+       ASSERT_TRUE(SECITEM_ItemsAreEqual(expected_public, &value))
+           << "expected: "
+           << DataBuffer(expected_public->data, expected_public->len)
+           << std::endl
+           << "actual: " << DataBuffer(value.data, value.len) << std::endl;
++
++      // Finally, convert the private to public and ensure it matches.
++      ScopedSECKEYPublicKey pub_key(
++            SECKEY_ConvertToPublicKey(priv_key.get()));
++      ASSERT_TRUE(pub_key);
++      SECItem converted_public = GetPublicComponent(pub_key);
++      ASSERT_TRUE(converted_public.len != 0);
++
++      ASSERT_TRUE(SECITEM_ItemsAreEqual(expected_public, &converted_public))
++            << "expected: "
++            << DataBuffer(expected_public->data, expected_public->len)
++            << std::endl
++            << "actual: "
++            << DataBuffer(converted_public.data, converted_public.len)
++            << std::endl;
+     }
+   }
+ 
+diff -up ./lib/cryptohi/seckey.c.pub-priv-mech ./lib/cryptohi/seckey.c
+--- ./lib/cryptohi/seckey.c.pub-priv-mech	2019-05-10 14:14:18.000000000 -0700
++++ ./lib/cryptohi/seckey.c	2019-06-05 16:43:42.277498676 -0700
+@@ -1206,6 +1206,37 @@ SECKEY_CopyPublicKey(const SECKEYPublicK
+     return NULL;
+ }
+ 
++/*
++ * Use the private key to find a public key handle. The handle will be on
++ * the same slot as the private key.
++ */
++static CK_OBJECT_HANDLE
++seckey_FindPublicKeyHandle(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk)
++{
++    CK_OBJECT_HANDLE keyID;
++
++    /* this helper function is only used below. If we want to make this more
++     * general, we would need to free up any already cached handles if the
++     * slot doesn't match up with the private key slot */
++    PORT_Assert(pubk->pkcs11ID == CK_INVALID_HANDLE);
++
++    /* first look for a matching public key */
++    keyID = PK11_MatchItem(privk->pkcs11Slot, privk->pkcs11ID, CKO_PUBLIC_KEY);
++    if (keyID != CK_INVALID_HANDLE) {
++        return keyID;
++    }
++
++    /* none found, create a temp one, make the pubk the owner */
++    pubk->pkcs11ID = PK11_DerivePubKeyFromPrivKey(privk);
++    if (pubk->pkcs11ID == CK_INVALID_HANDLE) {
++        /* end of the road. Token doesn't have matching public key, nor can
++          * token regenerate a new public key from and existing private key. */
++        return CK_INVALID_HANDLE;
++    }
++    pubk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
++    return pubk->pkcs11ID;
++}
++
+ SECKEYPublicKey *
+ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
+ {
+@@ -1213,6 +1244,8 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateK
+     PLArenaPool *arena;
+     CERTCertificate *cert;
+     SECStatus rv;
++    CK_OBJECT_HANDLE pubKeyHandle;
++    SECItem decodedPoint;
+ 
+     /*
+      * First try to look up the cert.
+@@ -1243,11 +1276,47 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateK
+ 
+     switch (privk->keyType) {
+         case nullKey:
+-        case dhKey:
+-        case dsaKey:
+             /* Nothing to query, if the cert isn't there, we're done -- no way
+              * to get the public key */
+             break;
++        case dsaKey:
++            pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk);
++            if (pubKeyHandle == CK_INVALID_HANDLE)
++                break;
++            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
++                                    CKA_BASE, arena, &pubk->u.dsa.params.base);
++            if (rv != SECSuccess)
++                break;
++            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
++                                    CKA_PRIME, arena, &pubk->u.dsa.params.prime);
++            if (rv != SECSuccess)
++                break;
++            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
++                                    CKA_SUBPRIME, arena, &pubk->u.dsa.params.subPrime);
++            if (rv != SECSuccess)
++                break;
++            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
++                                    CKA_VALUE, arena, &pubk->u.dsa.publicValue);
++            if (rv != SECSuccess)
++                break;
++            return pubk;
++        case dhKey:
++            pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk);
++            if (pubKeyHandle == CK_INVALID_HANDLE)
++                break;
++            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
++                                    CKA_BASE, arena, &pubk->u.dh.base);
++            if (rv != SECSuccess)
++                break;
++            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
++                                    CKA_PRIME, arena, &pubk->u.dh.prime);
++            if (rv != SECSuccess)
++                break;
++            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
++                                    CKA_VALUE, arena, &pubk->u.dh.publicValue);
++            if (rv != SECSuccess)
++                break;
++            return pubk;
+         case rsaKey:
+             rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
+                                     CKA_MODULUS, arena, &pubk->u.rsa.modulus);
+@@ -1258,7 +1327,6 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateK
+             if (rv != SECSuccess)
+                 break;
+             return pubk;
+-            break;
+         case ecKey:
+             rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
+                                     CKA_EC_PARAMS, arena, &pubk->u.ec.DEREncodedParams);
+@@ -1268,7 +1336,23 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateK
+             rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
+                                     CKA_EC_POINT, arena, &pubk->u.ec.publicValue);
+             if (rv != SECSuccess || pubk->u.ec.publicValue.len == 0) {
+-                break;
++                pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk);
++                if (pubKeyHandle == CK_INVALID_HANDLE)
++                    break;
++                rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
++                                        CKA_EC_POINT, arena, &pubk->u.ec.publicValue);
++                if (rv != SECSuccess)
++                    break;
++            }
++            /* ec.publicValue should be decoded, PKCS #11 defines CKA_EC_POINT
++             * as encoded, but it's not always. try do decoded it and if it
++             * succeeds store the decoded value */
++            rv = SEC_QuickDERDecodeItem(arena, &decodedPoint,
++                                        SEC_ASN1_GET(SEC_OctetStringTemplate), &pubk->u.ec.publicValue);
++            if (rv == SECSuccess) {
++                /* both values are in the public key arena, so it's safe to
++                 * overwrite  the old value */
++                pubk->u.ec.publicValue = decodedPoint;
+             }
+             pubk->u.ec.encoding = ECPoint_Undefined;
+             return pubk;
+@@ -1276,7 +1360,9 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateK
+             break;
+     }
+ 
+-    PORT_FreeArena(arena, PR_FALSE);
++    /* must use Destroy public key here, because some paths create temporary
++     * PKCS #11 objects which need to be freed */
++    SECKEY_DestroyPublicKey(pubk);
+     return NULL;
+ }
+ 
+diff -up ./lib/pk11wrap/pk11priv.h.pub-priv-mech ./lib/pk11wrap/pk11priv.h
+--- ./lib/pk11wrap/pk11priv.h.pub-priv-mech	2019-05-10 14:14:18.000000000 -0700
++++ ./lib/pk11wrap/pk11priv.h	2019-06-05 16:43:42.277498676 -0700
+@@ -111,6 +111,7 @@ CK_OBJECT_HANDLE PK11_FindObjectForCert(
+ PK11SymKey *pk11_CopyToSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
+                             CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey);
+ unsigned int pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType);
++CK_OBJECT_HANDLE PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey);
+ 
+ /**********************************************************************
+  *                   Certs
+diff -up ./lib/pk11wrap/pk11skey.c.pub-priv-mech ./lib/pk11wrap/pk11skey.c
+--- ./lib/pk11wrap/pk11skey.c.pub-priv-mech	2019-06-05 16:37:38.726685789 -0700
++++ ./lib/pk11wrap/pk11skey.c	2019-06-05 16:43:42.278498675 -0700
+@@ -1841,6 +1841,35 @@ loser:
+ }
+ 
+ /*
++ * This regenerate a public key from a private key. This function is currently
++ * NSS private. If we want to make it public, we need to add and optional
++ * template or at least flags (a.la. PK11_DeriveWithFlags).
++ */
++CK_OBJECT_HANDLE
++PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey)
++{
++    PK11SlotInfo *slot = privKey->pkcs11Slot;
++    CK_MECHANISM mechanism;
++    CK_OBJECT_HANDLE objectID = CK_INVALID_HANDLE;
++    CK_RV crv;
++
++    mechanism.mechanism = CKM_NSS_PUB_FROM_PRIV;
++    mechanism.pParameter = NULL;
++    mechanism.ulParameterLen = 0;
++
++    PK11_EnterSlotMonitor(slot);
++    crv = PK11_GETTAB(slot)->C_DeriveKey(slot->session, &mechanism,
++                                         privKey->pkcs11ID, NULL, 0,
++                                         &objectID);
++    PK11_ExitSlotMonitor(slot);
++    if (crv != CKR_OK) {
++        PORT_SetError(PK11_MapError(crv));
++        return CK_INVALID_HANDLE;
++    }
++    return objectID;
++}
++
++/*
+  * This Generates a wrapping key based on a privateKey, publicKey, and two
+  * random numbers. For Mail usage RandomB should be NULL. In the Sender's
+  * case RandomA is generate, outherwize it is passed.
+diff -up ./lib/softoken/lowkey.c.pub-priv-mech ./lib/softoken/lowkey.c
+--- ./lib/softoken/lowkey.c.pub-priv-mech	2019-05-10 14:14:18.000000000 -0700
++++ ./lib/softoken/lowkey.c	2019-06-05 16:44:20.469479019 -0700
+@@ -261,6 +261,7 @@ NSSLOWKEYPublicKey *
+ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
+ {
+     NSSLOWKEYPublicKey *pubk;
++    SECItem publicValue;
+     PLArenaPool *arena;
+ 
+     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+@@ -301,6 +302,19 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPr
+ 
+                 pubk->arena = arena;
+                 pubk->keyType = privk->keyType;
++                /* if the public key value doesn't exist, calculate it */
++                if (privk->u.dsa.publicValue.len == 0) {
++                    rv = DH_Derive(&privk->u.dsa.params.base, &privk->u.dsa.params.prime,
++                                   &privk->u.dsa.privateValue, &publicValue, 0);
++                    if (rv != SECSuccess) {
++                        break;
++                    }
++                    rv = SECITEM_CopyItem(privk->arena, &privk->u.dsa.publicValue, &publicValue);
++                    SECITEM_FreeItem(&publicValue, PR_FALSE);
++                    if (rv != SECSuccess) {
++                        break;
++                    }
++                }
+                 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
+                                       &privk->u.dsa.publicValue);
+                 if (rv != SECSuccess)
+@@ -327,6 +341,19 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPr
+ 
+                 pubk->arena = arena;
+                 pubk->keyType = privk->keyType;
++                /* if the public key value doesn't exist, calculate it */
++                if (privk->u.dh.publicValue.len == 0) {
++                    rv = DH_Derive(&privk->u.dh.base, &privk->u.dh.prime,
++                                   &privk->u.dh.privateValue, &publicValue, 0);
++                    if (rv != SECSuccess) {
++                        break;
++                    }
++                    rv = SECITEM_CopyItem(privk->arena, &privk->u.dh.publicValue, &publicValue);
++                    SECITEM_FreeItem(&publicValue, PR_FALSE);
++                    if (rv != SECSuccess) {
++                        break;
++                    }
++                }
+                 rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
+                                       &privk->u.dh.publicValue);
+                 if (rv != SECSuccess)
+diff -up ./lib/softoken/pkcs11c.c.pub-priv-mech ./lib/softoken/pkcs11c.c
+--- ./lib/softoken/pkcs11c.c.pub-priv-mech	2019-06-05 16:37:38.743685780 -0700
++++ ./lib/softoken/pkcs11c.c	2019-06-05 16:44:20.472479017 -0700
+@@ -6569,6 +6569,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
+             extractValue = PR_FALSE;
+             classType = CKO_PRIVATE_KEY;
+             break;
++        case CKM_NSS_PUB_FROM_PRIV:
++            extractValue = PR_FALSE;
++            classType = CKO_PUBLIC_KEY;
++            break;
+         case CKM_NSS_JPAKE_FINAL_SHA1:   /* fall through */
+         case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
+         case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
+@@ -6610,6 +6614,35 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
+     }
+ 
+     switch (mechanism) {
++        /* get a public key from a private key. nsslowkey_ConvertToPublickey()
++         * will generate the public portion if it doesn't already exist. */
++        case CKM_NSS_PUB_FROM_PRIV: {
++            NSSLOWKEYPrivateKey *privKey;
++            NSSLOWKEYPublicKey *pubKey;
++            int error;
++
++            crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType);
++            if (crv != CKR_OK) {
++                break;
++            }
++
++            /* privKey is stored in sourceKey and will be destroyed when
++             * the sourceKey is freed. */
++            privKey = sftk_GetPrivKey(sourceKey, keyType, &crv);
++            if (privKey == NULL) {
++                break;
++            }
++            pubKey = nsslowkey_ConvertToPublicKey(privKey);
++            if (pubKey == NULL) {
++                error = PORT_GetError();
++                crv = sftk_MapCryptError(error);
++                break;
++            }
++            crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey);
++            nsslowkey_DestroyPublicKey(pubKey);
++            break;
++        }
++
+         case CKM_NSS_IKE_PRF_DERIVE:
+             if (pMechanism->ulParameterLen !=
+                 sizeof(CK_NSS_IKE_PRF_DERIVE_PARAMS)) {
+diff -up ./lib/softoken/pkcs11.c.pub-priv-mech ./lib/softoken/pkcs11.c
+--- ./lib/softoken/pkcs11.c.pub-priv-mech	2019-06-05 16:37:38.728685788 -0700
++++ ./lib/softoken/pkcs11.c	2019-06-05 16:44:20.473479017 -0700
+@@ -2206,6 +2206,123 @@ sftk_GetPrivKey(SFTKObject *object, CK_K
+     return priv;
+ }
+ 
++/* populate a public key object from a lowpublic keys structure */
++CK_RV
++sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType, NSSLOWKEYPublicKey *pubKey)
++{
++    CK_OBJECT_CLASS classType = CKO_PUBLIC_KEY;
++    CK_BBOOL cktrue = CK_TRUE;
++    CK_RV crv = CKR_OK;
++    sftk_DeleteAttributeType(publicKey, CKA_CLASS);
++    sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE);
++    sftk_DeleteAttributeType(publicKey, CKA_VALUE);
++
++    switch (keyType) {
++        case CKK_RSA:
++            sftk_DeleteAttributeType(publicKey, CKA_MODULUS);
++            sftk_DeleteAttributeType(publicKey, CKA_PUBLIC_EXPONENT);
++            /* format the keys */
++            /* fill in the RSA dependent paramenters in the public key */
++            crv = sftk_AddAttributeType(publicKey, CKA_MODULUS,
++                                        sftk_item_expand(&pubKey->u.rsa.modulus));
++            if (crv != CKR_OK)
++                break;
++            crv = sftk_AddAttributeType(publicKey, CKA_PUBLIC_EXPONENT,
++                                        sftk_item_expand(&pubKey->u.rsa.publicExponent));
++            break;
++        case CKK_DSA:
++            sftk_DeleteAttributeType(publicKey, CKA_PRIME);
++            sftk_DeleteAttributeType(publicKey, CKA_SUBPRIME);
++            sftk_DeleteAttributeType(publicKey, CKA_BASE);
++            crv = sftk_AddAttributeType(publicKey, CKA_PRIME,
++                                        sftk_item_expand(&pubKey->u.dsa.params.prime));
++            if (crv != CKR_OK) {
++                break;
++            }
++            crv = sftk_AddAttributeType(publicKey, CKA_SUBPRIME,
++                                        sftk_item_expand(&pubKey->u.dsa.params.subPrime));
++            if (crv != CKR_OK) {
++                break;
++            }
++            crv = sftk_AddAttributeType(publicKey, CKA_BASE,
++                                        sftk_item_expand(&pubKey->u.dsa.params.base));
++            if (crv != CKR_OK) {
++                break;
++            }
++            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
++                                        sftk_item_expand(&pubKey->u.dsa.publicValue));
++            break;
++
++        case CKK_DH:
++            sftk_DeleteAttributeType(publicKey, CKA_PRIME);
++            sftk_DeleteAttributeType(publicKey, CKA_BASE);
++            crv = sftk_AddAttributeType(publicKey, CKA_PRIME,
++                                        sftk_item_expand(&pubKey->u.dh.prime));
++            if (crv != CKR_OK) {
++                break;
++            }
++            crv = sftk_AddAttributeType(publicKey, CKA_BASE,
++                                        sftk_item_expand(&pubKey->u.dh.base));
++            if (crv != CKR_OK) {
++                break;
++            }
++            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
++                                        sftk_item_expand(&pubKey->u.dh.publicValue));
++            break;
++
++        case CKK_EC:
++            sftk_DeleteAttributeType(publicKey, CKA_EC_PARAMS);
++            sftk_DeleteAttributeType(publicKey, CKA_EC_POINT);
++
++            crv = sftk_AddAttributeType(publicKey, CKA_EC_PARAMS,
++                                        sftk_item_expand(&pubKey->u.ec.ecParams.DEREncoding));
++            if (crv != CKR_OK) {
++                break;
++            }
++
++            crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
++                                        sftk_item_expand(&pubKey->u.ec.publicValue));
++            break;
++
++        default:
++            return CKR_KEY_TYPE_INCONSISTENT;
++    }
++    crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &classType,
++                                sizeof(CK_OBJECT_CLASS));
++    if (crv != CKR_OK)
++        return crv;
++    crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &keyType,
++                                sizeof(CK_KEY_TYPE));
++    if (crv != CKR_OK)
++        return crv;
++    /* now handle the operator attributes */
++    if (sftk_isTrue(privateKey, CKA_DECRYPT)) {
++        crv = sftk_forceAttribute(publicKey, CKA_ENCRYPT, &cktrue, sizeof(CK_BBOOL));
++        if (crv != CKR_OK) {
++            return crv;
++        }
++    }
++    if (sftk_isTrue(privateKey, CKA_SIGN)) {
++        crv = sftk_forceAttribute(publicKey, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
++        if (crv != CKR_OK) {
++            return crv;
++        }
++    }
++    if (sftk_isTrue(privateKey, CKA_SIGN_RECOVER)) {
++        crv = sftk_forceAttribute(publicKey, CKA_VERIFY_RECOVER, &cktrue, sizeof(CK_BBOOL));
++        if (crv != CKR_OK) {
++            return crv;
++        }
++    }
++    if (sftk_isTrue(privateKey, CKA_DERIVE)) {
++        crv = sftk_forceAttribute(publicKey, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
++        if (crv != CKR_OK) {
++            return crv;
++        }
++    }
++    return crv;
++}
++
+ /*
+  **************************** Symetric Key utils ************************
+  */
+diff -up ./lib/softoken/pkcs11i.h.pub-priv-mech ./lib/softoken/pkcs11i.h
+--- ./lib/softoken/pkcs11i.h.pub-priv-mech	2019-06-05 16:37:38.730685787 -0700
++++ ./lib/softoken/pkcs11i.h	2019-06-05 16:44:20.473479017 -0700
+@@ -695,6 +695,9 @@ extern NSSLOWKEYPublicKey *sftk_GetPubKe
+                                           CK_KEY_TYPE key_type, CK_RV *crvp);
+ extern NSSLOWKEYPrivateKey *sftk_GetPrivKey(SFTKObject *object,
+                                             CK_KEY_TYPE key_type, CK_RV *crvp);
++extern CK_RV sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privKey,
++                            CK_KEY_TYPE keyType,
++                            NSSLOWKEYPublicKey *pubKey);
+ extern void sftk_FormatDESKey(unsigned char *key, int length);
+ extern PRBool sftk_CheckDESKey(unsigned char *key);
+ extern PRBool sftk_IsWeakKey(unsigned char *key, CK_KEY_TYPE key_type);
+diff -up ./lib/util/pkcs11n.h.pub-priv-mech ./lib/util/pkcs11n.h
+--- ./lib/util/pkcs11n.h.pub-priv-mech	2019-06-05 16:37:38.733685785 -0700
++++ ./lib/util/pkcs11n.h	2019-06-05 16:44:54.389461561 -0700
+@@ -152,11 +152,6 @@
+ #define CKM_NSS_HKDF_SHA384 (CKM_NSS + 5)
+ #define CKM_NSS_HKDF_SHA512 (CKM_NSS + 6)
+ 
+-/* IKE mechanism (to be proposed to PKCS #11 */
+-#define CKM_NSS_IKE_PRF_PLUS_DERIVE (CKM_NSS + 7)
+-#define CKM_NSS_IKE_PRF_DERIVE (CKM_NSS + 8)
+-#define CKM_NSS_IKE1_PRF_DERIVE (CKM_NSS + 9)
+-#define CKM_NSS_IKE1_APP_B_PRF_DERIVE (CKM_NSS + 10)
+ 
+ /* J-PAKE round 1 key generation mechanisms.
+  *
+@@ -238,6 +233,15 @@
+ 
+ #define CKM_NSS_CHACHA20_CTR (CKM_NSS + 33)
+ 
++/* IKE mechanism (to be proposed to PKCS #11 */
++#define CKM_NSS_IKE_PRF_PLUS_DERIVE (CKM_NSS + 34)
++#define CKM_NSS_IKE_PRF_DERIVE (CKM_NSS + 35)
++#define CKM_NSS_IKE1_PRF_DERIVE (CKM_NSS + 36)
++#define CKM_NSS_IKE1_APP_B_PRF_DERIVE (CKM_NSS + 37)
++
++/* Derive a public key from a bare private key */
++#define CKM_NSS_PUB_FROM_PRIV (CKM_NSS + 40)
++
+ /*
+  * HISTORICAL:
+  * Do not attempt to use these. They are only used by NETSCAPE's internal
diff --git a/SOURCES/nss-disable-pkcs1-sigalgs-tls13.patch b/SOURCES/nss-disable-pkcs1-sigalgs-tls13.patch
new file mode 100644
index 0000000..1b57e75
--- /dev/null
+++ b/SOURCES/nss-disable-pkcs1-sigalgs-tls13.patch
@@ -0,0 +1,202 @@
+# HG changeset patch
+# User Daiki Ueno <dueno@redhat.com>
+# Date 1559031046 -7200
+#      Tue May 28 10:10:46 2019 +0200
+# Node ID 0a4e8b72a92e144663c2f35d3836f7828cfc97f2
+# Parent  370a9e85f216f5f4ff277995a997c5c9b23a819f
+Bug 1552208, prohibit use of RSASSA-PKCS1-v1_5 algorithms in TLS 1.3, r=mt
+
+Reviewers: mt
+
+Reviewed By: mt
+
+Subscribers: mt, jcj, ueno, rrelyea, HubertKario, KevinJacobs
+
+Tags: #secure-revision, #bmo-crypto-core-security
+
+Bug #: 1552208
+
+Differential Revision: https://phabricator.services.mozilla.com/D32454
+
+diff --git a/gtests/ssl_gtest/ssl_auth_unittest.cc b/gtests/ssl_gtest/ssl_auth_unittest.cc
+--- a/gtests/ssl_gtest/ssl_auth_unittest.cc
++++ b/gtests/ssl_gtest/ssl_auth_unittest.cc
+@@ -701,6 +701,44 @@ TEST_P(TlsConnectTls12, ClientAuthIncons
+   ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
+ }
+ 
++TEST_P(TlsConnectTls13, ClientAuthPkcs1SignatureScheme) {
++  static const SSLSignatureScheme kSignatureScheme[] = {
++      ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pss_rsae_sha256};
++
++  Reset(TlsAgent::kServerRsa, "rsa");
++  client_->SetSignatureSchemes(kSignatureScheme,
++                               PR_ARRAY_SIZE(kSignatureScheme));
++  server_->SetSignatureSchemes(kSignatureScheme,
++                               PR_ARRAY_SIZE(kSignatureScheme));
++  client_->SetupClientAuth();
++  server_->RequestClientAuth(true);
++
++  auto capture_cert_verify = MakeTlsFilter<TlsHandshakeRecorder>(
++      client_, kTlsHandshakeCertificateVerify);
++  capture_cert_verify->EnableDecryption();
++
++  Connect();
++  CheckSigScheme(capture_cert_verify, 0, server_, ssl_sig_rsa_pss_rsae_sha256,
++                 1024);
++}
++
++TEST_P(TlsConnectTls13, ClientAuthPkcs1SignatureSchemeOnly) {
++  static const SSLSignatureScheme kSignatureScheme[] = {
++      ssl_sig_rsa_pkcs1_sha256};
++
++  Reset(TlsAgent::kServerRsa, "rsa");
++  client_->SetSignatureSchemes(kSignatureScheme,
++                               PR_ARRAY_SIZE(kSignatureScheme));
++  server_->SetSignatureSchemes(kSignatureScheme,
++                               PR_ARRAY_SIZE(kSignatureScheme));
++  client_->SetupClientAuth();
++  server_->RequestClientAuth(true);
++
++  ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
++  server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
++  client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
++}
++
+ class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter {
+  public:
+   TlsZeroCertificateRequestSigAlgsFilter(const std::shared_ptr<TlsAgent>& a)
+@@ -933,7 +971,7 @@ TEST_P(TlsConnectTls13, InconsistentSign
+   client_->CheckErrorCode(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
+ }
+ 
+-TEST_P(TlsConnectTls12Plus, RequestClientAuthWithSha384) {
++TEST_P(TlsConnectTls12, RequestClientAuthWithSha384) {
+   server_->SetSignatureSchemes(kSignatureSchemeRsaSha384,
+                                PR_ARRAY_SIZE(kSignatureSchemeRsaSha384));
+   server_->RequestClientAuth(false);
+@@ -1395,12 +1433,21 @@ TEST_P(TlsSignatureSchemeConfiguration, 
+ INSTANTIATE_TEST_CASE_P(
+     SignatureSchemeRsa, TlsSignatureSchemeConfiguration,
+     ::testing::Combine(
+-        TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV12Plus,
++        TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV12,
+         ::testing::Values(TlsAgent::kServerRsaSign),
+         ::testing::Values(ssl_auth_rsa_sign),
+         ::testing::Values(ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pkcs1_sha384,
+                           ssl_sig_rsa_pkcs1_sha512, ssl_sig_rsa_pss_rsae_sha256,
+                           ssl_sig_rsa_pss_rsae_sha384)));
++// RSASSA-PKCS1-v1_5 is not allowed to be used in TLS 1.3
++INSTANTIATE_TEST_CASE_P(
++    SignatureSchemeRsaTls13, TlsSignatureSchemeConfiguration,
++    ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
++                       TlsConnectTestBase::kTlsV13,
++                       ::testing::Values(TlsAgent::kServerRsaSign),
++                       ::testing::Values(ssl_auth_rsa_sign),
++                       ::testing::Values(ssl_sig_rsa_pss_rsae_sha256,
++                                         ssl_sig_rsa_pss_rsae_sha384)));
+ // PSS with SHA-512 needs a bigger key to work.
+ INSTANTIATE_TEST_CASE_P(
+     SignatureSchemeBigRsa, TlsSignatureSchemeConfiguration,
+diff --git a/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc b/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc
+--- a/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc
++++ b/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc
+@@ -68,12 +68,6 @@ class TlsCipherSuiteTestBase : public Tl
+   virtual void SetupCertificate() {
+     if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+       switch (sig_scheme_) {
+-        case ssl_sig_rsa_pkcs1_sha256:
+-        case ssl_sig_rsa_pkcs1_sha384:
+-        case ssl_sig_rsa_pkcs1_sha512:
+-          Reset(TlsAgent::kServerRsaSign);
+-          auth_type_ = ssl_auth_rsa_sign;
+-          break;
+         case ssl_sig_rsa_pss_rsae_sha256:
+         case ssl_sig_rsa_pss_rsae_sha384:
+           Reset(TlsAgent::kServerRsaSign);
+@@ -330,6 +324,12 @@ static SSLSignatureScheme kSignatureSche
+     ssl_sig_rsa_pss_pss_sha256,     ssl_sig_rsa_pss_pss_sha384,
+     ssl_sig_rsa_pss_pss_sha512};
+ 
++static SSLSignatureScheme kSignatureSchemesParamsArrTls13[] = {
++    ssl_sig_ecdsa_secp256r1_sha256, ssl_sig_ecdsa_secp384r1_sha384,
++    ssl_sig_rsa_pss_rsae_sha256,    ssl_sig_rsa_pss_rsae_sha384,
++    ssl_sig_rsa_pss_rsae_sha512,    ssl_sig_rsa_pss_pss_sha256,
++    ssl_sig_rsa_pss_pss_sha384,     ssl_sig_rsa_pss_pss_sha512};
++
+ INSTANTIATE_CIPHER_TEST_P(RC4, Stream, V10ToV12, kDummyNamedGroupParams,
+                           kDummySignatureSchemesParams,
+                           TLS_RSA_WITH_RC4_128_SHA,
+@@ -394,7 +394,7 @@ INSTANTIATE_CIPHER_TEST_P(
+ #ifndef NSS_DISABLE_TLS_1_3
+ INSTANTIATE_CIPHER_TEST_P(TLS13, All, V13,
+                           ::testing::ValuesIn(kFasterDHEGroups),
+-                          ::testing::ValuesIn(kSignatureSchemesParamsArr),
++                          ::testing::ValuesIn(kSignatureSchemesParamsArrTls13),
+                           TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256,
+                           TLS_AES_256_GCM_SHA384);
+ INSTANTIATE_CIPHER_TEST_P(TLS13AllGroups, All, V13,
+diff --git a/gtests/ssl_gtest/ssl_extension_unittest.cc b/gtests/ssl_gtest/ssl_extension_unittest.cc
+--- a/gtests/ssl_gtest/ssl_extension_unittest.cc
++++ b/gtests/ssl_gtest/ssl_extension_unittest.cc
+@@ -436,14 +436,14 @@ TEST_P(TlsExtensionTest12Plus, Signature
+ }
+ 
+ TEST_F(TlsExtensionTest13Stream, SignatureAlgorithmsPrecedingGarbage) {
+-  // 31 unknown signature algorithms followed by sha-256, rsa
++  // 31 unknown signature algorithms followed by sha-256, rsa-pss
+   const uint8_t val[] = {
+       0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+-      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0x01};
++      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x04};
+   DataBuffer extension(val, sizeof(val));
+   MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_signature_algorithms_xtn,
+                                       extension);
+diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
+--- a/lib/ssl/ssl3con.c
++++ b/lib/ssl/ssl3con.c
+@@ -64,6 +64,7 @@ static SECStatus ssl3_FlushHandshakeMess
+ static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType);
+ static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash);
+ PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme);
++PRBool ssl_IsRsaPkcs1SignatureScheme(SSLSignatureScheme scheme);
+ PRBool ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme);
+ 
+ const PRUint8 ssl_hello_retry_random[] = {
+@@ -4101,6 +4102,9 @@ ssl_SignatureSchemeValid(SSLSignatureSch
+         if (ssl_SignatureSchemeToHashType(scheme) == ssl_hash_sha1) {
+             return PR_FALSE;
+         }
++        if (ssl_IsRsaPkcs1SignatureScheme(scheme)) {
++            return PR_FALSE;
++        }
+         /* With TLS 1.3, EC keys should have been selected based on calling
+          * ssl_SignatureSchemeFromSpki(), reject them otherwise. */
+         return spkiOid != SEC_OID_ANSIX962_EC_PUBLIC_KEY;
+@@ -4351,6 +4355,22 @@ ssl_IsRsaPssSignatureScheme(SSLSignature
+ }
+ 
+ PRBool
++ssl_IsRsaPkcs1SignatureScheme(SSLSignatureScheme scheme)
++{
++    switch (scheme) {
++        case ssl_sig_rsa_pkcs1_sha256:
++        case ssl_sig_rsa_pkcs1_sha384:
++        case ssl_sig_rsa_pkcs1_sha512:
++        case ssl_sig_rsa_pkcs1_sha1:
++            return PR_TRUE;
++
++        default:
++            return PR_FALSE;
++    }
++    return PR_FALSE;
++}
++
++PRBool
+ ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme)
+ {
+     switch (scheme) {
diff --git a/SOURCES/nss-drbg-continuous.patch b/SOURCES/nss-drbg-continuous.patch
new file mode 100644
index 0000000..742f2e4
--- /dev/null
+++ b/SOURCES/nss-drbg-continuous.patch
@@ -0,0 +1,169 @@
+# HG changeset patch
+# User Daiki Ueno <dueno@redhat.com>
+# Date 1561465415 -7200
+#      Tue Jun 25 14:23:35 2019 +0200
+# Node ID a0114e3d8b22d4c6ee77504c483a0fe0037f4c71
+# Parent  313dfef345bd93bc67982249bffa2cfdd5a9d1b5
+Bug 1560329, drbg: perform continuous test on entropy source
+
+Summary: FIPS 140-2 section 4.9.2 requires a conditional self test to check that consecutive entropy blocks from the system are different.  As neither getentropy() nor /dev/urandom provides that check on the output, this adds the self test at caller side.
+
+Reviewers: rrelyea
+
+Bug #: 1560329
+
+Differential Revision: https://phabricator.services.mozilla.com/D35636
+
+diff --git a/lib/freebl/drbg.c b/lib/freebl/drbg.c
+--- a/lib/freebl/drbg.c
++++ b/lib/freebl/drbg.c
+@@ -30,6 +30,7 @@
+ #define PRNG_ADDITONAL_DATA_CACHE_SIZE (8 * 1024) /* must be less than          \
+                                                    *  PRNG_MAX_ADDITIONAL_BYTES \
+                                                    */
++#define PRNG_ENTROPY_BLOCK_SIZE SHA256_LENGTH
+ 
+ /* RESEED_COUNT is how many calls to the prng before we need to reseed
+  * under normal NIST rules, you must return an error. In the NSS case, we
+@@ -96,6 +97,8 @@ struct RNGContextStr {
+     PRUint32 additionalAvail;
+     PRBool isValid;   /* false if RNG reaches an invalid state */
+     PRBool isKatTest; /* true if running NIST PRNG KAT tests */
++    /* for continuous entropy check */
++    PRUint8 previousEntropyHash[SHA256_LENGTH];
+ };
+ 
+ typedef struct RNGContextStr RNGContext;
+@@ -169,6 +172,82 @@ prng_instantiate(RNGContext *rng, const 
+     return SECSuccess;
+ }
+ 
++static PRCallOnceType coRNGInitEntropy;
++
++static PRStatus
++prng_initEntropy(void)
++{
++    size_t length;
++    PRUint8 block[PRNG_ENTROPY_BLOCK_SIZE];
++    SHA256Context ctx;
++
++    /* For FIPS 140-2 4.9.2 continuous random number generator test,
++     * fetch the initial entropy from the system RNG and keep it for
++     * later comparison. */
++    length = RNG_SystemRNG(block, sizeof(block));
++    if (length == 0) {
++        return PR_FAILURE; /* error is already set */
++    }
++    PORT_Assert(length == sizeof(block));
++
++    /* Store the hash of the entropy block rather than the block
++     * itself for backward secrecy. */
++    SHA256_Begin(&ctx);
++    SHA256_Update(&ctx, block, sizeof(block));
++    SHA256_End(&ctx, globalrng->previousEntropyHash, NULL,
++               sizeof(globalrng->previousEntropyHash));
++    PORT_Memset(block, 0, sizeof(block));
++    return PR_SUCCESS;
++}
++
++static SECStatus
++prng_getEntropy(PRUint8 *buffer, size_t requestLength)
++{
++    size_t total = 0;
++    PRUint8 block[PRNG_ENTROPY_BLOCK_SIZE];
++    PRUint8 hash[SHA256_LENGTH];
++    SHA256Context ctx;
++    SECStatus rv = SECSuccess;
++
++    if (PR_CallOnce(&coRNGInitEntropy, prng_initEntropy) != PR_SUCCESS) {
++        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++        return SECFailure;
++    }
++
++    /* For FIPS 140-2 4.9.2 continuous random generator test,
++     * iteratively fetch fixed sized blocks from the system and
++     * compare consecutive blocks. */
++    while (total < requestLength) {
++        size_t length = RNG_SystemRNG(block, sizeof(block));
++        if (length == 0) {
++            rv = SECFailure; /* error is already set */
++            goto out;
++        }
++        PORT_Assert(length == sizeof(block));
++
++        /* Store the hash of the entropy block rather than the block
++         * itself for backward secrecy. */
++        SHA256_Begin(&ctx);
++        SHA256_Update(&ctx, block, sizeof(block));
++        SHA256_End(&ctx, hash, NULL, sizeof(hash));
++
++        if (PORT_Memcmp(globalrng->previousEntropyHash, hash, sizeof(hash)) == 0) {
++            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++            rv = SECFailure;
++            goto out;
++        }
++        PORT_Memcpy(globalrng->previousEntropyHash, hash, sizeof(hash));
++        length = PR_MIN(requestLength - total, sizeof(block));
++        PORT_Memcpy(buffer, block, length);
++        total += length;
++        buffer += length;
++    }
++
++  out:
++    PORT_Memset(block, 0, sizeof block);
++    return rv;
++}
++
+ /*
+  * Update the global random number generator with more seeding
+  * material. Use the Hash_DRBG reseed algorithm from NIST SP-800-90
+@@ -182,11 +261,15 @@ prng_reseed(RNGContext *rng, const PRUin
+ {
+     PRUint8 noiseData[(sizeof rng->V_Data) + PRNG_SEEDLEN];
+     PRUint8 *noise = &noiseData[0];
++    SECStatus rv;
+ 
+     /* if entropy wasn't supplied, fetch it. (normal operation case) */
+     if (entropy == NULL) {
+-        entropy_len = (unsigned int)RNG_SystemRNG(
+-            &noiseData[sizeof rng->V_Data], PRNG_SEEDLEN);
++        entropy_len = PRNG_SEEDLEN;
++        rv = prng_getEntropy(&noiseData[sizeof rng->V_Data], entropy_len);
++        if (rv != SECSuccess) {
++            return SECFailure; /* error is already set */
++        }
+     } else {
+         /* NOTE: this code is only available for testing, not to applications */
+         /* if entropy was too big for the stack variable, get it from malloc */
+@@ -384,7 +467,6 @@ static PRStatus
+ rng_init(void)
+ {
+     PRUint8 bytes[PRNG_SEEDLEN * 2]; /* entropy + nonce */
+-    unsigned int numBytes;
+     SECStatus rv = SECSuccess;
+ 
+     if (globalrng == NULL) {
+@@ -403,18 +485,17 @@ rng_init(void)
+         }
+ 
+         /* Try to get some seed data for the RNG */
+-        numBytes = (unsigned int)RNG_SystemRNG(bytes, sizeof bytes);
+-        PORT_Assert(numBytes == 0 || numBytes == sizeof bytes);
+-        if (numBytes != 0) {
++        rv = prng_getEntropy(bytes, sizeof bytes);
++        if (rv == SECSuccess) {
+             /* if this is our first call,  instantiate, otherwise reseed
+              * prng_instantiate gets a new clean state, we want to mix
+              * any previous entropy we may have collected */
+             if (V(globalrng)[0] == 0) {
+-                rv = prng_instantiate(globalrng, bytes, numBytes);
++                rv = prng_instantiate(globalrng, bytes, sizeof bytes);
+             } else {
+-                rv = prng_reseed_test(globalrng, bytes, numBytes, NULL, 0);
++                rv = prng_reseed_test(globalrng, bytes, sizeof bytes, NULL, 0);
+             }
+-            memset(bytes, 0, numBytes);
++            memset(bytes, 0, sizeof bytes);
+         } else {
+             PZ_DestroyLock(globalrng->lock);
+             globalrng->lock = NULL;
diff --git a/SOURCES/nss-dsa.patch b/SOURCES/nss-dsa.patch
deleted file mode 100644
index 6a068f7..0000000
--- a/SOURCES/nss-dsa.patch
+++ /dev/null
@@ -1,170 +0,0 @@
-# HG changeset patch
-# User Daiki Ueno <dueno@redhat.com>
-# Date 1542120846 -3600
-#      Tue Nov 13 15:54:06 2018 +0100
-# Node ID 5046749fa8a56a99c251bc1cdd1b3302f43947d2
-# Parent  0d97145d524ab35b8bc2a4a8aea60a83bd244f14
-Bug 1493936, add a new "DSA" policy keyword
-
-Summary:
-This adds a new policy keyword "DSA" to explicitly disable DSA in TLS 1.2 or earlier.
-
-We could make this a bit more generic, e.g., by adding "ECDSA", "RSA-PSS" etc.   However, considering the current use of policy in [fedora-crypto-policies](https://gitlab.com/redhat-crypto/fedora-crypto-policies), I realized that adding new keywords may cause compatibility problems; because the Fedora configuration has `disallow=ALL`, all new keywords would be disabled by default.   I think it's okay for DSA, though.
-
-Reviewers: kaie
-
-Reviewed By: kaie
-
-Bug #: 1493936
-
-Differential Revision: https://phabricator.services.mozilla.com/D6777
-
-diff --git a/lib/certhigh/certvfy.c b/lib/certhigh/certvfy.c
---- a/lib/certhigh/certvfy.c
-+++ b/lib/certhigh/certvfy.c
-@@ -37,7 +37,7 @@ CERT_CertTimesValid(CERTCertificate *c)
-     return (valid == secCertTimeValid) ? SECSuccess : SECFailure;
- }
- 
--SECStatus
-+static SECStatus
- checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
- {
-     SECStatus rv;
-@@ -47,6 +47,12 @@ checkKeyParams(const SECAlgorithmID *sig
-     PRInt32 minLen, len;
- 
-     sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
-+    rv = NSS_GetAlgorithmPolicy(sigAlg, &policyFlags);
-+    if (rv == SECSuccess &&
-+        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
-+        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
-+        return SECFailure;
-+    }
- 
-     switch (sigAlg) {
-         case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
-diff --git a/lib/pk11wrap/pk11pars.c b/lib/pk11wrap/pk11pars.c
---- a/lib/pk11wrap/pk11pars.c
-+++ b/lib/pk11wrap/pk11pars.c
-@@ -384,18 +384,26 @@ static const oidValDef kxOptList[] = {
-     { CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX },
- };
- 
-+static const oidValDef signOptList[] = {
-+    /* Signatures */
-+    { CIPHER_NAME("DSA"), SEC_OID_ANSIX9_DSA_SIGNATURE,
-+      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
-+};
-+
- typedef struct {
-     const oidValDef *list;
-     PRUint32 entries;
-     const char *description;
-+    PRBool allowEmpty;
- } algListsDef;
- 
- static const algListsDef algOptLists[] = {
--    { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC" },
--    { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH" },
--    { macOptList, PR_ARRAY_SIZE(macOptList), "MAC" },
--    { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER" },
--    { kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX" },
-+    { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC", PR_FALSE },
-+    { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH", PR_FALSE },
-+    { macOptList, PR_ARRAY_SIZE(macOptList), "MAC", PR_FALSE },
-+    { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER", PR_FALSE },
-+    { kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX", PR_FALSE },
-+    { signOptList, PR_ARRAY_SIZE(signOptList), "OTHER-SIGN", PR_TRUE },
- };
- 
- static const optionFreeDef sslOptList[] = {
-@@ -718,7 +726,7 @@ secmod_sanityCheckCryptoPolicy(void)
-     for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
-         const algListsDef *algOptList = &algOptLists[i];
-         fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s: %u\n", enabledCount[i] ? sInfo : sWarn, algOptList->description, enabledCount[i]);
--        if (!enabledCount[i]) {
-+        if (!enabledCount[i] && !algOptList->allowEmpty) {
-             haveWarning = PR_TRUE;
-         }
-     }
-diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
---- a/lib/ssl/ssl3con.c
-+++ b/lib/ssl/ssl3con.c
-@@ -64,6 +64,7 @@ static SECStatus ssl3_FlushHandshakeMess
- static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType);
- static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash);
- PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme);
-+PRBool ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme);
- 
- const PRUint8 ssl_hello_retry_random[] = {
-     0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
-@@ -4309,6 +4310,22 @@ ssl_IsRsaPssSignatureScheme(SSLSignature
-     return PR_FALSE;
- }
- 
-+PRBool
-+ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme)
-+{
-+    switch (scheme) {
-+        case ssl_sig_dsa_sha256:
-+        case ssl_sig_dsa_sha384:
-+        case ssl_sig_dsa_sha512:
-+        case ssl_sig_dsa_sha1:
-+            return PR_TRUE;
-+
-+        default:
-+            return PR_FALSE;
-+    }
-+    return PR_FALSE;
-+}
-+
- SSLAuthType
- ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme)
- {
-@@ -6017,6 +6034,13 @@ ssl_CanUseSignatureScheme(SSLSignatureSc
-         return PR_FALSE;
-     }
- 
-+    if (ssl_IsDsaSignatureScheme(scheme) &&
-+        (NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) ==
-+         SECSuccess) &&
-+        !(policy & NSS_USE_ALG_IN_SSL_KX)) {
-+        return PR_FALSE;
-+    }
-+
-     hashType = ssl_SignatureSchemeToHashType(scheme);
-     if (requireSha1 && (hashType != ssl_hash_sha1)) {
-         return PR_FALSE;
-@@ -9490,6 +9514,14 @@ ssl3_EncodeSigAlgs(const sslSocket *ss, 
-             continue;
-         }
- 
-+        /* Skip DSA scheme if it is disabled by policy. */
-+        if (ssl_IsDsaSignatureScheme(ss->ssl3.signatureSchemes[i]) &&
-+            (NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) ==
-+             SECSuccess) &&
-+            !(policy & NSS_USE_ALG_IN_SSL_KX)) {
-+            continue;
-+        }
-+
-         if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess) ||
-             (policy & NSS_USE_ALG_IN_SSL_KX)) {
-             rv = sslBuffer_AppendNumber(buf, ss->ssl3.signatureSchemes[i], 2);
-diff --git a/tests/ssl/sslpolicy.txt b/tests/ssl/sslpolicy.txt
---- a/tests/ssl/sslpolicy.txt
-+++ b/tests/ssl/sslpolicy.txt
-@@ -74,6 +74,8 @@
- #	SECT409R1
- #	SECT571K1
- #	SECT571R1
-+# Signatures:
-+#	DSA
- # Hashes:
- #	MD2
- #	MD4
-@@ -172,3 +174,4 @@
-   1 noECC  SSL3   d    allow=tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Exlicitly
-   1 noECC  SSL3   d    disallow=all_allow=hmac-sha1:sha256:rsa:des-ede3-cbc:tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Implicitly Narrow.
-   1 noECC  SSL3   d    disallow=all_allow=md2/all:md4/all:md5/all:sha1/all:sha256/all:sha384/all:sha512/all:hmac-sha1/all:hmac-sha224/all:hmac-sha256/all:hmac-sha384/all:hmac-sha512/all:hmac-md5/all:camellia128-cbc/all:camellia192-cbc/all:camellia256-cbc/all:seed-cbc/all:des-ede3-cbc/all:des-40-cbc/all:des-cbc/all:null-cipher/all:rc2/all:rc4/all:idea/all:rsa/all:rsa-export/all:dhe-rsa/all:dhe-dss/all:ecdhe-ecdsa/all:ecdhe-rsa/all:ecdh-ecdsa/all:ecdh-rsa/all:tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Implicitly.
-+  0 noECC  SSL3   d    disallow=dsa Disallow DSA Signatures Explicitly.
diff --git a/SOURCES/nss-dso-ldflags.patch b/SOURCES/nss-dso-ldflags.patch
index fe39ae3..d5485ae 100644
--- a/SOURCES/nss-dso-ldflags.patch
+++ b/SOURCES/nss-dso-ldflags.patch
@@ -1,12 +1,8 @@
-diff --git a/coreconf/Linux.mk b/coreconf/Linux.mk
---- a/coreconf/Linux.mk
-+++ b/coreconf/Linux.mk
-@@ -135,17 +135,17 @@ ifeq ($(KERNEL),Linux)
- endif
- OS_LIBS			= $(OS_PTHREAD) -ldl -lc
- 
- ifdef USE_PTHREADS
- 	DEFINES		+= -D_REENTRANT
+Index: nss/coreconf/Linux.mk
+===================================================================
+--- nss.orig/coreconf/Linux.mk
++++ nss/coreconf/Linux.mk
+@@ -144,7 +144,7 @@ ifdef USE_PTHREADS
  endif
  
  DSO_CFLAGS		= -fPIC
@@ -15,8 +11,3 @@ diff --git a/coreconf/Linux.mk b/coreconf/Linux.mk
  # The linker on Red Hat Linux 7.2 and RHEL 2.1 (GNU ld version 2.11.90.0.8)
  # incorrectly reports undefined references in the libraries we link with, so
  # we don't use -z defs there.
- # Also, -z defs conflicts with Address Sanitizer, which emits relocations
- # against the libsanitizer runtime built into the main executable.
- ZDEFS_FLAG		= -Wl,-z,defs
- DSO_LDOPTS		+= $(if $(findstring 2.11.90.0.8,$(shell ld -v)),,$(ZDEFS_FLAG))
- LDFLAGS			+= $(ARCHFLAG) -z noexecstack
diff --git a/SOURCES/nss-fips-disable-tls13.patch b/SOURCES/nss-fips-disable-tls13.patch
new file mode 100644
index 0000000..8b30bbc
--- /dev/null
+++ b/SOURCES/nss-fips-disable-tls13.patch
@@ -0,0 +1,30 @@
+diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
+--- a/lib/ssl/sslsock.c
++++ b/lib/ssl/sslsock.c
+@@ -2382,16 +2382,26 @@ ssl3_CreateOverlapWithPolicy(SSLProtocol
+     rv = ssl3_GetEffectiveVersionPolicy(protocolVariant,
+                                         &effectivePolicyBoundary);
+     if (rv == SECFailure) {
+         /* SECFailure means internal failure or invalid configuration. */
+         overlap->min = overlap->max = SSL_LIBRARY_VERSION_NONE;
+         return SECFailure;
+     }
+ 
++    /* TODO: TLSv1.3 doesn't work yet under FIPS mode */
++    if (PK11_IsFIPS()) {
++        if (effectivePolicyBoundary.min >= SSL_LIBRARY_VERSION_TLS_1_3) {
++            effectivePolicyBoundary.min = SSL_LIBRARY_VERSION_TLS_1_2;
++        }
++        if (effectivePolicyBoundary.max >= SSL_LIBRARY_VERSION_TLS_1_3) {
++            effectivePolicyBoundary.max = SSL_LIBRARY_VERSION_TLS_1_2;
++        }
++    }
++
+     vrange.min = PR_MAX(input->min, effectivePolicyBoundary.min);
+     vrange.max = PR_MIN(input->max, effectivePolicyBoundary.max);
+ 
+     if (vrange.max < vrange.min) {
+         /* there was no overlap, turn off range altogether */
+         overlap->min = overlap->max = SSL_LIBRARY_VERSION_NONE;
+         return SECFailure;
+     }
diff --git a/SOURCES/nss-fipstest-tls12-prf.patch b/SOURCES/nss-fipstest-tls12-prf.patch
new file mode 100644
index 0000000..207a0c0
--- /dev/null
+++ b/SOURCES/nss-fipstest-tls12-prf.patch
@@ -0,0 +1,81 @@
+# HG changeset patch
+# User Tomas Mraz <tmraz@fedoraproject.org>
+# Date 1560861770 -7200
+#      Tue Jun 18 14:42:50 2019 +0200
+# Node ID 6ef49fe67d6227a1d290da5537ec0dade379a15a
+# Parent  ebc93d6daeaa9001d31fd18b5199779da99ae9aa
+Bug 1559906, fipstest: use CKM_TLS12_MASTER_KEY_DERIVE in TLS test, r=rrelyea
+
+This also lets us CAVS tests more than just SHA256.
+
+diff --git a/cmd/fipstest/fipstest.c b/cmd/fipstest/fipstest.c
+--- a/cmd/fipstest/fipstest.c
++++ b/cmd/fipstest/fipstest.c
+@@ -6669,12 +6669,13 @@ tls(char *reqfn)
+ 
+     CK_MECHANISM master_mech = { CKM_TLS_MASTER_KEY_DERIVE, NULL, 0 };
+     CK_MECHANISM key_block_mech = { CKM_TLS_KEY_AND_MAC_DERIVE, NULL, 0 };
+-    CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params;
+-    CK_SSL3_KEY_MAT_PARAMS key_block_params;
++    CK_TLS12_MASTER_KEY_DERIVE_PARAMS master_params;
++    CK_TLS12_KEY_MAT_PARAMS key_block_params;
+     CK_SSL3_KEY_MAT_OUT key_material;
+     CK_RV crv;
+ 
+     /* set up PKCS #11 parameters */
++    master_params.prfHashMechanism = CKM_SHA256;
+     master_params.pVersion = NULL;
+     master_params.RandomInfo.pClientRandom = clientHello_random;
+     master_params.RandomInfo.ulClientRandomLen = sizeof(clientHello_random);
+@@ -6682,6 +6683,7 @@ tls(char *reqfn)
+     master_params.RandomInfo.ulServerRandomLen = sizeof(serverHello_random);
+     master_mech.pParameter = (void *)&master_params;
+     master_mech.ulParameterLen = sizeof(master_params);
++    key_block_params.prfHashMechanism = CKM_SHA256;
+     key_block_params.ulMacSizeInBits = 0;
+     key_block_params.ulKeySizeInBits = 0;
+     key_block_params.ulIVSizeInBits = 0;
+@@ -6724,13 +6726,39 @@ tls(char *reqfn)
+         if (buf[0] == '[') {
+             if (strncmp(buf, "[TLS", 4) == 0) {
+                 if (buf[7] == '0') {
++                    /* CK_SSL3_MASTER_KEY_DERIVE_PARAMS is a subset of
++                     * CK_TLS12_MASTER_KEY_DERIVE_PARAMS and
++                     * CK_SSL3_KEY_MAT_PARAMS is a subset of
++                     * CK_TLS12_KEY_MAT_PARAMS. The latter params have
++                     * an extra prfHashMechanism field at the end. */
+                     master_mech.mechanism = CKM_TLS_MASTER_KEY_DERIVE;
+                     key_block_mech.mechanism = CKM_TLS_KEY_AND_MAC_DERIVE;
++                    master_mech.ulParameterLen = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
++                    key_block_mech.ulParameterLen = sizeof(CK_SSL3_KEY_MAT_PARAMS);
+                 } else if (buf[7] == '2') {
+-                    master_mech.mechanism =
+-                        CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256;
+-                    key_block_mech.mechanism =
+-                        CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256;
++                    if (strncmp(&buf[10], "SHA-1", 5) == 0) {
++                        master_params.prfHashMechanism = CKM_SHA_1;
++                        key_block_params.prfHashMechanism = CKM_SHA_1;
++                    } else if (strncmp(&buf[10], "SHA-224", 7) == 0) {
++                        master_params.prfHashMechanism = CKM_SHA224;
++                        key_block_params.prfHashMechanism = CKM_SHA224;
++                    } else if (strncmp(&buf[10], "SHA-256", 7) == 0) {
++                        master_params.prfHashMechanism = CKM_SHA256;
++                        key_block_params.prfHashMechanism = CKM_SHA256;
++                    } else if (strncmp(&buf[10], "SHA-384", 7) == 0) {
++                        master_params.prfHashMechanism = CKM_SHA384;
++                        key_block_params.prfHashMechanism = CKM_SHA384;
++                    } else if (strncmp(&buf[10], "SHA-512", 7) == 0) {
++                        master_params.prfHashMechanism = CKM_SHA512;
++                        key_block_params.prfHashMechanism = CKM_SHA512;
++                    } else {
++                        fprintf(tlsresp, "ERROR: Unable to find prf Hash type");
++                        goto loser;
++                    }
++                    master_mech.mechanism = CKM_TLS12_MASTER_KEY_DERIVE;
++                    key_block_mech.mechanism = CKM_TLS12_KEY_AND_MAC_DERIVE;
++                    master_mech.ulParameterLen = sizeof(master_params);
++                    key_block_mech.ulParameterLen = sizeof(key_block_params);
+                 } else {
+                     fprintf(stderr, "Unknown TLS type %x\n",
+                             (unsigned int)buf[0]);
diff --git a/SOURCES/nss-ike-patch.patch b/SOURCES/nss-ike-patch.patch
new file mode 100644
index 0000000..3ecfa63
--- /dev/null
+++ b/SOURCES/nss-ike-patch.patch
@@ -0,0 +1,4513 @@
+diff --git a/cmd/fipstest/README b/cmd/fipstest/README
+new file mode 100644
+--- /dev/null
++++ b/cmd/fipstest/README
+@@ -0,0 +1,1 @@
++The scripts have been moved to tests/fips/cavs_scripts
+diff --git a/cmd/fipstest/aes.sh b/cmd/fipstest/aes.sh
+deleted file mode 100644
+--- a/cmd/fipstest/aes.sh
++++ /dev/null
+@@ -1,112 +0,0 @@
+-#!/bin/sh
+-#
+-# 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/.
+-#
+-#
+-# A Bourne shell script for running the NIST AES Algorithm Validation Suite
+-#
+-# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+-# variables appropriately so that the fipstest command and the NSPR and NSS
+-# shared libraries/DLLs are on the search path.  Then run this script in the
+-# directory where the REQUEST (.req) files reside.  The script generates the
+-# RESPONSE (.rsp) files in the same directory.
+-
+-BASEDIR=${1-.}
+-TESTDIR=${BASEDIR}/AES
+-COMMAND=${2-run}
+-REQDIR=${TESTDIR}/req
+-RSPDIR=${TESTDIR}/resp
+-
+-cbc_kat_requests="
+-CBCGFSbox128.req
+-CBCGFSbox192.req
+-CBCGFSbox256.req
+-CBCKeySbox128.req
+-CBCKeySbox192.req
+-CBCKeySbox256.req
+-CBCVarKey128.req
+-CBCVarKey192.req
+-CBCVarKey256.req
+-CBCVarTxt128.req
+-CBCVarTxt192.req
+-CBCVarTxt256.req
+-"
+-
+-cbc_mct_requests="
+-CBCMCT128.req
+-CBCMCT192.req
+-CBCMCT256.req
+-"
+-
+-cbc_mmt_requests="
+-CBCMMT128.req
+-CBCMMT192.req
+-CBCMMT256.req
+-"
+-
+-ecb_kat_requests="
+-ECBGFSbox128.req
+-ECBGFSbox192.req
+-ECBGFSbox256.req
+-ECBKeySbox128.req
+-ECBKeySbox192.req
+-ECBKeySbox256.req
+-ECBVarKey128.req
+-ECBVarKey192.req
+-ECBVarKey256.req
+-ECBVarTxt128.req
+-ECBVarTxt192.req
+-ECBVarTxt256.req
+-"
+-
+-ecb_mct_requests="
+-ECBMCT128.req
+-ECBMCT192.req
+-ECBMCT256.req
+-"
+-
+-ecb_mmt_requests="
+-ECBMMT128.req
+-ECBMMT192.req
+-ECBMMT256.req
+-"
+-
+-if [ ${COMMAND} = "verify" ]; then
+-    for request in $cbc_kat_requests $cbc_mct_requests $cbc_mmt_requests $ecb_kat_requests $ecb_mct_requests $ecb_mmt_requests; do
+-	sh ./validate1.sh ${TESTDIR} $request
+-    done
+-    exit 0
+-fi
+-
+-for request in $cbc_kat_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest aes kat cbc ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $cbc_mct_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest aes mct cbc ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $cbc_mmt_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest aes mmt cbc ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $ecb_kat_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest aes kat ecb ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $ecb_mct_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest aes mct ecb ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $ecb_mmt_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest aes mmt ecb ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+diff --git a/cmd/fipstest/aesgcm.sh b/cmd/fipstest/aesgcm.sh
+deleted file mode 100644
+--- a/cmd/fipstest/aesgcm.sh
++++ /dev/null
+@@ -1,67 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-# A Bourne shell script for running the NIST AES Algorithm Validation Suite
+-#
+-# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+-# variables appropriately so that the fipstest command and the NSPR and NSS
+-# shared libraries/DLLs are on the search path.  Then run this script in the
+-# directory where the REQUEST (.req) files reside.  The script generates the
+-# RESPONSE (.rsp) files in the same directory.
+-
+-BASEDIR=${1-.}
+-TESTDIR=${BASEDIR}/AES_GCM
+-COMMAND=${2-run}
+-REQDIR=${TESTDIR}/req
+-RSPDIR=${TESTDIR}/resp
+-
+-gcm_decrypt_requests="
+-gcmDecrypt128.req
+-gcmDecrypt192.req
+-gcmDecrypt256.req
+-"
+-
+-gcm_encrypt_extiv_requests="
+-gcmEncryptExtIV128.req
+-gcmEncryptExtIV192.req
+-gcmEncryptExtIV256.req
+-"
+-gcm_encrypt_intiv_requests="
+-"
+-
+-#gcm_encrypt_intiv_requests="
+-#gcmEncryptIntIV128.req
+-#gcmEncryptIntIV192.req
+-#gcmEncryptIntIV256.req
+-#"
+-
+-if [ ${COMMAND} = "verify" ]; then
+-    for request in $gcm_decrypt_requests $gcm_encrypt_extiv_requests; do
+-	sh ./validate1.sh ${TESTDIR} $request ' ' '-e /Reason:/d'
+-    done
+-    for request in $gcm_encrypt_intiv_requests; do
+-	name=`basename $request .req`
+-    	echo ">>>>>  $name"
+-        fipstest aes gcm decrypt ${RSPDIR}/$name.rsp | grep FAIL
+-    done
+-    exit 0
+-fi
+-
+-for request in $gcm_decrypt_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest aes gcm decrypt ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $gcm_encrypt_intiv_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest aes gcm encrypt_intiv ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $gcm_encrypt_extiv_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest aes gcm encrypt_extiv ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+diff --git a/cmd/fipstest/dsa.sh b/cmd/fipstest/dsa.sh
+deleted file mode 100755
+--- a/cmd/fipstest/dsa.sh
++++ /dev/null
+@@ -1,71 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-# A Bourne shell script for running the NIST DSA Validation System
+-#
+-# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+-# variables appropriately so that the fipstest command and the NSPR and NSS
+-# shared libraries/DLLs are on the search path.  Then run this script in the
+-# directory where the REQUEST (.req) files reside.  The script generates the
+-# RESPONSE (.rsp) files in the same directory.
+-BASEDIR=${1-.}
+-TESTDIR=${BASEDIR}/DSA2
+-COMMAND=${2-run}
+-REQDIR=${TESTDIR}/req
+-RSPDIR=${TESTDIR}/resp
+-
+-
+-#
+-# several of the DSA tests do use known answer tests to verify the result.
+-# in those cases, feed generated tests back into the fipstest tool and
+-# see if we can verify those value. NOTE: th PQGVer and SigVer tests verify
+-# the dsa pqgver and dsa sigver functions, so we know they can detect errors
+-# in those PQGGen and SigGen. Only the KeyPair verify is potentially circular.
+-#
+-if [ ${COMMAND} = "verify" ]; then
+-# verify generated keys
+-    name=KeyPair
+-    echo ">>>>>  $name"
+-    fipstest dsa keyver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+-# verify generated pqg values
+-    name=PQGGen
+-    echo ">>>>>  $name"
+-    fipstest dsa pqgver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+-# verify PQGVer with known answer
+-#    sh ./validate1.sh ${TESTDIR} PQGVer.req ' ' '-e /^Result.=.F/s;.(.*);; -e /^Result.=.P/s;.(.*);;'
+-# verify signatures
+-    name=SigGen
+-    echo ">>>>>  $name"
+-    fipstest dsa sigver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+-# verify SigVer with known answer
+-    sh ./validate1.sh ${TESTDIR} SigVer.req ' ' '-e /^X.=/d -e /^Result.=.F/s;.(.*);;'
+-    exit 0
+-fi
+-
+-request=KeyPair.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest dsa keypair ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=PQGGen.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest dsa pqggen ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=PQGVer1863.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest dsa pqgver ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=SigGen.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest dsa siggen ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=SigVer.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest dsa sigver ${REQDIR}/$request > ${RSPDIR}/$response
+diff --git a/cmd/fipstest/ecdsa.sh b/cmd/fipstest/ecdsa.sh
+deleted file mode 100644
+--- a/cmd/fipstest/ecdsa.sh
++++ /dev/null
+@@ -1,60 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-# A Bourne shell script for running the NIST ECDSA Validation System
+-#
+-# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+-# variables appropriately so that the fipstest command and the NSPR and NSS
+-# shared libraries/DLLs are on the search path.  Then run this script in the
+-# directory where the REQUEST (.req) files reside.  The script generates the
+-# RESPONSE (.rsp) files in the same directory.
+-BASEDIR=${1-.}
+-TESTDIR=${BASEDIR}/ECDSA2
+-COMMAND=${2-run}
+-REQDIR=${TESTDIR}/req
+-RSPDIR=${TESTDIR}/resp
+-
+-#
+-# several of the ECDSA tests do not use known answer tests to verify the result.
+-# In those cases, feed generated tests back into the fipstest tool and
+-# see if we can verify those value. NOTE:  PQGVer and SigVer tests verify
+-# the dsa pqgver and dsa sigver functions, so we know they can detect errors
+-# in those PQGGen and SigGen. Only the KeyPair verify is potentially circular.
+-#
+-if [ ${COMMAND} = "verify" ]; then
+-# verify generated keys
+-    name=KeyPair
+-    echo ">>>>>  $name"
+-    fipstest ecdsa keyver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+-    sh ./validate1.sh ${TESTDIR} PKV.req ' ' '-e /^X.=/d -e /^Result.=.F/s;.(.*);; -e /^Result.=.P/s;.(.*);;'
+-# verify signatures
+-    name=SigGen
+-    echo ">>>>>  $name"
+-    fipstest ecdsa sigver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+-# verify SigVer with known answer
+-    sh ./validate1.sh ${TESTDIR} SigVer.req ' ' '-e /^X.=/d -e /^Result.=.F/s;.(.*);; -e /^Result.=.P/s;.(.*);;'
+-    exit 0
+-fi
+-
+-request=KeyPair.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest ecdsa keypair ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=PKV.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest ecdsa pkv ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=SigGen.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest ecdsa siggen ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=SigVer.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest ecdsa sigver ${REQDIR}/$request > ${RSPDIR}/$response
+diff --git a/cmd/fipstest/fipstest.c b/cmd/fipstest/fipstest.c
+--- a/cmd/fipstest/fipstest.c
++++ b/cmd/fipstest/fipstest.c
+@@ -29,16 +29,21 @@
+ #undef CK_PKCS11_FUNCTION_INFO
+ #undef CK_NEED_ARG_LIST
+ #undef __PASTE
+ #define SSL3_RANDOM_LENGTH 32
+ 
+ #if 0
+ #include "../../lib/freebl/mpi/mpi.h"
+ #endif
++#define MATCH_OPENSSL 1
++/*#define MATCH_NIST 1 */
++#ifdef MATCH_NIST
++#define VERBOSE_REASON 1
++#endif
+ 
+ extern SECStatus
+ EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
+ extern SECStatus
+ EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
+               const ECParams *srcParams);
+ 
+ #define ENCRYPT 1
+@@ -3164,16 +3169,20 @@ ecdh_functional(char *reqfn, PRBool resp
+                 fprintf(stderr, "generate key had invalid public value len\n");
+                 goto loser;
+             }
+             uit_len = (uit_len - 1) / 2;
+             if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
+                 fprintf(stderr, "generate key was compressed\n");
+                 goto loser;
+             }
++            fputs("deIUT = ", ecdhresp);
++            to_hex_str(buf, ecpriv->privateValue.data, ecpriv->privateValue.len);
++            fputs(buf, ecdhresp);
++            fputc('\n', ecdhresp);
+             fputs("QeIUTx = ", ecdhresp);
+             to_hex_str(buf, &ecpriv->publicValue.data[1], uit_len);
+             fputs(buf, ecdhresp);
+             fputc('\n', ecdhresp);
+             fputs("QeIUTy = ", ecdhresp);
+             to_hex_str(buf, &ecpriv->publicValue.data[1 + uit_len], uit_len);
+             fputs(buf, ecdhresp);
+             fputc('\n', ecdhresp);
+@@ -3210,17 +3219,16 @@ loser:
+         }
+     }
+     if (pubkey.data != NULL) {
+         PORT_Free(pubkey.data);
+     }
+     fclose(ecdhreq);
+ }
+ 
+-#define MATCH_OPENSSL 1
+ /*
+  * Perform the ECDH Validity Test.
+  *
+  * reqfn is the pathname of the REQUEST file.
+  *
+  * The output RESPONSE file is written to stdout.
+  */
+ void
+@@ -3403,42 +3411,47 @@ ecdh_verify(char *reqfn, PRBool response
+         if (strncmp(buf, "QeIUTx", 6) == 0) {
+             fputs(buf, ecdhresp);
+             continue;
+         }
+         if (strncmp(buf, "QeIUTy", 6) == 0) {
+             fputs(buf, ecdhresp);
+             continue;
+         }
+-        if (strncmp(buf, "CAVSHashZZ", 10) == 0) {
++        if ((strncmp(buf, "CAVSHashZZ", 10) == 0) ||
++            (strncmp(buf, "HashZZ", 6) == 0)) {
+             fputs(buf, ecdhresp);
+-            i = 10;
++            i = (buf[0] == 'C') ? 10 : 6;
+             while (isspace(buf[i]) || buf[i] == '=') {
+                 i++;
+             }
+             from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
+             if (current_ecparams == NULL) {
+                 fprintf(stderr, "no curve defined for type defined\n");
+                 goto loser;
+             }
+             /* validate CAVS public key */
+             if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) {
+-#ifdef MATCH_OPENSSL
++#ifdef VERBOSE_REASON
++                fprintf(ecdhresp, "Result = F # key didn't validate\n");
++#else
+                 fprintf(ecdhresp, "Result = F\n");
+-#else
+-                fprintf(ecdhresp, "Result = F # key didn't validate\n");
+ #endif
+                 continue;
+             }
+ 
+             /* ECDH */
+             if (ECDH_Derive(&pubkey, current_ecparams, &private_value,
+                             PR_FALSE, &ZZ) != SECSuccess) {
+-                fprintf(stderr, "Derive failed\n");
+-                goto loser;
++#ifdef VERBOSE_REASON
++                fprintf(ecdhresp, "Result = F # derive failure\n");
++#else
++                fprintf(ecdhresp, "Result = F\n");
++#endif
++                continue;
+             }
+ /* output  ZZ */
+ #ifndef MATCH_OPENSSL
+             fputs("Z = ", ecdhresp);
+             to_hex_str(buf, ZZ.data, ZZ.len);
+             fputs(buf, ecdhresp);
+             fputc('\n', ecdhresp);
+ #endif
+@@ -3450,20 +3463,20 @@ ecdh_verify(char *reqfn, PRBool response
+             SECITEM_FreeItem(&ZZ, PR_FALSE);
+ #ifndef MATCH_NIST
+             fputs("IUTHashZZ = ", ecdhresp);
+             to_hex_str(buf, hashBuf, fips_hashLen(hash));
+             fputs(buf, ecdhresp);
+             fputc('\n', ecdhresp);
+ #endif
+             if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
+-#ifdef MATCH_OPENSSL
++#ifdef VERBOSE_REASON
++                fprintf(ecdhresp, "Result = F # hash doesn't match\n");
++#else
+                 fprintf(ecdhresp, "Result = F\n");
+-#else
+-                fprintf(ecdhresp, "Result = F # hash doesn't match\n");
+ #endif
+             } else {
+                 fprintf(ecdhresp, "Result = P\n");
+             }
+ #ifndef MATCH_OPENSSL
+             fputc('\n', ecdhresp);
+ #endif
+             continue;
+@@ -3670,17 +3683,16 @@ dh_functional(char *reqfn, PRBool respon
+     }
+ loser:
+     if (dsapriv != NULL) {
+         PORT_FreeArena(dsapriv->params.arena, PR_TRUE);
+     }
+     fclose(dhreq);
+ }
+ 
+-#define MATCH_OPENSSL 1
+ /*
+  * Perform the DH Validity Test.
+  *
+  * reqfn is the pathname of the REQUEST file.
+  *
+  * The output RESPONSE file is written to stdout.
+  */
+ void
+@@ -3841,19 +3853,20 @@ dh_verify(char *reqfn, PRBool response)
+             continue;
+         }
+         /* YephemUIT = ... */
+         if (strncmp(buf, "YephemIUT", 9) == 0) {
+             fputs(buf, dhresp);
+             continue;
+         }
+         /* CAVSHashZZ = ... */
+-        if (strncmp(buf, "CAVSHashZZ", 10) == 0) {
++        if ((strncmp(buf, "CAVSHashZZ", 10) == 0) ||
++            (strncmp(buf, "HashZZ", 6) == 0)) {
+             fputs(buf, dhresp);
+-            i = 10;
++            i = buf[0] == 'C' ? 10 : 6;
+             while (isspace(buf[i]) || buf[i] == '=') {
+                 i++;
+             }
+             from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]);
+             /* do the DH operation*/
+             if (DH_Derive(&pubkey, &pqg.prime, &privkey,
+                           &ZZ, pqg.prime.len) != SECSuccess) {
+                 fprintf(stderr, "Derive failed\n");
+@@ -3866,17 +3879,17 @@ dh_verify(char *reqfn, PRBool response)
+             fputs(buf, dhresp);
+             fputc('\n', dhresp);
+ #endif
+             if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) {
+                 fprintf(stderr, "hash of derived key failed\n");
+                 goto loser;
+             }
+             SECITEM_FreeItem(&ZZ, PR_FALSE);
+-#ifndef MATCH_NIST_
++#ifndef MATCH_NIST
+             fputs("IUTHashZZ = ", dhresp);
+             to_hex_str(buf, hashBuf, fips_hashLen(hash));
+             fputs(buf, dhresp);
+             fputc('\n', dhresp);
+ #endif
+             if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) {
+                 fprintf(dhresp, "Result = F\n");
+             } else {
+@@ -6895,16 +6908,1306 @@ loser:
+     if (master_secret)
+         free(master_secret);
+     if (key_block)
+         free(key_block);
+     if (tlsreq)
+         fclose(tlsreq);
+ }
+ 
++void
++ikev1(char *reqfn)
++{
++    char buf[4096]; /* holds one line from the input REQUEST file.
++                         * needs to be large enough to hold the longest
++                         * line "g^xy = <2048 hex digits>\n".
++                         */
++    unsigned char *gxy = NULL;
++    int gxy_len;
++    unsigned char *Ni = NULL;
++    int Ni_len;
++    unsigned char *Nr = NULL;
++    int Nr_len;
++    unsigned char CKYi[8];
++    int CKYi_len;
++    unsigned char CKYr[8];
++    int CKYr_len;
++    unsigned int i, j;
++    FILE *ikereq = NULL; /* input stream from the REQUEST file */
++    FILE *ikeresp;       /* output stream to the RESPONSE file */
++
++    CK_SLOT_ID slotList[10];
++    CK_SLOT_ID slotID;
++    CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
++    CK_ULONG count;
++    static const CK_C_INITIALIZE_ARGS pk11args = {
++        NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
++        (void *)"flags=readOnly,noCertDB,noModDB", NULL
++    };
++    static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
++    static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
++    static CK_BBOOL ck_true = CK_TRUE;
++    static CK_ULONG keyLen = 1;
++    CK_ATTRIBUTE gxy_template[] = {
++        { CKA_VALUE, NULL, 0 }, /* must be first */
++        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
++        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
++        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
++    };
++    CK_ULONG gxy_template_count =
++        sizeof(gxy_template) / sizeof(gxy_template[0]);
++    CK_ATTRIBUTE derive_template[] = {
++        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
++        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
++        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
++        { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, /* must be last */
++    };
++    CK_ULONG derive_template_count =
++        sizeof(derive_template) / sizeof(derive_template[0]);
++    CK_ATTRIBUTE skeyid_template =
++        { CKA_VALUE, NULL, 0 };
++    CK_ATTRIBUTE skeyid_d_template =
++        { CKA_VALUE, NULL, 0 };
++    CK_ATTRIBUTE skeyid_a_template =
++        { CKA_VALUE, NULL, 0 };
++    CK_ATTRIBUTE skeyid_e_template =
++        { CKA_VALUE, NULL, 0 };
++    unsigned char skeyid_secret[HASH_LENGTH_MAX];
++    unsigned char skeyid_d_secret[HASH_LENGTH_MAX];
++    unsigned char skeyid_a_secret[HASH_LENGTH_MAX];
++    unsigned char skeyid_e_secret[HASH_LENGTH_MAX];
++
++    CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
++    CK_MECHANISM ike1_mech = { CKM_NSS_IKE1_PRF_DERIVE, NULL, 0 };
++    CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
++    CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf;
++    CK_RV crv;
++
++    /* set up PKCS #11 parameters */
++    ike_prf.bDataAsKey = PR_TRUE;
++    ike_prf.bRekey = PR_FALSE;
++    ike_prf.hNewKey = CK_INVALID_HANDLE;
++    CKYi_len = sizeof(CKYi);
++    CKYr_len = sizeof(CKYr);
++    ike1_prf.pCKYi = CKYi;
++    ike1_prf.ulCKYiLen = CKYi_len;
++    ike1_prf.pCKYr = CKYr;
++    ike1_prf.ulCKYrLen = CKYr_len;
++    ike_mech.pParameter = &ike_prf;
++    ike_mech.ulParameterLen = sizeof(ike_prf);
++    ike1_mech.pParameter = &ike1_prf;
++    ike1_mech.ulParameterLen = sizeof(ike1_prf);
++    skeyid_template.pValue = skeyid_secret;
++    skeyid_template.ulValueLen = HASH_LENGTH_MAX;
++    skeyid_d_template.pValue = skeyid_d_secret;
++    skeyid_d_template.ulValueLen = HASH_LENGTH_MAX;
++    skeyid_a_template.pValue = skeyid_a_secret;
++    skeyid_a_template.ulValueLen = HASH_LENGTH_MAX;
++    skeyid_e_template.pValue = skeyid_e_secret;
++    skeyid_e_template.ulValueLen = HASH_LENGTH_MAX;
++
++    crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
++    if (crv != CKR_OK) {
++        fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
++        goto loser;
++    }
++    count = slotListCount;
++    crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
++    if (crv != CKR_OK) {
++        fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
++        goto loser;
++    }
++    if ((count > slotListCount) || count < 1) {
++        fprintf(stderr,
++                "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
++                (int)count, (int)slotListCount);
++        goto loser;
++    }
++    slotID = slotList[0];
++    ikereq = fopen(reqfn, "r");
++    ikeresp = stdout;
++    while (fgets(buf, sizeof buf, ikereq) != NULL) {
++        /* a comment or blank line */
++        if (buf[0] == '#' || buf[0] == '\n') {
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* [.....] */
++        if (buf[0] == '[') {
++            if (strncmp(buf, "[SHA-1]", 7) == 0) {
++                ike_prf.prfMechanism = CKM_SHA_1_HMAC;
++                ike1_prf.prfMechanism = CKM_SHA_1_HMAC;
++            }
++            if (strncmp(buf, "[SHA-224]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA224_HMAC;
++                ike1_prf.prfMechanism = CKM_SHA224_HMAC;
++            }
++            if (strncmp(buf, "[SHA-256]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA256_HMAC;
++                ike1_prf.prfMechanism = CKM_SHA256_HMAC;
++            }
++            if (strncmp(buf, "[SHA-384]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA384_HMAC;
++                ike1_prf.prfMechanism = CKM_SHA384_HMAC;
++            }
++            if (strncmp(buf, "[SHA-512]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA512_HMAC;
++                ike1_prf.prfMechanism = CKM_SHA512_HMAC;
++            }
++            if (strncmp(buf, "[AES-XCBC", 9) == 0) {
++                ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
++                ike1_prf.prfMechanism = CKM_AES_XCBC_MAC;
++            }
++            if (strncmp(buf, "[g^xy", 5) == 0) {
++                if (sscanf(buf, "[g^xy length = %d]",
++                           &gxy_len) != 1) {
++                    goto loser;
++                }
++                gxy_len = gxy_len / 8;
++                if (gxy)
++                    free(gxy);
++                gxy = malloc(gxy_len);
++                gxy_template[0].pValue = gxy;
++                gxy_template[0].ulValueLen = gxy_len;
++            }
++            if (strncmp(buf, "[Ni", 3) == 0) {
++                if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
++                    goto loser;
++                }
++                Ni_len = Ni_len / 8;
++                if (Ni)
++                    free(Ni);
++                Ni = malloc(Ni_len);
++                ike_prf.pNi = Ni;
++                ike_prf.ulNiLen = Ni_len;
++            }
++            if (strncmp(buf, "[Nr", 3) == 0) {
++                if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
++                    goto loser;
++                }
++                Nr_len = Nr_len / 8;
++                if (Nr)
++                    free(Nr);
++                Nr = malloc(Nr_len);
++                ike_prf.pNr = Nr;
++                ike_prf.ulNrLen = Nr_len;
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* "COUNT = x" begins a new data set */
++        if (strncmp(buf, "COUNT", 5) == 0) {
++            /* zeroize the variables for the test with this data set */
++            memset(gxy, 0, gxy_len);
++            memset(Ni, 0, Ni_len);
++            memset(Nr, 0, Nr_len);
++            memset(CKYi, 0, CKYi_len);
++            memset(CKYr, 0, CKYr_len);
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* Ni = ... */
++        if (strncmp(buf, "Ni", 2) == 0) {
++            i = 2;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < Ni_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &Ni[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* Nr = ... */
++        if (strncmp(buf, "Nr", 2) == 0) {
++            i = 2;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < Nr_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &Nr[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* CKYi = ... */
++        if (strncmp(buf, "CKY_I", 5) == 0) {
++            i = 5;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < CKYi_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &CKYi[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* CKYr = ... */
++        if (strncmp(buf, "CKY_R", 5) == 0) {
++            i = 5;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < CKYr_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &CKYr[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* g^xy = ... */
++        if (strncmp(buf, "g^xy", 4) == 0) {
++            CK_SESSION_HANDLE session;
++            CK_OBJECT_HANDLE gxy_handle;
++            CK_OBJECT_HANDLE skeyid_handle;
++            CK_OBJECT_HANDLE skeyid_d_handle;
++            CK_OBJECT_HANDLE skeyid_a_handle;
++            CK_OBJECT_HANDLE skeyid_e_handle;
++            i = 4;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < gxy_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &gxy[j]);
++            }
++            fputs(buf, ikeresp);
++            crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            crv = NSC_CreateObject(session, gxy_template,
++                                   gxy_template_count, &gxy_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_CreateObject failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            /* get the skeyid key */
++            crv = NSC_DeriveKey(session, &ike_mech, gxy_handle,
++                                derive_template, derive_template_count - 1,
++                                &skeyid_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            skeyid_template.ulValueLen = HASH_LENGTH_MAX;
++            crv = NSC_GetAttributeValue(session, skeyid_handle,
++                                        &skeyid_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            /* use the length of the skeyid to set the target length of all the
++             * other keys */
++            keyLen = skeyid_template.ulValueLen;
++            ike1_prf.hKeygxy = gxy_handle;
++            ike1_prf.bHasPrevKey = PR_FALSE;
++            ike1_prf.keyNumber = 0;
++            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
++                                derive_template, derive_template_count,
++                                &skeyid_d_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++
++            ike1_prf.hKeygxy = gxy_handle;
++            ike1_prf.bHasPrevKey = CK_TRUE;
++            ike1_prf.hPrevKey = skeyid_d_handle;
++            ike1_prf.keyNumber = 1;
++            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
++                                derive_template, derive_template_count,
++                                &skeyid_a_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            ike1_prf.hKeygxy = gxy_handle;
++            ike1_prf.bHasPrevKey = CK_TRUE;
++            ike1_prf.hPrevKey = skeyid_a_handle;
++            ike1_prf.keyNumber = 2;
++            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
++                                derive_template, derive_template_count,
++                                &skeyid_e_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("SKEYID = ", ikeresp);
++            to_hex_str(buf, skeyid_secret, keyLen);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            skeyid_d_template.ulValueLen = keyLen;
++            crv = NSC_GetAttributeValue(session, skeyid_d_handle,
++                                        &skeyid_d_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("SKEYID_d = ", ikeresp);
++            to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            skeyid_a_template.ulValueLen = keyLen;
++            crv = NSC_GetAttributeValue(session, skeyid_a_handle,
++                                        &skeyid_a_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("SKEYID_a = ", ikeresp);
++            to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            skeyid_e_template.ulValueLen = keyLen;
++            crv = NSC_GetAttributeValue(session, skeyid_e_handle,
++                                        &skeyid_e_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("SKEYID_e = ", ikeresp);
++            to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            crv = NSC_CloseSession(session);
++            continue;
++        }
++    }
++loser:
++    NSC_Finalize(NULL);
++    if (gxy)
++        free(gxy);
++    if (Ni)
++        free(Ni);
++    if (Nr)
++        free(Nr);
++    if (ikereq)
++        fclose(ikereq);
++}
++
++void
++ikev1_psk(char *reqfn)
++{
++    char buf[4096]; /* holds one line from the input REQUEST file.
++                         * needs to be large enough to hold the longest
++                         * line "g^xy = <2048 hex digits>\n".
++                         */
++    unsigned char *gxy = NULL;
++    int gxy_len;
++    unsigned char *Ni = NULL;
++    int Ni_len;
++    unsigned char *Nr = NULL;
++    int Nr_len;
++    unsigned char CKYi[8];
++    int CKYi_len;
++    unsigned char CKYr[8];
++    int CKYr_len;
++    unsigned char *psk = NULL;
++    int psk_len;
++    unsigned int i, j;
++    FILE *ikereq = NULL; /* input stream from the REQUEST file */
++    FILE *ikeresp;       /* output stream to the RESPONSE file */
++
++    CK_SLOT_ID slotList[10];
++    CK_SLOT_ID slotID;
++    CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
++    CK_ULONG count;
++    static const CK_C_INITIALIZE_ARGS pk11args = {
++        NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
++        (void *)"flags=readOnly,noCertDB,noModDB", NULL
++    };
++    static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
++    static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
++    static CK_BBOOL ck_true = CK_TRUE;
++    static CK_ULONG keyLen = 1;
++    CK_ATTRIBUTE gxy_template[] = {
++        { CKA_VALUE, NULL, 0 }, /* must be first */
++        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
++        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
++        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
++    };
++    CK_ULONG gxy_template_count =
++        sizeof(gxy_template) / sizeof(gxy_template[0]);
++    CK_ATTRIBUTE psk_template[] = {
++        { CKA_VALUE, NULL, 0 }, /* must be first */
++        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
++        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
++        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
++    };
++    CK_ULONG psk_template_count =
++        sizeof(psk_template) / sizeof(psk_template[0]);
++    CK_ATTRIBUTE derive_template[] = {
++        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
++        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
++        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
++        { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, /* must be last */
++    };
++    CK_ULONG derive_template_count =
++        sizeof(derive_template) / sizeof(derive_template[0]);
++    CK_ATTRIBUTE skeyid_template =
++        { CKA_VALUE, NULL, 0 };
++    CK_ATTRIBUTE skeyid_d_template =
++        { CKA_VALUE, NULL, 0 };
++    CK_ATTRIBUTE skeyid_a_template =
++        { CKA_VALUE, NULL, 0 };
++    CK_ATTRIBUTE skeyid_e_template =
++        { CKA_VALUE, NULL, 0 };
++    unsigned char skeyid_secret[HASH_LENGTH_MAX];
++    unsigned char skeyid_d_secret[HASH_LENGTH_MAX];
++    unsigned char skeyid_a_secret[HASH_LENGTH_MAX];
++    unsigned char skeyid_e_secret[HASH_LENGTH_MAX];
++
++    CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
++    CK_MECHANISM ike1_mech = { CKM_NSS_IKE1_PRF_DERIVE, NULL, 0 };
++    CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
++    CK_NSS_IKE1_PRF_DERIVE_PARAMS ike1_prf;
++    CK_RV crv;
++
++    /* set up PKCS #11 parameters */
++    ike_prf.bDataAsKey = PR_FALSE;
++    ike_prf.bRekey = PR_FALSE;
++    ike_prf.hNewKey = CK_INVALID_HANDLE;
++    CKYi_len = 8;
++    CKYr_len = 8;
++    ike1_prf.pCKYi = CKYi;
++    ike1_prf.ulCKYiLen = CKYi_len;
++    ike1_prf.pCKYr = CKYr;
++    ike1_prf.ulCKYrLen = CKYr_len;
++    ike_mech.pParameter = &ike_prf;
++    ike_mech.ulParameterLen = sizeof(ike_prf);
++    ike1_mech.pParameter = &ike1_prf;
++    ike1_mech.ulParameterLen = sizeof(ike1_prf);
++    skeyid_template.pValue = skeyid_secret;
++    skeyid_template.ulValueLen = HASH_LENGTH_MAX;
++    skeyid_d_template.pValue = skeyid_d_secret;
++    skeyid_d_template.ulValueLen = HASH_LENGTH_MAX;
++    skeyid_a_template.pValue = skeyid_a_secret;
++    skeyid_a_template.ulValueLen = HASH_LENGTH_MAX;
++    skeyid_e_template.pValue = skeyid_e_secret;
++    skeyid_e_template.ulValueLen = HASH_LENGTH_MAX;
++
++    crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
++    if (crv != CKR_OK) {
++        fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
++        goto loser;
++    }
++    count = slotListCount;
++    crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
++    if (crv != CKR_OK) {
++        fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
++        goto loser;
++    }
++    if ((count > slotListCount) || count < 1) {
++        fprintf(stderr,
++                "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
++                (int)count, (int)slotListCount);
++        goto loser;
++    }
++    slotID = slotList[0];
++    ikereq = fopen(reqfn, "r");
++    ikeresp = stdout;
++    while (fgets(buf, sizeof buf, ikereq) != NULL) {
++        /* a comment or blank line */
++        if (buf[0] == '#' || buf[0] == '\n') {
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* [.....] */
++        if (buf[0] == '[') {
++            if (strncmp(buf, "[SHA-1]", 7) == 0) {
++                ike_prf.prfMechanism = CKM_SHA_1_HMAC;
++                ike1_prf.prfMechanism = CKM_SHA_1_HMAC;
++            }
++            if (strncmp(buf, "[SHA-224]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA224_HMAC;
++                ike1_prf.prfMechanism = CKM_SHA224_HMAC;
++            }
++            if (strncmp(buf, "[SHA-256]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA256_HMAC;
++                ike1_prf.prfMechanism = CKM_SHA256_HMAC;
++            }
++            if (strncmp(buf, "[SHA-384]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA384_HMAC;
++                ike1_prf.prfMechanism = CKM_SHA384_HMAC;
++            }
++            if (strncmp(buf, "[SHA-512]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA512_HMAC;
++                ike1_prf.prfMechanism = CKM_SHA512_HMAC;
++            }
++            if (strncmp(buf, "[AES-XCBC", 9) == 0) {
++                ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
++                ike1_prf.prfMechanism = CKM_AES_XCBC_MAC;
++            }
++            if (strncmp(buf, "[g^xy", 5) == 0) {
++                if (sscanf(buf, "[g^xy length = %d]",
++                           &gxy_len) != 1) {
++                    goto loser;
++                }
++                gxy_len = gxy_len / 8;
++                if (gxy)
++                    free(gxy);
++                gxy = malloc(gxy_len);
++                gxy_template[0].pValue = gxy;
++                gxy_template[0].ulValueLen = gxy_len;
++            }
++            if (strncmp(buf, "[pre-shared-key", 15) == 0) {
++                if (sscanf(buf, "[pre-shared-key length = %d]",
++                           &psk_len) != 1) {
++                    goto loser;
++                }
++                psk_len = psk_len / 8;
++                if (psk)
++                    free(psk);
++                psk = malloc(psk_len);
++                psk_template[0].pValue = psk;
++                psk_template[0].ulValueLen = psk_len;
++            }
++            if (strncmp(buf, "[Ni", 3) == 0) {
++                if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
++                    goto loser;
++                }
++                Ni_len = Ni_len / 8;
++                if (Ni)
++                    free(Ni);
++                Ni = malloc(Ni_len);
++                ike_prf.pNi = Ni;
++                ike_prf.ulNiLen = Ni_len;
++            }
++            if (strncmp(buf, "[Nr", 3) == 0) {
++                if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
++                    goto loser;
++                }
++                Nr_len = Nr_len / 8;
++                if (Nr)
++                    free(Nr);
++                Nr = malloc(Nr_len);
++                ike_prf.pNr = Nr;
++                ike_prf.ulNrLen = Nr_len;
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* "COUNT = x" begins a new data set */
++        if (strncmp(buf, "COUNT", 5) == 0) {
++            /* zeroize the variables for the test with this data set */
++            memset(gxy, 0, gxy_len);
++            memset(Ni, 0, Ni_len);
++            memset(Nr, 0, Nr_len);
++            memset(CKYi, 0, CKYi_len);
++            memset(CKYr, 0, CKYr_len);
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* Ni = ... */
++        if (strncmp(buf, "Ni", 2) == 0) {
++            i = 2;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < Ni_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &Ni[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* Nr = ... */
++        if (strncmp(buf, "Nr", 2) == 0) {
++            i = 2;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < Nr_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &Nr[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* CKYi = ... */
++        if (strncmp(buf, "CKY_I", 5) == 0) {
++            i = 5;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < CKYi_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &CKYi[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* CKYr = ... */
++        if (strncmp(buf, "CKY_R", 5) == 0) {
++            i = 5;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < CKYr_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &CKYr[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* g^xy = ... */
++        if (strncmp(buf, "g^xy", 4) == 0) {
++            i = 4;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < gxy_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &gxy[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* pre-shared-key = ... */
++        if (strncmp(buf, "pre-shared-key", 14) == 0) {
++            CK_SESSION_HANDLE session;
++            CK_OBJECT_HANDLE gxy_handle;
++            CK_OBJECT_HANDLE psk_handle;
++            CK_OBJECT_HANDLE skeyid_handle;
++            CK_OBJECT_HANDLE skeyid_d_handle;
++            CK_OBJECT_HANDLE skeyid_a_handle;
++            CK_OBJECT_HANDLE skeyid_e_handle;
++            i = 14;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < psk_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &psk[j]);
++            }
++            fputs(buf, ikeresp);
++            crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            crv = NSC_CreateObject(session, psk_template,
++                                   psk_template_count, &psk_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_CreateObject(psk) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            crv = NSC_CreateObject(session, gxy_template,
++                                   gxy_template_count, &gxy_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_CreateObject(gxy) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            /* get the skeyid key */
++            crv = NSC_DeriveKey(session, &ike_mech, psk_handle,
++                                derive_template, derive_template_count - 1,
++                                &skeyid_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            skeyid_template.ulValueLen = HASH_LENGTH_MAX;
++            crv = NSC_GetAttributeValue(session, skeyid_handle,
++                                        &skeyid_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            /* use the length of the skeyid to set the target length of all the
++             * other keys */
++            keyLen = skeyid_template.ulValueLen;
++            ike1_prf.hKeygxy = gxy_handle;
++            ike1_prf.bHasPrevKey = PR_FALSE;
++            ike1_prf.keyNumber = 0;
++            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
++                                derive_template, derive_template_count,
++                                &skeyid_d_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++
++            ike1_prf.hKeygxy = gxy_handle;
++            ike1_prf.bHasPrevKey = CK_TRUE;
++            ike1_prf.hPrevKey = skeyid_d_handle;
++            ike1_prf.keyNumber = 1;
++            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
++                                derive_template, derive_template_count,
++                                &skeyid_a_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            ike1_prf.hKeygxy = gxy_handle;
++            ike1_prf.bHasPrevKey = CK_TRUE;
++            ike1_prf.hPrevKey = skeyid_a_handle;
++            ike1_prf.keyNumber = 2;
++            crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle,
++                                derive_template, derive_template_count,
++                                &skeyid_e_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("SKEYID = ", ikeresp);
++            to_hex_str(buf, skeyid_secret, keyLen);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            skeyid_d_template.ulValueLen = keyLen;
++            crv = NSC_GetAttributeValue(session, skeyid_d_handle,
++                                        &skeyid_d_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("SKEYID_d = ", ikeresp);
++            to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            skeyid_a_template.ulValueLen = keyLen;
++            crv = NSC_GetAttributeValue(session, skeyid_a_handle,
++                                        &skeyid_a_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("SKEYID_a = ", ikeresp);
++            to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            skeyid_e_template.ulValueLen = keyLen;
++            crv = NSC_GetAttributeValue(session, skeyid_e_handle,
++                                        &skeyid_e_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("SKEYID_e = ", ikeresp);
++            to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            crv = NSC_CloseSession(session);
++            continue;
++        }
++    }
++loser:
++    NSC_Finalize(NULL);
++    if (psk)
++        free(psk);
++    if (gxy)
++        free(gxy);
++    if (Ni)
++        free(Ni);
++    if (Nr)
++        free(Nr);
++    if (ikereq)
++        fclose(ikereq);
++}
++
++void
++ikev2(char *reqfn)
++{
++    char buf[4096]; /* holds one line from the input REQUEST file.
++                         * needs to be large enough to hold the longest
++                         * line "g^xy = <2048 hex digits>\n".
++                         */
++    unsigned char *gir = NULL;
++    unsigned char *gir_new = NULL;
++    int gir_len;
++    unsigned char *Ni = NULL;
++    int Ni_len;
++    unsigned char *Nr = NULL;
++    int Nr_len;
++    unsigned char *SPIi = NULL;
++    int SPIi_len = 8;
++    unsigned char *SPIr = NULL;
++    int SPIr_len = 8;
++    unsigned char *DKM = NULL;
++    int DKM_len;
++    unsigned char *DKM_child = NULL;
++    int DKM_child_len;
++    unsigned char *seed_data = NULL;
++    int seed_data_len = 0;
++    unsigned int i, j;
++    FILE *ikereq = NULL; /* input stream from the REQUEST file */
++    FILE *ikeresp;       /* output stream to the RESPONSE file */
++
++    CK_SLOT_ID slotList[10];
++    CK_SLOT_ID slotID;
++    CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]);
++    CK_ULONG count;
++    static const CK_C_INITIALIZE_ARGS pk11args = {
++        NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS,
++        (void *)"flags=readOnly,noCertDB,noModDB", NULL
++    };
++    static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY;
++    static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET;
++    static CK_BBOOL ck_true = CK_TRUE;
++    static CK_ULONG keyLen = 1;
++    CK_ATTRIBUTE gir_template[] = {
++        { CKA_VALUE, NULL, 0 },
++        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
++        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
++        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
++    };
++    CK_ULONG gir_template_count =
++        sizeof(gir_template) / sizeof(gir_template[0]);
++    CK_ATTRIBUTE gir_new_template[] = {
++        { CKA_VALUE, NULL, 0 },
++        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
++        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
++        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
++    };
++    CK_ULONG gir_new_template_count =
++        sizeof(gir_new_template) / sizeof(gir_new_template[0]);
++    CK_ATTRIBUTE derive_template[] = {
++        { CKA_CLASS, &ck_secret, sizeof(ck_secret) },
++        { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) },
++        { CKA_DERIVE, &ck_true, sizeof(ck_true) },
++        { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) },
++    };
++    CK_ULONG derive_template_count =
++        sizeof(derive_template) / sizeof(derive_template[0]);
++    CK_ATTRIBUTE skeyseed_template =
++        { CKA_VALUE, NULL, 0 };
++    CK_ATTRIBUTE dkm_template =
++        { CKA_VALUE, NULL, 0 };
++    CK_ATTRIBUTE dkm_child_template =
++        { CKA_VALUE, NULL, 0 };
++    unsigned char skeyseed_secret[HASH_LENGTH_MAX];
++
++    CK_MECHANISM ike_mech = { CKM_NSS_IKE_PRF_DERIVE, NULL, 0 };
++    CK_MECHANISM ike2_mech = { CKM_NSS_IKE_PRF_PLUS_DERIVE, NULL, 0 };
++    CK_MECHANISM subset_mech = { CKM_EXTRACT_KEY_FROM_KEY, NULL, 0 };
++    CK_NSS_IKE_PRF_DERIVE_PARAMS ike_prf;
++    CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS ike2_prf;
++    CK_EXTRACT_PARAMS subset_params;
++    CK_RV crv;
++
++    /* set up PKCS #11 parameters */
++    ike_mech.pParameter = &ike_prf;
++    ike_mech.ulParameterLen = sizeof(ike_prf);
++    ike2_mech.pParameter = &ike2_prf;
++    ike2_mech.ulParameterLen = sizeof(ike2_prf);
++    subset_mech.pParameter = &subset_params;
++    subset_mech.ulParameterLen = sizeof(subset_params);
++    subset_params = 0;
++    skeyseed_template.pValue = skeyseed_secret;
++    skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
++
++    crv = NSC_Initialize((CK_VOID_PTR)&pk11args);
++    if (crv != CKR_OK) {
++        fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv);
++        goto loser;
++    }
++    count = slotListCount;
++    crv = NSC_GetSlotList(PR_TRUE, slotList, &count);
++    if (crv != CKR_OK) {
++        fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv);
++        goto loser;
++    }
++    if ((count > slotListCount) || count < 1) {
++        fprintf(stderr,
++                "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n",
++                (int)count, (int)slotListCount);
++        goto loser;
++    }
++    slotID = slotList[0];
++    ikereq = fopen(reqfn, "r");
++    ikeresp = stdout;
++    while (fgets(buf, sizeof buf, ikereq) != NULL) {
++        /* a comment or blank line */
++        if (buf[0] == '#' || buf[0] == '\n') {
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* [.....] */
++        if (buf[0] == '[') {
++            if (strncmp(buf, "[SHA-1]", 7) == 0) {
++                ike_prf.prfMechanism = CKM_SHA_1_HMAC;
++                ike2_prf.prfMechanism = CKM_SHA_1_HMAC;
++            }
++            if (strncmp(buf, "[SHA-224]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA224_HMAC;
++                ike2_prf.prfMechanism = CKM_SHA224_HMAC;
++            }
++            if (strncmp(buf, "[SHA-256]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA256_HMAC;
++                ike2_prf.prfMechanism = CKM_SHA256_HMAC;
++            }
++            if (strncmp(buf, "[SHA-384]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA384_HMAC;
++                ike2_prf.prfMechanism = CKM_SHA384_HMAC;
++            }
++            if (strncmp(buf, "[SHA-512]", 9) == 0) {
++                ike_prf.prfMechanism = CKM_SHA512_HMAC;
++                ike2_prf.prfMechanism = CKM_SHA512_HMAC;
++            }
++            if (strncmp(buf, "[AES-XCBC", 9) == 0) {
++                ike_prf.prfMechanism = CKM_AES_XCBC_MAC;
++                ike2_prf.prfMechanism = CKM_AES_XCBC_MAC;
++            }
++            if (strncmp(buf, "[g^ir", 5) == 0) {
++                if (sscanf(buf, "[g^ir length = %d]",
++                           &gir_len) != 1) {
++                    goto loser;
++                }
++                gir_len = gir_len / 8;
++                if (gir)
++                    free(gir);
++                if (gir_new)
++                    free(gir_new);
++                gir = malloc(gir_len);
++                gir_new = malloc(gir_len);
++                gir_template[0].pValue = gir;
++                gir_template[0].ulValueLen = gir_len;
++                gir_new_template[0].pValue = gir_new;
++                gir_new_template[0].ulValueLen = gir_len;
++            }
++            if (strncmp(buf, "[Ni", 3) == 0) {
++                if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) {
++                    goto loser;
++                }
++                Ni_len = Ni_len / 8;
++            }
++            if (strncmp(buf, "[Nr", 3) == 0) {
++                if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) {
++                    goto loser;
++                }
++                Nr_len = Nr_len / 8;
++            }
++            if (strncmp(buf, "[DKM", 4) == 0) {
++                if (sscanf(buf, "[DKM length = %d]",
++                           &DKM_len) != 1) {
++                    goto loser;
++                }
++                DKM_len = DKM_len / 8;
++                if (DKM)
++                    free(DKM);
++                DKM = malloc(DKM_len);
++                dkm_template.pValue = DKM;
++                dkm_template.ulValueLen = DKM_len;
++            }
++            if (strncmp(buf, "[Child SA DKM", 13) == 0) {
++                if (sscanf(buf, "[Child SA DKM length = %d]",
++                           &DKM_child_len) != 1) {
++                    goto loser;
++                }
++                DKM_child_len = DKM_child_len / 8;
++                if (DKM_child)
++                    free(DKM_child);
++                DKM_child = malloc(DKM_child_len);
++                dkm_child_template.pValue = DKM_child;
++                dkm_child_template.ulValueLen = DKM_child_len;
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* "COUNT = x" begins a new data set */
++        if (strncmp(buf, "COUNT", 5) == 0) {
++            /* zeroize the variables for the test with this data set */
++            int new_seed_len = Ni_len + Nr_len + SPIi_len + SPIr_len;
++            if (seed_data_len != new_seed_len) {
++                if (seed_data)
++                    free(seed_data);
++                seed_data_len = new_seed_len;
++                seed_data = malloc(seed_data_len);
++                Ni = seed_data;
++                Nr = &seed_data[Ni_len];
++                SPIi = &seed_data[Ni_len + Nr_len];
++                SPIr = &seed_data[new_seed_len - SPIr_len];
++                ike_prf.pNi = Ni;
++                ike_prf.ulNiLen = Ni_len;
++                ike_prf.pNr = Nr;
++                ike_prf.ulNrLen = Nr_len;
++                ike2_prf.pSeedData = seed_data;
++            }
++            memset(gir, 0, gir_len);
++            memset(gir_new, 0, gir_len);
++            memset(seed_data, 0, seed_data_len);
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* Ni = ... */
++        if (strncmp(buf, "Ni", 2) == 0) {
++            i = 2;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < Ni_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &Ni[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* Nr = ... */
++        if (strncmp(buf, "Nr", 2) == 0) {
++            i = 2;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < Nr_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &Nr[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* g^ir (new) = ... */
++        if (strncmp(buf, "g^ir (new)", 10) == 0) {
++            i = 10;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < gir_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &gir_new[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* g^ir = ... */
++        if (strncmp(buf, "g^ir", 4) == 0) {
++            i = 4;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < gir_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &gir[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* SPIi = ... */
++        if (strncmp(buf, "SPIi", 4) == 0) {
++            i = 4;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < SPIi_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &SPIi[j]);
++            }
++            fputs(buf, ikeresp);
++            continue;
++        }
++        /* SPIr = ... */
++        if (strncmp(buf, "SPIr", 4) == 0) {
++            CK_SESSION_HANDLE session;
++            CK_OBJECT_HANDLE gir_handle;
++            CK_OBJECT_HANDLE gir_new_handle;
++            CK_OBJECT_HANDLE skeyseed_handle;
++            CK_OBJECT_HANDLE sk_d_handle;
++            CK_OBJECT_HANDLE skeyseed_new_handle;
++            CK_OBJECT_HANDLE dkm_handle;
++            CK_OBJECT_HANDLE dkm_child_handle;
++            i = 4;
++            while (isspace(buf[i]) || buf[i] == '=') {
++                i++;
++            }
++            for (j = 0; j < SPIr_len; i += 2, j++) {
++                hex_to_byteval(&buf[i], &SPIr[j]);
++            }
++            fputs(buf, ikeresp);
++            crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            crv = NSC_CreateObject(session, gir_template,
++                                   gir_template_count, &gir_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_CreateObject (g^ir) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            crv = NSC_CreateObject(session, gir_new_template,
++                                   gir_new_template_count, &gir_new_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_CreateObject (g^ir new) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            /* get the SKEYSEED key */
++            ike_prf.bDataAsKey = CK_TRUE;
++            ike_prf.bRekey = CK_FALSE;
++            ike_prf.hNewKey = CK_INVALID_HANDLE;
++            crv = NSC_DeriveKey(session, &ike_mech, gir_handle,
++                                derive_template, derive_template_count - 1,
++                                &skeyseed_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
++            crv = NSC_GetAttributeValue(session, skeyseed_handle,
++                                        &skeyseed_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("SKEYSEED = ", ikeresp);
++            to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            /* get DKM */
++            keyLen = DKM_len;
++            ike2_prf.bHasSeedKey = CK_FALSE;
++            ike2_prf.hSeedKey = CK_INVALID_HANDLE;
++            ike2_prf.ulSeedDataLen = seed_data_len;
++            crv = NSC_DeriveKey(session, &ike2_mech, skeyseed_handle,
++                                derive_template, derive_template_count,
++                                &dkm_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(DKM) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            crv = NSC_GetAttributeValue(session, dkm_handle,
++                                        &dkm_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(DKM) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("DKM = ", ikeresp);
++            to_hex_str(buf, DKM, DKM_len);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            /* get the sk_d from the DKM */
++            keyLen = skeyseed_template.ulValueLen;
++            crv = NSC_DeriveKey(session, &subset_mech, dkm_handle,
++                                derive_template, derive_template_count,
++                                &sk_d_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(sk_d) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++
++            /* get DKM child */
++            keyLen = DKM_child_len;
++            ike2_prf.bHasSeedKey = CK_FALSE;
++            ike2_prf.hSeedKey = CK_INVALID_HANDLE;
++            ike2_prf.ulSeedDataLen = Ni_len + Nr_len;
++            crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle,
++                                derive_template, derive_template_count,
++                                &dkm_child_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(DKM Child SA) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            crv = NSC_GetAttributeValue(session, dkm_child_handle,
++                                        &dkm_child_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(DKM Child SA) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("DKM(Child SA) = ", ikeresp);
++            to_hex_str(buf, DKM_child, DKM_child_len);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            /* get DKM child D-H*/
++            keyLen = DKM_child_len;
++            ike2_prf.bHasSeedKey = CK_TRUE;
++            ike2_prf.hSeedKey = gir_new_handle;
++            ike2_prf.ulSeedDataLen = Ni_len + Nr_len;
++            crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle,
++                                derive_template, derive_template_count,
++                                &dkm_child_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(DKM Child SA D-H) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            crv = NSC_GetAttributeValue(session, dkm_child_handle,
++                                        &dkm_child_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(DKM Child SA D-H) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("DKM(Child SA D-H) = ", ikeresp);
++            to_hex_str(buf, DKM_child, DKM_child_len);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            /* get SKEYSEED(rekey) */
++            ike_prf.bDataAsKey = CK_FALSE;
++            ike_prf.bRekey = CK_TRUE;
++            ike_prf.hNewKey = gir_new_handle;
++            crv = NSC_DeriveKey(session, &ike_mech, sk_d_handle,
++                                derive_template, derive_template_count - 1,
++                                &skeyseed_new_handle);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_DeriveKey(skeyid rekey) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            skeyseed_template.ulValueLen = HASH_LENGTH_MAX;
++            crv = NSC_GetAttributeValue(session, skeyseed_new_handle,
++                                        &skeyseed_template, 1);
++            if (crv != CKR_OK) {
++                fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n",
++                        (unsigned int)crv);
++                goto loser;
++            }
++            fputs("SKEYSEED(rekey) = ", ikeresp);
++            to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen);
++            fputs(buf, ikeresp);
++            fputc('\n', ikeresp);
++
++            crv = NSC_CloseSession(session);
++            continue;
++        }
++    }
++loser:
++    NSC_Finalize(NULL);
++    if (gir)
++        free(gir);
++    if (gir_new)
++        free(gir_new);
++    if (seed_data)
++        free(seed_data);
++    if (DKM)
++        free(DKM);
++    if (DKM_child)
++        free(DKM_child);
++    if (ikereq)
++        fclose(ikereq);
++}
++
+ int
+ main(int argc, char **argv)
+ {
+     if (argc < 2)
+         exit(-1);
+ 
+     RNG_RNGInit();
+     SECOID_Init();
+@@ -7066,11 +8369,19 @@ main(int argc, char **argv)
+             rng_mct(argv[3]);
+         }
+     } else if (strcmp(argv[1], "drbg") == 0) {
+         /* Variable Seed Test */
+         drbg(argv[2]);
+     } else if (strcmp(argv[1], "ddrbg") == 0) {
+         debug = 1;
+         drbg(argv[2]);
++    } else if (strcmp(argv[1], "tls") == 0) {
++        tls(argv[2]);
++    } else if (strcmp(argv[1], "ikev1") == 0) {
++        ikev1(argv[2]);
++    } else if (strcmp(argv[1], "ikev1-psk") == 0) {
++        ikev1_psk(argv[2]);
++    } else if (strcmp(argv[1], "ikev2") == 0) {
++        ikev2(argv[2]);
+     }
+     return 0;
+ }
+diff --git a/cmd/fipstest/hmac.sh b/cmd/fipstest/hmac.sh
+deleted file mode 100755
+--- a/cmd/fipstest/hmac.sh
++++ /dev/null
+@@ -1,36 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-# A Bourne shell script for running the NIST HMAC Algorithm Validation Suite
+-#
+-# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+-# variables appropriately so that the fipstest command and the NSPR and NSS
+-# shared libraries/DLLs are on the search path.  Then run this script in the
+-# directory where the REQUEST (.req) files reside.  The script generates the
+-# RESPONSE (.rsp) files in the same directory.
+-
+-BASEDIR=${1-.}
+-TESTDIR=${BASEDIR}/HMAC
+-COMMAND=${2-run}
+-REQDIR=${TESTDIR}/req
+-RSPDIR=${TESTDIR}/resp
+-                               
+-hmac_requests="
+-HMAC.req
+-"
+-
+-if [ ${COMMAND} = "verify" ]; then
+-    for request in $hmac_requests; do
+-	sh ./validate1.sh ${TESTDIR} $request
+-    done
+-    exit 0
+-fi
+-for request in $hmac_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest hmac ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-
+diff --git a/cmd/fipstest/kas.sh b/cmd/fipstest/kas.sh
+deleted file mode 100755
+--- a/cmd/fipstest/kas.sh
++++ /dev/null
+@@ -1,84 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-# A Bourne shell script for running the NIST DSA Validation System
+-#
+-# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+-# variables appropriately so that the fipstest command and the NSPR and NSS
+-# shared libraries/DLLs are on the search path.  Then run this script in the
+-# directory where the REQUEST (.req) files reside.  The script generates the
+-# RESPONSE (.rsp) files in the same directory.
+-BASEDIR=${1-.}
+-TESTDIR=${BASEDIR}/KAS
+-COMMAND=${2-run}
+-REQDIR=${TESTDIR}/req
+-RSPDIR=${TESTDIR}/resp
+-
+-
+-#
+-if [ ${COMMAND} = "verify" ]; then
+-#
+-# need verify for KAS tests
+-
+-# verify generated keys
+-#    name=KeyPair
+-#    echo ">>>>>  $name"
+-#    fipstest dsa keyver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+-# verify generated pqg values
+-#    name=PQGGen
+-#    echo ">>>>>  $name"
+-#    fipstest dsa pqgver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+-# verify PQGVer with known answer
+-#    sh ./validate1.sh ${TESTDIR} PQGVer.req ' ' '-e /^Result.=.F/s;.(.*);; -e /^Result.=.P/s;.(.*);;'
+-# verify signatures
+-#    name=SigGen
+-#    echo ">>>>>  $name"
+-#    fipstest dsa sigver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+-# verify SigVer with known answer
+-#    sh ./validate1.sh ${TESTDIR} SigVer.req ' ' '-e /^X.=/d -e /^Result.=.F/s;.(.*);;'
+-    exit 0
+-fi
+-
+-request=KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest ecdh init-func ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest ecdh resp-func ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest ecdh init-verify ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest ecdh resp-verify ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=KASFunctionTest_FFCEphem_NOKC_ZZOnly_init.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest dh init-func ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=KASFunctionTest_FFCEphem_NOKC_ZZOnly_resp.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest dh resp-func ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=KASValidityTest_FFCEphem_NOKC_ZZOnly_init.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest dh init-verify ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=KASValidityTest_FFCEphem_NOKC_ZZOnly_resp.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest dh resp-verify ${REQDIR}/$request > ${RSPDIR}/$response
+-
+diff --git a/cmd/fipstest/rng.sh b/cmd/fipstest/rng.sh
+deleted file mode 100644
+--- a/cmd/fipstest/rng.sh
++++ /dev/null
+@@ -1,34 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-# A Bourne shell script for running the NIST RNG Validation Suite
+-#
+-# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+-# variables appropriately so that the fipstest command and the NSPR and NSS
+-# shared libraries/DLLs are on the search path.  Then run this script in the
+-# directory where the REQUEST (.req) files reside.  The script generates the
+-# RESPONSE (.rsp) files in the same directory.
+-BASEDIR=${1-.}
+-TESTDIR=${BASEDIR}/DRBG800-90A
+-COMMAND=${2-run}
+-REQDIR=${TESTDIR}/req
+-RSPDIR=${TESTDIR}/resp
+-
+-drbg_requests="
+-Hash_DRBG.req
+-"
+-
+-if [ ${COMMAND} = "verify" ]; then
+-    for request in $drbg_requests; do
+-	sh ./validate1.sh ${TESTDIR} $request
+-    done
+-    exit 0
+-fi
+-for request in $drbg_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest drbg ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+diff --git a/cmd/fipstest/rsa.sh b/cmd/fipstest/rsa.sh
+deleted file mode 100644
+--- a/cmd/fipstest/rsa.sh
++++ /dev/null
+@@ -1,50 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-# A Bourne shell script for running the NIST RSA Validation System
+-#
+-# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+-# variables appropriately so that the fipstest command and the NSPR and NSS
+-# shared libraries/DLLs are on the search path.  Then run this script in the
+-# directory where the REQUEST (.req) files reside.  The script generates the
+-# RESPONSE (.rsp) files in the same directory.
+-BASEDIR=${1-.}
+-TESTDIR=${BASEDIR}/RSA2
+-COMMAND=${2-run}
+-REQDIR=${TESTDIR}/req
+-RSPDIR=${TESTDIR}/resp
+-
+-if [ ${COMMAND} = "verify" ]; then
+-#verify the signatures. The fax file does not have any known answers, so
+-#use our own verify function.
+-    name=SigGen15_186-3
+-    echo ">>>>>  $name"
+-    fipstest rsa sigver ${RSPDIR}/$name.rsp | grep ^Result.=.F
+-#    fipstest rsa sigver ${REQDIR}/SigVer15_186-3.req | grep ^Result.=.F
+-#The Fax file has the private exponent and the salt value, remove it
+-#also remove the false reason
+-    sh ./validate1.sh ${TESTDIR} SigVer15_186-3.req ' ' '-e /^SaltVal/d -e/^d.=/d -e /^p.=/d -e /^q.=/d -e /^EM.with/d -e /^Result.=.F/s;.(.*);;'
+-#
+-# currently don't have a way to verify the RSA keygen
+-#
+-    exit 0
+-fi
+-
+-request=SigGen15_186-3.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest rsa siggen ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-request=SigVer15_186-3.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest rsa sigver ${REQDIR}/$request > ${RSPDIR}/$response
+-
+-#request=KeyGen_186-3.req
+-request=KeyGen_RandomProbablyPrime3_3.req
+-response=`echo $request | sed -e "s/req/rsp/"`
+-echo $request $response
+-fipstest rsa keypair ${REQDIR}/$request > ${RSPDIR}/$response
+diff --git a/cmd/fipstest/runtest.sh b/cmd/fipstest/runtest.sh
+deleted file mode 100644
+--- a/cmd/fipstest/runtest.sh
++++ /dev/null
+@@ -1,14 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-TESTDIR=${1-.}
+-COMMAND=${2-run}
+-TESTS="aes aesgcm dsa ecdsa hmac kas tls rng rsa sha tdea"
+-for i in $TESTS
+-do
+-    echo "********************Running $i tests"
+-    sh ./${i}.sh ${TESTDIR} ${COMMAND}
+-done
+diff --git a/cmd/fipstest/sha.sh b/cmd/fipstest/sha.sh
+deleted file mode 100644
+--- a/cmd/fipstest/sha.sh
++++ /dev/null
+@@ -1,66 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-# A Bourne shell script for running the NIST SHA Algorithm Validation Suite
+-#
+-# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+-# variables appropriately so that the fipstest command and the NSPR and NSS
+-# shared libraries/DLLs are on the search path.  Then run this script in the
+-# directory where the REQUEST (.req) files reside.  The script generates the
+-# RESPONSE (.rsp) files in the same directory.
+-BASEDIR=${1-.}
+-TESTDIR=${BASEDIR}/SHA
+-COMMAND=${2-run}
+-REQDIR=${TESTDIR}/req
+-RSPDIR=${TESTDIR}/resp
+-                               
+-sha_ShortMsg_requests="
+-SHA1ShortMsg.req
+-SHA224ShortMsg.req
+-SHA256ShortMsg.req
+-SHA384ShortMsg.req
+-SHA512ShortMsg.req
+-"
+-
+-sha_LongMsg_requests="
+-SHA1LongMsg.req
+-SHA224LongMsg.req
+-SHA256LongMsg.req
+-SHA384LongMsg.req
+-SHA512LongMsg.req
+-"
+-
+-sha_Monte_requests="
+-SHA1Monte.req
+-SHA224Monte.req
+-SHA256Monte.req
+-SHA384Monte.req
+-SHA512Monte.req
+-"
+-
+-if [ ${COMMAND} = "verify" ]; then
+-    for request in $sha_ShortMsg_requests $sha_LongMsg_requests $sha_Monte_requests; do
+-	sh ./validate1.sh ${TESTDIR} $request
+-    done
+-    exit 0
+-fi
+-
+-for request in $sha_ShortMsg_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest sha ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $sha_LongMsg_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest sha ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $sha_Monte_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest sha ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-
+diff --git a/cmd/fipstest/tdea.sh b/cmd/fipstest/tdea.sh
+deleted file mode 100644
+--- a/cmd/fipstest/tdea.sh
++++ /dev/null
+@@ -1,106 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-# A Bourne shell script for running the NIST tdea Algorithm Validation Suite
+-#
+-# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+-# variables appropriately so that the fipstest command and the NSPR and NSS
+-# shared libraries/DLLs are on the search path.  Then run this script in the
+-# directory where the REQUEST (.req) files reside.  The script generates the
+-# RESPONSE (.rsp) files in the same directory.
+-
+-BASEDIR=${1-.}
+-TESTDIR=${BASEDIR}/TDES
+-COMMAND=${2-run}
+-REQDIR=${TESTDIR}/req
+-RSPDIR=${TESTDIR}/resp
+-
+-#CBC_Known_Answer_tests
+-#Initial Permutation KAT  
+-#Permutation Operation KAT 
+-#Subsitution Table KAT    
+-#Variable Key KAT         
+-#Variable PlainText KAT   
+-cbc_kat_requests="
+-TCBCinvperm.req   
+-TCBCpermop.req    
+-TCBCsubtab.req    
+-TCBCvarkey.req    
+-TCBCvartext.req   
+-"
+-
+-#CBC Monte Carlo KATs
+-cbc_monte_requests="
+-TCBCMonte1.req
+-TCBCMonte2.req
+-TCBCMonte3.req
+-"
+-#Multi-block Message KATs
+-cbc_mmt_requests="
+-TCBCMMT1.req
+-TCBCMMT2.req
+-TCBCMMT3.req
+-"
+-
+-ecb_kat_requests="
+-TECBinvperm.req   
+-TECBpermop.req    
+-TECBsubtab.req    
+-TECBvarkey.req    
+-TECBvartext.req   
+-"
+-
+-ecb_monte_requests="
+-TECBMonte1.req
+-TECBMonte2.req
+-TECBMonte3.req
+-"
+-
+-ecb_mmt_requests="
+-TECBMMT1.req
+-TECBMMT2.req
+-TECBMMT3.req
+-"
+-
+-
+-if [ ${COMMAND} = "verify" ]; then
+-    for request in $cbc_kat_requests $cbc_monte_requests $cbc_mmt_requests $ecb_kat_requests $ecb_monte_requests $ecb_mmt_requests
+-    do
+-	sh ./validate1.sh ${TESTDIR} $request "-e /^NumKeys/d"
+-    done
+-    exit 0
+-fi
+-
+-for request in $cbc_kat_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest tdea kat cbc ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $cbc_mmt_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest tdea mmt cbc ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $cbc_monte_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest tdea mct cbc ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $ecb_kat_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest tdea kat ecb ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $ecb_mmt_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest tdea mmt ecb ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+-for request in $ecb_monte_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest tdea mct ecb ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+diff --git a/cmd/fipstest/tls.sh b/cmd/fipstest/tls.sh
+deleted file mode 100644
+--- a/cmd/fipstest/tls.sh
++++ /dev/null
+@@ -1,34 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-# A Bourne shell script for running the NIST RNG Validation Suite
+-#
+-# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+-# variables appropriately so that the fipstest command and the NSPR and NSS
+-# shared libraries/DLLs are on the search path.  Then run this script in the
+-# directory where the REQUEST (.req) files reside.  The script generates the
+-# RESPONSE (.rsp) files in the same directory.
+-BASEDIR=${1-.}
+-TESTDIR=${BASEDIR}/KDF135
+-COMMAND=${2-run}
+-REQDIR=${TESTDIR}/req
+-RSPDIR=${TESTDIR}/resp
+-
+-drbg_requests="
+-tls.req
+-"
+-
+-if [ ${COMMAND} = "verify" ]; then
+-    for request in $drbg_requests; do
+-	sh ./validate1.sh ${TESTDIR} $request
+-    done
+-    exit 0
+-fi
+-for request in $drbg_requests; do
+-    response=`echo $request | sed -e "s/req/rsp/"`
+-    echo $request $response
+-    fipstest tls ${REQDIR}/$request > ${RSPDIR}/$response
+-done
+diff --git a/cmd/fipstest/validate.sh b/cmd/fipstest/validate.sh
+deleted file mode 100644
+--- a/cmd/fipstest/validate.sh
++++ /dev/null
+@@ -1,7 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-sh ./runtest.sh ${1-.} verify
+diff --git a/cmd/fipstest/validate1.sh b/cmd/fipstest/validate1.sh
+deleted file mode 100644
+--- a/cmd/fipstest/validate1.sh
++++ /dev/null
+@@ -1,30 +0,0 @@
+-#!/bin/sh
+-# 
+-# 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/.
+-#
+-# Validate1.sh is a helper shell script that each of the base test shell 
+-# scripts call to help validate that the generated response (response) 
+-# matches the known answer response (fax). Sometimes (depending on the 
+-# individual tests) there are extraneous output in either or both response 
+-# and fax files. These allow the caller to pass in additional sed commands 
+-# to clear out those extraneous outputs before we compare the two files.
+-# The sed line always clears out Windows line endings, replaces tabs with 
+-# spaces, and removed comments.
+-#
+-TESTDIR=${1-.}
+-request=${2}
+-extraneous_response=${3}
+-extraneous_fax=${4}
+-name=`basename $request .req`
+-echo ">>>>>  $name"
+-sed -e 's;
;;g' -e 's;	; ;g' -e '/^#/d' $extraneous_response ${TESTDIR}/resp/${name}.rsp > /tmp/y1
+-# if we didn't generate any output, flag that as an error 
+-size=`sum /tmp/y1 | awk '{ print $NF }'`
+-if [ $size -eq 0 ]; then
+-   echo "${TESTDIR}/resp/${name}.rsp: empty"
+-   exit 1;
+-fi
+-sed -e 's;
;;g' -e 's;	; ;g' -e '/^#/d' $extraneous_fax ${TESTDIR}/fax/${name}.fax > /tmp/y2
+-diff -i -w -B /tmp/y1 /tmp/y2
+diff --git a/lib/pk11wrap/pk11mech.c b/lib/pk11wrap/pk11mech.c
+--- a/lib/pk11wrap/pk11mech.c
++++ b/lib/pk11wrap/pk11mech.c
+@@ -234,16 +234,18 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type, 
+         case CKM_AES_CTS:
+         case CKM_AES_GCM:
+         case CKM_AES_MAC:
+         case CKM_AES_MAC_GENERAL:
+         case CKM_AES_CBC_PAD:
+         case CKM_AES_KEY_GEN:
+         case CKM_NETSCAPE_AES_KEY_WRAP:
+         case CKM_NETSCAPE_AES_KEY_WRAP_PAD:
++        case CKM_AES_XCBC_MAC:
++        case CKM_AES_XCBC_MAC_96:
+             return CKK_AES;
+         case CKM_DES_ECB:
+         case CKM_DES_CBC:
+         case CKM_DES_MAC:
+         case CKM_DES_MAC_GENERAL:
+         case CKM_DES_CBC_PAD:
+         case CKM_DES_KEY_GEN:
+         case CKM_KEY_WRAP_LYNKS:
+diff --git a/lib/pk11wrap/pk11skey.c b/lib/pk11wrap/pk11skey.c
+--- a/lib/pk11wrap/pk11skey.c
++++ b/lib/pk11wrap/pk11skey.c
+@@ -1593,16 +1593,17 @@ PK11_DeriveWithTemplate(PK11SymKey *base
+         } else {
+             pk11_ExitKeyMonitor(symKey);
+         }
+     }
+     if (newBaseKey)
+         PK11_FreeSymKey(newBaseKey);
+     if (crv != CKR_OK) {
+         PK11_FreeSymKey(symKey);
++        PORT_SetError(PK11_MapError(crv));
+         return NULL;
+     }
+     return symKey;
+ }
+ 
+ /* Create a new key by concatenating base and data
+  */
+ static PK11SymKey *
+diff --git a/lib/softoken/fipstest.c b/lib/softoken/fipstest.c
+--- a/lib/softoken/fipstest.c
++++ b/lib/softoken/fipstest.c
+@@ -7,16 +7,17 @@
+ 
+ #ifndef NSS_FIPS_DISABLED
+ #include "seccomon.h"
+ #include "blapi.h"
+ #include "softoken.h"
+ #include "lowkeyi.h"
+ #include "secoid.h"
+ #include "secerr.h"
++#include "pkcs11i.h"
+ 
+ /*
+  * different platforms have different ways of calling and initial entry point
+  * when the dll/.so is loaded. Most platforms support either a posix pragma
+  * or the GCC attribute. Some platforms suppor a pre-defined name, and some
+  * platforms have a link line way of invoking this function.
+  */
+ 
+@@ -621,16 +622,20 @@ sftk_startup_tests(void)
+         return;
+     }
+     if (!BLAPI_SHVerify(libraryName,
+                         (PRFuncPtr)&sftk_fips_RSA_PowerUpSelfTest)) {
+         /* something is wrong with the library, fail without enabling
+          * the token */
+         return;
+     }
++    rv = sftk_fips_IKE_PowerUpSelfTests();
++    if (rv != SECSuccess) {
++        return;
++    }
+     sftk_self_tests_success = PR_TRUE;
+ }
+ 
+ /*
+  * this is called from nsc_Common_Initizialize entry points that gates access
+  * to * all other pkcs11 functions. This prevents softoken operation if our
+  * power on selftest failed.
+  */
+diff --git a/lib/softoken/manifest.mn b/lib/softoken/manifest.mn
+--- a/lib/softoken/manifest.mn
++++ b/lib/softoken/manifest.mn
+@@ -41,16 +41,17 @@ CSRCS = \
+ 	lowpbe.c   \
+ 	padbuf.c   \
+ 	pkcs11.c   \
+ 	pkcs11c.c  \
+ 	pkcs11u.c  \
+ 	sdb.c  \
+ 	sftkdb.c  \
+ 	sftkhmac.c  \
++	sftkike.c  \
+ 	sftkpars.c  \
+ 	sftkpwd.c  \
+ 	softkver.c  \
+ 	tlsprf.c   \
+ 	jpakesftk.c \
+ 	$(NULL)
+ 
+ ifdef SQLITE_UNSAFE_THREADS
+diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c
+--- a/lib/softoken/pkcs11.c
++++ b/lib/softoken/pkcs11.c
+@@ -323,16 +323,18 @@ static const struct mechanismList mechan
+     { CKM_AES_ECB, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
+     { CKM_AES_CBC, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
+     { CKM_AES_MAC, { 16, 32, CKF_SN_VR }, PR_TRUE },
+     { CKM_AES_MAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE },
+     { CKM_AES_CBC_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
+     { CKM_AES_CTS, { 16, 32, CKF_EN_DE }, PR_TRUE },
+     { CKM_AES_CTR, { 16, 32, CKF_EN_DE }, PR_TRUE },
+     { CKM_AES_GCM, { 16, 32, CKF_EN_DE }, PR_TRUE },
++    { CKM_AES_XCBC_MAC_96, { 12, 12, CKF_SN_VR }, PR_TRUE },
++    { CKM_AES_XCBC_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE },
+     /* ------------------------- Camellia Operations --------------------- */
+     { CKM_CAMELLIA_KEY_GEN, { 16, 32, CKF_GENERATE }, PR_TRUE },
+     { CKM_CAMELLIA_ECB, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
+     { CKM_CAMELLIA_CBC, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
+     { CKM_CAMELLIA_MAC, { 16, 32, CKF_SN_VR }, PR_TRUE },
+     { CKM_CAMELLIA_MAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE },
+     { CKM_CAMELLIA_CBC_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
+     /* ------------------------- SEED Operations --------------------------- */
+@@ -504,17 +506,21 @@ static const struct mechanismList mechan
+     { CKM_NSS_JPAKE_ROUND2_SHA384, { 0, 0, CKF_DERIVE }, PR_TRUE },
+     { CKM_NSS_JPAKE_ROUND2_SHA512, { 0, 0, CKF_DERIVE }, PR_TRUE },
+     { CKM_NSS_JPAKE_FINAL_SHA1, { 0, 0, CKF_DERIVE }, PR_TRUE },
+     { CKM_NSS_JPAKE_FINAL_SHA256, { 0, 0, CKF_DERIVE }, PR_TRUE },
+     { CKM_NSS_JPAKE_FINAL_SHA384, { 0, 0, CKF_DERIVE }, PR_TRUE },
+     { CKM_NSS_JPAKE_FINAL_SHA512, { 0, 0, CKF_DERIVE }, PR_TRUE },
+     /* -------------------- Constant Time TLS MACs ----------------------- */
+     { CKM_NSS_HMAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE },
+-    { CKM_NSS_SSL3_MAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE }
++    { CKM_NSS_SSL3_MAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE },
++    /* --------------------IPSEC ----------------------- */
++    { CKM_NSS_IKE_PRF_PLUS_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE },
++    { CKM_NSS_IKE_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE },
++    { CKM_NSS_IKE1_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE }
+ };
+ static const CK_ULONG mechanismCount = sizeof(mechanisms) / sizeof(mechanisms[0]);
+ 
+ /* sigh global so fipstokn can read it */
+ PRBool nsc_init = PR_FALSE;
+ 
+ #if defined(CHECK_FORK_PTHREAD) || defined(CHECK_FORK_MIXED)
+ 
+diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
+--- a/lib/softoken/pkcs11c.c
++++ b/lib/softoken/pkcs11c.c
+@@ -94,49 +94,16 @@ sftk_Space(void *data, PRBool freeit)
+     PORT_Free(data);
+ }
+ 
+ /*
+  * map all the SEC_ERROR_xxx error codes that may be returned by freebl
+  * functions to CKR_xxx.  return CKR_DEVICE_ERROR by default for backward
+  * compatibility.
+  */
+-static CK_RV
+-sftk_MapCryptError(int error)
+-{
+-    switch (error) {
+-        case SEC_ERROR_INVALID_ARGS:
+-        case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */
+-            return CKR_ARGUMENTS_BAD;
+-        case SEC_ERROR_INPUT_LEN:
+-            return CKR_DATA_LEN_RANGE;
+-        case SEC_ERROR_OUTPUT_LEN:
+-            return CKR_BUFFER_TOO_SMALL;
+-        case SEC_ERROR_LIBRARY_FAILURE:
+-            return CKR_GENERAL_ERROR;
+-        case SEC_ERROR_NO_MEMORY:
+-            return CKR_HOST_MEMORY;
+-        case SEC_ERROR_BAD_SIGNATURE:
+-            return CKR_SIGNATURE_INVALID;
+-        case SEC_ERROR_INVALID_KEY:
+-            return CKR_KEY_SIZE_RANGE;
+-        case SEC_ERROR_BAD_KEY:        /* an EC public key that fails validation */
+-            return CKR_KEY_SIZE_RANGE; /* the closest error code */
+-        case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM:
+-            return CKR_TEMPLATE_INCONSISTENT;
+-        case SEC_ERROR_UNSUPPORTED_KEYALG:
+-            return CKR_MECHANISM_INVALID;
+-        case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE:
+-            return CKR_DOMAIN_PARAMS_INVALID;
+-        /* key pair generation failed after max number of attempts */
+-        case SEC_ERROR_NEED_RANDOM:
+-            return CKR_FUNCTION_FAILED;
+-    }
+-    return CKR_DEVICE_ERROR;
+-}
+ 
+ /* used by Decrypt and UnwrapKey (indirectly) */
+ static CK_RV
+ sftk_MapDecryptError(int error)
+ {
+     switch (error) {
+         case SEC_ERROR_BAD_DATA:
+             return CKR_ENCRYPTED_DATA_INVALID;
+@@ -2075,19 +2042,22 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSessi
+     CK_MECHANISM cbc_mechanism;
+     CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE;
+     CK_RC2_CBC_PARAMS rc2_params;
+ #if NSS_SOFTOKEN_DOES_RC5
+     CK_RC5_CBC_PARAMS rc5_params;
+     CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
+ #endif
+     unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
++    unsigned char k2[SFTK_MAX_BLOCK_SIZE];
++    unsigned char k3[SFTK_MAX_BLOCK_SIZE];
+     SFTKSessionContext *context;
+     CK_RV crv;
+     unsigned int blockSize;
++    PRBool isXCBC = PR_FALSE;
+ 
+     switch (pMechanism->mechanism) {
+         case CKM_RC2_MAC_GENERAL:
+             if (!pMechanism->pParameter) {
+                 return CKR_MECHANISM_PARAM_INVALID;
+             }
+             mac_bytes =
+                 ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
+@@ -2181,43 +2151,82 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSessi
+         /* fall through */
+         case CKM_AES_MAC:
+             blockSize = 16;
+             PORT_Memset(ivBlock, 0, blockSize);
+             cbc_mechanism.mechanism = CKM_AES_CBC;
+             cbc_mechanism.pParameter = &ivBlock;
+             cbc_mechanism.ulParameterLen = blockSize;
+             break;
++        case CKM_AES_XCBC_MAC_96:
++        case CKM_AES_XCBC_MAC:
++            /* The only difference between CKM_AES_XCBC_MAC
++             * and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */
++            mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16;
++            blockSize = 16;
++            PORT_Memset(ivBlock, 0, blockSize);
++            cbc_mechanism.mechanism = CKM_AES_CBC;
++            cbc_mechanism.pParameter = &ivBlock;
++            cbc_mechanism.ulParameterLen = blockSize;
++            /* is XCBC requires extra processing at the end of the operation */
++            isXCBC = PR_TRUE;
++            /* The input key is used to generate k1, k2, and k3. k2 and k3
++             * are used at the end in the pad step. k1 replaces the input
++             * key in the aes cbc mac */
++            crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3);
++            if (crv != CKR_OK) {
++                return crv;
++            }
++            break;
+         default:
+             return CKR_FUNCTION_NOT_SUPPORTED;
+     }
+ 
+     /* if MAC size is externally supplied, it should be checked.
+      */
+     if (mac_bytes == SFTK_INVALID_MAC_SIZE)
+         mac_bytes = blockSize >> 1;
+     else {
+-        if (mac_bytes > blockSize)
+-            return CKR_MECHANISM_PARAM_INVALID;
++        if (mac_bytes > blockSize) {
++            crv = CKR_MECHANISM_PARAM_INVALID;
++            goto fail;
++        }
+     }
+ 
+     crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey,
+                          CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */
+                          keyUsage, contextType, PR_TRUE);
+     if (crv != CKR_OK)
+-        return crv;
++        goto fail;
+     crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
+ 
+     /* this shouldn't happen! */
+     PORT_Assert(crv == CKR_OK);
+     if (crv != CKR_OK)
+-        return crv;
++        goto fail;
+     context->blockSize = blockSize;
+     context->macSize = mac_bytes;
++    context->isXCBC = isXCBC;
++    if (isXCBC) {
++        /* save the xcbc specific parameters */
++        PORT_Memcpy(context->k2, k2, blockSize);
++        PORT_Memcpy(context->k3, k3, blockSize);
++        PORT_Memset(k2, 0, blockSize);
++        PORT_Memset(k3, 0, blockSize);
++        /* get rid of the temp key now that the context has been created */
++        NSC_DestroyObject(hSession, hKey);
++    }
+     return CKR_OK;
++fail:
++    if (isXCBC) {
++        PORT_Memset(k2, 0, blockSize);
++        PORT_Memset(k3, 0, blockSize);
++        NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */
++    }
++    return crv;
+ }
+ 
+ /*
+  * encode RSA PKCS #1 Signature data before signing...
+  */
+ static SECStatus
+ sftk_RSAHashSign(SFTKHashSignInfo *info, unsigned char *sig,
+                  unsigned int *sigLen, unsigned int maxLen,
+@@ -2823,16 +2832,23 @@ sftk_MACBlock(SFTKSessionContext *ctx, v
+  *
+  *  Call once, then terminate MACing operation.
+  */
+ static CK_RV
+ sftk_MACFinal(SFTKSessionContext *ctx)
+ {
+     unsigned int padLen = ctx->padDataLength;
+     /* pad and proceed the residual */
++    if (ctx->isXCBC) {
++        CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize,
++                                      ctx->k2, ctx->k3);
++        if (crv != CKR_OK)
++            return crv;
++        return sftk_MACBlock(ctx, ctx->padBuf);
++    }
+     if (padLen) {
+         /* shd clr ctx->padLen to make sftk_MACFinal idempotent */
+         PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen);
+         return sftk_MACBlock(ctx, ctx->padBuf);
+     } else
+         return CKR_OK;
+ }
+ 
+@@ -2861,31 +2877,31 @@ sftk_MACUpdate(CK_SESSION_HANDLE hSessio
+ 
+         unsigned int blkSize = context->blockSize;
+         unsigned char *residual = /* free room in context->padBuf */
+             context->padBuf + context->padDataLength;
+         unsigned int minInput = /* min input for MACing at least one block */
+             blkSize - context->padDataLength;
+ 
+         /* not enough data even for one block */
+-        if (ulPartLen < minInput) {
++        if (ulPartLen <= minInput) {
+             PORT_Memcpy(residual, pPart, ulPartLen);
+             context->padDataLength += ulPartLen;
+             goto cleanup;
+         }
+         /* MACing residual */
+         if (context->padDataLength) {
+             PORT_Memcpy(residual, pPart, minInput);
+             ulPartLen -= minInput;
+             pPart += minInput;
+             if (CKR_OK != (crv = sftk_MACBlock(context, context->padBuf)))
+                 goto terminate;
+         }
+         /* MACing full blocks */
+-        while (ulPartLen >= blkSize) {
++        while (ulPartLen > blkSize) {
+             if (CKR_OK != (crv = sftk_MACBlock(context, pPart)))
+                 goto terminate;
+             ulPartLen -= blkSize;
+             pPart += blkSize;
+         }
+         /* save the residual */
+         if ((context->padDataLength = ulPartLen))
+             PORT_Memcpy(context->padBuf, pPart, ulPartLen);
+@@ -6513,16 +6529,55 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
+         if (att == NULL) {
+             sftk_FreeObject(key);
+             sftk_FreeObject(sourceKey);
+             return CKR_KEY_HANDLE_INVALID;
+         }
+     }
+ 
+     switch (mechanism) {
++        case CKM_NSS_IKE_PRF_DERIVE:
++            if (pMechanism->ulParameterLen !=
++                sizeof(CK_NSS_IKE_PRF_DERIVE_PARAMS)) {
++                crv = CKR_MECHANISM_PARAM_INVALID;
++                break;
++            }
++            crv = sftk_ike_prf(hSession, att,
++                               (CK_NSS_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key);
++            break;
++        case CKM_NSS_IKE1_PRF_DERIVE:
++            if (pMechanism->ulParameterLen !=
++                sizeof(CK_NSS_IKE1_PRF_DERIVE_PARAMS)) {
++                crv = CKR_MECHANISM_PARAM_INVALID;
++                break;
++            }
++            crv = sftk_ike1_prf(hSession, att,
++                                (CK_NSS_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter,
++                                key, keySize);
++            break;
++        case CKM_NSS_IKE1_APP_B_PRF_DERIVE:
++            if (pMechanism->ulParameterLen !=
++                sizeof(CK_MECHANISM_TYPE)) {
++                crv = CKR_MECHANISM_PARAM_INVALID;
++                break;
++            }
++            crv = sftk_ike1_appendix_b_prf(hSession, att,
++                                           (CK_MECHANISM_TYPE *)pMechanism->pParameter,
++                                           key, keySize);
++            break;
++        case CKM_NSS_IKE_PRF_PLUS_DERIVE:
++            if (pMechanism->ulParameterLen !=
++                sizeof(CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS)) {
++                crv = CKR_MECHANISM_PARAM_INVALID;
++                break;
++            }
++            crv = sftk_ike_prf_plus(hSession, att,
++                                    (CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter,
++                                    key, keySize);
++            break;
+         /*
+          * generate the master secret
+          */
+         case CKM_TLS12_MASTER_KEY_DERIVE:
+         case CKM_TLS12_MASTER_KEY_DERIVE_DH:
+         case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256:
+         case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256:
+         case CKM_TLS_MASTER_KEY_DERIVE:
+diff --git a/lib/softoken/pkcs11i.h b/lib/softoken/pkcs11i.h
+--- a/lib/softoken/pkcs11i.h
++++ b/lib/softoken/pkcs11i.h
+@@ -248,22 +248,25 @@ typedef enum {
+  *      multi=0 hashInfo=0   PKC S/V one shot (w/o hashing)
+  *      multi=0 hashInfo=X   *** shouldn't happen ***
+  */
+ struct SFTKSessionContextStr {
+     SFTKContextType type;
+     PRBool multi;               /* is multipart */
+     PRBool rsa;                 /* is rsa */
+     PRBool doPad;               /* use PKCS padding for block ciphers */
++    PRBool isXCBC;              /* xcbc, use special handling in final */
+     unsigned int blockSize;     /* blocksize for padding */
+     unsigned int padDataLength; /* length of the valid data in padbuf */
+     /** latest incomplete block of data for block cipher */
+     unsigned char padBuf[SFTK_MAX_BLOCK_SIZE];
+     /** result of MAC'ing of latest full block of data with block cipher */
+     unsigned char macBuf[SFTK_MAX_BLOCK_SIZE];
++    unsigned char k2[SFTK_MAX_BLOCK_SIZE];
++    unsigned char k3[SFTK_MAX_BLOCK_SIZE];
+     CK_ULONG macSize; /* size of a general block cipher mac*/
+     void *cipherInfo;
+     void *hashInfo;
+     unsigned int cipherInfoLen;
+     CK_MECHANISM_TYPE currentMech;
+     SFTKCipher update;
+     SFTKHash hashUpdate;
+     SFTKEnd end;
+@@ -600,16 +603,17 @@ extern CK_RV SFTK_SlotInit(char *configd
+ extern CK_RV SFTK_SlotReInit(SFTKSlot *slot, char *configdir,
+                              char *updatedir, char *updateID,
+                              sftk_token_parameters *params, int moduleIndex);
+ extern CK_RV SFTK_DestroySlotData(SFTKSlot *slot);
+ extern CK_RV SFTK_ShutdownSlot(SFTKSlot *slot);
+ extern CK_RV sftk_CloseAllSessions(SFTKSlot *slot, PRBool logout);
+ 
+ /* internal utility functions used by pkcs11.c */
++extern CK_RV sftk_MapCryptError(int error);
+ extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object,
+                                          CK_ATTRIBUTE_TYPE type);
+ extern void sftk_FreeAttribute(SFTKAttribute *attribute);
+ extern CK_RV sftk_AddAttributeType(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
+                                    const void *valPtr, CK_ULONG length);
+ extern CK_RV sftk_Attribute2SecItem(PLArenaPool *arena, SECItem *item,
+                                     SFTKObject *object, CK_ATTRIBUTE_TYPE type);
+ extern CK_RV sftk_MultipleAttribute2SecItem(PLArenaPool *arena,
+@@ -681,16 +685,40 @@ extern void sftk_CleanupFreeLists(void);
+ extern NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKObject *object,
+                                           CK_KEY_TYPE key_type, CK_RV *crvp);
+ extern NSSLOWKEYPrivateKey *sftk_GetPrivKey(SFTKObject *object,
+                                             CK_KEY_TYPE key_type, CK_RV *crvp);
+ extern void sftk_FormatDESKey(unsigned char *key, int length);
+ extern PRBool sftk_CheckDESKey(unsigned char *key);
+ extern PRBool sftk_IsWeakKey(unsigned char *key, CK_KEY_TYPE key_type);
+ 
++/* ike and xcbc helpers */
++extern CK_RV sftk_ike_prf(CK_SESSION_HANDLE hSession,
++                          const SFTKAttribute *inKey,
++                          const CK_NSS_IKE_PRF_DERIVE_PARAMS *params, SFTKObject *outKey);
++extern CK_RV sftk_ike1_prf(CK_SESSION_HANDLE hSession,
++                           const SFTKAttribute *inKey,
++                           const CK_NSS_IKE1_PRF_DERIVE_PARAMS *params, SFTKObject *outKey,
++                           unsigned int keySize);
++extern CK_RV sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession,
++                                      const SFTKAttribute *inKey,
++                                      const CK_MECHANISM_TYPE *params, SFTKObject *outKey,
++                                      unsigned int keySize);
++extern CK_RV sftk_ike_prf_plus(CK_SESSION_HANDLE hSession,
++                               const SFTKAttribute *inKey,
++                               const CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *params, SFTKObject *outKey,
++                               unsigned int keySize);
++extern CK_RV sftk_aes_xcbc_new_keys(CK_SESSION_HANDLE hSession,
++                                    CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE_PTR phKey,
++                                    unsigned char *k2, unsigned char *k3);
++extern CK_RV sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen,
++                               int blockSize, const unsigned char *k2,
++                               const unsigned char *k3);
++extern SECStatus sftk_fips_IKE_PowerUpSelfTests(void);
++
+ /* mechanism allows this operation */
+ extern CK_RV sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op);
+ 
+ /* helper function which calls nsslowkey_FindKeyByPublicKey after safely
+  * acquiring a reference to the keydb from the slot */
+ NSSLOWKEYPrivateKey *sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey);
+ 
+ /*
+diff --git a/lib/softoken/pkcs11u.c b/lib/softoken/pkcs11u.c
+--- a/lib/softoken/pkcs11u.c
++++ b/lib/softoken/pkcs11u.c
+@@ -10,16 +10,57 @@
+ #include "secasn1.h"
+ #include "blapi.h"
+ #include "secerr.h"
+ #include "prnetdb.h" /* for PR_ntohl */
+ #include "sftkdb.h"
+ #include "softoken.h"
+ 
+ /*
++ * ******************** Error mapping *******************************
++ */
++/*
++ * map all the SEC_ERROR_xxx error codes that may be returned by freebl
++ * functions to CKR_xxx.  return CKR_DEVICE_ERROR by default for backward
++ * compatibility.
++ */
++CK_RV
++sftk_MapCryptError(int error)
++{
++    switch (error) {
++        case SEC_ERROR_INVALID_ARGS:
++        case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */
++            return CKR_ARGUMENTS_BAD;
++        case SEC_ERROR_INPUT_LEN:
++            return CKR_DATA_LEN_RANGE;
++        case SEC_ERROR_OUTPUT_LEN:
++            return CKR_BUFFER_TOO_SMALL;
++        case SEC_ERROR_LIBRARY_FAILURE:
++            return CKR_GENERAL_ERROR;
++        case SEC_ERROR_NO_MEMORY:
++            return CKR_HOST_MEMORY;
++        case SEC_ERROR_BAD_SIGNATURE:
++            return CKR_SIGNATURE_INVALID;
++        case SEC_ERROR_INVALID_KEY:
++            return CKR_KEY_SIZE_RANGE;
++        case SEC_ERROR_BAD_KEY:        /* an EC public key that fails validation */
++            return CKR_KEY_SIZE_RANGE; /* the closest error code */
++        case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM:
++            return CKR_TEMPLATE_INCONSISTENT;
++        case SEC_ERROR_UNSUPPORTED_KEYALG:
++            return CKR_MECHANISM_INVALID;
++        case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE:
++            return CKR_DOMAIN_PARAMS_INVALID;
++        /* key pair generation failed after max number of attempts */
++        case SEC_ERROR_NEED_RANDOM:
++            return CKR_FUNCTION_FAILED;
++    }
++    return CKR_DEVICE_ERROR;
++}
++/*
+  * ******************** Attribute Utilities *******************************
+  */
+ 
+ /*
+  * create a new attribute with type, value, and length. Space is allocated
+  * to hold value.
+  */
+ static SFTKAttribute *
+diff --git a/lib/softoken/sftkike.c b/lib/softoken/sftkike.c
+new file mode 100644
+--- /dev/null
++++ b/lib/softoken/sftkike.c
+@@ -0,0 +1,1288 @@
++/* 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/. */
++/*
++ * This file implements PKCS 11 on top of our existing security modules
++ *
++ * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
++ *   This implementation has two slots:
++ *      slot 1 is our generic crypto support. It does not require login.
++ *   It supports Public Key ops, and all they bulk ciphers and hashes.
++ *   It can also support Private Key ops for imported Private keys. It does
++ *   not have any token storage.
++ *      slot 2 is our private key support. It requires a login before use. It
++ *   can store Private Keys and Certs as token objects. Currently only private
++ *   keys and their associated Certificates are saved on the token.
++ *
++ *   In this implementation, session objects are only visible to the session
++ *   that created or generated them.
++ */
++#include "seccomon.h"
++#include "secitem.h"
++#include "secport.h"
++#include "blapi.h"
++#include "pkcs11.h"
++#include "pkcs11i.h"
++#include "pkcs1sig.h"
++#include "lowkeyi.h"
++#include "secder.h"
++#include "secdig.h"
++#include "lowpbe.h" /* We do PBE below */
++#include "pkcs11t.h"
++#include "secoid.h"
++#include "alghmac.h"
++#include "softoken.h"
++#include "secasn1.h"
++#include "secerr.h"
++
++#include "prprf.h"
++#include "prenv.h"
++
++/*
++ * A common prfContext to handle both hmac and aes xcbc
++ * hash contexts have non-null hashObj and hmac, aes
++ * contexts have non-null aes */
++typedef struct prfContextStr {
++    HASH_HashType hashType;
++    const SECHashObject *hashObj;
++    HMACContext *hmac;
++    AESContext *aes;
++    unsigned int nextChar;
++    unsigned char padBuf[AES_BLOCK_SIZE];
++    unsigned char macBuf[AES_BLOCK_SIZE];
++    unsigned char k1[AES_BLOCK_SIZE];
++    unsigned char k2[AES_BLOCK_SIZE];
++    unsigned char k3[AES_BLOCK_SIZE];
++} prfContext;
++
++/* iv full of zeros used in several places in aex xcbc */
++static const unsigned char iv_zero[] = {
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++
++/*
++ * Generate AES XCBC keys from the AES MAC key.
++ * k1 is used in the actual mac.
++ * k2 and k3 are used in the final pad step.
++ */
++static CK_RV
++sftk_aes_xcbc_get_keys(const unsigned char *keyValue, unsigned int keyLen,
++                       unsigned char *k1, unsigned char *k2, unsigned char *k3)
++{
++    SECStatus rv;
++    CK_RV crv;
++    unsigned int tmpLen;
++    AESContext *aes_context = NULL;
++    unsigned char newKey[AES_BLOCK_SIZE];
++
++    /* AES XCBC keys. k1, k2, and k3 are derived by encrypting
++     * k1data, k2data, and k3data with the mac key.
++     */
++    static const unsigned char k1data[] = {
++        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
++        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
++    };
++    static const unsigned char k2data[] = {
++        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
++        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
++    };
++    static const unsigned char k3data[] = {
++        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
++        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
++    };
++
++    /* k1_0 = aes_ecb(0, k1data) */
++    static const unsigned char k1_0[] = {
++        0xe1, 0x4d, 0x5d, 0x0e, 0xe2, 0x77, 0x15, 0xdf,
++        0x08, 0xb4, 0x15, 0x2b, 0xa2, 0x3d, 0xa8, 0xe0
++
++    };
++    /* k2_0 = aes_ecb(0, k2data) */
++    static const unsigned char k2_0[] = {
++        0x5e, 0xba, 0x73, 0xf8, 0x91, 0x42, 0xc5, 0x48,
++        0x80, 0xf6, 0x85, 0x94, 0x37, 0x3c, 0x5c, 0x37
++    };
++    /* k3_0 = aes_ecb(0, k3data) */
++    static const unsigned char k3_0[] = {
++        0x8d, 0x34, 0xef, 0xcb, 0x3b, 0xd5, 0x45, 0xca,
++        0x06, 0x2a, 0xec, 0xdf, 0xef, 0x7c, 0x0b, 0xfa
++    };
++
++    /* first make sure out input key is the correct length
++     * rfc 4434. If key is shorter, pad with zeros to the
++     * the right. If key is longer newKey = aes_xcbc(0, key, keyLen).
++     */
++    if (keyLen < AES_BLOCK_SIZE) {
++        PORT_Memcpy(newKey, keyValue, keyLen);
++        PORT_Memset(&newKey[keyLen], 0, AES_BLOCK_SIZE - keyLen);
++        keyValue = newKey;
++    } else if (keyLen > AES_BLOCK_SIZE) {
++        /* calculate our new key = aes_xcbc(0, key, keyLen). Because the
++         * key above is fixed (0), we can precalculate k1, k2, and k2.
++         * if this code ever needs to be more generic (support any xcbc
++         * function rather than just aes, we would probably want to just
++         * recurse here using our prf functions. This would be safe because
++         * the recurse case would have keyLen == blocksize and thus skip
++         * this conditional.
++         */
++        aes_context = AES_CreateContext(k1_0, iv_zero, NSS_AES_CBC,
++                                        PR_TRUE, AES_BLOCK_SIZE, AES_BLOCK_SIZE);
++        /* we know the following loop will execute at least once */
++        while (keyLen > AES_BLOCK_SIZE) {
++            rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE,
++                             keyValue, AES_BLOCK_SIZE);
++            if (rv != SECSuccess) {
++                goto fail;
++            }
++            keyValue += AES_BLOCK_SIZE;
++            keyLen -= AES_BLOCK_SIZE;
++        }
++        PORT_Memcpy(newKey, keyValue, keyLen);
++        sftk_xcbc_mac_pad(newKey, keyLen, AES_BLOCK_SIZE, k2_0, k3_0);
++        rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE,
++                         newKey, AES_BLOCK_SIZE);
++        if (rv != SECSuccess) {
++            goto fail;
++        }
++        keyValue = newKey;
++        AES_DestroyContext(aes_context, PR_TRUE);
++    }
++    /* the length of the key in keyValue is known to be AES_BLOCK_SIZE,
++     * either because it was on input, or it was shorter and extended, or
++     * because it was mac'd down using aes_xcbc_prf.
++     */
++    aes_context = AES_CreateContext(keyValue, iv_zero,
++                                    NSS_AES, PR_TRUE, AES_BLOCK_SIZE, AES_BLOCK_SIZE);
++    if (aes_context == NULL) {
++        goto fail;
++    }
++    rv = AES_Encrypt(aes_context, k1, &tmpLen, AES_BLOCK_SIZE,
++                     k1data, sizeof(k1data));
++    if (rv != SECSuccess) {
++        goto fail;
++    }
++    rv = AES_Encrypt(aes_context, k2, &tmpLen, AES_BLOCK_SIZE,
++                     k2data, sizeof(k2data));
++    if (rv != SECSuccess) {
++        goto fail;
++    }
++    rv = AES_Encrypt(aes_context, k3, &tmpLen, AES_BLOCK_SIZE,
++                     k3data, sizeof(k3data));
++    if (rv != SECSuccess) {
++        goto fail;
++    }
++    AES_DestroyContext(aes_context, PR_TRUE);
++    PORT_Memset(newKey, 0, AES_BLOCK_SIZE);
++    return CKR_OK;
++fail:
++    crv = sftk_MapCryptError(PORT_GetError());
++    if (aes_context) {
++        AES_DestroyContext(aes_context, PR_TRUE);
++    }
++    PORT_Memset(k1, 0, AES_BLOCK_SIZE);
++    PORT_Memset(k2, 0, AES_BLOCK_SIZE);
++    PORT_Memset(k3, 0, AES_BLOCK_SIZE);
++    PORT_Memset(newKey, 0, AES_BLOCK_SIZE);
++    return crv;
++}
++
++/* encode the final pad block of aes xcbc, padBuf is modified */
++CK_RV
++sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen, int blockSize,
++                  const unsigned char *k2, const unsigned char *k3)
++{
++    int i;
++    if (bufLen == blockSize) {
++        for (i = 0; i < blockSize; i++) {
++            padBuf[i] ^= k2[i];
++        }
++    } else {
++        padBuf[bufLen++] = 0x80;
++        for (i = bufLen; i < blockSize; i++) {
++            padBuf[i] = 0x00;
++        }
++        for (i = 0; i < blockSize; i++) {
++            padBuf[i] ^= k3[i];
++        }
++    }
++    return CKR_OK;
++}
++
++/* Map the mechanism to the underlying hash. If the type is not a hash
++ * or HMAC, return HASH_AlgNULL. This can happen legitimately if
++ * we are doing AES XCBC */
++static HASH_HashType
++sftk_map_hmac_to_hash(CK_MECHANISM_TYPE type)
++{
++    switch (type) {
++        case CKM_SHA_1_HMAC:
++        case CKM_SHA_1:
++            return HASH_AlgSHA1;
++        case CKM_MD5_HMAC:
++        case CKM_MD5:
++            return HASH_AlgMD5;
++        case CKM_MD2_HMAC:
++        case CKM_MD2:
++            return HASH_AlgMD2;
++        case CKM_SHA224_HMAC:
++        case CKM_SHA224:
++            return HASH_AlgSHA224;
++        case CKM_SHA256_HMAC:
++        case CKM_SHA256:
++            return HASH_AlgSHA256;
++        case CKM_SHA384_HMAC:
++        case CKM_SHA384:
++            return HASH_AlgSHA384;
++        case CKM_SHA512_HMAC:
++        case CKM_SHA512:
++            return HASH_AlgSHA512;
++    }
++    return HASH_AlgNULL;
++}
++
++/*
++ * Generally setup the context based on the mechanism.
++ * If the mech is HMAC, context->hashObj should be set
++ * Otherwise it is assumed to be AES XCBC. prf_setup
++ * checks these assumptions and will return an error
++ * if they are not met. NOTE: this function does not allocate
++ * anything, so there is no requirement to free context after
++ * prf_setup like there is if you call prf_init.
++ */
++static CK_RV
++prf_setup(prfContext *context, CK_MECHANISM_TYPE mech)
++{
++    context->hashType = sftk_map_hmac_to_hash(mech);
++    context->hashObj = NULL;
++    context->hmac = NULL;
++    context->aes = NULL;
++    if (context->hashType != HASH_AlgNULL) {
++        context->hashObj = HASH_GetRawHashObject(context->hashType);
++        if (context->hashObj == NULL) {
++            return CKR_GENERAL_ERROR;
++        }
++        return CKR_OK;
++    } else if (mech == CKM_AES_XCBC_MAC) {
++        return CKR_OK;
++    }
++    return CKR_MECHANISM_PARAM_INVALID;
++}
++
++/* return the underlying prf length for this context. This will
++ * function once the context is setup */
++static CK_RV
++prf_length(prfContext *context)
++{
++    if (context->hashObj) {
++        return context->hashObj->length;
++    }
++    return AES_BLOCK_SIZE; /* AES */
++}
++
++/* set up the key for the prf. prf_update or prf_final should not be called if
++ * prf_init has not been called first. Once prf_init returns hmac and
++ * aes contexts should set and valid.
++ */
++static CK_RV
++prf_init(prfContext *context, const unsigned char *keyValue,
++         unsigned int keyLen)
++{
++    CK_RV crv;
++
++    context->hmac = NULL;
++    if (context->hashObj) {
++        context->hmac = HMAC_Create(context->hashObj,
++                                    keyValue, keyLen, PR_FALSE);
++        if (context->hmac == NULL) {
++            return sftk_MapCryptError(PORT_GetError());
++        }
++        HMAC_Begin(context->hmac);
++    } else {
++        crv = sftk_aes_xcbc_get_keys(keyValue, keyLen, context->k1,
++                                     context->k2, context->k3);
++        if (crv != CKR_OK)
++            return crv;
++        context->nextChar = 0;
++        context->aes = AES_CreateContext(context->k1, iv_zero, NSS_AES_CBC,
++                                         PR_TRUE, sizeof(context->k1), AES_BLOCK_SIZE);
++        if (context->aes == NULL) {
++            crv = sftk_MapCryptError(PORT_GetError());
++            PORT_Memset(context->k1, 0, sizeof(context->k1));
++            PORT_Memset(context->k2, 0, sizeof(context->k2));
++            PORT_Memset(context->k3, 0, sizeof(context->k2));
++            return crv;
++        }
++    }
++    return CKR_OK;
++}
++
++/*
++ * process input to the prf
++ */
++static CK_RV
++prf_update(prfContext *context, const unsigned char *buf, unsigned int len)
++{
++    unsigned int tmpLen;
++    SECStatus rv;
++
++    if (context->hmac) {
++        HMAC_Update(context->hmac, buf, len);
++    } else {
++        /* AES MAC XCBC*/
++        /* We must keep the last block back so that it can be processed in
++         * final. This is why we only check that nextChar + len > blocksize,
++         * rather than checking that nextChar + len >= blocksize */
++        while (context->nextChar + len > AES_BLOCK_SIZE) {
++            if (context->nextChar != 0) {
++                /* first handle fill in any partial blocks in the buffer */
++                unsigned int left = AES_BLOCK_SIZE - context->nextChar;
++                /* note: left can be zero */
++                PORT_Memcpy(context->padBuf + context->nextChar, buf, left);
++                /* NOTE: AES MAC XCBC xors the data with the previous block
++                 * We don't do that step here because our AES_Encrypt mode
++                 * is CBC, which does the xor automatically */
++                rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,
++                                 sizeof(context->macBuf), context->padBuf,
++                                 sizeof(context->padBuf));
++                if (rv != SECSuccess) {
++                    return sftk_MapCryptError(PORT_GetError());
++                }
++                context->nextChar = 0;
++                len -= left;
++                buf += left;
++            } else {
++                /* optimization. if we have complete blocks to write out
++                 * (and will still have leftover blocks for padbuf in the end).
++                 * we can mac directly out of our buffer without first copying
++                 * them to padBuf */
++                rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,
++                                 sizeof(context->macBuf), buf, AES_BLOCK_SIZE);
++                if (rv != SECSuccess) {
++                    return sftk_MapCryptError(PORT_GetError());
++                }
++                len -= AES_BLOCK_SIZE;
++                buf += AES_BLOCK_SIZE;
++            }
++        }
++        PORT_Memcpy(context->padBuf + context->nextChar, buf, len);
++        context->nextChar += len;
++    }
++    return CKR_OK;
++}
++
++/*
++ * free the data associated with the prf. Clear any possible CSPs
++ * This can safely be called on any context after prf_setup. It can
++ * also be called an an already freed context.
++ * A free context can be reused by calling prf_init again without
++ * the need to call prf_setup.
++ */
++static void
++prf_free(prfContext *context)
++{
++    if (context->hmac) {
++        HMAC_Destroy(context->hmac, PR_TRUE);
++        context->hmac = NULL;
++    }
++    if (context->aes) {
++        PORT_Memset(context->k1, 0, sizeof(context->k1));
++        PORT_Memset(context->k2, 0, sizeof(context->k2));
++        PORT_Memset(context->k3, 0, sizeof(context->k2));
++        PORT_Memset(context->padBuf, 0, sizeof(context->padBuf));
++        PORT_Memset(context->macBuf, 0, sizeof(context->macBuf));
++        AES_DestroyContext(context->aes, PR_TRUE);
++        context->aes = NULL;
++    }
++}
++
++/*
++ * extract the final prf value. On success, this has the side effect of
++ * also freeing the context data and clearing the keys
++ */
++static CK_RV
++prf_final(prfContext *context, unsigned char *buf, unsigned int len)
++{
++    unsigned int tmpLen;
++    SECStatus rv;
++
++    if (context->hmac) {
++        unsigned int outLen;
++        HMAC_Finish(context->hmac, buf, &outLen, len);
++        if (outLen != len) {
++            return CKR_GENERAL_ERROR;
++        }
++    } else {
++        /* prf_update had guarrenteed that the last full block is still in
++         * the padBuf if the input data is a multiple of the blocksize. This
++         * allows sftk_xcbc_mac_pad to process that pad buf accordingly */
++        sftk_xcbc_mac_pad(context->padBuf, context->nextChar, AES_BLOCK_SIZE,
++                          context->k2, context->k3);
++        rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,
++                         sizeof(context->macBuf), context->padBuf, AES_BLOCK_SIZE);
++        if (rv != SECSuccess) {
++            return sftk_MapCryptError(PORT_GetError());
++        }
++        PORT_Memcpy(buf, context->macBuf, len);
++    }
++    prf_free(context);
++    return CKR_OK;
++}
++
++/*
++ * There are four flavors of ike prf functions here.
++ * ike_prf is used in both ikeV1 and ikeV2 to generate
++ * an initial key that all the other keys are generated with.
++ *
++ * These functions are called from NSC_DeriveKey with the inKey value
++ * already looked up, and it expects the CKA_VALUE for outKey to be set.
++ *
++ * Depending on usage it returns either:
++ *    1. prf(Ni|Nr, inKey); (bDataAsKey=TRUE, bRekey=FALSE)
++ *    2. prf(inKey, Ni|Nr); (bDataAsKkey=FALSE, bRekey=FALSE)
++ *    3. prf(inKey, newKey | Ni | Nr); (bDataAsKey=FALSE, bRekey=TRUE)
++ * The resulting output key is always the length of the underlying prf
++ * (as returned by prf_length()).
++ * The combination of bDataAsKey=TRUE and bRekey=TRUE is not allowed
++ *
++ * Case 1 is used in
++ *    a. ikev2 (rfc5996) inKey is called g^ir, the output is called SKEYSEED
++ *    b. ikev1 (rfc2409) inKey is called g^ir, the output is called SKEYID
++ * Case 2 is used in ikev1 (rfc2409) inkey is called pre-shared-key, output
++ *    is called SKEYID
++ * Case 3 is used in ikev2 (rfc5996) rekey case, inKey is SK_d, newKey is
++ *    g^ir (new), the output is called SKEYSEED
++ */
++CK_RV
++sftk_ike_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
++             const CK_NSS_IKE_PRF_DERIVE_PARAMS *params, SFTKObject *outKey)
++{
++    SFTKAttribute *newKeyValue = NULL;
++    SFTKObject *newKeyObj = NULL;
++    unsigned char outKeyData[HASH_LENGTH_MAX];
++    unsigned char *newInKey = NULL;
++    unsigned int newInKeySize;
++    unsigned int macSize;
++    CK_RV crv = CKR_OK;
++    prfContext context;
++
++    crv = prf_setup(&context, params->prfMechanism);
++    if (crv != CKR_OK) {
++        return crv;
++    }
++    macSize = prf_length(&context);
++    if ((params->bDataAsKey) && (params->bRekey)) {
++        return CKR_ARGUMENTS_BAD;
++    }
++    if (params->bRekey) {
++        /* lookup the value of new key from the session and key handle */
++        SFTKSession *session = sftk_SessionFromHandle(hSession);
++        if (session == NULL) {
++            return CKR_SESSION_HANDLE_INVALID;
++        }
++        newKeyObj = sftk_ObjectFromHandle(params->hNewKey, session);
++        sftk_FreeSession(session);
++        if (newKeyObj == NULL) {
++            return CKR_KEY_HANDLE_INVALID;
++        }
++        newKeyValue = sftk_FindAttribute(newKeyObj, CKA_VALUE);
++        if (newKeyValue == NULL) {
++            crv = CKR_KEY_HANDLE_INVALID;
++            goto fail;
++        }
++    }
++    if (params->bDataAsKey) {
++        /* The key is Ni || Np, so we need to concatenate them together first */
++        newInKeySize = params->ulNiLen + params->ulNrLen;
++        newInKey = PORT_Alloc(newInKeySize);
++        if (newInKey == NULL) {
++            crv = CKR_HOST_MEMORY;
++            goto fail;
++        }
++        PORT_Memcpy(newInKey, params->pNi, params->ulNiLen);
++        PORT_Memcpy(newInKey + params->ulNiLen, params->pNr, params->ulNrLen);
++        crv = prf_init(&context, newInKey, newInKeySize);
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++        /* key as the data */
++        crv = prf_update(&context, inKey->attrib.pValue,
++                         inKey->attrib.ulValueLen);
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++    } else {
++        crv = prf_init(&context, inKey->attrib.pValue,
++                       inKey->attrib.ulValueLen);
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++        if (newKeyValue) {
++            crv = prf_update(&context, newKeyValue->attrib.pValue,
++                             newKeyValue->attrib.ulValueLen);
++            if (crv != CKR_OK) {
++                goto fail;
++            }
++        }
++        crv = prf_update(&context, params->pNi, params->ulNiLen);
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++        crv = prf_update(&context, params->pNr, params->ulNrLen);
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++    }
++    crv = prf_final(&context, outKeyData, macSize);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++
++    crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, macSize);
++fail:
++    if (newInKey) {
++        PORT_Free(newInKey);
++    }
++    if (newKeyValue) {
++        sftk_FreeAttribute(newKeyValue);
++    }
++    if (newKeyObj) {
++        sftk_FreeObject(newKeyObj);
++    }
++    PORT_Memset(outKeyData, 0, macSize);
++    prf_free(&context);
++    return crv;
++}
++
++/*
++ * The second flavor of  ike prf is ike1_prf.
++ *
++ * It is used by ikeV1 to generate the various session keys used in the
++ * connection. It uses the initial key, an optional previous key, and a one byte
++ * key number to generate a unique key for each of the various session
++ * functions (encryption, decryption, mac). These keys expect a key size
++ * (as they may vary in length based on usage). If no length is provided,
++ * it will default to the length of the prf.
++ *
++ * This function returns either:
++ *     prf(inKey, gxyKey || CKYi || CKYr || key_number)
++ * or
++ *     prf(inKey, prevkey || gxyKey || CKYi || CKYr || key_number)
++ * depending on the stats of bHasPrevKey
++ *
++ * This is defined in rfc2409. For each of the following keys.
++ *     inKey is  SKEYID,    gxyKey is g^xy
++ *     for outKey = SKEYID_d, bHasPrevKey = false, key_number = 0
++ *     for outKey = SKEYID_a, prevKey= SKEYID_d,   key_number = 1
++ *     for outKey = SKEYID_e, prevKey= SKEYID_a,   key_number = 2
++ */
++CK_RV
++sftk_ike1_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
++              const CK_NSS_IKE1_PRF_DERIVE_PARAMS *params, SFTKObject *outKey,
++              unsigned int keySize)
++{
++    SFTKAttribute *gxyKeyValue = NULL;
++    SFTKObject *gxyKeyObj = NULL;
++    SFTKAttribute *prevKeyValue = NULL;
++    SFTKObject *prevKeyObj = NULL;
++    SFTKSession *session;
++    unsigned char outKeyData[HASH_LENGTH_MAX];
++    unsigned int macSize;
++    CK_RV crv;
++    prfContext context;
++
++    crv = prf_setup(&context, params->prfMechanism);
++    if (crv != CKR_OK) {
++        return crv;
++    }
++    macSize = prf_length(&context);
++    if (keySize > macSize) {
++        return CKR_KEY_SIZE_RANGE;
++    }
++    if (keySize == 0) {
++        keySize = macSize;
++    }
++
++    /* lookup the two keys from their passed in handles */
++    session = sftk_SessionFromHandle(hSession);
++    if (session == NULL) {
++        return CKR_SESSION_HANDLE_INVALID;
++    }
++    gxyKeyObj = sftk_ObjectFromHandle(params->hKeygxy, session);
++    if (params->bHasPrevKey) {
++        prevKeyObj = sftk_ObjectFromHandle(params->hPrevKey, session);
++    }
++    sftk_FreeSession(session);
++    if ((gxyKeyObj == NULL) || ((params->bHasPrevKey) &&
++                                (prevKeyObj == NULL))) {
++        crv = CKR_KEY_HANDLE_INVALID;
++        goto fail;
++    }
++    gxyKeyValue = sftk_FindAttribute(gxyKeyObj, CKA_VALUE);
++    if (gxyKeyValue == NULL) {
++        crv = CKR_KEY_HANDLE_INVALID;
++        goto fail;
++    }
++    if (prevKeyObj) {
++        prevKeyValue = sftk_FindAttribute(prevKeyObj, CKA_VALUE);
++        if (prevKeyValue == NULL) {
++            crv = CKR_KEY_HANDLE_INVALID;
++            goto fail;
++        }
++    }
++
++    /* outKey = prf(inKey, [prevKey|] gxyKey | CKYi | CKYr | keyNumber) */
++    crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    if (prevKeyValue) {
++        crv = prf_update(&context, prevKeyValue->attrib.pValue,
++                         prevKeyValue->attrib.ulValueLen);
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++    }
++    crv = prf_update(&context, gxyKeyValue->attrib.pValue,
++                     gxyKeyValue->attrib.ulValueLen);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = prf_update(&context, params->pCKYi, params->ulCKYiLen);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = prf_update(&context, params->pCKYr, params->ulCKYrLen);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = prf_update(&context, &params->keyNumber, 1);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = prf_final(&context, outKeyData, macSize);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++
++    crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
++fail:
++    if (gxyKeyValue) {
++        sftk_FreeAttribute(gxyKeyValue);
++    }
++    if (prevKeyValue) {
++        sftk_FreeAttribute(prevKeyValue);
++    }
++    if (gxyKeyObj) {
++        sftk_FreeObject(gxyKeyObj);
++    }
++    if (prevKeyObj) {
++        sftk_FreeObject(prevKeyObj);
++    }
++    PORT_Memset(outKeyData, 0, macSize);
++    prf_free(&context);
++    return crv;
++}
++
++/*
++ * The third flavor of ike prf is ike1_appendix_b.
++ *
++ * It is used by ikeV1 to generate longer key material from skeyid_e.
++ * Unlike ike1_prf, if no length is provided, this function
++ * will generate a KEY_RANGE_ERROR.
++ *
++ * This function returns (from rfc2409 appendix b):
++ * Ka = K1 | K2 | K3 | K4 |... Kn
++ * where:
++ *       K1 = prf(K, 0x00)
++ *       K2 = prf(K, K1)
++ *       K3 = prf(K, K2)
++ *       K4 = prf(K, K3)
++ *            .
++ *       Kn = prf(K, K(n-1))
++ * K = inKey
++ */
++CK_RV
++sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
++                         const CK_MECHANISM_TYPE *mech, SFTKObject *outKey, unsigned int keySize)
++{
++    unsigned char *outKeyData = NULL;
++    unsigned char *thisKey = NULL;
++    unsigned char *lastKey = NULL;
++    unsigned int macSize;
++    unsigned int outKeySize;
++    unsigned int genKeySize;
++    CK_RV crv;
++    prfContext context;
++
++    crv = prf_setup(&context, *mech);
++    if (crv != CKR_OK) {
++        return crv;
++    }
++
++    macSize = prf_length(&context);
++
++    if (keySize == 0) {
++        keySize = macSize;
++    }
++
++    if (keySize <= inKey->attrib.ulValueLen) {
++        return sftk_forceAttribute(outKey, CKA_VALUE,
++                                   inKey->attrib.pValue, keySize);
++    }
++    outKeySize = PR_ROUNDUP(keySize, macSize);
++    outKeyData = PORT_Alloc(outKeySize);
++    if (outKeyData == NULL) {
++        crv = CKR_HOST_MEMORY;
++        goto fail;
++    }
++
++    /*
++      * this loop generates on block of the prf, basically
++      *   kn = prf(key, Kn-1)
++      *   Kn is thisKey, Kn-1 is lastKey
++      *   key is inKey
++      */
++    thisKey = outKeyData;
++    for (genKeySize = 0; genKeySize <= keySize; genKeySize += macSize) {
++        crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen);
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++        if (lastKey == NULL) {
++            const unsigned char zero = 0;
++            crv = prf_update(&context, &zero, 1);
++        } else {
++            crv = prf_update(&context, lastKey, macSize);
++        }
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++        crv = prf_final(&context, thisKey, macSize);
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++        lastKey = thisKey;
++        thisKey += macSize;
++    }
++    crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
++fail:
++    if (outKeyData) {
++        PORT_ZFree(outKeyData, outKeySize);
++    }
++    prf_free(&context);
++    return crv;
++}
++
++/*
++ * The final flavor of ike prf is ike_prf_plus
++ *
++ * It is used by ikeV2 to generate the various session keys used in the
++ * connection. It uses the initial key and a feedback version of the prf
++ * to generate sufficient bytes to cover all the session keys. The application
++ * will then use CK_EXTRACT_KEY_FROM_KEY to pull out the various subkeys.
++ * This function expects a key size to be set by the application to cover
++ * all the keys.  Unlike ike1_prf, if no length is provided, this function
++ * will generate a KEY_RANGE_ERROR
++ *
++ * This function returns (from rfc5996):
++ * prfplus = T1 | T2 | T3 | T4 |... Tn
++ * where:
++ *       T1 = prf(K, S  | 0x01)
++ *       T2 = prf(K, T1 | S | 0x02)
++ *       T3 = prf(K, T3 | S | 0x03)
++ *       T4 = prf(K, T4 | S | 0x04)
++ *            .
++ *       Tn = prf(K, T(n-1) | n)
++ * K = inKey, S = seedKey | seedData
++ */
++
++CK_RV
++sftk_ike_prf_plus(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
++                  const CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *params, SFTKObject *outKey,
++                  unsigned int keySize)
++{
++    SFTKAttribute *seedValue = NULL;
++    SFTKObject *seedKeyObj = NULL;
++    unsigned char *outKeyData = NULL;
++    unsigned int outKeySize;
++    unsigned char *thisKey;
++    unsigned char *lastKey = NULL;
++    unsigned char currentByte = 0;
++    unsigned int getKeySize;
++    unsigned int macSize;
++    CK_RV crv;
++    prfContext context;
++
++    if (keySize == 0) {
++        return CKR_KEY_SIZE_RANGE;
++    }
++
++    crv = prf_setup(&context, params->prfMechanism);
++    if (crv != CKR_OK) {
++        return crv;
++    }
++    /* pull in optional seedKey */
++    if (params->bHasSeedKey) {
++        SFTKSession *session = sftk_SessionFromHandle(hSession);
++        if (session == NULL) {
++            return CKR_SESSION_HANDLE_INVALID;
++        }
++        seedKeyObj = sftk_ObjectFromHandle(params->hSeedKey, session);
++        sftk_FreeSession(session);
++        if (seedKeyObj == NULL) {
++            return CKR_KEY_HANDLE_INVALID;
++        }
++        seedValue = sftk_FindAttribute(seedKeyObj, CKA_VALUE);
++        if (seedValue == NULL) {
++            crv = CKR_KEY_HANDLE_INVALID;
++            goto fail;
++        }
++    } else if (params->ulSeedDataLen == 0) {
++        crv = CKR_ARGUMENTS_BAD;
++        goto fail;
++    }
++    macSize = prf_length(&context);
++    outKeySize = PR_ROUNDUP(keySize, macSize);
++    outKeyData = PORT_Alloc(outKeySize);
++    if (outKeyData == NULL) {
++        crv = CKR_HOST_MEMORY;
++        goto fail;
++    }
++
++    /*
++      * this loop generates on block of the prf, basically
++      *   Tn = prf(key, Tn-1 | S | n)
++      *   Tn is thisKey, Tn-2 is lastKey, S is seedKey || seedData,
++      *   key is inKey. currentByte = n-1 on entry.
++      */
++    thisKey = outKeyData;
++    for (getKeySize = 0; getKeySize < keySize; getKeySize += macSize) {
++        /* if currentByte is 255, we'll overflow when we increment it below.
++         * This can only happen if keysize > 255*macSize. In that case
++         * the application has asked for too much key material, so return
++         * an error */
++        if (currentByte == 255) {
++            crv = CKR_KEY_SIZE_RANGE;
++            goto fail;
++        }
++        crv = prf_init(&context, inKey->attrib.pValue,
++                       inKey->attrib.ulValueLen);
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++
++        if (lastKey) {
++            crv = prf_update(&context, lastKey, macSize);
++            if (crv != CKR_OK) {
++                goto fail;
++            }
++        }
++        /* prf the key first */
++        if (seedValue) {
++            crv = prf_update(&context, seedValue->attrib.pValue,
++                             seedValue->attrib.ulValueLen);
++            if (crv != CKR_OK) {
++                goto fail;
++            }
++        }
++        /* then prf the data */
++        if (params->ulSeedDataLen != 0) {
++            crv = prf_update(&context, params->pSeedData,
++                             params->ulSeedDataLen);
++            if (crv != CKR_OK) {
++                goto fail;
++            }
++        }
++        currentByte++;
++        crv = prf_update(&context, &currentByte, 1);
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++        crv = prf_final(&context, thisKey, macSize);
++        if (crv != CKR_OK) {
++            goto fail;
++        }
++        lastKey = thisKey;
++        thisKey += macSize;
++    }
++    crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
++fail:
++    if (outKeyData) {
++        PORT_ZFree(outKeyData, outKeySize);
++    }
++    if (seedValue) {
++        sftk_FreeAttribute(seedValue);
++    }
++    if (seedKeyObj) {
++        sftk_FreeObject(seedKeyObj);
++    }
++    prf_free(&context);
++    return crv;
++}
++
++/* sftk_aes_xcbc_new_keys:
++ *
++ * aes xcbc creates 3 new keys from the input key. The first key will be the
++ * base key of the underlying cbc. The sign code hooks directly into encrypt
++ * so we'll have to create a full PKCS #11 key with handle for that key. The
++ * caller needs to delete the key when it's through setting up the context.
++ *
++ * The other two keys will be stored in the sign context until we need them
++ * at the end.
++ */
++CK_RV
++sftk_aes_xcbc_new_keys(CK_SESSION_HANDLE hSession,
++                       CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE_PTR phKey,
++                       unsigned char *k2, unsigned char *k3)
++{
++    SFTKObject *key = NULL;
++    SFTKSession *session = NULL;
++    SFTKObject *inKeyObj = NULL;
++    SFTKAttribute *inKeyValue = NULL;
++    CK_KEY_TYPE key_type = CKK_AES;
++    CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
++    CK_BBOOL ck_true = CK_TRUE;
++    CK_RV crv = CKR_OK;
++    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
++    unsigned char buf[AES_BLOCK_SIZE];
++
++    if (!slot) {
++        return CKR_SESSION_HANDLE_INVALID;
++    }
++
++    /* get the session */
++    session = sftk_SessionFromHandle(hSession);
++    if (session == NULL) {
++        crv = CKR_SESSION_HANDLE_INVALID;
++        goto fail;
++    }
++
++    inKeyObj = sftk_ObjectFromHandle(hKey, session);
++    if (inKeyObj == NULL) {
++        crv = CKR_KEY_HANDLE_INVALID;
++        goto fail;
++    }
++
++    inKeyValue = sftk_FindAttribute(inKeyObj, CKA_VALUE);
++    if (inKeyValue == NULL) {
++        crv = CKR_KEY_HANDLE_INVALID;
++        goto fail;
++    }
++
++    crv = sftk_aes_xcbc_get_keys(inKeyValue->attrib.pValue,
++                                 inKeyValue->attrib.ulValueLen, buf, k2, k3);
++
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++
++    /*
++     * now lets create an object to hang the attributes off of
++     */
++    key = sftk_NewObject(slot); /* fill in the handle later */
++    if (key == NULL) {
++        crv = CKR_HOST_MEMORY;
++        goto fail;
++    }
++
++    /* make sure we don't have any class, key_type, or value fields */
++    sftk_DeleteAttributeType(key, CKA_CLASS);
++    sftk_DeleteAttributeType(key, CKA_KEY_TYPE);
++    sftk_DeleteAttributeType(key, CKA_VALUE);
++    sftk_DeleteAttributeType(key, CKA_SIGN);
++
++    /* Add the class, key_type, and value */
++    crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS));
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE));
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = sftk_AddAttributeType(key, CKA_SIGN, &ck_true, sizeof(CK_BBOOL));
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = sftk_AddAttributeType(key, CKA_VALUE, buf, AES_BLOCK_SIZE);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++
++    /*
++     * finish filling in the key and link it with our global system.
++     */
++    crv = sftk_handleObject(key, session);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    *phKey = key->handle;
++fail:
++    if (session) {
++        sftk_FreeSession(session);
++    }
++
++    if (inKeyValue) {
++        sftk_FreeAttribute(inKeyValue);
++    }
++    if (inKeyObj) {
++        sftk_FreeObject(inKeyObj);
++    }
++    if (key) {
++        sftk_FreeObject(key);
++    }
++    /* clear our CSPs */
++    if (crv != CKR_OK) {
++        PORT_Memset(k2, 0, AES_BLOCK_SIZE);
++        PORT_Memset(k3, 0, AES_BLOCK_SIZE);
++    }
++    return crv;
++}
++
++/*
++ * Helper function that tests a single prf test vector
++ */
++static SECStatus
++prf_test(CK_MECHANISM_TYPE mech,
++         const unsigned char *inKey, unsigned int inKeyLen,
++         const unsigned char *plainText, unsigned int plainTextLen,
++         const unsigned char *expectedResult, unsigned int expectedResultLen)
++{
++    PRUint8 ike_computed_mac[HASH_LENGTH_MAX];
++    prfContext context;
++    unsigned int macSize;
++    CK_RV crv;
++
++    crv = prf_setup(&context, mech);
++    if (crv != CKR_OK) {
++        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++        return SECFailure;
++    }
++    macSize = prf_length(&context);
++    crv = prf_init(&context, inKey, inKeyLen);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = prf_update(&context, plainText, plainTextLen);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = prf_final(&context, ike_computed_mac, macSize);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++
++    if (macSize != expectedResultLen) {
++        goto fail;
++    }
++    if (PORT_Memcmp(expectedResult, ike_computed_mac, macSize) != 0) {
++        goto fail;
++    }
++
++    /* only do the alignment if the plaintext is long enough */
++    if (plainTextLen <= macSize) {
++        return SECSuccess;
++    }
++    /* do it again, but this time tweak with the alignment */
++    crv = prf_init(&context, inKey, inKeyLen);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = prf_update(&context, plainText, 1);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = prf_update(&context, &plainText[1], macSize);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = prf_update(&context, &plainText[1 + macSize], plainTextLen - (macSize + 1));
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    crv = prf_final(&context, ike_computed_mac, macSize);
++    if (crv != CKR_OK) {
++        goto fail;
++    }
++    if (PORT_Memcmp(expectedResult, ike_computed_mac, macSize) != 0) {
++        goto fail;
++    }
++    return SECSuccess;
++fail:
++    prf_free(&context);
++    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++    return SECFailure;
++}
++
++/*
++ * FIPS Power up Self Tests for IKE. This is in this function so it
++ * can access the private prf_ functions here. It's called out of fipstest.c
++ */
++SECStatus
++sftk_fips_IKE_PowerUpSelfTests(void)
++{
++    /* PRF known test vectors */
++    static const PRUint8 ike_xcbc_known_key[] = {
++        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
++    };
++    static const PRUint8 ike_xcbc_known_plain_text[] = {
++        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
++    };
++    static const PRUint8 ike_xcbc_known_mac[] = {
++        0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7,
++        0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63
++    };
++    /* test 2 uses the same key as test 1 */
++    static const PRUint8 ike_xcbc_known_plain_text_2[] = {
++        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++        0x10, 0x11, 0x12, 0x13
++    };
++    static const PRUint8 ike_xcbc_known_mac_2[] = {
++        0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15,
++        0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08
++    };
++    static const PRUint8 ike_xcbc_known_key_3[] = {
++        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++        0x08, 0x09
++    };
++    /* test 3 uses the same plaintest as test 2 */
++    static const PRUint8 ike_xcbc_known_mac_3[] = {
++        0x0f, 0xa0, 0x87, 0xaf, 0x7d, 0x86, 0x6e, 0x76,
++        0x53, 0x43, 0x4e, 0x60, 0x2f, 0xdd, 0xe8, 0x35
++    };
++    static const PRUint8 ike_xcbc_known_key_4[] = {
++        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++        0xed, 0xcb
++    };
++    /* test 4 uses the same plaintest as test 2 */
++    static const PRUint8 ike_xcbc_known_mac_4[] = {
++        0x8c, 0xd3, 0xc9, 0x3a, 0xe5, 0x98, 0xa9, 0x80,
++        0x30, 0x06, 0xff, 0xb6, 0x7c, 0x40, 0xe9, 0xe4
++    };
++    static const PRUint8 ike_sha1_known_key[] = {
++        0x59, 0x98, 0x2b, 0x5b, 0xa5, 0x7e, 0x62, 0xc0,
++        0x46, 0x0d, 0xef, 0xc7, 0x1e, 0x18, 0x64, 0x63
++    };
++    static const PRUint8 ike_sha1_known_plain_text[] = {
++        0x1c, 0x07, 0x32, 0x1a, 0x9a, 0x7e, 0x41, 0xcd,
++        0x88, 0x0c, 0xa3, 0x7a, 0xdb, 0x10, 0xc7, 0x3b,
++        0xf0, 0x0e, 0x7a, 0xe3, 0xcf, 0xc6, 0xfd, 0x8b,
++        0x51, 0xbc, 0xe2, 0xb9, 0x90, 0xe6, 0xf2, 0x01
++    };
++    static const PRUint8 ike_sha1_known_mac[] = {
++        0x0c, 0x2a, 0xf3, 0x42, 0x97, 0x15, 0x62, 0x1d,
++        0x2a, 0xad, 0xc9, 0x94, 0x5a, 0x90, 0x26, 0xfa,
++        0xc7, 0x91, 0xe2, 0x4b
++    };
++    static const PRUint8 ike_sha256_known_key[] = {
++        0x9d, 0xa2, 0xd5, 0x8f, 0x57, 0xf0, 0x39, 0xf9,
++        0x20, 0x4e, 0x0d, 0xd0, 0xef, 0x04, 0xf3, 0x72
++    };
++    static const PRUint8 ike_sha256_known_plain_text[] = {
++        0x33, 0xf1, 0x7a, 0xfc, 0xb6, 0x13, 0x4c, 0xbf,
++        0x1c, 0xab, 0x59, 0x87, 0x7d, 0x42, 0xdb, 0x35,
++        0x82, 0x22, 0x6e, 0xff, 0x74, 0xdd, 0x37, 0xeb,
++        0x8b, 0x75, 0xe6, 0x75, 0x64, 0x5f, 0xc1, 0x69
++    };
++    static const PRUint8 ike_sha256_known_mac[] = {
++        0x80, 0x4b, 0x4a, 0x1e, 0x0e, 0xc5, 0x93, 0xcf, 0xb6,
++        0xe4, 0x54, 0x52, 0x41, 0x49, 0x39, 0x6d, 0xe2, 0x34,
++        0xd0, 0xda, 0xe2, 0x9f, 0x34, 0xa8, 0xfd, 0xb5, 0xf9,
++        0xaf, 0xe7, 0x6e, 0xa6, 0x52
++    };
++    static const PRUint8 ike_sha384_known_key[] = {
++        0xce, 0xc8, 0x9d, 0x84, 0x5a, 0xdd, 0x83, 0xef,
++        0xce, 0xbd, 0x43, 0xab, 0x71, 0xd1, 0x7d, 0xb9
++    };
++    static const PRUint8 ike_sha384_known_plain_text[] = {
++        0x17, 0x24, 0xdb, 0xd8, 0x93, 0x52, 0x37, 0x64,
++        0xbf, 0xef, 0x8c, 0x6f, 0xa9, 0x27, 0x85, 0x6f,
++        0xcc, 0xfb, 0x77, 0xae, 0x25, 0x43, 0x58, 0xcc,
++        0xe2, 0x9c, 0x27, 0x69, 0xa3, 0x29, 0x15, 0xc1
++    };
++    static const PRUint8 ike_sha384_known_mac[] = {
++        0x6e, 0x45, 0x14, 0x61, 0x0b, 0xf8, 0x2d, 0x0a,
++        0xb7, 0xbf, 0x02, 0x60, 0x09, 0x6f, 0x61, 0x46,
++        0xa1, 0x53, 0xc7, 0x12, 0x07, 0x1a, 0xbb, 0x63,
++        0x3c, 0xed, 0x81, 0x3c, 0x57, 0x21, 0x56, 0xc7,
++        0x83, 0xe3, 0x68, 0x74, 0xa6, 0x5a, 0x64, 0x69,
++        0x0c, 0xa7, 0x01, 0xd4, 0x0d, 0x56, 0xea, 0x18
++    };
++    static const PRUint8 ike_sha512_known_key[] = {
++        0xac, 0xad, 0xc6, 0x31, 0x4a, 0x69, 0xcf, 0xcd,
++        0x4e, 0x4a, 0xd1, 0x77, 0x18, 0xfe, 0xa7, 0xce
++    };
++    static const PRUint8 ike_sha512_known_plain_text[] = {
++        0xb1, 0x5a, 0x9c, 0xfc, 0xe8, 0xc8, 0xd7, 0xea,
++        0xb8, 0x79, 0xd6, 0x24, 0x30, 0x29, 0xd4, 0x01,
++        0x88, 0xd3, 0xb7, 0x40, 0x87, 0x5a, 0x6a, 0xc6,
++        0x2f, 0x56, 0xca, 0xc4, 0x37, 0x7e, 0x2e, 0xdd
++    };
++    static const PRUint8 ike_sha512_known_mac[] = {
++        0xf0, 0x5a, 0xa0, 0x36, 0xdf, 0xce, 0x45, 0xa5,
++        0x58, 0xd4, 0x04, 0x18, 0xde, 0xa9, 0x80, 0x96,
++        0xe5, 0x19, 0xbc, 0x78, 0x41, 0xe3, 0xdb, 0x3d,
++        0xd9, 0x36, 0x58, 0xd1, 0x18, 0xc3, 0xe8, 0x3b,
++        0x50, 0x2f, 0x39, 0x8e, 0xcb, 0x13, 0x61, 0xec,
++        0x77, 0xd3, 0x8a, 0x88, 0x55, 0xef, 0xff, 0x40,
++        0x7f, 0x6f, 0x77, 0x2e, 0x5d, 0x65, 0xb5, 0x8e,
++        0xb1, 0x13, 0x40, 0x96, 0xe8, 0x47, 0x8d, 0x2b
++    };
++    SECStatus rv;
++
++    rv = prf_test(CKM_AES_XCBC_MAC,
++                  ike_xcbc_known_key, sizeof(ike_xcbc_known_key),
++                  ike_xcbc_known_plain_text, sizeof(ike_xcbc_known_plain_text),
++                  ike_xcbc_known_mac, sizeof(ike_xcbc_known_mac));
++    if (rv != SECSuccess)
++        return rv;
++    rv = prf_test(CKM_AES_XCBC_MAC,
++                  ike_xcbc_known_key, sizeof(ike_xcbc_known_key),
++                  ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),
++                  ike_xcbc_known_mac_2, sizeof(ike_xcbc_known_mac_2));
++    if (rv != SECSuccess)
++        return rv;
++    rv = prf_test(CKM_AES_XCBC_MAC,
++                  ike_xcbc_known_key_3, sizeof(ike_xcbc_known_key_3),
++                  ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),
++                  ike_xcbc_known_mac_3, sizeof(ike_xcbc_known_mac_3));
++    if (rv != SECSuccess)
++        return rv;
++    rv = prf_test(CKM_AES_XCBC_MAC,
++                  ike_xcbc_known_key_4, sizeof(ike_xcbc_known_key_4),
++                  ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),
++                  ike_xcbc_known_mac_4, sizeof(ike_xcbc_known_mac_4));
++    if (rv != SECSuccess)
++        return rv;
++    rv = prf_test(CKM_SHA_1_HMAC,
++                  ike_sha1_known_key, sizeof(ike_sha1_known_key),
++                  ike_sha1_known_plain_text, sizeof(ike_sha1_known_plain_text),
++                  ike_sha1_known_mac, sizeof(ike_sha1_known_mac));
++    if (rv != SECSuccess)
++        return rv;
++    rv = prf_test(CKM_SHA256_HMAC,
++                  ike_sha256_known_key, sizeof(ike_sha256_known_key),
++                  ike_sha256_known_plain_text,
++                  sizeof(ike_sha256_known_plain_text),
++                  ike_sha256_known_mac, sizeof(ike_sha256_known_mac));
++    if (rv != SECSuccess)
++        return rv;
++    rv = prf_test(CKM_SHA384_HMAC,
++                  ike_sha384_known_key, sizeof(ike_sha384_known_key),
++                  ike_sha384_known_plain_text,
++                  sizeof(ike_sha384_known_plain_text),
++                  ike_sha384_known_mac, sizeof(ike_sha384_known_mac));
++    if (rv != SECSuccess)
++        return rv;
++    rv = prf_test(CKM_SHA512_HMAC,
++                  ike_sha512_known_key, sizeof(ike_sha512_known_key),
++                  ike_sha512_known_plain_text,
++                  sizeof(ike_sha512_known_plain_text),
++                  ike_sha512_known_mac, sizeof(ike_sha512_known_mac));
++    return rv;
++}
+diff --git a/lib/softoken/softoken.gyp b/lib/softoken/softoken.gyp
+--- a/lib/softoken/softoken.gyp
++++ b/lib/softoken/softoken.gyp
+@@ -53,16 +53,17 @@
+           'lowpbe.c',
+           'padbuf.c',
+           'pkcs11.c',
+           'pkcs11c.c',
+           'pkcs11u.c',
+           'sdb.c',
+           'sftkdb.c',
+           'sftkhmac.c',
++          'sftkike.c',
+           'sftkpars.c',
+           'sftkpwd.c',
+           'softkver.c',
+           'tlsprf.c'
+         ],
+       },
+     },
+     {
+diff --git a/lib/util/pkcs11n.h b/lib/util/pkcs11n.h
+--- a/lib/util/pkcs11n.h
++++ b/lib/util/pkcs11n.h
+@@ -147,16 +147,22 @@
+ #define CKM_NSS_AES_KEY_WRAP_PAD (CKM_NSS + 2)
+ 
+ /* HKDF key derivation mechanisms. See CK_NSS_HKDFParams for documentation. */
+ #define CKM_NSS_HKDF_SHA1 (CKM_NSS + 3)
+ #define CKM_NSS_HKDF_SHA256 (CKM_NSS + 4)
+ #define CKM_NSS_HKDF_SHA384 (CKM_NSS + 5)
+ #define CKM_NSS_HKDF_SHA512 (CKM_NSS + 6)
+ 
++/* IKE mechanism (to be proposed to PKCS #11 */
++#define CKM_NSS_IKE_PRF_PLUS_DERIVE (CKM_NSS + 7)
++#define CKM_NSS_IKE_PRF_DERIVE (CKM_NSS + 8)
++#define CKM_NSS_IKE1_PRF_DERIVE (CKM_NSS + 9)
++#define CKM_NSS_IKE1_APP_B_PRF_DERIVE (CKM_NSS + 10)
++
+ /* J-PAKE round 1 key generation mechanisms.
+  *
+  * Required template attributes: CKA_PRIME, CKA_SUBPRIME, CKA_BASE,
+  *                               CKA_NSS_JPAKE_SIGNERID
+  * Output key type: CKK_NSS_JPAKE_ROUND1
+  * Output key class: CKO_PRIVATE_KEY
+  * Parameter type: CK_NSS_JPAKERound1Params
+  *
+@@ -337,16 +343,82 @@ typedef struct CK_NSS_HKDFParams {
+     CK_BYTE_PTR pSalt;
+     CK_ULONG ulSaltLen;
+     CK_BBOOL bExpand;
+     CK_BYTE_PTR pInfo;
+     CK_ULONG ulInfoLen;
+ } CK_NSS_HKDFParams;
+ 
+ /*
++ * CK_NSS_IKE_PRF_PLUS_PARAMS is a structure that provides the parameters to
++ * the CKM_NSS_IKE_PRF_PLUS_DERIVE mechanism.
++ * The fields of the structure have the following meanings:
++ *      prfMechanism    underlying MAC mechanism used to generate the prf.
++ *      bHasSeedKey     hSeed key is present.
++ *      hSeedKey        optional seed from key
++ *      pSeedData       optional seed from data.
++ *      ulSeedDataLen   length of optional seed data.
++ *        If no seed data is present this value is NULL.
++ */
++typedef struct CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS {
++    CK_MECHANISM_TYPE prfMechanism;
++    CK_BBOOL bHasSeedKey;
++    CK_OBJECT_HANDLE hSeedKey;
++    CK_BYTE_PTR pSeedData;
++    CK_ULONG ulSeedDataLen;
++} CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS;
++
++/* CK_NSS_IKE_PRF_DERIVE_PARAMS is a structure that provides the parameters to
++ *  the CKM_NSS_IKE_PRF_DERIVE mechanism.
++ *
++ * The fields of the structure have the following meanings:
++ *     prfMechanism underlying MAC mechanism used to generate the prf.
++ *     bRekey       hNewKey is present.
++ *     pNi          Ni value
++ *     ulNiLen      length of Ni
++ *     pNr          Nr value
++ *     ulNrLen      length of Nr
++ *     hNewKey      New key value to drive the rekey.
++ */
++typedef struct CK_NSS_IKE_PRF_DERIVE_PARAMS {
++    CK_MECHANISM_TYPE prfMechanism;
++    CK_BBOOL bDataAsKey;
++    CK_BBOOL bRekey;
++    CK_BYTE_PTR pNi;
++    CK_ULONG ulNiLen;
++    CK_BYTE_PTR pNr;
++    CK_ULONG ulNrLen;
++    CK_OBJECT_HANDLE hNewKey;
++} CK_NSS_IKE_PRF_DERIVE_PARAMS;
++
++/* CK_NSS_IKE1_PRF_DERIVE_PARAMS is a structure that provides the parameters
++ * to the CKM_NSS_IKE_PRF_DERIVE mechanism.
++ *
++ * The fields of the structure have the following meanings:
++ *     prfMechanism  underlying MAC mechanism used to generate the prf.
++ *     bRekey        hNewKey is present.
++ *     pCKYi         CKYi value
++ *     ulCKYiLen     length of CKYi
++ *     pCKYr         CKYr value
++ *     ulCKYrLen     length of CKYr
++ *     hNewKey       New key value to drive the rekey.
++ */
++typedef struct CK_NSS_IKE1_PRF_DERIVE_PARAMS {
++    CK_MECHANISM_TYPE prfMechanism;
++    CK_BBOOL bHasPrevKey;
++    CK_OBJECT_HANDLE hKeygxy;
++    CK_OBJECT_HANDLE hPrevKey;
++    CK_BYTE_PTR pCKYi;
++    CK_ULONG ulCKYiLen;
++    CK_BYTE_PTR pCKYr;
++    CK_ULONG ulCKYrLen;
++    CK_BYTE keyNumber;
++} CK_NSS_IKE1_PRF_DERIVE_PARAMS;
++
++/*
+  * Parameter for the TLS extended master secret key derivation mechanisms:
+  *
+  *  * CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE
+  *  * CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH
+  *
+  * For the TLS 1.2 PRF, the prfHashMechanism parameter determines the hash
+  * function used. For earlier versions of the PRF, set the prfHashMechanism
+  * value to CKM_TLS_PRF.
+diff --git a/lib/util/pkcs11t.h b/lib/util/pkcs11t.h
+--- a/lib/util/pkcs11t.h
++++ b/lib/util/pkcs11t.h
+@@ -877,16 +877,18 @@ typedef CK_ULONG CK_MECHANISM_TYPE;
+ #define CKM_AES_MAC_GENERAL 0x00001084
+ #define CKM_AES_CBC_PAD 0x00001085
+ /* new for v2.20 amendment 3 */
+ #define CKM_AES_CTR 0x00001086
+ /* new for v2.30 */
+ #define CKM_AES_GCM 0x00001087
+ #define CKM_AES_CCM 0x00001088
+ #define CKM_AES_CTS 0x00001089
++#define CKM_AES_XCBC_MAC 0x0000108C
++#define CKM_AES_XCBC_MAC_96 0x0000108D
+ 
+ /* BlowFish and TwoFish are new for v2.20 */
+ #define CKM_BLOWFISH_KEY_GEN 0x00001090
+ #define CKM_BLOWFISH_CBC 0x00001091
+ #define CKM_TWOFISH_KEY_GEN 0x00001092
+ #define CKM_TWOFISH_CBC 0x00001093
+ 
+ /* Camellia is proposed for v2.20 Amendment 3 */
+diff --git a/tests/common/init.sh b/tests/common/init.sh
+--- a/tests/common/init.sh
++++ b/tests/common/init.sh
+@@ -646,18 +646,21 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOU
+ 
+     TOTAL_CRL_RANGE=`expr ${CRL_GRP_1_RANGE} + ${CRL_GRP_2_RANGE} + \
+                      ${CRL_GRP_3_RANGE}`
+ 
+     TOTAL_GRP_NUM=3
+ 
+     RELOAD_CRL=1
+ 
+-    NSS_DEFAULT_DB_TYPE="dbm"
+-    export NSS_DEFAULT_DB_TYPE
++    # if test mode isn't set, test scripts default to expecting dbm
++    if [ "${TEST_MODE}" = "" ]; then
++        NSS_DEFAULT_DB_TYPE="dbm"
++        export NSS_DEFAULT_DB_TYPE
++    fi
+ 
+     MSG_ID=0
+ 
+     #################################################
+     # Interoperability testing constatnts
+     #
+     # if suite is setup for testing, IOPR_HOSTADDR_LIST should have
+     # at least one host name(FQDN)
+diff --git a/tests/fips/fips.sh b/tests/fips/fips.sh
+--- a/tests/fips/fips.sh
++++ b/tests/fips/fips.sh
+@@ -40,27 +40,31 @@ fips_init()
+   SCRIPTNAME=fips.sh
+   html_head "FIPS 140 Compliance Tests"
+ 
+   grep "SUCCESS: FIPS passed" $CERT_LOG_FILE >/dev/null || {
+       Exit 15 "Fatal - FIPS of cert.sh needs to pass first"
+   }
+ 
+   COPYDIR=${FIPSDIR}/copydir
++  CAVSDIR=${FIPSDIR}/cavs/tests
++  CAVSRUNDIR=${FIPSDIR}/cavs/scripts
+ 
+   R_FIPSDIR=../fips
+   P_R_FIPSDIR=../fips
+   R_COPYDIR=../fips/copydir
+ 
+   if [ -n "${MULTIACCESS_DBM}" ]; then
+      P_R_FIPSDIR="multiaccess:${D_FIPS}"
+   fi
+ 
+   mkdir -p ${FIPSDIR}
+   mkdir -p ${COPYDIR}
++  mkdir -p ${CAVSDIR}
++  mkdir -p ${CAVSRUNDIR}
+ 
+   cd ${FIPSDIR}
+ }
+ 
+ ############################## fips_140 ##############################
+ # local shell function to test basic functionality of NSS while in
+ # FIPS 140 compliant mode
+ ########################################################################
+@@ -269,25 +273,51 @@ fips_140()
+     fi  
+ 
+     html_msg ${RESULT} 46 "Init NSS with a corrupted library (dbtest -r)" "."
+   else
+     html_failed "Mangle ${DLL_PREFIX}softokn3.${DLL_SUFFIX}"
+   fi
+ }
+ 
++fips_cavs()
++{
++    if [ "${CAVS_VECTORS}" = "all" ]; then
++        VECTORS=
++    elif [ "${CAVS_VECTORS}" = "" ]; then
++        VECTORS="aesgcm ecdsa hmac kas tls ike rng sha"
++    else
++        VECTORS=${CAVS_VECTORS}
++    fi
++    echo "Copying CAVS vectors"
++    cp -r ${QADIR}/fips/cavs_samples/* ${CAVSDIR}
++# we copy the scripts to the test directory because they are designed to run from their
++# own directory and we want any resulting core dumps to wind up in the test_results directory.
++    echo "Copying CAVS scripts"
++    cp -r ${QADIR}/fips/cavs_scripts/* ${CAVSRUNDIR}
++    echo "cd ${CAVSRUNDIR}"
++    cd ${CAVSRUNDIR}
++    echo "Running CAVS tests in ${CAVSDIR}"
++    ./runtest.sh ${CAVSDIR} run ${VECTORS}
++    echo "Verifying CAVS results in ${CAVSDIR}"
++    ./runtest.sh ${CAVSDIR} verify ${VECTORS}
++    RESULT=$?
++    html_msg $RESULT 0 "NIST CAVS test" "${CAVSDIR}"
++}
++
+ ############################## fips_cleanup ############################
+ # local shell function to finish this script (no exit since it might be 
+ # sourced)
+ ########################################################################
+ fips_cleanup()
+ {
+   html "</TABLE><BR>"
+   cd ${QADIR}
+   . common/cleanup.sh
+ }
+ 
+ ################## main #################################################
+ 
+ fips_init
+ fips_140
++fips_cavs
+ fips_cleanup
+ echo "fips.sh done"
diff --git a/SOURCES/nss-input-check.patch b/SOURCES/nss-input-check.patch
new file mode 100644
index 0000000..366b793
--- /dev/null
+++ b/SOURCES/nss-input-check.patch
@@ -0,0 +1,127 @@
+# HG changeset patch
+# User Martin Thomson <mt@lowentropy.net>
+# Date 1560498951 0
+#      Fri Jun 14 07:55:51 2019 +0000
+# Branch NSS_3_44_BRANCH
+# Node ID fb9932d6e083322e7b5dfcd3d6e67477e0bb075a
+# Parent  876bca2723a1f969422edc93e7504420d8331d3c
+Bug 1515342 - More thorough input checking, r=jcj
+
+All part of applying better discipline throughout.
+
+Differential Revision: https://phabricator.services.mozilla.com/D33736
+
+diff --git a/lib/cryptohi/seckey.c b/lib/cryptohi/seckey.c
+--- a/lib/cryptohi/seckey.c
++++ b/lib/cryptohi/seckey.c
+@@ -639,6 +639,11 @@ seckey_ExtractPublicKey(const CERTSubjec
+                     return pubk;
+                 break;
+             case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
++                /* A basic sanity check on inputs. */
++                if (spki->algorithm.parameters.len == 0 || newOs.len == 0) {
++                    PORT_SetError(SEC_ERROR_INPUT_LEN);
++                    break;
++                }
+                 pubk->keyType = ecKey;
+                 pubk->u.ec.size = 0;
+ 
+diff --git a/lib/freebl/dh.c b/lib/freebl/dh.c
+--- a/lib/freebl/dh.c
++++ b/lib/freebl/dh.c
+@@ -210,7 +210,8 @@ DH_Derive(SECItem *publicValue,
+     unsigned int len = 0;
+     unsigned int nb;
+     unsigned char *secret = NULL;
+-    if (!publicValue || !prime || !privateValue || !derivedSecret) {
++    if (!publicValue || !publicValue->len || !prime || !prime->len ||
++        !privateValue || !privateValue->len || !derivedSecret) {
+         PORT_SetError(SEC_ERROR_INVALID_ARGS);
+         return SECFailure;
+     }
+diff --git a/lib/freebl/ec.c b/lib/freebl/ec.c
+--- a/lib/freebl/ec.c
++++ b/lib/freebl/ec.c
+@@ -202,8 +202,8 @@ ec_NewKey(ECParams *ecParams, ECPrivateK
+ #endif
+     MP_DIGITS(&k) = 0;
+ 
+-    if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0) ||
+-        !ecParams->name) {
++    if (!ecParams || ecParams->name == ECCurve_noName ||
++        !privKey || !privKeyBytes || privKeyLen <= 0) {
+         PORT_SetError(SEC_ERROR_INVALID_ARGS);
+         return SECFailure;
+     }
+@@ -391,7 +391,7 @@ EC_NewKey(ECParams *ecParams, ECPrivateK
+     int len;
+     unsigned char *privKeyBytes = NULL;
+ 
+-    if (!ecParams) {
++    if (!ecParams || ecParams->name == ECCurve_noName || !privKey) {
+         PORT_SetError(SEC_ERROR_INVALID_ARGS);
+         return SECFailure;
+     }
+@@ -430,7 +430,8 @@ EC_ValidatePublicKey(ECParams *ecParams,
+     mp_err err = MP_OKAY;
+     int len;
+ 
+-    if (!ecParams || !publicValue || !ecParams->name) {
++    if (!ecParams || ecParams->name == ECCurve_noName ||
++        !publicValue || !publicValue->len) {
+         PORT_SetError(SEC_ERROR_INVALID_ARGS);
+         return SECFailure;
+     }
+@@ -536,8 +537,9 @@ ECDH_Derive(SECItem *publicValue,
+     int i;
+ #endif
+ 
+-    if (!publicValue || !ecParams || !privateValue || !derivedSecret ||
+-        !ecParams->name) {
++    if (!publicValue || !publicValue->len ||
++        !ecParams || ecParams->name == ECCurve_noName ||
++        !privateValue || !privateValue->len || !derivedSecret) {
+         PORT_SetError(SEC_ERROR_INVALID_ARGS);
+         return SECFailure;
+     }
+diff --git a/lib/util/quickder.c b/lib/util/quickder.c
+--- a/lib/util/quickder.c
++++ b/lib/util/quickder.c
+@@ -757,6 +757,13 @@ DecodeItem(void* dest,
+                         }
+ 
+                         case SEC_ASN1_BIT_STRING: {
++                            /* Can't be 8 or more spare bits, or any spare bits
++			     * if there are no octets. */
++                            if (temp.data[0] >= 8 || (temp.data[0] > 0 && temp.len == 1)) {
++                                PORT_SetError(SEC_ERROR_BAD_DER);
++                                rv = SECFailure;
++                                break;
++                            }
+                             /* change the length in the SECItem to be the number
+                                of bits */
+                             temp.len = (temp.len - 1) * 8 - (temp.data[0] & 0x7);
+# HG changeset patch
+# User Kevin Jacobs <kjacobs@mozilla.com>
+# Date 1561145635 0
+#      Fri Jun 21 19:33:55 2019 +0000
+# Branch NSS_3_44_BRANCH
+# Node ID 416a8f7cf8986103b4d74694aac1198edbb08b3e
+# Parent  fb9932d6e083322e7b5dfcd3d6e67477e0bb075a
+Bug 1515342 - Ignore spki decode failures on negative (expect_fail) tests. r=jcj
+
+Differential Revision: https://phabricator.services.mozilla.com/D35565
+
+diff --git a/gtests/pk11_gtest/pk11_curve25519_unittest.cc b/gtests/pk11_gtest/pk11_curve25519_unittest.cc
+--- a/gtests/pk11_gtest/pk11_curve25519_unittest.cc
++++ b/gtests/pk11_gtest/pk11_curve25519_unittest.cc
+@@ -40,6 +40,9 @@ class Pkcs11Curve25519Test
+ 
+     ScopedCERTSubjectPublicKeyInfo certSpki(
+         SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem));
++    if (!expect_success && !certSpki) {
++      return;
++    }
+     ASSERT_TRUE(certSpki);
+ 
+     ScopedSECKEYPublicKey pubKey(SECKEY_ExtractPublicKey(certSpki.get()));
diff --git a/SOURCES/nss-leading-zero.patch b/SOURCES/nss-leading-zero.patch
new file mode 100644
index 0000000..4ea008c
--- /dev/null
+++ b/SOURCES/nss-leading-zero.patch
@@ -0,0 +1,143 @@
+# HG changeset patch
+# User Kevin Jacobs <kjacobs@mozilla.com>
+# Date 1560499074 0
+#      Fri Jun 14 07:57:54 2019 +0000
+# Branch NSS_3_44_BRANCH
+# Node ID 876bca2723a1f969422edc93e7504420d8331d3c
+# Parent  20671f860c2619dc27208d64a84a759fdffc5ed1
+Bug 1540541 - Don't unnecessarily strip leading 0's from key material during PKCS11 import. r=jcj,mt
+
+Differential Revision: https://phabricator.services.mozilla.com/D31671
+
+diff --git a/lib/freebl/ecl/ecp_25519.c b/lib/freebl/ecl/ecp_25519.c
+--- a/lib/freebl/ecl/ecp_25519.c
++++ b/lib/freebl/ecl/ecp_25519.c
+@@ -114,6 +114,9 @@ ec_Curve25519_pt_mul(SECItem *X, SECItem
+         }
+         px = P->data;
+     }
++    if (k->len != 32) {
++        return SECFailure;
++    }
+ 
+     SECStatus rv = ec_Curve25519_mul(X->data, k->data, px);
+     if (NSS_SecureMemcmpZero(X->data, X->len) == 0) {
+diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c
+--- a/lib/pk11wrap/pk11akey.c
++++ b/lib/pk11wrap/pk11akey.c
+@@ -190,7 +190,6 @@ PK11_ImportPublicKey(PK11SlotInfo *slot,
+                 attrs++;
+                 PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
+                 attrs++;
+-                signedattr = attrs;
+                 PK11_SETATTRS(attrs, CKA_EC_PARAMS,
+                               pubKey->u.ec.DEREncodedParams.data,
+                               pubKey->u.ec.DEREncodedParams.len);
+@@ -222,12 +221,14 @@ PK11_ImportPublicKey(PK11SlotInfo *slot,
+                 PORT_SetError(SEC_ERROR_BAD_KEY);
+                 return CK_INVALID_HANDLE;
+         }
+-
+         templateCount = attrs - theTemplate;
+-        signedcount = attrs - signedattr;
+         PORT_Assert(templateCount <= (sizeof(theTemplate) / sizeof(CK_ATTRIBUTE)));
+-        for (attrs = signedattr; signedcount; attrs++, signedcount--) {
+-            pk11_SignedToUnsigned(attrs);
++        if (pubKey->keyType != ecKey) {
++            PORT_Assert(signedattr);
++            signedcount = attrs - signedattr;
++            for (attrs = signedattr; signedcount; attrs++, signedcount--) {
++                pk11_SignedToUnsigned(attrs);
++            }
+         }
+         rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate,
+                                   templateCount, isToken, &objectID);
+@@ -1074,9 +1075,13 @@ pk11_loadPrivKeyWithFlags(PK11SlotInfo *
+                                         &cktrue, &ckfalse);
+ 
+     /* Not everyone can handle zero padded key values, give
+-      * them the raw data as unsigned */
+-    for (ap = attrs; extra_count; ap++, extra_count--) {
+-        pk11_SignedToUnsigned(ap);
++     * them the raw data as unsigned. The exception is EC,
++     * where the values are encoded or zero-preserving
++     * per-RFC5915 */
++    if (privKey->keyType != ecKey) {
++        for (ap = attrs; extra_count; ap++, extra_count--) {
++            pk11_SignedToUnsigned(ap);
++        }
+     }
+ 
+     /* now Store the puppies */
+diff --git a/lib/pk11wrap/pk11cert.c b/lib/pk11wrap/pk11cert.c
+--- a/lib/pk11wrap/pk11cert.c
++++ b/lib/pk11wrap/pk11cert.c
+@@ -184,7 +184,9 @@ PK11_IsUserCert(PK11SlotInfo *slot, CERT
+             SECKEY_DestroyPublicKey(pubKey);
+             return PR_FALSE;
+         }
+-        pk11_SignedToUnsigned(&theTemplate);
++        if (pubKey->keyType != ecKey) {
++            pk11_SignedToUnsigned(&theTemplate);
++        }
+         if (pk11_FindObjectByTemplate(slot, &theTemplate, 1) != CK_INVALID_HANDLE) {
+             SECKEY_DestroyPublicKey(pubKey);
+             return PR_TRUE;
+diff --git a/lib/pk11wrap/pk11pk12.c b/lib/pk11wrap/pk11pk12.c
+--- a/lib/pk11wrap/pk11pk12.c
++++ b/lib/pk11wrap/pk11pk12.c
+@@ -505,7 +505,7 @@ PK11_ImportAndReturnPrivateKey(PK11SlotI
+             }
+             PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
+             attrs++;
+-            signedattr = attrs;
++            /* No signed attrs for EC */
+             /* curveOID always is a copy of AlgorithmID.parameters. */
+             PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data,
+                           lpk->u.ec.curveOID.len);
+@@ -523,11 +523,12 @@ PK11_ImportAndReturnPrivateKey(PK11SlotI
+     }
+     templateCount = attrs - theTemplate;
+     PORT_Assert(templateCount <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE));
+-    PORT_Assert(signedattr != NULL);
+-    signedcount = attrs - signedattr;
+-
+-    for (ap = signedattr; signedcount; ap++, signedcount--) {
+-        pk11_SignedToUnsigned(ap);
++    if (lpk->keyType != ecKey) {
++        PORT_Assert(signedattr);
++        signedcount = attrs - signedattr;
++        for (ap = signedattr; signedcount; ap++, signedcount--) {
++            pk11_SignedToUnsigned(ap);
++        }
+     }
+ 
+     rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION,
+diff --git a/lib/softoken/legacydb/lgattr.c b/lib/softoken/legacydb/lgattr.c
+--- a/lib/softoken/legacydb/lgattr.c
++++ b/lib/softoken/legacydb/lgattr.c
+@@ -950,9 +950,9 @@ lg_FindECPrivateKeyAttribute(NSSLOWKEYPr
+         case CKA_UNWRAP:
+             return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
+         case CKA_VALUE:
+-            return lg_CopyPrivAttrSigned(attribute, type,
+-                                         key->u.ec.privateValue.data,
+-                                         key->u.ec.privateValue.len, sdbpw);
++            return lg_CopyPrivAttribute(attribute, type,
++                                        key->u.ec.privateValue.data,
++                                        key->u.ec.privateValue.len, sdbpw);
+         case CKA_EC_PARAMS:
+             return lg_CopyAttributeSigned(attribute, type,
+                                           key->u.ec.ecParams.DEREncoding.data,
+diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
+--- a/lib/softoken/pkcs11c.c
++++ b/lib/softoken/pkcs11c.c
+@@ -7747,7 +7747,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
+ 
+             rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
+                              withCofactor, &tmp);
+-            PORT_Free(ecScalar.data);
++            PORT_ZFree(ecScalar.data, ecScalar.len);
+             ecScalar.data = NULL;
+             if (privKey != sourceKey->objectInfo) {
+                 nsslowkey_DestroyPrivateKey(privKey);
diff --git a/SOURCES/nss-manpage-fixes.patch b/SOURCES/nss-manpage-fixes.patch
deleted file mode 100644
index ae2b2fd..0000000
--- a/SOURCES/nss-manpage-fixes.patch
+++ /dev/null
@@ -1,170 +0,0 @@
-# HG changeset patch
-# User Daiki Ueno <dueno@redhat.com>
-# Date 1544699159 -3600
-#      Thu Dec 13 12:05:59 2018 +0100
-# Node ID 0124a811bdf7abfe4bcf135ccc8c719b14db0580
-# Parent  5b2efc615899a283c1ab2e26ddb41684aeae60f0
-Add manual for nss-policy-check
-
-diff --git a/doc/Makefile b/doc/Makefile
---- a/doc/Makefile
-+++ b/doc/Makefile
-@@ -21,7 +21,7 @@ all: prepare all-man all-html
- prepare: date-and-version
- 	mkdir -p html
- 	mkdir -p nroff
--	
-+
- clean:
- 	rm -f date.xml version.xml *.tar.bz2
- 	rm -f html/*.proc
-@@ -45,11 +45,11 @@ version.xml:
- 
- nroff/%.1 : %.xml
- 	$(COMPILE.1) $<
--	
-+
- MANPAGES = \
- nroff/certutil.1 nroff/cmsutil.1 nroff/crlutil.1 nroff/pk12util.1 \
- nroff/modutil.1 nroff/ssltap.1 nroff/derdump.1 nroff/signtool.1 nroff/signver.1 \
--nroff/pp.1 nroff/vfychain.1 nroff/vfyserv.1
-+nroff/pp.1 nroff/vfychain.1 nroff/vfyserv.1 nroff/nss-policy-check.1
- 
- all-man: prepare $(MANPAGES)
- 
-@@ -64,6 +64,6 @@ html/%.html : %.xml
- HTMLPAGES = \
- html/certutil.html html/cmsutil.html html/crlutil.html html/pk12util.html html/modutil.html \
- html/ssltap.html html/derdump.html html/signtool.html html/signver.html html/pp.html \
--html/vfychain.html html/vfyserv.html
-+html/vfychain.html html/vfyserv.html html/nss-policy-check.html
- 
- all-html: prepare $(HTMLPAGES)
-diff --git a/doc/certutil.xml b/doc/certutil.xml
---- a/doc/certutil.xml
-+++ b/doc/certutil.xml
-@@ -180,6 +180,10 @@ For certificate requests, ASCII output d
-       </varlistentry>
- 
-       <varlistentry>
-+	<term>--simple-self-signed</term>
-+	<listitem><para>When printing the certificate chain, don't search for a chain if issuer name equals to subject name.</para></listitem>
-+      </varlistentry>
-+      <varlistentry>
-         <term>-b validity-time</term>
-         <listitem><para>Specify a time at which a certificate is required to be valid. Use when checking certificate validity with the <option>-V</option> option. The format of the <emphasis>validity-time</emphasis> argument is <emphasis>YYMMDDHHMMSS[+HHMM|-HHMM|Z]</emphasis>, which allows offsets to be set relative to the validity end time. Specifying seconds (<emphasis>SS</emphasis>) is optional. When specifying an explicit time, use a Z at the end of the term, <emphasis>YYMMDDHHMMSSZ</emphasis>, to close it. When specifying an offset time, use <emphasis>YYMMDDHHMMSS+HHMM</emphasis> or <emphasis>YYMMDDHHMMSS-HHMM</emphasis> for adding or subtracting time, respectively.
- </para>
-diff --git a/doc/nss-policy-check.xml b/doc/nss-policy-check.xml
-new file mode 100644
---- /dev/null
-+++ b/doc/nss-policy-check.xml
-@@ -0,0 +1,97 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
-+<!ENTITY date SYSTEM "date.xml">
-+<!ENTITY version SYSTEM "version.xml">
-+]>
-+
-+<refentry id="nss-policy-check">
-+
-+  <refentryinfo>
-+    <date>&date;</date>
-+    <title>NSS Security Tools</title>
-+    <productname>nss-tools</productname>
-+    <productnumber>&version;</productnumber>
-+  </refentryinfo>
-+
-+  <refmeta>
-+    <refentrytitle>NSS-POLICY-CHECK</refentrytitle>
-+    <manvolnum>1</manvolnum>
-+  </refmeta>
-+
-+  <refnamediv>
-+    <refname>nss-policy-check</refname>
-+    <refpurpose>nss-policy-check policy-file</refpurpose>
-+  </refnamediv>
-+
-+ <refsynopsisdiv>
-+    <cmdsynopsis>
-+      <command>nss-policy-check</command>
-+    </cmdsynopsis>
-+  </refsynopsisdiv>
-+
-+  <refsection id="description">
-+    <title>Description</title>
-+    <para><command>nss-policy-check</command> verifies crypto-policy configuration that controls certain crypto algorithms are allowed/disallowed to use in the NSS library.</para>
-+
-+    <para>The crypto-policy configuration can be stored in either a system-wide configuration file, specified with the POLICY_PATH and POLICY_FILE build options, or in the pkcs11.txt in NSS database.</para>
-+  </refsection>
-+
-+  <refsection id="basic-usage">
-+    <title>Usage and Examples</title>
-+    <para>To check the global crypto-policy configuration in <filename>/etc/crypto-policies/back-ends/nss.config</filename>:
-+    </para>
-+    <programlisting>$ nss-policy-check /etc/crypto-policies/back-ends/nss.config
-+NSS-POLICY-INFO: LOADED-SUCCESSFULLY
-+NSS-POLICY-INFO: PRIME256V1 is enabled for KX
-+NSS-POLICY-INFO: PRIME256V1 is enabled for CERT-SIGNATURE
-+NSS-POLICY-INFO: SECP256R1 is enabled for KX
-+NSS-POLICY-INFO: SECP256R1 is enabled for CERT-SIGNATURE
-+NSS-POLICY-INFO: SECP384R1 is enabled for KX
-+NSS-POLICY-INFO: SECP384R1 is enabled for CERT-SIGNATURE
-+...
-+NSS-POLICY-INFO: NUMBER-OF-SSL-ALG-KX: 13
-+NSS-POLICY-INFO: NUMBER-OF-SSL-ALG: 9
-+NSS-POLICY-INFO: NUMBER-OF-CERT-SIG: 9
-+...
-+NSS-POLICY-INFO: ciphersuite TLS_AES_128_GCM_SHA256 is enabled
-+NSS-POLICY-INFO: ciphersuite TLS_CHACHA20_POLY1305_SHA256 is enabled
-+NSS-POLICY-INFO: ciphersuite TLS_AES_256_GCM_SHA384 is enabled
-+...
-+NSS-POLICY-INFO: NUMBER-OF-CIPHERSUITES: 24
-+NSS-POLICY-INFO: NUMBER-OF-TLS-VERSIONS: 3
-+NSS-POLICY-INFO: NUMBER-OF-DTLS-VERSIONS: 2
-+    </programlisting>
-+    <para>If there is a failure or warning, it will be prefixed with
-+    NSS-POLICY-FAIL or NSS-POLICY_WARN.
-+    </para>
-+    <para><command>nss-policy-check</command> exits with 2 if any
-+    failure is found, 1 if any warning is found, or 0 if no errors are
-+    found.</para>
-+  </refsection>
-+
-+<!-- don't change -->
-+  <refsection id="resources">
-+    <title>Additional Resources</title>
-+	<para>For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at <ulink url="http://www.mozilla.org/projects/security/pki/nss/">http://www.mozilla.org/projects/security/pki/nss/</ulink>. The NSS site relates directly to NSS code changes and releases.</para>
-+	<para>Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto</para>
-+	<para>IRC: Freenode at #dogtag-pki</para>
-+  </refsection>
-+
-+<!-- fill in your name first; keep the other names for reference -->
-+  <refsection id="authors">
-+    <title>Authors</title>
-+    <para>The NSS tools were written and maintained by developers with Netscape, Red Hat,  Sun, Oracle, Mozilla, and Google.</para>
-+    <para>
-+	Authors: Elio Maldonado &lt;emaldona@redhat.com>, Deon Lackey &lt;dlackey@redhat.com>.
-+    </para>
-+  </refsection>
-+
-+<!-- don't change -->
-+  <refsection id="license">
-+    <title>LICENSE</title>
-+    <para>Licensed under 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/.
-+    </para>
-+  </refsection>
-+
-+</refentry>
-diff --git a/doc/pk12util.xml b/doc/pk12util.xml
---- a/doc/pk12util.xml
-+++ b/doc/pk12util.xml
-@@ -108,7 +108,7 @@
-       </varlistentry>
- 
-       <varlistentry>
--        <term>-n | --cert-key-len  certKeyLength</term>
-+        <term>--cert-key-len  certKeyLength</term>
-         <listitem><para>Specify the desired length of the symmetric key to be used to encrypt the certificates and other meta-data.</para></listitem>
-       </varlistentry>
- 
diff --git a/SOURCES/nss-module-leak.patch b/SOURCES/nss-module-leak.patch
new file mode 100644
index 0000000..7acf3f3
--- /dev/null
+++ b/SOURCES/nss-module-leak.patch
@@ -0,0 +1,35 @@
+# HG changeset patch
+# User Daiki Ueno <dueno@redhat.com>
+# Date 1557150127 -7200
+#      Mon May 06 15:42:07 2019 +0200
+# Node ID 438ac983bda9ec7944990d22a37877e9111caa90
+# Parent  b018f3e84d87cce99a1fd81feeecb31123058687
+pk11slot: reference module from slot for finalization
+
+diff --git a/lib/pk11wrap/pk11slot.c b/lib/pk11wrap/pk11slot.c
+--- a/lib/pk11wrap/pk11slot.c
++++ b/lib/pk11wrap/pk11slot.c
+@@ -1439,6 +1439,11 @@ PK11_InitSlot(SECMODModule *mod, CK_SLOT
+     slot->slotID = slotID;
+     slot->isThreadSafe = mod->isThreadSafe;
+     slot->hasRSAInfo = PR_FALSE;
++    slot->module = mod; /* NOTE: we don't make a reference here because
++                         * modules have references to their slots. This
++                         * works because modules keep implicit references
++                         * from their slots, and won't unload and disappear
++                         * until all their slots have been freed */
+ 
+     if (PK11_GETTAB(slot)->C_GetSlotInfo(slotID, &slotInfo) != CKR_OK) {
+         slot->disabled = PR_TRUE;
+@@ -1448,11 +1453,6 @@ PK11_InitSlot(SECMODModule *mod, CK_SLOT
+ 
+     /* test to make sure claimed mechanism work */
+     slot->needTest = mod->internal ? PR_FALSE : PR_TRUE;
+-    slot->module = mod; /* NOTE: we don't make a reference here because
+-                         * modules have references to their slots. This
+-                         * works because modules keep implicit references
+-                         * from their slots, and won't unload and disappear
+-                         * until all their slots have been freed */
+     (void)PK11_MakeString(NULL, slot->slot_name,
+                           (char *)slotInfo.slotDescription, sizeof(slotInfo.slotDescription));
+     slot->isHW = (PRBool)((slotInfo.flags & CKF_HW_SLOT) == CKF_HW_SLOT);
diff --git a/SOURCES/nss-mpi-loop.patch b/SOURCES/nss-mpi-loop.patch
new file mode 100644
index 0000000..d919a5e
--- /dev/null
+++ b/SOURCES/nss-mpi-loop.patch
@@ -0,0 +1,24 @@
+# HG changeset patch
+# User Greg Rubin <rubin@amazon.com>
+# Date 1558464083 25200
+#      Tue May 21 11:41:23 2019 -0700
+# Branch NSS_3_44_BRANCH
+# Node ID 1eac9016c021055018389a5cb117678ecc61782a
+# Parent  416a8f7cf8986103b4d74694aac1198edbb08b3e
+Bug 1554336 - Optimize away unneeded loop in mpi.c r=kevinjacobs,jcj
+
+diff --git a/lib/freebl/mpi/mpi.c b/lib/freebl/mpi/mpi.c
+--- a/lib/freebl/mpi/mpi.c
++++ b/lib/freebl/mpi/mpi.c
+@@ -2063,7 +2063,10 @@ s_mp_almost_inverse(const mp_int *a, con
+             }
+         }
+     if (res >= 0) {
+-        while (MP_SIGN(c) != MP_ZPOS) {
++        if (mp_cmp_mag(c, p) >= 0) {
++            MP_CHECKOK(mp_div(c, p, NULL, c));
++        }
++        if (MP_SIGN(c) != MP_ZPOS) {
+             MP_CHECKOK(mp_add(c, p, c));
+         }
+         res = k;
diff --git a/SOURCES/nss-post-handshake-auth-with-tickets.patch b/SOURCES/nss-post-handshake-auth-with-tickets.patch
new file mode 100644
index 0000000..ac51f07
--- /dev/null
+++ b/SOURCES/nss-post-handshake-auth-with-tickets.patch
@@ -0,0 +1,96 @@
+# HG changeset patch
+# User Daiki Ueno <dueno@redhat.com>
+# Date 1559121620 -7200
+#      Wed May 29 11:20:20 2019 +0200
+# Node ID 29a48b604602a523defd6f9322a5adeca7e284a5
+# Parent  43a7fb4f994a31222c308113b0fccdd5480d5b8e
+Bug 1553443, send session ticket only after handshake is marked as finished
+
+Reviewers: mt
+
+Reviewed By: mt
+
+Bug #: 1553443
+
+Differential Revision: https://phabricator.services.mozilla.com/D32128
+
+diff --git a/gtests/ssl_gtest/ssl_auth_unittest.cc b/gtests/ssl_gtest/ssl_auth_unittest.cc
+--- a/gtests/ssl_gtest/ssl_auth_unittest.cc
++++ b/gtests/ssl_gtest/ssl_auth_unittest.cc
+@@ -537,6 +537,40 @@ TEST_F(TlsConnectStreamTls13, PostHandsh
+                       capture_cert_req->buffer().len()));
+ }
+ 
++// Check if post-handshake auth still works when session tickets are enabled:
++// https://bugzilla.mozilla.org/show_bug.cgi?id=1553443
++TEST_F(TlsConnectStreamTls13, PostHandshakeAuthWithSessionTicketsEnabled) {
++  EnsureTlsSetup();
++  client_->SetupClientAuth();
++  EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
++                                      SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
++  EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
++                                      SSL_ENABLE_SESSION_TICKETS, PR_TRUE));
++  EXPECT_EQ(SECSuccess, SSL_OptionSet(server_->ssl_fd(),
++                                      SSL_ENABLE_SESSION_TICKETS, PR_TRUE));
++  size_t called = 0;
++  server_->SetAuthCertificateCallback(
++      [&called](TlsAgent*, PRBool, PRBool) -> SECStatus {
++        called++;
++        return SECSuccess;
++      });
++  Connect();
++  EXPECT_EQ(0U, called);
++  // Send CertificateRequest.
++  EXPECT_EQ(SECSuccess, SSL_GetClientAuthDataHook(
++                            client_->ssl_fd(), GetClientAuthDataHook, nullptr));
++  EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
++      << "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
++  server_->SendData(50);
++  client_->ReadBytes(50);
++  client_->SendData(50);
++  server_->ReadBytes(50);
++  EXPECT_EQ(1U, called);
++  ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd()));
++  ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd()));
++  EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
++}
++
+ // In TLS 1.3, the client sends its cert rejection on the
+ // second flight, and since it has already received the
+ // server's Finished, it transitions to complete and
+diff --git a/lib/ssl/tls13con.c b/lib/ssl/tls13con.c
+--- a/lib/ssl/tls13con.c
++++ b/lib/ssl/tls13con.c
+@@ -4561,6 +4561,11 @@ tls13_ServerHandleFinished(sslSocket *ss
+         return SECFailure;
+     }
+ 
++    rv = tls13_FinishHandshake(ss);
++    if (rv != SECSuccess) {
++        return SECFailure;
++    }
++
+     ssl_GetXmitBufLock(ss);
+     if (ss->opt.enableSessionTickets) {
+         rv = tls13_SendNewSessionTicket(ss, NULL, 0);
+@@ -4573,8 +4578,7 @@ tls13_ServerHandleFinished(sslSocket *ss
+         }
+     }
+     ssl_ReleaseXmitBufLock(ss);
+-
+-    return tls13_FinishHandshake(ss);
++    return SECSuccess;
+ 
+ loser:
+     ssl_ReleaseXmitBufLock(ss);
+diff --git a/tests/ssl/sslauth.txt b/tests/ssl/sslauth.txt
+--- a/tests/ssl/sslauth.txt
++++ b/tests/ssl/sslauth.txt
+@@ -42,6 +42,7 @@
+   noECC     0       -r_-r_-r_-r_-E  -V_tls1.3:tls1.3_-E_-n_TestUser_-w_nss TLS 1.3 Require client auth on post hs (client auth)
+   noECC     0       -r_-r_-r_-E  -V_tls1.3:tls1.3_-E_-n_none_-w_nss TLS 1.3 Request don't require client auth on post hs (client does not provide auth)
+   noECC     1       -r_-r_-r_-r_-E  -V_tls1.3:tls1.3_-E_-n_none_-w_nss TLS 1.3 Require client auth on post hs (client does not provide auth)
++  noECC     0       -r_-r_-r_-E_-u  -V_tls1.3:tls1.3_-E_-n_TestUser_-w_nss TLS 1.3 Request don't require client auth on post hs with session ticket (client auth)
+ #
+ # Use EC cert for client authentication
+ #
diff --git a/SOURCES/nss-skip-sysinit-gtests.patch b/SOURCES/nss-skip-sysinit-gtests.patch
new file mode 100644
index 0000000..4c3ea29
--- /dev/null
+++ b/SOURCES/nss-skip-sysinit-gtests.patch
@@ -0,0 +1,11 @@
+diff -up nss/gtests/manifest.mn.skip-sysinit-gtests nss/gtests/manifest.mn
+--- nss/gtests/manifest.mn.skip-sysinit-gtests	2019-04-26 12:55:05.979302035 +0200
++++ nss/gtests/manifest.mn	2019-04-26 12:55:09.507228984 +0200
+@@ -27,7 +27,6 @@ NSS_SRCDIRS = \
+ 	smime_gtest \
+ 	softoken_gtest \
+ 	ssl_gtest \
+-	$(SYSINIT_GTEST) \
+ 	nss_bogo_shim \
+ 	$(NULL)
+ endif
diff --git a/SOURCES/nss-skip-tls13-fips.patch b/SOURCES/nss-skip-tls13-fips.patch
new file mode 100644
index 0000000..4a7c707
--- /dev/null
+++ b/SOURCES/nss-skip-tls13-fips.patch
@@ -0,0 +1,27 @@
+# HG changeset patch
+# User Daiki Ueno <dueno@redhat.com>
+# Date 1558341826 -7200
+#      Mon May 20 10:43:46 2019 +0200
+# Node ID b447f0046807b718d2928d0e33313620d38a287a
+# Parent  02ea5f29ac3c1f1c6e6eb4b655afd9b4fc075a9e
+tests: skip TLS 1.3 tests under FIPS mode
+
+diff --git a/tests/ssl/ssl.sh b/tests/ssl/ssl.sh
+--- a/tests/ssl/ssl.sh
++++ b/tests/ssl/ssl.sh
+@@ -393,6 +393,15 @@ ssl_auth()
+       echo "${testname}" | grep "TLS 1.3" > /dev/null
+       TLS13=$?
+ 
++      # Currently TLS 1.3 tests are known to fail under FIPS mode,
++      # because HKDF is implemented using the PKCS #11 functions
++      # prohibited under FIPS mode.
++      if [ "${TLS13}" -eq 0 ] && \
++	 [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] ; then
++          echo "$SCRIPTNAME: skipping  $testname (non-FIPS only)"
++          continue
++      fi
++
+       if [ "${CLIENT_MODE}" = "fips" -a "${CAUTH}" -eq 0 ] ; then
+           echo "$SCRIPTNAME: skipping  $testname (non-FIPS only)"
+       elif [ "$ectype" = "SNI" -a "$NORM_EXT" = "Extended Test" ] ; then
diff --git a/SOURCES/nss-softokn-fips-update.patch b/SOURCES/nss-softokn-fips-update.patch
new file mode 100644
index 0000000..604b947
--- /dev/null
+++ b/SOURCES/nss-softokn-fips-update.patch
@@ -0,0 +1,1148 @@
+diff --git a/lib/freebl/fipsfreebl.c b/lib/freebl/fipsfreebl.c
+--- a/lib/freebl/fipsfreebl.c
++++ b/lib/freebl/fipsfreebl.c
+@@ -10,18 +10,20 @@
+ #ifdef FREEBL_NO_DEPEND
+ #include "stubs.h"
+ #endif
+ 
+ #include "blapi.h"
+ #include "seccomon.h" /* Required for RSA and DSA. */
+ #include "secerr.h"
+ #include "prtypes.h"
++#include "secitem.h"
++#include "pkcs11t.h"
+ 
+-#include "ec.h" /* Required for ECDSA */
++#include "ec.h" /* Required for EC */
+ 
+ /*
+  * different platforms have different ways of calling and initial entry point
+  * when the dll/.so is loaded. Most platforms support either a posix pragma
+  * or the GCC attribute. Some platforms suppor a pre-defined name, and some
+  * platforms have a link line way of invoking this function.
+  */
+ 
+@@ -283,61 +285,88 @@ freebl_fips_AES_PowerUpSelfTest(int aes_
+ 
+     /* AES-CBC Known Initialization Vector (128-bits). */
+     static const PRUint8 aes_cbc_known_initialization_vector[] =
+         { "SecurityytiruceS" };
+ 
+     /* AES Known Plaintext (128-bits). (blocksize is 128-bits) */
+     static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" };
+ 
++    static const PRUint8 aes_gcm_known_aad[] = { "MozillaallizoM" };
++
+     /* AES Known Ciphertext (128-bit key). */
+     static const PRUint8 aes_ecb128_known_ciphertext[] = {
+         0x3c, 0xa5, 0x96, 0xf3, 0x34, 0x6a, 0x96, 0xc1,
+         0x03, 0x88, 0x16, 0x7b, 0x20, 0xbf, 0x35, 0x47
+     };
+ 
+     static const PRUint8 aes_cbc128_known_ciphertext[] = {
+         0xcf, 0x15, 0x1d, 0x4f, 0x96, 0xe4, 0x4f, 0x63,
+         0x15, 0x54, 0x14, 0x1d, 0x4e, 0xd8, 0xd5, 0xea
+     };
+ 
++    static const PRUint8 aes_gcm128_known_ciphertext[] = {
++        0x63, 0xf4, 0x95, 0x28, 0xe6, 0x78, 0xee, 0x6e,
++        0x4f, 0xe0, 0xfc, 0x8d, 0xd7, 0xa2, 0xb1, 0xff,
++        0x0c, 0x97, 0x1b, 0x0a, 0xdd, 0x97, 0x75, 0xed,
++        0x8b, 0xde, 0xbf, 0x16, 0x5e, 0x57, 0x6b, 0x4f
++    };
++
+     /* AES Known Ciphertext (192-bit key). */
+     static const PRUint8 aes_ecb192_known_ciphertext[] = {
+         0xa0, 0x18, 0x62, 0xed, 0x88, 0x19, 0xcb, 0x62,
+         0x88, 0x1d, 0x4d, 0xfe, 0x84, 0x02, 0x89, 0x0e
+     };
+ 
+     static const PRUint8 aes_cbc192_known_ciphertext[] = {
+         0x83, 0xf7, 0xa4, 0x76, 0xd1, 0x6f, 0x07, 0xbe,
+         0x07, 0xbc, 0x43, 0x2f, 0x6d, 0xad, 0x29, 0xe1
+     };
+ 
++    static const PRUint8 aes_gcm192_known_ciphertext[] = {
++        0xc1, 0x0b, 0x92, 0x1d, 0x68, 0x21, 0xf4, 0x25,
++        0x41, 0x61, 0x20, 0x2d, 0x59, 0x7f, 0x53, 0xde,
++        0x93, 0x39, 0xab, 0x09, 0x76, 0x41, 0x57, 0x2b,
++        0x90, 0x2e, 0x44, 0xbb, 0x52, 0x03, 0xe9, 0x07
++    };
++
+     /* AES Known Ciphertext (256-bit key). */
+     static const PRUint8 aes_ecb256_known_ciphertext[] = {
+         0xdb, 0xa6, 0x52, 0x01, 0x8a, 0x70, 0xae, 0x66,
+         0x3a, 0x99, 0xd8, 0x95, 0x7f, 0xfb, 0x01, 0x67
+     };
+ 
+     static const PRUint8 aes_cbc256_known_ciphertext[] = {
+         0x37, 0xea, 0x07, 0x06, 0x31, 0x1c, 0x59, 0x27,
+         0xc5, 0xc5, 0x68, 0x71, 0x6e, 0x34, 0x40, 0x16
+     };
+ 
++    static const PRUint8 aes_gcm256_known_ciphertext[] = {
++        0x5d, 0x9e, 0xd2, 0xa2, 0x74, 0x9c, 0xd9, 0x1c,
++        0xd1, 0xc9, 0xee, 0x5d, 0xb6, 0xf2, 0xc9, 0xb6,
++        0x79, 0x27, 0x53, 0x02, 0xa3, 0xdc, 0x22, 0xce,
++        0xf4, 0xb0, 0xc1, 0x8c, 0x86, 0x51, 0xf5, 0xa1
++    };
++
+     const PRUint8 *aes_ecb_known_ciphertext =
+         (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_ecb128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_ecb192_known_ciphertext : aes_ecb256_known_ciphertext;
+ 
+     const PRUint8 *aes_cbc_known_ciphertext =
+         (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_cbc128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_cbc192_known_ciphertext : aes_cbc256_known_ciphertext;
+ 
++    const PRUint8 *aes_gcm_known_ciphertext =
++        (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_gcm128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_gcm192_known_ciphertext : aes_gcm256_known_ciphertext;
++
+     /* AES variables. */
+-    PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH];
+-    PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH];
++    PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH * 2];
++    PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH * 2];
+     AESContext *aes_context;
+     unsigned int aes_bytes_encrypted;
+     unsigned int aes_bytes_decrypted;
++    CK_GCM_PARAMS gcmParams;
+     SECStatus aes_status;
+ 
+     /*check if aes_key_size is 128, 192, or 256 bits */
+     if ((aes_key_size != FIPS_AES_128_KEY_SIZE) &&
+         (aes_key_size != FIPS_AES_192_KEY_SIZE) &&
+         (aes_key_size != FIPS_AES_256_KEY_SIZE)) {
+         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+         return (SECFailure);
+@@ -450,16 +479,79 @@ freebl_fips_AES_PowerUpSelfTest(int aes_
+     if ((aes_status != SECSuccess) ||
+         (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
+         (PORT_Memcmp(aes_computed_plaintext, aes_known_plaintext,
+                      FIPS_AES_DECRYPT_LENGTH) != 0)) {
+         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+         return (SECFailure);
+     }
+ 
++    /******************************************************/
++    /* AES-GCM Single-Round Known Answer Encryption Test. */
++    /******************************************************/
++
++    gcmParams.pIv = (PRUint8 *)aes_cbc_known_initialization_vector;
++    gcmParams.ulIvLen = FIPS_AES_BLOCK_SIZE;
++    gcmParams.pAAD = (PRUint8 *)aes_gcm_known_aad;
++    gcmParams.ulAADLen = sizeof(aes_gcm_known_aad);
++    gcmParams.ulTagBits = FIPS_AES_BLOCK_SIZE * 8;
++    aes_context = AES_CreateContext(aes_known_key,
++                                    (PRUint8 *)&gcmParams,
++                                    NSS_AES_GCM, PR_TRUE, aes_key_size,
++                                    FIPS_AES_BLOCK_SIZE);
++
++    if (aes_context == NULL) {
++        PORT_SetError(SEC_ERROR_NO_MEMORY);
++        return (SECFailure);
++    }
++
++    aes_status = AES_Encrypt(aes_context, aes_computed_ciphertext,
++                             &aes_bytes_encrypted, FIPS_AES_ENCRYPT_LENGTH * 2,
++                             aes_known_plaintext,
++                             FIPS_AES_DECRYPT_LENGTH);
++
++    AES_DestroyContext(aes_context, PR_TRUE);
++
++    if ((aes_status != SECSuccess) ||
++        (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH * 2) ||
++        (PORT_Memcmp(aes_computed_ciphertext, aes_gcm_known_ciphertext,
++                     FIPS_AES_ENCRYPT_LENGTH * 2) != 0)) {
++        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++        return (SECFailure);
++    }
++
++    /******************************************************/
++    /* AES-GCM Single-Round Known Answer Decryption Test. */
++    /******************************************************/
++
++    aes_context = AES_CreateContext(aes_known_key,
++                                    (PRUint8 *)&gcmParams,
++                                    NSS_AES_GCM, PR_FALSE, aes_key_size,
++                                    FIPS_AES_BLOCK_SIZE);
++
++    if (aes_context == NULL) {
++        PORT_SetError(SEC_ERROR_NO_MEMORY);
++        return (SECFailure);
++    }
++
++    aes_status = AES_Decrypt(aes_context, aes_computed_plaintext,
++                             &aes_bytes_decrypted, FIPS_AES_DECRYPT_LENGTH * 2,
++                             aes_gcm_known_ciphertext,
++                             FIPS_AES_ENCRYPT_LENGTH * 2);
++
++    AES_DestroyContext(aes_context, PR_TRUE);
++
++    if ((aes_status != SECSuccess) ||
++        (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
++        (PORT_Memcmp(aes_computed_plaintext, aes_known_plaintext,
++                     FIPS_AES_DECRYPT_LENGTH) != 0)) {
++        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++        return (SECFailure);
++    }
++
+     return (SECSuccess);
+ }
+ 
+ /* Known Hash Message (512-bits).  Used for all hashes (incl. SHA-N [N>1]). */
+ static const PRUint8 known_hash_message[] = {
+     "The test message for the MD2, MD5, and SHA-1 hashing algorithms."
+ };
+ 
+@@ -1089,17 +1181,17 @@ freebl_fips_ECDSA_Test(ECParams *ecparam
+         0x7b, 0x5a, 0x3b, 0x76, 0x4e, 0x7b, 0x7c, 0xbc,
+         0xf2, 0x76, 0x1c, 0x1c, 0x7f, 0xc5, 0x53, 0x2f
+     };
+ 
+     static const PRUint8 msg[] = {
+         "Firefox and ThunderBird are awesome!"
+     };
+ 
+-    unsigned char sha1[SHA1_LENGTH]; /* SHA-1 hash (160 bits) */
++    unsigned char sha256[SHA256_LENGTH]; /* SHA-256 hash (256 bits) */
+     unsigned char sig[2 * MAX_ECKEY_LEN];
+     SECItem signature, digest;
+     ECPrivateKey *ecdsa_private_key = NULL;
+     ECPublicKey ecdsa_public_key;
+     SECStatus ecdsaStatus = SECSuccess;
+ 
+     /* Generates a new EC key pair. The private key is a supplied
+      * random value (in seed) and the public key is the result of
+@@ -1131,23 +1223,23 @@ freebl_fips_ECDSA_Test(ECParams *ecparam
+     if (ecdsaStatus != SECSuccess) {
+         goto loser;
+     }
+ 
+     /***************************************************/
+     /* ECDSA Single-Round Known Answer Signature Test. */
+     /***************************************************/
+ 
+-    ecdsaStatus = SHA1_HashBuf(sha1, msg, sizeof msg);
++    ecdsaStatus = SHA256_HashBuf(sha256, msg, sizeof msg);
+     if (ecdsaStatus != SECSuccess) {
+         goto loser;
+     }
+     digest.type = siBuffer;
+-    digest.data = sha1;
+-    digest.len = SHA1_LENGTH;
++    digest.data = sha256;
++    digest.len = SHA256_LENGTH;
+ 
+     memset(sig, 0, sizeof sig);
+     signature.type = siBuffer;
+     signature.data = sig;
+     signature.len = sizeof sig;
+ 
+     ecdsaStatus = ECDSA_SignDigestWithSeed(ecdsa_private_key, &signature,
+                                            &digest, ecdsa_Known_Seed, sizeof ecdsa_Known_Seed);
+@@ -1176,20 +1268,93 @@ loser:
+     if (ecdsaStatus != SECSuccess) {
+         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+         return (SECFailure);
+     }
+     return (SECSuccess);
+ }
+ 
+ static SECStatus
+-freebl_fips_ECDSA_PowerUpSelfTest()
++freebl_fips_ECDH_Test(ECParams *ecparams)
+ {
+ 
+-    /* ECDSA Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
++    /* ECDH Known result (reused old CAVS vector)  */
++    static const PRUint8 ecdh_known_pub_key_1[] = {
++        EC_POINT_FORM_UNCOMPRESSED,
++        /* pubX */
++        0x16, 0x81, 0x32, 0x86, 0xc8, 0xe4, 0x3a, 0x1f,
++        0x5d, 0xe3, 0x06, 0x22, 0x8b, 0x99, 0x14, 0x25,
++        0xf7, 0x9c, 0x5b, 0x1e, 0x96, 0x84, 0x85, 0x3b,
++        0x17, 0xfe, 0xf3, 0x1c, 0x0e, 0xed, 0xc4, 0xce,
++        /* pubY */
++        0x7a, 0x44, 0xfe, 0xbd, 0x91, 0x71, 0x7d, 0x73,
++        0xd9, 0x45, 0xea, 0xae, 0x66, 0x78, 0xfa, 0x6e,
++        0x46, 0xcd, 0xfa, 0x95, 0x15, 0x47, 0x62, 0x5d,
++        0xbb, 0x1b, 0x9f, 0xe6, 0x39, 0xfc, 0xfd, 0x47
++    };
++    static const PRUint8 ecdh_known_priv_key_2[] = {
++        0xb4, 0x2a, 0xe3, 0x69, 0x19, 0xec, 0xf0, 0x42,
++        0x6d, 0x45, 0x8c, 0x94, 0x4a, 0x26, 0xa7, 0x5c,
++        0xea, 0x9d, 0xd9, 0x0f, 0x59, 0xe0, 0x1a, 0x9d,
++        0x7c, 0xb7, 0x1c, 0x04, 0x53, 0xb8, 0x98, 0x5a
++    };
++    static const PRUint8 ecdh_known_hash_result[] = {
++        0x16, 0xf3, 0x85, 0xa2, 0x41, 0xf3, 0x7f, 0xc4,
++        0x0b, 0x56, 0x47, 0xee, 0xa7, 0x74, 0xb9, 0xdb,
++        0xe1, 0xfa, 0x22, 0xe9, 0x04, 0xf1, 0xb6, 0x12,
++        0x4b, 0x44, 0x8a, 0xbb, 0xbc, 0x08, 0x2b, 0xa7,
++    };
++
++    SECItem ecdh_priv_2, ecdh_pub_1;
++    SECItem ZZ = { 0, 0, 0 };
++    SECStatus ecdhStatus = SECSuccess;
++    PRUint8 computed_hash_result[HASH_LENGTH_MAX];
++
++    ecdh_priv_2.data = (PRUint8 *)ecdh_known_priv_key_2;
++    ecdh_priv_2.len = sizeof(ecdh_known_priv_key_2);
++    ecdh_pub_1.data = (PRUint8 *)ecdh_known_pub_key_1;
++    ecdh_pub_1.len = sizeof(ecdh_known_pub_key_1);
++
++    /* Generates a new EC key pair. The private key is a supplied
++     * random value (in seed) and the public key is the result of
++     * performing a scalar point multiplication of that value with
++     * the curve's base point.
++     */
++    ecdhStatus = ECDH_Derive(&ecdh_pub_1, ecparams, &ecdh_priv_2, PR_FALSE, &ZZ);
++    if (ecdhStatus != SECSuccess) {
++        goto loser;
++    }
++    ecdhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
++    if (ecdhStatus != SECSuccess) {
++        goto loser;
++    }
++
++    if (PORT_Memcmp(computed_hash_result, ecdh_known_hash_result,
++                    sizeof(ecdh_known_hash_result)) != 0) {
++        ecdhStatus = SECFailure;
++        goto loser;
++    }
++
++loser:
++    if (ZZ.data) {
++        SECITEM_FreeItem(&ZZ, PR_FALSE);
++    }
++
++    if (ecdhStatus != SECSuccess) {
++        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++        return (SECFailure);
++    }
++    return (SECSuccess);
++}
++
++static SECStatus
++freebl_fips_EC_PowerUpSelfTest()
++{
++
++    /* EC Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
+     static const unsigned char p256_prime[] = {
+         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+     };
+     static const unsigned char p256_a[] = {
+         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+@@ -1212,17 +1377,17 @@ freebl_fips_ECDSA_PowerUpSelfTest()
+     static const unsigned char p256_order[] = {
+         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+         0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9,
+         0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
+     };
+     static const unsigned char p256_encoding[] = {
+         0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
+     };
+-    static const ECParams ecdsa_known_P256_Params = {
++    static const ECParams ec_known_P256_Params = {
+         NULL, ec_params_named,                                               /* arena, type */
+                                                                              /* fieldID */
+         { 256, ec_field_GFp,                                                 /* size and type */
+           { { siBuffer, (unsigned char *)p256_prime, sizeof(p256_prime) } }, /* u.prime */
+           0,
+           0,
+           0 },
+         /* curve */
+@@ -1245,34 +1410,39 @@ freebl_fips_ECDSA_PowerUpSelfTest()
+         { siBuffer, (unsigned char *)(p256_encoding) + 2, sizeof(p256_encoding) - 2 },
+     };
+ 
+     static const PRUint8 ecdsa_known_P256_signature[] = {
+         0x07, 0xb1, 0xcb, 0x57, 0x20, 0xa7, 0x10, 0xd6,
+         0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff,
+         0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f,
+         0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5,
+-        0x59, 0x6a, 0x62, 0x49, 0x3d, 0x50, 0xc9, 0xe1,
+-        0x27, 0x3b, 0xff, 0x9b, 0x13, 0x66, 0x67, 0xdd,
+-        0x7d, 0xd1, 0x0d, 0x2d, 0x7c, 0x44, 0x04, 0x1b,
+-        0x16, 0x21, 0x12, 0xc5, 0xcb, 0xbd, 0x9e, 0x75
++        0xa7, 0xd2, 0x20, 0xdd, 0x45, 0xf9, 0x2b, 0xdd,
++        0xda, 0x98, 0x99, 0x5b, 0x1c, 0x02, 0x3a, 0x27,
++        0x8b, 0x7d, 0xb6, 0xed, 0x0e, 0xe0, 0xa7, 0xac,
++        0xaa, 0x36, 0x2c, 0xfa, 0x1a, 0xdf, 0x0d, 0xe1,
+     };
+ 
+     ECParams ecparams;
+ 
+     SECStatus rv;
+ 
+     /* ECDSA GF(p) prime field curve test */
+-    ecparams = ecdsa_known_P256_Params;
++    ecparams = ec_known_P256_Params;
+     rv = freebl_fips_ECDSA_Test(&ecparams,
+                                 ecdsa_known_P256_signature,
+                                 sizeof ecdsa_known_P256_signature);
+     if (rv != SECSuccess) {
+         return (SECFailure);
+     }
++    /* ECDH GF(p) prime field curve test */
++    rv = freebl_fips_ECDH_Test(&ecparams);
++    if (rv != SECSuccess) {
++        return (SECFailure);
++    }
+ 
+     return (SECSuccess);
+ }
+ 
+ static SECStatus
+ freebl_fips_DSA_PowerUpSelfTest(void)
+ {
+     /* DSA Known P (1024-bits), Q (160-bits), and G (1024-bits) Values. */
+@@ -1413,16 +1583,148 @@ freebl_fips_DSA_PowerUpSelfTest(void)
+         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+         return SECFailure;
+     }
+ 
+     return (SECSuccess);
+ }
+ 
+ static SECStatus
++freebl_fips_DH_PowerUpSelfTest(void)
++{
++    /* DH Known P (2048-bits) */
++    static const PRUint8 dh_known_P[] = {
++        0xc2, 0x79, 0xbb, 0x76, 0x32, 0x0d, 0x43, 0xfd,
++        0x1b, 0x8c, 0xa2, 0x3c, 0x00, 0xdd, 0x6d, 0xef,
++        0xf8, 0x1a, 0xd9, 0xc1, 0xa2, 0xf5, 0x73, 0x2b,
++        0xdb, 0x1a, 0x3e, 0x84, 0x90, 0xeb, 0xe7, 0x8e,
++        0x5f, 0x5c, 0x6b, 0xb6, 0x61, 0x89, 0xd1, 0x03,
++        0xb0, 0x5f, 0x91, 0xe4, 0xd2, 0x82, 0x90, 0xfc,
++        0x3c, 0x49, 0x69, 0x59, 0xc1, 0x51, 0x6a, 0x85,
++        0x71, 0xe7, 0x5d, 0x72, 0x5a, 0x45, 0xad, 0x01,
++        0x6f, 0x82, 0xae, 0xec, 0x91, 0x08, 0x2e, 0x7c,
++        0x64, 0x93, 0x46, 0x1c, 0x68, 0xef, 0xc2, 0x03,
++        0x28, 0x1d, 0x75, 0x3a, 0xeb, 0x9c, 0x46, 0xf0,
++        0xc9, 0xdb, 0x99, 0x95, 0x13, 0x66, 0x4d, 0xd5,
++        0x1a, 0x78, 0x92, 0x51, 0x89, 0x72, 0x28, 0x7f,
++        0x20, 0x70, 0x41, 0x49, 0xa2, 0x86, 0xe9, 0xf9,
++        0x78, 0x5f, 0x8d, 0x2e, 0x5d, 0xfa, 0xdb, 0x57,
++        0xd4, 0x71, 0xdf, 0x66, 0xe3, 0x9e, 0x88, 0x70,
++        0xa4, 0x21, 0x44, 0x6a, 0xc7, 0xae, 0x30, 0x2c,
++        0x9c, 0x1f, 0x91, 0x57, 0xc8, 0x24, 0x34, 0x2d,
++        0x7a, 0x4a, 0x43, 0xc2, 0x5f, 0xab, 0x64, 0x2e,
++        0xaa, 0x28, 0x32, 0x95, 0x42, 0x7b, 0xa0, 0xcc,
++        0xdf, 0xfd, 0x22, 0xc8, 0x56, 0x84, 0xc1, 0x62,
++        0x15, 0xb2, 0x77, 0x86, 0x81, 0xfc, 0xa5, 0x12,
++        0x3c, 0xca, 0x28, 0x17, 0x8f, 0x03, 0x16, 0x6e,
++        0xb8, 0x24, 0xfa, 0x1b, 0x15, 0x02, 0xfd, 0x8b,
++        0xb6, 0x0a, 0x1a, 0xf7, 0x47, 0x41, 0xc5, 0x2b,
++        0x37, 0x3e, 0xa1, 0xbf, 0x68, 0xda, 0x1c, 0x55,
++        0x44, 0xc3, 0xee, 0xa1, 0x63, 0x07, 0x11, 0x3b,
++        0x5f, 0x00, 0x84, 0xb4, 0xc4, 0xe4, 0xa7, 0x97,
++        0x29, 0xf8, 0xce, 0xab, 0xfc, 0x27, 0x3e, 0x34,
++        0xe4, 0xc7, 0x81, 0x52, 0x32, 0x0e, 0x27, 0x3c,
++        0xa6, 0x70, 0x3f, 0x4a, 0x54, 0xda, 0xdd, 0x60,
++        0x26, 0xb3, 0x6e, 0x45, 0x26, 0x19, 0x41, 0x6f
++    };
++
++    static const PRUint8 dh_known_Y_1[] = {
++        0xb4, 0xc7, 0x85, 0xba, 0xa6, 0x98, 0xb3, 0x77,
++        0x41, 0x2b, 0xd9, 0x9a, 0x72, 0x90, 0xa4, 0xac,
++        0xc4, 0xf7, 0xc2, 0x23, 0x9a, 0x68, 0xe2, 0x7d,
++        0x3a, 0x54, 0x45, 0x91, 0xc1, 0xd7, 0x8a, 0x17,
++        0x54, 0xd3, 0x37, 0xaa, 0x0c, 0xcd, 0x0b, 0xe2,
++        0xf2, 0x34, 0x0f, 0x17, 0xa8, 0x07, 0x88, 0xaf,
++        0xed, 0xc1, 0x02, 0xd4, 0xdb, 0xdc, 0x0f, 0x22,
++        0x51, 0x23, 0x40, 0xb9, 0x65, 0x6d, 0x39, 0xf4,
++        0xe1, 0x8b, 0x57, 0x7d, 0xb6, 0xd3, 0xf2, 0x6b,
++        0x02, 0xa9, 0x36, 0xf0, 0x0d, 0xe3, 0xdb, 0x9a,
++        0xbf, 0x20, 0x00, 0x4d, 0xec, 0x6f, 0x68, 0x95,
++        0xee, 0x59, 0x4e, 0x3c, 0xb6, 0xda, 0x7b, 0x19,
++        0x08, 0x9a, 0xef, 0x61, 0x43, 0xf5, 0xfb, 0x25,
++        0x70, 0x19, 0xc1, 0x5f, 0x0e, 0x0f, 0x6a, 0x63,
++        0x44, 0xe9, 0xcf, 0x33, 0xce, 0x13, 0x4f, 0x34,
++        0x3c, 0x94, 0x40, 0x8d, 0xf2, 0x65, 0x42, 0xef,
++        0x70, 0x54, 0xdd, 0x5f, 0xc1, 0xd7, 0x0b, 0xa6,
++        0x06, 0xd5, 0xa6, 0x47, 0xae, 0x2c, 0x1f, 0x5a,
++        0xa6, 0xb3, 0xc1, 0x38, 0x3a, 0x3b, 0x60, 0x94,
++        0xa2, 0x95, 0xab, 0xb2, 0x86, 0x82, 0xc5, 0x3b,
++        0xb8, 0x6f, 0x3e, 0x55, 0x86, 0x84, 0xe0, 0x00,
++        0xe5, 0xef, 0xca, 0x5c, 0xec, 0x7e, 0x38, 0x0f,
++        0x82, 0xa2, 0xb1, 0xee, 0x48, 0x1b, 0x32, 0xbb,
++        0x5a, 0x33, 0xa5, 0x01, 0xba, 0xca, 0xa6, 0x64,
++        0x61, 0xb6, 0xe5, 0x5c, 0x0e, 0x5f, 0x2c, 0x66,
++        0x0d, 0x01, 0x6a, 0x20, 0x04, 0x70, 0x68, 0x82,
++        0x93, 0x29, 0x15, 0x3b, 0x7a, 0x06, 0xb2, 0x92,
++        0x61, 0xcd, 0x7e, 0xa4, 0xc1, 0x15, 0x64, 0x3b,
++        0x3c, 0x51, 0x10, 0x4c, 0x87, 0xa6, 0xaf, 0x07,
++        0xce, 0x46, 0x82, 0x75, 0xf3, 0x90, 0xf3, 0x21,
++        0x55, 0x74, 0xc2, 0xe4, 0x96, 0x7d, 0xc3, 0xe6,
++        0x33, 0xa5, 0xc6, 0x51, 0xef, 0xec, 0x90, 0x08
++    };
++
++    static const PRUint8 dh_known_x_2[] = {
++        0x9e, 0x9b, 0xc3, 0x25, 0x53, 0xf9, 0xfc, 0x92,
++        0xb6, 0xae, 0x54, 0x8e, 0x23, 0x4c, 0x94, 0xba,
++        0x41, 0xe6, 0x29, 0x33, 0xb9, 0xdb, 0xff, 0x6d,
++        0xa8, 0xb8, 0x48, 0x49, 0x66, 0x11, 0xa6, 0x13
++    };
++
++    static const PRUint8 dh_known_hash_result[] = {
++        0x93, 0xa2, 0x89, 0x1c, 0x8a, 0xc3, 0x70, 0xbf,
++        0xa7, 0xdf, 0xb6, 0xd7, 0x82, 0xfb, 0x87, 0x81,
++        0x09, 0x47, 0xf3, 0x9f, 0x5a, 0xbf, 0x4f, 0x3f,
++        0x8e, 0x5e, 0x06, 0xca, 0x30, 0xa7, 0xaf, 0x10
++    };
++
++    /* DH variables. */
++    SECStatus dhStatus;
++    SECItem dh_prime;
++    SECItem dh_pub_key_1;
++    SECItem dh_priv_key_2;
++    SECItem ZZ = { 0, 0, 0 };
++    PRUint8 computed_hash_result[HASH_LENGTH_MAX];
++
++    dh_prime.data = (PRUint8 *)dh_known_P;
++    dh_prime.len = sizeof(dh_known_P);
++    dh_pub_key_1.data = (PRUint8 *)dh_known_Y_1;
++    dh_pub_key_1.len = sizeof(dh_known_Y_1);
++    dh_priv_key_2.data = (PRUint8 *)dh_known_x_2;
++    dh_priv_key_2.len = sizeof(dh_known_x_2);
++
++    /* execute the derive */
++    dhStatus = DH_Derive(&dh_pub_key_1, &dh_prime, &dh_priv_key_2, &ZZ, dh_prime.len);
++    if (dhStatus != SECSuccess) {
++        goto loser;
++    }
++
++    dhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
++    if (dhStatus != SECSuccess) {
++        goto loser;
++    }
++
++    if (PORT_Memcmp(computed_hash_result, dh_known_hash_result,
++                    sizeof(dh_known_hash_result)) != 0) {
++        dhStatus = SECFailure;
++        goto loser;
++    }
++
++loser:
++    if (ZZ.data) {
++        SECITEM_FreeItem(&ZZ, PR_FALSE);
++    }
++
++    if (dhStatus != SECSuccess) {
++        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
++        return (SECFailure);
++    }
++    return (SECSuccess);
++}
++
++static SECStatus
+ freebl_fips_RNG_PowerUpSelfTest(void)
+ {
+     static const PRUint8 Q[] = {
+         0x85, 0x89, 0x9c, 0x77, 0xa3, 0x79, 0xff, 0x1a,
+         0x86, 0x6f, 0x2f, 0x3e, 0x2e, 0xf9, 0x8c, 0x9c,
+         0x9d, 0xef, 0xeb, 0xed
+     };
+     static const PRUint8 GENX[] = {
+@@ -1536,31 +1838,37 @@ freebl_fipsPowerUpSelfTest(unsigned int 
+ 
+         /* HMAC SHA-X Power-Up SelfTest(s). */
+         rv = freebl_fips_HMAC_PowerUpSelfTest();
+ 
+         if (rv != SECSuccess)
+             return rv;
+ 
+         /* NOTE: RSA can only be tested in full freebl. It requires access to
+-     * the locking primitives */
++         * the locking primitives */
+         /* RSA Power-Up SelfTest(s). */
+         rv = freebl_fips_RSA_PowerUpSelfTest();
+ 
+         if (rv != SECSuccess)
+             return rv;
+ 
+         /* DSA Power-Up SelfTest(s). */
+         rv = freebl_fips_DSA_PowerUpSelfTest();
+ 
+         if (rv != SECSuccess)
+             return rv;
+ 
+-        /* ECDSA Power-Up SelfTest(s). */
+-        rv = freebl_fips_ECDSA_PowerUpSelfTest();
++        /* DH Power-Up SelfTest(s). */
++        rv = freebl_fips_DH_PowerUpSelfTest();
++
++        if (rv != SECSuccess)
++            return rv;
++
++        /* EC Power-Up SelfTest(s). */
++        rv = freebl_fips_EC_PowerUpSelfTest();
+ 
+         if (rv != SECSuccess)
+             return rv;
+     }
+     /* Passed Power-Up SelfTest(s). */
+     return (SECSuccess);
+ }
+ 
+diff --git a/lib/freebl/intel-gcm-wrap.c b/lib/freebl/intel-gcm-wrap.c
+--- a/lib/freebl/intel-gcm-wrap.c
++++ b/lib/freebl/intel-gcm-wrap.c
+@@ -138,16 +138,17 @@ intel_AES_GCM_CreateContext(void *contex
+ loser:
+     PORT_Free(gcm);
+     return NULL;
+ }
+ 
+ void
+ intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit)
+ {
++    PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext));
+     if (freeit) {
+         PORT_Free(gcm);
+     }
+ }
+ 
+ SECStatus
+ intel_AES_GCM_EncryptUpdate(intel_AES_GCMContext *gcm,
+                             unsigned char *outbuf,
+diff --git a/lib/freebl/pqg.c b/lib/freebl/pqg.c
+--- a/lib/freebl/pqg.c
++++ b/lib/freebl/pqg.c
+@@ -486,21 +486,21 @@ cleanup:
+ **  Perform steps from  FIPS 186-3, Appendix A.1.2.1 and Appendix C.6
+ **
+ **  This generates a provable prime from two smaller prime. The resulting
+ **  prime p will have q0 as a multiple of p-1. q0 can be 1.
+ **
+ ** This implments steps 4 thorough 22 of FIPS 186-3 A.1.2.1 and
+ **                steps 16 through 34 of FIPS 186-2 C.6
+ */
+-#define MAX_ST_SEED_BITS (HASH_LENGTH_MAX * PR_BITS_PER_BYTE)
+ static SECStatus
+ makePrimefromPrimesShaweTaylor(
+     HASH_HashType hashtype,          /* selected Hashing algorithm */
+     unsigned int length,             /* input. Length of prime in bits. */
++    unsigned int seedlen,            /* input seed length in bits */
+     mp_int *c0,                      /* seed prime */
+     mp_int *q,                       /* sub prime, can be 1 */
+     mp_int *prime,                   /* output.  */
+     SECItem *prime_seed,             /* input/output.  */
+     unsigned int *prime_gen_counter) /* input/output.  */
+ {
+     mp_int c;
+     mp_int c0_2;
+@@ -552,33 +552,32 @@ makePrimefromPrimesShaweTaylor(
+     */
+ 
+     /* Step 4/16 iterations = ceiling(length/outlen)-1 */
+     iterations = (length + outlen - 1) / outlen; /* NOTE: iterations +1 */
+     /* Step 5/17 old_counter = prime_gen_counter */
+     old_counter = *prime_gen_counter;
+     /*
+     ** Comment: Generate a pseudorandom integer x in the interval
+-    ** [2**(lenght-1), 2**length].
++    ** [2**(length-1), 2**length].
+     **
+     ** Step 6/18 x = 0
+     */
+     PORT_Memset(x, 0, sizeof(x));
+     /*
+     ** Step 7/19 for i = 0 to iterations do
+     **  x = x + (HASH(prime_seed + i) * 2^(i*outlen))
+     */
+     for (i = 0; i < iterations; i++) {
+         /* is bigger than prime_seed should get to */
+         CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
+-                                       MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
++                                       seedlen, &x[(iterations - i - 1) * hashlen]));
+     }
+     /* Step 8/20 prime_seed = prime_seed + iterations + 1 */
+-    CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
+-                           prime_seed));
++    CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
+     /*
+     ** Step 9/21 x = 2 ** (length-1) + x mod 2 ** (length-1)
+     **
+     **   This step mathematically sets the high bit and clears out
+     **  all the other bits higher than length. 'x' is stored
+     **  in the x array, MSB first. The above formula gives us an 'x'
+     **  which is length bytes long and has the high bit set. We also know
+     **  that length <= iterations*outlen since
+@@ -590,17 +589,17 @@ makePrimefromPrimesShaweTaylor(
+      * multiple of 8,*/
+     bit = 1 << ((length - 1) & 0x7); /* select the proper bit in the byte */
+     /* we need to zero out the rest of the bits in the byte above */
+     mask = (bit - 1);
+     /* now we set it */
+     x[offset] = (mask & x[offset]) | bit;
+     /*
+     ** Comment: Generate a candidate prime c in the interval
+-    ** [2**(lenght-1), 2**length].
++    ** [2**(length-1), 2**length].
+     **
+     ** Step 10 t = ceiling(x/(2q(p0)))
+     ** Step 22 t = ceiling(x/(2(c0)))
+     */
+     CHECK_MPI_OK(mp_read_unsigned_octets(&t, &x[offset],
+                                          hashlen * iterations - offset)); /* t = x */
+     CHECK_MPI_OK(mp_mul(c0, q, &c0_2));                                   /* c0_2 is now c0*q */
+     CHECK_MPI_OK(mp_add(&c0_2, &c0_2, &c0_2));                            /* c0_2 is now 2*q*c0 */
+@@ -619,17 +618,17 @@ makePrimefromPrimesShaweTaylor(
+ step_23:
+     CHECK_MPI_OK(mp_mul(&t, &c0_2, &c));                /* c = t*2qc0 */
+     CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c));        /* c= 2tqc0 + 1*/
+     if (mpl_significant_bits(&c) > length) {            /* if c > 2**length */
+         CHECK_MPI_OK(mp_sub_d(&c0_2, (mp_digit)1, &t)); /* t = 2qc0-1 */
+         /* t = 2**(length-1) + 2qc0 -1 */
+         CHECK_MPI_OK(mp_add(&two_length_minus_1, &t, &t));
+         /* t = floor((2**(length-1)+2qc0 -1)/2qco)
+-         *   = ceil(2**(lenght-2)/2qc0) */
++         *   = ceil(2**(length-2)/2qc0) */
+         CHECK_MPI_OK(mp_div(&t, &c0_2, &t, NULL));
+         CHECK_MPI_OK(mp_mul(&t, &c0_2, &c));
+         CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c)); /* c= 2tqc0 + 1*/
+     }
+     /* Step 13/25 prime_gen_counter = prime_gen_counter + 1*/
+     (*prime_gen_counter)++;
+     /*
+     ** Comment: Test the candidate prime c for primality; first pick an
+@@ -640,23 +639,21 @@ step_23:
+     PORT_Memset(x, 0, sizeof(x)); /* use x for a */
+     /*
+     ** Step 15/27 for i = 0 to iterations do
+     **  a = a + (HASH(prime_seed + i) * 2^(i*outlen))
+     **
+     ** NOTE: we reuse the x array for 'a' initially.
+     */
+     for (i = 0; i < iterations; i++) {
+-        /* MAX_ST_SEED_BITS is bigger than prime_seed should get to */
+         CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
+-                                       MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
++                                       seedlen, &x[(iterations - i - 1) * hashlen]));
+     }
+     /* Step 16/28 prime_seed = prime_seed + iterations + 1 */
+-    CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
+-                           prime_seed));
++    CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
+     /* Step 17/29 a = 2 + (a mod (c-3)). */
+     CHECK_MPI_OK(mp_read_unsigned_octets(&a, x, iterations * hashlen));
+     CHECK_MPI_OK(mp_sub_d(&c, (mp_digit)3, &z)); /* z = c -3 */
+     CHECK_MPI_OK(mp_mod(&a, &z, &a));            /* a = a mod c -3 */
+     CHECK_MPI_OK(mp_add_d(&a, (mp_digit)2, &a)); /* a = 2 + a mod c -3 */
+     /*
+     ** Step 18 z = a**(2tq) mod p.
+     ** Step 30 z = a**(2t) mod c.
+@@ -737,16 +734,17 @@ makePrimefromSeedShaweTaylor(
+ {
+     mp_int c;
+     mp_int c0;
+     mp_int one;
+     SECStatus rv = SECFailure;
+     int hashlen = HASH_ResultLen(hashtype);
+     int outlen = hashlen * PR_BITS_PER_BYTE;
+     int offset;
++    int seedlen = input_seed->len * 8; /*seedlen is in bits */
+     unsigned char bit, mask;
+     unsigned char x[HASH_LENGTH_MAX * 2];
+     mp_digit dummy;
+     mp_err err = MP_OKAY;
+     int i;
+ 
+     MP_DIGITS(&c) = 0;
+     MP_DIGITS(&c0) = 0;
+@@ -770,30 +768,29 @@ makePrimefromSeedShaweTaylor(
+     */
+         rv = makePrimefromSeedShaweTaylor(hashtype, (length + 1) / 2 + 1,
+                                           input_seed, &c0, prime_seed, prime_gen_counter);
+         /* Step 15 if FAILURE is returned, return (FAILURE, 0, 0, 0). */
+         if (rv != SECSuccess) {
+             goto cleanup;
+         }
+         /* Steps 16-34 */
+-        rv = makePrimefromPrimesShaweTaylor(hashtype, length, &c0, &one,
++        rv = makePrimefromPrimesShaweTaylor(hashtype, length, seedlen, &c0, &one,
+                                             prime, prime_seed, prime_gen_counter);
+         goto cleanup; /* we're done, one way or the other */
+     }
+     /* Step 3 prime_seed = input_seed */
+     CHECK_SEC_OK(SECITEM_CopyItem(NULL, prime_seed, input_seed));
+     /* Step 4 prime_gen_count = 0 */
+     *prime_gen_counter = 0;
+ 
+ step_5:
+     /* Step 5 c = Hash(prime_seed) xor Hash(prime_seed+1). */
+     CHECK_SEC_OK(HASH_HashBuf(hashtype, x, prime_seed->data, prime_seed->len));
+-    CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1,
+-                                   MAX_ST_SEED_BITS, &x[hashlen]));
++    CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1, seedlen, &x[hashlen]));
+     for (i = 0; i < hashlen; i++) {
+         x[i] = x[i] ^ x[i + hashlen];
+     }
+     /* Step 6 c = 2**length-1 + c mod 2**length-1 */
+     /*   This step mathematically sets the high bit and clears out
+     **  all the other bits higher than length. Right now c is stored
+     **  in the x array, MSB first. The above formula gives us a c which
+     **  is length bytes long and has the high bit set. We also know that
+@@ -812,17 +809,17 @@ step_5:
+     /* Step 7 c = c*floor(c/2) + 1 */
+     /* set the low bit. much easier to find (the end of the array) */
+     x[hashlen - 1] |= 1;
+     /* now that we've set our bits, we can create our candidate "c" */
+     CHECK_MPI_OK(mp_read_unsigned_octets(&c, &x[offset], hashlen - offset));
+     /* Step 8 prime_gen_counter = prime_gen_counter + 1 */
+     (*prime_gen_counter)++;
+     /* Step 9 prime_seed = prime_seed + 2 */
+-    CHECK_SEC_OK(addToSeed(prime_seed, 2, MAX_ST_SEED_BITS, prime_seed));
++    CHECK_SEC_OK(addToSeed(prime_seed, 2, seedlen, prime_seed));
+     /* Step 10 Perform deterministic primality test on c. For example, since
+     ** c is small, it's primality can be tested by trial division, See
+     ** See Appendic C.7.
+     **
+     ** We in fact test with trial division. mpi has a built int trial divider
+     ** that divides all divisors up to 2^16.
+     */
+     if (prime_tab[prime_tab_size - 1] < 0xFFF1) {
+@@ -885,17 +882,18 @@ findQfromSeed(
+     unsigned int L,             /* input.  Length of p in bits. */
+     unsigned int N,             /* input.  Length of q in bits. */
+     unsigned int g,             /* input.  Length of seed in bits. */
+     const SECItem *seed,        /* input.  */
+     mp_int *Q,                  /* input. */
+     mp_int *Q_,                 /* output. */
+     unsigned int *qseed_len,    /* output */
+     HASH_HashType *hashtypePtr, /* output. Hash uses */
+-    pqgGenType *typePtr)        /* output. Generation Type used */
++    pqgGenType *typePtr,        /* output. Generation Type used */
++    unsigned int *qgen_counter) /* output. q_counter */
+ {
+     HASH_HashType hashtype;
+     SECItem firstseed = { 0, 0, 0 };
+     SECItem qseed = { 0, 0, 0 };
+     SECStatus rv;
+ 
+     *qseed_len = 0; /* only set if FIPS186_3_ST_TYPE */
+ 
+@@ -959,16 +957,17 @@ findQfromSeed(
+          * accident, someone has been tweeking with the seeds, just
+          * fail a this point. */
+                 SECITEM_FreeItem(&qseed, PR_FALSE);
+                 return SECFailure;
+             }
+             *qseed_len = qseed.len;
+             *hashtypePtr = hashtype;
+             *typePtr = FIPS186_3_ST_TYPE;
++            *qgen_counter = count;
+             SECITEM_FreeItem(&qseed, PR_FALSE);
+             return SECSuccess;
+         }
+         SECITEM_FreeItem(&qseed, PR_FALSE);
+     }
+     /* no hash algorithms found which match seed to Q, fail */
+     return SECFailure;
+ }
+@@ -1383,29 +1382,33 @@ step_5:
+         CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, N, &firstseed, &Q,
+                                                   &qseed, &qgen_counter));
+         /* Step 3. Use floor(L/2+1) and qseed to generate random prime p0
+      * using Appendix C.6 */
+         pgen_counter = 0;
+         CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
+                                                   &qseed, &p0, &pseed, &pgen_counter));
+         /* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
+-        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
++        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, seedBytes * 8,
+                                                     &p0, &Q, &P, &pseed, &pgen_counter));
+ 
+         /* combine all the seeds */
+-        seed->len = firstseed.len + qseed.len + pseed.len;
++        if ((qseed.len > firstseed.len) || (pseed.len > firstseed.len)) {
++            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); /* shouldn't happen */
++            goto cleanup;
++        }
++        seed->len = firstseed.len * 3; /*handle leading zeros in pseed and qseed*/
+         seed->data = PORT_ArenaZAlloc(verify->arena, seed->len);
+         if (seed->data == NULL) {
+             goto cleanup;
+         }
+         PORT_Memcpy(seed->data, firstseed.data, firstseed.len);
+-        PORT_Memcpy(seed->data + firstseed.len, pseed.data, pseed.len);
+-        PORT_Memcpy(seed->data + firstseed.len + pseed.len, qseed.data, qseed.len);
+-        counter = 0; /* (qgen_counter << 16) | pgen_counter; */
++        PORT_Memcpy(seed->data + 2 * firstseed.len - pseed.len, pseed.data, pseed.len);
++        PORT_Memcpy(seed->data + 3 * firstseed.len - qseed.len, qseed.data, qseed.len);
++        counter = (qgen_counter << 16) | pgen_counter;
+ 
+         /* we've generated both P and Q now, skip to generating G */
+         goto generate_G;
+     }
+     /* ******************************************************************
+     ** Step 8. (Step 4 in 186-1)
+     ** "Use a robust primality testing algorithm to test whether q is prime."
+     **
+@@ -1615,16 +1618,17 @@ PQG_VerifyParams(const PQGParams *params
+ {
+     SECStatus rv = SECSuccess;
+     unsigned int g, n, L, N, offset, outlen;
+     mp_int p0, P, Q, G, P_, Q_, G_, r, h;
+     mp_err err = MP_OKAY;
+     int j;
+     unsigned int counter_max = 0; /* handle legacy L < 1024 */
+     unsigned int qseed_len;
++    unsigned int qgen_counter_ = 0;
+     SECItem pseed_ = { 0, 0, 0 };
+     HASH_HashType hashtype;
+     pqgGenType type;
+ 
+ #define CHECKPARAM(cond)      \
+     if (!(cond)) {            \
+         *result = SECFailure; \
+         goto cleanup;         \
+@@ -1694,77 +1698,104 @@ PQG_VerifyParams(const PQGParams *params
+     CHECKPARAM(mp_cmp_d(&r, 1) == 0);
+     /* 5.  Q is prime */
+     CHECKPARAM(mpp_pprime(&Q, prime_testcount_q(L, N)) == MP_YES);
+     /* 6.  P is prime */
+     CHECKPARAM(mpp_pprime(&P, prime_testcount_p(L, N)) == MP_YES);
+     /* Steps 7-12 are done only if the optional PQGVerify is supplied. */
+     /* continue processing P */
+     /* 7.  counter < 4*L */
+-    CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
+     /* 8.  g >= N and g < 2*L   (g is length of seed in bits) */
+-    g = vfy->seed.len * 8;
+-    CHECKPARAM(g >= N && g < counter_max / 2);
++    /* step 7 and 8 are delayed until we determine which type of generation
++     * was used */
+     /* 9.  Q generated from SEED matches Q in PQGParams. */
+     /* This function checks all possible hash and generation types to
+      * find a Q_ which matches Q. */
++    g = vfy->seed.len * 8;
+     CHECKPARAM(findQfromSeed(L, N, g, &vfy->seed, &Q, &Q_, &qseed_len,
+-                             &hashtype, &type) == SECSuccess);
++                             &hashtype, &type, &qgen_counter_) == SECSuccess);
+     CHECKPARAM(mp_cmp(&Q, &Q_) == 0);
++    /* now we can do steps 7  & 8*/
++    if ((type == FIPS186_1_TYPE) || (type == FIPS186_3_TYPE)) {
++        CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
++        CHECKPARAM(g >= N && g < counter_max / 2);
++    }
+     if (type == FIPS186_3_ST_TYPE) {
+         SECItem qseed = { 0, 0, 0 };
+         SECItem pseed = { 0, 0, 0 };
+         unsigned int first_seed_len;
+-        unsigned int pgen_counter = 0;
++        unsigned int pgen_counter_ = 0;
++        unsigned int qgen_counter = (vfy->counter >> 16) & 0xffff;
++        unsigned int pgen_counter = (vfy->counter) & 0xffff;
+ 
+         /* extract pseed and qseed from domain_parameter_seed, which is
+          * first_seed || pseed || qseed. qseed is first_seed + small_integer
+-         * pseed is qseed + small_integer. This means most of the time
++         * mod the length of first_seed. pseed is qseed + small_integer mod
++         * the length of first_seed. This means most of the time
+          * first_seed.len == qseed.len == pseed.len. Rarely qseed.len and/or
+-         * pseed.len will be one greater than first_seed.len, so we can
+-         * depend on the fact that
+-         *   first_seed.len = floor(domain_parameter_seed.len/3).
+-         * findQfromSeed returned qseed.len, so we can calculate pseed.len as
+-         *   pseed.len = domain_parameter_seed.len - first_seed.len - qseed.len
+-         * this is probably over kill, since 99.999% of the time they will all
+-         * be equal.
+-         *
+-         * With the lengths, we can now find the offsets;
++         * pseed.len will be smaller because mpi clamps them. pqgGen
++         * automatically adds the zero pad back though, so we can depend
++         * domain_parameter_seed.len to be a multiple of three. We only have
++         * to deal with the fact that the returned seeds from our functions
++         * could be shorter.
++         *   first_seed.len = domain_parameter_seed.len/3
++         * We can now find the offsets;
+          * first_seed.data = domain_parameter_seed.data + 0
+          * pseed.data = domain_parameter_seed.data + first_seed.len
+          * qseed.data = domain_parameter_seed.data
+          *         + domain_paramter_seed.len - qseed.len
+-         *
++         * We deal with pseed possibly having zero pad in the pseed check later.
+          */
+         first_seed_len = vfy->seed.len / 3;
+         CHECKPARAM(qseed_len < vfy->seed.len);
+         CHECKPARAM(first_seed_len * 8 > N - 1);
+-        CHECKPARAM(first_seed_len + qseed_len < vfy->seed.len);
++        CHECKPARAM(first_seed_len * 8 < counter_max / 2);
++        CHECKPARAM(first_seed_len >= qseed_len);
+         qseed.len = qseed_len;
+         qseed.data = vfy->seed.data + vfy->seed.len - qseed.len;
+-        pseed.len = vfy->seed.len - (first_seed_len + qseed_len);
++        pseed.len = first_seed_len;
+         pseed.data = vfy->seed.data + first_seed_len;
+ 
+         /*
+          * now complete FIPS 186-3 A.1.2.1.2. Step 1 was completed
+          * above in our initial checks, Step 2 was completed by
+          * findQfromSeed */
+ 
+         /* Step 3 (status, c0, prime_seed, prime_gen_counter) =
+         ** (ST_Random_Prime((ceil(length/2)+1, input_seed)
+         */
+         CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
+-                                                  &qseed, &p0, &pseed_, &pgen_counter));
++                                                  &qseed, &p0, &pseed_, &pgen_counter_));
+         /* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
+-        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
+-                                                    &p0, &Q_, &P_, &pseed_, &pgen_counter));
++        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, first_seed_len * 8,
++                                                    &p0, &Q_, &P_, &pseed_, &pgen_counter_));
+         CHECKPARAM(mp_cmp(&P, &P_) == 0);
+         /* make sure pseed wasn't tampered with (since it is part of
+          * calculating G) */
++        if (pseed.len > pseed_.len) {
++            /* handle the case of zero pad for pseed */
++            int extra = pseed.len - pseed_.len;
++            int i;
++            for (i = 0; i < extra; i++) {
++                if (pseed.data[i] != 0) {
++                    *result = SECFailure;
++                    goto cleanup;
++                }
++            }
++            pseed.data += extra;
++            pseed.len -= extra;
++            /* the rest is handled in the normal compare below */
++        }
+         CHECKPARAM(SECITEM_CompareItem(&pseed, &pseed_) == SECEqual);
++        if (vfy->counter != -1) {
++            CHECKPARAM(pgen_counter < counter_max);
++            CHECKPARAM(qgen_counter < counter_max);
++            CHECKPARAM((pgen_counter_ == pgen_counter));
++            CHECKPARAM((qgen_counter_ == qgen_counter));
++        }
+     } else if (vfy->counter == -1) {
+         /* If counter is set to -1, we are really only verifying G, skip
+          * the remainder of the checks for P */
+         CHECKPARAM(type != FIPS186_1_TYPE); /* we only do this for DSA2 */
+     } else {
+         /* 10. P generated from (L, counter, g, SEED, Q) matches P
+          * in PQGParams. */
+         outlen = HASH_ResultLen(hashtype) * PR_BITS_PER_BYTE;
+diff --git a/lib/freebl/rijndael.c b/lib/freebl/rijndael.c
+--- a/lib/freebl/rijndael.c
++++ b/lib/freebl/rijndael.c
+@@ -1027,23 +1027,25 @@ AES_CreateContext(const unsigned char *k
+  * AES_DestroyContext
+  *
+  * Zero an AES cipher context.  If freeit is true, also free the pointer
+  * to the context.
+  */
+ void
+ AES_DestroyContext(AESContext *cx, PRBool freeit)
+ {
++    void *mem = cx->mem;
+     if (cx->worker_cx && cx->destroy) {
+         (*cx->destroy)(cx->worker_cx, PR_TRUE);
+         cx->worker_cx = NULL;
+         cx->destroy = NULL;
+     }
++    PORT_Memset(cx, 0, sizeof(AESContext));
+     if (freeit) {
+-        PORT_Free(cx->mem);
++        PORT_Free(mem);
+     }
+ }
+ 
+ /*
+  * AES_Encrypt
+  *
+  * Encrypt an arbitrary-length buffer.  The output buffer must already be
+  * allocated to at least inputLen.
+diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
+--- a/lib/softoken/pkcs11c.c
++++ b/lib/softoken/pkcs11c.c
+@@ -4708,16 +4708,24 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
+                        pairwise_digest_length,
+                        signature,
+                        &signature_length);
+         if (crv != CKR_OK) {
+             PORT_Free(signature);
+             return crv;
+         }
+ 
++        /* detect trivial signing transforms */
++        if (signature_length >= pairwise_digest_length) {
++            if (PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0) {
++                PORT_Free(signature);
++                return CKR_DEVICE_ERROR;
++            }
++        }
++
+         /* Verify the known hash using the public key. */
+         crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
+         if (crv != CKR_OK) {
+             PORT_Free(signature);
+             return crv;
+         }
+ 
+         crv = NSC_Verify(hSession,
+@@ -7543,40 +7551,55 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
+             SHA512_HashBuf(key_block, (const unsigned char *)att->attrib.pValue,
+                            att->attrib.ulValueLen);
+ 
+             crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);
+             break;
+ 
+         case CKM_DH_PKCS_DERIVE: {
+             SECItem derived, dhPublic;
+-            SECItem dhPrime, dhValue;
++            SECItem dhPrime, dhSubPrime, dhValue;
+             /* sourceKey - values for the local existing low key */
+             /* get prime and value attributes */
+             crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
+-            if (crv != SECSuccess)
++            if (crv != CKR_OK)
+                 break;
+             crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
+-            if (crv != SECSuccess) {
++            if (crv != CKR_OK) {
+                 PORT_Free(dhPrime.data);
+                 break;
+             }
+ 
+             dhPublic.data = pMechanism->pParameter;
+             dhPublic.len = pMechanism->ulParameterLen;
+ 
++            /* if the caller bothered to provide Q, use Q to validate.
++             * the public key */
++            crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, sourceKey, CKA_SUBPRIME);
++            if (crv == CKR_OK) {
++                rv = KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime);
++                PORT_Free(dhSubPrime.data);
++                if (rv != SECSuccess) {
++                    crv = CKR_ARGUMENTS_BAD;
++                    PORT_Free(dhPrime.data);
++                    PORT_Free(dhValue.data);
++                    break;
++                }
++            }
++
+             /* calculate private value - oct */
+             rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
+ 
+             PORT_Free(dhPrime.data);
+             PORT_Free(dhValue.data);
+ 
+             if (rv == SECSuccess) {
+                 sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
+                 PORT_ZFree(derived.data, derived.len);
++                crv = CKR_OK;
+             } else
+                 crv = CKR_HOST_MEMORY;
+ 
+             break;
+         }
+ 
+         case CKM_ECDH1_DERIVE:
+         case CKM_ECDH1_COFACTOR_DERIVE: {
diff --git a/SOURCES/nss-softokn-prelink.conf b/SOURCES/nss-softokn-prelink.conf
deleted file mode 100644
index 11d7fb0..0000000
--- a/SOURCES/nss-softokn-prelink.conf
+++ /dev/null
@@ -1,6 +0,0 @@
--b /lib{,64}/libfreeblpriv3.so
--b /lib{,64}/libsoftokn3.so
--b /lib{,64}/libnssdbm3.so
--b /usr/lib{,64}/libfreeblpriv3.so
--b /usr/lib{,64}/libsoftokn3.so
--b /usr/lib{,64}/libnssdbm3.so
diff --git a/SOURCES/nss-sysinit-userdb.patch b/SOURCES/nss-sysinit-userdb.patch
new file mode 100644
index 0000000..7347260
--- /dev/null
+++ b/SOURCES/nss-sysinit-userdb.patch
@@ -0,0 +1,106 @@
+Index: nss/lib/sysinit/nsssysinit.c
+===================================================================
+--- nss.orig/lib/sysinit/nsssysinit.c
++++ nss/lib/sysinit/nsssysinit.c
+@@ -36,41 +36,9 @@ testdir(char *dir)
+     return S_ISDIR(buf.st_mode);
+ }
+ 
+-/**
+- * Append given @dir to @path and creates the directory with mode @mode.
+- * Returns 0 if successful, -1 otherwise.
+- * Assumes that the allocation for @path has sufficient space for @dir
+- * to be added.
+- */
+-static int
+-appendDirAndCreate(char *path, char *dir, mode_t mode)
+-{
+-    PORT_Strcat(path, dir);
+-    if (!testdir(path)) {
+-        if (mkdir(path, mode)) {
+-            return -1;
+-        }
+-    }
+-    return 0;
+-}
+-
+-#define XDG_NSS_USER_PATH1 "/.local"
+-#define XDG_NSS_USER_PATH2 "/share"
+-#define XDG_NSS_USER_PATH3 "/pki"
+-
+ #define NSS_USER_PATH1 "/.pki"
+ #define NSS_USER_PATH2 "/nssdb"
+-
+-/**
+- * Return the path to user's NSS database.
+- * We search in the following dirs in order:
+- * (1) $HOME/.pki/nssdb;
+- * (2) $XDG_DATA_HOME/pki/nssdb if XDG_DATA_HOME is set;
+- * (3) $HOME/.local/share/pki/nssdb (default XDG_DATA_HOME value).
+- * If (1) does not exist, then the returned dir will be set to either
+- * (2) or (3), depending if XDG_DATA_HOME is set.
+- */
+-char *
++static char *
+ getUserDB(void)
+ {
+     char *userdir = PR_GetEnvSecure("HOME");
+@@ -81,47 +49,22 @@ getUserDB(void)
+     }
+ 
+     nssdir = PORT_Alloc(strlen(userdir) + sizeof(NSS_USER_PATH1) + sizeof(NSS_USER_PATH2));
++    if (nssdir == NULL) {
++        return NULL;
++    }
+     PORT_Strcpy(nssdir, userdir);
+-    PORT_Strcat(nssdir, NSS_USER_PATH1 NSS_USER_PATH2);
+-    if (testdir(nssdir)) {
+-        /* $HOME/.pki/nssdb exists */
+-        return nssdir;
+-    } else {
+-        /* either $HOME/.pki or $HOME/.pki/nssdb does not exist */
++    /* verify it exists */
++    if (!testdir(nssdir)) {
+         PORT_Free(nssdir);
+-    }
+-    int size = 0;
+-    char *xdguserdatadir = PR_GetEnvSecure("XDG_DATA_HOME");
+-    if (xdguserdatadir) {
+-        size = strlen(xdguserdatadir);
+-    } else {
+-        size = strlen(userdir) + sizeof(XDG_NSS_USER_PATH1) + sizeof(XDG_NSS_USER_PATH2);
+-    }
+-    size += sizeof(XDG_NSS_USER_PATH3) + sizeof(NSS_USER_PATH2);
+-
+-    nssdir = PORT_Alloc(size);
+-    if (nssdir == NULL) {
+         return NULL;
+     }
+-
+-    if (xdguserdatadir) {
+-        PORT_Strcpy(nssdir, xdguserdatadir);
+-        if (!testdir(nssdir)) {
+-            PORT_Free(nssdir);
+-            return NULL;
+-        }
+-
+-    } else {
+-        PORT_Strcpy(nssdir, userdir);
+-        if (appendDirAndCreate(nssdir, XDG_NSS_USER_PATH1, 0755) ||
+-            appendDirAndCreate(nssdir, XDG_NSS_USER_PATH2, 0755)) {
+-            PORT_Free(nssdir);
+-            return NULL;
+-        }
++    PORT_Strcat(nssdir, NSS_USER_PATH1);
++    if (!testdir(nssdir) && mkdir(nssdir, 0760)) {
++        PORT_Free(nssdir);
++        return NULL;
+     }
+-    /* ${XDG_DATA_HOME:-$HOME/.local/share}/pki/nssdb */
+-    if (appendDirAndCreate(nssdir, XDG_NSS_USER_PATH3, 0760) ||
+-        appendDirAndCreate(nssdir, NSS_USER_PATH2, 0760)) {
++    PORT_Strcat(nssdir, NSS_USER_PATH2);
++    if (!testdir(nssdir) && mkdir(nssdir, 0760)) {
+         PORT_Free(nssdir);
+         return NULL;
+     }
diff --git a/SPECS/nss.spec b/SPECS/nss.spec
index ddbb575..194c7ac 100644
--- a/SPECS/nss.spec
+++ b/SPECS/nss.spec
@@ -1,12 +1,14 @@
-%global nspr_version 4.20.0
-%global nss_version 3.41.0
+%global nspr_version 4.21.0
+%global nss_version 3.44.0
 %global unsupported_tools_directory %{_libdir}/nss/unsupported-tools
 %global saved_files_dir %{_libdir}/nss/saved
-%global prelink_conf_dir %{_sysconfdir}/prelink.conf.d/
 %global dracutlibdir %{_prefix}/lib/dracut
 %global dracut_modules_dir %{dracutlibdir}/modules.d/05nss-softokn/
 %global dracut_conf_dir %{dracutlibdir}/dracut.conf.d
 
+# The timestamp of our downstream manual pages, e.g., nss-config.1
+%global manual_date "Nov 13 2013"
+
 %bcond_without tests
 
 # Produce .chk files for the final stripped binaries
@@ -44,7 +46,7 @@ rpm.define(string.format("nss_release_tag NSS_%s_RTM",
 Summary:          Network Security Services
 Name:             nss
 Version:          %{nss_version}
-Release:          5%{?dist}
+Release:          7%{?dist}
 License:          MPLv2.0
 URL:              http://www.mozilla.org/projects/security/pki/nss/
 Requires:         nspr >= %{nspr_version}
@@ -70,7 +72,6 @@ Source1:          nss-util.pc.in
 Source2:          nss-util-config.in
 Source3:          nss-softokn.pc.in
 Source4:          nss-softokn-config.in
-Source5:          nss-softokn-prelink.conf
 Source6:          nss-softokn-dracut-module-setup.sh
 Source7:          nss-softokn-dracut.conf
 Source8:          nss.pc.in
@@ -91,11 +92,14 @@ Source25:         key3.db.xml
 Source26:         key4.db.xml
 Source27:         secmod.db.xml
 Source28:         nss-p11-kit.config
+Source29:         nss-softokn-cavs-1.0.tar.gz
 
 # To inject hardening flags for DSO
 Patch1:           nss-dso-ldflags.patch
 # Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=617723
 Patch2:           nss-539183.patch
+# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1549382
+Patch3:           nss-module-leak.patch
 # This patch uses the GCC -iquote option documented at
 # http://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html#Directory-Options
 # to give the in-tree headers a higher priority over the system headers,
@@ -108,17 +112,41 @@ Patch2:           nss-539183.patch
 # Once the buildroot aha been bootstrapped the patch may be removed
 # but it doesn't hurt to keep it.
 Patch4:           iquote.patch
-# Local patch for enabling FIPS when the system is in FIPS mode:
-# https://bugzilla.redhat.com/show_bug.cgi?id=852023
-Patch55:          enable-fips-when-system-is-in-fips-mode.patch
+# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1552767
+Patch5:           nss-skip-tls13-fips.patch
+# TLS 1.3 currently doesn't work under FIPS mode:
+# https://bugzilla.redhat.com/show_bug.cgi?id=1710372
+Patch6:           nss-fips-disable-tls13.patch
+# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1552208
+Patch7:           nss-disable-pkcs1-sigalgs-tls13.patch
+# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1553443
+Patch8:           nss-post-handshake-auth-with-tickets.patch
+# To revert the change in:
+# https://bugzilla.mozilla.org/show_bug.cgi?id=818686
+Patch9:		  nss-sysinit-userdb.patch
+# Disable nss-sysinit test which is sorely to test the above change
+Patch10:	  nss-skip-sysinit-gtests.patch
+# Upstream patch didn't make 3.44
+# https://bugzilla.mozilla.org/show_bug.cgi?id=1546229
+Patch200:         nss-ike-patch.patch
+# https://bugzilla.mozilla.org/show_bug.cgi?id=1546477
+Patch201:         nss-softokn-fips-update.patch
 # Local patch for TLS_ECDHE_{ECDSA|RSA}_WITH_3DES_EDE_CBC_SHA ciphers
 Patch58:          rhbz1185708-enable-ecc-3des-ciphers-by-default.patch
-# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1493936
-Patch129:         nss-dsa.patch
-# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1496124
-Patch150:         nss-3.39-create-public-key-on-private-import.patch
-# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1513909
-Patch151:         nss-manpage-fixes.patch
+# https://bugzilla.mozilla.org/show_bug.cgi?id=1473806
+Patch202:         nss-8-fix-public-key-from-priv.patch
+Patch204:         nss-8-add-ipsec-usage-to-manpage.patch
+# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1560329
+Patch205:         nss-drbg-continuous.patch
+# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1559906
+Patch206:         nss-fipstest-tls12-prf.patch
+# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1554336
+Patch210:         nss-mpi-loop.patch
+# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1540541
+Patch211:         nss-leading-zero.patch
+# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1515342
+Patch212:         nss-input-check.patch
+
 
 %description
 Network Security Services (NSS) is a set of libraries designed to
@@ -213,7 +241,6 @@ Requires:         nspr >= 4.12
 # For NSS_SecureMemcmpZero() from nss-util >= 3.33
 Requires:         nss-util >= 3.33
 Conflicts:        nss < 3.12.2.99.3-5
-Conflicts:        prelink < 0.4.3
 Conflicts:        filesystem < 3
 
 %description softokn-freebl
@@ -247,11 +274,15 @@ Header and library files for doing development with Network Security Services.
 
 
 %prep
-%setup -q -n %{name}-%{nss_archive_version}
+#autosetup -N -S quilt -n %{name}-%{nss_archive_version}
+%autosetup -N -n %{name}-%{nss_archive_version} -a 29
 pushd nss
 %autopatch -p1
 popd
 
+# https://bugzilla.redhat.com/show_bug.cgi?id=1247353
+find nss/lib/libpkix -perm /u+x -type f -exec chmod -x {} \;
+
 
 %build
 
@@ -292,6 +323,8 @@ export NSS_USE_SYSTEM_SQLITE=1
 
 export NSS_ALLOW_SSLKEYLOGFILE=1
 
+export NSS_SEED_ONLY_DEV_URANDOM=1
+
 %ifnarch noarch
 %if 0%{__isa_bits} == 64
 export USE_64=1
@@ -311,8 +344,12 @@ export POLICY_PATH="/etc/crypto-policies/back-ends"
 make -C ./nss
 
 # build the man pages clean
-pushd ./nss
-make clean_docs build_docs
+pushd ./nss/doc
+rm -rf ./nroff
+make clean
+echo -n %{manual_date} > date.xml
+echo -n %{version} > version.xml
+make
 popd
 
 # and copy them to the dist directory for %%install to find them
@@ -493,35 +530,6 @@ pushd nss/tests
 HOST=localhost DOMSUF=localdomain PORT=$MYRAND NSS_CYCLES=%{?nss_cycles} NSS_TESTS=%{?nss_tests} NSS_SSL_TESTS=%{?nss_ssl_tests} NSS_SSL_RUN=%{?nss_ssl_run} ./all.sh
 popd
 
-# Normally, the grep exit status is 0 if selected lines are found and 1 otherwise,
-# Grep exits with status greater than 1 if an error ocurred.
-# If there are test failures we expect TEST_FAILURES > 0 and GREP_EXIT_STATUS = 0,
-# With no test failures we expect TEST_FAILURES = 0 and GREP_EXIT_STATUS = 1, whereas
-# GREP_EXIT_STATUS > 1 would indicate an error in grep such as failure to find the log file.
-killall $RANDSERV || :
-
-TEST_FAILURES=$(grep -c -- '- FAILED$' ./tests_results/security/localhost.1/output.log) || GREP_EXIT_STATUS=$?
-
-if [ ${GREP_EXIT_STATUS:-0} -eq 1 ]; then
-  echo "okay: test suite detected no failures"
-else
-  if [ ${GREP_EXIT_STATUS:-0} -eq 0 ]; then
-    # while a situation in which grep return status is 0 and it doesn't output
-    # anything shouldn't happen, set the default to something that is
-    # obviously wrong (-1)
-    echo "error: test suite had ${TEST_FAILURES:--1} test failure(s)"
-    exit 1
-  else
-    if [ ${GREP_EXIT_STATUS:-0} -eq 2 ]; then
-      echo "error: grep has not found log file"
-      exit 1
-    else
-      echo "error: grep failed with exit code: ${GREP_EXIT_STATUS}"
-      exit 1
-    fi
-  fi
-fi
-echo "test suite completed"
 %endif
 
 %install
@@ -535,7 +543,6 @@ mkdir -p $RPM_BUILD_ROOT/%{_libdir}
 mkdir -p $RPM_BUILD_ROOT/%{unsupported_tools_directory}
 mkdir -p $RPM_BUILD_ROOT/%{_libdir}/pkgconfig
 mkdir -p $RPM_BUILD_ROOT/%{saved_files_dir}
-mkdir -p $RPM_BUILD_ROOT/%{prelink_conf_dir}
 mkdir -p $RPM_BUILD_ROOT/%{dracut_modules_dir}
 mkdir -p $RPM_BUILD_ROOT/%{dracut_conf_dir}
 mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/crypto-policies/local.d
@@ -546,7 +553,6 @@ mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/crypto-policies/local.d
 mkdir -p $RPM_BUILD_ROOT%{_datadir}/doc/nss-tools
 %endif
 
-install -m 644 %{SOURCE5} $RPM_BUILD_ROOT/%{prelink_conf_dir}
 install -m 755 %{SOURCE6} $RPM_BUILD_ROOT/%{dracut_modules_dir}/module-setup.sh
 install -m 644 %{SOURCE7} $RPM_BUILD_ROOT/%{dracut_conf_dir}/50-nss-softokn.conf
 
@@ -657,10 +663,10 @@ install -p -m 644 %{SOURCE28} $RPM_BUILD_ROOT/%{_sysconfdir}/crypto-policies/loc
 /usr/bin/setup-nsssysinit.sh on
 
 %post
-update-crypto-policies --no-reload
+update-crypto-policies --no-reload &> /dev/null || :
 
 %postun
-update-crypto-policies --no-reload
+update-crypto-policies --no-reload &> /dev/null || :
 
 
 %files
@@ -880,8 +886,6 @@ update-crypto-policies --no-reload
 %{_libdir}/libfreeblpriv3.so
 %{_libdir}/libfreeblpriv3.chk
 #shared
-%dir %{prelink_conf_dir}
-%{prelink_conf_dir}/nss-softokn-prelink.conf
 %dir %{dracut_modules_dir}
 %{dracut_modules_dir}/module-setup.sh
 %{dracut_conf_dir}/50-nss-softokn.conf
@@ -915,6 +919,43 @@ update-crypto-policies --no-reload
 
 
 %changelog
+* Wed Jul  3 2019 Daiki Ueno <dueno@redhat.com> - 3.44.0-7
+- Backport fixes from 3.44.1
+
+* Wed Jun 26 2019 Daiki Ueno <dueno@redhat.com> - 3.44.0-6
+- Add continuous RNG test required by FIPS
+- fipstest: use CKM_TLS12_MASTER_KEY_DERIVE instead of vendor specific mechanism
+
+* Mon Jun 10 2019 Daiki Ueno <dueno@redhat.com> - 3.44.0-5
+- Rebuild with the correct build target
+
+*Fri Jun 7 2019 Bob Relyea <rrelyea@redhat.com> - 3.44.0-4.1
+- rebuild to try to retrigger CI tests
+
+*Wed Jun 5 2019 Bob Relyea <rrelyea@redhat.com> - 3.44.0-4
+- Fix certutil man page
+- Fix extracting a public key from a private key for dh, ec, and dsa
+
+* Thu May 30 2019 Daiki Ueno <dueno@redhat.com> - 3.44.0-3
+- Disable TLS 1.3 under FIPS mode
+- Disable RSASSA-PKCS1-v1_5 in TLS 1.3
+- Fix post-handshake auth transcript calculation if
+  SSL_ENABLE_SESSION_TICKETS is set
+- Revert the change to use XDG basedirs (mozilla#818686)
+
+* Fri May 24 2019 Bob Relyea <rrelyea@redhat.com> - 3.44.0-2
+- Add ike mechanisms in softokn
+- Add FIPS checks in softoken
+
+* Fri May 24 2019 Daiki Ueno <dueno@redhat.com> - 3.44.0-1
+- Update to NSS 3.44
+- Define NSS_SEED_ONLY_DEV_URANDOM=1 to exclusively use getentropy
+- Use %%autosetup
+- Clean up manual pages generation
+- Clean up %%check
+- Remove prelink dependency, which is not available in RHEL-8
+- Remove upstreamed patches
+
 * Mon Dec 17 2018 Daiki Ueno <dueno@redhat.com> - 3.41.0-5
 - Update manual pages to reflect recent changes in commands