Bug 1550889 - land NSS d17569aa9d56 UPGRADE_NSS_RELEASE, r=me
authorJ.C. Jones <jc@mozilla.com>
Fri, 07 Jun 2019 17:51:08 +0000
changeset 537592 3906116736820329110a4b81a15088e353267f56
parent 537591 aaaad6b92dcde51784d7146efbf9a6ea78a6c92c
child 537593 461450502164ef7361927cddeb520e52d8bbae5d
push id11522
push userffxbld-merge
push dateMon, 01 Jul 2019 09:00:55 +0000
treeherdermozilla-beta@53ea74d2bd09 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1550889
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1550889 - land NSS d17569aa9d56 UPGRADE_NSS_RELEASE, r=me
security/nss/.taskcluster.yml
security/nss/TAG-INFO
security/nss/automation/taskcluster/docker-fuzz/Dockerfile
security/nss/automation/taskcluster/graph/src/extend.js
security/nss/automation/taskcluster/graph/src/index.js
security/nss/automation/taskcluster/graph/src/queue.js
security/nss/automation/taskcluster/graph/src/try_syntax.js
security/nss/automation/taskcluster/scripts/check_abi.sh
security/nss/automation/taskcluster/scripts/run_coverity.sh
security/nss/cmd/fipstest/README
security/nss/cmd/fipstest/aes.sh
security/nss/cmd/fipstest/aesgcm.sh
security/nss/cmd/fipstest/dsa.sh
security/nss/cmd/fipstest/ecdsa.sh
security/nss/cmd/fipstest/fipstest.c
security/nss/cmd/fipstest/hmac.sh
security/nss/cmd/fipstest/kas.sh
security/nss/cmd/fipstest/rng.sh
security/nss/cmd/fipstest/rsa.sh
security/nss/cmd/fipstest/runtest.sh
security/nss/cmd/fipstest/sha.sh
security/nss/cmd/fipstest/tdea.sh
security/nss/cmd/fipstest/tls.sh
security/nss/cmd/fipstest/validate.sh
security/nss/cmd/fipstest/validate1.sh
security/nss/coreconf/coreconf.dep
security/nss/doc/certutil.xml
security/nss/gtests/pk11_gtest/pk11_import_unittest.cc
security/nss/lib/cryptohi/seckey.c
security/nss/lib/freebl/freebl.gyp
security/nss/lib/pk11wrap/pk11mech.c
security/nss/lib/pk11wrap/pk11priv.h
security/nss/lib/pk11wrap/pk11skey.c
security/nss/lib/softoken/fipstest.c
security/nss/lib/softoken/lowkey.c
security/nss/lib/softoken/manifest.mn
security/nss/lib/softoken/pkcs11.c
security/nss/lib/softoken/pkcs11c.c
security/nss/lib/softoken/pkcs11i.h
security/nss/lib/softoken/pkcs11u.c
security/nss/lib/softoken/sftkike.c
security/nss/lib/softoken/softoken.gyp
security/nss/lib/ssl/sslt.h
security/nss/lib/util/pkcs11n.h
security/nss/lib/util/pkcs11t.h
security/nss/mach
security/nss/nss.gyp
security/nss/tests/common/init.sh
security/nss/tests/fips/cavs_samples/AES/fax/CBCGFSbox128.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCGFSbox192.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCGFSbox256.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCKeySbox128.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCKeySbox192.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCKeySbox256.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCMCT128.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCMCT192.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCMCT256.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCMMT128.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCMMT192.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCMMT256.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCVarKey128.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCVarKey192.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCVarKey256.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCVarTxt128.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCVarTxt192.fax
security/nss/tests/fips/cavs_samples/AES/fax/CBCVarTxt256.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBGFSbox128.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBGFSbox192.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBGFSbox256.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBKeySbox128.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBKeySbox192.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBKeySbox256.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBMCT128.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBMCT192.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBMCT256.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBMMT128.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBMMT192.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBMMT256.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBVarKey128.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBVarKey192.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBVarKey256.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBVarTxt128.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBVarTxt192.fax
security/nss/tests/fips/cavs_samples/AES/fax/ECBVarTxt256.fax
security/nss/tests/fips/cavs_samples/AES/req/CBCGFSbox128.req
security/nss/tests/fips/cavs_samples/AES/req/CBCGFSbox192.req
security/nss/tests/fips/cavs_samples/AES/req/CBCGFSbox256.req
security/nss/tests/fips/cavs_samples/AES/req/CBCKeySbox128.req
security/nss/tests/fips/cavs_samples/AES/req/CBCKeySbox192.req
security/nss/tests/fips/cavs_samples/AES/req/CBCKeySbox256.req
security/nss/tests/fips/cavs_samples/AES/req/CBCMCT128.req
security/nss/tests/fips/cavs_samples/AES/req/CBCMCT192.req
security/nss/tests/fips/cavs_samples/AES/req/CBCMCT256.req
security/nss/tests/fips/cavs_samples/AES/req/CBCMMT128.req
security/nss/tests/fips/cavs_samples/AES/req/CBCMMT192.req
security/nss/tests/fips/cavs_samples/AES/req/CBCMMT256.req
security/nss/tests/fips/cavs_samples/AES/req/CBCVarKey128.req
security/nss/tests/fips/cavs_samples/AES/req/CBCVarKey192.req
security/nss/tests/fips/cavs_samples/AES/req/CBCVarKey256.req
security/nss/tests/fips/cavs_samples/AES/req/CBCVarTxt128.req
security/nss/tests/fips/cavs_samples/AES/req/CBCVarTxt192.req
security/nss/tests/fips/cavs_samples/AES/req/CBCVarTxt256.req
security/nss/tests/fips/cavs_samples/AES/req/ECBGFSbox128.req
security/nss/tests/fips/cavs_samples/AES/req/ECBGFSbox192.req
security/nss/tests/fips/cavs_samples/AES/req/ECBGFSbox256.req
security/nss/tests/fips/cavs_samples/AES/req/ECBKeySbox128.req
security/nss/tests/fips/cavs_samples/AES/req/ECBKeySbox192.req
security/nss/tests/fips/cavs_samples/AES/req/ECBKeySbox256.req
security/nss/tests/fips/cavs_samples/AES/req/ECBMCT128.req
security/nss/tests/fips/cavs_samples/AES/req/ECBMCT192.req
security/nss/tests/fips/cavs_samples/AES/req/ECBMCT256.req
security/nss/tests/fips/cavs_samples/AES/req/ECBMMT128.req
security/nss/tests/fips/cavs_samples/AES/req/ECBMMT192.req
security/nss/tests/fips/cavs_samples/AES/req/ECBMMT256.req
security/nss/tests/fips/cavs_samples/AES/req/ECBVarKey128.req
security/nss/tests/fips/cavs_samples/AES/req/ECBVarKey192.req
security/nss/tests/fips/cavs_samples/AES/req/ECBVarKey256.req
security/nss/tests/fips/cavs_samples/AES/req/ECBVarTxt128.req
security/nss/tests/fips/cavs_samples/AES/req/ECBVarTxt192.req
security/nss/tests/fips/cavs_samples/AES/req/ECBVarTxt256.req
security/nss/tests/fips/cavs_samples/AES/sample/CBCGFSbox128.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCGFSbox192.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCGFSbox256.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCKeySbox128.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCKeySbox192.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCKeySbox256.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCMCT128.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCMCT192.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCMCT256.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCMMT128.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCMMT192.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCMMT256.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCVarKey128.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCVarKey192.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCVarKey256.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCVarTxt128.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCVarTxt192.sam
security/nss/tests/fips/cavs_samples/AES/sample/CBCVarTxt256.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBGFSbox128.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBGFSbox192.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBGFSbox256.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBKeySbox128.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBKeySbox192.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBKeySbox256.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBMCT128.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBMCT192.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBMCT256.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBMMT128.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBMMT192.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBMMT256.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBVarKey128.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBVarKey192.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBVarKey256.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBVarTxt128.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBVarTxt192.sam
security/nss/tests/fips/cavs_samples/AES/sample/ECBVarTxt256.sam
security/nss/tests/fips/cavs_samples/AES_GCM/fax/gcmDecrypt128.fax
security/nss/tests/fips/cavs_samples/AES_GCM/fax/gcmDecrypt192.fax
security/nss/tests/fips/cavs_samples/AES_GCM/fax/gcmDecrypt256.fax
security/nss/tests/fips/cavs_samples/AES_GCM/fax/gcmEncryptExtIV128.fax
security/nss/tests/fips/cavs_samples/AES_GCM/fax/gcmEncryptExtIV192.fax
security/nss/tests/fips/cavs_samples/AES_GCM/fax/gcmEncryptExtIV256.fax
security/nss/tests/fips/cavs_samples/AES_GCM/req/gcmDecrypt128.req
security/nss/tests/fips/cavs_samples/AES_GCM/req/gcmDecrypt192.req
security/nss/tests/fips/cavs_samples/AES_GCM/req/gcmDecrypt256.req
security/nss/tests/fips/cavs_samples/AES_GCM/req/gcmEncryptExtIV128.req
security/nss/tests/fips/cavs_samples/AES_GCM/req/gcmEncryptExtIV192.req
security/nss/tests/fips/cavs_samples/AES_GCM/req/gcmEncryptExtIV256.req
security/nss/tests/fips/cavs_samples/AES_GCM/sample/gcmDecrypt128.sam
security/nss/tests/fips/cavs_samples/AES_GCM/sample/gcmDecrypt192.sam
security/nss/tests/fips/cavs_samples/AES_GCM/sample/gcmDecrypt256.sam
security/nss/tests/fips/cavs_samples/AES_GCM/sample/gcmEncryptExtIV128.sam
security/nss/tests/fips/cavs_samples/AES_GCM/sample/gcmEncryptExtIV192.sam
security/nss/tests/fips/cavs_samples/AES_GCM/sample/gcmEncryptExtIV256.sam
security/nss/tests/fips/cavs_samples/DRBG800-90A/fax/Hash_DRBG.fax
security/nss/tests/fips/cavs_samples/DRBG800-90A/req/Hash_DRBG.req
security/nss/tests/fips/cavs_samples/DRBG800-90A/sample/Hash_DRBG.sam
security/nss/tests/fips/cavs_samples/DSA2/fax/KeyPair.fax
security/nss/tests/fips/cavs_samples/DSA2/fax/PQGGen.fax
security/nss/tests/fips/cavs_samples/DSA2/fax/PQGVer1863.fax
security/nss/tests/fips/cavs_samples/DSA2/fax/SigGen.fax
security/nss/tests/fips/cavs_samples/DSA2/fax/SigVer.fax
security/nss/tests/fips/cavs_samples/DSA2/req/KeyPair.req
security/nss/tests/fips/cavs_samples/DSA2/req/PQGGen.req
security/nss/tests/fips/cavs_samples/DSA2/req/PQGVer1863.req
security/nss/tests/fips/cavs_samples/DSA2/req/SigGen.req
security/nss/tests/fips/cavs_samples/DSA2/req/SigVer.req
security/nss/tests/fips/cavs_samples/DSA2/sample/KeyPair.sam
security/nss/tests/fips/cavs_samples/DSA2/sample/PQGVer1863.sam
security/nss/tests/fips/cavs_samples/DSA2/sample/SigGen.sam
security/nss/tests/fips/cavs_samples/DSA2/sample/SigVer.sam
security/nss/tests/fips/cavs_samples/ECDSA2/fax/KeyPair.fax
security/nss/tests/fips/cavs_samples/ECDSA2/fax/PKV.fax
security/nss/tests/fips/cavs_samples/ECDSA2/fax/SigGen.fax
security/nss/tests/fips/cavs_samples/ECDSA2/fax/SigVer.fax
security/nss/tests/fips/cavs_samples/ECDSA2/req/KeyPair.req
security/nss/tests/fips/cavs_samples/ECDSA2/req/PKV.req
security/nss/tests/fips/cavs_samples/ECDSA2/req/SigGen.req
security/nss/tests/fips/cavs_samples/ECDSA2/req/SigVer.req
security/nss/tests/fips/cavs_samples/ECDSA2/sample/KeyPair.sam
security/nss/tests/fips/cavs_samples/ECDSA2/sample/PKV.sam
security/nss/tests/fips/cavs_samples/ECDSA2/sample/SigGen.sam
security/nss/tests/fips/cavs_samples/ECDSA2/sample/SigVer.sam
security/nss/tests/fips/cavs_samples/HMAC/fax/HMAC.fax
security/nss/tests/fips/cavs_samples/HMAC/req/HMAC.req
security/nss/tests/fips/cavs_samples/HMAC/sample/HMAC.sam
security/nss/tests/fips/cavs_samples/IKE/fax/README
security/nss/tests/fips/cavs_samples/IKE/fax/ikev1_dsa.fax
security/nss/tests/fips/cavs_samples/IKE/fax/ikev1_psk.fax
security/nss/tests/fips/cavs_samples/IKE/fax/ikev2.fax
security/nss/tests/fips/cavs_samples/IKE/req/ikev1_dsa.req
security/nss/tests/fips/cavs_samples/IKE/req/ikev1_dsa.req_orig
security/nss/tests/fips/cavs_samples/IKE/req/ikev1_psk.req
security/nss/tests/fips/cavs_samples/IKE/req/ikev2.req
security/nss/tests/fips/cavs_samples/KAS/fax/KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_init.fax
security/nss/tests/fips/cavs_samples/KAS/fax/KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.fax
security/nss/tests/fips/cavs_samples/KAS/fax/KASFunctionTest_FFCEphem_NOKC_ZZOnly_init.fax
security/nss/tests/fips/cavs_samples/KAS/fax/KASFunctionTest_FFCEphem_NOKC_ZZOnly_resp.fax
security/nss/tests/fips/cavs_samples/KAS/fax/KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.fax
security/nss/tests/fips/cavs_samples/KAS/fax/KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.fax
security/nss/tests/fips/cavs_samples/KAS/fax/KASValidityTest_FFCEphem_NOKC_ZZOnly_init.fax
security/nss/tests/fips/cavs_samples/KAS/fax/KASValidityTest_FFCEphem_NOKC_ZZOnly_resp.fax
security/nss/tests/fips/cavs_samples/KAS/req/KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req
security/nss/tests/fips/cavs_samples/KAS/req/KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req
security/nss/tests/fips/cavs_samples/KAS/req/KASFunctionTest_FFCEphem_NOKC_ZZOnly_init.req
security/nss/tests/fips/cavs_samples/KAS/req/KASFunctionTest_FFCEphem_NOKC_ZZOnly_resp.req
security/nss/tests/fips/cavs_samples/KAS/req/KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req
security/nss/tests/fips/cavs_samples/KAS/req/KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req
security/nss/tests/fips/cavs_samples/KAS/req/KASValidityTest_FFCEphem_NOKC_ZZOnly_init.req
security/nss/tests/fips/cavs_samples/KAS/req/KASValidityTest_FFCEphem_NOKC_ZZOnly_resp.req
security/nss/tests/fips/cavs_samples/KDF135/fax/tls.fax
security/nss/tests/fips/cavs_samples/KDF135/req/tls.req
security/nss/tests/fips/cavs_samples/KDF135/sample/tls.sam
security/nss/tests/fips/cavs_samples/RSA2/fax/KeyGen3_3_KAT.fax
security/nss/tests/fips/cavs_samples/RSA2/fax/KeyGen_RandomProbablyPrime3_3.fax
security/nss/tests/fips/cavs_samples/RSA2/fax/SigGen15_186-3.fax
security/nss/tests/fips/cavs_samples/RSA2/fax/SigGen931_186-3.fax
security/nss/tests/fips/cavs_samples/RSA2/fax/SigGenPSS_186-3.fax
security/nss/tests/fips/cavs_samples/RSA2/fax/SigVer15_186-3.fax
security/nss/tests/fips/cavs_samples/RSA2/fax/SigVer931_186-3.fax
security/nss/tests/fips/cavs_samples/RSA2/fax/SigVerPSS_186-3.fax
security/nss/tests/fips/cavs_samples/RSA2/req/KeyGen3_3_KAT.req
security/nss/tests/fips/cavs_samples/RSA2/req/KeyGenRSA1862.req
security/nss/tests/fips/cavs_samples/RSA2/req/KeyGen_186-3.req
security/nss/tests/fips/cavs_samples/RSA2/req/KeyGen_RandomProbablyPrime3_3.req
security/nss/tests/fips/cavs_samples/RSA2/req/SigGen15_186-3.req
security/nss/tests/fips/cavs_samples/RSA2/req/SigGen931_186-3.req
security/nss/tests/fips/cavs_samples/RSA2/req/SigGenPSS_186-3.req
security/nss/tests/fips/cavs_samples/RSA2/req/SigVer15_186-3.req
security/nss/tests/fips/cavs_samples/RSA2/req/SigVer931_186-3.req
security/nss/tests/fips/cavs_samples/RSA2/req/SigVerPSS_186-3.req
security/nss/tests/fips/cavs_samples/RSA2/sample/SigGen15_186-3.sam
security/nss/tests/fips/cavs_samples/RSA2/sample/SigVer15_186-3.sam
security/nss/tests/fips/cavs_samples/SHA/fax/SHA1LongMsg.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA1Monte.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA1ShortMsg.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA224LongMsg.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA224Monte.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA224ShortMsg.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA256LongMsg.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA256Monte.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA256ShortMsg.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA384LongMsg.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA384Monte.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA384ShortMsg.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA512LongMsg.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA512Monte.fax
security/nss/tests/fips/cavs_samples/SHA/fax/SHA512ShortMsg.fax
security/nss/tests/fips/cavs_samples/SHA/req/SHA1LongMsg.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA1Monte.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA1ShortMsg.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA224LongMsg.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA224Monte.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA224ShortMsg.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA256LongMsg.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA256Monte.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA256ShortMsg.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA384LongMsg.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA384Monte.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA384ShortMsg.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA512LongMsg.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA512Monte.req
security/nss/tests/fips/cavs_samples/SHA/req/SHA512ShortMsg.req
security/nss/tests/fips/cavs_samples/SHA/sample/SHA1LongMsg.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA1Monte.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA1ShortMsg.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA224LongMsg.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA224Monte.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA224ShortMsg.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA256LongMsg.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA256Monte.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA256ShortMsg.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA384LongMsg.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA384Monte.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA384ShortMsg.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA512LongMsg.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA512Monte.sam
security/nss/tests/fips/cavs_samples/SHA/sample/SHA512ShortMsg.sam
security/nss/tests/fips/cavs_samples/TDES/fax/TCBCMMT1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCBCMMT2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCBCMMT3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCBCMonte1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCBCMonte2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCBCMonte3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCBCinvperm.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCBCpermop.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCBCsubtab.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCBCvarkey.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCBCvartext.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB1MMT1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB1MMT2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB1MMT3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB1Monte1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB1Monte2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB1Monte3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB1invperm.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB1permop.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB1subtab.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB1varkey.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB1vartext.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB64MMT1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB64MMT2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB64MMT3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB64Monte1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB64Monte2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB64Monte3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB64invperm.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB64permop.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB64subtab.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB64varkey.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB64vartext.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB8MMT1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB8MMT2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB8MMT3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB8Monte1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB8Monte2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB8Monte3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB8invperm.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB8permop.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB8subtab.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB8varkey.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TCFB8vartext.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TECBMMT1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TECBMMT2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TECBMMT3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TECBMonte1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TECBMonte2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TECBMonte3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TECBinvperm.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TECBpermop.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TECBsubtab.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TECBvarkey.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TECBvartext.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TOFBMMT1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TOFBMMT2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TOFBMMT3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TOFBMonte1.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TOFBMonte2.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TOFBMonte3.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TOFBinvperm.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TOFBpermop.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TOFBsubtab.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TOFBvarkey.fax
security/nss/tests/fips/cavs_samples/TDES/fax/TOFBvartext.fax
security/nss/tests/fips/cavs_samples/TDES/req/TCBCMMT1.req
security/nss/tests/fips/cavs_samples/TDES/req/TCBCMMT2.req
security/nss/tests/fips/cavs_samples/TDES/req/TCBCMMT3.req
security/nss/tests/fips/cavs_samples/TDES/req/TCBCMonte1.req
security/nss/tests/fips/cavs_samples/TDES/req/TCBCMonte2.req
security/nss/tests/fips/cavs_samples/TDES/req/TCBCMonte3.req
security/nss/tests/fips/cavs_samples/TDES/req/TCBCinvperm.req
security/nss/tests/fips/cavs_samples/TDES/req/TCBCpermop.req
security/nss/tests/fips/cavs_samples/TDES/req/TCBCsubtab.req
security/nss/tests/fips/cavs_samples/TDES/req/TCBCvarkey.req
security/nss/tests/fips/cavs_samples/TDES/req/TCBCvartext.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB1MMT1.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB1MMT2.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB1MMT3.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB1Monte1.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB1Monte2.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB1Monte3.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB1invperm.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB1permop.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB1subtab.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB1varkey.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB1vartext.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB64MMT1.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB64MMT2.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB64MMT3.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB64Monte1.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB64Monte2.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB64Monte3.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB64invperm.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB64permop.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB64subtab.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB64varkey.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB64vartext.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB8MMT1.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB8MMT2.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB8MMT3.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB8Monte1.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB8Monte2.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB8Monte3.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB8invperm.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB8permop.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB8subtab.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB8varkey.req
security/nss/tests/fips/cavs_samples/TDES/req/TCFB8vartext.req
security/nss/tests/fips/cavs_samples/TDES/req/TECBMMT1.req
security/nss/tests/fips/cavs_samples/TDES/req/TECBMMT2.req
security/nss/tests/fips/cavs_samples/TDES/req/TECBMMT3.req
security/nss/tests/fips/cavs_samples/TDES/req/TECBMonte1.req
security/nss/tests/fips/cavs_samples/TDES/req/TECBMonte2.req
security/nss/tests/fips/cavs_samples/TDES/req/TECBMonte3.req
security/nss/tests/fips/cavs_samples/TDES/req/TECBinvperm.req
security/nss/tests/fips/cavs_samples/TDES/req/TECBpermop.req
security/nss/tests/fips/cavs_samples/TDES/req/TECBsubtab.req
security/nss/tests/fips/cavs_samples/TDES/req/TECBvarkey.req
security/nss/tests/fips/cavs_samples/TDES/req/TECBvartext.req
security/nss/tests/fips/cavs_samples/TDES/req/TOFBMMT1.req
security/nss/tests/fips/cavs_samples/TDES/req/TOFBMMT2.req
security/nss/tests/fips/cavs_samples/TDES/req/TOFBMMT3.req
security/nss/tests/fips/cavs_samples/TDES/req/TOFBMonte1.req
security/nss/tests/fips/cavs_samples/TDES/req/TOFBMonte2.req
security/nss/tests/fips/cavs_samples/TDES/req/TOFBMonte3.req
security/nss/tests/fips/cavs_samples/TDES/req/TOFBinvperm.req
security/nss/tests/fips/cavs_samples/TDES/req/TOFBpermop.req
security/nss/tests/fips/cavs_samples/TDES/req/TOFBsubtab.req
security/nss/tests/fips/cavs_samples/TDES/req/TOFBvarkey.req
security/nss/tests/fips/cavs_samples/TDES/req/TOFBvartext.req
security/nss/tests/fips/cavs_samples/TDES/sample/TCBCMMT2.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TCBCMMT3.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TCBCMonte2.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TCBCMonte3.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TCBCinvperm.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TCBCpermop.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TCBCsubtab.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TCBCvarkey.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TCBCvartext.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TECBMMT2.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TECBMMT3.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TECBMonte2.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TECBMonte3.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TECBinvperm.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TECBpermop.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TECBsubtab.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TECBvarkey.sam
security/nss/tests/fips/cavs_samples/TDES/sample/TECBvartext.sam
security/nss/tests/fips/cavs_scripts/README
security/nss/tests/fips/cavs_scripts/aes.sh
security/nss/tests/fips/cavs_scripts/aesgcm.sh
security/nss/tests/fips/cavs_scripts/dsa.sh
security/nss/tests/fips/cavs_scripts/ecdsa.sh
security/nss/tests/fips/cavs_scripts/hmac.sh
security/nss/tests/fips/cavs_scripts/ike.sh
security/nss/tests/fips/cavs_scripts/kas.sh
security/nss/tests/fips/cavs_scripts/rng.sh
security/nss/tests/fips/cavs_scripts/rsa.sh
security/nss/tests/fips/cavs_scripts/runtest.sh
security/nss/tests/fips/cavs_scripts/sha.sh
security/nss/tests/fips/cavs_scripts/tdea.sh
security/nss/tests/fips/cavs_scripts/tls.sh
security/nss/tests/fips/cavs_scripts/validate.sh
security/nss/tests/fips/cavs_scripts/validate1.sh
security/nss/tests/fips/fips.sh
--- a/security/nss/.taskcluster.yml
+++ b/security/nss/.taskcluster.yml
@@ -16,20 +16,22 @@ tasks:
         $if: '"@" in push.owner'
         then: '${push.owner}'
         else: '${push.owner}@noreply.mozilla.org'
       # ensure there's no trailing `/` on the repo URL
       repoUrl:
         $if: 'repository.url[-1] == "/"'
         then: {$eval: 'repository.url[:-1]'}
         else: {$eval: 'repository.url'}
