bug 1466942 - avoid l10n string bundles in nsNSSComponent initialization r=fkiefer
authorDavid Keeler <dkeeler@mozilla.com>
Mon, 04 Jun 2018 17:07:06 -0700
changeset 475847 1ab062fd31db7d4367a479fedb350dc6fcee7a3f
parent 475846 ec66192b6be9139037a7a40145570ddd6598bb19
child 475848 f7fd9b08c0156be5b5cd99de5ed0ed0b98d93051
child 475849 00f45773f03d8a98b4d426abc758e63853b96819
child 475907 5e2b8c50e708e20fb90ea6486eb254b4f51479de
push id9374
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:43:20 +0000
treeherdermozilla-beta@160e085dfb0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfkiefer
bugs1466942
milestone62.0a1
first release with
nightly linux32
1ab062fd31db / 62.0a1 / 20180606220131 / files
nightly linux64
1ab062fd31db / 62.0a1 / 20180606220131 / files
nightly mac
1ab062fd31db / 62.0a1 / 20180606220131 / files
nightly win32
1ab062fd31db / 62.0a1 / 20180606220131 / files
nightly win64
1ab062fd31db / 62.0a1 / 20180606220131 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1466942 - avoid l10n string bundles in nsNSSComponent initialization r=fkiefer Before this patch, nsNSSComponent initialization would call PK11_ConfigurePKCS11 with some localized strings, which contributed to startup time. Also, PK11_UnconfigurePKCS11 was never called, so the memory allocated to these strings would stick around forever. This patch addresses both of these problems by not calling PK11_ConfigurePKCS11. This means that some properties of NSS' internal "PKCS#11 slots/tokens" have to be localized when displaying them to the user. MozReview-Commit-ID: BbAgbgpFfFG
security/manager/locales/en-US/chrome/pipnss/pipnss.properties
security/manager/pki/resources/content/device_manager.js
security/manager/ssl/nsIPK11Token.idl
security/manager/ssl/nsNSSCertHelper.cpp
security/manager/ssl/nsNSSCertHelper.h
security/manager/ssl/nsNSSCertificate.cpp
security/manager/ssl/nsNSSComponent.cpp
security/manager/ssl/nsNSSComponent.h
security/manager/ssl/nsPK11TokenDB.cpp
security/manager/ssl/nsPK11TokenDB.h
security/manager/ssl/nsPKCS11Slot.cpp
security/manager/ssl/nsPKCS11Slot.h
security/manager/ssl/tests/unit/test_certDB_import.js
security/manager/ssl/tests/unit/test_pkcs11_slot.js
security/manager/ssl/tests/unit/test_pkcs11_token.js
--- a/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
+++ b/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
@@ -51,20 +51,16 @@ PrivateSlotDescription=PSM Private Keys
 # LOCALIZATION NOTE (Fips140TokenDescription): string limit is 32 bytes after
 # conversion to UTF-8.
 # length_limit = 32 bytes
 Fips140TokenDescription=Software Security Device (FIPS)
 # LOCALIZATION NOTE (Fips140SlotDescription): string limit is 64 bytes after
 # conversion to UTF-8.
 # length_limit = 64 bytes
 Fips140SlotDescription=FIPS 140 Cryptographic, Key and Certificate Services
-# LOCALIZATION NOTE (InternalToken): string limit is 32 bytes after conversion
-# to UTF-8.
-# length_limit = 32 bytes
-InternalToken=Software Security Device
 
 VerifySSLClient=SSL Client Certificate
 VerifySSLServer=SSL Server Certificate
 VerifySSLCA=SSL Certificate Authority
 VerifyEmailSigner=Email Signer Certificate
 VerifyEmailRecip=Email Recipient Certificate
 HighGrade=High Grade
 MediumGrade=Medium Grade
