Bug 1772097 - Part 3: Use plain object for lazy getter in services/crypto/modules/. r=markh

Differential Revision: https://phabricator.services.mozilla.com/D147918
This commit is contained in:
Tooru Fujisawa 2022-06-02 12:27:42 +00:00
Родитель f3d348703f
Коммит 819c5382fe
3 изменённых файлов: 51 добавлений и 34 удалений

Просмотреть файл

@ -9,7 +9,9 @@ const { XPCOMUtils } = ChromeUtils.import(
);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGlobalGetters(this, ["crypto"]);
const lazy = {};
XPCOMUtils.defineLazyGlobalGetters(lazy, ["crypto"]);
const CRYPT_ALGO = "AES-CBC";
const CRYPT_ALGO_LENGTH = 256;
@ -76,7 +78,7 @@ WeaveCrypto.prototype = {
// /!\ Only use this for tests! /!\
_getCrypto() {
return crypto;
return lazy.crypto;
},
async encrypt(clearTextUCS2, symmetricKey, iv) {
@ -133,12 +135,17 @@ WeaveCrypto.prototype = {
let iv = this.byteCompressInts(ivStr);
let symKey = await this.importSymKey(symKeyStr, operation);
let cryptMethod = (operation === OPERATIONS.ENCRYPT
? crypto.subtle.encrypt
: crypto.subtle.decrypt
).bind(crypto.subtle);
? lazy.crypto.subtle.encrypt
: lazy.crypto.subtle.decrypt
).bind(lazy.crypto.subtle);
let algo = { name: CRYPT_ALGO, iv };
let keyBytes = await cryptMethod.call(crypto.subtle, algo, symKey, data);
let keyBytes = await cryptMethod.call(
lazy.crypto.subtle,
algo,
symKey,
data
);
return new Uint8Array(keyBytes);
},
@ -148,8 +155,12 @@ WeaveCrypto.prototype = {
name: CRYPT_ALGO,
length: CRYPT_ALGO_LENGTH,
};
let key = await crypto.subtle.generateKey(algo, true, CRYPT_ALGO_USAGES);
let keyBytes = await crypto.subtle.exportKey("raw", key);
let key = await lazy.crypto.subtle.generateKey(
algo,
true,
CRYPT_ALGO_USAGES
);
let keyBytes = await lazy.crypto.subtle.exportKey("raw", key);
return this.encodeBase64(new Uint8Array(keyBytes));
},
@ -161,7 +172,7 @@ WeaveCrypto.prototype = {
this.log("generateRandomBytes() called");
let randBytes = new Uint8Array(byteCount);
crypto.getRandomValues(randBytes);
lazy.crypto.getRandomValues(randBytes);
return this.encodeBase64(randBytes);
},
@ -197,7 +208,7 @@ WeaveCrypto.prototype = {
let symmetricKeyBuffer = this.makeUint8Array(encodedKeyString, true);
let algo = { name: CRYPT_ALGO };
let usages = [operation === OPERATIONS.ENCRYPT ? "encrypt" : "decrypt"];
let symKey = await crypto.subtle.importKey(
let symKey = await lazy.crypto.subtle.importKey(
"raw",
symmetricKeyBuffer,
algo,

Просмотреть файл

@ -8,7 +8,9 @@ const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
XPCOMUtils.defineLazyGlobalGetters(this, ["crypto"]);
const lazy = {};
XPCOMUtils.defineLazyGlobalGetters(lazy, ["crypto"]);
const EXPORTED_SYMBOLS = ["jwcrypto"];
@ -45,10 +47,13 @@ class JWCrypto {
async generateJWE(key, data) {
// Generate an ephemeral key to use just for this encryption.
// The public component gets embedded in the JWE header.
const epk = await crypto.subtle.generateKey(ECDH_PARAMS, true, [
const epk = await lazy.crypto.subtle.generateKey(ECDH_PARAMS, true, [
"deriveKey",
]);
const ownPublicJWK = await crypto.subtle.exportKey("jwk", epk.publicKey);
const ownPublicJWK = await lazy.crypto.subtle.exportKey(
"jwk",
epk.publicKey
);
// Remove properties added by our WebCrypto implementation but that aren't typically
// used with JWE in the wild. This saves space in the resulting JWE, and makes it easier
// to re-import the resulting JWK.
@ -56,7 +61,7 @@ class JWCrypto {
delete ownPublicJWK.ext;
let header = { alg: "ECDH-ES", enc: "A256GCM", epk: ownPublicJWK };
// Import the peer's public key.
const peerPublicKey = await crypto.subtle.importKey(
const peerPublicKey = await lazy.crypto.subtle.importKey(
"jwk",
key,
ECDH_PARAMS,
@ -76,14 +81,14 @@ class JWCrypto {
// Note that the IV is generated randomly, which *in general* is not safe to do with AES-GCM because
// it's too short to guarantee uniqueness. But we know that the AES-GCM key itself is unique and will
// only be used for this single encryption, making a random IV safe to use for this particular use-case.
let iv = crypto.getRandomValues(new Uint8Array(AES_GCM_IV_SIZE));
let iv = lazy.crypto.getRandomValues(new Uint8Array(AES_GCM_IV_SIZE));
// Yes, additionalData is the byte representation of the base64 representation of the stringified header.
const additionalData = UTF8_ENCODER.encode(
ChromeUtils.base64URLEncode(UTF8_ENCODER.encode(JSON.stringify(header)), {
pad: false,
})
);
const encrypted = await crypto.subtle.encrypt(
const encrypted = await lazy.crypto.subtle.encrypt(
{
name: "AES-GCM",
iv,
@ -138,7 +143,7 @@ class JWCrypto {
if ("apu" in header || "apv" in header) {
throw new Error("apu and apv header values are not supported.");
}
const peerPublicKey = await crypto.subtle.importKey(
const peerPublicKey = await lazy.crypto.subtle.importKey(
"jwk",
header.epk,
ECDH_PARAMS,
@ -158,7 +163,7 @@ class JWCrypto {
);
const bundle = new Uint8Array([...ciphertext, ...authTag]);
const decrypted = await crypto.subtle.decrypt(
const decrypted = await lazy.crypto.subtle.decrypt(
{
name: "AES-GCM",
iv,
@ -185,7 +190,7 @@ class JWCrypto {
*/
async function deriveECDHSharedAESKey(privateKey, publicKey, keyUsages) {
const params = { ...ECDH_PARAMS, ...{ public: publicKey } };
const sharedKey = await crypto.subtle.deriveKey(
const sharedKey = await lazy.crypto.subtle.deriveKey(
params,
privateKey,
AES_PARAMS,
@ -195,7 +200,7 @@ async function deriveECDHSharedAESKey(privateKey, publicKey, keyUsages) {
// This is the NIST Concat KDF specialized to a specific set of parameters,
// which basically turn it into a single application of SHA256.
// The details are from the JWA RFC.
let sharedKeyBytes = await crypto.subtle.exportKey("raw", sharedKey);
let sharedKeyBytes = await lazy.crypto.subtle.exportKey("raw", sharedKey);
sharedKeyBytes = new Uint8Array(sharedKeyBytes);
const info = [
"\x00\x00\x00\x07A256GCM", // 7-byte algorithm identifier
@ -210,13 +215,13 @@ async function deriveECDHSharedAESKey(privateKey, publicKey, keyUsages) {
const pkcsBuf = Uint8Array.from(
Array.prototype.map.call(pkcs, c => c.charCodeAt(0))
);
const derivedKeyBytes = await crypto.subtle.digest(
const derivedKeyBytes = await lazy.crypto.subtle.digest(
{
name: "SHA-256",
},
pkcsBuf
);
return crypto.subtle.importKey(
return lazy.crypto.subtle.importKey(
"raw",
derivedKeyBytes,
AES_PARAMS,

Просмотреть файл

@ -13,9 +13,10 @@ const { CommonUtils } = ChromeUtils.import(
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
XPCOMUtils.defineLazyGlobalGetters(this, ["crypto"]);
const lazy = {};
XPCOMUtils.defineLazyGlobalGetters(lazy, ["crypto"]);
XPCOMUtils.defineLazyGetter(this, "textEncoder", function() {
XPCOMUtils.defineLazyGetter(lazy, "textEncoder", function() {
return new TextEncoder();
});
@ -51,7 +52,7 @@ var CryptoUtils = {
},
generateRandomBytes(length) {
return crypto.getRandomValues(new Uint8Array(length));
return lazy.crypto.getRandomValues(new Uint8Array(length));
},
/**
@ -135,7 +136,7 @@ var CryptoUtils = {
async hkdfLegacy(ikm, xts, info, len) {
ikm = CommonUtils.byteStringToArrayBuffer(ikm);
xts = CommonUtils.byteStringToArrayBuffer(xts);
info = textEncoder.encode(info);
info = lazy.textEncoder.encode(info);
const okm = await CryptoUtils.hkdf(ikm, xts, info, len);
return CommonUtils.arrayBufferToByteString(okm);
},
@ -148,14 +149,14 @@ var CryptoUtils = {
* @returns {Uint8Array}
*/
async hmac(alg, key, data) {
const hmacKey = await crypto.subtle.importKey(
const hmacKey = await lazy.crypto.subtle.importKey(
"raw",
key,
{ name: "HMAC", hash: alg },
false,
["sign"]
);
const result = await crypto.subtle.sign("HMAC", hmacKey, data);
const result = await lazy.crypto.subtle.sign("HMAC", hmacKey, data);
return new Uint8Array(result);
},
@ -167,14 +168,14 @@ var CryptoUtils = {
* @returns {Uint8Array}
*/
async hkdf(ikm, salt, info, len) {
const key = await crypto.subtle.importKey(
const key = await lazy.crypto.subtle.importKey(
"raw",
ikm,
{ name: "HKDF" },
false,
["deriveBits"]
);
const okm = await crypto.subtle.deriveBits(
const okm = await lazy.crypto.subtle.deriveBits(
{
name: "HKDF",
hash: "SHA-256",
@ -198,14 +199,14 @@ var CryptoUtils = {
async pbkdf2Generate(passphrase, salt, iterations, len) {
passphrase = CommonUtils.byteStringToArrayBuffer(passphrase);
salt = CommonUtils.byteStringToArrayBuffer(salt);
const key = await crypto.subtle.importKey(
const key = await lazy.crypto.subtle.importKey(
"raw",
passphrase,
{ name: "PBKDF2" },
false,
["deriveBits"]
);
const output = await crypto.subtle.deriveBits(
const output = await lazy.crypto.subtle.deriveBits(
{
name: "PBKDF2",
hash: "SHA-256",
@ -469,10 +470,10 @@ var CryptoUtils = {
options.hasOwnProperty("payload") &&
options.payload
) {
const buffer = textEncoder.encode(
const buffer = lazy.textEncoder.encode(
`hawk.1.payload\n${contentType}\n${options.payload}\n`
);
const hash = await crypto.subtle.digest("SHA-256", buffer);
const hash = await lazy.crypto.subtle.digest("SHA-256", buffer);
// HAWK specifies this .hash to use +/ (not _-) and include the
// trailing "==" padding.
artifacts.hash = ChromeUtils.base64URLEncode(hash, { pad: true })