Bug 1550889 - land NSS 8082be3a6363 UPGRADE_NSS_RELEASE, r=me
authorJ.C. Jones <jc@mozilla.com>
Tue, 04 Jun 2019 19:39:40 +0000
changeset 536710 3709f100f2649fc571f15d142fb29c61010861b3
parent 536709 44235c868eaf2f9f718383f24f314a26a0dcc63a
child 536711 b58a59871bca61224e9219c4df5be6163adffe45
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 8082be3a6363 UPGRADE_NSS_RELEASE, r=me
security/nss/TAG-INFO
security/nss/automation/abi-check/expected-report-libnss3.so.txt
security/nss/coreconf/coreconf.dep
security/nss/cpputil/nss_scoped_ptrs.h
security/nss/gtests/common/util.h
security/nss/gtests/pk11_gtest/manifest.mn
security/nss/gtests/pk11_gtest/pk11_find_certs_unittest.cc
security/nss/gtests/pk11_gtest/pk11_gtest.gyp
security/nss/gtests/softoken_gtest/manifest.mn
security/nss/gtests/softoken_gtest/softoken_gtest.cc
security/nss/gtests/ssl_gtest/ssl_gtest.gyp
security/nss/lib/ckfw/builtins/certdata.txt
security/nss/lib/ckfw/builtins/nssckbi.h
security/nss/lib/freebl/fipsfreebl.c
security/nss/lib/freebl/intel-gcm-wrap.c
security/nss/lib/freebl/pqg.c
security/nss/lib/freebl/rijndael.c
security/nss/lib/nss/nss.def
security/nss/lib/pk11wrap/pk11obj.c
security/nss/lib/pk11wrap/pk11pub.h
security/nss/lib/softoken/pkcs11c.c
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-29a48b604602
+8082be3a6363
--- a/security/nss/automation/abi-check/expected-report-libnss3.so.txt
+++ b/security/nss/automation/abi-check/expected-report-libnss3.so.txt
@@ -0,0 +1,4 @@
+
+1 Added function:
+
+  'function SECStatus PK11_FindRawCertsWithSubject(PK11SlotInfo*, SECItem*, CERTCertificateList**)'    {PK11_FindRawCertsWithSubject@@NSS_3.45}
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,8 +5,9 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
+
--- a/security/nss/cpputil/nss_scoped_ptrs.h
+++ b/security/nss/cpputil/nss_scoped_ptrs.h
@@ -9,16 +9,17 @@
 
 #include <memory>
 #include "cert.h"
 #include "keyhi.h"
 #include "p12.h"
 #include "pk11pqg.h"
 #include "pk11pub.h"
 #include "pkcs11uri.h"
+#include "secmod.h"
 
 struct ScopedDelete {
   void operator()(CERTCertificate* cert) { CERT_DestroyCertificate(cert); }
   void operator()(CERTCertificateList* list) {
     CERT_DestroyCertificateList(list);
   }
   void operator()(CERTName* name) { CERT_DestroyName(name); }
   void operator()(CERTCertList* list) { CERT_DestroyCertList(list); }
@@ -42,16 +43,17 @@ struct ScopedDelete {
   void operator()(PLArenaPool* arena) { PORT_FreeArena(arena, PR_FALSE); }
   void operator()(PK11Context* context) { PK11_DestroyContext(context, true); }
   void operator()(PK11GenericObject* obj) { PK11_DestroyGenericObject(obj); }
   void operator()(PQGParams* pqg) { PK11_PQG_DestroyParams(pqg); }
   void operator()(SEC_PKCS12DecoderContext* dcx) {
     SEC_PKCS12DecoderFinish(dcx);
   }
   void operator()(CERTDistNames* names) { CERT_FreeDistNames(names); }
+  void operator()(SECMODModule* module) { SECMOD_DestroyModule(module); }
 };
 
 template <class T>
 struct ScopedMaybeDelete {
   void operator()(T* ptr) {
     if (ptr) {
       ScopedDelete del;
       del(ptr);
@@ -77,16 +79,17 @@ SCOPED(SECKEYPublicKey);
 SCOPED(SECKEYPrivateKey);
 SCOPED(SECKEYPrivateKeyList);
 SCOPED(PK11URI);
 SCOPED(PLArenaPool);
 SCOPED(PK11Context);
 SCOPED(PK11GenericObject);
 SCOPED(SEC_PKCS12DecoderContext);
 SCOPED(CERTDistNames);
+SCOPED(SECMODModule);
 
 #undef SCOPED
 
 struct StackSECItem : public SECItem {
   StackSECItem() : SECItem({siBuffer, nullptr, 0}) {}
   ~StackSECItem() { SECITEM_FreeItem(this, PR_FALSE); }
 };
 
--- a/security/nss/gtests/common/util.h
+++ b/security/nss/gtests/common/util.h
@@ -3,19 +3,110 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef util_h__
 #define util_h__
 
 #include <cassert>
+#include <cstdlib>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <sys/stat.h>
 #include <vector>
+#if defined(_WIN32)
+#include <windows.h>
+#include <codecvt>
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "nspr.h"
 
 static inline std::vector<uint8_t> hex_string_to_bytes(std::string s) {
   std::vector<uint8_t> bytes;
   for (size_t i = 0; i < s.length(); i += 2) {
     bytes.push_back(std::stoul(s.substr(i, 2), nullptr, 16));
   }
   return bytes;
 }
 
+// Given a prefix, attempts to create a unique directory that the user can do
+// work in without impacting other tests. For example, if given the prefix
+// "scratch", a directory like "scratch05c17b25" will be created in the current
+// working directory (or the location specified by NSS_GTEST_WORKDIR, if
+// defined).
+// Upon destruction, the implementation will attempt to delete the directory.
+// However, no attempt is made to first remove files in the directory - the
+// user is responsible for this. If the directory is not empty, deleting it will
+// fail.
+// Statistically, it is technically possible to fail to create a unique
+// directory name, but this is extremely unlikely given the expected workload of
+// this implementation.
+class ScopedUniqueDirectory {
+ public:
+  explicit ScopedUniqueDirectory(const std::string &prefix) {
+    std::string path;
+    const char *workingDirectory = PR_GetEnvSecure("NSS_GTEST_WORKDIR");
+    if (workingDirectory) {
+      path.assign(workingDirectory);
+    }
+    path.append(prefix);
+    for (int i = 0; i < RETRY_LIMIT; i++) {
+      std::string pathCopy(path);
+      // TryMakingDirectory will modify its input. If it fails, we want to throw
+      // away the modified result.
+      if (TryMakingDirectory(pathCopy)) {
+        mPath.assign(pathCopy);
+        break;
+      }
+    }
+    assert(mPath.length() > 0);
+#if defined(_WIN32)
+    // sqldb always uses UTF-8 regardless of the current system locale.
+    DWORD len =
+        MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), nullptr, 0);
+    std::vector<wchar_t> buf(len, L'\0');
+    MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), buf.data(),
+                        buf.size());
+    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
+    mUTF8Path = converter.to_bytes(std::wstring(buf.begin(), buf.end()));
+#else
+    mUTF8Path = mPath;
+#endif
+  }
+
+  // NB: the directory must be empty upon destruction
+  ~ScopedUniqueDirectory() { assert(rmdir(mPath.c_str()) == 0); }
+
+  const std::string &GetPath() { return mPath; }
+  const std::string &GetUTF8Path() { return mUTF8Path; }
+
+ private:
+  static const int RETRY_LIMIT = 5;
+
+  static void GenerateRandomName(/*in/out*/ std::string &prefix) {
+    std::stringstream ss;
+    ss << prefix;
+    // RAND_MAX is at least 32767.
+    ss << std::setfill('0') << std::setw(4) << std::hex << rand() << rand();
+    // This will overwrite the value of prefix. This is a little inefficient,
+    // but at least it makes the code simple.
+    ss >> prefix;
+  }
+
+  static bool TryMakingDirectory(/*in/out*/ std::string &prefix) {
+    GenerateRandomName(prefix);
+#if defined(_WIN32)
+    return _mkdir(prefix.c_str()) == 0;
+#else
+    return mkdir(prefix.c_str(), 0777) == 0;
+#endif
+  }
+
+  std::string mPath;
+  std::string mUTF8Path;
+};
+
 #endif  // util_h__
--- a/security/nss/gtests/pk11_gtest/manifest.mn
+++ b/security/nss/gtests/pk11_gtest/manifest.mn
@@ -2,23 +2,25 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 CORE_DEPTH = ../..
 DEPTH      = ../..
 MODULE = nss
 
 CPPSRCS = \
+      pk11_aes_gcm_unittest.cc \
       pk11_aeskeywrap_unittest.cc \
       pk11_cbc_unittest.cc \
       pk11_chacha20poly1305_unittest.cc \
       pk11_curve25519_unittest.cc \
       pk11_ecdsa_unittest.cc \
       pk11_encrypt_derive_unittest.cc \
       pk11_export_unittest.cc \
+      pk11_find_certs_unittest.cc \
       pk11_import_unittest.cc \
       pk11_pbkdf2_unittest.cc \
       pk11_prf_unittest.cc \
       pk11_prng_unittest.cc \
       pk11_rsapkcs1_unittest.cc \
       pk11_rsapss_unittest.cc \
       pk11_der_private_key_import_unittest.cc \
       $(NULL)
