Skip to content

Commit f3ae011

Browse files
authored
refactor: remove unused evp support for md5+sha1 (#5106)
1 parent e4a5a74 commit f3ae011

File tree

26 files changed

+109
-129
lines changed

26 files changed

+109
-129
lines changed

crypto/s2n_evp_signing.c

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "crypto/s2n_evp_signing.h"
1717

1818
#include "crypto/s2n_evp.h"
19+
#include "crypto/s2n_fips.h"
1920
#include "crypto/s2n_pkey.h"
2021
#include "crypto/s2n_rsa_pss.h"
2122
#include "error/s2n_errno.h"
@@ -50,18 +51,58 @@ static S2N_RESULT s2n_evp_pkey_set_rsa_pss_saltlen(EVP_PKEY_CTX *pctx)
5051
#endif
5152
}
5253

53-
bool s2n_evp_signing_supported()
54+
static bool s2n_evp_md5_sha1_is_supported()
55+
{
56+
#if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH)
57+
return true;
58+
#else
59+
return false;
60+
#endif
61+
}
62+
63+
static bool s2n_evp_md_ctx_set_pkey_ctx_is_supported()
5464
{
5565
#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX
56-
/* We can only use EVP signing if the hash state has an EVP_MD_CTX
57-
* that we can pass to the EVP signing methods.
58-
*/
59-
return s2n_hash_evp_fully_supported();
66+
return true;
6067
#else
6168
return false;
6269
#endif
6370
}
6471

72+
bool s2n_evp_signing_supported()
73+
{
74+
/* We must use the FIPS-approved EVP APIs in FIPS mode,
75+
* but we could also use the EVP APIs outside of FIPS mode.
76+
* Only using the EVP APIs in FIPS mode was a choice made to reduce
77+
* the impact of adding support for the EVP APIs.
78+
* We should consider instead making the EVP APIs the default.
79+
*/
80+
if (!s2n_is_in_fips_mode()) {
81+
return false;
82+
}
83+
84+
/* Our EVP signing logic is intended to support FIPS 140-3.
85+
* FIPS 140-3 does not allow externally calculated digests (except for
86+
* signing, but not verifying, with ECDSA).
87+
* See https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures,
88+
* and note that "component" tests only exist for ECDSA sign.
89+
*
90+
* We currently work around that restriction by calling EVP_MD_CTX_set_pkey_ctx,
91+
* which lets us set a key on an existing hash state. This is important
92+
* when we need to handle signing the TLS1.2 client cert verify message,
93+
* which requires signing the entire message transcript. If EVP_MD_CTX_set_pkey_ctx
94+
* is unavailable (true for openssl-1.0.2), our current EVP logic will not work.
95+
*
96+
* FIPS 140-3 is also not possible if EVP_md5_sha1() isn't available
97+
* (again true for openssl-1.0.2). In that case, we use two separate hash
98+
* states to track the md5 and sha1 parts of the hash separately. That means
99+
* that we also have to calculate the digests separately, then combine the
100+
* result. We therefore only have an externally calculated digest available
101+
* for signing or verifying.
102+
*/
103+
return s2n_evp_md_ctx_set_pkey_ctx_is_supported() && s2n_evp_md5_sha1_is_supported();
104+
}
105+
65106
/* If using EVP signing, override the sign and verify pkey methods.
66107
* The EVP methods can handle all pkey types / signature algorithms.
67108
*/

crypto/s2n_hash.c

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,22 @@
1515

1616
#include "crypto/s2n_hash.h"
1717

18-
#include "crypto/s2n_fips.h"
18+
#include "crypto/s2n_evp_signing.h"
1919
#include "crypto/s2n_hmac.h"
2020
#include "crypto/s2n_openssl.h"
2121
#include "error/s2n_errno.h"
2222
#include "utils/s2n_safety.h"
2323

24-
static bool s2n_use_custom_md5_sha1()
25-
{
26-
#if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH)
27-
return false;
28-
#else
29-
return true;
30-
#endif
31-
}
32-
3324
static bool s2n_use_evp_impl()
3425
{
35-
return s2n_is_in_fips_mode();
36-
}
37-
38-
bool s2n_hash_evp_fully_supported()
39-
{
40-
return s2n_use_evp_impl() && !s2n_use_custom_md5_sha1();
26+
/* Our current EVP signing implementation requires EVP hashing.
27+
*
28+
* We could use the EVP hashing impl with legacy signing, but that would
29+
* unnecessarily complicate the logic. The only known libcrypto that
30+
* doesn't support EVP signing is openssl-1.0.2. Just let legacy
31+
* libcryptos use legacy methods.
32+
*/
33+
return s2n_evp_signing_supported();
4134
}
4235

