diff options
author | robot-contrib <robot-contrib@yandex-team.com> | 2023-05-24 09:09:04 +0300 |
---|---|---|
committer | robot-contrib <robot-contrib@yandex-team.com> | 2023-05-24 09:09:04 +0300 |
commit | 7cf122beb332410caf13409c7e4cf1b08863ffa6 (patch) | |
tree | f61eafd13e35e74208861c50473c92402c21a341 | |
parent | 568cf2d405812450db0298f1fe9446b8d19561e3 (diff) | |
download | ydb-7cf122beb332410caf13409c7e4cf1b08863ffa6.tar.gz |
Update contrib/restricted/aws/s2n to 1.3.44
-rw-r--r-- | contrib/restricted/aws/s2n/api/s2n.h | 30 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/crypto/s2n_cipher.h | 3 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c | 41 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h | 2 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/crypto/s2n_openssl.h | 1 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c | 105 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c | 6 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_config.c | 39 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_config.h | 3 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_recv.c | 27 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_shutdown.c | 75 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_x509_validator.c | 17 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_x509_validator.h | 6 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/utils/s2n_init.c | 2 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/utils/s2n_random.c | 1 |
15 files changed, 237 insertions, 121 deletions
diff --git a/contrib/restricted/aws/s2n/api/s2n.h b/contrib/restricted/aws/s2n/api/s2n.h index 665370da4b..91dcc2eb43 100644 --- a/contrib/restricted/aws/s2n/api/s2n.h +++ b/contrib/restricted/aws/s2n/api/s2n.h @@ -1964,7 +1964,7 @@ S2N_API extern int s2n_connection_free(struct s2n_connection *conn); * * Once `s2n_shutdown` is complete: * * The s2n_connection handle cannot be used for reading for writing. - * * The underlying transport can be closed. Most likely via `close()`. + * * The underlying transport can be closed. Most likely via `shutdown()` or `close()`. * * The s2n_connection handle can be freed via s2n_connection_free() or reused via s2n_connection_wipe() * * @param conn A pointer to the s2n_connection object @@ -1974,6 +1974,34 @@ S2N_API extern int s2n_connection_free(struct s2n_connection *conn); S2N_API extern int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked); /** + * Attempts to close the write side of the TLS connection. + * + * TLS1.3 supports closing the write side of a TLS connection while leaving the read + * side unaffected. This feature is usually referred to as "half-close". We send + * a close_notify alert, but do not wait for the peer to respond. + * + * Like `s2n_shutdown()`, this method does not affect the underlying transport. + * + * `s2n_shutdown_send()` may still be called for earlier TLS versions, but most + * TLS implementations will react by immediately discarding any pending writes and + * closing the connection. + * + * Once `s2n_shutdown_send()` is complete: + * * The s2n_connection handle CANNOT be used for writing. + * * The s2n_connection handle CAN be used for reading. + * * The write side of the underlying transport can be closed. Most likely via `shutdown()`. + * + * The application should still call `s2n_shutdown()` or wait for `s2n_recv()` to + * return 0 to indicate end-of-data before cleaning up the connection or closing + * the read side of the underlying transport. + * + * @param conn A pointer to the s2n_connection object + * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate() + * @returns S2N_SUCCESS on success. S2N_FAILURE on failure + */ +S2N_API extern int s2n_shutdown_send(struct s2n_connection *conn, s2n_blocked_status *blocked); + +/** * Used to declare what type of client certificate authentication to use. * * Currently the default for s2n-tls is for neither the server side or the client side to use Client (aka Mutual) authentication. diff --git a/contrib/restricted/aws/s2n/crypto/s2n_cipher.h b/contrib/restricted/aws/s2n/crypto/s2n_cipher.h index a58163025f..18ac7cdccf 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_cipher.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_cipher.h @@ -107,3 +107,6 @@ extern const struct s2n_cipher s2n_chacha20_poly1305; extern const struct s2n_cipher s2n_tls13_aes128_gcm; extern const struct s2n_cipher s2n_tls13_aes256_gcm; + +S2N_RESULT s2n_rc4_init(); +S2N_RESULT s2n_rc4_cleanup(); diff --git a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c index 1b73ff782d..d92da10a08 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c @@ -17,17 +17,13 @@ #include <openssl/crypto.h> #include <openssl/opensslv.h> +#include <string.h> #include "crypto/s2n_crypto.h" #include "crypto/s2n_fips.h" #include "crypto/s2n_openssl.h" #include "utils/s2n_safety.h" #include "utils/s2n_safety_macros.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 * and version name. We have to handle that by using old functions @@ -140,39 +136,14 @@ 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) +bool s2n_libcrypto_is_libressl() { - RESULT_GUARD_OSSL(OSSL_PROVIDER_do_all(NULL, *s2n_libcrypto_cleanup_cb, NULL), S2N_ERR_ATEXIT); - - return S2N_RESULT_OK; -} +#if defined(LIBRESSL_VERSION_NUMBER) + return true; #else -S2N_RESULT s2n_libcrypto_cleanup(void) -{ - return S2N_RESULT_OK; -} + return false; #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 c3b933562f..34d9ef2aac 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h @@ -17,6 +17,4 @@ #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_openssl.h b/contrib/restricted/aws/s2n/crypto/s2n_openssl.h index 39ff57f6aa..cd43cb8f4e 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_openssl.h +++ b/contrib/restricted/aws/s2n/crypto/s2n_openssl.h @@ -58,3 +58,4 @@ bool s2n_libcrypto_is_awslc(); bool s2n_libcrypto_is_boringssl(); +bool s2n_libcrypto_is_libressl(); 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 85bf5bca90..4c4bc14914 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c @@ -21,20 +21,62 @@ #include "utils/s2n_blob.h" #include "utils/s2n_safety.h" -static uint8_t s2n_stream_cipher_rc4_available() +#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0) + #error #include "openssl/provider.h" +DEFINE_POINTER_CLEANUP_FUNC(OSSL_LIB_CTX *, OSSL_LIB_CTX_free); +#endif + +static EVP_CIPHER *s2n_rc4_cipher = NULL; + +S2N_RESULT s2n_rc4_init() +{ + /* In Openssl-3.0, RC4 is only available from the "legacy" provider, + * which is not loaded in the default library context. + */ +#if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_RC4) && S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0) + DEFER_CLEANUP(OSSL_LIB_CTX *lib_ctx = OSSL_LIB_CTX_new(), OSSL_LIB_CTX_free_pointer); + RESULT_ENSURE_REF(lib_ctx); + RESULT_ENSURE_REF(OSSL_PROVIDER_load(lib_ctx, "legacy")); + s2n_rc4_cipher = EVP_CIPHER_fetch(lib_ctx, "rc4", "provider=legacy"); + RESULT_ENSURE_REF(s2n_rc4_cipher); +#endif + return S2N_RESULT_OK; +} + +S2N_RESULT s2n_rc4_cleanup() { -#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 +#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0) + EVP_CIPHER_free(s2n_rc4_cipher); +#endif + return S2N_RESULT_OK; +} + +static S2N_RESULT s2n_get_rc4_cipher(const EVP_CIPHER **cipher) +{ + RESULT_ENSURE_REF(cipher); + *cipher = NULL; if (s2n_is_in_fips_mode()) { - return 0; + *cipher = NULL; + } else if (s2n_rc4_cipher) { + *cipher = s2n_rc4_cipher; +#if S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 } else { - return (EVP_rc4() ? 1 : 0); + *cipher = EVP_rc4(); +#endif + } + RESULT_ENSURE(*cipher, S2N_ERR_UNIMPLEMENTED); + return S2N_RESULT_OK; +} + +static uint8_t s2n_stream_cipher_rc4_available() +{ + const EVP_CIPHER *cipher = NULL; + if (s2n_result_is_ok(s2n_get_rc4_cipher(&cipher)) && cipher) { + return 1; } -#else return 0; -#endif /* S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 */ } -#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 static int s2n_stream_cipher_rc4_encrypt(struct s2n_session_key *key, struct s2n_blob *in, struct s2n_blob *out) { POSIX_ENSURE_GTE(out->size, in->size); @@ -64,17 +106,25 @@ static int s2n_stream_cipher_rc4_decrypt(struct s2n_session_key *key, struct s2n static int s2n_stream_cipher_rc4_set_encryption_key(struct s2n_session_key *key, struct s2n_blob *in) { POSIX_ENSURE_EQ(in->size, 16); - POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, EVP_rc4(), NULL, in->data, NULL), S2N_ERR_KEY_INIT); - return 0; + const EVP_CIPHER *evp_rc4 = NULL; + POSIX_GUARD_RESULT(s2n_get_rc4_cipher(&evp_rc4)); + + POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, evp_rc4, NULL, in->data, NULL), S2N_ERR_KEY_INIT); + + return S2N_SUCCESS; } static int s2n_stream_cipher_rc4_set_decryption_key(struct s2n_session_key *key, struct s2n_blob *in) { POSIX_ENSURE_EQ(in->size, 16); - POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, EVP_rc4(), NULL, in->data, NULL), S2N_ERR_KEY_INIT); - return 0; + const EVP_CIPHER *evp_rc4 = NULL; + POSIX_GUARD_RESULT(s2n_get_rc4_cipher(&evp_rc4)); + + POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, evp_rc4, NULL, in->data, NULL), S2N_ERR_KEY_INIT); + + return S2N_SUCCESS; } static int s2n_stream_cipher_rc4_init(struct s2n_session_key *key) @@ -90,39 +140,6 @@ static int s2n_stream_cipher_rc4_destroy_key(struct s2n_session_key *key) return 0; } -#else - -static int s2n_stream_cipher_rc4_encrypt(struct s2n_session_key *key, struct s2n_blob *in, struct s2n_blob *out) -{ - POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); -} - -static int s2n_stream_cipher_rc4_decrypt(struct s2n_session_key *key, struct s2n_blob *in, struct s2n_blob *out) -{ - POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); -} - -static int s2n_stream_cipher_rc4_set_encryption_key(struct s2n_session_key *key, struct s2n_blob *in) -{ - POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); -} - -static int s2n_stream_cipher_rc4_set_decryption_key(struct s2n_session_key *key, struct s2n_blob *in) -{ - POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); -} - -static int s2n_stream_cipher_rc4_init(struct s2n_session_key *key) -{ - POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); -} - -static int s2n_stream_cipher_rc4_destroy_key(struct s2n_session_key *key) -{ - POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); -} - -#endif /* S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 */ const struct s2n_cipher s2n_rc4 = { .type = S2N_STREAM, diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c index e9c38dc0a6..d20325270b 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c @@ -971,6 +971,9 @@ int s2n_crypto_disable_init(void) /* Determines cipher suite availability and selects record algorithms */ int s2n_cipher_suites_init(void) { + /* RC4 requires some extra setup */ + POSIX_GUARD_RESULT(s2n_rc4_init()); + const int num_cipher_suites = s2n_array_len(s2n_all_cipher_suites); for (int i = 0; i < num_cipher_suites; i++) { struct s2n_cipher_suite *cur_suite = s2n_all_cipher_suites[i]; @@ -1052,6 +1055,9 @@ S2N_RESULT s2n_cipher_suites_cleanup(void) #endif } + /* RC4 requires some extra cleanup */ + RESULT_GUARD(s2n_rc4_cleanup()); + return S2N_RESULT_OK; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.c b/contrib/restricted/aws/s2n/tls/s2n_config.c index 6420766352..80c56247aa 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_config.c +++ b/contrib/restricted/aws/s2n/tls/s2n_config.c @@ -113,7 +113,6 @@ static int s2n_config_init(struct s2n_config *config) POSIX_GUARD_RESULT(s2n_map_complete(config->domain_name_to_cert_map)); s2n_x509_trust_store_init_empty(&config->trust_store); - POSIX_GUARD(s2n_x509_trust_store_from_system_defaults(&config->trust_store)); return 0; } @@ -232,15 +231,18 @@ int s2n_config_defaults_init(void) if (s2n_is_in_fips_mode()) { POSIX_GUARD(s2n_config_init(&s2n_default_fips_config)); POSIX_GUARD(s2n_config_setup_fips(&s2n_default_fips_config)); + POSIX_GUARD(s2n_config_load_system_certs(&s2n_default_fips_config)); } else { /* Set up default */ POSIX_GUARD(s2n_config_init(&s2n_default_config)); POSIX_GUARD(s2n_config_setup_default(&s2n_default_config)); + POSIX_GUARD(s2n_config_load_system_certs(&s2n_default_config)); } /* Set up TLS 1.3 defaults */ POSIX_GUARD(s2n_config_init(&s2n_default_tls13_config)); POSIX_GUARD(s2n_config_setup_tls13(&s2n_default_tls13_config)); + POSIX_GUARD(s2n_config_load_system_certs(&s2n_default_tls13_config)); return S2N_SUCCESS; } @@ -252,7 +254,29 @@ void s2n_wipe_static_configs(void) s2n_config_cleanup(&s2n_default_tls13_config); } -struct s2n_config *s2n_config_new(void) +int s2n_config_load_system_certs(struct s2n_config *config) +{ + POSIX_ENSURE_REF(config); + + struct s2n_x509_trust_store *store = &config->trust_store; + POSIX_ENSURE(!store->loaded_system_certs, S2N_ERR_X509_TRUST_STORE); + + if (!store->trust_store) { + store->trust_store = X509_STORE_new(); + POSIX_ENSURE_REF(store->trust_store); + } + + int err_code = X509_STORE_set_default_paths(store->trust_store); + if (!err_code) { + s2n_x509_trust_store_wipe(store); + POSIX_BAIL(S2N_ERR_X509_TRUST_STORE); + } + store->loaded_system_certs = true; + + return S2N_SUCCESS; +} + +struct s2n_config *s2n_config_new_minimal(void) { struct s2n_blob allocator = { 0 }; struct s2n_config *new_config; @@ -269,6 +293,17 @@ struct s2n_config *s2n_config_new(void) return new_config; } +struct s2n_config *s2n_config_new(void) +{ + struct s2n_config *new_config = s2n_config_new_minimal(); + PTR_ENSURE_REF(new_config); + + /* For backwards compatibility, s2n_config_new loads system certs by default. */ + PTR_GUARD_POSIX(s2n_config_load_system_certs(new_config)); + + return new_config; +} + static int s2n_config_store_ticket_key_comparator(const void *a, const void *b) { if (((const struct s2n_ticket_key *) a)->intro_timestamp >= ((const struct s2n_ticket_key *) b)->intro_timestamp) { diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.h b/contrib/restricted/aws/s2n/tls/s2n_config.h index 82588b780d..176d6a16e5 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_config.h +++ b/contrib/restricted/aws/s2n/tls/s2n_config.h @@ -193,6 +193,9 @@ struct s2n_config { s2n_renegotiate_request_cb renegotiate_request_cb; }; +struct s2n_config *s2n_config_new_minimal(void); +int s2n_config_load_system_certs(struct s2n_config *config); + S2N_CLEANUP_RESULT s2n_config_ptr_free(struct s2n_config **config); int s2n_config_defaults_init(void); diff --git a/contrib/restricted/aws/s2n/tls/s2n_recv.c b/contrib/restricted/aws/s2n/tls/s2n_recv.c index d1f04814dc..0f6256844f 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_recv.c +++ b/contrib/restricted/aws/s2n/tls/s2n_recv.c @@ -115,8 +115,23 @@ ssize_t s2n_recv_impl(struct s2n_connection *conn, void *buf, ssize_t size, s2n_ POSIX_GUARD(s2n_blob_init(&out, (uint8_t *) buf, 0)); if (!s2n_connection_check_io_status(conn, S2N_IO_READABLE)) { + /* + *= https://tools.ietf.org/rfc/rfc8446#6.1 + *# If a transport-level close + *# is received prior to a "close_notify", the receiver cannot know that + *# all the data that was sent has been received. + * + *= https://tools.ietf.org/rfc/rfc8446#6.1 + *# If the application protocol using TLS provides that any data may be + *# carried over the underlying transport after the TLS connection is + *# closed, the TLS implementation MUST receive a "close_notify" alert + *# before indicating end-of-data to the application layer. + */ + POSIX_ENSURE(conn->close_notify_received, S2N_ERR_CLOSED); + *blocked = S2N_NOT_BLOCKED; return 0; } + *blocked = S2N_BLOCKED_ON_READ; POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_UNSUPPORTED_WITH_QUIC); @@ -127,13 +142,11 @@ ssize_t s2n_recv_impl(struct s2n_connection *conn, void *buf, ssize_t size, s2n_ uint8_t record_type; int r = s2n_read_full_record(conn, &record_type, &isSSLv2); if (r < 0) { - if (s2n_errno == S2N_ERR_CLOSED) { - *blocked = S2N_NOT_BLOCKED; - if (!bytes_read) { - return 0; - } else { - return bytes_read; - } + /* Don't propagate the error if we already read some bytes. + * We'll report S2N_ERR_CLOSED on the next call. + */ + if (s2n_errno == S2N_ERR_CLOSED && bytes_read) { + return bytes_read; } /* Don't propagate the error if we already read some bytes */ diff --git a/contrib/restricted/aws/s2n/tls/s2n_shutdown.c b/contrib/restricted/aws/s2n/tls/s2n_shutdown.c index 4afe783d61..c02ead0b02 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_shutdown.c +++ b/contrib/restricted/aws/s2n/tls/s2n_shutdown.c @@ -19,22 +19,43 @@ #include "tls/s2n_tls.h" #include "utils/s2n_safety.h" -static bool s2n_is_close_notify_required(struct s2n_connection *conn) +typedef enum { + S2N_SHUTDOWN_RDWR, + S2N_SHUTDOWN_WR, +} s2n_shutdown_how; + +static bool s2n_error_alert_received(struct s2n_connection *conn) { - /* We only send one close_notify */ - if (conn->close_notify_queued) { + /* We don't check s2n_connection_get_alert() or s2n_stuffer_data_available() + * because of https://github.com/aws/s2n-tls/issues/3933. + * We need to check if the stuffer contains an alert, regardless of its + * read state. + */ + if (conn->alert_in.write_cursor == 0) { return false; } - /* We don't send a close_notify if an error alert was already sent. - * Sending an error alert always sets conn->closing: see s2n_flush. - */ - if (conn->write_closing) { + /* Verify that the stuffer doesn't just contain a close_notify alert */ + if (conn->close_notify_received) { return false; } return true; } -int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked) +static bool s2n_error_alert_sent(struct s2n_connection *conn) +{ + /* Sending an alert always sets conn->write_closing: see s2n_flush() */ + if (!conn->write_closing) { + return false; + } + /* Verify that the alert sent wasn't just a close_notify */ + if (conn->close_notify_queued) { + return false; + } + return true; +} + +int s2n_shutdown_impl(struct s2n_connection *conn, s2n_shutdown_how how, + s2n_blocked_status *blocked) { POSIX_ENSURE_REF(conn); POSIX_ENSURE_REF(blocked); @@ -44,6 +65,16 @@ int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked) return S2N_SUCCESS; } + /* Treat this call as a no-op if an error alert was already received. + * Error alerts close the connection without any exchange of close_notify alerts. */ + if (s2n_error_alert_received(conn)) { + return S2N_SUCCESS; + } + + /* Enforce blinding. + * If an application is using self-service blinding, ensure that they have + * waited the required time before triggering the close_notify alert. + */ uint64_t elapsed = 0; POSIX_GUARD_RESULT(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed)); S2N_ERROR_IF(elapsed < conn->delay, S2N_ERR_SHUTDOWN_PAUSED); @@ -51,17 +82,30 @@ int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked) /* Flush any outstanding data or alerts */ POSIX_GUARD(s2n_flush(conn, blocked)); + /* Error alerts close the connection without any exchange of close_notify alerts. + * We need to check after flushing to account for any pending alerts. + */ + if (s2n_error_alert_sent(conn)) { + conn->read_closed = 1; + return S2N_SUCCESS; + } + /** *= https://tools.ietf.org/rfc/rfc8446#section-6.1 *# Each party MUST send a "close_notify" alert before closing its write *# side of the connection, unless it has already sent some error alert. */ - if (s2n_is_close_notify_required(conn)) { + if (!conn->close_notify_queued) { POSIX_GUARD(s2n_queue_writer_close_alert_warning(conn)); conn->close_notify_queued = 1; POSIX_GUARD(s2n_flush(conn, blocked)); } + /* If we're only closing the write side, then we've succeeded. */ + if (how == S2N_SHUTDOWN_WR) { + return S2N_SUCCESS; + } + /* * The purpose of the peer responding to our close_notify * with its own close_notify is to prevent application data truncation. @@ -73,6 +117,7 @@ int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked) */ if (!s2n_handshake_is_complete(conn)) { POSIX_GUARD_RESULT(s2n_connection_set_closed(conn)); + *blocked = S2N_NOT_BLOCKED; return S2N_SUCCESS; } @@ -96,3 +141,15 @@ int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked) *blocked = S2N_NOT_BLOCKED; return S2N_SUCCESS; } + +int s2n_shutdown_send(struct s2n_connection *conn, s2n_blocked_status *blocked) +{ + POSIX_GUARD(s2n_shutdown_impl(conn, S2N_SHUTDOWN_WR, blocked)); + return S2N_SUCCESS; +} + +int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked) +{ + POSIX_GUARD(s2n_shutdown_impl(conn, S2N_SHUTDOWN_RDWR, blocked)); + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c index 78fdb3fbb2..791ae3bd80 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c +++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c @@ -62,22 +62,6 @@ uint8_t s2n_x509_trust_store_has_certs(struct s2n_x509_trust_store *store) return store->trust_store ? (uint8_t) 1 : (uint8_t) 0; } -int s2n_x509_trust_store_from_system_defaults(struct s2n_x509_trust_store *store) -{ - if (!store->trust_store) { - store->trust_store = X509_STORE_new(); - POSIX_ENSURE_REF(store->trust_store); - } - - int err_code = X509_STORE_set_default_paths(store->trust_store); - if (!err_code) { - s2n_x509_trust_store_wipe(store); - POSIX_BAIL(S2N_ERR_X509_TRUST_STORE); - } - - return 0; -} - int s2n_x509_trust_store_add_pem(struct s2n_x509_trust_store *store, const char *pem) { POSIX_ENSURE_REF(store); @@ -141,6 +125,7 @@ void s2n_x509_trust_store_wipe(struct s2n_x509_trust_store *store) if (store->trust_store) { X509_STORE_free(store->trust_store); store->trust_store = NULL; + store->loaded_system_certs = false; } } diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h index 7d5ebc38ce..5f5e113421 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h +++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h @@ -47,6 +47,9 @@ struct s2n_connection; */ struct s2n_x509_trust_store { X509_STORE *trust_store; + + /* Indicates whether system default certs have been loaded into the trust store */ + unsigned loaded_system_certs : 1; }; /** @@ -72,9 +75,6 @@ void s2n_x509_trust_store_init_empty(struct s2n_x509_trust_store *store); /** Returns TRUE if the trust store has certificates installed, FALSE otherwise */ uint8_t s2n_x509_trust_store_has_certs(struct s2n_x509_trust_store *store); -/** Initializes the trust store to default system paths **/ -int s2n_x509_trust_store_from_system_defaults(struct s2n_x509_trust_store *store); - /** Initialize trust store from a PEM. This will allocate memory, and load PEM into the Trust Store **/ int s2n_x509_trust_store_add_pem(struct s2n_x509_trust_store *store, const char *pem); diff --git a/contrib/restricted/aws/s2n/utils/s2n_init.c b/contrib/restricted/aws/s2n/utils/s2n_init.c index 8f1b66e0f9..420ebf0e88 100644 --- a/contrib/restricted/aws/s2n/utils/s2n_init.c +++ b/contrib/restricted/aws/s2n/utils/s2n_init.c @@ -66,7 +66,6 @@ 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()); @@ -100,7 +99,6 @@ static bool s2n_cleanup_atexit_impl(void) bool cleaned_up = s2n_result_is_ok(s2n_cipher_suites_cleanup()) && s2n_result_is_ok(s2n_rand_cleanup_thread()) && s2n_result_is_ok(s2n_rand_cleanup()) - && s2n_result_is_ok(s2n_libcrypto_cleanup()) && s2n_result_is_ok(s2n_locking_cleanup()) && (s2n_mem_cleanup() == S2N_SUCCESS); diff --git a/contrib/restricted/aws/s2n/utils/s2n_random.c b/contrib/restricted/aws/s2n/utils/s2n_random.c index d730c64d03..70b02eff7f 100644 --- a/contrib/restricted/aws/s2n/utils/s2n_random.c +++ b/contrib/restricted/aws/s2n/utils/s2n_random.c @@ -440,6 +440,7 @@ S2N_RESULT s2n_rand_cleanup(void) if (rand_engine) { ENGINE_remove(rand_engine); ENGINE_finish(rand_engine); + ENGINE_unregister_RAND(rand_engine); ENGINE_free(rand_engine); ENGINE_cleanup(); RAND_set_rand_engine(NULL); |