Bug 1401594 - land NSS 4bf658832d89 UPGRADE_NSS_RELEASE, r=me
authorTim Taubert <ttaubert@mozilla.com>
Thu, 12 Oct 2017 15:34:02 +0200
changeset 385796 ce1462f8f6cd02014d9451ab1f050f6c274a55a9
parent 385795 df8f9a0ccc91adf71e23280b5eefd7d3b6064b04
child 385797 1f4d35d137631cde34f318fac0c33421d5360dc3
push id96104
push userttaubert@mozilla.com
push dateThu, 12 Oct 2017 13:34:56 +0000
treeherdermozilla-inbound@ce1462f8f6cd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1401594
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1401594 - land NSS 4bf658832d89 UPGRADE_NSS_RELEASE, r=me
security/nss/TAG-INFO
security/nss/coreconf/coreconf.dep
security/nss/gtests/pk11_gtest/pk11_ecdsa_unittest.cc
security/nss/gtests/pk11_gtest/pk11_rsapss_unittest.cc
security/nss/gtests/pk11_gtest/pk11_signature_test.h
security/nss/gtests/softoken_gtest/softoken_gtest.cc
security/nss/lib/softoken/sftkdb.c
security/nss/lib/softoken/sftkdbti.h
security/nss/lib/softoken/sftkpwd.c
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-6fb9c5396d52
+f3766809817b
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/security/nss/gtests/pk11_gtest/pk11_ecdsa_unittest.cc
+++ b/security/nss/gtests/pk11_gtest/pk11_ecdsa_unittest.cc
@@ -10,145 +10,159 @@
 #include "gtest/gtest.h"
 #include "scoped_ptrs.h"
 
 #include "pk11_ecdsa_vectors.h"
 #include "pk11_signature_test.h"
 
 namespace nss_test {
 
-class Pkcs11EcdsaTest : public Pk11SignatureTest {
+class Pkcs11EcdsaTestBase : public Pk11SignatureTest {
  protected:
-  CK_MECHANISM_TYPE mechanism() { return CKM_ECDSA; }
-  SECItem* parameters() { return nullptr; }
+  Pkcs11EcdsaTestBase(SECOidTag hash_oid)
+      : Pk11SignatureTest(CKM_ECDSA, hash_oid) {}
 };
 
-class Pkcs11EcdsaSha256Test : public Pkcs11EcdsaTest {
- protected:
-  SECOidTag hashOID() { return SEC_OID_SHA256; }
+struct Pkcs11EcdsaTestParams {
+  SECOidTag hash_oid_;
+  Pkcs11SignatureTestParams sig_params_;
 };
 
-class Pkcs11EcdsaSha384Test : public Pkcs11EcdsaTest {
- protected:
-  SECOidTag hashOID() { return SEC_OID_SHA384; }
-};
-
-class Pkcs11EcdsaSha512Test : public Pkcs11EcdsaTest {
- protected:
-  SECOidTag hashOID() { return SEC_OID_SHA512; }
+class Pkcs11EcdsaTest
+    : public Pkcs11EcdsaTestBase,
+      public ::testing::WithParamInterface<Pkcs11EcdsaTestParams> {
+ public:
+  Pkcs11EcdsaTest() : Pkcs11EcdsaTestBase(GetParam().hash_oid_) {}
 };
 
-TEST_F(Pkcs11EcdsaSha256Test, VerifyP256) {
-  SIG_TEST_VECTOR_VERIFY(kP256Spki, kP256Data, kP256Signature)
-}
-TEST_F(Pkcs11EcdsaSha256Test, SignAndVerifyP256) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kP256Pkcs8, kP256Spki, kP256Data)
+TEST_P(Pkcs11EcdsaTest, Verify) { Verify(GetParam().sig_params_); }
+
+TEST_P(Pkcs11EcdsaTest, SignAndVerify) {
+  SignAndVerify(GetParam().sig_params_);
 }
 
-TEST_F(Pkcs11EcdsaSha384Test, VerifyP384) {
-  SIG_TEST_VECTOR_VERIFY(kP384Spki, kP384Data, kP384Signature)
-}
-TEST_F(Pkcs11EcdsaSha384Test, SignAndVerifyP384) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kP384Pkcs8, kP384Spki, kP384Data)
-}
+static const Pkcs11EcdsaTestParams kEcdsaVectors[] = {
+    {SEC_OID_SHA256,
+     {DataBuffer(kP256Pkcs8, sizeof(kP256Pkcs8)),
+      DataBuffer(kP256Spki, sizeof(kP256Spki)),
+      DataBuffer(kP256Data, sizeof(kP256Data)),
+      DataBuffer(kP256Signature, sizeof(kP256Signature))}},
+    {SEC_OID_SHA384,
+     {DataBuffer(kP384Pkcs8, sizeof(kP384Pkcs8)),
+      DataBuffer(kP384Spki, sizeof(kP384Spki)),
+      DataBuffer(kP384Data, sizeof(kP384Data)),
+      DataBuffer(kP384Signature, sizeof(kP384Signature))}},
+    {SEC_OID_SHA512,
+     {DataBuffer(kP521Pkcs8, sizeof(kP521Pkcs8)),
+      DataBuffer(kP521Spki, sizeof(kP521Spki)),
+      DataBuffer(kP521Data, sizeof(kP521Data)),
+      DataBuffer(kP521Signature, sizeof(kP521Signature))}}};
 
-TEST_F(Pkcs11EcdsaSha512Test, VerifyP521) {
-  SIG_TEST_VECTOR_VERIFY(kP521Spki, kP521Data, kP521Signature)
-}
-TEST_F(Pkcs11EcdsaSha512Test, SignAndVerifyP521) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kP521Pkcs8, kP521Spki, kP521Data)
-}
+INSTANTIATE_TEST_CASE_P(EcdsaSignVerify, Pkcs11EcdsaTest,
+                        ::testing::ValuesIn(kEcdsaVectors));
+
+class Pkcs11EcdsaSha256Test : public Pkcs11EcdsaTestBase {
+ public:
+  Pkcs11EcdsaSha256Test() : Pkcs11EcdsaTestBase(SEC_OID_SHA256) {}
+};
 
 // Importing a private key in PKCS#8 format must fail when the outer AlgID
 // struct contains neither id-ecPublicKey nor a namedCurve parameter.
 TEST_F(Pkcs11EcdsaSha256Test, ImportNoCurveOIDOrAlgorithmParams) {
-  EXPECT_FALSE(ImportPrivateKey(kP256Pkcs8NoCurveOIDOrAlgorithmParams,
-                                sizeof(kP256Pkcs8NoCurveOIDOrAlgorithmParams)));
+  DataBuffer k(kP256Pkcs8NoCurveOIDOrAlgorithmParams,
+               sizeof(kP256Pkcs8NoCurveOIDOrAlgorithmParams));
+  EXPECT_FALSE(ImportPrivateKey(k));
 };
 
 // Importing a private key in PKCS#8 format must succeed when only the outer
 // AlgID struct contains the namedCurve parameters.
 TEST_F(Pkcs11EcdsaSha256Test, ImportOnlyAlgorithmParams) {
-  EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(
-      kP256Pkcs8OnlyAlgorithmParams, sizeof(kP256Pkcs8OnlyAlgorithmParams),
-      kP256Data, sizeof(kP256Data)));
+  DataBuffer k(kP256Pkcs8OnlyAlgorithmParams,
+               sizeof(kP256Pkcs8OnlyAlgorithmParams));
+  DataBuffer data(kP256Data, sizeof(kP256Data));
+  DataBuffer sig;
+  EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig));
 };
 
 // Importing a private key in PKCS#8 format must succeed when the outer AlgID
 // struct and the inner ECPrivateKey contain the same namedCurve parameters.
 // The inner curveOID is always ignored, so only the outer one will be used.
 TEST_F(Pkcs11EcdsaSha256Test, ImportMatchingCurveOIDAndAlgorithmParams) {
-  EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(
-      kP256Pkcs8MatchingCurveOIDAndAlgorithmParams,
-      sizeof(kP256Pkcs8MatchingCurveOIDAndAlgorithmParams), kP256Data,
-      sizeof(kP256Data)));
+  DataBuffer k(kP256Pkcs8MatchingCurveOIDAndAlgorithmParams,
+               sizeof(kP256Pkcs8MatchingCurveOIDAndAlgorithmParams));
+  DataBuffer data(kP256Data, sizeof(kP256Data));
+  DataBuffer sig;
+  EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig));
 };
 
 // Importing a private key in PKCS#8 format must succeed when the outer AlgID
 // struct and the inner ECPrivateKey contain dissimilar namedCurve parameters.
 // The inner curveOID is always ignored, so only the outer one will be used.
 TEST_F(Pkcs11EcdsaSha256Test, ImportDissimilarCurveOIDAndAlgorithmParams) {
-  EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(
-      kP256Pkcs8DissimilarCurveOIDAndAlgorithmParams,
-      sizeof(kP256Pkcs8DissimilarCurveOIDAndAlgorithmParams), kP256Data,
-      sizeof(kP256Data)));
+  DataBuffer k(kP256Pkcs8DissimilarCurveOIDAndAlgorithmParams,
+               sizeof(kP256Pkcs8DissimilarCurveOIDAndAlgorithmParams));
+  DataBuffer data(kP256Data, sizeof(kP256Data));
+  DataBuffer sig;
+  EXPECT_TRUE(ImportPrivateKeyAndSignHashedData(k, data, &sig));
 };
 
 // Importing a private key in PKCS#8 format must fail when the outer ASN.1
 // AlgorithmID struct contains only id-ecPublicKey but no namedCurve parameter.
 TEST_F(Pkcs11EcdsaSha256Test, ImportNoAlgorithmParams) {
-  EXPECT_FALSE(ImportPrivateKey(kP256Pkcs8NoAlgorithmParams,
-                                sizeof(kP256Pkcs8NoAlgorithmParams)));
+  DataBuffer k(kP256Pkcs8NoAlgorithmParams,
+               sizeof(kP256Pkcs8NoAlgorithmParams));
+  EXPECT_FALSE(ImportPrivateKey(k));
 };
 
 // Importing a private key in PKCS#8 format must fail when id-ecPublicKey is
 // given (so we know it's an EC key) but the namedCurve parameter is unknown.
 TEST_F(Pkcs11EcdsaSha256Test, ImportInvalidAlgorithmParams) {
-  EXPECT_FALSE(ImportPrivateKey(kP256Pkcs8InvalidAlgorithmParams,
-                                sizeof(kP256Pkcs8InvalidAlgorithmParams)));
+  DataBuffer k(kP256Pkcs8InvalidAlgorithmParams,
+               sizeof(kP256Pkcs8InvalidAlgorithmParams));
+  EXPECT_FALSE(ImportPrivateKey(k));
 };
 
 // Importing a private key in PKCS#8 format with a point not on the curve will
 // succeed. Using the contained public key however will fail when trying to
 // import it before using it for any operation.
 TEST_F(Pkcs11EcdsaSha256Test, ImportPointNotOnCurve) {
-  ScopedSECKEYPrivateKey privKey(ImportPrivateKey(
-      kP256Pkcs8PointNotOnCurve, sizeof(kP256Pkcs8PointNotOnCurve)));
+  DataBuffer k(kP256Pkcs8PointNotOnCurve, sizeof(kP256Pkcs8PointNotOnCurve));
+  ScopedSECKEYPrivateKey privKey(ImportPrivateKey(k));
   ASSERT_TRUE(privKey);
 
   ScopedSECKEYPublicKey pubKey(SECKEY_ConvertToPublicKey(privKey.get()));
   ASSERT_TRUE(pubKey);
 
   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
   ASSERT_TRUE(slot);
 
   auto handle = PK11_ImportPublicKey(slot.get(), pubKey.get(), false);
   EXPECT_EQ(handle, static_cast<decltype(handle)>(CK_INVALID_HANDLE));
 };
 
 // Importing a private key in PKCS#8 format must fail when no point is given.
 // PK11 currently offers no APIs to derive raw public keys from private values.
 TEST_F(Pkcs11EcdsaSha256Test, ImportNoPublicKey) {
-  EXPECT_FALSE(
-      ImportPrivateKey(kP256Pkcs8NoPublicKey, sizeof(kP256Pkcs8NoPublicKey)));
+  DataBuffer k(kP256Pkcs8NoPublicKey, sizeof(kP256Pkcs8NoPublicKey));
+  EXPECT_FALSE(ImportPrivateKey(k));
 };
 
 // Importing a public key in SPKI format must fail when id-ecPublicKey is
 // given (so we know it's an EC key) but the namedCurve parameter is missing.
 TEST_F(Pkcs11EcdsaSha256Test, ImportSpkiNoAlgorithmParams) {
-  EXPECT_FALSE(ImportPublicKey(kP256SpkiNoAlgorithmParams,
-                               sizeof(kP256SpkiNoAlgorithmParams)));
+  DataBuffer k(kP256SpkiNoAlgorithmParams, sizeof(kP256SpkiNoAlgorithmParams));
+  EXPECT_FALSE(ImportPublicKey(k));
 }
 
 // Importing a public key in SPKI format with a point not on the curve will
 // succeed. Using the public key however will fail when trying to import
 // it before using it for any operation.
 TEST_F(Pkcs11EcdsaSha256Test, ImportSpkiPointNotOnCurve) {
-  ScopedSECKEYPublicKey pubKey(ImportPublicKey(
-      kP256SpkiPointNotOnCurve, sizeof(kP256SpkiPointNotOnCurve)));
+  DataBuffer k(kP256SpkiPointNotOnCurve, sizeof(kP256SpkiPointNotOnCurve));
+  ScopedSECKEYPublicKey pubKey(ImportPublicKey(k));
   ASSERT_TRUE(pubKey);
 
   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
   ASSERT_TRUE(slot);
 
   auto handle = PK11_ImportPublicKey(slot.get(), pubKey.get(), false);
   EXPECT_EQ(handle, static_cast<decltype(handle)>(CK_INVALID_HANDLE));
 }
