aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2022-08-23 13:55:32 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2022-08-23 13:55:32 +0300
commit843fc844ab1de7725a9eaaab9d308ada1aa87e72 (patch)
tree82a048515821a5c92a53a278ec3e81aa44b3772e /contrib/restricted/aws
parente200c8e2aa45d15f672a8ea2029e39a9f1620e6a (diff)
downloadydb-843fc844ab1de7725a9eaaab9d308ada1aa87e72.tar.gz
Update contrib/restricted/aws/s2n to 1.3.20
Diffstat (limited to 'contrib/restricted/aws')
-rw-r--r--contrib/restricted/aws/s2n/README.md33
-rw-r--r--contrib/restricted/aws/s2n/api/s2n.h25
-rw-r--r--contrib/restricted/aws/s2n/error/s2n_errno.c7
-rw-r--r--contrib/restricted/aws/s2n/error/s2n_errno.h5
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c5
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_alerts.c4
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_cert.c5
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.c7
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.h3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection.c4
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection.h7
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_early_data_io.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_key_update.c9
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_record_write.c95
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_recv.c13
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_resume.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_resume.h3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_send.c85
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_cert.c4
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c15
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_x509_validator.c188
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_x509_validator.h21
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_init.c14
23 files changed, 335 insertions, 221 deletions
diff --git a/contrib/restricted/aws/s2n/README.md b/contrib/restricted/aws/s2n/README.md
index c7be8baa46..2c0e042865 100644
--- a/contrib/restricted/aws/s2n/README.md
+++ b/contrib/restricted/aws/s2n/README.md
@@ -1,6 +1,6 @@
<img src="docs/images/s2n_logo_github.png" alt="s2n">
-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 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.
[![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/)
@@ -21,8 +21,7 @@ cd s2n-tls
# Pick an "env" line from the codebuild/codebuild.config file and run it, in this case choose the openssl-1.1.1 with GCC 9 build
S2N_LIBCRYPTO=openssl-1.1.1 BUILD_S2N=true TESTS=integration GCC_VERSION=9
-source codebuild/bin/s2n_setup_env.sh
-codebuild/bin/s2n_install_test_dependencies.sh
+sudo codebuild/bin/s2n_install_test_dependencies.sh
codebuild/bin/s2n_codebuild.sh
```
@@ -77,7 +76,7 @@ Doxygen installation instructions are available at the [Doxygen](https://doxygen
## Using s2n-tls
-The s2n-tls I/O APIs are designed to be intuitive to developers familiar with the widely-used POSIX I/O APIs, and s2n-tls supports blocking, non-blocking, and full-duplex I/O. Additionally there are no locks or mutexes within s2n-tls.
+The s2n-tls I/O APIs are designed to be intuitive to developers familiar with the widely-used POSIX I/O APIs, and s2n-tls supports blocking, non-blocking, and full-duplex I/O. Additionally there are no locks or mutexes within s2n-tls.
```c
/* Create a server mode connection handle */
@@ -96,7 +95,7 @@ s2n_blocked_status blocked;
if (s2n_negotiate(conn, &blocked) < 0) {
... error ...
}
-
+
/* Write data to the connection */
int bytes_written;
bytes_written = s2n_send(conn, "Hello World", sizeof("Hello World"), &blocked);
@@ -106,9 +105,9 @@ For details on building the s2n-tls library and how to use s2n-tls in an applica
## s2n-tls features
-s2n-tls implements SSLv3, TLS1.0, TLS1.1, TLS1.2, and TLS1.3. For encryption, s2n-tls supports 128-bit and 256-bit AES in the CBC and GCM modes, ChaCha20, 3DES, and RC4. For forward secrecy, s2n-tls supports both DHE and ECDHE. s2n-tls also supports the Server Name Indicator (SNI), Application-Layer Protocol Negotiation (ALPN), and Online Certificate Status Protocol (OCSP) TLS extensions. SSLv3, RC4, 3DES, and DHE are each disabled by default for security reasons.
+s2n-tls implements SSLv3, TLS1.0, TLS1.1, TLS1.2, and TLS1.3. For encryption, s2n-tls supports 128-bit and 256-bit AES in the CBC and GCM modes, ChaCha20, 3DES, and RC4. For forward secrecy, s2n-tls supports both DHE and ECDHE. s2n-tls also supports the Server Name Indicator (SNI), Application-Layer Protocol Negotiation (ALPN), and Online Certificate Status Protocol (OCSP) TLS extensions. SSLv3, RC4, 3DES, and DHE are each disabled by default for security reasons.
-As it can be difficult to keep track of which encryption algorithms and protocols are best to use, s2n-tls features a simple API to use the latest "default" set of preferences. If you prefer to remain on a specific version for backwards compatibility, that is also supported.
+As it can be difficult to keep track of which encryption algorithms and protocols are best to use, s2n-tls features a simple API to use the latest "default" set of preferences. If you prefer to remain on a specific version for backwards compatibility, that is also supported.
```c
/* Use the latest s2n-tls "default" set of ciphersuite and protocol preferences */
@@ -125,15 +124,15 @@ Internally s2n-tls takes a systematic approach to data protection and includes s
##### Small and auditable code base
Ignoring tests, blank lines and comments, s2n-tls is about 6,000 lines of code. s2n's code is also structured and written with a focus on reviewability. All s2n-tls code is subject to code review, and we plan to complete security evaluations of s2n-tls on an annual basis.
-To date there have been two external code-level reviews of s2n-tls, including one by a commercial security vendor. s2n-tls has also been shared with some trusted members of the broader cryptography, security, and Open Source communities. Any issues discovered are always recorded in the s2n-tls issue tracker.
+To date there have been two external code-level reviews of s2n-tls, including one by a commercial security vendor. s2n-tls has also been shared with some trusted members of the broader cryptography, security, and Open Source communities. Any issues discovered are always recorded in the s2n-tls issue tracker.
##### Static analysis, fuzz-testing and penetration testing
-In addition to code reviews, s2n-tls is subject to regular static analysis, fuzz-testing, and penetration testing. Several penetration tests have occurred, including two by commercial vendors.
+In addition to code reviews, s2n-tls is subject to regular static analysis, fuzz-testing, and penetration testing. Several penetration tests have occurred, including two by commercial vendors.
##### Unit tests and end-to-end testing
-s2n-tls includes positive and negative unit tests and end-to-end test cases.
+s2n-tls includes positive and negative unit tests and end-to-end test cases.
##### Erase on read
s2n-tls encrypts or erases plaintext data as quickly as possible. For example, decrypted data buffers are erased as they are read by the application.
@@ -145,28 +144,28 @@ s2n-tls uses operating system features to protect data from being swapped to dis
s2n-tls avoids implementing rarely used options and extensions, as well as features with a history of triggering protocol-level vulnerabilities. For example there is no support for session renegotiation or DTLS.
##### Compartmentalized random number generation
-The security of TLS and its associated encryption algorithms depends upon secure random number generation. s2n-tls provides every thread with two separate random number generators. One for "public" randomly generated data that may appear in the clear, and one for "private" data that should remain secret. This approach lessens the risk of potential predictability weaknesses in random number generation algorithms from leaking information across contexts.
+The security of TLS and its associated encryption algorithms depends upon secure random number generation. s2n-tls provides every thread with two separate random number generators. One for "public" randomly generated data that may appear in the clear, and one for "private" data that should remain secret. This approach lessens the risk of potential predictability weaknesses in random number generation algorithms from leaking information across contexts.
##### Modularized encryption
s2n-tls has been structured so that different encryption libraries may be used. Today s2n-tls supports OpenSSL, LibreSSL, BoringSSL, and the Apple Common Crypto framework to perform the underlying cryptographic operations.
##### Timing blinding
-s2n-tls includes structured support for blinding time-based side-channels that may leak sensitive data. For example, if s2n-tls fails to parse a TLS record or handshake message, s2n-tls will add a randomized delay of between 10 and 30 seconds, granular to nanoseconds, before responding. This raises the complexity of real-world timing side-channel attacks by a factor of at least tens of trillions.
+s2n-tls includes structured support for blinding time-based side-channels that may leak sensitive data. For example, if s2n-tls fails to parse a TLS record or handshake message, s2n-tls will add a randomized delay of between 10 and 30 seconds, granular to nanoseconds, before responding. This raises the complexity of real-world timing side-channel attacks by a factor of at least tens of trillions.
##### Table based state-machines
-s2n-tls uses simple tables to drive the TLS/SSL state machines, making it difficult for invalid out-of-order states to arise.
+s2n-tls uses simple tables to drive the TLS/SSL state machines, making it difficult for invalid out-of-order states to arise.
##### C safety
-s2n-tls is written in C, but makes light use of standard C library functions and wraps all memory handling, string handling, and serialization in systematic boundary-enforcing checks.
+s2n-tls is written in C, but makes light use of standard C library functions and wraps all memory handling, string handling, and serialization in systematic boundary-enforcing checks.
## Security issue notifications
If you discover a potential security issue in s2n-tls we ask that you notify
-AWS Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
+AWS Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
-If you package or distribute s2n-tls, or use s2n-tls as part of a large multi-user service, you may be eligible for pre-notification of future s2n-tls releases. Please contact s2n-pre-notification@amazon.com.
+If you package or distribute s2n-tls, or use s2n-tls as part of a large multi-user service, you may be eligible for pre-notification of future s2n-tls releases. Please contact s2n-pre-notification@amazon.com.
## Contributing to s2n-tls
If you are interested in contributing to s2n-tls, please see our [development guide](https://github.com/aws/s2n-tls/blob/main/docs/DEVELOPMENT-GUIDE.md).
## Language Bindings for s2n-tls
-See our [language bindings list](https://github.com/aws/s2n-tls/blob/main/docs/BINDINGS.md) for language bindings for s2n-tls that we're aware of.
+See our [language bindings list](https://github.com/aws/s2n-tls/blob/main/docs/BINDINGS.md) for language bindings for s2n-tls that we're aware of.
diff --git a/contrib/restricted/aws/s2n/api/s2n.h b/contrib/restricted/aws/s2n/api/s2n.h
index e1d4c587bd..c361dd09bb 100644
--- a/contrib/restricted/aws/s2n/api/s2n.h
+++ b/contrib/restricted/aws/s2n/api/s2n.h
@@ -872,6 +872,31 @@ S2N_API
extern int s2n_config_wipe_trust_store(struct s2n_config *config);
/**
+ * Set a custom send buffer size.
+ *
+ * This buffer is used to stage records for sending. By default,
+ * enough memory is allocated to hold a single record of the maximum
+ * size configured for the connection. With the default fragment size,
+ * that is about 8K bytes.
+ *
+ * Less memory can be allocated for the send buffer, but this will result in
+ * smaller, more fragmented records and increased overhead. While the absolute
+ * minimum size required is 1025 bytes, at least 2K bytes is recommended for
+ * reasonable record sizes.
+ *
+ * More memory can be allocated for the send buffer. This will result in s2n-tls
+ * buffering multiple records before sending them, reducing system write calls.
+ * At least 17K bytes is recommended for this use case, or at least 35K bytes
+ * if larger fragment sizes are used via `s2n_connection_prefer_throughput()`.
+ *
+ * @param config The configuration object being updated
+ * @param size The desired custom buffer size.
+ * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
+ */
+S2N_API
+extern int s2n_config_set_send_buffer_size(struct s2n_config *config, uint32_t size);
+
+/**
* A callback function invoked (usually multiple times) during X.509 validation for each
* name encountered in the leaf certificate.
*
diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.c b/contrib/restricted/aws/s2n/error/s2n_errno.c
index 3ade2ea4ee..f2848af900 100644
--- a/contrib/restricted/aws/s2n/error/s2n_errno.c
+++ b/contrib/restricted/aws/s2n/error/s2n_errno.c
@@ -94,7 +94,11 @@ static const char *no_such_error = "Internal s2n error";
ERR_ENTRY(S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO, "renegotiation_info should be empty") \
ERR_ENTRY(S2N_ERR_RECORD_LIMIT, "TLS record limit reached") \
ERR_ENTRY(S2N_ERR_CERT_UNTRUSTED, "Certificate is untrusted") \
+ ERR_ENTRY(S2N_ERR_CERT_REVOKED, "Certificate has been revoked by the CA") \
+ ERR_ENTRY(S2N_ERR_CERT_EXPIRED, "Certificate has expired") \
ERR_ENTRY(S2N_ERR_CERT_TYPE_UNSUPPORTED, "Certificate Type is unsupported") \
+ ERR_ENTRY(S2N_ERR_CERT_INVALID, "Certificate is invalid") \
+ ERR_ENTRY(S2N_ERR_CERT_MAX_CHAIN_DEPTH_EXCEEDED, "The maximum certificate chain depth has been exceeded") \
ERR_ENTRY(S2N_ERR_INVALID_MAX_FRAG_LEN, "invalid Maximum Fragmentation Length encountered") \
ERR_ENTRY(S2N_ERR_MAX_FRAG_LEN_MISMATCH, "Negotiated Maximum Fragmentation Length from server does not match the requested length by client") \
ERR_ENTRY(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED, "TLS protocol version is not supported by configuration") \
@@ -270,7 +274,8 @@ 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_CERT_OWNERSHIP, "The ownership of the certificate chain is incompatible with the operation")
+ 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 */
#define ERR_STR_CASE(ERR, str) case ERR: return str;
diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.h b/contrib/restricted/aws/s2n/error/s2n_errno.h
index a257500ef4..f0901c768b 100644
--- a/contrib/restricted/aws/s2n/error/s2n_errno.h
+++ b/contrib/restricted/aws/s2n/error/s2n_errno.h
@@ -107,7 +107,11 @@ typedef enum {
S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO,
S2N_ERR_RECORD_LIMIT,
S2N_ERR_CERT_UNTRUSTED,
+ S2N_ERR_CERT_REVOKED,
+ S2N_ERR_CERT_EXPIRED,
S2N_ERR_CERT_TYPE_UNSUPPORTED,
+ S2N_ERR_CERT_INVALID,
+ S2N_ERR_CERT_MAX_CHAIN_DEPTH_EXCEEDED,
S2N_ERR_INVALID_MAX_FRAG_LEN,
S2N_ERR_MAX_FRAG_LEN_MISMATCH,
S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED,
@@ -288,6 +292,7 @@ typedef enum {
S2N_ERR_KEYING_MATERIAL_EXPIRED,
S2N_ERR_SECRET_SCHEDULE_STATE,
S2N_ERR_CERT_OWNERSHIP,
+ S2N_ERR_INTERNAL_LIBCRYPTO_ERROR,
S2N_ERR_T_USAGE_END,
} s2n_error;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c
index 05063011c7..243cd753ee 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c
@@ -88,9 +88,8 @@ int s2n_server_certificate_status_recv(struct s2n_connection *conn, struct s2n_s
POSIX_GUARD(s2n_realloc(&conn->status_response, status_size));
POSIX_GUARD(s2n_stuffer_read_bytes(in, conn->status_response.data, status_size));
- POSIX_ENSURE(s2n_x509_validator_validate_cert_stapled_ocsp_response(
- &conn->x509_validator, conn, conn->status_response.data, conn->status_response.size) == S2N_CERT_OK,
- S2N_ERR_CERT_UNTRUSTED);
+ POSIX_GUARD_RESULT(s2n_x509_validator_validate_cert_stapled_ocsp_response(&conn->x509_validator, conn,
+ conn->status_response.data, conn->status_response.size));
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_alerts.c b/contrib/restricted/aws/s2n/tls/s2n_alerts.c
index c745a0d193..51f13b416f 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_alerts.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_alerts.c
@@ -96,7 +96,11 @@ static S2N_RESULT s2n_translate_protocol_error_to_alert(int error_code, uint8_t
S2N_NO_ALERT(S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
S2N_NO_ALERT(S2N_ERR_RECORD_LIMIT);
S2N_NO_ALERT(S2N_ERR_CERT_UNTRUSTED);
+ S2N_NO_ALERT(S2N_ERR_CERT_REVOKED);
+ S2N_NO_ALERT(S2N_ERR_CERT_EXPIRED);
S2N_NO_ALERT(S2N_ERR_CERT_TYPE_UNSUPPORTED);
+ S2N_NO_ALERT(S2N_ERR_CERT_INVALID);
+ S2N_NO_ALERT(S2N_ERR_CERT_MAX_CHAIN_DEPTH_EXCEEDED);
S2N_NO_ALERT(S2N_ERR_INVALID_MAX_FRAG_LEN);
S2N_NO_ALERT(S2N_ERR_MAX_FRAG_LEN_MISMATCH);
S2N_NO_ALERT(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_cert.c b/contrib/restricted/aws/s2n/tls/s2n_client_cert.c
index 757b13430d..6795ea8626 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_cert.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_cert.c
@@ -122,9 +122,8 @@ int s2n_client_cert_recv(struct s2n_connection *conn)
s2n_pkey_type pkey_type;
/* Determine the Cert Type, Verify the Cert, and extract the Public Key */
- S2N_ERROR_IF(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, conn,
- client_cert_chain.data, client_cert_chain.size,
- &pkey_type, &public_key) != S2N_CERT_OK, S2N_ERR_CERT_UNTRUSTED);
+ POSIX_GUARD_RESULT(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, conn, client_cert_chain.data,
+ client_cert_chain.size, &pkey_type, &public_key));
conn->handshake_params.client_cert_pkey_type = pkey_type;
POSIX_GUARD(s2n_pkey_setup_for_type(&public_key, pkey_type));
diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.c b/contrib/restricted/aws/s2n/tls/s2n_config.c
index dd8e06b0ad..ce7c666097 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_config.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_config.c
@@ -986,3 +986,10 @@ int s2n_config_client_hello_cb_enable_poll(struct s2n_config *config) {
return S2N_SUCCESS;
}
+
+int s2n_config_set_send_buffer_size(struct s2n_config *config, uint32_t size) {
+ POSIX_ENSURE_REF(config);
+ POSIX_ENSURE(size > S2N_TLS_MAX_RECORD_LEN_FOR(0), S2N_ERR_INVALID_ARGUMENT);
+ config->send_buffer_size_override = size;
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.h b/contrib/restricted/aws/s2n/tls/s2n_config.h
index cfc7474c04..c128dd82bb 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_config.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_config.h
@@ -149,6 +149,9 @@ struct s2n_config {
void *context;
s2n_cert_ownership cert_ownership;
+
+ /* Used to override the stuffer size for a connection's `out` stuffer. */
+ uint32_t send_buffer_size_override;
};
S2N_CLEANUP_RESULT s2n_config_ptr_free(struct s2n_config **config);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.c b/contrib/restricted/aws/s2n/tls/s2n_connection.c
index eb965d3836..92b51cdb25 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection.c
@@ -434,6 +434,10 @@ int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *co
POSIX_GUARD(s2n_connection_enable_quic(conn));
}
+ if (config->send_buffer_size_override) {
+ conn->multirecord_send = true;
+ }
+
conn->config = config;
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.h b/contrib/restricted/aws/s2n/tls/s2n_connection.h
index be375551b1..2965de74e6 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection.h
@@ -123,6 +123,10 @@ struct s2n_connection {
/* Connection successfully set a ticket on the connection */
unsigned set_session:1;
+ /* Buffer multiple records before flushing them.
+ * This allows multiple records to be written with one socket send. */
+ unsigned multirecord_send:1;
+
/* The configuration (cert, key .. etc ) */
struct s2n_config *config;
@@ -277,7 +281,8 @@ struct s2n_connection {
/* Reset record size back to a single segment after threshold seconds of inactivity */
uint16_t dynamic_record_timeout_threshold;
- /* number of bytes consumed during application activity */
+ /* The number of bytes consumed during a period of application activity.
+ * Used for dynamic record sizing. */
uint64_t active_application_bytes_consumed;
/* Negotiated TLS extension Maximum Fragment Length code.
diff --git a/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c b/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c
index 1f3d9a9750..2af36c5a2f 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c
@@ -84,7 +84,7 @@ static bool s2n_is_early_data_io(struct s2n_connection *conn)
S2N_RESULT s2n_early_data_record_bytes(struct s2n_connection *conn, ssize_t data_len)
{
RESULT_ENSURE_REF(conn);
- if (!s2n_is_early_data_io(conn)) {
+ if (data_len < 0 || !s2n_is_early_data_io(conn)) {
return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_key_update.c b/contrib/restricted/aws/s2n/tls/s2n_key_update.c
index 3c862eb98e..6e8fbaca37 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_key_update.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_key_update.c
@@ -65,6 +65,15 @@ int s2n_key_update_send(struct s2n_connection *conn, s2n_blocked_status *blocked
POSIX_GUARD(s2n_check_record_limit(conn, &sequence_number));
if (conn->key_update_pending) {
+ /* Flush any buffered records to ensure an empty output buffer.
+ *
+ * This is important when buffering multiple records because we don't:
+ * 1) Respect max fragment length for handshake messages
+ * 2) Check if there is sufficient space in the output buffer for
+ * post-handshake messages.
+ */
+ POSIX_GUARD(s2n_flush(conn, blocked));
+
uint8_t key_update_data[S2N_KEY_UPDATE_MESSAGE_SIZE];
struct s2n_blob key_update_blob = {0};
POSIX_GUARD(s2n_blob_init(&key_update_blob, key_update_data, sizeof(key_update_data)));
diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_write.c b/contrib/restricted/aws/s2n/tls/s2n_record_write.c
index c9c654f983..323a3ce944 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_record_write.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_record_write.c
@@ -74,11 +74,26 @@ static S2N_RESULT s2n_tls_record_overhead(struct s2n_connection *conn, uint16_t
S2N_RESULT s2n_record_max_write_payload_size(struct s2n_connection *conn, uint16_t *max_fragment_size)
{
RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->config);
RESULT_ENSURE_MUT(max_fragment_size);
RESULT_ENSURE(conn->max_outgoing_fragment_length > 0, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
*max_fragment_size = MIN(conn->max_outgoing_fragment_length, S2N_TLS_MAXIMUM_FRAGMENT_LENGTH);
+ /* If a custom send buffer is configured, ensure it will be large enough for the payload.
+ * That may mean we need a smaller fragment size.
+ */
+ uint32_t send_buffer_override = conn->config->send_buffer_size_override;
+ if (send_buffer_override) {
+ uint16_t max_record_size = 0;
+ RESULT_GUARD(s2n_record_max_write_size(conn, *max_fragment_size, &max_record_size));
+ if (send_buffer_override < max_record_size) {
+ size_t overhead = (max_record_size - *max_fragment_size);
+ RESULT_ENSURE_GT(send_buffer_override, overhead);
+ *max_fragment_size = send_buffer_override - overhead;
+ }
+ }
+
return S2N_RESULT_OK;
}
@@ -143,7 +158,7 @@ S2N_RESULT s2n_record_min_write_payload_size(struct s2n_connection *conn, uint16
return S2N_RESULT_OK;
}
-int s2n_record_write_protocol_version(struct s2n_connection *conn)
+int s2n_record_write_protocol_version(struct s2n_connection *conn, struct s2n_stuffer *out)
{
uint8_t record_protocol_version = conn->actual_protocol_version;
if (conn->server_protocol_version == s2n_unknown_protocol_version
@@ -164,7 +179,7 @@ int s2n_record_write_protocol_version(struct s2n_connection *conn)
protocol_version[0] = record_protocol_version / 10;
protocol_version[1] = record_protocol_version % 10;
- POSIX_GUARD(s2n_stuffer_write_bytes(&conn->out, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(out, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
return 0;
}
@@ -250,7 +265,10 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
const int is_tls13_record = cipher_suite->record_alg->flags & S2N_TLS13_RECORD_AEAD_NONCE;
s2n_stack_blob(aad, is_tls13_record ? S2N_TLS13_AAD_LEN : S2N_TLS_MAX_AAD_LEN, S2N_TLS_MAX_AAD_LEN);
- S2N_ERROR_IF(s2n_stuffer_data_available(&conn->out), S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
+ /* If we aren't buffering multiple records, then the output stuffer should be empty. */
+ if (!conn->multirecord_send) {
+ POSIX_ENSURE(s2n_stuffer_data_available(&conn->out) == 0, S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
+ }
uint8_t mac_digest_size;
POSIX_GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size));
@@ -279,37 +297,51 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
POSIX_GUARD(s2n_hmac_update(mac, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
if (s2n_stuffer_is_freed(&conn->out)) {
- /* If the output buffer has not been allocated yet, allocate enough memory to hold
- * a record with the local maximum fragment length. Because this only occurs if the
- * output buffer has not been allocated, it does NOT resize existing buffers.
+ /* If the output buffer has not been allocated yet, allocate
+ * at least enough memory to hold a record with the local maximum fragment length.
*
- * The maximum fragment length is:
+ * The local maximum fragment length is:
* 1) The local default configured for new connections
* 2) The local value set by the user via s2n_connection_prefer_throughput()
* or s2n_connection_prefer_low_latency()
* 3) On the server, the minimum of the local value and the value negotiated with the
* client via the max_fragment_length extension
+ *
+ * Because this only occurs if the output buffer has not been allocated,
+ * it does NOT resize existing buffers.
*/
uint16_t max_wire_record_size = 0;
POSIX_GUARD_RESULT(s2n_record_max_write_size(conn, max_write_payload_size, &max_wire_record_size));
- POSIX_GUARD(s2n_stuffer_growable_alloc(&conn->out, max_wire_record_size));
+
+ uint32_t buffer_size = MAX(conn->config->send_buffer_size_override, max_wire_record_size);
+ POSIX_GUARD(s2n_stuffer_growable_alloc(&conn->out, buffer_size));
}
+ /* A record only local stuffer used to avoid tainting the conn->out stuffer or overwriting
+ * previous records. It should be used to add an individual record to the out stuffer.
+ */
+ struct s2n_blob record_blob = { 0 };
+ struct s2n_stuffer record_stuffer = { 0 };
+ POSIX_GUARD(s2n_blob_init(&record_blob,
+ conn->out.blob.data + conn->out.write_cursor,
+ s2n_stuffer_space_remaining(&conn->out)));
+ POSIX_GUARD(s2n_stuffer_init(&record_stuffer, &record_blob));
+
/* Now that we know the length, start writing the record */
- POSIX_GUARD(s2n_stuffer_write_uint8(&conn->out, is_tls13_record ?
+ POSIX_GUARD(s2n_stuffer_write_uint8(&record_stuffer, is_tls13_record ?
/* tls 1.3 opaque type */ TLS_APPLICATION_DATA :
/* actual content_type */ content_type ));
- POSIX_GUARD(s2n_record_write_protocol_version(conn));
+ POSIX_GUARD(s2n_record_write_protocol_version(conn, &record_stuffer));
/* First write a header that has the payload length, this is for the MAC */
- POSIX_GUARD(s2n_stuffer_write_uint16(&conn->out, data_bytes_to_take));
+ POSIX_GUARD(s2n_stuffer_write_uint16(&record_stuffer, data_bytes_to_take));
if (conn->actual_protocol_version > S2N_SSLv3) {
- POSIX_GUARD(s2n_hmac_update(mac, conn->out.blob.data, S2N_TLS_RECORD_HEADER_LENGTH));
+ POSIX_GUARD(s2n_hmac_update(mac, record_stuffer.blob.data, S2N_TLS_RECORD_HEADER_LENGTH));
} else {
/* SSLv3 doesn't include the protocol version in the MAC */
- POSIX_GUARD(s2n_hmac_update(mac, conn->out.blob.data, 1));
- POSIX_GUARD(s2n_hmac_update(mac, conn->out.blob.data + 3, 2));
+ POSIX_GUARD(s2n_hmac_update(mac, record_stuffer.blob.data, 1));
+ POSIX_GUARD(s2n_hmac_update(mac, record_stuffer.blob.data + 3, 2));
}
/* Compute non-payload parts of the MAC(seq num, type, proto vers, fragment length) for composite ciphers.
@@ -339,8 +371,8 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
/* ensure actual_fragment_length + S2N_TLS_RECORD_HEADER_LENGTH <= max record length */
const uint16_t max_record_length = is_tls13_record ? S2N_TLS13_MAXIMUM_RECORD_LENGTH : S2N_TLS_MAXIMUM_RECORD_LENGTH;
S2N_ERROR_IF(actual_fragment_length + S2N_TLS_RECORD_HEADER_LENGTH > max_record_length, S2N_ERR_RECORD_LENGTH_TOO_LARGE);
- POSIX_GUARD(s2n_stuffer_wipe_n(&conn->out, 2));
- POSIX_GUARD(s2n_stuffer_write_uint16(&conn->out, actual_fragment_length));
+ POSIX_GUARD(s2n_stuffer_wipe_n(&record_stuffer, 2));
+ POSIX_GUARD(s2n_stuffer_write_uint16(&record_stuffer, actual_fragment_length));
/* If we're AEAD, write the sequence number as an IV, and generate the AAD */
if (cipher_suite->record_alg->cipher->type == S2N_AEAD) {
@@ -350,7 +382,7 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
if (cipher_suite->record_alg->flags & S2N_TLS12_AES_GCM_AEAD_NONCE) {
/* Partially explicit nonce. See RFC 5288 Section 3 */
- POSIX_GUARD(s2n_stuffer_write_bytes(&conn->out, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&record_stuffer, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, implicit_iv, cipher_suite->record_alg->cipher->io.aead.fixed_iv_size));
POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
} else if (cipher_suite->record_alg->flags & S2N_TLS12_CHACHA_POLY_AEAD_NONCE || is_tls13_record) {
@@ -396,12 +428,12 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
uint8_t zero_block[S2N_TLS_MAX_IV_LEN] = { 0 };
POSIX_GUARD(s2n_blob_init(&explicit_iv_placeholder, zero_block, block_size));
POSIX_GUARD_RESULT(s2n_get_public_random_data(&explicit_iv_placeholder));
- POSIX_GUARD(s2n_stuffer_write(&conn->out, &explicit_iv_placeholder));
+ POSIX_GUARD(s2n_stuffer_write(&record_stuffer, &explicit_iv_placeholder));
} else {
/* We can write the explicit IV directly to the record for non composite CBC because
* s2n starts AES *after* the explicit IV.
*/
- POSIX_GUARD(s2n_stuffer_write(&conn->out, &iv));
+ POSIX_GUARD(s2n_stuffer_write(&record_stuffer, &iv));
}
}
}
@@ -411,12 +443,12 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
POSIX_GUARD(s2n_increment_sequence_number(&seq));
/* Write the plaintext data */
- POSIX_GUARD(s2n_stuffer_writev_bytes(&conn->out, in, in_count, offs, data_bytes_to_take));
- void *orig_write_ptr = conn->out.blob.data + conn->out.write_cursor - data_bytes_to_take;
+ POSIX_GUARD(s2n_stuffer_writev_bytes(&record_stuffer, in, in_count, offs, data_bytes_to_take));
+ void *orig_write_ptr = record_stuffer.blob.data + record_stuffer.write_cursor - data_bytes_to_take;
POSIX_GUARD(s2n_hmac_update(mac, orig_write_ptr, data_bytes_to_take));
/* Write the digest */
- uint8_t *digest = s2n_stuffer_raw_write(&conn->out, mac_digest_size);
+ uint8_t *digest = s2n_stuffer_raw_write(&record_stuffer, mac_digest_size);
POSIX_ENSURE_REF(digest);
POSIX_GUARD(s2n_hmac_digest(mac, digest, mac_digest_size));
@@ -424,7 +456,7 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
/* Write content type for TLS 1.3 record (RFC 8446 Section 5.2) */
if (is_tls13_record) {
- POSIX_GUARD(s2n_stuffer_write_uint8(&conn->out, content_type));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&record_stuffer, content_type));
}
if (cipher_suite->record_alg->cipher->type == S2N_CBC) {
@@ -432,20 +464,20 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
* include an extra padding length byte, also with the value 'p'.
*/
for (int i = 0; i <= padding; i++) {
- POSIX_GUARD(s2n_stuffer_write_uint8(&conn->out, padding));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&record_stuffer, padding));
}
}
/* Rewind to rewrite/encrypt the packet */
- POSIX_GUARD(s2n_stuffer_rewrite(&conn->out));
+ POSIX_GUARD(s2n_stuffer_rewrite(&record_stuffer));
/* Skip the header */
- POSIX_GUARD(s2n_stuffer_skip_write(&conn->out, S2N_TLS_RECORD_HEADER_LENGTH));
+ POSIX_GUARD(s2n_stuffer_skip_write(&record_stuffer, S2N_TLS_RECORD_HEADER_LENGTH));
uint16_t encrypted_length = data_bytes_to_take + mac_digest_size;
switch (cipher_suite->record_alg->cipher->type) {
case S2N_AEAD:
- POSIX_GUARD(s2n_stuffer_skip_write(&conn->out, cipher_suite->record_alg->cipher->io.aead.record_iv_size));
+ POSIX_GUARD(s2n_stuffer_skip_write(&record_stuffer, cipher_suite->record_alg->cipher->io.aead.record_iv_size));
encrypted_length += cipher_suite->record_alg->cipher->io.aead.tag_size;
if (is_tls13_record) {
/* one extra byte for content type */
@@ -455,7 +487,7 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
case S2N_CBC:
if (conn->actual_protocol_version > S2N_TLS10) {
/* Leave the IV alone and unencrypted */
- POSIX_GUARD(s2n_stuffer_skip_write(&conn->out, iv.size));
+ POSIX_GUARD(s2n_stuffer_skip_write(&record_stuffer, iv.size));
}
/* Encrypt the padding and the padding length byte too */
encrypted_length += padding + 1;
@@ -471,12 +503,15 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
}
/* Check that stuffer have enough space to write encrypted record, because raw_write cannot expand tainted stuffer */
- S2N_ERROR_IF(s2n_stuffer_space_remaining(&conn->out) < encrypted_length, S2N_ERR_RECORD_STUFFER_SIZE);
+ S2N_ERROR_IF(s2n_stuffer_space_remaining(&record_stuffer) < encrypted_length, S2N_ERR_RECORD_STUFFER_SIZE);
/* Do the encryption */
- struct s2n_blob en = { .size = encrypted_length, .data = s2n_stuffer_raw_write(&conn->out, encrypted_length) };
+ struct s2n_blob en = { .size = encrypted_length, .data = s2n_stuffer_raw_write(&record_stuffer, encrypted_length) };
POSIX_GUARD(s2n_record_encrypt(conn, cipher_suite, session_key, &iv, &aad, &en, implicit_iv, block_size));
+ /* Sync the out stuffer write cursor with the record stuffer. */
+ POSIX_GUARD(s2n_stuffer_skip_write(&conn->out, s2n_stuffer_data_available(&record_stuffer)));
+
if (conn->actual_protocol_version == S2N_TLS13 && content_type == TLS_CHANGE_CIPHER_SPEC) {
conn->client = current_client_crypto;
conn->server = current_server_crypto;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_recv.c b/contrib/restricted/aws/s2n/tls/s2n_recv.c
index 3d0907573f..bbf48b1ff8 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_recv.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_recv.c
@@ -199,7 +199,6 @@ ssize_t s2n_recv_impl(struct s2n_connection * conn, void *buf, ssize_t size, s2n
*blocked = S2N_NOT_BLOCKED;
}
- POSIX_GUARD_RESULT(s2n_early_data_record_bytes(conn, bytes_read));
return bytes_read;
}
@@ -208,11 +207,23 @@ 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));
conn->recv_in_use = false;
return result;
}
uint32_t s2n_peek(struct s2n_connection *conn) {
+ if (conn == NULL) {
+ return 0;
+ }
+
+ /* If we have partially buffered an encrypted record,
+ * we should not report those bytes as available to read.
+ */
+ if (conn->in_status != PLAINTEXT) {
+ return 0;
+ }
+
return s2n_stuffer_data_available(&conn->in);
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_resume.c b/contrib/restricted/aws/s2n/tls/s2n_resume.c
index 31ba8e97a0..952ae9cbde 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_resume.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_resume.c
@@ -316,7 +316,7 @@ static S2N_RESULT s2n_tls13_deserialize_session_state(struct s2n_connection *con
return S2N_RESULT_OK;
}
-static S2N_RESULT s2n_deserialize_resumption_state(struct s2n_connection *conn, struct s2n_blob *psk_identity, struct s2n_stuffer *from)
+S2N_RESULT s2n_deserialize_resumption_state(struct s2n_connection *conn, struct s2n_blob *psk_identity, struct s2n_stuffer *from)
{
RESULT_ENSURE_REF(conn);
RESULT_ENSURE_REF(from);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_resume.h b/contrib/restricted/aws/s2n/tls/s2n_resume.h
index 2d104d6b4c..326307acf9 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_resume.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_resume.h
@@ -99,3 +99,6 @@ extern int s2n_allowed_to_cache_connection(struct s2n_connection *conn);
extern int s2n_resume_from_cache(struct s2n_connection *conn);
S2N_RESULT s2n_store_to_cache(struct s2n_connection *conn);
S2N_RESULT s2n_connection_get_session_state_size(struct s2n_connection *conn, size_t *state_size);
+S2N_RESULT s2n_deserialize_resumption_state(struct s2n_connection *conn, struct s2n_blob *psk_identity,
+ struct s2n_stuffer *from);
+
diff --git a/contrib/restricted/aws/s2n/tls/s2n_send.c b/contrib/restricted/aws/s2n/tls/s2n_send.c
index 013fa28b66..cc7188eb73 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_send.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_send.c
@@ -32,7 +32,46 @@
#include "utils/s2n_safety.h"
#include "utils/s2n_blob.h"
-int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * blocked)
+bool s2n_should_flush(struct s2n_connection *conn, ssize_t total_message_size)
+{
+ /* Always flush if not buffering multiple records. */
+ if (!conn->multirecord_send) {
+ return true;
+ }
+
+ /* Flush if all data has been sent. */
+ ssize_t remaining_payload_size = total_message_size - conn->current_user_data_consumed;
+ if (remaining_payload_size <= 0) {
+ return true;
+ }
+
+ uint16_t max_payload_size = 0;
+ if (!s2n_result_is_ok(s2n_record_max_write_payload_size(conn, &max_payload_size))) {
+ /* When in doubt, flush */
+ return true;
+ }
+ max_payload_size = MIN(max_payload_size, remaining_payload_size);
+
+ uint16_t max_write_size = 0;
+ if (!s2n_result_is_ok(s2n_record_max_write_size(conn, max_payload_size, &max_write_size))) {
+ /* When in doubt, flush */
+ return true;
+ }
+
+ /* Flush if the stuffer can't store the max possible record size without growing.
+ *
+ * However, the stuffer is allocated when the record is sent, so if the stuffer
+ * hasn't been allocated, assume it will have enough space.
+ */
+ uint32_t available_space = s2n_stuffer_space_remaining(&conn->out);
+ if (available_space < max_write_size && !s2n_stuffer_is_freed(&conn->out)) {
+ return true;
+ }
+
+ return false;
+}
+
+int s2n_flush(struct s2n_connection *conn, s2n_blocked_status *blocked)
{
int w;
@@ -168,40 +207,39 @@ ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iov
cbcHackUsed = 1;
}
}
-
- POSIX_GUARD(s2n_stuffer_rewrite(&conn->out));
POSIX_GUARD(s2n_post_handshake_send(conn, blocked));
/* Write and encrypt the record */
- POSIX_GUARD(s2n_record_writev(conn, TLS_APPLICATION_DATA, bufs, count,
- conn->current_user_data_consumed + offs, to_write));
- conn->current_user_data_consumed += to_write;
- conn->active_application_bytes_consumed += to_write;
-
- /* Send it */
- if (s2n_flush(conn, blocked) < 0) {
- if (s2n_errno == S2N_ERR_IO_BLOCKED && user_data_sent > 0) {
- /* We successfully sent >0 user bytes on the wire, but not the full requested payload
- * because we became blocked on I/O. Acknowledge the data sent. */
-
- conn->current_user_data_consumed -= user_data_sent;
- return user_data_sent;
- } else {
- S2N_ERROR_PRESERVE_ERRNO();
+ int written_to_record = s2n_record_writev(conn, TLS_APPLICATION_DATA, bufs, count,
+ conn->current_user_data_consumed + offs, to_write);
+ POSIX_GUARD(written_to_record);
+ conn->current_user_data_consumed += written_to_record;
+ conn->active_application_bytes_consumed += written_to_record;
+
+ /* Send it, unless we're waiting for more records */
+ if (s2n_should_flush(conn, total_size)) {
+ if (s2n_flush(conn, blocked) < 0) {
+ if (s2n_errno == S2N_ERR_IO_BLOCKED && user_data_sent > 0) {
+ /* We successfully sent >0 user bytes on the wire, but not the full requested payload
+ * because we became blocked on I/O. Acknowledge the data sent. */
+
+ conn->current_user_data_consumed -= user_data_sent;
+ return user_data_sent;
+ } else {
+ S2N_ERROR_PRESERVE_ERRNO();
+ }
}
- }
- /* Acknowledge consumed and flushed user data as sent */
- user_data_sent = conn->current_user_data_consumed;
+ /* Acknowledge consumed and flushed user data as sent */
+ user_data_sent = conn->current_user_data_consumed;
+ }
}
/* If everything has been written, then there's no user data pending */
conn->current_user_data_consumed = 0;
*blocked = S2N_NOT_BLOCKED;
-
- POSIX_GUARD_RESULT(s2n_early_data_record_bytes(conn, total_size));
return total_size;
}
@@ -210,6 +248,7 @@ 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));
conn->send_in_use = false;
return result;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_cert.c b/contrib/restricted/aws/s2n/tls/s2n_server_cert.c
index 6be1ac6202..1328f59286 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_cert.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_cert.c
@@ -45,8 +45,8 @@ int s2n_server_cert_recv(struct s2n_connection *conn)
cert_chain.data = s2n_stuffer_raw_read(&conn->handshake.io, size_of_all_certificates);
POSIX_ENSURE_REF(cert_chain.data);
- POSIX_ENSURE(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, conn, cert_chain.data,
- cert_chain.size, &actual_cert_pkey_type, &public_key) == S2N_CERT_OK, S2N_ERR_CERT_UNTRUSTED);
+ POSIX_GUARD_RESULT(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, conn, cert_chain.data,
+ cert_chain.size, &actual_cert_pkey_type, &public_key));
POSIX_GUARD(s2n_is_cert_type_valid_for_auth(conn, actual_cert_pkey_type));
POSIX_GUARD(s2n_pkey_setup_for_type(&public_key, actual_cert_pkey_type));
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c b/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c
index a0af0e56ac..08b5371d24 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c
@@ -150,6 +150,21 @@ S2N_RESULT s2n_tls13_server_nst_send(struct s2n_connection *conn, s2n_blocked_st
RESULT_ENSURE(conn->tickets_sent <= conn->tickets_to_send, S2N_ERR_INTEGER_OVERFLOW);
+ /* Flush any buffered records to ensure an empty output buffer.
+ *
+ * This is important when buffering multiple records because we don't:
+ * 1) Respect max fragment length for handshake messages
+ * 2) Check if there is sufficient space in the output buffer for
+ * post-handshake messages.
+ *
+ * Careful how this flush fits into the ordering of this method:
+ * We want to avoid unnecessary work like repeatedly encrypting
+ * the ticket if the flush repeatedly blocks, but we also want
+ * to avoid unnecessarily flushing if no ticket will actually
+ * need to be sent.
+ */
+ RESULT_GUARD_POSIX(s2n_flush(conn, blocked));
+
size_t session_state_size = 0;
RESULT_GUARD(s2n_connection_get_session_state_size(conn, &session_state_size));
const size_t maximum_nst_size = session_state_size + S2N_TLS13_MAX_FIXED_NEW_SESSION_TICKET_SIZE;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
index 4506878ced..39f24eacd3 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
@@ -30,8 +30,10 @@
#include <openssl/asn1.h>
#include <openssl/x509.h>
-#if !defined(OPENSSL_IS_BORINGSSL)
+#if S2N_OCSP_STAPLING_SUPPORTED
#include <openssl/ocsp.h>
+DEFINE_POINTER_CLEANUP_FUNC(OCSP_RESPONSE*, OCSP_RESPONSE_free);
+DEFINE_POINTER_CLEANUP_FUNC(OCSP_BASICRESP*, OCSP_BASICRESP_free);
#endif
#ifndef X509_V_FLAG_PARTIAL_CHAIN
@@ -284,16 +286,16 @@ static uint8_t s2n_verify_host_information(struct s2n_x509_validator *validator,
return verified;
}
-s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_validator *validator, struct s2n_connection *conn,
+S2N_RESULT s2n_x509_validator_validate_cert_chain(struct s2n_x509_validator *validator, struct s2n_connection *conn,
uint8_t *cert_chain_in, uint32_t cert_chain_len, s2n_pkey_type *pkey_type, struct s2n_pkey *public_key_out) {
- S2N_ERROR_IF(!validator->skip_cert_validation && !s2n_x509_trust_store_has_certs(validator->trust_store), S2N_ERR_CERT_UNTRUSTED);
- S2N_ERROR_IF(validator->state != INIT, S2N_ERR_INVALID_CERT_STATE);
+ RESULT_ENSURE(validator->skip_cert_validation || s2n_x509_trust_store_has_certs(validator->trust_store), S2N_ERR_CERT_UNTRUSTED);
+ RESULT_ENSURE(validator->state == INIT, S2N_ERR_INVALID_CERT_STATE);
struct s2n_blob cert_chain_blob = {.data = cert_chain_in, .size = cert_chain_len};
DEFER_CLEANUP(struct s2n_stuffer cert_chain_in_stuffer = {0}, s2n_stuffer_free);
- S2N_ERROR_IF(s2n_stuffer_init(&cert_chain_in_stuffer, &cert_chain_blob) < 0, S2N_ERR_CERT_UNTRUSTED);
- S2N_ERROR_IF(s2n_stuffer_write(&cert_chain_in_stuffer, &cert_chain_blob) < 0, S2N_ERR_CERT_UNTRUSTED);
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&cert_chain_in_stuffer, &cert_chain_blob));
+ RESULT_GUARD_POSIX(s2n_stuffer_write(&cert_chain_in_stuffer, &cert_chain_blob));
s2n_parsed_extensions_list first_certificate_extensions = {0};
@@ -305,39 +307,43 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_
while (s2n_stuffer_data_available(&cert_chain_in_stuffer) && sk_X509_num(validator->cert_chain_from_wire) < validator->max_chain_depth) {
uint32_t certificate_size = 0;
- S2N_ERROR_IF(s2n_stuffer_read_uint24(&cert_chain_in_stuffer, &certificate_size) < 0, S2N_ERR_CERT_UNTRUSTED);
- S2N_ERROR_IF(certificate_size == 0 || certificate_size > s2n_stuffer_data_available(&cert_chain_in_stuffer), S2N_ERR_CERT_UNTRUSTED);
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint24(&cert_chain_in_stuffer, &certificate_size));
+ RESULT_ENSURE(certificate_size > 0, S2N_ERR_CERT_INVALID);
+ RESULT_ENSURE(certificate_size <= s2n_stuffer_data_available(&cert_chain_in_stuffer), S2N_ERR_CERT_INVALID);
struct s2n_blob asn1cert = {0};
asn1cert.size = certificate_size;
asn1cert.data = s2n_stuffer_raw_read(&cert_chain_in_stuffer, certificate_size);
- POSIX_ENSURE_REF(asn1cert.data);
+ RESULT_ENSURE_REF(asn1cert.data);
const uint8_t *data = asn1cert.data;
/* the cert is der encoded, just convert it. */
server_cert = d2i_X509(NULL, &data, asn1cert.size);
- S2N_ERROR_IF(!server_cert, S2N_ERR_CERT_UNTRUSTED);
+ RESULT_ENSURE_REF(server_cert);
/* add the cert to the chain. */
if (!sk_X509_push(validator->cert_chain_from_wire, server_cert)) {
+ /* After the cert is added to cert_chain_from_wire, it will be freed with the call to
+ * s2n_x509_validator_wipe. If adding the cert fails, free it now instead. */
X509_free(server_cert);
- POSIX_BAIL(S2N_ERR_CERT_UNTRUSTED);
+ RESULT_BAIL(S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
}
if (!validator->skip_cert_validation) {
- POSIX_GUARD_RESULT(s2n_validate_certificate_signature(conn, server_cert));
+ RESULT_ENSURE_OK(s2n_validate_certificate_signature(conn, server_cert), S2N_ERR_CERT_UNTRUSTED);
}
/* Pull the public key from the first certificate */
if (sk_X509_num(validator->cert_chain_from_wire) == 1) {
- S2N_ERROR_IF(s2n_asn1der_to_public_key_and_type(&public_key, pkey_type, &asn1cert) < 0, S2N_ERR_CERT_UNTRUSTED);
+ RESULT_ENSURE(s2n_asn1der_to_public_key_and_type(&public_key, pkey_type, &asn1cert) == 0,
+ S2N_ERR_CERT_UNTRUSTED);
}
/* certificate extensions is a field in TLS 1.3 - https://tools.ietf.org/html/rfc8446#section-4.4.2 */
if (conn->actual_protocol_version >= S2N_TLS13) {
s2n_parsed_extensions_list parsed_extensions_list = { 0 };
- POSIX_GUARD(s2n_extension_list_parse(&cert_chain_in_stuffer, &parsed_extensions_list));
+ RESULT_GUARD_POSIX(s2n_extension_list_parse(&cert_chain_in_stuffer, &parsed_extensions_list));
/* RFC 8446: if an extension applies to the entire chain, it SHOULD be included in the first CertificateEntry */
if (sk_X509_num(validator->cert_chain_from_wire) == 1) {
@@ -347,16 +353,19 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_
}
/* if this occurred we exceeded validator->max_chain_depth */
- S2N_ERROR_IF(!validator->skip_cert_validation && s2n_stuffer_data_available(&cert_chain_in_stuffer), S2N_ERR_CERT_UNTRUSTED);
- S2N_ERROR_IF(sk_X509_num(validator->cert_chain_from_wire) < 1, S2N_ERR_CERT_UNTRUSTED);
+ RESULT_ENSURE(validator->skip_cert_validation || s2n_stuffer_data_available(&cert_chain_in_stuffer) == 0,
+ S2N_ERR_CERT_MAX_CHAIN_DEPTH_EXCEEDED);
+ RESULT_ENSURE(sk_X509_num(validator->cert_chain_from_wire) > 0, S2N_ERR_NO_CERT_FOUND);
if (!validator->skip_cert_validation) {
X509 *leaf = sk_X509_value(validator->cert_chain_from_wire, 0);
- S2N_ERROR_IF(!leaf, S2N_ERR_CERT_UNTRUSTED);
- S2N_ERROR_IF(conn->verify_host_fn && !s2n_verify_host_information(validator, conn, leaf), S2N_ERR_CERT_UNTRUSTED);
+ RESULT_ENSURE_REF(leaf);
+ if (conn->verify_host_fn) {
+ RESULT_ENSURE(s2n_verify_host_information(validator, conn, leaf), S2N_ERR_CERT_UNTRUSTED);
+ }
- int op_code = X509_STORE_CTX_init(validator->store_ctx, validator->trust_store->trust_store, leaf, validator->cert_chain_from_wire);
- S2N_ERROR_IF(op_code <= 0, S2N_ERR_CERT_UNTRUSTED);
+ RESULT_GUARD_OSSL(X509_STORE_CTX_init(validator->store_ctx, validator->trust_store->trust_store, leaf,
+ validator->cert_chain_from_wire), S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(validator->store_ctx);
X509_VERIFY_PARAM_set_depth(param, validator->max_chain_depth);
@@ -368,14 +377,22 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_
time_t current_time = (time_t)(current_sys_time / 1000000000);
X509_STORE_CTX_set_time(validator->store_ctx, 0, current_time);
- op_code = X509_verify_cert(validator->store_ctx);
+ int verify_ret = X509_verify_cert(validator->store_ctx);
+ if (verify_ret <= 0) {
+ int ossl_error = X509_STORE_CTX_get_error(validator->store_ctx);
+ switch (ossl_error) {
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ RESULT_BAIL(S2N_ERR_CERT_EXPIRED);
+ default:
+ RESULT_BAIL(S2N_ERR_CERT_UNTRUSTED);
+ }
+ }
- S2N_ERROR_IF(op_code <= 0, S2N_ERR_CERT_UNTRUSTED);
validator->state = VALIDATED;
}
if (conn->actual_protocol_version >= S2N_TLS13) {
- POSIX_GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_CERTIFICATE, conn, &first_certificate_extensions));
+ RESULT_GUARD_POSIX(s2n_extension_list_process(S2N_EXTENSION_LIST_CERTIFICATE, conn, &first_certificate_extensions));
}
*public_key_out = public_key;
@@ -383,66 +400,47 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_
/* Reset the old struct, so we don't clean up public_key_out */
s2n_pkey_zero_init(&public_key);
- return S2N_CERT_OK;
+ return S2N_RESULT_OK;
}
-s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(struct s2n_x509_validator *validator,
+S2N_RESULT s2n_x509_validator_validate_cert_stapled_ocsp_response(struct s2n_x509_validator *validator,
struct s2n_connection *conn, const uint8_t *ocsp_response_raw, uint32_t ocsp_response_length) {
if (validator->skip_cert_validation || !validator->check_stapled_ocsp) {
validator->state = OCSP_VALIDATED;
- return S2N_CERT_OK;
+ return S2N_RESULT_OK;
}
- S2N_ERROR_IF(validator->state != VALIDATED, S2N_ERR_INVALID_CERT_STATE);
+ RESULT_ENSURE(validator->state == VALIDATED, S2N_ERR_INVALID_CERT_STATE);
#if !S2N_OCSP_STAPLING_SUPPORTED
/* Default to safety */
- return S2N_CERT_ERR_UNTRUSTED;
+ RESULT_BAIL(S2N_ERR_CERT_UNTRUSTED);
#else
- OCSP_RESPONSE *ocsp_response = NULL;
- OCSP_BASICRESP *basic_response = NULL;
- STACK_OF(X509) *cert_chain = NULL;
-
- s2n_cert_validation_code ret_val = S2N_CERT_ERR_INVALID;
-
- if (!ocsp_response_raw) {
- return ret_val;
- }
-
- ocsp_response = d2i_OCSP_RESPONSE(NULL, &ocsp_response_raw, ocsp_response_length);
+ RESULT_ENSURE_REF(ocsp_response_raw);
- if (!ocsp_response) {
- goto clean_up;
- }
+ DEFER_CLEANUP(OCSP_RESPONSE *ocsp_response = d2i_OCSP_RESPONSE(NULL, &ocsp_response_raw, ocsp_response_length),
+ OCSP_RESPONSE_free_pointer);
+ RESULT_ENSURE(ocsp_response != NULL, S2N_ERR_INVALID_OCSP_RESPONSE);
int ocsp_status = OCSP_response_status(ocsp_response);
+ RESULT_ENSURE(ocsp_status == OCSP_RESPONSE_STATUS_SUCCESSFUL, S2N_ERR_CERT_UNTRUSTED);
- if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
- goto clean_up;
- }
-
- basic_response = OCSP_response_get1_basic(ocsp_response);
- if (!basic_response) {
- goto clean_up;
- }
+ DEFER_CLEANUP(OCSP_BASICRESP *basic_response = OCSP_response_get1_basic(ocsp_response), OCSP_BASICRESP_free_pointer);
+ RESULT_ENSURE(basic_response != NULL, S2N_ERR_INVALID_OCSP_RESPONSE);
/* X509_STORE_CTX_get0_chain() is better because it doesn't return a copy. But it's not available for Openssl 1.0.2.
* Therefore, we call this variant and clean it up at the end of the function.
* See the comments here:
* https://www.openssl.org/docs/man1.0.2/man3/X509_STORE_CTX_get1_chain.html
*/
- cert_chain = X509_STORE_CTX_get1_chain(validator->store_ctx);
- if (!cert_chain) {
- goto clean_up;
- }
+ DEFER_CLEANUP(STACK_OF(X509) *cert_chain = X509_STORE_CTX_get1_chain(validator->store_ctx),
+ s2n_openssl_x509_stack_pop_free);
+ RESULT_ENSURE_REF(cert_chain);
const int certs_in_chain = sk_X509_num(cert_chain);
-
- if (!certs_in_chain) {
- goto clean_up;
- }
+ RESULT_ENSURE(certs_in_chain > 0, S2N_ERR_NO_CERT_FOUND);
/* leaf is the top: not the bottom. */
X509 *subject = sk_X509_value(cert_chain, 0);
@@ -457,19 +455,11 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(
break;
}
}
-
- if (!issuer) {
- goto clean_up;
- }
+ RESULT_ENSURE(issuer != NULL, S2N_ERR_CERT_UNTRUSTED);
/* Important: this checks that the stapled ocsp response CAN be verified, not that it has been verified. */
const int ocsp_verify_res = OCSP_basic_verify(basic_response, cert_chain, validator->trust_store->trust_store, 0);
-
- /* OCSP_basic_verify() returns 1 on success, 0 on error, or -1 on fatal error such as malloc failure. */
- if (ocsp_verify_res != _OSSL_SUCCESS) {
- ret_val = ocsp_verify_res == 0 ? S2N_CERT_ERR_UNTRUSTED : S2N_CERT_ERR_INTERNAL_ERROR;
- goto clean_up;
- }
+ RESULT_GUARD_OSSL(ocsp_verify_res, S2N_ERR_CERT_UNTRUSTED);
/* do the crypto checks on the response.*/
int status = 0;
@@ -477,79 +467,41 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(
/* sha1 is the only supported OCSP digest */
OCSP_CERTID *cert_id = OCSP_cert_to_id(EVP_sha1(), subject, issuer);
-
- if (!cert_id) {
- goto clean_up;
- }
+ RESULT_ENSURE_REF(cert_id);
ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd;
/* Actual verification of the response */
const int ocsp_resp_find_status_res = OCSP_resp_find_status(basic_response, cert_id, &status, &reason, &revtime, &thisupd, &nextupd);
OCSP_CERTID_free(cert_id);
-
- if (!ocsp_resp_find_status_res) {
- ret_val = S2N_CERT_ERR_UNTRUSTED;
- goto clean_up;
- }
+ RESULT_GUARD_OSSL(ocsp_resp_find_status_res, S2N_ERR_CERT_UNTRUSTED);
uint64_t this_update = 0;
- s2n_result thisupd_result = s2n_asn1_time_to_nano_since_epoch_ticks((const char *) thisupd->data,
- (uint32_t) thisupd->length, &this_update);
+ RESULT_GUARD(s2n_asn1_time_to_nano_since_epoch_ticks((const char *) thisupd->data,
+ (uint32_t) thisupd->length, &this_update));
uint64_t next_update = 0;
- s2n_result nextupd_result = S2N_RESULT_OK;
if (nextupd) {
- nextupd_result = s2n_asn1_time_to_nano_since_epoch_ticks((const char *) nextupd->data,
- (uint32_t) nextupd->length, &next_update);
+ RESULT_GUARD(s2n_asn1_time_to_nano_since_epoch_ticks((const char *) nextupd->data,
+ (uint32_t) nextupd->length, &next_update));
} else {
next_update = this_update + DEFAULT_OCSP_NEXT_UPDATE_PERIOD;
}
uint64_t current_time = 0;
- const int current_time_err = conn->config->wall_clock(conn->config->sys_clock_ctx, &current_time);
+ RESULT_GUARD_POSIX(conn->config->wall_clock(conn->config->sys_clock_ctx, &current_time));
- if (current_time_err) {
- goto clean_up;
- }
-
- if (s2n_result_is_error(thisupd_result) || s2n_result_is_error(nextupd_result) || current_time_err) {
- ret_val = S2N_CERT_ERR_UNTRUSTED;
- goto clean_up;
- }
-
- if (current_time < this_update || current_time > next_update) {
- ret_val = S2N_CERT_ERR_EXPIRED;
- goto clean_up;
- }
+ RESULT_ENSURE(current_time >= this_update, S2N_ERR_CERT_INVALID);
+ RESULT_ENSURE(current_time <= next_update, S2N_ERR_CERT_EXPIRED);
switch (status) {
case V_OCSP_CERTSTATUS_GOOD:
validator->state = OCSP_VALIDATED;
- ret_val = S2N_CERT_OK;
- break;
+ return S2N_RESULT_OK;
case V_OCSP_CERTSTATUS_REVOKED:
- ret_val = S2N_CERT_ERR_REVOKED;
- goto clean_up;
- case V_OCSP_CERTSTATUS_UNKNOWN:
- goto clean_up;
+ RESULT_BAIL(S2N_ERR_CERT_REVOKED);
default:
- goto clean_up;
- }
-
- clean_up:
- if (basic_response) {
- OCSP_BASICRESP_free(basic_response);
- }
-
- if (ocsp_response) {
- OCSP_RESPONSE_free(ocsp_response);
+ RESULT_BAIL(S2N_ERR_CERT_UNTRUSTED);
}
-
- if (cert_chain) {
- wipe_cert_chain(cert_chain);
- }
-
- return ret_val;
#endif /* S2N_OCSP_STAPLING_SUPPORTED */
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
index b35d535141..55b0956fa1 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
@@ -30,17 +30,6 @@
#endif /* defined(OPENSSL_IS_BORINGSSL) && !defined(OCSP_RESPONSE_STATUS_SUCCESSFUL) */
typedef enum {
- S2N_CERT_OK = 0,
- S2N_CERT_ERR_UNTRUSTED = -1,
- S2N_CERT_ERR_REVOKED = -2,
- S2N_CERT_ERR_EXPIRED = -3,
- S2N_CERT_ERR_TYPE_UNSUPPORTED = -4,
- S2N_CERT_ERR_INVALID = -5,
- S2N_CERT_ERR_MAX_CHAIN_DEPTH_EXCEEDED = -6,
- S2N_CERT_ERR_INTERNAL_ERROR = -7
-} s2n_cert_validation_code;
-
-typedef enum {
UNINIT,
INIT,
VALIDATED,
@@ -121,16 +110,16 @@ void s2n_x509_validator_wipe(struct s2n_x509_validator *validator);
* This function can only be called once per instance of an s2n_x509_validator. If must be called prior to calling
* s2n_x509_validator_validate_cert_stapled_ocsp_response().
*/
-s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_validator *validator, struct s2n_connection *conn,
- uint8_t *cert_chain_in, uint32_t cert_chain_len, s2n_pkey_type *pkey_type,
- struct s2n_pkey *public_key_out);
+S2N_RESULT s2n_x509_validator_validate_cert_chain(struct s2n_x509_validator *validator, struct s2n_connection *conn,
+ uint8_t *cert_chain_in, uint32_t cert_chain_len, s2n_pkey_type *pkey_type,
+ struct s2n_pkey *public_key_out);
/**
* Validates an ocsp response against the most recent certificate chain. Also verifies the timestamps on the response. This function can only be
* called once per instance of an s2n_x509_validator and only after a successful call to s2n_x509_validator_validate_cert_chain().
*/
-s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(struct s2n_x509_validator *validator, struct s2n_connection *conn,
- const uint8_t *ocsp_response, uint32_t size);
+S2N_RESULT s2n_x509_validator_validate_cert_stapled_ocsp_response(struct s2n_x509_validator *validator, struct s2n_connection *conn,
+ const uint8_t *ocsp_response, uint32_t size);
/**
* Checks whether the peer's certificate chain has been received and validated.
diff --git a/contrib/restricted/aws/s2n/utils/s2n_init.c b/contrib/restricted/aws/s2n/utils/s2n_init.c
index 7ea035ded2..2b3d78fefd 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_init.c
+++ b/contrib/restricted/aws/s2n/utils/s2n_init.c
@@ -49,11 +49,17 @@ int s2n_disable_atexit(void) {
int s2n_init(void)
{
main_thread = pthread_self();
+ /* Should run before any init method that calls libcrypto methods
+ * to ensure we don't try to call methods that don't exist.
+ * It doesn't require any locks since it only deals with values that
+ * should be constant, so can run before s2n_locking_init. */
POSIX_GUARD_RESULT(s2n_libcrypto_validate_runtime());
- POSIX_GUARD(s2n_fips_init());
+ /* Must run before any init method that allocates memory. */
POSIX_GUARD(s2n_mem_init());
- POSIX_GUARD_RESULT(s2n_rand_init());
+ /* Must run before any init method that calls libcrypto methods. */
POSIX_GUARD_RESULT(s2n_locking_init());
+ POSIX_GUARD(s2n_fips_init());
+ POSIX_GUARD_RESULT(s2n_rand_init());
POSIX_GUARD(s2n_cipher_suites_init());
POSIX_GUARD(s2n_security_policies_init());
POSIX_GUARD(s2n_config_defaults_init());
@@ -82,9 +88,9 @@ 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_locking_cleanup()) &&
- s2n_result_is_ok(s2n_rand_cleanup_thread()) &&
+ 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);
}