@@ -175,7 +175,102 @@ 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
+ ssize_t key_size = EVP_KDF_CTX_get_kdf_size (hkdf_ctx );
231
+ RESULT_ENSURE (key_size > 0 , S2N_ERR_HKDF_OUTPUT_SIZE );
232
+ RESULT_ENSURE (key_size <= output -> size , S2N_ERR_HKDF_OUTPUT_SIZE );
233
+ output -> size = key_size ;
234
+ }
235
+
236
+ RESULT_GUARD_OSSL (EVP_KDF_derive (hkdf_ctx , output -> data , output -> size , params ),
237
+ S2N_ERR_HKDF );
238
+ return S2N_RESULT_OK ;
239
+ }
240
+
241
+ static int s2n_libcrypto_hkdf_extract (struct s2n_hmac_state * hmac , s2n_hmac_algorithm alg ,
242
+ const struct s2n_blob * salt , const struct s2n_blob * key , struct s2n_blob * pseudo_rand_key )
243
+ {
244
+ struct s2n_blob empty_info = { 0 };
245
+ POSIX_GUARD_RESULT (s2n_hkdf_kdf (hmac , alg , salt , key , & empty_info , pseudo_rand_key ,
246
+ EVP_KDF_HKDF_MODE_EXTRACT_ONLY ));
247
+ return S2N_SUCCESS ;
248
+ }
249
+
250
+ static int s2n_libcrypto_hkdf_expand (struct s2n_hmac_state * hmac , s2n_hmac_algorithm alg ,
251
+ const struct s2n_blob * pseudo_rand_key , const struct s2n_blob * info , struct s2n_blob * output )
252
+ {
253
+ struct s2n_blob empty_salt = { 0 };
254
+ POSIX_GUARD_RESULT (s2n_hkdf_kdf (hmac , alg , & empty_salt , pseudo_rand_key , info , output ,
255
+ EVP_KDF_HKDF_MODE_EXPAND_ONLY ));
256
+ return S2N_SUCCESS ;
257
+ }
258
+
259
+ static int s2n_libcrypto_hkdf (struct s2n_hmac_state * hmac , s2n_hmac_algorithm alg , const struct s2n_blob * salt ,
260
+ const struct s2n_blob * key , const struct s2n_blob * info , struct s2n_blob * output )
261
+ {
262
+ POSIX_GUARD_RESULT (s2n_hkdf_kdf (hmac , alg , salt , key , info , output ,
263
+ EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND ));
264
+ return S2N_SUCCESS ;
265
+ }
266
+
267
+ bool s2n_libcrypto_supports_hkdf ()
268
+ {
269
+ return true;
270
+ }
271
+
178
272
#else
273
+
179
274
static int s2n_libcrypto_hkdf_extract (struct s2n_hmac_state * hmac , s2n_hmac_algorithm alg , const struct s2n_blob * salt ,
180
275
const struct s2n_blob * key , struct s2n_blob * pseudo_rand_key )
181
276
{
@@ -193,6 +288,12 @@ static int s2n_libcrypto_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm al
193
288
{
194
289
POSIX_BAIL (S2N_ERR_UNIMPLEMENTED );
195
290
}
291
+
292
+ bool s2n_libcrypto_supports_hkdf ()
293
+ {
294
+ return false;
295
+ }
296
+
196
297
#endif /* S2N_LIBCRYPTO_SUPPORTS_HKDF */
197
298
198
299
const struct s2n_hkdf_impl s2n_libcrypto_hkdf_impl = {
@@ -290,12 +391,3 @@ int s2n_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s
290
391
291
392
return S2N_SUCCESS ;
292
393
}
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