new file mode 100644
--- /dev/null
+++ b/security/nss/gtests/pk11_gtest/pk11_find_certs_unittest.cc
@@ -0,0 +1,347 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 et sw=4 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <string.h>
+
+#include "nss.h"
+#include "pk11pub.h"
+#include "prenv.h"
+#include "prerror.h"
+#include "secmod.h"
+
+#include "gtest/gtest.h"
+#include "nss_scoped_ptrs.h"
+#include "util.h"
+
+namespace nss_test {
+
+// These test certificates were generated using pycert/pykey from
+// mozilla-central (https://hg.mozilla.org/mozilla-central/file/ ...
+// 9968319230a74eb8c1953444a0e6973c7500a9f8/security/manager/ssl/ ...
+// tests/unit/pycert.py).
+
+// issuer:test cert
+// subject:test cert
+// issuerKey:secp256r1
+// subjectKey:secp256r1
+// serialNumber:1
+std::vector<uint8_t> kTestCert1DER = {
+    0x30, 0x82, 0x01, 0x1D, 0x30, 0x81, 0xC2, 0xA0, 0x03, 0x02, 0x01, 0x02,
+    0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
+    0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10,
+    0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20,
+    0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37,
+    0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18,
+    0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30,
+    0x30, 0x30, 0x30, 0x5A, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
+    0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65,
+    0x72, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
+    0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01,
+    0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8,
+    0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B,
+    0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45,
+    0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07,
+    0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B,
+    0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06,
+    0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00,
+    0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13,
+    0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91,
+    0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80,
+    0x0A, 0x70, 0xE6, 0x02, 0x20, 0x11, 0xFA, 0xA2, 0xCA, 0x06, 0xF3, 0xBC,
+    0x5F, 0x8A, 0xCA, 0x17, 0x63, 0x36, 0x87, 0xCF, 0x8D, 0x5C, 0xA0, 0x56,
+    0x84, 0x44, 0x61, 0xB2, 0x33, 0x42, 0x07, 0x58, 0x9F, 0x0C, 0x9E, 0x49,
+    0x83,
+};
+
+// issuer:test cert
+// subject:test cert
+// issuerKey:secp256r1
+// subjectKey:secp256r1
+// serialNumber:2
+std::vector<uint8_t> kTestCert2DER = {
+    0x30, 0x82, 0x01, 0x1E, 0x30, 0x81, 0xC2, 0xA0, 0x03, 0x02, 0x01, 0x02,
+    0x02, 0x01, 0x02, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
+    0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10,
+    0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20,
+    0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37,
+    0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18,
+    0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30,
+    0x30, 0x30, 0x30, 0x5A, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
+    0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65,
+    0x72, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
+    0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01,
+    0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8,
+    0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B,
+    0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45,
+    0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07,
+    0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B,
+    0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06,
+    0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00,
+    0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13,
+    0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91,
+    0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80,
+    0x0A, 0x70, 0xE6, 0x02, 0x21, 0x00, 0xF6, 0x5E, 0x42, 0xC7, 0x54, 0x40,
+    0x81, 0xE9, 0x4C, 0x16, 0x48, 0xB1, 0x39, 0x0A, 0xA0, 0xE2, 0x8C, 0x23,
+    0xAA, 0xC5, 0xBB, 0xAC, 0xEB, 0x9B, 0x15, 0x0B, 0x2F, 0xB7, 0xF5, 0x85,
+    0xB2, 0x54,
+};
+
+std::vector<uint8_t> kTestCertSubjectDER = {
+    0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03,
+    0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65, 0x72, 0x74,
+};
+
+// issuer:test cert
+// subject:unrelated subject DN
+// issuerKey:secp256r1
+// subjectKey:secp256r1
+// serialNumber:3
+std::vector<uint8_t> kUnrelatedTestCertDER = {
+    0x30, 0x82, 0x01, 0x28, 0x30, 0x81, 0xCD, 0xA0, 0x03, 0x02, 0x01, 0x02,
+    0x02, 0x01, 0x03, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
+    0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10,
+    0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20,
+    0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37,
+    0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18,
+    0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30,
+    0x30, 0x30, 0x30, 0x5A, 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03,
+    0x55, 0x04, 0x03, 0x0C, 0x14, 0x75, 0x6E, 0x72, 0x65, 0x6C, 0x61, 0x74,
+    0x65, 0x64, 0x20, 0x73, 0x75, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x44,
+    0x4E, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+    0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
+    0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8, 0xF9,
+    0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B, 0x42,
+    0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45, 0x5C,
+    0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07, 0x06,
+    0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B, 0x2D,
+    0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06, 0x09,
+    0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03,
+    0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13, 0x11,
+    0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91, 0xFF,
+    0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80, 0x0A,
+    0x70, 0xE6, 0x02, 0x20, 0x0F, 0x1A, 0x04, 0xC2, 0xF8, 0xBA, 0xC2, 0x94,
+    0x26, 0x6E, 0xBC, 0x91, 0x7D, 0xDB, 0x75, 0x7B, 0xE8, 0xA3, 0x4F, 0x69,
+    0x1B, 0xF3, 0x1F, 0x2C, 0xCE, 0x82, 0x67, 0xC9, 0x5B, 0xBB, 0xBA, 0x0A,
+};
+
+class PK11FindRawCertsBySubjectTest : public ::testing::Test {
+ protected:
+  PK11FindRawCertsBySubjectTest()
+      : mSlot(nullptr), mTestCertDBDir("PK11FindRawCertsBySubjectTest-") {}
+
+  virtual void SetUp() {
+    std::string testCertDBPath(mTestCertDBDir.GetPath());
+    const char* testName =
+        ::testing::UnitTest::GetInstance()->current_test_info()->name();
+    std::string modspec = "configDir='sql:";
+    modspec.append(testCertDBPath);
+    modspec.append("' tokenDescription='");
+    modspec.append(testName);
+    modspec.append("'");
+    mSlot = SECMOD_OpenUserDB(modspec.c_str());
+    ASSERT_NE(mSlot, nullptr);
+  }
+
+  virtual void TearDown() {
+    ASSERT_EQ(SECMOD_CloseUserDB(mSlot), SECSuccess);
+    PK11_FreeSlot(mSlot);
+    std::string testCertDBPath(mTestCertDBDir.GetPath());
+    ASSERT_EQ(0, unlink((testCertDBPath + "/cert9.db").c_str()));
+    ASSERT_EQ(0, unlink((testCertDBPath + "/key4.db").c_str()));
+  }
+
+  PK11SlotInfo* mSlot;
+  ScopedUniqueDirectory mTestCertDBDir;
+};
+
+// If we don't have any certificates, we shouldn't get any when we search for
+// them.
+TEST_F(PK11FindRawCertsBySubjectTest, TestNoCertsImportedNoCertsFound) {
+  SECItem subjectItem = {siBuffer,
+                         const_cast<unsigned char*>(kTestCertSubjectDER.data()),
+                         (unsigned int)kTestCertSubjectDER.size()};
+  CERTCertificateList* certificates = nullptr;
+  SECStatus rv =
+      PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates);
+  EXPECT_EQ(rv, SECSuccess);
+  EXPECT_EQ(certificates, nullptr);
+}
+
+// If we have one certificate but it has an unrelated subject DN, we shouldn't
+// get it when we search.
+TEST_F(PK11FindRawCertsBySubjectTest, TestOneCertImportedNoCertsFound) {
+  char certNickname[] = "Unrelated Cert";
+  SECItem certItem = {siBuffer,
+                      const_cast<unsigned char*>(kUnrelatedTestCertDER.data()),
+                      (unsigned int)kUnrelatedTestCertDER.size()};
+  ASSERT_EQ(PK11_ImportDERCert(mSlot, &certItem, CK_INVALID_HANDLE,
+                               certNickname, false),
+            SECSuccess);
+
+  SECItem subjectItem = {siBuffer,
+                         const_cast<unsigned char*>(kTestCertSubjectDER.data()),
+                         (unsigned int)kTestCertSubjectDER.size()};
+  CERTCertificateList* certificates = nullptr;
+  SECStatus rv =
+      PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates);
+  EXPECT_EQ(rv, SECSuccess);
+  EXPECT_EQ(certificates, nullptr);
+}
+
+TEST_F(PK11FindRawCertsBySubjectTest, TestMultipleMatchingCertsFound) {
+  char cert1Nickname[] = "Test Cert 1";
+  SECItem cert1Item = {siBuffer,
+                       const_cast<unsigned char*>(kTestCert1DER.data()),
+                       (unsigned int)kTestCert1DER.size()};
+  ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert1Item, CK_INVALID_HANDLE,
+                               cert1Nickname, false),
+            SECSuccess);
+  char cert2Nickname[] = "Test Cert 2";
+  SECItem cert2Item = {siBuffer,
+                       const_cast<unsigned char*>(kTestCert2DER.data()),
+                       (unsigned int)kTestCert2DER.size()};
+  ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert2Item, CK_INVALID_HANDLE,
+                               cert2Nickname, false),
+            SECSuccess);
+  char unrelatedCertNickname[] = "Unrelated Test Cert";
+  SECItem unrelatedCertItem = {
+      siBuffer, const_cast<unsigned char*>(kUnrelatedTestCertDER.data()),
+      (unsigned int)kUnrelatedTestCertDER.size()};
+  ASSERT_EQ(PK11_ImportDERCert(mSlot, &unrelatedCertItem, CK_INVALID_HANDLE,
+                               unrelatedCertNickname, false),
+            SECSuccess);
+
+  CERTCertificateList* certificates = nullptr;
+  SECItem subjectItem = {siBuffer,
+                         const_cast<unsigned char*>(kTestCertSubjectDER.data()),
+                         (unsigned int)kTestCertSubjectDER.size()};
+  SECStatus rv =
+      PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates);
+  EXPECT_EQ(rv, SECSuccess);
+  ASSERT_NE(certificates, nullptr);
+  ScopedCERTCertificateList scopedCertificates(certificates);
+  ASSERT_EQ(scopedCertificates->len, 2);
+
+  std::vector<uint8_t> foundCert1(
+      scopedCertificates->certs[0].data,
+      scopedCertificates->certs[0].data + scopedCertificates->certs[0].len);
+  std::vector<uint8_t> foundCert2(
+      scopedCertificates->certs[1].data,
+      scopedCertificates->certs[1].data + scopedCertificates->certs[1].len);
+  EXPECT_TRUE(foundCert1 == kTestCert1DER || foundCert1 == kTestCert2DER);
+  EXPECT_TRUE(foundCert2 == kTestCert1DER || foundCert2 == kTestCert2DER);
+  EXPECT_TRUE(foundCert1 != foundCert2);
+}
+
+// If we try to search the internal slots, we won't find the certificate we just
+// imported (because it's on a different slot).
+TEST_F(PK11FindRawCertsBySubjectTest, TestNoCertsOnInternalSlots) {
+  char cert1Nickname[] = "Test Cert 1";
+  SECItem cert1Item = {siBuffer,
+                       const_cast<unsigned char*>(kTestCert1DER.data()),
+                       (unsigned int)kTestCert1DER.size()};
+  ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert1Item, CK_INVALID_HANDLE,
+                               cert1Nickname, false),
+            SECSuccess);
+
+  SECItem subjectItem = {siBuffer,
+                         const_cast<unsigned char*>(kTestCertSubjectDER.data()),
+                         (unsigned int)kTestCertSubjectDER.size()};
+  CERTCertificateList* internalKeySlotCertificates = nullptr;
+  ScopedPK11SlotInfo internalKeySlot(PK11_GetInternalKeySlot());
+  SECStatus rv = PK11_FindRawCertsWithSubject(
+      internalKeySlot.get(), &subjectItem, &internalKeySlotCertificates);
+  EXPECT_EQ(rv, SECSuccess);
+  EXPECT_EQ(internalKeySlotCertificates, nullptr);
+
+  CERTCertificateList* internalSlotCertificates = nullptr;
+  ScopedPK11SlotInfo internalSlot(PK11_GetInternalSlot());
+  rv = PK11_FindRawCertsWithSubject(internalSlot.get(), &subjectItem,
+                                    &internalSlotCertificates);
+  EXPECT_EQ(rv, SECSuccess);
+  EXPECT_EQ(internalSlotCertificates, nullptr);
+}
+
+// issuer:test cert
+// subject:(empty - this had to be done by hand as pycert doesn't support this)
+// issuerKey:secp256r1
+// subjectKey:secp256r1
+// serialNumber:4
+std::vector<uint8_t> kEmptySubjectCertDER = {
+    0x30, 0x82, 0x01, 0x09, 0x30, 0x81, 0xAE, 0xA0, 0x03, 0x02, 0x01, 0x02,
+    0x02, 0x01, 0x04, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
+    0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10,
+    0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20,
+    0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37,
+    0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18,
+    0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30,
+    0x30, 0x30, 0x30, 0x5A, 0x30, 0x00, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
+    0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48,
+    0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB,
+    0xBB, 0x61, 0xE0, 0xF8, 0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04,
+    0xE2, 0xEC, 0x05, 0x0B, 0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C,
+    0x4F, 0x79, 0x4B, 0x45, 0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36,
+    0xC4, 0x11, 0x9D, 0x07, 0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90,
+    0xD7, 0x99, 0x1B, 0x7B, 0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6,
+    0xC0, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
+    0x01, 0x0B, 0x05, 0x00, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C,
+    0x75, 0x51, 0x9F, 0x13, 0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3,
+    0xBC, 0x06, 0x30, 0x91, 0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC,
+    0xFD, 0xCB, 0x42, 0x80, 0x0A, 0x70, 0xE6, 0x02, 0x20, 0x31, 0x1B, 0x92,
+    0xAA, 0xA8, 0xB7, 0x51, 0x52, 0x7B, 0x64, 0xD6, 0xF7, 0x2F, 0x0C, 0xFB,
+    0xBB, 0xD5, 0xDF, 0x86, 0xA3, 0x97, 0x96, 0x60, 0x42, 0xDA, 0xD4, 0xA8,
+    0x5F, 0x2F, 0xA4, 0xDE, 0x7C};
+
+std::vector<uint8_t> kEmptySubjectDER = {0x30, 0x00};
+
+// This certificate has the smallest possible subject. Finding it should work.
+TEST_F(PK11FindRawCertsBySubjectTest, TestFindEmptySubject) {
+  char emptySubjectCertNickname[] = "Empty Subject Cert";
+  SECItem emptySubjectCertItem = {
+      siBuffer, const_cast<unsigned char*>(kEmptySubjectCertDER.data()),
+      (unsigned int)kEmptySubjectCertDER.size()};
+  ASSERT_EQ(PK11_ImportDERCert(mSlot, &emptySubjectCertItem, CK_INVALID_HANDLE,
+                               emptySubjectCertNickname, false),
+            SECSuccess);
+
+  SECItem subjectItem = {siBuffer,
+                         const_cast<unsigned char*>(kEmptySubjectDER.data()),
+                         (unsigned int)kEmptySubjectDER.size()};
+  CERTCertificateList* certificates = nullptr;
+  SECStatus rv =
+      PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates);
+  EXPECT_EQ(rv, SECSuccess);
+  ASSERT_NE(certificates, nullptr);
+  ScopedCERTCertificateList scopedCertificates(certificates);
+  ASSERT_EQ(scopedCertificates->len, 1);
+
+  std::vector<uint8_t> foundCert(
+      scopedCertificates->certs[0].data,
+      scopedCertificates->certs[0].data + scopedCertificates->certs[0].len);
+  EXPECT_EQ(foundCert, kEmptySubjectCertDER);
+}
+
+// Searching for a zero-length subject doesn't make sense (the minimum subject
+// is the SEQUENCE tag followed by a length byte of 0), but it shouldn't cause
+// problems.
+TEST_F(PK11FindRawCertsBySubjectTest, TestSearchForNullSubject) {
+  char cert1Nickname[] = "Test Cert 1";
+  SECItem cert1Item = {siBuffer,
+                       const_cast<unsigned char*>(kTestCert1DER.data()),
+                       (unsigned int)kTestCert1DER.size()};
+  ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert1Item, CK_INVALID_HANDLE,
+                               cert1Nickname, false),
+            SECSuccess);
+
+  SECItem subjectItem = {siBuffer, nullptr, 0};
+  CERTCertificateList* certificates = nullptr;
+  SECStatus rv =
+      PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates);
+  EXPECT_EQ(rv, SECSuccess);
+  EXPECT_EQ(certificates, nullptr);
+}
+
+}  // namespace nss_test
--- a/security/nss/gtests/pk11_gtest/pk11_gtest.gyp
+++ b/security/nss/gtests/pk11_gtest/pk11_gtest.gyp
@@ -14,16 +14,17 @@
         'pk11_aeskeywrap_unittest.cc',
         'pk11_aes_gcm_unittest.cc',
         'pk11_cbc_unittest.cc',
         'pk11_chacha20poly1305_unittest.cc',
         'pk11_cipherop_unittest.cc',
         'pk11_curve25519_unittest.cc',
         'pk11_ecdsa_unittest.cc',
         'pk11_encrypt_derive_unittest.cc',
+        'pk11_find_certs_unittest.cc',
         'pk11_import_unittest.cc',
         'pk11_pbkdf2_unittest.cc',
         'pk11_prf_unittest.cc',
         'pk11_prng_unittest.cc',
         'pk11_rsapkcs1_unittest.cc',
         'pk11_rsapss_unittest.cc',
         'pk11_der_private_key_import_unittest.cc',
         '<(DEPTH)/gtests/common/gtests.cc'