--- a/security/nss/gtests/pk11_gtest/pk11_rsapss_unittest.cc
+++ b/security/nss/gtests/pk11_gtest/pk11_rsapss_unittest.cc
@@ -7,44 +7,42 @@
 #include <memory>
 #include "nss.h"
 #include "pk11pub.h"
 #include "sechash.h"
 
 #include "gtest/gtest.h"
 #include "scoped_ptrs.h"
 
+#include "pk11_signature_test.h"
 #include "pk11_rsapss_vectors.h"
-#include "pk11_signature_test.h"
 
 namespace nss_test {
 
-class Pkcs11RsaPssVectorTest : public Pk11SignatureTest {
+class Pkcs11RsaPssTest : public Pk11SignatureTest {
  public:
-  Pkcs11RsaPssVectorTest() {
+  Pkcs11RsaPssTest() : Pk11SignatureTest(CKM_RSA_PKCS_PSS, SEC_OID_SHA1) {
     rsaPssParams_.hashAlg = CKM_SHA_1;
     rsaPssParams_.mgf = CKG_MGF1_SHA1;
     rsaPssParams_.sLen = HASH_ResultLenByOidTag(SEC_OID_SHA1);
 
     params_.type = siBuffer;
     params_.data = reinterpret_cast<unsigned char*>(&rsaPssParams_);
     params_.len = sizeof(rsaPssParams_);
   }
 
  protected:
-  CK_MECHANISM_TYPE mechanism() { return CKM_RSA_PKCS_PSS; }
-  SECItem* parameters() { return &params_; }
-  SECOidTag hashOID() { return SEC_OID_SHA1; }
+  const SECItem* parameters() const { return &params_; }
 
  private:
   CK_RSA_PKCS_PSS_PARAMS rsaPssParams_;
   SECItem params_;
 };
 
-TEST_F(Pkcs11RsaPssVectorTest, GenerateAndSignAndVerify) {
+TEST_F(Pkcs11RsaPssTest, GenerateAndSignAndVerify) {
   // Sign data with a 1024-bit RSA key, using PSS/SHA-256.
   SECOidTag hashOid = SEC_OID_SHA256;
   CK_MECHANISM_TYPE hashMech = CKM_SHA256;
   CK_RSA_PKCS_MGF_TYPE mgf = CKG_MGF1_SHA256;
   PK11RSAGenParams rsaGenParams = {1024, 0x10001};
 
   // Generate RSA key pair.
   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
@@ -90,110 +88,61 @@ TEST_F(Pkcs11RsaPssVectorTest, GenerateA
   // Verification with original data but the wrong signature must fail.
   data.data[0] ^= 0xff;  // Revert previous changes.
   sig.data[0] ^= 0xff;
   rv = PK11_VerifyWithMechanism(pubKey.get(), mechanism(), &params, &sig, &data,
                                 nullptr);
   EXPECT_EQ(rv, SECFailure);
 }
 
-// RSA-PSS test vectors, pss-vect.txt, Example 1.1: A 1024-bit RSA Key Pair
-// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
-TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature1) {
-  SIG_TEST_VECTOR_VERIFY(kTestVector1Spki, kTestVector1Data, kTestVector1Sig);
-}
-TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify1) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector1Pkcs8, kTestVector1Spki,
-                              kTestVector1Data);
-}
+class Pkcs11RsaPssVectorTest
+    : public Pkcs11RsaPssTest,
+      public ::testing::WithParamInterface<Pkcs11SignatureTestParams> {};
 
-// RSA-PSS test vectors, pss-vect.txt, Example 2.1: A 1025-bit RSA Key Pair
-// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
-TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature2) {
-  SIG_TEST_VECTOR_VERIFY(kTestVector2Spki, kTestVector2Data, kTestVector2Sig);
-}
-TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify2) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector2Pkcs8, kTestVector2Spki,
-                              kTestVector2Data);
-}
+TEST_P(Pkcs11RsaPssVectorTest, Verify) { Verify(GetParam()); }
+
+TEST_P(Pkcs11RsaPssVectorTest, SignAndVerify) { SignAndVerify(GetParam()); }
 