+      # scheduler id
+      schedulerId: 'nss-level-${repository.level}'
     in:
       taskId: '${ownTaskId}'
       taskGroupId: '${ownTaskId}'
-      schedulerId: 'nss-level-${repository.level}'
+      schedulerId: '${schedulerId}'
       created: {$fromNow: ''}
       deadline: {$fromNow: '1 day'}
       expires: {$fromNow: '14 days'}
 
       metadata:
         owner: mozilla-taskcluster-maintenance@mozilla.com
         source: "${repository.url}"
         name: "NSS Decision Task"
@@ -51,16 +53,17 @@ tasks:
       payload:
         # TODO: use nssdev org , not djmitche, once the image is pushed there
         image: djmitche/nss-decision:0.0.3
 
         env:
           TC_OWNER: "${push.owner}"
           TC_SOURCE: "${repository.url}"
           TC_PROJECT: ${repository.project}
+          TC_SCHEDULER_ID: "${schedulerId}"
           NSS_PUSHLOG_ID: '${push.pushlog_id}'
           NSS_HEAD_REPOSITORY: '${repository.url}'
           NSS_HEAD_REVISION: '${push.revision}'
 
         maxRunTime: 1800
 
         command:
           - bash
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-8082be3a6363
+d17569aa9d56
--- a/security/nss/automation/taskcluster/docker-fuzz/Dockerfile
+++ b/security/nss/automation/taskcluster/docker-fuzz/Dockerfile
@@ -1,13 +1,13 @@
 # Dockerfile for running fuzzing tests.
