bug 1272858 - use a name-agnostic method to find the built-in root PKCS#11 slot r?Cykesiopka draft
authorDavid Keeler <dkeeler@mozilla.com>
Thu, 23 Jun 2016 15:43:47 -0700
changeset 382548 e0978be09ea6a516637a59215b16db66f377387b
parent 382391 b69a5bbb5e40bd426e35222baa600b481e50d265
child 524216 6831fedbe68c5d106634effae752db55611eab5f
push id21747
push userdkeeler@mozilla.com
push dateWed, 29 Jun 2016 19:45:42 +0000
reviewersCykesiopka
bugs1272858
milestone50.0a1
bug 1272858 - use a name-agnostic method to find the built-in root PKCS#11 slot r?Cykesiopka Previously this implementation would use the expected names of the built-in module and slot to get a handle on them. This doesn't work on distributions that use other names. The new implementation searches through the slots from the default module list for one where PK11_HasRootCerts returns true (which indicates that NSS considers that slot to contain the default built-in root list). MozReview-Commit-ID: LmX27hQfFJU
config/external/nss/nss.symbols
security/certverifier/CertVerifier.cpp
security/manager/ssl/ScopedNSSTypes.h
security/manager/ssl/nsPKCS11Slot.h
--- a/config/external/nss/nss.symbols
+++ b/config/external/nss/nss.symbols
@@ -552,17 +552,16 @@ SECMOD_AddNewModuleEx
 SECMOD_CancelWait
 SECMOD_CanDeleteInternalModule
 SECMOD_CloseUserDB
 SECMOD_CreateModule
 SECMOD_DeleteInternalModule
 SECMOD_DeleteModule
 SECMOD_DestroyModule
 SECMOD_FindModule
-SECMOD_FindSlot
 SECMOD_GetDeadModuleList
 SECMOD_GetDefaultModuleList
 SECMOD_GetDefaultModuleListLock
 SECMOD_GetInternalModule
 SECMOD_GetModuleSpecList
 SECMOD_GetReadLock
 SECMOD_HasRemovableSlots
 SECMOD_InternaltoPubMechFlags
