Skip to content

Commit 7a4d1e7

Browse files
authored
Revert "refactor: remove unused evp support for md5+sha1 (#5106)" (#5118)
1 parent 8201205 commit 7a4d1e7

File tree

26 files changed

+129
-109
lines changed

26 files changed

+129
-109
lines changed

crypto/s2n_evp_signing.c

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

1818
#include "crypto/s2n_evp.h"
19-
#include "crypto/s2n_fips.h"
2019
#include "crypto/s2n_pkey.h"
2120
#include "crypto/s2n_rsa_pss.h"
2221
#include "error/s2n_errno.h"
@@ -51,58 +50,18 @@ static S2N_RESULT s2n_evp_pkey_set_rsa_pss_saltlen(EVP_PKEY_CTX *pctx)
5150
#endif
5251
}
5352

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()
53+
bool s2n_evp_signing_supported()
6454
{
6555
#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX
66-
return true;
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();
6760
#else
6861
return false;
6962
#endif
7063
}
7164

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-
10665
/* If using EVP signing, override the sign and verify pkey methods.
10766
* The EVP methods can handle all pkey types / signature algorithms.
10867
*/

crypto/s2n_hash.c

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

1616
#include "crypto/s2n_hash.h"
1717

18-
#include "crypto/s2n_evp_signing.h"
18+
#include "crypto/s2n_fips.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+
2433
static bool s2n_use_evp_impl()
2534
{
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();
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();
3441
}
3542

3643
const EVP_MD *s2n_hash_alg_to_evp_md(s2n_hash_algorithm alg)
@@ -282,8 +289,13 @@ static int s2n_low_level_hash_free(struct s2n_hash_state *state)
282289
static int s2n_evp_hash_new(struct s2n_hash_state *state)
283290
{
284291
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+
285296
state->is_ready_for_input = 0;
286297
state->currently_in_hash = 0;
298+
287299
return S2N_SUCCESS;
288300
}
289301

@@ -299,6 +311,13 @@ static int s2n_evp_hash_init(struct s2n_hash_state *state, s2n_hash_algorithm al
299311
return S2N_SUCCESS;
300312
}
301313

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+
302321
POSIX_ENSURE_REF(s2n_hash_alg_to_evp_md(alg));
303322
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);
304323
return S2N_SUCCESS;
@@ -316,6 +335,12 @@ static int s2n_evp_hash_update(struct s2n_hash_state *state, const void *data, u
316335

317336
POSIX_ENSURE_REF(EVP_MD_CTX_md(state->digest.high_level.evp.ctx));
318337
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+
319344
return S2N_SUCCESS;
320345
}
321346

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

338363
POSIX_ENSURE_REF(EVP_MD_CTX_md(state->digest.high_level.evp.ctx));
339364

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+
340382
POSIX_ENSURE((size_t) EVP_MD_CTX_size(state->digest.high_level.evp.ctx) <= digest_size, S2N_ERR_HASH_DIGEST_FAILED);
341383
POSIX_GUARD_OSSL(EVP_DigestFinal_ex(state->digest.high_level.evp.ctx, out, &digest_size), S2N_ERR_HASH_DIGEST_FAILED);
342384
return S2N_SUCCESS;
@@ -355,12 +397,21 @@ static int s2n_evp_hash_copy(struct s2n_hash_state *to, struct s2n_hash_state *f
355397

356398
POSIX_ENSURE_REF(to->digest.high_level.evp.ctx);
357399
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+
358406
return S2N_SUCCESS;
359407
}
360408

361409
static int s2n_evp_hash_reset(struct s2n_hash_state *state)
362410
{
363411
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+
}
364415

365416
/* hash_init resets the ready_for_input and currently_in_hash fields. */
366417
return s2n_evp_hash_init(state, state->alg);
@@ -370,6 +421,12 @@ static int s2n_evp_hash_free(struct s2n_hash_state *state)
370421
{
371422
S2N_EVP_MD_CTX_FREE(state->digest.high_level.evp.ctx);
372423
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+
373430
state->is_ready_for_input = 0;
374431
return S2N_SUCCESS;
375432
}

crypto/s2n_hash.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ 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;
5759
};
5860

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

tests/cbmc/include/cbmc_proof/cbmc_utils.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,13 @@ 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+
*/
5054
struct rc_keys_from_hash_state {
5155
struct rc_keys_from_evp_pkey_ctx evp;
56+
struct rc_keys_from_evp_pkey_ctx evp_md5;
5257
};
5358

5459
/**

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_evp_signing_supported.c
25+
PROOF_SOURCES += $(PROOF_STUB)/s2n_is_in_fips_mode.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_evp_signing_supported.c
28+
PROOF_SOURCES += $(PROOF_STUB)/s2n_is_in_fips_mode.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_evp_signing_supported.c
30+
PROOF_SOURCES += $(PROOF_STUB)/s2n_is_in_fips_mode.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_evp_signing_supported.c
27+
PROOF_SOURCES += $(PROOF_STUB)/s2n_is_in_fips_mode.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: 6 additions & 4 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_evp_signing.h"
16+
#include "crypto/s2n_fips.h"
1717
#include "crypto/s2n_hash.h"
1818

1919
#include <cbmc_proof/make_common_datastructures.h>
@@ -35,8 +35,9 @@ 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_evp_signing_supported()) {
38+
if (s2n_is_in_fips_mode()) {
3939
assert(state->digest.high_level.evp.ctx == NULL);
40+
assert(state->digest.high_level.evp_md5_secondary.ctx == NULL);
4041
assert_rc_decrement_on_hash_state(&saved_hash_state);
4142
} else {
4243
assert_rc_unchanged_on_hash_state(&saved_hash_state);
@@ -46,10 +47,11 @@ void s2n_hash_free_harness()
4647

4748
/* Cleanup after expected error cases, for memory leak check. */
4849
if (state != NULL) {
49-
/* 1. `free` leftover EVP_MD_CTX objects if `s2n_evp_signing_supported`,
50+
/* 1. `free` leftover EVP_MD_CTX objects if `s2n_is_in_fips_mode`,
5051
since `s2n_hash_free` is a NO-OP in that case. */
51-
if (!s2n_evp_signing_supported()) {
52+
if (!s2n_is_in_fips_mode()) {
5253
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);
5355
}
5456

5557
/* 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_evp_signing_supported.c
25+
PROOF_SOURCES += $(PROOF_STUB)/s2n_is_in_fips_mode.c
2626

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

0 commit comments

Comments
 (0)