services/fxaccounts/Credentials.jsm

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 file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /**
     6  * This module implements client-side key stretching for use in Firefox
     7  * Accounts account creation and login.
     8  *
     9  * See https://github.com/mozilla/fxa-auth-server/wiki/onepw-protocol
    10  */
    12 "use strict";
    14 this.EXPORTED_SYMBOLS = ["Credentials"];
    16 const {utils: Cu, interfaces: Ci} = Components;
    18 Cu.import("resource://gre/modules/Log.jsm");
    19 Cu.import("resource://gre/modules/Services.jsm");
    20 Cu.import("resource://gre/modules/Promise.jsm");
    21 Cu.import("resource://services-crypto/utils.js");
    22 Cu.import("resource://services-common/utils.js");
    24 const PROTOCOL_VERSION = "identity.mozilla.com/picl/v1/";
    25 const PBKDF2_ROUNDS = 1000;
    26 const STRETCHED_PW_LENGTH_BYTES = 32;
    27 const HKDF_SALT = CommonUtils.hexToBytes("00");
    28 const HKDF_LENGTH = 32;
    29 const HMAC_ALGORITHM = Ci.nsICryptoHMAC.SHA256;
    30 const HMAC_LENGTH = 32;
    32 // loglevel preference should be one of: "FATAL", "ERROR", "WARN", "INFO",
    33 // "CONFIG", "DEBUG", "TRACE" or "ALL". We will be logging error messages by
    34 // default.
    35 const PREF_LOG_LEVEL = "identity.fxaccounts.loglevel";
    36 try {
    37   this.LOG_LEVEL =
    38     Services.prefs.getPrefType(PREF_LOG_LEVEL) == Ci.nsIPrefBranch.PREF_STRING
    39     && Services.prefs.getCharPref(PREF_LOG_LEVEL);
    40 } catch (e) {
    41   this.LOG_LEVEL = Log.Level.Error;
    42 }
    44 let log = Log.repository.getLogger("Identity.FxAccounts");
    45 log.level = LOG_LEVEL;
    46 log.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
    48 this.Credentials = Object.freeze({
    49   /**
    50    * Make constants accessible to tests
    51    */
    52   constants: {
    53     PROTOCOL_VERSION: PROTOCOL_VERSION,
    54     PBKDF2_ROUNDS: PBKDF2_ROUNDS,
    55     STRETCHED_PW_LENGTH_BYTES: STRETCHED_PW_LENGTH_BYTES,
    56     HKDF_SALT: HKDF_SALT,
    57     HKDF_LENGTH: HKDF_LENGTH,
    58     HMAC_ALGORITHM: HMAC_ALGORITHM,
    59     HMAC_LENGTH: HMAC_LENGTH,
    60   },
    62   /**
    63    * KW function from https://github.com/mozilla/fxa-auth-server/wiki/onepw-protocol
    64    *
    65    * keyWord derivation for use as a salt.
    66    *
    67    *
    68    *   @param {String} context  String for use in generating salt
    69    *
    70    *   @return {bitArray} the salt
    71    *
    72    * Note that PROTOCOL_VERSION does not refer in any way to the version of the
    73    * Firefox Accounts API.
    74    */
    75   keyWord: function(context) {
    76     return CommonUtils.stringToBytes(PROTOCOL_VERSION + context);
    77   },
    79   /**
    80    * KWE function from https://github.com/mozilla/fxa-auth-server/wiki/onepw-protocol
    81    *
    82    * keyWord extended with a name and an email.
    83    *
    84    *   @param {String} name The name of the salt
    85    *   @param {String} email The email of the user.
    86    *
    87    *   @return {bitArray} the salt combination with the namespace
    88    *
    89    * Note that PROTOCOL_VERSION does not refer in any way to the version of the
    90    * Firefox Accounts API.
    91    */
    92   keyWordExtended: function(name, email) {
    93     return CommonUtils.stringToBytes(PROTOCOL_VERSION + name + ':' + email);
    94   },
    96   setup: function(emailInput, passwordInput, options={}) {
    97     let deferred = Promise.defer();
    98     log.debug("setup credentials for " + emailInput);
   100     let hkdfSalt = options.hkdfSalt || HKDF_SALT;
   101     let hkdfLength = options.hkdfLength || HKDF_LENGTH;
   102     let hmacLength = options.hmacLength || HMAC_LENGTH;
   103     let hmacAlgorithm = options.hmacAlgorithm || HMAC_ALGORITHM;
   104     let stretchedPWLength = options.stretchedPassLength || STRETCHED_PW_LENGTH_BYTES;
   105     let pbkdf2Rounds = options.pbkdf2Rounds || PBKDF2_ROUNDS;
   107     let result = {
   108       emailUTF8: emailInput,
   109       passwordUTF8: passwordInput,
   110     };
   112     let password = CommonUtils.encodeUTF8(passwordInput);
   113     let salt = this.keyWordExtended("quickStretch", emailInput);
   115     let runnable = () => {
   116       let start = Date.now();
   117       let quickStretchedPW = CryptoUtils.pbkdf2Generate(
   118           password, salt, pbkdf2Rounds, stretchedPWLength, hmacAlgorithm, hmacLength);
   120       result.quickStretchedPW = quickStretchedPW;
   122       result.authPW =
   123         CryptoUtils.hkdf(quickStretchedPW, hkdfSalt, this.keyWord("authPW"), hkdfLength);
   125       result.unwrapBKey =
   126         CryptoUtils.hkdf(quickStretchedPW, hkdfSalt, this.keyWord("unwrapBkey"), hkdfLength);
   128       log.debug("Credentials set up after " + (Date.now() - start) + " ms");
   129       deferred.resolve(result);
   130     }
   132     Services.tm.currentThread.dispatch(runnable,
   133         Ci.nsIThread.DISPATCH_NORMAL);
   134     log.debug("Dispatched thread for credentials setup crypto work");
   136     return deferred.promise;
   137   }
   138 });

mercurial