diff options
Diffstat (limited to 'ext/crypto/00_crypto.js')
-rw-r--r-- | ext/crypto/00_crypto.js | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js index 0e5a511e5..2cb7a3bb2 100644 --- a/ext/crypto/00_crypto.js +++ b/ext/crypto/00_crypto.js @@ -61,6 +61,11 @@ RsaPssParams: {}, EcdsaParams: { hash: "HashAlgorithmIdentifier" }, HmacImportParams: { hash: "HashAlgorithmIdentifier" }, + HkdfParams: { + hash: "HashAlgorithmIdentifier", + salt: "BufferSource", + info: "BufferSource", + }, Pbkdf2Params: { hash: "HashAlgorithmIdentifier", salt: "BufferSource" }, RsaOaepParams: { label: "BufferSource" }, }; @@ -97,9 +102,11 @@ }, "importKey": { "HMAC": "HmacImportParams", + "HKDF": null, "PBKDF2": null, }, "deriveBits": { + "HKDF": "HkdfParams", "PBKDF2": "Pbkdf2Params", }, "encrypt": { @@ -893,6 +900,51 @@ // TODO(@littledivy): RSASSA-PKCS1-v1_5 // TODO(@littledivy): RSA-PSS // TODO(@littledivy): ECDSA + case "HKDF": { + if (format !== "raw") { + throw new DOMException("Format not supported", "NotSupportedError"); + } + + // 1. + if ( + ArrayPrototypeFind( + keyUsages, + (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u), + ) !== undefined + ) { + throw new DOMException("Invalid key usages", "SyntaxError"); + } + + // 2. + if (extractable !== false) { + throw new DOMException( + "Key must not be extractable", + "SyntaxError", + ); + } + + // 3. + const handle = {}; + WeakMapPrototypeSet(KEY_STORE, handle, { + type: "raw", + data: keyData, + }); + + // 4-8. + const algorithm = { + name: "HKDF", + }; + const key = constructKey( + "secret", + false, + usageIntersection(keyUsages, recognisedUsages), + algorithm, + handle, + ); + + // 9. + return key; + } case "PBKDF2": { // 1. if (format !== "raw") { @@ -1604,6 +1656,51 @@ return buf.buffer; } + case "HKDF": { + // 1. + if (length === null || length === 0 || length % 8 !== 0) { + throw new DOMException("Invalid length", "OperationError"); + } + + const handle = baseKey[_handle]; + const keyDerivationKey = WeakMapPrototypeGet(KEY_STORE, handle); + + if (ArrayBufferIsView(normalizedAlgorithm.salt)) { + normalizedAlgorithm.salt = new Uint8Array( + normalizedAlgorithm.salt.buffer, + normalizedAlgorithm.salt.byteOffset, + normalizedAlgorithm.salt.byteLength, + ); + } else { + normalizedAlgorithm.salt = new Uint8Array(normalizedAlgorithm.salt); + } + normalizedAlgorithm.salt = TypedArrayPrototypeSlice( + normalizedAlgorithm.salt, + ); + + if (ArrayBufferIsView(normalizedAlgorithm.info)) { + normalizedAlgorithm.info = new Uint8Array( + normalizedAlgorithm.info.buffer, + normalizedAlgorithm.info.byteOffset, + normalizedAlgorithm.info.byteLength, + ); + } else { + normalizedAlgorithm.info = new Uint8Array(normalizedAlgorithm.info); + } + normalizedAlgorithm.info = TypedArrayPrototypeSlice( + normalizedAlgorithm.info, + ); + + const buf = await core.opAsync("op_crypto_derive_bits", { + key: keyDerivationKey, + algorithm: "HKDF", + hash: normalizedAlgorithm.hash.name, + info: normalizedAlgorithm.info, + length, + }, normalizedAlgorithm.salt); + + return buf.buffer; + } default: throw new DOMException("Not implemented", "NotSupportedError"); } |