Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions doc/api/webcrypto.md
Original file line number Diff line number Diff line change
Expand Up @@ -1830,6 +1830,9 @@ changes:
description: Renamed `cShakeParams.length` to `cShakeParams.outputLength`.
-->

When both `functionName` and `customization` are empty or `undefined`, cSHAKE is
equivalent to plain SHAKE.

#### `cShakeParams.name`

<!-- YAML
Expand All @@ -1844,7 +1847,8 @@ added: v24.7.0
added: v25.9.0
-->

* Type: {number} represents the requested output length in bits.
* Type: {number} represents the requested output length in bits. Must be a
multiple of 8.

#### `cShakeParams.functionName`

Expand All @@ -1859,9 +1863,10 @@ changes:
* Type: {ArrayBuffer|TypedArray|DataView|Buffer|undefined}

The `functionName` member represents the NIST function-name byte string used to
domain-separate functions built on top of cSHAKE. Accepted values are:
domain-separate functions built on top of cSHAKE. Non-empty values require
OpenSSL 4.0 or later. Accepted values are:

* empty or `undefined`, in which case cSHAKE is equivalent to plain SHAKE
* empty or `undefined`
* the ASCII byte sequence `'KMAC'`
* the ASCII byte sequence `'TupleHash'`
* the ASCII byte sequence `'ParallelHash'`
Expand All @@ -1878,11 +1883,11 @@ changes:

* Type: {ArrayBuffer|TypedArray|DataView|Buffer|undefined}

The `customization` member represents the customization data. Accepted
values are:
The `customization` member represents the customization data. Non-empty values
require OpenSSL 4.0 or later. Accepted values are:

* empty or `undefined`, in which case cSHAKE is equivalent to plain SHAKE
* up to 512 bytes of arbitrary data
* empty or `undefined`
* up to 512 bytes of data without null bytes

### Class: `EcdhKeyDeriveParams`

Expand Down Expand Up @@ -2332,7 +2337,7 @@ added: v24.8.0
* Type: {number}

The optional number of bits in the KMAC key. This is optional and should
be omitted for most cases.
be omitted for most cases. The key length must be at least 32 and a multiple of 8.

#### `kmacImportParams.name`

Expand Down Expand Up @@ -2382,7 +2387,8 @@ added: v24.8.0

The number of bits to generate for the KMAC key. If omitted,
the length will be determined by the KMAC algorithm used.
This is optional and should be omitted for most cases.
This is optional and should be omitted for most cases. Must be at least 32 and a
multiple of 8.

#### `kmacKeyGenParams.name`

Expand Down Expand Up @@ -2416,7 +2422,8 @@ added: v24.8.0
added: v25.9.0
-->

* Type: {number} represents the requested output length in bits.
* Type: {number} represents the requested output length in bits. Must be a
multiple of 8.

#### `kmacParams.customization`

Expand Down
7 changes: 5 additions & 2 deletions lib/internal/crypto/aes.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const {
getUsagesMask,
jobPromise,
getBufferSourceByteLength,
validateAlgorithm,
} = require('internal/crypto/util');

