diff options
author | robot-contrib <robot-contrib@yandex-team.com> | 2023-10-23 21:53:30 +0300 |
---|---|---|
committer | robot-contrib <robot-contrib@yandex-team.com> | 2023-10-23 22:17:19 +0300 |
commit | 185aad3f5de6274260a161e58d92312d91813770 (patch) | |
tree | 39b2a93a9a649bffaaea9e405b00ceeea0d13c11 /contrib/restricted/aws/s2n/crypto | |
parent | a14514f8c6ab647d334ae41253e65f69ee9b5fa6 (diff) | |
download | ydb-185aad3f5de6274260a161e58d92312d91813770.tar.gz |
Update contrib/restricted/aws/s2n to 1.3.54
Diffstat (limited to 'contrib/restricted/aws/s2n/crypto')
17 files changed, 456 insertions, 101 deletions
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_aes_gcm.c b/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_aes_gcm.c index 5fb83b3df7..0d7a8f2d84 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_aes_gcm.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_aes_gcm.c @@ -17,6 +17,7 @@ #include <openssl/evp.h> #include "crypto/s2n_cipher.h" +#include "crypto/s2n_ktls_crypto.h" #include "tls/s2n_crypto.h" #include "utils/s2n_blob.h" #include "utils/s2n_safety.h" @@ -376,6 +377,74 @@ static int s2n_aead_cipher_aes_gcm_destroy_key(struct s2n_session_key *key) #endif +static S2N_RESULT s2n_aead_cipher_aes128_gcm_set_ktls_info(struct s2n_ktls_crypto_info_inputs *in, + struct s2n_ktls_crypto_info *out) +{ + RESULT_ENSURE_REF(in); + RESULT_ENSURE_REF(out); + + s2n_ktls_crypto_info_tls12_aes_gcm_128 *crypto_info = &out->ciphers.aes_gcm_128; + crypto_info->info.version = TLS_1_2_VERSION; + crypto_info->info.cipher_type = TLS_CIPHER_AES_GCM_128; + + RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size); + RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key)); + + RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->iv.size); + RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data, sizeof(crypto_info->iv)); + + RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size); + RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq)); + + /* The salt is a prefix of the IV + * + *= https://www.rfc-editor.org/rfc/rfc4106#section-4 + *# The salt field is a four-octet value that is assigned at the + *# beginning of the security association, and then remains constant + *# for the life of the security association. + */ + RESULT_ENSURE_LTE(sizeof(crypto_info->salt), in->iv.size); + RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, sizeof(crypto_info->salt)); + + RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info, + sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_128))); + return S2N_RESULT_OK; +} + +static S2N_RESULT s2n_aead_cipher_aes256_gcm_set_ktls_info( + struct s2n_ktls_crypto_info_inputs *in, struct s2n_ktls_crypto_info *out) +{ + RESULT_ENSURE_REF(in); + RESULT_ENSURE_REF(out); + + s2n_ktls_crypto_info_tls12_aes_gcm_256 *crypto_info = &out->ciphers.aes_gcm_256; + crypto_info->info.version = TLS_1_2_VERSION; + crypto_info->info.cipher_type = TLS_CIPHER_AES_GCM_256; + + RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size); + RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key)); + + RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->iv.size); + RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data, sizeof(crypto_info->iv)); + + RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size); + RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq)); + + /* The salt is a prefix of the IV + * + *= https://www.rfc-editor.org/rfc/rfc4106#section-4 + *# The salt field is a four-octet value that is assigned at the + *# beginning of the security association, and then remains constant + *# for the life of the security association. + */ + RESULT_ENSURE_LTE(sizeof(crypto_info->salt), in->iv.size); + RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, sizeof(crypto_info->salt)); + + RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info, + sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_256))); + return S2N_RESULT_OK; +} + const struct s2n_cipher s2n_aes128_gcm = { .key_material_size = S2N_TLS_AES_128_GCM_KEY_LEN, .type = S2N_AEAD, @@ -390,7 +459,7 @@ const struct s2n_cipher s2n_aes128_gcm = { .set_encryption_key = s2n_aead_cipher_aes128_gcm_set_encryption_key, .set_decryption_key = s2n_aead_cipher_aes128_gcm_set_decryption_key, .destroy_key = s2n_aead_cipher_aes_gcm_destroy_key, - .ktls_supported = true, + .set_ktls_info = s2n_aead_cipher_aes128_gcm_set_ktls_info, }; const struct s2n_cipher s2n_aes256_gcm = { @@ -407,6 +476,7 @@ const struct s2n_cipher s2n_aes256_gcm = { .set_encryption_key = s2n_aead_cipher_aes256_gcm_set_encryption_key, .set_decryption_key = s2n_aead_cipher_aes256_gcm_set_decryption_key, .destroy_key = s2n_aead_cipher_aes_gcm_destroy_key, + .set_ktls_info = s2n_aead_cipher_aes256_gcm_set_ktls_info, }; /* TLS 1.3 GCM ciphers */ diff --git a/contrib/restricted/aws/s2n/crypto/s2n_cipher.h b/contrib/restricted/aws/s2n/crypto/s2n_cipher.h index 18ac7cdccf..47c724ea63 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_cipher.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_cipher.h @@ -23,6 +23,7 @@ #include <openssl/rsa.h> #include "crypto/s2n_crypto.h" +#include "crypto/s2n_ktls_crypto.h" #include "utils/s2n_blob.h" #if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) @@ -81,12 +82,13 @@ struct s2n_cipher { struct s2n_composite_cipher comp; } io; uint8_t key_material_size; - bool ktls_supported; uint8_t (*is_available)(void); int (*init)(struct s2n_session_key *key); int (*set_decryption_key)(struct s2n_session_key *key, struct s2n_blob *in); int (*set_encryption_key)(struct s2n_session_key *key, struct s2n_blob *in); int (*destroy_key)(struct s2n_session_key *key); + S2N_RESULT (*set_ktls_info)(struct s2n_ktls_crypto_info_inputs *inputs, + struct s2n_ktls_crypto_info *crypto_info); }; int s2n_session_key_alloc(struct s2n_session_key *key); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_dhe.c b/contrib/restricted/aws/s2n/crypto/s2n_dhe.c index aa5b629c09..da8f845e3b 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_dhe.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_dhe.c @@ -138,24 +138,29 @@ int s2n_pkcs3_to_dh_params(struct s2n_dh_params *dh_params, struct s2n_blob *pkc { POSIX_ENSURE_REF(dh_params); POSIX_PRECONDITION(s2n_blob_validate(pkcs3)); + DEFER_CLEANUP(struct s2n_dh_params temp_dh_params = { 0 }, s2n_dh_params_free); uint8_t *original_ptr = pkcs3->data; - dh_params->dh = d2i_DHparams(NULL, (const unsigned char **) (void *) &pkcs3->data, pkcs3->size); - POSIX_GUARD(s2n_check_p_g_dh_params(dh_params)); - if (pkcs3->data && (pkcs3->data - original_ptr != pkcs3->size)) { - DH_free(dh_params->dh); - POSIX_BAIL(S2N_ERR_INVALID_PKCS3); + temp_dh_params.dh = d2i_DHparams(NULL, (const unsigned char **) (void *) &pkcs3->data, pkcs3->size); + + POSIX_GUARD(s2n_check_p_g_dh_params(&temp_dh_params)); + + if (pkcs3->data) { + POSIX_ENSURE_GTE(pkcs3->data, original_ptr); + POSIX_ENSURE((uint32_t) (pkcs3->data - original_ptr) == pkcs3->size, S2N_ERR_INVALID_PKCS3); } + pkcs3->data = original_ptr; /* Require at least 2048 bits for the DH size */ - if (DH_size(dh_params->dh) < S2N_MIN_DH_PRIME_SIZE_BYTES) { - DH_free(dh_params->dh); - POSIX_BAIL(S2N_ERR_DH_TOO_SMALL); - } + POSIX_ENSURE(DH_size(temp_dh_params.dh) >= S2N_MIN_DH_PRIME_SIZE_BYTES, S2N_ERR_DH_TOO_SMALL); /* Check the generator and prime */ - POSIX_GUARD(s2n_dh_params_check(dh_params)); + POSIX_GUARD(s2n_dh_params_check(&temp_dh_params)); + + dh_params->dh = temp_dh_params.dh; + + ZERO_TO_DISABLE_DEFER_CLEANUP(temp_dh_params); return S2N_SUCCESS; } diff --git a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c index e4da43f7f0..2761f93327 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c @@ -40,13 +40,12 @@ EC_KEY *s2n_unsafe_ecdsa_get_non_const(const struct s2n_ecdsa_key *ecdsa_key) { PTR_ENSURE_REF(ecdsa_key); - /* pragma gcc diagnostic was added in gcc 4.6 */ -#if defined(__clang__) || S2N_GCC_VERSION_AT_LEAST(4, 6, 0) +#ifdef S2N_DIAGNOSTICS_PUSH_SUPPORTED #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" #endif EC_KEY *out_ec_key = (EC_KEY *) ecdsa_key->ec_key; -#if defined(__clang__) || S2N_GCC_VERSION_AT_LEAST(4, 6, 0) +#ifdef S2N_DIAGNOSTICS_POP_SUPPORTED #pragma GCC diagnostic pop #endif diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hkdf.c b/contrib/restricted/aws/s2n/crypto/s2n_hkdf.c index dd666ae653..da5a16ad3f 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_hkdf.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_hkdf.c @@ -13,8 +13,9 @@ * permissions and limitations under the License. */ -#include <stdio.h> +#include "crypto/s2n_hkdf.h" +#include "crypto/s2n_fips.h" #include "crypto/s2n_hmac.h" #include "error/s2n_errno.h" #include "stuffer/s2n_stuffer.h" @@ -22,28 +23,43 @@ #include "utils/s2n_mem.h" #include "utils/s2n_safety.h" +#ifdef S2N_LIBCRYPTO_SUPPORTS_HKDF + #error #include <openssl/hkdf.h> +#endif + #define MAX_DIGEST_SIZE 64 /* Current highest is SHA512 */ #define MAX_HKDF_ROUNDS 255 /* Reference: RFC 5869 */ -int s2n_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, +struct s2n_hkdf_impl { + int (*hkdf)(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, + const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output); + int (*hkdf_extract)(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, + const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key); + int (*hkdf_expand)(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *pseudo_rand_key, + const struct s2n_blob *info, struct s2n_blob *output); +}; + +static int s2n_custom_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key) { - uint8_t hmac_size; + uint8_t hmac_size = 0; POSIX_GUARD(s2n_hmac_digest_size(alg, &hmac_size)); + POSIX_ENSURE(hmac_size <= pseudo_rand_key->size, S2N_ERR_HKDF_OUTPUT_SIZE); pseudo_rand_key->size = hmac_size; + POSIX_GUARD(s2n_hmac_init(hmac, alg, salt->data, salt->size)); POSIX_GUARD(s2n_hmac_update(hmac, key->data, key->size)); POSIX_GUARD(s2n_hmac_digest(hmac, pseudo_rand_key->data, pseudo_rand_key->size)); POSIX_GUARD(s2n_hmac_reset(hmac)); - return 0; + return S2N_SUCCESS; } -static int s2n_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *pseudo_rand_key, - const struct s2n_blob *info, struct s2n_blob *output) +static int s2n_custom_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, + const struct s2n_blob *pseudo_rand_key, const struct s2n_blob *info, struct s2n_blob *output) { uint8_t prev[MAX_DIGEST_SIZE] = { 0 }; @@ -56,7 +72,8 @@ static int s2n_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, total_rounds++; } - S2N_ERROR_IF(total_rounds > MAX_HKDF_ROUNDS || total_rounds == 0, S2N_ERR_HKDF_OUTPUT_SIZE); + POSIX_ENSURE(total_rounds > 0, S2N_ERR_HKDF_OUTPUT_SIZE); + POSIX_ENSURE(total_rounds <= MAX_HKDF_ROUNDS, S2N_ERR_HKDF_OUTPUT_SIZE); for (uint32_t curr_round = 1; curr_round <= total_rounds; curr_round++) { uint32_t cat_len; @@ -80,21 +97,167 @@ static int s2n_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, POSIX_GUARD(s2n_hmac_reset(hmac)); } - return 0; + return S2N_SUCCESS; +} + +static int s2n_custom_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, + const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output) +{ + uint8_t prk_pad[MAX_DIGEST_SIZE] = { 0 }; + struct s2n_blob pseudo_rand_key = { 0 }; + POSIX_GUARD(s2n_blob_init(&pseudo_rand_key, prk_pad, sizeof(prk_pad))); + + POSIX_GUARD(s2n_custom_hkdf_extract(hmac, alg, salt, key, &pseudo_rand_key)); + POSIX_GUARD(s2n_custom_hkdf_expand(hmac, alg, &pseudo_rand_key, info, output)); + + return S2N_SUCCESS; +} + +const struct s2n_hkdf_impl s2n_custom_hkdf_impl = { + .hkdf = &s2n_custom_hkdf, + .hkdf_extract = &s2n_custom_hkdf_extract, + .hkdf_expand = &s2n_custom_hkdf_expand, +}; + +#ifdef S2N_LIBCRYPTO_SUPPORTS_HKDF +static int s2n_libcrypto_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, + const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key) +{ + const EVP_MD *digest = NULL; + POSIX_GUARD_RESULT(s2n_hmac_md_from_alg(alg, &digest)); + + /* The out_len argument of HKDF_extract is set to the number of bytes written to out_key, and + * is not used to ensure that out_key is large enough to contain the PRK. Ensure that the PRK + * output will fit in the blob. + */ + uint8_t hmac_size = 0; + POSIX_GUARD(s2n_hmac_digest_size(alg, &hmac_size)); + POSIX_ENSURE(hmac_size <= pseudo_rand_key->size, S2N_ERR_HKDF_OUTPUT_SIZE); + + size_t bytes_written = 0; + POSIX_GUARD_OSSL(HKDF_extract(pseudo_rand_key->data, &bytes_written, digest, key->data, key->size, + salt->data, salt->size), + S2N_ERR_HKDF); + + /* HKDF_extract updates the out_len argument based on the digest size. Update the blob's size based on this. */ + POSIX_ENSURE_LTE(bytes_written, pseudo_rand_key->size); + pseudo_rand_key->size = bytes_written; + + return S2N_SUCCESS; +} + +static int s2n_libcrypto_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, + const struct s2n_blob *pseudo_rand_key, const struct s2n_blob *info, struct s2n_blob *output) +{ + POSIX_ENSURE(output->size > 0, S2N_ERR_HKDF_OUTPUT_SIZE); + + const EVP_MD *digest = NULL; + POSIX_GUARD_RESULT(s2n_hmac_md_from_alg(alg, &digest)); + + POSIX_GUARD_OSSL(HKDF_expand(output->data, output->size, digest, pseudo_rand_key->data, pseudo_rand_key->size, + info->data, info->size), + S2N_ERR_HKDF); + + return S2N_SUCCESS; +} + +static int s2n_libcrypto_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, + const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output) +{ + POSIX_ENSURE(output->size > 0, S2N_ERR_HKDF_OUTPUT_SIZE); + + const EVP_MD *digest = NULL; + POSIX_GUARD_RESULT(s2n_hmac_md_from_alg(alg, &digest)); + + POSIX_GUARD_OSSL(HKDF(output->data, output->size, digest, key->data, key->size, salt->data, salt->size, + info->data, info->size), + S2N_ERR_HKDF); + + return S2N_SUCCESS; +} +#else +static int s2n_libcrypto_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, + const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key) +{ + POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); +} + +static int s2n_libcrypto_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, + const struct s2n_blob *pseudo_rand_key, const struct s2n_blob *info, struct s2n_blob *output) +{ + POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); +} + +static int s2n_libcrypto_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, + const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output) +{ + POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); +} +#endif /* S2N_LIBCRYPTO_SUPPORTS_HKDF */ + +const struct s2n_hkdf_impl s2n_libcrypto_hkdf_impl = { + .hkdf = &s2n_libcrypto_hkdf, + .hkdf_extract = &s2n_libcrypto_hkdf_extract, + .hkdf_expand = &s2n_libcrypto_hkdf_expand, +}; + +static const struct s2n_hkdf_impl *s2n_get_hkdf_implementation() +{ + /* By default, s2n-tls uses a custom HKDF implementation. When operating in FIPS mode, the + * FIPS-validated libcrypto implementation is used instead, if an implementation is provided. + */ + if (s2n_is_in_fips_mode() && s2n_libcrypto_supports_hkdf()) { + return &s2n_libcrypto_hkdf_impl; + } + + return &s2n_custom_hkdf_impl; +} + +int s2n_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, + const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key) +{ + POSIX_ENSURE_REF(hmac); + POSIX_ENSURE_REF(salt); + POSIX_ENSURE_REF(key); + POSIX_ENSURE_REF(pseudo_rand_key); + + const struct s2n_hkdf_impl *hkdf_implementation = s2n_get_hkdf_implementation(); + POSIX_ENSURE_REF(hkdf_implementation); + + POSIX_GUARD(hkdf_implementation->hkdf_extract(hmac, alg, salt, key, pseudo_rand_key)); + + return S2N_SUCCESS; +} + +static int s2n_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *pseudo_rand_key, + const struct s2n_blob *info, struct s2n_blob *output) +{ + POSIX_ENSURE_REF(hmac); + POSIX_ENSURE_REF(pseudo_rand_key); + POSIX_ENSURE_REF(info); + POSIX_ENSURE_REF(output); + + const struct s2n_hkdf_impl *hkdf_implementation = s2n_get_hkdf_implementation(); + POSIX_ENSURE_REF(hkdf_implementation); + + POSIX_GUARD(hkdf_implementation->hkdf_expand(hmac, alg, pseudo_rand_key, info, output)); + + return S2N_SUCCESS; } int s2n_hkdf_expand_label(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *secret, const struct s2n_blob *label, const struct s2n_blob *context, struct s2n_blob *output) { + POSIX_ENSURE_REF(label); + POSIX_ENSURE_REF(context); + POSIX_ENSURE_REF(output); + /* Per RFC8446: 7.1, a HKDF label is a 2 byte length field, and two 1...255 byte arrays with a one byte length field each. */ uint8_t hkdf_label_buf[2 + 256 + 256]; struct s2n_blob hkdf_label_blob = { 0 }; struct s2n_stuffer hkdf_label = { 0 }; - /* RFC8446 specifies that labels must be 12 characters or less, to avoid - ** incurring two hash rounds. - */ - POSIX_ENSURE_LTE(label->size, 12); + POSIX_ENSURE_LTE(label->size, S2N_MAX_HKDF_EXPAND_LABEL_LENGTH); POSIX_GUARD(s2n_blob_init(&hkdf_label_blob, hkdf_label_buf, sizeof(hkdf_label_buf))); POSIX_GUARD(s2n_stuffer_init(&hkdf_label, &hkdf_label_blob)); @@ -108,18 +271,31 @@ int s2n_hkdf_expand_label(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, c hkdf_label_blob.size = s2n_stuffer_data_available(&hkdf_label); POSIX_GUARD(s2n_hkdf_expand(hmac, alg, secret, &hkdf_label_blob, output)); - return 0; + return S2N_SUCCESS; } int s2n_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output) { - uint8_t prk_pad[MAX_DIGEST_SIZE]; - struct s2n_blob pseudo_rand_key = { 0 }; - POSIX_GUARD(s2n_blob_init(&pseudo_rand_key, prk_pad, sizeof(prk_pad))); + POSIX_ENSURE_REF(hmac); + POSIX_ENSURE_REF(salt); + POSIX_ENSURE_REF(key); + POSIX_ENSURE_REF(info); + POSIX_ENSURE_REF(output); - POSIX_GUARD(s2n_hkdf_extract(hmac, alg, salt, key, &pseudo_rand_key)); - POSIX_GUARD(s2n_hkdf_expand(hmac, alg, &pseudo_rand_key, info, output)); + const struct s2n_hkdf_impl *hkdf_implementation = s2n_get_hkdf_implementation(); + POSIX_ENSURE_REF(hkdf_implementation); - return 0; + POSIX_GUARD(hkdf_implementation->hkdf(hmac, alg, salt, key, info, output)); + + return S2N_SUCCESS; +} + +bool s2n_libcrypto_supports_hkdf() +{ +#ifdef S2N_LIBCRYPTO_SUPPORTS_HKDF + return true; +#else + return false; +#endif } diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hkdf.h b/contrib/restricted/aws/s2n/crypto/s2n_hkdf.h index cb9424e7d7..8dc53636e7 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_hkdf.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_hkdf.h @@ -20,6 +20,16 @@ #include "crypto/s2n_hmac.h" #include "utils/s2n_blob.h" +/* + * Label structure is `opaque label<7..255> = "tls13 " + Label` per RFC8446. + * So, we have 255-sizeof("tls13 ") = 249, the maximum label length. + * + * Note that all labels defined by RFC 8446 are <12 characters, which + * avoids an extra hash iteration. However, the exporter functionality + * (s2n_connection_tls_exporter) allows for longer labels. + */ +#define S2N_MAX_HKDF_EXPAND_LABEL_LENGTH 249 + int s2n_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt, const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output); @@ -28,3 +38,5 @@ int s2n_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const int s2n_hkdf_expand_label(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *secret, const struct s2n_blob *label, const struct s2n_blob *context, struct s2n_blob *output); + +bool s2n_libcrypto_supports_hkdf(); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hmac.c b/contrib/restricted/aws/s2n/crypto/s2n_hmac.c index d2bb4e6684..20be85ffee 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_hmac.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_hmac.c @@ -396,3 +396,34 @@ int s2n_hmac_restore_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s POSIX_POSTCONDITION(s2n_hmac_state_validate(hmac)); return S2N_SUCCESS; } + +S2N_RESULT s2n_hmac_md_from_alg(s2n_hmac_algorithm alg, const EVP_MD **md) +{ + RESULT_ENSURE_REF(md); + + switch (alg) { + case S2N_HMAC_SSLv3_MD5: + case S2N_HMAC_MD5: + *md = EVP_md5(); + break; + case S2N_HMAC_SSLv3_SHA1: + case S2N_HMAC_SHA1: + *md = EVP_sha1(); + break; + case S2N_HMAC_SHA224: + *md = EVP_sha224(); + break; + case S2N_HMAC_SHA256: + *md = EVP_sha256(); + break; + case S2N_HMAC_SHA384: + *md = EVP_sha384(); + break; + case S2N_HMAC_SHA512: + *md = EVP_sha512(); + break; + default: + RESULT_BAIL(S2N_ERR_P_HASH_INVALID_ALGORITHM); + } + return S2N_RESULT_OK; +} diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hmac.h b/contrib/restricted/aws/s2n/crypto/s2n_hmac.h index fe532ca5c8..81b96c06ea 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_hmac.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_hmac.h @@ -77,3 +77,5 @@ int s2n_hmac_reset(struct s2n_hmac_state *state); int s2n_hmac_copy(struct s2n_hmac_state *to, struct s2n_hmac_state *from); int s2n_hmac_save_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac); int s2n_hmac_restore_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac); + +S2N_RESULT s2n_hmac_md_from_alg(s2n_hmac_algorithm alg, const EVP_MD **md); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_ktls_crypto.h b/contrib/restricted/aws/s2n/crypto/s2n_ktls_crypto.h new file mode 100644 index 0000000000..b665e913fe --- /dev/null +++ b/contrib/restricted/aws/s2n/crypto/s2n_ktls_crypto.h @@ -0,0 +1,63 @@ +/* + * 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 "utils/s2n_blob.h" + +/* clang-format off */ +#if defined(S2N_KTLS_SUPPORTED) + #include <linux/tls.h> + + typedef struct tls12_crypto_info_aes_gcm_128 s2n_ktls_crypto_info_tls12_aes_gcm_128; + typedef struct tls12_crypto_info_aes_gcm_256 s2n_ktls_crypto_info_tls12_aes_gcm_256; +#else + #define TLS_1_2_VERSION 0 + + #define TLS_CIPHER_AES_GCM_128 0 + typedef struct s2n_ktls_crypto_info_stub s2n_ktls_crypto_info_tls12_aes_gcm_128; + #define TLS_CIPHER_AES_GCM_256 0 + typedef struct s2n_ktls_crypto_info_stub s2n_ktls_crypto_info_tls12_aes_gcm_256; +#endif +/* clang-format on */ + +/* To avoid compile-time errors, this must contain every field that we reference + * from any crypto_info. However, it is only a placeholder-- it should never + * actually be used. + */ +struct s2n_ktls_crypto_info_stub { + struct { + uint8_t version; + uint8_t cipher_type; + } info; + uint8_t iv[1]; + uint8_t key[1]; + uint8_t salt[1]; + uint8_t rec_seq[1]; +}; + +struct s2n_ktls_crypto_info { + struct s2n_blob value; + union { + s2n_ktls_crypto_info_tls12_aes_gcm_128 aes_gcm_128; + s2n_ktls_crypto_info_tls12_aes_gcm_256 aes_gcm_256; + } ciphers; +}; + +struct s2n_ktls_crypto_info_inputs { + struct s2n_blob iv; + struct s2n_blob key; + struct s2n_blob seq; +}; diff --git a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c index d92da10a08..9e40500da6 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c @@ -118,7 +118,7 @@ bool s2n_libcrypto_is_awslc() #endif } -static uint64_t s2n_libcrypto_awslc_api_version(void) +uint64_t s2n_libcrypto_awslc_api_version(void) { #if defined(OPENSSL_IS_AWSLC) return AWSLC_API_VERSION; @@ -191,3 +191,12 @@ unsigned long s2n_get_openssl_version(void) { return OPENSSL_VERSION_NUMBER; } + +bool s2n_libcrypto_supports_flag_no_check_time() +{ +#ifdef S2N_LIBCRYPTO_SUPPORTS_FLAG_NO_CHECK_TIME + return true; +#else + return false; +#endif +} diff --git a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h index 34d9ef2aac..9e7aff882b 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h @@ -18,3 +18,5 @@ #include "utils/s2n_result.h" S2N_RESULT s2n_libcrypto_validate_runtime(void); + +bool s2n_libcrypto_supports_flag_no_check_time(); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.c b/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.c index f0909fd897..bc659e28a8 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.c @@ -17,10 +17,25 @@ #include "api/s2n.h" -int s2n_openssl_x509_stack_pop_free(STACK_OF(X509) **cert_chain) +S2N_CLEANUP_RESULT s2n_openssl_x509_stack_pop_free(STACK_OF(X509) **cert_chain) { - if (*cert_chain != NULL) { - sk_X509_pop_free(*cert_chain, X509_free); - } - return S2N_SUCCESS; + RESULT_ENSURE_REF(*cert_chain); + sk_X509_pop_free(*cert_chain, X509_free); + *cert_chain = NULL; + return S2N_RESULT_OK; +} + +S2N_CLEANUP_RESULT s2n_openssl_asn1_time_free_pointer(ASN1_GENERALIZEDTIME **time_ptr) +{ + /* The ANS1_*TIME structs are just typedef wrappers around ASN1_STRING + * + * The ASN1_TIME, ASN1_UTCTIME and ASN1_GENERALIZEDTIME structures are + * represented as an ASN1_STRING internally and can be freed up using + * ASN1_STRING_free(). + * https://www.openssl.org/docs/man1.1.1/man3/ASN1_TIME_to_tm.html + */ + RESULT_ENSURE_REF(*time_ptr); + ASN1_STRING_free((ASN1_STRING *) *time_ptr); + *time_ptr = NULL; + return S2N_RESULT_OK; } diff --git a/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.h b/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.h index 1eb2069054..aac6d87315 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.h @@ -15,6 +15,7 @@ #pragma once +#include <openssl/asn1.h> #include <openssl/x509.h> #include <stdint.h> @@ -22,4 +23,6 @@ DEFINE_POINTER_CLEANUP_FUNC(X509 *, X509_free); -int s2n_openssl_x509_stack_pop_free(STACK_OF(X509) **cert_chain); +S2N_CLEANUP_RESULT s2n_openssl_x509_stack_pop_free(STACK_OF(X509) **cert_chain); + +S2N_CLEANUP_RESULT s2n_openssl_asn1_time_free_pointer(ASN1_GENERALIZEDTIME **time); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_rsa.c b/contrib/restricted/aws/s2n/crypto/s2n_rsa.c index 9fc1d4b5ca..96ce8f4140 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_rsa.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_rsa.c @@ -36,13 +36,12 @@ RSA *s2n_unsafe_rsa_get_non_const(const struct s2n_rsa_key *rsa_key) { PTR_ENSURE_REF(rsa_key); - /* pragma gcc diagnostic was added in gcc 4.6 */ -#if defined(__clang__) || S2N_GCC_VERSION_AT_LEAST(4, 6, 0) +#ifdef S2N_DIAGNOSTICS_PUSH_SUPPORTED #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" #endif RSA *out_rsa_key = (RSA *) rsa_key->rsa; -#if defined(__clang__) || S2N_GCC_VERSION_AT_LEAST(4, 6, 0) +#ifdef S2N_DIAGNOSTICS_POP_SUPPORTED #pragma GCC diagnostic pop #endif diff --git a/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c b/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c index 4c4bc14914..30be7e6a43 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c @@ -21,60 +21,28 @@ #include "utils/s2n_blob.h" #include "utils/s2n_safety.h" -#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0) - #error #include "openssl/provider.h" -DEFINE_POINTER_CLEANUP_FUNC(OSSL_LIB_CTX *, OSSL_LIB_CTX_free); -#endif - -static EVP_CIPHER *s2n_rc4_cipher = NULL; - -S2N_RESULT s2n_rc4_init() -{ - /* In Openssl-3.0, RC4 is only available from the "legacy" provider, - * which is not loaded in the default library context. - */ -#if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_RC4) && S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0) - DEFER_CLEANUP(OSSL_LIB_CTX *lib_ctx = OSSL_LIB_CTX_new(), OSSL_LIB_CTX_free_pointer); - RESULT_ENSURE_REF(lib_ctx); - RESULT_ENSURE_REF(OSSL_PROVIDER_load(lib_ctx, "legacy")); - s2n_rc4_cipher = EVP_CIPHER_fetch(lib_ctx, "rc4", "provider=legacy"); - RESULT_ENSURE_REF(s2n_rc4_cipher); -#endif - return S2N_RESULT_OK; -} - -S2N_RESULT s2n_rc4_cleanup() +static const EVP_CIPHER *s2n_evp_rc4() { -#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0) - EVP_CIPHER_free(s2n_rc4_cipher); +#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 + return EVP_rc4(); +#else + return NULL; #endif - return S2N_RESULT_OK; } -static S2N_RESULT s2n_get_rc4_cipher(const EVP_CIPHER **cipher) +static uint8_t s2n_stream_cipher_rc4_available() { - RESULT_ENSURE_REF(cipher); - *cipher = NULL; if (s2n_is_in_fips_mode()) { - *cipher = NULL; - } else if (s2n_rc4_cipher) { - *cipher = s2n_rc4_cipher; -#if S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 - } else { - *cipher = EVP_rc4(); -#endif + return 0; } - RESULT_ENSURE(*cipher, S2N_ERR_UNIMPLEMENTED); - return S2N_RESULT_OK; -} - -static uint8_t s2n_stream_cipher_rc4_available() -{ - const EVP_CIPHER *cipher = NULL; - if (s2n_result_is_ok(s2n_get_rc4_cipher(&cipher)) && cipher) { - return 1; + /* RC4 MIGHT be available in Openssl-3.0, depending on whether or not the + * "legacy" provider is loaded. However, for simplicity, assume that RC4 + * is unavailable. + */ + if (S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)) { + return 0; } - return 0; + return (s2n_evp_rc4() ? 1 : 0); } static int s2n_stream_cipher_rc4_encrypt(struct s2n_session_key *key, struct s2n_blob *in, struct s2n_blob *out) @@ -106,11 +74,7 @@ static int s2n_stream_cipher_rc4_decrypt(struct s2n_session_key *key, struct s2n static int s2n_stream_cipher_rc4_set_encryption_key(struct s2n_session_key *key, struct s2n_blob *in) { POSIX_ENSURE_EQ(in->size, 16); - - const EVP_CIPHER *evp_rc4 = NULL; - POSIX_GUARD_RESULT(s2n_get_rc4_cipher(&evp_rc4)); - - POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, evp_rc4, NULL, in->data, NULL), S2N_ERR_KEY_INIT); + POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, s2n_evp_rc4(), NULL, in->data, NULL), S2N_ERR_KEY_INIT); return S2N_SUCCESS; } @@ -118,11 +82,7 @@ static int s2n_stream_cipher_rc4_set_encryption_key(struct s2n_session_key *key, static int s2n_stream_cipher_rc4_set_decryption_key(struct s2n_session_key *key, struct s2n_blob *in) { POSIX_ENSURE_EQ(in->size, 16); - - const EVP_CIPHER *evp_rc4 = NULL; - POSIX_GUARD_RESULT(s2n_get_rc4_cipher(&evp_rc4)); - - POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, evp_rc4, NULL, in->data, NULL), S2N_ERR_KEY_INIT); + POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, s2n_evp_rc4(), NULL, in->data, NULL), S2N_ERR_KEY_INIT); return S2N_SUCCESS; } diff --git a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c index 3b5c284080..91d7aae5e0 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c @@ -37,7 +37,7 @@ * [x] server_handshake_traffic_secret * [x] client_application_traffic_secret_0 * [x] server_application_traffic_secret_0 - * [ ] exporter_master_secret + * [x] exporter_master_secret * [x] resumption_master_secret * * The TLS 1.3 key generation can be divided into 3 phases @@ -80,6 +80,11 @@ S2N_BLOB_LABEL(s2n_tls13_label_traffic_secret_key, "key") S2N_BLOB_LABEL(s2n_tls13_label_traffic_secret_iv, "iv") /* + * TLS 1.3 Exporter label + */ +S2N_BLOB_LABEL(s2n_tls13_label_exporter, "exporter") + +/* * TLS 1.3 Finished label */ S2N_BLOB_LABEL(s2n_tls13_label_finished, "finished") diff --git a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h index 5bd7455dc2..ac96ceb51f 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h @@ -70,6 +70,8 @@ extern const struct s2n_blob s2n_tls13_label_resumption_master_secret; extern const struct s2n_blob s2n_tls13_label_finished; +extern const struct s2n_blob s2n_tls13_label_exporter; + /* Traffic secret labels */ extern const struct s2n_blob s2n_tls13_label_traffic_secret_key; |