Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTobias Nießen <tniessen@tnie.de>2022-08-25 19:36:08 +0300
committerGitHub <noreply@github.com>2022-08-25 19:36:08 +0300
commit4d49d6507e33c8f01de96488e9be6fdaee059d55 (patch)
tree404c658f41827f0a3f8b84255e9fc87244af8eda /src
parentbb4dff783ddb3b20c67041f7ccef796c335c2407 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/crypto/crypto_hkdf.cc66
1 files changed, 26 insertions, 40 deletions
diff --git a/src/crypto/crypto_hkdf.cc b/src/crypto/crypto_hkdf.cc
index bff8cc60c4c..081a930e69f 100644
--- a/src/crypto/crypto_hkdf.cc
+++ b/src/crypto/crypto_hkdf.cc
@@ -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;