-#
+# Used for ASAN and Coverity based static-analysis.
 # Note that when running this, you need to add `--cap-add SYS_PTRACE` to the
 # docker invocation or ASAN won't work.
-# On taskcluster use `features: ["allowPtrace"]`.
+# On taskcluster for ASAN use `features: ["allowPtrace"]`.
 # See https://github.com/google/sanitizers/issues/764#issuecomment-276700920
 FROM ubuntu:18.04
 LABEL maintainer="Martin Thomson <martin.thomson@gmail.com>"
 
 RUN dpkg --add-architecture i386
 RUN apt-get update \
  && apt-get install -y --no-install-recommends \
     build-essential \
@@ -23,20 +23,22 @@ RUN apt-get update \
     libxml2-utils \
     lib32z1-dev \
     linux-libc-dev:i386 \
     llvm-dev \
     locales \
     mercurial \
     ninja-build \
     pkg-config \
+    python-pip \
     valgrind \
     zlib1g-dev \
  && rm -rf /var/lib/apt/lists/* \
- && apt-get autoremove -y && apt-get clean -y
+ && apt-get autoremove -y && apt-get clean -y \
+ && pip install requests
 
 ENV SHELL /bin/bash
 ENV USER worker
 ENV LOGNAME $USER
 ENV HOME /home/$USER
 ENV LANG en_US.UTF-8
 ENV LC_ALL $LANG
 ENV HOST localhost
--- a/security/nss/automation/taskcluster/graph/src/extend.js
+++ b/security/nss/automation/taskcluster/graph/src/extend.js
@@ -291,16 +291,20 @@ export default async function main() {
          "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh"
       ],
       collection: "make",
     })
   );
 
   await scheduleMac("Mac (opt)", {collection: "opt"}, "--opt");
   await scheduleMac("Mac (debug)", {collection: "debug"});
+
+  // Must be executed after all other tasks are scheduled
+  queue.clearFilters();
+  await scheduleCodeReview();
 }
 
 
 async function scheduleMac(name, base, args = "") {
   let mac_base = merge(base, {
     env: {
       PATH: "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin",
       NSS_TASKCLUSTER_MAC: "1",
@@ -455,17 +459,16 @@ async function scheduleLinux(name, overr
   queue.scheduleTask(merge(extra_base, {
     name: `${name} w/ clang-4`,
     env: {
       CC: "clang-4.0",
       CCC: "clang++-4.0",
     },
     symbol: "clang-4"
   }));
-
   queue.scheduleTask(merge(extra_base, {
     name: `${name} w/ gcc-4.4`,
     image: LINUX_GCC44_IMAGE,
     env: {
       USE_64: "1",
       CC: "gcc-4.4",
       CCC: "g++-4.4",
       // gcc-4.6 introduced nullptr.
@@ -1000,16 +1003,43 @@ async function scheduleTools() {
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/run_scan_build.sh"
     ]
   }));
 
   queue.scheduleTask(merge(base, {
+    symbol: "coverity",
+    name: "coverity",
+    image: FUZZ_IMAGE,
+    tags: ['code-review'],
+    env: {
+      USE_64: "1",
+      CC: "clang",
+      CCC: "clang++",
+      NSS_AUTOMATION: "1"
+    },
+    features: ["taskclusterProxy"],
+    scopes: ["secrets:get:project/relman/coverity-nss"],
+    artifacts: {
+      "public/code-review/coverity.json": {
+        expires: 24 * 7,
+        type: "file",
+        path: "/home/worker/nss/coverity/coverity.json"
+      }
+    },
+    command: [
+      "/bin/bash",
+      "-c",
+      "bin/checkout.sh && nss/automation/taskcluster/scripts/run_coverity.sh"
+    ]
+  }));
+
+  queue.scheduleTask(merge(base, {
     symbol: "hacl",
     name: "hacl",
     image: HACL_GEN_IMAGE,
     command: [
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/run_hacl.sh"
     ]
@@ -1088,8 +1118,43 @@ async function scheduleTools() {
       "/bin/bash",
       "-c",
       "bin/checkout.sh && nss/automation/taskcluster/scripts/gen_coverage_report.sh"
     ]
   }));
 
   return queue.submit();
 }
+
+async function scheduleCodeReview() {
+  let tasks = queue.taggedTasks("code-review");
+  if(! tasks) {
+    console.debug("No code review tasks, skipping ending task");
+    return
+  }
+
+  // From https://hg.mozilla.org/mozilla-central/file/tip/taskcluster/ci/code-review/kind.yml
+  queue.scheduleTask({
+    platform: "nss-tools",
+    name: "code-review-issues",
+    description: "List all issues found in static analysis and linting tasks",
+
+    // No logic on that task
+    image: LINUX_IMAGE,
+    command: ["/bin/true"],
+
+    // This task must run after all analyzer tasks are completed
+    parents: tasks,
+
+    // This option permits to run the task
+    // regardless of the analyzers tasks exit status
+    // as we are interested in the task failures
+    requires: "all-resolved",
+
+    // Publish code review trigger on pulse
+    routes: ["project.relman.codereview.v1.try_ending"],
+
+    kind: "code-review",
+    symbol: "E"
+  });
+
+  return queue.submit();
+};
--- a/security/nss/automation/taskcluster/graph/src/index.js
+++ b/security/nss/automation/taskcluster/graph/src/index.js
@@ -1,19 +1,26 @@
 /* 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/. */
 
 import * as try_syntax from "./try_syntax";