--- a/security/nss/gtests/softoken_gtest/manifest.mn
+++ b/security/nss/gtests/softoken_gtest/manifest.mn
@@ -7,16 +7,17 @@ DEPTH      = ../..
 MODULE = nss
 
 CPPSRCS = \
 	softoken_gtest.cc \
 	$(NULL)
 
 INCLUDES += \
 	-I$(CORE_DEPTH)/gtests/google_test/gtest/include \
+  -I$(CORE_DEPTH)/gtests/common \
 	-I$(CORE_DEPTH)/cpputil \
 	$(NULL)
 
 REQUIRES = nspr gtest
 
 PROGRAM = softoken_gtest
 
 EXTRA_LIBS = \
--- a/security/nss/gtests/softoken_gtest/softoken_gtest.cc
+++ b/security/nss/gtests/softoken_gtest/softoken_gtest.cc
@@ -1,109 +1,23 @@
-#include <cstdlib>
-#if defined(_WIN32)
-#include <windows.h>
-#include <codecvt>
-#endif
-
 #include "cert.h"
 #include "certdb.h"
 #include "nspr.h"
 #include "nss.h"
 #include "pk11pub.h"
 #include "secerr.h"
 
 #include "nss_scoped_ptrs.h"
+#include "util.h"
 
 #define GTEST_HAS_RTTI 0
 #include "gtest/gtest.h"
 
 namespace nss_test {
 
-// Given a prefix, attempts to create a unique directory that the user can do
-// work in without impacting other tests. For example, if given the prefix
-// "scratch", a directory like "scratch05c17b25" will be created in the current
-// working directory (or the location specified by NSS_GTEST_WORKDIR, if
-// defined).
-// Upon destruction, the implementation will attempt to delete the directory.
-// However, no attempt is made to first remove files in the directory - the
-// user is responsible for this. If the directory is not empty, deleting it will
-// fail.
-// Statistically, it is technically possible to fail to create a unique
-// directory name, but this is extremely unlikely given the expected workload of
-// this implementation.
-class ScopedUniqueDirectory {
- public:
-  explicit ScopedUniqueDirectory(const std::string &prefix);
-
-  // NB: the directory must be empty upon destruction
-  ~ScopedUniqueDirectory() { assert(rmdir(mPath.c_str()) == 0); }
-
-  const std::string &GetPath() { return mPath; }
-  const std::string &GetUTF8Path() { return mUTF8Path; }
-
- private:
-  static const int RETRY_LIMIT = 5;
-  static void GenerateRandomName(/*in/out*/ std::string &prefix);
-  static bool TryMakingDirectory(/*in/out*/ std::string &prefix);
-
-  std::string mPath;
-  std::string mUTF8Path;
-};
-
-ScopedUniqueDirectory::ScopedUniqueDirectory(const std::string &prefix) {
-  std::string path;
-  const char *workingDirectory = PR_GetEnvSecure("NSS_GTEST_WORKDIR");
-  if (workingDirectory) {
-    path.assign(workingDirectory);
-  }
-  path.append(prefix);
-  for (int i = 0; i < RETRY_LIMIT; i++) {
-    std::string pathCopy(path);
-    // TryMakingDirectory will modify its input. If it fails, we want to throw
-    // away the modified result.
-    if (TryMakingDirectory(pathCopy)) {
-      mPath.assign(pathCopy);
-      break;
-    }
-  }
-  assert(mPath.length() > 0);
-#if defined(_WIN32)
-  // sqldb always uses UTF-8 regardless of the current system locale.
-  DWORD len =
-      MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), nullptr, 0);
-  std::vector<wchar_t> buf(len, L'\0');
-  MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), buf.data(),
-                      buf.size());
-  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
-  mUTF8Path = converter.to_bytes(std::wstring(buf.begin(), buf.end()));
-#else
-  mUTF8Path = mPath;
-#endif
-}
-
-void ScopedUniqueDirectory::GenerateRandomName(std::string &prefix) {
-  std::stringstream ss;
-  ss << prefix;
-  // RAND_MAX is at least 32767.
-  ss << std::setfill('0') << std::setw(4) << std::hex << rand() << rand();
-  // This will overwrite the value of prefix. This is a little inefficient, but
-  // at least it makes the code simple.
-  ss >> prefix;
-}
-
-bool ScopedUniqueDirectory::TryMakingDirectory(std::string &prefix) {
-  GenerateRandomName(prefix);
-#if defined(_WIN32)
-  return _mkdir(prefix.c_str()) == 0;
-#else
-  return mkdir(prefix.c_str(), 0777) == 0;
-#endif
-}
-
 class SoftokenTest : public ::testing::Test {
  protected:
   SoftokenTest() : mNSSDBDir("SoftokenTest.d-") {}
   SoftokenTest(const std::string &prefix) : mNSSDBDir(prefix) {}
 
   virtual void SetUp() {
     std::string nssInitArg("sql:");
     nssInitArg.append(mNSSDBDir.GetUTF8Path());
--- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
+++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
@@ -88,17 +88,17 @@
             '<(DEPTH)/lib/freebl/freebl.gyp:freebl',
           ],
         }],
         [ 'disable_dbm==0', {
           'dependencies': [
             '<(DEPTH)/lib/dbm/src/src.gyp:dbm',
           ],
         }],
