diff options
author | Luca Casonato <hello@lcas.dev> | 2021-11-25 15:57:01 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-25 15:57:01 +0100 |
commit | 2853e3760471560c1812b46007e1a525966b1365 (patch) | |
tree | 4045b423de91c4443dc3e2993f852440d58c7f5e /ext/crypto/00_crypto.js | |
parent | 47cf7b0b2e62c1c0852da5f7c378965ee91a3b46 (diff) |
fix(ext/crypto): throw on key & op algo mismatch (#12838)
Diffstat (limited to 'ext/crypto/00_crypto.js')
-rw-r--r-- | ext/crypto/00_crypto.js | 204 |
1 files changed, 120 insertions, 84 deletions
diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js index 2885a9699..c23fd5a36 100644 --- a/ext/crypto/00_crypto.js +++ b/ext/crypto/00_crypto.js @@ -472,88 +472,23 @@ // 3. const normalizedAlgorithm = normalizeAlgorithm(algorithm, "encrypt"); - const handle = key[_handle]; - const keyData = WeakMapPrototypeGet(KEY_STORE, handle); - - switch (normalizedAlgorithm.name) { - case "RSA-OAEP": { - // 1. - if (key[_type] !== "public") { - throw new DOMException( - "Key type not supported", - "InvalidAccessError", - ); - } - - // 2. - if (normalizedAlgorithm.label) { - if (ArrayBufferIsView(normalizedAlgorithm.label)) { - normalizedAlgorithm.label = new Uint8Array( - normalizedAlgorithm.label.buffer, - normalizedAlgorithm.label.byteOffset, - normalizedAlgorithm.label.byteLength, - ); - } else { - normalizedAlgorithm.label = new Uint8Array( - normalizedAlgorithm.label, - ); - } - normalizedAlgorithm.label = TypedArrayPrototypeSlice( - normalizedAlgorithm.label, - ); - } else { - normalizedAlgorithm.label = new Uint8Array(); - } - - // 3-5. - const hashAlgorithm = key[_algorithm].hash.name; - const cipherText = await core.opAsync("op_crypto_encrypt_key", { - key: keyData, - algorithm: "RSA-OAEP", - hash: hashAlgorithm, - }, data); - - // 6. - return cipherText.buffer; - } - case "AES-CBC": { - if (ArrayBufferIsView(normalizedAlgorithm.iv)) { - normalizedAlgorithm.iv = new Uint8Array( - normalizedAlgorithm.iv.buffer, - normalizedAlgorithm.iv.byteOffset, - normalizedAlgorithm.iv.byteLength, - ); - } else { - normalizedAlgorithm.iv = new Uint8Array( - normalizedAlgorithm.iv, - ); - } - normalizedAlgorithm.iv = TypedArrayPrototypeSlice( - normalizedAlgorithm.iv, - ); - - // 1. - if (normalizedAlgorithm.iv.byteLength !== 16) { - throw new DOMException( - "Initialization vector must be 16 bytes", - "OperationError", - ); - } - - // 2. - const cipherText = await core.opAsync("op_crypto_encrypt_key", { - key: keyData, - algorithm: "AES-CBC", - length: key[_algorithm].length, - iv: normalizedAlgorithm.iv, - }, data); + // 8. + if (normalizedAlgorithm.name !== key[_algorithm].name) { + throw new DOMException( + "Encryption algorithm doesn't match key algorithm.", + "InvalidAccessError", + ); + } - // 4. - return cipherText.buffer; - } - default: - throw new DOMException("Not implemented", "NotSupportedError"); + // 9. + if (!ArrayPrototypeIncludes(key[_usages], "encrypt")) { + throw new DOMException( + "Key does not support the 'encrypt' operation.", + "InvalidAccessError", + ); } + + return await encrypt(normalizedAlgorithm, key, data); } /** @@ -590,6 +525,22 @@ // 3. const normalizedAlgorithm = normalizeAlgorithm(algorithm, "decrypt"); + // 8. + if (normalizedAlgorithm.name !== key[_algorithm].name) { + throw new DOMException( + "Decryption algorithm doesn't match key algorithm.", + "OperationError", + ); + } + + // 9. + if (!ArrayPrototypeIncludes(key[_usages], "decrypt")) { + throw new DOMException( + "Key does not support the 'decrypt' operation.", + "InvalidAccessError", + ); + } + const handle = key[_handle]; const keyData = WeakMapPrototypeGet(KEY_STORE, handle); @@ -1415,7 +1366,7 @@ // 4-7. const algorithm = { - name: "AES-CBC", + name: "AES-CTR", length: keyData.byteLength * 8, }; @@ -1471,7 +1422,7 @@ // 4-7. const algorithm = { - name: "AES-CTR", + name: "AES-CBC", length: keyData.byteLength * 8, }; @@ -2238,7 +2189,7 @@ let bytes; // 13. if (format !== "jwk") { - bytes = exportedKey; + bytes = new Uint8Array(exportedKey); } else { // TODO(@littledivy): Implement JWK. throw new DOMException( @@ -2259,7 +2210,7 @@ } else if ( supportedAlgorithms["encrypt"][normalizedAlgorithm.name] !== undefined ) { - return this.encrypt(normalizedAlgorithm, wrappingKey, bytes); + return await encrypt(normalizedAlgorithm, wrappingKey, bytes); } else { throw new DOMException( "Algorithm not supported", @@ -2819,6 +2770,91 @@ } } + async function encrypt(normalizedAlgorithm, key, data) { + const handle = key[_handle]; + const keyData = WeakMapPrototypeGet(KEY_STORE, handle); + + switch (normalizedAlgorithm.name) { + case "RSA-OAEP": { + // 1. + if (key[_type] !== "public") { + throw new DOMException( + "Key type not supported", + "InvalidAccessError", + ); + } + + // 2. + if (normalizedAlgorithm.label) { + if (ArrayBufferIsView(normalizedAlgorithm.label)) { + normalizedAlgorithm.label = new Uint8Array( + normalizedAlgorithm.label.buffer, + normalizedAlgorithm.label.byteOffset, + normalizedAlgorithm.label.byteLength, + ); + } else { + normalizedAlgorithm.label = new Uint8Array( + normalizedAlgorithm.label, + ); + } + normalizedAlgorithm.label = TypedArrayPrototypeSlice( + normalizedAlgorithm.label, + ); + } else { + normalizedAlgorithm.label = new Uint8Array(); + } + + // 3-5. + const hashAlgorithm = key[_algorithm].hash.name; + const cipherText = await core.opAsync("op_crypto_encrypt_key", { + key: keyData, + algorithm: "RSA-OAEP", + hash: hashAlgorithm, + }, data); + + // 6. + return cipherText.buffer; + } + case "AES-CBC": { + if (ArrayBufferIsView(normalizedAlgorithm.iv)) { + normalizedAlgorithm.iv = new Uint8Array( + normalizedAlgorithm.iv.buffer, + normalizedAlgorithm.iv.byteOffset, + normalizedAlgorithm.iv.byteLength, + ); + } else { + normalizedAlgorithm.iv = new Uint8Array( + normalizedAlgorithm.iv, + ); + } + normalizedAlgorithm.iv = TypedArrayPrototypeSlice( + normalizedAlgorithm.iv, + ); + + // 1. + if (normalizedAlgorithm.iv.byteLength !== 16) { + throw new DOMException( + "Initialization vector must be 16 bytes", + "OperationError", + ); + } + + // 2. + const cipherText = await core.opAsync("op_crypto_encrypt_key", { + key: keyData, + algorithm: "AES-CBC", + length: key[_algorithm].length, + iv: normalizedAlgorithm.iv, + }, data); + + // 4. + return cipherText.buffer; + } + default: + throw new DOMException("Not implemented", "NotSupportedError"); + } + } + webidl.configurePrototype(SubtleCrypto); const subtle = webidl.createBranded(SubtleCrypto); |