diff options
author | robot-contrib <robot-contrib@yandex-team.com> | 2023-05-12 10:28:42 +0300 |
---|---|---|
committer | robot-contrib <robot-contrib@yandex-team.com> | 2023-05-12 10:28:42 +0300 |
commit | bb9187654c4ea19cbbac471a7d9ba158fa0ebe99 (patch) | |
tree | 20e41b05f4a95138a08c6e2225030958624ba263 | |
parent | aa95211fddb9867731b60e56b78ac75f05f42243 (diff) | |
download | ydb-bb9187654c4ea19cbbac471a7d9ba158fa0ebe99.tar.gz |
Update contrib/restricted/aws/s2n to 1.3.43
-rw-r--r-- | contrib/restricted/aws/s2n/README.md | 4 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/api/s2n.h | 23 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c | 12 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/pq-crypto/README.md | 6 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_alerts.c | 11 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c | 1 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_config.c | 2 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_config.h | 2 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_connection.c | 109 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_connection.h | 29 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_handshake_io.c | 5 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_recv.c | 7 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_security_policies.c | 40 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_security_policies.h | 41 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_send.c | 6 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_shutdown.c | 34 | ||||
-rw-r--r-- | contrib/restricted/aws/s2n/tls/s2n_x509_validator.c | 41 |
17 files changed, 286 insertions, 87 deletions
diff --git a/contrib/restricted/aws/s2n/README.md b/contrib/restricted/aws/s2n/README.md index e3e9b08057..64baa0db5c 100644 --- a/contrib/restricted/aws/s2n/README.md +++ b/contrib/restricted/aws/s2n/README.md @@ -2,6 +2,10 @@ s2n-tls is a C99 implementation of the TLS/SSL protocols that is designed to be simple, small, fast, and with security as a priority. It is released and licensed under the Apache License 2.0. +> s2n-tls is short for "signal to noise" and is a nod to the almost magical act of encryption — disguising meaningful signals, like your critical data, as seemingly random noise. +> +> -- [s2n-tls announcement](https://aws.amazon.com/blogs/security/introducing-s2n-a-new-open-source-tls-implementation/) + [![Build Status](https://codebuild.us-west-2.amazonaws.com/badges?uuid=eyJlbmNyeXB0ZWREYXRhIjoiMndlTzJNbHVxWEo3Nm82alp4eGdGNm4rTWdxZDVYU2VTbitIR0ZLbHVtcFFGOW5majk5QnhqaUp3ZEkydG1ueWg0NGlhRE43a1ZnUzZaQTVnSm91TzFFPSIsIml2UGFyYW1ldGVyU3BlYyI6IlJLbW42NENlYXhJNy80QnYiLCJtYXRlcmlhbFNldFNlcmlhbCI6MX0%3D&branch=main)](https://github.com/aws/s2n-tls/) [![Apache 2 License](https://img.shields.io/github/license/aws/s2n-tls.svg)](http://aws.amazon.com/apache-2-0/) [![C99](https://img.shields.io/badge/language-C99-blue.svg)](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf) diff --git a/contrib/restricted/aws/s2n/api/s2n.h b/contrib/restricted/aws/s2n/api/s2n.h index ca8d4d4923..665370da4b 100644 --- a/contrib/restricted/aws/s2n/api/s2n.h +++ b/contrib/restricted/aws/s2n/api/s2n.h @@ -869,13 +869,20 @@ S2N_API extern int s2n_config_set_verify_after_sign(struct s2n_config *config, s S2N_API extern int s2n_config_set_send_buffer_size(struct s2n_config *config, uint32_t size); /** - * Enable or disable recieving of multiple TLS records in a single s2n_recv call + * Enable or disable receiving of multiple TLS records in a single s2n_recv call * - * Legacy behavior is to return after reading a single TLS record which may not be the most - * efficient way to invoke this function, especially if larger receive buffers are used. + * By default, s2n-tls returns from s2n_recv() after reading a single TLS record. + * Enabling receiving of multiple records will instead cause s2n_recv() to attempt + * to read until the application-provided output buffer is full. This may be more + * efficient, especially if larger receive buffers are used. + * + * @note If this option is enabled with blocking IO, the call to s2n_recv() will + * not return until either the application-provided output buffer is full or the + * peer closes the connection. This may lead to unintentionally long waits if the + * peer does not send enough data. * * @param config The configuration object being updated - * @param enabled Set to `true` if multiple record recieve is to be enabled; `false` to disable. + * @param enabled Set to `true` if multiple record receive is to be enabled; `false` to disable. * @returns S2N_SUCCESS on success. S2N_FAILURE on failure */ S2N_API extern int s2n_config_set_recv_multi_record(struct s2n_config *config, bool enabled); @@ -1711,11 +1718,17 @@ S2N_API extern int s2n_connection_set_protocol_preferences(struct s2n_connection /** * Sets the server name for the connection. * - * It may be desirable for clients + * The provided server name will be sent by the client to the server in the + * server_name ClientHello extension. It may be desirable for clients * to provide this information to facilitate secure connections to * servers that host multiple 'virtual' servers at a single underlying * network address. * + * s2n-tls does not place any restrictions on the provided server name. However, + * other TLS implementations might. Specifically, the TLS specification for the + * server_name extension requires that it be an ASCII-encoded DNS name without a + * trailing dot, and explicitly forbids literal IPv4 or IPv6 addresses. + * * @param conn The connection object being queried * @param server_name A pointer to a string containing the desired server name * @warning `server_name` must be a NULL terminated string. diff --git a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c index 92ed4bf15d..1b73ff782d 100644 --- a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c +++ b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c @@ -43,9 +43,9 @@ * distinguish AWS-LC fips and non-fips at pre-processing time since AWS-LC * doesn't distribute fips-specific header files. */ -#define EXPECTED_AWSLC_VERSION_PREFIX_FIPS_OR_OLD "BoringSSL" -#define EXPECTED_AWSLC_VERSION_PREFIX_NON_FIPS "AWS-LC" -#define EXPECTED_BORINGSSL_VERSION_PREFIX "BoringSSL" +#define EXPECTED_AWSLC_VERSION_PREFIX_OLD "BoringSSL" +#define EXPECTED_AWSLC_VERSION_PREFIX_NEW "AWS-LC" +#define EXPECTED_BORINGSSL_VERSION_PREFIX "BoringSSL" /* https://www.openssl.org/docs/man{1.0.2, 1.1.1, 3.0}/man3/OPENSSL_VERSION_NUMBER.html * OPENSSL_VERSION_NUMBER in hex is: MNNFFPPS major minor fix patch status. @@ -192,10 +192,10 @@ S2N_RESULT s2n_libcrypto_validate_runtime(void) * don't meet anymore "old" AWS-LC libcrypto's, this API version check * can be removed. */ - if (s2n_libcrypto_is_fips() || s2n_libcrypto_awslc_api_version() < 17) { - expected_awslc_name_prefix = EXPECTED_AWSLC_VERSION_PREFIX_FIPS_OR_OLD; + if (s2n_libcrypto_awslc_api_version() < 17) { + expected_awslc_name_prefix = EXPECTED_AWSLC_VERSION_PREFIX_OLD; } else { - expected_awslc_name_prefix = EXPECTED_AWSLC_VERSION_PREFIX_NON_FIPS; + expected_awslc_name_prefix = EXPECTED_AWSLC_VERSION_PREFIX_NEW; } RESULT_GUARD(s2n_libcrypto_validate_expected_version_prefix(expected_awslc_name_prefix)); } else if (s2n_libcrypto_is_boringssl()) { diff --git a/contrib/restricted/aws/s2n/pq-crypto/README.md b/contrib/restricted/aws/s2n/pq-crypto/README.md index f798ccc2c1..3e1c0d0543 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/README.md +++ b/contrib/restricted/aws/s2n/pq-crypto/README.md @@ -49,9 +49,9 @@ variable before compiling. 1. Add fuzz testing in `tests/fuzz/s2n_KEM_NAME_fuzz_test.c` 1. Add formal verification in `tests/saw/KEM_NAME/verify.saw` 1. Create a new `s2n_cipher_suite` in `tls/s2n_cipher_suites.c` -1. Create a new `s2n_cipher_preferences` in `tls/s2n_cipher_prefrences.c` that uses the new cipher suite +1. Create a new `s2n_cipher_preferences` in `tls/s2n_cipher_preferences.c` that uses the new cipher suite 1. Once this change is made, the KEM will be available for use in TLS handshakes; ensure that all testing/verification has been completed - + ## How to add a new variant to an existing PQ KEM family for use in hybrid TLS 1.2 1. Add the code to `pq-crypto/KEM_NAME/` 1. Update `pq-crypto/Makefile` to build that directory @@ -64,7 +64,7 @@ variable before compiling. 1. Add fuzz testing in `tests/fuzz/s2n_KEM_NAME_fuzz_test.c` 1. Add formal verification in `tests/saw/KEM_NAME/verify.saw` 1. Update the appropriate `supported_KEM_NAME_params` array in `tls/s2n_kem.c` - 1. Once this change is made, the KEM extension will be available for use in TLS handshakes; ensure that all testing/verification has been completed + 1. Once this change is made, the KEM extension will be available for use in TLS handshakes; ensure that all testing/verification has been completed ## How to use PQ cipher suites for hybrid TLS 1.2 1. Checkout s2n `git clone https://github.com/awslabs/s2n.git` diff --git a/contrib/restricted/aws/s2n/tls/s2n_alerts.c b/contrib/restricted/aws/s2n/tls/s2n_alerts.c index 4e1ea5f31a..1ca06577d5 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_alerts.c +++ b/contrib/restricted/aws/s2n/tls/s2n_alerts.c @@ -168,7 +168,7 @@ S2N_RESULT s2n_alerts_close_if_fatal(struct s2n_connection *conn, struct s2n_blo RESULT_ENSURE_EQ(alert->data[0], S2N_TLS_ALERT_LEVEL_WARNING); return S2N_RESULT_OK; } - conn->closing = true; + conn->write_closing = 1; return S2N_RESULT_OK; } @@ -220,7 +220,7 @@ int s2n_process_alert_fragment(struct s2n_connection *conn) if (s2n_stuffer_data_available(&conn->alert_in) == 2) { /* Close notifications are handled as shutdowns */ if (conn->alert_in_data[1] == S2N_TLS_ALERT_CLOSE_NOTIFY) { - conn->closed = 1; + conn->read_closed = 1; conn->close_notify_received = true; return 0; } @@ -237,7 +237,7 @@ int s2n_process_alert_fragment(struct s2n_connection *conn) } /* All other alerts are treated as fatal errors */ - conn->closed = 1; + POSIX_GUARD_RESULT(s2n_connection_set_closed(conn)); POSIX_BAIL(S2N_ERR_ALERT); } } @@ -256,8 +256,8 @@ int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn) struct s2n_blob out = { 0 }; POSIX_GUARD(s2n_blob_init(&out, alert, sizeof(alert))); - /* If there is an alert pending or we've already sent a close_notify, do nothing */ - if (s2n_stuffer_data_available(&conn->writer_alert_out) || conn->close_notify_queued) { + /* If there is an alert pending, do nothing */ + if (s2n_stuffer_data_available(&conn->writer_alert_out)) { return S2N_SUCCESS; } @@ -266,7 +266,6 @@ int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn) } POSIX_GUARD(s2n_stuffer_write(&conn->writer_alert_out, &out)); - conn->close_notify_queued = 1; return S2N_SUCCESS; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c index 84e0c94d02..e9c38dc0a6 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c @@ -1210,7 +1210,6 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire, if (conn->client_protocol_version < conn->server_protocol_version) { uint8_t fallback_scsv[S2N_TLS_CIPHER_SUITE_LEN] = { TLS_FALLBACK_SCSV }; if (s2n_wire_ciphers_contain(fallback_scsv, wire, count, cipher_suite_len)) { - conn->closed = 1; POSIX_BAIL(S2N_ERR_FALLBACK_DETECTED); } } diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.c b/contrib/restricted/aws/s2n/tls/s2n_config.c index 9545defa4c..6420766352 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_config.c +++ b/contrib/restricted/aws/s2n/tls/s2n_config.c @@ -402,7 +402,7 @@ int s2n_config_set_alert_behavior(struct s2n_config *config, s2n_alert_behavior int s2n_config_set_verify_host_callback(struct s2n_config *config, s2n_verify_host_fn verify_host_fn, void *data) { POSIX_ENSURE_REF(config); - config->verify_host = verify_host_fn; + config->verify_host_fn = verify_host_fn; config->data_for_verify_host = data; return 0; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.h b/contrib/restricted/aws/s2n/tls/s2n_config.h index 16eaba6183..82588b780d 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_config.h +++ b/contrib/restricted/aws/s2n/tls/s2n_config.h @@ -146,7 +146,7 @@ struct s2n_config { /* Return TRUE if the host should be trusted, If FALSE this will likely be called again for every host/alternative name * in the certificate. If any respond TRUE. If none return TRUE, the cert will be considered untrusted. */ - uint8_t (*verify_host)(const char *host_name, size_t host_name_len, void *data); + s2n_verify_host_fn verify_host_fn; void *data_for_verify_host; s2n_crl_lookup_callback crl_lookup_cb; diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.c b/contrib/restricted/aws/s2n/tls/s2n_connection.c index 16d1c19850..07768e2075 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_connection.c +++ b/contrib/restricted/aws/s2n/tls/s2n_connection.c @@ -306,8 +306,8 @@ int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *co } else { POSIX_GUARD(s2n_x509_validator_init(&conn->x509_validator, &config->trust_store, config->check_ocsp)); if (!conn->verify_host_fn_overridden) { - if (config->verify_host != NULL) { - conn->verify_host_fn = config->verify_host; + if (config->verify_host_fn != NULL) { + conn->verify_host_fn = config->verify_host_fn; conn->data_for_verify_host = config->data_for_verify_host; } else { conn->verify_host_fn = s2n_default_verify_host; @@ -1093,6 +1093,35 @@ uint64_t s2n_connection_get_delay(struct s2n_connection *conn) return conn->delay - elapsed; } +static S2N_RESULT s2n_connection_kill(struct s2n_connection *conn) +{ + RESULT_ENSURE_REF(conn); + RESULT_GUARD(s2n_connection_set_closed(conn)); + + /* Delay between 10 and 30 seconds in nanoseconds */ + int64_t min = TEN_S, max = 3 * TEN_S; + + /* Keep track of the delay so that it can be enforced */ + uint64_t rand_delay = 0; + RESULT_GUARD(s2n_public_random(max - min, &rand_delay)); + + conn->delay = min + rand_delay; + + /* Restart the write timer */ + RESULT_GUARD(s2n_timer_start(conn->config, &conn->write_timer)); + + if (conn->blinding == S2N_BUILT_IN_BLINDING) { + struct timespec sleep_time = { .tv_sec = conn->delay / ONE_S, .tv_nsec = conn->delay % ONE_S }; + + int r = 0; + do { + r = nanosleep(&sleep_time, &sleep_time); + } while (r != 0); + } + + return S2N_RESULT_OK; +} + S2N_CLEANUP_RESULT s2n_connection_apply_error_blinding(struct s2n_connection **conn) { RESULT_ENSURE_REF(conn); @@ -1126,45 +1155,23 @@ S2N_CLEANUP_RESULT s2n_connection_apply_error_blinding(struct s2n_connection **c case S2N_ERR_CANCELLED: case S2N_ERR_CIPHER_NOT_SUPPORTED: case S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED: - (*conn)->closed = 1; + RESULT_GUARD(s2n_connection_set_closed(*conn)); break; default: /* Apply blinding to all other errors */ - RESULT_GUARD_POSIX(s2n_connection_kill(*conn)); + RESULT_GUARD(s2n_connection_kill(*conn)); break; } return S2N_RESULT_OK; } -int s2n_connection_kill(struct s2n_connection *conn) +S2N_RESULT s2n_connection_set_closed(struct s2n_connection *conn) { - POSIX_ENSURE_REF(conn); - - conn->closed = 1; - - /* Delay between 10 and 30 seconds in nanoseconds */ - int64_t min = TEN_S, max = 3 * TEN_S; - - /* Keep track of the delay so that it can be enforced */ - uint64_t rand_delay = 0; - POSIX_GUARD_RESULT(s2n_public_random(max - min, &rand_delay)); - - conn->delay = min + rand_delay; - - /* Restart the write timer */ - POSIX_GUARD_RESULT(s2n_timer_start(conn->config, &conn->write_timer)); - - if (conn->blinding == S2N_BUILT_IN_BLINDING) { - struct timespec sleep_time = { .tv_sec = conn->delay / ONE_S, .tv_nsec = conn->delay % ONE_S }; - int r; - - do { - r = nanosleep(&sleep_time, &sleep_time); - } while (r != 0); - } - - return 0; + RESULT_ENSURE_REF(conn); + conn->read_closed = 1; + conn->write_closed = 1; + return S2N_RESULT_OK; } const uint8_t *s2n_connection_get_ocsp_response(struct s2n_connection *conn, uint32_t *length) @@ -1534,3 +1541,43 @@ S2N_RESULT s2n_connection_dynamic_free_in_buffer(struct s2n_connection *conn) return S2N_RESULT_OK; } + +bool s2n_connection_check_io_status(struct s2n_connection *conn, s2n_io_status status) +{ + if (!conn) { + return false; + } + + const bool is_full_duplex = !conn->read_closed && !conn->write_closed; + + /* + *= https://tools.ietf.org/rfc/rfc8446#section-6.1 + *# Note that this is a change from versions of TLS prior to TLS 1.3 in + *# which implementations were required to react to a "close_notify" by + *# discarding pending writes and sending an immediate "close_notify" + *# alert of their own. + */ + if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { + switch (status) { + case S2N_IO_WRITABLE: + case S2N_IO_READABLE: + case S2N_IO_FULL_DUPLEX: + return is_full_duplex; + case S2N_IO_CLOSED: + return !is_full_duplex; + } + } + + switch (status) { + case S2N_IO_WRITABLE: + return !conn->write_closed; + case S2N_IO_READABLE: + return !conn->read_closed; + case S2N_IO_FULL_DUPLEX: + return is_full_duplex; + case S2N_IO_CLOSED: + return conn->read_closed && conn->write_closed; + } + + return false; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.h b/contrib/restricted/aws/s2n/tls/s2n_connection.h index 60d29b6cad..e177889b63 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_connection.h +++ b/contrib/restricted/aws/s2n/tls/s2n_connection.h @@ -316,21 +316,14 @@ struct s2n_connection { uint64_t wire_bytes_out; uint64_t early_data_bytes; - /* Is the connection open or closed ? We use C's only - * atomic type as both the reader and the writer threads - * may declare a connection closed. + /* Is the connection open or closed? * - * A connection can be gracefully closed or hard-closed. - * When gracefully closed the reader or the writer mark - * the connection as closing, and then the writer will - * send an alert message before closing the connection - * and marking it as closed. - * - * A hard-close goes straight to closed with no alert - * message being sent. + * We use C's only atomic type as an error requires shutting down both read + * and write, so both the reader and writer threads may access both fields. */ - sig_atomic_t closing; - sig_atomic_t closed; + sig_atomic_t read_closed; + sig_atomic_t write_closing; + sig_atomic_t write_closed; /* TLS extension data */ char server_name[S2N_MAX_SERVER_NAME + 1]; @@ -405,8 +398,14 @@ S2N_CLEANUP_RESULT s2n_connection_ptr_free(struct s2n_connection **s2n_connectio int s2n_connection_is_managed_corked(const struct s2n_connection *s2n_connection); int s2n_connection_is_client_auth_enabled(struct s2n_connection *s2n_connection); -/* Kill a bad connection */ -int s2n_connection_kill(struct s2n_connection *conn); +typedef enum { + S2N_IO_WRITABLE, + S2N_IO_READABLE, + S2N_IO_FULL_DUPLEX, + S2N_IO_CLOSED, +} s2n_io_status; +bool s2n_connection_check_io_status(struct s2n_connection *conn, s2n_io_status status); +S2N_RESULT s2n_connection_set_closed(struct s2n_connection *conn); /* Send/recv a stuffer to/from a connection */ int s2n_connection_send_stuffer(struct s2n_stuffer *stuffer, struct s2n_connection *conn, uint32_t len); diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c index efc92eb625..6bc5d16d12 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c +++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c @@ -1622,10 +1622,7 @@ int s2n_negotiate_impl(struct s2n_connection *conn, s2n_blocked_status *blocked) /* Flush any pending I/O or alert messages */ POSIX_GUARD(s2n_flush(conn, blocked)); - /* If the connection is closed, the handshake will never complete. */ - if (conn->closed) { - POSIX_BAIL(S2N_ERR_CLOSED); - } + POSIX_ENSURE(s2n_connection_check_io_status(conn, S2N_IO_FULL_DUPLEX), S2N_ERR_CLOSED); /* If the handshake was paused, retry the current message */ if (conn->handshake.paused) { diff --git a/contrib/restricted/aws/s2n/tls/s2n_recv.c b/contrib/restricted/aws/s2n/tls/s2n_recv.c index cf267f1926..d1f04814dc 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_recv.c +++ b/contrib/restricted/aws/s2n/tls/s2n_recv.c @@ -42,7 +42,7 @@ S2N_RESULT s2n_read_in_bytes(struct s2n_connection *conn, struct s2n_stuffer *ou errno = 0; int r = s2n_connection_recv_stuffer(output, conn, remaining); if (r == 0) { - conn->closed = 1; + conn->read_closed = 1; RESULT_BAIL(S2N_ERR_CLOSED); } else if (r < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) { @@ -114,7 +114,7 @@ ssize_t s2n_recv_impl(struct s2n_connection *conn, void *buf, ssize_t size, s2n_ struct s2n_blob out = { 0 }; POSIX_GUARD(s2n_blob_init(&out, (uint8_t *) buf, 0)); - if (conn->closed) { + if (!s2n_connection_check_io_status(conn, S2N_IO_READABLE)) { return 0; } *blocked = S2N_BLOCKED_ON_READ; @@ -122,7 +122,7 @@ ssize_t s2n_recv_impl(struct s2n_connection *conn, void *buf, ssize_t size, s2n_ POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_UNSUPPORTED_WITH_QUIC); POSIX_GUARD_RESULT(s2n_early_data_validate_recv(conn)); - while (size && !conn->closed) { + while (size && s2n_connection_check_io_status(conn, S2N_IO_READABLE)) { int isSSLv2 = 0; uint8_t record_type; int r = s2n_read_full_record(conn, &record_type, &isSSLv2); @@ -174,7 +174,6 @@ ssize_t s2n_recv_impl(struct s2n_connection *conn, void *buf, ssize_t size, s2n_ switch (record_type) { case TLS_ALERT: POSIX_GUARD(s2n_process_alert_fragment(conn)); - POSIX_GUARD(s2n_flush(conn, blocked)); break; case TLS_HANDSHAKE: { s2n_result result = s2n_post_handshake_recv(conn); diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c index 1f51175d7c..40c410b92b 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c +++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c @@ -523,6 +523,42 @@ const struct s2n_security_policy security_policy_pq_tls_1_0_2023_01_24 = { .ecc_preferences = &s2n_ecc_preferences_20200310, }; +/* Same as security_policy_pq_tls_1_1_2021_05_21, but with TLS 1.2 as minimum */ +const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_07 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_pq_tls_1_1_2021_05_21, + .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +/* Same as security_policy_pq_tls_1_0_2021_05_22, but with TLS 1.2 as minimum */ +const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_08 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_pq_tls_1_0_2021_05_22, + .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +/* Same as security_policy_pq_tls_1_0_2021_05_24, but with TLS 1.2 as minimum */ +const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_09 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_pq_tls_1_0_2021_05_24, + .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +/* Same as security_policy_pq_tls_1_0_2021_05_26, but with TLS 1.2 as minimum */ +const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_10 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_pq_tls_1_0_2021_05_26, + .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10 = { .minimum_protocol_version = S2N_TLS12, .cipher_preferences = &cipher_preferences_kms_fips_tls_1_2_2018_10, @@ -856,6 +892,10 @@ struct s2n_security_policy_selection security_policy_selection[] = { { .version = "PQ-TLS-1-0-2021-05-25", .security_policy = &security_policy_pq_tls_1_0_2021_05_25, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, { .version = "PQ-TLS-1-0-2021-05-26", .security_policy = &security_policy_pq_tls_1_0_2021_05_26, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, { .version = "PQ-TLS-1-0-2023-01-24", .security_policy = &security_policy_pq_tls_1_0_2023_01_24, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, + { .version = "PQ-TLS-1-2-2023-04-07", .security_policy = &security_policy_pq_tls_1_2_2023_04_07, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, + { .version = "PQ-TLS-1-2-2023-04-08", .security_policy = &security_policy_pq_tls_1_2_2023_04_08, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, + { .version = "PQ-TLS-1-2-2023-04-09", .security_policy = &security_policy_pq_tls_1_2_2023_04_09, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, + { .version = "PQ-TLS-1-2-2023-04-10", .security_policy = &security_policy_pq_tls_1_2_2023_04_10, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, { .version = "20140601", .security_policy = &security_policy_20140601, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, { .version = "20141001", .security_policy = &security_policy_20141001, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, { .version = "20150202", .security_policy = &security_policy_20150202, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h index ad98ab6923..367aeeb8c1 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h +++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h @@ -25,12 +25,49 @@ /* Kept up-to-date by s2n_security_policies_test */ #define NUM_RSA_PSS_SCHEMES 6 +/* The s2n_security_policy struct is used to define acceptable and available + * algorithms for use in the TLS protocol. Note that the behavior of each field + * likely differs between different TLS versions, as the mechanics of cipher + * negotiation often have significant differences between TLS versions. + * + * In s2n-tls, the signature_algorithms extension only applies to signatures in + * CertificateVerify messages. To specify acceptable signature algorithms for + * certificates the certificate_signature_preferences field should be set in the + * security policy. + */ struct s2n_security_policy { uint8_t minimum_protocol_version; + /* TLS 1.0 - 1.2 - cipher preference includes multiple elements such + * as signature algorithms, record algorithms, and key exchange algorithms + * TLS 1.3 - cipher preference only determines record encryption + */ const struct s2n_cipher_preferences *cipher_preferences; + /* kem_preferences is only used for Post-Quantum cryptography */ const struct s2n_kem_preferences *kem_preferences; + /* This field roughly corresponds to the "signature_algorithms" extension. + * The client serializes this field of the security_policy to populate the + * extension, and it is also used by the server to choose an appropriate + * entry from the options supplied by the client. + * TLS 1.2 - optional extension to specify signature algorithms other than + * default: https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1 + * TLS 1.3 - required extension specifying signature algorithms + */ const struct s2n_signature_preferences *signature_preferences; + /* When this field is set, the endpoint will ensure that the signatures on + * the certificates in the peer's certificate chain are in the specified + * list. Note that s2n-tls does not support the signature_algorithms_cert + * extension. Unlike the signature_preferences field, this information is + * never transmitted to a peer. + */ const struct s2n_signature_preferences *certificate_signature_preferences; + /* This field roughly corresponds to the information in the + * "supported_groups" extension. + * TLS 1.0 - 1.2 - "elliptic_curves" extension indicates supported groups + * for both key exchange and signature algorithms. + * TLS 1.3 - the "supported_groups" extension indicates the named groups + * which the client supports for key exchange + * https://www.rfc-editor.org/rfc/rfc8446#section-4.2.7 + */ const struct s2n_ecc_preferences *ecc_preferences; }; @@ -109,6 +146,10 @@ extern const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_24; extern const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_25; extern const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_26; extern const struct s2n_security_policy security_policy_pq_tls_1_0_2023_01_24; +extern const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_07; +extern const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_08; +extern const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_09; +extern const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_10; extern const struct s2n_security_policy security_policy_cloudfront_upstream; extern const struct s2n_security_policy security_policy_cloudfront_upstream_tls10; diff --git a/contrib/restricted/aws/s2n/tls/s2n_send.c b/contrib/restricted/aws/s2n/tls/s2n_send.c index 34d7a8f613..4fea390c88 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_send.c +++ b/contrib/restricted/aws/s2n/tls/s2n_send.c @@ -98,8 +98,8 @@ WRITE: conn->wire_bytes_out += w; } - if (conn->closing) { - conn->closed = 1; + if (conn->write_closing) { + conn->write_closed = 1; } POSIX_GUARD(s2n_stuffer_rewrite(&conn->out)); @@ -139,7 +139,7 @@ ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iov { ssize_t user_data_sent, total_size = 0; - POSIX_ENSURE(!conn->closed, S2N_ERR_CLOSED); + POSIX_ENSURE(s2n_connection_check_io_status(conn, S2N_IO_WRITABLE), S2N_ERR_CLOSED); POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_UNSUPPORTED_WITH_QUIC); /* Flush any pending I/O */ diff --git a/contrib/restricted/aws/s2n/tls/s2n_shutdown.c b/contrib/restricted/aws/s2n/tls/s2n_shutdown.c index 3a89221375..4afe783d61 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_shutdown.c +++ b/contrib/restricted/aws/s2n/tls/s2n_shutdown.c @@ -19,6 +19,21 @@ #include "tls/s2n_tls.h" #include "utils/s2n_safety.h" +static bool s2n_is_close_notify_required(struct s2n_connection *conn) +{ + /* We only send one close_notify */ + if (conn->close_notify_queued) { + 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) { + return false; + } + return true; +} + int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked) { POSIX_ENSURE_REF(conn); @@ -33,14 +48,20 @@ int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked) POSIX_GUARD_RESULT(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed)); S2N_ERROR_IF(elapsed < conn->delay, S2N_ERR_SHUTDOWN_PAUSED); - /* Queue our close_notify alert. - * If we have already sent a close_notify, then this operation is a no-op. - */ - POSIX_GUARD(s2n_queue_writer_close_alert_warning(conn)); - - /* Flush any pending records, then send the queued close_notify. */ + /* Flush any outstanding data or alerts */ POSIX_GUARD(s2n_flush(conn, blocked)); + /** + *= 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)) { + POSIX_GUARD(s2n_queue_writer_close_alert_warning(conn)); + conn->close_notify_queued = 1; + POSIX_GUARD(s2n_flush(conn, blocked)); + } + /* * The purpose of the peer responding to our close_notify * with its own close_notify is to prevent application data truncation. @@ -51,6 +72,7 @@ int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked) * and unnecessary blinding. */ if (!s2n_handshake_is_complete(conn)) { + POSIX_GUARD_RESULT(s2n_connection_set_closed(conn)); 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 3f63c81fa0..78fdb3fbb2 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c +++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c @@ -354,11 +354,26 @@ static S2N_RESULT s2n_verify_host_information(struct s2n_connection *conn, X509 /* Check SubjectAltNames before CommonName as per RFC 6125 6.4.4 */ s2n_result result = s2n_verify_host_information_san(conn, public_cert, &entry_found); + + /* + *= https://www.rfc-editor.org/rfc/rfc6125#section-6.4.4 + *# As noted, a client MUST NOT seek a match for a reference identifier + *# of CN-ID if the presented identifiers include a DNS-ID, SRV-ID, + *# URI-ID, or any application-specific identifier types supported by the + *# client. + */ if (entry_found) { return result; } - /* if no SubjectAltNames of type DNS found, go to the common name. */ + /* + *= https://www.rfc-editor.org/rfc/rfc6125#section-6.4.4 + *# Therefore, if and only if the presented identifiers do not include a + *# DNS-ID, SRV-ID, URI-ID, or any application-specific identifier types + *# supported by the client, then the client MAY as a last resort check + *# for a string whose form matches that of a fully qualified DNS domain + *# name in a Common Name field of the subject field (i.e., a CN-ID). + */ result = s2n_verify_host_information_common_name(conn, public_cert, &entry_found); if (entry_found) { return result; @@ -717,6 +732,30 @@ S2N_RESULT s2n_validate_certificate_signature(struct s2n_connection *conn, X509 const struct s2n_security_policy *security_policy; RESULT_GUARD_POSIX(s2n_connection_get_security_policy(conn, &security_policy)); + /** + * We only restrict the signature algorithm on the certificates in the + * peer's certificate chain if the certificate_signature_preferences field + * is set in the security policy. This is contrary to the RFC, which + * specifies that the signatures in the "signature_algorithms" extension + * apply to signatures in the certificate chain in certain scenarios, so RFC + * compliance would imply validating that the certificate chain signature + * algorithm matches one of the algorithms specified in the + * "signature_algorithms" extension. + * + *= https://www.rfc-editor.org/rfc/rfc5246#section-7.4.2 + *= type=exception + *= reason=not implemented due to lack of utility + *# If the client provided a "signature_algorithms" extension, then all + *# certificates provided by the server MUST be signed by a + *# hash/signature algorithm pair that appears in that extension. + * + *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.3 + *= type=exception + *= reason=not implemented due to lack of utility + *# If no "signature_algorithms_cert" extension is present, then the + *# "signature_algorithms" extension also applies to signatures appearing in + *# certificates. + */ if (security_policy->certificate_signature_preferences == NULL) { return S2N_RESULT_OK; } |