bug 1324071 - add nsIPK11Token.hasPassword to replace unnecessary uses of nsIPKCS11Slot.status r=Cykesiopka,gps,MattN,sebastian
authorDavid Keeler <dkeeler@mozilla.com>
Fri, 02 Dec 2016 15:09:35 -0800
changeset 327125 6f732b38a5a2
parent 327124 d116e76778e6
child 327126 f95e3018e089
push id31121
push userphilringnalda@gmail.com
push date2016-12-25 00:50 +0000
treeherdermozilla-central@693dabe3a92a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersCykesiopka, gps, MattN, sebastian
bugs1324071
milestone53.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 1324071 - add nsIPK11Token.hasPassword to replace unnecessary uses of nsIPKCS11Slot.status r=Cykesiopka,gps,MattN,sebastian MozReview-Commit-ID: C2jwQHPEDC0
browser/base/content/browser.js
mobile/android/chrome/content/MasterPassword.js
security/manager/pki/resources/content/changepassword.js
security/manager/pki/resources/content/device_manager.js
security/manager/ssl/nsIPK11Token.idl
security/manager/ssl/nsPK11TokenDB.cpp
security/manager/ssl/nsPKCS11Slot.cpp
security/manager/ssl/tests/unit/test_pkcs11_module.js
security/manager/ssl/tests/unit/test_pkcs11_token.js
services/sync/modules/util.js
toolkit/components/passwordmgr/LoginHelper.jsm
toolkit/components/passwordmgr/crypto-SDR.js
toolkit/components/passwordmgr/test/LoginTestUtils.jsm
toolkit/mozapps/preferences/changemp.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1425,22 +1425,20 @@ var gBrowserInit = {
       AddonWatcher.init();
 
       // Telemetry for master-password - we do this after 5 seconds as it
       // can cause IO if NSS/PSM has not already initialized.
       setTimeout(() => {
         if (window.closed) {
           return;
         }
-        let secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"]
-                       .getService(Ci.nsIPKCS11ModuleDB);
-        let slot = secmodDB.findSlotByName("");
-        let mpEnabled = slot &&
-                        slot.status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED &&
-                        slot.status != Ci.nsIPKCS11Slot.SLOT_READY;
+        let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"]
+                        .getService(Ci.nsIPK11TokenDB);
+        let token = tokenDB.getInternalKeyToken();
+        let mpEnabled = token.hasPassword;
         if (mpEnabled) {
           Services.telemetry.getHistogramById("MASTER_PASSWORD_ENABLED").add(mpEnabled);
         }
       }, 5000);
 
       PanicButtonNotifier.init();
     });
 
