toolkit/components/passwordmgr/crypto-SDR.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 const Cc = Components.classes;
     7 const Ci = Components.interfaces;
     8 const Cr = Components.results;
    10 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
    11 Components.utils.import("resource://gre/modules/Services.jsm");
    13 function LoginManagerCrypto_SDR() {
    14     this.init();
    15 };
    17 LoginManagerCrypto_SDR.prototype = {
    19     classID : Components.ID("{dc6c2976-0f73-4f1f-b9ff-3d72b4e28309}"),
    20     QueryInterface : XPCOMUtils.generateQI([Ci.nsILoginManagerCrypto]),
    22     __sdrSlot : null, // PKCS#11 slot being used by the SDR.
    23     get _sdrSlot() {
    24         if (!this.__sdrSlot) {
    25             let modules = Cc["@mozilla.org/security/pkcs11moduledb;1"].
    26                           getService(Ci.nsIPKCS11ModuleDB);
    27             this.__sdrSlot = modules.findSlotByName("");
    28         }
    29         return this.__sdrSlot;
    30     },
    32     __decoderRing : null,  // nsSecretDecoderRing service
    33     get _decoderRing() {
    34         if (!this.__decoderRing)
    35             this.__decoderRing = Cc["@mozilla.org/security/sdr;1"].
    36                                  getService(Ci.nsISecretDecoderRing);
    37         return this.__decoderRing;
    38     },
    40     __utfConverter : null, // UCS2 <--> UTF8 string conversion
    41     get _utfConverter() {
    42         if (!this.__utfConverter) {
    43             this.__utfConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
    44                                   createInstance(Ci.nsIScriptableUnicodeConverter);
    45             this.__utfConverter.charset = "UTF-8";
    46         }
    47         return this.__utfConverter;
    48     },
    50     _utfConverterReset : function() {
    51         this.__utfConverter = null;
    52     },
    54     _debug  : false, // mirrors signon.debug
    55     _uiBusy : false,
    58     /*
    59      * log
    60      *
    61      * Internal function for logging debug messages to the Error Console.
    62      */
    63     log : function (message) {
    64         if (!this._debug)
    65             return;
    66         dump("PwMgr cryptoSDR: " + message + "\n");
    67         Services.console.logStringMessage("PwMgr cryptoSDR: " + message);
    68     },
    71     init : function () {
    72         // Connect to the correct preferences branch.
    73         this._prefBranch = Services.prefs.getBranch("signon.");
    75         this._debug = this._prefBranch.getBoolPref("debug");
    77         // Check to see if the internal PKCS#11 token has been initialized.
    78         // If not, set a blank password.
    79         let tokenDB = Cc["@mozilla.org/security/pk11tokendb;1"].
    80                       getService(Ci.nsIPK11TokenDB);
    82         let token = tokenDB.getInternalKeyToken();
    83         if (token.needsUserInit) {
    84             this.log("Initializing key3.db with default blank password.");
    85             token.initPassword("");
    86         }
    87     },
    90     /*
    91      * encrypt
    92      *
    93      * Encrypts the specified string, using the SecretDecoderRing.
    94      *
    95      * Returns the encrypted string, or throws an exception if there was a
    96      * problem.
    97      */
    98     encrypt : function (plainText) {
    99         let cipherText = null;
   101         let wasLoggedIn = this.isLoggedIn;
   102         let canceledMP = false;
   104         this._uiBusy = true;
   105         try {
   106             let plainOctet = this._utfConverter.ConvertFromUnicode(plainText);
   107             plainOctet += this._utfConverter.Finish();
   108             cipherText = this._decoderRing.encryptString(plainOctet);
   109         } catch (e) {
   110             this.log("Failed to encrypt string. (" + e.name + ")");
   111             // If the user clicks Cancel, we get NS_ERROR_FAILURE.
   112             // (unlike decrypting, which gets NS_ERROR_NOT_AVAILABLE).
   113             if (e.result == Cr.NS_ERROR_FAILURE) {
   114                 canceledMP = true;
   115                 throw Components.Exception("User canceled master password entry", Cr.NS_ERROR_ABORT);
   116             } else {
   117                 throw Components.Exception("Couldn't encrypt string", Cr.NS_ERROR_FAILURE);
   118             }
   119         } finally {
   120             this._uiBusy = false;
   121             // If we triggered a master password prompt, notify observers.
   122             if (!wasLoggedIn && this.isLoggedIn)
   123                 this._notifyObservers("passwordmgr-crypto-login");
   124             else if (canceledMP)
   125                 this._notifyObservers("passwordmgr-crypto-loginCanceled");
   126         }
   127         return cipherText;
   128     },
   131     /*
   132      * decrypt
   133      *
   134      * Decrypts the specified string, using the SecretDecoderRing.
   135      *
   136      * Returns the decrypted string, or throws an exception if there was a
   137      * problem.
   138      */
   139     decrypt : function (cipherText) {
   140         let plainText = null;
   142         let wasLoggedIn = this.isLoggedIn;
   143         let canceledMP = false;
   145         this._uiBusy = true;
   146         try {
   147             let plainOctet;
   148             plainOctet = this._decoderRing.decryptString(cipherText);
   149             plainText = this._utfConverter.ConvertToUnicode(plainOctet);
   150         } catch (e) {
   151             this.log("Failed to decrypt string: " + cipherText +
   152                 " (" + e.name + ")");
   154             // In the unlikely event the converter threw, reset it.
   155             this._utfConverterReset();
   157             // If the user clicks Cancel, we get NS_ERROR_NOT_AVAILABLE.
   158             // If the cipherText is bad / wrong key, we get NS_ERROR_FAILURE
   159             // Wrong passwords are handled by the decoderRing reprompting;
   160             // we get no notification.
   161             if (e.result == Cr.NS_ERROR_NOT_AVAILABLE) {
   162                 canceledMP = true;
   163                 throw Components.Exception("User canceled master password entry", Cr.NS_ERROR_ABORT);
   164             } else {
   165                 throw Components.Exception("Couldn't decrypt string", Cr.NS_ERROR_FAILURE);
   166             }
   167         } finally {
   168             this._uiBusy = false;
   169             // If we triggered a master password prompt, notify observers.
   170             if (!wasLoggedIn && this.isLoggedIn)
   171                 this._notifyObservers("passwordmgr-crypto-login");
   172             else if (canceledMP)
   173                 this._notifyObservers("passwordmgr-crypto-loginCanceled");
   174         }
   176         return plainText;
   177     },
   180     /*
   181      * uiBusy
   182      */
   183     get uiBusy() {
   184         return this._uiBusy;
   185     },
   188     /*
   189      * isLoggedIn
   190      */
   191     get isLoggedIn() {
   192         let status = this._sdrSlot.status;
   193         this.log("SDR slot status is " + status);
   194         if (status == Ci.nsIPKCS11Slot.SLOT_READY ||
   195             status == Ci.nsIPKCS11Slot.SLOT_LOGGED_IN)
   196             return true;
   197         if (status == Ci.nsIPKCS11Slot.SLOT_NOT_LOGGED_IN)
   198             return false;
   199         throw Components.Exception("unexpected slot status: " + status, Cr.NS_ERROR_FAILURE);
   200     },
   203     /*
   204      * defaultEncType
   205      */
   206     get defaultEncType() {
   207         return Ci.nsILoginManagerCrypto.ENCTYPE_SDR;
   208     },
   211     /*
   212      * _notifyObservers
   213      */
   214     _notifyObservers : function(topic) {
   215         this.log("Prompted for a master password, notifying for " + topic);
   216         Services.obs.notifyObservers(null, topic, null);
   217      },
   218 }; // end of nsLoginManagerCrypto_SDR implementation
   220 let component = [LoginManagerCrypto_SDR];
   221 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(component);

mercurial