-        [ 'enable_sslkeylogfile==1', {
+        [ 'enable_sslkeylogfile==1 and sanitizer_flags==0', {
           'sources': [
             'ssl_keylog_unittest.cc',
           ],
           'defines': [
             'NSS_ALLOW_SSLKEYLOGFILE',
           ],
         }],
       ],
--- a/security/nss/lib/ckfw/builtins/certdata.txt
+++ b/security/nss/lib/ckfw/builtins/certdata.txt
@@ -17741,182 +17741,16 @@ CKA_SERIAL_NUMBER MULTILINE_OCTAL
 \002\004\030\112\314\326
 END
 CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
 CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
 CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
 CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
 
 #
-# Certificate "Certinomis - Root CA"
-#
-# Issuer: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR
-# Serial Number: 1 (0x1)
-# Subject: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR
-# Not Valid Before: Mon Oct 21 09:17:18 2013
-# Not Valid After : Fri Oct 21 09:17:18 2033
-# Fingerprint (SHA-256): 2A:99:F5:BC:11:74:B7:3C:BB:1D:62:08:84:E0:1C:34:E5:1C:CB:39:78:DA:12:5F:0E:33:26:88:83:BF:41:58
-# Fingerprint (SHA1): 9D:70:BB:01:A5:A4:A0:18:11:2E:F7:1C:01:B9:32:C5:34:E7:88:A8
-CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
-CKA_TOKEN CK_BBOOL CK_TRUE
-CKA_PRIVATE CK_BBOOL CK_FALSE
-CKA_MODIFIABLE CK_BBOOL CK_FALSE
-CKA_LABEL UTF8 "Certinomis - Root CA"
-CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
-CKA_SUBJECT MULTILINE_OCTAL
-\060\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061
-\023\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156
-\157\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060
-\060\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060
-\033\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155
-\151\163\040\055\040\122\157\157\164\040\103\101
-END
-CKA_ID UTF8 "0"
-CKA_ISSUER MULTILINE_OCTAL
-\060\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061
-\023\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156
-\157\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060
-\060\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060
-\033\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155
-\151\163\040\055\040\122\157\157\164\040\103\101
-END
-CKA_SERIAL_NUMBER MULTILINE_OCTAL
-\002\001\001
-END
-CKA_VALUE MULTILINE_OCTAL
-\060\202\005\222\060\202\003\172\240\003\002\001\002\002\001\001
-\060\015\006\011\052\206\110\206\367\015\001\001\013\005\000\060
-\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061\023
-\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156\157
-\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060\060
-\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060\033
-\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155\151
-\163\040\055\040\122\157\157\164\040\103\101\060\036\027\015\061
-\063\061\060\062\061\060\071\061\067\061\070\132\027\015\063\063
-\061\060\062\061\060\071\061\067\061\070\132\060\132\061\013\060
-\011\006\003\125\004\006\023\002\106\122\061\023\060\021\006\003
-\125\004\012\023\012\103\145\162\164\151\156\157\155\151\163\061
-\027\060\025\006\003\125\004\013\023\016\060\060\060\062\040\064
-\063\063\071\071\070\071\060\063\061\035\060\033\006\003\125\004
-\003\023\024\103\145\162\164\151\156\157\155\151\163\040\055\040
-\122\157\157\164\040\103\101\060\202\002\042\060\015\006\011\052
-\206\110\206\367\015\001\001\001\005\000\003\202\002\017\000\060
-\202\002\012\002\202\002\001\000\324\314\011\012\054\077\222\366
-\177\024\236\013\234\232\152\035\100\060\144\375\252\337\016\036
-\006\133\237\120\205\352\315\215\253\103\147\336\260\372\176\200
-\226\236\204\170\222\110\326\343\071\356\316\344\131\130\227\345
-\056\047\230\352\223\250\167\233\112\360\357\164\200\055\353\060
-\037\265\331\307\200\234\142\047\221\210\360\112\211\335\334\210
-\346\024\371\325\003\057\377\225\333\275\237\354\054\372\024\025
-\131\225\012\306\107\174\151\030\271\247\003\371\312\166\251\317
-\307\157\264\136\005\376\356\301\122\262\165\062\207\354\355\051
-\146\073\363\112\026\202\366\326\232\333\162\230\351\336\360\305
-\114\245\253\265\352\001\342\214\056\144\177\144\157\375\243\045
-\223\213\310\242\016\111\215\064\360\037\354\130\105\056\064\252
-\204\120\275\347\262\112\023\270\260\017\256\070\135\260\251\033
-\346\163\311\132\241\331\146\100\252\251\115\246\064\002\255\204
-\176\262\043\301\373\052\306\147\364\064\266\260\225\152\063\117
-\161\104\265\255\300\171\063\210\340\277\355\243\240\024\264\234
-\011\260\012\343\140\276\370\370\146\210\315\133\361\167\005\340
-\265\163\156\301\175\106\056\216\113\047\246\315\065\012\375\345
-\115\175\252\052\243\051\307\132\150\004\350\345\326\223\244\142
-\302\305\346\364\117\306\371\237\032\215\202\111\031\212\312\131
-\103\072\350\015\062\301\364\114\023\003\157\156\246\077\221\163
-\313\312\163\157\022\040\213\356\300\202\170\336\113\056\302\111
-\303\035\355\026\366\044\364\047\033\134\127\061\334\125\356\250
-\036\157\154\254\342\105\314\127\127\212\165\127\031\340\265\130
-\231\111\066\061\074\063\001\155\026\112\315\270\052\203\204\206
-\233\371\140\322\037\155\221\003\323\140\246\325\075\232\335\167
-\220\075\065\244\237\017\136\365\122\104\151\271\300\272\334\317
-\175\337\174\331\304\254\206\042\062\274\173\153\221\357\172\370
-\027\150\260\342\123\125\140\055\257\076\302\203\330\331\011\053
-\360\300\144\333\207\213\221\314\221\353\004\375\166\264\225\232
-\346\024\006\033\325\064\035\276\330\377\164\034\123\205\231\340
-\131\122\112\141\355\210\236\153\111\211\106\176\040\132\331\347
-\112\345\152\356\322\145\021\103\002\003\001\000\001\243\143\060
-\141\060\016\006\003\125\035\017\001\001\377\004\004\003\002\001
-\006\060\017\006\003\125\035\023\001\001\377\004\005\060\003\001
-\001\377\060\035\006\003\125\035\016\004\026\004\024\357\221\114
-\365\245\303\060\350\057\010\352\323\161\042\244\222\150\170\164
-\331\060\037\006\003\125\035\043\004\030\060\026\200\024\357\221
-\114\365\245\303\060\350\057\010\352\323\161\042\244\222\150\170
-\164\331\060\015\006\011\052\206\110\206\367\015\001\001\013\005
-\000\003\202\002\001\000\176\075\124\332\042\135\032\130\076\073
-\124\047\272\272\314\310\343\032\152\352\076\371\022\353\126\137
-\075\120\316\340\352\110\046\046\317\171\126\176\221\034\231\077
-\320\241\221\034\054\017\117\230\225\131\123\275\320\042\330\210
-\135\234\067\374\373\144\301\170\214\213\232\140\011\352\325\372
-\041\137\320\164\145\347\120\305\277\056\271\013\013\255\265\260
-\027\246\022\214\324\142\170\352\126\152\354\012\322\100\303\074
-\005\060\076\115\224\267\237\112\003\323\175\047\113\266\376\104
-\316\372\031\063\032\155\244\102\321\335\314\310\310\327\026\122
-\203\117\065\224\263\022\125\175\345\342\102\353\344\234\223\011
-\300\114\133\007\253\307\155\021\240\120\027\224\043\250\265\012
-\222\017\262\172\301\140\054\070\314\032\246\133\377\362\014\343
-\252\037\034\334\270\240\223\047\336\143\343\177\041\237\072\345
-\236\372\340\023\152\165\353\226\134\142\221\224\216\147\123\266
-\211\370\022\011\313\157\122\133\003\162\206\120\225\010\324\215
-\207\206\025\037\225\044\330\244\157\232\316\244\235\233\155\322
-\262\166\006\206\306\126\010\305\353\011\332\066\302\033\133\101
-\276\141\052\343\160\346\270\246\370\266\132\304\275\041\367\377
-\252\137\241\154\166\071\146\326\352\114\125\341\000\063\233\023
-\230\143\311\157\320\001\040\011\067\122\347\014\117\076\315\274
-\365\137\226\047\247\040\002\225\340\056\350\007\101\005\037\025
-\156\326\260\344\031\340\017\002\223\000\047\162\305\213\321\124
-\037\135\112\303\100\227\176\125\246\174\301\063\004\024\001\035
-\111\040\151\013\031\223\235\156\130\042\367\100\014\106\014\043
-\143\363\071\322\177\166\121\247\364\310\241\361\014\166\042\043
-\106\122\051\055\342\243\101\007\126\151\230\322\005\011\274\151
-\307\132\141\315\217\201\140\025\115\200\335\220\342\175\304\120
-\362\214\073\156\112\307\306\346\200\053\074\201\274\021\200\026
-\020\047\327\360\315\077\171\314\163\052\303\176\123\221\326\156
-\370\365\363\307\320\121\115\216\113\245\133\346\031\027\073\326
-\201\011\334\042\334\356\216\271\304\217\123\341\147\273\063\270
-\210\025\106\317\355\151\065\377\165\015\106\363\316\161\341\305
-\153\206\102\006\271\101
-END
-CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
-
-# Trust for "Certinomis - Root CA"
-# Issuer: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR
-# Serial Number: 1 (0x1)
-# Subject: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR
-# Not Valid Before: Mon Oct 21 09:17:18 2013
-# Not Valid After : Fri Oct 21 09:17:18 2033
-# Fingerprint (SHA-256): 2A:99:F5:BC:11:74:B7:3C:BB:1D:62:08:84:E0:1C:34:E5:1C:CB:39:78:DA:12:5F:0E:33:26:88:83:BF:41:58
-# Fingerprint (SHA1): 9D:70:BB:01:A5:A4:A0:18:11:2E:F7:1C:01:B9:32:C5:34:E7:88:A8
-CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
-CKA_TOKEN CK_BBOOL CK_TRUE
-CKA_PRIVATE CK_BBOOL CK_FALSE
-CKA_MODIFIABLE CK_BBOOL CK_FALSE
-CKA_LABEL UTF8 "Certinomis - Root CA"
-CKA_CERT_SHA1_HASH MULTILINE_OCTAL
-\235\160\273\001\245\244\240\030\021\056\367\034\001\271\062\305
-\064\347\210\250
-END
-CKA_CERT_MD5_HASH MULTILINE_OCTAL
-\024\012\375\215\250\050\265\070\151\333\126\176\141\042\003\077
-END
-CKA_ISSUER MULTILINE_OCTAL
-\060\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061
-\023\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156
-\157\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060
-\060\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060
-\033\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155
-\151\163\040\055\040\122\157\157\164\040\103\101
-END
-CKA_SERIAL_NUMBER MULTILINE_OCTAL
-\002\001\001
-END
-CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
-CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
-CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
-CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
-
-#
 # Certificate "OISTE WISeKey Global Root GB CA"
 #
 # Issuer: CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH
 # Serial Number:76:b1:20:52:74:f0:85:87:46:b3:f8:23:1a:f6:c2:c0
 # Subject: CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH
 # Not Valid Before: Mon Dec 01 15:00:32 2014
 # Not Valid After : Thu Dec 01 15:10:31 2039
 # Fingerprint (SHA-256): 6B:9C:08:E8:6E:B0:F7:67:CF:AD:65:CD:98:B6:21:49:E5:49:4A:67:F5:84:5E:7B:D1:ED:01:9F:27:B8:6B:D6
--- a/security/nss/lib/ckfw/builtins/nssckbi.h
+++ b/security/nss/lib/ckfw/builtins/nssckbi.h
@@ -41,18 +41,18 @@
  *   made on that branch.
  *
  * NSS_BUILTINS_LIBRARY_VERSION_MINOR is a CK_BYTE.  It's not clear
  * whether we may use its full range (0-255) or only 0-99 because
  * of the comment in the CK_VERSION type definition.
  * It's recommend to switch back to 0 after having reached version 98/99.
  */
 #define NSS_BUILTINS_LIBRARY_VERSION_MAJOR 2
-#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 32
-#define NSS_BUILTINS_LIBRARY_VERSION "2.32"
+#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 34
+#define NSS_BUILTINS_LIBRARY_VERSION "2.34"
 
 /* These version numbers detail the semantic changes to the ckfw engine. */
 #define NSS_BUILTINS_HARDWARE_VERSION_MAJOR 1
 #define NSS_BUILTINS_HARDWARE_VERSION_MINOR 0
 
 /* These version numbers detail the semantic changes to ckbi itself
  * (new PKCS #11 objects), etc. */
 #define NSS_BUILTINS_FIRMWARE_VERSION_MAJOR 1
--- a/security/nss/lib/freebl/fipsfreebl.c
+++ b/security/nss/lib/freebl/fipsfreebl.c
@@ -10,18 +10,20 @@
 #ifdef FREEBL_NO_DEPEND
 #include "stubs.h"
 #endif
 
 #include "blapi.h"
 #include "seccomon.h" /* Required for RSA and DSA. */
 #include "secerr.h"
 #include "prtypes.h"
+#include "secitem.h"
+#include "pkcs11t.h"
 
-#include "ec.h" /* Required for ECDSA */
+#include "ec.h" /* Required for EC */
 
 /*
  * different platforms have different ways of calling and initial entry point
  * when the dll/.so is loaded. Most platforms support either a posix pragma
  * or the GCC attribute. Some platforms suppor a pre-defined name, and some
  * platforms have a link line way of invoking this function.
  */
 
@@ -283,61 +285,88 @@ freebl_fips_AES_PowerUpSelfTest(int aes_
 
     /* AES-CBC Known Initialization Vector (128-bits). */
     static const PRUint8 aes_cbc_known_initialization_vector[] =
         { "SecurityytiruceS" };
 
     /* AES Known Plaintext (128-bits). (blocksize is 128-bits) */
     static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" };
 
+    static const PRUint8 aes_gcm_known_aad[] = { "MozillaallizoM" };
+
     /* AES Known Ciphertext (128-bit key). */
     static const PRUint8 aes_ecb128_known_ciphertext[] = {
         0x3c, 0xa5, 0x96, 0xf3, 0x34, 0x6a, 0x96, 0xc1,
         0x03, 0x88, 0x16, 0x7b, 0x20, 0xbf, 0x35, 0x47
     };
 
     static const PRUint8 aes_cbc128_known_ciphertext[] = {
         0xcf, 0x15, 0x1d, 0x4f, 0x96, 0xe4, 0x4f, 0x63,
         0x15, 0x54, 0x14, 0x1d, 0x4e, 0xd8, 0xd5, 0xea
     };
 
+    static const PRUint8 aes_gcm128_known_ciphertext[] = {
+        0x63, 0xf4, 0x95, 0x28, 0xe6, 0x78, 0xee, 0x6e,
+        0x4f, 0xe0, 0xfc, 0x8d, 0xd7, 0xa2, 0xb1, 0xff,
+        0x0c, 0x97, 0x1b, 0x0a, 0xdd, 0x97, 0x75, 0xed,
+        0x8b, 0xde, 0xbf, 0x16, 0x5e, 0x57, 0x6b, 0x4f
+    };
+
     /* AES Known Ciphertext (192-bit key). */
     static const PRUint8 aes_ecb192_known_ciphertext[] = {
         0xa0, 0x18, 0x62, 0xed, 0x88, 0x19, 0xcb, 0x62,
         0x88, 0x1d, 0x4d, 0xfe, 0x84, 0x02, 0x89, 0x0e
     };
 
     static const PRUint8 aes_cbc192_known_ciphertext[] = {
         0x83, 0xf7, 0xa4, 0x76, 0xd1, 0x6f, 0x07, 0xbe,
         0x07, 0xbc, 0x43, 0x2f, 0x6d, 0xad, 0x29, 0xe1
     };
 
+    static const PRUint8 aes_gcm192_known_ciphertext[] = {
+        0xc1, 0x0b, 0x92, 0x1d, 0x68, 0x21, 0xf4, 0x25,
+        0x41, 0x61, 0x20, 0x2d, 0x59, 0x7f, 0x53, 0xde,
+        0x93, 0x39, 0xab, 0x09, 0x76, 0x41, 0x57, 0x2b,
+        0x90, 0x2e, 0x44, 0xbb, 0x52, 0x03, 0xe9, 0x07
+    };
+
     /* AES Known Ciphertext (256-bit key). */
     static const PRUint8 aes_ecb256_known_ciphertext[] = {
         0xdb, 0xa6, 0x52, 0x01, 0x8a, 0x70, 0xae, 0x66,
         0x3a, 0x99, 0xd8, 0x95, 0x7f, 0xfb, 0x01, 0x67
     };
 
     static const PRUint8 aes_cbc256_known_ciphertext[] = {
         0x37, 0xea, 0x07, 0x06, 0x31, 0x1c, 0x59, 0x27,
         0xc5, 0xc5, 0x68, 0x71, 0x6e, 0x34, 0x40, 0x16
     };
 
+    static const PRUint8 aes_gcm256_known_ciphertext[] = {
+        0x5d, 0x9e, 0xd2, 0xa2, 0x74, 0x9c, 0xd9, 0x1c,
+        0xd1, 0xc9, 0xee, 0x5d, 0xb6, 0xf2, 0xc9, 0xb6,
+        0x79, 0x27, 0x53, 0x02, 0xa3, 0xdc, 0x22, 0xce,
+        0xf4, 0xb0, 0xc1, 0x8c, 0x86, 0x51, 0xf5, 0xa1
+    };
+
     const PRUint8 *aes_ecb_known_ciphertext =
         (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_ecb128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_ecb192_known_ciphertext : aes_ecb256_known_ciphertext;
 
     const PRUint8 *aes_cbc_known_ciphertext =
         (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_cbc128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_cbc192_known_ciphertext : aes_cbc256_known_ciphertext;
 
+    const PRUint8 *aes_gcm_known_ciphertext =
+        (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_gcm128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_gcm192_known_ciphertext : aes_gcm256_known_ciphertext;
+
     /* AES variables. */
-    PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH];
-    PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH];
+    PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH * 2];
+    PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH * 2];
     AESContext *aes_context;
     unsigned int aes_bytes_encrypted;
     unsigned int aes_bytes_decrypted;
+    CK_GCM_PARAMS gcmParams;
     SECStatus aes_status;
 
     /*check if aes_key_size is 128, 192, or 256 bits */
     if ((aes_key_size != FIPS_AES_128_KEY_SIZE) &&
         (aes_key_size != FIPS_AES_192_KEY_SIZE) &&
         (aes_key_size != FIPS_AES_256_KEY_SIZE)) {
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return (SECFailure);
@@ -450,16 +479,79 @@ freebl_fips_AES_PowerUpSelfTest(int aes_
     if ((aes_status != SECSuccess) ||
         (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
         (PORT_Memcmp(aes_computed_plaintext, aes_known_plaintext,
                      FIPS_AES_DECRYPT_LENGTH) != 0)) {
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return (SECFailure);
     }
 
+    /******************************************************/
+    /* AES-GCM Single-Round Known Answer Encryption Test. */
+    /******************************************************/
+
+    gcmParams.pIv = (PRUint8 *)aes_cbc_known_initialization_vector;
+    gcmParams.ulIvLen = FIPS_AES_BLOCK_SIZE;
+    gcmParams.pAAD = (PRUint8 *)aes_gcm_known_aad;
+    gcmParams.ulAADLen = sizeof(aes_gcm_known_aad);
+    gcmParams.ulTagBits = FIPS_AES_BLOCK_SIZE * 8;
+    aes_context = AES_CreateContext(aes_known_key,
+                                    (PRUint8 *)&gcmParams,
+                                    NSS_AES_GCM, PR_TRUE, aes_key_size,
+                                    FIPS_AES_BLOCK_SIZE);
+
+    if (aes_context == NULL) {
+        PORT_SetError(SEC_ERROR_NO_MEMORY);
+        return (SECFailure);
+    }
+
+    aes_status = AES_Encrypt(aes_context, aes_computed_ciphertext,
+                             &aes_bytes_encrypted, FIPS_AES_ENCRYPT_LENGTH * 2,
+                             aes_known_plaintext,
+                             FIPS_AES_DECRYPT_LENGTH);
+
+    AES_DestroyContext(aes_context, PR_TRUE);
+
+    if ((aes_status != SECSuccess) ||
+        (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH * 2) ||
+        (PORT_Memcmp(aes_computed_ciphertext, aes_gcm_known_ciphertext,
+                     FIPS_AES_ENCRYPT_LENGTH * 2) != 0)) {
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return (SECFailure);
+    }
+
+    /******************************************************/
+    /* AES-GCM Single-Round Known Answer Decryption Test. */
+    /******************************************************/
+
+    aes_context = AES_CreateContext(aes_known_key,
+                                    (PRUint8 *)&gcmParams,
+                                    NSS_AES_GCM, PR_FALSE, aes_key_size,
+                                    FIPS_AES_BLOCK_SIZE);
+
+    if (aes_context == NULL) {
+        PORT_SetError(SEC_ERROR_NO_MEMORY);
+        return (SECFailure);
+    }
+
+    aes_status = AES_Decrypt(aes_context, aes_computed_plaintext,
+                             &aes_bytes_decrypted, FIPS_AES_DECRYPT_LENGTH * 2,
+                             aes_gcm_known_ciphertext,
+                             FIPS_AES_ENCRYPT_LENGTH * 2);
+
+    AES_DestroyContext(aes_context, PR_TRUE);
+
+    if ((aes_status != SECSuccess) ||
+        (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
+        (PORT_Memcmp(aes_computed_plaintext, aes_known_plaintext,
+                     FIPS_AES_DECRYPT_LENGTH) != 0)) {
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return (SECFailure);
+    }
+
     return (SECSuccess);
 }
 
 /* Known Hash Message (512-bits).  Used for all hashes (incl. SHA-N [N>1]). */
 static const PRUint8 known_hash_message[] = {
     "The test message for the MD2, MD5, and SHA-1 hashing algorithms."
 };
 
@@ -1089,17 +1181,17 @@ freebl_fips_ECDSA_Test(ECParams *ecparam
         0x7b, 0x5a, 0x3b, 0x76, 0x4e, 0x7b, 0x7c, 0xbc,
         0xf2, 0x76, 0x1c, 0x1c, 0x7f, 0xc5, 0x53, 0x2f
     };
 
     static const PRUint8 msg[] = {
         "Firefox and ThunderBird are awesome!"
     };
 
-    unsigned char sha1[SHA1_LENGTH]; /* SHA-1 hash (160 bits) */
+    unsigned char sha256[SHA256_LENGTH]; /* SHA-256 hash (256 bits) */
     unsigned char sig[2 * MAX_ECKEY_LEN];
     SECItem signature, digest;
     ECPrivateKey *ecdsa_private_key = NULL;
     ECPublicKey ecdsa_public_key;
     SECStatus ecdsaStatus = SECSuccess;
 
     /* Generates a new EC key pair. The private key is a supplied
      * random value (in seed) and the public key is the result of
@@ -1131,23 +1223,23 @@ freebl_fips_ECDSA_Test(ECParams *ecparam
     if (ecdsaStatus != SECSuccess) {
         goto loser;
     }
 
     /***************************************************/
     /* ECDSA Single-Round Known Answer Signature Test. */
     /***************************************************/
 
-    ecdsaStatus = SHA1_HashBuf(sha1, msg, sizeof msg);
+    ecdsaStatus = SHA256_HashBuf(sha256, msg, sizeof msg);
     if (ecdsaStatus != SECSuccess) {
         goto loser;
     }
     digest.type = siBuffer;
-    digest.data = sha1;
-    digest.len = SHA1_LENGTH;
+    digest.data = sha256;
+    digest.len = SHA256_LENGTH;
 
     memset(sig, 0, sizeof sig);
     signature.type = siBuffer;
     signature.data = sig;
     signature.len = sizeof sig;
 
     ecdsaStatus = ECDSA_SignDigestWithSeed(ecdsa_private_key, &signature,
                                            &digest, ecdsa_Known_Seed, sizeof ecdsa_Known_Seed);
@@ -1176,20 +1268,93 @@ loser:
     if (ecdsaStatus != SECSuccess) {
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return (SECFailure);
     }
     return (SECSuccess);
 }
 
 static SECStatus
-freebl_fips_ECDSA_PowerUpSelfTest()
+freebl_fips_ECDH_Test(ECParams *ecparams)
 {
 
-    /* ECDSA Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
+    /* ECDH Known result (reused old CAVS vector)  */
+    static const PRUint8 ecdh_known_pub_key_1[] = {
+        EC_POINT_FORM_UNCOMPRESSED,
+        /* pubX */
+        0x16, 0x81, 0x32, 0x86, 0xc8, 0xe4, 0x3a, 0x1f,
+        0x5d, 0xe3, 0x06, 0x22, 0x8b, 0x99, 0x14, 0x25,
+        0xf7, 0x9c, 0x5b, 0x1e, 0x96, 0x84, 0x85, 0x3b,
+        0x17, 0xfe, 0xf3, 0x1c, 0x0e, 0xed, 0xc4, 0xce,
+        /* pubY */
+        0x7a, 0x44, 0xfe, 0xbd, 0x91, 0x71, 0x7d, 0x73,
+        0xd9, 0x45, 0xea, 0xae, 0x66, 0x78, 0xfa, 0x6e,
+        0x46, 0xcd, 0xfa, 0x95, 0x15, 0x47, 0x62, 0x5d,
+        0xbb, 0x1b, 0x9f, 0xe6, 0x39, 0xfc, 0xfd, 0x47
+    };
+    static const PRUint8 ecdh_known_priv_key_2[] = {
+        0xb4, 0x2a, 0xe3, 0x69, 0x19, 0xec, 0xf0, 0x42,
+        0x6d, 0x45, 0x8c, 0x94, 0x4a, 0x26, 0xa7, 0x5c,
+        0xea, 0x9d, 0xd9, 0x0f, 0x59, 0xe0, 0x1a, 0x9d,
+        0x7c, 0xb7, 0x1c, 0x04, 0x53, 0xb8, 0x98, 0x5a
+    };
+    static const PRUint8 ecdh_known_hash_result[] = {
+        0x16, 0xf3, 0x85, 0xa2, 0x41, 0xf3, 0x7f, 0xc4,
+        0x0b, 0x56, 0x47, 0xee, 0xa7, 0x74, 0xb9, 0xdb,
+        0xe1, 0xfa, 0x22, 0xe9, 0x04, 0xf1, 0xb6, 0x12,
+        0x4b, 0x44, 0x8a, 0xbb, 0xbc, 0x08, 0x2b, 0xa7,
+    };
+
+    SECItem ecdh_priv_2, ecdh_pub_1;
+    SECItem ZZ = { 0, 0, 0 };
+    SECStatus ecdhStatus = SECSuccess;
+    PRUint8 computed_hash_result[HASH_LENGTH_MAX];
+
+    ecdh_priv_2.data = (PRUint8 *)ecdh_known_priv_key_2;
+    ecdh_priv_2.len = sizeof(ecdh_known_priv_key_2);
+    ecdh_pub_1.data = (PRUint8 *)ecdh_known_pub_key_1;
+    ecdh_pub_1.len = sizeof(ecdh_known_pub_key_1);
+
+    /* Generates a new EC key pair. The private key is a supplied
+     * random value (in seed) and the public key is the result of
+     * performing a scalar point multiplication of that value with
+     * the curve's base point.
+     */
+    ecdhStatus = ECDH_Derive(&ecdh_pub_1, ecparams, &ecdh_priv_2, PR_FALSE, &ZZ);
+    if (ecdhStatus != SECSuccess) {
+        goto loser;
+    }
+    ecdhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
+    if (ecdhStatus != SECSuccess) {
+        goto loser;
+    }
+
+    if (PORT_Memcmp(computed_hash_result, ecdh_known_hash_result,
+                    sizeof(ecdh_known_hash_result)) != 0) {
+        ecdhStatus = SECFailure;
+        goto loser;
+    }
+
+loser:
+    if (ZZ.data) {
+        SECITEM_FreeItem(&ZZ, PR_FALSE);
+    }
+
+    if (ecdhStatus != SECSuccess) {
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return (SECFailure);
+    }
+    return (SECSuccess);
+}
+
+static SECStatus
+freebl_fips_EC_PowerUpSelfTest()
+{
+
+    /* EC Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
     static const unsigned char p256_prime[] = {
         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
     };
     static const unsigned char p256_a[] = {
         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -1212,17 +1377,17 @@ freebl_fips_ECDSA_PowerUpSelfTest()
     static const unsigned char p256_order[] = {
         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
         0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9,
         0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
     };
     static const unsigned char p256_encoding[] = {
         0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
     };
-    static const ECParams ecdsa_known_P256_Params = {
+    static const ECParams ec_known_P256_Params = {
         NULL, ec_params_named,                                               /* arena, type */
                                                                              /* fieldID */
         { 256, ec_field_GFp,                                                 /* size and type */
           { { siBuffer, (unsigned char *)p256_prime, sizeof(p256_prime) } }, /* u.prime */
           0,
           0,
           0 },
         /* curve */
@@ -1245,34 +1410,39 @@ freebl_fips_ECDSA_PowerUpSelfTest()
         { siBuffer, (unsigned char *)(p256_encoding) + 2, sizeof(p256_encoding) - 2 },
     };
 
     static const PRUint8 ecdsa_known_P256_signature[] = {
         0x07, 0xb1, 0xcb, 0x57, 0x20, 0xa7, 0x10, 0xd6,
         0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff,
         0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f,
         0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5,
-        0x59, 0x6a, 0x62, 0x49, 0x3d, 0x50, 0xc9, 0xe1,
-        0x27, 0x3b, 0xff, 0x9b, 0x13, 0x66, 0x67, 0xdd,
-        0x7d, 0xd1, 0x0d, 0x2d, 0x7c, 0x44, 0x04, 0x1b,
-        0x16, 0x21, 0x12, 0xc5, 0xcb, 0xbd, 0x9e, 0x75
+        0xa7, 0xd2, 0x20, 0xdd, 0x45, 0xf9, 0x2b, 0xdd,
+        0xda, 0x98, 0x99, 0x5b, 0x1c, 0x02, 0x3a, 0x27,
+        0x8b, 0x7d, 0xb6, 0xed, 0x0e, 0xe0, 0xa7, 0xac,
+        0xaa, 0x36, 0x2c, 0xfa, 0x1a, 0xdf, 0x0d, 0xe1,
     };
 
     ECParams ecparams;
 
     SECStatus rv;
 
     /* ECDSA GF(p) prime field curve test */
-    ecparams = ecdsa_known_P256_Params;
+    ecparams = ec_known_P256_Params;
     rv = freebl_fips_ECDSA_Test(&ecparams,
                                 ecdsa_known_P256_signature,
                                 sizeof ecdsa_known_P256_signature);
     if (rv != SECSuccess) {
         return (SECFailure);
     }
+    /* ECDH GF(p) prime field curve test */
+    rv = freebl_fips_ECDH_Test(&ecparams);
+    if (rv != SECSuccess) {
+        return (SECFailure);
+    }
 
     return (SECSuccess);
 }
 
 static SECStatus
 freebl_fips_DSA_PowerUpSelfTest(void)
 {
     /* DSA Known P (1024-bits), Q (160-bits), and G (1024-bits) Values. */
@@ -1413,16 +1583,148 @@ freebl_fips_DSA_PowerUpSelfTest(void)
         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
         return SECFailure;
     }
 
     return (SECSuccess);
 }
 
 static SECStatus
+freebl_fips_DH_PowerUpSelfTest(void)
+{
+    /* DH Known P (2048-bits) */
+    static const PRUint8 dh_known_P[] = {
+        0xc2, 0x79, 0xbb, 0x76, 0x32, 0x0d, 0x43, 0xfd,
+        0x1b, 0x8c, 0xa2, 0x3c, 0x00, 0xdd, 0x6d, 0xef,
+        0xf8, 0x1a, 0xd9, 0xc1, 0xa2, 0xf5, 0x73, 0x2b,
+        0xdb, 0x1a, 0x3e, 0x84, 0x90, 0xeb, 0xe7, 0x8e,
+        0x5f, 0x5c, 0x6b, 0xb6, 0x61, 0x89, 0xd1, 0x03,
+        0xb0, 0x5f, 0x91, 0xe4, 0xd2, 0x82, 0x90, 0xfc,
+        0x3c, 0x49, 0x69, 0x59, 0xc1, 0x51, 0x6a, 0x85,
+        0x71, 0xe7, 0x5d, 0x72, 0x5a, 0x45, 0xad, 0x01,
+        0x6f, 0x82, 0xae, 0xec, 0x91, 0x08, 0x2e, 0x7c,
+        0x64, 0x93, 0x46, 0x1c, 0x68, 0xef, 0xc2, 0x03,
+        0x28, 0x1d, 0x75, 0x3a, 0xeb, 0x9c, 0x46, 0xf0,
+        0xc9, 0xdb, 0x99, 0x95, 0x13, 0x66, 0x4d, 0xd5,
+        0x1a, 0x78, 0x92, 0x51, 0x89, 0x72, 0x28, 0x7f,
+        0x20, 0x70, 0x41, 0x49, 0xa2, 0x86, 0xe9, 0xf9,
+        0x78, 0x5f, 0x8d, 0x2e, 0x5d, 0xfa, 0xdb, 0x57,
+        0xd4, 0x71, 0xdf, 0x66, 0xe3, 0x9e, 0x88, 0x70,
+        0xa4, 0x21, 0x44, 0x6a, 0xc7, 0xae, 0x30, 0x2c,
+        0x9c, 0x1f, 0x91, 0x57, 0xc8, 0x24, 0x34, 0x2d,
+        0x7a, 0x4a, 0x43, 0xc2, 0x5f, 0xab, 0x64, 0x2e,
+        0xaa, 0x28, 0x32, 0x95, 0x42, 0x7b, 0xa0, 0xcc,
+        0xdf, 0xfd, 0x22, 0xc8, 0x56, 0x84, 0xc1, 0x62,
+        0x15, 0xb2, 0x77, 0x86, 0x81, 0xfc, 0xa5, 0x12,
+        0x3c, 0xca, 0x28, 0x17, 0x8f, 0x03, 0x16, 0x6e,
+        0xb8, 0x24, 0xfa, 0x1b, 0x15, 0x02, 0xfd, 0x8b,
+        0xb6, 0x0a, 0x1a, 0xf7, 0x47, 0x41, 0xc5, 0x2b,
+        0x37, 0x3e, 0xa1, 0xbf, 0x68, 0xda, 0x1c, 0x55,
+        0x44, 0xc3, 0xee, 0xa1, 0x63, 0x07, 0x11, 0x3b,
+        0x5f, 0x00, 0x84, 0xb4, 0xc4, 0xe4, 0xa7, 0x97,
+        0x29, 0xf8, 0xce, 0xab, 0xfc, 0x27, 0x3e, 0x34,
+        0xe4, 0xc7, 0x81, 0x52, 0x32, 0x0e, 0x27, 0x3c,
+        0xa6, 0x70, 0x3f, 0x4a, 0x54, 0xda, 0xdd, 0x60,
+        0x26, 0xb3, 0x6e, 0x45, 0x26, 0x19, 0x41, 0x6f
+    };
+
+    static const PRUint8 dh_known_Y_1[] = {
+        0xb4, 0xc7, 0x85, 0xba, 0xa6, 0x98, 0xb3, 0x77,
+        0x41, 0x2b, 0xd9, 0x9a, 0x72, 0x90, 0xa4, 0xac,
+        0xc4, 0xf7, 0xc2, 0x23, 0x9a, 0x68, 0xe2, 0x7d,
+        0x3a, 0x54, 0x45, 0x91, 0xc1, 0xd7, 0x8a, 0x17,
+        0x54, 0xd3, 0x37, 0xaa, 0x0c, 0xcd, 0x0b, 0xe2,
+        0xf2, 0x34, 0x0f, 0x17, 0xa8, 0x07, 0x88, 0xaf,
+        0xed, 0xc1, 0x02, 0xd4, 0xdb, 0xdc, 0x0f, 0x22,
+        0x51, 0x23, 0x40, 0xb9, 0x65, 0x6d, 0x39, 0xf4,
+        0xe1, 0x8b, 0x57, 0x7d, 0xb6, 0xd3, 0xf2, 0x6b,
+        0x02, 0xa9, 0x36, 0xf0, 0x0d, 0xe3, 0xdb, 0x9a,
+        0xbf, 0x20, 0x00, 0x4d, 0xec, 0x6f, 0x68, 0x95,
+        0xee, 0x59, 0x4e, 0x3c, 0xb6, 0xda, 0x7b, 0x19,
+        0x08, 0x9a, 0xef, 0x61, 0x43, 0xf5, 0xfb, 0x25,
+        0x70, 0x19, 0xc1, 0x5f, 0x0e, 0x0f, 0x6a, 0x63,
+        0x44, 0xe9, 0xcf, 0x33, 0xce, 0x13, 0x4f, 0x34,
+        0x3c, 0x94, 0x40, 0x8d, 0xf2, 0x65, 0x42, 0xef,
+        0x70, 0x54, 0xdd, 0x5f, 0xc1, 0xd7, 0x0b, 0xa6,
+        0x06, 0xd5, 0xa6, 0x47, 0xae, 0x2c, 0x1f, 0x5a,
+        0xa6, 0xb3, 0xc1, 0x38, 0x3a, 0x3b, 0x60, 0x94,
+        0xa2, 0x95, 0xab, 0xb2, 0x86, 0x82, 0xc5, 0x3b,
+        0xb8, 0x6f, 0x3e, 0x55, 0x86, 0x84, 0xe0, 0x00,
+        0xe5, 0xef, 0xca, 0x5c, 0xec, 0x7e, 0x38, 0x0f,
+        0x82, 0xa2, 0xb1, 0xee, 0x48, 0x1b, 0x32, 0xbb,
+        0x5a, 0x33, 0xa5, 0x01, 0xba, 0xca, 0xa6, 0x64,
+        0x61, 0xb6, 0xe5, 0x5c, 0x0e, 0x5f, 0x2c, 0x66,
+        0x0d, 0x01, 0x6a, 0x20, 0x04, 0x70, 0x68, 0x82,
+        0x93, 0x29, 0x15, 0x3b, 0x7a, 0x06, 0xb2, 0x92,
+        0x61, 0xcd, 0x7e, 0xa4, 0xc1, 0x15, 0x64, 0x3b,
+        0x3c, 0x51, 0x10, 0x4c, 0x87, 0xa6, 0xaf, 0x07,
+        0xce, 0x46, 0x82, 0x75, 0xf3, 0x90, 0xf3, 0x21,
+        0x55, 0x74, 0xc2, 0xe4, 0x96, 0x7d, 0xc3, 0xe6,
+        0x33, 0xa5, 0xc6, 0x51, 0xef, 0xec, 0x90, 0x08
+    };
+
+    static const PRUint8 dh_known_x_2[] = {
+        0x9e, 0x9b, 0xc3, 0x25, 0x53, 0xf9, 0xfc, 0x92,
+        0xb6, 0xae, 0x54, 0x8e, 0x23, 0x4c, 0x94, 0xba,
+        0x41, 0xe6, 0x29, 0x33, 0xb9, 0xdb, 0xff, 0x6d,
+        0xa8, 0xb8, 0x48, 0x49, 0x66, 0x11, 0xa6, 0x13
+    };
+
+    static const PRUint8 dh_known_hash_result[] = {
+        0x93, 0xa2, 0x89, 0x1c, 0x8a, 0xc3, 0x70, 0xbf,
+        0xa7, 0xdf, 0xb6, 0xd7, 0x82, 0xfb, 0x87, 0x81,
+        0x09, 0x47, 0xf3, 0x9f, 0x5a, 0xbf, 0x4f, 0x3f,
+        0x8e, 0x5e, 0x06, 0xca, 0x30, 0xa7, 0xaf, 0x10
+    };
+
+    /* DH variables. */
+    SECStatus dhStatus;
+    SECItem dh_prime;
+    SECItem dh_pub_key_1;
+    SECItem dh_priv_key_2;
+    SECItem ZZ = { 0, 0, 0 };
+    PRUint8 computed_hash_result[HASH_LENGTH_MAX];
+
+    dh_prime.data = (PRUint8 *)dh_known_P;
+    dh_prime.len = sizeof(dh_known_P);
+    dh_pub_key_1.data = (PRUint8 *)dh_known_Y_1;
+    dh_pub_key_1.len = sizeof(dh_known_Y_1);
+    dh_priv_key_2.data = (PRUint8 *)dh_known_x_2;
+    dh_priv_key_2.len = sizeof(dh_known_x_2);
+
+    /* execute the derive */
+    dhStatus = DH_Derive(&dh_pub_key_1, &dh_prime, &dh_priv_key_2, &ZZ, dh_prime.len);
+    if (dhStatus != SECSuccess) {
+        goto loser;
+    }
+
+    dhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
+    if (dhStatus != SECSuccess) {
+        goto loser;
+    }
+
+    if (PORT_Memcmp(computed_hash_result, dh_known_hash_result,
+                    sizeof(dh_known_hash_result)) != 0) {
+        dhStatus = SECFailure;
+        goto loser;
+    }
+
+loser:
+    if (ZZ.data) {
+        SECITEM_FreeItem(&ZZ, PR_FALSE);
+    }
+
+    if (dhStatus != SECSuccess) {
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return (SECFailure);
+    }
+    return (SECSuccess);
+}
+
+static SECStatus
 freebl_fips_RNG_PowerUpSelfTest(void)
 {
     static const PRUint8 Q[] = {
         0x85, 0x89, 0x9c, 0x77, 0xa3, 0x79, 0xff, 0x1a,
         0x86, 0x6f, 0x2f, 0x3e, 0x2e, 0xf9, 0x8c, 0x9c,
         0x9d, 0xef, 0xeb, 0xed
     };
     static const PRUint8 GENX[] = {
@@ -1536,31 +1838,37 @@ freebl_fipsPowerUpSelfTest(unsigned int 
 
         /* HMAC SHA-X Power-Up SelfTest(s). */
         rv = freebl_fips_HMAC_PowerUpSelfTest();
 
         if (rv != SECSuccess)
             return rv;
 
         /* NOTE: RSA can only be tested in full freebl. It requires access to
-     * the locking primitives */
+         * the locking primitives */
         /* RSA Power-Up SelfTest(s). */
         rv = freebl_fips_RSA_PowerUpSelfTest();
 
         if (rv != SECSuccess)
             return rv;
 
         /* DSA Power-Up SelfTest(s). */
         rv = freebl_fips_DSA_PowerUpSelfTest();
 
         if (rv != SECSuccess)
             return rv;
 
-        /* ECDSA Power-Up SelfTest(s). */
-        rv = freebl_fips_ECDSA_PowerUpSelfTest();
+        /* DH Power-Up SelfTest(s). */
+        rv = freebl_fips_DH_PowerUpSelfTest();
+
+        if (rv != SECSuccess)
+            return rv;
+
+        /* EC Power-Up SelfTest(s). */
+        rv = freebl_fips_EC_PowerUpSelfTest();
 
         if (rv != SECSuccess)
             return rv;
     }
     /* Passed Power-Up SelfTest(s). */
     return (SECSuccess);
 }
 
--- a/security/nss/lib/freebl/intel-gcm-wrap.c
+++ b/security/nss/lib/freebl/intel-gcm-wrap.c
@@ -138,16 +138,17 @@ intel_AES_GCM_CreateContext(void *contex
 loser:
     PORT_Free(gcm);
     return NULL;
 }
 
 void
 intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit)
 {
+    PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext));
     if (freeit) {
         PORT_Free(gcm);
     }
 }
 
 SECStatus
 intel_AES_GCM_EncryptUpdate(intel_AES_GCMContext *gcm,
                             unsigned char *outbuf,
--- a/security/nss/lib/freebl/pqg.c
+++ b/security/nss/lib/freebl/pqg.c
@@ -486,21 +486,21 @@ cleanup:
 **  Perform steps from  FIPS 186-3, Appendix A.1.2.1 and Appendix C.6
 **
 **  This generates a provable prime from two smaller prime. The resulting
 **  prime p will have q0 as a multiple of p-1. q0 can be 1.
 **
 ** This implments steps 4 thorough 22 of FIPS 186-3 A.1.2.1 and
 **                steps 16 through 34 of FIPS 186-2 C.6
 */
-#define MAX_ST_SEED_BITS (HASH_LENGTH_MAX * PR_BITS_PER_BYTE)
 static SECStatus
 makePrimefromPrimesShaweTaylor(
     HASH_HashType hashtype,          /* selected Hashing algorithm */
     unsigned int length,             /* input. Length of prime in bits. */
+    unsigned int seedlen,            /* input seed length in bits */
     mp_int *c0,                      /* seed prime */
     mp_int *q,                       /* sub prime, can be 1 */
     mp_int *prime,                   /* output.  */
     SECItem *prime_seed,             /* input/output.  */
     unsigned int *prime_gen_counter) /* input/output.  */
 {
     mp_int c;
     mp_int c0_2;
@@ -552,33 +552,32 @@ makePrimefromPrimesShaweTaylor(
     */
 
     /* Step 4/16 iterations = ceiling(length/outlen)-1 */
     iterations = (length + outlen - 1) / outlen; /* NOTE: iterations +1 */
     /* Step 5/17 old_counter = prime_gen_counter */
     old_counter = *prime_gen_counter;
     /*
     ** Comment: Generate a pseudorandom integer x in the interval
-    ** [2**(lenght-1), 2**length].
+    ** [2**(length-1), 2**length].
     **
     ** Step 6/18 x = 0
     */
     PORT_Memset(x, 0, sizeof(x));
     /*
     ** Step 7/19 for i = 0 to iterations do
     **  x = x + (HASH(prime_seed + i) * 2^(i*outlen))
     */
     for (i = 0; i < iterations; i++) {
         /* is bigger than prime_seed should get to */
         CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
-                                       MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
+                                       seedlen, &x[(iterations - i - 1) * hashlen]));
     }
     /* Step 8/20 prime_seed = prime_seed + iterations + 1 */
-    CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
-                           prime_seed));
+    CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
     /*
     ** Step 9/21 x = 2 ** (length-1) + x mod 2 ** (length-1)
     **
     **   This step mathematically sets the high bit and clears out
     **  all the other bits higher than length. 'x' is stored
     **  in the x array, MSB first. The above formula gives us an 'x'
     **  which is length bytes long and has the high bit set. We also know
     **  that length <= iterations*outlen since
@@ -590,17 +589,17 @@ makePrimefromPrimesShaweTaylor(
      * multiple of 8,*/
     bit = 1 << ((length - 1) & 0x7); /* select the proper bit in the byte */
     /* we need to zero out the rest of the bits in the byte above */
     mask = (bit - 1);
     /* now we set it */
     x[offset] = (mask & x[offset]) | bit;
     /*
     ** Comment: Generate a candidate prime c in the interval
-    ** [2**(lenght-1), 2**length].
+    ** [2**(length-1), 2**length].
     **
     ** Step 10 t = ceiling(x/(2q(p0)))
     ** Step 22 t = ceiling(x/(2(c0)))
     */
     CHECK_MPI_OK(mp_read_unsigned_octets(&t, &x[offset],
                                          hashlen * iterations - offset)); /* t = x */
     CHECK_MPI_OK(mp_mul(c0, q, &c0_2));                                   /* c0_2 is now c0*q */
     CHECK_MPI_OK(mp_add(&c0_2, &c0_2, &c0_2));                            /* c0_2 is now 2*q*c0 */
