From fa0a2d8e5d17a1dbc9a13cf571c971730d1048a8 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Tue, 22 Nov 2022 12:46:05 +0100 Subject: [PATCH] crypto: refactor verify acceptable key usage functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/45569 Reviewed-By: Antoine du Hamel Reviewed-By: Tobias Nießen --- lib/internal/crypto/cfrg.js | 32 +++++++++++------------------- lib/internal/crypto/ec.js | 39 +++++++++++++------------------------ lib/internal/crypto/rsa.js | 32 ++++++++++++------------------ 3 files changed, 37 insertions(+), 66 deletions(-) diff --git a/lib/internal/crypto/cfrg.js b/lib/internal/crypto/cfrg.js index 39063f258706dc..68293663e1d552 100644 --- a/lib/internal/crypto/cfrg.js +++ b/lib/internal/crypto/cfrg.js @@ -47,32 +47,22 @@ const { const generateKeyPair = promisify(_generateKeyPair); -function verifyAcceptableCfrgKeyUse(name, type, usages) { +function verifyAcceptableCfrgKeyUse(name, isPublic, usages) { let checkSet; switch (name) { case 'X25519': // Fall through case 'X448': - switch (type) { - case 'private': - checkSet = ['deriveKey', 'deriveBits']; - break; - case 'public': - checkSet = []; - break; - } + checkSet = isPublic ? [] : ['deriveKey', 'deriveBits']; break; case 'Ed25519': // Fall through case 'Ed448': - switch (type) { - case 'private': - checkSet = ['sign']; - break; - case 'public': - checkSet = ['verify']; - break; - } + checkSet = isPublic ? ['verify'] : ['sign']; + break; + default: + throw lazyDOMException( + 'The algorithm is not supported', 'NotSupportedError'); } if (hasAnyNotIn(usages, checkSet)) { throw lazyDOMException( @@ -219,7 +209,7 @@ async function cfrgImportKey( const usagesSet = new SafeSet(keyUsages); switch (format) { case 'spki': { - verifyAcceptableCfrgKeyUse(name, 'public', usagesSet); + verifyAcceptableCfrgKeyUse(name, true, usagesSet); try { keyObject = createPublicKey({ key: keyData, @@ -233,7 +223,7 @@ async function cfrgImportKey( break; } case 'pkcs8': { - verifyAcceptableCfrgKeyUse(name, 'private', usagesSet); + verifyAcceptableCfrgKeyUse(name, false, usagesSet); try { keyObject = createPrivateKey({ key: keyData, @@ -298,7 +288,7 @@ async function cfrgImportKey( verifyAcceptableCfrgKeyUse( name, - isPublic ? 'public' : 'private', + isPublic, usagesSet); const publicKeyObject = createCFRGRawKey( @@ -321,7 +311,7 @@ async function cfrgImportKey( break; } case 'raw': { - verifyAcceptableCfrgKeyUse(name, 'public', usagesSet); + verifyAcceptableCfrgKeyUse(name, true, usagesSet); keyObject = createCFRGRawKey(name, keyData, true); break; } diff --git a/lib/internal/crypto/ec.js b/lib/internal/crypto/ec.js index 09a2395a8525c2..d433e34c4861cf 100644 --- a/lib/internal/crypto/ec.js +++ b/lib/internal/crypto/ec.js @@ -54,28 +54,18 @@ const { const generateKeyPair = promisify(_generateKeyPair); -function verifyAcceptableEcKeyUse(name, type, usages) { +function verifyAcceptableEcKeyUse(name, isPublic, usages) { let checkSet; switch (name) { case 'ECDH': - switch (type) { - case 'private': - checkSet = ['deriveKey', 'deriveBits']; - break; - case 'public': - checkSet = []; - break; - } + checkSet = isPublic ? [] : ['deriveKey', 'deriveBits']; break; case 'ECDSA': - switch (type) { - case 'private': - checkSet = ['sign']; - break; - case 'public': - checkSet = ['verify']; - break; - } + checkSet = isPublic ? ['verify'] : ['sign']; + break; + default: + throw lazyDOMException( + 'The algorithm is not supported', 'NotSupportedError'); } if (hasAnyNotIn(usages, checkSet)) { throw lazyDOMException( @@ -186,7 +176,7 @@ async function ecImportKey( const usagesSet = new SafeSet(keyUsages); switch (format) { case 'spki': { - verifyAcceptableEcKeyUse(name, 'public', usagesSet); + verifyAcceptableEcKeyUse(name, true, usagesSet); try { keyObject = createPublicKey({ key: keyData, @@ -200,7 +190,7 @@ async function ecImportKey( break; } case 'pkcs8': { - verifyAcceptableEcKeyUse(name, 'private', usagesSet); + verifyAcceptableEcKeyUse(name, false, usagesSet); try { keyObject = createPrivateKey({ key: keyData, @@ -221,11 +211,10 @@ async function ecImportKey( if (keyData.crv !== namedCurve) throw lazyDOMException('Named curve mismatch', 'DataError'); - if (keyData.d !== undefined) { - verifyAcceptableEcKeyUse(name, 'private', usagesSet); - } else { - verifyAcceptableEcKeyUse(name, 'public', usagesSet); - } + verifyAcceptableEcKeyUse( + name, + keyData.d === undefined, + usagesSet); if (usagesSet.size > 0 && keyData.use !== undefined) { if (algorithm.name === 'ECDSA' && keyData.use !== 'sig') @@ -265,7 +254,7 @@ async function ecImportKey( break; } case 'raw': { - verifyAcceptableEcKeyUse(name, 'public', usagesSet); + verifyAcceptableEcKeyUse(name, true, usagesSet); keyObject = createECPublicKeyRaw(namedCurve, keyData); break; } diff --git a/lib/internal/crypto/rsa.js b/lib/internal/crypto/rsa.js index 03930d2bf19ac8..2c05f6c8c1c165 100644 --- a/lib/internal/crypto/rsa.js +++ b/lib/internal/crypto/rsa.js @@ -74,28 +74,20 @@ const kRsaVariants = { }; const generateKeyPair = promisify(_generateKeyPair); -function verifyAcceptableRsaKeyUse(name, type, usages) { +function verifyAcceptableRsaKeyUse(name, isPublic, usages) { let checkSet; switch (name) { case 'RSA-OAEP': - switch (type) { - case 'private': - checkSet = ['decrypt', 'unwrapKey']; - break; - case 'public': - checkSet = ['encrypt', 'wrapKey']; - break; - } + checkSet = isPublic ? ['encrypt', 'wrapKey'] : ['decrypt', 'unwrapKey']; + break; + case 'RSA-PSS': + // Fall through + case 'RSASSA-PKCS1-v1_5': + checkSet = isPublic ? ['verify'] : ['sign']; break; default: - switch (type) { - case 'private': - checkSet = ['sign']; - break; - case 'public': - checkSet = ['verify']; - break; - } + throw lazyDOMException( + 'The algorithm is not supported', 'NotSupportedError'); } if (hasAnyNotIn(usages, checkSet)) { throw lazyDOMException( @@ -244,7 +236,7 @@ async function rsaImportKey( let keyObject; switch (format) { case 'spki': { - verifyAcceptableRsaKeyUse(algorithm.name, 'public', usagesSet); + verifyAcceptableRsaKeyUse(algorithm.name, true, usagesSet); try { keyObject = createPublicKey({ key: keyData, @@ -258,7 +250,7 @@ async function rsaImportKey( break; } case 'pkcs8': { - verifyAcceptableRsaKeyUse(algorithm.name, 'private', usagesSet); + verifyAcceptableRsaKeyUse(algorithm.name, false, usagesSet); try { keyObject = createPrivateKey({ key: keyData, @@ -277,7 +269,7 @@ async function rsaImportKey( verifyAcceptableRsaKeyUse( algorithm.name, - keyData.d !== undefined ? 'private' : 'public', + keyData.d === undefined, usagesSet); if (keyData.kty !== 'RSA')