--- a/security/manager/pki/resources/content/device_manager.js
+++ b/security/manager/pki/resources/content/device_manager.js
@@ -358,17 +358,17 @@ function changePassword() {
   enableButtons();
 }
 
 // -------------------------------------   Old code
 
 function showTokenInfo() {
   var selected_token = selected_slot.getToken();
   AddInfoRow(bundle.getString("devinfo_label"),
-             selected_token.tokenLabel, "tok_label");
+             selected_token.tokenName, "tok_label");
   AddInfoRow(bundle.getString("devinfo_manID"),
              selected_token.tokenManID, "tok_manID");
   AddInfoRow(bundle.getString("devinfo_serialnum"),
              selected_token.tokenSerialNumber, "tok_sNum");
   AddInfoRow(bundle.getString("devinfo_hwversion"),
              selected_token.tokenHWVersion, "tok_hwv");
   AddInfoRow(bundle.getString("devinfo_fwversion"),
              selected_token.tokenFWVersion, "tok_fwv");
--- a/security/manager/ssl/nsIPK11Token.idl
+++ b/security/manager/ssl/nsIPK11Token.idl
@@ -10,18 +10,16 @@
 interface nsIPK11Token : nsISupports
 {
   /*
    * The name of the token
    */
   [must_use]
   readonly attribute AUTF8String tokenName;
   [must_use]
-  readonly attribute AUTF8String tokenLabel;
-  [must_use]
   readonly attribute boolean isInternalKeyToken;
   /**
    * Manufacturer ID of the token.
    */
   [must_use]
   readonly attribute AUTF8String tokenManID;
   /**
    * Hardware version of the token.
--- a/security/manager/ssl/nsNSSCertHelper.cpp
+++ b/security/manager/ssl/nsNSSCertHelper.cpp
@@ -61,16 +61,28 @@ GetPIPNSSBundleString(const char* string
   if (NS_FAILED(rv)) {
     return rv;
   }
   result.Truncate();
   return pipnssBundle->GetStringFromName(stringName, result);
 }
 
 nsresult
+GetPIPNSSBundleString(const char* stringName, nsACString& result)
+{
+  nsAutoString tmp;
+  nsresult rv = GetPIPNSSBundleString(stringName, tmp);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  result.Assign(NS_ConvertUTF16toUTF8(tmp));
+  return NS_OK;
+}
+
+nsresult
 PIPBundleFormatStringFromName(const char* stringName, const char16_t** params,
                               uint32_t numParams, nsAString& result)
 {
   MOZ_ASSERT(stringName);
   MOZ_ASSERT(params);
   if (!stringName || !params) {
     return NS_ERROR_INVALID_ARG;
   }
--- a/security/manager/ssl/nsNSSCertHelper.h
+++ b/security/manager/ssl/nsNSSCertHelper.h
@@ -24,12 +24,14 @@ GetCertFingerprintByOidTag(CERTCertifica
 
 void
 LossyUTF8ToUTF16(const char* str, uint32_t len, /*out*/ nsAString& result);
 
 // Must be used on the main thread only.
 nsresult
 GetPIPNSSBundleString(const char* stringName, nsAString& result);
 nsresult
+GetPIPNSSBundleString(const char* stringName, nsACString& result);
+nsresult
 PIPBundleFormatStringFromName(const char* stringName, const char16_t** params,
                               uint32_t numParams, nsAString& result);
 
 #endif // nsNSSCertHelper_h
