123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- /* 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;
- Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
- Components.utils.import("resource://gre/modules/Services.jsm");
- XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
- "resource://gre/modules/LoginHelper.jsm");
- 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;
- },
- __utfConverter : null, // UCS2 <--> UTF8 string conversion
- get _utfConverter() {
- if (!this.__utfConverter) {
- this.__utfConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
- createInstance(Ci.nsIScriptableUnicodeConverter);
- this.__utfConverter.charset = "UTF-8";
- }
- return this.__utfConverter;
- },
- _utfConverterReset : function() {
- this.__utfConverter = null;
- },
- _uiBusy : false,
- init : function () {
- // Check to see if the internal PKCS#11 token has been initialized.
- // If not, set a blank password.
- let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"].
- getService(Ci.nsIPK11TokenDB);
- let token = tokenDB.getInternalKeyToken();
- if (token.needsUserInit) {
- this.log("Initializing key3.db with default blank password.");
- token.initPassword("");
- }
- },
- /*
- * encrypt
- *
- * Encrypts the specified string, using the SecretDecoderRing.
- *
- * Returns the encrypted string, or throws an exception if there was a
- * problem.
- */
- encrypt : function (plainText) {
- let cipherText = null;
- let wasLoggedIn = this.isLoggedIn;
- let canceledMP = false;
- this._uiBusy = true;
- try {
- let plainOctet = this._utfConverter.ConvertFromUnicode(plainText);
- plainOctet += this._utfConverter.Finish();
- cipherText = this._decoderRing.encryptString(plainOctet);
- } catch (e) {
- this.log("Failed to encrypt string. (" + e.name + ")");
- // If the user clicks Cancel, we get NS_ERROR_FAILURE.
- // (unlike decrypting, which gets NS_ERROR_NOT_AVAILABLE).
- if (e.result == Cr.NS_ERROR_FAILURE) {
- canceledMP = true;
- throw Components.Exception("User canceled master password entry", Cr.NS_ERROR_ABORT);
- } else {
- throw Components.Exception("Couldn't encrypt string", Cr.NS_ERROR_FAILURE);
- }
- } finally {
- this._uiBusy = false;
- // If we triggered a master password prompt, notify observers.
- if (!wasLoggedIn && this.isLoggedIn)
- this._notifyObservers("passwordmgr-crypto-login");
- else if (canceledMP)
- this._notifyObservers("passwordmgr-crypto-loginCanceled");
- }
- return cipherText;
- },
- /*
- * decrypt
- *
- * Decrypts the specified string, using the SecretDecoderRing.
- *
- * Returns the decrypted string, or throws an exception if there was a
- * problem.
- */
- decrypt : function (cipherText) {
- let plainText = null;
- let wasLoggedIn = this.isLoggedIn;
- let canceledMP = false;
- this._uiBusy = true;
- try {
- let plainOctet;
- plainOctet = this._decoderRing.decryptString(cipherText);
- plainText = this._utfConverter.ConvertToUnicode(plainOctet);
- } catch (e) {
- this.log("Failed to decrypt string: " + cipherText +
- " (" + e.name + ")");
- // In the unlikely event the converter threw, reset it.
- this._utfConverterReset();
- // If the user clicks Cancel, we get NS_ERROR_NOT_AVAILABLE.
- // If the cipherText is bad / wrong key, we get NS_ERROR_FAILURE
- // Wrong passwords are handled by the decoderRing reprompting;
- // we get no notification.
- if (e.result == Cr.NS_ERROR_NOT_AVAILABLE) {
- canceledMP = true;
- throw Components.Exception("User canceled master password entry", Cr.NS_ERROR_ABORT);
- } else {
- throw Components.Exception("Couldn't decrypt string", Cr.NS_ERROR_FAILURE);
- }
- } finally {
- this._uiBusy = false;
- // If we triggered a master password prompt, notify observers.
- if (!wasLoggedIn && this.isLoggedIn)
- this._notifyObservers("passwordmgr-crypto-login");
- else if (canceledMP)
- this._notifyObservers("passwordmgr-crypto-loginCanceled");
- }
- return plainText;
- },
- /*
- * uiBusy
- */
- get uiBusy() {
- 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);
- },
- /*
- * defaultEncType
- */
- get defaultEncType() {
- return Ci.nsILoginManagerCrypto.ENCTYPE_SDR;
- },
- /*
- * _notifyObservers
- */
- _notifyObservers : function(topic) {
- this.log("Prompted for a master password, notifying for " + topic);
- Services.obs.notifyObservers(null, topic, null);
- },
- }; // end of nsLoginManagerCrypto_SDR implementation
- XPCOMUtils.defineLazyGetter(this.LoginManagerCrypto_SDR.prototype, "log", () => {
- let logger = LoginHelper.createLogger("Login crypto");
- return logger.log.bind(logger);
- });
- var component = [LoginManagerCrypto_SDR];
- this.NSGetFactory = XPCOMUtils.generateNSGetFactory(component);
|