Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto: remove webcrypto HKDF and PBKDF2 default-applied lengths #44945

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 19 additions & 27 deletions lib/internal/crypto/hkdf.js
Expand Up @@ -2,7 +2,6 @@

const {
FunctionPrototypeCall,
Promise,
} = primordials;

const {
Expand All @@ -15,7 +14,6 @@ const {
validateFunction,
validateInteger,
validateString,
validateUint32,
} = require('internal/validators');

const { kMaxLength } = require('buffer');
Expand All @@ -35,6 +33,7 @@ const {

const {
lazyDOMException,
promisify,
} = require('internal/util');

const {
Expand Down Expand Up @@ -139,40 +138,33 @@ function hkdfSync(hash, key, salt, info, length) {
return bits;
}

const hkdfPromise = promisify(hkdf);
async function hkdfDeriveBits(algorithm, baseKey, length) {
const { hash } = algorithm;
const salt = getArrayBufferOrView(algorithm.salt, 'algorithm.salt');
const info = getArrayBufferOrView(algorithm.info, 'algorithm.info');
if (hash === undefined)
throw new ERR_MISSING_OPTION('algorithm.hash');

let byteLength = 512 / 8;
if (length !== undefined) {
if (length === 0)
throw lazyDOMException('length cannot be zero', 'OperationError');
if (length === null)
throw lazyDOMException('length cannot be null', 'OperationError');
validateUint32(length, 'length');
if (length % 8) {
throw lazyDOMException(
'length must be a multiple of 8',
'OperationError');
}
byteLength = length / 8;
if (length === 0)
throw lazyDOMException('length cannot be zero', 'OperationError');
if (length === null)
throw lazyDOMException('length cannot be null', 'OperationError');
if (length % 8) {
throw lazyDOMException(
'length must be a multiple of 8',
'OperationError');
}

return new Promise((resolve, reject) => {
hkdf(
normalizeHashName(hash.name),
baseKey[kKeyObject],
salt,
info,
byteLength,
(err, bits) => {
if (err) return reject(err);
resolve(bits);
});
});
try {
return await hkdfPromise(
normalizeHashName(hash.name), baseKey[kKeyObject], salt, info, length / 8,
);
} catch (err) {
throw lazyDOMException(
'The operation failed for an operation-specific reason',
{ name: 'OperationError', cause: err });
}
}

module.exports = {
Expand Down
41 changes: 20 additions & 21 deletions lib/internal/crypto/pbkdf2.js
Expand Up @@ -2,7 +2,6 @@

const {
FunctionPrototypeCall,
Promise,
} = primordials;

const { Buffer } = require('buffer');
Expand All @@ -18,7 +17,6 @@ const {
validateInt32,
validateInteger,
validateString,
validateUint32,
} = require('internal/validators');

const { ERR_MISSING_OPTION } = require('internal/errors').codes;
Expand All @@ -32,6 +30,7 @@ const {

const {
lazyDOMException,
promisify,
} = require('internal/util');

function pbkdf2(password, salt, iterations, keylen, digest, callback) {
Expand Down Expand Up @@ -100,6 +99,7 @@ function check(password, salt, iterations, keylen, digest) {
return { password, salt, iterations, keylen, digest };
}

const pbkdf2Promise = promisify(pbkdf2);
async function pbkdf2DeriveBits(algorithm, baseKey, length) {
const { iterations } = algorithm;
let { hash } = algorithm;
Expand All @@ -116,27 +116,26 @@ async function pbkdf2DeriveBits(algorithm, baseKey, length) {

const raw = baseKey[kKeyObject].export();

let byteLength = 64; // the default
if (length !== undefined) {
if (length === 0)
throw lazyDOMException('length cannot be zero', 'OperationError');
if (length === null)
throw lazyDOMException('length cannot be null', 'OperationError');
validateUint32(length, 'length');
if (length % 8) {
throw lazyDOMException(
'length must be a multiple of 8',
'OperationError');
}
byteLength = length / 8;
if (length === 0)
throw lazyDOMException('length cannot be zero', 'OperationError');
if (length === null)
throw lazyDOMException('length cannot be null', 'OperationError');
if (length % 8) {
throw lazyDOMException(
'length must be a multiple of 8',
'OperationError');
}

let result;
try {
result = await pbkdf2Promise(raw, salt, iterations, length / 8, hash);
Comment on lines +129 to +131
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let result;
try {
result = await pbkdf2Promise(raw, salt, iterations, length / 8, hash);
try {
const { buffer } = await pbkdf2Promise(raw, salt, iterations, length / 8, hash);
return buffer;

} catch (err) {
throw lazyDOMException(
'The operation failed for an operation-specific reason',
{ name: 'OperationError', cause: err });
}

return new Promise((resolve, reject) => {
pbkdf2(raw, salt, iterations, byteLength, hash, (err, result) => {
if (err) return reject(err);
resolve(result.buffer);
});
});
return result.buffer;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return result.buffer;

}

module.exports = {
Expand Down
4 changes: 4 additions & 0 deletions test/parallel/test-webcrypto-derivebits-hkdf.js
Expand Up @@ -257,6 +257,10 @@ async function testDeriveBitsBadLengths(
};

return Promise.all([
assert.rejects(
subtle.deriveBits(algorithm, baseKeys[size], undefined), {
name: 'OperationError',
}),
assert.rejects(
subtle.deriveBits(algorithm, baseKeys[size], 0), {
message: /length cannot be zero/,
Expand Down
4 changes: 4 additions & 0 deletions test/pummel/test-webcrypto-derivebits-pbkdf2.js
Expand Up @@ -445,6 +445,10 @@ async function testDeriveBitsBadLengths(
};

return Promise.all([
assert.rejects(
subtle.deriveBits(algorithm, baseKeys[size], undefined), {
name: 'OperationError',
}),
assert.rejects(
subtle.deriveBits(algorithm, baseKeys[size], 0), {
message: /length cannot be zero/,
Expand Down