--- a/security/manager/ssl/nsNSSCertificate.cpp
+++ b/security/manager/ssl/nsNSSCertificate.cpp
@@ -666,38 +666,32 @@ NS_IMETHODIMP
 nsNSSCertificate::GetSha1Fingerprint(nsAString& _sha1Fingerprint)
 {
   return GetCertificateHash(_sha1Fingerprint, SEC_OID_SHA1);
 }
 
 NS_IMETHODIMP
 nsNSSCertificate::GetTokenName(nsAString& aTokenName)
 {
-  aTokenName.Truncate();
-  if (mCert) {
-    // HACK alert
-    // When the trust of a builtin cert is modified, NSS copies it into the
-    // cert db.  At this point, it is now "managed" by the user, and should
-    // not be listed with the builtins.  However, in the collection code
-    // used by PK11_ListCerts, the cert is found in the temp db, where it
-    // has been loaded from the token.  Though the trust is correct (grabbed
-    // from the cert db), the source is wrong.  I believe this is a safe
-    // way to work around this.
-    if (mCert->slot) {
-      char* token = PK11_GetTokenName(mCert->slot);
-      if (token) {
-        aTokenName = NS_ConvertUTF8toUTF16(token);
-      }
-    } else {
-      nsAutoString tok;
-      if (NS_SUCCEEDED(GetPIPNSSBundleString("InternalToken", tok))) {
-        aTokenName = tok;
-      }
-    }
+  MOZ_ASSERT(mCert);
+  if (!mCert) {
+    return NS_ERROR_FAILURE;
+  }
+  UniquePK11SlotInfo internalSlot(PK11_GetInternalSlot());
+  if (!internalSlot) {
+    return NS_ERROR_FAILURE;
   }
+  nsCOMPtr<nsIPK11Token> token(
+    new nsPK11Token(mCert->slot ? mCert->slot : internalSlot.get()));
+  nsAutoCString tmp;
+  nsresult rv = token->GetTokenName(tmp);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  aTokenName.Assign(NS_ConvertUTF8toUTF16(tmp));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNSSCertificate::GetSha256SubjectPublicKeyInfoDigest(nsACString& aSha256SPKIDigest)
 {
   aSha256SPKIDigest.Truncate();
   Digest digest;
--- a/security/manager/ssl/nsNSSComponent.cpp
+++ b/security/manager/ssl/nsNSSComponent.cpp
@@ -1224,65 +1224,16 @@ LoadLoadableRootsTask::LoadLoadableRoots
                                             possibleCKBILocation.get()));
       return NS_OK;
     }
   }
   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("could not load loadable roots"));
   return NS_ERROR_FAILURE;
 }
 
-nsresult
-nsNSSComponent::ConfigureInternalPKCS11Token()
-{
-  nsAutoString manufacturerID;
-  nsAutoString libraryDescription;
-  nsAutoString tokenDescription;
-  nsAutoString privateTokenDescription;
-  nsAutoString slotDescription;
-  nsAutoString privateSlotDescription;
-  nsAutoString fips140SlotDescription;
-  nsAutoString fips140TokenDescription;
-
-  nsresult rv;
-  rv = GetPIPNSSBundleString("ManufacturerID", manufacturerID);
-  if (NS_FAILED(rv)) return rv;
-
-  rv = GetPIPNSSBundleString("LibraryDescription", libraryDescription);
-  if (NS_FAILED(rv)) return rv;
-
-  rv = GetPIPNSSBundleString("TokenDescription", tokenDescription);
-  if (NS_FAILED(rv)) return rv;
-
-  rv = GetPIPNSSBundleString("PrivateTokenDescription", privateTokenDescription);
-  if (NS_FAILED(rv)) return rv;
-
-  rv = GetPIPNSSBundleString("SlotDescription", slotDescription);
-  if (NS_FAILED(rv)) return rv;
-
-  rv = GetPIPNSSBundleString("PrivateSlotDescription", privateSlotDescription);
-  if (NS_FAILED(rv)) return rv;
-
-  rv = GetPIPNSSBundleString("Fips140SlotDescription", fips140SlotDescription);
-  if (NS_FAILED(rv)) return rv;
-
-  rv = GetPIPNSSBundleString("Fips140TokenDescription", fips140TokenDescription);
-  if (NS_FAILED(rv)) return rv;
-
-  PK11_ConfigurePKCS11(NS_ConvertUTF16toUTF8(manufacturerID).get(),
-                       NS_ConvertUTF16toUTF8(libraryDescription).get(),
-                       NS_ConvertUTF16toUTF8(tokenDescription).get(),
-                       NS_ConvertUTF16toUTF8(privateTokenDescription).get(),
-                       NS_ConvertUTF16toUTF8(slotDescription).get(),
-                       NS_ConvertUTF16toUTF8(privateSlotDescription).get(),
-                       NS_ConvertUTF16toUTF8(fips140SlotDescription).get(),
-                       NS_ConvertUTF16toUTF8(fips140TokenDescription).get(),
-                       0, 0);
-  return NS_OK;
-}
-
 // Table of pref names and SSL cipher ID
 typedef struct {
   const char* pref;
   long id;
   bool enabledByDefault;
 } CipherPref;
 
 // Update the switch statement in AccumulateCipherSuite in nsNSSCallbacks.cpp
