21
21
#include "error/s2n_errno.h"
22
22
#include "utils/s2n_safety.h"
23
23
24
+ #if S2N_LIBCRYPTO_SUPPORTS_PROVIDERS
25
+ static EVP_MD * evp_mds [S2N_HASH_ALGS_COUNT ] = { 0 };
26
+ #else
27
+ static const EVP_MD * evp_mds [S2N_HASH_ALGS_COUNT ] = { 0 };
28
+ #endif
29
+
24
30
static bool s2n_use_custom_md5_sha1 ()
25
31
{
26
32
#if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH )
@@ -40,28 +46,65 @@ bool s2n_hash_evp_fully_supported()
40
46
return s2n_use_evp_impl () && !s2n_use_custom_md5_sha1 ();
41
47
}
42
48
43
- const EVP_MD * s2n_hash_alg_to_evp_md ( s2n_hash_algorithm alg )
49
+ S2N_RESULT s2n_hash_algorithms_init ( )
44
50
{
45
- switch (alg ) {
46
- case S2N_HASH_MD5 :
47
- return EVP_md5 ();
48
- case S2N_HASH_SHA1 :
49
- return EVP_sha1 ();
50
- case S2N_HASH_SHA224 :
51
- return EVP_sha224 ();
52
- case S2N_HASH_SHA256 :
53
- return EVP_sha256 ();
54
- case S2N_HASH_SHA384 :
55
- return EVP_sha384 ();
56
- case S2N_HASH_SHA512 :
57
- return EVP_sha512 ();
58
- #if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH )
59
- case S2N_HASH_MD5_SHA1 :
60
- return EVP_md5_sha1 ();
51
+ #if S2N_LIBCRYPTO_SUPPORTS_PROVIDERS
52
+ /* openssl-3.0 introduced the concept of providers.
53
+ * After openssl-3.0, the old EVP_sha256()-style methods will still work,
54
+ * but may be inefficient. See
55
+ * https://docs.openssl.org/3.4/man7/ossl-guide-libcrypto-introduction/#performance
56
+ *
57
+ * Additionally, the old style methods do not support property query strings
58
+ * to guide which provider to fetch from. This is important for FIPS, where
59
+ * the default query string of "fips=yes" will need to be overridden for
60
+ * legacy algorithms.
61
+ */
62
+ evp_mds [S2N_HASH_MD5 ] = EVP_MD_fetch (NULL , "MD5" , "-fips" );
63
+ evp_mds [S2N_HASH_MD5_SHA1 ] = EVP_MD_fetch (NULL , "MD5-SHA1" , "-fips" );
64
+ evp_mds [S2N_HASH_SHA1 ] = EVP_MD_fetch (NULL , "SHA1" , NULL );
65
+ evp_mds [S2N_HASH_SHA224 ] = EVP_MD_fetch (NULL , "SHA224" , NULL );
66
+ evp_mds [S2N_HASH_SHA256 ] = EVP_MD_fetch (NULL , "SHA256" , NULL );
67
+ evp_mds [S2N_HASH_SHA384 ] = EVP_MD_fetch (NULL , "SHA384" , NULL );
68
+ evp_mds [S2N_HASH_SHA512 ] = EVP_MD_fetch (NULL , "SHA512" , NULL );
69
+ #else
70
+ evp_mds [S2N_HASH_MD5 ] = EVP_md5 ();
71
+ evp_mds [S2N_HASH_SHA1 ] = EVP_sha1 ();
72
+ evp_mds [S2N_HASH_SHA224 ] = EVP_sha224 ();
73
+ evp_mds [S2N_HASH_SHA256 ] = EVP_sha256 ();
74
+ evp_mds [S2N_HASH_SHA384 ] = EVP_sha384 ();
75
+ evp_mds [S2N_HASH_SHA512 ] = EVP_sha512 ();
76
+ /* Very old libcryptos like openssl-1.0.2 do not support EVP_MD_md5_sha1().
77
+ * We work around that by manually combining MD5 and SHA1, rather than
78
+ * using the composite algorithm.
79
+ */
80
+ #if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH )
81
+ evp_mds [S2N_HASH_MD5_SHA1 ] = EVP_md5_sha1 ();
82
+ #endif
61
83
#endif
62
- default :
63
- return NULL ;
84
+ return S2N_RESULT_OK ;
85
+ }
86
+
87
+ S2N_RESULT s2n_hash_algorithms_cleanup ()
88
+ {
89
+ #if S2N_LIBCRYPTO_SUPPORTS_PROVIDERS
90
+ for (size_t i = 0 ; i < S2N_HASH_ALGS_COUNT ; i ++ ) {
91
+ /* https://docs.openssl.org/3.4/man3/EVP_DigestInit/
92
+ * > Decrements the reference count for the fetched EVP_MD structure.
93
+ * > If the reference count drops to 0 then the structure is freed.
94
+ * > If the argument is NULL, nothing is done.
95
+ */
96
+ EVP_MD_free (evp_mds [i ]);
97
+ evp_mds [i ] = NULL ;
64
98
}
99
+ #endif
100
+ return S2N_RESULT_OK ;
101
+ }
102
+
103
+ const EVP_MD * s2n_hash_alg_to_evp_md (s2n_hash_algorithm alg )
104
+ {
105
+ PTR_ENSURE_GTE (alg , 0 );
106
+ PTR_ENSURE_LT (alg , S2N_HASH_ALGS_COUNT );
107
+ return evp_mds [alg ];
65
108
}
66
109
67
110
int s2n_hash_digest_size (s2n_hash_algorithm alg , uint8_t * out )
@@ -120,7 +163,7 @@ bool s2n_hash_is_available(s2n_hash_algorithm alg)
120
163
case S2N_HASH_SHA384 :
121
164
case S2N_HASH_SHA512 :
122
165
return true;
123
- case S2N_HASH_SENTINEL :
166
+ case S2N_HASH_ALGS_COUNT :
124
167
return false;
125
168
}
126
169
return false;
@@ -313,13 +356,20 @@ static int s2n_evp_hash_init(struct s2n_hash_state *state, s2n_hash_algorithm al
313
356
314
357
if (alg == S2N_HASH_MD5_SHA1 && s2n_use_custom_md5_sha1 ()) {
315
358
POSIX_ENSURE_REF (state -> digest .high_level .evp_md5_secondary .ctx );
316
- POSIX_GUARD_OSSL (EVP_DigestInit_ex (state -> digest .high_level .evp .ctx , EVP_sha1 (), NULL ), S2N_ERR_HASH_INIT_FAILED );
317
- POSIX_GUARD_OSSL (EVP_DigestInit_ex (state -> digest .high_level .evp_md5_secondary .ctx , EVP_md5 (), NULL ), S2N_ERR_HASH_INIT_FAILED );
359
+ POSIX_GUARD_OSSL (EVP_DigestInit_ex (state -> digest .high_level .evp .ctx ,
360
+ s2n_hash_alg_to_evp_md (S2N_HASH_SHA1 ), NULL ),
361
+ S2N_ERR_HASH_INIT_FAILED );
362
+ POSIX_GUARD_OSSL (EVP_DigestInit_ex (state -> digest .high_level .evp_md5_secondary .ctx ,
363
+ s2n_hash_alg_to_evp_md (S2N_HASH_MD5 ), NULL ),
364
+ S2N_ERR_HASH_INIT_FAILED );
318
365
return S2N_SUCCESS ;
319
366
}
320
367
321
- POSIX_ENSURE_REF (s2n_hash_alg_to_evp_md (alg ));
322
- POSIX_GUARD_OSSL (EVP_DigestInit_ex (state -> digest .high_level .evp .ctx , s2n_hash_alg_to_evp_md (alg ), NULL ), S2N_ERR_HASH_INIT_FAILED );
368
+ const EVP_MD * md = s2n_hash_alg_to_evp_md (alg );
369
+ POSIX_ENSURE (md , S2N_ERR_HASH_INVALID_ALGORITHM );
370
+ POSIX_GUARD_OSSL (EVP_DigestInit_ex (state -> digest .high_level .evp .ctx , md , NULL ),
371
+ S2N_ERR_HASH_INIT_FAILED );
372
+
323
373
return S2N_SUCCESS ;
324
374
}
325
375
0 commit comments