Skip to content

Commit

Permalink
crypto: refactor hasAnyNotIn to avoid unsafe array iteration
Browse files Browse the repository at this point in the history
PR-URL: #37433
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Tobias Nießen <[email protected]>
Reviewed-By: Juan José Arboleda <[email protected]>
  • Loading branch information
aduh95 authored and targos committed Feb 28, 2021
1 parent c0cdb83 commit b1e188d
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 41 deletions.
9 changes: 4 additions & 5 deletions lib/internal/crypto/aes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ const {
ArrayPrototypePush,
MathFloor,
Promise,
ReflectApply,
SafeSet,
TypedArrayPrototypeSlice,
} = primordials;
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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');
Expand Down
11 changes: 5 additions & 6 deletions lib/internal/crypto/diffiehellman.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

const {
ArrayBufferPrototypeSlice,
ArrayPrototypePush,
FunctionPrototypeCall,
MathFloor,
ObjectDefineProperty,
Promise,
ReflectApply,
SafeSet,
} = primordials;

Expand Down Expand Up @@ -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');
Expand All @@ -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');
Expand Down
10 changes: 5 additions & 5 deletions lib/internal/crypto/dsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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');
Expand Down
16 changes: 7 additions & 9 deletions lib/internal/crypto/ec.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
'use strict';

const {
ArrayPrototypePush,
ObjectKeys,
Promise,
ReflectApply,
SafeSet,
} = primordials;

Expand Down Expand Up @@ -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
Expand All @@ -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');
Expand Down Expand Up @@ -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');
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/crypto/mac.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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');
Expand Down
19 changes: 9 additions & 10 deletions lib/internal/crypto/rsa.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
'use strict';

const {
ArrayPrototypePush,
Promise,
ReflectApply,
SafeSet,
Uint8Array,
} = primordials;
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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');
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/crypto/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/crypto/webcrypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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');
Expand Down

0 comments on commit b1e188d

Please sign in to comment.