@@ -619,17 +618,17 @@ makePrimefromPrimesShaweTaylor(
 step_23:
     CHECK_MPI_OK(mp_mul(&t, &c0_2, &c));                /* c = t*2qc0 */
     CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c));        /* c= 2tqc0 + 1*/
     if (mpl_significant_bits(&c) > length) {            /* if c > 2**length */
         CHECK_MPI_OK(mp_sub_d(&c0_2, (mp_digit)1, &t)); /* t = 2qc0-1 */
         /* t = 2**(length-1) + 2qc0 -1 */
         CHECK_MPI_OK(mp_add(&two_length_minus_1, &t, &t));
         /* t = floor((2**(length-1)+2qc0 -1)/2qco)
-         *   = ceil(2**(lenght-2)/2qc0) */
+         *   = ceil(2**(length-2)/2qc0) */
         CHECK_MPI_OK(mp_div(&t, &c0_2, &t, NULL));
         CHECK_MPI_OK(mp_mul(&t, &c0_2, &c));
         CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c)); /* c= 2tqc0 + 1*/
     }
     /* Step 13/25 prime_gen_counter = prime_gen_counter + 1*/
     (*prime_gen_counter)++;
     /*
     ** Comment: Test the candidate prime c for primality; first pick an
@@ -640,23 +639,21 @@ step_23:
     PORT_Memset(x, 0, sizeof(x)); /* use x for a */
     /*
     ** Step 15/27 for i = 0 to iterations do
     **  a = a + (HASH(prime_seed + i) * 2^(i*outlen))
     **
     ** NOTE: we reuse the x array for 'a' initially.
     */
     for (i = 0; i < iterations; i++) {
-        /* MAX_ST_SEED_BITS is bigger than prime_seed should get to */
         CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
-                                       MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
+                                       seedlen, &x[(iterations - i - 1) * hashlen]));
     }
     /* Step 16/28 prime_seed = prime_seed + iterations + 1 */
