mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
crypto: simplify control flow in HKDF
Unify the implementation and perform the same OpenSSL calls regardless of whether the key and/or salt are empty. This simplifies the code and improves coverage. Refs: https://github.com/nodejs/node/pull/44201 PR-URL: https://github.com/nodejs/node/pull/44272 Reviewed-By: Filip Skokan <panva.ip@gmail.com>
This commit is contained in:
1 parent
bb4dff783d
commit
4d49d6507e
1 file changed
+26
-40
+26
-40
@@ -112,47 +112,33 @@ bool HKDFTraits::DeriveBits(
|
||||
// TODO(panva): Once support for OpenSSL 1.1.1 is dropped the whole
|
||||
// of HKDFTraits::DeriveBits can be refactored to use
|
||||
// EVP_KDF which does handle zero length key.
|
||||
if (params.key->GetSymmetricKeySize() != 0) {
|
||||
if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(),
|
||||
EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) ||
|
||||
!EVP_PKEY_CTX_set1_hkdf_salt(
|
||||
ctx.get(), params.salt.data<unsigned char>(), params.salt.size()) ||
|
||||
!EVP_PKEY_CTX_set1_hkdf_key(ctx.get(),
|
||||
reinterpret_cast<const unsigned char*>(
|
||||
params.key->GetSymmetricKey()),
|
||||
params.key->GetSymmetricKeySize())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string_view salt;
|
||||
if (params.salt.size() != 0) {
|
||||
salt = {params.salt.data<char>(), params.salt.size()};
|
||||
} else {
|
||||
// Workaround for EVP_PKEY_derive HKDF not handling zero length keys.
|
||||
unsigned char temp_key[EVP_MAX_MD_SIZE];
|
||||
unsigned int len = sizeof(temp_key);
|
||||
if (params.salt.size() != 0) {
|
||||
if (HMAC(params.digest,
|
||||
params.salt.data(),
|
||||
params.salt.size(),
|
||||
nullptr,
|
||||
0,
|
||||
temp_key,
|
||||
&len) == nullptr) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
char salt[EVP_MAX_MD_SIZE] = {0};
|
||||
if (HMAC(params.digest,
|
||||
salt,
|
||||
EVP_MD_size(params.digest),
|
||||
nullptr,
|
||||
0,
|
||||
temp_key,
|
||||
&len) == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(), EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) ||
|
||||
!EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), temp_key, len)) {
|
||||
return false;
|
||||
}
|
||||
static const char default_salt[EVP_MAX_MD_SIZE] = {0};
|
||||
salt = {default_salt, static_cast<unsigned>(EVP_MD_size(params.digest))};
|
||||
}
|
||||
|
||||
// We do not use EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND and instead implement
|
||||
// the extraction step ourselves because EVP_PKEY_derive does not handle
|
||||
// zero-length keys, which are required for Web Crypto.
|
||||
unsigned char pseudorandom_key[EVP_MAX_MD_SIZE];
|
||||
unsigned int prk_len = sizeof(pseudorandom_key);
|
||||
if (HMAC(
|
||||
params.digest,
|
||||
salt.data(),
|
||||
salt.size(),
|
||||
reinterpret_cast<const unsigned char*>(params.key->GetSymmetricKey()),
|
||||
params.key->GetSymmetricKeySize(),
|
||||
pseudorandom_key,
|
||||
&prk_len) == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(), EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) ||
|
||||
!EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), pseudorandom_key, prk_len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t length = params.length;
|
||||
|
||||
Reference in new issue
Block a user