40
40
#define S2N_LIBCRYPTO_SUPPORTS_TLS_PRF 0
41
41
#endif
42
42
43
- /* The s2n p_hash implementation is abstracted to allow for separate implementations, using
44
- * either s2n's formally verified HMAC or OpenSSL's EVP HMAC, for use by the TLS PRF. */
43
+ /* The s2n p_hash implementation is abstracted to allow for separate implementations.
44
+ * Currently the only implementation uses s2n-tls's custom HMAC implementation.
45
+ */
45
46
struct s2n_p_hash_hmac {
46
47
int (* alloc )(struct s2n_prf_working_space * ws );
47
48
int (* init )(struct s2n_prf_working_space * ws , s2n_hmac_algorithm alg , struct s2n_blob * secret );
@@ -194,175 +195,9 @@ static int s2n_prf_sslv3(struct s2n_connection *conn, struct s2n_blob *secret, s
194
195
return 0 ;
195
196
}
196
197
197
- #if !defined(OPENSSL_IS_BORINGSSL ) && !defined(OPENSSL_IS_AWSLC )
198
- static int s2n_evp_pkey_p_hash_alloc (struct s2n_prf_working_space * ws )
199
- {
200
- POSIX_ENSURE_REF (ws -> p_hash .evp_hmac .evp_digest .ctx = S2N_EVP_MD_CTX_NEW ());
201
- return 0 ;
202
- }
203
-
204
- static int s2n_evp_pkey_p_hash_digest_init (struct s2n_prf_working_space * ws )
205
- {
206
- POSIX_ENSURE_REF (ws -> p_hash .evp_hmac .evp_digest .md );
207
- POSIX_ENSURE_REF (ws -> p_hash .evp_hmac .evp_digest .ctx );
208
- POSIX_ENSURE_REF (ws -> p_hash .evp_hmac .ctx .evp_pkey );
209
-
210
- POSIX_GUARD_OSSL (EVP_DigestSignInit (ws -> p_hash .evp_hmac .evp_digest .ctx , NULL , ws -> p_hash .evp_hmac .evp_digest .md , NULL , ws -> p_hash .evp_hmac .ctx .evp_pkey ),
211
- S2N_ERR_P_HASH_INIT_FAILED );
212
-
213
- return 0 ;
214
- }
215
-
216
- static int s2n_evp_pkey_p_hash_init (struct s2n_prf_working_space * ws , s2n_hmac_algorithm alg , struct s2n_blob * secret )
217
- {
218
- /* Initialize the message digest */
219
- POSIX_GUARD_RESULT (s2n_hmac_md_from_alg (alg , & ws -> p_hash .evp_hmac .evp_digest .md ));
220
-
221
- /* Initialize the mac key using the provided secret */
222
- POSIX_ENSURE_REF (ws -> p_hash .evp_hmac .ctx .evp_pkey = EVP_PKEY_new_mac_key (EVP_PKEY_HMAC , NULL , secret -> data , secret -> size ));
223
-
224
- /* Initialize the message digest context with the above message digest and mac key */
225
- return s2n_evp_pkey_p_hash_digest_init (ws );
226
- }
227
-
228
- static int s2n_evp_pkey_p_hash_update (struct s2n_prf_working_space * ws , const void * data , uint32_t size )
229
- {
230
- POSIX_GUARD_OSSL (EVP_DigestSignUpdate (ws -> p_hash .evp_hmac .evp_digest .ctx , data , (size_t ) size ), S2N_ERR_P_HASH_UPDATE_FAILED );
231
-
232
- return 0 ;
233
- }
234
-
235
- static int s2n_evp_pkey_p_hash_final (struct s2n_prf_working_space * ws , void * digest , uint32_t size )
236
- {
237
- /* EVP_DigestSign API's require size_t data structures */
238
- size_t digest_size = size ;
239
-
240
- POSIX_GUARD_OSSL (EVP_DigestSignFinal (ws -> p_hash .evp_hmac .evp_digest .ctx , (unsigned char * ) digest , & digest_size ), S2N_ERR_P_HASH_FINAL_FAILED );
241
-
242
- return 0 ;
243
- }
244
-
245
- static int s2n_evp_pkey_p_hash_wipe (struct s2n_prf_working_space * ws )
246
- {
247
- POSIX_GUARD_OSSL (S2N_EVP_MD_CTX_RESET (ws -> p_hash .evp_hmac .evp_digest .ctx ), S2N_ERR_P_HASH_WIPE_FAILED );
248
-
249
- return 0 ;
250
- }
251
-
252
- static int s2n_evp_pkey_p_hash_reset (struct s2n_prf_working_space * ws )
253
- {
254
- POSIX_GUARD (s2n_evp_pkey_p_hash_wipe (ws ));
255
-
256
- /*
257
- * On some cleanup paths s2n_evp_pkey_p_hash_reset can be called before s2n_evp_pkey_p_hash_init so there is nothing
258
- * to reset.
259
- */
260
- if (ws -> p_hash .evp_hmac .ctx .evp_pkey == NULL ) {
261
- return S2N_SUCCESS ;
262
- }
263
- return s2n_evp_pkey_p_hash_digest_init (ws );
264
- }
265
-
266
- static int s2n_evp_pkey_p_hash_cleanup (struct s2n_prf_working_space * ws )
267
- {
268
- /* Prepare the workspace md_ctx for the next p_hash */
269
- POSIX_GUARD (s2n_evp_pkey_p_hash_wipe (ws ));
270
-
271
- /* Free mac key - PKEYs cannot be reused */
272
- POSIX_ENSURE_REF (ws -> p_hash .evp_hmac .ctx .evp_pkey );
273
- EVP_PKEY_free (ws -> p_hash .evp_hmac .ctx .evp_pkey );
274
- ws -> p_hash .evp_hmac .ctx .evp_pkey = NULL ;
275
-
276
- return 0 ;
277
- }
278
-
279
- static int s2n_evp_pkey_p_hash_free (struct s2n_prf_working_space * ws )
280
- {
281
- POSIX_ENSURE_REF (ws -> p_hash .evp_hmac .evp_digest .ctx );
282
- S2N_EVP_MD_CTX_FREE (ws -> p_hash .evp_hmac .evp_digest .ctx );
283
- ws -> p_hash .evp_hmac .evp_digest .ctx = NULL ;
284
-
285
- return 0 ;
286
- }
287
-
288
- static const struct s2n_p_hash_hmac s2n_evp_pkey_p_hash_hmac = {
289
- .alloc = & s2n_evp_pkey_p_hash_alloc ,
290
- .init = & s2n_evp_pkey_p_hash_init ,
291
- .update = & s2n_evp_pkey_p_hash_update ,
292
- .final = & s2n_evp_pkey_p_hash_final ,
293
- .reset = & s2n_evp_pkey_p_hash_reset ,
294
- .cleanup = & s2n_evp_pkey_p_hash_cleanup ,
295
- .free = & s2n_evp_pkey_p_hash_free ,
296
- };
297
- #else
298
- static int s2n_evp_hmac_p_hash_alloc (struct s2n_prf_working_space * ws )
299
- {
300
- POSIX_ENSURE_REF (ws -> p_hash .evp_hmac .ctx .hmac_ctx = HMAC_CTX_new ());
301
- return S2N_SUCCESS ;
302
- }
303
-
304
- static int s2n_evp_hmac_p_hash_init (struct s2n_prf_working_space * ws , s2n_hmac_algorithm alg , struct s2n_blob * secret )
305
- {
306
- /* Figure out the correct EVP_MD from s2n_hmac_algorithm */
307
- POSIX_GUARD_RESULT (s2n_hmac_md_from_alg (alg , & ws -> p_hash .evp_hmac .evp_digest .md ));
308
-
309
- /* Initialize the mac and digest */
310
- POSIX_GUARD_OSSL (HMAC_Init_ex (ws -> p_hash .evp_hmac .ctx .hmac_ctx , secret -> data , secret -> size , ws -> p_hash .evp_hmac .evp_digest .md , NULL ), S2N_ERR_P_HASH_INIT_FAILED );
311
- return S2N_SUCCESS ;
312
- }
313
-
314
- static int s2n_evp_hmac_p_hash_update (struct s2n_prf_working_space * ws , const void * data , uint32_t size )
315
- {
316
- POSIX_GUARD_OSSL (HMAC_Update (ws -> p_hash .evp_hmac .ctx .hmac_ctx , data , (size_t ) size ), S2N_ERR_P_HASH_UPDATE_FAILED );
317
- return S2N_SUCCESS ;
318
- }
319
-
320
- static int s2n_evp_hmac_p_hash_final (struct s2n_prf_working_space * ws , void * digest , uint32_t size )
321
- {
322
- /* HMAC_Final API's require size_t data structures */
323
- unsigned int digest_size = size ;
324
- POSIX_GUARD_OSSL (HMAC_Final (ws -> p_hash .evp_hmac .ctx .hmac_ctx , (unsigned char * ) digest , & digest_size ), S2N_ERR_P_HASH_FINAL_FAILED );
325
- return S2N_SUCCESS ;
326
- }
327
-
328
- static int s2n_evp_hmac_p_hash_reset (struct s2n_prf_working_space * ws )
329
- {
330
- POSIX_ENSURE_REF (ws );
331
- if (ws -> p_hash .evp_hmac .evp_digest .md == NULL ) {
332
- return S2N_SUCCESS ;
333
- }
334
- POSIX_GUARD_OSSL (HMAC_Init_ex (ws -> p_hash .evp_hmac .ctx .hmac_ctx , NULL , 0 , ws -> p_hash .evp_hmac .evp_digest .md , NULL ), S2N_ERR_P_HASH_INIT_FAILED );
335
- return S2N_SUCCESS ;
336
- }
337
-
338
- static int s2n_evp_hmac_p_hash_cleanup (struct s2n_prf_working_space * ws )
339
- {
340
- /* Prepare the workspace md_ctx for the next p_hash */
341
- HMAC_CTX_reset (ws -> p_hash .evp_hmac .ctx .hmac_ctx );
342
- return S2N_SUCCESS ;
343
- }
344
-
345
- static int s2n_evp_hmac_p_hash_free (struct s2n_prf_working_space * ws )
346
- {
347
- HMAC_CTX_free (ws -> p_hash .evp_hmac .ctx .hmac_ctx );
348
- return S2N_SUCCESS ;
349
- }
350
-
351
- static const struct s2n_p_hash_hmac s2n_evp_hmac_p_hash_hmac = {
352
- .alloc = & s2n_evp_hmac_p_hash_alloc ,
353
- .init = & s2n_evp_hmac_p_hash_init ,
354
- .update = & s2n_evp_hmac_p_hash_update ,
355
- .final = & s2n_evp_hmac_p_hash_final ,
356
- .reset = & s2n_evp_hmac_p_hash_reset ,
357
- .cleanup = & s2n_evp_hmac_p_hash_cleanup ,
358
- .free = & s2n_evp_hmac_p_hash_free ,
359
- };
360
- #endif /* !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC) */
361
-
362
198
static int s2n_hmac_p_hash_new (struct s2n_prf_working_space * ws )
363
199
{
364
200
POSIX_GUARD (s2n_hmac_new (& ws -> p_hash .s2n_hmac ));
365
-
366
201
return s2n_hmac_init (& ws -> p_hash .s2n_hmac , S2N_HMAC_NONE , NULL , 0 );
367
202
}
368
203
@@ -412,13 +247,20 @@ static const struct s2n_p_hash_hmac s2n_internal_p_hash_hmac = {
412
247
.free = & s2n_hmac_p_hash_free ,
413
248
};
414
249
250
+ /*
251
+ * For now, use the internal s2n-tls hmac abstraction.
252
+ * However, that is a custom implementation of hmac built on hashes.
253
+ * Ideally we should stop using our custom implementation here and switch
254
+ * to using a libcrypto implementation. Unfortunately, what each libcrypto
255
+ * can support varies a lot for HMACs.
256
+ *
257
+ * For historical reference, there used to be two other hmac implementations:
258
+ * https://github.com/aws/s2n-tls/blob/711ee0df658cd7c44088cf7a1b20a9f3cf5296d6/tls/s2n_prf.c#L174-L337
259
+ * Both implementations have compatibility issues with one or more libcryptos.
260
+ */
415
261
const struct s2n_p_hash_hmac * s2n_get_hmac_implementation ()
416
262
{
417
- #if defined(OPENSSL_IS_BORINGSSL ) || defined(OPENSSL_IS_AWSLC )
418
- return s2n_is_in_fips_mode () ? & s2n_evp_hmac_p_hash_hmac : & s2n_internal_p_hash_hmac ;
419
- #else
420
- return s2n_is_in_fips_mode () ? & s2n_evp_pkey_p_hash_hmac : & s2n_internal_p_hash_hmac ;
421
- #endif
263
+ return & s2n_internal_p_hash_hmac ;
422
264
}
423
265
424
266
static int s2n_p_hash (struct s2n_prf_working_space * ws , s2n_hmac_algorithm alg , struct s2n_blob * secret , struct s2n_blob * label ,
@@ -428,6 +270,7 @@ static int s2n_p_hash(struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg,
428
270
POSIX_GUARD (s2n_hmac_digest_size (alg , & digest_size ));
429
271
430
272
const struct s2n_p_hash_hmac * hmac = s2n_get_hmac_implementation ();
273
+ POSIX_ENSURE_REF (hmac );
431
274
432
275
/* First compute hmac(secret + A(0)) */
433
276
POSIX_GUARD (hmac -> init (ws , alg , secret ));
@@ -494,6 +337,7 @@ S2N_RESULT s2n_prf_new(struct s2n_connection *conn)
494
337
495
338
/* Allocate the hmac state */
496
339
const struct s2n_p_hash_hmac * hmac_impl = s2n_get_hmac_implementation ();
340
+ RESULT_ENSURE_REF (hmac_impl );
497
341
RESULT_GUARD_POSIX (hmac_impl -> alloc (conn -> prf_space ));
498
342
return S2N_RESULT_OK ;
499
343
}
@@ -504,6 +348,7 @@ S2N_RESULT s2n_prf_wipe(struct s2n_connection *conn)
504
348
RESULT_ENSURE_REF (conn -> prf_space );
505
349
506
350
const struct s2n_p_hash_hmac * hmac_impl = s2n_get_hmac_implementation ();
351
+ RESULT_ENSURE_REF (hmac_impl );
507
352
RESULT_GUARD_POSIX (hmac_impl -> reset (conn -> prf_space ));
508
353
509
354
return S2N_RESULT_OK ;
@@ -517,6 +362,7 @@ S2N_RESULT s2n_prf_free(struct s2n_connection *conn)
517
362
}
518
363
519
364
const struct s2n_p_hash_hmac * hmac_impl = s2n_get_hmac_implementation ();
365
+ RESULT_ENSURE_REF (hmac_impl );
520
366
RESULT_GUARD_POSIX (hmac_impl -> free (conn -> prf_space ));
521
367
522
368
RESULT_GUARD_POSIX (s2n_free_object ((uint8_t * * ) & conn -> prf_space , sizeof (struct s2n_prf_working_space )));
0 commit comments