const {
Expand Down Expand Up @@ -173,6 +174,7 @@ function asyncAesOcbCipher(mode, key, data, algorithm) {
}

function aesCipher(mode, key, data, algorithm) {
validateAlgorithm(algorithm, 'encrypt');
switch (algorithm.name) {
case 'AES-CTR': return asyncAesCtrCipher(mode, key, data, algorithm);
case 'AES-CBC': return asyncAesCbcCipher(mode, key, data, algorithm);
Expand All @@ -185,8 +187,9 @@ function aesCipher(mode, key, data, algorithm) {
function aesGenerateKey(algorithm, extractable, usages) {
const { name, length } = algorithm;

const usagesSet = validateUsagesNotEmpty(
validateKeyUsages(usages, kUsages[name], name));
const usagesSet = validateKeyUsages(usages, kUsages[name], name);
validateAlgorithm(algorithm, 'generateKey');
validateUsagesNotEmpty(usagesSet);

return jobPromise(() => new SecretKeyGenJob(
kCryptoJobWebCrypto,
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/crypto/argon2.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const {
const {
getArrayBufferOrView,
jobPromise,
validateAlgorithm,
} = require('internal/crypto/util');

const {
Expand Down Expand Up @@ -203,6 +204,7 @@ function validateArgon2DeriveBitsLength(length) {

function argon2DeriveBits(algorithm, baseKey, length) {
validateArgon2DeriveBitsLength(length);
validateAlgorithm(algorithm, 'deriveBits');

const type = {
'__proto__': null,
Expand Down
3 changes: 3 additions & 0 deletions lib/internal/crypto/cfrg.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const {
getUsagesMask,
jobPromise,
toUsagesSet,
validateAlgorithm,
} = require('internal/crypto/util');

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

validateAlgorithm(algorithm, mode === kSignJobModeSign ? 'sign' : 'verify');

return jobPromise(() => new SignJob(
kCryptoJobWebCrypto,
mode,
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/crypto/chacha20_poly1305.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
const {
getUsagesMask,
jobPromise,
validateAlgorithm,
} = require('internal/crypto/util');

const {
Expand Down Expand Up @@ -36,6 +37,7 @@ function validateKeyLength(length) {
}

function c20pCipher(mode, key, data, algorithm) {
validateAlgorithm(algorithm, 'encrypt');
return jobPromise(() => new ChaCha20Poly1305CipherJob(
kCryptoJobWebCrypto,
mode,
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/crypto/diffiehellman.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const {
numBitsToBytes,
toBuf,
truncateToBitLength,
validateAlgorithm,
kHandle,
} = require('internal/crypto/util');

Expand Down Expand Up @@ -372,6 +373,7 @@ function diffieHellman(options, callback) {
// The ecdhDeriveBits function is part of the Web Crypto API and serves both
// deriveKeys and deriveBits functions.
function ecdhDeriveBits(algorithm, baseKey, length) {
validateAlgorithm(algorithm, 'deriveBits');
const { 'public': key } = algorithm;

if (getCryptoKeyType(baseKey) !== 'private') {
Expand Down
3 changes: 3 additions & 0 deletions lib/internal/crypto/ec.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const {
getUsagesMask,
jobPromise,
normalizeHashName,
validateAlgorithm,
kNamedCurveAliases,
toUsagesSet,
} = require('internal/crypto/util');
Expand Down Expand Up @@ -72,6 +73,7 @@ function ecGenerateKey(algorithm, extractable, usages) {
const { name, namedCurve } = algorithm;
const allowedUsages = kUsages[name];
const usagesSet = validateKeyUsages(usages, allowedUsages.keygen, name);
validateAlgorithm(algorithm, 'generateKey');

const keyAlgorithm = { name, namedCurve };
const keyUsages = getKeyPairUsages(usagesSet, allowedUsages);
Expand Down Expand Up @@ -139,6 +141,7 @@ function ecImportKey(
usages,
) {
const { name, namedCurve } = algorithm;
validateAlgorithm(algorithm, 'importKey');

let handle;
const allowedUsages = kUsages[name];
Expand Down
30 changes: 8 additions & 22 deletions lib/internal/crypto/hash.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ const {
StringPrototypeReplace,
StringPrototypeToLowerCase,
Symbol,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeIncludes,
} = primordials;

const {
CShakeJob,
Hash: _Hash,
HashJob,
Hmac: _Hmac,
Expand All @@ -24,10 +22,8 @@ const {
const {
getStringOption,
jobPromise,
jobPromiseThen,
normalizeHashName,
numBitsToBytes,
truncateToBitLength,
validateAlgorithm,
validateMaxBufferLength,
kHandle,
getCachedHashId,
Expand All @@ -42,7 +38,6 @@ const {
} = require('internal/crypto/keys');

const {
lazyDOMException,
normalizeEncoding,
encodingsMap,
getDeprecationWarningEmitter,
Expand Down Expand Up @@ -257,6 +252,7 @@ Hmac.prototype._transform = Hash.prototype._transform;

function asyncDigest(algorithm, data) {
validateMaxBufferLength(data, 'data');
validateAlgorithm(algorithm, 'digest');

switch (algorithm.name) {
case 'SHA-1':
Expand All @@ -282,30 +278,20 @@ function asyncDigest(algorithm, data) {
const outputLength = algorithm.outputLength;
if (getOptionalByteLength(algorithm.functionName) ||
getOptionalByteLength(algorithm.customization)) {
if (CShakeJob === undefined) {
throw lazyDOMException(
'Non-empty CShakeParams functionName or customization is not supported',
'NotSupportedError');
}

return jobPromise(() => new CShakeJob(
return jobPromise(() => new HashJob(
kCryptoJobWebCrypto,
algorithm.name,
StringPrototypeToLowerCase(algorithm.name),
data,
outputLength,
algorithm.functionName,
algorithm.customization,
outputLength));
algorithm.customization));
}

const bits = jobPromise(() => new HashJob(
return jobPromise(() => new HashJob(
kCryptoJobWebCrypto,
normalizeHashName(algorithm.name),
data,
numBitsToBytes(outputLength) * 8));
if (outputLength % 8 === 0)
return bits;
return jobPromiseThen(bits, (bits) =>
TypedArrayPrototypeGetBuffer(truncateToBitLength(outputLength, bits)));
outputLength));
}
case 'TurboSHAKE128':
// Fall through
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/crypto/hkdf.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const {
normalizeHashName,
toBuf,
validateByteSource,
validateAlgorithm,
} = require('internal/crypto/util');

const {
Expand Down Expand Up @@ -182,6 +183,7 @@ function validateHkdfDeriveBitsLength(length, hash) {
function hkdfDeriveBits(algorithm, baseKey, length) {
const { hash, salt, info } = algorithm;
validateHkdfDeriveBitsLength(length, hash);
validateAlgorithm(algorithm, 'deriveBits');

if (length === 0)
return PromiseResolve(new ArrayBuffer(0));
Expand Down
16 changes: 10 additions & 6 deletions lib/internal/crypto/mac.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const {
numBitsToBytes,
truncateToBitLength,
validateKmacKeyLength,
validateAlgorithm,
} = require('internal/crypto/util');

const {
Expand Down Expand Up @@ -71,11 +72,12 @@ function hmacGenerateKey(algorithm, extractable, usages) {
const {
hash,
name,
length = getBlockSize(hash.name),
} = algorithm;

const usageSet = validateUsagesNotEmpty(
validateKeyUsages(usages, kUsages, name));
const usageSet = validateKeyUsages(usages, kUsages, name);
validateAlgorithm(algorithm, 'generateKey');
const { length = getBlockSize(hash.name) } = algorithm;
validateUsagesNotEmpty(usageSet);

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

const usageSet = validateUsagesNotEmpty(
validateKeyUsages(usages, kUsages, name));
const usageSet = validateKeyUsages(usages, kUsages, name);
validateAlgorithm(algorithm, 'generateKey');
validateUsagesNotEmpty(usageSet);

return jobPromise(() => new SecretKeyGenJob(
kCryptoJobWebCrypto,
Expand All @@ -114,6 +117,7 @@ function macImportKey(
usages,
) {
const isHmac = algorithm.name === 'HMAC';
validateAlgorithm(algorithm, 'importKey');
const usagesSet = validateKeyUsages(
usages, kUsages, algorithm.name);
let handle;
Expand Down Expand Up @@ -181,14 +185,14 @@ function hmacSignVerify(key, data, algorithm, signature) {
}

function kmacSignVerify(key, data, algorithm, signature) {
validateAlgorithm(algorithm, 'sign');
const mode = signature === undefined ? kSignJobModeSign : kSignJobModeVerify;
return jobPromise(() => new KmacJob(
kCryptoJobWebCrypto,
mode,
getCryptoKeyHandle(key),
algorithm.name,
algorithm.customization,
getCryptoKeyAlgorithm(key).length,
algorithm.outputLength,
data,
signature));
Expand Down
3 changes: 3 additions & 0 deletions lib/internal/crypto/ml_dsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const {
getUsagesMask,
jobPromise,
toUsagesSet,
validateAlgorithm,
getBufferSourceByteLength,
} = require('internal/crypto/util');

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

validateAlgorithm(algorithm, mode === kSignJobModeSign ? 'sign' : 'verify');

return jobPromise(() => new SignJob(
kCryptoJobWebCrypto,
mode,
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/crypto/rsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const {
jobPromise,
jobPromiseThen,
normalizeHashName,
validateAlgorithm,
validateMaxBufferLength,
toUsagesSet,
} = require('internal/crypto/util');
Expand Down Expand Up @@ -113,6 +114,7 @@ function rsaKeyGenerate(

const allowedUsages = kUsages[name];
const usagesSet = validateKeyUsages(usages, allowedUsages.keygen, name);
validateAlgorithm(algorithm, 'generateKey');
const publicExponentConverted = bigIntArrayToUnsignedInt(publicExponent);
let firstNonzeroByte = 0;
while (publicExponent[firstNonzeroByte] === 0)
Expand Down
Loading
Loading