Bug 1389570 - set slot->flags for user pin initialized when in nodb mode, r=mt
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Thu, 17 Aug 2017 11:18:37 +0200
changeset 13529 984849c0a0f1e2e62cbe5654e679c90b7a5a8f94
parent 13528 d83f2573b84eccb40a6e517340b488e7d2ad538b
child 13530 f4a9de53fe5a6c0ed6ba5290b5901c0c2eeb56ce
push id2322
push userfranziskuskiefer@gmail.com
push dateThu, 17 Aug 2017 09:19:48 +0000
reviewersmt
bugs1389570
Bug 1389570 - set slot->flags for user pin initialized when in nodb mode, r=mt Summary: NSS_NoDB_Init("."); PK11SlotInfo* slot = PK11_GetInternalKeySlot(); PK11_NeedUserInit(slot) used to returned PR_TRUE because we never set the init flag that's checked by that function when we start in noDB mode. This patch fixes that. As mentioned in the patch this is not the nicest way to fix this. The way login/init status and these flags are handled shold probably be rewritten. Differential Revision: https://nss-review.dev.mozaws.net/D406
gtests/softoken_gtest/softoken_gtest.cc
lib/pk11wrap/pk11slot.c
lib/softoken/pkcs11.c
--- a/gtests/softoken_gtest/softoken_gtest.cc
+++ b/gtests/softoken_gtest/softoken_gtest.cc
@@ -195,15 +195,28 @@ 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);
 }
 
+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) {
   ::testing::InitGoogleTest(&argc, argv);
 
   return RUN_ALL_TESTS();
 }
--- a/lib/pk11wrap/pk11slot.c
+++ b/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/lib/softoken/pkcs11.c
+++ b/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;
 }