From b1e188de8df5a1a86bb5eae34c958e5b02d89f19 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Thu, 18 Feb 2021 14:51:48 +0100 Subject: [PATCH] crypto: refactor hasAnyNotIn to avoid unsafe array iteration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/37433 Reviewed-By: James M Snell Reviewed-By: Tobias Nießen Reviewed-By: Juan José Arboleda --- lib/internal/crypto/aes.js | 9 ++++----- lib/internal/crypto/diffiehellman.js | 11 +++++------ lib/internal/crypto/dsa.js | 10 +++++----- lib/internal/crypto/ec.js | 16 +++++++--------- lib/internal/crypto/mac.js | 4 ++-- lib/internal/crypto/rsa.js | 19 +++++++++---------- lib/internal/crypto/util.js | 4 ++-- lib/internal/crypto/webcrypto.js | 4 ++-- 8 files changed, 36 insertions(+), 41 deletions(-) diff --git a/lib/internal/crypto/aes.js b/lib/internal/crypto/aes.js index 76b3b90b753e68..a35e3469a514bc 100644 --- a/lib/internal/crypto/aes.js +++ b/lib/internal/crypto/aes.js @@ -8,7 +8,6 @@ const { ArrayPrototypePush, MathFloor, Promise, - ReflectApply, SafeSet, TypedArrayPrototypeSlice, } = primordials; @@ -223,7 +222,7 @@ async function aesGenerateKey(algorithm, extractable, keyUsages) { const usageSet = new SafeSet(keyUsages); - if (hasAnyNotIn(usageSet, 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey')) { + if (hasAnyNotIn(usageSet, ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'])) { throw lazyDOMException( 'Unsupported key usage for an AES key', 'SyntaxError'); @@ -253,12 +252,12 @@ async function aesImportKey( extractable, keyUsages) { const { name } = algorithm; - const usagesSet = new SafeSet(keyUsages); - const checkUsages = [usagesSet, 'wrapKey', 'unwrapKey']; + const checkUsages = ['wrapKey', 'unwrapKey']; if (name !== 'AES-KW') ArrayPrototypePush(checkUsages, 'encrypt', 'decrypt'); - if (ReflectApply(hasAnyNotIn, null, checkUsages)) { + const usagesSet = new SafeSet(keyUsages); + if (hasAnyNotIn(usagesSet, checkUsages)) { throw lazyDOMException( 'Unsupported key usage for an AES key', 'SyntaxError'); diff --git a/lib/internal/crypto/diffiehellman.js b/lib/internal/crypto/diffiehellman.js index a23974a531e402..1132b090d36d16 100644 --- a/lib/internal/crypto/diffiehellman.js +++ b/lib/internal/crypto/diffiehellman.js @@ -2,12 +2,10 @@ const { ArrayBufferPrototypeSlice, - ArrayPrototypePush, FunctionPrototypeCall, MathFloor, ObjectDefineProperty, Promise, - ReflectApply, SafeSet, } = primordials; @@ -349,15 +347,16 @@ function deriveBitsDH(publicKey, privateKey, callback) { } function verifyAcceptableDhKeyUse(name, type, usages) { - const args = [usages]; + let checkSet; switch (type) { case 'private': - ArrayPrototypePush(args, 'deriveBits', 'deriveKey'); + checkSet = ['deriveBits', 'deriveKey']; break; case 'public': + checkSet = []; break; } - if (ReflectApply(hasAnyNotIn, null, args)) { + if (hasAnyNotIn(usages, checkSet)) { throw lazyDOMException( `Unsupported key usage for an ${name} key`, 'SyntaxError'); @@ -370,7 +369,7 @@ async function dhGenerateKey( keyUsages) { const usageSet = new SafeSet(keyUsages); - if (hasAnyNotIn(usageSet, 'deriveKey', 'deriveBits')) { + if (hasAnyNotIn(usageSet, ['deriveKey', 'deriveBits'])) { throw lazyDOMException( 'Unsupported key usage for a DH key', 'SyntaxError'); diff --git a/lib/internal/crypto/dsa.js b/lib/internal/crypto/dsa.js index 17a255fa77727c..27cba2139ed691 100644 --- a/lib/internal/crypto/dsa.js +++ b/lib/internal/crypto/dsa.js @@ -51,16 +51,16 @@ const { } = require('internal/crypto/util'); function verifyAcceptableDsaKeyUse(name, type, usages) { - let check; + let checkSet; switch (type) { case 'private': - check = 'sign'; + checkSet = ['sign']; break; case 'public': - check = 'verify'; + checkSet = ['verify']; break; } - if (hasAnyNotIn(usages, check)) { + if (hasAnyNotIn(usages, checkSet)) { throw lazyDOMException( `Unsupported key usage for an ${name} key`, 'SyntaxError'); @@ -84,7 +84,7 @@ async function dsaGenerateKey( const usageSet = new SafeSet(keyUsages); - if (hasAnyNotIn(usageSet, 'sign', 'verify')) { + if (hasAnyNotIn(usageSet, ['sign', 'verify'])) { throw lazyDOMException( 'Unsupported key usage for a DSA key', 'SyntaxError'); diff --git a/lib/internal/crypto/ec.js b/lib/internal/crypto/ec.js index a12ec3e505a757..19ec84fae3b614 100644 --- a/lib/internal/crypto/ec.js +++ b/lib/internal/crypto/ec.js @@ -1,10 +1,8 @@ 'use strict'; const { - ArrayPrototypePush, ObjectKeys, Promise, - ReflectApply, SafeSet, } = primordials; @@ -61,10 +59,10 @@ const { } = require('internal/crypto/keys'); function verifyAcceptableEcKeyUse(name, type, usages) { - const args = [usages]; + let checkSet; switch (name) { case 'ECDH': - ArrayPrototypePush(args, 'deriveKey', 'deriveBits'); + checkSet = ['deriveKey', 'deriveBits']; break; case 'NODE-ED25519': // Fall through @@ -73,14 +71,14 @@ function verifyAcceptableEcKeyUse(name, type, usages) { case 'ECDSA': switch (type) { case 'private': - ArrayPrototypePush(args, 'sign'); + checkSet = ['sign']; break; case 'public': - ArrayPrototypePush(args, 'verify'); + checkSet = ['verify']; break; } } - if (ReflectApply(hasAnyNotIn, null, args)) { + if (hasAnyNotIn(usages, checkSet)) { throw lazyDOMException( `Unsupported key usage for a ${name} key`, 'SyntaxError'); @@ -150,14 +148,14 @@ async function ecGenerateKey(algorithm, extractable, keyUsages) { case 'NODE-ED25519': // Fall through case 'NODE-ED448': - if (hasAnyNotIn(usageSet, 'sign', 'verify')) { + if (hasAnyNotIn(usageSet, ['sign', 'verify'])) { throw lazyDOMException( 'Unsupported key usage for an ECDSA key', 'SyntaxError'); } break; case 'ECDH': - if (hasAnyNotIn(usageSet, 'deriveKey', 'deriveBits')) { + if (hasAnyNotIn(usageSet, ['deriveKey', 'deriveBits'])) { throw lazyDOMException( 'Unsupported key usage for an ECDH key', 'SyntaxError'); diff --git a/lib/internal/crypto/mac.js b/lib/internal/crypto/mac.js index af6b95340f73bd..5ee1f0918db7e1 100644 --- a/lib/internal/crypto/mac.js +++ b/lib/internal/crypto/mac.js @@ -56,7 +56,7 @@ async function hmacGenerateKey(algorithm, extractable, keyUsages) { validateBitLength(length, 'algorithm.length', true); const usageSet = new SafeSet(keyUsages); - if (hasAnyNotIn(usageSet, 'sign', 'verify')) { + if (hasAnyNotIn(usageSet, ['sign', 'verify'])) { throw lazyDOMException( 'Unsupported key usage for an HMAC key', 'SyntaxError'); @@ -89,7 +89,7 @@ async function hmacImportKey( throw new ERR_MISSING_OPTION('algorithm.hash'); const usagesSet = new SafeSet(keyUsages); - if (hasAnyNotIn(usagesSet, 'sign', 'verify')) { + if (hasAnyNotIn(usagesSet, ['sign', 'verify'])) { throw lazyDOMException( 'Unsupported key usage for an HMAC key', 'SyntaxError'); diff --git a/lib/internal/crypto/rsa.js b/lib/internal/crypto/rsa.js index 809747ea011373..c930c284cd23b2 100644 --- a/lib/internal/crypto/rsa.js +++ b/lib/internal/crypto/rsa.js @@ -1,9 +1,7 @@ 'use strict'; const { - ArrayPrototypePush, Promise, - ReflectApply, SafeSet, Uint8Array, } = primordials; @@ -73,29 +71,29 @@ const kRsaVariants = { }; function verifyAcceptableRsaKeyUse(name, type, usages) { - const args = [usages]; + let checkSet; switch (name) { case 'RSA-OAEP': switch (type) { case 'private': - ArrayPrototypePush(args, 'decrypt', 'unwrapKey'); + checkSet = ['decrypt', 'unwrapKey']; break; case 'public': - ArrayPrototypePush(args, 'encrypt', 'wrapKey'); + checkSet = ['encrypt', 'wrapKey']; break; } break; default: switch (type) { case 'private': - ArrayPrototypePush(args, 'sign'); + checkSet = ['sign']; break; case 'public': - ArrayPrototypePush(args, 'verify'); + checkSet = ['verify']; break; } } - if (ReflectApply(hasAnyNotIn, null, args)) { + if (hasAnyNotIn(usages, checkSet)) { throw lazyDOMException( `Unsupported key usage for an ${name} key`, 'SyntaxError'); @@ -157,14 +155,15 @@ async function rsaKeyGenerate( switch (name) { case 'RSA-OAEP': - if (hasAnyNotIn(usageSet, 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey')) { + if (hasAnyNotIn(usageSet, + ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'])) { throw lazyDOMException( 'Unsupported key usage for a RSA key', 'SyntaxError'); } break; default: - if (hasAnyNotIn(usageSet, 'sign', 'verify')) { + if (hasAnyNotIn(usageSet, ['sign', 'verify'])) { throw lazyDOMException( 'Unsupported key usage for a RSA key', 'SyntaxError'); diff --git a/lib/internal/crypto/util.js b/lib/internal/crypto/util.js index 2345fd64f3d359..b0a903f03dd3b4 100644 --- a/lib/internal/crypto/util.js +++ b/lib/internal/crypto/util.js @@ -236,9 +236,9 @@ function normalizeAlgorithm(algorithm, label = 'algorithm') { throw lazyDOMException('Unrecognized name.', 'NotSupportedError'); } -function hasAnyNotIn(set, ...check) { +function hasAnyNotIn(set, checks) { for (const s of set) - if (!ArrayPrototypeIncludes(check, s)) + if (!ArrayPrototypeIncludes(checks, s)) return true; return false; } diff --git a/lib/internal/crypto/webcrypto.js b/lib/internal/crypto/webcrypto.js index eba0b08e836c38..57e3ee3af11eb2 100644 --- a/lib/internal/crypto/webcrypto.js +++ b/lib/internal/crypto/webcrypto.js @@ -402,7 +402,7 @@ async function importGenericSecretKey( if (extractable) throw lazyDOMException(`${name} keys are not extractable`, 'SyntaxError'); - if (hasAnyNotIn(usagesSet, 'deriveKey', 'deriveBits')) { + if (hasAnyNotIn(usagesSet, ['deriveKey', 'deriveBits'])) { throw lazyDOMException( `Unsupported key usage for a ${name} key`, 'SyntaxError'); @@ -419,7 +419,7 @@ async function importGenericSecretKey( break; } case 'raw': - if (hasAnyNotIn(usagesSet, 'deriveKey', 'deriveBits')) { + if (hasAnyNotIn(usagesSet, ['deriveKey', 'deriveBits'])) { throw lazyDOMException( `Unsupported key usage for a ${name} key`, 'SyntaxError');