+import * as queue from "./queue";
 import extend from "./extend";
 
 const main = async () => {
   // Init try syntax filter.
   if (process.env.TC_PROJECT == "nss-try") {
     await try_syntax.initFilter();
+  } else {
+    // Coverity should not be run on landings, only by request (typically
+    // by Phabricator).
+    queue.filter(task => {
+      return task.symbol != "coverity";
+    });
   }
 
   // Extend the task graph.
   await extend();
 };
 
 main().catch(err => {
   console.error(err);
--- a/security/nss/automation/taskcluster/graph/src/queue.js
+++ b/security/nss/automation/taskcluster/graph/src/queue.js
@@ -7,16 +7,17 @@ import merge from "./merge";
 import slugid from "slugid";
 import taskcluster from "taskcluster-client";
 import * as image_builder from "./image_builder";
 
 let maps = [];
 let filters = [];
 
 let tasks = new Map();
+let tags = new Map();
 let image_tasks = new Map();
 
 let queue = new taskcluster.Queue({
   baseUrl: "http://taskcluster/queue/v1"
 });
 
 function fromNow(hours) {
   let d = new Date();
@@ -96,16 +97,19 @@ function convertTask(def) {
     NSS_HEAD_REPOSITORY: process.env.NSS_HEAD_REPOSITORY,
     NSS_HEAD_REVISION: process.env.NSS_HEAD_REVISION
   }, def.env || {});
 
   if (def.parent) {
     dependencies.push(def.parent);
     env.TC_PARENT_TASK_ID = def.parent;
   }
+  if (def.parents) {
+    dependencies = dependencies.concat(def.parents);
+  }
 
   if (def.tests) {
     env.NSS_TESTS = def.tests;
   }
 
   if (def.cycle) {
     env.NSS_CYCLES = def.cycle;
   }
@@ -127,26 +131,33 @@ function convertTask(def) {
   if (def.features) {
     payload.features = parseFeatures(def.features);
 
     if (payload.features.allowPtrace) {
       scopes.push("docker-worker:feature:allowPtrace");
     }
   }
 
+  if (def.scopes) {
+    // Need to add existing scopes in the task definition
+    scopes.push.apply(scopes, def.scopes)
+  }
+
   return {
     provisionerId: def.provisioner || "aws-provisioner-v1",
     workerType: def.workerType || "hg-worker",
-    schedulerId: "task-graph-scheduler",
+    schedulerId: process.env.TC_SCHEDULER_ID,
+    taskGroupId: process.env.TASK_ID,
 
     scopes,
     created: fromNow(0),
     deadline: fromNow(24),
 
     dependencies,
+    requires: def.requires || "all-completed",
     routes: parseRoutes(def.routes || []),
 
     metadata: {
       name: def.name,
       description: def.name,
       owner: process.env.TC_OWNER,
       source: process.env.TC_SOURCE
     },
@@ -162,16 +173,24 @@ function convertTask(def) {
 export function map(fun) {
   maps.push(fun);
 }
 
 export function filter(fun) {
   filters.push(fun);
 }
 
+export function clearFilters(fun) {
+  filters = [];
+}
+
+export function taggedTasks(tag) {
+  return tags[tag];
+}
+
 export function scheduleTask(def) {
   let taskId = slugid.v4();
   tasks.set(taskId, merge({}, def));
   return taskId;
 }
 
 export async function submit() {
   let promises = new Map();
@@ -183,16 +202,26 @@ export async function submit() {
     }
 
     // Allow changing tasks before we schedule them.
     maps.forEach(map => { task = map(merge({}, task)) });
 
     let log_id = `${task.name} @ ${task.platform}[${task.collection || "opt"}]`;
     console.log(`+ Submitting ${log_id}.`);
 
+    // Index that task for each tag specified
+    if(task.tags) {
+      task.tags.map(tag => {
+        if(!tags[tag]) {
+          tags[tag] = [];
+        }
+        tags[tag].push(taskId);
+      });
+    }
+
     let parent = task.parent;
 
     // Convert the task definition.
     task = await convertTask(task);
 
     // Convert the docker image definition.
     let image_def = task.payload.image;
     if (image_def && image_def.hasOwnProperty("path")) {
--- a/security/nss/automation/taskcluster/graph/src/try_syntax.js
+++ b/security/nss/automation/taskcluster/graph/src/try_syntax.js
@@ -50,17 +50,17 @@ function parseOptions(opts) {
   // If it's nonsense then don't run any tests.
   if (opts.unittests == "all") {
     unittests = allUnitTests;
   } else if (unittests.length == 0) {
     unittests = [];
   }
 
   // Parse tools.
-  let allTools = ["clang-format", "scan-build", "hacl", "saw", "abi", "coverage"];
+  let allTools = ["clang-format", "scan-build", "coverity", "hacl", "saw", "abi", "coverage"];
   let tools = intersect(opts.tools.split(/\s*,\s*/), allTools);
 
   // If the given value is "all" run all tools.
   // If it's nonsense then don't run any tools.
   if (opts.tools == "all") {
     tools = allTools;
   } else if (tools.length == 0) {
     tools = [];
--- a/security/nss/automation/taskcluster/scripts/check_abi.sh
+++ b/security/nss/automation/taskcluster/scripts/check_abi.sh
@@ -98,16 +98,17 @@ abi_diff()
       fi
       abidiff --hd1 $PREVDIST/public/ --hd2 $NEWDIST/public \
           $PREVDIST/*/lib/$SO $NEWDIST/*/lib/$SO \
           > ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt
       RET=$?
       cat ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt \
           | grep -v "^Functions changes summary:" \
           | grep -v "^Variables changes summary:" \
+          | sed -e 's/__anonymous_enum__[0-9]*/__anonymous_enum__/g' \
           > ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt
       rm -f ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt
 
       ABIDIFF_ERROR=$((($RET & 0x01) != 0))
       ABIDIFF_USAGE_ERROR=$((($RET & 0x02) != 0))
       ABIDIFF_ABI_CHANGE=$((($RET & 0x04) != 0))
       ABIDIFF_ABI_INCOMPATIBLE_CHANGE=$((($RET & 0x08) != 0))
       ABIDIFF_UNKNOWN_BIT_SET=$((($RET & 0xf0) != 0))
new file mode 100755
--- /dev/null
+++ b/security/nss/automation/taskcluster/scripts/run_coverity.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+source $(dirname "$0")/tools.sh
+
+# Clone NSPR if needed.
+if [ ! -d "nspr" ]; then
+    hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
+fi
+
+# Build and run Coverity
+cd nss
+./mach static-analysis
+
+# Return the exit code of the Coverity Analysis
+exit $?
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/security/nss/cmd/fipstest/README
@@ -0,0 +1,1 @@
+The scripts have been moved to tests/fips/cavs_scripts
deleted file mode 100644
--- a/security/nss/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
deleted file mode 100644
--- a/security/nss/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
deleted file mode 100755
--- a/security/nss/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
deleted file mode 100644
--- a/security/nss/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
--- a/security/nss/cmd/fipstest/fipstest.c
+++ b/security/nss/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;
 }
deleted file mode 100755
--- a/security/nss/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
-
deleted file mode 100755
--- a/security/nss/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
-
deleted file mode 100644
--- a/security/nss/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
deleted file mode 100644
--- a/security/nss/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
deleted file mode 100644
--- a/security/nss/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
deleted file mode 100644
--- a/security/nss/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
-
deleted file mode 100644
--- a/security/nss/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
deleted file mode 100644
--- a/security/nss/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
deleted file mode 100644
--- a/security/nss/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
deleted file mode 100644
--- a/security/nss/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
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/security/nss/doc/certutil.xml
+++ b/security/nss/doc/certutil.xml
@@ -423,16 +423,19 @@ of the attribute codes:
 <para><command>R</command> (as an email recipient)</para>
 	</listitem>
 	<listitem>
 <para><command>O</command> (as an OCSP status responder)</para>
 	</listitem>
 	<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>
 
       <varlistentry>
         <term>-v valid-months</term>
         <listitem><para>Set the number of months a new certificate will be valid. The validity period begins at the current system time unless an offset is added or subtracted with the <option>-w</option> option. If this argument is not used, the default validity period is three months. </para></listitem>
       </varlistentry>
 
--- a/security/nss/gtests/pk11_gtest/pk11_import_unittest.cc
+++ b/security/nss/gtests/pk11_gtest/pk11_import_unittest.cc
@@ -43,18 +43,25 @@ class Pk11KeyImportTestBase : public ::t
   }
 
   void Test() {
     // Generate a key and export it.
     KeyType key_type;
     ScopedSECKEYEncryptedPrivateKeyInfo key_info;
     ScopedSECItem public_value;
     GenerateAndExport(&key_type, &key_info, &public_value);
+
+    ASSERT_NE(nullptr, public_value);
+    // Note: NSS is currently unable export wrapped DH keys, so this doesn't
+    // test
+    // CKM_DH_PKCS_KEY_PAIR_GEN beyond generate and verify
+    if (key_type == dhKey) {
+      return;
+    }
     ASSERT_NE(nullptr, key_info);
-    ASSERT_NE(nullptr, public_value);
 
     // Now import the encrypted key.
     static const uint8_t nick[] = "nick";
     SECItem nickname = {siBuffer, toUcharPtr(nick), sizeof(nick)};
     SECKEYPrivateKey* priv_tmp;
     SECStatus rv = PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(
         slot_.get(), key_info.get(), password_.get(), &nickname,
         public_value.get(), PR_TRUE, PR_TRUE, key_type, 0, &priv_tmp, NULL);
@@ -73,27 +80,51 @@ class Pk11KeyImportTestBase : public ::t
     virtual void* get() = 0;
   };
 
   virtual std::unique_ptr<ParamHolder> MakeParams() = 0;
 
   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;
 
       case dhKey:
       case dsaKey:
         value_type = CKA_VALUE;
         break;
@@ -101,16 +132,18 @@ class Pk11KeyImportTestBase : public ::t
       case ecKey:
         value_type = CKA_EC_POINT;
         break;
 
       default:
         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);
     for (PK11GenericObject* obj = objs.get(); obj != nullptr;
          obj = PK11_GetNextGenericObject(obj)) {
       StackSECItem pub_id;
       rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_ID, &pub_id);
       if (rv != SECSuccess) {
@@ -123,30 +156,54 @@ class Pk11KeyImportTestBase : public ::t
       }
 
       StackSECItem token;
       rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_TOKEN, &token);
       ASSERT_EQ(SECSuccess, rv);
       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;
     }
   }
 
   void GenerateAndExport(KeyType* key_type,
                          ScopedSECKEYEncryptedPrivateKeyInfo* key_info,
                          ScopedSECItem* public_value) {
     auto params = MakeParams();
     ASSERT_NE(nullptr, params);
@@ -155,23 +212,16 @@ class Pk11KeyImportTestBase : public ::t
     ScopedSECKEYPrivateKey priv_key(
         PK11_GenerateKeyPair(slot_.get(), mech_, params->get(), &pub_tmp,
                              PR_FALSE, PR_TRUE, nullptr));
     ASSERT_NE(nullptr, priv_key) << "PK11_GenerateKeyPair failed: "
                                  << PORT_ErrorToName(PORT_GetError());
     ScopedSECKEYPublicKey pub_key(pub_tmp);
     ASSERT_NE(nullptr, pub_key);
 
-    // Wrap and export the key.
-    ScopedSECKEYEncryptedPrivateKeyInfo epki(PK11_ExportEncryptedPrivKeyInfo(
-        slot_.get(), SEC_OID_AES_256_CBC, password_.get(), priv_key.get(), 1,
-        nullptr));
-    ASSERT_NE(nullptr, epki) << "PK11_ExportEncryptedPrivKeyInfo failed: "
-                             << PORT_ErrorToName(PORT_GetError());
-
     // Save the public value, which we will need on import */
     SECItem* pub_val;
     KeyType t = SECKEY_GetPublicKeyType(pub_key.get());
     switch (t) {
       case rsaKey:
         pub_val = &pub_key->u.rsa.modulus;
         break;
       case dhKey:
@@ -185,18 +235,32 @@ class Pk11KeyImportTestBase : public ::t
         break;
       default:
         FAIL() << "Unknown key type";
     }
 
     CheckForPublicKey(priv_key, pub_val);
 
     *key_type = t;
+    public_value->reset(SECITEM_DupItem(pub_val));
+
+    // Note: NSS is currently unable export wrapped DH keys, so this doesn't
+    // test
+    // CKM_DH_PKCS_KEY_PAIR_GEN beyond generate and verify
+    if (mech_ == CKM_DH_PKCS_KEY_PAIR_GEN) {
+      return;
+    }
+    // Wrap and export the key.
+    ScopedSECKEYEncryptedPrivateKeyInfo epki(PK11_ExportEncryptedPrivKeyInfo(
+        slot_.get(), SEC_OID_AES_256_CBC, password_.get(), priv_key.get(), 1,
+        nullptr));
+    ASSERT_NE(nullptr, epki) << "PK11_ExportEncryptedPrivKeyInfo failed: "
+                             << PORT_ErrorToName(PORT_GetError());
+
     key_info->swap(epki);
-    public_value->reset(SECITEM_DupItem(pub_val));
   }
 
   ScopedPK11SlotInfo slot_;
   ScopedSECItem password_;
 };
 
 class Pk11KeyImportTest
     : public Pk11KeyImportTestBase,
@@ -276,19 +340,18 @@ class Pk11KeyImportTest
     SECKEYDHParams params_;
   };
 };
 
 TEST_P(Pk11KeyImportTest, GenerateExportImport) { Test(); }
 
 INSTANTIATE_TEST_CASE_P(Pk11KeyImportTest, Pk11KeyImportTest,
                         ::testing::Values(CKM_RSA_PKCS_KEY_PAIR_GEN,
-                                          CKM_DSA_KEY_PAIR_GEN));
-// Note: NSS is currently unable export wrapped DH keys, so this doesn't test
-// CKM_DH_PKCS_KEY_PAIR_GEN.
+                                          CKM_DSA_KEY_PAIR_GEN,
+                                          CKM_DH_PKCS_KEY_PAIR_GEN));
 
 class Pk11KeyImportTestEC : public Pk11KeyImportTestBase,
                             public ::testing::WithParamInterface<SECOidTag> {
  public:
   Pk11KeyImportTestEC() : Pk11KeyImportTestBase(CKM_EC_KEY_PAIR_GEN) {}
   virtual ~Pk11KeyImportTestEC() = default;
 
  protected:
--- a/security/nss/lib/cryptohi/seckey.c
+++ b/security/nss/lib/cryptohi/seckey.c
@@ -1201,23 +1201,56 @@ SECKEY_CopyPublicKey(const SECKEYPublicK
     }
     if (rv == SECSuccess)
         return copyk;
 
     SECKEY_DestroyPublicKey(copyk);
     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)
 {
     SECKEYPublicKey *pubk;
     PLArenaPool *arena;
     CERTCertificate *cert;
     SECStatus rv;
+    CK_OBJECT_HANDLE pubKeyHandle;
+    SECItem decodedPoint;
 
     /*
      * First try to look up the cert.
      */
     cert = PK11_GetCertFromPrivateKey(privk);
     if (cert) {
         pubk = CERT_ExtractPublicKey(cert);
         CERT_DestroyCertificate(cert);
@@ -1238,50 +1271,103 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateK
     }
     pubk->keyType = privk->keyType;
     pubk->pkcs11Slot = NULL;
     pubk->pkcs11ID = CK_INVALID_HANDLE;
     pubk->arena = arena;
 
     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);
             if (rv != SECSuccess)
                 break;
             rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
                                     CKA_PUBLIC_EXPONENT, arena, &pubk->u.rsa.publicExponent);
             if (rv != SECSuccess)
                 break;
             return pubk;