-    CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
-                           prime_seed));
+    CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
     /* Step 17/29 a = 2 + (a mod (c-3)). */
     CHECK_MPI_OK(mp_read_unsigned_octets(&a, x, iterations * hashlen));
     CHECK_MPI_OK(mp_sub_d(&c, (mp_digit)3, &z)); /* z = c -3 */
     CHECK_MPI_OK(mp_mod(&a, &z, &a));            /* a = a mod c -3 */
     CHECK_MPI_OK(mp_add_d(&a, (mp_digit)2, &a)); /* a = 2 + a mod c -3 */
     /*
     ** Step 18 z = a**(2tq) mod p.
     ** Step 30 z = a**(2t) mod c.
@@ -737,16 +734,17 @@ makePrimefromSeedShaweTaylor(
 {
     mp_int c;
     mp_int c0;
     mp_int one;
     SECStatus rv = SECFailure;
     int hashlen = HASH_ResultLen(hashtype);
     int outlen = hashlen * PR_BITS_PER_BYTE;
     int offset;
+    int seedlen = input_seed->len * 8; /*seedlen is in bits */
     unsigned char bit, mask;
     unsigned char x[HASH_LENGTH_MAX * 2];
     mp_digit dummy;
     mp_err err = MP_OKAY;
     int i;
 
     MP_DIGITS(&c) = 0;
     MP_DIGITS(&c0) = 0;
