@@ -112,47 +112,33 @@ bool HKDFTraits::DeriveBits(
112112 // TODO(panva): Once support for OpenSSL 1.1.1 is dropped the whole
113113 // of HKDFTraits::DeriveBits can be refactored to use
114114 // 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- }
115+
116+ std::string_view salt;
117+ if (params.salt.size() != 0) {
118+ salt = {params.salt.data<char>(), params.salt.size()};
126119 } 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- }
120+ static const char default_salt[EVP_MAX_MD_SIZE] = {0};
121+ salt = {default_salt, static_cast<unsigned>(EVP_MD_size(params.digest))};
122+ }
123+
124+ // We do not use EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND and instead implement
125+ // the extraction step ourselves because EVP_PKEY_derive does not handle
126+ // zero-length keys, which are required for Web Crypto.
127+ unsigned char pseudorandom_key[EVP_MAX_MD_SIZE];
128+ unsigned int prk_len = sizeof(pseudorandom_key);
129+ if (HMAC(
130+ params.digest,
131+ salt.data(),
132+ salt.size(),
133+ reinterpret_cast<const unsigned char*>(params.key->GetSymmetricKey()),
134+ params.key->GetSymmetricKeySize(),
135+ pseudorandom_key,
136+ &prk_len) == nullptr) {
137+ return false;
138+ }
139+ if (!EVP_PKEY_CTX_hkdf_mode(ctx.get(), EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) ||
140+ !EVP_PKEY_CTX_set1_hkdf_key(ctx.get(), pseudorandom_key, prk_len)) {
141+ return false;
156142 }
157143
158144 size_t length = params.length;
0 commit comments