@@ -103,20 +103,58 @@ bool HKDFTraits::DeriveBits(
103
103
EVPKeyCtxPointer ctx =
104
104
EVPKeyCtxPointer (EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF, nullptr ));
105
105
if (!ctx || !EVP_PKEY_derive_init (ctx.get ()) ||
106
- !EVP_PKEY_CTX_hkdf_mode (ctx.get (),
107
- EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND) ||
108
106
!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 ()) ||
115
107
!EVP_PKEY_CTX_add1_hkdf_info (
116
108
ctx.get (), params.info .data <unsigned char >(), params.info .size ())) {
117
109
return false ;
118
110
}
119
111
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
+
120
158
size_t length = params.length ;
121
159
ByteSource::Builder buf (length);
122
160
if (EVP_PKEY_derive (ctx.get (), buf.data <unsigned char >(), &length) <= 0 )
0 commit comments