@@ -770,30 +768,29 @@ makePrimefromSeedShaweTaylor(
     */
         rv = makePrimefromSeedShaweTaylor(hashtype, (length + 1) / 2 + 1,
                                           input_seed, &c0, prime_seed, prime_gen_counter);
         /* Step 15 if FAILURE is returned, return (FAILURE, 0, 0, 0). */
         if (rv != SECSuccess) {
             goto cleanup;
         }
         /* Steps 16-34 */
-        rv = makePrimefromPrimesShaweTaylor(hashtype, length, &c0, &one,
+        rv = makePrimefromPrimesShaweTaylor(hashtype, length, seedlen, &c0, &one,
                                             prime, prime_seed, prime_gen_counter);
         goto cleanup; /* we're done, one way or the other */
     }
     /* Step 3 prime_seed = input_seed */
     CHECK_SEC_OK(SECITEM_CopyItem(NULL, prime_seed, input_seed));
     /* Step 4 prime_gen_count = 0 */
     *prime_gen_counter = 0;
 
 step_5:
     /* Step 5 c = Hash(prime_seed) xor Hash(prime_seed+1). */
     CHECK_SEC_OK(HASH_HashBuf(hashtype, x, prime_seed->data, prime_seed->len));
-    CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1,
-                                   MAX_ST_SEED_BITS, &x[hashlen]));
+    CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1, seedlen, &x[hashlen]));
     for (i = 0; i < hashlen; i++) {
         x[i] = x[i] ^ x[i + hashlen];
     }
     /* Step 6 c = 2**length-1 + c mod 2**length-1 */
     /*   This step mathematically sets the high bit and clears out
     **  all the other bits higher than length. Right now c is stored
     **  in the x array, MSB first. The above formula gives us a c which
     **  is length bytes long and has the high bit set. We also know that
@@ -812,17 +809,17 @@ step_5:
     /* Step 7 c = c*floor(c/2) + 1 */
     /* set the low bit. much easier to find (the end of the array) */
     x[hashlen - 1] |= 1;
     /* now that we've set our bits, we can create our candidate "c" */
     CHECK_MPI_OK(mp_read_unsigned_octets(&c, &x[offset], hashlen - offset));
     /* Step 8 prime_gen_counter = prime_gen_counter + 1 */
     (*prime_gen_counter)++;
     /* Step 9 prime_seed = prime_seed + 2 */
-    CHECK_SEC_OK(addToSeed(prime_seed, 2, MAX_ST_SEED_BITS, prime_seed));
+    CHECK_SEC_OK(addToSeed(prime_seed, 2, seedlen, prime_seed));
     /* Step 10 Perform deterministic primality test on c. For example, since
     ** c is small, it's primality can be tested by trial division, See
     ** See Appendic C.7.
     **
     ** We in fact test with trial division. mpi has a built int trial divider
     ** that divides all divisors up to 2^16.
     */
     if (prime_tab[prime_tab_size - 1] < 0xFFF1) {
@@ -885,17 +882,18 @@ findQfromSeed(
     unsigned int L,             /* input.  Length of p in bits. */
     unsigned int N,             /* input.  Length of q in bits. */
     unsigned int g,             /* input.  Length of seed in bits. */
     const SECItem *seed,        /* input.  */
     mp_int *Q,                  /* input. */
     mp_int *Q_,                 /* output. */
     unsigned int *qseed_len,    /* output */
     HASH_HashType *hashtypePtr, /* output. Hash uses */
-    pqgGenType *typePtr)        /* output. Generation Type used */
+    pqgGenType *typePtr,        /* output. Generation Type used */
+    unsigned int *qgen_counter) /* output. q_counter */
 {
     HASH_HashType hashtype;
     SECItem firstseed = { 0, 0, 0 };
     SECItem qseed = { 0, 0, 0 };
     SECStatus rv;
 
     *qseed_len = 0; /* only set if FIPS186_3_ST_TYPE */
 
@@ -959,16 +957,17 @@ findQfromSeed(
          * accident, someone has been tweeking with the seeds, just
          * fail a this point. */
                 SECITEM_FreeItem(&qseed, PR_FALSE);
                 return SECFailure;
             }
             *qseed_len = qseed.len;
             *hashtypePtr = hashtype;
             *typePtr = FIPS186_3_ST_TYPE;
+            *qgen_counter = count;
             SECITEM_FreeItem(&qseed, PR_FALSE);
             return SECSuccess;
         }
         SECITEM_FreeItem(&qseed, PR_FALSE);
     }
     /* no hash algorithms found which match seed to Q, fail */
     return SECFailure;
 }
@@ -1385,29 +1384,36 @@ step_5:
         CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, N, &firstseed, &Q,
                                                   &qseed, &qgen_counter));
         /* Step 3. Use floor(L/2+1) and qseed to generate random prime p0
      * using Appendix C.6 */
         pgen_counter = 0;
         CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
                                                   &qseed, &p0, &pseed, &pgen_counter));
         /* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
-        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
+        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, seedBytes * 8,
                                                     &p0, &Q, &P, &pseed, &pgen_counter));
 
         /* combine all the seeds */
-        seed->len = firstseed.len + qseed.len + pseed.len;
+        if ((qseed.len > firstseed.len) || (pseed.len > firstseed.len)) {
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); /* shouldn't happen */
+            goto cleanup;
+        }
+        /* If the seed overflows, then pseed and qseed may have leading zeros which the mpl code clamps.
+         * we want to make sure those are added back in so the individual seed lengths are predictable from
+         * the overall seed length */
+        seed->len = firstseed.len * 3;
         seed->data = PORT_ArenaZAlloc(verify->arena, seed->len);
         if (seed->data == NULL) {
             goto cleanup;
         }
         PORT_Memcpy(seed->data, firstseed.data, firstseed.len);
-        PORT_Memcpy(seed->data + firstseed.len, pseed.data, pseed.len);
-        PORT_Memcpy(seed->data + firstseed.len + pseed.len, qseed.data, qseed.len);
-        counter = 0; /* (qgen_counter << 16) | pgen_counter; */
+        PORT_Memcpy(seed->data + 2 * firstseed.len - pseed.len, pseed.data, pseed.len);
+        PORT_Memcpy(seed->data + 3 * firstseed.len - qseed.len, qseed.data, qseed.len);
+        counter = (qgen_counter << 16) | pgen_counter;
 
         /* we've generated both P and Q now, skip to generating G */
         goto generate_G;
     }
     /* ******************************************************************
     ** Step 8. (Step 4 in 186-1)
     ** "Use a robust primality testing algorithm to test whether q is prime."
     **
@@ -1617,16 +1623,17 @@ PQG_VerifyParams(const PQGParams *params
 {
     SECStatus rv = SECSuccess;
     unsigned int g, n, L, N, offset, outlen;
     mp_int p0, P, Q, G, P_, Q_, G_, r, h;
     mp_err err = MP_OKAY;
     int j;
     unsigned int counter_max = 0; /* handle legacy L < 1024 */
     unsigned int qseed_len;
+    unsigned int qgen_counter_ = 0;
     SECItem pseed_ = { 0, 0, 0 };
     HASH_HashType hashtype;
     pqgGenType type;
 
 #define CHECKPARAM(cond)      \
     if (!(cond)) {            \
         *result = SECFailure; \
         goto cleanup;         \
@@ -1696,77 +1703,104 @@ PQG_VerifyParams(const PQGParams *params
     CHECKPARAM(mp_cmp_d(&r, 1) == 0);
     /* 5.  Q is prime */
     CHECKPARAM(mpp_pprime(&Q, prime_testcount_q(L, N)) == MP_YES);
     /* 6.  P is prime */
     CHECKPARAM(mpp_pprime(&P, prime_testcount_p(L, N)) == MP_YES);
     /* Steps 7-12 are done only if the optional PQGVerify is supplied. */
     /* continue processing P */
     /* 7.  counter < 4*L */
-    CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
     /* 8.  g >= N and g < 2*L   (g is length of seed in bits) */
-    g = vfy->seed.len * 8;
-    CHECKPARAM(g >= N && g < counter_max / 2);
+    /* step 7 and 8 are delayed until we determine which type of generation
+     * was used */
     /* 9.  Q generated from SEED matches Q in PQGParams. */
     /* This function checks all possible hash and generation types to
      * find a Q_ which matches Q. */
+    g = vfy->seed.len * 8;
     CHECKPARAM(findQfromSeed(L, N, g, &vfy->seed, &Q, &Q_, &qseed_len,
-                             &hashtype, &type) == SECSuccess);
+                             &hashtype, &type, &qgen_counter_) == SECSuccess);
     CHECKPARAM(mp_cmp(&Q, &Q_) == 0);
