From 1f0edde412bcd673e3fd471e1bd46cdd18ad0b40 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Mon, 7 Nov 2022 07:35:35 +0100 Subject: [PATCH] crypto: handle more webcrypto errors with OperationError MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/45320 Reviewed-By: Yagiz Nizipli Reviewed-By: Antoine du Hamel Reviewed-By: Tobias Nießen --- lib/internal/crypto/aes.js | 8 ++++---- lib/internal/crypto/cfrg.js | 4 ++-- lib/internal/crypto/diffiehellman.js | 2 +- lib/internal/crypto/ec.js | 4 ++-- lib/internal/crypto/hash.js | 2 +- lib/internal/crypto/mac.js | 2 +- lib/internal/crypto/rsa.js | 6 +++--- lib/internal/crypto/util.js | 11 ++++++++--- test/parallel/test-webcrypto-digest.js | 2 +- 9 files changed, 23 insertions(+), 18 deletions(-) diff --git a/lib/internal/crypto/aes.js b/lib/internal/crypto/aes.js index 862d5127448ec4..5b4e7d8f743469 100644 --- a/lib/internal/crypto/aes.js +++ b/lib/internal/crypto/aes.js @@ -124,7 +124,7 @@ function asyncAesCtrCipher(mode, key, data, { counter, length }) { 'OperationError'); } - return jobPromise(new AESCipherJob( + return jobPromise(() => new AESCipherJob( kCryptoJobAsync, mode, key[kKeyObject][kHandle], @@ -137,7 +137,7 @@ function asyncAesCtrCipher(mode, key, data, { counter, length }) { function asyncAesCbcCipher(mode, key, data, { iv }) { iv = getArrayBufferOrView(iv, 'algorithm.iv'); validateByteLength(iv, 'algorithm.iv', 16); - return jobPromise(new AESCipherJob( + return jobPromise(() => new AESCipherJob( kCryptoJobAsync, mode, key[kKeyObject][kHandle], @@ -147,7 +147,7 @@ function asyncAesCbcCipher(mode, key, data, { iv }) { } function asyncAesKwCipher(mode, key, data) { - return jobPromise(new AESCipherJob( + return jobPromise(() => new AESCipherJob( kCryptoJobAsync, mode, key[kKeyObject][kHandle], @@ -201,7 +201,7 @@ function asyncAesGcmCipher( break; } - return jobPromise(new AESCipherJob( + return jobPromise(() => new AESCipherJob( kCryptoJobAsync, mode, key[kKeyObject][kHandle], diff --git a/lib/internal/crypto/cfrg.js b/lib/internal/crypto/cfrg.js index 3227b692afb99e..a4b57825f3702e 100644 --- a/lib/internal/crypto/cfrg.js +++ b/lib/internal/crypto/cfrg.js @@ -193,7 +193,7 @@ async function cfrgGenerateKey(algorithm, extractable, keyUsages) { function cfrgExportKey(key, format) { emitExperimentalWarning(`The ${key.algorithm.name} Web Crypto API algorithm`); - return jobPromise(new ECKeyExportJob( + return jobPromise(() => new ECKeyExportJob( kCryptoJobAsync, format, key[kKeyObject][kHandle])); @@ -322,7 +322,7 @@ function eddsaSignVerify(key, data, { name, context }, signature) { } } - return jobPromise(new SignJob( + return jobPromise(() => new SignJob( kCryptoJobAsync, mode, key[kKeyObject][kHandle], diff --git a/lib/internal/crypto/diffiehellman.js b/lib/internal/crypto/diffiehellman.js index 096d32f7def93b..391832fde46bc2 100644 --- a/lib/internal/crypto/diffiehellman.js +++ b/lib/internal/crypto/diffiehellman.js @@ -357,7 +357,7 @@ async function ecdhDeriveBits(algorithm, baseKey, length) { throw lazyDOMException('Named curve mismatch', 'InvalidAccessError'); } - const bits = await jobPromise(new ECDHBitsJob( + const bits = await jobPromise(() => new ECDHBitsJob( kCryptoJobAsync, key.algorithm.name === 'ECDH' ? baseKey.algorithm.namedCurve : baseKey.algorithm.name, key[kKeyObject][kHandle], diff --git a/lib/internal/crypto/ec.js b/lib/internal/crypto/ec.js index d1aa2a7b0af9ac..8d70633b28b244 100644 --- a/lib/internal/crypto/ec.js +++ b/lib/internal/crypto/ec.js @@ -150,7 +150,7 @@ async function ecGenerateKey(algorithm, extractable, keyUsages) { } function ecExportKey(key, format) { - return jobPromise(new ECKeyExportJob( + return jobPromise(() => new ECKeyExportJob( kCryptoJobAsync, format, key[kKeyObject][kHandle])); @@ -285,7 +285,7 @@ function ecdsaSignVerify(key, data, { name, hash }, signature) { throw new ERR_MISSING_OPTION('algorithm.hash'); const hashname = normalizeHashName(hash.name); - return jobPromise(new SignJob( + return jobPromise(() => new SignJob( kCryptoJobAsync, mode, key[kKeyObject][kHandle], diff --git a/lib/internal/crypto/hash.js b/lib/internal/crypto/hash.js index 956053af0a8c2c..72d127b37cbeb6 100644 --- a/lib/internal/crypto/hash.js +++ b/lib/internal/crypto/hash.js @@ -183,7 +183,7 @@ async function asyncDigest(algorithm, data) { case 'SHA-384': // Fall through case 'SHA-512': - return jobPromise(new HashJob( + return jobPromise(() => new HashJob( kCryptoJobAsync, normalizeHashName(algorithm.name), data, diff --git a/lib/internal/crypto/mac.js b/lib/internal/crypto/mac.js index 0d83691ba55548..bcd66ae80c1c49 100644 --- a/lib/internal/crypto/mac.js +++ b/lib/internal/crypto/mac.js @@ -183,7 +183,7 @@ async function hmacImportKey( function hmacSignVerify(key, data, algorithm, signature) { const mode = signature === undefined ? kSignJobModeSign : kSignJobModeVerify; - return jobPromise(new HmacJob( + return jobPromise(() => new HmacJob( kCryptoJobAsync, mode, normalizeHashName(key.algorithm.hash.name), diff --git a/lib/internal/crypto/rsa.js b/lib/internal/crypto/rsa.js index 83e174fb6b4a52..044d19374ba597 100644 --- a/lib/internal/crypto/rsa.js +++ b/lib/internal/crypto/rsa.js @@ -116,7 +116,7 @@ function rsaOaepCipher(mode, key, data, { label }) { validateMaxBufferLength(label, 'algorithm.label'); } - return jobPromise(new RSACipherJob( + return jobPromise(() => new RSACipherJob( kCryptoJobAsync, mode, key[kKeyObject][kHandle], @@ -223,7 +223,7 @@ async function rsaKeyGenerate( } function rsaExportKey(key, format) { - return jobPromise(new RSAKeyExportJob( + return jobPromise(() => new RSAKeyExportJob( kCryptoJobAsync, format, key[kKeyObject][kHandle], @@ -346,7 +346,7 @@ function rsaSignVerify(key, data, { saltLength }, signature) { if (key.type !== type) throw lazyDOMException(`Key must be a ${type} key`, 'InvalidAccessError'); - return jobPromise(new SignJob( + return jobPromise(() => new SignJob( kCryptoJobAsync, signature === undefined ? kSignJobModeSign : kSignJobModeVerify, key[kKeyObject][kHandle], diff --git a/lib/internal/crypto/util.js b/lib/internal/crypto/util.js index c94725dd82ddcb..a5446aee187382 100644 --- a/lib/internal/crypto/util.js +++ b/lib/internal/crypto/util.js @@ -286,10 +286,15 @@ function onDone(resolve, reject, err, result) { resolve(result); } -function jobPromise(job) { +function jobPromise(getJob) { return new Promise((resolve, reject) => { - job.ondone = FunctionPrototypeBind(onDone, job, resolve, reject); - job.run(); + try { + const job = getJob(); + job.ondone = FunctionPrototypeBind(onDone, job, resolve, reject); + job.run(); + } catch (err) { + onDone(resolve, reject, err); + } }); } diff --git a/test/parallel/test-webcrypto-digest.js b/test/parallel/test-webcrypto-digest.js index b8680564d1a1a3..25b78500b7d346 100644 --- a/test/parallel/test-webcrypto-digest.js +++ b/test/parallel/test-webcrypto-digest.js @@ -83,7 +83,7 @@ Promise.all([1, [], {}, null, undefined].map((i) => // addition to the API, and is added as a support for future additional // hash algorithms that support variable digest output lengths. assert.rejects(subtle.digest({ name: 'SHA-512', length: 510 }, kData), { - message: /Digest method not supported/ + name: 'OperationError', }).then(common.mustCall()); const kSourceData = {