-            break;
         case ecKey:
             rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
                                     CKA_EC_PARAMS, arena, &pubk->u.ec.DEREncodedParams);
             if (rv != SECSuccess) {
                 break;
             }
             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;
         default:
             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;
 }
 
 static CERTSubjectPublicKeyInfo *
 seckey_CreateSubjectPublicKeyInfo_helper(SECKEYPublicKey *pubk)
 {
     CERTSubjectPublicKeyInfo *spki;
     PLArenaPool *arena;
--- a/security/nss/lib/freebl/freebl.gyp
+++ b/security/nss/lib/freebl/freebl.gyp
@@ -217,16 +217,53 @@
          [ 'OS=="linux"', {
            'mapfile': 'freebl_hash_vector.def',
          }, {
            'mapfile': 'freebl.def',
          }],
        ]
       },
     },
+    {
+      'target_name': 'freebl_64int_3',
+      'includes': [
+        'freebl_base.gypi',
+      ],
+      'type': 'shared_library',
+      'dependencies': [
+        '<(DEPTH)/exports.gyp:nss_exports',
+        'hw-acc-crypto',
+      ],
+    },
+    {
+      'target_name': 'freebl_64fpu_3',
+      'includes': [
+        'freebl_base.gypi',
+      ],
+      'type': 'shared_library',
+      'sources': [
+        'mpi/mpi_sparc.c',
+        'mpi/mpv_sparcv9.s',
+        'mpi/montmulfv9.s',
+      ],
+      'dependencies': [
+        '<(DEPTH)/exports.gyp:nss_exports',
+        'hw-acc-crypto',
+      ],
+      'asflags_mozilla': [
+        '-mcpu=v9', '-Wa,-xarch=v9a'
+      ],
+      'defines': [
+        'MP_NO_MP_WORD',
+        'MP_USE_UINT_DIGIT',
+        'MP_ASSEMBLY_MULTIPLY',
+        'MP_USING_MONT_MULF',
+        'MP_MONT_USE_MP_MUL',
+      ],
+    },
   ],
   'conditions': [
     [ 'OS=="linux"', {
       # stub build
       'targets': [
         {
           'target_name': 'freebl3',
           'type': 'shared_library',
--- a/security/nss/lib/pk11wrap/pk11mech.c
+++ b/security/nss/lib/pk11wrap/pk11mech.c
@@ -235,16 +235,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:
--- a/security/nss/lib/pk11wrap/pk11priv.h
+++ b/security/nss/lib/pk11wrap/pk11priv.h
@@ -106,16 +106,17 @@ CK_MECHANISM_TYPE PK11_GetKeyGenWithSize
 PK11SymKey *PK11_GenDES3TokenKey(PK11SlotInfo *slot, SECItem *keyid, void *cx);
 SECKEYPublicKey *PK11_ExtractPublicKey(PK11SlotInfo *slot, KeyType keyType,
                                        CK_OBJECT_HANDLE id);
 CK_OBJECT_HANDLE PK11_FindObjectForCert(CERTCertificate *cert,
                                         void *wincx, PK11SlotInfo **pSlot);
 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
  **********************************************************************/
 SECStatus PK11_TraversePrivateKeysInSlot(PK11SlotInfo *slot,
                                          SECStatus (*callback)(SECKEYPrivateKey *, void *), void *arg);
 SECKEYPrivateKey *PK11_FindPrivateKeyFromNickname(char *nickname, void *wincx);
 CK_OBJECT_HANDLE *PK11_FindObjectsFromNickname(char *nickname,
--- a/security/nss/lib/pk11wrap/pk11skey.c
+++ b/security/nss/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 *
@@ -1835,16 +1836,45 @@ loser:
     if (newSharedSecret != NULL)
         PK11_FreeSymKey(newSharedSecret);
     if (intermediateResult != NULL)
         PK11_FreeSymKey(intermediateResult);
     return NULL;
 }
 
 /*
+ * 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.
  */
 PK11SymKey *
 PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
                PRBool isSender, SECItem *randomA, SECItem *randomB,
                CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
--- a/security/nss/lib/softoken/fipstest.c
+++ b/security/nss/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.
  */
--- a/security/nss/lib/softoken/lowkey.c
+++ b/security/nss/lib/softoken/lowkey.c
@@ -256,16 +256,17 @@ nsslowkey_PrivateModulusLen(NSSLOWKEYPri
     }
     return 0;
 }
 
 NSSLOWKEYPublicKey *
 nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
 {
     NSSLOWKEYPublicKey *pubk;
+    SECItem publicValue;
     PLArenaPool *arena;
 
     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     if (arena == NULL) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         return NULL;
     }
 
@@ -296,16 +297,29 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPr
         case NSSLOWKEYDSAKey:
             pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
                                                           sizeof(NSSLOWKEYPublicKey));
             if (pubk != NULL) {
                 SECStatus rv;
 
                 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)
                     break;
                 rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
                                       &privk->u.dsa.params.prime);
                 if (rv != SECSuccess)
                     break;
@@ -322,16 +336,29 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPr
         case NSSLOWKEYDHKey:
             pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
                                                           sizeof(NSSLOWKEYPublicKey));
             if (pubk != NULL) {
                 SECStatus rv;
 
                 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)
                     break;
                 rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
                                       &privk->u.dh.prime);
                 if (rv != SECSuccess)
                     break;
