diff options
author | robot-contrib <robot-contrib@yandex-team.com> | 2022-11-07 16:54:51 +0300 |
---|---|---|
committer | robot-contrib <robot-contrib@yandex-team.com> | 2022-11-07 16:54:51 +0300 |
commit | 9ca5282bca79550f17a48f7aef639f0e6d477b2c (patch) | |
tree | 6b03d26c014c76bea0c1743e7f03dd066023b72e | |
parent | 964584075fe8d2284078222e1e7e2e424c8bd9a1 (diff) | |
download | ydb-9ca5282bca79550f17a48f7aef639f0e6d477b2c.tar.gz |
Update contrib/restricted/aws/s2n to 1.3.25
37 files changed, 764 insertions, 71 deletions
diff --git a/contrib/restricted/aws/s2n/CMakeLists.darwin.txt b/contrib/restricted/aws/s2n/CMakeLists.darwin.txt index dd09fdecd4..b3c337c78b 100644 --- a/contrib/restricted/aws/s2n/CMakeLists.darwin.txt +++ b/contrib/restricted/aws/s2n/CMakeLists.darwin.txt @@ -139,6 +139,7 @@ target_sources(restricted-aws-s2n PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_config.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_connection.c + ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_crl.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_crypto.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_early_data.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c @@ -185,6 +186,7 @@ target_sources(restricted-aws-s2n PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls.c + ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls12_encrypted_extensions.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c diff --git a/contrib/restricted/aws/s2n/CMakeLists.linux-aarch64.txt b/contrib/restricted/aws/s2n/CMakeLists.linux-aarch64.txt index 9e3cb12f6f..c10014f87f 100644 --- a/contrib/restricted/aws/s2n/CMakeLists.linux-aarch64.txt +++ b/contrib/restricted/aws/s2n/CMakeLists.linux-aarch64.txt @@ -133,6 +133,7 @@ target_sources(restricted-aws-s2n PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_config.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_connection.c + ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_crl.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_crypto.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_early_data.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c @@ -179,6 +180,7 @@ target_sources(restricted-aws-s2n PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls.c + ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls12_encrypted_extensions.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c diff --git a/contrib/restricted/aws/s2n/CMakeLists.linux.txt b/contrib/restricted/aws/s2n/CMakeLists.linux.txt index f22ac9bb39..504c30980d 100644 --- a/contrib/restricted/aws/s2n/CMakeLists.linux.txt +++ b/contrib/restricted/aws/s2n/CMakeLists.linux.txt @@ -140,6 +140,7 @@ target_sources(restricted-aws-s2n PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_config.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_connection.c + ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_crl.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_crypto.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_early_data.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c @@ -186,6 +187,7 @@ target_sources(restricted-aws-s2n PRIVATE ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls.c + ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls12_encrypted_extensions.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.c ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c diff --git a/contrib/restricted/aws/s2n/api/s2n.h b/contrib/restricted/aws/s2n/api/s2n.h index c555b1bc2f..7e2e6581c8 100644 --- a/contrib/restricted/aws/s2n/api/s2n.h +++ b/contrib/restricted/aws/s2n/api/s2n.h @@ -1854,7 +1854,7 @@ typedef enum { * * @param conn A pointer to the s2n_connection object * @param blocked A pointer which will be set to the blocked status. - * @returns The number of bytes written, and may indicate a partial write + * @returns S2N_SUCCESS if the handshake completed. S2N_FAILURE if the handshake encountered an error or is blocked. */ S2N_API extern int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked); diff --git a/contrib/restricted/aws/s2n/api/unstable/renegotiate.h b/contrib/restricted/aws/s2n/api/unstable/renegotiate.h new file mode 100644 index 0000000000..c605988cb8 --- /dev/null +++ b/contrib/restricted/aws/s2n/api/unstable/renegotiate.h @@ -0,0 +1,145 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include <s2n.h> + +/** + * @file renegotiate.h + * + * "Renegotiation" is a TLS feature offered in TLS1.2 and earlier. + * During renegotiation, a new handshake is performed on an already established + * connection. The new handshake is encrypted using the keys from the original handshake. + * The new handshake may not match the first handshake; for example, the server may choose + * a different cipher suite or require client authentication for the new handshake. + * + * s2n-tls clients support secure (compliant with RFC5746) renegotiation for compatibility reasons, + * but s2n-tls does NOT recommend its use. While s2n-tls addresses all currently known security concerns, + * renegotiation has appeared in many CVEs and was completely removed from TLS1.3. + */ + +/** + * Used to indicate that an attempt to renegotiate encountered + * application data which the application should process before + * continuing the handshake. + */ +extern const s2n_blocked_status S2N_BLOCKED_ON_APPLICATION_DATA; + +/** + * Indicates how a renegotiation request should be handled. + */ +typedef enum { + /* The client will take no action */ + S2N_RENEGOTIATE_IGNORE = 0, + /* The client will send a warning alert to the server */ + S2N_RENEGOTIATE_REJECT, + /* The client will begin renegotiation in the future */ + S2N_RENEGOTIATE_ACCEPT, +} s2n_renegotiate_response; + +/** + * Callback function to handle requests for renegotiation. + * + * s2n-tls calls this method when a client receives a request from the server + * to renegotiate the connection. If the server makes multiple requests, + * s2n-tls will call this method multiple times. + * + * Applications should use the `response` value to indicate how the request + * should be handled. If `response` is set to `S2N_RENEGOTIATE_IGNORE` + * or `S2N_RENEGOTIATE_REJECT`, no further application involvement is required. + * + * If `response` is set to `S2N_RENEGOTIATE_ACCEPT`, then the application should + * handle renegotiation. The application should stop calling s2n_send and s2n_recv, + * wipe the connection with s2n_renegotiate_wipe, and then call s2n_renegotiate + * until the handshake is complete. + * + * @param conn A pointer to the connection object. + * @param context Context for the callback function. + * @param response How the request should be handled. + * @returns S2N_SUCCESS on success, S2N_FAILURE on error. + */ +typedef int (*s2n_renegotiate_request_cb)(struct s2n_connection *conn, void *context, s2n_renegotiate_response *response); + +/** + * Sets a method to be called when the client receives a request to renegotiate. + * + * @param config A pointer to the config object. + * @param callback The function to be called when a renegotiation request is received. + * @param context Context to be passed to the callback function. + * @returns S2N_SUCCESS on success, S2N_FAILURE on error. + */ +S2N_API +int s2n_config_set_renegotiate_request_cb(struct s2n_config *config, s2n_renegotiate_request_cb callback, void *context); + +/** + * Reset the connection so that it can be renegotiated. + * + * Similar to `s2n_connection_wipe`, this method resets a connection so that it can be used again. + * However, unlike `s2n_connection_wipe`, it retains enough state from the previous connection + * that the connection can continue to send and receive data encrypted with the old keys. + * + * The application MUST handle any incomplete IO before calling this method. The last call to `s2n_send` must + * have succeeded, and `s2n_peek` must return zero. If there is any data in the send or receive buffers, + * this method will fail. + * + * The application MUST repeat any connection-specific setup after calling this method. This method + * cannot distinguish between internal connection state and configuration state set by the application, + * so it wipes all state not directly related to handling encrypted records. For example, + * if the application originally called `s2n_connection_set_blinding` on the connection, + * then the application will need to call `s2n_connection_set_blinding` again after `s2n_renegotiate_wipe`. + * + * The connection-specific setup methods the application does not need to call again are: + * - Methods to set the file descriptors + * (`s2n_connection_set_fd`, `s2n_connection_set_read_fd`, `s2n_connection_set_write_fd`) + * - Methods to set the send callback + * (`s2n_connection_set_send_cb`, `s2n_connection_set_send_ctx`) + * - Methods to set the recv callback + * (`s2n_connection_set_recv_cb`, `s2n_connection_set_recv_ctx`) + * + * @note This method MUST be called before s2n_renegotiate. + * @note Calling this method on a server connection will fail. s2n-tls servers do not support renegotiation. + * + * @param conn A pointer to the connection object. + * @returns S2N_SUCCESS on success, S2N_FAILURE on error. + */ +S2N_API +int s2n_renegotiate_wipe(struct s2n_connection *conn); + +/** + * Perform a new handshake on an already established connection. + * + * This method should be called like `s2n_negotiate`, with the same handling of return values, + * error types, and blocked statuses. + * + * However, unlike the initial handshake performed by `s2n_negotiate`, the renegotiation + * handshake can encounter valid application data. In that case, this method will fail + * with an error of type S2N_ERR_T_BLOCKED, set the `blocked` field to `S2N_BLOCKED_ON_APPLICATION_DATA`, + * copy the data to `app_data_buf`, and set `app_data_size` to the size of the data. + * The application should handle the data in `app_data_buf` before calling s2n_renegotiate again. + * + * @note s2n_renegotiate_wipe MUST be called before this method. + * @note Calling this method on a server connection will fail. s2n-tls servers do not support renegotiation. + * + * @param conn A pointer to the connection object. + * @param app_data_buf A pointer to a buffer that s2n will copy application data read into. + * @param app_data_buf_size The size of `app_data_buf`. + * @param app_data_size The number of application data bytes read. + * @param blocked A pointer which will be set to the blocked status. + * @returns S2N_SUCCESS if the handshake completed. S2N_FAILURE if the handshake encountered an error or is blocked. + */ +S2N_API +int s2n_renegotiate(struct s2n_connection *conn, uint8_t *app_data_buf, ssize_t app_data_buf_size, + ssize_t *app_data_size, s2n_blocked_status *blocked); diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.c b/contrib/restricted/aws/s2n/error/s2n_errno.c index 816b76780e..ce77f9f315 100644 --- a/contrib/restricted/aws/s2n/error/s2n_errno.c +++ b/contrib/restricted/aws/s2n/error/s2n_errno.c @@ -278,6 +278,7 @@ static const char *no_such_error = "Internal s2n error"; 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") \ ERR_ENTRY(S2N_ERR_NO_RENEGOTIATION, "Only secure, server-initiated renegotiation is supported") \ + ERR_ENTRY(S2N_ERR_APP_DATA_BLOCKED, "Blocked on application data during handshake") \ /* 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 17482e6033..40eebfa157 100644 --- a/contrib/restricted/aws/s2n/error/s2n_errno.h +++ b/contrib/restricted/aws/s2n/error/s2n_errno.h @@ -59,6 +59,7 @@ typedef enum { S2N_ERR_IO_BLOCKED = S2N_ERR_T_BLOCKED_START, S2N_ERR_ASYNC_BLOCKED, S2N_ERR_EARLY_DATA_BLOCKED, + S2N_ERR_APP_DATA_BLOCKED, S2N_ERR_T_BLOCKED_END, /* S2N_ERR_T_ALERT */ diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_cbd.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_cbd.c index 72f2941683..82acdb30f8 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_cbd.c +++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_cbd.c @@ -2,9 +2,7 @@ #include "kyber512r3_params.h" #include "kyber512r3_cbd.h" -#if S2N_ANY_NONPORTABLE_OPTIMIZATIONS_ENABLED -#error "Compiling portable code with non-portable assembly optimizations is not allowed" -#endif +S2N_ENSURE_PORTABLE_OPTIMIZATIONS /************************************************* * Name: load32_littleendian diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_fips202.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_fips202.c index b9f7fbaea8..3632963ed8 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_fips202.c +++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_fips202.c @@ -14,9 +14,7 @@ #define NROUNDS 24 #define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64 - (offset)))) -#if S2N_ANY_NONPORTABLE_OPTIMIZATIONS_ENABLED -#error "Compiling portable code with non-portable assembly optimizations is not allowed" -#endif +S2N_ENSURE_PORTABLE_OPTIMIZATIONS /************************************************* * Name: load64 diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_indcpa.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_indcpa.c index 5b03bc7cff..bbb77259df 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_indcpa.c +++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_indcpa.c @@ -9,9 +9,7 @@ #include "pq-crypto/s2n_pq_random.h" #include "utils/s2n_safety.h" -#if S2N_ANY_NONPORTABLE_OPTIMIZATIONS_ENABLED -#error "Compiling portable code with non-portable assembly optimizations is not allowed" -#endif +S2N_ENSURE_PORTABLE_OPTIMIZATIONS /************************************************* * Name: pack_pk diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_kem.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_kem.c index d5d1dd22be..e35b3df805 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_kem.c +++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_kem.c @@ -9,9 +9,7 @@ #include "pq-crypto/s2n_pq_random.h" #include "pq-crypto/s2n_pq.h" -#if S2N_ANY_NONPORTABLE_OPTIMIZATIONS_ENABLED -#error "Compiling portable code with non-portable assembly optimizations is not allowed" -#endif +S2N_ENSURE_PORTABLE_OPTIMIZATIONS /************************************************* * Name: crypto_kem_keypair diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_ntt.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_ntt.c index 921f6ffc2c..c38147bafe 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_ntt.c +++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_ntt.c @@ -3,9 +3,7 @@ #include "kyber512r3_ntt.h" #include "kyber512r3_reduce.h" -#if S2N_ANY_NONPORTABLE_OPTIMIZATIONS_ENABLED -#error "Compiling portable code with non-portable assembly optimizations is not allowed" -#endif +S2N_ENSURE_PORTABLE_OPTIMIZATIONS const int16_t zetas[128] = { 2285, 2571, 2970, 1812, 1493, 1422, 287, 202, 3158, 622, 1577, 182, 962, diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_poly.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_poly.c index 3cc392b0d4..61a725ec44 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_poly.c +++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_poly.c @@ -6,9 +6,7 @@ #include "kyber512r3_cbd.h" #include "kyber512r3_symmetric.h" -#if S2N_ANY_NONPORTABLE_OPTIMIZATIONS_ENABLED -#error "Compiling portable code with non-portable assembly optimizations is not allowed" -#endif +S2N_ENSURE_PORTABLE_OPTIMIZATIONS /************************************************* * Name: poly_compress diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_polyvec.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_polyvec.c index 9800da93e7..fb3b54f8cc 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_polyvec.c +++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_polyvec.c @@ -3,9 +3,7 @@ #include "kyber512r3_poly.h" #include "kyber512r3_polyvec.h" -#if S2N_ANY_NONPORTABLE_OPTIMIZATIONS_ENABLED -#error "Compiling portable code with non-portable assembly optimizations is not allowed" -#endif +S2N_ENSURE_PORTABLE_OPTIMIZATIONS /************************************************* * Name: polyvec_compress diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_reduce.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_reduce.c index e764568826..ed7099f7ae 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_reduce.c +++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_reduce.c @@ -2,9 +2,7 @@ #include "kyber512r3_params.h" #include "kyber512r3_reduce.h" -#if S2N_ANY_NONPORTABLE_OPTIMIZATIONS_ENABLED -#error "Compiling portable code with non-portable assembly optimizations is not allowed" -#endif +S2N_ENSURE_PORTABLE_OPTIMIZATIONS /************************************************* * Name: montgomery_reduce diff --git a/contrib/restricted/aws/s2n/pq-crypto/s2n_pq_asm.h b/contrib/restricted/aws/s2n/pq-crypto/s2n_pq_asm.h index 1a39464d48..0701e6b270 100644 --- a/contrib/restricted/aws/s2n/pq-crypto/s2n_pq_asm.h +++ b/contrib/restricted/aws/s2n/pq-crypto/s2n_pq_asm.h @@ -15,4 +15,15 @@ #pragma once +#ifndef S2N_BLOCK_NONPORTABLE_OPTIMIZATIONS +#define S2N_BLOCK_NONPORTABLE_OPTIMIZATIONS 0 +#endif + #define S2N_ANY_NONPORTABLE_OPTIMIZATIONS_ENABLED __AVX__ || __AVX2__ || __BMI2__ + +#if S2N_BLOCK_NONPORTABLE_OPTIMIZATIONS && S2N_ANY_NONPORTABLE_OPTIMIZATIONS_ENABLED +#define S2N_ENSURE_PORTABLE_OPTIMIZATIONS \ + #error "Compiling portable code with non-portable assembly optimizations. This can result in runtime crashes if artifacts are deployed to older CPU's without these CPU instructions" +#else +#define S2N_ENSURE_PORTABLE_OPTIMIZATIONS +#endif diff --git a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.h b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.h index 91de251eaf..52b6761e54 100644 --- a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.h +++ b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.h @@ -167,6 +167,9 @@ extern int s2n_stuffer_private_key_from_pem(struct s2n_stuffer *pem, struct s2n_ /* Read a certificate from a PEM encoded stuffer to an ASN1/DER encoded one */ extern int s2n_stuffer_certificate_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1); +/* Read a CRL from a PEM encoded stuffer to an ASN1/DER encoded one */ +extern int s2n_stuffer_crl_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1); + /* Read DH parameters om a PEM encoded stuffer to a PKCS3 encoded one */ extern int s2n_stuffer_dhparams_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *pkcs3); diff --git a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_pem.c b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_pem.c index 6c18694179..bd2f591fc6 100644 --- a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_pem.c +++ b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_pem.c @@ -31,6 +31,7 @@ #define S2N_PEM_DH_PARAMETERS "DH PARAMETERS" #define S2N_PEM_EC_PARAMETERS "EC PARAMETERS" #define S2N_PEM_CERTIFICATE "CERTIFICATE" +#define S2N_PEM_CRL "X509 CRL" static int s2n_stuffer_pem_read_encapsulation_line(struct s2n_stuffer *pem, const char* encap_marker, const char *keyword) { @@ -165,6 +166,10 @@ int s2n_stuffer_certificate_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer return s2n_stuffer_data_from_pem(pem, asn1, S2N_PEM_CERTIFICATE); } +int s2n_stuffer_crl_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1) { + return s2n_stuffer_data_from_pem(pem, asn1, S2N_PEM_CRL); +} + int s2n_stuffer_dhparams_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *pkcs3) { return s2n_stuffer_data_from_pem(pem, pkcs3, S2N_PEM_DH_PARAMETERS); diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.c index ac11ad22e2..187d5603dc 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.c @@ -24,6 +24,7 @@ static int s2n_client_renegotiation_send(struct s2n_connection *conn, struct s2n_stuffer *out); static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); static bool s2n_client_renegotiation_should_send(struct s2n_connection *conn); +static int s2n_client_renegotiation_if_missing(struct s2n_connection *conn); const s2n_extension_type s2n_client_renegotiation_info_extension = { .iana_value = TLS_EXTENSION_RENEGOTIATION_INFO, @@ -31,21 +32,7 @@ const s2n_extension_type s2n_client_renegotiation_info_extension = { .send = s2n_client_renegotiation_send, .recv = s2n_client_renegotiation_recv, .should_send = s2n_client_renegotiation_should_send, - - /** - *= https://tools.ietf.org/rfc/rfc5746#3.6 - *# o If neither the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV nor the - *# "renegotiation_info" extension was included, set the - *# secure_renegotiation flag to FALSE. In this case, some servers - *# may want to terminate the handshake instead of continuing - * - * The conn->secure_renegotiation flag defaults to false, so this is a no-op. - * We do not terminate the handshake, although missing messaging for secure - * renegotiation degrades client security. - * - * We could introduce an option to fail in this case in the future. - */ - .if_missing = s2n_extension_noop_if_missing, + .if_missing = s2n_client_renegotiation_if_missing, }; /** @@ -75,6 +62,7 @@ static int s2n_client_renegotiation_send(struct s2n_connection *conn, struct s2n POSIX_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION); uint8_t renegotiated_connection_len = conn->handshake.finished_len; + POSIX_ENSURE_GT(renegotiated_connection_len, 0); POSIX_GUARD(s2n_stuffer_write_uint8(out, renegotiated_connection_len)); POSIX_GUARD(s2n_stuffer_write_bytes(out, conn->handshake.client_finished, renegotiated_connection_len)); @@ -85,8 +73,14 @@ static int s2n_client_renegotiation_send(struct s2n_connection *conn, struct s2n *= https://tools.ietf.org/rfc/rfc5746#3.6 *# o The server MUST check if the "renegotiation_info" extension is *# included in the ClientHello. + * + * Note that this extension must also work for SSLv3: + *= https://tools.ietf.org/rfc/rfc5746#4.5 + *# TLS servers that support secure renegotiation and support SSLv3 MUST accept SCSV or the + *# "renegotiation_info" extension and respond as described in this + *# specification even if the offered client version is {0x03, 0x00}. */ -static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +static int s2n_client_renegotiation_recv_initial(struct s2n_connection *conn, struct s2n_stuffer *extension) { /** *= https://tools.ietf.org/rfc/rfc5746#3.6 @@ -108,6 +102,94 @@ static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n return S2N_SUCCESS; } +static int s2n_client_renegotiation_recv_renegotiation(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + POSIX_ENSURE_REF(conn); + + /* s2n-tls servers do not support renegotiation. + * We add the renegotiation version of this logic only for testing. + */ + POSIX_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST); + + /** + *= https://tools.ietf.org/rfc/rfc5746#3.7 + *# This text applies if the connection's "secure_renegotiation" flag is + *# set to TRUE (if it is set to FALSE, see Section 4.4). + */ + POSIX_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION); + + /** + *= https://tools.ietf.org/rfc/rfc5746#3.7 + *# o The server MUST verify that the value of the + *# "renegotiated_connection" field is equal to the saved + *# client_verify_data value; if it is not, the server MUST abort the + *# handshake. + */ + + uint8_t verify_data_len = conn->handshake.finished_len; + POSIX_ENSURE_GT(verify_data_len, 0); + + uint8_t renegotiated_connection_len = 0; + POSIX_GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len)); + POSIX_ENSURE(verify_data_len == renegotiated_connection_len, S2N_ERR_BAD_MESSAGE); + + uint8_t *renegotiated_connection = s2n_stuffer_raw_read(extension, verify_data_len); + POSIX_ENSURE_REF(renegotiated_connection); + POSIX_ENSURE(s2n_constant_time_equals(renegotiated_connection, conn->handshake.client_finished, verify_data_len), + S2N_ERR_BAD_MESSAGE); + + return S2N_SUCCESS; +} + +static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + if (s2n_handshake_is_renegotiation(conn)) { + POSIX_GUARD(s2n_client_renegotiation_recv_renegotiation(conn, extension)); + } else { + POSIX_GUARD(s2n_client_renegotiation_recv_initial(conn, extension)); + } + POSIX_ENSURE(s2n_stuffer_data_available(extension) == 0, S2N_ERR_BAD_MESSAGE); + return S2N_SUCCESS; +} + +static int s2n_client_renegotiation_if_missing(struct s2n_connection *conn) +{ + POSIX_ENSURE_REF(conn); + if (s2n_handshake_is_renegotiation(conn)) { + /* s2n-tls servers do not support renegotiation. + * We add the renegotiation version of this logic only for testing. + */ + POSIX_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST); + + /** + *= https://tools.ietf.org/rfc/rfc5746#3.7 + *# This text applies if the connection's "secure_renegotiation" flag is + *# set to TRUE (if it is set to FALSE, see Section 4.4). + */ + POSIX_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION); + + /** + *= https://tools.ietf.org/rfc/rfc5746#3.7 + *# o The server MUST verify that the "renegotiation_info" extension is + *# present; if it is not, the server MUST abort the handshake. + */ + POSIX_BAIL(S2N_ERR_MISSING_EXTENSION); + } else { + /** + *= https://tools.ietf.org/rfc/rfc5746#3.6 + *# o If neither the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV nor the + *# "renegotiation_info" extension was included, set the + *# secure_renegotiation flag to FALSE. In this case, some servers + *# may want to terminate the handshake instead of continuing + * + * We do not terminate the handshake for compatibility reasons. + * See https://github.com/aws/s2n-tls/issues/3528 + */ + conn->secure_renegotiation = false; + return S2N_SUCCESS; + } +} + /* Old-style extension functions -- remove after extensions refactor is complete */ int s2n_recv_client_renegotiation_info(struct s2n_connection *conn, struct s2n_stuffer *extension) diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h index 00245dacec..cddddf4135 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h @@ -42,6 +42,7 @@ typedef enum { S2N_EXTENSION_LIST_CERT_REQ, S2N_EXTENSION_LIST_CERTIFICATE, S2N_EXTENSION_LIST_NST, + S2N_EXTENSION_LIST_ENCRYPTED_EXTENSIONS_TLS12, S2N_EXTENSION_LIST_EMPTY, S2N_EXTENSION_LIST_IDS_COUNT, } s2n_extension_list_id; diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h index f3ccf58730..a5ecb36ce4 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h @@ -67,6 +67,7 @@ static const uint16_t s2n_supported_extensions[] = { TLS_EXTENSION_PRE_SHARED_KEY, TLS_EXTENSION_EARLY_DATA, TLS_EXTENSION_EMS, + TLS_EXTENSION_NPN, }; typedef char s2n_extension_bitfield[S2N_SUPPORTED_EXTENSIONS_BITFIELD_LEN]; diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c index e28e774acc..d8505894cd 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c @@ -49,6 +49,7 @@ #include "tls/extensions/s2n_server_supported_versions.h" #include "tls/extensions/s2n_server_key_share.h" #include "tls/extensions/s2n_server_psk.h" +#include "tls/extensions/s2n_npn.h" static const s2n_extension_type *const client_hello_extensions[] = { &s2n_client_supported_versions_extension, @@ -74,6 +75,7 @@ static const s2n_extension_type *const client_hello_extensions[] = { &s2n_psk_key_exchange_modes_extension, &s2n_client_early_data_indication_extension, &s2n_client_ems_extension, + &s2n_client_npn_extension, &s2n_client_psk_extension /* MUST be last */ }; @@ -88,6 +90,7 @@ static const s2n_extension_type *const tls12_server_hello_extensions[] = { &s2n_server_max_fragment_length_extension, &s2n_server_session_ticket_extension, &s2n_server_ems_extension, + &s2n_server_npn_extension, }; /** @@ -121,6 +124,10 @@ static const s2n_extension_type *const encrypted_extensions[] = { &s2n_server_early_data_indication_extension, }; +static const s2n_extension_type *const tls12_encrypted_extensions[] = { + &s2n_npn_encrypted_extension, +}; + static const s2n_extension_type *const cert_req_extensions[] = { &s2n_server_signature_algorithms_extension, }; @@ -145,6 +152,7 @@ static s2n_extension_type_list extension_lists[] = { [S2N_EXTENSION_LIST_CERT_REQ] = S2N_EXTENSION_LIST(cert_req_extensions), [S2N_EXTENSION_LIST_CERTIFICATE] = S2N_EXTENSION_LIST(certificate_extensions), [S2N_EXTENSION_LIST_NST] = S2N_EXTENSION_LIST(nst_extensions), + [S2N_EXTENSION_LIST_ENCRYPTED_EXTENSIONS_TLS12] = S2N_EXTENSION_LIST(tls12_encrypted_extensions), [S2N_EXTENSION_LIST_EMPTY] = { .extension_types = NULL, .count = 0 }, }; diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.c index 61c5b3a6d1..4731f97ffb 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.c @@ -66,7 +66,33 @@ int s2n_server_npn_recv(struct s2n_connection *conn, struct s2n_stuffer *extensi return S2N_SUCCESS; } - POSIX_GUARD_RESULT(s2n_select_server_preference_protocol(conn, extension, supported_protocols)); + /* + *= https://datatracker.ietf.org/doc/id/draft-agl-tls-nextprotoneg-04#section-3 + *# The "extension_data" field of a "next_protocol_negotiation" extension + *# in a "ServerHello" contains an optional list of protocols advertised + *# by the server. + */ + if (s2n_stuffer_data_available(extension)) { + POSIX_GUARD_RESULT(s2n_select_server_preference_protocol(conn, extension, supported_protocols)); + } + + /* + *= https://datatracker.ietf.org/doc/id/draft-agl-tls-nextprotoneg-04#section-4 + *# In the event that the client doesn't support any of server's protocols, or + *# the server doesn't advertise any, it SHOULD select the first protocol + *# that it supports. + */ + if (s2n_get_application_protocol(conn) == NULL) { + struct s2n_stuffer stuffer = { 0 }; + POSIX_GUARD(s2n_stuffer_init(&stuffer, supported_protocols)); + POSIX_GUARD(s2n_stuffer_skip_write(&stuffer, supported_protocols->size)); + struct s2n_blob protocol = { 0 }; + POSIX_GUARD_RESULT(s2n_protocol_preferences_read(&stuffer, &protocol)); + + POSIX_ENSURE_LT(protocol.size, sizeof(conn->application_protocol)); + POSIX_CHECKED_MEMCPY(conn->application_protocol, protocol.data, protocol.size); + conn->application_protocol[protocol.size] = '\0'; + } return S2N_SUCCESS; } @@ -79,3 +105,73 @@ const s2n_extension_type s2n_server_npn_extension = { .should_send = s2n_server_npn_should_send, .if_missing = s2n_extension_noop_if_missing, }; + +bool s2n_npn_encrypted_should_send(struct s2n_connection *conn) +{ + return s2n_server_alpn_should_send(conn); +} + +S2N_RESULT s2n_calculate_padding(uint8_t protocol_len, uint8_t *padding_len) +{ + RESULT_ENSURE_REF(padding_len); + + /* + *= https://datatracker.ietf.org/doc/id/draft-agl-tls-nextprotoneg-04#section-3 + *# The length of "padding" SHOULD be 32 - ((len(selected_protocol) + 2) % 32). + */ + *padding_len = 32 - ((protocol_len + 2) % 32); + return S2N_RESULT_OK; +} + +int s2n_npn_encrypted_extension_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + uint8_t protocol_len = strlen(conn->application_protocol); + POSIX_GUARD(s2n_stuffer_write_uint8(out, protocol_len)); + POSIX_GUARD(s2n_stuffer_write_bytes(out, (uint8_t*) conn->application_protocol, protocol_len)); + + uint8_t padding_len = 0; + POSIX_GUARD_RESULT(s2n_calculate_padding(protocol_len, &padding_len)); + POSIX_GUARD(s2n_stuffer_write_uint8(out, padding_len)); + for (size_t i = 0; i < padding_len; i++) { + POSIX_GUARD(s2n_stuffer_write_uint8(out, 0)); + } + + return S2N_SUCCESS; +} + +int s2n_npn_encrypted_extension_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + uint8_t protocol_len = 0; + POSIX_GUARD(s2n_stuffer_read_uint8(extension, &protocol_len)); + + uint8_t *protocol = s2n_stuffer_raw_read(extension, protocol_len); + POSIX_ENSURE_REF(protocol); + POSIX_CHECKED_MEMCPY(conn->application_protocol, protocol, protocol_len); + conn->application_protocol[protocol_len] = '\0'; + + uint8_t expected_padding_len = 0; + POSIX_GUARD_RESULT(s2n_calculate_padding(protocol_len, &expected_padding_len)); + uint8_t padding_len = 0; + POSIX_GUARD(s2n_stuffer_read_uint8(extension, &padding_len)); + POSIX_ENSURE_EQ(padding_len, expected_padding_len); + + for (size_t i = 0; i < padding_len; i++) { + uint8_t byte = 0; + POSIX_GUARD(s2n_stuffer_read_uint8(extension, &byte)); + POSIX_ENSURE_EQ(byte, 0); + } + POSIX_ENSURE_EQ(s2n_stuffer_data_available(extension), 0); + + return S2N_SUCCESS; +} + +const s2n_extension_type s2n_npn_encrypted_extension = { + .iana_value = TLS_EXTENSION_NPN, + .is_response = true, + .send = s2n_npn_encrypted_extension_send, + .recv = s2n_npn_encrypted_extension_recv, + .should_send = s2n_npn_encrypted_should_send, + /* The NPN extension is the only one defined for TLS1.2 Encrypted Extensions. + * If it's missing, something has gone wrong. */ + .if_missing = s2n_extension_error_if_missing, +}; diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.h index 0b03e5c1b4..81f0f60220 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.h @@ -19,3 +19,4 @@ extern const s2n_extension_type s2n_client_npn_extension; extern const s2n_extension_type s2n_server_npn_extension; +extern const s2n_extension_type s2n_npn_encrypted_extension; diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c index 1052a41ab1..5834412e10 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c @@ -24,6 +24,17 @@ #include "tls/s2n_tls.h" #include "tls/extensions/s2n_server_renegotiation_info.h" +/** + * s2n-tls servers do NOT support renegotiation. + * + * We implement this extension to handle clients that require secure renegotiation support: + *= https://tools.ietf.org/rfc/rfc5746#4.3 + *# In order to enable clients to probe, even servers that do not support + *# renegotiation MUST implement the minimal version of the extension + *# described in this document for initial handshakes, thus signaling + *# that they have been upgraded. + */ + static bool s2n_renegotiation_info_should_send(struct s2n_connection *conn); static int s2n_renegotiation_info_send(struct s2n_connection *conn, struct s2n_stuffer *out); static int s2n_renegotiation_info_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); @@ -69,12 +80,53 @@ static bool s2n_renegotiation_info_should_send(struct s2n_connection *conn) *# include an empty "renegotiation_info" extension in the ServerHello *# message. */ -static int s2n_renegotiation_info_send(struct s2n_connection *conn, struct s2n_stuffer *out) +static int s2n_renegotiation_info_send_initial(struct s2n_connection *conn, struct s2n_stuffer *out) { POSIX_GUARD(s2n_stuffer_write_uint8(out, 0)); return S2N_SUCCESS; } +static int s2n_renegotiation_info_send_renegotiation(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + POSIX_ENSURE_REF(conn); + + /* s2n-tls servers do not support renegotiation. + * We add the renegotiation version of this logic only for testing. + */ + POSIX_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST); + + /** + *= https://tools.ietf.org/rfc/rfc5746#3.7 + *# This text applies if the connection's "secure_renegotiation" flag is + *# set to TRUE (if it is set to FALSE, see Section 4.4). + */ + POSIX_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION); + + /** + *= https://tools.ietf.org/rfc/rfc5746#3.7 + *# o The server MUST include a "renegotiation_info" extension + *# containing the saved client_verify_data and server_verify_data in + *# the ServerHello. + */ + const uint8_t verify_data_len = conn->handshake.finished_len; + POSIX_ENSURE_GT(verify_data_len, 0); + POSIX_GUARD(s2n_stuffer_write_uint8(out, verify_data_len * 2)); + POSIX_GUARD(s2n_stuffer_write_bytes(out, conn->handshake.client_finished, verify_data_len)); + POSIX_GUARD(s2n_stuffer_write_bytes(out, conn->handshake.server_finished, verify_data_len)); + + return S2N_SUCCESS; +} + +static int s2n_renegotiation_info_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + if (s2n_handshake_is_renegotiation(conn)) { + POSIX_GUARD(s2n_renegotiation_info_send_renegotiation(conn, out)); + } else { + POSIX_GUARD(s2n_renegotiation_info_send_initial(conn, out)); + } + return S2N_SUCCESS; +} + /** *= https://tools.ietf.org/rfc/rfc5746#3.4 *# o When a ServerHello is received, the client MUST check if it @@ -142,6 +194,14 @@ static int s2n_renegotiation_info_recv_renegotiation(struct s2n_connection *conn return S2N_SUCCESS; } +/** + * Note that this extension must also work for SSLv3: + *= https://tools.ietf.org/rfc/rfc5746#4.5 + *# Clients that support SSLv3 and offer secure renegotiation (either via SCSV or + *# "renegotiation_info") MUST accept the "renegotiation_info" extension + *# from the server, even if the server version is {0x03, 0x00}, and + *# behave as described in this specification. + */ static int s2n_renegotiation_info_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) { if (s2n_handshake_is_renegotiation(conn)) { @@ -170,13 +230,24 @@ static int s2n_renegotiation_info_if_missing(struct s2n_connection *conn) *# secure renegotiation; set secure_renegotiation flag to FALSE. *# In this case, some clients may want to terminate the handshake *# instead of continuing; see Section 4.1 for discussion. - * - * We do not terminate the handshake, although missing messaging for secure - * renegotiation degrades server security. - * - * We could introduce an option to fail in this case in the future. */ conn->secure_renegotiation = false; + + /** + *= https://tools.ietf.org/rfc/rfc5746#4.1 + *= type=exception + *= reason=Avoid interoperability problems + *# If clients wish to ensure that such attacks are impossible, they need + *# to terminate the connection immediately upon failure to receive the + *# extension without completing the handshake. Such clients MUST + *# generate a fatal "handshake_failure" alert prior to terminating the + *# connection. However, it is expected that many TLS servers that do + *# not support renegotiation (and thus are not vulnerable) will not + *# support this extension either, so in general, clients that implement + *# this behavior will encounter interoperability problems. + * + * TODO: https://github.com/aws/s2n-tls/issues/3528 + */ return S2N_SUCCESS; } } diff --git a/contrib/restricted/aws/s2n/tls/s2n_alerts.c b/contrib/restricted/aws/s2n/tls/s2n_alerts.c index 5ecf10b47d..8ed8a3adc1 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_alerts.c +++ b/contrib/restricted/aws/s2n/tls/s2n_alerts.c @@ -300,6 +300,18 @@ int s2n_queue_reader_handshake_failure_alert(struct s2n_connection *conn) S2N_RESULT s2n_queue_reader_no_renegotiation_alert(struct s2n_connection *conn) { + /** + *= https://tools.ietf.org/rfc/rfc5746#4.5 + *# SSLv3 does not define the "no_renegotiation" alert (and does + *# not offer a way to indicate a refusal to renegotiate at a "warning" + *# level). SSLv3 clients that refuse renegotiation SHOULD use a fatal + *# handshake_failure alert. + **/ + if (s2n_connection_get_protocol_version(conn) == S2N_SSLv3) { + RESULT_GUARD_POSIX(s2n_queue_reader_alert(conn, S2N_TLS_ALERT_LEVEL_FATAL, S2N_TLS_ALERT_HANDSHAKE_FAILURE)); + return S2N_RESULT_OK; + } + RESULT_GUARD_POSIX(s2n_queue_reader_alert(conn, S2N_TLS_ALERT_LEVEL_WARNING, S2N_TLS_ALERT_NO_RENEGOTIATION)); return S2N_RESULT_OK; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c index 75cf0f6ba4..df7aa796c6 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c @@ -1188,13 +1188,21 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire, } } - /** - *= https://tools.ietf.org/rfc/rfc5746#3.6 - *# o When a ClientHello is received, the server MUST check if it - *# includes the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, - *# set the secure_renegotiation flag to TRUE. - */ if (s2n_wire_ciphers_contain(renegotiation_info_scsv, wire, count, cipher_suite_len)) { + /** For renegotiation handshakes: + *= https://tools.ietf.org/rfc/rfc5746#3.7 + *# o When a ClientHello is received, the server MUST verify that it + *# does not contain the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If + *# the SCSV is present, the server MUST abort the handshake. + */ + POSIX_ENSURE(!s2n_handshake_is_renegotiation(conn), S2N_ERR_BAD_MESSAGE); + + /** For initial handshakes: + *= https://tools.ietf.org/rfc/rfc5746#3.6 + *# o When a ClientHello is received, the server MUST check if it + *# includes the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, + *# set the secure_renegotiation flag to TRUE. + */ conn->secure_renegotiation = 1; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_hello_request.c b/contrib/restricted/aws/s2n/tls/s2n_client_hello_request.c index 824c1eb2dc..188f9440cc 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_hello_request.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello_request.c @@ -41,6 +41,13 @@ S2N_RESULT s2n_client_hello_request_recv(struct s2n_connection *conn) RESULT_ENSURE_REF(conn->config); RESULT_GUARD(s2n_client_hello_request_validate(conn)); + /* Maintain the old s2n-tls behavior by default. + * Traditionally, s2n-tls has just ignored all hello requests. + */ + if (!conn->config->renegotiate_request_cb) { + return S2N_RESULT_OK; + } + /* *= https://tools.ietf.org/rfc/rfc5746#section-4.2 *# This text applies if the connection's "secure_renegotiation" flag is @@ -61,10 +68,8 @@ S2N_RESULT s2n_client_hello_request_recv(struct s2n_connection *conn) } s2n_renegotiate_response response = S2N_RENEGOTIATE_REJECT; - if (conn->config->renegotiate_request_cb) { - RESULT_GUARD_POSIX((conn->config->renegotiate_request_cb)( - conn, conn->config->renegotiate_request_ctx, &response)); - } + int result = conn->config->renegotiate_request_cb(conn, conn->config->renegotiate_request_ctx, &response); + RESULT_ENSURE(result == S2N_SUCCESS, S2N_ERR_CANCELLED); /* *= https://tools.ietf.org/rfc/rfc5246#section-7.4.1.1 @@ -72,7 +77,7 @@ S2N_RESULT s2n_client_hello_request_recv(struct s2n_connection *conn) *# the client if it does not wish to renegotiate a session, or the *# client may, if it wishes, respond with a no_renegotiation alert. */ - if (response != S2N_RENEGOTIATE_ACCEPT) { + if (response == S2N_RENEGOTIATE_REJECT) { RESULT_GUARD(s2n_queue_reader_no_renegotiation_alert(conn)); 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 dba71e2bf3..adaa533287 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_config.c +++ b/contrib/restricted/aws/s2n/tls/s2n_config.c @@ -1019,6 +1019,11 @@ int s2n_config_set_verify_after_sign(struct s2n_config *config, s2n_verify_after return S2N_SUCCESS; } +/* + *= https://tools.ietf.org/rfc/rfc5746#5 + *# TLS implementations SHOULD provide a mechanism to disable and enable + *# renegotiation. + */ int s2n_config_set_renegotiate_request_cb(struct s2n_config *config, s2n_renegotiate_request_cb cb, void *ctx) { POSIX_ENSURE_REF(config); diff --git a/contrib/restricted/aws/s2n/tls/s2n_crl.c b/contrib/restricted/aws/s2n/tls/s2n_crl.c new file mode 100644 index 0000000000..a3c404c353 --- /dev/null +++ b/contrib/restricted/aws/s2n/tls/s2n_crl.c @@ -0,0 +1,88 @@ +/* +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"). +* You may not use this file except in compliance with the License. +* A copy of the License is located at +* +* http://aws.amazon.com/apache2.0 +* +* or in the "license" file accompanying this file. This file is distributed +* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +* express or implied. See the License for the specific language governing +* permissions and limitations under the License. +*/ + +#include "s2n_crl.h" +#include "tls/s2n_connection.h" + +struct s2n_crl *s2n_crl_new(void) { + DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free); + PTR_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_crl))); + PTR_GUARD_POSIX(s2n_blob_zero(&mem)); + + struct s2n_crl *crl = (struct s2n_crl *)(void*) mem.data; + + ZERO_TO_DISABLE_DEFER_CLEANUP(mem); + return crl; +} + +int s2n_crl_load_pem(struct s2n_crl *crl, uint8_t *pem, size_t len) { + POSIX_ENSURE_REF(crl); + POSIX_ENSURE(crl->crl == NULL, S2N_ERR_INVALID_ARGUMENT); + + struct s2n_blob pem_blob = { 0 }; + POSIX_GUARD(s2n_blob_init(&pem_blob, pem, len)); + + struct s2n_stuffer pem_stuffer = { 0 }; + POSIX_GUARD(s2n_stuffer_init(&pem_stuffer, &pem_blob)); + POSIX_GUARD(s2n_stuffer_skip_write(&pem_stuffer, pem_blob.size)); + + DEFER_CLEANUP(struct s2n_stuffer der_out_stuffer = {0}, s2n_stuffer_free); + POSIX_GUARD(s2n_stuffer_growable_alloc(&der_out_stuffer, len)); + POSIX_GUARD(s2n_stuffer_crl_from_pem(&pem_stuffer, &der_out_stuffer)); + + uint32_t data_size = s2n_stuffer_data_available(&der_out_stuffer); + const uint8_t *data = s2n_stuffer_raw_read(&der_out_stuffer, data_size); + POSIX_ENSURE_REF(data); + crl->crl = d2i_X509_CRL(NULL, &data, data_size); + POSIX_ENSURE(crl->crl != NULL, S2N_ERR_INVALID_PEM); + + return S2N_SUCCESS; +} + +int s2n_crl_free(struct s2n_crl **crl) { + if (crl == NULL) { + return S2N_SUCCESS; + } + if (*crl == NULL) { + return S2N_SUCCESS; + } + + if ((*crl)->crl != NULL) { + X509_CRL_free((*crl)->crl); + (*crl)->crl = NULL; + } + + POSIX_GUARD(s2n_free_object((uint8_t **) crl, sizeof(struct s2n_crl))); + + *crl = NULL; + + return S2N_SUCCESS; +} + +int s2n_crl_get_issuer_hash(struct s2n_crl *crl, uint64_t *hash) { + POSIX_ENSURE_REF(crl); + POSIX_ENSURE_REF(crl->crl); + POSIX_ENSURE_REF(hash); + + X509_NAME *crl_name = X509_CRL_get_issuer(crl->crl); + POSIX_ENSURE_REF(crl_name); + + unsigned long temp_hash = X509_NAME_hash(crl_name); + POSIX_ENSURE(temp_hash != 0, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR); + + *hash = temp_hash; + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_crl.h b/contrib/restricted/aws/s2n/tls/s2n_crl.h new file mode 100644 index 0000000000..db8c967d32 --- /dev/null +++ b/contrib/restricted/aws/s2n/tls/s2n_crl.h @@ -0,0 +1,31 @@ +/* +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"). +* You may not use this file except in compliance with the License. +* A copy of the License is located at +* +* http://aws.amazon.com/apache2.0 +* +* or in the "license" file accompanying this file. This file is distributed +* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +* express or implied. See the License for the specific language governing +* permissions and limitations under the License. +*/ + +#pragma once + +#include "api/s2n.h" + +#include <openssl/x509v3.h> + +struct s2n_crl { + X509_CRL *crl; +}; + +/* TODO: APIs are part of an unfinished CRL validation feature and are temporarily hidden + * https://github.com/aws/s2n-tls/issues/3499 */ +struct s2n_crl *s2n_crl_new(void); +int s2n_crl_load_pem(struct s2n_crl *crl, uint8_t *pem, size_t len); +int s2n_crl_free(struct s2n_crl **crl); +int s2n_crl_get_issuer_hash(struct s2n_crl *crl, uint64_t *hash); diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_handshake.c index e8a8b12c58..cc343d622d 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_handshake.c +++ b/contrib/restricted/aws/s2n/tls/s2n_handshake.c @@ -373,6 +373,5 @@ S2N_RESULT s2n_handshake_set_finished_len(struct s2n_connection *conn, uint8_t l bool s2n_handshake_is_renegotiation(struct s2n_connection *conn) { - return s2n_in_unit_test() && conn && - (conn->mode == S2N_CLIENT) && conn->handshake.renegotiation; + return conn && conn->handshake.renegotiation; } diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c index 4e1737e2dc..7a28eb34b8 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c +++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c @@ -1149,6 +1149,25 @@ static S2N_RESULT s2n_finish_read(struct s2n_connection *conn) return S2N_RESULT_OK; } +static S2N_RESULT s2n_handshake_app_data_recv(struct s2n_connection *conn) +{ + if (conn->early_data_expected) { + RESULT_GUARD(s2n_early_data_validate_recv(conn)); + RESULT_BAIL(S2N_ERR_EARLY_DATA_BLOCKED); + } + + if (conn->handshake.renegotiation) { + RESULT_GUARD(s2n_renegotiate_validate(conn)); + /* During renegotiation, Application Data may only be received until + * the server acknowledges the new handshake with a ServerHello. + */ + RESULT_ENSURE(ACTIVE_MESSAGE(conn) == SERVER_HELLO, S2N_ERR_BAD_MESSAGE); + RESULT_BAIL(S2N_ERR_APP_DATA_BLOCKED); + } + + RESULT_BAIL(S2N_ERR_BAD_MESSAGE); +} + /* Reading is a little more complicated than writing as the TLS RFCs allow content * types to be interleaved at the record layer. We may get an alert message * during the handshake phase, or messages of types that we don't support (e.g. @@ -1204,9 +1223,7 @@ static int s2n_handshake_read_io(struct s2n_connection *conn) */ if (record_type == TLS_APPLICATION_DATA) { - POSIX_ENSURE(conn->early_data_expected, S2N_ERR_BAD_MESSAGE); - POSIX_GUARD_RESULT(s2n_early_data_validate_recv(conn)); - POSIX_BAIL(S2N_ERR_EARLY_DATA_BLOCKED); + POSIX_GUARD_RESULT(s2n_handshake_app_data_recv(conn)); } else if (record_type == TLS_CHANGE_CIPHER_SPEC) { /* TLS1.3 can receive unexpected CCS messages at any point in the handshake * due to a peer operating in middlebox compatibility mode. diff --git a/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c b/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c index f8bf49ddf8..f930390d79 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c +++ b/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c @@ -20,6 +20,25 @@ #include "tls/s2n_connection.h" #include "utils/s2n_safety.h" +/* We don't want to introduce a new blocked status for renegotiation + * because that would potentially require applications to update their + * blocked status handling logic for no reason. + * + * It is impossible to use both early data and renegotiation for the same handshake, + * and both are just application data received during the handshake. + * Therefore, we will alias S2N_BLOCKED_ON_EARLY_DATA for reuse with renegotiation. + */ +const s2n_blocked_status S2N_BLOCKED_ON_APPLICATION_DATA = S2N_BLOCKED_ON_EARLY_DATA; + +S2N_RESULT s2n_renegotiate_validate(struct s2n_connection *conn) +{ + RESULT_ENSURE_REF(conn); + RESULT_ENSURE(conn->mode == S2N_CLIENT, S2N_ERR_NO_RENEGOTIATION); + RESULT_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION); + RESULT_ENSURE(conn->handshake.renegotiation, S2N_ERR_INVALID_STATE); + return S2N_RESULT_OK; +} + /* * Prepare a connection to be reused for a second handshake. * @@ -93,6 +112,15 @@ int s2n_renegotiate_wipe(struct s2n_connection *conn) bool secure_renegotiation = conn->secure_renegotiation; POSIX_ENSURE(secure_renegotiation, S2N_ERR_NO_RENEGOTIATION); + /* Save the finished data. + * This is required for the renegotiate_info extension on the new handshake. + */ + uint8_t finished_len = conn->handshake.finished_len; + uint8_t client_finished[sizeof(conn->handshake.client_finished)] = { 0 }; + POSIX_CHECKED_MEMCPY(client_finished, conn->handshake.client_finished, finished_len); + uint8_t server_finished[sizeof(conn->handshake.server_finished)] = { 0 }; + POSIX_CHECKED_MEMCPY(server_finished, conn->handshake.server_finished, finished_len); + POSIX_GUARD(s2n_connection_wipe(conn)); /* Setup the new crypto parameters. @@ -107,6 +135,9 @@ int s2n_renegotiate_wipe(struct s2n_connection *conn) /* Restore saved values */ POSIX_GUARD_RESULT(s2n_connection_set_max_fragment_length(conn, max_frag_len)); + POSIX_CHECKED_MEMCPY(conn->handshake.client_finished, client_finished, finished_len); + POSIX_CHECKED_MEMCPY(conn->handshake.server_finished, server_finished, finished_len); + conn->handshake.finished_len = finished_len; conn->actual_protocol_version = actual_protocol_version; conn->server_protocol_version = server_protocol_version; conn->client_protocol_version = client_protocol_version; @@ -123,3 +154,45 @@ int s2n_renegotiate_wipe(struct s2n_connection *conn) conn->handshake.renegotiation = true; return S2N_SUCCESS; } + +static S2N_RESULT s2n_renegotiate_read_app_data(struct s2n_connection *conn, uint8_t *app_data_buf, ssize_t app_data_buf_size, + ssize_t *app_data_size, s2n_blocked_status *blocked) +{ + RESULT_ENSURE_REF(blocked); + + ssize_t r = s2n_recv(conn, app_data_buf, app_data_buf_size, blocked); + RESULT_GUARD_POSIX(r); + *app_data_size = r; + + *blocked = S2N_BLOCKED_ON_APPLICATION_DATA; + RESULT_BAIL(S2N_ERR_APP_DATA_BLOCKED); +} + +int s2n_renegotiate(struct s2n_connection *conn, uint8_t *app_data_buf, ssize_t app_data_buf_size, + ssize_t *app_data_size, s2n_blocked_status *blocked) +{ + POSIX_GUARD_RESULT(s2n_renegotiate_validate(conn)); + + POSIX_ENSURE_REF(app_data_size); + *app_data_size = 0; + + /* If there is outstanding application data, pass it back to the application. + * We can't read the next handshake record until we drain the buffer. + */ + if (s2n_peek(conn) > 0) { + POSIX_GUARD_RESULT(s2n_renegotiate_read_app_data(conn, + app_data_buf, app_data_buf_size, app_data_size, blocked)); + } + + int result = s2n_negotiate(conn, blocked); + + /* If we encounter application data while reading handshake records, + * pass it back to the application. + */ + if (result != S2N_SUCCESS && s2n_errno == S2N_ERR_APP_DATA_BLOCKED) { + POSIX_GUARD_RESULT(s2n_renegotiate_read_app_data(conn, + app_data_buf, app_data_buf_size, app_data_size, blocked)); + } + + return result; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_renegotiate.h b/contrib/restricted/aws/s2n/tls/s2n_renegotiate.h index 9e11e6e892..83333aa49b 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_renegotiate.h +++ b/contrib/restricted/aws/s2n/tls/s2n_renegotiate.h @@ -15,11 +15,7 @@ #pragma once -struct s2n_connection; -struct s2n_config; +#include "api/unstable/renegotiate.h" +#include "utils/s2n_result.h" -typedef enum { S2N_RENEGOTIATE_REJECT, S2N_RENEGOTIATE_ACCEPT} s2n_renegotiate_response; -typedef int (*s2n_renegotiate_request_cb)(struct s2n_connection *conn, void *context, s2n_renegotiate_response *response); -int s2n_config_set_renegotiate_request_cb(struct s2n_config *config, s2n_renegotiate_request_cb cb, void *ctx); - -int s2n_renegotiate_wipe(struct s2n_connection *conn); +S2N_RESULT s2n_renegotiate_validate(struct s2n_connection *conn); diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls.h b/contrib/restricted/aws/s2n/tls/s2n_tls.h index ca398b92b2..a4bffb18bf 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls.h +++ b/contrib/restricted/aws/s2n/tls/s2n_tls.h @@ -37,6 +37,8 @@ extern int s2n_server_hello_send(struct s2n_connection *conn); extern int s2n_server_hello_recv(struct s2n_connection *conn); extern int s2n_encrypted_extensions_send(struct s2n_connection *conn); extern int s2n_encrypted_extensions_recv(struct s2n_connection *conn); +extern int s2n_tls12_encrypted_extensions_send(struct s2n_connection *conn); +extern int s2n_tls12_encrypted_extensions_recv(struct s2n_connection *conn); extern int s2n_server_cert_send(struct s2n_connection *conn); extern int s2n_server_cert_recv(struct s2n_connection *conn); extern int s2n_server_status_send(struct s2n_connection *conn); diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls12_encrypted_extensions.c b/contrib/restricted/aws/s2n/tls/s2n_tls12_encrypted_extensions.c new file mode 100644 index 0000000000..b248ac5d3b --- /dev/null +++ b/contrib/restricted/aws/s2n/tls/s2n_tls12_encrypted_extensions.c @@ -0,0 +1,41 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "error/s2n_errno.h" +#include "utils/s2n_safety.h" +#include "stuffer/s2n_stuffer.h" + +#include "tls/s2n_tls.h" +#include "tls/extensions/s2n_extension_list.h" + +int s2n_tls12_encrypted_extensions_send(struct s2n_connection *conn) +{ + POSIX_ENSURE_REF(conn); + POSIX_ENSURE(conn->actual_protocol_version < S2N_TLS13, S2N_ERR_BAD_MESSAGE); + + struct s2n_stuffer *out = &conn->handshake.io; + POSIX_GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_ENCRYPTED_EXTENSIONS_TLS12, conn, out)); + return S2N_SUCCESS; +} + +int s2n_tls12_encrypted_extensions_recv(struct s2n_connection *conn) +{ + POSIX_ENSURE_REF(conn); + POSIX_ENSURE(conn->actual_protocol_version < S2N_TLS13, S2N_ERR_BAD_MESSAGE); + + struct s2n_stuffer *in = &conn->handshake.io; + POSIX_GUARD(s2n_extension_list_recv(S2N_EXTENSION_LIST_ENCRYPTED_EXTENSIONS_TLS12, conn, in)); + return S2N_SUCCESS; +} |