-// RSA-PSS test vectors, pss-vect.txt, Example 3.1: A 1026-bit RSA Key Pair
-// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
-TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature3) {
-  SIG_TEST_VECTOR_VERIFY(kTestVector3Spki, kTestVector3Data, kTestVector3Sig);
-}
-TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify3) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector3Pkcs8, kTestVector3Spki,
-                              kTestVector3Data);
-}
-
-// RSA-PSS test vectors, pss-vect.txt, Example 4.1: A 1027-bit RSA Key Pair
-// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
-TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature4) {
-  SIG_TEST_VECTOR_VERIFY(kTestVector4Spki, kTestVector4Data, kTestVector4Sig);
-}
-TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify4) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector4Pkcs8, kTestVector4Spki,
-                              kTestVector4Data);
-}
-
-// RSA-PSS test vectors, pss-vect.txt, Example 5.1: A 1028-bit RSA Key Pair
-// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
-TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature5) {
-  SIG_TEST_VECTOR_VERIFY(kTestVector5Spki, kTestVector5Data, kTestVector5Sig);
-}
-TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify5) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector5Pkcs8, kTestVector5Spki,
-                              kTestVector5Data);
-}
+#define VECTOR(pkcs8, spki, data, sig)                                \
+  {                                                                   \
+    DataBuffer(pkcs8, sizeof(pkcs8)), DataBuffer(spki, sizeof(spki)), \
+        DataBuffer(data, sizeof(data)), DataBuffer(sig, sizeof(sig))  \
+  }
+#define VECTOR_N(n)                                                         \
+  VECTOR(kTestVector##n##Pkcs8, kTestVector##n##Spki, kTestVector##n##Data, \
+         kTestVector##n##Sig)
 
-// RSA-PSS test vectors, pss-vect.txt, Example 6.1: A 1029-bit RSA Key Pair
-// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
-TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature6) {
-  SIG_TEST_VECTOR_VERIFY(kTestVector6Spki, kTestVector6Data, kTestVector6Sig);
-}
-TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify6) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector6Pkcs8, kTestVector6Spki,
-                              kTestVector6Data);
-}
-
-// RSA-PSS test vectors, pss-vect.txt, Example 7.1: A 1030-bit RSA Key Pair
-// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
-TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature7) {
-  SIG_TEST_VECTOR_VERIFY(kTestVector7Spki, kTestVector7Data, kTestVector7Sig);
-}
-TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify7) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector7Pkcs8, kTestVector7Spki,
-                              kTestVector7Data);
-}
+static const Pkcs11SignatureTestParams kRsaPssVectors[] = {
+    // RSA-PSS test vectors, pss-vect.txt, Example 1.1: A 1024-bit RSA Key Pair
+    // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
+    VECTOR_N(1),
+    // RSA-PSS test vectors, pss-vect.txt, Example 2.1: A 1025-bit RSA Key Pair
+    // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
+    VECTOR_N(2),
+    // RSA-PSS test vectors, pss-vect.txt, Example 3.1: A 1026-bit RSA Key Pair
+    // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
+    VECTOR_N(3),
+    // RSA-PSS test vectors, pss-vect.txt, Example 4.1: A 1027-bit RSA Key Pair
+    // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
+    VECTOR_N(4),
+    // RSA-PSS test vectors, pss-vect.txt, Example 5.1: A 1028-bit RSA Key Pair
+    // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
+    VECTOR_N(5),
+    // RSA-PSS test vectors, pss-vect.txt, Example 6.1: A 1029-bit RSA Key Pair
+    // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
+    VECTOR_N(6),
+    // RSA-PSS test vectors, pss-vect.txt, Example 7.1: A 1030-bit RSA Key Pair
+    // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
+    VECTOR_N(7),
+    // RSA-PSS test vectors, pss-vect.txt, Example 8.1: A 1031-bit RSA Key Pair
+    // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
+    VECTOR_N(8),
+    // RSA-PSS test vectors, pss-vect.txt, Example 9.1: A 1536-bit RSA Key Pair
+    // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
+    VECTOR_N(9),
+    // RSA-PSS test vectors, pss-vect.txt, Example 10.1: A 2048-bit RSA Key Pair
+    // <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
+    VECTOR_N(10)};
 
