diff options
author | robot-contrib <robot-contrib@yandex-team.com> | 2022-09-14 08:47:09 +0300 |
---|---|---|
committer | robot-contrib <robot-contrib@yandex-team.com> | 2022-09-14 08:47:09 +0300 |
commit | b9de4b17d67a2320369697088b3528b0434f1843 (patch) | |
tree | fde557e95170880f4b3154ff66a1671c679d34e8 /contrib/restricted | |
parent | 1330c9bc362d84c753ba1c08ce51da6619ead01f (diff) | |
download | ydb-b9de4b17d67a2320369697088b3528b0434f1843.tar.gz |
Update contrib/restricted/aws/s2n to 1.3.21
Diffstat (limited to 'contrib/restricted')
63 files changed, 838 insertions, 436 deletions
diff --git a/contrib/restricted/aws/s2n/CMakeLists.darwin.txt b/contrib/restricted/aws/s2n/CMakeLists.darwin.txt index 01ab97e6c8..f634b97407 100644 --- a/contrib/restricted/aws/s2n/CMakeLists.darwin.txt +++ b/contrib/restricted/aws/s2n/CMakeLists.darwin.txt @@ -138,7 +138,7 @@ target_sources(restricted-aws-s2n PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_config.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_connection.c - ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c + ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_crypto.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_early_data.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c diff --git a/contrib/restricted/aws/s2n/CMakeLists.linux.txt b/contrib/restricted/aws/s2n/CMakeLists.linux.txt index 2403724ef1..b1364fede1 100644 --- a/contrib/restricted/aws/s2n/CMakeLists.linux.txt +++ b/contrib/restricted/aws/s2n/CMakeLists.linux.txt @@ -139,7 +139,7 @@ target_sources(restricted-aws-s2n PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_config.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_connection.c - ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c + ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_crypto.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_early_data.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c diff --git a/contrib/restricted/aws/s2n/api/s2n.h b/contrib/restricted/aws/s2n/api/s2n.h index c361dd09bb..bd1d83ba0c 100644 --- a/contrib/restricted/aws/s2n/api/s2n.h +++ b/contrib/restricted/aws/s2n/api/s2n.h @@ -1141,6 +1141,9 @@ extern int s2n_config_set_session_tickets_onoff(struct s2n_config *config, uint8 /** * Enable or disable session caching. + * + * @note Session caching will not be turned on unless all three session cache callbacks are set + * prior to calling this function. * * @param config The configuration object being updated * @param enabled The configuration object being updated. Set to 1 to enable. Set to 0 to disable. @@ -1617,7 +1620,9 @@ S2N_API extern int s2n_connection_set_send_cb(struct s2n_connection *conn, s2n_send_fn send); /** - * Change the behavior of s2n-tls when sending data to prefer high throughput. Connections preferring throughput will use + * Change the behavior of s2n-tls when sending data to prefer high throughput. + * + * Connections preferring throughput will use * large record sizes that minimize overhead. * * @param conn The connection object being updated @@ -1627,7 +1632,9 @@ S2N_API extern int s2n_connection_prefer_throughput(struct s2n_connection *conn); /** - * Change the behavior of s2n-tls when sending data to prefer low latency. Connections preferring low latency will be encrypted + * Change the behavior of s2n-tls when sending data to prefer low latency. + * + * Connections preferring low latency will be encrypted * using small record sizes that can be decrypted sooner by the recipient. * * @param conn The connection object being updated @@ -1637,10 +1644,32 @@ S2N_API extern int s2n_connection_prefer_low_latency(struct s2n_connection *conn); /** - * Provides a smooth transition from s2n_connection_prefer_low_latency() to s2n_connection_prefer_throughput(). + * Configure the connection to free IO buffers when they are not currently in use. + * + * This configuration can be used to minimize connection memory footprint size, at the cost + * of more calls to alloc and free. Some of these costs can be mitigated by configuring s2n-tls + * to use an allocator that includes thread-local caches or lock-free allocation patterns. + * + * @param conn The connection object being update + * @param enabled Set to `true` if dynamic buffers are enabled; `false` if disabled + * @returns S2N_SUCCESS on success. S2N_FAILURE on failure + */ +S2N_API +extern int s2n_connection_set_dynamic_buffers(struct s2n_connection *conn, bool enabled); + +/** + * Changes the behavior of s2n-tls when sending data to initially prefer records + * small enough to fit in single ethernet frames. + * + * When dynamic record sizing is active, the connection sends records small enough + * to fit in a single standard 1500 byte ethernet frame. Otherwise, the connection + * chooses record sizes according to the configured maximum fragment length. + * + * Dynamic record sizing is active for the first resize_threshold bytes of a connection, + * and is reactivated whenever timeout_threshold seconds pass without sending data. * * @param conn The connection object being updated - * @param resize_threshold The number of bytes to send before changing the record size + * @param resize_threshold The number of bytes to send before changing the record size. Maximum 8MiB. * @param timeout_threshold Reset record size back to a single segment after threshold seconds of inactivity * @returns S2N_SUCCESS on success. S2N_FAILURE on failure */ @@ -1672,7 +1701,7 @@ extern int s2n_connection_set_verify_host_callback(struct s2n_connection *conn, * Setting the S2N_SELF_SERVICE_BLINDING option with s2n_connection_set_blinding() * turns off this behavior. This is useful for applications that are handling many connections * in a single thread. In that case, if s2n_recv() or s2n_negotiate() return an error, - * self-service applications should call *2n_connection_get_delay() and pause + * self-service applications should call s2n_connection_get_delay() and pause * activity on the connection for the specified number of nanoseconds before calling * close() or shutdown(). */ @@ -2114,6 +2143,8 @@ struct s2n_session_ticket; /** * Callback function for receiving a session ticket. * + * This function will be called each time a session ticket is received, which may be multiple times for TLS1.3. + * * # Safety * * `ctx` is a void pointer and the caller is responsible for ensuring it is cast to the correct type. @@ -2187,9 +2218,9 @@ extern int s2n_connection_set_session(struct s2n_connection *conn, const uint8_t /** * Serializes the session state from connection and copies into the `session` buffer and returns the number of copied bytes * - * The output of this function depends on whether session ids or session tickets are being used for resumption. - * - * @note This is for < TLS 1.3 session resumption. + * @note This function is not recommended for > TLS 1.2 because in TLS1.3 + * servers can send multiple session tickets and this function will only + * return the most recently received ticket. * * @param conn A pointer to the s2n_connection object * @param session A pointer to a buffer of size `max_length` @@ -2201,7 +2232,11 @@ S2N_API extern int s2n_connection_get_session(struct s2n_connection *conn, uint8_t *session, size_t max_length); /** - * Get the lifetime hint for a session. + * Retrieves a hint from the server indicating how long this ticket's lifetime is. + * + * @note This function is not recommended for > TLS 1.2 because in TLS1.3 + * servers can send multiple session tickets and this function will only + * return the most recently received ticket lifetime hint. * * @param conn A pointer to the s2n_connection object * @@ -2962,7 +2997,7 @@ extern int s2n_config_set_async_pkey_callback(struct s2n_config *config, s2n_asy * * @param op An opaque object representing the private key operation * @param key The private key used for the operation. It can be extracted from - * `conn` through the `s2n_connection_get_selected_cert` and `s2n_cert_chain_and_key_get_key` calls + * `conn` through the `s2n_connection_get_selected_cert` and `s2n_cert_chain_and_key_get_private_key` calls */ S2N_API extern int s2n_async_pkey_op_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *key); 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 172736ac1e..914a44ceae 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 @@ -62,6 +62,7 @@ static int s2n_aead_cipher_aes_gcm_encrypt(struct s2n_session_key *key, struct s /* Adjust input length to account for the Tag length */ size_t in_len = in->size - S2N_TLS_GCM_TAG_LEN; + /* out_len is set by EVP_AEAD_CTX_seal and checked post operation */ size_t out_len = 0; POSIX_GUARD_OSSL(EVP_AEAD_CTX_seal(key->evp_aead_ctx, out->data, &out_len, out->size, iv->data, iv->size, in->data, in_len, aad->data, aad->size), S2N_ERR_ENCRYPT); @@ -83,6 +84,7 @@ static int s2n_aead_cipher_aes_gcm_decrypt(struct s2n_session_key *key, struct s POSIX_ENSURE_GTE(out->size, in->size - S2N_TLS_GCM_TAG_LEN); POSIX_ENSURE_EQ(iv->size, S2N_TLS_GCM_IV_LEN); + /* out_len is set by EVP_AEAD_CTX_open and checked post operation */ size_t out_len = 0; POSIX_GUARD_OSSL(EVP_AEAD_CTX_open(key->evp_aead_ctx, out->data, &out_len, out->size, iv->data, iv->size, in->data, in->size, aad->data, aad->size), S2N_ERR_DECRYPT); @@ -222,7 +224,8 @@ static int s2n_aead_cipher_aes_gcm_encrypt(struct s2n_session_key *key, struct s int in_len = in->size - S2N_TLS_GCM_TAG_LEN; uint8_t *tag_data = out->data + out->size - S2N_TLS_GCM_TAG_LEN; - int out_len; + /* out_len is set by EVP_EncryptUpdate and checked post operation */ + int out_len = 0; /* Specify the AAD */ POSIX_GUARD_OSSL(EVP_EncryptUpdate(key->evp_cipher_ctx, NULL, &out_len, aad->data, aad->size), S2N_ERR_ENCRYPT); @@ -260,7 +263,10 @@ static int s2n_aead_cipher_aes_gcm_decrypt(struct s2n_session_key *key, struct s /* Set the TAG */ POSIX_GUARD_OSSL(EVP_CIPHER_CTX_ctrl(key->evp_cipher_ctx, EVP_CTRL_GCM_SET_TAG, S2N_TLS_GCM_TAG_LEN, tag_data), S2N_ERR_DECRYPT); - int out_len; + /* out_len is set by EVP_DecryptUpdate. While we verify the content of out_len in + * s2n_aead_chacha20_poly1305_encrypt, we refrain from this here. This is to avoid + * doing any branching before the ciphertext is verified. */ + int out_len = 0; /* Specify the AAD */ POSIX_GUARD_OSSL(EVP_DecryptUpdate(key->evp_cipher_ctx, NULL, &out_len, aad->data, aad->size), S2N_ERR_DECRYPT); @@ -273,8 +279,6 @@ static int s2n_aead_cipher_aes_gcm_decrypt(struct s2n_session_key *key, struct s S2N_ERROR_IF(evp_decrypt_rc != 1, S2N_ERR_DECRYPT); - /* While we verify the content of out_len in s2n_aead_cipher_aes_gcm_encrypt, we refrain from this here. This is to avoid doing any branching before the ciphertext is verified. */ - return S2N_SUCCESS; } diff --git a/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_chacha20_poly1305.c b/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_chacha20_poly1305.c index a4db7815f2..0768451c1b 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_chacha20_poly1305.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_chacha20_poly1305.c @@ -61,7 +61,8 @@ static int s2n_aead_chacha20_poly1305_encrypt(struct s2n_session_key *key, struc int in_len = in->size - S2N_TLS_CHACHA20_POLY1305_TAG_LEN; uint8_t *tag_data = out->data + out->size - S2N_TLS_CHACHA20_POLY1305_TAG_LEN; - int out_len; + /* out_len is set by EVP_EncryptUpdate and checked post operation */ + int out_len = 0; /* Specify the AAD */ POSIX_GUARD_OSSL(EVP_EncryptUpdate(key->evp_cipher_ctx, NULL, &out_len, aad->data, aad->size), S2N_ERR_ENCRYPT); @@ -99,7 +100,10 @@ static int s2n_aead_chacha20_poly1305_decrypt(struct s2n_session_key *key, struc /* Set the TAG */ POSIX_GUARD_OSSL(EVP_CIPHER_CTX_ctrl(key->evp_cipher_ctx, EVP_CTRL_GCM_SET_TAG, S2N_TLS_CHACHA20_POLY1305_TAG_LEN, tag_data), S2N_ERR_DECRYPT); - int out_len; + /* out_len is set by EVP_DecryptUpdate. While we verify the content of out_len in + * s2n_aead_chacha20_poly1305_encrypt, we refrain from this here. This is to avoid + * doing any branching before the ciphertext is verified. */ + int out_len = 0; /* Specify the AAD */ POSIX_GUARD_OSSL(EVP_DecryptUpdate(key->evp_cipher_ctx, NULL, &out_len, aad->data, aad->size), S2N_ERR_DECRYPT); @@ -112,8 +116,6 @@ static int s2n_aead_chacha20_poly1305_decrypt(struct s2n_session_key *key, struc S2N_ERROR_IF(evp_decrypt_rc != 1, S2N_ERR_DECRYPT); - /* While we verify the content of out_len in s2n_aead_chacha20_poly1305_encrypt, we refrain from this here. This is to avoid doing any branching before the ciphertext is verified. */ - return 0; } @@ -168,6 +170,7 @@ static int s2n_aead_chacha20_poly1305_encrypt(struct s2n_session_key *key, struc /* Adjust input length to account for the Tag length */ size_t in_len = in->size - S2N_TLS_CHACHA20_POLY1305_TAG_LEN; + /* out_len is set by EVP_AEAD_CTX_seal and checked post operation */ size_t out_len = 0; POSIX_GUARD_OSSL(EVP_AEAD_CTX_seal(key->evp_aead_ctx, out->data, &out_len, out->size, iv->data, iv->size, in->data, in_len, aad->data, aad->size), S2N_ERR_ENCRYPT); @@ -183,6 +186,7 @@ static int s2n_aead_chacha20_poly1305_decrypt(struct s2n_session_key *key, struc POSIX_ENSURE_GTE(out->size, in->size - S2N_TLS_CHACHA20_POLY1305_TAG_LEN); POSIX_ENSURE_EQ(iv->size, S2N_TLS_CHACHA20_POLY1305_IV_LEN); + /* out_len is set by EVP_AEAD_CTX_open and checked post operation */ size_t out_len = 0; POSIX_GUARD_OSSL(EVP_AEAD_CTX_open(key->evp_aead_ctx, out->data, &out_len, out->size, iv->data, iv->size, in->data, in->size, aad->data, aad->size), S2N_ERR_DECRYPT); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_cbc_cipher_3des.c b/contrib/restricted/aws/s2n/crypto/s2n_cbc_cipher_3des.c index 9a3e440653..2704a0deb3 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_cbc_cipher_3des.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_cbc_cipher_3des.c @@ -34,7 +34,8 @@ static int s2n_cbc_cipher_3des_encrypt(struct s2n_session_key *key, struct s2n_b POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, NULL, NULL, NULL, iv->data), S2N_ERR_KEY_INIT); - int len = out->size; + /* len is set by EVP_EncryptUpdate and checked post operation */ + int len = 0; POSIX_GUARD_OSSL(EVP_EncryptUpdate(key->evp_cipher_ctx, out->data, &len, in->data, in->size), S2N_ERR_ENCRYPT); S2N_ERROR_IF(len != in->size, S2N_ERR_ENCRYPT); @@ -47,7 +48,9 @@ static int s2n_cbc_cipher_3des_decrypt(struct s2n_session_key *key, struct s2n_b POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, NULL, NULL, NULL, iv->data), S2N_ERR_KEY_INIT); - int len = out->size; + /* len is set by EVP_DecryptUpdate. It is not checked here but padding is manually removed and therefore + * the decryption operation is validated. */ + int len = 0; POSIX_GUARD_OSSL(EVP_DecryptUpdate(key->evp_cipher_ctx, out->data, &len, in->data, in->size), S2N_ERR_DECRYPT); return 0; @@ -57,7 +60,7 @@ static int s2n_cbc_cipher_3des_set_decryption_key(struct s2n_session_key *key, s { POSIX_ENSURE_EQ(in->size, 192 / 8); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, EVP_des_ede3_cbc(), NULL, in->data, NULL), S2N_ERR_KEY_INIT); return 0; @@ -67,7 +70,7 @@ static int s2n_cbc_cipher_3des_set_encryption_key(struct s2n_session_key *key, s { POSIX_ENSURE_EQ(in->size, 192 / 8); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, EVP_des_ede3_cbc(), NULL, in->data, NULL), S2N_ERR_KEY_INIT); return 0; diff --git a/contrib/restricted/aws/s2n/crypto/s2n_cbc_cipher_aes.c b/contrib/restricted/aws/s2n/crypto/s2n_cbc_cipher_aes.c index e737242ff0..d4a49940d6 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_cbc_cipher_aes.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_cbc_cipher_aes.c @@ -39,7 +39,8 @@ static int s2n_cbc_cipher_aes_encrypt(struct s2n_session_key *key, struct s2n_bl POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, NULL, NULL, NULL, iv->data), S2N_ERR_KEY_INIT); - int len = out->size; + /* len is set by EVP_EncryptUpdate and checked post operation */ + int len = 0; POSIX_GUARD_OSSL(EVP_EncryptUpdate(key->evp_cipher_ctx, out->data, &len, in->data, in->size), S2N_ERR_ENCRYPT); S2N_ERROR_IF(len != in->size, S2N_ERR_ENCRYPT); @@ -51,7 +52,10 @@ int s2n_cbc_cipher_aes_decrypt(struct s2n_session_key *key, struct s2n_blob *iv, POSIX_ENSURE_GTE(out->size, in->size); POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, NULL, NULL, NULL, iv->data), S2N_ERR_KEY_INIT); - int len = out->size; + + /* len is set by EVP_DecryptUpdate. It is not checked here but padding is manually removed and therefore + * the decryption operation is validated. */ + int len = 0; POSIX_GUARD_OSSL(EVP_DecryptUpdate(key->evp_cipher_ctx, out->data, &len, in->data, in->size), S2N_ERR_DECRYPT); return 0; @@ -62,7 +66,7 @@ int s2n_cbc_cipher_aes128_set_decryption_key(struct s2n_session_key *key, struct POSIX_ENSURE_EQ(in->size, 128 / 8); /* Always returns 1 */ - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, EVP_aes_128_cbc(), NULL, in->data, NULL), S2N_ERR_KEY_INIT); return 0; @@ -72,7 +76,7 @@ static int s2n_cbc_cipher_aes128_set_encryption_key(struct s2n_session_key *key, { POSIX_ENSURE_EQ(in->size, 128 / 8); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, EVP_aes_128_cbc(), NULL, in->data, NULL), S2N_ERR_KEY_INIT); return 0; @@ -82,7 +86,7 @@ static int s2n_cbc_cipher_aes256_set_decryption_key(struct s2n_session_key *key, { POSIX_ENSURE_EQ(in->size, 256 / 8); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, EVP_aes_256_cbc(), NULL, in->data, NULL), S2N_ERR_KEY_INIT); return 0; @@ -92,7 +96,7 @@ int s2n_cbc_cipher_aes256_set_encryption_key(struct s2n_session_key *key, struct { POSIX_ENSURE_EQ(in->size, 256 / 8); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, EVP_aes_256_cbc(), NULL, in->data, NULL), S2N_ERR_KEY_INIT); return 0; diff --git a/contrib/restricted/aws/s2n/crypto/s2n_composite_cipher_aes_sha.c b/contrib/restricted/aws/s2n/crypto/s2n_composite_cipher_aes_sha.c index 353c841f87..7141f9ccf1 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_composite_cipher_aes_sha.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_composite_cipher_aes_sha.c @@ -167,7 +167,12 @@ static int s2n_composite_cipher_aes_sha_encrypt(struct s2n_session_key *key, str POSIX_ENSURE_EQ(out->size, in->size); POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, NULL, NULL, NULL, iv->data), S2N_ERR_KEY_INIT); - POSIX_GUARD_OSSL(EVP_Cipher(key->evp_cipher_ctx, out->data, in->data, in->size), S2N_ERR_ENCRYPT); + + /* len is set by EVP_EncryptUpdate and checked post operation */ + int len = 0; + POSIX_GUARD_OSSL(EVP_EncryptUpdate(key->evp_cipher_ctx, out->data, &len, in->data, in->size), S2N_ERR_ENCRYPT); + + S2N_ERROR_IF(len != in->size, S2N_ERR_ENCRYPT); return 0; } @@ -175,9 +180,12 @@ static int s2n_composite_cipher_aes_sha_encrypt(struct s2n_session_key *key, str static int s2n_composite_cipher_aes_sha_decrypt(struct s2n_session_key *key, struct s2n_blob *iv, struct s2n_blob *in, struct s2n_blob *out) { POSIX_ENSURE_EQ(out->size, in->size); - POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, NULL, NULL, NULL, iv->data), S2N_ERR_KEY_INIT); - POSIX_GUARD_OSSL(EVP_Cipher(key->evp_cipher_ctx, out->data, in->data, in->size), S2N_ERR_DECRYPT); + + /* len is set by EVP_DecryptUpdate. It is not checked here but padding is manually removed and therefore + * the decryption operation is validated. */ + int len = 0; + POSIX_GUARD_OSSL(EVP_DecryptUpdate(key->evp_cipher_ctx, out->data, &len, in->data, in->size), S2N_ERR_DECRYPT); return 0; } @@ -205,7 +213,7 @@ static int s2n_composite_cipher_aes128_sha_set_encryption_key(struct s2n_session { POSIX_ENSURE_EQ(in->size, 16); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); EVP_EncryptInit_ex(key->evp_cipher_ctx, s2n_evp_aes_128_cbc_hmac_sha1(), NULL, in->data, NULL); return 0; @@ -215,7 +223,7 @@ static int s2n_composite_cipher_aes128_sha_set_decryption_key(struct s2n_session { POSIX_ENSURE_EQ(in->size, 16); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); EVP_DecryptInit_ex(key->evp_cipher_ctx, s2n_evp_aes_128_cbc_hmac_sha1(), NULL, in->data, NULL); return 0; @@ -225,7 +233,7 @@ static int s2n_composite_cipher_aes256_sha_set_encryption_key(struct s2n_session { POSIX_ENSURE_EQ(in->size, 32); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); EVP_EncryptInit_ex(key->evp_cipher_ctx, s2n_evp_aes_256_cbc_hmac_sha1(), NULL, in->data, NULL); return 0; @@ -235,7 +243,7 @@ static int s2n_composite_cipher_aes256_sha_set_decryption_key(struct s2n_session { POSIX_ENSURE_EQ(in->size, 32); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); EVP_DecryptInit_ex(key->evp_cipher_ctx, s2n_evp_aes_256_cbc_hmac_sha1(), NULL, in->data, NULL); return 0; @@ -245,7 +253,7 @@ static int s2n_composite_cipher_aes128_sha256_set_encryption_key(struct s2n_sess { POSIX_ENSURE_EQ(in->size, 16); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); EVP_EncryptInit_ex(key->evp_cipher_ctx, s2n_evp_aes_128_cbc_hmac_sha256(), NULL, in->data, NULL); return 0; @@ -255,7 +263,7 @@ static int s2n_composite_cipher_aes128_sha256_set_decryption_key(struct s2n_sess { POSIX_ENSURE_EQ(in->size, 16); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); EVP_DecryptInit_ex(key->evp_cipher_ctx, s2n_evp_aes_128_cbc_hmac_sha256(), NULL, in->data, NULL); return 0; @@ -265,7 +273,7 @@ static int s2n_composite_cipher_aes256_sha256_set_encryption_key(struct s2n_sess { POSIX_ENSURE_EQ(in->size, 32); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); EVP_EncryptInit_ex(key->evp_cipher_ctx, s2n_evp_aes_256_cbc_hmac_sha256(), NULL, in->data, NULL); return 0; @@ -275,7 +283,7 @@ static int s2n_composite_cipher_aes256_sha256_set_decryption_key(struct s2n_sess { POSIX_ENSURE_EQ(in->size, 32); - EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, EVP_CIPH_NO_PADDING); + EVP_CIPHER_CTX_set_padding(key->evp_cipher_ctx, 0); EVP_DecryptInit_ex(key->evp_cipher_ctx, s2n_evp_aes_256_cbc_hmac_sha256(), NULL, in->data, NULL); return 0; diff --git a/contrib/restricted/aws/s2n/crypto/s2n_drbg.c b/contrib/restricted/aws/s2n/crypto/s2n_drbg.c index 242fd5ab9c..9f0acd5bf2 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_drbg.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_drbg.c @@ -48,6 +48,7 @@ static S2N_RESULT s2n_drbg_block_encrypt(EVP_CIPHER_CTX *ctx, uint8_t in[S2N_DRB { RESULT_ENSURE_REF(ctx); + /* len is set by EVP_EncryptUpdate and checked post operation */ int len = S2N_DRBG_BLOCK_SIZE; RESULT_GUARD_OSSL(EVP_EncryptUpdate(ctx, out, &len, in, S2N_DRBG_BLOCK_SIZE), S2N_ERR_DRBG); RESULT_ENSURE_EQ(len, S2N_DRBG_BLOCK_SIZE); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c index 23050ffea4..d775e5b7b9 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c @@ -16,10 +16,13 @@ #include <openssl/ec.h> #include <openssl/ecdsa.h> #include <openssl/x509.h> -#include "stuffer/s2n_stuffer.h" #include "error/s2n_errno.h" +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_safety_macros.h" #include "utils/s2n_blob.h" +#include "utils/s2n_compiler.h" #include "utils/s2n_mem.h" #include "utils/s2n_random.h" #include "utils/s2n_result.h" @@ -32,8 +35,25 @@ #include "crypto/s2n_openssl.h" #include "crypto/s2n_pkey.h" + #define S2N_ECDSA_TYPE 0 +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) +#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) +#pragma GCC diagnostic pop +#endif + + return out_ec_key; +} + S2N_RESULT s2n_ecdsa_der_signature_size(const struct s2n_pkey *pkey, uint32_t *size_out) { RESULT_ENSURE_REF(pkey); @@ -59,7 +79,10 @@ int s2n_ecdsa_sign_digest(const struct s2n_pkey *priv, struct s2n_blob *digest, POSIX_ENSURE_REF(key->ec_key); unsigned int signature_size = signature->size; - POSIX_GUARD_OSSL(ECDSA_sign(S2N_ECDSA_TYPE, digest->data, digest->size, signature->data, &signature_size, key->ec_key), S2N_ERR_SIGN); + + /* Safety: ECDSA_sign does not mutate the key */ + POSIX_GUARD_OSSL(ECDSA_sign(S2N_ECDSA_TYPE, digest->data, digest->size, signature->data, &signature_size, + s2n_unsafe_ecdsa_get_non_const(key)), S2N_ERR_SIGN); POSIX_ENSURE(signature_size <= signature->size, S2N_ERR_SIZE_MISMATCH); signature->size = signature_size; @@ -84,7 +107,7 @@ static int s2n_ecdsa_sign(const struct s2n_pkey *priv, s2n_signature_algorithm s POSIX_GUARD(s2n_ecdsa_sign_digest(priv, &digest_blob, signature)); POSIX_GUARD(s2n_hash_reset(digest)); - + return S2N_SUCCESS; } @@ -102,16 +125,18 @@ static int s2n_ecdsa_verify(const struct s2n_pkey *pub, s2n_signature_algorithm uint8_t digest_out[S2N_MAX_DIGEST_LEN]; POSIX_GUARD(s2n_hash_digest(digest, digest_out, digest_length)); - + + /* Safety: ECDSA_verify does not mutate the key */ /* ECDSA_verify ignores the first parameter */ - POSIX_GUARD_OSSL(ECDSA_verify(0, digest_out, digest_length, signature->data, signature->size, key->ec_key), S2N_ERR_VERIFY_SIGNATURE); + POSIX_GUARD_OSSL(ECDSA_verify(0, digest_out, digest_length, signature->data, signature->size, + s2n_unsafe_ecdsa_get_non_const(key)), S2N_ERR_VERIFY_SIGNATURE); POSIX_GUARD(s2n_hash_reset(digest)); - + return 0; } -static int s2n_ecdsa_keys_match(const struct s2n_pkey *pub, const struct s2n_pkey *priv) +static int s2n_ecdsa_keys_match(const struct s2n_pkey *pub, const struct s2n_pkey *priv) { uint8_t input[16] = { 1 }; DEFER_CLEANUP(struct s2n_blob signature = { 0 }, s2n_free); @@ -139,15 +164,17 @@ static int s2n_ecdsa_keys_match(const struct s2n_pkey *pub, const struct s2n_pke static int s2n_ecdsa_key_free(struct s2n_pkey *pkey) { + POSIX_ENSURE_REF(pkey); struct s2n_ecdsa_key *ecdsa_key = &pkey->key.ecdsa_key; if (ecdsa_key->ec_key == NULL) { - return 0; + return S2N_SUCCESS; } - - EC_KEY_free(ecdsa_key->ec_key); + + /* Safety: freeing the key owned by this object */ + EC_KEY_free(s2n_unsafe_ecdsa_get_non_const(ecdsa_key)); ecdsa_key->ec_key = NULL; - return 0; + return S2N_SUCCESS; } static int s2n_ecdsa_check_key_exists(const struct s2n_pkey *pkey) @@ -159,18 +186,18 @@ static int s2n_ecdsa_check_key_exists(const struct s2n_pkey *pkey) int s2n_evp_pkey_to_ecdsa_private_key(s2n_ecdsa_private_key *ecdsa_key, EVP_PKEY *evp_private_key) { - EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(evp_private_key); + const EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(evp_private_key); S2N_ERROR_IF(ec_key == NULL, S2N_ERR_DECODE_PRIVATE_KEY); - + ecdsa_key->ec_key = ec_key; return 0; } int s2n_evp_pkey_to_ecdsa_public_key(s2n_ecdsa_public_key *ecdsa_key, EVP_PKEY *evp_public_key) { - EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(evp_public_key); + const EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(evp_public_key); S2N_ERROR_IF(ec_key == NULL, S2N_ERR_DECODE_CERTIFICATE); - + ecdsa_key->ec_key = ec_key; return 0; } @@ -194,7 +221,8 @@ int s2n_ecdsa_pkey_matches_curve(const struct s2n_ecdsa_key *ecdsa_key, const st POSIX_ENSURE_REF(ecdsa_key->ec_key); POSIX_ENSURE_REF(curve); - int curve_id = EC_GROUP_get_curve_name(EC_KEY_get0_group(ecdsa_key->ec_key)); + const EC_KEY *key = ecdsa_key->ec_key; + int curve_id = EC_GROUP_get_curve_name(EC_KEY_get0_group(key)); POSIX_ENSURE_EQ(curve_id, curve->libcrypto_nid); return 0; diff --git a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.h b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.h index e4ad664349..f6670a7b04 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.h @@ -30,7 +30,16 @@ struct s2n_pkey; struct s2n_ecdsa_key { - EC_KEY *ec_key; + /* + * Starting in openssl_3, `EVP_PKEY_get1_EC_KEY` and `EVP_PKEY_get0_EC_KEY` + * functions return a pre-cached copy of the underlying key. This means that any + * mutations are not reflected back onto the underlying key. + * + * The `const` identifier is present to help ensure that the key is not mutated. + * Usecases which require a non-const EC_KEY (some openssl functions), should + * use `s2n_unsafe_ecdsa_get_non_const` while ensuring that the usage is safe. + */ + const EC_KEY *ec_key; }; typedef struct s2n_ecdsa_key s2n_ecdsa_public_key; diff --git a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c index f9ee9d135c..bf85f2773f 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c @@ -22,6 +22,10 @@ #include <openssl/crypto.h> #include <openssl/opensslv.h> +#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0) +#error #include <openssl/provider.h> +#endif + #include <string.h> /* Note: OpenSSL 1.0.2 -> 1.1.0 implemented a new API to get the version number @@ -134,6 +138,37 @@ bool s2n_libcrypto_is_boringssl() #endif } +S2N_RESULT s2n_libcrypto_init(void) +{ +#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0) + RESULT_ENSURE(OSSL_PROVIDER_load(NULL, "default") != NULL, S2N_ERR_OSSL_PROVIDER); + #ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 + /* needed to support RC4 algorithm + * https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html + */ + RESULT_ENSURE(OSSL_PROVIDER_load(NULL, "legacy") != NULL, S2N_ERR_OSSL_PROVIDER); + #endif +#endif + + return S2N_RESULT_OK; +} + +#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0) +int s2n_libcrypto_cleanup_cb(OSSL_PROVIDER *provider, void *cbdata) { + return OSSL_PROVIDER_unload(provider); +} + +S2N_RESULT s2n_libcrypto_cleanup(void) { + RESULT_GUARD_OSSL(OSSL_PROVIDER_do_all(NULL, *s2n_libcrypto_cleanup_cb, NULL), S2N_ERR_ATEXIT); + + return S2N_RESULT_OK; +} +#else +S2N_RESULT s2n_libcrypto_cleanup(void) { + return S2N_RESULT_OK; +} +#endif + /* Performs various checks to validate that the libcrypto used at compile-time * is the same libcrypto being used at run-time. */ diff --git a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h index 34d9ef2aac..c3b933562f 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h @@ -17,4 +17,6 @@ #include "utils/s2n_result.h" +S2N_RESULT s2n_libcrypto_init(void); S2N_RESULT s2n_libcrypto_validate_runtime(void); +S2N_RESULT s2n_libcrypto_cleanup(void); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_rsa.c b/contrib/restricted/aws/s2n/crypto/s2n_rsa.c index 164496f93f..27d2f7c32c 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_rsa.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_rsa.c @@ -13,25 +13,43 @@ * 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_drbg.h" +#include "crypto/s2n_evp_signing.h" #include "crypto/s2n_hash.h" #include "crypto/s2n_pkey.h" -#include "crypto/s2n_evp_signing.h" +#include "crypto/s2n_rsa.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_compiler.h" #include "utils/s2n_random.h" #include "utils/s2n_result.h" #include "utils/s2n_safety.h" -static S2N_RESULT s2n_rsa_modulus_check(RSA *rsa) +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) +#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) +#pragma GCC diagnostic pop +#endif + + return out_rsa_key; +} + +static S2N_RESULT s2n_rsa_modulus_check(const 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) @@ -45,13 +63,14 @@ static S2N_RESULT s2n_rsa_modulus_check(RSA *rsa) return S2N_RESULT_OK; } -static S2N_RESULT s2n_rsa_encrypted_size(const struct s2n_pkey *key, uint32_t *size_out) +static S2N_RESULT s2n_rsa_encrypted_size(const struct s2n_pkey *pkey, uint32_t *size_out) { - RESULT_ENSURE_REF(key); + RESULT_ENSURE_REF(pkey); RESULT_ENSURE_REF(size_out); - const struct s2n_rsa_key *rsa_key = &key->key.rsa_key; + const struct s2n_rsa_key *rsa_key = &pkey->key.rsa_key; RESULT_ENSURE_REF(rsa_key->rsa); + RESULT_GUARD(s2n_rsa_modulus_check(rsa_key->rsa)); const int size = RSA_size(rsa_key->rsa); @@ -97,9 +116,11 @@ static int s2n_rsa_encrypt(const struct s2n_pkey *pub, struct s2n_blob *in, stru POSIX_GUARD_RESULT(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); + const s2n_rsa_public_key *pub_key = &pub->key.rsa_key; + + /* Safety: RSA_public_encrypt does not mutate the key */ + int r = RSA_public_encrypt(in->size, ( unsigned char * )in->data, ( unsigned char * )out->data, + s2n_unsafe_rsa_get_non_const(pub_key), RSA_PKCS1_PADDING); S2N_ERROR_IF(r != out->size, S2N_ERR_SIZE_MISMATCH); return 0; @@ -117,8 +138,11 @@ static int s2n_rsa_decrypt(const struct s2n_pkey *priv, struct s2n_blob *in, str POSIX_GUARD_RESULT(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); + const s2n_rsa_private_key *priv_key = &priv->key.rsa_key; + + /* Safety: RSA_private_decrypt does not mutate the key */ + int r = RSA_private_decrypt(in->size, ( unsigned char * )in->data, intermediate, + s2n_unsafe_rsa_get_non_const(priv_key), 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); @@ -150,13 +174,17 @@ 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) { + POSIX_ENSURE_REF(pkey); struct s2n_rsa_key *rsa_key = &pkey->key.rsa_key; - if (rsa_key->rsa == NULL) { return 0; } + if (rsa_key->rsa == NULL) { + return S2N_SUCCESS; + } - RSA_free(rsa_key->rsa); + /* Safety: freeing the key owned by this object */ + RSA_free(s2n_unsafe_rsa_get_non_const(rsa_key)); rsa_key->rsa = NULL; - return 0; + return S2N_SUCCESS; } static int s2n_rsa_check_key_exists(const struct s2n_pkey *pkey) @@ -168,7 +196,7 @@ static int s2n_rsa_check_key_exists(const struct s2n_pkey *pkey) int s2n_evp_pkey_to_rsa_public_key(s2n_rsa_public_key *rsa_key, EVP_PKEY *evp_public_key) { - RSA *rsa = EVP_PKEY_get1_RSA(evp_public_key); + const RSA *rsa = EVP_PKEY_get1_RSA(evp_public_key); S2N_ERROR_IF(rsa == NULL, S2N_ERR_DECODE_CERTIFICATE); rsa_key->rsa = rsa; @@ -177,7 +205,7 @@ int s2n_evp_pkey_to_rsa_public_key(s2n_rsa_public_key *rsa_key, EVP_PKEY *evp_pu int s2n_evp_pkey_to_rsa_private_key(s2n_rsa_private_key *rsa_key, EVP_PKEY *evp_private_key) { - RSA *rsa = EVP_PKEY_get1_RSA(evp_private_key); + const RSA *rsa = EVP_PKEY_get1_RSA(evp_private_key); S2N_ERROR_IF(rsa == NULL, S2N_ERR_DECODE_PRIVATE_KEY); rsa_key->rsa = rsa; diff --git a/contrib/restricted/aws/s2n/crypto/s2n_rsa.h b/contrib/restricted/aws/s2n/crypto/s2n_rsa.h index 3bba4ff863..52724530a1 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_rsa.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_rsa.h @@ -28,9 +28,20 @@ struct s2n_pkey; struct s2n_rsa_key { - RSA *rsa; + /* + * Starting in openssl_3, `EVP_PKEY_get1_RSA` and `EVP_PKEY_get0_RSA` functions + * return a pre-cached copy of the underlying key. This means that any mutations + * are not reflected back onto the underlying key. + * + * The `const` identifier is present to help ensure that the key is not mutated. + * Usecases which require a non-const RSA key (some openssl functions), should + * use `s2n_unsafe_rsa_get_non_const` while ensuring that the usage is safe. + */ + const RSA *rsa; }; +RSA *s2n_unsafe_rsa_get_non_const(const struct s2n_rsa_key *rsa_key); + typedef struct s2n_rsa_key s2n_rsa_public_key; typedef struct s2n_rsa_key s2n_rsa_private_key; diff --git a/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c b/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c index da034d6ad3..70be214cf6 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c @@ -18,7 +18,6 @@ #include <stdint.h> #include "error/s2n_errno.h" - #include "stuffer/s2n_stuffer.h" #include "crypto/s2n_evp_signing.h" @@ -55,7 +54,7 @@ static S2N_RESULT s2n_rsa_pss_size(const struct s2n_pkey *key, uint32_t *size_ou return S2N_RESULT_OK; } -static int s2n_rsa_is_private_key(RSA *rsa_key) +static int s2n_rsa_is_private_key(const RSA *rsa_key) { const BIGNUM *d = NULL; RSA_get0_key(rsa_key, NULL, NULL, &d); @@ -73,7 +72,8 @@ int s2n_rsa_pss_key_sign(const struct s2n_pkey *priv, s2n_signature_algorithm si sig_alg_check(sig_alg, S2N_SIGNATURE_RSA_PSS_PSS); /* Not Possible to Sign with Public Key */ - S2N_ERROR_IF(!s2n_rsa_is_private_key(priv->key.rsa_key.rsa), S2N_ERR_KEY_MISMATCH); + const RSA *key = priv->key.rsa_key.rsa; + POSIX_ENSURE(s2n_rsa_is_private_key(key), S2N_ERR_KEY_MISMATCH); return s2n_rsa_pss_sign(priv, digest, signature_out); } @@ -85,7 +85,8 @@ int s2n_rsa_pss_key_verify(const struct s2n_pkey *pub, s2n_signature_algorithm s sig_alg_check(sig_alg, S2N_SIGNATURE_RSA_PSS_PSS); /* Using Private Key to Verify means the public/private keys were likely swapped, and likely indicates a bug. */ - S2N_ERROR_IF(s2n_rsa_is_private_key(pub->key.rsa_key.rsa), S2N_ERR_KEY_MISMATCH); + const RSA *key = pub->key.rsa_key.rsa; + POSIX_ENSURE(!s2n_rsa_is_private_key(key), S2N_ERR_KEY_MISMATCH); return s2n_rsa_pss_verify(pub, digest, signature_in); } @@ -144,11 +145,11 @@ static int s2n_rsa_validate_params_match(const struct s2n_pkey *pub, const struc POSIX_ENSURE_REF(priv); /* OpenSSL Documentation Links: - * - https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_get0_RSA.html + * - https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_get1_RSA.html * - https://www.openssl.org/docs/manmaster/man3/RSA_get0_key.html */ - RSA *pub_rsa_key = pub->key.rsa_key.rsa; - RSA *priv_rsa_key = priv->key.rsa_key.rsa; + const RSA *pub_rsa_key = pub->key.rsa_key.rsa; + const RSA *priv_rsa_key = priv->key.rsa_key.rsa; POSIX_ENSURE_REF(pub_rsa_key); POSIX_ENSURE_REF(priv_rsa_key); @@ -176,14 +177,22 @@ static int s2n_rsa_pss_keys_match(const struct s2n_pkey *pub, const struct s2n_p static int s2n_rsa_pss_key_free(struct s2n_pkey *pkey) { - /* This object does not own the reference to the key -- - * s2n_pkey handles it. */ + POSIX_ENSURE_REF(pkey); + struct s2n_rsa_key *rsa_key = &pkey->key.rsa_key; + if (rsa_key->rsa == NULL) { + return S2N_SUCCESS; + } - return 0; + /* Safety: freeing the key owned by this object */ + RSA_free(s2n_unsafe_rsa_get_non_const(rsa_key)); + rsa_key->rsa = NULL; + + return S2N_SUCCESS; } int s2n_evp_pkey_to_rsa_pss_public_key(struct s2n_rsa_key *rsa_key, EVP_PKEY *pkey) { - RSA *pub_rsa_key = EVP_PKEY_get0_RSA(pkey); + const RSA *pub_rsa_key = EVP_PKEY_get1_RSA(pkey); + POSIX_ENSURE_REF(pub_rsa_key); S2N_ERROR_IF(s2n_rsa_is_private_key(pub_rsa_key), S2N_ERR_KEY_MISMATCH); @@ -193,7 +202,7 @@ int s2n_evp_pkey_to_rsa_pss_public_key(struct s2n_rsa_key *rsa_key, EVP_PKEY *pk int s2n_evp_pkey_to_rsa_pss_private_key(struct s2n_rsa_key *rsa_key, EVP_PKEY *pkey) { - RSA *priv_rsa_key = EVP_PKEY_get0_RSA(pkey); + const RSA *priv_rsa_key = EVP_PKEY_get1_RSA(pkey); POSIX_ENSURE_REF(priv_rsa_key); /* Documentation: https://www.openssl.org/docs/man1.1.1/man3/RSA_check_key.html */ diff --git a/contrib/restricted/aws/s2n/crypto/s2n_rsa_signing.c b/contrib/restricted/aws/s2n/crypto/s2n_rsa_signing.c index 57a31172b7..fc74fa24d3 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_rsa_signing.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_rsa_signing.c @@ -64,10 +64,13 @@ int s2n_rsa_pkcs1v15_sign_digest(const struct s2n_pkey *priv, s2n_hash_algorithm int NID_type = 0; POSIX_GUARD(s2n_hash_NID_type(hash_alg, &NID_type)); - const s2n_rsa_private_key *key = &priv->key.rsa_key; + const s2n_rsa_private_key *rsa_key = &priv->key.rsa_key; unsigned int signature_size = signature->size; - POSIX_GUARD_OSSL(RSA_sign(NID_type, digest->data, digest->size, signature->data, &signature_size, key->rsa), S2N_ERR_SIGN); + + /* Safety: RSA_sign does not mutate the key */ + POSIX_GUARD_OSSL(RSA_sign(NID_type, digest->data, digest->size, signature->data, &signature_size, + s2n_unsafe_rsa_get_non_const(rsa_key)), S2N_ERR_SIGN); POSIX_ENSURE(signature_size <= signature->size, S2N_ERR_SIZE_MISMATCH); signature->size = signature_size; @@ -100,12 +103,14 @@ int s2n_rsa_pkcs1v15_verify(const struct s2n_pkey *pub, struct s2n_hash_state *d POSIX_GUARD(s2n_hash_NID_type(digest->alg, &digest_NID_type)); POSIX_ENSURE_LTE(digest_length, S2N_MAX_DIGEST_LEN); - const s2n_rsa_public_key *key = &pub->key.rsa_key; + const s2n_rsa_public_key *rsa_key = &pub->key.rsa_key; uint8_t digest_out[S2N_MAX_DIGEST_LEN]; POSIX_GUARD(s2n_hash_digest(digest, digest_out, digest_length)); - POSIX_GUARD_OSSL(RSA_verify(digest_NID_type, digest_out, digest_length, signature->data, signature->size, key->rsa), S2N_ERR_VERIFY_SIGNATURE); + /* Safety: RSA_verify does not mutate the key */ + POSIX_GUARD_OSSL(RSA_verify(digest_NID_type, digest_out, digest_length, signature->data, signature->size, + s2n_unsafe_rsa_get_non_const(rsa_key)), S2N_ERR_VERIFY_SIGNATURE); return 0; } 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 f5b2695da5..e5eab24391 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c @@ -40,7 +40,8 @@ static int s2n_stream_cipher_rc4_encrypt(struct s2n_session_key *key, struct s2n { POSIX_ENSURE_GTE(out->size, in->size); - int len = out->size; + /* len is set by EVP_EncryptUpdate and checked post operation */ + int len = 0; POSIX_GUARD_OSSL(EVP_EncryptUpdate(key->evp_cipher_ctx, out->data, &len, in->data, in->size), S2N_ERR_ENCRYPT); S2N_ERROR_IF(len != in->size, S2N_ERR_ENCRYPT); @@ -52,10 +53,11 @@ static int s2n_stream_cipher_rc4_decrypt(struct s2n_session_key *key, struct s2n { POSIX_ENSURE_GTE(out->size, in->size); - int len = out->size; - POSIX_GUARD_OSSL(EVP_DecryptUpdate(key->evp_cipher_ctx, out->data, &len, in->data, in->size), S2N_ERR_ENCRYPT); + /* len is set by EVP_DecryptUpdate and checked post operation */ + int len = 0; + POSIX_GUARD_OSSL(EVP_DecryptUpdate(key->evp_cipher_ctx, out->data, &len, in->data, in->size), S2N_ERR_DECRYPT); - S2N_ERROR_IF(len != in->size, S2N_ERR_ENCRYPT); + S2N_ERROR_IF(len != in->size, S2N_ERR_DECRYPT); return 0; } diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.c b/contrib/restricted/aws/s2n/error/s2n_errno.c index f2848af900..15b20d51bd 100644 --- a/contrib/restricted/aws/s2n/error/s2n_errno.c +++ b/contrib/restricted/aws/s2n/error/s2n_errno.c @@ -274,6 +274,7 @@ static const char *no_such_error = "Internal s2n error"; ERR_ENTRY(S2N_ERR_SECRET_SCHEDULE_STATE, "Correct inputs to secret calculation not available") \ ERR_ENTRY(S2N_ERR_LIBCRYPTO_VERSION_NUMBER_MISMATCH, "The libcrypto major version number seen at compile-time is different from the major version number seen at run-time") \ ERR_ENTRY(S2N_ERR_LIBCRYPTO_VERSION_NAME_MISMATCH, "The libcrypto major version name seen at compile-time is different from the major version name seen at run-time") \ + ERR_ENTRY(S2N_ERR_OSSL_PROVIDER, "Failed to load or unload an openssl provider") \ ERR_ENTRY(S2N_ERR_CERT_OWNERSHIP, "The ownership of the certificate chain is incompatible with the operation") \ ERR_ENTRY(S2N_ERR_INTERNAL_LIBCRYPTO_ERROR, "An internal error has occurred in the libcrypto API") /* clang-format on */ diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.h b/contrib/restricted/aws/s2n/error/s2n_errno.h index f0901c768b..473daa4fd4 100644 --- a/contrib/restricted/aws/s2n/error/s2n_errno.h +++ b/contrib/restricted/aws/s2n/error/s2n_errno.h @@ -215,6 +215,7 @@ typedef enum { S2N_ERR_RETRIEVE_FORK_GENERATION_NUMBER, S2N_ERR_LIBCRYPTO_VERSION_NUMBER_MISMATCH, S2N_ERR_LIBCRYPTO_VERSION_NAME_MISMATCH, + S2N_ERR_OSSL_PROVIDER, S2N_ERR_T_INTERNAL_END, /* S2N_ERR_T_USAGE */ diff --git a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.c b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.c index a2b1024732..d1727d7fa9 100644 --- a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.c +++ b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.c @@ -105,12 +105,20 @@ int s2n_stuffer_growable_alloc(struct s2n_stuffer *stuffer, const uint32_t size) int s2n_stuffer_free(struct s2n_stuffer *stuffer) { POSIX_PRECONDITION(s2n_stuffer_validate(stuffer)); - if (stuffer != NULL) { - if (stuffer->alloced) { - POSIX_GUARD(s2n_free(&stuffer->blob)); - } - *stuffer = (struct s2n_stuffer) {0}; + if (stuffer->alloced) { + POSIX_GUARD(s2n_free(&stuffer->blob)); } + *stuffer = (struct s2n_stuffer) {0}; + return S2N_SUCCESS; +} + +int s2n_stuffer_free_without_wipe(struct s2n_stuffer *stuffer) +{ + POSIX_PRECONDITION(s2n_stuffer_validate(stuffer)); + if (stuffer->alloced) { + POSIX_GUARD(s2n_free_without_wipe(&stuffer->blob)); + } + *stuffer = (struct s2n_stuffer) {0}; return S2N_SUCCESS; } diff --git a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.h b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.h index 99233e2cde..91de251eaf 100644 --- a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.h +++ b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.h @@ -68,6 +68,13 @@ extern int s2n_stuffer_init(struct s2n_stuffer *stuffer, struct s2n_blob *in); extern int s2n_stuffer_alloc(struct s2n_stuffer *stuffer, const uint32_t size); extern int s2n_stuffer_growable_alloc(struct s2n_stuffer *stuffer, const uint32_t size); extern int s2n_stuffer_free(struct s2n_stuffer *stuffer); +/** + * Frees the stuffer without zeroizing the contained data. + * + * This should only be used in scenarios where the data is encrypted or has been + * cleared with `s2n_stuffer_erase_and_read`. In most cases, prefer `s2n_stuffer_free`. + */ +extern int s2n_stuffer_free_without_wipe(struct s2n_stuffer *stuffer); extern int s2n_stuffer_resize(struct s2n_stuffer *stuffer, const uint32_t size); extern int s2n_stuffer_resize_if_empty(struct s2n_stuffer *stuffer, const uint32_t size); extern int s2n_stuffer_rewind_read(struct s2n_stuffer *stuffer, const uint32_t size); diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_early_data_indication.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_early_data_indication.c index 3cfea591cd..63de6d52f5 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_early_data_indication.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_early_data_indication.c @@ -145,6 +145,9 @@ static int s2n_client_early_data_indication_is_missing(struct s2n_connection *co static int s2n_client_early_data_indication_send(struct s2n_connection *conn, struct s2n_stuffer *out) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + POSIX_GUARD_RESULT(s2n_setup_middlebox_compat_for_early_data(conn)); POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_REQUESTED)); @@ -152,7 +155,7 @@ static int s2n_client_early_data_indication_send(struct s2n_connection *conn, st struct s2n_psk *first_psk = NULL; POSIX_GUARD_RESULT(s2n_array_get(&conn->psk_params.psk_list, 0, (void**) &first_psk)); POSIX_ENSURE_REF(first_psk); - conn->secure.cipher_suite = first_psk->early_data_config.cipher_suite; + conn->secure->cipher_suite = first_psk->early_data_config.cipher_suite; return S2N_SUCCESS; } 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 f8278f36b4..6abb8bf568 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c @@ -66,7 +66,7 @@ int s2n_client_psk_is_missing(struct s2n_connection *conn) bool s2n_client_psk_should_send(struct s2n_connection *conn) { - if (conn == NULL) { + if (!conn || !conn->secure) { return false; } @@ -84,7 +84,7 @@ bool s2n_client_psk_should_send(struct s2n_connection *conn) 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) { + && conn->secure->cipher_suite->prf_alg == psk->hmac_alg) { return true; } } @@ -134,6 +134,7 @@ static S2N_RESULT s2n_generate_obfuscated_ticket_age(struct s2n_psk *psk, uint64 static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); struct s2n_psk_parameters *psk_params = &conn->psk_params; struct s2n_array *psk_list = &psk_params->psk_list; @@ -154,7 +155,7 @@ static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer * *# 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) { + if (s2n_is_hello_retry_handshake(conn) && conn->secure->cipher_suite->prf_alg != psk->hmac_alg) { continue; } diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c index 00d0a240f9..20a3acfa9a 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c @@ -47,8 +47,8 @@ const s2n_extension_type s2n_server_ec_point_format_extension = { static bool s2n_server_ec_point_format_should_send(struct s2n_connection *conn) { - return conn && conn->secure.cipher_suite - && s2n_kex_includes(conn->secure.cipher_suite->key_exchange_alg, &s2n_ecdhe); + return conn && conn->secure && conn->secure->cipher_suite + && s2n_kex_includes(conn->secure->cipher_suite->key_exchange_alg, &s2n_ecdhe); } static int s2n_ec_point_format_send(struct s2n_connection *conn, struct s2n_stuffer *out) diff --git a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c index eb132cc642..7d9656d4d4 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c +++ b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c @@ -175,9 +175,10 @@ int s2n_is_cipher_suite_valid_for_auth(struct s2n_connection *conn, struct s2n_c int s2n_is_sig_scheme_valid_for_auth(struct s2n_connection *conn, const struct s2n_signature_scheme *sig_scheme) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); POSIX_ENSURE_REF(sig_scheme); - struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite; + struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite; POSIX_ENSURE_REF(cipher_suite); POSIX_GUARD(s2n_certs_exist_for_sig_scheme(conn, sig_scheme)); @@ -201,13 +202,14 @@ int s2n_is_sig_scheme_valid_for_auth(struct s2n_connection *conn, const struct s int s2n_is_cert_type_valid_for_auth(struct s2n_connection *conn, s2n_pkey_type cert_type) { POSIX_ENSURE_REF(conn); - POSIX_ENSURE_REF(conn->secure.cipher_suite); + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); s2n_authentication_method auth_method; POSIX_GUARD(s2n_get_auth_method_for_cert_type(cert_type, &auth_method)); - if (conn->secure.cipher_suite->auth_method != S2N_AUTHENTICATION_METHOD_SENTINEL) { - S2N_ERROR_IF(auth_method != conn->secure.cipher_suite->auth_method, S2N_ERR_CERT_TYPE_UNSUPPORTED); + if (conn->secure->cipher_suite->auth_method != S2N_AUTHENTICATION_METHOD_SENTINEL) { + S2N_ERROR_IF(auth_method != conn->secure->cipher_suite->auth_method, S2N_ERR_CERT_TYPE_UNSUPPORTED); } return S2N_SUCCESS; diff --git a/contrib/restricted/aws/s2n/tls/s2n_change_cipher_spec.c b/contrib/restricted/aws/s2n/tls/s2n_change_cipher_spec.c index 99dfdfb22a..dbdb9dfb78 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_change_cipher_spec.c +++ b/contrib/restricted/aws/s2n/tls/s2n_change_cipher_spec.c @@ -40,17 +40,20 @@ int s2n_basic_ccs_recv(struct s2n_connection *conn) int s2n_client_ccs_recv(struct s2n_connection *conn) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + POSIX_GUARD(s2n_basic_ccs_recv(conn)); /* Zero the sequence number */ - struct s2n_blob seq = {.data = conn->secure.client_sequence_number,.size = sizeof(conn->secure.client_sequence_number) }; + struct s2n_blob seq = {.data = conn->secure->client_sequence_number,.size = sizeof(conn->secure->client_sequence_number) }; POSIX_GUARD(s2n_blob_zero(&seq)); /* Compute the finished message */ POSIX_GUARD(s2n_prf_client_finished(conn)); /* Update the client to use the cipher-suite */ - conn->client = &conn->secure; + conn->client = conn->secure; /* Flush any partial alert messages that were pending. * If we don't do this, an attacker can inject a 1-byte alert message into the handshake @@ -62,17 +65,20 @@ int s2n_client_ccs_recv(struct s2n_connection *conn) int s2n_server_ccs_recv(struct s2n_connection *conn) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + POSIX_GUARD(s2n_basic_ccs_recv(conn)); /* Zero the sequence number */ - struct s2n_blob seq = {.data = conn->secure.server_sequence_number,.size = sizeof(conn->secure.server_sequence_number) }; + struct s2n_blob seq = {.data = conn->secure->server_sequence_number,.size = sizeof(conn->secure->server_sequence_number) }; POSIX_GUARD(s2n_blob_zero(&seq)); /* Compute the finished message */ POSIX_GUARD(s2n_prf_server_finished(conn)); /* Update the secure state to active, and point the client at the active state */ - conn->server = &conn->secure; + conn->server = conn->secure; /* Flush any partial alert messages that were pending. * If we don't do this, an attacker can inject a 1-byte alert message into the handshake diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c index 8d4aee52b2..3690338fd3 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c @@ -1768,4 +1768,20 @@ const struct s2n_cipher_preferences cipher_preferences_20210816_gcm = { .suites = cipher_suites_20210816_gcm, }; +struct s2n_cipher_suite *cipher_suites_rfc9151[] = { + /* TLS1.2 */ + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, + &s2n_rsa_with_aes_256_gcm_sha384, + &s2n_dhe_rsa_with_aes_256_gcm_sha384, + + /* TLS1.3 */ + &s2n_tls13_aes_256_gcm_sha384, +}; + +const struct s2n_cipher_preferences cipher_preferences_rfc9151 = { + .count = s2n_array_len(cipher_suites_rfc9151), + .suites = cipher_suites_rfc9151, +}; + /* clang-format on */ diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h index c7305a3908..455c8a71f2 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h @@ -46,6 +46,7 @@ extern const struct s2n_cipher_preferences cipher_preferences_20190801; extern const struct s2n_cipher_preferences cipher_preferences_20190120; extern const struct s2n_cipher_preferences cipher_preferences_20190121; extern const struct s2n_cipher_preferences cipher_preferences_20190122; +extern const struct s2n_cipher_preferences cipher_preferences_rfc9151; extern const struct s2n_cipher_preferences cipher_preferences_20210816; extern const struct s2n_cipher_preferences cipher_preferences_20210816_gcm; extern const struct s2n_cipher_preferences cipher_preferences_20210825; diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c index 99398da903..7e0256524a 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c @@ -1086,7 +1086,8 @@ S2N_RESULT s2n_cipher_suite_from_iana(const uint8_t iana[static S2N_TLS_CIPHER_S int s2n_set_cipher_as_client(struct s2n_connection *conn, uint8_t wire[S2N_TLS_CIPHER_SUITE_LEN]) { POSIX_ENSURE_REF(conn); - POSIX_ENSURE_REF(conn->secure.cipher_suite); + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); const struct s2n_security_policy *security_policy; POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy)); @@ -1139,16 +1140,16 @@ int s2n_set_cipher_as_client(struct s2n_connection *conn, uint8_t wire[S2N_TLS_C *# otherwise abort the handshake with an "illegal_parameter" alert. **/ if (s2n_is_hello_retry_handshake(conn) && !s2n_is_hello_retry_message(conn)) { - POSIX_ENSURE(conn->secure.cipher_suite->iana_value == cipher_suite->iana_value, S2N_ERR_CIPHER_NOT_SUPPORTED); + POSIX_ENSURE(conn->secure->cipher_suite->iana_value == cipher_suite->iana_value, S2N_ERR_CIPHER_NOT_SUPPORTED); return S2N_SUCCESS; } - conn->secure.cipher_suite = cipher_suite; + conn->secure->cipher_suite = cipher_suite; /* For SSLv3 use SSLv3-specific ciphers */ if (conn->actual_protocol_version == S2N_SSLv3) { - conn->secure.cipher_suite = conn->secure.cipher_suite->sslv3_cipher_suite; - POSIX_ENSURE_REF(conn->secure.cipher_suite); + conn->secure->cipher_suite = conn->secure->cipher_suite->sslv3_cipher_suite; + POSIX_ENSURE_REF(conn->secure->cipher_suite); } return 0; @@ -1169,6 +1170,9 @@ static int s2n_wire_ciphers_contain(const uint8_t *match, const uint8_t *wire, u static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire, uint32_t count, uint32_t cipher_suite_len) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + uint8_t renegotiation_info_scsv[S2N_TLS_CIPHER_SUITE_LEN] = { TLS_EMPTY_RENEGOTIATION_INFO_SCSV }; struct s2n_cipher_suite *higher_vers_match = NULL; @@ -1254,14 +1258,14 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire, continue; } - conn->secure.cipher_suite = match; + conn->secure->cipher_suite = match; return S2N_SUCCESS; } } /* Settle for a cipher with a higher required proto version, if it was set */ if (higher_vers_match) { - conn->secure.cipher_suite = higher_vers_match; + conn->secure->cipher_suite = higher_vers_match; return S2N_SUCCESS; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_finished.c b/contrib/restricted/aws/s2n/tls/s2n_client_finished.c index 871e7db15f..5a17228754 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_finished.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_finished.c @@ -39,15 +39,18 @@ int s2n_client_finished_recv(struct s2n_connection *conn) int s2n_client_finished_send(struct s2n_connection *conn) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + uint8_t *our_version; POSIX_GUARD(s2n_prf_client_finished(conn)); - struct s2n_blob seq = {.data = conn->secure.client_sequence_number,.size = sizeof(conn->secure.client_sequence_number) }; + struct s2n_blob seq = {.data = conn->secure->client_sequence_number,.size = sizeof(conn->secure->client_sequence_number) }; POSIX_GUARD(s2n_blob_zero(&seq)); our_version = conn->handshake.client_finished; /* Update the server to use the cipher suite */ - conn->client = &conn->secure; + conn->client = conn->secure; if (conn->actual_protocol_version == S2N_SSLv3) { POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, our_version, S2N_SSL_FINISHED_LEN)); diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c index 32506f495d..d382cb1ab8 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c @@ -392,6 +392,8 @@ int s2n_parse_client_hello(struct s2n_connection *conn) int s2n_process_client_hello(struct s2n_connection *conn) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); /* Client hello is parsed and config is finalized. * Negotiate protocol version, cipher suite, ALPN, select a cert, etc. */ @@ -431,7 +433,7 @@ int s2n_process_client_hello(struct s2n_connection *conn) /* Save the previous cipher suite */ uint8_t previous_cipher_suite_iana[S2N_TLS_CIPHER_SUITE_LEN] = { 0 }; - POSIX_CHECKED_MEMCPY(previous_cipher_suite_iana, conn->secure.cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN); + POSIX_CHECKED_MEMCPY(previous_cipher_suite_iana, conn->secure->cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN); /* Now choose the ciphers we have certs for. */ POSIX_GUARD(s2n_set_cipher_as_tls_server(conn, client_hello->cipher_suites.data, client_hello->cipher_suites.size / 2)); @@ -447,7 +449,7 @@ int s2n_process_client_hello(struct s2n_connection *conn) *# the server selects the cipher suite as the first step in the *# negotiation, then this will happen automatically). **/ - POSIX_ENSURE(s2n_constant_time_equals(previous_cipher_suite_iana, conn->secure.cipher_suite->iana_value, + POSIX_ENSURE(s2n_constant_time_equals(previous_cipher_suite_iana, conn->secure->cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN),S2N_ERR_BAD_MESSAGE); } 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 7b669e1ba6..37f4964f91 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c @@ -46,11 +46,14 @@ static int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rs static int s2n_hybrid_client_action(struct s2n_connection *conn, struct s2n_blob *combined_shared_key, s2n_kex_client_key_method kex_method, uint32_t *cursor, s2n_stuffer_action stuffer_action) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); POSIX_ENSURE_REF(kex_method); POSIX_ENSURE_REF(stuffer_action); + struct s2n_stuffer *io = &conn->handshake.io; - const struct s2n_kex *hybrid_kex_0 = conn->secure.cipher_suite->key_exchange_alg->hybrid[0]; - const struct s2n_kex *hybrid_kex_1 = conn->secure.cipher_suite->key_exchange_alg->hybrid[1]; + const struct s2n_kex *hybrid_kex_0 = conn->secure->cipher_suite->key_exchange_alg->hybrid[0]; + const struct s2n_kex *hybrid_kex_1 = conn->secure->cipher_suite->key_exchange_alg->hybrid[1]; /* Keep a copy to the start of the entire hybrid client key exchange message for the hybrid PRF */ struct s2n_blob *client_key_exchange_message = &conn->kex_params.client_key_exchange_message; @@ -81,8 +84,12 @@ 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) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); + /* Turn the pre-master secret into a master secret */ - POSIX_GUARD_RESULT(s2n_kex_tls_prf(conn->secure.cipher_suite->key_exchange_alg, conn, shared_key)); + POSIX_GUARD_RESULT(s2n_kex_tls_prf(conn->secure->cipher_suite->key_exchange_alg, conn, shared_key)); /* Expand the keys */ POSIX_GUARD(s2n_prf_key_expansion(conn)); @@ -214,7 +221,11 @@ int s2n_hybrid_client_key_recv(struct s2n_connection *conn, struct s2n_blob *com int s2n_client_key_recv(struct s2n_connection *conn) { - const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg; + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); + + const struct s2n_kex *key_exchange = conn->secure->cipher_suite->key_exchange_alg; DEFER_CLEANUP(struct s2n_blob shared_key = { 0 }, s2n_blob_zeroize_free); POSIX_GUARD_RESULT(s2n_kex_client_key_recv(key_exchange, conn, &shared_key)); @@ -309,7 +320,11 @@ int s2n_hybrid_client_key_send(struct s2n_connection *conn, struct s2n_blob *com int s2n_client_key_send(struct s2n_connection *conn) { - const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg; + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); + + const struct s2n_kex *key_exchange = conn->secure->cipher_suite->key_exchange_alg; DEFER_CLEANUP(struct s2n_blob shared_key = { 0 }, s2n_blob_zeroize_free); POSIX_GUARD_RESULT(s2n_kex_client_key_send(key_exchange, conn, &shared_key)); diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.c b/contrib/restricted/aws/s2n/tls/s2n_connection.c index 92b51cdb25..6901a8b95d 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_connection.c +++ b/contrib/restricted/aws/s2n/tls/s2n_connection.c @@ -32,7 +32,6 @@ #include "tls/s2n_alerts.h" #include "tls/s2n_cipher_suites.h" #include "tls/s2n_connection.h" -#include "tls/s2n_connection_evp_digests.h" #include "tls/s2n_handshake.h" #include "tls/s2n_kem.h" #include "tls/s2n_internal.h" @@ -59,28 +58,6 @@ #define S2N_SET_KEY_SHARE_LIST_EMPTY(keyshares) (keyshares |= 1) #define S2N_SET_KEY_SHARE_REQUEST(keyshares, i) (keyshares |= ( 1 << ( i + 1 ))) -static int s2n_connection_new_hmacs(struct s2n_connection *conn) -{ - /* Allocate long-term memory for the Connection's HMAC states */ - POSIX_GUARD(s2n_hmac_new(&conn->initial.client_record_mac)); - POSIX_GUARD(s2n_hmac_new(&conn->initial.server_record_mac)); - POSIX_GUARD(s2n_hmac_new(&conn->secure.client_record_mac)); - POSIX_GUARD(s2n_hmac_new(&conn->secure.server_record_mac)); - - return 0; -} - -static int s2n_connection_init_hmacs(struct s2n_connection *conn) -{ - /* Initialize all of the Connection's HMAC states */ - POSIX_GUARD(s2n_hmac_init(&conn->initial.client_record_mac, S2N_HMAC_NONE, NULL, 0)); - POSIX_GUARD(s2n_hmac_init(&conn->initial.server_record_mac, S2N_HMAC_NONE, NULL, 0)); - POSIX_GUARD(s2n_hmac_init(&conn->secure.client_record_mac, S2N_HMAC_NONE, NULL, 0)); - POSIX_GUARD(s2n_hmac_init(&conn->secure.server_record_mac, S2N_HMAC_NONE, NULL, 0)); - - return 0; -} - /* Allocates and initializes memory for a new connection. * * Since customers can reuse a connection, ensure that values on the connection are @@ -118,19 +95,10 @@ struct s2n_connection *s2n_connection_new(s2n_mode mode) PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->ticket_ext_data, S2N_TLS12_TICKET_SIZE_IN_BYTES)); PTR_GUARD_POSIX(s2n_stuffer_init(&conn->client_ticket_to_decrypt, &blob)); - /* Allocate long term key memory */ - PTR_GUARD_POSIX(s2n_session_key_alloc(&conn->secure.client_key)); - PTR_GUARD_POSIX(s2n_session_key_alloc(&conn->secure.server_key)); - PTR_GUARD_POSIX(s2n_session_key_alloc(&conn->initial.client_key)); - PTR_GUARD_POSIX(s2n_session_key_alloc(&conn->initial.server_key)); - /* Allocate long term hash and HMAC memory */ PTR_GUARD_RESULT(s2n_prf_new(conn)); PTR_GUARD_RESULT(s2n_handshake_hashes_new(&conn->handshake.hashes)); - PTR_GUARD_POSIX(s2n_connection_new_hmacs(conn)); - PTR_GUARD_POSIX(s2n_connection_init_hmacs(conn)); - /* Initialize the growable stuffers. Zero length at first, but the resize * in _wipe will fix that */ @@ -152,26 +120,12 @@ struct s2n_connection *s2n_connection_new(s2n_mode mode) return conn; } -static int s2n_connection_free_keys(struct s2n_connection *conn) -{ - POSIX_GUARD(s2n_session_key_free(&conn->secure.client_key)); - POSIX_GUARD(s2n_session_key_free(&conn->secure.server_key)); - POSIX_GUARD(s2n_session_key_free(&conn->initial.client_key)); - POSIX_GUARD(s2n_session_key_free(&conn->initial.server_key)); - - return 0; -} - static int s2n_connection_zero(struct s2n_connection *conn, int mode, struct s2n_config *config) { /* Zero the whole connection structure */ POSIX_CHECKED_MEMSET(conn, 0, sizeof(struct s2n_connection)); conn->mode = mode; - conn->initial.cipher_suite = &s2n_null_cipher_suite; - conn->secure.cipher_suite = &s2n_null_cipher_suite; - conn->server = &conn->initial; - conn->client = &conn->initial; conn->max_outgoing_fragment_length = S2N_DEFAULT_FRAGMENT_LENGTH; conn->handshake.end_of_messages = APPLICATION_DATA; s2n_connection_set_config(conn, config); @@ -194,16 +148,6 @@ S2N_RESULT s2n_connection_wipe_all_keyshares(struct s2n_connection *conn) static int s2n_connection_wipe_keys(struct s2n_connection *conn) { - /* Destroy any keys - we call destroy on the object as that is where - * keys are allocated. */ - if (conn->secure.cipher_suite - && conn->secure.cipher_suite->record_alg - && conn->secure.cipher_suite->record_alg->cipher - && conn->secure.cipher_suite->record_alg->cipher->destroy_key) { - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->destroy_key(&conn->secure.client_key)); - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->destroy_key(&conn->secure.server_key)); - } - /* Free any server key received (we may not have completed a * handshake, so this may not have been free'd yet) */ POSIX_GUARD(s2n_pkey_free(&conn->handshake_params.server_public_key)); @@ -220,17 +164,6 @@ static int s2n_connection_wipe_keys(struct s2n_connection *conn) return 0; } -static int s2n_connection_reset_hmacs(struct s2n_connection *conn) -{ - /* Reset all of the Connection's HMAC states */ - POSIX_GUARD(s2n_hmac_reset(&conn->initial.client_record_mac)); - POSIX_GUARD(s2n_hmac_reset(&conn->initial.server_record_mac)); - POSIX_GUARD(s2n_hmac_reset(&conn->secure.client_record_mac)); - POSIX_GUARD(s2n_hmac_reset(&conn->secure.server_record_mac)); - - return 0; -} - static int s2n_connection_free_managed_recv_io(struct s2n_connection *conn) { POSIX_ENSURE_REF(conn); @@ -277,17 +210,6 @@ static int s2n_connection_wipe_io(struct s2n_connection *conn) return 0; } -static int s2n_connection_free_hmacs(struct s2n_connection *conn) -{ - /* Free all of the Connection's HMAC states */ - POSIX_GUARD(s2n_hmac_free(&conn->initial.client_record_mac)); - POSIX_GUARD(s2n_hmac_free(&conn->initial.server_record_mac)); - POSIX_GUARD(s2n_hmac_free(&conn->secure.client_record_mac)); - POSIX_GUARD(s2n_hmac_free(&conn->secure.server_record_mac)); - - return 0; -} - static uint8_t s2n_default_verify_host(const char *host_name, size_t len, void *data) { /* if present, match server_name of the connection using rules @@ -333,15 +255,11 @@ S2N_CLEANUP_RESULT s2n_connection_ptr_free(struct s2n_connection **conn) int s2n_connection_free(struct s2n_connection *conn) { POSIX_GUARD(s2n_connection_wipe_keys(conn)); - POSIX_GUARD(s2n_connection_free_keys(conn)); POSIX_GUARD_RESULT(s2n_psk_parameters_wipe(&conn->psk_params)); POSIX_GUARD_RESULT(s2n_prf_free(conn)); POSIX_GUARD_RESULT(s2n_handshake_hashes_free(&conn->handshake.hashes)); - POSIX_GUARD(s2n_connection_reset_hmacs(conn)); - POSIX_GUARD(s2n_connection_free_hmacs(conn)); - POSIX_GUARD(s2n_connection_free_managed_io(conn)); POSIX_GUARD(s2n_free(&conn->client_ticket)); @@ -357,6 +275,8 @@ int s2n_connection_free(struct s2n_connection *conn) POSIX_GUARD(s2n_client_hello_free(&conn->client_hello)); POSIX_GUARD(s2n_free(&conn->application_protocols_overridden)); POSIX_GUARD(s2n_free(&conn->cookie)); + POSIX_GUARD_RESULT(s2n_crypto_parameters_free(&conn->initial)); + POSIX_GUARD_RESULT(s2n_crypto_parameters_free(&conn->secure)); POSIX_GUARD(s2n_free_object((uint8_t **)&conn, sizeof(struct s2n_connection))); return 0; @@ -488,6 +408,14 @@ int s2n_connection_free_handshake(struct s2n_connection *conn) POSIX_GUARD_RESULT(s2n_handshake_hashes_free(&conn->handshake.hashes)); POSIX_GUARD_RESULT(s2n_prf_free(conn)); + /* All IO should use conn->secure after the handshake. + * However, if this method is called before the handshake completes, + * the connection may still be using conn->initial. + */ + if (conn->client != conn->initial && conn->server != conn->initial) { + POSIX_GUARD_RESULT(s2n_crypto_parameters_free(&conn->initial)); + } + /* Wipe the buffers we are going to free */ POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io)); POSIX_GUARD(s2n_blob_zero(&conn->client_hello.raw_message)); @@ -525,13 +453,6 @@ int s2n_connection_wipe(struct s2n_connection *conn) struct s2n_stuffer header_in = {0}; struct s2n_stuffer in = {0}; struct s2n_stuffer out = {0}; - /* Session keys will be wiped. Preserve structs to avoid reallocation */ - struct s2n_session_key initial_client_key = {0}; - struct s2n_session_key initial_server_key = {0}; - struct s2n_session_key secure_client_key = {0}; - struct s2n_session_key secure_server_key = {0}; - /* Parts of the hmac states will be wiped. Preserve structs to avoid reallocation */ - struct s2n_connection_hmac_handles hmac_handles = {0}; /* Some required structures might have been freed to conserve memory between handshakes. * Restore them. @@ -546,10 +467,21 @@ int s2n_connection_wipe(struct s2n_connection *conn) } POSIX_GUARD_RESULT(s2n_prf_wipe(conn)); struct s2n_prf_working_space *prf_workspace = conn->prf_space; + if (!conn->initial) { + POSIX_GUARD_RESULT(s2n_crypto_parameters_new(&conn->initial)); + } else { + POSIX_GUARD_RESULT(s2n_crypto_parameters_wipe(conn->initial)); + } + struct s2n_crypto_parameters *initial = conn->initial; + if (!conn->secure) { + POSIX_GUARD_RESULT(s2n_crypto_parameters_new(&conn->secure)); + } else { + POSIX_GUARD_RESULT(s2n_crypto_parameters_wipe(conn->secure)); + } + struct s2n_crypto_parameters *secure = conn->secure; /* Wipe all of the sensitive stuff */ POSIX_GUARD(s2n_connection_wipe_keys(conn)); - POSIX_GUARD(s2n_connection_reset_hmacs(conn)); POSIX_GUARD(s2n_stuffer_wipe(&conn->alert_in)); POSIX_GUARD(s2n_stuffer_wipe(&conn->reader_alert_out)); POSIX_GUARD(s2n_stuffer_wipe(&conn->writer_alert_out)); @@ -603,11 +535,6 @@ int s2n_connection_wipe(struct s2n_connection *conn) POSIX_CHECKED_MEMCPY(&header_in, &conn->header_in, sizeof(struct s2n_stuffer)); POSIX_CHECKED_MEMCPY(&in, &conn->in, sizeof(struct s2n_stuffer)); POSIX_CHECKED_MEMCPY(&out, &conn->out, sizeof(struct s2n_stuffer)); - POSIX_CHECKED_MEMCPY(&initial_client_key, &conn->initial.client_key, sizeof(struct s2n_session_key)); - POSIX_CHECKED_MEMCPY(&initial_server_key, &conn->initial.server_key, sizeof(struct s2n_session_key)); - POSIX_CHECKED_MEMCPY(&secure_client_key, &conn->secure.client_key, sizeof(struct s2n_session_key)); - POSIX_CHECKED_MEMCPY(&secure_server_key, &conn->secure.server_key, sizeof(struct s2n_session_key)); - POSIX_GUARD(s2n_connection_save_hmac_state(&hmac_handles, conn)); #if S2N_GCC_VERSION_AT_LEAST(4,6,0) #pragma GCC diagnostic pop #endif @@ -622,16 +549,13 @@ int s2n_connection_wipe(struct s2n_connection *conn) POSIX_CHECKED_MEMCPY(&conn->header_in, &header_in, sizeof(struct s2n_stuffer)); POSIX_CHECKED_MEMCPY(&conn->in, &in, sizeof(struct s2n_stuffer)); POSIX_CHECKED_MEMCPY(&conn->out, &out, sizeof(struct s2n_stuffer)); - POSIX_CHECKED_MEMCPY(&conn->initial.client_key, &initial_client_key, sizeof(struct s2n_session_key)); - POSIX_CHECKED_MEMCPY(&conn->initial.server_key, &initial_server_key, sizeof(struct s2n_session_key)); - POSIX_CHECKED_MEMCPY(&conn->secure.client_key, &secure_client_key, sizeof(struct s2n_session_key)); - POSIX_CHECKED_MEMCPY(&conn->secure.server_key, &secure_server_key, sizeof(struct s2n_session_key)); - POSIX_GUARD(s2n_connection_restore_hmac_state(conn, &hmac_handles)); + conn->handshake.hashes = handshake_hashes; conn->prf_space = prf_workspace; - - /* Re-initialize hash and hmac states */ - POSIX_GUARD(s2n_connection_init_hmacs(conn)); + conn->initial = initial; + conn->secure = secure; + conn->client = conn->initial; + conn->server = conn->initial; POSIX_GUARD_RESULT(s2n_psk_parameters_init(&conn->psk_params)); conn->server_keying_material_lifetime = ONE_WEEK_IN_SEC; @@ -942,29 +866,31 @@ uint64_t s2n_connection_get_wire_bytes_out(struct s2n_connection *conn) const char *s2n_connection_get_cipher(struct s2n_connection *conn) { PTR_ENSURE_REF(conn); - PTR_ENSURE_REF(conn->secure.cipher_suite); + PTR_ENSURE_REF(conn->secure); + PTR_ENSURE_REF(conn->secure->cipher_suite); - return conn->secure.cipher_suite->name; + return conn->secure->cipher_suite->name; } int s2n_connection_get_cipher_iana_value(struct s2n_connection *conn, uint8_t *first, uint8_t *second) { POSIX_ENSURE_REF(conn); - POSIX_ENSURE_REF(conn->secure.cipher_suite); + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); POSIX_ENSURE_MUT(first); POSIX_ENSURE_MUT(second); /* ensure we've negotiated a cipher suite */ POSIX_ENSURE( memcmp( - conn->secure.cipher_suite->iana_value, + conn->secure->cipher_suite->iana_value, s2n_null_cipher_suite.iana_value, sizeof(s2n_null_cipher_suite.iana_value) ) != 0, S2N_ERR_INVALID_STATE ); - const uint8_t *iana_value = conn->secure.cipher_suite->iana_value; + const uint8_t *iana_value = conn->secure->cipher_suite->iana_value; *first = iana_value[0]; *second = iana_value[1]; @@ -974,10 +900,12 @@ int s2n_connection_get_cipher_iana_value(struct s2n_connection *conn, uint8_t *f const char *s2n_connection_get_curve(struct s2n_connection *conn) { PTR_ENSURE_REF(conn); + PTR_ENSURE_REF(conn->secure); + PTR_ENSURE_REF(conn->secure->cipher_suite); if (conn->kex_params.server_ecc_evp_params.negotiated_curve) { /* TLS1.3 currently only uses ECC groups. */ - if (conn->actual_protocol_version >= S2N_TLS13 || s2n_kex_includes(conn->secure.cipher_suite->key_exchange_alg, &s2n_ecdhe)) { + if (conn->actual_protocol_version >= S2N_TLS13 || s2n_kex_includes(conn->secure->cipher_suite->key_exchange_alg, &s2n_ecdhe)) { return conn->kex_params.server_ecc_evp_params.negotiated_curve->name; } } @@ -1280,6 +1208,13 @@ int s2n_connection_prefer_low_latency(struct s2n_connection *conn) return S2N_SUCCESS; } +int s2n_connection_set_dynamic_buffers(struct s2n_connection *conn, bool enabled) +{ + POSIX_ENSURE_REF(conn); + conn->dynamic_buffers = enabled; + return S2N_SUCCESS; +} + int s2n_connection_set_dynamic_record_threshold(struct s2n_connection *conn, uint32_t resize_threshold, uint16_t timeout_threshold) { POSIX_ENSURE_REF(conn); @@ -1554,3 +1489,35 @@ int s2n_connection_get_config(struct s2n_connection *conn, struct s2n_config **c return S2N_SUCCESS; } + +S2N_RESULT s2n_connection_dynamic_free_out_buffer(struct s2n_connection *conn) +{ + RESULT_ENSURE_REF(conn); + + /* free the out buffer if we're in dynamic mode and it's completely flushed */ + if (conn->dynamic_buffers && s2n_stuffer_is_consumed(&conn->out)) { + /* since outgoing buffers are already encrypted, the buffers don't need to be zeroed, which saves some overhead */ + RESULT_GUARD_POSIX(s2n_stuffer_free_without_wipe(&conn->out)); + + /* reset the stuffer to its initial state */ + RESULT_GUARD_POSIX(s2n_stuffer_growable_alloc(&conn->out, 0)); + } + + return S2N_RESULT_OK; +} + +S2N_RESULT s2n_connection_dynamic_free_in_buffer(struct s2n_connection *conn) +{ + RESULT_ENSURE_REF(conn); + + /* free the `in` buffer if we're in dynamic mode and it's completely flushed */ + if (conn->dynamic_buffers && s2n_stuffer_is_consumed(&conn->in)) { + /* when copying the buffer into the application, we use `s2n_stuffer_erase_and_read`, which already zeroes the memory */ + RESULT_GUARD_POSIX(s2n_stuffer_free_without_wipe(&conn->in)); + + /* reset the stuffer to its initial state */ + RESULT_GUARD_POSIX(s2n_stuffer_growable_alloc(&conn->in, 0)); + } + + return S2N_RESULT_OK; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.h b/contrib/restricted/aws/s2n/tls/s2n_connection.h index 2965de74e6..9d7d5bdf68 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_connection.h +++ b/contrib/restricted/aws/s2n/tls/s2n_connection.h @@ -127,6 +127,10 @@ struct s2n_connection { * This allows multiple records to be written with one socket send. */ unsigned multirecord_send:1; + /* If enabled, this connection will free each of its IO buffers after all data + * has been flushed */ + unsigned dynamic_buffers:1; + /* The configuration (cert, key .. etc ) */ struct s2n_config *config; @@ -193,8 +197,8 @@ struct s2n_connection { uint8_t actual_protocol_version_established; /* Our crypto parameters */ - struct s2n_crypto_parameters initial; - struct s2n_crypto_parameters secure; + struct s2n_crypto_parameters *initial; + struct s2n_crypto_parameters *secure; union s2n_secrets secrets; /* Which set is the client/server actually using? */ @@ -390,6 +394,10 @@ int s2n_connection_recv_stuffer(struct s2n_stuffer *stuffer, struct s2n_connecti S2N_RESULT s2n_connection_wipe_all_keyshares(struct s2n_connection *conn); +/* If dynamic buffers are enabled, the IO buffers may be freed if they are completely consumed */ +S2N_RESULT s2n_connection_dynamic_free_in_buffer(struct s2n_connection *conn); +S2N_RESULT s2n_connection_dynamic_free_out_buffer(struct s2n_connection *conn); + int s2n_connection_get_cipher_preferences(struct s2n_connection *conn, const struct s2n_cipher_preferences **cipher_preferences); int s2n_connection_get_security_policy(struct s2n_connection *conn, const struct s2n_security_policy **security_policy); int s2n_connection_get_kem_preferences(struct s2n_connection *conn, const struct s2n_kem_preferences **kem_preferences); diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c b/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c deleted file mode 100644 index 856ca79f89..0000000000 --- a/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 "tls/s2n_connection_evp_digests.h" - -#include "utils/s2n_safety.h" - -/* On s2n_connection_wipe, save all pointers to OpenSSL EVP digest structs in a temporary - * s2n_connection_hmac_handles struct to avoid re-allocation after zeroing the connection struct. - * Do not store any additional HMAC state as it is unnecessary and excessive copying would impact performance. - */ -int s2n_connection_save_hmac_state(struct s2n_connection_hmac_handles *hmac_handles, struct s2n_connection *conn) -{ - POSIX_GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->initial_client, &conn->initial.client_record_mac)); - POSIX_GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->initial_server, &conn->initial.server_record_mac)); - POSIX_GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->secure_client, &conn->secure.client_record_mac)); - POSIX_GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->secure_server, &conn->secure.server_record_mac)); - return 0; -} - -/* On s2n_connection_wipe, restore all pointers to OpenSSL EVP digest structs after zeroing the connection struct - * to avoid re-allocation. Do not store any additional HMAC state as it is unnecessary and excessive copying - * would impact performance. - */ -int s2n_connection_restore_hmac_state(struct s2n_connection *conn, struct s2n_connection_hmac_handles *hmac_handles) -{ - POSIX_GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->initial_client, &conn->initial.client_record_mac)); - POSIX_GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->initial_server, &conn->initial.server_record_mac)); - POSIX_GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->secure_client, &conn->secure.client_record_mac)); - POSIX_GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->secure_server, &conn->secure.server_record_mac)); - return 0; -} diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.h b/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.h deleted file mode 100644 index e94e19d010..0000000000 --- a/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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/s2n_connection.h" -#include "tls/s2n_prf.h" - -#include "crypto/s2n_hash.h" - -/* Allocationg new EVP structs is expensive, so we back them up here and reuse them */ -struct s2n_connection_hmac_handles { - struct s2n_hmac_evp_backup initial_client; - struct s2n_hmac_evp_backup initial_client_copy; - struct s2n_hmac_evp_backup initial_server; - struct s2n_hmac_evp_backup secure_client; - struct s2n_hmac_evp_backup secure_client_copy; - struct s2n_hmac_evp_backup secure_server; -}; - -extern int s2n_connection_save_hmac_state(struct s2n_connection_hmac_handles *hmac_handles, struct s2n_connection *conn); -extern int s2n_connection_restore_hmac_state(struct s2n_connection *conn, struct s2n_connection_hmac_handles *hmac_handles); diff --git a/contrib/restricted/aws/s2n/tls/s2n_crypto.c b/contrib/restricted/aws/s2n/tls/s2n_crypto.c new file mode 100644 index 0000000000..a5fac27a10 --- /dev/null +++ b/contrib/restricted/aws/s2n/tls/s2n_crypto.c @@ -0,0 +1,97 @@ +/* + * 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 "api/s2n.h" +#include "tls/s2n_crypto.h" + +#include "tls/s2n_cipher_suites.h" +#include "utils/s2n_result.h" +#include "utils/s2n_safety.h" + +S2N_RESULT s2n_crypto_parameters_new(struct s2n_crypto_parameters **new_params) +{ + RESULT_ENSURE_REF(new_params); + RESULT_ENSURE_EQ(*new_params, NULL); + + DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free); + RESULT_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_crypto_parameters))); + RESULT_GUARD_POSIX(s2n_blob_zero(&mem)); + + DEFER_CLEANUP(struct s2n_crypto_parameters *params = (struct s2n_crypto_parameters*)(void*) mem.data, + s2n_crypto_parameters_free); + ZERO_TO_DISABLE_DEFER_CLEANUP(mem); + + /* Allocate long-term memory for the HMAC states */ + RESULT_GUARD_POSIX(s2n_hmac_new(¶ms->client_record_mac)); + RESULT_GUARD_POSIX(s2n_hmac_new(¶ms->server_record_mac)); + + /* Allocate key memory */ + RESULT_GUARD_POSIX(s2n_session_key_alloc(¶ms->client_key)); + RESULT_GUARD_POSIX(s2n_session_key_alloc(¶ms->server_key)); + + /* Setup */ + RESULT_GUARD(s2n_crypto_parameters_wipe(params)); + + *new_params = params; + ZERO_TO_DISABLE_DEFER_CLEANUP(params); + return S2N_RESULT_OK; +} + +S2N_RESULT s2n_crypto_parameters_wipe(struct s2n_crypto_parameters *params) +{ + RESULT_ENSURE_REF(params); + + /* Wipe the hmacs for reuse */ + struct s2n_hmac_state client_state = params->client_record_mac; + struct s2n_hmac_state server_state = params->server_record_mac; + RESULT_GUARD_POSIX(s2n_hmac_init(&client_state, S2N_HMAC_NONE, NULL, 0)); + RESULT_GUARD_POSIX(s2n_hmac_init(&server_state, S2N_HMAC_NONE, NULL, 0)); + + /* Wipe the keys for reuse */ + struct s2n_session_key client_key = params->client_key; + struct s2n_session_key server_key = params->server_key; + if (params->cipher_suite && params->cipher_suite->record_alg && + params->cipher_suite->record_alg->cipher && params->cipher_suite->record_alg->cipher->destroy_key) { + RESULT_GUARD_POSIX(params->cipher_suite->record_alg->cipher->destroy_key(¶ms->client_key)); + RESULT_GUARD_POSIX(params->cipher_suite->record_alg->cipher->destroy_key(¶ms->server_key)); + } + + *params = (struct s2n_crypto_parameters) { 0 }; + + params->client_record_mac = client_state; + params->server_record_mac = server_state; + params->client_key = client_key; + params->server_key = server_key; + params->cipher_suite = &s2n_null_cipher_suite; + return S2N_RESULT_OK; +} + +S2N_CLEANUP_RESULT s2n_crypto_parameters_free(struct s2n_crypto_parameters **params) +{ + if (params == NULL || *params == NULL) { + return S2N_RESULT_OK; + } + + /* Free HMAC states */ + RESULT_GUARD_POSIX(s2n_hmac_free(&(*params)->client_record_mac)); + RESULT_GUARD_POSIX(s2n_hmac_free(&(*params)->server_record_mac)); + + /* Free session keys */ + RESULT_GUARD_POSIX(s2n_session_key_free(&(*params)->client_key)); + RESULT_GUARD_POSIX(s2n_session_key_free(&(*params)->server_key)); + + RESULT_GUARD_POSIX(s2n_free_object((uint8_t **) params, sizeof(struct s2n_crypto_parameters))); + return S2N_RESULT_OK; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_crypto.h b/contrib/restricted/aws/s2n/tls/s2n_crypto.h index de6c18b332..37997bb8eb 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_crypto.h +++ b/contrib/restricted/aws/s2n/tls/s2n_crypto.h @@ -65,3 +65,7 @@ struct s2n_crypto_parameters { uint8_t client_sequence_number[S2N_TLS_SEQUENCE_NUM_LEN]; uint8_t server_sequence_number[S2N_TLS_SEQUENCE_NUM_LEN]; }; + +S2N_RESULT s2n_crypto_parameters_new(struct s2n_crypto_parameters **params); +S2N_RESULT s2n_crypto_parameters_wipe(struct s2n_crypto_parameters *params); +S2N_CLEANUP_RESULT s2n_crypto_parameters_free(struct s2n_crypto_parameters **params); diff --git a/contrib/restricted/aws/s2n/tls/s2n_early_data.c b/contrib/restricted/aws/s2n/tls/s2n_early_data.c index 102ceed334..309f108f38 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_early_data.c +++ b/contrib/restricted/aws/s2n/tls/s2n_early_data.c @@ -61,6 +61,7 @@ int s2n_connection_set_end_of_early_data(struct s2n_connection *conn) static S2N_RESULT s2n_early_data_validate(struct s2n_connection *conn) { RESULT_ENSURE_REF(conn); + RESULT_ENSURE_REF(conn->secure); /** *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10 @@ -87,7 +88,7 @@ static S2N_RESULT s2n_early_data_validate(struct s2n_connection *conn) *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10 *# - The selected cipher suite **/ - RESULT_ENSURE_EQ(config->cipher_suite, conn->secure.cipher_suite); + RESULT_ENSURE_EQ(config->cipher_suite, conn->secure->cipher_suite); /** *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10 *# - The selected ALPN [RFC7301] protocol, if any diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_handshake.c index eb46950ebe..0923c3d9a7 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_handshake.c +++ b/contrib/restricted/aws/s2n/tls/s2n_handshake.c @@ -143,6 +143,9 @@ uint8_t s2n_handshake_is_hash_required(struct s2n_handshake *handshake, s2n_hash */ int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + /* Clear all of the required hashes */ memset(conn->handshake.required_hash_algs, 0, sizeof(conn->handshake.required_hash_algs)); @@ -170,7 +173,7 @@ int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn) case S2N_TLS13: { /* For TLS 1.2 and TLS 1.3, the cipher suite defines the PRF hash alg */ - s2n_hmac_algorithm prf_alg = conn->secure.cipher_suite->prf_alg; + s2n_hmac_algorithm prf_alg = conn->secure->cipher_suite->prf_alg; s2n_hash_algorithm hash_alg; POSIX_GUARD(s2n_hmac_hash_alg(prf_alg, &hash_alg)); POSIX_GUARD(s2n_handshake_require_hash(&conn->handshake, hash_alg)); diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c index a1f5c1215f..641bebe6ca 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c +++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c @@ -62,7 +62,7 @@ static int s2n_always_fail_recv(struct s2n_connection *conn) POSIX_BAIL(S2N_ERR_HANDSHAKE_UNREACHABLE); } -/* Client and Server handlers for each message type we support. +/* Client and Server handlers for each message type we support. * See http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-7 for the list of handshake message types */ static struct s2n_handshake_action state_machine[] = { @@ -811,6 +811,9 @@ static S2N_RESULT s2n_validate_ems_status(struct s2n_connection *conn) int s2n_conn_set_handshake_type(struct s2n_connection *conn) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + if (IS_TLS13_HANDSHAKE(conn)) { POSIX_GUARD_RESULT(s2n_conn_set_tls13_handshake_type(conn)); return S2N_SUCCESS; @@ -876,7 +879,7 @@ skip_cache_lookup: POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, FULL_HANDSHAKE)); bool is_ephemeral = false; - POSIX_GUARD_RESULT(s2n_kex_is_ephemeral(conn->secure.cipher_suite->key_exchange_alg, &is_ephemeral)); + POSIX_GUARD_RESULT(s2n_kex_is_ephemeral(conn->secure->cipher_suite->key_exchange_alg, &is_ephemeral)); if (is_ephemeral) { POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, TLS12_PERFECT_FORWARD_SECRECY)); } @@ -1452,7 +1455,13 @@ int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked) POSIX_ENSURE_REF(conn); POSIX_ENSURE(!conn->negotiate_in_use, S2N_ERR_REENTRANCY); conn->negotiate_in_use = true; + int result = s2n_negotiate_impl(conn, blocked); + + /* finish up sending and receiving */ + POSIX_GUARD_RESULT(s2n_connection_dynamic_free_in_buffer(conn)); + POSIX_GUARD_RESULT(s2n_connection_dynamic_free_out_buffer(conn)); + conn->negotiate_in_use = false; return result; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_key_update.c b/contrib/restricted/aws/s2n/tls/s2n_key_update.c index 6e8fbaca37..92d5509788 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_key_update.c +++ b/contrib/restricted/aws/s2n/tls/s2n_key_update.c @@ -54,12 +54,13 @@ int s2n_key_update_recv(struct s2n_connection *conn, struct s2n_stuffer *request int s2n_key_update_send(struct s2n_connection *conn, s2n_blocked_status *blocked) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); struct s2n_blob sequence_number = {0}; if (conn->mode == S2N_CLIENT) { - POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure.client_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN)); + POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure->client_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN)); } else { - POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure.server_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN)); + POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure->server_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN)); } POSIX_GUARD(s2n_check_record_limit(conn, &sequence_number)); @@ -113,8 +114,9 @@ int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequenc { POSIX_ENSURE_REF(conn); POSIX_ENSURE_REF(sequence_number); - POSIX_ENSURE_REF(conn->secure.cipher_suite); - POSIX_ENSURE_REF(conn->secure.cipher_suite->record_alg); + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); + POSIX_ENSURE_REF(conn->secure->cipher_suite->record_alg); /* * This is the sequence number that will be used for the next record, @@ -129,7 +131,7 @@ int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequenc * * This should always trigger on "==", but we use ">=" just in case. */ - if (next_seq_num >= conn->secure.cipher_suite->record_alg->encryption_limit) { + if (next_seq_num >= conn->secure->cipher_suite->record_alg->encryption_limit) { conn->key_update_pending = true; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_prf.c b/contrib/restricted/aws/s2n/tls/s2n_prf.c index 161f28eae1..043778d78a 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_prf.c +++ b/contrib/restricted/aws/s2n/tls/s2n_prf.c @@ -466,6 +466,7 @@ static int s2n_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct POSIX_ENSURE_REF(conn); POSIX_ENSURE_REF(secret); POSIX_ENSURE_REF(conn->prf_space); + POSIX_ENSURE_REF(conn->secure); /* seed_a is always required, seed_b is optional, if seed_c is provided seed_b must also be provided */ S2N_ERROR_IF(seed_a == NULL, S2N_ERR_PRF_INVALID_SEED); @@ -484,7 +485,7 @@ static int s2n_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct POSIX_GUARD(s2n_blob_zero(out)); if (conn->actual_protocol_version == S2N_TLS12) { - return s2n_p_hash(conn->prf_space, conn->secure.cipher_suite->prf_alg, secret, label, seed_a, seed_b, + return s2n_p_hash(conn->prf_space, conn->secure->cipher_suite->prf_alg, secret, label, seed_a, seed_b, seed_c, out); } @@ -524,6 +525,7 @@ int s2n_hybrid_prf_master_secret(struct s2n_connection *conn, struct s2n_blob *p int s2n_prf_calculate_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(conn), CLIENT_KEY); @@ -553,7 +555,7 @@ int s2n_prf_calculate_master_secret(struct s2n_connection *conn, struct s2n_blob POSIX_GUARD_RESULT(s2n_prf_get_digest_for_ems(conn, &client_key_blob, S2N_HASH_SHA1, &sha1_digest)); POSIX_GUARD_RESULT(s2n_tls_prf_extended_master_secret(conn, premaster_secret, &digest, &sha1_digest)); } else { - s2n_hmac_algorithm prf_alg = conn->secure.cipher_suite->prf_alg; + s2n_hmac_algorithm prf_alg = conn->secure->cipher_suite->prf_alg; s2n_hash_algorithm hash_alg = 0; POSIX_GUARD(s2n_hmac_hash_alg(prf_alg, &hash_alg)); POSIX_GUARD_RESULT(s2n_prf_get_digest_for_ems(conn, &client_key_blob, hash_alg, &digest)); @@ -675,6 +677,7 @@ static int s2n_sslv3_server_finished(struct s2n_connection *conn) int s2n_prf_client_finished(struct s2n_connection *conn) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); POSIX_ENSURE_REF(conn->handshake.hashes); struct s2n_blob master_secret, md5, sha; @@ -696,7 +699,7 @@ int s2n_prf_client_finished(struct s2n_connection *conn) master_secret.data = conn->secrets.tls12.master_secret; master_secret.size = sizeof(conn->secrets.tls12.master_secret); if (conn->actual_protocol_version == S2N_TLS12) { - switch (conn->secure.cipher_suite->prf_alg) { + switch (conn->secure->cipher_suite->prf_alg) { case S2N_HMAC_SHA256: POSIX_GUARD(s2n_hash_copy(&conn->handshake.hashes->hash_workspace, &conn->handshake.hashes->sha256)); POSIX_GUARD(s2n_hash_digest(&conn->handshake.hashes->hash_workspace, sha_digest, SHA256_DIGEST_LENGTH)); @@ -731,6 +734,7 @@ int s2n_prf_client_finished(struct s2n_connection *conn) int s2n_prf_server_finished(struct s2n_connection *conn) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); POSIX_ENSURE_REF(conn->handshake.hashes); struct s2n_blob master_secret, md5, sha; @@ -752,7 +756,7 @@ int s2n_prf_server_finished(struct s2n_connection *conn) master_secret.data = conn->secrets.tls12.master_secret; master_secret.size = sizeof(conn->secrets.tls12.master_secret); if (conn->actual_protocol_version == S2N_TLS12) { - switch (conn->secure.cipher_suite->prf_alg) { + switch (conn->secure->cipher_suite->prf_alg) { case S2N_HMAC_SHA256: POSIX_GUARD(s2n_hash_copy(&conn->handshake.hashes->hash_workspace, &conn->handshake.hashes->sha256)); POSIX_GUARD(s2n_hash_digest(&conn->handshake.hashes->hash_workspace, sha_digest, SHA256_DIGEST_LENGTH)); @@ -786,15 +790,18 @@ int s2n_prf_server_finished(struct s2n_connection *conn) static int s2n_prf_make_client_key(struct s2n_connection *conn, struct s2n_stuffer *key_material) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + struct s2n_blob client_key = {0}; - client_key.size = conn->secure.cipher_suite->record_alg->cipher->key_material_size; + client_key.size = conn->secure->cipher_suite->record_alg->cipher->key_material_size; client_key.data = s2n_stuffer_raw_read(key_material, client_key.size); POSIX_ENSURE_REF(client_key.data); if (conn->mode == S2N_CLIENT) { - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure.client_key, &client_key)); + POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure->client_key, &client_key)); } else { - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure.client_key, &client_key)); + POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure->client_key, &client_key)); } return 0; @@ -802,15 +809,18 @@ static int s2n_prf_make_client_key(struct s2n_connection *conn, struct s2n_stuff static int s2n_prf_make_server_key(struct s2n_connection *conn, struct s2n_stuffer *key_material) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + struct s2n_blob server_key = {0}; - server_key.size = conn->secure.cipher_suite->record_alg->cipher->key_material_size; + server_key.size = conn->secure->cipher_suite->record_alg->cipher->key_material_size; server_key.data = s2n_stuffer_raw_read(key_material, server_key.size); POSIX_ENSURE_REF(server_key.data); if (conn->mode == S2N_SERVER) { - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure.server_key, &server_key)); + POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure->server_key, &server_key)); } else { - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure.server_key, &server_key)); + POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure->server_key, &server_key)); } return 0; @@ -818,6 +828,9 @@ static int s2n_prf_make_server_key(struct s2n_connection *conn, struct s2n_stuff int s2n_prf_key_expansion(struct s2n_connection *conn) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + struct s2n_blob client_random = {.data = conn->handshake_params.client_random,.size = sizeof(conn->handshake_params.client_random) }; struct s2n_blob server_random = {.data = conn->handshake_params.server_random,.size = sizeof(conn->handshake_params.server_random) }; struct s2n_blob master_secret = {.data = conn->secrets.tls12.master_secret,.size = sizeof(conn->secrets.tls12.master_secret) }; @@ -834,29 +847,29 @@ int s2n_prf_key_expansion(struct s2n_connection *conn) POSIX_GUARD(s2n_stuffer_init(&key_material, &out)); POSIX_GUARD(s2n_stuffer_write(&key_material, &out)); - POSIX_ENSURE(conn->secure.cipher_suite->available, S2N_ERR_PRF_INVALID_ALGORITHM); - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->init(&conn->secure.client_key)); - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->init(&conn->secure.server_key)); + POSIX_ENSURE(conn->secure->cipher_suite->available, S2N_ERR_PRF_INVALID_ALGORITHM); + POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->client_key)); + POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->server_key)); /* Check that we have a valid MAC and key size */ uint8_t mac_size; - if (conn->secure.cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) { - mac_size = conn->secure.cipher_suite->record_alg->cipher->io.comp.mac_key_size; + if (conn->secure->cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) { + mac_size = conn->secure->cipher_suite->record_alg->cipher->io.comp.mac_key_size; } else { - POSIX_GUARD(s2n_hmac_digest_size(conn->secure.cipher_suite->record_alg->hmac_alg, &mac_size)); + POSIX_GUARD(s2n_hmac_digest_size(conn->secure->cipher_suite->record_alg->hmac_alg, &mac_size)); } /* Seed the client MAC */ uint8_t *client_mac_write_key = s2n_stuffer_raw_read(&key_material, mac_size); POSIX_ENSURE_REF(client_mac_write_key); - POSIX_GUARD(s2n_hmac_reset(&conn->secure.client_record_mac)); - POSIX_GUARD(s2n_hmac_init(&conn->secure.client_record_mac, conn->secure.cipher_suite->record_alg->hmac_alg, client_mac_write_key, mac_size)); + POSIX_GUARD(s2n_hmac_reset(&conn->secure->client_record_mac)); + POSIX_GUARD(s2n_hmac_init(&conn->secure->client_record_mac, conn->secure->cipher_suite->record_alg->hmac_alg, client_mac_write_key, mac_size)); /* Seed the server MAC */ uint8_t *server_mac_write_key = s2n_stuffer_raw_read(&key_material, mac_size); POSIX_ENSURE_REF(server_mac_write_key); - POSIX_GUARD(s2n_hmac_reset(&conn->secure.server_record_mac)); - POSIX_GUARD(s2n_hmac_init(&conn->secure.server_record_mac, conn->secure.cipher_suite->record_alg->hmac_alg, server_mac_write_key, mac_size)); + POSIX_GUARD(s2n_hmac_reset(&conn->secure->server_record_mac)); + POSIX_GUARD(s2n_hmac_init(&conn->secure->server_record_mac, conn->secure->cipher_suite->record_alg->hmac_alg, server_mac_write_key, mac_size)); /* Make the client key */ POSIX_GUARD(s2n_prf_make_client_key(conn, &key_material)); @@ -867,34 +880,34 @@ int s2n_prf_key_expansion(struct s2n_connection *conn) /* Composite CBC does MAC inside the cipher, pass it the MAC key. * Must happen after setting encryption/decryption keys. */ - if (conn->secure.cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) { - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->io.comp.set_mac_write_key(&conn->secure.server_key, server_mac_write_key, mac_size)); - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->io.comp.set_mac_write_key(&conn->secure.client_key, client_mac_write_key, mac_size)); + if (conn->secure->cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) { + POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->io.comp.set_mac_write_key(&conn->secure->server_key, server_mac_write_key, mac_size)); + POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->io.comp.set_mac_write_key(&conn->secure->client_key, client_mac_write_key, mac_size)); } /* TLS >= 1.1 has no implicit IVs for non AEAD ciphers */ - if (conn->actual_protocol_version > S2N_TLS10 && conn->secure.cipher_suite->record_alg->cipher->type != S2N_AEAD) { + if (conn->actual_protocol_version > S2N_TLS10 && conn->secure->cipher_suite->record_alg->cipher->type != S2N_AEAD) { return 0; } uint32_t implicit_iv_size = 0; - switch (conn->secure.cipher_suite->record_alg->cipher->type) { + switch (conn->secure->cipher_suite->record_alg->cipher->type) { case S2N_AEAD: - implicit_iv_size = conn->secure.cipher_suite->record_alg->cipher->io.aead.fixed_iv_size; + implicit_iv_size = conn->secure->cipher_suite->record_alg->cipher->io.aead.fixed_iv_size; break; case S2N_CBC: - implicit_iv_size = conn->secure.cipher_suite->record_alg->cipher->io.cbc.block_size; + implicit_iv_size = conn->secure->cipher_suite->record_alg->cipher->io.cbc.block_size; break; case S2N_COMPOSITE: - implicit_iv_size = conn->secure.cipher_suite->record_alg->cipher->io.comp.block_size; + implicit_iv_size = conn->secure->cipher_suite->record_alg->cipher->io.comp.block_size; break; /* No-op for stream ciphers */ default: break; } - struct s2n_blob client_implicit_iv = {.data = conn->secure.client_implicit_iv,.size = implicit_iv_size }; - struct s2n_blob server_implicit_iv = {.data = conn->secure.server_implicit_iv,.size = implicit_iv_size }; + struct s2n_blob client_implicit_iv = {.data = conn->secure->client_implicit_iv,.size = implicit_iv_size }; + struct s2n_blob server_implicit_iv = {.data = conn->secure->server_implicit_iv,.size = implicit_iv_size }; POSIX_GUARD(s2n_stuffer_read(&key_material, &client_implicit_iv)); POSIX_GUARD(s2n_stuffer_read(&key_material, &server_implicit_iv)); diff --git a/contrib/restricted/aws/s2n/tls/s2n_psk.c b/contrib/restricted/aws/s2n/tls/s2n_psk.c index 7a42ab28dc..b33071dca5 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_psk.c +++ b/contrib/restricted/aws/s2n/tls/s2n_psk.c @@ -478,6 +478,7 @@ static S2N_RESULT s2n_psk_write_binder_list(struct s2n_connection *conn, const s { RESULT_ENSURE_REF(conn); RESULT_ENSURE_REF(partial_client_hello); + RESULT_ENSURE_REF(conn->secure); struct s2n_psk_parameters *psk_params = &conn->psk_params; struct s2n_array *psk_list = &psk_params->psk_list; @@ -504,7 +505,7 @@ static S2N_RESULT s2n_psk_write_binder_list(struct s2n_connection *conn, const s *# 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) { + if (s2n_is_hello_retry_handshake(conn) && conn->secure->cipher_suite->prf_alg != psk->hmac_alg) { continue; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_read.c b/contrib/restricted/aws/s2n/tls/s2n_record_read.c index 8a1bf8836f..42e8bd4603 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_record_read.c +++ b/contrib/restricted/aws/s2n/tls/s2n_record_read.c @@ -121,8 +121,9 @@ int s2n_record_parse(struct s2n_connection *conn) struct s2n_crypto_parameters *current_client_crypto = conn->client; struct s2n_crypto_parameters *current_server_crypto = conn->server; if (s2n_is_tls13_plaintext_content(conn, content_type)) { - conn->client = &conn->initial; - conn->server = &conn->initial; + POSIX_ENSURE_REF(conn->initial); + conn->client = conn->initial; + conn->server = conn->initial; } const struct s2n_cipher_suite *cipher_suite = conn->client->cipher_suite; diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_write.c b/contrib/restricted/aws/s2n/tls/s2n_record_write.c index 323a3ce944..c1ac2b9e78 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_record_write.c +++ b/contrib/restricted/aws/s2n/tls/s2n_record_write.c @@ -238,8 +238,9 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s struct s2n_crypto_parameters *current_client_crypto = conn->client; struct s2n_crypto_parameters *current_server_crypto = conn->server; if (conn->actual_protocol_version == S2N_TLS13 && content_type == TLS_CHANGE_CIPHER_SPEC) { - conn->client = &conn->initial; - conn->server = &conn->initial; + POSIX_ENSURE_REF(conn->initial); + conn->client = conn->initial; + conn->server = conn->initial; } uint8_t *sequence_number = conn->server->server_sequence_number; diff --git a/contrib/restricted/aws/s2n/tls/s2n_recv.c b/contrib/restricted/aws/s2n/tls/s2n_recv.c index bbf48b1ff8..ddd3fa8062 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_recv.c +++ b/contrib/restricted/aws/s2n/tls/s2n_recv.c @@ -206,8 +206,13 @@ ssize_t s2n_recv(struct s2n_connection * conn, void *buf, ssize_t size, s2n_bloc { POSIX_ENSURE(!conn->recv_in_use, S2N_ERR_REENTRANCY); conn->recv_in_use = true; + ssize_t result = s2n_recv_impl(conn, buf, size, blocked); POSIX_GUARD_RESULT(s2n_early_data_record_bytes(conn, result)); + + /* finish the recv call */ + POSIX_GUARD_RESULT(s2n_connection_dynamic_free_in_buffer(conn)); + conn->recv_in_use = false; return result; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_resume.c b/contrib/restricted/aws/s2n/tls/s2n_resume.c index 952ae9cbde..6f0bd07858 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_resume.c +++ b/contrib/restricted/aws/s2n/tls/s2n_resume.c @@ -46,8 +46,9 @@ int s2n_allowed_to_cache_connection(struct s2n_connection *conn) static int s2n_tls12_serialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *to) { - POSIX_ENSURE_REF(conn); POSIX_ENSURE_REF(to); + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); uint64_t now; @@ -59,7 +60,7 @@ static int s2n_tls12_serialize_resumption_state(struct s2n_connection *conn, str /* Write the entry */ POSIX_GUARD(s2n_stuffer_write_uint8(to, S2N_SERIALIZED_FORMAT_TLS12_V3)); POSIX_GUARD(s2n_stuffer_write_uint8(to, conn->actual_protocol_version)); - POSIX_GUARD(s2n_stuffer_write_bytes(to, conn->secure.cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN)); + POSIX_GUARD(s2n_stuffer_write_bytes(to, conn->secure->cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN)); POSIX_GUARD(s2n_stuffer_write_uint64(to, now)); POSIX_GUARD(s2n_stuffer_write_bytes(to, conn->secrets.tls12.master_secret, S2N_TLS_SECRET_LEN)); POSIX_GUARD(s2n_stuffer_write_uint8(to, conn->ems_negotiated)); @@ -90,8 +91,9 @@ static S2N_RESULT s2n_tls13_serialize_keying_material_expiration(struct s2n_conn static S2N_RESULT s2n_tls13_serialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *out) { - RESULT_ENSURE_REF(conn); RESULT_ENSURE_REF(out); + RESULT_ENSURE_REF(conn); + RESULT_ENSURE_REF(conn->secure); uint64_t current_time = 0; struct s2n_ticket_fields *ticket_fields = &conn->tls13_ticket_fields; @@ -101,7 +103,7 @@ static S2N_RESULT s2n_tls13_serialize_resumption_state(struct s2n_connection *co RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, S2N_SERIALIZED_FORMAT_TLS13_V1)); RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, conn->actual_protocol_version)); - RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(out, conn->secure.cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN)); + RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(out, conn->secure->cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN)); RESULT_GUARD_POSIX(s2n_stuffer_write_uint64(out, current_time)); RESULT_GUARD_POSIX(s2n_stuffer_write_uint32(out, ticket_fields->ticket_age_add)); RESULT_ENSURE_LTE(ticket_fields->session_secret.size, UINT8_MAX); @@ -135,6 +137,9 @@ static S2N_RESULT s2n_serialize_resumption_state(struct s2n_connection *conn, st static int s2n_tls12_deserialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *from) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + uint8_t protocol_version = 0; uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN] = { 0 }; @@ -144,7 +149,7 @@ static int s2n_tls12_deserialize_resumption_state(struct s2n_connection *conn, s S2N_ERROR_IF(protocol_version != conn->actual_protocol_version, S2N_ERR_INVALID_SERIALIZED_SESSION_STATE); POSIX_GUARD(s2n_stuffer_read_bytes(from, cipher_suite, S2N_TLS_CIPHER_SUITE_LEN)); - S2N_ERROR_IF(memcmp(conn->secure.cipher_suite->iana_value, cipher_suite, S2N_TLS_CIPHER_SUITE_LEN), S2N_ERR_INVALID_SERIALIZED_SESSION_STATE); + S2N_ERROR_IF(memcmp(conn->secure->cipher_suite->iana_value, cipher_suite, S2N_TLS_CIPHER_SUITE_LEN), S2N_ERR_INVALID_SERIALIZED_SESSION_STATE); uint64_t now; POSIX_GUARD(conn->config->wall_clock(conn->config->sys_clock_ctx, &now)); @@ -497,6 +502,7 @@ int s2n_connection_get_session_ticket_lifetime_hint(struct s2n_connection *conn) S2N_RESULT s2n_connection_get_session_state_size(struct s2n_connection *conn, size_t *state_size) { RESULT_ENSURE_REF(conn); + RESULT_ENSURE_REF(conn->secure); RESULT_ENSURE_REF(state_size); if (conn->actual_protocol_version < S2N_TLS13) { @@ -507,8 +513,8 @@ S2N_RESULT s2n_connection_get_session_state_size(struct s2n_connection *conn, si *state_size = S2N_TLS13_FIXED_STATE_SIZE; uint8_t secret_size = 0; - RESULT_ENSURE_REF(conn->secure.cipher_suite); - RESULT_GUARD_POSIX(s2n_hmac_digest_size(conn->secure.cipher_suite->prf_alg, &secret_size)); + RESULT_ENSURE_REF(conn->secure->cipher_suite); + RESULT_GUARD_POSIX(s2n_hmac_digest_size(conn->secure->cipher_suite->prf_alg, &secret_size)); *state_size += secret_size; uint32_t server_max_early_data = 0; diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c index 8dd9496de7..9072932670 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c +++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c @@ -682,6 +682,19 @@ const struct s2n_security_policy security_policy_20210816_gcm = { .ecc_preferences = &s2n_ecc_preferences_20210816, }; +/* + * This security policy is derived from the following specification: + * https://datatracker.ietf.org/doc/html/rfc9151 + */ +const struct s2n_security_policy security_policy_rfc9151 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_rfc9151, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_rfc9151, + .certificate_signature_preferences = &s2n_certificate_signature_preferences_rfc9151, + .ecc_preferences = &s2n_ecc_preferences_20210816, +}; + const struct s2n_security_policy security_policy_test_all = { .minimum_protocol_version = S2N_SSLv3, .cipher_preferences = &cipher_preferences_test_all, @@ -834,6 +847,7 @@ struct s2n_security_policy_selection security_policy_selection[] = { { .version="20201021", .security_policy=&security_policy_20201021, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="20210816", .security_policy=&security_policy_20210816, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="20210816_GCM", .security_policy=&security_policy_20210816_gcm, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="rfc9151", .security_policy=&security_policy_rfc9151, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="test_all", .security_policy=&security_policy_test_all, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="test_all_fips", .security_policy=&security_policy_test_all_fips, .ecc_extension_required=0, .pq_kem_extension_required=0 }, { .version="test_all_ecdsa", .security_policy=&security_policy_test_all_ecdsa, .ecc_extension_required=0, .pq_kem_extension_required=0 }, @@ -1028,7 +1042,8 @@ int s2n_connection_is_valid_for_cipher_preferences(struct s2n_connection *conn, { POSIX_ENSURE_REF(conn); POSIX_ENSURE_REF(version); - POSIX_ENSURE_REF(conn->secure.cipher_suite); + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); const struct s2n_security_policy *security_policy = NULL; POSIX_GUARD(s2n_find_security_policy_from_version(version, &security_policy)); @@ -1039,7 +1054,7 @@ int s2n_connection_is_valid_for_cipher_preferences(struct s2n_connection *conn, return 0; } - struct s2n_cipher_suite *cipher = conn->secure.cipher_suite; + struct s2n_cipher_suite *cipher = conn->secure->cipher_suite; POSIX_ENSURE_REF(cipher); for (int i = 0; i < security_policy->cipher_preferences->count; ++i) { if (0 == memcmp(security_policy->cipher_preferences->suites[i]->iana_value, cipher->iana_value, S2N_TLS_CIPHER_SUITE_LEN)) { @@ -1084,7 +1099,10 @@ S2N_RESULT s2n_validate_certificate_signature_preferences(const struct s2n_signa } } - /* The Openssl function used to parse signatures off certificates does not differentiate between any rsa pss + /* + * https://github.com/aws/s2n-tls/issues/3435 + * + * The Openssl function used to parse signatures off certificates does not differentiate between any rsa pss * signature schemes. Therefore a security policy with a certificate signatures preference list must include * all rsa_pss signature schemes. */ RESULT_ENSURE(rsa_pss_scheme_count == NUM_RSA_PSS_SCHEMES || rsa_pss_scheme_count == 0, S2N_ERR_INVALID_SECURITY_POLICY); diff --git a/contrib/restricted/aws/s2n/tls/s2n_send.c b/contrib/restricted/aws/s2n/tls/s2n_send.c index cc7188eb73..6f31935ceb 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_send.c +++ b/contrib/restricted/aws/s2n/tls/s2n_send.c @@ -209,7 +209,7 @@ ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iov } POSIX_GUARD(s2n_post_handshake_send(conn, blocked)); - + /* Write and encrypt the record */ int written_to_record = s2n_record_writev(conn, TLS_APPLICATION_DATA, bufs, count, conn->current_user_data_consumed + offs, to_write); @@ -247,8 +247,12 @@ ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *b { POSIX_ENSURE(!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); POSIX_GUARD_RESULT(s2n_early_data_record_bytes(conn, result)); + + POSIX_GUARD_RESULT(s2n_connection_dynamic_free_out_buffer(conn)); + conn->send_in_use = false; return result; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_finished.c b/contrib/restricted/aws/s2n/tls/s2n_server_finished.c index d7e57a222b..05c553799f 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_finished.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_finished.c @@ -46,6 +46,9 @@ int s2n_server_finished_recv(struct s2n_connection *conn) int s2n_server_finished_send(struct s2n_connection *conn) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + uint8_t *our_version; int length = S2N_TLS_FINISHED_LEN; @@ -61,11 +64,11 @@ int s2n_server_finished_send(struct s2n_connection *conn) POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, our_version, length)); /* Zero the sequence number */ - struct s2n_blob seq = {.data = conn->secure.server_sequence_number,.size = S2N_TLS_SEQUENCE_NUM_LEN }; + struct s2n_blob seq = {.data = conn->secure->server_sequence_number,.size = S2N_TLS_SEQUENCE_NUM_LEN }; POSIX_GUARD(s2n_blob_zero(&seq)); /* Update the secure state to active, and point the client at the active state */ - conn->server = &conn->secure; + conn->server = conn->secure; if (s2n_connection_is_session_resumed(conn)) { POSIX_GUARD(s2n_prf_key_expansion(conn)); diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_hello.c b/contrib/restricted/aws/s2n/tls/s2n_server_hello.c index efe4c08114..4962dfb3b2 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_hello.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_hello.c @@ -98,6 +98,7 @@ static int s2n_server_add_downgrade_mechanism(struct s2n_connection *conn) { static int s2n_server_hello_parse(struct s2n_connection *conn) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); struct s2n_stuffer *in = &conn->handshake.io; uint8_t compression_method; @@ -232,7 +233,7 @@ static int s2n_server_hello_parse(struct s2n_connection *conn) if (session_ids_match) { /* check if the resumed session state is valid */ S2N_ERROR_IF(conn->actual_protocol_version != actual_protocol_version, S2N_ERR_BAD_MESSAGE); - S2N_ERROR_IF(memcmp(conn->secure.cipher_suite->iana_value, cipher_suite_wire, S2N_TLS_CIPHER_SUITE_LEN) != 0, S2N_ERR_BAD_MESSAGE); + S2N_ERROR_IF(memcmp(conn->secure->cipher_suite->iana_value, cipher_suite_wire, S2N_TLS_CIPHER_SUITE_LEN) != 0, S2N_ERR_BAD_MESSAGE); /* Session is resumed */ conn->client_session_resumed = 1; @@ -296,6 +297,7 @@ int s2n_server_hello_recv(struct s2n_connection *conn) int s2n_server_hello_write_message(struct s2n_connection *conn) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); /* The actual_protocol_version is set while processing the CLIENT_HELLO message, so * it could be S2N_TLS13. SERVER_HELLO should always respond with the legacy version. @@ -309,7 +311,7 @@ int s2n_server_hello_write_message(struct s2n_connection *conn) POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN)); POSIX_GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, conn->session_id_len)); POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->session_id, conn->session_id_len)); - POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->secure.cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN)); + POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->secure->cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN)); POSIX_GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, S2N_TLS_COMPRESSION_METHOD_NULL)); return 0; 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 0d3f05b2c9..dc87d4184e 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c @@ -39,12 +39,13 @@ static int s2n_server_key_send_write_signature(struct s2n_connection *conn, stru int s2n_server_key_recv(struct s2n_connection *conn) { POSIX_ENSURE_REF(conn); - POSIX_ENSURE_REF(conn->secure.cipher_suite); - POSIX_ENSURE_REF(conn->secure.cipher_suite->key_exchange_alg); + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); + POSIX_ENSURE_REF(conn->secure->cipher_suite->key_exchange_alg); POSIX_ENSURE_REF(conn->handshake.hashes); struct s2n_hash_state *signature_hash = &conn->handshake.hashes->hash_workspace; - const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg; + const struct s2n_kex *key_exchange = conn->secure->cipher_suite->key_exchange_alg; struct s2n_stuffer *in = &conn->handshake.io; struct s2n_blob data_to_verify = {0}; @@ -183,6 +184,9 @@ int s2n_kem_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_bl int s2n_kem_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data) { + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + struct s2n_kem_raw_server_params *kem_data = &raw_server_data->kem_data; /* Check that the server's requested kem is supported by the client */ @@ -190,7 +194,7 @@ int s2n_kem_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_k POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences)); POSIX_ENSURE_REF(kem_preferences); - const struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite; + const struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite; const struct s2n_kem *match = NULL; S2N_ERROR_IF(s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, &kem_data->kem_name, kem_preferences->kems, kem_preferences->kem_count, &match) != 0, S2N_ERR_KEM_UNSUPPORTED_PARAMS); @@ -204,8 +208,9 @@ int s2n_kem_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_k int s2n_hybrid_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *total_data_to_verify, struct s2n_kex_raw_server_data *raw_server_data) { POSIX_ENSURE_REF(conn); - POSIX_ENSURE_REF(conn->secure.cipher_suite); - const struct s2n_kex *kex = conn->secure.cipher_suite->key_exchange_alg; + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); + const struct s2n_kex *kex = conn->secure->cipher_suite->key_exchange_alg; const struct s2n_kex *hybrid_kex_0 = kex->hybrid[0]; const struct s2n_kex *hybrid_kex_1 = kex->hybrid[1]; @@ -226,8 +231,9 @@ int s2n_hybrid_server_key_recv_read_data(struct s2n_connection *conn, struct s2n int s2n_hybrid_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data) { POSIX_ENSURE_REF(conn); - POSIX_ENSURE_REF(conn->secure.cipher_suite); - const struct s2n_kex *kex = conn->secure.cipher_suite->key_exchange_alg; + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); + const struct s2n_kex *kex = conn->secure->cipher_suite->key_exchange_alg; const struct s2n_kex *hybrid_kex_0 = kex->hybrid[0]; const struct s2n_kex *hybrid_kex_1 = kex->hybrid[1]; @@ -244,7 +250,7 @@ int s2n_server_key_send(struct s2n_connection *conn) S2N_ASYNC_PKEY_GUARD(conn); struct s2n_hash_state *signature_hash = &conn->handshake.hashes->hash_workspace; - const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg; + const struct s2n_kex *key_exchange = conn->secure->cipher_suite->key_exchange_alg; struct s2n_stuffer *out = &conn->handshake.io; struct s2n_blob data_to_sign = {0}; @@ -318,8 +324,9 @@ int s2n_kem_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_t int s2n_hybrid_server_key_send(struct s2n_connection *conn, struct s2n_blob *total_data_to_sign) { POSIX_ENSURE_REF(conn); - POSIX_ENSURE_REF(conn->secure.cipher_suite); - const struct s2n_kex *kex = conn->secure.cipher_suite->key_exchange_alg; + POSIX_ENSURE_REF(conn->secure); + POSIX_ENSURE_REF(conn->secure->cipher_suite); + const struct s2n_kex *kex = conn->secure->cipher_suite->key_exchange_alg; const struct s2n_kex *hybrid_kex_0 = kex->hybrid[0]; const struct s2n_kex *hybrid_kex_1 = kex->hybrid[1]; diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c index f7775ccee8..3158c0df92 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c +++ b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c @@ -75,11 +75,12 @@ static int s2n_choose_sig_scheme(struct s2n_connection *conn, struct s2n_sig_sch struct s2n_signature_scheme *chosen_scheme_out) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); const struct s2n_signature_preferences *signature_preferences = NULL; POSIX_GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences)); POSIX_ENSURE_REF(signature_preferences); - struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite; + struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite; POSIX_ENSURE_REF(cipher_suite); for (size_t i = 0; i < signature_preferences->count; i++) { @@ -107,11 +108,13 @@ static int s2n_choose_sig_scheme(struct s2n_connection *conn, struct s2n_sig_sch int s2n_tls13_default_sig_scheme(struct s2n_connection *conn, struct s2n_signature_scheme *chosen_scheme_out) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); + const struct s2n_signature_preferences *signature_preferences = NULL; POSIX_GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences)); POSIX_ENSURE_REF(signature_preferences); - struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite; + struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite; POSIX_ENSURE_REF(cipher_suite); for (size_t i = 0; i < signature_preferences->count; i++) { @@ -171,14 +174,15 @@ int s2n_get_and_validate_negotiated_signature_scheme(struct s2n_connection *conn int s2n_choose_default_sig_scheme(struct s2n_connection *conn, struct s2n_signature_scheme *sig_scheme_out, s2n_mode signer) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); POSIX_ENSURE_REF(sig_scheme_out); s2n_authentication_method auth_method = 0; if (signer == S2N_CLIENT) { POSIX_GUARD(s2n_get_auth_method_for_cert_type(conn->handshake_params.client_cert_pkey_type, &auth_method)); } else { - POSIX_ENSURE_REF(conn->secure.cipher_suite); - auth_method = conn->secure.cipher_suite->auth_method; + POSIX_ENSURE_REF(conn->secure->cipher_suite); + auth_method = conn->secure->cipher_suite->auth_method; } /* Default our signature digest algorithms. diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c index 2ccc0fd651..e986013be5 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c +++ b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c @@ -377,3 +377,52 @@ const struct s2n_signature_preferences s2n_signature_preferences_20210816 = { .count = s2n_array_len(s2n_sig_scheme_pref_list_20210816), .signature_schemes = s2n_sig_scheme_pref_list_20210816 }; + +const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_rfc9151[] = { + /* ECDSA - TLS 1.3 */ + &s2n_ecdsa_secp384r1_sha384, + + /* RSA PSS - TLS 1.3 */ + &s2n_rsa_pss_pss_sha384, + + /* ECDSA - TLS 1.2 */ + &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */ + + /* RSA */ + &s2n_rsa_pss_rsae_sha384, + + &s2n_rsa_pkcs1_sha384, +}; + +const struct s2n_signature_scheme* const s2n_cert_sig_scheme_pref_list_rfc9151[] = { + /* ECDSA - TLS 1.3 */ + &s2n_ecdsa_secp384r1_sha384, + + /* RSA PSS + * https://github.com/aws/s2n-tls/issues/3435 + * + * The Openssl function used to parse signatures off certificates does not differentiate + * between any rsa pss signature schemes. Therefore a security policy with a certificate + * signatures preference list must include all rsa_pss signature schemes. + * + * Since only sha384 is allowed by rfc9151, this certificate signing policy does not + * support rsa_pss. + */ + + /* ECDSA - TLS 1.2 */ + &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */ + + /* RSA */ + &s2n_rsa_pkcs1_sha384, +}; + + +const struct s2n_signature_preferences s2n_signature_preferences_rfc9151 = { + .count = s2n_array_len(s2n_sig_scheme_pref_list_rfc9151), + .signature_schemes = s2n_sig_scheme_pref_list_rfc9151 +}; + +const struct s2n_signature_preferences s2n_certificate_signature_preferences_rfc9151 = { + .count = s2n_array_len(s2n_cert_sig_scheme_pref_list_rfc9151), + .signature_schemes = s2n_cert_sig_scheme_pref_list_rfc9151 +}; diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h index d8eee975ab..a3259804fe 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h +++ b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h @@ -77,6 +77,8 @@ extern const struct s2n_signature_preferences s2n_signature_preferences_20140601 extern const struct s2n_signature_preferences s2n_signature_preferences_20200207; extern const struct s2n_signature_preferences s2n_signature_preferences_20201021; extern const struct s2n_signature_preferences s2n_signature_preferences_20210816; +extern const struct s2n_signature_preferences s2n_signature_preferences_rfc9151; +extern const struct s2n_signature_preferences s2n_certificate_signature_preferences_rfc9151; extern const struct s2n_signature_preferences s2n_signature_preferences_default_fips; extern const struct s2n_signature_preferences s2n_signature_preferences_null; diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c index e5b2bd3202..91729d3a1e 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c +++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c @@ -21,11 +21,12 @@ static int s2n_zero_sequence_number(struct s2n_connection *conn, s2n_mode mode) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); struct s2n_blob sequence_number; if (mode == S2N_CLIENT) { - POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure.client_sequence_number, sizeof(conn->secure.client_sequence_number))); + POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure->client_sequence_number, sizeof(conn->secure->client_sequence_number))); } else { - POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure.server_sequence_number, sizeof(conn->secure.server_sequence_number))); + POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure->server_sequence_number, sizeof(conn->secure->server_sequence_number))); } POSIX_GUARD(s2n_blob_zero(&sequence_number)); return S2N_SUCCESS; @@ -43,7 +44,7 @@ int s2n_tls13_mac_verify(struct s2n_tls13_keys *keys, struct s2n_blob *finished_ int s2n_tls13_keys_from_conn(struct s2n_tls13_keys *keys, struct s2n_connection *conn) { - POSIX_GUARD(s2n_tls13_keys_init(keys, conn->secure.cipher_suite->prf_alg)); + POSIX_GUARD(s2n_tls13_keys_init(keys, conn->secure->cipher_suite->prf_alg)); return S2N_SUCCESS; } @@ -152,6 +153,7 @@ int s2n_tls13_compute_shared_secret(struct s2n_connection *conn, struct s2n_blob int s2n_update_application_traffic_keys(struct s2n_connection *conn, s2n_mode mode, keyupdate_status status) { POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->secure); /* get tls13 key context */ s2n_tls13_connection_keys(keys, conn); @@ -161,13 +163,13 @@ int s2n_update_application_traffic_keys(struct s2n_connection *conn, s2n_mode mo struct s2n_blob app_iv; if (mode == S2N_CLIENT) { - old_key = &conn->secure.client_key; + old_key = &conn->secure->client_key; POSIX_GUARD(s2n_blob_init(&old_app_secret, conn->secrets.tls13.client_app_secret, keys.size)); - POSIX_GUARD(s2n_blob_init(&app_iv, conn->secure.client_implicit_iv, S2N_TLS13_FIXED_IV_LEN)); + POSIX_GUARD(s2n_blob_init(&app_iv, conn->secure->client_implicit_iv, S2N_TLS13_FIXED_IV_LEN)); } else { - old_key = &conn->secure.server_key; + old_key = &conn->secure->server_key; POSIX_GUARD(s2n_blob_init(&old_app_secret, conn->secrets.tls13.server_app_secret, keys.size)); - POSIX_GUARD(s2n_blob_init(&app_iv, conn->secure.server_implicit_iv, S2N_TLS13_FIXED_IV_LEN)); + POSIX_GUARD(s2n_blob_init(&app_iv, conn->secure->server_implicit_iv, S2N_TLS13_FIXED_IV_LEN)); } /* Produce new application secret */ @@ -176,14 +178,14 @@ int s2n_update_application_traffic_keys(struct s2n_connection *conn, s2n_mode mo /* Derives next generation of traffic secret */ POSIX_GUARD(s2n_tls13_update_application_traffic_secret(&keys, &old_app_secret, &app_secret_update)); - s2n_tls13_key_blob(app_key, conn->secure.cipher_suite->record_alg->cipher->key_material_size); + s2n_tls13_key_blob(app_key, conn->secure->cipher_suite->record_alg->cipher->key_material_size); /* Derives next generation of traffic key */ POSIX_GUARD(s2n_tls13_derive_traffic_keys(&keys, &app_secret_update, &app_key, &app_iv)); if (status == RECEIVING) { - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(old_key, &app_key)); + POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(old_key, &app_key)); } else { - POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(old_key, &app_key)); + POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->set_encryption_key(old_key, &app_key)); } /* According to https://tools.ietf.org/html/rfc8446#section-5.3: diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.c index 16fd78c042..dbf7608ffe 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.c +++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.c @@ -34,13 +34,14 @@ static const struct s2n_blob s2n_zero_length_context = { 0 }; static S2N_RESULT s2n_zero_sequence_number(struct s2n_connection *conn, s2n_mode mode) { RESULT_ENSURE_REF(conn); + RESULT_ENSURE_REF(conn->secure); struct s2n_blob sequence_number; if (mode == S2N_CLIENT) { RESULT_GUARD_POSIX(s2n_blob_init(&sequence_number, - conn->secure.client_sequence_number, sizeof(conn->secure.client_sequence_number))); + conn->secure->client_sequence_number, sizeof(conn->secure->client_sequence_number))); } else { RESULT_GUARD_POSIX(s2n_blob_init(&sequence_number, - conn->secure.server_sequence_number, sizeof(conn->secure.server_sequence_number))); + conn->secure->server_sequence_number, sizeof(conn->secure->server_sequence_number))); } RESULT_GUARD_POSIX(s2n_blob_zero(&sequence_number)); return S2N_RESULT_OK; @@ -49,22 +50,23 @@ static S2N_RESULT s2n_zero_sequence_number(struct s2n_connection *conn, s2n_mode static S2N_RESULT s2n_set_key(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type, s2n_mode mode) { RESULT_ENSURE_REF(conn); - RESULT_ENSURE_REF(conn->secure.cipher_suite); - const struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite; - RESULT_ENSURE_REF(conn->secure.cipher_suite->record_alg); - RESULT_ENSURE_REF(conn->secure.cipher_suite->record_alg->cipher); - const struct s2n_cipher *cipher = conn->secure.cipher_suite->record_alg->cipher; + RESULT_ENSURE_REF(conn->secure); + RESULT_ENSURE_REF(conn->secure->cipher_suite); + const struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite; + RESULT_ENSURE_REF(conn->secure->cipher_suite->record_alg); + RESULT_ENSURE_REF(conn->secure->cipher_suite->record_alg->cipher); + const struct s2n_cipher *cipher = conn->secure->cipher_suite->record_alg->cipher; uint8_t *implicit_iv_data = NULL; struct s2n_session_key *session_key = NULL; if (mode == S2N_CLIENT) { - implicit_iv_data = conn->secure.client_implicit_iv; - session_key = &conn->secure.client_key; - conn->client = &conn->secure; + implicit_iv_data = conn->secure->client_implicit_iv; + session_key = &conn->secure->client_key; + conn->client = conn->secure; } else { - implicit_iv_data = conn->secure.server_implicit_iv; - session_key = &conn->secure.server_key; - conn->server = &conn->secure; + implicit_iv_data = conn->secure->server_implicit_iv; + session_key = &conn->secure->server_key; + conn->server = conn->secure; } /** @@ -321,8 +323,9 @@ S2N_RESULT s2n_tls13_key_schedule_update(struct s2n_connection *conn) S2N_RESULT s2n_tls13_key_schedule_reset(struct s2n_connection *conn) { RESULT_ENSURE_REF(conn); - conn->client = &conn->initial; - conn->server = &conn->initial; + RESULT_ENSURE_REF(conn->initial); + conn->client = conn->initial; + conn->server = conn->initial; conn->secrets.tls13.extract_secret_type = S2N_NONE_SECRET; return S2N_RESULT_OK; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c index 9bbe24ec84..103590c122 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c +++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c @@ -22,7 +22,7 @@ #define S2N_MAX_HASHLEN SHA384_DIGEST_LENGTH -#define CONN_HMAC_ALG(conn) ((conn)->secure.cipher_suite->prf_alg) +#define CONN_HMAC_ALG(conn) ((conn)->secure->cipher_suite->prf_alg) #define CONN_SECRETS(conn) ((conn)->secrets.tls13) #define CONN_HASHES(conn) ((conn)->handshake.hashes) @@ -103,11 +103,12 @@ S2N_RESULT s2n_tls13_empty_transcripts_init() static S2N_RESULT s2n_calculate_transcript_digest(struct s2n_connection *conn) { RESULT_ENSURE_REF(conn); + RESULT_ENSURE_REF(conn->secure); + RESULT_ENSURE_REF(conn->secure->cipher_suite); RESULT_ENSURE_REF(conn->handshake.hashes); s2n_hash_algorithm hash_algorithm = S2N_HASH_NONE; - RESULT_ENSURE_REF(conn->secure.cipher_suite); - RESULT_GUARD_POSIX(s2n_hmac_hash_alg(conn->secure.cipher_suite->prf_alg, &hash_algorithm)); + RESULT_GUARD_POSIX(s2n_hmac_hash_alg(conn->secure->cipher_suite->prf_alg, &hash_algorithm)); uint8_t digest_size = 0; RESULT_GUARD_POSIX(s2n_hash_digest_size(hash_algorithm, &digest_size)); @@ -494,7 +495,8 @@ static s2n_result (*extract_methods[])(struct s2n_connection *conn) = { S2N_RESULT s2n_tls13_extract_secret(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type) { RESULT_ENSURE_REF(conn); - RESULT_ENSURE_REF(conn->secure.cipher_suite); + RESULT_ENSURE_REF(conn->secure); + RESULT_ENSURE_REF(conn->secure->cipher_suite); RESULT_ENSURE_REF(conn->handshake.hashes); RESULT_ENSURE_NE(secret_type, S2N_NONE_SECRET); @@ -522,7 +524,8 @@ S2N_RESULT s2n_tls13_derive_secret(struct s2n_connection *conn, s2n_extract_secr { RESULT_ENSURE_REF(conn); RESULT_ENSURE_REF(secret); - RESULT_ENSURE_REF(conn->secure.cipher_suite); + RESULT_ENSURE_REF(conn->secure); + RESULT_ENSURE_REF(conn->secure->cipher_suite); RESULT_ENSURE_REF(conn->handshake.hashes); RESULT_ENSURE_NE(secret_type, S2N_NONE_SECRET); @@ -567,7 +570,8 @@ S2N_RESULT s2n_tls13_secrets_update(struct s2n_connection *conn) if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { return S2N_RESULT_OK; } - RESULT_ENSURE_REF(conn->secure.cipher_suite); + RESULT_ENSURE_REF(conn->secure); + RESULT_ENSURE_REF(conn->secure->cipher_suite); message_type_t message_type = s2n_conn_get_current_message_type(conn); switch(message_type) { diff --git a/contrib/restricted/aws/s2n/utils/s2n_init.c b/contrib/restricted/aws/s2n/utils/s2n_init.c index 2b3d78fefd..1195b3b450 100644 --- a/contrib/restricted/aws/s2n/utils/s2n_init.c +++ b/contrib/restricted/aws/s2n/utils/s2n_init.c @@ -58,6 +58,7 @@ int s2n_init(void) POSIX_GUARD(s2n_mem_init()); /* Must run before any init method that calls libcrypto methods. */ POSIX_GUARD_RESULT(s2n_locking_init()); + POSIX_GUARD_RESULT(s2n_libcrypto_init()); POSIX_GUARD(s2n_fips_init()); POSIX_GUARD_RESULT(s2n_rand_init()); POSIX_GUARD(s2n_cipher_suites_init()); @@ -88,10 +89,11 @@ static bool s2n_cleanup_atexit_impl(void) /* the configs need to be wiped before resetting the memory callbacks */ s2n_wipe_static_configs(); - return s2n_result_is_ok(s2n_rand_cleanup_thread()) && - s2n_result_is_ok(s2n_rand_cleanup()) && - s2n_result_is_ok(s2n_locking_cleanup()) && - (s2n_mem_cleanup() == S2N_SUCCESS); + return s2n_result_is_ok(s2n_libcrypto_cleanup()) && + s2n_result_is_ok(s2n_rand_cleanup_thread()) && + s2n_result_is_ok(s2n_rand_cleanup()) && + s2n_result_is_ok(s2n_locking_cleanup()) && + (s2n_mem_cleanup() == S2N_SUCCESS); } int s2n_cleanup(void) diff --git a/contrib/restricted/aws/s2n/utils/s2n_mem.c b/contrib/restricted/aws/s2n/utils/s2n_mem.c index fcb848fec4..4d88a52bcc 100644 --- a/contrib/restricted/aws/s2n/utils/s2n_mem.c +++ b/contrib/restricted/aws/s2n/utils/s2n_mem.c @@ -218,7 +218,7 @@ int s2n_free_object(uint8_t **p_data, uint32_t size) if (*p_data == NULL) { return S2N_SUCCESS; } - + POSIX_ENSURE(initialized, S2N_ERR_NOT_INITIALIZED); struct s2n_blob b = {.data = *p_data, .allocated = size, .size = size, .growable = 1}; @@ -275,11 +275,16 @@ int s2n_mem_cleanup(void) int s2n_free(struct s2n_blob *b) { - POSIX_PRECONDITION(s2n_blob_validate(b)); - /* To avoid memory leaks, don't exit the function until the memory has been freed */ int zero_rc = s2n_blob_zero(b); + POSIX_GUARD(s2n_free_without_wipe(b)); + return zero_rc; +} + +int s2n_free_without_wipe(struct s2n_blob *b) +{ + POSIX_PRECONDITION(s2n_blob_validate(b)); POSIX_ENSURE(initialized, S2N_ERR_NOT_INITIALIZED); POSIX_ENSURE(s2n_blob_is_growable(b), S2N_ERR_FREE_STATIC_BLOB); @@ -288,8 +293,6 @@ int s2n_free(struct s2n_blob *b) *b = (struct s2n_blob) {0}; - POSIX_GUARD(zero_rc); - return S2N_SUCCESS; } diff --git a/contrib/restricted/aws/s2n/utils/s2n_mem.h b/contrib/restricted/aws/s2n/utils/s2n_mem.h index 78d600db32..4c0fb76822 100644 --- a/contrib/restricted/aws/s2n/utils/s2n_mem.h +++ b/contrib/restricted/aws/s2n/utils/s2n_mem.h @@ -26,6 +26,7 @@ int s2n_mem_cleanup(void); int s2n_alloc(struct s2n_blob *b, uint32_t size); int s2n_realloc(struct s2n_blob *b, uint32_t size); int s2n_free(struct s2n_blob *b); +int s2n_free_without_wipe(struct s2n_blob *b); int s2n_blob_zeroize_free(struct s2n_blob *b); int s2n_free_object(uint8_t **p_data, uint32_t size); int s2n_dup(struct s2n_blob *from, struct s2n_blob *to); |