Bug 1386955 - land NSS 984849c0a0f1 UPGRADE_NSS_RELEASE, r=me
☠☠ backed out by 952c576fdcd6 ☠ ☠
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Thu, 17 Aug 2017 11:57:16 +0200
changeset 424852 0777ec282546ac242f730942d081346a20da18f0
parent 424851 39d42c06e5ae1816f9daa0ea426ce52d469be1da
child 424853 62c399b27d0a79157c82e7564bf9e7555c4f9214
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1386955
milestone57.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 1386955 - land NSS 984849c0a0f1 UPGRADE_NSS_RELEASE, r=me
security/nss/TAG-INFO
security/nss/coreconf/config.gypi
security/nss/coreconf/coreconf.dep
security/nss/cpputil/scoped_ptrs.h
security/nss/gtests/softoken_gtest/softoken_gtest.cc
security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc
security/nss/lib/freebl/gcm.c
security/nss/lib/freebl/rijndael.c
security/nss/lib/pk11wrap/pk11slot.c
security/nss/lib/softoken/pkcs11.c
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-3e81bdac8449
+984849c0a0f1
--- a/security/nss/coreconf/config.gypi
+++ b/security/nss/coreconf/config.gypi
@@ -162,17 +162,17 @@
         'msvs_settings': {
           'VCCLCompilerTool': {
             'PreprocessorDefinitions': [
               'NSS_X86',
             ],
           },
         },
       }],