-// RSA-PSS test vectors, pss-vect.txt, Example 8.1: A 1031-bit RSA Key Pair
-// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
-TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature8) {
-  SIG_TEST_VECTOR_VERIFY(kTestVector8Spki, kTestVector8Data, kTestVector8Sig);
-}
-TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify8) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector8Pkcs8, kTestVector8Spki,
-                              kTestVector8Data);
-}
-
-// RSA-PSS test vectors, pss-vect.txt, Example 9.1: A 1536-bit RSA Key Pair
-// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
-TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature9) {
-  SIG_TEST_VECTOR_VERIFY(kTestVector9Spki, kTestVector9Data, kTestVector9Sig);
-}
-TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify9) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector9Pkcs8, kTestVector9Spki,
-                              kTestVector9Data);
-}
-
-// RSA-PSS test vectors, pss-vect.txt, Example 10.1: A 2048-bit RSA Key Pair
-// <ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip>
-TEST_F(Pkcs11RsaPssVectorTest, VerifyKnownSignature10) {
-  SIG_TEST_VECTOR_VERIFY(kTestVector10Spki, kTestVector10Data,
-                         kTestVector10Sig);
-}
-TEST_F(Pkcs11RsaPssVectorTest, SignAndVerify10) {
-  SIG_TEST_VECTOR_SIGN_VERIFY(kTestVector10Pkcs8, kTestVector10Spki,
-                              kTestVector10Data);
-}
+INSTANTIATE_TEST_CASE_P(RsaPssSignVerify, Pkcs11RsaPssVectorTest,
+                        ::testing::ValuesIn(kRsaPssVectors));
 
 }  // namespace nss_test
