зеркало из https://github.com/mozilla/pjs.git
Bug 603388 - Merge fx-sync to mozilla-central. a=blockers
--HG-- rename : services/crypto/WeaveCrypto.js => services/crypto/modules/WeaveCrypto.js
This commit is contained in:
Коммит
c367d18067
|
@ -34,26 +34,21 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const EXPORTED_SYMBOLS = ["WeaveCrypto"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
try {
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||
}
|
||||
catch(ex) {}
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||
|
||||
function WeaveCrypto() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
WeaveCrypto.prototype = {
|
||||
classDescription: "WeaveCrypto",
|
||||
contractID: "@labs.mozilla.com/Weave/Crypto;2",
|
||||
classID: Components.ID("{7fa20841-c90e-4432-a1a1-ba3b20cb6b37}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.IWeaveCrypto]),
|
||||
|
||||
prefBranch : null,
|
||||
|
@ -76,6 +71,12 @@ WeaveCrypto.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
// This is its own method so that it can be overridden.
|
||||
// (Components.Exception isn't thread-safe for instance)
|
||||
makeException : function makeException(message, result) {
|
||||
return Components.Exception(message, result);
|
||||
},
|
||||
|
||||
init : function() {
|
||||
try {
|
||||
// Preferences. Add observer so we get notified of changes.
|
||||
|
@ -129,7 +130,7 @@ WeaveCrypto.prototype = {
|
|||
nssfile.append("libnss3.so");
|
||||
break;
|
||||
default:
|
||||
throw Components.Exception("unsupported platform: " + os, Cr.NS_ERROR_UNEXPECTED);
|
||||
throw this.makeException("unsupported platform: " + os, Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
this.log("Using NSS library " + nssfile.path);
|
||||
|
||||
|
@ -529,31 +530,31 @@ WeaveCrypto.prototype = {
|
|||
let mechanism = this.nss.PK11_AlgtagToMechanism(this.algorithm);
|
||||
mechanism = this.nss.PK11_GetPadMechanism(mechanism);
|
||||
if (mechanism == this.nss.CKM_INVALID_MECHANISM)
|
||||
throw Components.Exception("invalid algorithm (can't pad)", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("invalid algorithm (can't pad)", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
let ctx, symKey, slot, ivParam;
|
||||
try {
|
||||
ivParam = this.nss.PK11_ParamFromIV(mechanism, ivItem.address());
|
||||
if (ivParam.isNull())
|
||||
throw Components.Exception("can't convert IV to param", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("can't convert IV to param", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
slot = this.nss.PK11_GetInternalKeySlot();
|
||||
if (slot.isNull())
|
||||
throw Components.Exception("can't get internal key slot", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("can't get internal key slot", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
symKey = this.nss.PK11_ImportSymKey(slot, mechanism, this.nss.PK11_OriginUnwrap, operation, keyItem.address(), null);
|
||||
if (symKey.isNull())
|
||||
throw Components.Exception("symkey import failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("symkey import failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
ctx = this.nss.PK11_CreateContextBySymKey(mechanism, operation, symKey, ivParam);
|
||||
if (ctx.isNull())
|
||||
throw Components.Exception("couldn't create context for symkey", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("couldn't create context for symkey", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
let maxOutputSize = output.length;
|
||||
let tmpOutputSize = new ctypes.int(); // Note 1: NSS uses a signed int here...
|
||||
|
||||
if (this.nss.PK11_CipherOp(ctx, output, tmpOutputSize.address(), maxOutputSize, input, input.length))
|
||||
throw Components.Exception("cipher operation failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("cipher operation failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
let actualOutputSize = tmpOutputSize.value;
|
||||
let finalOutput = output.addressOfElement(actualOutputSize);
|
||||
|
@ -564,7 +565,7 @@ WeaveCrypto.prototype = {
|
|||
// cipher operation. You'd think it would be called PK11_CipherOpFinal...
|
||||
let tmpOutputSize2 = new ctypes.unsigned_int(); // Note 2: ...but an unsigned here!
|
||||
if (this.nss.PK11_DigestFinal(ctx, finalOutput, tmpOutputSize2.address(), maxOutputSize))
|
||||
throw Components.Exception("cipher finalize failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("cipher finalize failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
actualOutputSize += tmpOutputSize2.value;
|
||||
let newOutput = ctypes.cast(output, ctypes.unsigned_char.array(actualOutputSize));
|
||||
|
@ -603,7 +604,7 @@ WeaveCrypto.prototype = {
|
|||
|
||||
slot = this.nss.PK11_GetInternalSlot();
|
||||
if (slot.isNull())
|
||||
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Generate the keypair.
|
||||
privKey = this.nss.PK11_GenerateKeyPairWithFlags(slot,
|
||||
|
@ -612,18 +613,18 @@ WeaveCrypto.prototype = {
|
|||
pubKey.address(),
|
||||
attrFlags, null);
|
||||
if (privKey.isNull())
|
||||
throw Components.Exception("keypair generation failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("keypair generation failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
let s = this.nss.PK11_SetPrivateKeyNickname(privKey, "Weave User PrivKey");
|
||||
if (s)
|
||||
throw Components.Exception("key nickname failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("key nickname failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
let wrappedPrivateKey = this._wrapPrivateKey(privKey, passphrase, salt, iv);
|
||||
out_wrappedPrivateKey.value = wrappedPrivateKey; // outparam
|
||||
|
||||
let derKey = this.nss.SECKEY_EncodeDERSubjectPublicKeyInfo(pubKey);
|
||||
if (derKey.isNull())
|
||||
throw Components.Exception("SECKEY_EncodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("SECKEY_EncodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
let encodedPublicKey = this.encodeBase64(derKey.contents.data, derKey.contents.len);
|
||||
out_encodedPublicKey.value = encodedPublicKey; // outparam
|
||||
|
@ -663,27 +664,27 @@ WeaveCrypto.prototype = {
|
|||
break;
|
||||
|
||||
default:
|
||||
throw Components.Exception("unknown algorithm", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("unknown algorithm", Cr.NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
let slot, randKey, keydata;
|
||||
try {
|
||||
slot = this.nss.PK11_GetInternalSlot();
|
||||
if (slot.isNull())
|
||||
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
randKey = this.nss.PK11_KeyGen(slot, keygenMech, null, keySize, null);
|
||||
if (randKey.isNull())
|
||||
throw Components.Exception("PK11_KeyGen failed.", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_KeyGen failed.", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Slightly odd API, this call just prepares the key value for
|
||||
// extraction, we get the actual bits from the call to PK11_GetKeyData().
|
||||
if (this.nss.PK11_ExtractKeyValue(randKey))
|
||||
throw Components.Exception("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
keydata = this.nss.PK11_GetKeyData(randKey);
|
||||
if (keydata.isNull())
|
||||
throw Components.Exception("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
return this.encodeBase64(keydata.contents.data, keydata.contents.len);
|
||||
} catch (e) {
|
||||
|
@ -714,7 +715,7 @@ WeaveCrypto.prototype = {
|
|||
// Temporary buffer to hold the generated data.
|
||||
let scratch = new ctypes.ArrayType(ctypes.unsigned_char, byteCount)();
|
||||
if (this.nss.PK11_GenerateRandom(scratch, byteCount))
|
||||
throw Components.Exception("PK11_GenrateRandom failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_GenrateRandom failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
return this.encodeBase64(scratch.address(), scratch.length);
|
||||
},
|
||||
|
@ -737,7 +738,7 @@ WeaveCrypto.prototype = {
|
|||
try {
|
||||
slot = this.nss.PK11_GetInternalSlot();
|
||||
if (slot.isNull())
|
||||
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// ImportSymKey wants a mechanism, from which it derives the key type.
|
||||
let keyMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
|
||||
|
@ -746,7 +747,7 @@ WeaveCrypto.prototype = {
|
|||
// really matter because we're just going to wrap it up and not use it.
|
||||
symKey = this.nss.PK11_ImportSymKey(slot, keyMech, this.nss.PK11_OriginUnwrap, this.nss.CKA_ENCRYPT, symKeyData.address(), null);
|
||||
if (symKey.isNull())
|
||||
throw Components.Exception("symkey import failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("symkey import failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Step 3. Put the public key bits into a P11 key object.
|
||||
|
||||
|
@ -754,11 +755,11 @@ WeaveCrypto.prototype = {
|
|||
// pubKey = SECKEY_ImportDERPublicKey(&pubKeyData, CKK_RSA);
|
||||
pubKeyInfo = this.nss.SECKEY_DecodeDERSubjectPublicKeyInfo(pubKeyData.address());
|
||||
if (pubKeyInfo.isNull())
|
||||
throw Components.Exception("SECKEY_DecodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("SECKEY_DecodeDERSubjectPublicKeyInfo failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
pubKey = this.nss.SECKEY_ExtractPublicKey(pubKeyInfo);
|
||||
if (pubKey.isNull())
|
||||
throw Components.Exception("SECKEY_ExtractPublicKey failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("SECKEY_ExtractPublicKey failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Step 4. Wrap the symmetric key with the public key.
|
||||
|
||||
|
@ -766,7 +767,7 @@ WeaveCrypto.prototype = {
|
|||
|
||||
let s = this.nss.PK11_PubWrapSymKey(wrapMech, pubKey, symKey, wrappedKey.address());
|
||||
if (s)
|
||||
throw Components.Exception("PK11_PubWrapSymKey failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_PubWrapSymKey failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Step 5. Base64 encode the wrapped key, cleanup, and return to caller.
|
||||
return this.encodeBase64(wrappedKey.data, wrappedKey.len);
|
||||
|
@ -806,16 +807,16 @@ WeaveCrypto.prototype = {
|
|||
let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
|
||||
wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
|
||||
if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
|
||||
throw Components.Exception("unwrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("unwrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
|
||||
if (ivParam.isNull())
|
||||
throw Components.Exception("unwrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("unwrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Step 3. Unwrap the private key with the key from the passphrase.
|
||||
slot = this.nss.PK11_GetInternalSlot();
|
||||
if (slot.isNull())
|
||||
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Normally, one wants to associate a private key with a public key.
|
||||
// P11_UnwrapPrivKey() passes its keyID arg to PK11_MakeIDFromPubKey(),
|
||||
|
@ -836,7 +837,7 @@ WeaveCrypto.prototype = {
|
|||
privKeyUsage.addressOfElement(0), privKeyUsageLength,
|
||||
null); // wincx
|
||||
if (privKey.isNull())
|
||||
throw Components.Exception("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Step 4. Unwrap the symmetric key with the user's private key.
|
||||
|
||||
|
@ -845,15 +846,15 @@ WeaveCrypto.prototype = {
|
|||
symKey = this.nss.PK11_PubUnwrapSymKey(privKey, wrappedSymKey.address(), wrapMech,
|
||||
this.nss.CKA_DECRYPT, 0);
|
||||
if (symKey.isNull())
|
||||
throw Components.Exception("PK11_PubUnwrapSymKey failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_PubUnwrapSymKey failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Step 5. Base64 encode the unwrapped key, cleanup, and return to caller.
|
||||
if (this.nss.PK11_ExtractKeyValue(symKey))
|
||||
throw Components.Exception("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_ExtractKeyValue failed.", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
symKeyData = this.nss.PK11_GetKeyData(symKey);
|
||||
if (symKeyData.isNull())
|
||||
throw Components.Exception("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_GetKeyData failed.", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
return this.encodeBase64(symKeyData.contents.data, symKeyData.contents.len);
|
||||
} catch (e) {
|
||||
|
@ -893,16 +894,16 @@ WeaveCrypto.prototype = {
|
|||
let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
|
||||
wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
|
||||
if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
|
||||
throw Components.Exception("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
|
||||
if (ivParam.isNull())
|
||||
throw Components.Exception("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Step 3. Unwrap the private key with the key from the passphrase.
|
||||
slot = this.nss.PK11_GetInternalSlot();
|
||||
if (slot.isNull())
|
||||
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
let keyID = ivItem.address();
|
||||
|
||||
|
@ -916,7 +917,7 @@ WeaveCrypto.prototype = {
|
|||
privKeyUsage.addressOfElement(0), privKeyUsageLength,
|
||||
null); // wincx
|
||||
if (privKey.isNull())
|
||||
throw Components.Exception("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_UnwrapPrivKey failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Step 4. Rewrap the private key with the new passphrase.
|
||||
return this._wrapPrivateKey(privKey, newPassphrase, salt, iv);
|
||||
|
@ -955,16 +956,16 @@ WeaveCrypto.prototype = {
|
|||
let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
|
||||
wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
|
||||
if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
|
||||
throw Components.Exception("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("rewrapSymKey: unknown key mech", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
|
||||
if (ivParam.isNull())
|
||||
throw Components.Exception("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("rewrapSymKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Step 3. Unwrap the private key with the key from the passphrase.
|
||||
slot = this.nss.PK11_GetInternalSlot();
|
||||
if (slot.isNull())
|
||||
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
let keyID = ivItem.address();
|
||||
|
||||
|
@ -1004,7 +1005,7 @@ WeaveCrypto.prototype = {
|
|||
byteCompress : function (jsString, charArray) {
|
||||
let intArray = ctypes.cast(charArray, ctypes.uint8_t.array(charArray.length));
|
||||
for (let i = 0; i < jsString.length; i++)
|
||||
intArray[i] = jsString.charCodeAt(i);
|
||||
intArray[i] = jsString.charCodeAt(i) % 256; // convert to bytes
|
||||
},
|
||||
|
||||
// Expand a normal C string (1-byte chars) into a JS string (2-byte chars)
|
||||
|
@ -1058,15 +1059,15 @@ WeaveCrypto.prototype = {
|
|||
algid = this.nss.PK11_CreatePBEV2AlgorithmID(pbeAlg, cipherAlg, prfAlg,
|
||||
keyLength, iterations, saltItem.address());
|
||||
if (algid.isNull())
|
||||
throw Components.Exception("PK11_CreatePBEV2AlgorithmID failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_CreatePBEV2AlgorithmID failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
slot = this.nss.PK11_GetInternalSlot();
|
||||
if (slot.isNull())
|
||||
throw Components.Exception("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("couldn't get internal slot", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
symKey = this.nss.PK11_PBEKeyGen(slot, algid, passItem.address(), false, null);
|
||||
if (symKey.isNull())
|
||||
throw Components.Exception("PK11_PBEKeyGen failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("PK11_PBEKeyGen failed", Cr.NS_ERROR_FAILURE);
|
||||
} catch (e) {
|
||||
this.log("_deriveKeyFromPassphrase: failed: " + e);
|
||||
throw e;
|
||||
|
@ -1094,11 +1095,11 @@ WeaveCrypto.prototype = {
|
|||
let wrapMech = this.nss.PK11_AlgtagToMechanism(this.algorithm);
|
||||
wrapMech = this.nss.PK11_GetPadMechanism(wrapMech);
|
||||
if (wrapMech == this.nss.CKM_INVALID_MECHANISM)
|
||||
throw Components.Exception("wrapPrivKey: unknown key mech", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("wrapPrivKey: unknown key mech", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
let ivParam = this.nss.PK11_ParamFromIV(wrapMech, ivItem.address());
|
||||
if (ivParam.isNull())
|
||||
throw Components.Exception("wrapPrivKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("wrapPrivKey: PK11_ParamFromIV failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
// Use a buffer to hold the wrapped key. NSS says about 1200 bytes for
|
||||
// a 2048-bit RSA key, so a 4096 byte buffer should be plenty.
|
||||
|
@ -1110,7 +1111,7 @@ WeaveCrypto.prototype = {
|
|||
wrapMech, ivParam,
|
||||
wrappedKey.address(), null);
|
||||
if (s)
|
||||
throw Components.Exception("wrapPrivKey: PK11_WrapPrivKey failed", Cr.NS_ERROR_FAILURE);
|
||||
throw this.makeException("wrapPrivKey: PK11_WrapPrivKey failed", Cr.NS_ERROR_FAILURE);
|
||||
|
||||
return this.encodeBase64(wrappedKey.data, wrappedKey.len);
|
||||
} catch (e) {
|
||||
|
@ -1124,13 +1125,3 @@ WeaveCrypto.prototype = {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Gecko <2.0
|
||||
let component = typeof Services == "undefined" || typeof ctypes == "undefined" ? [] : [WeaveCrypto];
|
||||
function NSGetModule (compMgr, fileSpec) {
|
||||
return XPCOMUtils.generateModule(component);
|
||||
}
|
||||
|
||||
// Gecko >=2.0
|
||||
if (typeof XPCOMUtils.generateNSGetFactory == "function")
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([WeaveCrypto]);
|
|
@ -0,0 +1,150 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Firefox Sync.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Philipp von Weitershausen <philipp@weitershausen>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const EXPORTED_SYMBOLS = ["ThreadedCrypto"];
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://services-sync/ext/Sync.js");
|
||||
Cu.import("resource://services-crypto/WeaveCrypto.js");
|
||||
|
||||
/*
|
||||
* Execute a function in a thread.
|
||||
*/
|
||||
function Runner(func, thisObj, returnval, error) {
|
||||
this.func = func;
|
||||
this.thisObj = thisObj;
|
||||
this.returnval = returnval;
|
||||
this.error = error;
|
||||
}
|
||||
Runner.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRunnable]),
|
||||
|
||||
run: function run() {
|
||||
let ex = this.error;
|
||||
if (ex) {
|
||||
this.func.throw(ex);
|
||||
} else {
|
||||
this.func.call(this.thisObj, this.returnval);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Execute a function in a thread and notify a callback on another thread
|
||||
* afterward.
|
||||
*/
|
||||
function CallbackRunner(func, thisObj, args, callback, cbThread) {
|
||||
this.func = func;
|
||||
this.thisObj = thisObj;
|
||||
this.args = args;
|
||||
this.callback = callback;
|
||||
this.cbThread = cbThread;
|
||||
}
|
||||
CallbackRunner.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRunnable]),
|
||||
|
||||
run: function run() {
|
||||
let returnval, error;
|
||||
try {
|
||||
returnval = this.func.apply(this.thisObj, this.args);
|
||||
} catch(ex) {
|
||||
error = ex;
|
||||
}
|
||||
this.cbThread.dispatch(new Runner(this.callback, this.thisObj,
|
||||
returnval, error),
|
||||
Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Implementation of IWeaveCrypto that defers method calls to another thread
|
||||
* but keeps the synchronous API. (Don't ask...)
|
||||
*/
|
||||
function ThreadedCrypto() {
|
||||
this.backgroundThread = Services.tm.newThread(0);
|
||||
this.crypto = new WeaveCrypto();
|
||||
|
||||
// Components.Exception isn't thread-safe.
|
||||
this.crypto.makeException = function makeException(message, result) {
|
||||
return result;
|
||||
};
|
||||
|
||||
// Make sure to kill the thread before XPCOM shuts down.
|
||||
Services.obs.addObserver(this, "profile-before-change", true);
|
||||
}
|
||||
ThreadedCrypto.deferToThread = function deferToThread(methodname) {
|
||||
return function threadMethod() {
|
||||
// Dispatch method call to background thread.
|
||||
let args = Array.slice(arguments);
|
||||
return Sync(function(callback) {
|
||||
let runner = new CallbackRunner(this.crypto[methodname], this.crypto,
|
||||
args, callback, Services.tm.mainThread);
|
||||
this.backgroundThread.dispatch(runner, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}, this)();
|
||||
};
|
||||
};
|
||||
ThreadedCrypto.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.IWeaveCrypto,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
observe: function observe() {
|
||||
this.backgroundThread.shutdown();
|
||||
},
|
||||
|
||||
get algorithm() this.crypto.algorithm,
|
||||
set algorithm(value) this.crypto.algorithm = value,
|
||||
|
||||
get keypairBits() this.crypto.keypairBits,
|
||||
set keypairBits(value) this.crypto.keypairBits = value,
|
||||
|
||||
encrypt: ThreadedCrypto.deferToThread("encrypt"),
|
||||
decrypt: ThreadedCrypto.deferToThread("decrypt"),
|
||||
generateKeypair: ThreadedCrypto.deferToThread("generateKeypair"),
|
||||
generateRandomKey: ThreadedCrypto.deferToThread("generateRandomKey"),
|
||||
generateRandomIV: ThreadedCrypto.deferToThread("generateRandomIV"),
|
||||
generateRandomBytes: ThreadedCrypto.deferToThread("generateRandomBytes"),
|
||||
wrapSymmetricKey: ThreadedCrypto.deferToThread("wrapSymmetricKey"),
|
||||
unwrapSymmetricKey: ThreadedCrypto.deferToThread("unwrapSymmetricKey"),
|
||||
rewrapPrivateKey: ThreadedCrypto.deferToThread("rewrapPrivateKey"),
|
||||
verifyPassphrase: ThreadedCrypto.deferToThread("verifyPassphrase")
|
||||
};
|
|
@ -0,0 +1,68 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
try {
|
||||
// In the context of xpcshell tests, there won't be a default AppInfo
|
||||
Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
|
||||
}
|
||||
catch(ex) {
|
||||
|
||||
do_get_profile();
|
||||
|
||||
// Make sure to provide the right OS so crypto loads the right binaries
|
||||
let OS = "XPCShell";
|
||||
if ("@mozilla.org/windows-registry-key;1" in Cc)
|
||||
OS = "WINNT";
|
||||
else if ("nsILocalFileMac" in Ci)
|
||||
OS = "Darwin";
|
||||
else
|
||||
OS = "Linux";
|
||||
|
||||
let XULAppInfo = {
|
||||
vendor: "Mozilla",
|
||||
name: "XPCShell",
|
||||
ID: "{3e3ba16c-1675-4e88-b9c8-afef81b3d2ef}",
|
||||
version: "1",
|
||||
appBuildID: "20100621",
|
||||
platformVersion: "",
|
||||
platformBuildID: "20100621",
|
||||
inSafeMode: false,
|
||||
logConsoleErrors: true,
|
||||
OS: OS,
|
||||
XPCOMABI: "noarch-spidermonkey",
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIXULAppInfo, Ci.nsIXULRuntime])
|
||||
};
|
||||
|
||||
let XULAppInfoFactory = {
|
||||
createInstance: function (outer, iid) {
|
||||
if (outer != null)
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
return XULAppInfo.QueryInterface(iid);
|
||||
}
|
||||
};
|
||||
|
||||
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.registerFactory(Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}"),
|
||||
"XULAppInfo", "@mozilla.org/xre/app-info;1",
|
||||
XULAppInfoFactory);
|
||||
|
||||
}
|
||||
|
||||
// Provide resource://services-crypto if it isn't already available
|
||||
let weaveService = Cc["@mozilla.org/weave/service;1"].getService();
|
||||
weaveService.wrappedJSObject.addResourceAlias();
|
||||
|
||||
/**
|
||||
* Print some debug message to the console. All arguments will be printed,
|
||||
* separated by spaces.
|
||||
*
|
||||
* @param [arg0, arg1, arg2, ...]
|
||||
* Any number of arguments to print out
|
||||
* @usage _("Hello World") -> prints "Hello World"
|
||||
* @usage _(1, 2, 3) -> prints "1 2 3"
|
||||
*/
|
||||
let _ = function(some, debug, text, to) print(Array.slice(arguments).join(" "));
|
|
@ -1,8 +1,14 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
let cryptoSvc;
|
||||
try {
|
||||
Components.utils.import("resource://services-crypto/threaded.js");
|
||||
cryptoSvc = new ThreadedCrypto();
|
||||
} catch (ex) {
|
||||
// Fallback to binary WeaveCrypto
|
||||
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]
|
||||
.getService(Ci.IWeaveCrypto);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let cryptoSvc = Svc.Crypto;
|
||||
|
||||
// First, do a normal run with expected usage... Generate a random key and
|
||||
// iv, encrypt and decrypt a string.
|
||||
var iv = cryptoSvc.generateRandomIV();
|
||||
|
@ -119,7 +125,7 @@ function run_test() {
|
|||
do_check_eq(cipherText, "T6fik9Ros+DB2ablH9zZ8FWZ0xm/szSwJjIHZu7sjPs=");
|
||||
|
||||
var badkey = "badkeybadkeybadkeybadk==";
|
||||
var badiv = "badivbadivbadivbadivbad==";
|
||||
var badiv = "badivbadivbadivbadivbad=";
|
||||
var badcipher = "crapinputcrapinputcrapinputcrapinputcrapinp=";
|
||||
var failure;
|
||||
|
|
@ -1,8 +1,14 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
let cryptoSvc;
|
||||
try {
|
||||
Components.utils.import("resource://services-crypto/threaded.js");
|
||||
cryptoSvc = new ThreadedCrypto();
|
||||
} catch (ex) {
|
||||
// Fallback to binary WeaveCrypto
|
||||
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]
|
||||
.getService(Ci.IWeaveCrypto);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let cryptoSvc = Svc.Crypto;
|
||||
|
||||
var salt = cryptoSvc.generateRandomBytes(16);
|
||||
do_check_eq(salt.length, 24);
|
||||
|
|
@ -1,8 +1,14 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
let cryptoSvc;
|
||||
try {
|
||||
Components.utils.import("resource://services-crypto/threaded.js");
|
||||
cryptoSvc = new ThreadedCrypto();
|
||||
} catch (ex) {
|
||||
// Fallback to binary WeaveCrypto
|
||||
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]
|
||||
.getService(Ci.IWeaveCrypto);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let cryptoSvc = Svc.Crypto;
|
||||
|
||||
// Test salt generation.
|
||||
var salt;
|
||||
|
|
@ -1,8 +1,14 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
let cryptoSvc;
|
||||
try {
|
||||
Components.utils.import("resource://services-crypto/threaded.js");
|
||||
cryptoSvc = new ThreadedCrypto();
|
||||
} catch (ex) {
|
||||
// Fallback to binary WeaveCrypto
|
||||
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]
|
||||
.getService(Ci.IWeaveCrypto);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let cryptoSvc = Svc.Crypto;
|
||||
|
||||
var salt = cryptoSvc.generateRandomBytes(16);
|
||||
var iv = cryptoSvc.generateRandomIV();
|
||||
var symKey = cryptoSvc.generateRandomKey();
|
|
@ -1,8 +1,14 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
let cryptoSvc;
|
||||
try {
|
||||
Components.utils.import("resource://services-crypto/threaded.js");
|
||||
cryptoSvc = new ThreadedCrypto();
|
||||
} catch (ex) {
|
||||
// Fallback to binary WeaveCrypto
|
||||
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"]
|
||||
.getService(Ci.IWeaveCrypto);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let cryptoSvc = Svc.Crypto;
|
||||
|
||||
var salt = cryptoSvc.generateRandomBytes(16);
|
||||
var iv = cryptoSvc.generateRandomIV();
|
||||
|
|
@ -80,12 +80,16 @@ WeaveService.prototype = {
|
|||
.QueryInterface(Ci.nsIResProtocolHandler);
|
||||
|
||||
// Only create alias if resource://services-sync doesn't already exist.
|
||||
if (resProt.hasSubstitution("services-sync"))
|
||||
return;
|
||||
|
||||
let uri = ioService.newURI("resource:///modules/services-sync/",
|
||||
null, null);
|
||||
resProt.setSubstitution("services-sync", uri);
|
||||
if (!resProt.hasSubstitution("services-sync")) {
|
||||
let uri = ioService.newURI("resource:///modules/services-sync/",
|
||||
null, null);
|
||||
resProt.setSubstitution("services-sync", uri);
|
||||
}
|
||||
if (!resProt.hasSubstitution("services-crypto")) {
|
||||
let uri = ioService.newURI("resource:///modules/services-crypto/",
|
||||
null, null);
|
||||
resProt.setSubstitution("services-crypto", uri);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ ClientEngine.prototype = {
|
|||
|
||||
// Generate a client name if we don't have a useful one yet
|
||||
let user = Svc.Env.get("USER") || Svc.Env.get("USERNAME") ||
|
||||
Svc.Prefs.get("username");
|
||||
Svc.Prefs.get("account") || Svc.Prefs.get("username");
|
||||
let brand = new StringBundle("chrome://branding/locale/brand.properties");
|
||||
let app = brand.get("brandShortName");
|
||||
|
||||
|
|
|
@ -48,12 +48,19 @@ Cu.import("resource://services-sync/stores.js");
|
|||
Cu.import("resource://services-sync/trackers.js");
|
||||
Cu.import("resource://services-sync/type_records/history.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
|
||||
// Create some helper functions to handle GUIDs
|
||||
function setGUID(uri, guid) {
|
||||
if (arguments.length == 1)
|
||||
guid = Utils.makeGUID();
|
||||
Utils.anno(uri, GUID_ANNO, guid, "WITH_HISTORY");
|
||||
|
||||
try {
|
||||
Utils.anno(uri, GUID_ANNO, guid, "WITH_HISTORY");
|
||||
} catch (ex) {
|
||||
let log = Log4Moz.repository.getLogger("Engine.History");
|
||||
log.warn("Couldn't annotate URI " + uri + ": " + ex);
|
||||
}
|
||||
return guid;
|
||||
}
|
||||
function GUIDForUri(uri, create) {
|
||||
|
|
|
@ -357,22 +357,26 @@ WeaveSvc.prototype = {
|
|||
dapp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.dump")];
|
||||
root.addAppender(dapp);
|
||||
|
||||
let verbose = Svc.Directory.get("ProfD", Ci.nsIFile);
|
||||
verbose.QueryInterface(Ci.nsILocalFile);
|
||||
verbose.append("weave");
|
||||
verbose.append("logs");
|
||||
verbose.append("verbose-log.txt");
|
||||
if (!verbose.exists())
|
||||
verbose.create(verbose.NORMAL_FILE_TYPE, PERMS_FILE);
|
||||
|
||||
let maxSize = 65536; // 64 * 1024 (64KB)
|
||||
this._debugApp = new Log4Moz.RotatingFileAppender(verbose, formatter, maxSize);
|
||||
this._debugApp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.debugLog")];
|
||||
root.addAppender(this._debugApp);
|
||||
let enabled = Svc.Prefs.get("log.appender.debugLog.enabled", false);
|
||||
if (enabled) {
|
||||
let verbose = Svc.Directory.get("ProfD", Ci.nsIFile);
|
||||
verbose.QueryInterface(Ci.nsILocalFile);
|
||||
verbose.append("weave");
|
||||
verbose.append("logs");
|
||||
verbose.append("verbose-log.txt");
|
||||
if (!verbose.exists())
|
||||
verbose.create(verbose.NORMAL_FILE_TYPE, PERMS_FILE);
|
||||
|
||||
let maxSize = 65536; // 64 * 1024 (64KB)
|
||||
this._debugApp = new Log4Moz.RotatingFileAppender(verbose, formatter, maxSize);
|
||||
this._debugApp.level = Log4Moz.Level[Svc.Prefs.get("log.appender.debugLog")];
|
||||
root.addAppender(this._debugApp);
|
||||
}
|
||||
},
|
||||
|
||||
clearLogs: function WeaveSvc_clearLogs() {
|
||||
this._debugApp.clear();
|
||||
if (this._debugApp)
|
||||
this._debugApp.clear();
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -997,11 +997,6 @@ let FakeSvc = {
|
|||
}
|
||||
};
|
||||
|
||||
// Use the binary WeaveCrypto (;1) if the js-ctypes version (;2) fails to load
|
||||
// by adding an alias on FakeSvc from ;2 to ;1
|
||||
Utils.lazySvc(FakeSvc, "@labs.mozilla.com/Weave/Crypto;2",
|
||||
"@labs.mozilla.com/Weave/Crypto;1", "IWeaveCrypto");
|
||||
|
||||
/*
|
||||
* Commonly-used services
|
||||
*/
|
||||
|
@ -1019,7 +1014,6 @@ this.__defineGetter__("_sessionCID", function() {
|
|||
[["Annos", "@mozilla.org/browser/annotation-service;1", "nsIAnnotationService"],
|
||||
["AppInfo", "@mozilla.org/xre/app-info;1", "nsIXULAppInfo"],
|
||||
["Bookmark", "@mozilla.org/browser/nav-bookmarks-service;1", "nsINavBookmarksService"],
|
||||
["Crypto", "@labs.mozilla.com/Weave/Crypto;2", "IWeaveCrypto"],
|
||||
["Directory", "@mozilla.org/file/directory_service;1", "nsIProperties"],
|
||||
["Env", "@mozilla.org/process/environment;1", "nsIEnvironment"],
|
||||
["Favicon", "@mozilla.org/browser/favicon-service;1", "nsIFaviconService"],
|
||||
|
@ -1041,6 +1035,21 @@ this.__defineGetter__("_sessionCID", function() {
|
|||
["Session", this._sessionCID, "nsISessionStore"],
|
||||
].forEach(function(lazy) Utils.lazySvc(Svc, lazy[0], lazy[1], lazy[2]));
|
||||
|
||||
Svc.__defineGetter__("Crypto", function() {
|
||||
let cryptoSvc;
|
||||
try {
|
||||
let ns = {};
|
||||
Cu.import("resource://services-crypto/threaded.js", ns);
|
||||
cryptoSvc = new ns.ThreadedCrypto();
|
||||
} catch (ex) {
|
||||
// Fallback to binary WeaveCrypto
|
||||
cryptoSvc = Cc["@labs.mozilla.com/Weave/Crypto;1"].
|
||||
getService(Ci.IWeaveCrypto);
|
||||
}
|
||||
delete Svc.Crypto;
|
||||
return Svc.Crypto = cryptoSvc;
|
||||
});
|
||||
|
||||
let Str = {};
|
||||
["errors", "sync"]
|
||||
.forEach(function(lazy) Utils.lazy2(Str, lazy, Utils.lazyStrings(lazy)));
|
||||
|
|
|
@ -113,6 +113,14 @@ function run_test() {
|
|||
do_check_eq(queryres[0].time, TIMESTAMP3);
|
||||
do_check_eq(queryres[0].title, "The bird is the word!");
|
||||
|
||||
_("Make sure we handle invalid URLs in places databases gracefully.");
|
||||
let query = "INSERT INTO moz_places "
|
||||
+ "(url, title, rev_host, visit_count, last_visit_date) "
|
||||
+ "VALUES ('invalid-uri', 'Invalid URI', '.', 1, " + TIMESTAMP3 + ")";
|
||||
let stmt = Utils.createStatement(Svc.History.DBConnection, query);
|
||||
let result = Utils.queryAsync(stmt);
|
||||
do_check_eq([id for (id in store.getAllIDs())].length, 3);
|
||||
|
||||
_("Remove a record from the store.");
|
||||
store.remove({id: fxguid});
|
||||
do_check_false(store.itemExists(fxguid));
|
||||
|
|
Загрузка…
Ссылка в новой задаче