Skip to content

Commit 1c0d66e

Browse files
panvaruyadorno
authored andcommitted
crypto: allow zero-length IKM in HKDF and in webcrypto PBKDF2
PR-URL: #44201 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
1 parent 07d90c8 commit 1c0d66e

File tree

8 files changed

+164
-2251
lines changed

8 files changed

+164
-2251
lines changed

doc/api/crypto.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -4203,6 +4203,9 @@ web-compatible code use [`crypto.webcrypto.getRandomValues()`][] instead.
42034203
<!-- YAML
42044204
added: v15.0.0
42054205
changes:
4206+
- version: REPLACEME
4207+
pr-url: https://github.com/nodejs/node/pull/44201
4208+
description: The input keying material can now be zero-length.
42064209
- version: v18.0.0
42074210
pr-url: https://github.com/nodejs/node/pull/41678
42084211
description: Passing an invalid callback to the `callback` argument
@@ -4212,7 +4215,7 @@ changes:
42124215

42134216
* `digest` {string} The digest algorithm to use.
42144217
* `ikm` {string|ArrayBuffer|Buffer|TypedArray|DataView|KeyObject} The input
4215-
keying material. It must be at least one byte in length.
4218+
keying material. Must be provided but can be zero-length.
42164219
* `salt` {string|ArrayBuffer|Buffer|TypedArray|DataView} The salt value. Must
42174220
be provided but can be zero-length.
42184221
* `info` {string|ArrayBuffer|Buffer|TypedArray|DataView} Additional info value.
@@ -4262,11 +4265,15 @@ hkdf('sha512', 'key', 'salt', 'info', 64, (err, derivedKey) => {
42624265

42634266
<!-- YAML
42644267
added: v15.0.0
4268+
changes:
4269+
- version: REPLACEME
4270+
pr-url: https://github.com/nodejs/node/pull/44201
4271+
description: The input keying material can now be zero-length.
42654272
-->
42664273

42674274
* `digest` {string} The digest algorithm to use.
42684275
* `ikm` {string|ArrayBuffer|Buffer|TypedArray|DataView|KeyObject} The input
4269-
keying material. It must be at least one byte in length.
4276+
keying material. Must be provided but can be zero-length.
42704277
* `salt` {string|ArrayBuffer|Buffer|TypedArray|DataView} The salt value. Must
42714278
be provided but can be zero-length.
42724279
* `info` {string|ArrayBuffer|Buffer|TypedArray|DataView} Additional info value.

lib/internal/crypto/hkdf.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
const {
44
FunctionPrototypeCall,
55
Promise,
6-
Uint8Array,
76
} = primordials;
87

98
const {
@@ -80,9 +79,8 @@ function prepareKey(key) {
8079
if (isKeyObject(key))
8180
return key;
8281

83-
// TODO(@jasnell): createSecretKey should allow using an ArrayBuffer
8482
if (isAnyArrayBuffer(key))
85-
return createSecretKey(new Uint8Array(key));
83+
return createSecretKey(key);
8684

8785
key = toBuf(key);
8886

lib/internal/crypto/webcrypto.js

-3
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,6 @@ async function importGenericSecretKey(
494494

495495
const checkLength = keyData.byteLength * 8;
496496

497-
if (checkLength === 0 || length === 0)
498-
throw lazyDOMException('Zero-length key is not supported', 'DataError');
499-
500497
// The Web Crypto spec allows for key lengths that are not multiples of
501498
// 8. We don't. Our check here is stricter than that defined by the spec
502499
// in that we require that algorithm.length match keyData.length * 8 if

src/crypto/crypto_hkdf.cc

+46-8
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,58 @@ bool HKDFTraits::DeriveBits(
103103
EVPKeyCtxPointer ctx =
104104
EVPKeyCtxPointer(EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr));
105105
if (!ctx || !EVP_PKEY_derive_init(ctx.get()) ||
106-
!EVP_PKEY_CTX_hkdf_mode(ctx.get(),
107-
EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) ||
108106
!EVP_PKEY_CTX_set_hkdf_md(ctx.get(), params.digest) ||
109-
!EVP_PKEY_CTX_set1_hkdf_salt(
110-
ctx.get(), params.salt.data<unsigned char>(), params.salt.size()) ||
111-
!EVP_PKEY_CTX_set1_hkdf_key(
112-
ctx.get(),
113-
reinterpret_cast<const unsigned char*>(params.key->GetSymmetricKey()),
114-
params.key->GetSymmetricKeySize()) ||
115107
!EVP_PKEY_CTX_add1_hkdf_info(
116108
ctx.get(), params.info.data<unsigned char>(), params.info.size())) {
117109
return false;
118110
}
119111

112+
// TODO(panva): Once support for OpenSSL 1.1.1 is dropped the whole
113+
// of HKDFTraits::DeriveBits can be refactored to use
114+
// EVP_KDF which does handle zero length key.
115+
if (params.key->GetSymmetricKeySize() != 0) {
116+
if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(),
117+
EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) ||
118+
!EVP_PKEY_CTX_set1_hkdf_salt(
119+
ctx.get(), params.salt.data<unsigned char>(), params.salt.size()) ||
120+
!EVP_PKEY_CTX_set1_hkdf_key(ctx.get(),
121+
reinterpret_cast<const unsigned char*>(
122+
params.key->GetSymmetricKey()),
123+
params.key->GetSymmetricKeySize())) {
124+
return false;
125+
}
126+
} else {
127+
// Workaround for EVP_PKEY_derive HKDF not handling zero length keys.
128+
unsigned char temp_key[EVP_MAX_MD_SIZE];
129+
unsigned int len = sizeof(temp_key);
130+
if (params.salt.size() != 0) {
131+
if (HMAC(params.digest,
132+
params.salt.data(),
133+
params.salt.size(),
134+
nullptr,
135+
0,
136+
temp_key,
137+
&len) == nullptr) {
138+
return false;
139+
}
140+
} else {
141+
char salt[EVP_MAX_MD_SIZE] = {0};
142+
if (HMAC(params.digest,
143+
salt,
144+
EVP_MD_size(params.digest),
145+
nullptr,
146+
0,
147+
temp_key,
148+
&len) == nullptr) {
149+
return false;
150+
}
151+
}
152+
if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(), EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) ||
153+
!EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), temp_key, len)) {
154+
return false;
155+
}
156+
}
157+
120158
size_t length = params.length;
121159
ByteSource::Builder buf(length);
122160
if (EVP_PKEY_derive(ctx.get(), buf.data<unsigned char>(), &length) <= 0)

