Skip to content

Commit 9fc8672

Browse files
committed
refactor: use EVP_MD_fetch() if available
1 parent 7a4d1e7 commit 9fc8672

18 files changed

+146
-48
lines changed

codebuild/spec/buildspec_openssl3fips.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ phases:
3232
- export CTEST_PARALLEL_LEVEL=$(nproc)
3333
# openssl3fips is still a work-in-progress. Not all tests pass.
3434
- make -C build test -- ARGS="-R 's2n_build_test|s2n_fips_test'"
35+
- make -C build test -- ARGS="-R 's2n_hash_test|s2n_hash_all_algs_test|s2n_openssl_test|s2n_init_test'"

crypto/s2n_hash.c

Lines changed: 74 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
#include "error/s2n_errno.h"
2222
#include "utils/s2n_safety.h"
2323

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+
2430
static bool s2n_use_custom_md5_sha1()
2531
{
2632
#if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH)
@@ -40,28 +46,65 @@ bool s2n_hash_evp_fully_supported()
4046
return s2n_use_evp_impl() && !s2n_use_custom_md5_sha1();
4147
}
4248

43-
const EVP_MD *s2n_hash_alg_to_evp_md(s2n_hash_algorithm alg)
49+
S2N_RESULT s2n_hash_algorithms_init()
4450
{
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
6183
#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;
6498
}
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];
65108
}
66109

67110
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)
120163
case S2N_HASH_SHA384:
121164
case S2N_HASH_SHA512:
122165
return true;
123-
case S2N_HASH_SENTINEL:
166+
case S2N_HASH_ALGS_COUNT:
124167
return false;
125168
}
126169
return false;
@@ -313,13 +356,20 @@ static int s2n_evp_hash_init(struct s2n_hash_state *state, s2n_hash_algorithm al
313356

314357
if (alg == S2N_HASH_MD5_SHA1 && s2n_use_custom_md5_sha1()) {
315358
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);
318365
return S2N_SUCCESS;
319366
}
320367

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+
323373
return S2N_SUCCESS;
324374
}
325375

crypto/s2n_hash.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ typedef enum {
3333
S2N_HASH_SHA384,
3434
S2N_HASH_SHA512,
3535
S2N_HASH_MD5_SHA1,
36-
/* Don't add any hash algorithms below S2N_HASH_SENTINEL */
37-
S2N_HASH_SENTINEL
36+
/* Don't add any hash algorithms below S2N_HASH_ALGS_COUNT */
37+
S2N_HASH_ALGS_COUNT
3838
} s2n_hash_algorithm;
3939

4040
/* The low_level_digest stores all OpenSSL structs that are alg-specific to be used with OpenSSL's low-level hash API's. */
@@ -85,6 +85,8 @@ struct s2n_hash {
8585
int (*free)(struct s2n_hash_state *state);
8686
};
8787

88+
S2N_RESULT s2n_hash_algorithms_init();
89+
S2N_RESULT s2n_hash_algorithms_cleanup();
8890
bool s2n_hash_evp_fully_supported();
8991
const EVP_MD *s2n_hash_alg_to_evp_md(s2n_hash_algorithm alg);
9092
int s2n_hash_digest_size(s2n_hash_algorithm alg, uint8_t *out);

crypto/s2n_libcrypto.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,12 @@ bool s2n_libcrypto_supports_flag_no_check_time()
226226
return false;
227227
#endif
228228
}
229+
230+
bool s2n_libcrypto_supports_providers(void)
231+
{
232+
#ifdef S2N_LIBCRYPTO_SUPPORTS_PROVIDERS
233+
return true;
234+
#else
235+
return false;
236+
#endif
237+
}

crypto/s2n_libcrypto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ uint64_t s2n_libcrypto_awslc_api_version(void);
2121
S2N_RESULT s2n_libcrypto_validate_runtime(void);
2222
const char *s2n_libcrypto_get_version_name(void);
2323
bool s2n_libcrypto_supports_flag_no_check_time();
24+
bool s2n_libcrypto_supports_providers(void);

tests/cbmc/proofs/s2n_hash_is_available/s2n_hash_is_available_harness.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ void s2n_hash_is_available_harness()
3939
case S2N_HASH_SHA384:
4040
case S2N_HASH_SHA512:
4141
assert(is_available); break;
42-
case S2N_HASH_SENTINEL:
43-
assert(!is_available); break;
4442
default:
4543
__CPROVER_assert(!is_available, "Unsupported algorithm.");
4644
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
/*
17+
* This feature probe checks if the linked libcrypto has "provider" support:
18+
* https://docs.openssl.org/3.4/man7/provider/
19+
* Fetching algorithms from providers:
20+
* https://docs.openssl.org/3.4/man7/ossl-guide-libcrypto-introduction/#algorithm-fetching
21+
*/
22+
23+
#include <openssl/evp.h>
24+
25+
int main()
26+
{
27+
/* Supports fetching hash algorithms */
28+
EVP_MD *md = EVP_MD_fetch(NULL, NULL, NULL);
29+
EVP_MD_free(md);
30+
31+
return 0;
32+
}

tests/features/S2N_LIBCRYPTO_SUPPORTS_PROVIDERS.flags

Whitespace-only changes.

tests/sidetrail/working/s2n-cbc/stubs/s2n_hash.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ typedef enum {
3232
S2N_HASH_SHA384,
3333
S2N_HASH_SHA512,
3434
S2N_HASH_MD5_SHA1,
35-
/* Don't add any hash algorithms below S2N_HASH_SENTINEL */
36-
S2N_HASH_SENTINEL
35+
/* Don't add any hash algorithms below S2N_HASH_ALGS_COUNT */
36+
S2N_HASH_ALGS_COUNT
3737
} s2n_hash_algorithm;
3838

3939
struct s2n_hash_state {

tests/sidetrail/working/stubs/s2n_hash.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ typedef enum {
3232
S2N_HASH_SHA384,
3333
S2N_HASH_SHA512,
3434
S2N_HASH_MD5_SHA1,
35-
/* Don't add any hash algorithms below S2N_HASH_SENTINEL */
36-
S2N_HASH_SENTINEL
35+
/* Don't add any hash algorithms below S2N_HASH_ALGS_COUNT */
36+
S2N_HASH_ALGS_COUNT
3737
} s2n_hash_algorithm;
3838

3939
struct s2n_hash_state {

0 commit comments

Comments
 (0)