--- a/security/certverifier/CertVerifier.cpp
+++ b/security/certverifier/CertVerifier.cpp
@@ -78,55 +78,46 @@ IsCertChainRootBuiltInRoot(const UniqueC
   }
   return IsCertBuiltInRoot(root, result);
 }
 
 Result
 IsCertBuiltInRoot(CERTCertificate* cert, bool& result)
 {
   result = false;
+#ifdef DEBUG
   nsCOMPtr<nsINSSComponent> component(do_GetService(PSM_COMPONENT_CONTRACTID));
   if (!component) {
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
   }
-  nsresult rv;
-#ifdef DEBUG
-  rv = component->IsCertTestBuiltInRoot(cert, result);
+  nsresult rv = component->IsCertTestBuiltInRoot(cert, result);
   if (NS_FAILED(rv)) {
     return Result::FATAL_ERROR_LIBRARY_FAILURE;
   }
   if (result) {
     return Success;
   }
 #endif // DEBUG
-  nsAutoString modName;
-  rv = component->GetPIPNSSBundleString("RootCertModuleName", modName);
-  if (NS_FAILED(rv)) {
-    return Result::FATAL_ERROR_LIBRARY_FAILURE;
-  }
-  NS_ConvertUTF16toUTF8 modNameUTF8(modName);
-  UniqueSECMODModule builtinRootsModule(SECMOD_FindModule(modNameUTF8.get()));
-  // If the built-in roots module isn't loaded, nothing is a built-in root.
-  if (!builtinRootsModule) {
-    return Success;
+  AutoSECMODListReadLock lock;
+  for (SECMODModuleList* list = SECMOD_GetDefaultModuleList(); list;
+       list = list->next) {
+    for (int i = 0; i < list->module->slotCount; i++) {
+      PK11SlotInfo* slot = list->module->slots[i];
+      // PK11_HasRootCerts should return true if and only if the given slot has
+      // an object with a CKA_CLASS of CKO_NETSCAPE_BUILTIN_ROOT_LIST, which
+      // should be true only of the builtin root list.
+      // If we can find a copy of the given certificate on the slot with the
+      // builtin root list, that certificate must be a builtin.
+      if (PK11_IsPresent(slot) && PK11_HasRootCerts(slot) &&
+          PK11_FindCertInSlot(slot, cert, nullptr) != CK_INVALID_HANDLE) {
+        result = true;
+        return Success;
+      }
+    }
   }
-  UniquePK11SlotInfo builtinSlot(SECMOD_FindSlot(builtinRootsModule.get(),
-                                                 "Builtin Object Token"));
-  // This could happen if the user loaded a module that is acting like the
-  // built-in roots module but doesn't actually have a slot called "Builtin
-  // Object Token". In that case, again nothing is a built-in root.
-  if (!builtinSlot) {
-    return Success;
-  }
-  // Attempt to find a copy of the given certificate in the "Builtin Object
-  // Token" slot of the built-in root module. If we get a valid handle, this
-  // certificate exists in the root module, so we consider it a built-in root.
-  CK_OBJECT_HANDLE handle = PK11_FindCertInSlot(builtinSlot.get(), cert,
-                                                nullptr);
-  result = (handle != CK_INVALID_HANDLE);
   return Success;
 }
 
 static Result
 BuildCertChainForOneKeyUsage(NSSCertDBTrustDomain& trustDomain, Input certDER,
                              Time time, KeyUsage ku1, KeyUsage ku2,
                              KeyUsage ku3, KeyPurposeId eku,
                              const CertPolicyId& requiredPolicy,
--- a/security/manager/ssl/ScopedNSSTypes.h
+++ b/security/manager/ssl/ScopedNSSTypes.h
@@ -282,16 +282,35 @@ public:
   }
 
   ~ScopedAutoSECItem()
   {
     reset();
   }
 };
 
+class MOZ_RAII AutoSECMODListReadLock final
+{
+public:
+  AutoSECMODListReadLock()
+    : mLock(SECMOD_GetDefaultModuleListLock())
+  {
+    MOZ_ASSERT(mLock, "should have SECMOD lock (has NSS been initialized?)");
+    SECMOD_GetReadLock(mLock);
+  }
+
+  ~AutoSECMODListReadLock()
+  {
+    SECMOD_ReleaseReadLock(mLock);
+  }
+
+private:
+  SECMODListLock* mLock;
+};
+
 namespace internal {
 
 inline void SECITEM_FreeItem_true(SECItem * s)
 {
   return SECITEM_FreeItem(s, true);
 }
 
 inline void SECOID_DestroyAlgorithmID_true(SECAlgorithmID * a)
--- a/security/manager/ssl/nsPKCS11Slot.h
+++ b/security/manager/ssl/nsPKCS11Slot.h
@@ -75,28 +75,9 @@ protected:
   // Nothing to release.
   virtual void virtualDestroyNSSReference() override {}
 };
 
 #define NS_PKCS11MODULEDB_CID \
 { 0xff9fbcd7, 0x9517, 0x4334, \
   { 0xb9, 0x7a, 0xce, 0xed, 0x78, 0x90, 0x99, 0x74 }}
 
-class MOZ_RAII AutoSECMODListReadLock final
-{
-public:
-  AutoSECMODListReadLock()
-    : mLock(SECMOD_GetDefaultModuleListLock())
-  {
-    MOZ_ASSERT(mLock, "Should have the default SECMOD lock");
-    SECMOD_GetReadLock(mLock);
-  }
-
-  ~AutoSECMODListReadLock()
-  {
-    SECMOD_ReleaseReadLock(mLock);
-  }
-
-private:
-  SECMODListLock* mLock;
-};
-
 #endif // nsPKCS11Slot_h