--- a/security/nss/gtests/pk11_gtest/pk11_signature_test.h
+++ b/security/nss/gtests/pk11_gtest/pk11_signature_test.h
@@ -4,135 +4,133 @@
 
 #include <memory>
 #include "nss.h"
 #include "pk11pub.h"
 #include "sechash.h"
 
 #include "cpputil.h"
 #include "scoped_ptrs.h"
+#include "databuffer.h"
 
 #include "gtest/gtest.h"
 
 namespace nss_test {
 
+// For test vectors.
+struct Pkcs11SignatureTestParams {
+  const DataBuffer pkcs8_;
+  const DataBuffer spki_;
+  const DataBuffer data_;
+  const DataBuffer signature_;
+};
+
 class Pk11SignatureTest : public ::testing::Test {
  protected:
-  virtual CK_MECHANISM_TYPE mechanism() = 0;
-  virtual SECItem* parameters() = 0;
-  virtual SECOidTag hashOID() = 0;
+  Pk11SignatureTest(CK_MECHANISM_TYPE mechanism, SECOidTag hash_oid)
+      : mechanism_(mechanism), hash_oid_(hash_oid) {}
 
-  ScopedSECKEYPrivateKey ImportPrivateKey(const uint8_t* pkcs8,
-                                          size_t pkcs8_len) {
+  virtual const SECItem* parameters() const { return nullptr; }
+  CK_MECHANISM_TYPE mechanism() const { return mechanism_; }
+
+  ScopedSECKEYPrivateKey ImportPrivateKey(const DataBuffer& pkcs8) {
     ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
     if (!slot) {
+      ADD_FAILURE() << "No slot";
       return nullptr;
     }
 
-    SECItem pkcs8Item = {siBuffer, toUcharPtr(pkcs8),
-                         static_cast<unsigned int>(pkcs8_len)};
+    SECItem pkcs8Item = {siBuffer, toUcharPtr(pkcs8.data()),
+                         static_cast<unsigned int>(pkcs8.len())};
 
     SECKEYPrivateKey* key = nullptr;
     SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
         slot.get(), &pkcs8Item, nullptr, nullptr, false, false, KU_ALL, &key,
         nullptr);
 
     if (rv != SECSuccess) {
       return nullptr;
     }
 
     return ScopedSECKEYPrivateKey(key);
   }
 
-  ScopedSECKEYPublicKey ImportPublicKey(const uint8_t* spki, size_t spki_len) {
-    SECItem spkiItem = {siBuffer, toUcharPtr(spki),
-                        static_cast<unsigned int>(spki_len)};
+  ScopedSECKEYPublicKey ImportPublicKey(const DataBuffer& spki) {
+    SECItem spkiItem = {siBuffer, toUcharPtr(spki.data()),
+                        static_cast<unsigned int>(spki.len())};
 
     ScopedCERTSubjectPublicKeyInfo certSpki(
         SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem));
 
     return ScopedSECKEYPublicKey(SECKEY_ExtractPublicKey(certSpki.get()));
   }
 
-  ScopedSECItem ComputeHash(const uint8_t* data, size_t len) {
-    unsigned int hLen = HASH_ResultLenByOidTag(hashOID());
-    ScopedSECItem hash(SECITEM_AllocItem(nullptr, nullptr, hLen));
-    if (!hash) {
-      return nullptr;
-    }
-
-    SECStatus rv = PK11_HashBuf(hashOID(), hash->data, data, len);
-    if (rv != SECSuccess) {
-      return nullptr;
-    }
-
-    return hash;
+  bool ComputeHash(const DataBuffer& data, DataBuffer* hash) {
+    hash->Allocate(static_cast<size_t>(HASH_ResultLenByOidTag(hash_oid_)));
+    SECStatus rv =
+        PK11_HashBuf(hash_oid_, hash->data(), data.data(), data.len());
+    return rv == SECSuccess;
   }
 
-  ScopedSECItem SignHashedData(ScopedSECKEYPrivateKey& privKey,
-                               ScopedSECItem& hash) {
-    unsigned int sLen = PK11_SignatureLen(privKey.get());
-    ScopedSECItem sig(SECITEM_AllocItem(nullptr, nullptr, sLen));
-    if (!sig) {
-      return nullptr;
-    }
-
-    SECStatus rv = PK11_SignWithMechanism(privKey.get(), mechanism(),
-                                          parameters(), sig.get(), hash.get());
-    if (rv != SECSuccess) {
-      return nullptr;
-    }
-
-    return sig;
+  bool SignHashedData(ScopedSECKEYPrivateKey& privKey, const DataBuffer& hash,
+                      DataBuffer* sig) {
+    SECItem hashItem = {siBuffer, toUcharPtr(hash.data()),
+                        static_cast<unsigned int>(hash.len())};
+    int sigLen = PK11_SignatureLen(privKey.get());
+    EXPECT_LT(0, sigLen);
+    sig->Allocate(static_cast<size_t>(sigLen));
+    SECItem sigItem = {siBuffer, toUcharPtr(sig->data()),
+                       static_cast<unsigned int>(sig->len())};
+    SECStatus rv = PK11_SignWithMechanism(privKey.get(), mechanism_,
+                                          parameters(), &sigItem, &hashItem);
+    return rv == SECSuccess;
   }
 
-  ScopedSECItem ImportPrivateKeyAndSignHashedData(const uint8_t* pkcs8,
-                                                  size_t pkcs8_len,
-                                                  const uint8_t* data,
-                                                  size_t data_len) {
-    ScopedSECKEYPrivateKey privKey(ImportPrivateKey(pkcs8, pkcs8_len));
+  bool ImportPrivateKeyAndSignHashedData(const DataBuffer& pkcs8,
+                                         const DataBuffer& data,
+                                         DataBuffer* sig) {
+    ScopedSECKEYPrivateKey privKey(ImportPrivateKey(pkcs8));
     if (!privKey) {
-      return nullptr;
-    }
-
-    ScopedSECItem hash(ComputeHash(data, data_len));
-    if (!hash) {
-      return nullptr;
+      return false;
     }
 
-    return ScopedSECItem(SignHashedData(privKey, hash));
+    DataBuffer hash;
+    if (!ComputeHash(data, &hash)) {
+      ADD_FAILURE() << "Failed to compute hash";
+      return false;
+    }
+    return SignHashedData(privKey, hash, sig);
   }
 
-  void Verify(const uint8_t* spki, size_t spki_len, const uint8_t* data,
-              size_t data_len, const uint8_t* sig, size_t sig_len) {
-    ScopedSECKEYPublicKey pubKey(ImportPublicKey(spki, spki_len));
+  void Verify(const Pkcs11SignatureTestParams& params, const DataBuffer& sig) {
+    ScopedSECKEYPublicKey pubKey(ImportPublicKey(params.spki_));
     ASSERT_TRUE(pubKey);
 
-    ScopedSECItem hash(ComputeHash(data, data_len));
-    ASSERT_TRUE(hash);
-
-    SECItem sigItem = {siBuffer, toUcharPtr(sig),
-                       static_cast<unsigned int>(sig_len)};
+    DataBuffer hash;
+    ASSERT_TRUE(ComputeHash(params.data_, &hash));
 
     // Verify.
+    SECItem hashItem = {siBuffer, toUcharPtr(hash.data()),
+                        static_cast<unsigned int>(hash.len())};
+    SECItem sigItem = {siBuffer, toUcharPtr(sig.data()),
+                       static_cast<unsigned int>(sig.len())};
     SECStatus rv = PK11_VerifyWithMechanism(
-        pubKey.get(), mechanism(), parameters(), &sigItem, hash.get(), nullptr);
+        pubKey.get(), mechanism_, parameters(), &sigItem, &hashItem, nullptr);
     EXPECT_EQ(rv, SECSuccess);
   }
 
-  void SignAndVerify(const uint8_t* pkcs8, size_t pkcs8_len,
-                     const uint8_t* spki, size_t spki_len, const uint8_t* data,
-                     size_t data_len) {
-    ScopedSECItem sig(
-        ImportPrivateKeyAndSignHashedData(pkcs8, pkcs8_len, data, data_len));
-    ASSERT_TRUE(sig);
+  void Verify(const Pkcs11SignatureTestParams& params) {
+    Verify(params, params.signature_);
+  }
 
-    Verify(spki, spki_len, data, data_len, sig->data, sig->len);
+  void SignAndVerify(const Pkcs11SignatureTestParams& params) {
+    DataBuffer sig;
+    ASSERT_TRUE(
+        ImportPrivateKeyAndSignHashedData(params.pkcs8_, params.data_, &sig));
+    Verify(params, sig);
   }
+
+ private:
+  CK_MECHANISM_TYPE mechanism_;
+  SECOidTag hash_oid_;
 };
 
-#define SIG_TEST_VECTOR_VERIFY(spki, data, sig) \
-  Verify(spki, sizeof(spki), data, sizeof(data), sig, sizeof(sig));
-
-#define SIG_TEST_VECTOR_SIGN_VERIFY(pkcs8, spki, data) \
-  SignAndVerify(pkcs8, sizeof(pkcs8), spki, sizeof(spki), data, sizeof(data));
-
 }  // namespace nss_test
--- a/security/nss/gtests/softoken_gtest/softoken_gtest.cc
+++ b/security/nss/gtests/softoken_gtest/softoken_gtest.cc
@@ -1,10 +1,12 @@
 #include <cstdlib>
 
+#include "cert.h"
+#include "certdb.h"
 #include "nspr.h"
 #include "nss.h"
 #include "pk11pub.h"
 #include "secerr.h"
 
 #include "scoped_ptrs.h"
 
 #define GTEST_HAS_RTTI 0
@@ -195,16 +197,120 @@ TEST_F(SoftokenTest, CreateObjectChangeT
   EXPECT_EQ(SEC_ERROR_TOKEN_NOT_LOGGED_IN, PORT_GetError());
   ScopedPK11GenericObject obj(PK11_CreateGenericObject(
       slot.get(), attributes, PR_ARRAY_SIZE(attributes), true));
   // Because there's no password we can't logout and the operation should have
   // succeeded.
   EXPECT_NE(nullptr, obj);
 }
 
+// This is just any X509 certificate. Its contents don't matter.
+static unsigned char certDER[] = {
+    0x30, 0x82, 0x01, 0xEF, 0x30, 0x82, 0x01, 0x94, 0xA0, 0x03, 0x02, 0x01,
+    0x02, 0x02, 0x14, 0x49, 0xC4, 0xC4, 0x4A, 0xB6, 0x86, 0x07, 0xA3, 0x06,
+    0xDC, 0x4D, 0xC8, 0xC3, 0xFE, 0xC7, 0x21, 0x3A, 0x2D, 0xE4, 0xDA, 0x30,
+    0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
+    0x30, 0x0F, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
+    0x04, 0x74, 0x65, 0x73, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31,
+    0x35, 0x31, 0x31, 0x32, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A,
+    0x18, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30,
+    0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x0F, 0x31, 0x0D, 0x30, 0x0B, 0x06,
+    0x03, 0x55, 0x04, 0x03, 0x0C, 0x04, 0x74, 0x65, 0x73, 0x74, 0x30, 0x82,
+    0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
+    0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82,
+    0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBA, 0x88, 0x51, 0xA8, 0x44,
+    0x8E, 0x16, 0xD6, 0x41, 0xFD, 0x6E, 0xB6, 0x88, 0x06, 0x36, 0x10, 0x3D,
+    0x3C, 0x13, 0xD9, 0xEA, 0xE4, 0x35, 0x4A, 0xB4, 0xEC, 0xF5, 0x68, 0x57,
+    0x6C, 0x24, 0x7B, 0xC1, 0xC7, 0x25, 0xA8, 0xE0, 0xD8, 0x1F, 0xBD, 0xB1,
+    0x9C, 0x06, 0x9B, 0x6E, 0x1A, 0x86, 0xF2, 0x6B, 0xE2, 0xAF, 0x5A, 0x75,
+    0x6B, 0x6A, 0x64, 0x71, 0x08, 0x7A, 0xA5, 0x5A, 0xA7, 0x45, 0x87, 0xF7,
+    0x1C, 0xD5, 0x24, 0x9C, 0x02, 0x7E, 0xCD, 0x43, 0xFC, 0x1E, 0x69, 0xD0,
+    0x38, 0x20, 0x29, 0x93, 0xAB, 0x20, 0xC3, 0x49, 0xE4, 0xDB, 0xB9, 0x4C,
+    0xC2, 0x6B, 0x6C, 0x0E, 0xED, 0x15, 0x82, 0x0F, 0xF1, 0x7E, 0xAD, 0x69,
+    0x1A, 0xB1, 0xD3, 0x02, 0x3A, 0x8B, 0x2A, 0x41, 0xEE, 0xA7, 0x70, 0xE0,
+    0x0F, 0x0D, 0x8D, 0xFD, 0x66, 0x0B, 0x2B, 0xB0, 0x24, 0x92, 0xA4, 0x7D,
+    0xB9, 0x88, 0x61, 0x79, 0x90, 0xB1, 0x57, 0x90, 0x3D, 0xD2, 0x3B, 0xC5,
+    0xE0, 0xB8, 0x48, 0x1F, 0xA8, 0x37, 0xD3, 0x88, 0x43, 0xEF, 0x27, 0x16,
+    0xD8, 0x55, 0xB7, 0x66, 0x5A, 0xAA, 0x7E, 0x02, 0x90, 0x2F, 0x3A, 0x7B,
+    0x10, 0x80, 0x06, 0x24, 0xCC, 0x1C, 0x6C, 0x97, 0xAD, 0x96, 0x61, 0x5B,
+    0xB7, 0xE2, 0x96, 0x12, 0xC0, 0x75, 0x31, 0xA3, 0x0C, 0x91, 0xDD, 0xB4,
+    0xCA, 0xF7, 0xFC, 0xAD, 0x1D, 0x25, 0xD3, 0x09, 0xEF, 0xB9, 0x17, 0x0E,
+    0xA7, 0x68, 0xE1, 0xB3, 0x7B, 0x2F, 0x22, 0x6F, 0x69, 0xE3, 0xB4, 0x8A,
+    0x95, 0x61, 0x1D, 0xEE, 0x26, 0xD6, 0x25, 0x9D, 0xAB, 0x91, 0x08, 0x4E,
+    0x36, 0xCB, 0x1C, 0x24, 0x04, 0x2C, 0xBF, 0x16, 0x8B, 0x2F, 0xE5, 0xF1,
+    0x8F, 0x99, 0x17, 0x31, 0xB8, 0xB3, 0xFE, 0x49, 0x23, 0xFA, 0x72, 0x51,
+    0xC4, 0x31, 0xD5, 0x03, 0xAC, 0xDA, 0x18, 0x0A, 0x35, 0xED, 0x8D, 0x02,
+    0x03, 0x01, 0x00, 0x01, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+    0xF7, 0x0D, 0x01, 0x01, 0x0B, 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, 0x82,
+    0x12, 0xF7, 0xE5, 0xEA, 0x40, 0x27, 0xFD, 0xF7, 0xC0, 0x0E, 0x25, 0xF3,
+    0x3E, 0x34, 0x95, 0x80, 0xB9, 0xA3, 0x38, 0xE0, 0x56, 0x68, 0xDA, 0xE5,
+    0xC1, 0xF5, 0x37, 0xC7, 0xB5, 0xCE, 0x0D};
+
+struct PasswordPair {
+  const char *mInitialPassword;
+  const char *mSecondPassword;
+};
+
+class SoftokenPasswordChangeTest
+    : public SoftokenTest,
+      public ::testing::WithParamInterface<PasswordPair> {};
+
+TEST_P(SoftokenPasswordChangeTest, KeepTrustAfterPasswordChange) {
+  const PasswordPair &passwords = GetParam();
+  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+  ASSERT_TRUE(slot);
+  // Set a password.
+  EXPECT_EQ(SECSuccess,
+            PK11_InitPin(slot.get(), nullptr, passwords.mInitialPassword));
+  SECItem certDERItem = {siBuffer, certDER, sizeof(certDER)};
+  // Import a certificate.
+  ScopedCERTCertificate cert(CERT_NewTempCertificate(
+      CERT_GetDefaultCertDB(), &certDERItem, nullptr, true, true));
+  EXPECT_TRUE(cert);
+  SECStatus result =
+      PK11_ImportCert(slot.get(), cert.get(), CK_INVALID_HANDLE, "test", false);
+  EXPECT_EQ(SECSuccess, result);
+  // Set a trust value.
+  CERTCertTrust trust = {CERTDB_TRUSTED_CLIENT_CA | CERTDB_NS_TRUSTED_CA |
+                             CERTDB_TRUSTED_CA | CERTDB_VALID_CA,
+                         0, 0};
+  result = CERT_ChangeCertTrust(nullptr, cert.get(), &trust);
+  EXPECT_EQ(SECSuccess, result);
+  // Release the certificate to ensure we get it from the DB rather than an
+  // in-memory cache, below.
+  cert = nullptr;
+  // Change the password.
+  result = PK11_ChangePW(slot.get(), passwords.mInitialPassword,
+                         passwords.mSecondPassword);
+  EXPECT_EQ(SECSuccess, result);
+  // Look up the certificate again.
+  ScopedCERTCertificate newCert(
+      PK11_FindCertFromDERCertItem(slot.get(), &certDERItem, nullptr));
+  EXPECT_TRUE(newCert.get());
+  // The trust should be the same as before.
+  CERTCertTrust newTrust = {0, 0, 0};
+  result = CERT_GetCertTrust(newCert.get(), &newTrust);
+  EXPECT_EQ(SECSuccess, result);
+  EXPECT_EQ(trust.sslFlags, newTrust.sslFlags);
+  EXPECT_EQ(trust.emailFlags, newTrust.emailFlags);
+  EXPECT_EQ(trust.objectSigningFlags, newTrust.objectSigningFlags);
+}
+
+static const PasswordPair PASSWORD_CHANGE_TESTS[] = {
+    {"password", ""},           // non-empty to empty password
+    {"", "password"},           // empty to non-empty password
+    {"password", "password2"},  // non-empty to non-empty password
+};
+
+INSTANTIATE_TEST_CASE_P(SoftokenPasswordChangeTests, SoftokenPasswordChangeTest,
+                        ::testing::ValuesIn(PASSWORD_CHANGE_TESTS));
+
 class SoftokenNoDBTest : public ::testing::Test {};
 
 TEST_F(SoftokenNoDBTest, NeedUserInitNoDB) {
   ASSERT_EQ(SECSuccess, NSS_NoDB_Init("."));
   ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
   ASSERT_TRUE(slot);
   EXPECT_EQ(PR_FALSE, PK11_NeedUserInit(slot.get()));
 
--- a/security/nss/lib/softoken/sftkdb.c
+++ b/security/nss/lib/softoken/sftkdb.c
@@ -35,17 +35,17 @@
  * are endian/length independent except those attributes that pass CK_ULONG.
  *
  * The following functions fixes up the CK_ULONG type attributes so that the data
  * base sees a machine independent view. CK_ULONGs are stored as 4 byte network
  * byte order values (big endian).
  */
 #define BBP 8
 
-static PRBool
+PRBool
 sftkdb_isULONGAttribute(CK_ATTRIBUTE_TYPE type)
 {
     switch (type) {
         case CKA_CERTIFICATE_CATEGORY:
         case CKA_CERTIFICATE_TYPE:
         case CKA_CLASS:
         case CKA_JAVA_MIDP_SECURITY_DOMAIN:
         case CKA_KEY_GEN_MECHANISM:
@@ -1365,34 +1365,35 @@ sftkdb_SetAttributeValue(SFTKDBHandle *h
     }
 
     ntemplate = sftkdb_fixupTemplateIn(template, count, &data);
     if (ntemplate == NULL) {
         return CKR_HOST_MEMORY;
     }
 
     /* make sure we don't have attributes that conflict with the existing DB */
-    crv = sftkdb_checkConflicts(db, object->objclass, template, count, objectID);
+    crv = sftkdb_checkConflicts(db, object->objclass, ntemplate, count,
+                                objectID);
     if (crv != CKR_OK) {
         goto loser;
     }
 
     arena = PORT_NewArena(256);
     if (arena == NULL) {
         crv = CKR_HOST_MEMORY;
         goto loser;
     }
 
     crv = (*db->sdb_Begin)(db);
     if (crv != CKR_OK) {
         goto loser;
     }
     inTransaction = PR_TRUE;
-    crv = sftkdb_setAttributeValue(arena, handle, db,
-                                   objectID, template, count);
+    crv = sftkdb_setAttributeValue(arena, handle, db, objectID, ntemplate,
+                                   count);
     if (crv != CKR_OK) {
         goto loser;
     }
     crv = (*db->sdb_Commit)(db);
 loser:
     if (crv != CKR_OK && inTransaction) {
         (*db->sdb_Abort)(db);
     }
--- a/security/nss/lib/softoken/sftkdbti.h
+++ b/security/nss/lib/softoken/sftkdbti.h
@@ -44,15 +44,16 @@ SECStatus sftkdb_SignAttribute(PLArenaPo
                                CK_OBJECT_HANDLE objectID,
                                CK_ATTRIBUTE_TYPE attrType,
                                SECItem *plainText, SECItem **sigText);
 SECStatus sftkdb_VerifyAttribute(SECItem *passKey,
                                  CK_OBJECT_HANDLE objectID,
                                  CK_ATTRIBUTE_TYPE attrType,
                                  SECItem *plainText, SECItem *sigText);
 
+PRBool sftkdb_isULONGAttribute(CK_ATTRIBUTE_TYPE type);
 void sftk_ULong2SDBULong(unsigned char *data, CK_ULONG value);
 CK_RV sftkdb_Update(SFTKDBHandle *handle, SECItem *key);
 CK_RV sftkdb_PutAttributeSignature(SFTKDBHandle *handle,
                                    SDB *keyTarget, CK_OBJECT_HANDLE objectID,
                                    CK_ATTRIBUTE_TYPE type, SECItem *signText);
 
 #endif
--- a/security/nss/lib/softoken/sftkpwd.c
+++ b/security/nss/lib/softoken/sftkpwd.c
@@ -921,16 +921,23 @@ sftk_updateMacs(PLArenaPool *arena, SFTK
         SECItem *signText;
         SECItem plainText;
         SECStatus rv;
 
         if ((authAttrs[i].ulValueLen == -1) || (authAttrs[i].ulValueLen == 0)) {
             continue;
         }
 
+        if (authAttrs[i].ulValueLen == sizeof(CK_ULONG) &&
+            sftkdb_isULONGAttribute(authAttrs[i].type)) {
+            CK_ULONG value = *(CK_ULONG *)authAttrs[i].pValue;
+            sftk_ULong2SDBULong(authAttrs[i].pValue, value);
+            authAttrs[i].ulValueLen = SDB_ULONG_SIZE;
+        }
+
         plainText.data = authAttrs[i].pValue;
         plainText.len = authAttrs[i].ulValueLen;
         rv = sftkdb_SignAttribute(arena, newKey, id,
                                   authAttrs[i].type, &plainText, &signText);
         if (rv != SECSuccess) {
             return CKR_GENERAL_ERROR;
         }
         rv = sftkdb_PutAttributeSignature(handle, keyTarget, id,