@@ -1929,24 +1880,16 @@ nsNSSComponent::InitializeNSS()
   static_assert(nsINSSErrorsService::NSS_SEC_ERROR_BASE == SEC_ERROR_BASE &&
                 nsINSSErrorsService::NSS_SEC_ERROR_LIMIT == SEC_ERROR_LIMIT &&
                 nsINSSErrorsService::NSS_SSL_ERROR_BASE == SSL_ERROR_BASE &&
                 nsINSSErrorsService::NSS_SSL_ERROR_LIMIT == SSL_ERROR_LIMIT,
                 "You must update the values in nsINSSErrorsService.idl");
 
   MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("NSS Initialization beginning\n"));
 
-  // The call to ConfigureInternalPKCS11Token needs to be done before NSS is initialized,
-  // but affects only static data.
-  // If we could assume i18n will not change between profiles, one call per application
-  // run were sufficient. As I can't predict what happens in the future, let's repeat
-  // this call for every re-init of NSS.
-
-  ConfigureInternalPKCS11Token();
-
   nsAutoCString profileStr;
   nsresult rv = GetNSSProfilePath(profileStr);
   if (NS_FAILED(rv)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
 #if defined(XP_WIN) || (defined(XP_LINUX) && !defined(ANDROID))
   SetNSSDatabaseCacheModeAsAppropriate();
--- a/security/manager/ssl/nsNSSComponent.h
+++ b/security/manager/ssl/nsNSSComponent.h
@@ -142,17 +142,16 @@ protected:
 
 private:
   nsresult InitializeNSS();
   void ShutdownNSS();
 
   void setValidationOptions(bool isInitialSetting,
                             const mozilla::MutexAutoLock& proofOfLock);
   nsresult setEnabledTLSVersions();
-  nsresult ConfigureInternalPKCS11Token();
   nsresult RegisterObservers();
 
   void MaybeEnableFamilySafetyCompatibility();
   void MaybeImportEnterpriseRoots();
 #ifdef XP_WIN
   void ImportEnterpriseRootsForLocation(
     DWORD locationFlag, const mozilla::MutexAutoLock& proofOfLock);
   nsresult MaybeImportFamilySafetyRoot(PCCERT_CONTEXT certificate,
--- a/security/manager/ssl/nsPK11TokenDB.cpp
+++ b/security/manager/ssl/nsPK11TokenDB.cpp
@@ -22,44 +22,65 @@ extern mozilla::LazyLogModule gPIPNSSLog
 
 NS_IMPL_ISUPPORTS(nsPK11Token, nsIPK11Token)
 
 nsPK11Token::nsPK11Token(PK11SlotInfo* slot)
   : mUIContext(new PipUIContext())
 {
   MOZ_ASSERT(slot);
   mSlot.reset(PK11_ReferenceSlot(slot));
+  mIsInternalCryptoToken = PK11_IsInternal(mSlot.get()) &&
+                           !PK11_IsInternalKeySlot(mSlot.get());
+  mIsInternalKeyToken = PK11_IsInternalKeySlot(mSlot.get());
   mSeries = PK11_GetSlotSeries(slot);
-
   Unused << refreshTokenInfo();
 }
 
 nsresult
 nsPK11Token::refreshTokenInfo()
 {
-  mTokenName = PK11_GetTokenName(mSlot.get());
+  if (mIsInternalCryptoToken) {
+    nsresult rv;
+    if (PK11_IsFIPS()) {
+      rv = GetPIPNSSBundleString("Fips140TokenDescription", mTokenName);
+    } else {
+      rv = GetPIPNSSBundleString("TokenDescription", mTokenName);
+    }
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  } else if (mIsInternalKeyToken) {
+    nsresult rv = GetPIPNSSBundleString("PrivateTokenDescription", mTokenName);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  } else {
+    mTokenName.Assign(PK11_GetTokenName(mSlot.get()));
+  }
 
   CK_TOKEN_INFO tokInfo;
   nsresult rv = MapSECStatus(PK11_GetTokenInfo(mSlot.get(), &tokInfo));
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  // Set the Label field
-  const char* ccLabel = mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(tokInfo.label);
-  mTokenLabel.Assign(ccLabel, strnlen(ccLabel, sizeof(tokInfo.label)));
-  mTokenLabel.Trim(" ", false, true);
-
   // Set the Manufacturer field
-  const char* ccManID =
-    mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(tokInfo.manufacturerID);
-  mTokenManufacturerID.Assign(
-    ccManID,
-    strnlen(ccManID, sizeof(tokInfo.manufacturerID)));
-  mTokenManufacturerID.Trim(" ", false, true);
+  if (mIsInternalCryptoToken || mIsInternalKeyToken) {
+    rv = GetPIPNSSBundleString("ManufacturerID", mTokenManufacturerID);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  } else {
+    const char* ccManID =
+      mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(tokInfo.manufacturerID);
+    mTokenManufacturerID.Assign(
+      ccManID,
+      strnlen(ccManID, sizeof(tokInfo.manufacturerID)));
+    mTokenManufacturerID.Trim(" ", false, true);
+  }
 
   // Set the Hardware Version field
   mTokenHWVersion.Truncate();
   mTokenHWVersion.AppendInt(tokInfo.hardwareVersion.major);
   mTokenHWVersion.Append('.');
   mTokenHWVersion.AppendInt(tokInfo.hardwareVersion.minor);
 
   // Set the Firmware Version field
@@ -96,26 +117,20 @@ nsPK11Token::GetAttributeHelper(const ns
 
 NS_IMETHODIMP
 nsPK11Token::GetTokenName(/*out*/ nsACString& tokenName)
 {
   return GetAttributeHelper(mTokenName, tokenName);
 }
 
 NS_IMETHODIMP
-nsPK11Token::GetTokenLabel(/*out*/ nsACString& tokenLabel)
-{
-  return GetAttributeHelper(mTokenLabel, tokenLabel);
-}
-
-NS_IMETHODIMP
 nsPK11Token::GetIsInternalKeyToken(/*out*/ bool* _retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
-  *_retval = PK11_IsInternalKeySlot(mSlot.get());
+  *_retval = mIsInternalKeyToken;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPK11Token::GetTokenManID(/*out*/ nsACString& tokenManufacturerID)
 {
   return GetAttributeHelper(mTokenManufacturerID, tokenManufacturerID);
 }
--- a/security/manager/ssl/nsPK11TokenDB.h
+++ b/security/manager/ssl/nsPK11TokenDB.h
@@ -27,22 +27,25 @@ public:
 protected:
   virtual ~nsPK11Token() {}
 
 private:
   friend class nsPK11TokenDB;
   nsresult refreshTokenInfo();
 
   nsCString mTokenName;
-  nsCString mTokenLabel;
   nsCString mTokenManufacturerID;
   nsCString mTokenHWVersion;
   nsCString mTokenFWVersion;
   nsCString mTokenSerialNum;
   mozilla::UniquePK11SlotInfo mSlot;
+  // True if this is the "PKCS#11 token" that provides cryptographic functions.
+  bool mIsInternalCryptoToken;
+  // True if this is the "PKCS#11 token" where private keys are stored.
+  bool mIsInternalKeyToken;
   int mSeries;
   nsCOMPtr<nsIInterfaceRequestor> mUIContext;
   nsresult GetAttributeHelper(const nsACString& attribute,
                       /*out*/ nsACString& xpcomOutParam);
 };
 
 class nsPK11TokenDB : public nsIPK11TokenDB
 {
--- a/security/manager/ssl/nsPKCS11Slot.cpp
+++ b/security/manager/ssl/nsPKCS11Slot.cpp
@@ -22,42 +22,69 @@ using mozilla::LogLevel;
 extern mozilla::LazyLogModule gPIPNSSLog;
 
 NS_IMPL_ISUPPORTS(nsPKCS11Slot, nsIPKCS11Slot)
 
 nsPKCS11Slot::nsPKCS11Slot(PK11SlotInfo* slot)
 {
   MOZ_ASSERT(slot);
   mSlot.reset(PK11_ReferenceSlot(slot));
+  mIsInternalCryptoSlot = PK11_IsInternal(mSlot.get()) &&
+                          !PK11_IsInternalKeySlot(mSlot.get());
+  mIsInternalKeySlot = PK11_IsInternalKeySlot(mSlot.get());
   mSeries = PK11_GetSlotSeries(slot);
   Unused << refreshSlotInfo();
 }
 
 nsresult
 nsPKCS11Slot::refreshSlotInfo()
 {
   CK_SLOT_INFO slotInfo;
   nsresult rv = MapSECStatus(PK11_GetSlotInfo(mSlot.get(), &slotInfo));
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   // Set the Description field
-  const char* ccDesc =
-    mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(slotInfo.slotDescription);
-  mSlotDesc.Assign(ccDesc, strnlen(ccDesc, sizeof(slotInfo.slotDescription)));
-  mSlotDesc.Trim(" ", false, true);
+  if (mIsInternalCryptoSlot) {
+    nsresult rv;
+    if (PK11_IsFIPS()) {
+      rv = GetPIPNSSBundleString("Fips140SlotDescription", mSlotDesc);
+    } else {
+      rv = GetPIPNSSBundleString("SlotDescription", mSlotDesc);
+    }
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  } else if (mIsInternalKeySlot) {
+    rv = GetPIPNSSBundleString("PrivateSlotDescription", mSlotDesc);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  } else {
+    const char* ccDesc =
+      mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(slotInfo.slotDescription);
+    mSlotDesc.Assign(ccDesc, strnlen(ccDesc, sizeof(slotInfo.slotDescription)));
+    mSlotDesc.Trim(" ", false, true);
+  }
 
   // Set the Manufacturer field
-  const char* ccManID =
-    mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(slotInfo.manufacturerID);
-  mSlotManufacturerID.Assign(
-    ccManID,
-    strnlen(ccManID, sizeof(slotInfo.manufacturerID)));
-  mSlotManufacturerID.Trim(" ", false, true);
+  if (mIsInternalCryptoSlot || mIsInternalKeySlot) {
+    rv = GetPIPNSSBundleString("ManufacturerID", mSlotManufacturerID);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  } else {
+    const char* ccManID =
+      mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(slotInfo.manufacturerID);
+    mSlotManufacturerID.Assign(
+      ccManID,
+      strnlen(ccManID, sizeof(slotInfo.manufacturerID)));
+    mSlotManufacturerID.Trim(" ", false, true);
+  }
 
   // Set the Hardware Version field
   mSlotHWVersion.Truncate();
   mSlotHWVersion.AppendInt(slotInfo.hardwareVersion.major);
   mSlotHWVersion.Append('.');
   mSlotHWVersion.AppendInt(slotInfo.hardwareVersion.minor);
 
   // Set the Firmware Version field
@@ -82,29 +109,26 @@ nsPKCS11Slot::GetAttributeHelper(const n
 
   xpcomOutParam = attribute;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPKCS11Slot::GetName(/*out*/ nsACString& name)
 {
-  // |csn| is non-owning.
-  char* csn = PK11_GetSlotName(mSlot.get());
-  if (csn && *csn) {
-    name = csn;
-  } else if (PK11_HasRootCerts(mSlot.get())) {
-    // This is a workaround to an Root Module bug - the root certs module has
-    // no slot name.  Not bothering to localize, because this is a workaround
-    // and for now all the slot names returned by NSS are char * anyway.
-    name = NS_LITERAL_CSTRING("Root Certificates");
-  } else {
-    // same as above, this is a catch-all
-    name = NS_LITERAL_CSTRING("Unnamed Slot");
+  if (mIsInternalCryptoSlot) {
+    if (PK11_IsFIPS()) {
+      return GetPIPNSSBundleString("Fips140TokenDescription", name);
+    }
+    return GetPIPNSSBundleString("TokenDescription", name);
   }
+  if (mIsInternalKeySlot) {
+    return GetPIPNSSBundleString("PrivateTokenDescription", name);
+  }
+  name.Assign(PK11_GetSlotName(mSlot.get()));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPKCS11Slot::GetDesc(/*out*/ nsACString& desc)
 {
   return GetAttributeHelper(mSlotDesc, desc);
@@ -147,17 +171,27 @@ nsPKCS11Slot::GetTokenName(/*out*/ nsACS
 
   if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
     nsresult rv = refreshSlotInfo();
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
 
-  tokenName = PK11_GetTokenName(mSlot.get());
+  if (mIsInternalCryptoSlot) {
+    if (PK11_IsFIPS()) {
+      return GetPIPNSSBundleString("Fips140TokenDescription", tokenName);
+    }
+    return GetPIPNSSBundleString("TokenDescription", tokenName);
+  }
+  if (mIsInternalKeySlot) {
+    return GetPIPNSSBundleString("PrivateTokenDescription", tokenName);
+  }
+
+  tokenName.Assign(PK11_GetTokenName(mSlot.get()));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPKCS11Slot::GetStatus(uint32_t* _retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   if (PK11_IsDisabled(mSlot.get())) {
--- a/security/manager/ssl/nsPKCS11Slot.h
+++ b/security/manager/ssl/nsPKCS11Slot.h
@@ -22,16 +22,20 @@ public:
 
   explicit nsPKCS11Slot(PK11SlotInfo* slot);
 
 protected:
   virtual ~nsPKCS11Slot() {}
 
 private:
   mozilla::UniquePK11SlotInfo mSlot;
+  // True if this is the "PKCS#11 slot" that provides cryptographic functions.
+  bool mIsInternalCryptoSlot;
+  // True if this is the "PKCS#11 slot" where private keys are stored.
+  bool mIsInternalKeySlot;
   nsCString mSlotDesc;
   nsCString mSlotManufacturerID;
   nsCString mSlotHWVersion;
   nsCString mSlotFWVersion;
   int mSeries;
 
   nsresult refreshSlotInfo();
   nsresult GetAttributeHelper(const nsACString& attribute,
--- a/security/manager/ssl/tests/unit/test_certDB_import.js
+++ b/security/manager/ssl/tests/unit/test_certDB_import.js
@@ -120,11 +120,16 @@ function run_test() {
 
   // Import the CA cert so that the e-mail import succeeds.
   testImportCACert();
 
   // Import the e-mail cert and check for success.
   let emailArray = getCertAsByteArray("test_certDB_import/emailEE.pem");
   gCertDB.importEmailCertificate(emailArray, emailArray.length,
                                  gInterfaceRequestor);
-  notEqual(findCertByEmailAddress(TEST_EMAIL_ADDRESS), null,
-           "E-mail cert should now be found in the database");
+  let emailCert = findCertByEmailAddress(TEST_EMAIL_ADDRESS);
+  notEqual(emailCert, null, "E-mail cert should now be found in the database");
+  let bundle =
+    Services.strings.createBundle("chrome://pipnss/locale/pipnss.properties");
+  equal(emailCert.tokenName,
+        bundle.GetStringFromName("PrivateTokenDescription"),
+        "cert's tokenName should be the expected localized value");
 }
--- a/security/manager/ssl/tests/unit/test_pkcs11_slot.js
+++ b/security/manager/ssl/tests/unit/test_pkcs11_slot.js
@@ -13,29 +13,33 @@ function find_slot_by_name(module, name)
                                                    Ci.nsIPKCS11Slot)) {
     if (slot.name == name) {
       return slot;
     }
   }
   return null;
 }
 
+function find_module_by_name(moduleDB, name) {
+  for (let slot of XPCOMUtils.IterSimpleEnumerator(moduleDB.listModules(),
+                                                   Ci.nsIPKCS11Module)) {
+    if (slot.name == name) {
+      return slot;
+    }
+  }
+  return null;
+}
+
 function run_test() {
   loadPKCS11TestModule(false);
 
   let moduleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"]
                    .getService(Ci.nsIPKCS11ModuleDB);
-  let testModule;
-  for (let module of XPCOMUtils.IterSimpleEnumerator(moduleDB.listModules(),
-                                                     Ci.nsIPKCS11Module)) {
-    if (module.name == "PKCS11 Test Module") {
-      testModule = module;
-      break;
-    }
-  }
+  let testModule = find_module_by_name(moduleDB, "PKCS11 Test Module");
+  notEqual(testModule, null, "should be able to find test module");
   let testSlot = find_slot_by_name(testModule, "Test PKCS11 Slot 二");
   notEqual(testSlot, null, "should be able to find 'Test PKCS11 Slot 二'");
 
   equal(testSlot.name, "Test PKCS11 Slot 二",
         "Actual and expected name should match");
   equal(testSlot.desc, "Test PKCS11 Slot 二",
         "Actual and expected description should match");
   equal(testSlot.manID, "Test PKCS11 Manufacturer ID",
@@ -46,18 +50,38 @@ function run_test() {
         "Actual and expected firmware version should match");
   equal(testSlot.status, Ci.nsIPKCS11Slot.SLOT_READY,
         "Actual and expected status should match");
   equal(testSlot.tokenName, "Test PKCS11 Tokeñ 2 Label",
         "Actual and expected token name should match");
 
   let testToken = testSlot.getToken();
   notEqual(testToken, null, "getToken() should succeed");
-  equal(testToken.tokenLabel, "Test PKCS11 Tokeñ 2 Label",
-        "Spot check: the actual and expected test token labels should be equal");
+  equal(testToken.tokenName, "Test PKCS11 Tokeñ 2 Label",
+        "Spot check: the actual and expected test token names should be equal");
   ok(!testToken.isInternalKeyToken, "This token is not the internal key token");
 
   testSlot = find_slot_by_name(testModule, "Empty PKCS11 Slot");
   notEqual(testSlot, null, "should be able to find 'Empty PKCS11 Slot'");
   equal(testSlot.tokenName, null, "Empty slot is empty");
   equal(testSlot.status, Ci.nsIPKCS11Slot.SLOT_NOT_PRESENT,
         "Actual and expected status should match");
+
+  let bundle =
+    Services.strings.createBundle("chrome://pipnss/locale/pipnss.properties");
+  let internalModule = find_module_by_name(moduleDB,
+                                           "NSS Internal PKCS #11 Module");
+  notEqual(internalModule, null, "should be able to find internal module");
+  let cryptoSlot = find_slot_by_name(
+    internalModule, bundle.GetStringFromName("TokenDescription"));
+  notEqual(cryptoSlot, "should be able to find internal crypto slot");
+  equal(cryptoSlot.desc, bundle.GetStringFromName("SlotDescription"),
+        "crypto slot should have expected 'desc'");
+  equal(cryptoSlot.manID, bundle.GetStringFromName("ManufacturerID"),
+        "crypto slot should have expected 'manID'");
+  let keySlot = find_slot_by_name(
+    internalModule, bundle.GetStringFromName("PrivateTokenDescription"));
+  notEqual(keySlot, "should be able to find internal key slot");
+  equal(keySlot.desc, bundle.GetStringFromName("PrivateSlotDescription"),
+        "key slot should have expected 'desc'");
+  equal(keySlot.manID, bundle.GetStringFromName("ManufacturerID"),
+        "key slot should have expected 'manID'");
 }
--- a/security/manager/ssl/tests/unit/test_pkcs11_token.js
+++ b/security/manager/ssl/tests/unit/test_pkcs11_token.js
@@ -19,18 +19,16 @@ do_get_profile();
 
 function checkBasicAttributes(token) {
   let bundle =
     Services.strings.createBundle("chrome://pipnss/locale/pipnss.properties");
 
   let expectedTokenName = bundle.GetStringFromName("PrivateTokenDescription");
   equal(token.tokenName, expectedTokenName,
         "Actual and expected name should match");
-  equal(token.tokenLabel, expectedTokenName,
-        "Actual and expected label should match");
   equal(token.tokenManID, bundle.GetStringFromName("ManufacturerID"),
         "Actual and expected manufacturer ID should match");
   equal(token.tokenHWVersion, "0.0",
         "Actual and expected hardware version should match");
   equal(token.tokenFWVersion, "0.0",
         "Actual and expected firmware version should match");
   equal(token.tokenSerialNumber, "0000000000000000",
         "Actual and expected serial number should match");