4336
const EVP_MD *s2n_hash_alg_to_evp_md(s2n_hash_algorithm alg)
@@ -289,13 +282,8 @@ static int s2n_low_level_hash_free(struct s2n_hash_state *state)
289282
static int s2n_evp_hash_new(struct s2n_hash_state *state)
290283
{
291284
POSIX_ENSURE_REF(state->digest.high_level.evp.ctx = S2N_EVP_MD_CTX_NEW());
292-
if (s2n_use_custom_md5_sha1()) {
293-
POSIX_ENSURE_REF(state->digest.high_level.evp_md5_secondary.ctx = S2N_EVP_MD_CTX_NEW());
294-
}
295-
296285
state->is_ready_for_input = 0;
297286
state->currently_in_hash = 0;
298-
299287
return S2N_SUCCESS;
300288
}
301289

@@ -311,13 +299,6 @@ static int s2n_evp_hash_init(struct s2n_hash_state *state, s2n_hash_algorithm al
311299
return S2N_SUCCESS;
312300
}
313301

314-
if (alg == S2N_HASH_MD5_SHA1 && s2n_use_custom_md5_sha1()) {
315-
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);
318-
return S2N_SUCCESS;
319-
}
320-
321302
POSIX_ENSURE_REF(s2n_hash_alg_to_evp_md(alg));
322303
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);
323304
return S2N_SUCCESS;
@@ -335,12 +316,6 @@ static int s2n_evp_hash_update(struct s2n_hash_state *state, const void *data, u
335316

336317
POSIX_ENSURE_REF(EVP_MD_CTX_md(state->digest.high_level.evp.ctx));
337318
POSIX_GUARD_OSSL(EVP_DigestUpdate(state->digest.high_level.evp.ctx, data, size), S2N_ERR_HASH_UPDATE_FAILED);
338-
339-
if (state->alg == S2N_HASH_MD5_SHA1 && s2n_use_custom_md5_sha1()) {
340-
POSIX_ENSURE_REF(EVP_MD_CTX_md(state->digest.high_level.evp_md5_secondary.ctx));
341-
POSIX_GUARD_OSSL(EVP_DigestUpdate(state->digest.high_level.evp_md5_secondary.ctx, data, size), S2N_ERR_HASH_UPDATE_FAILED);
342-
}
343-
344319
return S2N_SUCCESS;
345320
}
346321

