@@ -175,7 +175,101 @@ static int s2n_libcrypto_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm al
175
175
176
176
return S2N_SUCCESS ;
177
177
}
178
+
179
+ bool s2n_libcrypto_supports_hkdf ()
180
+ {
181
+ return true;
182
+ }
183
+
184
+ #elif S2N_OPENSSL_VERSION_AT_LEAST (3 , 0 , 0 )
185
+
186
+ #include "crypto/s2n_kdf.h"
187
+
188
+ static S2N_RESULT s2n_hkdf_kdf (struct s2n_hmac_state * hmac , s2n_hmac_algorithm alg ,
189
+ const struct s2n_blob * salt , const struct s2n_blob * key , const struct s2n_blob * info ,
190
+ struct s2n_blob * output , int mode )
191
+ {
192
+ /* As an optimization, we should be able to fetch and cache this EVP_KDF*
193
+ * once when s2n_init is called.
194
+ */
195
+ DEFER_CLEANUP (EVP_KDF * hkdf_impl = EVP_KDF_fetch (NULL , "HKDF" , NULL ),
196
+ EVP_KDF_free_pointer );
197
+ RESULT_ENSURE (hkdf_impl , S2N_ERR_PRF_INVALID_ALGORITHM );
198
+
199
+ DEFER_CLEANUP (EVP_KDF_CTX * hkdf_ctx = EVP_KDF_CTX_new (hkdf_impl ),
200
+ EVP_KDF_CTX_free_pointer );
201
+ RESULT_ENSURE_REF (hkdf_ctx );
202
+
203
+ const EVP_MD * digest = NULL ;
204
+ RESULT_GUARD (s2n_hmac_md_from_alg (alg , & digest ));
205
+ RESULT_ENSURE_REF (digest );
206
+ const char * digest_name = EVP_MD_get0_name (digest );
207
+ RESULT_ENSURE_REF (digest_name );
208
+
209
+ OSSL_PARAM params [] = {
210
+ S2N_OSSL_PARAM_INT (OSSL_KDF_PARAM_MODE , mode ),
211
+ S2N_OSSL_PARAM_BLOB (OSSL_KDF_PARAM_KEY , key ),
212
+ S2N_OSSL_PARAM_BLOB (OSSL_KDF_PARAM_INFO , info ),
213
+ S2N_OSSL_PARAM_BLOB (OSSL_KDF_PARAM_SALT , salt ),
214
+ /* Casting away the const is safe because providers are forbidden from
215
+ * modifying any OSSL_PARAM value other than return_size.
216
+ * Even the examples in the Openssl documentation cast const strings to
217
+ * non-const void pointers when setting up OSSL_PARAMs.
218
+ */
219
+ S2N_OSSL_PARAM_STR (OSSL_KDF_PARAM_DIGEST , (void * ) (uintptr_t ) digest_name ),
220
+ OSSL_PARAM_END ,
221
+ };
222
+
223
+ /* From the HKDF docs (https://docs.openssl.org/3.1/man7/EVP_KDF-HKDF/):
224
+ * > When using EVP_KDF_HKDF_MODE_EXTRACT_ONLY the keylen parameter must equal
225
+ * > the size of the intermediate fixed-length pseudorandom key otherwise an
226
+ * > error will occur.
227
+ */
228
+ if (mode == EVP_KDF_HKDF_MODE_EXTRACT_ONLY ) {
229
+ RESULT_GUARD_OSSL (EVP_KDF_CTX_set_params (hkdf_ctx , params ), S2N_ERR_HKDF );
230
+ size_t key_size = EVP_KDF_CTX_get_kdf_size (hkdf_ctx );
231
+ RESULT_ENSURE (key_size <= output -> size , S2N_ERR_HKDF_OUTPUT_SIZE );
232
+ output -> size = key_size ;
233
+ }
234
+
235
+ RESULT_GUARD_OSSL (EVP_KDF_derive (hkdf_ctx , output -> data , output -> size , params ),
236
+ S2N_ERR_HKDF );
237
+ return S2N_RESULT_OK ;
238
+ }
239
+
240
+ static int s2n_libcrypto_hkdf_extract (struct s2n_hmac_state * hmac , s2n_hmac_algorithm alg ,
241
+ const struct s2n_blob * salt , const struct s2n_blob * key , struct s2n_blob * pseudo_rand_key )
242
+ {
243
+ struct s2n_blob empty_info = { 0 };
244
+ POSIX_GUARD_RESULT (s2n_hkdf_kdf (hmac , alg , salt , key , & empty_info , pseudo_rand_key ,
245
+ EVP_KDF_HKDF_MODE_EXTRACT_ONLY ));
246
+ return S2N_SUCCESS ;
247
+ }
248
+
249
+ static int s2n_libcrypto_hkdf_expand (struct s2n_hmac_state * hmac , s2n_hmac_algorithm alg ,
250
+ const struct s2n_blob * pseudo_rand_key , const struct s2n_blob * info , struct s2n_blob * output )
251
+ {
252
+ struct s2n_blob empty_salt = { 0 };
253
+ POSIX_GUARD_RESULT (s2n_hkdf_kdf (hmac , alg , & empty_salt , pseudo_rand_key , info , output ,
254
+ EVP_KDF_HKDF_MODE_EXPAND_ONLY ));
255
+ return S2N_SUCCESS ;
256
+ }
257
+
258
+ static int s2n_libcrypto_hkdf (struct s2n_hmac_state * hmac , s2n_hmac_algorithm alg , const struct s2n_blob * salt ,
259
+ const struct s2n_blob * key , const struct s2n_blob * info , struct s2n_blob * output )
260
+ {
261
+ POSIX_GUARD_RESULT (s2n_hkdf_kdf (hmac , alg , salt , key , info , output ,
262
+ EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND ));
263
+ return S2N_SUCCESS ;
264
+ }
265
+
266
+ bool s2n_libcrypto_supports_hkdf ()
267
+ {
268
+ return true;
269
+ }
270
+
178
271
#else
272
+
179
273
static int s2n_libcrypto_hkdf_extract (struct s2n_hmac_state * hmac , s2n_hmac_algorithm alg , const struct s2n_blob * salt ,
180
274
const struct s2n_blob * key , struct s2n_blob * pseudo_rand_key )
181
275
{
@@ -193,6 +287,12 @@ static int s2n_libcrypto_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm al
193
287
{
194
288
POSIX_BAIL (S2N_ERR_UNIMPLEMENTED );
195
289
}
290
+
291
+ bool s2n_libcrypto_supports_hkdf ()
292
+ {
293
+ return false;
294
+ }
295
+
196
296
#endif /* S2N_LIBCRYPTO_SUPPORTS_HKDF */
197
297
198
298
const struct s2n_hkdf_impl s2n_libcrypto_hkdf_impl = {
@@ -290,12 +390,3 @@ int s2n_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s
290
390
291
391
return S2N_SUCCESS ;
292
392
}
293
-
294
- bool s2n_libcrypto_supports_hkdf ()
295
- {
296
- #ifdef S2N_LIBCRYPTO_SUPPORTS_HKDF
297
- return true;
298
- #else
299
- return false;
300
- #endif
301
- }
0 commit comments