Skip to content

Commit fb602d1

Browse files
panvanodejs-github-bot
authored andcommitted
crypto: separate conversion from validation
Convert algorithm dictionaries on the original receiver, with name read once. Validate normalized parameters in their operation steps after the method-level key checks and generation usage checks. This also makes Argon2 validation use converted parallelism and keeps later dictionary conversion errors ahead of semantic parameter errors. Signed-off-by: Filip Skokan <panva.ip@gmail.com> Assisted-by: Codex PR-URL: #66237 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Aviv Keller <me@aviv.sh>
1 parent 36b76ca commit fb602d1

19 files changed

Lines changed: 258 additions & 47 deletions

‎lib/internal/crypto/aes.js‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const {
2525
getUsagesMask,
2626
jobPromise,
2727
getBufferSourceByteLength,
28+
validateAlgorithm,
2829
} = require('internal/crypto/util');
2930

3031
const {
@@ -173,6 +174,7 @@ function asyncAesOcbCipher(mode, key, data, algorithm) {
173174
}
174175

175176
function aesCipher(mode, key, data, algorithm) {
177+
validateAlgorithm(algorithm, 'encrypt');
176178
switch (algorithm.name) {
177179
case 'AES-CTR': return asyncAesCtrCipher(mode, key, data, algorithm);
178180
case 'AES-CBC': return asyncAesCbcCipher(mode, key, data, algorithm);
@@ -185,8 +187,9 @@ function aesCipher(mode, key, data, algorithm) {
185187
function aesGenerateKey(algorithm, extractable, usages) {
186188
const { name, length } = algorithm;
187189

188-
const usagesSet = validateUsagesNotEmpty(
189-
validateKeyUsages(usages, kUsages[name], name));
190+
const usagesSet = validateKeyUsages(usages, kUsages[name], name);
191+
validateAlgorithm(algorithm, 'generateKey');
192+
validateUsagesNotEmpty(usagesSet);
190193

191194
return jobPromise(() => new SecretKeyGenJob(
192195
kCryptoJobWebCrypto,

‎lib/internal/crypto/argon2.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const {
2929
const {
3030
getArrayBufferOrView,
3131
jobPromise,
32+
validateAlgorithm,
3233
} = require('internal/crypto/util');
3334

3435
const {
@@ -203,6 +204,7 @@ function validateArgon2DeriveBitsLength(length) {
203204

204205
function argon2DeriveBits(algorithm, baseKey, length) {
205206
validateArgon2DeriveBitsLength(length);
207+
validateAlgorithm(algorithm, 'deriveBits');
206208

207209
const type = {
208210
'__proto__': null,

‎lib/internal/crypto/cfrg.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const {
2323
getUsagesMask,
2424
jobPromise,
2525
toUsagesSet,
26+
validateAlgorithm,
2627
} = require('internal/crypto/util');
2728

2829
const {
@@ -184,6 +185,8 @@ function eddsaSignVerify(key, data, algorithm, signature) {
184185
if (getCryptoKeyType(key) !== type)
185186
throw lazyDOMException(`Key must be a ${type} key`, 'InvalidAccessError');
186187

188+
validateAlgorithm(algorithm, mode === kSignJobModeSign ? 'sign' : 'verify');
189+
187190
return jobPromise(() => new SignJob(
188191
kCryptoJobWebCrypto,
189192
mode,

‎lib/internal/crypto/chacha20_poly1305.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const {
99
const {
1010
getUsagesMask,
1111
jobPromise,
12+
validateAlgorithm,
1213
} = require('internal/crypto/util');
1314

1415
const {
@@ -36,6 +37,7 @@ function validateKeyLength(length) {
3637
}
3738

3839
function c20pCipher(mode, key, data, algorithm) {
40+
validateAlgorithm(algorithm, 'encrypt');
3941
return jobPromise(() => new ChaCha20Poly1305CipherJob(
4042
kCryptoJobWebCrypto,
4143
mode,

‎lib/internal/crypto/diffiehellman.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const {
6161
numBitsToBytes,
6262
toBuf,
6363
truncateToBitLength,
64+
validateAlgorithm,
6465
kHandle,
6566
} = require('internal/crypto/util');
6667

@@ -332,6 +333,7 @@ function diffieHellman(options, callback) {
332333
// The ecdhDeriveBits function is part of the Web Crypto API and serves both
333334
// deriveKeys and deriveBits functions.
334335
function ecdhDeriveBits(algorithm, baseKey, length) {
336+
validateAlgorithm(algorithm, 'deriveBits');
335337
const { 'public': key } = algorithm;
336338

337339
if (getCryptoKeyType(baseKey) !== 'private') {

‎lib/internal/crypto/ec.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const {
3131
getUsagesMask,
3232
jobPromise,
3333
normalizeHashName,
34+
validateAlgorithm,
3435
kNamedCurveAliases,
3536
toUsagesSet,
3637
} = require('internal/crypto/util');
@@ -72,6 +73,7 @@ function ecGenerateKey(algorithm, extractable, usages) {
7273
const { name, namedCurve } = algorithm;
7374
const allowedUsages = kUsages[name];
7475
const usagesSet = validateKeyUsages(usages, allowedUsages.keygen, name);
76+
validateAlgorithm(algorithm, 'generateKey');
7577

7678
const keyAlgorithm = { name, namedCurve };
7779
const keyUsages = getKeyPairUsages(usagesSet, allowedUsages);
@@ -139,6 +141,7 @@ function ecImportKey(
139141
usages,
140142
) {
141143
const { name, namedCurve } = algorithm;
144+
validateAlgorithm(algorithm, 'importKey');
142145

143146
let handle;
144147
const allowedUsages = kUsages[name];

‎lib/internal/crypto/hash.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const {
2727
normalizeHashName,
2828
numBitsToBytes,
2929
truncateToBitLength,
30+
validateAlgorithm,
3031
validateMaxBufferLength,
3132
kHandle,
3233
getCachedHashId,
@@ -240,6 +241,7 @@ Hmac.prototype._transform = Hash.prototype._transform;
240241

241242
function asyncDigest(algorithm, data) {
242243
validateMaxBufferLength(data, 'data');
244+
validateAlgorithm(algorithm, 'digest');
243245

244246
switch (algorithm.name) {
245247
case 'SHA-1':

‎lib/internal/crypto/hkdf.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const {
2929
normalizeHashName,
3030
toBuf,
3131
validateByteSource,
32+
validateAlgorithm,
3233
} = require('internal/crypto/util');
3334

3435
const {
@@ -182,6 +183,7 @@ function validateHkdfDeriveBitsLength(length, hash) {
182183
function hkdfDeriveBits(algorithm, baseKey, length) {
183184
const { hash, salt, info } = algorithm;
184185
validateHkdfDeriveBitsLength(length, hash);
186+
validateAlgorithm(algorithm, 'deriveBits');
185187

186188
if (length === 0)
187189
return PromiseResolve(new ArrayBuffer(0));

‎lib/internal/crypto/mac.js‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const {
2121
numBitsToBytes,
2222
truncateToBitLength,
2323
validateKmacKeyLength,
24+
validateAlgorithm,
2425
} = require('internal/crypto/util');
2526

2627
const {
@@ -71,11 +72,12 @@ function hmacGenerateKey(algorithm, extractable, usages) {
7172
const {
7273
hash,
7374
name,
74-
length = getBlockSize(hash.name),
7575
} = algorithm;
7676

77-
const usageSet = validateUsagesNotEmpty(
78-
validateKeyUsages(usages, kUsages, name));
77+
const usageSet = validateKeyUsages(usages, kUsages, name);
78+
validateAlgorithm(algorithm, 'generateKey');
79+
const { length = getBlockSize(hash.name) } = algorithm;
80+
validateUsagesNotEmpty(usageSet);
7981

8082
return jobPromise(() => new SecretKeyGenJob(
8183
kCryptoJobWebCrypto,
@@ -95,8 +97,9 @@ function kmacGenerateKey(algorithm, extractable, usages) {
9597
}[name],
9698
} = algorithm;
9799

98-
const usageSet = validateUsagesNotEmpty(
99-
validateKeyUsages(usages, kUsages, name));
100+
const usageSet = validateKeyUsages(usages, kUsages, name);
101+
validateAlgorithm(algorithm, 'generateKey');
102+
validateUsagesNotEmpty(usageSet);
100103

101104
return jobPromise(() => new SecretKeyGenJob(
102105
kCryptoJobWebCrypto,
@@ -114,6 +117,7 @@ function macImportKey(
114117
usages,
115118
) {
116119
const isHmac = algorithm.name === 'HMAC';
120+
validateAlgorithm(algorithm, 'importKey');
117121
const usagesSet = validateKeyUsages(
118122
usages, kUsages, algorithm.name);
119123
let handle;
@@ -181,6 +185,7 @@ function hmacSignVerify(key, data, algorithm, signature) {
181185
}
182186

183187
function kmacSignVerify(key, data, algorithm, signature) {
188+
validateAlgorithm(algorithm, 'sign');
184189
const mode = signature === undefined ? kSignJobModeSign : kSignJobModeVerify;
185190
return jobPromise(() => new KmacJob(
186191
kCryptoJobWebCrypto,

‎lib/internal/crypto/ml_dsa.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const {
2525
getUsagesMask,
2626
jobPromise,
2727
toUsagesSet,
28+
validateAlgorithm,
2829
getBufferSourceByteLength,
2930
} = require('internal/crypto/util');
3031

@@ -197,6 +198,8 @@ function mlDsaSignVerify(key, data, algorithm, signature) {
197198
if (getCryptoKeyType(key) !== type)
198199
throw lazyDOMException(`Key must be a ${type} key`, 'InvalidAccessError');
199200

201+
validateAlgorithm(algorithm, mode === kSignJobModeSign ? 'sign' : 'verify');
202+
200203
return jobPromise(() => new SignJob(
201204
kCryptoJobWebCrypto,
202205
mode,

0 commit comments

Comments
 (0)