diff options
author | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-03-02 12:50:27 +0300 |
---|---|---|
committer | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-03-02 12:50:27 +0300 |
commit | d0f80d5e60d77854f9d6262a59a7349e2b21f9d2 (patch) | |
tree | 01f1e033ce5519d96b7d6a83718221dcb8021eec /contrib/restricted/aws | |
parent | 26286f616cee657612a9d820be6da2cdbd4de0ef (diff) | |
download | ydb-d0f80d5e60d77854f9d6262a59a7349e2b21f9d2.tar.gz |
intermediate changes
ref:40ac71fae6ea311a73473cf4297ca93bf27559c3
Diffstat (limited to 'contrib/restricted/aws')
72 files changed, 1312 insertions, 471 deletions
diff --git a/contrib/restricted/aws/s2n/.yandex_meta/devtools.copyrights.report b/contrib/restricted/aws/s2n/.yandex_meta/devtools.copyrights.report index 4e2f77d918..c6657ea2b7 100644 --- a/contrib/restricted/aws/s2n/.yandex_meta/devtools.copyrights.report +++ b/contrib/restricted/aws/s2n/.yandex_meta/devtools.copyrights.report @@ -187,6 +187,8 @@ BELONGS ya.make tls/extensions/s2n_extension_type_lists.h [2:2] tls/extensions/s2n_key_share.c [2:2] tls/extensions/s2n_key_share.h [2:2] + tls/extensions/s2n_psk_key_exchange_modes.c [2:2] + tls/extensions/s2n_psk_key_exchange_modes.h [2:2] tls/extensions/s2n_quic_transport_params.c [2:2] tls/extensions/s2n_quic_transport_params.h [2:2] tls/extensions/s2n_server_alpn.c [2:2] @@ -197,6 +199,8 @@ BELONGS ya.make tls/extensions/s2n_server_key_share.h [2:2] tls/extensions/s2n_server_max_fragment_length.c [2:2] tls/extensions/s2n_server_max_fragment_length.h [2:2] + tls/extensions/s2n_server_psk.c [2:2] + tls/extensions/s2n_server_psk.h [2:2] tls/extensions/s2n_server_renegotiation_info.c [2:2] tls/extensions/s2n_server_renegotiation_info.h [2:2] tls/extensions/s2n_server_sct_list.c [2:2] diff --git a/contrib/restricted/aws/s2n/.yandex_meta/devtools.licenses.report b/contrib/restricted/aws/s2n/.yandex_meta/devtools.licenses.report index 2411f3a704..42c940cc02 100644 --- a/contrib/restricted/aws/s2n/.yandex_meta/devtools.licenses.report +++ b/contrib/restricted/aws/s2n/.yandex_meta/devtools.licenses.report @@ -363,6 +363,8 @@ BELONGS ya.make tls/extensions/s2n_extension_type_lists.h [4:13] tls/extensions/s2n_key_share.c [4:13] tls/extensions/s2n_key_share.h [4:13] + tls/extensions/s2n_psk_key_exchange_modes.c [4:13] + tls/extensions/s2n_psk_key_exchange_modes.h [4:13] tls/extensions/s2n_quic_transport_params.c [4:13] tls/extensions/s2n_quic_transport_params.h [4:13] tls/extensions/s2n_server_alpn.c [4:13] @@ -373,6 +375,8 @@ BELONGS ya.make tls/extensions/s2n_server_key_share.h [4:13] tls/extensions/s2n_server_max_fragment_length.c [4:13] tls/extensions/s2n_server_max_fragment_length.h [4:13] + tls/extensions/s2n_server_psk.c [4:13] + tls/extensions/s2n_server_psk.h [4:13] tls/extensions/s2n_server_renegotiation_info.c [4:13] tls/extensions/s2n_server_renegotiation_info.h [4:13] tls/extensions/s2n_server_sct_list.c [4:13] diff --git a/contrib/restricted/aws/s2n/CMakeLists.txt b/contrib/restricted/aws/s2n/CMakeLists.txt index 2c5722b2de..cf54c00743 100644 --- a/contrib/restricted/aws/s2n/CMakeLists.txt +++ b/contrib/restricted/aws/s2n/CMakeLists.txt @@ -132,11 +132,13 @@ target_sources(restricted-aws-s2n PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.c + ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_max_fragment_length.c + ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_sct_list.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_server_name.c diff --git a/contrib/restricted/aws/s2n/api/s2n.h b/contrib/restricted/aws/s2n/api/s2n.h index 55a3ccf4bc..0dfa21bf26 100644 --- a/contrib/restricted/aws/s2n/api/s2n.h +++ b/contrib/restricted/aws/s2n/api/s2n.h @@ -51,6 +51,15 @@ extern "C" { S2N_API extern __thread int s2n_errno; +/** + * Returns the address of the thread-local `s2n_errno` variable + * + * This function can be used instead of trying to resolve `s2n_errno` directly + * in runtimes where thread-local variables may not be easily accessible. + */ +S2N_API +extern int *s2n_errno_location(); + typedef enum { S2N_ERR_T_OK=0, S2N_ERR_T_IO, diff --git a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c index d1d37d1bee..240f0f87b1 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c @@ -22,6 +22,7 @@ #include "utils/s2n_blob.h" #include "utils/s2n_mem.h" #include "utils/s2n_random.h" +#include "utils/s2n_result.h" #include "utils/s2n_safety.h" #include "crypto/s2n_ecdsa.h" @@ -30,12 +31,19 @@ #include "crypto/s2n_openssl.h" #include "crypto/s2n_pkey.h" -int s2n_ecdsa_der_signature_size(const struct s2n_pkey *pkey) +S2N_RESULT s2n_ecdsa_der_signature_size(const struct s2n_pkey *pkey, uint32_t *size_out) { + ENSURE_REF(pkey); + ENSURE_REF(size_out); + const struct s2n_ecdsa_key *ecdsa_key = &pkey->key.ecdsa_key; - notnull_check(ecdsa_key->ec_key); + ENSURE_REF(ecdsa_key->ec_key); + + const int size = ECDSA_size(ecdsa_key->ec_key); + GUARD_AS_RESULT(size); + *size_out = size; - return ECDSA_size(ecdsa_key->ec_key); + return S2N_RESULT_OK; } static int s2n_ecdsa_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig_alg, @@ -102,7 +110,9 @@ static int s2n_ecdsa_keys_match(const struct s2n_pkey *pub, const struct s2n_pke GUARD(s2n_hash_update(&state_in, input, sizeof(input))); GUARD(s2n_hash_update(&state_out, input, sizeof(input))); - GUARD(s2n_alloc(&signature, s2n_ecdsa_der_signature_size(priv))); + uint32_t size = 0; + GUARD_AS_POSIX(s2n_ecdsa_der_signature_size(priv, &size)); + GUARD(s2n_alloc(&signature, size)); GUARD(s2n_ecdsa_sign(priv, S2N_SIGNATURE_ECDSA, &state_in, &signature)); GUARD(s2n_ecdsa_verify(pub, S2N_SIGNATURE_ECDSA, &state_out, &signature)); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_fips.h b/contrib/restricted/aws/s2n/crypto/s2n_fips.h index 23c3ea4bd0..e0644f4080 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_fips.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_fips.h @@ -13,6 +13,10 @@ * permissions and limitations under the License. */ +#include <stdbool.h> + +#include "api/s2n.h" + #pragma once extern int s2n_fips_init(void); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hash.c b/contrib/restricted/aws/s2n/crypto/s2n_hash.c index 0a3ad28130..27a9358438 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_hash.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_hash.c @@ -22,27 +22,9 @@ #include "utils/s2n_safety.h" -int s2n_hash_hmac_alg(s2n_hash_algorithm hash_alg, s2n_hmac_algorithm *out) -{ - ENSURE_POSIX(S2N_MEM_IS_READABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION); - switch(hash_alg) { - case S2N_HASH_NONE: *out = S2N_HMAC_NONE; break; - case S2N_HASH_MD5: *out = S2N_HMAC_MD5; break; - case S2N_HASH_SHA1: *out = S2N_HMAC_SHA1; break; - case S2N_HASH_SHA224: *out = S2N_HMAC_SHA224; break; - case S2N_HASH_SHA256: *out = S2N_HMAC_SHA256; break; - case S2N_HASH_SHA384: *out = S2N_HMAC_SHA384; break; - case S2N_HASH_SHA512: *out = S2N_HMAC_SHA512; break; - case S2N_HASH_MD5_SHA1: /* Fall through ... */ - default: - S2N_ERROR(S2N_ERR_HASH_INVALID_ALGORITHM); - } - return S2N_SUCCESS; -} - int s2n_hash_digest_size(s2n_hash_algorithm alg, uint8_t *out) { - notnull_check(out); + ENSURE_POSIX(S2N_MEM_IS_WRITABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION); switch (alg) { case S2N_HASH_NONE: *out = 0; break; case S2N_HASH_MD5: *out = MD5_DIGEST_LENGTH; break; @@ -63,7 +45,7 @@ int s2n_hash_digest_size(s2n_hash_algorithm alg, uint8_t *out) * If this ever becomes untrue, this would require fixing*/ int s2n_hash_block_size(s2n_hash_algorithm alg, uint64_t *block_size) { - ENSURE_POSIX(S2N_MEM_IS_READABLE(block_size, sizeof(*block_size)), S2N_ERR_PRECONDITION_VIOLATION); + ENSURE_POSIX(S2N_MEM_IS_WRITABLE(block_size, sizeof(*block_size)), S2N_ERR_PRECONDITION_VIOLATION); switch(alg) { case S2N_HASH_NONE: *block_size = 64; break; case S2N_HASH_MD5: *block_size = 64; break; @@ -523,7 +505,6 @@ int s2n_hash_new(struct s2n_hash_state *state) S2N_RESULT s2n_hash_state_validate(struct s2n_hash_state *state) { ENSURE_REF(state); - ENSURE_REF(state->hash_impl); return S2N_RESULT_OK; } @@ -623,7 +604,7 @@ int s2n_hash_free(struct s2n_hash_state *state) int s2n_hash_get_currently_in_hash_total(struct s2n_hash_state *state, uint64_t *out) { PRECONDITION_POSIX(s2n_hash_state_validate(state)); - ENSURE_POSIX(S2N_MEM_IS_READABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION); + ENSURE_POSIX(S2N_MEM_IS_WRITABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION); ENSURE_POSIX(state->is_ready_for_input, S2N_ERR_HASH_NOT_READY); *out = state->currently_in_hash; @@ -635,7 +616,7 @@ int s2n_hash_get_currently_in_hash_total(struct s2n_hash_state *state, uint64_t int s2n_hash_const_time_get_currently_in_hash_block(struct s2n_hash_state *state, uint64_t *out) { PRECONDITION_POSIX(s2n_hash_state_validate(state)); - ENSURE_POSIX(S2N_MEM_IS_READABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION); + ENSURE_POSIX(S2N_MEM_IS_WRITABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION); ENSURE_POSIX(state->is_ready_for_input, S2N_ERR_HASH_NOT_READY); uint64_t hash_block_size; GUARD(s2n_hash_block_size(state->alg, &hash_block_size)); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hmac.c b/contrib/restricted/aws/s2n/crypto/s2n_hmac.c index 8f5acf045a..2689545abb 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_hmac.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_hmac.c @@ -28,9 +28,27 @@ #include <stdint.h> +int s2n_hash_hmac_alg(s2n_hash_algorithm hash_alg, s2n_hmac_algorithm *out) +{ + ENSURE_POSIX(S2N_MEM_IS_WRITABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION); + switch(hash_alg) { + case S2N_HASH_NONE: *out = S2N_HMAC_NONE; break; + case S2N_HASH_MD5: *out = S2N_HMAC_MD5; break; + case S2N_HASH_SHA1: *out = S2N_HMAC_SHA1; break; + case S2N_HASH_SHA224: *out = S2N_HMAC_SHA224; break; + case S2N_HASH_SHA256: *out = S2N_HMAC_SHA256; break; + case S2N_HASH_SHA384: *out = S2N_HMAC_SHA384; break; + case S2N_HASH_SHA512: *out = S2N_HMAC_SHA512; break; + case S2N_HASH_MD5_SHA1: /* Fall through ... */ + default: + S2N_ERROR(S2N_ERR_HASH_INVALID_ALGORITHM); + } + return S2N_SUCCESS; +} int s2n_hmac_hash_alg(s2n_hmac_algorithm hmac_alg, s2n_hash_algorithm *out) { + ENSURE_POSIX(S2N_MEM_IS_WRITABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION); switch(hmac_alg) { case S2N_HMAC_NONE: *out = S2N_HASH_NONE; break; case S2N_HMAC_MD5: *out = S2N_HASH_MD5; break; @@ -44,7 +62,7 @@ int s2n_hmac_hash_alg(s2n_hmac_algorithm hmac_alg, s2n_hash_algorithm *out) default: S2N_ERROR(S2N_ERR_HMAC_INVALID_ALGORITHM); } - return 0; + return S2N_SUCCESS; } int s2n_hmac_digest_size(s2n_hmac_algorithm hmac_alg, uint8_t *out) @@ -52,33 +70,27 @@ int s2n_hmac_digest_size(s2n_hmac_algorithm hmac_alg, uint8_t *out) s2n_hash_algorithm hash_alg; GUARD(s2n_hmac_hash_alg(hmac_alg, &hash_alg)); GUARD(s2n_hash_digest_size(hash_alg, out)); - return 0; + return S2N_SUCCESS; } /* Return 1 if hmac algorithm is available, 0 otherwise. */ -int s2n_hmac_is_available(s2n_hmac_algorithm hmac_alg) +bool s2n_hmac_is_available(s2n_hmac_algorithm hmac_alg) { - int is_available = 0; switch(hmac_alg) { case S2N_HMAC_MD5: case S2N_HMAC_SSLv3_MD5: case S2N_HMAC_SSLv3_SHA1: /* Set is_available to 0 if in FIPS mode, as MD5/SSLv3 algs are not available in FIPS mode. */ - is_available = !s2n_is_in_fips_mode(); - break; - case S2N_HMAC_NONE: + return !s2n_is_in_fips_mode(); + case S2N_HMAC_NONE: case S2N_HMAC_SHA1: case S2N_HMAC_SHA224: case S2N_HMAC_SHA256: case S2N_HMAC_SHA384: case S2N_HMAC_SHA512: - is_available = 1; - break; - default: - S2N_ERROR(S2N_ERR_HMAC_INVALID_ALGORITHM); + return true; } - - return is_available; + return false; } static int s2n_sslv3_mac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm alg, const void *key, uint32_t klen) @@ -97,13 +109,13 @@ static int s2n_sslv3_mac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm a GUARD(s2n_hash_update(&state->outer_just_key, key, klen)); GUARD(s2n_hash_update(&state->outer_just_key, state->xor_pad, state->xor_pad_size)); - return 0; + return S2N_SUCCESS; } static int s2n_tls_hmac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm alg, const void *key, uint32_t klen) { memset(&state->xor_pad, 0, sizeof(state->xor_pad)); - + if (klen > state->xor_pad_size) { GUARD(s2n_hash_update(&state->outer, key, klen)); GUARD(s2n_hash_digest(&state->outer, state->digest_pad, state->digest_size)); @@ -124,11 +136,12 @@ static int s2n_tls_hmac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm al } GUARD(s2n_hash_update(&state->outer_just_key, state->xor_pad, state->xor_pad_size)); - return 0; + return S2N_SUCCESS; } int s2n_hmac_xor_pad_size(s2n_hmac_algorithm hmac_alg, uint16_t *xor_pad_size) { + ENSURE_POSIX(S2N_MEM_IS_WRITABLE(xor_pad_size, sizeof(*xor_pad_size)), S2N_ERR_PRECONDITION_VIOLATION); switch(hmac_alg) { case S2N_HMAC_NONE: *xor_pad_size = 64; break; case S2N_HMAC_MD5: *xor_pad_size = 64; break; @@ -142,11 +155,12 @@ int s2n_hmac_xor_pad_size(s2n_hmac_algorithm hmac_alg, uint16_t *xor_pad_size) default: S2N_ERROR(S2N_ERR_HMAC_INVALID_ALGORITHM); } - return 0; + return S2N_SUCCESS; } int s2n_hmac_hash_block_size(s2n_hmac_algorithm hmac_alg, uint16_t *block_size) { + ENSURE_POSIX(S2N_MEM_IS_WRITABLE(block_size, sizeof(*block_size)), S2N_ERR_PRECONDITION_VIOLATION); switch(hmac_alg) { case S2N_HMAC_NONE: *block_size = 64; break; case S2N_HMAC_MD5: *block_size = 64; break; @@ -160,21 +174,33 @@ int s2n_hmac_hash_block_size(s2n_hmac_algorithm hmac_alg, uint16_t *block_size) default: S2N_ERROR(S2N_ERR_HMAC_INVALID_ALGORITHM); } - return 0; + return S2N_SUCCESS; } int s2n_hmac_new(struct s2n_hmac_state *state) { + ENSURE_POSIX_REF(state); GUARD(s2n_hash_new(&state->inner)); GUARD(s2n_hash_new(&state->inner_just_key)); GUARD(s2n_hash_new(&state->outer)); GUARD(s2n_hash_new(&state->outer_just_key)); + POSTCONDITION_POSIX(s2n_hmac_state_validate(state)); + return S2N_SUCCESS; +} - return 0; +S2N_RESULT s2n_hmac_state_validate(struct s2n_hmac_state *state) +{ + ENSURE_REF(state); + GUARD_RESULT(s2n_hash_state_validate(&state->inner)); + GUARD_RESULT(s2n_hash_state_validate(&state->inner_just_key)); + GUARD_RESULT(s2n_hash_state_validate(&state->outer)); + GUARD_RESULT(s2n_hash_state_validate(&state->outer_just_key)); + return S2N_RESULT_OK; } int s2n_hmac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm alg, const void *key, uint32_t klen) { + notnull_check(state); if (!s2n_hmac_is_available(alg)) { /* Prevent hmacs from being used if they are not available. */ S2N_ERROR(S2N_ERR_HMAC_INVALID_ALGORITHM); @@ -212,20 +238,22 @@ int s2n_hmac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm alg, const vo memset(&state->xor_pad, 0, sizeof(state->xor_pad)); GUARD(s2n_hmac_reset(state)); - return 0; + return S2N_SUCCESS; } int s2n_hmac_update(struct s2n_hmac_state *state, const void *in, uint32_t size) { + PRECONDITION_POSIX(s2n_hmac_state_validate(state)); + ENSURE_POSIX(state->hash_block_size != 0, S2N_ERR_PRECONDITION_VIOLATION); /* Keep track of how much of the current hash block is full * * Why the 4294949760 constant in this code? 4294949760 is the highest 32-bit * value that is congruent to 0 modulo all of our HMAC block sizes, that is also * at least 16k smaller than 2^32. It therefore has no effect on the mathematical * result, and no valid record size can cause it to overflow. - * + * * The value was found with the following python code; - * + * * x = (2 ** 32) - (2 ** 14) * while True: * if x % 40 | x % 48 | x % 64 | x % 128 == 0: @@ -238,7 +266,10 @@ int s2n_hmac_update(struct s2n_hmac_state *state, const void *in, uint32_t size) * input. On some platforms, including Intel, the operation can take a * smaller number of cycles if the input is "small". */ - state->currently_in_hash_block += (4294949760 + size) % state->hash_block_size; + const uint32_t HIGHEST_32_BIT = 4294949760; + ENSURE_POSIX(size <= (UINT32_MAX - HIGHEST_32_BIT), S2N_ERR_INTEGER_OVERFLOW); + uint32_t value = (HIGHEST_32_BIT + size) % state->hash_block_size; + GUARD(s2n_add_overflow(state->currently_in_hash_block, value, &state->currently_in_hash_block)); state->currently_in_hash_block %= state->hash_block_size; return s2n_hash_update(&state->inner, in, size); @@ -246,6 +277,7 @@ int s2n_hmac_update(struct s2n_hmac_state *state, const void *in, uint32_t size) int s2n_hmac_digest(struct s2n_hmac_state *state, void *out, uint32_t size) { + PRECONDITION_POSIX(s2n_hmac_state_validate(state)); GUARD(s2n_hash_digest(&state->inner, state->digest_pad, state->digest_size)); GUARD(s2n_hash_copy(&state->outer, &state->outer_just_key)); GUARD(s2n_hash_update(&state->outer, state->digest_pad, state->digest_size)); @@ -267,8 +299,8 @@ int s2n_hmac_digest_two_compression_rounds(struct s2n_hmac_state *state, void *o * 17 bytes if the block size is 128. */ const uint8_t space_left = (state->hash_block_size == 128) ? 17 : 9; - if (state->currently_in_hash_block > (state->hash_block_size - space_left)) { - return 0; + if ((int64_t)state->currently_in_hash_block > (state->hash_block_size - space_left)) { + return S2N_SUCCESS; } /* Can't reuse a hash after it has been finalized, so reset and push another block in */ @@ -280,32 +312,40 @@ int s2n_hmac_digest_two_compression_rounds(struct s2n_hmac_state *state, void *o int s2n_hmac_free(struct s2n_hmac_state *state) { - GUARD(s2n_hash_free(&state->inner)); - GUARD(s2n_hash_free(&state->inner_just_key)); - GUARD(s2n_hash_free(&state->outer)); - GUARD(s2n_hash_free(&state->outer_just_key)); + if (state) { + GUARD(s2n_hash_free(&state->inner)); + GUARD(s2n_hash_free(&state->inner_just_key)); + GUARD(s2n_hash_free(&state->outer)); + GUARD(s2n_hash_free(&state->outer_just_key)); + } - return 0; + return S2N_SUCCESS; } int s2n_hmac_reset(struct s2n_hmac_state *state) { + PRECONDITION_POSIX(s2n_hmac_state_validate(state)); + ENSURE_POSIX(state->hash_block_size != 0, S2N_ERR_PRECONDITION_VIOLATION); GUARD(s2n_hash_copy(&state->inner, &state->inner_just_key)); - + uint64_t bytes_in_hash; GUARD(s2n_hash_get_currently_in_hash_total(&state->inner, &bytes_in_hash)); + bytes_in_hash %= state->hash_block_size; + ENSURE_POSIX(bytes_in_hash <= UINT32_MAX, S2N_ERR_INTEGER_OVERFLOW); /* The length of the key is not private, so don't need to do tricky math here */ - state->currently_in_hash_block = bytes_in_hash % state->hash_block_size; - return 0; + state->currently_in_hash_block = bytes_in_hash; + return S2N_SUCCESS; } int s2n_hmac_digest_verify(const void *a, const void *b, uint32_t len) { - return 0 - !s2n_constant_time_equals(a, b, len); + return S2N_SUCCESS - !s2n_constant_time_equals(a, b, len); } int s2n_hmac_copy(struct s2n_hmac_state *to, struct s2n_hmac_state *from) { + PRECONDITION_POSIX(s2n_hmac_state_validate(to)); + PRECONDITION_POSIX(s2n_hmac_state_validate(from)); /* memcpy cannot be used on s2n_hmac_state as the underlying s2n_hash implementation's * copy must be used. This is enforced when the s2n_hash implementation is s2n_evp_hash. */ @@ -323,28 +363,34 @@ int s2n_hmac_copy(struct s2n_hmac_state *to, struct s2n_hmac_state *from) memcpy_check(to->xor_pad, from->xor_pad, sizeof(to->xor_pad)); memcpy_check(to->digest_pad, from->digest_pad, sizeof(to->digest_pad)); - - return 0; + POSTCONDITION_POSIX(s2n_hmac_state_validate(to)); + POSTCONDITION_POSIX(s2n_hmac_state_validate(from)); + return S2N_SUCCESS; } -/* Preserve the handlers for hmac state pointers to avoid re-allocation +/* Preserve the handlers for hmac state pointers to avoid re-allocation * Only valid if the HMAC is in EVP mode */ int s2n_hmac_save_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac) { + ENSURE_POSIX_REF(backup); + PRECONDITION_POSIX(s2n_hmac_state_validate(hmac)); backup->inner = hmac->inner.digest.high_level; backup->inner_just_key = hmac->inner_just_key.digest.high_level; backup->outer = hmac->outer.digest.high_level; backup->outer_just_key = hmac->outer_just_key.digest.high_level; - return 0; + return S2N_SUCCESS; } int s2n_hmac_restore_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac) { + ENSURE_POSIX_REF(backup); + PRECONDITION_POSIX(s2n_hmac_state_validate(hmac)); hmac->inner.digest.high_level = backup->inner; hmac->inner_just_key.digest.high_level = backup->inner_just_key; hmac->outer.digest.high_level = backup->outer; hmac->outer_just_key.digest.high_level = backup->outer_just_key; - return 0; + POSTCONDITION_POSIX(s2n_hmac_state_validate(hmac)); + return S2N_SUCCESS; } diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hmac.h b/contrib/restricted/aws/s2n/crypto/s2n_hmac.h index b54966f8c3..34f8314b2d 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_hmac.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_hmac.h @@ -60,11 +60,12 @@ struct s2n_hmac_evp_backup { }; extern int s2n_hmac_digest_size(s2n_hmac_algorithm alg, uint8_t *out); -extern int s2n_hmac_is_available(s2n_hmac_algorithm alg); +extern bool s2n_hmac_is_available(s2n_hmac_algorithm alg); extern int s2n_hmac_hash_alg(s2n_hmac_algorithm hmac_alg, s2n_hash_algorithm *out); extern int s2n_hash_hmac_alg(s2n_hash_algorithm hash_alg, s2n_hmac_algorithm *out); extern int s2n_hmac_new(struct s2n_hmac_state *state); +S2N_RESULT s2n_hmac_state_validate(struct s2n_hmac_state *state); extern int s2n_hmac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm alg, const void *key, uint32_t klen); extern int s2n_hmac_update(struct s2n_hmac_state *state, const void *in, uint32_t size); extern int s2n_hmac_digest(struct s2n_hmac_state *state, void *out, uint32_t size); @@ -75,5 +76,3 @@ extern int s2n_hmac_reset(struct s2n_hmac_state *state); extern int s2n_hmac_copy(struct s2n_hmac_state *to, struct s2n_hmac_state *from); extern int s2n_hmac_save_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac); extern int s2n_hmac_restore_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac); - - diff --git a/contrib/restricted/aws/s2n/crypto/s2n_pkey.c b/contrib/restricted/aws/s2n/crypto/s2n_pkey.c index 9123e88080..69c0c25178 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_pkey.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_pkey.c @@ -21,8 +21,11 @@ #include "crypto/s2n_rsa_pss.h" #include "crypto/s2n_pkey.h" +#include "utils/s2n_result.h" #include "utils/s2n_safety.h" +#define S2N_MAX_ALLOWED_CERT_TRAILING_BYTES 3 + int s2n_pkey_zero_init(struct s2n_pkey *pkey) { pkey->pkey = NULL; @@ -61,11 +64,15 @@ int s2n_pkey_check_key_exists(const struct s2n_pkey *pkey) return pkey->check_key(pkey); } -int s2n_pkey_size(const struct s2n_pkey *pkey) +S2N_RESULT s2n_pkey_size(const struct s2n_pkey *pkey, uint32_t *size_out) { - notnull_check(pkey->size); + ENSURE_REF(pkey); + ENSURE_REF(pkey->size); + ENSURE_REF(size_out); + + GUARD_RESULT(pkey->size(pkey, size_out)); - return pkey->size(pkey); + return S2N_RESULT_OK; } int s2n_pkey_sign(const struct s2n_pkey *pkey, s2n_signature_algorithm sig_alg, @@ -185,10 +192,10 @@ int s2n_asn1der_to_public_key_and_type(struct s2n_pkey *pub_key, s2n_pkey_type * /* If cert parsing is successful, d2i_X509 increments *cert_to_parse to the byte following the parsed data */ uint32_t parsed_len = cert_to_parse - asn1der->data; - /* Some TLS clients in the wild send one extra trailing byte after the Certificate. + /* Some TLS clients in the wild send extra trailing bytes after the Certificate. * Allow this in s2n for backwards compatibility with existing clients. */ uint32_t trailing_bytes = asn1der->size - parsed_len; - ENSURE_POSIX(trailing_bytes <= 1, S2N_ERR_DECODE_CERTIFICATE); + ENSURE_POSIX(trailing_bytes <= S2N_MAX_ALLOWED_CERT_TRAILING_BYTES, S2N_ERR_DECODE_CERTIFICATE); DEFER_CLEANUP(EVP_PKEY *evp_public_key = X509_get_pubkey(cert), EVP_PKEY_free_pointer); S2N_ERROR_IF(evp_public_key == NULL, S2N_ERR_DECODE_CERTIFICATE); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_pkey.h b/contrib/restricted/aws/s2n/crypto/s2n_pkey.h index 1da8f785c6..0edc9f662e 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_pkey.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_pkey.h @@ -23,6 +23,7 @@ #include "crypto/s2n_rsa.h" #include "utils/s2n_blob.h" +#include "utils/s2n_result.h" /* Public/Private Key Type */ typedef enum { @@ -43,7 +44,7 @@ struct s2n_pkey { } key; EVP_PKEY *pkey; - int (*size)(const struct s2n_pkey *key); + S2N_RESULT (*size)(const struct s2n_pkey *key, uint32_t *size_out); int (*sign)(const struct s2n_pkey *priv_key, s2n_signature_algorithm sig_alg, struct s2n_hash_state *digest, struct s2n_blob *signature); int (*verify)(const struct s2n_pkey *pub_key, s2n_signature_algorithm sig_alg, @@ -59,7 +60,7 @@ int s2n_pkey_zero_init(struct s2n_pkey *pkey); int s2n_pkey_setup_for_type(struct s2n_pkey *pkey, s2n_pkey_type pkey_type); int s2n_pkey_check_key_exists(const struct s2n_pkey *pkey); -int s2n_pkey_size(const struct s2n_pkey *pkey); +S2N_RESULT s2n_pkey_size(const struct s2n_pkey *pkey, uint32_t *size_out); int s2n_pkey_sign(const struct s2n_pkey *pkey, s2n_signature_algorithm sig_alg, struct s2n_hash_state *digest, struct s2n_blob *signature); int s2n_pkey_verify(const struct s2n_pkey *pkey, s2n_signature_algorithm sig_alg, diff --git a/contrib/restricted/aws/s2n/crypto/s2n_rsa.c b/contrib/restricted/aws/s2n/crypto/s2n_rsa.c index 38eba11e0b..cfce3054bf 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_rsa.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_rsa.c @@ -13,51 +13,57 @@ * permissions and limitations under the License. */ +#include "crypto/s2n_rsa.h" + #include <openssl/evp.h> #include <openssl/rsa.h> #include <stdint.h> -#include "error/s2n_errno.h" - -#include "stuffer/s2n_stuffer.h" - -#include "crypto/s2n_hash.h" #include "crypto/s2n_drbg.h" -#include "crypto/s2n_rsa.h" -#include "crypto/s2n_rsa_signing.h" +#include "crypto/s2n_hash.h" #include "crypto/s2n_pkey.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_random.h" +#include "crypto/s2n_rsa_signing.h" +#include "error/s2n_errno.h" +#include "stuffer/s2n_stuffer.h" #include "utils/s2n_blob.h" +#include "utils/s2n_random.h" +#include "utils/s2n_result.h" +#include "utils/s2n_safety.h" -static int s2n_rsa_modulus_check(RSA *rsa) +static S2N_RESULT s2n_rsa_modulus_check(RSA *rsa) { - /* RSA was made opaque starting in Openssl 1.1.0 */ - #if S2N_OPENSSL_VERSION_AT_LEAST(1,1,0) && !defined(LIBRESSL_VERSION_NUMBER) - const BIGNUM *n = NULL; - /* RSA still owns the memory for n */ - RSA_get0_key(rsa, &n, NULL, NULL); - notnull_check(n); - #else - notnull_check(rsa->n); - #endif - return 0; +/* RSA was made opaque starting in Openssl 1.1.0 */ +#if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0) && !defined(LIBRESSL_VERSION_NUMBER) + const BIGNUM *n = NULL; + /* RSA still owns the memory for n */ + RSA_get0_key(rsa, &n, NULL, NULL); + ENSURE_REF(n); +#else + ENSURE_REF(rsa->n); +#endif + return S2N_RESULT_OK; } -static int s2n_rsa_encrypted_size(const struct s2n_pkey *key) +static S2N_RESULT s2n_rsa_encrypted_size(const struct s2n_pkey *key, uint32_t *size_out) { + ENSURE_REF(key); + ENSURE_REF(size_out); + const struct s2n_rsa_key *rsa_key = &key->key.rsa_key; - notnull_check(rsa_key->rsa); - GUARD(s2n_rsa_modulus_check(rsa_key->rsa)); + ENSURE_REF(rsa_key->rsa); + GUARD_RESULT(s2n_rsa_modulus_check(rsa_key->rsa)); - return RSA_size(rsa_key->rsa); + const int size = RSA_size(rsa_key->rsa); + GUARD_AS_RESULT(size); + *size_out = size; + + return S2N_RESULT_OK; } -static int s2n_rsa_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig_alg, - struct s2n_hash_state *digest, struct s2n_blob *signature) +static int s2n_rsa_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig_alg, struct s2n_hash_state *digest, + struct s2n_blob *signature) { - switch(sig_alg) { + switch (sig_alg) { case S2N_SIGNATURE_RSA: return s2n_rsa_pkcs1v15_sign(priv, digest, signature); case S2N_SIGNATURE_RSA_PSS_RSAE: @@ -69,10 +75,10 @@ static int s2n_rsa_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig return S2N_SUCCESS; } -static int s2n_rsa_verify(const struct s2n_pkey *pub, s2n_signature_algorithm sig_alg, - struct s2n_hash_state *digest, struct s2n_blob *signature) +static int s2n_rsa_verify(const struct s2n_pkey *pub, s2n_signature_algorithm sig_alg, struct s2n_hash_state *digest, + struct s2n_blob *signature) { - switch(sig_alg) { + switch (sig_alg) { case S2N_SIGNATURE_RSA: return s2n_rsa_pkcs1v15_verify(pub, digest, signature); case S2N_SIGNATURE_RSA_PSS_RSAE: @@ -86,10 +92,13 @@ static int s2n_rsa_verify(const struct s2n_pkey *pub, s2n_signature_algorithm si static int s2n_rsa_encrypt(const struct s2n_pkey *pub, struct s2n_blob *in, struct s2n_blob *out) { - S2N_ERROR_IF(out->size < s2n_rsa_encrypted_size(pub), S2N_ERR_NOMEM); + uint32_t size = 0; + GUARD_AS_POSIX(s2n_rsa_encrypted_size(pub, &size)); + S2N_ERROR_IF(out->size < size, S2N_ERR_NOMEM); const s2n_rsa_public_key *key = &pub->key.rsa_key; - int r = RSA_public_encrypt(in->size, (unsigned char *)in->data, (unsigned char *)out->data, key->rsa, RSA_PKCS1_PADDING); + int r = RSA_public_encrypt(in->size, ( unsigned char * )in->data, ( unsigned char * )out->data, key->rsa, + RSA_PKCS1_PADDING); S2N_ERROR_IF(r != out->size, S2N_ERR_SIZE_MISMATCH); return 0; @@ -97,17 +106,18 @@ static int s2n_rsa_encrypt(const struct s2n_pkey *pub, struct s2n_blob *in, stru static int s2n_rsa_decrypt(const struct s2n_pkey *priv, struct s2n_blob *in, struct s2n_blob *out) { - unsigned char intermediate[4096]; - const int expected_size = s2n_rsa_encrypted_size(priv); + unsigned char intermediate[ 4096 ]; + uint32_t expected_size = 0; + + GUARD_AS_POSIX(s2n_rsa_encrypted_size(priv, &expected_size)); - GUARD(expected_size); S2N_ERROR_IF(expected_size > sizeof(intermediate), S2N_ERR_NOMEM); S2N_ERROR_IF(out->size > sizeof(intermediate), S2N_ERR_NOMEM); GUARD_AS_POSIX(s2n_get_public_random_data(out)); const s2n_rsa_private_key *key = &priv->key.rsa_key; - int r = RSA_private_decrypt(in->size, (unsigned char *)in->data, intermediate, key->rsa, RSA_NO_PADDING); + int r = RSA_private_decrypt(in->size, ( unsigned char * )in->data, intermediate, key->rsa, RSA_NO_PADDING); S2N_ERROR_IF(r != expected_size, S2N_ERR_SIZE_MISMATCH); s2n_constant_time_pkcs1_unpad_or_dont(out->data, intermediate, r, out->size); @@ -117,14 +127,14 @@ static int s2n_rsa_decrypt(const struct s2n_pkey *priv, struct s2n_blob *in, str static int s2n_rsa_keys_match(const struct s2n_pkey *pub, const struct s2n_pkey *priv) { - uint8_t plain_inpad[36] = {1}, plain_outpad[36] = {0}, encpad[8192]; + uint8_t plain_inpad[ 36 ] = { 1 }, plain_outpad[ 36 ] = { 0 }, encpad[ 8192 ]; struct s2n_blob plain_in = { 0 }, plain_out = { 0 }, enc = { 0 }; plain_in.data = plain_inpad; plain_in.size = sizeof(plain_inpad); enc.data = encpad; - enc.size = s2n_rsa_encrypted_size(pub); + GUARD_AS_POSIX(s2n_rsa_encrypted_size(pub, &enc.size)); lte_check(enc.size, sizeof(encpad)); GUARD(s2n_rsa_encrypt(pub, &plain_in, &enc)); @@ -140,9 +150,7 @@ static int s2n_rsa_keys_match(const struct s2n_pkey *pub, const struct s2n_pkey static int s2n_rsa_key_free(struct s2n_pkey *pkey) { struct s2n_rsa_key *rsa_key = &pkey->key.rsa_key; - if (rsa_key->rsa == NULL) { - return 0; - } + if (rsa_key->rsa == NULL) { return 0; } RSA_free(rsa_key->rsa); rsa_key->rsa = NULL; @@ -177,13 +185,13 @@ int s2n_evp_pkey_to_rsa_private_key(s2n_rsa_private_key *rsa_key, EVP_PKEY *evp_ int s2n_rsa_pkey_init(struct s2n_pkey *pkey) { - pkey->size = &s2n_rsa_encrypted_size; - pkey->sign = &s2n_rsa_sign; - pkey->verify = &s2n_rsa_verify; - pkey->encrypt = &s2n_rsa_encrypt; - pkey->decrypt = &s2n_rsa_decrypt; - pkey->match = &s2n_rsa_keys_match; - pkey->free = &s2n_rsa_key_free; + pkey->size = &s2n_rsa_encrypted_size; + pkey->sign = &s2n_rsa_sign; + pkey->verify = &s2n_rsa_verify; + pkey->encrypt = &s2n_rsa_encrypt; + pkey->decrypt = &s2n_rsa_decrypt; + pkey->match = &s2n_rsa_keys_match; + pkey->free = &s2n_rsa_key_free; pkey->check_key = &s2n_rsa_check_key_exists; return 0; } diff --git a/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c b/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c index 1bb444b25c..98fbd6ad23 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c @@ -41,12 +41,17 @@ int s2n_is_rsa_pss_certs_supported() #if RSA_PSS_CERTS_SUPPORTED -static int s2n_rsa_pss_size(const struct s2n_pkey *key) +static S2N_RESULT s2n_rsa_pss_size(const struct s2n_pkey *key, uint32_t *size_out) { - notnull_check(key); + ENSURE_REF(key); + ENSURE_REF(size_out); /* For more info, see: https://www.openssl.org/docs/man1.1.0/man3/EVP_PKEY_size.html */ - return EVP_PKEY_size(key->pkey); + const int size = EVP_PKEY_size(key->pkey); + GUARD_AS_RESULT(size); + *size_out = size; + + return S2N_RESULT_OK; } static int s2n_rsa_is_private_key(RSA *rsa_key) diff --git a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c index 978ce2431e..1b472937ad 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c @@ -41,7 +41,7 @@ * [x] client_application_traffic_secret_0 * [x] server_application_traffic_secret_0 * [ ] exporter_master_secret - * [ ] resumption_master_secret + * [x] resumption_master_secret * * The TLS 1.3 key generation can be divided into 3 phases * 1. early secrets @@ -74,6 +74,7 @@ S2N_BLOB_LABEL(s2n_tls13_label_server_application_traffic_secret, "s ap traffic" S2N_BLOB_LABEL(s2n_tls13_label_exporter_master_secret, "exp master") S2N_BLOB_LABEL(s2n_tls13_label_resumption_master_secret, "res master") +S2N_BLOB_LABEL(s2n_tls13_label_session_ticket_secret, "resumption") /* * Traffic secret labels @@ -172,14 +173,21 @@ int s2n_tls13_derive_binder_key(struct s2n_tls13_keys *keys, struct s2n_psk *psk /* * Derives early secrets */ -int s2n_tls13_derive_early_secrets(struct s2n_tls13_keys *keys) +int s2n_tls13_derive_early_secrets(struct s2n_tls13_keys *keys, struct s2n_psk *psk) { notnull_check(keys); - s2n_tls13_key_blob(psk_ikm, keys->size); /* in 1-RTT, PSK is 0-filled of key length */ - /* Early Secret */ - GUARD(s2n_hkdf_extract(&keys->hmac, keys->hmac_algorithm, &zero_length_blob, &psk_ikm, &keys->extract_secret)); + if (psk == NULL) { + /* in 1-RTT, PSK is 0-filled of key length */ + s2n_tls13_key_blob(psk_ikm, keys->size); + + GUARD(s2n_hkdf_extract(&keys->hmac, keys->hmac_algorithm, &zero_length_blob, &psk_ikm, &keys->extract_secret)); + } else { + /* Sanity check that an early secret exists */ + ne_check(psk->early_secret.size, 0); + keys->extract_secret = psk->early_secret; + } /* client_early_traffic_secret and early_exporter_master_secret can be derived here */ @@ -189,7 +197,7 @@ int s2n_tls13_derive_early_secrets(struct s2n_tls13_keys *keys) GUARD(s2n_hkdf_expand_label(&keys->hmac, keys->hmac_algorithm, &keys->extract_secret, &s2n_tls13_label_derived_secret, &message_digest, &keys->derive_secret)); - return 0; + return S2N_SUCCESS; } /* @@ -336,3 +344,42 @@ int s2n_tls13_update_application_traffic_secret(struct s2n_tls13_keys *keys, str return 0; } + +int s2n_tls13_derive_resumption_master_secret(struct s2n_tls13_keys *keys, struct s2n_hash_state *hashes, struct s2n_blob *secret_blob) +{ + notnull_check(keys); + notnull_check(hashes); + notnull_check(secret_blob); + + /* Sanity check that input hash is of expected type */ + ENSURE_POSIX(keys->hash_algorithm == hashes->alg, S2N_ERR_HASH_INVALID_ALGORITHM); + + s2n_tls13_key_blob(message_digest, keys->size); + + /* Copy the hashes into the message_digest */ + DEFER_CLEANUP(struct s2n_hash_state hkdf_hash_copy, s2n_hash_free); + GUARD(s2n_hash_new(&hkdf_hash_copy)); + GUARD(s2n_hash_copy(&hkdf_hash_copy, hashes)); + GUARD(s2n_hash_digest(&hkdf_hash_copy, message_digest.data, message_digest.size)); + + /* Derive master session resumption from master secret */ + GUARD(s2n_hkdf_expand_label(&keys->hmac, keys->hmac_algorithm, &keys->extract_secret, + &s2n_tls13_label_resumption_master_secret, &message_digest, secret_blob)); + + return S2N_SUCCESS; +} + +S2N_RESULT s2n_tls13_derive_session_ticket_secret(struct s2n_tls13_keys *keys, struct s2n_blob *resumption_secret, + struct s2n_blob *ticket_nonce, struct s2n_blob *secret_blob) +{ + ENSURE_REF(keys); + ENSURE_REF(resumption_secret); + ENSURE_REF(ticket_nonce); + ENSURE_REF(secret_blob); + + /* Derive session ticket secret from master session resumption secret */ + GUARD_AS_RESULT(s2n_hkdf_expand_label(&keys->hmac, keys->hmac_algorithm, resumption_secret, + &s2n_tls13_label_session_ticket_secret, ticket_nonce, secret_blob)); + + return S2N_RESULT_OK; +} diff --git a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h index c572f6edfd..cf4e6185f4 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h @@ -74,7 +74,7 @@ extern const struct s2n_blob s2n_tls13_label_traffic_secret_iv; int s2n_tls13_keys_init(struct s2n_tls13_keys *handshake, s2n_hmac_algorithm alg); int s2n_tls13_keys_free(struct s2n_tls13_keys *keys); int s2n_tls13_derive_binder_key(struct s2n_tls13_keys *keys, struct s2n_psk *psk); -int s2n_tls13_derive_early_secrets(struct s2n_tls13_keys *handshake); +int s2n_tls13_derive_early_secrets(struct s2n_tls13_keys *handshake, struct s2n_psk *psk); int s2n_tls13_derive_handshake_secrets(struct s2n_tls13_keys *handshake, const struct s2n_blob *ecdhe, struct s2n_hash_state *client_server_hello_hash, @@ -87,3 +87,7 @@ int s2n_tls13_derive_traffic_keys(struct s2n_tls13_keys *handshake, struct s2n_b int s2n_tls13_derive_finished_key(struct s2n_tls13_keys *keys, struct s2n_blob *secret_key, struct s2n_blob *output_finish_key); int s2n_tls13_calculate_finished_mac(struct s2n_tls13_keys *keys, struct s2n_blob *finished_key, struct s2n_hash_state *hash_state, struct s2n_blob *finished_verify); int s2n_tls13_update_application_traffic_secret(struct s2n_tls13_keys *keys, struct s2n_blob *old_secret, struct s2n_blob *new_secret); + +int s2n_tls13_derive_resumption_master_secret(struct s2n_tls13_keys *keys, struct s2n_hash_state *hashes, struct s2n_blob *secret_blob); +S2N_RESULT s2n_tls13_derive_session_ticket_secret(struct s2n_tls13_keys *keys, struct s2n_blob *resumption_secret, + struct s2n_blob *ticket_nonce, struct s2n_blob *secret_blob); diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.c b/contrib/restricted/aws/s2n/error/s2n_errno.c index 14c5450d96..1fcc1b6634 100644 --- a/contrib/restricted/aws/s2n/error/s2n_errno.c +++ b/contrib/restricted/aws/s2n/error/s2n_errno.c @@ -31,6 +31,14 @@ __thread int s2n_errno; __thread const char *s2n_debug_str; +/** + * Returns the address of the thread-local `s2n_errno` variable + */ +int *s2n_errno_location() +{ + return &s2n_errno; +} + static const char *no_such_language = "Language is not supported for error translation"; static const char *no_such_error = "Internal s2n error"; @@ -215,7 +223,6 @@ static const char *no_such_error = "Internal s2n error"; ERR_ENTRY(S2N_ERR_SESSION_TICKET_NOT_SUPPORTED, "Session ticket not supported for this connection") \ ERR_ENTRY(S2N_ERR_OCSP_NOT_SUPPORTED, "OCSP stapling was requested, but is not supported") \ ERR_ENTRY(S2N_ERR_INVALID_SIGNATURE_ALGORITHMS_PREFERENCES, "Invalid signature algorithms preferences version") \ - ERR_ENTRY(S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS, "PQ KEMs are disallowed while in FIPS mode") \ ERR_ENTRY(S2N_RSA_PSS_NOT_SUPPORTED, "RSA-PSS signing not supported by underlying libcrypto implementation") \ ERR_ENTRY(S2N_ERR_MAX_INNER_PLAINTEXT_SIZE, "Inner plaintext size exceeds limit") \ ERR_ENTRY(S2N_ERR_INVALID_ECC_PREFERENCES, "Invalid ecc curves preferences version") \ @@ -235,9 +242,12 @@ static const char *no_such_error = "Internal s2n error"; ERR_ENTRY(S2N_ERR_ASYNC_APPLY_WHILE_INVOKING, "Async private key operation cannot consumed inside async pkey callback") \ ERR_ENTRY(S2N_ERR_ASYNC_ALREADY_APPLIED, "Async operation was already applied to connection, cannot apply it again") \ ERR_ENTRY(S2N_ERR_INVALID_HELLO_RETRY, "Invalid hello retry request") \ - ERR_ENTRY(S2N_ERR_INVALID_STATE, "Invalid state, this is the result of invalid use of an API. Check the API documentation for the function that raised this error for more info.") \ + ERR_ENTRY(S2N_ERR_INVALID_STATE, "Invalid state, this is the result of invalid use of an API. Check the API documentation for the function that raised this error for more info") \ ERR_ENTRY(S2N_ERR_UNSUPPORTED_WITH_QUIC, "Functionality not supported when running with QUIC support enabled") \ - ERR_ENTRY(S2N_ERR_PQ_CRYPTO, "An error occurred in a post-quantum crypto function.") \ + ERR_ENTRY(S2N_ERR_PQ_CRYPTO, "An error occurred in a post-quantum crypto function") \ + ERR_ENTRY(S2N_ERR_PQ_DISABLED, "Post-quantum crypto is disabled") \ + ERR_ENTRY(S2N_ERR_DUPLICATE_PSK_IDENTITIES, "The list of pre-shared keys provided contains duplicate psk identities") \ + ERR_ENTRY(S2N_ERR_REENTRANCY, "Original execution must complete before method can be called again") \ /* clang-format on */ diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.h b/contrib/restricted/aws/s2n/error/s2n_errno.h index 9151feabd3..1c5afb8f2b 100644 --- a/contrib/restricted/aws/s2n/error/s2n_errno.h +++ b/contrib/restricted/aws/s2n/error/s2n_errno.h @@ -111,7 +111,6 @@ typedef enum { S2N_ERR_BAD_KEY_SHARE, S2N_ERR_CANCELLED, S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED, - S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS, S2N_ERR_MAX_INNER_PLAINTEXT_SIZE, S2N_ERR_RECORD_STUFFER_SIZE, S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE, @@ -200,6 +199,7 @@ typedef enum { S2N_ERR_ASYNC_MORE_THAN_ONE, S2N_ERR_INVALID_STATE, S2N_ERR_PQ_CRYPTO, + S2N_ERR_PQ_DISABLED, S2N_ERR_T_INTERNAL_END, /* S2N_ERR_T_USAGE */ @@ -261,6 +261,8 @@ typedef enum { S2N_ERR_ASYNC_APPLY_WHILE_INVOKING, S2N_ERR_ASYNC_ALREADY_APPLIED, S2N_ERR_UNSUPPORTED_WITH_QUIC, + S2N_ERR_DUPLICATE_PSK_IDENTITIES, + S2N_ERR_REENTRANCY, S2N_ERR_T_USAGE_END, } s2n_error; diff --git a/contrib/restricted/aws/s2n/pq-crypto/bike_r1/bike_r1_kem.c b/contrib/restricted/aws/s2n/pq-crypto/bike_r1/bike_r1_kem.c index cb566d7435..21b0b6f5a3 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/bike_r1/bike_r1_kem.c +++ b/contrib/restricted/aws/s2n/pq-crypto/bike_r1/bike_r1_kem.c @@ -13,6 +13,7 @@ #include "parallel_hash.h" #include "sampling.h" #include "tls/s2n_kem.h" +#include "pq-crypto/s2n_pq.h" _INLINE_ void split_e(OUT split_e_t *splitted_e, IN const e_t *e) @@ -155,6 +156,8 @@ get_ss(OUT ss_t *out, IN const e_t *e) int BIKE1_L1_R1_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); + // Convert to this implementation types pk_t *l_pk = (pk_t *)pk; @@ -211,6 +214,7 @@ BIKE1_L1_R1_crypto_kem_enc(OUT unsigned char * ct, IN const unsigned char *pk) { DMSG(" Enter crypto_kem_enc.\n"); + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); // Convert to this implementation types const pk_t *l_pk = (const pk_t *)pk; @@ -265,6 +269,7 @@ BIKE1_L1_R1_crypto_kem_dec(OUT unsigned char * ss, IN const unsigned char *sk) { DMSG(" Enter crypto_kem_dec.\n"); + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); // Convert to this implementation types const ct_t *l_ct = (const ct_t *)ct; diff --git a/contrib/restricted/aws/s2n/pq-crypto/bike_r2/bike_r2_kem.c b/contrib/restricted/aws/s2n/pq-crypto/bike_r2/bike_r2_kem.c index 3539827d14..8f29f3add9 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/bike_r2/bike_r2_kem.c +++ b/contrib/restricted/aws/s2n/pq-crypto/bike_r2/bike_r2_kem.c @@ -11,6 +11,7 @@ #include "sampling.h" #include "sha.h" #include "tls/s2n_kem.h" +#include "pq-crypto/s2n_pq.h" _INLINE_ void split_e(OUT split_e_t *splitted_e, IN const e_t *e) @@ -211,6 +212,8 @@ get_ss(OUT ss_t *out, IN const r_t *in0, IN const r_t *in1, IN const ct_t *ct) int BIKE1_L1_R2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); + notnull_check(sk); notnull_check(pk); @@ -283,6 +286,7 @@ BIKE1_L1_R2_crypto_kem_enc(OUT unsigned char * ct, IN const unsigned char *pk) { DMSG(" Enter crypto_kem_enc.\n"); + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); // Convert to the types that are used by this implementation const pk_t *l_pk = (const pk_t *)pk; @@ -323,6 +327,7 @@ BIKE1_L1_R2_crypto_kem_dec(OUT unsigned char * ss, IN const unsigned char *sk) { DMSG(" Enter crypto_kem_dec.\n"); + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); // Convert to the types used by this implementation const ct_t *l_ct = (const ct_t *)ct; diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_90s_r2/kyber_90s_r2_kem.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_90s_r2/kyber_90s_r2_kem.c index ff28dd0351..9de3c1daef 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/kyber_90s_r2/kyber_90s_r2_kem.c +++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_90s_r2/kyber_90s_r2_kem.c @@ -6,6 +6,7 @@ #include "../s2n_pq_random.h" #include "utils/s2n_safety.h" #include "tls/s2n_kem.h" +#include "pq-crypto/s2n_pq.h" #include <stdlib.h> @@ -21,6 +22,7 @@ * Returns 0 (success) **************************************************/ int kyber_512_90s_r2_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); size_t i; PQCLEAN_KYBER51290S_CLEAN_indcpa_keypair(pk, sk); for (i = 0; i < KYBER_INDCPA_PUBLICKEYBYTES; i++) { @@ -44,6 +46,7 @@ int kyber_512_90s_r2_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { * Returns 0 (success) **************************************************/ int kyber_512_90s_r2_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) { + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); uint8_t kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */ uint8_t buf[2 * KYBER_SYMBYTES]; @@ -75,6 +78,7 @@ int kyber_512_90s_r2_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) * On failure, ss will contain a pseudo-random value. **************************************************/ int kyber_512_90s_r2_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) { + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); size_t i; uint8_t fail; uint8_t cmp[KYBER_CIPHERTEXTBYTES]; diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_r2/kyber_r2_kem.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_r2/kyber_r2_kem.c index d9b64d4336..9871084bb4 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/kyber_r2/kyber_r2_kem.c +++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_r2/kyber_r2_kem.c @@ -6,6 +6,7 @@ #include "../s2n_pq_random.h" #include "utils/s2n_safety.h" #include "tls/s2n_kem.h" +#include "pq-crypto/s2n_pq.h" #include <stdlib.h> @@ -21,6 +22,7 @@ * Returns 0 (success) **************************************************/ int kyber_512_r2_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); size_t i; PQCLEAN_KYBER512_CLEAN_indcpa_keypair(pk, sk); for (i = 0; i < KYBER_INDCPA_PUBLICKEYBYTES; i++) { @@ -44,6 +46,7 @@ int kyber_512_r2_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { * Returns 0 (success) **************************************************/ int kyber_512_r2_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) { + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); uint8_t kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */ uint8_t buf[2 * KYBER_SYMBYTES]; @@ -75,6 +78,7 @@ int kyber_512_r2_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) { * On failure, ss will contain a pseudo-random value. **************************************************/ int kyber_512_r2_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) { + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); size_t i; uint8_t fail; uint8_t cmp[KYBER_CIPHERTEXTBYTES]; diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c index 858676fe67..3122eb6539 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c +++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c @@ -10,11 +10,13 @@ #include "pq-crypto/s2n_pq_random.h" #include "utils/s2n_safety.h" #include "tls/s2n_kem.h" +#include "pq-crypto/s2n_pq.h" int SIKE_P503_r1_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { // SIKE's key generation // Outputs: secret key sk (SIKE_P503_R1_SECRET_KEY_BYTES = MSG_BYTES + SECRETKEY_B_BYTES + SIKE_P503_R1_PUBLIC_KEY_BYTES bytes) // public key pk (SIKE_P503_R1_PUBLIC_KEY_BYTES bytes) + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); digit_t _sk[SECRETKEY_B_BYTES/sizeof(digit_t)]; @@ -38,6 +40,8 @@ int SIKE_P503_r1_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsi // Input: public key pk (SIKE_P503_R1_PUBLIC_KEY_BYTES bytes) // Outputs: shared secret ss (SIKE_P503_R1_SHARED_SECRET_BYTES bytes) // ciphertext message ct (SIKE_P503_R1_CIPHERTEXT_BYTES = SIKE_P503_R1_PUBLIC_KEY_BYTES + MSG_BYTES bytes) + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); + const uint16_t G = 0; const uint16_t H = 1; const uint16_t P = 2; @@ -78,6 +82,8 @@ int SIKE_P503_r1_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, cons // Input: secret key sk (SIKE_P503_R1_SECRET_KEY_BYTES = MSG_BYTES + SECRETKEY_B_BYTES + SIKE_P503_R1_PUBLIC_KEY_BYTES bytes) // ciphertext message ct (SIKE_P503_R1_CIPHERTEXT_BYTES = SIKE_P503_R1_PUBLIC_KEY_BYTES + MSG_BYTES bytes) // Outputs: shared secret ss (SIKE_P503_R1_SHARED_SECRET_BYTES bytes) + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); + const uint16_t G = 0; const uint16_t H = 1; const uint16_t P = 2; diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r2/sike_r2_kem.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r2/sike_r2_kem.c index 453e3b4690..7768ad3650 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/sike_r2/sike_r2_kem.c +++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r2/sike_r2_kem.c @@ -9,11 +9,13 @@ #include "fips202.h" #include "utils/s2n_safety.h" #include "tls/s2n_kem.h" +#include "pq-crypto/s2n_pq.h" int SIKE_P434_r2_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { // SIKE's key generation // Outputs: secret key sk (CRYPTO_SECRETKEYBYTES = MSG_BYTES + SECRETKEY_B_BYTES + CRYPTO_PUBLICKEYBYTES bytes) // public key pk (CRYPTO_PUBLICKEYBYTES bytes) + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); digit_t _sk[(SECRETKEY_B_BYTES / sizeof(digit_t)) + 1]; @@ -37,6 +39,7 @@ int SIKE_P434_r2_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsi // Input: public key pk (CRYPTO_PUBLICKEYBYTES bytes) // Outputs: shared secret ss (CRYPTO_BYTES bytes) // ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = CRYPTO_PUBLICKEYBYTES + MSG_BYTES bytes) + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); union { unsigned char b[SECRETKEY_A_BYTES]; @@ -75,6 +78,7 @@ int SIKE_P434_r2_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, cons // Input: secret key sk (CRYPTO_SECRETKEYBYTES = MSG_BYTES + SECRETKEY_B_BYTES + CRYPTO_PUBLICKEYBYTES bytes) // ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = CRYPTO_PUBLICKEYBYTES + MSG_BYTES bytes) // Outputs: shared secret ss (CRYPTO_BYTES bytes) + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); union { unsigned char b[SECRETKEY_A_BYTES]; diff --git a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_network_order.c b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_network_order.c index f30c10e82f..eb75409b6a 100644 --- a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_network_order.c +++ b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_network_order.c @@ -28,7 +28,7 @@ int s2n_stuffer_write_network_order(struct s2n_stuffer *stuffer, const uint64_t uint8_t *data = stuffer->blob.data + stuffer->write_cursor - length; for (int i = 0; i < length; i++) { - S2N_INVARIENT(i <= length); + S2N_INVARIANT(i <= length); uint8_t shift = (length - i - 1) * CHAR_BIT; data[i] = (input >> (shift)) & UINT8_MAX; } diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.c index 97797cc054..178f2e9c1d 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.c @@ -22,7 +22,7 @@ #include "stuffer/s2n_stuffer.h" #include "utils/s2n_safety.h" #include "tls/s2n_tls13.h" -#include "crypto/s2n_fips.h" +#include "pq-crypto/s2n_pq.h" #define S2N_IS_KEY_SHARE_LIST_EMPTY(preferred_key_shares) (preferred_key_shares & 1) #define S2N_IS_KEY_SHARE_REQUESTED(preferred_key_shares, i) ((preferred_key_shares >> (i + 1)) & 1) @@ -107,8 +107,8 @@ static int s2n_generate_pq_hybrid_key_share(struct s2n_stuffer *out, struct s2n_ notnull_check(out); notnull_check(kem_group_params); - /* This function should never be called when in FIPS mode */ - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + /* This function should never be called when PQ is disabled */ + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); const struct s2n_kem_group *kem_group = kem_group_params->kem_group; notnull_check(kem_group); @@ -144,8 +144,8 @@ static int s2n_generate_default_pq_hybrid_key_share(struct s2n_connection *conn, notnull_check(conn); notnull_check(out); - /* Client should skip sending PQ groups/key shares if in FIPS mode */ - if (s2n_is_in_fips_mode()) { + /* Client should skip sending PQ groups/key shares if PQ is disabled */ + if (!s2n_pq_is_enabled()) { return S2N_SUCCESS; } @@ -227,9 +227,9 @@ static int s2n_send_hrr_pq_hybrid_keyshare(struct s2n_connection *conn, struct s notnull_check(conn); notnull_check(out); - /* If in FIPS mode, the client should not have sent any PQ IDs + /* If PQ is disabled, the client should not have sent any PQ IDs * in the supported_groups list of the initial ClientHello */ - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); const struct s2n_kem_preferences *kem_pref = NULL; GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); @@ -377,7 +377,10 @@ static int s2n_client_key_share_recv_pq_hybrid(struct s2n_connection *conn, stru GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); notnull_check(kem_pref); - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + /* Ignore key share if PQ is not enabled */ + if (!s2n_pq_is_enabled()) { + return S2N_SUCCESS; + } const struct s2n_kem_group *kem_group = NULL; struct s2n_kem_group_params *client_kem_group_params = NULL; @@ -476,9 +479,7 @@ static int s2n_client_key_share_recv(struct s2n_connection *conn, struct s2n_stu /* Try to parse the share as ECC, then as PQ/hybrid; will ignore * shares for unrecognized groups. */ GUARD(s2n_client_key_share_recv_ecc(conn, &key_share, named_group, &match_found)); - if (!s2n_is_in_fips_mode()) { - GUARD(s2n_client_key_share_recv_pq_hybrid(conn, &key_share, named_group, &match_found)); - } + GUARD(s2n_client_key_share_recv_pq_hybrid(conn, &key_share, named_group, &match_found)); } /* If there were no matching key shares, then we received an empty key share extension diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c index 450e293299..83c4c8f1d0 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c @@ -21,6 +21,7 @@ #include "tls/s2n_security_policies.h" #include "tls/s2n_tls.h" #include "tls/s2n_tls_parameters.h" +#include "pq-crypto/s2n_pq.h" #include "utils/s2n_safety.h" @@ -41,7 +42,8 @@ static bool s2n_client_pq_kem_should_send(struct s2n_connection *conn) { const struct s2n_security_policy *security_policy; return s2n_connection_get_security_policy(conn, &security_policy) == S2N_SUCCESS - && s2n_pq_kem_is_extension_required(security_policy); + && s2n_pq_kem_is_extension_required(security_policy) + && s2n_pq_is_enabled(); } static int s2n_client_pq_kem_send(struct s2n_connection *conn, struct s2n_stuffer *out) @@ -63,6 +65,11 @@ static int s2n_client_pq_kem_recv(struct s2n_connection *conn, struct s2n_stuffe uint16_t size_of_all; struct s2n_blob *proposed_kems = &conn->secure.client_pq_kem_extension; + /* Ignore extension if PQ is disabled */ + if (!s2n_pq_is_enabled()) { + return S2N_SUCCESS; + } + GUARD(s2n_stuffer_read_uint16(extension, &size_of_all)); if (size_of_all > s2n_stuffer_data_available(extension) || size_of_all % sizeof(kem_extension_size)) { /* Malformed length, ignore the extension */ diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c index 6e058d4392..d457829022 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c @@ -18,14 +18,17 @@ #include "crypto/s2n_hash.h" #include "tls/s2n_tls.h" +#include "tls/s2n_psk.h" #include "tls/s2n_tls_parameters.h" +#include "tls/extensions/s2n_client_psk.h" +#include "utils/s2n_bitmap.h" #include "utils/s2n_safety.h" #define SIZE_OF_BINDER_SIZE sizeof(uint8_t) #define SIZE_OF_BINDER_LIST_SIZE sizeof(uint16_t) +#define MAX_NUM_OF_PSK_IDENTITIES 100 -static bool s2n_client_psk_should_send(struct s2n_connection *conn); static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out); static int s2n_client_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); @@ -38,10 +41,35 @@ const s2n_extension_type s2n_client_psk_extension = { .if_missing = s2n_extension_noop_if_missing, }; -static bool s2n_client_psk_should_send(struct s2n_connection *conn) +bool s2n_client_psk_should_send(struct s2n_connection *conn) { - return conn && s2n_connection_get_protocol_version(conn) >= S2N_TLS13 - && conn->psk_params.psk_list.len; + if (conn == NULL) { + return false; + } + + if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { + return false; + } + + /* If this is NOT the second ClientHello after a retry, then all PSKs are viable. + * Send the extension if any PSKs are configured. + */ + if (!s2n_is_hello_retry_handshake(conn)) { + return conn->psk_params.psk_list.len > 0; + } + + /* If this is the second ClientHello after a retry, then only PSKs that match the cipher suite + * are viable. Only send the extension if at least one configured PSK matches the cipher suite. + */ + for (size_t i = 0; i < conn->psk_params.psk_list.len; i++) { + struct s2n_psk *psk = NULL; + if (s2n_result_is_ok(s2n_array_get(&conn->psk_params.psk_list, i, (void**) &psk)) + && psk != NULL + && conn->secure.cipher_suite->prf_alg == psk->hmac_alg) { + return true; + } + } + return false; } static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out) @@ -61,6 +89,16 @@ static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer * GUARD_AS_POSIX(s2n_array_get(psk_list, i, (void**) &psk)); notnull_check(psk); + /** + *= https://tools.ietf.org/rfc/rfc8446#section-4.1.4 + *# In addition, in its updated ClientHello, the client SHOULD NOT offer + *# any pre-shared keys associated with a hash other than that of the + *# selected cipher suite. + */ + if (s2n_is_hello_retry_handshake(conn) && conn->secure.cipher_suite->prf_alg != psk->hmac_alg) { + continue; + } + /* Write the identity */ GUARD(s2n_stuffer_write_uint16(out, psk->identity.size)); GUARD(s2n_stuffer_write(out, &psk->identity)); @@ -68,7 +106,7 @@ static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer * /* Calculate binder size */ uint8_t hash_size = 0; - GUARD(s2n_hash_digest_size(psk->hash_alg, &hash_size)); + GUARD(s2n_hmac_digest_size(psk->hmac_alg, &hash_size)); binder_list_size += hash_size + SIZE_OF_BINDER_SIZE; } @@ -121,44 +159,104 @@ static S2N_RESULT s2n_match_psk_identity(struct s2n_array *known_psks, const str return S2N_RESULT_OK; } +static S2N_RESULT s2n_select_psk_identity(struct s2n_connection *conn, struct s2n_psk_identity *identities, size_t identities_length) +{ + ENSURE_REF(conn); + ENSURE_REF(identities); + + struct s2n_array *known_psks = &conn->psk_params.psk_list; + conn->psk_params.chosen_psk = NULL; + + for (size_t i = 0; i < identities_length; i++) { + struct s2n_blob wire_identity = { 0 }; + GUARD_AS_RESULT(s2n_blob_init(&wire_identity, identities[i].data, identities[i].length)); + + struct s2n_psk *local_match = NULL; + GUARD_RESULT(s2n_match_psk_identity(known_psks, &wire_identity, &local_match)); + + /* When a local match is found we do not end this loop early in an attempt + * to keep the server's known identities a secret and hide its ordering. + */ + if (local_match != NULL && conn->psk_params.chosen_psk == NULL) { + conn->psk_params.chosen_psk_wire_index = i; + conn->psk_params.chosen_psk = local_match; + } + } + + return S2N_RESULT_OK; +} + +static S2N_RESULT s2n_count_psk_identities(struct s2n_stuffer *input, uint16_t *identity_count) +{ + ENSURE_REF(input); + ENSURE_REF(identity_count); + + const size_t obfuscated_ticket_age_size = sizeof(uint32_t); + + *identity_count = 0; + while (s2n_stuffer_data_available(input) > 0) { + uint16_t identity_size = 0; + GUARD_AS_RESULT(s2n_stuffer_read_uint16(input, &identity_size)); + GUARD_AS_RESULT(s2n_stuffer_skip_read(input, identity_size)); + GUARD_AS_RESULT(s2n_stuffer_skip_read(input, obfuscated_ticket_age_size)); + (*identity_count)++; + } + GUARD_AS_RESULT(s2n_stuffer_reread(input)); + return S2N_RESULT_OK; +} + static S2N_RESULT s2n_client_psk_recv_identity_list(struct s2n_connection *conn, struct s2n_stuffer *wire_identities_in) { ENSURE_REF(conn); ENSURE_REF(wire_identities_in); - uint8_t wire_index = 0; + uint16_t identities_count = 0; + GUARD_RESULT(s2n_count_psk_identities(wire_identities_in, &identities_count)); + ENSURE_GT(identities_count, 0); + ENSURE_LTE(identities_count, MAX_NUM_OF_PSK_IDENTITIES); + + DEFER_CLEANUP(struct s2n_blob wire_identities_blob = { 0 }, s2n_free); + GUARD_AS_RESULT(s2n_alloc(&wire_identities_blob, identities_count * sizeof(struct s2n_psk_identity))); + struct s2n_psk_identity *wire_identities = (struct s2n_psk_identity*)(void*) wire_identities_blob.data; + + uint16_t wire_index = 0; while (s2n_stuffer_data_available(wire_identities_in) > 0) { uint16_t identity_size = 0; GUARD_AS_RESULT(s2n_stuffer_read_uint16(wire_identities_in, &identity_size)); + ENSURE_GT(identity_size, 0); - uint8_t *identity_data; - ENSURE_REF(identity_data = s2n_stuffer_raw_read(wire_identities_in, identity_size)); + uint8_t *identity_data = s2n_stuffer_raw_read(wire_identities_in, identity_size); + ENSURE_REF(identity_data); - struct s2n_blob identity = { 0 }; - GUARD_AS_RESULT(s2n_blob_init(&identity, identity_data, identity_size)); + wire_identities[wire_index].data = identity_data; + wire_identities[wire_index].length = identity_size; - /* TODO: Validate obfuscated_ticket_age when using session tickets: - * https://github.com/awslabs/s2n/issues/2417 - * - * "For identities established externally, an obfuscated_ticket_age of 0 SHOULD be - * used, and servers MUST ignore the value." + /** + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11 + *# For identities established externally, an obfuscated_ticket_age of 0 SHOULD be + *# used, and servers MUST ignore the value. */ uint32_t obfuscated_ticket_age = 0; GUARD_AS_RESULT(s2n_stuffer_read_uint32(wire_identities_in, &obfuscated_ticket_age)); - /* TODO: Implement the callback to choose a PSK: https://github.com/awslabs/s2n/issues/2397 - * - * When we don't have a callback configured to choose a PSK, we should fall back to accepting - * the first PSK identity that also exists in our list of supported PSKs. */ - GUARD_RESULT(s2n_match_psk_identity(&conn->psk_params.psk_list, &identity, &conn->psk_params.chosen_psk)); - - if (conn->psk_params.chosen_psk) { - conn->psk_params.chosen_psk_wire_index = wire_index; - return S2N_RESULT_OK; - } - wire_index++; } + + if (conn->config->psk_selection_cb) { + GUARD_AS_RESULT(conn->config->psk_selection_cb(conn, wire_identities, identities_count, + &conn->psk_params.chosen_psk_wire_index)); + struct s2n_blob chosen_wire_identity = { 0 }; + GUARD_AS_RESULT(s2n_blob_init(&chosen_wire_identity, + wire_identities[conn->psk_params.chosen_psk_wire_index].data, + wire_identities[conn->psk_params.chosen_psk_wire_index].length)); + GUARD_RESULT(s2n_match_psk_identity(&conn->psk_params.psk_list, &chosen_wire_identity, &conn->psk_params.chosen_psk)); + } else { + GUARD_RESULT(s2n_select_psk_identity(conn, wire_identities, identities_count)); + } + + ENSURE_LT(conn->psk_params.chosen_psk_wire_index, identities_count); + ENSURE_REF(conn->psk_params.chosen_psk); + return S2N_RESULT_OK; } @@ -168,7 +266,7 @@ static S2N_RESULT s2n_client_psk_recv_binder_list(struct s2n_connection *conn, s ENSURE_REF(conn); ENSURE_REF(wire_binders_in); - uint8_t wire_index = 0; + uint16_t wire_index = 0; while (s2n_stuffer_data_available(wire_binders_in) > 0) { uint8_t wire_binder_size = 0; GUARD_AS_RESULT(s2n_stuffer_read_uint8(wire_binders_in, &wire_binder_size)); @@ -246,26 +344,66 @@ int s2n_client_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extensi return S2N_SUCCESS; } + /** + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11 + *# The "pre_shared_key" extension MUST be the last extension in the + *# ClientHello (this facilitates implementation as described below). + *# Servers MUST check that it is the last extension and otherwise fail + *# the handshake with an "illegal_parameter" alert. + */ + s2n_extension_type_id psk_ext_id; + GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_PRE_SHARED_KEY, &psk_ext_id)); + ne_check(conn->client_hello.extensions.count, 0); + uint16_t last_wire_index = conn->client_hello.extensions.count - 1; + uint16_t extension_wire_index = conn->client_hello.extensions.parsed_extensions[psk_ext_id].wire_index; + ENSURE_POSIX(extension_wire_index == last_wire_index, S2N_ERR_UNSUPPORTED_EXTENSION); + + /** + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.9 + *# If clients offer "pre_shared_key" without a "psk_key_exchange_modes" extension, + *# servers MUST abort the handshake. + * + * We can safely do this check here because s2n_client_psk is + * required to be the last extension sent in the list. + */ + s2n_extension_type_id psk_ke_mode_ext_id; + GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES, &psk_ke_mode_ext_id)); + ENSURE_POSIX(S2N_CBIT_TEST(conn->extension_requests_received, psk_ke_mode_ext_id), S2N_ERR_MISSING_EXTENSION); + + if (conn->psk_params.psk_ke_mode == S2N_PSK_DHE_KE) { + s2n_extension_type_id key_share_ext_id; + GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_KEY_SHARE, &key_share_ext_id)); + /* A key_share extension must have been received in order to use a pre-shared key + * in (EC)DHE key exchange mode. + */ + ENSURE_POSIX(S2N_CBIT_TEST(conn->extension_requests_received, key_share_ext_id), S2N_ERR_MISSING_EXTENSION); + } else { + /* s2n currently only supports pre-shared keys in (EC)DHE key exchange mode. If we receive keys with any other + * exchange mode we fall back to a full handshake. + */ + return S2N_SUCCESS; + } + if (s2n_result_is_error(s2n_client_psk_recv_identities(conn, extension))) { - /* https://tools.ietf.org/html/rfc8446#section-4.2.11: - * "If no acceptable PSKs are found, the server SHOULD perform a non-PSK - * handshake if possible." + /** + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11 + *# If no acceptable PSKs are found, the server SHOULD perform a non-PSK + *# handshake if possible. */ conn->psk_params.chosen_psk = NULL; } if (conn->psk_params.chosen_psk) { - /* https://tools.ietf.org/html/rfc8446#section-4.2.11: - * "Prior to accepting PSK key establishment, the server MUST validate - * the corresponding binder value. If this value is not present or does - * not validate, the server MUST abort the handshake." + /** + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11 + *# Prior to accepting PSK key establishment, the server MUST validate + *# the corresponding binder value (see Section 4.2.11.2 below). If this + *# value is not present or does not validate, the server MUST abort the + *# handshake. */ GUARD_AS_POSIX(s2n_client_psk_recv_binders(conn, extension)); } - /* At this point, we have either chosen a PSK or fallen back to a full handshake. - * Wipe any PSKs not chosen. */ - GUARD_AS_POSIX(s2n_psk_parameters_free_unused_psks(&conn->psk_params)); - + /* At this point, we have either chosen a PSK or fallen back to a full handshake. */ return S2N_SUCCESS; } diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h index a317ace2bc..1fdabff50d 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h @@ -20,3 +20,5 @@ #include "stuffer/s2n_stuffer.h" extern const s2n_extension_type s2n_client_psk_extension; + +bool s2n_client_psk_should_send(struct s2n_connection *conn); diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.c index 9c1bf71092..4cb2f9e3c5 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.c @@ -24,7 +24,7 @@ #include "tls/s2n_security_policies.h" #include "utils/s2n_safety.h" -#include "crypto/s2n_fips.h" +#include "pq-crypto/s2n_pq.h" #include "tls/s2n_tls13.h" static int s2n_client_supported_groups_send(struct s2n_connection *conn, struct s2n_stuffer *out); @@ -63,7 +63,7 @@ static int s2n_client_supported_groups_send(struct s2n_connection *conn, struct GUARD(s2n_stuffer_reserve_uint16(out, &group_list_len)); /* Send KEM groups list first */ - if (s2n_connection_get_protocol_version(conn) >= S2N_TLS13 && !s2n_is_in_fips_mode()) { + if (s2n_connection_get_protocol_version(conn) >= S2N_TLS13 && s2n_pq_is_enabled()) { for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) { GUARD(s2n_stuffer_write_uint16(out, kem_pref->tls13_kem_groups[i]->iana_id)); } @@ -97,8 +97,8 @@ static int s2n_client_supported_groups_recv_iana_id(struct s2n_connection *conn, } } - /* Return early if in FIPS mode, or if TLS 1.3 is disabled, so as to ignore PQ IDs */ - if (s2n_is_in_fips_mode() || s2n_connection_get_protocol_version(conn) < S2N_TLS13) { + /* Return early if PQ is disabled, or if TLS version is less than 1.3, so as to ignore PQ IDs */ + if (!s2n_pq_is_enabled() || s2n_connection_get_protocol_version(conn) < S2N_TLS13) { return S2N_SUCCESS; } @@ -135,7 +135,7 @@ static int s2n_choose_supported_group(struct s2n_connection *conn) { conn->secure.server_kem_group_params.kem_params.kem = NULL; conn->secure.server_ecc_evp_params.negotiated_curve = NULL; - /* Prefer to negotiate hybrid PQ over ECC. If in FIPS mode, we will never choose a + /* Prefer to negotiate hybrid PQ over ECC. If PQ is disabled, we will never choose a * PQ group because the mutually_supported_kem_groups array will not have been * populated with anything. */ for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) { diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c index 81c9e9bf5a..5188535bf4 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c @@ -120,9 +120,10 @@ int s2n_extension_list_process(s2n_extension_list_id list_type, struct s2n_conne return S2N_SUCCESS; } -static int s2n_extension_parse(struct s2n_stuffer *in, s2n_parsed_extension *parsed_extensions) +static int s2n_extension_parse(struct s2n_stuffer *in, s2n_parsed_extension *parsed_extensions, uint16_t *wire_index) { notnull_check(parsed_extensions); + notnull_check(wire_index); uint16_t extension_type; ENSURE_POSIX(s2n_stuffer_read_uint16(in, &extension_type) == S2N_SUCCESS, @@ -149,7 +150,9 @@ static int s2n_extension_parse(struct s2n_stuffer *in, s2n_parsed_extension *par /* Fill in parsed extension */ parsed_extension->extension_type = extension_type; + parsed_extension->wire_index = *wire_index; GUARD(s2n_blob_init(&parsed_extension->extension, extension_data, extension_size)); + (*wire_index)++; return S2N_SUCCESS; } @@ -176,9 +179,11 @@ int s2n_extension_list_parse(struct s2n_stuffer *in, s2n_parsed_extensions_list GUARD(s2n_stuffer_init(&extensions_stuffer, &parsed_extension_list->raw)); GUARD(s2n_stuffer_skip_write(&extensions_stuffer, total_extensions_size)); + uint16_t wire_index = 0; while (s2n_stuffer_data_available(&extensions_stuffer)) { - GUARD(s2n_extension_parse(&extensions_stuffer, parsed_extension_list->parsed_extensions)); + GUARD(s2n_extension_parse(&extensions_stuffer, parsed_extension_list->parsed_extensions, &wire_index)); } + parsed_extension_list->count = wire_index; return S2N_SUCCESS; } diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h index 35582e5638..dcf7c9da9b 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h @@ -23,11 +23,13 @@ typedef struct { uint16_t extension_type; struct s2n_blob extension; + uint16_t wire_index; } s2n_parsed_extension; typedef struct { s2n_parsed_extension parsed_extensions[S2N_PARSED_EXTENSIONS_COUNT]; struct s2n_blob raw; /* Needed by some ClientHello APIs */ + uint16_t count; } s2n_parsed_extensions_list; typedef enum { diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h index 674c8e63dd..3c95af639f 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h @@ -61,6 +61,7 @@ static const uint16_t s2n_supported_extensions[] = { TLS_EXTENSION_KEY_SHARE, TLS_EXTENSION_COOKIE, TLS_QUIC_TRANSPORT_PARAMETERS, + TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES, TLS_EXTENSION_PRE_SHARED_KEY, }; diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c index ed4c196f59..5395366a6c 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c @@ -31,6 +31,7 @@ #include "tls/extensions/s2n_client_supported_groups.h" #include "tls/extensions/s2n_client_pq_kem.h" #include "tls/extensions/s2n_client_psk.h" +#include "tls/extensions/s2n_psk_key_exchange_modes.h" #include "tls/extensions/s2n_client_renegotiation_info.h" #include "tls/extensions/s2n_ec_point_format.h" #include "tls/extensions/s2n_quic_transport_params.h" @@ -45,6 +46,7 @@ #include "tls/extensions/s2n_server_signature_algorithms.h" #include "tls/extensions/s2n_server_supported_versions.h" #include "tls/extensions/s2n_server_key_share.h" +#include "tls/extensions/s2n_server_psk.h" static const s2n_extension_type *const client_hello_extensions[] = { &s2n_client_supported_versions_extension, @@ -62,6 +64,7 @@ static const s2n_extension_type *const client_hello_extensions[] = { &s2n_client_renegotiation_info_extension, &s2n_client_cookie_extension, &s2n_quic_transport_parameters_extension, + &s2n_psk_key_exchange_modes_extension, &s2n_client_psk_extension /* MUST be last */ }; @@ -81,6 +84,7 @@ static const s2n_extension_type *const tls13_server_hello_extensions[] = { &s2n_server_supported_versions_extension, &s2n_server_key_share_extension, &s2n_server_cookie_extension, + &s2n_server_psk_extension, /* MUST appear after keyshare extension */ }; static const s2n_extension_type *const encrypted_extensions[] = { diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c new file mode 100644 index 0000000000..67b1904b6b --- /dev/null +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c @@ -0,0 +1,83 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <sys/param.h> +#include <stdint.h> + +#include "tls/s2n_tls_parameters.h" +#include "tls/extensions/s2n_client_psk.h" +#include "utils/s2n_safety.h" + +#define PSK_KEY_EXCHANGE_MODE_SIZE sizeof(uint8_t) + +static bool s2n_psk_key_exchange_modes_should_send(struct s2n_connection *conn); +static int s2n_psk_key_exchange_modes_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_psk_key_exchange_modes_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_psk_key_exchange_modes_extension = { + .iana_value = TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES, + .is_response = false, + .send = s2n_psk_key_exchange_modes_send, + .recv = s2n_psk_key_exchange_modes_recv, + .should_send = s2n_psk_key_exchange_modes_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_psk_key_exchange_modes_should_send(struct s2n_connection *conn) +{ + /* Only send a psk_key_exchange_modes extension if a psk extension is also being sent */ + return s2n_client_psk_should_send(conn); +} + +static int s2n_psk_key_exchange_modes_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + notnull_check(conn); + + GUARD(s2n_stuffer_write_uint8(out, PSK_KEY_EXCHANGE_MODE_SIZE)); + + /* s2n currently only supports pre-shared keys with (EC)DHE key establishment */ + GUARD(s2n_stuffer_write_uint8(out, TLS_PSK_DHE_KE_MODE)); + + return S2N_SUCCESS; +} + +static int s2n_psk_key_exchange_modes_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + notnull_check(conn); + + if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { + return S2N_SUCCESS; + } + + uint8_t psk_ke_mode_list_len; + GUARD(s2n_stuffer_read_uint8(extension, &psk_ke_mode_list_len)); + if (psk_ke_mode_list_len > s2n_stuffer_data_available(extension)) { + /* Malformed length, ignore the extension */ + return S2N_SUCCESS; + } + + for (size_t i = 0; i < psk_ke_mode_list_len; i++) { + uint8_t wire_psk_ke_mode; + GUARD(s2n_stuffer_read_uint8(extension, &wire_psk_ke_mode)); + + /* s2n currently only supports pre-shared keys with (EC)DHE key establishment */ + if (wire_psk_ke_mode == TLS_PSK_DHE_KE_MODE) { + conn->psk_params.psk_ke_mode = S2N_PSK_DHE_KE; + return S2N_SUCCESS; + } + } + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.h new file mode 100644 index 0000000000..3c64f64489 --- /dev/null +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.h @@ -0,0 +1,22 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_psk_key_exchange_modes_extension; diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c index af112de0f4..eb0ead255a 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c @@ -20,7 +20,7 @@ #include "utils/s2n_safety.h" -#include "crypto/s2n_fips.h" +#include "pq-crypto/s2n_pq.h" static int s2n_server_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out); static int s2n_server_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); @@ -38,7 +38,7 @@ static int s2n_server_key_share_generate_pq_hybrid(struct s2n_connection *conn, notnull_check(out); notnull_check(conn); - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); struct s2n_kem_group_params *server_kem_group_params = &conn->secure.server_kem_group_params; @@ -71,7 +71,7 @@ static int s2n_server_key_share_generate_pq_hybrid(struct s2n_connection *conn, int s2n_server_key_share_send_check_pq_hybrid(struct s2n_connection *conn) { notnull_check(conn); - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); notnull_check(conn->secure.server_kem_group_params.kem_group); notnull_check(conn->secure.server_kem_group_params.kem_params.kem); @@ -167,9 +167,9 @@ static int s2n_server_key_share_recv_pq_hybrid(struct s2n_connection *conn, uint notnull_check(conn); notnull_check(extension); - /* If in FIPS mode, the client should not have sent any PQ IDs + /* If PQ is disabled, the client should not have sent any PQ IDs * in the supported_groups list of the initial ClientHello */ - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); const struct s2n_kem_preferences *kem_pref = NULL; GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c new file mode 100644 index 0000000000..cb930b17a4 --- /dev/null +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c @@ -0,0 +1,92 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <sys/param.h> +#include <stdint.h> + +#include "tls/s2n_tls.h" +#include "tls/extensions/s2n_server_psk.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_bitmap.h" + +static bool s2n_server_psk_should_send(struct s2n_connection *conn); +static int s2n_server_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_server_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_server_psk_extension = { + .iana_value = TLS_EXTENSION_PRE_SHARED_KEY, + .is_response = true, + .send = s2n_server_psk_send, + .recv = s2n_server_psk_recv, + .should_send = s2n_server_psk_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_server_psk_should_send(struct s2n_connection *conn) +{ + /* Only send a server pre_shared_key extension if a chosen PSK is set on the connection */ + return conn && s2n_connection_get_protocol_version(conn) >= S2N_TLS13 + && conn->psk_params.chosen_psk; +} + +static int s2n_server_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + notnull_check(conn); + + /* Send the index of the chosen PSK that is stored on the connection. */ + GUARD(s2n_stuffer_write_uint16(out, conn->psk_params.chosen_psk_wire_index)); + + return S2N_SUCCESS; +} + +static int s2n_server_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + notnull_check(conn); + + if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { + return S2N_SUCCESS; + } + + /* Currently in s2n, only (EC)DHE key exchange mode is supported. + * Any other mode selected by the server is invalid because it was not offered by the client. + * A key_share extension MUST have been received in order to use a pre-shared key in (EC)DHE key exchange mode. + */ + s2n_extension_type_id key_share_ext_id; + GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_KEY_SHARE, &key_share_ext_id)); + ENSURE_POSIX(S2N_CBIT_TEST(conn->extension_requests_received, key_share_ext_id), S2N_ERR_MISSING_EXTENSION); + + /* From RFC section: https://tools.ietf.org/html/rfc8446#section-4.2.8.1 + * Any future values that are allocated must ensure that the transmitted protocol messages + * unambiguously identify which mode was selected by the server; at present, this is + * indicated by the presence of the "key_share" in the ServerHello. + */ + conn->psk_params.psk_ke_mode = S2N_PSK_DHE_KE; + + uint16_t chosen_psk_wire_index = 0; + GUARD(s2n_stuffer_read_uint16(extension, &chosen_psk_wire_index)); + + /* From RFC section: https://tools.ietf.org/html/rfc8446#section-4.2.11 + * Clients MUST verify that the server's selected_identity is within the + * range supplied by the client. + */ + ENSURE_POSIX(chosen_psk_wire_index < conn->psk_params.psk_list.len, S2N_ERR_INVALID_ARGUMENT); + conn->psk_params.chosen_psk_wire_index = chosen_psk_wire_index; + + GUARD_AS_POSIX(s2n_array_get(&conn->psk_params.psk_list, conn->psk_params.chosen_psk_wire_index, + (void **)&conn->psk_params.chosen_psk)); + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.h new file mode 100644 index 0000000000..d6956e9dbf --- /dev/null +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.h @@ -0,0 +1,20 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" + +extern const s2n_extension_type s2n_server_psk_extension; diff --git a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c index 15c539da6b..d1960eac69 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c +++ b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c @@ -262,7 +262,8 @@ S2N_RESULT s2n_async_pkey_sign_sync(struct s2n_connection *conn, s2n_signature_a const struct s2n_pkey *pkey = conn->handshake_params.our_chain_and_key->private_key; DEFER_CLEANUP(struct s2n_blob signed_content = { 0 }, s2n_free); - uint32_t maximum_signature_length = s2n_pkey_size(pkey); + uint32_t maximum_signature_length = 0; + GUARD_RESULT(s2n_pkey_size(pkey, &maximum_signature_length)); GUARD_AS_RESULT(s2n_alloc(&signed_content, maximum_signature_length)); GUARD_AS_RESULT(s2n_pkey_sign(pkey, sig_alg, digest, &signed_content)); @@ -378,7 +379,8 @@ S2N_RESULT s2n_async_pkey_sign_perform(struct s2n_async_pkey_op *op, s2n_cert_pr struct s2n_async_pkey_sign_data *sign = &op->op.sign; - uint32_t maximum_signature_length = s2n_pkey_size(pkey); + uint32_t maximum_signature_length = 0; + GUARD_RESULT(s2n_pkey_size(pkey, &maximum_signature_length)); GUARD_AS_RESULT(s2n_alloc(&sign->signature, maximum_signature_length)); GUARD_AS_RESULT(s2n_pkey_sign(pkey, sign->sig_alg, &sign->digest, &sign->signature)); diff --git a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c index 2d5070e32e..33404c811b 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c +++ b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c @@ -130,11 +130,15 @@ static int s2n_certs_exist_for_sig_scheme(struct s2n_connection *conn, const str static int s2n_certs_exist_for_auth_method(struct s2n_connection *conn, s2n_authentication_method auth_method) { + if (auth_method == S2N_AUTHENTICATION_METHOD_SENTINEL) { + return S2N_SUCCESS; + } + s2n_authentication_method auth_method_for_cert_type; for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { GUARD(s2n_get_auth_method_for_cert_type(i, &auth_method_for_cert_type)); - if (auth_method != S2N_AUTHENTICATION_METHOD_SENTINEL && auth_method != auth_method_for_cert_type) { + if (auth_method != auth_method_for_cert_type) { continue; } @@ -145,11 +149,10 @@ static int s2n_certs_exist_for_auth_method(struct s2n_connection *conn, s2n_auth S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED); } -/* A cipher suite is valid if: - * - At least one compatible cert is configured +/* TLS1.3 ciphers are always valid, as they don't include an auth method. * - * TLS1.3 ciphers are valid if ANY certs are configured, as authentication - * method is not tied to cipher suites in TLS1.3. + * A pre-TLS1.3 cipher suite is valid if: + * - At least one compatible cert is configured * * This method is called by the server when choosing a cipher suite. */ diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c index 4343b88f00..67893009b1 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c @@ -989,6 +989,21 @@ const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2019 = .suites = cipher_suites_cloudfront_tls_1_2_2019, }; +struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_2_2021[] = { + S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716, + &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256 +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2021 = { + .count = s2n_array_len(cipher_suites_cloudfront_tls_1_2_2021), + .suites = cipher_suites_cloudfront_tls_1_2_2021, +}; + struct s2n_cipher_suite *cipher_suites_kms_tls_1_0_2018_10[] = { &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, @@ -1007,8 +1022,6 @@ const struct s2n_cipher_preferences cipher_preferences_kms_tls_1_0_2018_10 = { .suites = cipher_suites_kms_tls_1_0_2018_10, }; -#if !defined(S2N_NO_PQ) - struct s2n_cipher_suite *cipher_suites_kms_pq_tls_1_0_2019_06[] = { &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384, &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384, @@ -1108,8 +1121,6 @@ const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2020_12 = { .suites = cipher_suites_pq_tls_1_0_2020_12, }; -#endif - struct s2n_cipher_suite *cipher_suites_kms_fips_tls_1_2_2018_10[] = { &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h index b70fa55922..8dabb707ff 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h @@ -76,6 +76,7 @@ extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0 extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_1_2016; extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2018; extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2019; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2021; /* CloudFront viewer facing legacy TLS 1.2 policies */ extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_ssl_v_3_legacy; @@ -87,8 +88,6 @@ extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2 extern const struct s2n_cipher_preferences cipher_preferences_kms_tls_1_0_2018_10; -#if !defined(S2N_NO_PQ) - extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2019_06; extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2020_02; extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2020_07; @@ -96,8 +95,6 @@ extern const struct s2n_cipher_preferences cipher_preferences_pq_sike_test_tls_1 extern const struct s2n_cipher_preferences cipher_preferences_pq_sike_test_tls_1_0_2020_02; extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2020_12; -#endif - extern const struct s2n_cipher_preferences cipher_preferences_kms_fips_tls_1_2_2018_10; extern const struct s2n_cipher_preferences cipher_preferences_null; diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c index f3597ee3c2..ea478e27b8 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c @@ -29,6 +29,7 @@ #include "tls/s2n_tls13.h" #include "utils/s2n_safety.h" #include "tls/s2n_psk.h" +#include "pq-crypto/s2n_pq.h" /************************* * S2n Record Algorithms * @@ -809,11 +810,9 @@ static struct s2n_cipher_suite *s2n_all_cipher_suites[] = { &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA8 */ &s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */ &s2n_dhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xAA */ -#if !defined(S2N_NO_PQ) &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x04 */ &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x08 */ &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x0C */ -#endif }; /* All supported ciphers. Exposed for integration testing. */ @@ -859,11 +858,9 @@ static struct s2n_cipher_suite *s2n_all_tls12_cipher_suites[] = { &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA8 */ &s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */ &s2n_dhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xAA */ -#if !defined(S2N_NO_PQ) &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x04 */ &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x08 */ &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x0C */ -#endif }; const struct s2n_cipher_preferences cipher_preferences_test_all_tls12 = { @@ -1019,6 +1016,12 @@ int s2n_cipher_suites_init(void) } } + /* Mark PQ cipher suites as unavailable if PQ is disabled */ + if (s2n_kex_includes(cur_suite->key_exchange_alg, &s2n_kem) && !s2n_pq_is_enabled()) { + cur_suite->available = 0; + cur_suite->record_alg = NULL; + } + /* Initialize SSLv3 cipher suite if SSLv3 utilizes a different record algorithm */ if (cur_suite->sslv3_record_alg && cur_suite->sslv3_record_alg->cipher->is_available()) { struct s2n_blob cur_suite_mem = { .data = (uint8_t *) cur_suite, .size = sizeof(struct s2n_cipher_suite) }; @@ -1103,6 +1106,15 @@ int s2n_set_cipher_as_client(struct s2n_connection *conn, uint8_t wire[S2N_TLS_C cipher_suite = s2n_cipher_suite_from_wire(wire); ENSURE_POSIX(cipher_suite != NULL, S2N_ERR_CIPHER_NOT_SUPPORTED); + /* From RFC section: https://tools.ietf.org/html/rfc8446#section-4.2.11: + * Client MUST verify that the server selected a cipher suite indicating a Hash + * associated with the chosen PSK if it exists. + * */ + if (conn->psk_params.chosen_psk) { + ENSURE_POSIX(cipher_suite->prf_alg == conn->psk_params.chosen_psk->hmac_alg, + S2N_ERR_CIPHER_NOT_SUPPORTED); + } + /* Verify cipher suite sent in server hello is the same as sent in hello retry */ if (s2n_is_hello_retry_handshake(conn) && !s2n_is_hello_retry_message(conn)) { ENSURE_POSIX(conn->secure.cipher_suite->iana_value == cipher_suite->iana_value, S2N_ERR_CIPHER_NOT_SUPPORTED); @@ -1210,24 +1222,25 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire, /* TLS 1.3 does not include key exchange in cipher suites */ if (match->minimum_required_tls_version < S2N_TLS13) { /* If the kex is not supported continue to the next candidate */ - if (!s2n_kex_supported(match, conn)) { + bool kex_supported = false; + GUARD_AS_POSIX(s2n_kex_supported(match, conn, &kex_supported)); + if (!kex_supported) { continue; } /* If the kex is not configured correctly continue to the next candidate */ - if (s2n_configure_kex(match, conn)) { + if (s2n_result_is_error(s2n_configure_kex(match, conn))) { continue; } } - /* For TLS1.3 when PSKs are present, the server must consider the hash algorithm associated with the chosen PSK - * when choosing a cipher suite. Server MUST reject any cipher suite without a matching hash algorithm and - * continue to the next candidate. - * */ - if (conn->actual_protocol_version >= S2N_TLS13 && conn->psk_params.chosen_psk != NULL) { - s2n_hmac_algorithm chosen_psk_hmac_alg = { 0 }; - GUARD(s2n_hash_hmac_alg(conn->psk_params.chosen_psk->hash_alg, &chosen_psk_hmac_alg)); - if (match->prf_alg != chosen_psk_hmac_alg) { + /** + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11 + *# The server MUST ensure that it selects a compatible PSK + *# (if any) and cipher suite. + **/ + if (conn->psk_params.chosen_psk != NULL) { + if (match->prf_alg != conn->psk_params.chosen_psk->hmac_alg) { continue; } } diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h index 009f13471b..2bee39ec4c 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h @@ -31,14 +31,9 @@ #define S2N_KEY_EXCHANGE_ECC 0x04 /* Elliptic curve cryptography */ #define S2N_MAX_POSSIBLE_RECORD_ALGS 2 -#if !defined(S2N_NO_PQ) -#define S2N_PQ_CIPHER_SUITE_COUNT 3 -#else -#define S2N_PQ_CIPHER_SUITE_COUNT 0 -#endif /* Kept up-to-date by s2n_cipher_suite_match_test */ -#define S2N_CIPHER_SUITE_COUNT (36 + S2N_PQ_CIPHER_SUITE_COUNT) +#define S2N_CIPHER_SUITE_COUNT 39 /* Record algorithm flags that can be OR'ed */ diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c b/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c index a218c13c18..b11150c48c 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c @@ -76,7 +76,8 @@ int s2n_client_cert_verify_send(struct s2n_connection *conn) struct s2n_cert_chain_and_key *cert_chain_and_key = conn->handshake_params.our_chain_and_key; DEFER_CLEANUP(struct s2n_blob signature = {0}, s2n_free); - uint32_t max_signature_size = s2n_pkey_size(cert_chain_and_key->private_key); + uint32_t max_signature_size = 0; + GUARD_AS_POSIX(s2n_pkey_size(cert_chain_and_key->private_key, &max_signature_size)); GUARD(s2n_alloc(&signature, max_signature_size)); GUARD(s2n_pkey_sign(cert_chain_and_key->private_key, chosen_sig_scheme.sig_alg, &conn->handshake.ccv_hash_copy, &signature)); diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c index 15bf12c525..b03cda1491 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c @@ -285,6 +285,12 @@ int s2n_process_client_hello(struct s2n_connection *conn) /* Now choose the ciphers we have certs for. */ GUARD(s2n_set_cipher_as_tls_server(conn, client_hello->cipher_suites.data, client_hello->cipher_suites.size / 2)); + /* If we're using a PSK, we don't need to choose a signature algorithm or certificate, + * because no additional auth is required. */ + if (conn->psk_params.chosen_psk != NULL) { + return S2N_SUCCESS; + } + /* And set the signature and hash algorithm used for key exchange signatures */ GUARD(s2n_choose_sig_scheme_from_peer_preference_list(conn, &conn->handshake_params.client_sig_hash_algs, @@ -293,7 +299,7 @@ int s2n_process_client_hello(struct s2n_connection *conn) /* And finally, set the certs specified by the final auth + sig_alg combo. */ GUARD(s2n_select_certs_for_server_auth(conn, &conn->handshake_params.our_chain_and_key)); - return 0; + return S2N_SUCCESS; } int s2n_client_hello_recv(struct s2n_connection *conn) diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c b/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c index 99510d8628..1428e177b2 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c @@ -37,7 +37,7 @@ #define get_client_hello_protocol_version(conn) (conn->client_hello_version == S2N_SSLv2 ? conn->client_protocol_version : conn->client_hello_version) -typedef int s2n_kex_client_key_method(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); +typedef S2N_RESULT s2n_kex_client_key_method(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); typedef void *s2n_stuffer_action(struct s2n_stuffer *stuffer, uint32_t data_len); static int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rsa_failed, struct s2n_blob *shared_key); @@ -58,10 +58,10 @@ static int s2n_hybrid_client_action(struct s2n_connection *conn, struct s2n_blob const uint32_t start_cursor = *cursor; DEFER_CLEANUP(struct s2n_blob shared_key_0 = {0}, s2n_free); - GUARD(kex_method(hybrid_kex_0, conn, &shared_key_0)); + GUARD_AS_POSIX(kex_method(hybrid_kex_0, conn, &shared_key_0)); struct s2n_blob *shared_key_1 = &(conn->secure.kem_params.shared_secret); - GUARD(kex_method(hybrid_kex_1, conn, shared_key_1)); + GUARD_AS_POSIX(kex_method(hybrid_kex_1, conn, shared_key_1)); const uint32_t end_cursor = *cursor; gte_check(end_cursor, start_cursor); @@ -81,7 +81,7 @@ static int s2n_hybrid_client_action(struct s2n_connection *conn, struct s2n_blob static int s2n_calculate_keys(struct s2n_connection *conn, struct s2n_blob *shared_key) { /* Turn the pre-master secret into a master secret */ - GUARD(s2n_kex_tls_prf(conn->secure.cipher_suite->key_exchange_alg, conn, shared_key)); + GUARD_AS_POSIX(s2n_kex_tls_prf(conn->secure.cipher_suite->key_exchange_alg, conn, shared_key)); /* Erase the pre-master secret */ GUARD(s2n_blob_zero(shared_key)); if (shared_key->allocated) { @@ -216,7 +216,7 @@ int s2n_client_key_recv(struct s2n_connection *conn) const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg; struct s2n_blob shared_key = {0}; - GUARD(s2n_kex_client_key_recv(key_exchange, conn, &shared_key)); + GUARD_AS_POSIX(s2n_kex_client_key_recv(key_exchange, conn, &shared_key)); GUARD(s2n_calculate_keys(conn, &shared_key)); return 0; @@ -260,8 +260,9 @@ int s2n_rsa_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared */ memcpy_check(conn->secure.rsa_premaster_secret, client_hello_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN); - int encrypted_size = s2n_pkey_size(&conn->secure.server_public_key); - S2N_ERROR_IF(encrypted_size < 0 || encrypted_size > 0xffff, S2N_ERR_SIZE_MISMATCH); + uint32_t encrypted_size = 0; + GUARD_AS_POSIX(s2n_pkey_size(&conn->secure.server_public_key, &encrypted_size)); + S2N_ERROR_IF(encrypted_size > 0xffff, S2N_ERR_SIZE_MISMATCH); if (conn->actual_protocol_version > S2N_SSLv3) { GUARD(s2n_stuffer_write_uint16(&conn->handshake.io, encrypted_size)); @@ -311,7 +312,7 @@ int s2n_client_key_send(struct s2n_connection *conn) const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg; struct s2n_blob shared_key = {0}; - GUARD(s2n_kex_client_key_send(key_exchange, conn, &shared_key)); + GUARD_AS_POSIX(s2n_kex_client_key_send(key_exchange, conn, &shared_key)); GUARD(s2n_calculate_keys(conn, &shared_key)); return 0; diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.c b/contrib/restricted/aws/s2n/tls/s2n_config.c index 51a974f8c7..db3a8819bc 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_config.c +++ b/contrib/restricted/aws/s2n/tls/s2n_config.c @@ -123,6 +123,7 @@ static int s2n_config_init(struct s2n_config *config) config->max_verify_cert_chain_depth_set = 0; config->cert_tiebreak_cb = NULL; config->async_pkey_cb = NULL; + config->psk_selection_cb = NULL; config->cert_req_dss_legacy_compat_enabled = 0; GUARD(s2n_config_setup_default(config)); @@ -858,3 +859,13 @@ int s2n_config_enable_cert_req_dss_legacy_compat(struct s2n_config *config) config->cert_req_dss_legacy_compat_enabled = 1; return S2N_SUCCESS; } + +int s2n_config_set_psk_selection_callback(struct s2n_connection *conn, s2n_psk_selection_callback cb) +{ + notnull_check(conn); + notnull_check(cb); + + conn->config->psk_selection_cb = cb; + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.h b/contrib/restricted/aws/s2n/tls/s2n_config.h index be8baf1da1..c5edf02418 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_config.h +++ b/contrib/restricted/aws/s2n/tls/s2n_config.h @@ -22,6 +22,7 @@ #include "tls/s2n_x509_validator.h" #include "utils/s2n_blob.h" #include "utils/s2n_set.h" +#include "tls/s2n_psk.h" #define S2N_MAX_TICKET_KEYS 48 #define S2N_MAX_TICKET_KEY_HASHES 500 /* 10KB */ @@ -101,6 +102,7 @@ struct s2n_config { uint16_t max_verify_cert_chain_depth; s2n_async_pkey_fn async_pkey_cb; + s2n_psk_selection_callback psk_selection_cb; }; int s2n_config_defaults_init(void); diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.c b/contrib/restricted/aws/s2n/tls/s2n_connection.c index ae23da2439..f2393fd2a1 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_connection.c +++ b/contrib/restricted/aws/s2n/tls/s2n_connection.c @@ -452,7 +452,7 @@ int s2n_connection_free(struct s2n_connection *conn) { GUARD(s2n_connection_wipe_keys(conn)); GUARD(s2n_connection_free_keys(conn)); - GUARD(s2n_psk_parameters_free(&conn->psk_params)); + GUARD_AS_POSIX(s2n_psk_parameters_wipe(&conn->psk_params)); GUARD(s2n_prf_free(conn)); diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.h b/contrib/restricted/aws/s2n/tls/s2n_connection.h index 5ba5667fc2..9864111db1 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_connection.h +++ b/contrib/restricted/aws/s2n/tls/s2n_connection.h @@ -307,6 +307,8 @@ struct s2n_connection { uint8_t ticket_ext_data[S2N_TICKET_SIZE_IN_BYTES]; struct s2n_stuffer client_ticket_to_decrypt; + uint8_t resumption_master_secret[S2N_TLS13_SECRET_MAX_LEN]; + /* application protocols overridden */ struct s2n_blob application_protocols_overridden; @@ -323,6 +325,12 @@ struct s2n_connection { * Setting and manipulating this value requires security_policy to be configured prior. * */ uint8_t preferred_key_shares; + + /* Flags to prevent users from calling methods recursively. + * This can be an easy mistake to make when implementing send/receive callbacks. + */ + bool send_in_use; + bool recv_in_use; }; int s2n_connection_is_managed_corked(const struct s2n_connection *s2n_connection); diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c index ad53a33938..5b78ef79c6 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c +++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c @@ -357,8 +357,6 @@ static message_type_t handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_LENGTH] /* * This selection of handshakes resembles the standard set, but with changes made to support tls1.3. * - * These are just the basic handshakes. At the moment hello retries, session resumption, and early data are not supported. - * * The CHANGE_CIPHER_SPEC messages are included only for middlebox compatibility. * See https://tools.ietf.org/html/rfc8446#appendix-D.4 */ @@ -373,6 +371,38 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L HELLO_RETRY_MSG }, + [NEGOTIATED] = { + CLIENT_HELLO, + SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED, + CLIENT_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | MIDDLEBOX_COMPAT] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_FINISHED, + CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | HELLO_RETRY_REQUEST] = { + CLIENT_HELLO, + HELLO_RETRY_MSG, + CLIENT_HELLO, + SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED, + CLIENT_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT] = { + CLIENT_HELLO, + HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC, + CLIENT_CHANGE_CIPHER_SPEC, CLIENT_HELLO, + SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED, + CLIENT_FINISHED, + APPLICATION_DATA + }, + [NEGOTIATED | FULL_HANDSHAKE] = { CLIENT_HELLO, SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, @@ -593,10 +623,10 @@ bool s2n_is_hello_retry_handshake(struct s2n_connection *conn) return conn->handshake.handshake_type & HELLO_RETRY_REQUEST; } -int s2n_conn_set_handshake_type(struct s2n_connection *conn) -{ +static S2N_RESULT s2n_conn_set_tls13_handshake_type(struct s2n_connection *conn) { + ENSURE_REF(conn); + if (conn->handshake.handshake_type & HELLO_RETRY_REQUEST) { - ENSURE_POSIX(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_INVALID_HELLO_RETRY); conn->handshake.handshake_type = HELLO_RETRY_REQUEST; } else { conn->handshake.handshake_type = INITIAL; @@ -605,26 +635,53 @@ int s2n_conn_set_handshake_type(struct s2n_connection *conn) /* A handshake type has been negotiated */ conn->handshake.handshake_type |= NEGOTIATED; + if (conn->psk_params.chosen_psk == NULL) { + conn->handshake.handshake_type |= FULL_HANDSHAKE; + } + s2n_cert_auth_type client_cert_auth_type; - GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type)); + GUARD_AS_RESULT(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type)); - if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED) { + if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED + && conn->handshake.handshake_type & FULL_HANDSHAKE) { /* If we're a client, and Client Auth is REQUIRED, then the Client must expect the CLIENT_CERT_REQ Message */ conn->handshake.handshake_type |= CLIENT_AUTH; - } else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE) { + } else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE + && conn->handshake.handshake_type & FULL_HANDSHAKE) { /* If we're a server, and Client Auth is REQUIRED or OPTIONAL, then the server must send the CLIENT_CERT_REQ Message*/ conn->handshake.handshake_type |= CLIENT_AUTH; } + /* Use middlebox compatibility mode for TLS1.3 by default. + * For now, only disable it when QUIC support is enabled. */ + if (!conn->config->quic_enabled) { + conn->handshake.handshake_type |= MIDDLEBOX_COMPAT; + } + + return S2N_RESULT_OK; +} + +int s2n_conn_set_handshake_type(struct s2n_connection *conn) +{ if (IS_TLS13_HANDSHAKE(conn)) { - /* Use middlebox compatibility mode for TLS1.3 by default. - * For now, only disable it when QUIC support is enabled. */ - if (!conn->config->quic_enabled) { - conn->handshake.handshake_type |= MIDDLEBOX_COMPAT; - } - conn->handshake.handshake_type |= FULL_HANDSHAKE; + GUARD_AS_POSIX(s2n_conn_set_tls13_handshake_type(conn)); + return S2N_SUCCESS; + } - return 0; + S2N_ERROR_IF(conn->handshake.handshake_type & HELLO_RETRY_REQUEST, S2N_ERR_INVALID_HELLO_RETRY); + + /* A handshake type has been negotiated */ + conn->handshake.handshake_type = NEGOTIATED; + + s2n_cert_auth_type client_cert_auth_type; + GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type)); + + if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED) { + /* If we're a client, and Client Auth is REQUIRED, then the Client must expect the CLIENT_CERT_REQ Message */ + conn->handshake.handshake_type |= CLIENT_AUTH; + } else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE) { + /* If we're a server, and Client Auth is REQUIRED or OPTIONAL, then the server must send the CLIENT_CERT_REQ Message*/ + conn->handshake.handshake_type |= CLIENT_AUTH; } if (conn->config->use_tickets) { @@ -667,7 +724,9 @@ skip_cache_lookup: /* If we get this far, it's a full handshake */ conn->handshake.handshake_type |= FULL_HANDSHAKE; - if (s2n_kex_is_ephemeral(conn->secure.cipher_suite->key_exchange_alg)) { + bool is_ephemeral = false; + GUARD_AS_POSIX(s2n_kex_is_ephemeral(conn->secure.cipher_suite->key_exchange_alg, &is_ephemeral)); + if (is_ephemeral) { conn->handshake.handshake_type |= TLS12_PERFECT_FORWARD_SECRECY; } @@ -1032,6 +1091,7 @@ static int s2n_handshake_read_io(struct s2n_connection *conn) if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_OPTIONAL && message_type == TLS_CERT_REQ) { + ENSURE_POSIX(conn->handshake.handshake_type & FULL_HANDSHAKE, S2N_ERR_HANDSHAKE_STATE); conn->handshake.handshake_type |= CLIENT_AUTH; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem.c b/contrib/restricted/aws/s2n/tls/s2n_kem.c index 4ddbbc8683..aef1665918 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kem.c +++ b/contrib/restricted/aws/s2n/tls/s2n_kem.c @@ -480,7 +480,7 @@ int s2n_kem_recv_ciphertext(struct s2n_stuffer *in, struct s2n_kem_params *kem_p } #if defined(S2N_NO_PQ) -/* IF S2N_NO_PQ was defined at compile time, the PQ KEM code will have been entirely excluded +/* If S2N_NO_PQ was defined at compile time, the PQ KEM code will have been entirely excluded * from compilation. We define stubs of these functions here to error if they are called. */ /* sikep503r1 */ int SIKE_P503_r1_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); } diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c index 4b9290c418..3e3fa71323 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c +++ b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c @@ -15,8 +15,6 @@ #include "tls/s2n_kem_preferences.h" -#if !defined(S2N_NO_PQ) - /* Extension list for round 1 PQ KEMs, in order of preference */ const struct s2n_kem *pq_kems_r1[2] = { &s2n_bike1_l1_r1, @@ -112,8 +110,6 @@ const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2020_12 = { .tls13_kem_groups = pq_kem_groups_r2, }; -#endif - const struct s2n_kem_preferences kem_preferences_null = { .kem_count = 0, .kems = NULL, diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h index e6226bb8f3..cad4f39c8e 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h +++ b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h @@ -29,8 +29,6 @@ struct s2n_kem_preferences { const struct s2n_kem_group **tls13_kem_groups; }; -#if !defined(S2N_NO_PQ) - extern const struct s2n_kem *pq_kems_r1[2]; extern const struct s2n_kem *pq_kems_r2r1[4]; extern const struct s2n_kem *pq_kems_r2r1_2020_07[5]; @@ -45,9 +43,6 @@ extern const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2020_07; extern const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2019_11; extern const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2020_02; extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2020_12; - -#endif - extern const struct s2n_kem_preferences kem_preferences_null; bool s2n_kem_preferences_includes_tls13_kem_group(const struct s2n_kem_preferences *kem_preferences, diff --git a/contrib/restricted/aws/s2n/tls/s2n_kex.c b/contrib/restricted/aws/s2n/tls/s2n_kex.c index d01a25faef..b9fb9800ad 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kex.c +++ b/contrib/restricted/aws/s2n/tls/s2n_kex.c @@ -14,7 +14,7 @@ */ #include "tls/s2n_kex.h" -#include "crypto/s2n_fips.h" +#include "pq-crypto/s2n_pq.h" #include "tls/s2n_cipher_preferences.h" #include "tls/s2n_cipher_suites.h" #include "tls/s2n_client_key_exchange.h" @@ -24,44 +24,65 @@ #include "tls/s2n_tls.h" #include "utils/s2n_safety.h" -static int s2n_check_rsa_key(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +static S2N_RESULT s2n_check_rsa_key(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported) { - return s2n_get_compatible_cert_chain_and_key(conn, S2N_PKEY_TYPE_RSA) != NULL; + ENSURE_REF(cipher_suite); + ENSURE_REF(conn); + ENSURE_REF(is_supported); + + *is_supported = s2n_get_compatible_cert_chain_and_key(conn, S2N_PKEY_TYPE_RSA) != NULL; + + return S2N_RESULT_OK; } -static int s2n_check_dhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +static S2N_RESULT s2n_check_dhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported) { - return conn->config->dhparams != NULL; + ENSURE_REF(cipher_suite); + ENSURE_REF(conn); + ENSURE_REF(conn->config); + ENSURE_REF(is_supported); + + *is_supported = conn->config->dhparams != NULL; + + return S2N_RESULT_OK; } -static int s2n_check_ecdhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +static S2N_RESULT s2n_check_ecdhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported) { - return conn->secure.server_ecc_evp_params.negotiated_curve != NULL; + ENSURE_REF(cipher_suite); + ENSURE_REF(conn); + ENSURE_REF(is_supported); + + *is_supported = conn->secure.server_ecc_evp_params.negotiated_curve != NULL; + + return S2N_RESULT_OK; } -static int s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +static S2N_RESULT s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported) { - notnull_check(conn); - /* There is no support for PQ KEMs while in FIPS mode */ - if (s2n_is_in_fips_mode()) { - return 0; - } + ENSURE_REF(cipher_suite); + ENSURE_REF(conn); + ENSURE_REF(is_supported); + + /* If any of the necessary conditions are not met, we will return early and indicate KEM is not supported. */ + *is_supported = false; const struct s2n_kem_preferences *kem_preferences = NULL; - GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences)); - notnull_check(kem_preferences); + GUARD_AS_RESULT(s2n_connection_get_kem_preferences(conn, &kem_preferences)); + ENSURE_REF(kem_preferences); - if (kem_preferences->kem_count == 0) { - return 0; + if (!s2n_pq_is_enabled() || kem_preferences->kem_count == 0) { + return S2N_RESULT_OK; } const struct s2n_iana_to_kem *supported_params = NULL; - /* If the cipher suite has no supported KEMs return false */ - if (s2n_cipher_suite_to_kem(cipher_suite->iana_value, &supported_params) != 0) { - return 0; + if (s2n_cipher_suite_to_kem(cipher_suite->iana_value, &supported_params) != S2N_SUCCESS) { + return S2N_RESULT_OK; } + + ENSURE_REF(supported_params); if (supported_params->kem_count == 0) { - return 0; + return S2N_RESULT_OK; } struct s2n_blob *client_kem_pref_list = &(conn->secure.client_pq_kem_extension); @@ -69,60 +90,71 @@ static int s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n if (client_kem_pref_list == NULL || client_kem_pref_list->data == NULL) { /* If the client did not send a PQ KEM extension, then the server can pick its preferred parameter */ if (s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems, - kem_preferences->kem_count, &chosen_kem) - != 0) { - return 0; + kem_preferences->kem_count, &chosen_kem) != S2N_SUCCESS) { + return S2N_RESULT_OK; } } else { /* If the client did send a PQ KEM extension, then the server must find a mutually supported parameter. */ if (s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, client_kem_pref_list, kem_preferences->kems, - kem_preferences->kem_count, &chosen_kem) - != 0) { - return 0; + kem_preferences->kem_count, &chosen_kem) != S2N_SUCCESS) { + return S2N_RESULT_OK; } } - return chosen_kem != NULL; + *is_supported = chosen_kem != NULL; + return S2N_RESULT_OK; } -static int s2n_configure_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +static S2N_RESULT s2n_configure_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) { - notnull_check(conn); - /* There is no support for PQ KEMs while in FIPS mode */ - S2N_ERROR_IF(s2n_is_in_fips_mode(), S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + ENSURE_REF(cipher_suite); + ENSURE_REF(conn); + + ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); const struct s2n_kem_preferences *kem_preferences = NULL; - GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences)); - notnull_check(kem_preferences); + GUARD_AS_RESULT(s2n_connection_get_kem_preferences(conn, &kem_preferences)); + ENSURE_REF(kem_preferences); struct s2n_blob *proposed_kems = &(conn->secure.client_pq_kem_extension); const struct s2n_kem *chosen_kem = NULL; if (proposed_kems == NULL || proposed_kems->data == NULL) { /* If the client did not send a PQ KEM extension, then the server can pick its preferred parameter */ - GUARD(s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems, - kem_preferences->kem_count, &chosen_kem)); + GUARD_AS_RESULT(s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems, + kem_preferences->kem_count, &chosen_kem)); } else { /* If the client did send a PQ KEM extension, then the server must find a mutually supported parameter. */ - GUARD(s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, proposed_kems, kem_preferences->kems, - kem_preferences->kem_count, &chosen_kem)); + GUARD_AS_RESULT(s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, proposed_kems, kem_preferences->kems, + kem_preferences->kem_count, &chosen_kem)); } conn->secure.kem_params.kem = chosen_kem; - return 0; + return S2N_RESULT_OK; } -static int s2n_no_op_configure(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +static S2N_RESULT s2n_no_op_configure(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) { - return 0; + return S2N_RESULT_OK; } -static int s2n_check_hybrid_ecdhe_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +static S2N_RESULT s2n_check_hybrid_ecdhe_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported) { - return s2n_check_ecdhe(cipher_suite, conn) && s2n_check_kem(cipher_suite, conn); + ENSURE_REF(cipher_suite); + ENSURE_REF(conn); + ENSURE_REF(is_supported); + + bool ecdhe_supported = false; + bool kem_supported = false; + GUARD_RESULT(s2n_check_ecdhe(cipher_suite, conn, &ecdhe_supported)); + GUARD_RESULT(s2n_check_kem(cipher_suite, conn, &kem_supported)); + + *is_supported = ecdhe_supported && kem_supported; + + return S2N_RESULT_OK; } const struct s2n_kex s2n_kem = { - .is_ephemeral = 1, + .is_ephemeral = true, .connection_supported = &s2n_check_kem, .configure_connection = &s2n_configure_kem, .server_key_recv_read_data = &s2n_kem_server_key_recv_read_data, @@ -133,7 +165,7 @@ const struct s2n_kex s2n_kem = { }; const struct s2n_kex s2n_rsa = { - .is_ephemeral = 0, + .is_ephemeral = false, .connection_supported = &s2n_check_rsa_key, .configure_connection = &s2n_no_op_configure, .server_key_recv_read_data = NULL, @@ -145,7 +177,7 @@ const struct s2n_kex s2n_rsa = { }; const struct s2n_kex s2n_dhe = { - .is_ephemeral = 1, + .is_ephemeral = true, .connection_supported = &s2n_check_dhe, .configure_connection = &s2n_no_op_configure, .server_key_recv_read_data = &s2n_dhe_server_key_recv_read_data, @@ -157,7 +189,7 @@ const struct s2n_kex s2n_dhe = { }; const struct s2n_kex s2n_ecdhe = { - .is_ephemeral = 1, + .is_ephemeral = true, .connection_supported = &s2n_check_ecdhe, .configure_connection = &s2n_no_op_configure, .server_key_recv_read_data = &s2n_ecdhe_server_key_recv_read_data, @@ -169,7 +201,7 @@ const struct s2n_kex s2n_ecdhe = { }; const struct s2n_kex s2n_hybrid_ecdhe_kem = { - .is_ephemeral = 1, + .is_ephemeral = true, .hybrid = { &s2n_ecdhe, &s2n_kem }, .connection_supported = &s2n_check_hybrid_ecdhe_kem, .configure_connection = &s2n_configure_kem, @@ -181,66 +213,112 @@ const struct s2n_kex s2n_hybrid_ecdhe_kem = { .prf = &s2n_hybrid_prf_master_secret, }; -int s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +S2N_RESULT s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported) { - /* Don't return -1 from notnull_check because that might allow a improperly configured kex to be marked as "supported" */ - return cipher_suite->key_exchange_alg->connection_supported != NULL && cipher_suite->key_exchange_alg->connection_supported(cipher_suite, conn); + ENSURE_REF(cipher_suite); + ENSURE_REF(cipher_suite->key_exchange_alg); + ENSURE_REF(cipher_suite->key_exchange_alg->connection_supported); + ENSURE_REF(conn); + ENSURE_REF(is_supported); + + GUARD_RESULT(cipher_suite->key_exchange_alg->connection_supported(cipher_suite, conn, is_supported)); + + return S2N_RESULT_OK; } -int s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +S2N_RESULT s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) { - notnull_check(cipher_suite); - notnull_check(cipher_suite->key_exchange_alg); - notnull_check(cipher_suite->key_exchange_alg->configure_connection); - return cipher_suite->key_exchange_alg->configure_connection(cipher_suite, conn); + ENSURE_REF(cipher_suite); + ENSURE_REF(cipher_suite->key_exchange_alg); + ENSURE_REF(cipher_suite->key_exchange_alg->configure_connection); + ENSURE_REF(conn); + + GUARD_RESULT(cipher_suite->key_exchange_alg->configure_connection(cipher_suite, conn)); + + return S2N_RESULT_OK; } -int s2n_kex_is_ephemeral(const struct s2n_kex *kex) +S2N_RESULT s2n_kex_is_ephemeral(const struct s2n_kex *kex, bool *is_ephemeral) { - notnull_check(kex); - return kex->is_ephemeral; + ENSURE_REF(kex); + ENSURE_REF(is_ephemeral); + + *is_ephemeral = kex->is_ephemeral; + + return S2N_RESULT_OK; } -int s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data) +S2N_RESULT s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data) { - notnull_check(kex); - notnull_check(kex->server_key_recv_parse_data); - return kex->server_key_recv_parse_data(conn, raw_server_data); + ENSURE_REF(kex); + ENSURE_REF(kex->server_key_recv_parse_data); + ENSURE_REF(conn); + ENSURE_REF(raw_server_data); + + GUARD_AS_RESULT(kex->server_key_recv_parse_data(conn, raw_server_data)); + + return S2N_RESULT_OK; } -int s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data) +S2N_RESULT s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify, + struct s2n_kex_raw_server_data *raw_server_data) { - notnull_check(kex); - notnull_check(kex->server_key_recv_read_data); - return kex->server_key_recv_read_data(conn, data_to_verify, raw_server_data); + ENSURE_REF(kex); + ENSURE_REF(kex->server_key_recv_read_data); + ENSURE_REF(conn); + ENSURE_REF(data_to_verify); + + GUARD_AS_RESULT(kex->server_key_recv_read_data(conn, data_to_verify, raw_server_data)); + + return S2N_RESULT_OK; } -int s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign) +S2N_RESULT s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign) { - notnull_check(kex); - notnull_check(kex->server_key_send); - return kex->server_key_send(conn, data_to_sign); + ENSURE_REF(kex); + ENSURE_REF(kex->server_key_send); + ENSURE_REF(conn); + ENSURE_REF(data_to_sign); + + GUARD_AS_RESULT(kex->server_key_send(conn, data_to_sign)); + + return S2N_RESULT_OK; } -int s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key) +S2N_RESULT s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key) { - notnull_check(kex); - notnull_check(kex->client_key_recv); - return kex->client_key_recv(conn, shared_key); + ENSURE_REF(kex); + ENSURE_REF(kex->client_key_recv); + ENSURE_REF(conn); + ENSURE_REF(shared_key); + + GUARD_AS_RESULT(kex->client_key_recv(conn, shared_key)); + + return S2N_RESULT_OK; } -int s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key) +S2N_RESULT s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key) { - notnull_check(kex); - notnull_check(kex->client_key_send); - return kex->client_key_send(conn, shared_key); + ENSURE_REF(kex); + ENSURE_REF(kex->client_key_send); + ENSURE_REF(conn); + ENSURE_REF(shared_key); + + GUARD_AS_RESULT(kex->client_key_send(conn, shared_key)); + + return S2N_RESULT_OK; } -int s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret) +S2N_RESULT s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret) { - notnull_check(kex); - notnull_check(kex->prf); - return kex->prf(conn, premaster_secret); + ENSURE_REF(kex); + ENSURE_REF(kex->prf); + ENSURE_REF(conn); + ENSURE_REF(premaster_secret); + + GUARD_AS_RESULT(kex->prf(conn, premaster_secret)); + + return S2N_RESULT_OK; } bool s2n_kex_includes(const struct s2n_kex *kex, const struct s2n_kex *query) diff --git a/contrib/restricted/aws/s2n/tls/s2n_kex.h b/contrib/restricted/aws/s2n/tls/s2n_kex.h index 587cde5d63..e65392cce7 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kex.h +++ b/contrib/restricted/aws/s2n/tls/s2n_kex.h @@ -18,13 +18,14 @@ #include <stdint.h> #include "tls/s2n_connection.h" #include "tls/s2n_kex_data.h" +#include "utils/s2n_result.h" struct s2n_kex { - uint8_t is_ephemeral; + bool is_ephemeral; const struct s2n_kex *hybrid[2]; - int (*connection_supported)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); - int (*configure_connection)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); + S2N_RESULT (*connection_supported)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported); + S2N_RESULT (*configure_connection)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); int (*server_key_recv_read_data)(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *kex_data); int (*server_key_recv_parse_data)(struct s2n_connection *conn, struct s2n_kex_raw_server_data *kex_data); int (*server_key_send)(struct s2n_connection *conn, struct s2n_blob *data_to_sign); @@ -39,17 +40,17 @@ extern const struct s2n_kex s2n_dhe; extern const struct s2n_kex s2n_ecdhe; extern const struct s2n_kex s2n_hybrid_ecdhe_kem; -extern int s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); -extern int s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); -extern int s2n_kex_is_ephemeral(const struct s2n_kex *kex); +extern S2N_RESULT s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported); +extern S2N_RESULT s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); +extern S2N_RESULT s2n_kex_is_ephemeral(const struct s2n_kex *kex, bool *is_ephemeral); -extern int s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify, +extern S2N_RESULT s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data); -extern int s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); -extern int s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign); -extern int s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); -extern int s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); +extern S2N_RESULT s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); +extern S2N_RESULT s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign); +extern S2N_RESULT s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); +extern S2N_RESULT s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); -extern int s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret); +extern S2N_RESULT s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret); extern bool s2n_kex_includes(const struct s2n_kex *kex, const struct s2n_kex *query); diff --git a/contrib/restricted/aws/s2n/tls/s2n_psk.c b/contrib/restricted/aws/s2n/tls/s2n_psk.c index 2d764a00ed..59d4d75158 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_psk.c +++ b/contrib/restricted/aws/s2n/tls/s2n_psk.c @@ -16,7 +16,6 @@ #include "crypto/s2n_tls13_keys.h" #include "tls/s2n_handshake.h" -#include "tls/s2n_psk.h" #include "tls/s2n_tls13_handshake.h" #include "tls/s2n_tls.h" @@ -31,7 +30,7 @@ int s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type) notnull_check(psk); memset_check(psk, 0, sizeof(struct s2n_psk)); - psk->hash_alg = S2N_HASH_SHA256; + psk->hmac_alg = S2N_HMAC_SHA256; psk->type = type; return S2N_SUCCESS; @@ -78,48 +77,25 @@ S2N_RESULT s2n_psk_parameters_init(struct s2n_psk_parameters *params) return S2N_RESULT_OK; } -S2N_RESULT s2n_psk_parameters_free_unused_psks(struct s2n_psk_parameters *params) +S2N_CLEANUP_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params) { ENSURE_REF(params); + for (size_t i = 0; i < params->psk_list.len; i++) { struct s2n_psk *psk; GUARD_RESULT(s2n_array_get(¶ms->psk_list, i, (void**)&psk)); - - if(psk == params->chosen_psk) { - continue; - } GUARD_AS_RESULT(s2n_psk_free(psk)); } - return S2N_RESULT_OK; -} - -S2N_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params) -{ - ENSURE_REF(params); - - /* Free all PSKs */ - GUARD_RESULT(s2n_psk_parameters_free_unused_psks(params)); - GUARD_AS_RESULT(s2n_psk_free(params->chosen_psk)); - - struct s2n_blob psk_list_mem = params->psk_list.mem; - s2n_result result = s2n_psk_parameters_init(params); - params->psk_list.mem = psk_list_mem; + GUARD_AS_RESULT(s2n_free(¶ms->psk_list.mem)); + GUARD_RESULT(s2n_psk_parameters_init(params)); - return result; -} - -int s2n_psk_parameters_free(struct s2n_psk_parameters *params) -{ - notnull_check(params); - GUARD_AS_POSIX(s2n_psk_parameters_wipe(params)); - GUARD(s2n_free(¶ms->psk_list.mem)); - return S2N_SUCCESS; + return S2N_RESULT_OK; } /* The binder hash is computed by hashing the concatenation of the current transcript * and a partial ClientHello that does not include the binders themselves. */ -int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, +int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hmac_algorithm hmac_alg, const struct s2n_blob *partial_client_hello, struct s2n_blob *output_binder_hash) { notnull_check(partial_client_hello); @@ -128,6 +104,9 @@ int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hash_algorith /* Retrieve the current transcript. * The current transcript will be empty unless this handshake included a HelloRetryRequest. */ struct s2n_hash_state current_hash_state = {0}; + + s2n_hash_algorithm hash_alg; + GUARD(s2n_hmac_hash_alg(hmac_alg, &hash_alg)); GUARD(s2n_handshake_get_hash_state(conn, hash_alg, ¤t_hash_state)); /* Copy the current transcript to avoid modifying the original. */ @@ -144,20 +123,6 @@ int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hash_algorith return S2N_SUCCESS; } -static int s2n_tls13_keys_init_with_psk(struct s2n_tls13_keys *keys, struct s2n_psk *psk) -{ - notnull_check(keys); - - keys->hash_algorithm = psk->hash_alg; - GUARD(s2n_hash_hmac_alg(keys->hash_algorithm, &keys->hmac_algorithm)); - GUARD(s2n_hash_digest_size(keys->hash_algorithm, &keys->size)); - GUARD(s2n_blob_init(&keys->extract_secret, keys->extract_secret_bytes, keys->size)); - GUARD(s2n_blob_init(&keys->derive_secret, keys->derive_secret_bytes, keys->size)); - GUARD(s2n_hmac_new(&keys->hmac)); - - return S2N_SUCCESS; -} - /* The binder is computed in the same way as the Finished message * (https://tools.ietf.org/html/rfc8446#section-4.4.4) but with the BaseKey being the binder_key * derived via the key schedule from the corresponding PSK which is being offered @@ -171,7 +136,7 @@ int s2n_psk_calculate_binder(struct s2n_psk *psk, const struct s2n_blob *binder_ notnull_check(output_binder); DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free); - GUARD(s2n_tls13_keys_init_with_psk(&psk_keys, psk)); + GUARD(s2n_tls13_keys_init(&psk_keys, psk->hmac_alg)); eq_check(binder_hash->size, psk_keys.size); eq_check(output_binder->size, psk_keys.size); @@ -200,12 +165,12 @@ int s2n_psk_verify_binder(struct s2n_connection *conn, struct s2n_psk *psk, notnull_check(binder_to_verify); DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free); - GUARD(s2n_tls13_keys_init_with_psk(&psk_keys, psk)); + GUARD(s2n_tls13_keys_init(&psk_keys, psk->hmac_alg)); eq_check(binder_to_verify->size, psk_keys.size); /* Calculate the binder hash from the transcript */ s2n_tls13_key_blob(binder_hash, psk_keys.size); - GUARD(s2n_psk_calculate_binder_hash(conn, psk->hash_alg, partial_client_hello, &binder_hash)); + GUARD(s2n_psk_calculate_binder_hash(conn, psk->hmac_alg, partial_client_hello, &binder_hash)); /* Calculate the expected binder from the binder hash */ s2n_tls13_key_blob(expected_binder, psk_keys.size); @@ -257,13 +222,25 @@ static S2N_RESULT s2n_psk_write_binder_list(struct s2n_connection *conn, const s GUARD_RESULT(s2n_array_get(psk_list, i, (void**) &psk)); ENSURE_REF(psk); + /** + *= https://tools.ietf.org/rfc/rfc8446#section-4.1.4 + *# In addition, in its updated ClientHello, the client SHOULD NOT offer + *# any pre-shared keys associated with a hash other than that of the + *# selected cipher suite. This allows the client to avoid having to + *# compute partial hash transcripts for multiple hashes in the second + *# ClientHello. + */ + if (s2n_is_hello_retry_handshake(conn) && conn->secure.cipher_suite->prf_alg != psk->hmac_alg) { + continue; + } + /* Retrieve or calculate the binder hash. */ - struct s2n_blob *binder_hash = &binder_hashes[psk->hash_alg]; + struct s2n_blob *binder_hash = &binder_hashes[psk->hmac_alg]; if (binder_hash->size == 0) { uint8_t hash_size = 0; - GUARD_AS_RESULT(s2n_hash_digest_size(psk->hash_alg, &hash_size)); - GUARD_AS_RESULT(s2n_blob_init(binder_hash, binder_hashes_data[psk->hash_alg], hash_size)); - GUARD_AS_RESULT(s2n_psk_calculate_binder_hash(conn, psk->hash_alg, partial_client_hello, binder_hash)); + GUARD_AS_RESULT(s2n_hmac_digest_size(psk->hmac_alg, &hash_size)); + GUARD_AS_RESULT(s2n_blob_init(binder_hash, binder_hashes_data[psk->hmac_alg], hash_size)); + GUARD_AS_RESULT(s2n_psk_calculate_binder_hash(conn, psk->hmac_alg, partial_client_hello, binder_hash)); } GUARD_RESULT(s2n_psk_write_binder(conn, psk, binder_hash, out)); @@ -300,3 +277,57 @@ S2N_RESULT s2n_finish_psk_extension(struct s2n_connection *conn) GUARD_RESULT(s2n_psk_write_binder_list(conn, &partial_client_hello, client_hello)); return S2N_RESULT_OK; } + +static S2N_RESULT s2n_psk_set_hmac(struct s2n_psk *psk, s2n_psk_hmac psk_hmac_alg) +{ + switch(psk_hmac_alg) { + case S2N_PSK_HMAC_SHA224: psk->hmac_alg = S2N_HMAC_SHA224; break; + case S2N_PSK_HMAC_SHA256: psk->hmac_alg = S2N_HMAC_SHA256; break; + case S2N_PSK_HMAC_SHA384: psk->hmac_alg = S2N_HMAC_SHA384; break; + default: + BAIL(S2N_ERR_HMAC_INVALID_ALGORITHM); + } + return S2N_RESULT_OK; +} + +int s2n_connection_set_external_psks(struct s2n_connection *conn, struct s2n_external_psk *psk_vec, size_t psk_vec_length) +{ + ENSURE_POSIX_REF(conn); + ENSURE_POSIX_REF(psk_vec); + + /* Remove all previously-set external psks */ + /* The loop iterates from len to 1 instead of from len-1 to 0 to avoid size_t underflowing */ + for (size_t i = conn->psk_params.psk_list.len; i > 0; i--) { + size_t i_index = i - 1; + struct s2n_psk *psk = NULL; + GUARD_AS_POSIX(s2n_array_get(&conn->psk_params.psk_list, i_index, (void**) &psk)); + ENSURE_POSIX_REF(psk); + if (psk->type == S2N_PSK_TYPE_EXTERNAL) { + GUARD(s2n_psk_free(psk)); + GUARD_AS_POSIX(s2n_array_remove(&conn->psk_params.psk_list, i_index)); + } + } + + for (size_t i = 0; i < psk_vec_length; i++) { + /* Check for duplicate identities */ + size_t array_len = conn->psk_params.psk_list.len; + for (size_t j = 0; j < array_len; j++) { + struct s2n_psk *psk = NULL; + GUARD_AS_POSIX(s2n_array_get(&conn->psk_params.psk_list, j, (void**) &psk)); + ENSURE_POSIX_REF(psk); + if (psk->identity.size == psk_vec[i].identity_length) { + ENSURE_POSIX(memcmp(psk->identity.data, psk_vec[i].identity, psk->identity.size) != 0, S2N_ERR_DUPLICATE_PSK_IDENTITIES); + } + } + + struct s2n_psk *new_psk = NULL; + GUARD_AS_POSIX(s2n_array_pushback(&conn->psk_params.psk_list, (void**) &new_psk)); + ENSURE_POSIX_REF(new_psk); + GUARD(s2n_psk_init(new_psk, S2N_PSK_TYPE_EXTERNAL)); + GUARD(s2n_psk_new_identity(new_psk, psk_vec[i].identity, psk_vec[i].identity_length)); + GUARD(s2n_psk_new_secret(new_psk, psk_vec[i].secret, psk_vec[i].secret_length)); + GUARD_AS_POSIX(s2n_psk_set_hmac(new_psk, psk_vec[i].hmac)); + } + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_psk.h b/contrib/restricted/aws/s2n/tls/s2n_psk.h index a805eaddfa..6d7052c876 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_psk.h +++ b/contrib/restricted/aws/s2n/tls/s2n_psk.h @@ -17,7 +17,7 @@ #include <s2n.h> -#include "crypto/s2n_hash.h" +#include "crypto/s2n_hmac.h" #include "utils/s2n_array.h" #include "utils/s2n_blob.h" #include "utils/s2n_result.h" @@ -27,37 +27,71 @@ typedef enum { S2N_PSK_TYPE_EXTERNAL, } s2n_psk_type; +typedef enum { + S2N_PSK_KE_UNKNOWN = 0, + S2N_PSK_KE, + S2N_PSK_DHE_KE, +} s2n_psk_key_exchange_mode; + +typedef enum { + S2N_PSK_HMAC_SHA224 = 0, + S2N_PSK_HMAC_SHA256, + S2N_PSK_HMAC_SHA384, +} s2n_psk_hmac; + +struct s2n_external_psk { + uint8_t *identity; + size_t identity_length; + uint8_t *secret; + size_t secret_length; + s2n_psk_hmac hmac; +}; + struct s2n_psk { s2n_psk_type type; struct s2n_blob identity; struct s2n_blob secret; - s2n_hash_algorithm hash_alg; + s2n_hmac_algorithm hmac_alg; uint32_t obfuscated_ticket_age; struct s2n_blob early_secret; }; +struct s2n_psk_identity { + uint8_t *data; + uint16_t length; +}; + struct s2n_psk_parameters { struct s2n_array psk_list; uint16_t binder_list_size; - uint8_t chosen_psk_wire_index; + uint16_t chosen_psk_wire_index; struct s2n_psk *chosen_psk; + s2n_psk_key_exchange_mode psk_ke_mode; }; +/* This function will be labeled S2N_API and become a publicly visible api once we release the psk API. */ +int s2n_connection_set_external_psks(struct s2n_connection *conn, struct s2n_external_psk *psk_vec, size_t psk_vec_length); + int s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type); int s2n_psk_new_identity(struct s2n_psk *psk, const uint8_t *identity, size_t identity_size); int s2n_psk_new_secret(struct s2n_psk *psk, const uint8_t *secret, size_t secret_size); int s2n_psk_free(struct s2n_psk *psk); S2N_RESULT s2n_psk_parameters_init(struct s2n_psk_parameters *params); -S2N_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params); -S2N_RESULT s2n_psk_parameters_free_unused_psks(struct s2n_psk_parameters *params); -int s2n_psk_parameters_free(struct s2n_psk_parameters *params); +S2N_CLEANUP_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params); S2N_RESULT s2n_finish_psk_extension(struct s2n_connection *conn); -int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, +int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hmac_algorithm hmac_alg, const struct s2n_blob *partial_client_hello, struct s2n_blob *output_binder_hash); int s2n_psk_calculate_binder(struct s2n_psk *psk, const struct s2n_blob *binder_hash, struct s2n_blob *output_binder); int s2n_psk_verify_binder(struct s2n_connection *conn, struct s2n_psk *psk, const struct s2n_blob *partial_client_hello, struct s2n_blob *binder_to_verify); + +typedef int (*s2n_psk_selection_callback)(struct s2n_connection *conn, + struct s2n_psk_identity *identities, size_t identities_length, + uint16_t *chosen_wire_index); +/* This function will be labeled S2N_API and become a publicly visible api once we release the psk API. */ +int s2n_config_set_psk_selection_callback(struct s2n_connection *conn, s2n_psk_selection_callback cb); + diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c b/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c index 2c2c8df1f1..87207d3723 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c +++ b/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c @@ -71,7 +71,7 @@ int s2n_record_parse_aead( GUARD(s2n_stuffer_write_bytes(&iv_stuffer, four_zeroes, 4)); GUARD(s2n_stuffer_write_bytes(&iv_stuffer, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN)); for (int i = 0; i < cipher_suite->record_alg->cipher->io.aead.fixed_iv_size; i++) { - S2N_INVARIENT(i <= cipher_suite->record_alg->cipher->io.aead.fixed_iv_size); + S2N_INVARIANT(i <= cipher_suite->record_alg->cipher->io.aead.fixed_iv_size); aad_iv[i] = aad_iv[i] ^ implicit_iv[i]; } } else { diff --git a/contrib/restricted/aws/s2n/tls/s2n_recv.c b/contrib/restricted/aws/s2n/tls/s2n_recv.c index 8d0d04d4f0..8aa34e6d06 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_recv.c +++ b/contrib/restricted/aws/s2n/tls/s2n_recv.c @@ -117,7 +117,7 @@ int s2n_read_full_record(struct s2n_connection *conn, uint8_t * record_type, int return 0; } -ssize_t s2n_recv(struct s2n_connection * conn, void *buf, ssize_t size, s2n_blocked_status * blocked) +ssize_t s2n_recv_impl(struct s2n_connection * conn, void *buf, ssize_t size, s2n_blocked_status * blocked) { ssize_t bytes_read = 0; struct s2n_blob out = {.data = (uint8_t *) buf }; @@ -204,6 +204,15 @@ ssize_t s2n_recv(struct s2n_connection * conn, void *buf, ssize_t size, s2n_bloc return bytes_read; } +ssize_t s2n_recv(struct s2n_connection * conn, void *buf, ssize_t size, s2n_blocked_status * blocked) +{ + ENSURE_POSIX(!conn->recv_in_use, S2N_ERR_REENTRANCY); + conn->recv_in_use = true; + ssize_t result = s2n_recv_impl(conn, buf, size, blocked); + conn->recv_in_use = false; + return result; +} + uint32_t s2n_peek(struct s2n_connection *conn) { return s2n_stuffer_data_available(&conn->in); } diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c index 2daa495369..388fb25b56 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c +++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c @@ -224,6 +224,14 @@ const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2019 = { .ecc_preferences = &s2n_ecc_preferences_20200310, }; +const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2021 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_cloudfront_tls_1_2_2021, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + /* CloudFront viewer facing legacy TLS 1.2 policies */ const struct s2n_security_policy security_policy_cloudfront_ssl_v_3_legacy = { .minimum_protocol_version = S2N_SSLv3, @@ -281,8 +289,6 @@ const struct s2n_security_policy security_policy_kms_tls_1_0_2018_10 = { .ecc_preferences = &s2n_ecc_preferences_20140601, }; -#if !defined(S2N_NO_PQ) - const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2019_06 = { .minimum_protocol_version = S2N_TLS10, .cipher_preferences = &cipher_preferences_kms_pq_tls_1_0_2019_06, @@ -331,7 +337,6 @@ const struct s2n_security_policy security_policy_pq_tls_1_0_2020_12 = { .ecc_preferences = &s2n_ecc_preferences_20200310, }; -#endif const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10 = { .minimum_protocol_version = S2N_TLS12, .cipher_preferences = &cipher_preferences_kms_fips_tls_1_2_2018_10, @@ -463,11 +468,7 @@ const struct s2n_security_policy security_policy_20201021 = { const struct s2n_security_policy security_policy_test_all = { .minimum_protocol_version = S2N_SSLv3, .cipher_preferences = &cipher_preferences_test_all, -#if !defined(S2N_NO_PQ) .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_07, -#else - .kem_preferences = &kem_preferences_null, -#endif .signature_preferences = &s2n_signature_preferences_20201021, .ecc_preferences = &s2n_ecc_preferences_test_all, }; @@ -475,11 +476,7 @@ const struct s2n_security_policy security_policy_test_all = { const struct s2n_security_policy security_policy_test_all_tls12 = { .minimum_protocol_version = S2N_SSLv3, .cipher_preferences = &cipher_preferences_test_all_tls12, -#if !defined(S2N_NO_PQ) .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_07, -#else - .kem_preferences = &kem_preferences_null, -#endif .signature_preferences = &s2n_signature_preferences_20201021, .ecc_preferences = &s2n_ecc_preferences_20201021, }; @@ -488,8 +485,8 @@ const struct s2n_security_policy security_policy_test_all_fips = { .minimum_protocol_version = S2N_TLS10, .cipher_preferences = &cipher_preferences_test_all_fips, .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, + .signature_preferences = &s2n_signature_preferences_20201021, + .ecc_preferences = &s2n_ecc_preferences_20201021, }; const struct s2n_security_policy security_policy_test_all_ecdsa = { @@ -558,6 +555,7 @@ struct s2n_security_policy_selection security_policy_selection[] = { { .version="CloudFront-TLS-1-1-2016", .security_policy=&security_policy_cloudfront_tls_1_1_2016, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="CloudFront-TLS-1-2-2018", .security_policy=&security_policy_cloudfront_tls_1_2_2018, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="CloudFront-TLS-1-2-2019", .security_policy=&security_policy_cloudfront_tls_1_2_2019, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-TLS-1-2-2021", .security_policy=&security_policy_cloudfront_tls_1_2_2021, .ecc_extension_required=0, .pq_kem_extension_required=0 }, /* CloudFront Legacy (TLS 1.2) policies */ { .version="CloudFront-SSL-v-3-Legacy", .security_policy=&security_policy_cloudfront_ssl_v_3_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="CloudFront-TLS-1-0-2014-Legacy", .security_policy=&security_policy_cloudfront_tls_1_0_2014_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 }, @@ -566,14 +564,12 @@ struct s2n_security_policy_selection security_policy_selection[] = { { .version="CloudFront-TLS-1-2-2018-Legacy", .security_policy=&security_policy_cloudfront_tls_1_2_2018_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="CloudFront-TLS-1-2-2019-Legacy", .security_policy=&security_policy_cloudfront_tls_1_2_2019_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="KMS-TLS-1-0-2018-10", .security_policy=&security_policy_kms_tls_1_0_2018_10, .ecc_extension_required=0, .pq_kem_extension_required=0 }, -#if !defined(S2N_NO_PQ) { .version="KMS-PQ-TLS-1-0-2019-06", .security_policy=&security_policy_kms_pq_tls_1_0_2019_06, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="KMS-PQ-TLS-1-0-2020-02", .security_policy=&security_policy_kms_pq_tls_1_0_2020_02, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="KMS-PQ-TLS-1-0-2020-07", .security_policy=&security_policy_kms_pq_tls_1_0_2020_07, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="PQ-SIKE-TEST-TLS-1-0-2019-11", .security_policy=&security_policy_pq_sike_test_tls_1_0_2019_11, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="PQ-SIKE-TEST-TLS-1-0-2020-02", .security_policy=&security_policy_pq_sike_test_tls_1_0_2020_02, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="PQ-TLS-1-0-2020-12", .security_policy=&security_policy_pq_tls_1_0_2020_12, .ecc_extension_required=0, .pq_kem_extension_required=0 }, -#endif { .version="KMS-FIPS-TLS-1-2-2018-10", .security_policy=&security_policy_kms_fips_tls_1_2_2018_10, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="20140601", .security_policy=&security_policy_20140601, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="20141001", .security_policy=&security_policy_20141001, .ecc_extension_required=0, .pq_kem_extension_required=0 }, diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h index ab71889ad7..f724eb1934 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h +++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h @@ -79,14 +79,12 @@ extern const struct s2n_security_policy security_policy_elb_fs_1_2_2019_08; extern const struct s2n_security_policy security_policy_elb_fs_1_1_2019_08; extern const struct s2n_security_policy security_policy_elb_fs_1_2_res_2019_08; -#if !defined(S2N_NO_PQ) extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2019_06; extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_02; extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_07; extern const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2019_11; extern const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2020_02; extern const struct s2n_security_policy security_policy_pq_tls_1_0_2020_12; -#endif extern const struct s2n_security_policy security_policy_cloudfront_upstream; extern const struct s2n_security_policy security_policy_cloudfront_upstream_tls10; @@ -97,6 +95,7 @@ extern const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2016; extern const struct s2n_security_policy security_policy_cloudfront_tls_1_1_2016; extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2018; extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2019; +extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2021; extern const struct s2n_security_policy security_policy_kms_tls_1_0_2018_10; extern const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10; diff --git a/contrib/restricted/aws/s2n/tls/s2n_send.c b/contrib/restricted/aws/s2n/tls/s2n_send.c index c9f9cf89d6..4f59054845 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_send.c +++ b/contrib/restricted/aws/s2n/tls/s2n_send.c @@ -88,7 +88,7 @@ int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * blocked) return 0; } -ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, ssize_t offs, s2n_blocked_status *blocked) +ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, ssize_t offs, s2n_blocked_status *blocked) { ssize_t user_data_sent, total_size = 0; @@ -203,6 +203,15 @@ ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *b return total_size; } +ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, ssize_t offs, s2n_blocked_status *blocked) +{ + ENSURE_POSIX(!conn->send_in_use, S2N_ERR_REENTRANCY); + conn->send_in_use = true; + ssize_t result = s2n_sendv_with_offset_impl(conn, bufs, count, offs, blocked); + conn->send_in_use = false; + return result; +} + ssize_t s2n_sendv(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, s2n_blocked_status *blocked) { return s2n_sendv_with_offset(conn, bufs, count, 0, blocked); diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c b/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c index f35c5a0016..a6dda9edf8 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c @@ -22,7 +22,7 @@ #include "tls/s2n_tls13.h" #include "tls/s2n_tls13_handshake.h" #include "utils/s2n_safety.h" -#include "crypto/s2n_fips.h" +#include "pq-crypto/s2n_pq.h" /* From RFC5246 7.4.1.2. */ #define S2N_TLS_COMPRESSION_METHOD_NULL 0 @@ -107,9 +107,9 @@ int s2n_server_hello_retry_recv(struct s2n_connection *conn) } if (kem_group != NULL) { - /* If in FIPS mode, the client should not have sent any PQ IDs + /* If PQ is disabled, the client should not have sent any PQ IDs * in the supported_groups list of the initial ClientHello */ - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED); for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) { if (kem_pref->tls13_kem_groups[i] == kem_group) { diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c b/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c index 2169f7c5e2..9116868110 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c @@ -49,7 +49,7 @@ int s2n_server_key_recv(struct s2n_connection *conn) /* Read the KEX data */ struct s2n_kex_raw_server_data kex_data = {0}; - GUARD(s2n_kex_server_key_recv_read_data(key_exchange, conn, &data_to_verify, &kex_data)); + GUARD_AS_POSIX(s2n_kex_server_key_recv_read_data(key_exchange, conn, &data_to_verify, &kex_data)); /* Add common signature data */ struct s2n_signature_scheme active_sig_scheme; @@ -81,7 +81,7 @@ int s2n_server_key_recv(struct s2n_connection *conn) GUARD(s2n_pkey_free(&conn->secure.server_public_key)); /* Parse the KEX data into whatever form needed and save it to the connection object */ - GUARD(s2n_kex_server_key_recv_parse_data(key_exchange, conn, &kex_data)); + GUARD_AS_POSIX(s2n_kex_server_key_recv_parse_data(key_exchange, conn, &kex_data)); return 0; } @@ -209,10 +209,10 @@ int s2n_hybrid_server_key_recv_read_data(struct s2n_connection *conn, struct s2n notnull_check(total_data_to_verify->data); struct s2n_blob data_to_verify_0 = {0}; - GUARD(s2n_kex_server_key_recv_read_data(hybrid_kex_0, conn, &data_to_verify_0, raw_server_data)); + GUARD_AS_POSIX(s2n_kex_server_key_recv_read_data(hybrid_kex_0, conn, &data_to_verify_0, raw_server_data)); struct s2n_blob data_to_verify_1 = {0}; - GUARD(s2n_kex_server_key_recv_read_data(hybrid_kex_1, conn, &data_to_verify_1, raw_server_data)); + GUARD_AS_POSIX(s2n_kex_server_key_recv_read_data(hybrid_kex_1, conn, &data_to_verify_1, raw_server_data)); total_data_to_verify->size = data_to_verify_0.size + data_to_verify_1.size; return 0; @@ -226,8 +226,8 @@ int s2n_hybrid_server_key_recv_parse_data(struct s2n_connection *conn, struct s2 const struct s2n_kex *hybrid_kex_0 = kex->hybrid[0]; const struct s2n_kex *hybrid_kex_1 = kex->hybrid[1]; - GUARD(s2n_kex_server_key_recv_parse_data(hybrid_kex_0, conn, raw_server_data)); - GUARD(s2n_kex_server_key_recv_parse_data(hybrid_kex_1, conn, raw_server_data)); + GUARD_AS_POSIX(s2n_kex_server_key_recv_parse_data(hybrid_kex_0, conn, raw_server_data)); + GUARD_AS_POSIX(s2n_kex_server_key_recv_parse_data(hybrid_kex_1, conn, raw_server_data)); return 0; } @@ -241,7 +241,7 @@ int s2n_server_key_send(struct s2n_connection *conn) struct s2n_blob data_to_sign = {0}; /* Call the negotiated key exchange method to send it's data */ - GUARD(s2n_kex_server_key_send(key_exchange, conn, &data_to_sign)); + GUARD_AS_POSIX(s2n_kex_server_key_send(key_exchange, conn, &data_to_sign)); /* Add common signature data */ if (conn->actual_protocol_version == S2N_TLS12) { @@ -315,10 +315,10 @@ int s2n_hybrid_server_key_send(struct s2n_connection *conn, struct s2n_blob *tot notnull_check(total_data_to_sign->data); struct s2n_blob data_to_verify_0 = {0}; - GUARD(s2n_kex_server_key_send(hybrid_kex_0, conn, &data_to_verify_0)); + GUARD_AS_POSIX(s2n_kex_server_key_send(hybrid_kex_0, conn, &data_to_verify_0)); struct s2n_blob data_to_verify_1 = {0}; - GUARD(s2n_kex_server_key_send(hybrid_kex_1, conn, &data_to_verify_1)); + GUARD_AS_POSIX(s2n_kex_server_key_send(hybrid_kex_1, conn, &data_to_verify_1)); total_data_to_sign->size = data_to_verify_0.size + data_to_verify_1.size; return 0; diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c index fe000814e7..4382c02382 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c +++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c @@ -189,7 +189,9 @@ int s2n_tls13_handle_handshake_secrets(struct s2n_connection *conn) GUARD(s2n_tls13_compute_shared_secret(conn, &shared_secret)); /* derive early secrets */ - GUARD(s2n_tls13_derive_early_secrets(&secrets)); + GUARD(s2n_tls13_derive_early_secrets(&secrets, conn->psk_params.chosen_psk)); + /* since early secrets have been computed, PSKs are no longer needed and can be cleaned up */ + GUARD_AS_POSIX(s2n_psk_parameters_wipe(&conn->psk_params)); /* produce handshake secrets */ s2n_stack_blob(client_hs_secret, secrets.size, S2N_TLS13_SECRET_MAX_LEN); @@ -315,6 +317,19 @@ static int s2n_tls13_handle_master_secret(struct s2n_connection *conn) return S2N_SUCCESS; } +static int s2n_tls13_handle_resumption_master_secret(struct s2n_connection *conn) +{ + s2n_tls13_connection_keys(keys, conn); + + struct s2n_hash_state hash_state = {0}; + GUARD(s2n_handshake_get_hash_state(conn, keys.hash_algorithm, &hash_state)); + + struct s2n_blob resumption_master_secret = {0}; + GUARD(s2n_blob_init(&resumption_master_secret, conn->resumption_master_secret, keys.size)); + GUARD(s2n_tls13_derive_resumption_master_secret(&keys, &hash_state, &resumption_master_secret)); + return S2N_SUCCESS; +} + int s2n_tls13_handle_secrets(struct s2n_connection *conn) { notnull_check(conn); @@ -341,6 +356,7 @@ int s2n_tls13_handle_secrets(struct s2n_connection *conn) GUARD(s2n_tls13_handle_application_secret(conn, S2N_SERVER)); } GUARD(s2n_tls13_handle_application_secret(conn, S2N_CLIENT)); + GUARD(s2n_tls13_handle_resumption_master_secret(conn)); break; default: break; diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h b/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h index 1980a69138..7bce43d0b2 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h +++ b/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h @@ -106,12 +106,22 @@ #define TLS_EXTENSION_RENEGOTIATION_INFO 65281 /* TLS 1.3 extensions from https://tools.ietf.org/html/rfc8446#section-4.2 */ -#define TLS_EXTENSION_SUPPORTED_VERSIONS 43 -#define TLS_EXTENSION_COOKIE 44 -#define TLS_EXTENSION_KEY_SHARE 51 - -/* QUIC-TLS extension from https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-8.2 */ -#define TLS_QUIC_TRANSPORT_PARAMETERS 65535 +#define TLS_EXTENSION_SUPPORTED_VERSIONS 43 +#define TLS_EXTENSION_COOKIE 44 +#define TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES 45 +#define TLS_EXTENSION_KEY_SHARE 51 + +/* TLS 1.3 pre-shared key exchange modes from https://tools.ietf.org/html/rfc8446#section-4.2.9 */ +#define TLS_PSK_KE_MODE 0 +#define TLS_PSK_DHE_KE_MODE 1 + +/** + *= https://tools.ietf.org/id/draft-ietf-quic-tls-32.txt#8.2 + *# enum { + *# quic_transport_parameters(0xffa5), (65535) + *# } ExtensionType; + */ +#define TLS_QUIC_TRANSPORT_PARAMETERS 0xffa5 /* TLS Signature Algorithms - RFC 5246 7.4.1.4.1 */ /* https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16 */ diff --git a/contrib/restricted/aws/s2n/utils/s2n_annotations.h b/contrib/restricted/aws/s2n/utils/s2n_annotations.h index 4a004c92a1..0d6c01dd05 100644 --- a/contrib/restricted/aws/s2n/utils/s2n_annotations.h +++ b/contrib/restricted/aws/s2n/utils/s2n_annotations.h @@ -16,4 +16,4 @@ /* For compilation purposes, these annotations are no-ops */ #define S2N_PUBLIC_INPUT(__a) -#define S2N_INVARIENT(__a) +#define S2N_INVARIANT(__a) diff --git a/contrib/restricted/aws/s2n/utils/s2n_result.h b/contrib/restricted/aws/s2n/utils/s2n_result.h index 9a1b3ed13a..c135c55074 100644 --- a/contrib/restricted/aws/s2n/utils/s2n_result.h +++ b/contrib/restricted/aws/s2n/utils/s2n_result.h @@ -44,5 +44,10 @@ S2N_RESULT_MUST_USE bool s2n_result_is_error(s2n_result result); /* used in function declarations to signal function fallibility */ #define S2N_RESULT S2N_RESULT_MUST_USE s2n_result +/* The DEFER_CLEANUP macro discards the result of its cleanup function. + * We need a version of s2n_result which can be ignored. + */ +#define S2N_CLEANUP_RESULT s2n_result + /* converts the S2N_RESULT into posix error codes */ #define S2N_RESULT_TO_POSIX( x ) (s2n_result_is_ok(x) ? S2N_SUCCESS : S2N_FAILURE) diff --git a/contrib/restricted/aws/s2n/utils/s2n_safety.c b/contrib/restricted/aws/s2n/utils/s2n_safety.c index d786c4d852..13c741b3ec 100644 --- a/contrib/restricted/aws/s2n/utils/s2n_safety.c +++ b/contrib/restricted/aws/s2n/utils/s2n_safety.c @@ -60,6 +60,8 @@ bool s2n_constant_time_equals(const uint8_t * a, const uint8_t * b, const uint32 S2N_PUBLIC_INPUT(a); S2N_PUBLIC_INPUT(b); S2N_PUBLIC_INPUT(len); + ENSURE_POSIX((a == NULL) || S2N_MEM_IS_READABLE(a, len), S2N_ERR_SAFETY); + ENSURE_POSIX((b == NULL) || S2N_MEM_IS_READABLE(b, len), S2N_ERR_SAFETY); if (len != 0 && (a == NULL || b == NULL)) { return false; @@ -69,7 +71,7 @@ bool s2n_constant_time_equals(const uint8_t * a, const uint8_t * b, const uint32 for (int i = 0; i < len; i++) { /* Invariants must hold for each execution of the loop * and at loop exit, hence the <= */ - S2N_INVARIENT(i <= len); + S2N_INVARIANT(i <= len); xor |= a[i] ^ b[i]; } diff --git a/contrib/restricted/aws/s2n/ya.make b/contrib/restricted/aws/s2n/ya.make index f216afee82..f6de16d8f0 100644 --- a/contrib/restricted/aws/s2n/ya.make +++ b/contrib/restricted/aws/s2n/ya.make @@ -7,9 +7,9 @@ OWNER( g:cpp-contrib ) -VERSION(0.10.23) +VERSION(0.10.26) -ORIGINAL_SOURCE(https://github.com/aws/s2n-tls/archive/v0.10.23.tar.gz) +ORIGINAL_SOURCE(https://github.com/aws/s2n-tls/archive/v0.10.26.tar.gz) LICENSE( Apache-2.0 AND @@ -162,11 +162,13 @@ SRCS( tls/extensions/s2n_extension_type.c tls/extensions/s2n_extension_type_lists.c tls/extensions/s2n_key_share.c + tls/extensions/s2n_psk_key_exchange_modes.c tls/extensions/s2n_quic_transport_params.c tls/extensions/s2n_server_alpn.c tls/extensions/s2n_server_certificate_status.c tls/extensions/s2n_server_key_share.c tls/extensions/s2n_server_max_fragment_length.c + tls/extensions/s2n_server_psk.c tls/extensions/s2n_server_renegotiation_info.c tls/extensions/s2n_server_sct_list.c tls/extensions/s2n_server_server_name.c |