test/parallel/test-crypto-hkdf.js

+2
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ const {
120120

121121
const algorithms = [
122122
['sha256', 'secret', 'salt', 'info', 10],
123+
['sha256', '', '', '', 10],
124+
['sha256', '', 'salt', '', 10],
123125
['sha512', 'secret', 'salt', '', 15],
124126
];
125127
if (!common.hasOpenSSL3)

test/parallel/test-webcrypto-derivebits-hkdf.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const kDerivedKeys = {
3131
short: '5040737377307264',
3232
long: '55736572732073686f756c64207069636b206c6f6e6720706173737068726' +
3333
'173657320286e6f74207573652073686f72742070617373776f7264732921',
34-
// empty: ''
34+
empty: ''
3535
};
3636

3737
const kSalts = {

test/pummel/test-webcrypto-derivebits-pbkdf2.js

+105-106
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ const kPasswords = {
3737
long: '55736572732073686f756c64207069636b206c6f6' +
3838
'e6720706173737068726173657320286e6f742075' +
3939
'73652073686f72742070617373776f7264732921',
40-
// TODO(@jasnell): Zero-length password not currently supported
41-
// empty: ''
40+
empty: ''
4241
};
4342

4443
const kSalts = {
@@ -256,110 +255,110 @@ const kDerivations = {
256255
}
257256
}
258257
},
259-
// empty: {
260-
// short: {
261-
// 'SHA-384': {
262-
// '1': 'e9f0da1e97dfa455f858ce6b9af1ecc0299' +
263-
// 'f125ff1a847eb5d4955866f43e604',
264-
// '1000': '7ff7954aeddf41795fc8300666786d49' +
265-
// '74269aa91cc7e93811c953331d56d609',
266-
// '100000': '1c73132b6a55e9d9de2cdbfe1f55bf' +
267-
// '0ab59fd91f78f109c50096038b8557b147'
268-
// },
269-
// 'SHA-512': {
270-
// '1': 'e7e2b41f4887421bcb764eb4a56f63d2502' +
271-
// 'e33c764fbdf60626ad42ed9672342',
272-
// '1000': 'd561c4c84e9c60ba4752a2d383bf55ef' +
273-
// 'f643fc9e452252d6821e39449350cf72',
274-
// '100000': 'efd00752bc9ffafb5a399dd1d5834e' +
275-
// '8d2c2b676ecd4b2063fb1fe581d0f1380b'
276-
// },
277-
// 'SHA-1': {
278-
// '1': 'a667da47b8f857b7c65f70a6c8e7a06ce0d' +
279-
// '25211a2b6ebaf58dcaaf268b46b1d',
280-
// '1000': '72c92bbd3ddab4789e88e42ad1cda83c' +
281-
// 'c0729e6cb5106a577e50d5cf61782481',
282-
// '100000': '06e19e1b83e6480b1554df2b31a2c9' +
283-
// '2d1bfcf9bc1bdbc8751ff8685bdeef7dc9'
284-
// },
285-
// 'SHA-256': {
286-
// '1': '2ddb49243eb3b5912cb260cdd87fb04ef0d' +
287-
// '111bfa44d40a45e02a8a5c3c1518d',
288-
// '1000': '2835f3ed53565420c90951509b0c1173' +
289-
// 'b645174f1546ab3ac3e6c85cb471b53b',
290-
// '100000': '80aed905ca32ae0bb2a9d8f532f048' +
291-
// 'a0e672463eef9f83dfa7d88bca726553ea'
292-
// }
293-
// },
294-
// long: {
295-
// 'SHA-384': {
296-
// '1': '7b0bcca81dd637a3b3398666619716c5f2b1' +
297-
// 'f4a5c24e85c18a9955559e4d7692',
298-
// '1000': '8bb89cf71972fe5acc16fdc5f8cffd2c2' +
299-
// 'e7178c086b3bbe61cc1314619135958',
300-
// '100000': '26c6a8ae4bd1fbe715ae478efff3eca' +
301-
// 'e83afa617ed35bd4a3f63c3da76a42d22'
302-
// },
303-
// 'SHA-512': {
304-
// '1': 'bb73f8168a8f391d3d54ca892fb72b8e603' +
305-
// '5e37f891e5a70491b94dc05510bc4',
306-
// '1000': '5cacc16cdfbe052cfd73a9891b8c0e78' +
307-
// 'b19b2e07eae2423d48fed5e08aa8494b',
308-
// '100000': '87fdfc293392cbf33ecc9b5141a2fe' +
309-
// 'fa74d150499756863c484c0a78b6274d7f'
310-
// },
311-
// 'SHA-1': {
312-
// '1': '1f46b40cf2fb3dc41a3d9ced8897b861050' +
313-
// '36810e2bfac7040814bd65d428d67',
314-
// '1000': 'cc5748ecc41288a0e13368543aaa2ef6' +
315-
// '2c97ba7518fa88f6e11c35763fc930b4',
316-
// '100000': '33e2993bf4729dc993fff66e69cc55' +
317-
// '777135ebfabce533575bce4a96645a742c'
318-
// },
319-
// 'SHA-256': {
320-
// '1': '61c935c462c3321c89663545d13a4f6b52b' +
321-
// '5191cfb7479e58dcfe6444d43106c',
322-
// '1000': '1353f7458237ab332ee052e29f829a2a' +
323-
// 'b90e72630ea10493b4eecffb9ff89e1d',
324-
// '100000': '79baf80ec582920538801e9d929ce0' +
325-
// '7084277987488d733a026852c452f06fb4'
326-
// }
327-
// },
328-
// empty: {
329-
// 'SHA-384': {
330-
// '1': '4bb042a5c28cee6f66f991c717fd7702677' +
331-
// '87e2bb3031eae270d87d63ad99534',
332-
// '1000': '9cbfe72d194da34e17c821dd1569ef50' +
333-
// 'a86eb4d893591776adc6a5c21e0031cf',
334-
// '100000': 'ed6bd7282567abe48d542d067d09f4' +
335-
// '04bd044ae2cefe11dacc531c4764cd35cd'
336-
// },
337-
// 'SHA-512': {
338-
// '1': '6d2ecbbbfb2e6dcd7056faf9af6aa06eae5' +
339-
// '94391db983279a6bf27e0eb228614',
340-
// '1000': 'cb93096c3a02beeb1c5fac36765c9011' +
341-
// 'fe99f8d8ea62366048fc98cb98dfea8f',
342-
// '100000': '89e16254ebad5cba72e0aebe1614c7' +
343-
// 'f9b795a7505f2637206ce10a3449a2b8bb'
344-
// },
345-
// 'SHA-1': {
346-
// '1': '1e437a1c79d75be61e91141dae20affc489' +
347-
// '2cc99abcc3fe753887bccc8920176',
348-
// '1000': '6e40910ac02ec89cebb9d898b13a09d1' +
349-
// 'cd7adf6f8cc08cc473302c8973aa2e19',
350-
// '100000': 'a9e1bebb36bc26d7c997d5483cbc8d' +
351-
// 'e4a419d1e706571342632586ec330a7290'
352-
// },
353-
// 'SHA-256': {
354-
// '1': 'f7ce0b653d2d72a4108cf5abe912ffdd777' +
355-
// '616dbbb27a70e8204f3ae2d0f6fad',
356-
// '1000': '4fc58a21c100ce1835b8f9991d738b56' +
357-
// '965d14b24e1761fbdffc69ac5e0b667a',
358-
// '100000': '64a868d4b23af696d3734d0b814d04' +
359-
// 'cdd1ac280128e97653a05f32b49c13a29a'
360-
// }
361-
// }
362-
// }
258+
empty: {
259+
short: {
260+
'SHA-384': {
261+
'1': 'e9f0da1e97dfa455f858ce6b9af1ecc0299' +
262+
'f125ff1a847eb5d4955866f43e604',
263+
'1000': '7ff7954aeddf41795fc8300666786d49' +
264+
'74269aa91cc7e93811c953331d56d609',
265+
'100000': '1c73132b6a55e9d9de2cdbfe1f55bf' +
266+
'0ab59fd91f78f109c50096038b8557b147'
267+
},
268+
'SHA-512': {
269+
'1': 'e7e2b41f4887421bcb764eb4a56f63d2502' +
270+
'e33c764fbdf60626ad42ed9672342',
271+
'1000': 'd561c4c84e9c60ba4752a2d383bf55ef' +
272+
'f643fc9e452252d6821e39449350cf72',
273+
'100000': 'efd00752bc9ffafb5a399dd1d5834e' +
274+
'8d2c2b676ecd4b2063fb1fe581d0f1380b'
275+
},
276+
'SHA-1': {
277+
'1': 'a667da47b8f857b7c65f70a6c8e7a06ce0d' +
278+
'25211a2b6ebaf58dcaaf268b46b1d',
279+
'1000': '72c92bbd3ddab4789e88e42ad1cda83c' +
280+
'c0729e6cb5106a577e50d5cf61782481',
281+
'100000': '06e19e1b83e6480b1554df2b31a2c9' +
282+
'2d1bfcf9bc1bdbc8751ff8685bdeef7dc9'
283+
},
284+
'SHA-256': {
285+
'1': '2ddb49243eb3b5912cb260cdd87fb04ef0d' +
286+
'111bfa44d40a45e02a8a5c3c1518d',
287+
'1000': '2835f3ed53565420c90951509b0c1173' +
288+
'b645174f1546ab3ac3e6c85cb471b53b',
289+
'100000': '80aed905ca32ae0bb2a9d8f532f048' +
290+
'a0e672463eef9f83dfa7d88bca726553ea'
291+
}
292+
},
293+
long: {
294+
'SHA-384': {
295+
'1': '7b0bcca81dd637a3b3398666619716c5f2b1' +
296+
'f4a5c24e85c18a9955559e4d7692',
297+
'1000': '8bb89cf71972fe5acc16fdc5f8cffd2c2' +
298+
'e7178c086b3bbe61cc1314619135958',
299+
'100000': '26c6a8ae4bd1fbe715ae478efff3eca' +
300+
'e83afa617ed35bd4a3f63c3da76a42d22'
301+
},
302+
'SHA-512': {
303+
'1': 'bb73f8168a8f391d3d54ca892fb72b8e603' +
304+
'5e37f891e5a70491b94dc05510bc4',
305+
'1000': '5cacc16cdfbe052cfd73a9891b8c0e78' +
306+
'b19b2e07eae2423d48fed5e08aa8494b',
307+
'100000': '87fdfc293392cbf33ecc9b5141a2fe' +
308+
'fa74d150499756863c484c0a78b6274d7f'
309+
},
310+
'SHA-1': {
311+
'1': '1f46b40cf2fb3dc41a3d9ced8897b861050' +
312+
'36810e2bfac7040814bd65d428d67',
313+
'1000': 'cc5748ecc41288a0e13368543aaa2ef6' +
314+
'2c97ba7518fa88f6e11c35763fc930b4',
315+
'100000': '33e2993bf4729dc993fff66e69cc55' +
316+
'777135ebfabce533575bce4a96645a742c'
317+
},
318+
'SHA-256': {
319+
'1': '61c935c462c3321c89663545d13a4f6b52b' +
320+
'5191cfb7479e58dcfe6444d43106c',
321+
'1000': '1353f7458237ab332ee052e29f829a2a' +
322+
'b90e72630ea10493b4eecffb9ff89e1d',
323+
'100000': '79baf80ec582920538801e9d929ce0' +
324+
'7084277987488d733a026852c452f06fb4'
325+
}
326+
},
327+
empty: {
328+
'SHA-384': {
329+
'1': '4bb042a5c28cee6f66f991c717fd7702677' +
330+
'87e2bb3031eae270d87d63ad99534',
331+
'1000': '9cbfe72d194da34e17c821dd1569ef50' +
332+
'a86eb4d893591776adc6a5c21e0031cf',
333+
'100000': 'ed6bd7282567abe48d542d067d09f4' +
334+
'04bd044ae2cefe11dacc531c4764cd35cd'
335+
},
336+
'SHA-512': {
337+
'1': '6d2ecbbbfb2e6dcd7056faf9af6aa06eae5' +
338+
'94391db983279a6bf27e0eb228614',
339+
'1000': 'cb93096c3a02beeb1c5fac36765c9011' +
340+
'fe99f8d8ea62366048fc98cb98dfea8f',
341+
'100000': '89e16254ebad5cba72e0aebe1614c7' +
342+
'f9b795a7505f2637206ce10a3449a2b8bb'
343+
},
344+
'SHA-1': {
345+
'1': '1e437a1c79d75be61e91141dae20affc489' +
346+
'2cc99abcc3fe753887bccc8920176',
347+
'1000': '6e40910ac02ec89cebb9d898b13a09d1' +
348+
'cd7adf6f8cc08cc473302c8973aa2e19',
349+
'100000': 'a9e1bebb36bc26d7c997d5483cbc8d' +
350+
'e4a419d1e706571342632586ec330a7290'
351+
},
352+
'SHA-256': {
353+
'1': 'f7ce0b653d2d72a4108cf5abe912ffdd777' +
354+
'616dbbb27a70e8204f3ae2d0f6fad',
355+
'1000': '4fc58a21c100ce1835b8f9991d738b56' +
356+
'965d14b24e1761fbdffc69ac5e0b667a',
357+
'100000': '64a868d4b23af696d3734d0b814d04' +
358+
'cdd1ac280128e97653a05f32b49c13a29a'
359+
}
360+
}
361+
}
363362
};
364363

365364
async function setupBaseKeys() {

0 commit comments

Comments
 (0)