--- a/mobile/android/chrome/content/MasterPassword.js
+++ b/mobile/android/chrome/content/MasterPassword.js
@@ -2,52 +2,38 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 XPCOMUtils.defineLazyModuleGetter(this, "Snackbars", "resource://gre/modules/Snackbars.jsm");
 
 var MasterPassword = {
   pref: "privacy.masterpassword.enabled",
-  _tokenName: "",
-
-  get _secModuleDB() {
-    delete this._secModuleDB;
-    return this._secModuleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(Ci.nsIPKCS11ModuleDB);
-  },
 
   get _pk11DB() {
     delete this._pk11DB;
     return this._pk11DB = Cc["@mozilla.org/security/pk11tokendb;1"].getService(Ci.nsIPK11TokenDB);
   },
 
   get enabled() {
-    let slot = this._secModuleDB.findSlotByName(this._tokenName);
-    if (slot) {
-      let status = slot.status;
-      return status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED && status != Ci.nsIPKCS11Slot.SLOT_READY;
+    let token = this._pk11DB.getInternalKeyToken();
+    if (token) {
+      return token.hasPassword;
     }
     return false;
   },
 
   setPassword: function setPassword(aPassword) {
     try {
-      let status;
-      let slot = this._secModuleDB.findSlotByName(this._tokenName);
-      if (slot)
-        status = slot.status;
-      else
-        return false;
-
-      let token = this._pk11DB.findTokenByName(this._tokenName);
-
-      if (status == Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED)
+      let token = this._pk11DB.getInternalKeyToken();
+      if (token.needsUserInit) {
         token.initPassword(aPassword);
-      else if (status == Ci.nsIPKCS11Slot.SLOT_READY)
+      } else if (!token.needsLogin()) {
         token.changePassword("", aPassword);
+      }
 
       return true;
     } catch(e) {
       dump("MasterPassword.setPassword: " + e);
     }
     return false;
   },
 
--- a/security/manager/pki/resources/content/changepassword.js
+++ b/security/manager/pki/resources/content/changepassword.js
@@ -1,13 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
 const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
 const nsIPK11TokenDB = Components.interfaces.nsIPK11TokenDB;
 const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
 const nsPKCS11ModuleDB = "@mozilla.org/security/pkcs11moduledb;1";
 const nsIPKCS11ModuleDB = Components.interfaces.nsIPKCS11ModuleDB;
 const nsIPKCS11Slot = Components.interfaces.nsIPKCS11Slot;
 const nsIPK11Token = Components.interfaces.nsIPK11Token;
 
@@ -76,63 +78,72 @@ function onMenuChange()
    tokenName = list.value;
 
    process();
 }
 
 
 function process()
 {
-   var secmoddb = Components.classes[nsPKCS11ModuleDB].getService(nsIPKCS11ModuleDB);
-   var bundle = document.getElementById("pippki_bundle");
-
-   // If the token is unitialized, don't use the old password box.
-   // Otherwise, do.
+  let bundle = document.getElementById("pippki_bundle");
 
-   var slot = secmoddb.findSlotByName(tokenName);
-   if (slot) {
-     var oldpwbox = document.getElementById("oldpw");
-     var msgBox = document.getElementById("message");
-     var status = slot.status;
-     if (status == nsIPKCS11Slot.SLOT_UNINITIALIZED
-         || status == nsIPKCS11Slot.SLOT_READY) {
+  // If the token is unitialized, don't use the old password box.
+  // Otherwise, do.
 
-       oldpwbox.setAttribute("hidden", "true");
-       msgBox.setAttribute("value", bundle.getString("password_not_set"));
-       msgBox.setAttribute("hidden", "false");
-
-       if (status == nsIPKCS11Slot.SLOT_READY) {
-         oldpwbox.setAttribute("inited", "empty");
-       } else {
-         oldpwbox.setAttribute("inited", "true");
-       }
+  let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"]
+                  .getService(Ci.nsIPK11TokenDB);
+  let token;
+  if (tokenName.length > 0) {
+    token = tokenDB.findTokenByName(tokenName);
+  } else {
+    token = tokenDB.getInternalKeyToken();
+  }
+  if (token) {
+    let oldpwbox = document.getElementById("oldpw");
+    let msgBox = document.getElementById("message");
+    if ((token.needsLogin() && token.needsUserInit) || !token.needsLogin()) {
+      oldpwbox.setAttribute("hidden", "true");
+      msgBox.setAttribute("value", bundle.getString("password_not_set"));
+      msgBox.setAttribute("hidden", "false");
 
-       // Select first password field
-       document.getElementById("pw1").focus();
-     } else {
-       // Select old password field
-       oldpwbox.setAttribute("hidden", "false");
-       msgBox.setAttribute("hidden", "true");
-       oldpwbox.setAttribute("inited", "false");
-       oldpwbox.focus();
-     }
-   }
+      if (!token.needsLogin()) {
+        oldpwbox.setAttribute("inited", "empty");
+      } else {
+        oldpwbox.setAttribute("inited", "true");
+      }
+
+      // Select first password field
+      document.getElementById("pw1").focus();
+    } else {
+      // Select old password field
+      oldpwbox.setAttribute("hidden", "false");
+      msgBox.setAttribute("hidden", "true");
+      oldpwbox.setAttribute("inited", "false");
+      oldpwbox.focus();
+    }
+  }
 
   if (params) {
     // Return value 0 means "canceled"
     params.SetInt(1, 0);
   }
 
   checkPasswords();
 }
 
 function setPassword()
 {
-  var pk11db = Components.classes[nsPK11TokenDB].getService(nsIPK11TokenDB);
-  var token = pk11db.findTokenByName(tokenName);
+  let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"]
+                  .getService(Ci.nsIPK11TokenDB);
+  let token;
+  if (tokenName.length > 0) {
+    token = tokenDB.findTokenByName(tokenName);
+  } else {
+    token = tokenDB.getInternalKeyToken();
+  }
 
   var oldpwbox = document.getElementById("oldpw");
   var initpw = oldpwbox.getAttribute("inited");
   var bundle = document.getElementById("pippki_bundle");
 
   var success = false;
 
   if (initpw == "false" || initpw == "empty") {
--- a/security/manager/pki/resources/content/device_manager.js
+++ b/security/manager/pki/resources/content/device_manager.js
@@ -475,23 +475,20 @@ function toggleFIPS()
 {
   if (!secmoddb.isFIPSEnabled) {
     // A restriction of FIPS mode is, the password must be set
     // In FIPS mode the password must be non-empty.
     // This is different from what we allow in NON-Fips mode.
 
     var tokendb = Components.classes[nsPK11TokenDB].getService(nsIPK11TokenDB);
     var internal_token = tokendb.getInternalKeyToken(); // nsIPK11Token
-    var slot = secmoddb.findSlotByName(internal_token.tokenName);
-    switch (slot.status) {
-      case nsIPKCS11Slot.SLOT_UNINITIALIZED:
-      case nsIPKCS11Slot.SLOT_READY:
-        // Token has either no or an empty password.
-        doPrompt(bundle.getString("fips_nonempty_password_required"));
-        return;
+    if (!internal_token.hasPassword) {
+      // Token has either no or an empty password.
+      doPrompt(bundle.getString("fips_nonempty_password_required"));
+      return;
     }
   }
 
   try {
     secmoddb.toggleFIPSMode();
   }
   catch (e) {
     doPrompt(bundle.getString("unable_to_toggle_fips"));
--- a/security/manager/ssl/nsIPK11Token.idl
+++ b/security/manager/ssl/nsIPK11Token.idl
@@ -60,15 +60,23 @@ interface nsIPK11Token : nsISupports
   boolean checkPassword(in AUTF8String password);
   void initPassword(in AUTF8String initialPassword);
   void changePassword(in AUTF8String oldPassword, in AUTF8String newPassword);
   long getAskPasswordTimes();
   long getAskPasswordTimeout();
   void setAskPasswordDefaults([const] in long askTimes, [const] in long timeout);
 
   /*
+   * True if a password has been configured for this token, and false otherwise.
+   * (Whether or not the user is currently logged in makes no difference.)
+   * In particular, this can be used to determine if a user has set a master
+   * password (if this is the internal key token).
+   */
+  readonly attribute boolean hasPassword;
+
+  /*
    * Other attributes
    */
   boolean isHardwareToken();
   boolean needsLogin();
   boolean isFriendly();
 };
 
--- a/security/manager/ssl/nsPK11TokenDB.cpp
+++ b/security/manager/ssl/nsPK11TokenDB.cpp
@@ -354,16 +354,33 @@ nsPK11Token::ChangePassword(const nsACSt
   // See Bug 447589.
   return MapSECStatus(PK11_ChangePW(
     mSlot.get(),
     oldPassword.IsVoid() ? nullptr : PromiseFlatCString(oldPassword).get(),
     newPassword.IsVoid() ? nullptr : PromiseFlatCString(newPassword).get()));
 }
 
 NS_IMETHODIMP
+nsPK11Token::GetHasPassword(bool* hasPassword)
+{
+  NS_ENSURE_ARG_POINTER(hasPassword);
+
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  // PK11_NeedLogin returns true if the token is currently configured to require
+  // the user to log in (whether or not the user is actually logged in makes no
+  // difference).
+  *hasPassword = PK11_NeedLogin(mSlot.get()) && !PK11_NeedUserInit(mSlot.get());
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsPK11Token::IsHardwareToken(bool* _retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
 
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown())
     return NS_ERROR_NOT_AVAILABLE;
 
--- a/security/manager/ssl/nsPKCS11Slot.cpp
+++ b/security/manager/ssl/nsPKCS11Slot.cpp
@@ -448,16 +448,20 @@ nsPKCS11ModuleDB::FindSlotByName(const n
 {
   NS_ENSURE_ARG_POINTER(_retval);
 
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
+  if (name.IsEmpty()) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+
   UniquePK11SlotInfo slotInfo(
     PK11_FindSlotByName(PromiseFlatCString(name).get()));
   if (!slotInfo) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIPKCS11Slot> slot = new nsPKCS11Slot(slotInfo.get());
   slot.forget(_retval);
--- a/security/manager/ssl/tests/unit/test_pkcs11_module.js
+++ b/security/manager/ssl/tests/unit/test_pkcs11_module.js
@@ -100,16 +100,18 @@ function run_test() {
            "Internal 'slot' should be findable by name via the module DB");
   ok(internalTokenAsSlot instanceof Ci.nsIPKCS11Slot,
      "Module DB findSlotByName() should return a token as an nsIPKCS11Slot");
   equal(internalTokenAsSlot.name,
         bundle.GetStringFromName("PrivateSlotDescription"),
         "Spot check: actual and expected internal 'slot' names should be equal");
   throws(() => gModuleDB.findSlotByName("Not Present"), /NS_ERROR_FAILURE/,
          "Non-present 'slot' should not be findable by name via the module DB");
+  throws(() => gModuleDB.findSlotByName(""), /NS_ERROR_ILLEGAL_VALUE/,
+         "nsIPKCS11ModuleDB.findSlotByName should throw given an empty name");
 
   // Check that deleting the test module makes it disappear from the module list.
   let pkcs11 = Cc["@mozilla.org/security/pkcs11;1"].getService(Ci.nsIPKCS11);
   pkcs11.deleteModule("PKCS11 Test Module");
   checkTestModuleNotPresent();
 
   // Check miscellaneous module DB methods and attributes.
   notEqual(gModuleDB.getInternal(), null,
--- a/security/manager/ssl/tests/unit/test_pkcs11_token.js
+++ b/security/manager/ssl/tests/unit/test_pkcs11_token.js
@@ -46,16 +46,18 @@ function checkBasicAttributes(token) {
  * @param {nsIPK11Token} token
  *        The token to test.
  * @param {String} initialPW
  *        The password that the token should have been init with.
  */
 function checkPasswordFeaturesAndResetPassword(token, initialPW) {
   ok(!token.needsUserInit,
      "Token should not need user init after setting a password");
+  ok(token.hasPassword,
+     "Token should have a password after setting a password");
 
   equal(token.minimumPasswordLength, 0,
         "Actual and expected min password length should match");
 
   token.setAskPasswordDefaults(10, 20);
   equal(token.getAskPasswordTimes(), 10,
         "Actual and expected ask password times should match");
   equal(token.getAskPasswordTimeout(), 20,
@@ -71,34 +73,36 @@ function checkPasswordFeaturesAndResetPa
      "checkPassword() should fail if an incorrect password is given");
   ok(!token.isLoggedIn(),
      "Token should be logged out after an incorrect password was given");
   ok(!token.needsUserInit,
      "Token should still be init with a password even if an incorrect " +
      "password was given");
 
   token.reset();
-  ok(token.needsUserInit,
-     "Token should need password init after reset");
+  ok(token.needsUserInit, "Token should need password init after reset");
+  ok(!token.hasPassword, "Token should not have a password after reset");
   ok(!token.isLoggedIn(), "Token should be logged out of after reset");
 }
 
 function run_test() {
   let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"]
                   .getService(Ci.nsIPK11TokenDB);
   let token = tokenDB.getInternalKeyToken();
   notEqual(token, null, "The internal token should be present");
 
   checkBasicAttributes(token);
 
   ok(!token.isLoggedIn(), "Token should not be logged into yet");
   // Test that attempting to log out even when the token was not logged into
   // does not result in an error.
   token.logoutSimple();
   ok(!token.isLoggedIn(), "Token should still not be logged into");
+  ok(!token.hasPassword,
+     "Token should not have a password before it has been set");
 
   let initialPW = "foo 1234567890`~!@#$%^&*()-_=+{[}]|\\:;'\",<.>/? 一二三";
   token.initPassword(initialPW);
   token.login(/*force*/ false);
   ok(token.isLoggedIn(), "Token should now be logged into");
 
   checkPasswordFeaturesAndResetPassword(token, initialPW);
 
--- a/services/sync/modules/util.js
+++ b/services/sync/modules/util.js
@@ -597,44 +597,30 @@ this.Utils = {
   bind2: function Async_bind2(object, method) {
     return function innerBind() { return method.apply(object, arguments); };
   },
 
   /**
    * Is there a master password configured, regardless of current lock state?
    */
   mpEnabled: function mpEnabled() {
-    let modules = Cc["@mozilla.org/security/pkcs11moduledb;1"]
-                    .getService(Ci.nsIPKCS11ModuleDB);
-    let sdrSlot = modules.findSlotByName("");
-    let status  = sdrSlot.status;
-    let slots = Ci.nsIPKCS11Slot;
-
-    return status != slots.SLOT_UNINITIALIZED && status != slots.SLOT_READY;
+    let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"]
+                    .getService(Ci.nsIPK11TokenDB);
+    let token = tokenDB.getInternalKeyToken();
+    return token.hasPassword;
   },
 
   /**
    * Is there a master password configured and currently locked?
    */
   mpLocked: function mpLocked() {
-    let modules = Cc["@mozilla.org/security/pkcs11moduledb;1"]
-                    .getService(Ci.nsIPKCS11ModuleDB);
-    let sdrSlot = modules.findSlotByName("");
-    let status  = sdrSlot.status;
-    let slots = Ci.nsIPKCS11Slot;
-
-    if (status == slots.SLOT_READY || status == slots.SLOT_LOGGED_IN
-                                   || status == slots.SLOT_UNINITIALIZED)
-      return false;
-
-    if (status == slots.SLOT_NOT_LOGGED_IN)
-      return true;
-
-    // something wacky happened, pretend MP is locked
-    return true;
+    let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"]
+                    .getService(Ci.nsIPK11TokenDB);
+    let token = tokenDB.getInternalKeyToken();
+    return token.hasPassword && !token.isLoggedIn();
   },
 
   // If Master Password is enabled and locked, present a dialog to unlock it.
   // Return whether the system is unlocked.
   ensureMPUnlocked: function ensureMPUnlocked() {
     if (!Utils.mpLocked()) {
       return true;
     }
--- a/toolkit/components/passwordmgr/LoginHelper.jsm
+++ b/toolkit/components/passwordmgr/LoginHelper.jsm
@@ -682,25 +682,20 @@ this.LoginHelper = {
       File.remove(file);
     }
   },
 
   /**
    * Returns true if the user has a master password set and false otherwise.
    */
   isMasterPasswordSet() {
-    let secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].
-                   getService(Ci.nsIPKCS11ModuleDB);
-    let slot = secmodDB.findSlotByName("");
-    if (!slot) {
-      return false;
-    }
-    let hasMP = slot.status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED &&
-                slot.status != Ci.nsIPKCS11Slot.SLOT_READY;
-    return hasMP;
+    let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"]
+                    .getService(Ci.nsIPK11TokenDB);
+    let token = tokenDB.getInternalKeyToken();
+    return token.hasPassword;
   },
 
   /**
    * Send a notification when stored data is changed.
    */
   notifyStorageChanged(changeType, data) {
     let dataObject = data;
     // Can't pass a raw JS string or array though notifyObservers(). :-(
--- a/toolkit/components/passwordmgr/crypto-SDR.js
+++ b/toolkit/components/passwordmgr/crypto-SDR.js
@@ -14,26 +14,16 @@ function LoginManagerCrypto_SDR() {
   this.init();
 }
 
 LoginManagerCrypto_SDR.prototype = {
 
   classID : Components.ID("{dc6c2976-0f73-4f1f-b9ff-3d72b4e28309}"),
   QueryInterface : XPCOMUtils.generateQI([Ci.nsILoginManagerCrypto]),
 
-  __sdrSlot : null, // PKCS#11 slot being used by the SDR.
-  get _sdrSlot() {
-    if (!this.__sdrSlot) {
-      let modules = Cc["@mozilla.org/security/pkcs11moduledb;1"].
-                    getService(Ci.nsIPKCS11ModuleDB);
-      this.__sdrSlot = modules.findSlotByName("");
-    }
-    return this.__sdrSlot;
-  },
-
   __decoderRing : null,  // nsSecretDecoderRing service
   get _decoderRing() {
     if (!this.__decoderRing)
       this.__decoderRing = Cc["@mozilla.org/security/sdr;1"].
                            getService(Ci.nsISecretDecoderRing);
     return this.__decoderRing;
   },
 
@@ -165,24 +155,20 @@ LoginManagerCrypto_SDR.prototype = {
     return this._uiBusy;
   },
 
 
   /*
    * isLoggedIn
    */
   get isLoggedIn() {
-    let status = this._sdrSlot.status;
-    this.log("SDR slot status is " + status);
-    if (status == Ci.nsIPKCS11Slot.SLOT_READY ||
-        status == Ci.nsIPKCS11Slot.SLOT_LOGGED_IN)
-      return true;
-    if (status == Ci.nsIPKCS11Slot.SLOT_NOT_LOGGED_IN)
-      return false;
-    throw Components.Exception("unexpected slot status: " + status, Cr.NS_ERROR_FAILURE);
+    let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"].
+                  getService(Ci.nsIPK11TokenDB);
+    let token = tokenDB.getInternalKeyToken();
+    return !token.hasPassword || token.isLoggedIn();
   },
 
 
   /*
    * defaultEncType
    */
   get defaultEncType() {
     return Ci.nsILoginManagerCrypto.ENCTYPE_SDR;
--- a/toolkit/components/passwordmgr/test/LoginTestUtils.jsm
+++ b/toolkit/components/passwordmgr/test/LoginTestUtils.jsm
@@ -258,29 +258,22 @@ this.LoginTestUtils.masterPassword = {
     if (enable) {
       oldPW = "";
       newPW = this.masterPassword;
     } else {
       oldPW = this.masterPassword;
       newPW = "";
     }
 
-    let secmodDB = Cc["@mozilla.org/security/pkcs11moduledb;1"]
-                     .getService(Ci.nsIPKCS11ModuleDB);
-    let slot = secmodDB.findSlotByName("");
-    if (!slot) {
-      throw new Error("Can't find slot");
-    }
-
     // Set master password. Note that this does not log you in, so the next
     // invocation of pwmgr can trigger a MP prompt.
     let pk11db = Cc["@mozilla.org/security/pk11tokendb;1"]
                    .getService(Ci.nsIPK11TokenDB);
-    let token = pk11db.findTokenByName("");
-    if (slot.status == Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED) {
+    let token = pk11db.getInternalKeyToken();
+    if (token.needsUserInit) {
       dump("MP initialized to " + newPW + "\n");
       token.initPassword(newPW);
     } else {
       token.checkPassword(oldPW);
       dump("MP change from " + oldPW + " to " + newPW + "\n");
       token.changePassword(oldPW, newPW);
     }
   },
--- a/toolkit/mozapps/preferences/changemp.js
+++ b/toolkit/mozapps/preferences/changemp.js
@@ -1,88 +1,85 @@
 // -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*-
 
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
 const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
 const nsIPK11TokenDB = Components.interfaces.nsIPK11TokenDB;
 const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
 const nsPKCS11ModuleDB = "@mozilla.org/security/pkcs11moduledb;1";
 const nsIPKCS11ModuleDB = Components.interfaces.nsIPKCS11ModuleDB;
 const nsIPKCS11Slot = Components.interfaces.nsIPKCS11Slot;
 const nsIPK11Token = Components.interfaces.nsIPK11Token;
 
 
 var params;
-var tokenName = "";
 var pw1;
 
 function init()
 {
   pw1 = document.getElementById("pw1");
 
   process();
 }
 
 
 function process()
 {
-   var secmoddb = Components.classes[nsPKCS11ModuleDB].getService(nsIPKCS11ModuleDB);
-   var bundle = document.getElementById("bundlePreferences");
+  let bundle = document.getElementById("bundlePreferences");
 
-   // If the token is unitialized, don't use the old password box.
-   // Otherwise, do.
+  // If the token is unitialized, don't use the old password box.
+  // Otherwise, do.
 
-   var slot = secmoddb.findSlotByName(tokenName);
-   if (slot) {
-     var oldpwbox = document.getElementById("oldpw");
-     var msgBox = document.getElementById("message");
-     var status = slot.status;
-     if (status == nsIPKCS11Slot.SLOT_UNINITIALIZED
-         || status == nsIPKCS11Slot.SLOT_READY) {
-
-       oldpwbox.setAttribute("hidden", "true");
-       msgBox.setAttribute("value", bundle.getString("password_not_set"));
-       msgBox.setAttribute("hidden", "false");
+  let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"]
+                  .getService(Ci.nsIPK11TokenDB);
+  let token = tokenDB.getInternalKeyToken();
+  if (token) {
+    let oldpwbox = document.getElementById("oldpw");
+    let msgBox = document.getElementById("message");
+    if ((token.needsLogin() && token.needsUserInit) || !token.needsLogin()) {
+      oldpwbox.setAttribute("hidden", "true");
+      msgBox.setAttribute("value", bundle.getString("password_not_set"));
+      msgBox.setAttribute("hidden", "false");
 
-       if (status == nsIPKCS11Slot.SLOT_READY) {
-         oldpwbox.setAttribute("inited", "empty");
-       } else {
-         oldpwbox.setAttribute("inited", "true");
-       }
-
-       // Select first password field
-       document.getElementById('pw1').focus();
+      if (!token.needsLogin()) {
+        oldpwbox.setAttribute("inited", "empty");
+      } else {
+        oldpwbox.setAttribute("inited", "true");
+      }
 
-     } else {
-       // Select old password field
-       oldpwbox.setAttribute("hidden", "false");
-       msgBox.setAttribute("hidden", "true");
-       oldpwbox.setAttribute("inited", "false");
-       oldpwbox.focus();
-     }
-   }
+      // Select first password field
+      document.getElementById('pw1').focus();
+    } else {
+      // Select old password field
+      oldpwbox.setAttribute("hidden", "false");
+      msgBox.setAttribute("hidden", "true");
+      oldpwbox.setAttribute("inited", "false");
+      oldpwbox.focus();
+    }
+  }
 
   if (params) {
     // Return value 0 means "canceled"
     params.SetInt(1, 0);
   }
 
   checkPasswords();
 }
 
 function setPassword()
 {
   var pk11db = Components.classes[nsPK11TokenDB].getService(nsIPK11TokenDB);
   var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                                 .getService(Components.interfaces.nsIPromptService);
-  var token = pk11db.findTokenByName(tokenName);
-  dump("*** TOKEN!!!! (name = |" + token + "|\n");
+  var token = pk11db.getInternalKeyToken();
 
   var oldpwbox = document.getElementById("oldpw");
   var initpw = oldpwbox.getAttribute("inited");
   var bundle = document.getElementById("bundlePreferences");
 
   var success = false;
 
   if (initpw == "false" || initpw == "empty") {