aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2023-05-24 09:09:04 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2023-05-24 09:09:04 +0300
commit7cf122beb332410caf13409c7e4cf1b08863ffa6 (patch)
treef61eafd13e35e74208861c50473c92402c21a341
parent568cf2d405812450db0298f1fe9446b8d19561e3 (diff)
downloadydb-7cf122beb332410caf13409c7e4cf1b08863ffa6.tar.gz
Update contrib/restricted/aws/s2n to 1.3.44
-rw-r--r--contrib/restricted/aws/s2n/api/s2n.h30
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_cipher.h3
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c41
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h2
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_openssl.h1
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c105
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c6
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.c39
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.h3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_recv.c27
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_shutdown.c75
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_x509_validator.c17
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_x509_validator.h6
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_init.c2
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_random.c1
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);