-      [ 'target_arch=="arm64" or target_arch=="aarch64"', {
+      [ 'target_arch=="arm64" or target_arch=="aarch64" or target_arch=="sparc64"', {
         'defines': [
           'NSS_USE_64',
         ],
       }],
       [ 'target_arch=="x64"', {
         'defines': [
           'NSS_X64',
           'NSS_USE_64',
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,8 +5,9 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
+
--- a/security/nss/cpputil/scoped_ptrs.h
+++ b/security/nss/cpputil/scoped_ptrs.h
@@ -31,16 +31,17 @@ struct ScopedDelete {
   void operator()(SECKEYPublicKey* key) { SECKEY_DestroyPublicKey(key); }
   void operator()(SECKEYPrivateKey* key) { SECKEY_DestroyPrivateKey(key); }
   void operator()(SECKEYPrivateKeyList* list) {
     SECKEY_DestroyPrivateKeyList(list);
   }
   void operator()(PK11URI* uri) { PK11URI_DestroyURI(uri); }
   void operator()(PLArenaPool* arena) { PORT_FreeArena(arena, PR_FALSE); }
   void operator()(PK11Context* context) { PK11_DestroyContext(context, true); }
+  void operator()(PK11GenericObject* obj) { PK11_DestroyGenericObject(obj); }
 };
 
 template <class T>
 struct ScopedMaybeDelete {
   void operator()(T* ptr) {
     if (ptr) {
       ScopedDelete del;
       del(ptr);
@@ -61,12 +62,13 @@ SCOPED(PRFileDesc);
 SCOPED(SECAlgorithmID);
 SCOPED(SECItem);
 SCOPED(SECKEYPublicKey);
 SCOPED(SECKEYPrivateKey);
 SCOPED(SECKEYPrivateKeyList);
 SCOPED(PK11URI);
 SCOPED(PLArenaPool);
 SCOPED(PK11Context);
+SCOPED(PK11GenericObject);
 
 #undef SCOPED
 
 #endif  // scoped_ptrs_h__
--- a/security/nss/gtests/softoken_gtest/softoken_gtest.cc
+++ b/security/nss/gtests/softoken_gtest/softoken_gtest.cc
@@ -1,13 +1,14 @@
 #include <cstdlib>
 
 #include "nspr.h"
 #include "nss.h"
 #include "pk11pub.h"
+#include "secerr.h"
 
 #include "scoped_ptrs.h"
 
 #define GTEST_HAS_RTTI 0
 #include "gtest/gtest.h"
 
 namespace nss_test {
 
@@ -20,61 +21,61 @@ namespace nss_test {
 // 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);
+  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 &GetPath() { return mPath; }
 
  private:
   static const int RETRY_LIMIT = 5;
-  static void GenerateRandomName(/*in/out*/ std::string& prefix);
-  static bool TryMakingDirectory(/*in/out*/ std::string& prefix);
+  static void GenerateRandomName(/*in/out*/ std::string &prefix);
+  static bool TryMakingDirectory(/*in/out*/ std::string &prefix);
 
   std::string mPath;
 };
 
-ScopedUniqueDirectory::ScopedUniqueDirectory(const std::string& prefix) {
+ScopedUniqueDirectory::ScopedUniqueDirectory(const std::string &prefix) {
   std::string path;
-  const char* workingDirectory = PR_GetEnvSecure("NSS_GTEST_WORKDIR");
+  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);
 }
 
-void ScopedUniqueDirectory::GenerateRandomName(std::string& prefix) {
+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) {
+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
 }
 
@@ -86,17 +87,17 @@ class SoftokenTest : public ::testing::T
     std::string nssInitArg("sql:");
     nssInitArg.append(mNSSDBDir.GetPath());
     ASSERT_EQ(SECSuccess, NSS_Initialize(nssInitArg.c_str(), "", "", SECMOD_DB,
                                          NSS_INIT_NOROOTINIT));
   }
 
   virtual void TearDown() {
     ASSERT_EQ(SECSuccess, NSS_Shutdown());
-    const std::string& nssDBDirPath = mNSSDBDir.GetPath();
+    const std::string &nssDBDirPath = mNSSDBDir.GetPath();
     ASSERT_EQ(0, unlink((nssDBDirPath + "/cert9.db").c_str()));
     ASSERT_EQ(0, unlink((nssDBDirPath + "/key4.db").c_str()));
     ASSERT_EQ(0, unlink((nssDBDirPath + "/pkcs11.txt").c_str()));
   }
 
   ScopedUniqueDirectory mNSSDBDir;
 };
 
@@ -111,15 +112,111 @@ TEST_F(SoftokenTest, ResetSoftokenEmptyP
 TEST_F(SoftokenTest, ResetSoftokenNonEmptyPassword) {
   ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
   ASSERT_TRUE(slot);
   EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password"));
   EXPECT_EQ(SECSuccess, PK11_ResetToken(slot.get(), nullptr));
   EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password2"));
 }
 
+// Test certificate to use in the CreateObject tests.
+static const CK_OBJECT_CLASS cko_nss_trust = CKO_NSS_TRUST;
+static const CK_BBOOL ck_false = CK_FALSE;
+static const CK_BBOOL ck_true = CK_TRUE;
+static const CK_TRUST ckt_nss_must_verify_trust = CKT_NSS_MUST_VERIFY_TRUST;
+static const CK_TRUST ckt_nss_trusted_delegator = CKT_NSS_TRUSTED_DELEGATOR;
+static const CK_ATTRIBUTE attributes[] = {
+    {CKA_CLASS, (void *)&cko_nss_trust, (PRUint32)sizeof(CK_OBJECT_CLASS)},
+    {CKA_TOKEN, (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL)},
+    {CKA_PRIVATE, (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL)},
+    {CKA_MODIFIABLE, (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL)},
+    {CKA_LABEL,
+     (void *)"Symantec Class 2 Public Primary Certification Authority - G4",
+     (PRUint32)61},
+    {CKA_CERT_SHA1_HASH,
+     (void *)"\147\044\220\056\110\001\260\042\226\100\020\106\264\261\147\054"
+             "\251\165\375\053",
+     (PRUint32)20},
+    {CKA_CERT_MD5_HASH,
+     (void *)"\160\325\060\361\332\224\227\324\327\164\337\276\355\150\336\226",
+     (PRUint32)16},
+    {CKA_ISSUER,
+     (void *)"\060\201\224\061\013\060\011\006\003\125\004\006\023\002\125\123"
+             "\061\035\060\033\006\003\125\004\012\023\024\123\171\155\141\156"
+             "\164\145\143\040\103\157\162\160\157\162\141\164\151\157\156\061"
+             "\037\060\035\006\003\125\004\013\023\026\123\171\155\141\156\164"
+             "\145\143\040\124\162\165\163\164\040\116\145\164\167\157\162\153"
+             "\061\105\060\103\006\003\125\004\003\023\074\123\171\155\141\156"
+             "\164\145\143\040\103\154\141\163\163\040\062\040\120\165\142\154"
+             "\151\143\040\120\162\151\155\141\162\171\040\103\145\162\164\151"
+             "\146\151\143\141\164\151\157\156\040\101\165\164\150\157\162\151"
+             "\164\171\040\055\040\107\064",
+     (PRUint32)151},
+    {CKA_SERIAL_NUMBER,
+     (void *)"\002\020\064\027\145\022\100\073\267\126\200\055\200\313\171\125"
+             "\246\036",
+     (PRUint32)18},
+    {CKA_TRUST_SERVER_AUTH, (void *)&ckt_nss_must_verify_trust,
+     (PRUint32)sizeof(CK_TRUST)},
+    {CKA_TRUST_EMAIL_PROTECTION, (void *)&ckt_nss_trusted_delegator,
+     (PRUint32)sizeof(CK_TRUST)},
+    {CKA_TRUST_CODE_SIGNING, (void *)&ckt_nss_must_verify_trust,
+     (PRUint32)sizeof(CK_TRUST)},
+    {CKA_TRUST_STEP_UP_APPROVED, (void *)&ck_false,
+     (PRUint32)sizeof(CK_BBOOL)}};
+
+TEST_F(SoftokenTest, CreateObjectNonEmptyPassword) {
+  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+  ASSERT_TRUE(slot);
+  EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password"));
+  EXPECT_EQ(SECSuccess, PK11_Logout(slot.get()));
+  ScopedPK11GenericObject obj(PK11_CreateGenericObject(
+      slot.get(), attributes, PR_ARRAY_SIZE(attributes), true));
+  EXPECT_EQ(nullptr, obj);
+}
+
+TEST_F(SoftokenTest, CreateObjectChangePassword) {
+  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+  ASSERT_TRUE(slot);
+  EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, nullptr));
+  EXPECT_EQ(SECSuccess, PK11_ChangePW(slot.get(), "", "password"));
+  EXPECT_EQ(SECSuccess, PK11_Logout(slot.get()));
+  ScopedPK11GenericObject obj(PK11_CreateGenericObject(
+      slot.get(), attributes, PR_ARRAY_SIZE(attributes), true));
+  EXPECT_EQ(nullptr, obj);
+}
+
+TEST_F(SoftokenTest, CreateObjectChangeToEmptyPassword) {
+  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+  ASSERT_TRUE(slot);
+  EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password"));
+  EXPECT_EQ(SECSuccess, PK11_ChangePW(slot.get(), "password", ""));
+  // PK11_Logout returnes an error and SEC_ERROR_TOKEN_NOT_LOGGED_IN if the user
+  // is not "logged in".
+  EXPECT_EQ(SECFailure, PK11_Logout(slot.get()));
+  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);
+}
+
+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()));
+
+  // When shutting down in here we have to release the slot first.
+  slot = nullptr;
+  ASSERT_EQ(SECSuccess, NSS_Shutdown());
+}
+
 }  // namespace nss_test
 
-int main(int argc, char** argv) {
+int main(int argc, char **argv) {
   ::testing::InitGoogleTest(&argc, argv);
 
   return RUN_ALL_TESTS();
 }
--- a/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc
@@ -546,17 +546,17 @@ class ECCServerKEXFilter : public TlsHan
                                                DataBuffer *output) {
     if (header.handshake_type() != kTlsHandshakeServerKeyExchange) {
       return KEEP;
     }
 
     // Replace the server key exchange message with an empty point
     output->Allocate(4);
     output->Write(0, 3U, 1);  // named curve
-    uint32_t curve;
+    uint32_t curve = 0;
     EXPECT_TRUE(input.Read(1, 2, &curve));  // get curve id
     output->Write(1, curve, 2);             // write curve id
     output->Write(3, 0U, 1);                // point length 0
     return CHANGE;
   }
 };
 
 TEST_P(TlsConnectGenericPre13, ConnectECDHEmptyServerPoint) {
--- a/security/nss/lib/freebl/gcm.c
+++ b/security/nss/lib/freebl/gcm.c
@@ -569,17 +569,17 @@ struct GCMContextStr {
     unsigned char tagKey[MAX_BLOCK_SIZE];
 };
 
 GCMContext *
 GCM_CreateContext(void *context, freeblCipherFunc cipher,
                   const unsigned char *params)
 {
     GCMContext *gcm = NULL;
-    gcmHashContext *ghash = NULL;
+    gcmHashContext *ghash = NULL, *ghashmem = NULL;
     unsigned char H[MAX_BLOCK_SIZE];
     unsigned int tmp;
     PRBool freeCtr = PR_FALSE;
     const CK_GCM_PARAMS *gcmParams = (const CK_GCM_PARAMS *)params;
     CK_AES_CTR_PARAMS ctrParams;
     SECStatus rv;
 #ifdef DISABLE_HW_GCM
     const PRBool sw = PR_TRUE;
@@ -591,23 +591,23 @@ GCM_CreateContext(void *context, freeblC
         PORT_SetError(SEC_ERROR_INVALID_ARGS);
         return NULL;
     }
     gcm = PORT_ZNew(GCMContext);
     if (gcm == NULL) {
         return NULL;
     }
     /* aligned_alloc is C11 so we have to do it the old way. */
-    ghash = PORT_ZAlloc(sizeof(gcmHashContext) + 15);
-    if (ghash == NULL) {
+    ghashmem = PORT_ZAlloc(sizeof(gcmHashContext) + 15);
+    if (ghashmem == NULL) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         goto loser;
     }
-    ghash->mem = ghash;
-    ghash = (gcmHashContext *)(((uintptr_t)ghash + 15) & ~(uintptr_t)0x0F);
+    ghash = (gcmHashContext *)(((uintptr_t)ghashmem + 15) & ~(uintptr_t)0x0F);
+    ghash->mem = ghashmem;
 
     /* first plug in the ghash context */
     gcm->ghash_context = ghash;
     PORT_Memset(H, 0, AES_BLOCK_SIZE);
     rv = (*cipher)(context, H, &tmp, AES_BLOCK_SIZE, H, AES_BLOCK_SIZE, AES_BLOCK_SIZE);
     if (rv != SECSuccess) {
         goto loser;
     }
--- a/security/nss/lib/freebl/rijndael.c
+++ b/security/nss/lib/freebl/rijndael.c
@@ -1013,23 +1013,25 @@ rijndael_decryptCBC(AESContext *cx, unsi
  * BLAPI for the AES cipher, Rijndael.
  *
  ***********************************************************************/
 
 AESContext *
 AES_AllocateContext(void)
 {
     /* aligned_alloc is C11 so we have to do it the old way. */
-    AESContext *ctx = PORT_ZAlloc(sizeof(AESContext) + 15);
-    if (ctx == NULL) {
+    AESContext *ctx, *ctxmem;
+    ctxmem = PORT_ZAlloc(sizeof(AESContext) + 15);
+    if (ctxmem == NULL) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         return NULL;
     }
-    ctx->mem = ctx;
-    return (AESContext *)(((uintptr_t)ctx + 15) & ~(uintptr_t)0x0F);
+    ctx = (AESContext *)(((uintptr_t)ctxmem + 15) & ~(uintptr_t)0x0F);
+    ctx->mem = ctxmem;
+    return ctx;
 }
 
 /*
 ** Initialize a new AES context suitable for AES encryption/decryption in
 ** the ECB or CBC mode.
 **  "mode" the mode of operation, which must be NSS_AES or NSS_AES_CBC
 */
 static SECStatus
--- a/security/nss/lib/pk11wrap/pk11slot.c
+++ b/security/nss/lib/pk11wrap/pk11slot.c
@@ -1177,17 +1177,17 @@ PK11_InitToken(PK11SlotInfo *slot, PRBoo
         PK11_ExitSlotMonitor(slot);
     if (crv != CKR_OK) {
         PORT_SetError(PK11_MapError(crv));
         return SECFailure;
     }
 
     /* set the slot flags to the current token values */
     slot->series++; /* allow other objects to detect that the
-                      * slot is different */
+                     * slot is different */
     slot->flags = slot->tokenInfo.flags;
     slot->needLogin = ((slot->tokenInfo.flags & CKF_LOGIN_REQUIRED) ? PR_TRUE : PR_FALSE);
     slot->readOnly = ((slot->tokenInfo.flags & CKF_WRITE_PROTECTED) ? PR_TRUE : PR_FALSE);
 
     slot->hasRandom = ((slot->tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE);
     slot->protectedAuthPath =
         ((slot->tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
              ? PR_TRUE
@@ -1466,16 +1466,19 @@ PK11_InitSlot(SECMODModule *mod, CK_SLOT
         }
         if (rv == SECSuccess && pk11_isRootSlot(slot)) {
             if (!slot->hasRootCerts) {
                 slot->module->trustOrder = 100;
             }
             slot->hasRootCerts = PR_TRUE;
         }
     }
+    if ((slotInfo.flags & CKF_USER_PIN_INITIALIZED) != 0) {
+        slot->flags |= CKF_USER_PIN_INITIALIZED;
+    }
 }
 
 /*********************************************************************
  *            Slot mapping utility functions.
  *********************************************************************/
 
 /*
  * determine if the token is present. If the token is present, make sure
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -3300,16 +3300,25 @@ NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SL
         if (handle) {
             if (sftkdb_InUpdateMerge(handle)) {
                 pInfo->flags |= CKF_REMOVABLE_DEVICE;
             }
             sftk_freeDB(handle);
         }
     }
 
+    /* If there is no key database, this is for example the case when NSS was
+     * initialized with NSS_NoDbInit(), then there won't be any point in
+     * requesting a PIN. Set the CKF_USER_PIN_INITIALIZED bit so that
+     * PK11_NeedUserInit() doesn't indicate that a PIN is needed.
+     */
+    if (slot->keyDB == NULL) {
+        pInfo->flags |= CKF_USER_PIN_INITIALIZED;
+    }
+
     /* ok we really should read it out of the keydb file. */
     /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */
     pInfo->hardwareVersion.major = SOFTOKEN_VMAJOR;
     pInfo->hardwareVersion.minor = SOFTOKEN_VMINOR;
     pInfo->firmwareVersion.major = SOFTOKEN_VPATCH;
     pInfo->firmwareVersion.minor = SOFTOKEN_VBUILD;
     return CKR_OK;
 }
@@ -3783,17 +3792,20 @@ NSC_SetPIN(CK_SESSION_HANDLE hSession, C
     }
     if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) {
         PR_Sleep(loginWaitTime);
     }
     PR_Unlock(slot->pwCheckLock);
 
     /* Now update our local copy of the pin */
     if (rv == SECSuccess) {
+        PZ_Lock(slot->slotLock);
         slot->needLogin = (PRBool)(ulNewLen != 0);
+        slot->isLoggedIn = (PRBool)(sftkdb_PWCached(handle) == SECSuccess);
+        PZ_Unlock(slot->slotLock);
         /* Reset login flags. */
         if (ulNewLen == 0) {
             PRBool tokenRemoved = PR_FALSE;
             PZ_Lock(slot->slotLock);
             slot->isLoggedIn = PR_FALSE;
             slot->ssoLoggedIn = PR_FALSE;
             PZ_Unlock(slot->slotLock);