--- a/security/nss/lib/softoken/manifest.mn
+++ b/security/nss/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
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/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, { 16, 16, 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 --------------------------- */
@@ -505,17 +507,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)
 
@@ -2195,16 +2201,129 @@ sftk_GetPrivKey(SFTKObject *object, CK_K
     }
 
     priv = sftk_mkPrivKey(object, key_type, crvp);
     object->objectInfo = priv;
     object->infoFree = (SFTKFree)nsslowkey_DestroyPrivateKey;
     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 ************************
  */
 /*
  * set the DES key with parity bits correctly
  */
 void
 sftk_FormatDESKey(unsigned char *key, int length)
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -91,52 +91,20 @@ sftk_FreePrivKey(NSSLOWKEYPrivateKey *ke
 static void
 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.
+ * functions to CKR_xxx.  Most of the mapping is done in 
+ * sftk_mapCryptError (now in pkcs11u.c). The next two functions adjust
+ * that mapping based for different contexts (Decrypt or Verify).
  */
-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;
@@ -2157,19 +2125,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;
@@ -2263,43 +2234,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,
@@ -2905,16 +2915,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;
 }
 
@@ -2943,31 +2960,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);
@@ -6561,16 +6578,20 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
     switch (mechanism) {
         case CKM_NSS_JPAKE_ROUND2_SHA1:   /* fall through */
         case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */
         case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */
         case CKM_NSS_JPAKE_ROUND2_SHA512:
             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 */
         case CKM_NSS_JPAKE_FINAL_SHA512:
             extractValue = PR_FALSE;
         /* fall through */
         default:
             classType = CKO_SECRET_KEY;
@@ -6602,16 +6623,83 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
         if (att == NULL) {
             sftk_FreeObject(key);
             sftk_FreeObject(sourceKey);
             return CKR_KEY_HANDLE_INVALID;
         }
     }
 
     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)) {
+                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:
--- a/security/nss/lib/softoken/pkcs11i.h
+++ b/security/nss/lib/softoken/pkcs11i.h
@@ -249,22 +249,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;
@@ -609,16 +612,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,
@@ -686,20 +690,46 @@ extern void sftk_update_all_states(SFTKS
 extern void sftk_FreeContext(SFTKSessionContext *context);
 extern void sftk_InitFreeLists(void);
 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 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);
 
+/* 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);
 
 /*
--- a/security/nss/lib/softoken/pkcs11u.c
+++ b/security/nss/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 *
new file mode 100644
--- /dev/null
+++ b/security/nss/lib/softoken/sftkike.c
@@ -0,0 +1,1294 @@
+/* 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 aes 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 k3.
+         * 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 */
+        CK_RV crv = sftk_xcbc_mac_pad(context->padBuf, context->nextChar,
+                                      AES_BLOCK_SIZE, context->k2, context->k3);
+        if (crv != CKR_OK) {
+            return crv;
+        }
+        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 */
+    PORT_Memset(buf, 0, sizeof(buf));
+    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;
+    }
+    prf_free(&context);
+    /* 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;
+    }
+    prf_free(&context);
+    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
+    };
+    s