@@ -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