@@ -362,23 +337,6 @@ static int s2n_evp_hash_digest(struct s2n_hash_state *state, void *out, uint32_t
362337

363338
POSIX_ENSURE_REF(EVP_MD_CTX_md(state->digest.high_level.evp.ctx));
364339

365-
if (state->alg == S2N_HASH_MD5_SHA1 && s2n_use_custom_md5_sha1()) {
366-
POSIX_ENSURE_REF(EVP_MD_CTX_md(state->digest.high_level.evp_md5_secondary.ctx));
367-
368-
uint8_t sha1_digest_size = 0;
369-
POSIX_GUARD(s2n_hash_digest_size(S2N_HASH_SHA1, &sha1_digest_size));
370-
371-
unsigned int sha1_primary_digest_size = sha1_digest_size;
372-
unsigned int md5_secondary_digest_size = digest_size - sha1_primary_digest_size;
373-
374-
POSIX_ENSURE(EVP_MD_CTX_size(state->digest.high_level.evp.ctx) <= sha1_digest_size, S2N_ERR_HASH_DIGEST_FAILED);
375-
POSIX_ENSURE((size_t) EVP_MD_CTX_size(state->digest.high_level.evp_md5_secondary.ctx) <= md5_secondary_digest_size, S2N_ERR_HASH_DIGEST_FAILED);
376-
377-
POSIX_GUARD_OSSL(EVP_DigestFinal_ex(state->digest.high_level.evp.ctx, ((uint8_t *) out) + MD5_DIGEST_LENGTH, &sha1_primary_digest_size), S2N_ERR_HASH_DIGEST_FAILED);
378-
POSIX_GUARD_OSSL(EVP_DigestFinal_ex(state->digest.high_level.evp_md5_secondary.ctx, out, &md5_secondary_digest_size), S2N_ERR_HASH_DIGEST_FAILED);
379-
return S2N_SUCCESS;
380-
}
381-
382340
POSIX_ENSURE((size_t) EVP_MD_CTX_size(state->digest.high_level.evp.ctx) <= digest_size, S2N_ERR_HASH_DIGEST_FAILED);
383341
POSIX_GUARD_OSSL(EVP_DigestFinal_ex(state->digest.high_level.evp.ctx, out, &digest_size), S2N_ERR_HASH_DIGEST_FAILED);
384342
return S2N_SUCCESS;
@@ -397,21 +355,12 @@ static int s2n_evp_hash_copy(struct s2n_hash_state *to, struct s2n_hash_state *f
397355

398356
POSIX_ENSURE_REF(to->digest.high_level.evp.ctx);
399357
POSIX_GUARD_OSSL(EVP_MD_CTX_copy_ex(to->digest.high_level.evp.ctx, from->digest.high_level.evp.ctx), S2N_ERR_HASH_COPY_FAILED);
400-
401-
if (from->alg == S2N_HASH_MD5_SHA1 && s2n_use_custom_md5_sha1()) {
402-
POSIX_ENSURE_REF(to->digest.high_level.evp_md5_secondary.ctx);
403-
POSIX_GUARD_OSSL(EVP_MD_CTX_copy_ex(to->digest.high_level.evp_md5_secondary.ctx, from->digest.high_level.evp_md5_secondary.ctx), S2N_ERR_HASH_COPY_FAILED);
404-
}
405-
406358
return S2N_SUCCESS;
407359
}
408360

409361
static int s2n_evp_hash_reset(struct s2n_hash_state *state)
410362
{
411363
POSIX_GUARD_OSSL(S2N_EVP_MD_CTX_RESET(state->digest.high_level.evp.ctx), S2N_ERR_HASH_WIPE_FAILED);
412-
if (state->alg == S2N_HASH_MD5_SHA1 && s2n_use_custom_md5_sha1()) {
413-
POSIX_GUARD_OSSL(S2N_EVP_MD_CTX_RESET(state->digest.high_level.evp_md5_secondary.ctx), S2N_ERR_HASH_WIPE_FAILED);
414-
}
415364

416365
/* hash_init resets the ready_for_input and currently_in_hash fields. */
417366
return s2n_evp_hash_init(state, state->alg);
@@ -421,12 +370,6 @@ static int s2n_evp_hash_free(struct s2n_hash_state *state)
421370
{
422371
S2N_EVP_MD_CTX_FREE(state->digest.high_level.evp.ctx);
423372
state->digest.high_level.evp.ctx = NULL;
424-
425-
if (s2n_use_custom_md5_sha1()) {
426-
S2N_EVP_MD_CTX_FREE(state->digest.high_level.evp_md5_secondary.ctx);
427-
state->digest.high_level.evp_md5_secondary.ctx = NULL;
428-
}
429-
430373
state->is_ready_for_input = 0;
431374
return S2N_SUCCESS;
432375
}

crypto/s2n_hash.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ union s2n_hash_low_level_digest {
5454
/* The evp_digest stores all OpenSSL structs to be used with OpenSSL's EVP hash API's. */
5555
struct s2n_hash_evp_digest {
5656
struct s2n_evp_digest evp;
57-
/* Always store a secondary evp_digest to allow resetting a hash_state to MD5_SHA1 from another alg. */
58-
struct s2n_evp_digest evp_md5_secondary;
5957
};
6058

6159
/* s2n_hash_state stores the s2n_hash implementation being used (low-level or EVP),

tests/cbmc/include/cbmc_proof/cbmc_utils.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,8 @@ struct rc_keys_from_evp_pkey_ctx {
4747
int pkey_eckey_refs;
4848
};
4949

50-
/**
51-
* In the `rc_keys_from_hash_state`, we store two `rc_keys_from_evp_pkey_ctx` objects:
52-
* one for the `evp` field and another for `evp_md5_secondary` field.
53-
*/
5450
struct rc_keys_from_hash_state {
5551
struct rc_keys_from_evp_pkey_ctx evp;
56-
struct rc_keys_from_evp_pkey_ctx evp_md5;
5752
};
5853

5954
/**

tests/cbmc/proofs/s2n_hash_const_time_get_currently_in_hash_block/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ HARNESS_FILE = $(HARNESS_ENTRY).c
2222
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE)
2323
PROOF_SOURCES += $(PROOF_SOURCE)/make_common_datastructures.c
2424
PROOF_SOURCES += $(PROOF_STUB)/s2n_calculate_stacktrace.c
25-
PROOF_SOURCES += $(PROOF_STUB)/s2n_is_in_fips_mode.c
25+
PROOF_SOURCES += $(PROOF_STUB)/s2n_evp_signing_supported.c
2626

2727
PROJECT_SOURCES += $(SRCDIR)/crypto/s2n_hash.c
2828

tests/cbmc/proofs/s2n_hash_copy/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ PROOF_SOURCES += $(OPENSSL_SOURCE)/ec_override.c
2525
PROOF_SOURCES += $(OPENSSL_SOURCE)/evp_override.c
2626
PROOF_SOURCES += $(PROOF_SOURCE)/make_common_datastructures.c
2727
PROOF_SOURCES += $(PROOF_STUB)/s2n_calculate_stacktrace.c
28-
PROOF_SOURCES += $(PROOF_STUB)/s2n_is_in_fips_mode.c
28+
PROOF_SOURCES += $(PROOF_STUB)/s2n_evp_signing_supported.c
2929

3030
PROJECT_SOURCES += $(SRCDIR)/crypto/s2n_hash.c
3131
PROJECT_SOURCES += $(SRCDIR)/utils/s2n_ensure.c

tests/cbmc/proofs/s2n_hash_digest/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ PROOF_SOURCES += $(OPENSSL_SOURCE)/md5_override.c
2727
PROOF_SOURCES += $(OPENSSL_SOURCE)/sha_override.c
2828
PROOF_SOURCES += $(PROOF_SOURCE)/make_common_datastructures.c
2929
PROOF_SOURCES += $(PROOF_STUB)/s2n_calculate_stacktrace.c
30-
PROOF_SOURCES += $(PROOF_STUB)/s2n_is_in_fips_mode.c
30+
PROOF_SOURCES += $(PROOF_STUB)/s2n_evp_signing_supported.c
3131

3232
PROJECT_SOURCES += $(SRCDIR)/crypto/s2n_hash.c
3333
PROJECT_SOURCES += $(SRCDIR)/utils/s2n_safety.c

tests/cbmc/proofs/s2n_hash_free/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ PROOF_SOURCES += $(OPENSSL_SOURCE)/ec_override.c
2424
PROOF_SOURCES += $(OPENSSL_SOURCE)/evp_override.c
2525
PROOF_SOURCES += $(PROOF_SOURCE)/cbmc_utils.c
2626
PROOF_SOURCES += $(PROOF_SOURCE)/make_common_datastructures.c
27-
PROOF_SOURCES += $(PROOF_STUB)/s2n_is_in_fips_mode.c
27+
PROOF_SOURCES += $(PROOF_STUB)/s2n_evp_signing_supported.c
2828
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE)
2929

3030
PROJECT_SOURCES += $(SRCDIR)/crypto/s2n_hash.c

tests/cbmc/proofs/s2n_hash_free/s2n_hash_free_harness.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* permissions and limitations under the License.
1414
*/
1515

16-
#include "crypto/s2n_fips.h"
16+
#include "crypto/s2n_evp_signing.h"
1717
#include "crypto/s2n_hash.h"
1818

1919
#include <cbmc_proof/make_common_datastructures.h>
@@ -35,9 +35,8 @@ void s2n_hash_free_harness()
3535
assert(s2n_hash_free(state) == S2N_SUCCESS);
3636
if (state != NULL) {
3737
assert(state->hash_impl->free != NULL);
38-
if (s2n_is_in_fips_mode()) {
38+
if (s2n_evp_signing_supported()) {
3939
assert(state->digest.high_level.evp.ctx == NULL);
40-
assert(state->digest.high_level.evp_md5_secondary.ctx == NULL);
4140
assert_rc_decrement_on_hash_state(&saved_hash_state);
4241
} else {
4342
assert_rc_unchanged_on_hash_state(&saved_hash_state);
@@ -47,11 +46,10 @@ void s2n_hash_free_harness()
4746

4847
/* Cleanup after expected error cases, for memory leak check. */
4948
if (state != NULL) {
50-
/* 1. `free` leftover EVP_MD_CTX objects if `s2n_is_in_fips_mode`,
49+
/* 1. `free` leftover EVP_MD_CTX objects if `s2n_evp_signing_supported`,
5150
since `s2n_hash_free` is a NO-OP in that case. */
52-
if (!s2n_is_in_fips_mode()) {
51+
if (!s2n_evp_signing_supported()) {
5352
S2N_EVP_MD_CTX_FREE(state->digest.high_level.evp.ctx);
54-
S2N_EVP_MD_CTX_FREE(state->digest.high_level.evp_md5_secondary.ctx);
5553
}
5654

5755
/* 2. `free` leftover reference-counted keys (i.e. those with non-zero ref-count),

tests/cbmc/proofs/s2n_hash_get_currently_in_hash_total/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ HARNESS_FILE = $(HARNESS_ENTRY).c
2222
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE)
2323
PROOF_SOURCES += $(PROOF_SOURCE)/make_common_datastructures.c
2424
PROOF_SOURCES += $(PROOF_STUB)/s2n_calculate_stacktrace.c
25-
PROOF_SOURCES += $(PROOF_STUB)/s2n_is_in_fips_mode.c
25+
PROOF_SOURCES += $(PROOF_STUB)/s2n_evp_signing_supported.c
2626

2727
PROJECT_SOURCES += $(SRCDIR)/crypto/s2n_hash.c
2828

0 commit comments

Comments
 (0)