+    /* now we can do steps 7  & 8*/
+    if ((type == FIPS186_1_TYPE) || (type == FIPS186_3_TYPE)) {
+        CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
+        CHECKPARAM(g >= N && g < counter_max / 2);
+    }
     if (type == FIPS186_3_ST_TYPE) {
         SECItem qseed = { 0, 0, 0 };
         SECItem pseed = { 0, 0, 0 };
         unsigned int first_seed_len;
-        unsigned int pgen_counter = 0;
+        unsigned int pgen_counter_ = 0;
+        unsigned int qgen_counter = (vfy->counter >> 16) & 0xffff;
+        unsigned int pgen_counter = (vfy->counter) & 0xffff;
 
         /* extract pseed and qseed from domain_parameter_seed, which is
          * first_seed || pseed || qseed. qseed is first_seed + small_integer
-         * pseed is qseed + small_integer. This means most of the time
+         * mod the length of first_seed. pseed is qseed + small_integer mod
+         * the length of first_seed. This means most of the time
          * first_seed.len == qseed.len == pseed.len. Rarely qseed.len and/or
-         * pseed.len will be one greater than first_seed.len, so we can
-         * depend on the fact that
-         *   first_seed.len = floor(domain_parameter_seed.len/3).
-         * findQfromSeed returned qseed.len, so we can calculate pseed.len as
-         *   pseed.len = domain_parameter_seed.len - first_seed.len - qseed.len
-         * this is probably over kill, since 99.999% of the time they will all
-         * be equal.
-         *
-         * With the lengths, we can now find the offsets;
+         * pseed.len will be smaller because mpi clamps them. pqgGen
+         * automatically adds the zero pad back though, so we can depend
+         * domain_parameter_seed.len to be a multiple of three. We only have
+         * to deal with the fact that the returned seeds from our functions
+         * could be shorter.
+         *   first_seed.len = domain_parameter_seed.len/3
+         * We can now find the offsets;
          * first_seed.data = domain_parameter_seed.data + 0
          * pseed.data = domain_parameter_seed.data + first_seed.len
          * qseed.data = domain_parameter_seed.data
          *         + domain_paramter_seed.len - qseed.len
-         *
+         * We deal with pseed possibly having zero pad in the pseed check later.
          */
         first_seed_len = vfy->seed.len / 3;
         CHECKPARAM(qseed_len < vfy->seed.len);
         CHECKPARAM(first_seed_len * 8 > N - 1);
-        CHECKPARAM(first_seed_len + qseed_len < vfy->seed.len);
+        CHECKPARAM(first_seed_len * 8 < counter_max / 2);
+        CHECKPARAM(first_seed_len >= qseed_len);
         qseed.len = qseed_len;
         qseed.data = vfy->seed.data + vfy->seed.len - qseed.len;
-        pseed.len = vfy->seed.len - (first_seed_len + qseed_len);
+        pseed.len = first_seed_len;
         pseed.data = vfy->seed.data + first_seed_len;
 
         /*
          * now complete FIPS 186-3 A.1.2.1.2. Step 1 was completed
          * above in our initial checks, Step 2 was completed by
          * findQfromSeed */
 
         /* Step 3 (status, c0, prime_seed, prime_gen_counter) =
         ** (ST_Random_Prime((ceil(length/2)+1, input_seed)
         */
         CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
-                                                  &qseed, &p0, &pseed_, &pgen_counter));
+                                                  &qseed, &p0, &pseed_, &pgen_counter_));
         /* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
-        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
-                                                    &p0, &Q_, &P_, &pseed_, &pgen_counter));
+        CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, first_seed_len * 8,
+                                                    &p0, &Q_, &P_, &pseed_, &pgen_counter_));
         CHECKPARAM(mp_cmp(&P, &P_) == 0);
         /* make sure pseed wasn't tampered with (since it is part of
          * calculating G) */
+        if (pseed.len > pseed_.len) {
+            /* handle the case of zero pad for pseed */
+            int extra = pseed.len - pseed_.len;
+            int i;
+            for (i = 0; i < extra; i++) {
+                if (pseed.data[i] != 0) {
+                    *result = SECFailure;
+                    goto cleanup;
+                }
+            }
+            pseed.data += extra;
+            pseed.len -= extra;
+            /* the rest is handled in the normal compare below */
+        }
         CHECKPARAM(SECITEM_CompareItem(&pseed, &pseed_) == SECEqual);
+        if (vfy->counter != -1) {
+            CHECKPARAM(pgen_counter < counter_max);
+            CHECKPARAM(qgen_counter < counter_max);
+            CHECKPARAM((pgen_counter_ == pgen_counter));
+            CHECKPARAM((qgen_counter_ == qgen_counter));
+        }
     } else if (vfy->counter == -1) {
         /* If counter is set to -1, we are really only verifying G, skip
          * the remainder of the checks for P */
         CHECKPARAM(type != FIPS186_1_TYPE); /* we only do this for DSA2 */
     } else {
         /* 10. P generated from (L, counter, g, SEED, Q) matches P
          * in PQGParams. */
         outlen = HASH_ResultLen(hashtype) * PR_BITS_PER_BYTE;
--- a/security/nss/lib/freebl/rijndael.c
+++ b/security/nss/lib/freebl/rijndael.c
@@ -1027,23 +1027,29 @@ AES_CreateContext(const unsigned char *k
  * AES_DestroyContext
  *
  * Zero an AES cipher context.  If freeit is true, also free the pointer
  * to the context.
  */
 void
 AES_DestroyContext(AESContext *cx, PRBool freeit)
 {
+    void *mem = cx->mem;
     if (cx->worker_cx && cx->destroy) {
         (*cx->destroy)(cx->worker_cx, PR_TRUE);
         cx->worker_cx = NULL;
         cx->destroy = NULL;
     }
+    PORT_Memset(cx, 0, sizeof(AESContext));
     if (freeit) {
-        PORT_Free(cx->mem);
+        PORT_Free(mem);
+    } else {
+        /* if we are not freeing the context, restore mem, We may get called
+         * again to actually free the context */
+        cx->mem = mem;
     }
 }
 
 /*
  * AES_Encrypt
  *
  * Encrypt an arbitrary-length buffer.  The output buffer must already be
  * allocated to at least inputLen.
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -1146,8 +1146,14 @@ HASH_GetHashOidTagByHashType;
 ;+       *;
 ;+};
 ;+NSS_3.44 { 	# NSS 3.44 release
 ;+    global:
 CERT_GetCertificateDer;
 ;+    local:
 ;+       *;
 ;+};
+;+NSS_3.45 { 	# NSS 3.45 release
+;+    global:
+PK11_FindRawCertsWithSubject;
+;+    local:
+;+       *;
+;+};
--- a/security/nss/lib/pk11wrap/pk11obj.c
+++ b/security/nss/lib/pk11wrap/pk11obj.c
@@ -1,14 +1,16 @@
 /* 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 manages object type indepentent functions.
  */
+#include <limits.h>
+
 #include "seccomon.h"
 #include "secmod.h"
 #include "secmodi.h"
 #include "secmodti.h"
 #include "pkcs11.h"
 #include "pkcs11t.h"
 #include "pk11func.h"
 #include "keyhi.h"
@@ -1878,16 +1880,106 @@ pk11_FindObjectsByTemplate(PK11SlotInfo 
     if (objID && (*object_count == 0)) {
         PORT_Free(objID);
         return NULL;
     }
     if (objID == NULL)
         *object_count = -1;
     return objID;
 }
+
+SECStatus
+PK11_FindRawCertsWithSubject(PK11SlotInfo *slot, SECItem *derSubject,
+                             CERTCertificateList **results)
+{
+    if (!slot || !derSubject || !results) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+    *results = NULL;
+
+    // derSubject->data may be null. If so, derSubject->len must be 0.
+    if (!derSubject->data && derSubject->len != 0) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return SECFailure;
+    }
+
+    CK_CERTIFICATE_TYPE ckc_x_509 = CKC_X_509;
+    CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
+    CK_ATTRIBUTE subjectTemplate[] = {
+        { CKA_CERTIFICATE_TYPE, &ckc_x_509, sizeof(ckc_x_509) },
+        { CKA_CLASS, &cko_certificate, sizeof(cko_certificate) },
+        { CKA_SUBJECT, derSubject->data, derSubject->len },
+    };
+    int templateCount = sizeof(subjectTemplate) / sizeof(subjectTemplate[0]);
+    int handleCount = 0;
+    CK_OBJECT_HANDLE *handles =
+        pk11_FindObjectsByTemplate(slot, subjectTemplate, templateCount,
+                                   &handleCount);
+    if (!handles) {
+        // pk11_FindObjectsByTemplate indicates there was an error by setting
+        // handleCount to -1 (and it has set an error with PORT_SetError).
+        if (handleCount == -1) {
+            return SECFailure;
+        }
+        return SECSuccess;
+    }
+    PORT_Assert(handleCount > 0);
+    if (handleCount <= 0) {
+        PORT_Free(handles);
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return SECFailure;
+    }
+    if (handleCount > INT_MAX / sizeof(SECItem)) {
+        PORT_Free(handles);
+        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+        return SECFailure;
+    }
+    PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    if (!arena) {
+        PORT_Free(handles);
+        return SECFailure;
+    }
+    CERTCertificateList *rawCertificates =
+        PORT_ArenaNew(arena, CERTCertificateList);
+    if (!rawCertificates) {
+        PORT_Free(handles);
+        PORT_FreeArena(arena, PR_FALSE);
+        return SECFailure;
+    }
+    rawCertificates->arena = arena;
+    rawCertificates->certs = PORT_ArenaNewArray(arena, SECItem, handleCount);
+    if (!rawCertificates->certs) {
+        PORT_Free(handles);
+        PORT_FreeArena(arena, PR_FALSE);
+        return SECFailure;
+    }
+    rawCertificates->len = handleCount;
+    int handleIndex;
+    for (handleIndex = 0; handleIndex < handleCount; handleIndex++) {
+        SECStatus rv =
+            PK11_ReadAttribute(slot, handles[handleIndex], CKA_VALUE, arena,
+                               &rawCertificates->certs[handleIndex]);
+        if (rv != SECSuccess) {
+            PORT_Free(handles);
+            PORT_FreeArena(arena, PR_FALSE);
+            return SECFailure;
+        }
+        if (!rawCertificates->certs[handleIndex].data) {
+            PORT_Free(handles);
+            PORT_FreeArena(arena, PR_FALSE);
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+            return SECFailure;
+        }
+    }
+    PORT_Free(handles);
+    *results = rawCertificates;
+    return SECSuccess;
+}
+
 /*
  * given a PKCS #11 object, match it's peer based on the KeyID. searchID
  * is typically a privateKey or a certificate while the peer is the opposite
  */
 CK_OBJECT_HANDLE
 PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE searchID,
                CK_OBJECT_CLASS matchclass)
 {
--- a/security/nss/lib/pk11wrap/pk11pub.h
+++ b/security/nss/lib/pk11wrap/pk11pub.h
@@ -870,16 +870,27 @@ SECStatus PK11_WriteRawAttribute(PK11Obj
 /*
  * PK11_GetAllSlotsForCert returns all the slots that a given certificate
  * exists on, since it's possible for a cert to exist on more than one
  * PKCS#11 token.
  */
 PK11SlotList *
 PK11_GetAllSlotsForCert(CERTCertificate *cert, void *arg);
 
+/*
+ * Finds all certificates on the given slot with the given subject distinguished
+ * name and returns them as DER bytes. If no such certificates can be found,
+ * returns SECSuccess and sets *results to NULL. If a failure is encountered
+ * while fetching any of the matching certificates, SECFailure is returned and
+ * *results will be NULL.
+ */
+SECStatus
+PK11_FindRawCertsWithSubject(PK11SlotInfo *slot, SECItem *derSubject,
+                             CERTCertificateList **results);
+
 /**********************************************************************
  * New functions which are already deprecated....
  **********************************************************************/
 SECItem *
 PK11_GetLowLevelKeyIDForCert(PK11SlotInfo *slot,
                              CERTCertificate *cert, void *pwarg);
 SECItem *
 PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *key);
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -4722,16 +4722,23 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
                        pairwise_digest_length,
                        signature,
                        &signature_length);
         if (crv != CKR_OK) {
             PORT_Free(signature);
             return crv;
         }
 
+        /* detect trivial signing transforms */
+        if ((signature_length >= pairwise_digest_length) &&
+            (PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) {
+            PORT_Free(signature);
+            return CKR_DEVICE_ERROR;
+        }
+
         /* Verify the known hash using the public key. */
         crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
         if (crv != CKR_OK) {
             PORT_Free(signature);
             return crv;
         }
 
         crv = NSC_Verify(hSession,
@@ -7557,40 +7564,55 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
             SHA512_HashBuf(key_block, (const unsigned char *)att->attrib.pValue,
                            att->attrib.ulValueLen);
 
             crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);
             break;
 
         case CKM_DH_PKCS_DERIVE: {
             SECItem derived, dhPublic;
-            SECItem dhPrime, dhValue;
+            SECItem dhPrime, dhSubPrime, dhValue;
             /* sourceKey - values for the local existing low key */
             /* get prime and value attributes */
             crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
-            if (crv != SECSuccess)
+            if (crv != CKR_OK)
                 break;
             crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
-            if (crv != SECSuccess) {
+            if (crv != CKR_OK) {
                 PORT_Free(dhPrime.data);
                 break;
             }
 
             dhPublic.data = pMechanism->pParameter;
             dhPublic.len = pMechanism->ulParameterLen;
 
+            /* If the caller bothered to provide Q, use Q to validate
+             * the public key. */
+            crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, sourceKey, CKA_SUBPRIME);
+            if (crv == CKR_OK) {
+                rv = KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime);
+                PORT_Free(dhSubPrime.data);
+                if (rv != SECSuccess) {
+                    crv = CKR_ARGUMENTS_BAD;
+                    PORT_Free(dhPrime.data);
+                    PORT_Free(dhValue.data);
+                    break;
+                }
+            }
+
             /* calculate private value - oct */
             rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
 
             PORT_Free(dhPrime.data);
             PORT_Free(dhValue.data);
 
             if (rv == SECSuccess) {
                 sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
                 PORT_ZFree(derived.data, derived.len);
+                crv = CKR_OK;
             } else
                 crv = CKR_HOST_MEMORY;
 
             break;
         }
 
         case CKM_ECDH1_DERIVE:
         case CKM_ECDH1_COFACTOR_DERIVE: {