aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2022-10-19 19:34:47 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2022-10-19 19:34:47 +0300
commita42f7e7e0064e0d5bc54bde4506539d4766e1356 (patch)
tree348bb42084aed2b557684fbe188656938ab1a492 /contrib/restricted
parentcd66afc0fd1f9359cdf239e4a4f3a345b174e00e (diff)
downloadydb-a42f7e7e0064e0d5bc54bde4506539d4766e1356.tar.gz
Update contrib/restricted/aws/s2n to 1.3.24
Diffstat (limited to 'contrib/restricted')
-rw-r--r--contrib/restricted/aws/s2n/CMakeLists.darwin.txt2
-rw-r--r--contrib/restricted/aws/s2n/CMakeLists.linux.txt2
-rw-r--r--contrib/restricted/aws/s2n/README.md2
-rw-r--r--contrib/restricted/aws/s2n/api/s2n.h17
-rw-r--r--contrib/restricted/aws/s2n/error/s2n_errno.c3
-rw-r--r--contrib/restricted/aws/s2n/error/s2n_errno.h1
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_cbd.c4
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_fips202.c4
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_indcpa.c4
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_kem.c4
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_ntt.c4
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_params.h2
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_poly.c4
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_polyvec.c4
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_reduce.c4
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/s2n_pq.h1
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/s2n_pq_asm.h18
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c52
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.h1
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.c75
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_npn.c81
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_npn.h21
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c6
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c139
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_alerts.c32
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_alerts.h7
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_async_pkey.c14
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c15
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_finished.c34
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_hello.c28
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_hello_request.c55
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.c57
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.h12
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection.c1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake.c30
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake.h15
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake_io.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_post_handshake.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_prf.c6
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c25
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_renegotiate.c125
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_renegotiate.h25
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_resume.c16
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_resume.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_send.c5
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_finished.c65
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_hello.c1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls.h3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c10
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h6
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_x509_validator.c175
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_x509_validator.h1
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_array.c8
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_init.c18
58 files changed, 1039 insertions, 219 deletions
diff --git a/contrib/restricted/aws/s2n/CMakeLists.darwin.txt b/contrib/restricted/aws/s2n/CMakeLists.darwin.txt
index f634b97407..dd09fdecd4 100644
--- a/contrib/restricted/aws/s2n/CMakeLists.darwin.txt
+++ b/contrib/restricted/aws/s2n/CMakeLists.darwin.txt
@@ -103,6 +103,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_nst_early_data_indication.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.c
@@ -167,6 +168,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_record_read_stream.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_record_write.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_recv.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_resume.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_send.c
diff --git a/contrib/restricted/aws/s2n/CMakeLists.linux.txt b/contrib/restricted/aws/s2n/CMakeLists.linux.txt
index b1364fede1..f22ac9bb39 100644
--- a/contrib/restricted/aws/s2n/CMakeLists.linux.txt
+++ b/contrib/restricted/aws/s2n/CMakeLists.linux.txt
@@ -104,6 +104,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_nst_early_data_indication.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.c
@@ -168,6 +169,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_record_read_stream.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_record_write.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_recv.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_resume.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_send.c
diff --git a/contrib/restricted/aws/s2n/README.md b/contrib/restricted/aws/s2n/README.md
index 2c0e042865..a8e777075b 100644
--- a/contrib/restricted/aws/s2n/README.md
+++ b/contrib/restricted/aws/s2n/README.md
@@ -147,7 +147,7 @@ s2n-tls avoids implementing rarely used options and extensions, as well as featu
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.
+s2n-tls has been structured so that different encryption libraries may be used. Today s2n-tls supports OpenSSL (versions 1.0.2, 1.1.1 and 3.0.x), 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.
diff --git a/contrib/restricted/aws/s2n/api/s2n.h b/contrib/restricted/aws/s2n/api/s2n.h
index bd1d83ba0c..c555b1bc2f 100644
--- a/contrib/restricted/aws/s2n/api/s2n.h
+++ b/contrib/restricted/aws/s2n/api/s2n.h
@@ -871,6 +871,23 @@ extern int s2n_config_add_pem_to_trust_store(struct s2n_config *config, const ch
S2N_API
extern int s2n_config_wipe_trust_store(struct s2n_config *config);
+typedef enum { S2N_VERIFY_AFTER_SIGN_DISABLED, S2N_VERIFY_AFTER_SIGN_ENABLED } s2n_verify_after_sign;
+
+/**
+ * Toggle whether generated signatures are verified before being sent.
+ *
+ * Although signatures produced by the underlying libcrypto should always be valid,
+ * hardware faults, bugs in the signing implementation, or other uncommon factors
+ * can cause unexpected mistakes in the final signatures. Because these mistakes
+ * can leak information about the private key, applications with low trust in their
+ * hardware or libcrypto may want to verify signatures before sending them.
+ *
+ * However, this feature will significantly impact handshake latency.
+ * Additionally, most libcrypto implementations already check for common errors in signatures.
+ */
+S2N_API
+extern int s2n_config_set_verify_after_sign(struct s2n_config *config, s2n_verify_after_sign mode);
+
/**
* Set a custom send buffer size.
*
diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.c b/contrib/restricted/aws/s2n/error/s2n_errno.c
index 15b20d51bd..816b76780e 100644
--- a/contrib/restricted/aws/s2n/error/s2n_errno.c
+++ b/contrib/restricted/aws/s2n/error/s2n_errno.c
@@ -276,7 +276,8 @@ static const char *no_such_error = "Internal s2n error";
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_OSSL_PROVIDER, "Failed to load or unload an openssl provider") \
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_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") \
/* 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 473daa4fd4..17482e6033 100644
--- a/contrib/restricted/aws/s2n/error/s2n_errno.h
+++ b/contrib/restricted/aws/s2n/error/s2n_errno.h
@@ -128,6 +128,7 @@ typedef enum {
S2N_ERR_DUPLICATE_EXTENSION,
S2N_ERR_MAX_EARLY_DATA_SIZE,
S2N_ERR_EARLY_DATA_TRIAL_DECRYPT,
+ S2N_ERR_NO_RENEGOTIATION,
S2N_ERR_T_PROTO_END,
/* S2N_ERR_T_INTERNAL */
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 ef0bb87946..72f2941683 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,6 +2,10 @@
#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
+
/*************************************************
* 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 c5ce0c91f2..b9f7fbaea8 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,6 +14,10 @@
#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
+
/*************************************************
* 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 ace1783448..5b03bc7cff 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,6 +9,10 @@
#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
+
/*************************************************
* 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 9d6c49b9c4..d5d1dd22be 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,6 +9,10 @@
#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
+
/*************************************************
* 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 6c82105c19..921f6ffc2c 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,6 +3,10 @@
#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
+
const int16_t zetas[128] = {
2285, 2571, 2970, 1812, 1493, 1422, 287, 202, 3158, 622, 1577, 182, 962,
2127, 1855, 1468, 573, 2004, 264, 383, 2500, 1458, 1727, 3199, 2648, 1017,
diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_params.h b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_params.h
index d2d32d08f1..76c1578584 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_params.h
+++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_params.h
@@ -1,5 +1,7 @@
#pragma once
+#include "pq-crypto/s2n_pq_asm.h"
+
/* All kyber512r3 functions and global variables in the pq-crypto/kyber_r3 directory
* should be defined using the namespace macro to avoid symbol collisions. For example,
* in foo.h, declare a function as follows:
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 76ae60a583..3cc392b0d4 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,6 +6,10 @@
#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
+
/*************************************************
* 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 0a84cd092a..9800da93e7 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,6 +3,10 @@
#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
+
/*************************************************
* 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 6219ad7e88..e764568826 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,6 +2,10 @@
#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
+
/*************************************************
* Name: montgomery_reduce
*
diff --git a/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.h b/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.h
index 6a4ed533f2..1c9ca37812 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.h
+++ b/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.h
@@ -19,6 +19,7 @@
#include "utils/s2n_result.h"
#include "utils/s2n_safety.h"
#include "crypto/s2n_fips.h"
+#include "pq-crypto/s2n_pq_asm.h"
bool s2n_kyber512r3_is_avx2_bmi2_enabled(void);
S2N_RESULT s2n_try_enable_kyber512r3_opt_avx2_bmi2(void);
diff --git a/contrib/restricted/aws/s2n/pq-crypto/s2n_pq_asm.h b/contrib/restricted/aws/s2n/pq-crypto/s2n_pq_asm.h
new file mode 100644
index 0000000000..1a39464d48
--- /dev/null
+++ b/contrib/restricted/aws/s2n/pq-crypto/s2n_pq_asm.h
@@ -0,0 +1,18 @@
+/*
+ * 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
+
+#define S2N_ANY_NONPORTABLE_OPTIMIZATIONS_ENABLED __AVX__ || __AVX2__ || __BMI2__
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c
index b7fd2678ed..0c85cc8389 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c
@@ -25,7 +25,7 @@
#include "utils/s2n_safety.h"
-static bool s2n_client_alpn_should_send(struct s2n_connection *conn);
+bool s2n_client_alpn_should_send(struct s2n_connection *conn);
static int s2n_client_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out);
static int s2n_client_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
@@ -38,7 +38,7 @@ const s2n_extension_type s2n_client_alpn_extension = {
.if_missing = s2n_extension_noop_if_missing,
};
-static bool s2n_client_alpn_should_send(struct s2n_connection *conn)
+bool s2n_client_alpn_should_send(struct s2n_connection *conn)
{
struct s2n_blob *client_app_protocols;
@@ -60,47 +60,31 @@ static int s2n_client_alpn_send(struct s2n_connection *conn, struct s2n_stuffer
static int s2n_client_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- uint16_t size_of_all;
- struct s2n_stuffer server_protos = {0};
+ struct s2n_blob *supported_protocols = NULL;
+ POSIX_GUARD(s2n_connection_get_protocol_preferences(conn, &supported_protocols));
+ POSIX_ENSURE_REF(supported_protocols);
- struct s2n_blob *server_app_protocols;
- POSIX_GUARD(s2n_connection_get_protocol_preferences(conn, &server_app_protocols));
-
- if (!server_app_protocols->size) {
+ if (supported_protocols->size == 0) {
/* No protocols configured, nothing to do */
return S2N_SUCCESS;
}
- POSIX_GUARD(s2n_stuffer_read_uint16(extension, &size_of_all));
- if (size_of_all > s2n_stuffer_data_available(extension) || size_of_all < 3) {
+ uint16_t wire_size = 0;
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &wire_size));
+ if (wire_size > s2n_stuffer_data_available(extension) || wire_size < 3) {
/* Malformed length, ignore the extension */
return S2N_SUCCESS;
}
+
+ struct s2n_blob client_protocols = { 0 };
+ POSIX_GUARD(s2n_blob_init(&client_protocols, s2n_stuffer_raw_read(extension, wire_size), wire_size));
+
+ struct s2n_stuffer server_protocols = { 0 };
+ POSIX_GUARD(s2n_stuffer_init(&server_protocols, supported_protocols));
+ POSIX_GUARD(s2n_stuffer_skip_write(&server_protocols, supported_protocols->size));
+
+ POSIX_GUARD_RESULT(s2n_select_server_preference_protocol(conn, &server_protocols, &client_protocols));
- struct s2n_blob client_app_protocols = { 0 };
- client_app_protocols.size = size_of_all;
- client_app_protocols.data = s2n_stuffer_raw_read(extension, size_of_all);
- POSIX_ENSURE_REF(client_app_protocols.data);
-
- /* Find a matching protocol */
- POSIX_GUARD(s2n_stuffer_init(&server_protos, server_app_protocols));
- POSIX_GUARD(s2n_stuffer_skip_write(&server_protos, server_app_protocols->size));
-
- while (s2n_stuffer_data_available(&server_protos) > 0) {
- struct s2n_blob server_protocol = { 0 };
- POSIX_ENSURE(s2n_result_is_ok(s2n_protocol_preferences_read(&server_protos, &server_protocol)),
- S2N_ERR_BAD_MESSAGE);
-
- bool is_match = false;
- POSIX_ENSURE(s2n_result_is_ok(s2n_protocol_preferences_contain(&client_app_protocols, &server_protocol, &is_match)),
- S2N_ERR_BAD_MESSAGE);
-
- if (is_match) {
- POSIX_CHECKED_MEMCPY(conn->application_protocol, server_protocol.data, server_protocol.size);
- conn->application_protocol[server_protocol.size] = '\0';
- return S2N_SUCCESS;
- }
- }
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.h
index 177ca5daea..bc0590b32a 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.h
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.h
@@ -20,6 +20,7 @@
#include "stuffer/s2n_stuffer.h"
extern const s2n_extension_type s2n_client_alpn_extension;
+bool s2n_client_alpn_should_send(struct s2n_connection *conn);
/* Old-style extension functions -- remove after extensions refactor is complete */
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 772712fda4..ac11ad22e2 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
@@ -21,25 +21,90 @@
#include "utils/s2n_safety.h"
+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);
const s2n_extension_type s2n_client_renegotiation_info_extension = {
.iana_value = TLS_EXTENSION_RENEGOTIATION_INFO,
.is_response = false,
- .send = s2n_extension_send_unimplemented,
+ .send = s2n_client_renegotiation_send,
.recv = s2n_client_renegotiation_recv,
- .should_send = s2n_extension_never_send,
+ .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,
};
+/**
+ *= https://tools.ietf.org/rfc/rfc5746#3.5
+ *# o The client MUST include the "renegotiation_info" extension in the
+ *# ClientHello
+ */
+static bool s2n_client_renegotiation_should_send(struct s2n_connection *conn)
+{
+ return conn && s2n_handshake_is_renegotiation(conn);
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc5746#3.5
+ *# o The client MUST include the "renegotiation_info" extension in the
+ *# ClientHello, containing the saved client_verify_data.
+ */
+static int s2n_client_renegotiation_send(struct s2n_connection *conn, struct s2n_stuffer *out)
+{
+ POSIX_ENSURE_REF(conn);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc5746#3.5
+ *# This text applies if the connection's "secure_renegotiation" flag is
+ *# set to TRUE (if it is set to FALSE, see Section 4.2).
+ */
+ POSIX_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION);
+
+ uint8_t renegotiated_connection_len = conn->handshake.finished_len;
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, renegotiated_connection_len));
+ POSIX_GUARD(s2n_stuffer_write_bytes(out, conn->handshake.client_finished, renegotiated_connection_len));
+
+ return S2N_SUCCESS;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc5746#3.6
+ *# o The server MUST check if the "renegotiation_info" extension is
+ *# included in the ClientHello.
+ */
static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- /* RFC5746 Section 3.2: The renegotiated_connection field is of zero length for the initial handshake. */
- uint8_t renegotiated_connection_len;
+ /**
+ *= https://tools.ietf.org/rfc/rfc5746#3.6
+ *# The server MUST then verify
+ *# that the length of the "renegotiated_connection" field is zero,
+ *# and if it is not, MUST abort the handshake.
+ */
+ uint8_t renegotiated_connection_len = 0;
POSIX_GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len));
- S2N_ERROR_IF(s2n_stuffer_data_available(extension) || renegotiated_connection_len, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
+ POSIX_ENSURE(s2n_stuffer_data_available(extension) == 0, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
+ POSIX_ENSURE(renegotiated_connection_len == 0, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
+ /**
+ *= https://tools.ietf.org/rfc/rfc5746#3.6
+ *# If the extension is present, set secure_renegotiation flag to TRUE.
+ */
conn->secure_renegotiation = 1;
+
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.c
new file mode 100644
index 0000000000..61c5b3a6d1
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.c
@@ -0,0 +1,81 @@
+/*
+ * 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 "tls/extensions/s2n_npn.h"
+#include "tls/extensions/s2n_client_alpn.h"
+#include "tls/extensions/s2n_server_alpn.h"
+#include "tls/s2n_tls.h"
+#include "tls/s2n_tls_parameters.h"
+#include "tls/s2n_protocol_preferences.h"
+
+#include "utils/s2n_safety.h"
+
+bool s2n_npn_should_send(struct s2n_connection *conn)
+{
+ return s2n_client_alpn_should_send(conn) && conn->config->npn_supported;
+}
+
+const s2n_extension_type s2n_client_npn_extension = {
+ .iana_value = TLS_EXTENSION_NPN,
+ .is_response = false,
+ .send = s2n_extension_send_noop,
+ .recv = s2n_extension_recv_noop,
+ .should_send = s2n_npn_should_send,
+ .if_missing = s2n_extension_noop_if_missing,
+};
+
+bool s2n_server_npn_should_send(struct s2n_connection *conn)
+{
+ /* Only use the NPN extension to negotiate a protocol if we don't have
+ * an option to use the ALPN extension.
+ */
+ return s2n_npn_should_send(conn) && !s2n_server_alpn_should_send(conn);
+}
+
+int s2n_server_npn_send(struct s2n_connection *conn, struct s2n_stuffer *out)
+{
+ struct s2n_blob *app_protocols = NULL;
+ POSIX_GUARD(s2n_connection_get_protocol_preferences(conn, &app_protocols));
+ POSIX_ENSURE_REF(app_protocols);
+
+ POSIX_GUARD(s2n_stuffer_write(out, app_protocols));
+
+ return S2N_SUCCESS;
+}
+
+int s2n_server_npn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
+{
+ struct s2n_blob *supported_protocols = NULL;
+ POSIX_GUARD(s2n_connection_get_protocol_preferences(conn, &supported_protocols));
+ POSIX_ENSURE_REF(supported_protocols);
+
+ if (supported_protocols->size == 0) {
+ /* No protocols configured */
+ return S2N_SUCCESS;
+ }
+
+ POSIX_GUARD_RESULT(s2n_select_server_preference_protocol(conn, extension, supported_protocols));
+
+ return S2N_SUCCESS;
+}
+
+const s2n_extension_type s2n_server_npn_extension = {
+ .iana_value = TLS_EXTENSION_NPN,
+ .is_response = true,
+ .send = s2n_server_npn_send,
+ .recv = s2n_server_npn_recv,
+ .should_send = s2n_server_npn_should_send,
+ .if_missing = s2n_extension_noop_if_missing,
+};
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.h
new file mode 100644
index 0000000000..0b03e5c1b4
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_npn.h
@@ -0,0 +1,21 @@
+/*
+ * 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 "tls/extensions/s2n_extension_type.h"
+
+extern const s2n_extension_type s2n_client_npn_extension;
+extern const s2n_extension_type s2n_server_npn_extension;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c
index 9e6dee2136..a62f63c167 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c
@@ -22,7 +22,7 @@
#include "tls/extensions/s2n_server_alpn.h"
-static bool s2n_alpn_should_send(struct s2n_connection *conn);
+bool s2n_server_alpn_should_send(struct s2n_connection *conn);
static int s2n_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out);
static int s2n_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
@@ -31,11 +31,11 @@ const s2n_extension_type s2n_server_alpn_extension = {
.is_response = true,
.send = s2n_alpn_send,
.recv = s2n_alpn_recv,
- .should_send = s2n_alpn_should_send,
+ .should_send = s2n_server_alpn_should_send,
.if_missing = s2n_extension_noop_if_missing,
};
-static bool s2n_alpn_should_send(struct s2n_connection *conn)
+bool s2n_server_alpn_should_send(struct s2n_connection *conn)
{
return conn && strlen(conn->application_protocol) > 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.h
index ccdf3fce9c..675e4dcffb 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.h
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.h
@@ -18,3 +18,5 @@
#include "tls/extensions/s2n_extension_type.h"
extern const s2n_extension_type s2n_server_alpn_extension;
+
+bool s2n_server_alpn_should_send(struct s2n_connection *conn);
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 6da5481ec9..1052a41ab1 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
@@ -27,43 +27,160 @@
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);
+static int s2n_renegotiation_info_if_missing(struct s2n_connection *conn);
const s2n_extension_type s2n_server_renegotiation_info_extension = {
.iana_value = TLS_EXTENSION_RENEGOTIATION_INFO,
- .is_response = false,
.send = s2n_renegotiation_info_send,
.recv = s2n_renegotiation_info_recv,
.should_send = s2n_renegotiation_info_should_send,
- .if_missing = s2n_extension_noop_if_missing,
+ .if_missing = s2n_renegotiation_info_if_missing,
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc5746#3.6
+ *# Note that sending a "renegotiation_info" extension in response to a
+ *# ClientHello containing only the SCSV is an explicit exception to the
+ *# prohibition in RFC 5246, Section 7.4.1.4, on the server sending
+ *# unsolicited extensions and is only allowed because the client is
+ *# signaling its willingness to receive the extension via the
+ *# TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
+ *
+ * This extension is technically a response extension, but doesn't
+ * follow any of the usual response extension rules.
+ * s2n-tls will therefore not treat it as a response extension.
+ */
+ .is_response = false,
};
+/**
+ *= https://tools.ietf.org/rfc/rfc5746#3.6
+ *# o If the secure_renegotiation flag is set to TRUE, the server MUST
+ *# include an empty "renegotiation_info" extension in the ServerHello
+ *# message.
+ */
static bool s2n_renegotiation_info_should_send(struct s2n_connection *conn)
{
return conn && conn->secure_renegotiation && s2n_connection_get_protocol_version(conn) < S2N_TLS13;
}
+/**
+ *= https://tools.ietf.org/rfc/rfc5746#3.6
+ *# o If the secure_renegotiation flag is set to TRUE, the server MUST
+ *# include an empty "renegotiation_info" extension in the ServerHello
+ *# message.
+ */
static int s2n_renegotiation_info_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- /* renegotiated_connection length. Zero since we don't support renegotiation. */
POSIX_GUARD(s2n_stuffer_write_uint8(out, 0));
return S2N_SUCCESS;
}
-static int s2n_renegotiation_info_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
+/**
+ *= https://tools.ietf.org/rfc/rfc5746#3.4
+ *# o When a ServerHello is received, the client MUST check if it
+ *# includes the "renegotiation_info" extension:
+ */
+static int s2n_renegotiation_info_recv_initial(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- /* RFC5746 Section 3.4: The client MUST then verify that the length of
- * the "renegotiated_connection" field is zero, and if it is not, MUST
- * abort the handshake. */
- uint8_t renegotiated_connection_len;
+ POSIX_ENSURE_REF(conn);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc5746#3.4
+ *# * The client MUST then verify that the length of the
+ *# "renegotiated_connection" field is zero, and if it is not, MUST
+ *# abort the handshake (by sending a fatal handshake_failure alert).
+ */
+ uint8_t renegotiated_connection_len = 0;
POSIX_GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len));
- S2N_ERROR_IF(s2n_stuffer_data_available(extension), S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
- S2N_ERROR_IF(renegotiated_connection_len, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
+ POSIX_ENSURE(s2n_stuffer_data_available(extension) == 0, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
+ POSIX_ENSURE(renegotiated_connection_len == 0, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
- POSIX_ENSURE_REF(conn);
+ /**
+ *= https://tools.ietf.org/rfc/rfc5746#3.4
+ *# * If the extension is present, set the secure_renegotiation flag to TRUE.
+ */
conn->secure_renegotiation = 1;
return S2N_SUCCESS;
}
+static int s2n_renegotiation_info_recv_renegotiation(struct s2n_connection *conn, struct s2n_stuffer *extension)
+{
+ POSIX_ENSURE_REF(conn);
+ uint8_t verify_data_len = conn->handshake.finished_len;
+ POSIX_ENSURE_GT(verify_data_len, 0);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc5746#3.5
+ *# This text applies if the connection's "secure_renegotiation" flag is
+ *# set to TRUE (if it is set to FALSE, see Section 4.2).
+ */
+ POSIX_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc5746#3.5
+ *# o The client MUST then verify that the first half of the
+ *# "renegotiated_connection" field is equal to the saved
+ *# client_verify_data value, and the second half is equal to the
+ *# saved server_verify_data value. If they are not, the client MUST
+ *# abort the handshake.
+ */
+
+ uint8_t renegotiated_connection_len = 0;
+ POSIX_GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len));
+ POSIX_ENSURE(verify_data_len * 2 == renegotiated_connection_len, S2N_ERR_BAD_MESSAGE);
+
+ uint8_t *first_half = s2n_stuffer_raw_read(extension, verify_data_len);
+ POSIX_ENSURE_REF(first_half);
+ POSIX_ENSURE(s2n_constant_time_equals(first_half, conn->handshake.client_finished, verify_data_len),
+ S2N_ERR_BAD_MESSAGE);
+
+ uint8_t *second_half = s2n_stuffer_raw_read(extension, verify_data_len);
+ POSIX_ENSURE_REF(second_half);
+ POSIX_ENSURE(s2n_constant_time_equals(second_half, conn->handshake.server_finished, verify_data_len),
+ S2N_ERR_BAD_MESSAGE);
+
+ return S2N_SUCCESS;
+}
+
+static int s2n_renegotiation_info_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
+{
+ if (s2n_handshake_is_renegotiation(conn)) {
+ POSIX_GUARD(s2n_renegotiation_info_recv_renegotiation(conn, extension));
+ } else {
+ POSIX_GUARD(s2n_renegotiation_info_recv_initial(conn, extension));
+ }
+ return S2N_SUCCESS;
+}
+
+static int s2n_renegotiation_info_if_missing(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+ if (s2n_handshake_is_renegotiation(conn)) {
+ /**
+ *= https://tools.ietf.org/rfc/rfc5746#3.5
+ *# o When a ServerHello is received, the client MUST verify that the
+ *# "renegotiation_info" extension is present; if it is not, the
+ *# client MUST abort the handshake.
+ */
+ POSIX_BAIL(S2N_ERR_NO_RENEGOTIATION);
+ } else {
+ /**
+ *= https://tools.ietf.org/rfc/rfc5746#3.4
+ *# * If the extension is not present, the server does not support
+ *# 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;
+ return S2N_SUCCESS;
+ }
+}
+
/* Old-style extension functions -- remove after extensions refactor is complete */
int s2n_recv_server_renegotiation_info_ext(struct s2n_connection *conn, struct s2n_stuffer *extension)
diff --git a/contrib/restricted/aws/s2n/tls/s2n_alerts.c b/contrib/restricted/aws/s2n/tls/s2n_alerts.c
index 51f13b416f..5ecf10b47d 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_alerts.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_alerts.c
@@ -54,6 +54,14 @@ static S2N_RESULT s2n_translate_protocol_error_to_alert(int error_code, uint8_t
*/
S2N_ALERT_CASE(S2N_ERR_BAD_MESSAGE, S2N_TLS_ALERT_UNEXPECTED_MESSAGE);
+ /* For errors involving secure renegotiation:
+ *= https://tools.ietf.org/rfc/rfc5746#3.4
+ *# Note: later in Section 3, "abort the handshake" is used as
+ *# shorthand for "send a fatal handshake_failure alert and
+ *# terminate the connection".
+ */
+ S2N_ALERT_CASE(S2N_ERR_NO_RENEGOTIATION, S2N_TLS_ALERT_HANDSHAKE_FAILURE);
+
/* TODO: Add mappings for other protocol errors.
*/
S2N_NO_ALERT(S2N_ERR_ENCRYPT);
@@ -128,7 +136,7 @@ static bool s2n_alerts_supported(struct s2n_connection *conn)
return !s2n_connection_is_quic_enabled(conn);
}
-static bool s2n_handle_as_warning(struct s2n_connection *conn, uint8_t level, uint8_t type)
+static bool s2n_process_as_warning(struct s2n_connection *conn, uint8_t level, uint8_t type)
{
/* Only TLS1.2 considers the alert level. The alert level field is
* considered deprecated in TLS1.3. */
@@ -143,6 +151,20 @@ static bool s2n_handle_as_warning(struct s2n_connection *conn, uint8_t level, ui
return type == S2N_TLS_ALERT_USER_CANCELED;
}
+S2N_RESULT s2n_alerts_close_if_fatal(struct s2n_connection *conn, struct s2n_blob *alert)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(alert);
+ RESULT_ENSURE_EQ(alert->size, S2N_ALERT_LENGTH);
+ /* Only one alert should currently be treated as a warning */
+ if (alert->data[1] == S2N_TLS_ALERT_NO_RENEGOTIATION) {
+ RESULT_ENSURE_EQ(alert->data[0], S2N_TLS_ALERT_LEVEL_WARNING);
+ return S2N_RESULT_OK;
+ }
+ conn->closing = true;
+ return S2N_RESULT_OK;
+}
+
int s2n_error_get_alert(int error, uint8_t *alert)
{
int error_type = s2n_error_get_type(error);
@@ -198,7 +220,7 @@ int s2n_process_alert_fragment(struct s2n_connection *conn)
}
/* Ignore warning-level alerts if we're in warning-tolerant mode */
- if (s2n_handle_as_warning(conn, conn->alert_in_data[0], conn->alert_in_data[1])) {
+ if (s2n_process_as_warning(conn, conn->alert_in_data[0], conn->alert_in_data[1])) {
POSIX_GUARD(s2n_stuffer_wipe(&conn->alert_in));
return 0;
}
@@ -275,3 +297,9 @@ int s2n_queue_reader_handshake_failure_alert(struct s2n_connection *conn)
{
return s2n_queue_reader_alert(conn, S2N_TLS_ALERT_LEVEL_FATAL, S2N_TLS_ALERT_HANDSHAKE_FAILURE);
}
+
+S2N_RESULT s2n_queue_reader_no_renegotiation_alert(struct s2n_connection *conn)
+{
+ 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_alerts.h b/contrib/restricted/aws/s2n/tls/s2n_alerts.h
index da735db9d8..eec1dde6fa 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_alerts.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_alerts.h
@@ -74,6 +74,11 @@ typedef enum {
S2N_TLS_ALERT_INAPPROPRIATE_FALLBACK = 86,
S2N_TLS_ALERT_USER_CANCELED = 90,
/*
+ *= https://tools.ietf.org/rfc/rfc5246#section-7.2
+ *# no_renegotiation(100),
+ */
+ S2N_TLS_ALERT_NO_RENEGOTIATION = 100,
+ /*
*= https://tools.ietf.org/rfc/rfc8446#section-6
*# missing_extension(109),
*# unsupported_extension(110),
@@ -101,3 +106,5 @@ extern int s2n_process_alert_fragment(struct s2n_connection *conn);
extern int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn);
extern int s2n_queue_reader_unsupported_protocol_version_alert(struct s2n_connection *conn);
extern int s2n_queue_reader_handshake_failure_alert(struct s2n_connection *conn);
+S2N_RESULT s2n_queue_reader_no_renegotiation_alert(struct s2n_connection *conn);
+S2N_RESULT s2n_alerts_close_if_fatal(struct s2n_connection *conn, struct s2n_blob *alert);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c
index 062324db57..1eb5611bd9 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c
@@ -253,6 +253,9 @@ S2N_RESULT s2n_async_pkey_sign_async(struct s2n_connection *conn, s2n_signature_
op->type = S2N_ASYNC_SIGN;
op->conn = conn;
op->validation_mode = conn->config->async_pkey_validation_mode;
+ if (conn->config->verify_after_sign) {
+ op->validation_mode = S2N_ASYNC_PKEY_VALIDATION_STRICT;
+ }
struct s2n_async_pkey_sign_data *sign = &op->op.sign;
sign->on_complete = on_complete;
@@ -279,7 +282,16 @@ S2N_RESULT s2n_async_pkey_sign_sync(struct s2n_connection *conn, s2n_signature_a
RESULT_GUARD(s2n_pkey_size(pkey, &maximum_signature_length));
RESULT_GUARD_POSIX(s2n_alloc(&signed_content, maximum_signature_length));
- RESULT_GUARD_POSIX(s2n_pkey_sign(pkey, sig_alg, digest, &signed_content));
+ RESULT_ENSURE_REF(conn->config);
+ if (conn->config->verify_after_sign) {
+ DEFER_CLEANUP(struct s2n_hash_state digest_for_verify, s2n_hash_free);
+ RESULT_GUARD_POSIX(s2n_hash_new(&digest_for_verify));
+ RESULT_GUARD_POSIX(s2n_hash_copy(&digest_for_verify, digest));
+ RESULT_GUARD_POSIX(s2n_pkey_sign(pkey, sig_alg, digest, &signed_content));
+ RESULT_GUARD(s2n_async_pkey_verify_signature(conn, sig_alg, &digest_for_verify, &signed_content));
+ } else {
+ RESULT_GUARD_POSIX(s2n_pkey_sign(pkey, sig_alg, digest, &signed_content));
+ }
RESULT_GUARD_POSIX(on_complete(conn, &signed_content));
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
index 7e0256524a..75cf0f6ba4 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
@@ -1028,7 +1028,7 @@ int s2n_cipher_suites_init(void)
}
/* Reset any selected record algorithms */
-int s2n_cipher_suites_cleanup(void)
+S2N_RESULT s2n_cipher_suites_cleanup(void)
{
const int num_cipher_suites = sizeof(s2n_all_cipher_suites) / sizeof(struct s2n_cipher_suite *);
for (int i = 0; i < num_cipher_suites; i++) {
@@ -1038,7 +1038,7 @@ int s2n_cipher_suites_cleanup(void)
/* Release custom SSLv3 cipher suites */
if (cur_suite->sslv3_cipher_suite != cur_suite) {
- POSIX_GUARD(s2n_free_object((uint8_t **)&cur_suite->sslv3_cipher_suite, sizeof(struct s2n_cipher_suite)));
+ RESULT_GUARD_POSIX(s2n_free_object((uint8_t **)&cur_suite->sslv3_cipher_suite, sizeof(struct s2n_cipher_suite)));
}
cur_suite->sslv3_cipher_suite = NULL;
}
@@ -1053,7 +1053,7 @@ int s2n_cipher_suites_cleanup(void)
#endif
}
- return 0;
+ return S2N_RESULT_OK;
}
S2N_RESULT s2n_cipher_suite_from_iana(const uint8_t iana[static S2N_TLS_CIPHER_SUITE_LEN], struct s2n_cipher_suite **cipher_suite)
@@ -1188,7 +1188,12 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire,
}
}
- /* RFC5746 Section 3.6: A server must check if TLS_EMPTY_RENEGOTIATION_INFO_SCSV is included */
+ /**
+ *= 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)) {
conn->secure_renegotiation = 1;
}
@@ -1210,7 +1215,7 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire,
}
/* If connection is for SSLv3, use SSLv3 version of suites */
- if (conn->client_protocol_version == S2N_SSLv3) {
+ if (conn->actual_protocol_version == S2N_SSLv3) {
match = match->sslv3_cipher_suite;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
index 686037c2fa..4467cbb894 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
@@ -159,7 +159,7 @@ extern struct s2n_cipher_suite s2n_tls13_aes_128_gcm_sha256;
extern struct s2n_cipher_suite s2n_tls13_chacha20_poly1305_sha256;
extern int s2n_cipher_suites_init(void);
-extern int s2n_cipher_suites_cleanup(void);
+S2N_RESULT s2n_cipher_suites_cleanup(void);
S2N_RESULT s2n_cipher_suite_from_iana(const uint8_t iana[S2N_TLS_CIPHER_SUITE_LEN], struct s2n_cipher_suite **cipher_suite);
extern int s2n_set_cipher_as_client(struct s2n_connection *conn, uint8_t wire[S2N_TLS_CIPHER_SUITE_LEN]);
extern int s2n_set_cipher_as_sslv2_server(struct s2n_connection *conn, uint8_t * wire, uint16_t count);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_finished.c b/contrib/restricted/aws/s2n/tls/s2n_client_finished.c
index 5a17228754..348b1602cd 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_finished.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_finished.c
@@ -25,39 +25,31 @@
#include "utils/s2n_safety.h"
+S2N_RESULT s2n_finished_recv(struct s2n_connection *conn, uint8_t *our_version);
+S2N_RESULT s2n_finished_send(struct s2n_connection *conn, uint8_t *seq_num, uint8_t *our_version);
+
int s2n_client_finished_recv(struct s2n_connection *conn)
{
- uint8_t *our_version;
- our_version = conn->handshake.client_finished;
- uint8_t *their_version = s2n_stuffer_raw_read(&conn->handshake.io, S2N_TLS_FINISHED_LEN);
- POSIX_ENSURE_REF(their_version);
-
- S2N_ERROR_IF(!s2n_constant_time_equals(our_version, their_version, S2N_TLS_FINISHED_LEN) || conn->handshake.rsa_failed, S2N_ERR_BAD_MESSAGE);
-
- return 0;
+ POSIX_ENSURE_REF(conn);
+ uint8_t *verify_data = conn->handshake.client_finished;
+ POSIX_GUARD_RESULT(s2n_finished_recv(conn, verify_data));
+ POSIX_ENSURE(!conn->handshake.rsa_failed, S2N_ERR_BAD_MESSAGE);
+ return S2N_SUCCESS;
}
int s2n_client_finished_send(struct s2n_connection *conn)
{
POSIX_ENSURE_REF(conn);
- POSIX_ENSURE_REF(conn->secure);
- uint8_t *our_version;
+ uint8_t *verify_data = conn->handshake.client_finished;
+ uint8_t *seq_num = conn->secure->client_sequence_number;
POSIX_GUARD(s2n_prf_client_finished(conn));
+ POSIX_GUARD_RESULT(s2n_finished_send(conn, seq_num, verify_data));
- struct s2n_blob seq = {.data = conn->secure->client_sequence_number,.size = sizeof(conn->secure->client_sequence_number) };
- POSIX_GUARD(s2n_blob_zero(&seq));
- our_version = conn->handshake.client_finished;
-
- /* Update the server to use the cipher suite */
+ POSIX_ENSURE_REF(conn->secure);
conn->client = conn->secure;
- if (conn->actual_protocol_version == S2N_SSLv3) {
- POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, our_version, S2N_SSL_FINISHED_LEN));
- } else {
- POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, our_version, S2N_TLS_FINISHED_LEN));
- }
- return 0;
+ return S2N_SUCCESS;
}
int s2n_tls13_client_finished_recv(struct s2n_connection *conn) {
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
index d382cb1ab8..e9d5bb6adf 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
@@ -320,6 +320,11 @@ int s2n_parse_client_hello(struct s2n_connection *conn)
POSIX_GUARD(s2n_collect_client_hello(conn, &conn->handshake.io));
+ /* The ClientHello version must be TLS12 after a HelloRetryRequest */
+ if (s2n_is_hello_retry_handshake(conn)) {
+ POSIX_ENSURE_EQ(conn->client_hello_version, S2N_TLS12);
+ }
+
if (conn->client_hello_version == S2N_SSLv2) {
POSIX_GUARD(s2n_sslv2_client_hello_recv(conn));
return S2N_SUCCESS;
@@ -592,20 +597,33 @@ int s2n_client_hello_send(struct s2n_connection *conn)
/* Now, write the IANA values of every available cipher suite in our list */
struct s2n_cipher_suite *cipher = NULL;
- bool legacy_renegotiation_signal_required = false;
- for (int i = 0; i < security_policy->cipher_preferences->count; i++ ) {
+ bool tls12_is_possible = false;
+ for (size_t i = 0; i < security_policy->cipher_preferences->count; i++) {
cipher = cipher_preferences->suites[i];
if (s2n_result_is_error(s2n_cipher_suite_validate_available(conn, cipher))) {
continue;
}
if (cipher->minimum_required_tls_version < S2N_TLS13) {
- legacy_renegotiation_signal_required = true;
+ tls12_is_possible = true;
}
POSIX_GUARD(s2n_stuffer_write_bytes(out, cipher->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
}
- if (legacy_renegotiation_signal_required) {
- /* Lastly, write TLS_EMPTY_RENEGOTIATION_INFO_SCSV so that server knows it's an initial handshake (RFC5746 Section 3.4) */
+ /**
+ * For initial handshakes:
+ *= https://tools.ietf.org/rfc/rfc5746#3.4
+ *# o The client MUST include either an empty "renegotiation_info"
+ *# extension, or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling
+ *# cipher suite value in the ClientHello. Including both is NOT
+ *# RECOMMENDED.
+ * For maximum backwards compatibility, we choose to use the TLS_EMPTY_RENEGOTIATION_INFO_SCSV cipher suite
+ * rather than the "renegotiation_info" extension.
+ *
+ * For renegotiation handshakes:
+ *= https://tools.ietf.org/rfc/rfc5746#3.5
+ *# The SCSV MUST NOT be included.
+ */
+ if (tls12_is_possible && !s2n_handshake_is_renegotiation(conn)) {
uint8_t renegotiation_info_scsv[S2N_TLS_CIPHER_SUITE_LEN] = { TLS_EMPTY_RENEGOTIATION_INFO_SCSV };
POSIX_GUARD(s2n_stuffer_write_bytes(out, renegotiation_info_scsv, S2N_TLS_CIPHER_SUITE_LEN));
}
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 6444c87f5d..824c1eb2dc 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_hello_request.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello_request.c
@@ -15,26 +15,67 @@
#include "api/s2n.h"
+#include "tls/s2n_alerts.h"
#include "tls/s2n_connection.h"
#include "utils/s2n_safety.h"
-int s2n_client_hello_request_recv(struct s2n_connection *conn)
+S2N_RESULT s2n_client_hello_request_validate(struct s2n_connection *conn)
{
- POSIX_ENSURE_REF(conn);
- POSIX_ENSURE(conn->actual_protocol_version < S2N_TLS13, S2N_ERR_BAD_MESSAGE);
+ RESULT_ENSURE_REF(conn);
+ if (IS_NEGOTIATED(conn)) {
+ RESULT_ENSURE(conn->actual_protocol_version < S2N_TLS13, S2N_ERR_BAD_MESSAGE);
+ }
/*
*= https://tools.ietf.org/rfc/rfc5246#section-7.4.1.1
*# The HelloRequest message MAY be sent by the server at any time.
*/
- POSIX_ENSURE(conn->mode == S2N_CLIENT, S2N_ERR_BAD_MESSAGE);
+ RESULT_ENSURE(conn->mode == S2N_CLIENT, S2N_ERR_BAD_MESSAGE);
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_client_hello_request_recv(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->config);
+ RESULT_GUARD(s2n_client_hello_request_validate(conn));
+
+ /*
+ *= https://tools.ietf.org/rfc/rfc5746#section-4.2
+ *# This text applies if the connection's "secure_renegotiation" flag is
+ *# set to FALSE.
+ *#
+ *# It is possible that un-upgraded servers will request that the client
+ *# renegotiate. It is RECOMMENDED that clients refuse this
+ *# renegotiation request. Clients that do so MUST respond to such
+ *# requests with a "no_renegotiation" alert (RFC 5246 requires this
+ *# alert to be at the "warning" level). It is possible that the
+ *# apparently un-upgraded server is in fact an attacker who is then
+ *# allowing the client to renegotiate with a different, legitimate,
+ *# upgraded server.
+ */
+ if (!conn->secure_renegotiation) {
+ RESULT_GUARD(s2n_queue_reader_no_renegotiation_alert(conn));
+ return S2N_RESULT_OK;
+ }
+
+ 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));
+ }
/*
*= https://tools.ietf.org/rfc/rfc5246#section-7.4.1.1
- *# This message will be ignored by the client if the client is
- *# currently negotiating a session. This message MAY be ignored by
+ *# This message MAY be ignored by
*# the client if it does not wish to renegotiate a session, or the
*# client may, if it wishes, respond with a no_renegotiation alert.
*/
- return S2N_SUCCESS;
+ if (response != S2N_RENEGOTIATE_ACCEPT) {
+ RESULT_GUARD(s2n_queue_reader_no_renegotiation_alert(conn));
+ return S2N_RESULT_OK;
+ }
+
+ 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 ce7c666097..dba71e2bf3 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_config.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_config.c
@@ -829,32 +829,41 @@ int s2n_config_add_ticket_crypto_key(struct s2n_config *config,
POSIX_GUARD(s2n_config_wipe_expired_ticket_crypto_keys(config, -1));
- S2N_ERROR_IF(key_len == 0, S2N_ERR_INVALID_TICKET_KEY_LENGTH);
+ POSIX_ENSURE(key_len != 0, S2N_ERR_INVALID_TICKET_KEY_LENGTH);
uint32_t ticket_keys_len = 0;
POSIX_GUARD_RESULT(s2n_set_len(config->ticket_keys, &ticket_keys_len));
- S2N_ERROR_IF(ticket_keys_len >= S2N_MAX_TICKET_KEYS, S2N_ERR_TICKET_KEY_LIMIT);
+ POSIX_ENSURE(ticket_keys_len < S2N_MAX_TICKET_KEYS, S2N_ERR_TICKET_KEY_LIMIT);
- S2N_ERROR_IF(name_len == 0 || name_len > S2N_TICKET_KEY_NAME_LEN || s2n_find_ticket_key(config, name), S2N_ERR_INVALID_TICKET_KEY_NAME_OR_NAME_LENGTH);
+ POSIX_ENSURE(name_len != 0, S2N_ERR_INVALID_TICKET_KEY_NAME_OR_NAME_LENGTH);
+ POSIX_ENSURE(name_len <= S2N_TICKET_KEY_NAME_LEN, S2N_ERR_INVALID_TICKET_KEY_NAME_OR_NAME_LENGTH);
- uint8_t output_pad[S2N_AES256_KEY_LEN + S2N_TICKET_AAD_IMPLICIT_LEN];
- struct s2n_blob out_key = { .data = output_pad, .size = sizeof(output_pad) };
+ /* Copy the name into a zero-padded array. */
+ /* This ensures that all ticket names are equal in length, as the serialized name is fixed length */
+ uint8_t name_data[S2N_TICKET_KEY_NAME_LEN] = { 0 };
+ POSIX_CHECKED_MEMCPY(name_data, name, name_len);
+
+ /* ensure the ticket name is not already present */
+ POSIX_ENSURE(s2n_find_ticket_key(config, name_data) == NULL, S2N_ERR_INVALID_TICKET_KEY_NAME_OR_NAME_LENGTH);
+
+ uint8_t output_pad[S2N_AES256_KEY_LEN + S2N_TICKET_AAD_IMPLICIT_LEN] = { 0 };
+ struct s2n_blob out_key = { .data = output_pad, .size = s2n_array_len(output_pad) };
struct s2n_blob in_key = { .data = key, .size = key_len };
struct s2n_blob salt = { .size = 0 };
struct s2n_blob info = { .size = 0 };
- struct s2n_ticket_key *session_ticket_key;
- DEFER_CLEANUP(struct s2n_blob allocator = {0}, s2n_free);
+ struct s2n_ticket_key *session_ticket_key = { 0 };
+ DEFER_CLEANUP(struct s2n_blob allocator = { 0 }, s2n_free);
POSIX_GUARD(s2n_alloc(&allocator, sizeof(struct s2n_ticket_key)));
session_ticket_key = (struct s2n_ticket_key *) (void *) allocator.data;
- DEFER_CLEANUP(struct s2n_hmac_state hmac = {0}, s2n_hmac_free);
+ DEFER_CLEANUP(struct s2n_hmac_state hmac = { 0 }, s2n_hmac_free);
POSIX_GUARD(s2n_hmac_new(&hmac));
POSIX_GUARD(s2n_hkdf(&hmac, S2N_HMAC_SHA256, &salt, &in_key, &info, &out_key));
- DEFER_CLEANUP(struct s2n_hash_state hash = {0}, s2n_hash_free);
- uint8_t hash_output[SHA_DIGEST_LENGTH];
+ DEFER_CLEANUP(struct s2n_hash_state hash = { 0 }, s2n_hash_free);
+ uint8_t hash_output[SHA_DIGEST_LENGTH] = { 0 };
POSIX_GUARD(s2n_hash_new(&hash));
POSIX_GUARD(s2n_hash_init(&hash, S2N_HASH_SHA1));
@@ -870,13 +879,13 @@ int s2n_config_add_ticket_crypto_key(struct s2n_config *config,
/* Insert hash key into a sorted array at known index */
POSIX_GUARD_RESULT(s2n_set_add(config->ticket_key_hashes, hash_output));
- POSIX_CHECKED_MEMCPY(session_ticket_key->key_name, name, S2N_TICKET_KEY_NAME_LEN);
+ POSIX_CHECKED_MEMCPY(session_ticket_key->key_name, name_data, s2n_array_len(name_data));
POSIX_CHECKED_MEMCPY(session_ticket_key->aes_key, out_key.data, S2N_AES256_KEY_LEN);
out_key.data = output_pad + S2N_AES256_KEY_LEN;
POSIX_CHECKED_MEMCPY(session_ticket_key->implicit_aad, out_key.data, S2N_TICKET_AAD_IMPLICIT_LEN);
if (intro_time_in_seconds_from_epoch == 0) {
- uint64_t now;
+ uint64_t now = 0;
POSIX_GUARD(config->wall_clock(config->sys_clock_ctx, &now));
session_ticket_key->intro_timestamp = now;
} else {
@@ -993,3 +1002,27 @@ int s2n_config_set_send_buffer_size(struct s2n_config *config, uint32_t size) {
config->send_buffer_size_override = size;
return S2N_SUCCESS;
}
+
+int s2n_config_set_verify_after_sign(struct s2n_config *config, s2n_verify_after_sign mode)
+{
+ POSIX_ENSURE_REF(config);
+ switch (mode) {
+ case S2N_VERIFY_AFTER_SIGN_DISABLED:
+ config->verify_after_sign = false;
+ break;
+ case S2N_VERIFY_AFTER_SIGN_ENABLED:
+ config->verify_after_sign = true;
+ break;
+ default:
+ POSIX_BAIL(S2N_ERR_INVALID_ARGUMENT);
+ }
+ return S2N_SUCCESS;
+}
+
+int s2n_config_set_renegotiate_request_cb(struct s2n_config *config, s2n_renegotiate_request_cb cb, void *ctx)
+{
+ POSIX_ENSURE_REF(config);
+ config->renegotiate_request_cb = cb;
+ config->renegotiate_request_ctx = ctx;
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.h b/contrib/restricted/aws/s2n/tls/s2n_config.h
index c128dd82bb..e9659fa2f8 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_config.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_config.h
@@ -19,6 +19,7 @@
#include "crypto/s2n_certificate.h"
#include "crypto/s2n_dhe.h"
#include "tls/s2n_psk.h"
+#include "tls/s2n_renegotiate.h"
#include "tls/s2n_resume.h"
#include "tls/s2n_x509_validator.h"
#include "utils/s2n_blob.h"
@@ -66,6 +67,14 @@ struct s2n_config {
* Note: This defaults to false to ensure backwards compatibility.
*/
unsigned client_hello_cb_enable_poll:1;
+ /*
+ * Whether to verify signatures locally before sending them over the wire.
+ * See s2n_config_set_verify_after_sign.
+ */
+ unsigned verify_after_sign:1;
+
+ /* Indicates support for the npn extension */
+ unsigned npn_supported:1;
struct s2n_dh_params *dhparams;
/* Needed until we can deprecate s2n_config_add_cert_chain_and_key. This is
@@ -152,6 +161,9 @@ struct s2n_config {
/* Used to override the stuffer size for a connection's `out` stuffer. */
uint32_t send_buffer_size_override;
+
+ void *renegotiate_request_ctx;
+ s2n_renegotiate_request_cb renegotiate_request_cb;
};
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 6901a8b95d..f0bb3c4888 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection.c
@@ -731,6 +731,7 @@ int s2n_connection_get_protocol_preferences(struct s2n_connection *conn, struct
if (conn->application_protocols_overridden.size > 0) {
*protocol_preferences = &conn->application_protocols_overridden;
} else {
+ POSIX_ENSURE_REF(conn->config);
*protocol_preferences = &conn->config->application_protocols;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_handshake.c
index 0923c3d9a7..e8a8b12c58 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_handshake.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake.c
@@ -346,3 +346,33 @@ S2N_RESULT s2n_handshake_validate(const struct s2n_handshake *s2n_handshake)
RESULT_DEBUG_ENSURE(s2n_handshake->message_number >= 0 && s2n_handshake->message_number < 32, S2N_ERR_SAFETY);
return S2N_RESULT_OK;
}
+
+S2N_RESULT s2n_handshake_set_finished_len(struct s2n_connection *conn, uint8_t len)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_GT(len, 0);
+ RESULT_ENSURE_LTE(len, sizeof(conn->handshake.server_finished));
+ RESULT_ENSURE_LTE(len, sizeof(conn->handshake.client_finished));
+
+ /*
+ * We maintain a version of the "finished" / "verify_data" field
+ * for both the client and server, so this method will be called
+ * once for the client version and once for the server version.
+ *
+ * The lengths of both versions must match, or something has
+ * gone wrong in our implementation.
+ */
+ uint8_t *finished_length = &conn->handshake.finished_len;
+ if (*finished_length == 0) {
+ *finished_length = len;
+ }
+ RESULT_ENSURE_EQ(*finished_length, len);
+
+ return S2N_RESULT_OK;
+}
+
+bool s2n_handshake_is_renegotiation(struct s2n_connection *conn)
+{
+ return s2n_in_unit_test() && conn &&
+ (conn->mode == S2N_CLIENT) && conn->handshake.renegotiation;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake.h b/contrib/restricted/aws/s2n/tls/s2n_handshake.h
index 5b73d1f626..e40a4d8d44 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_handshake.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake.h
@@ -142,8 +142,18 @@ struct s2n_handshake {
*/
uint8_t required_hash_algs[S2N_HASH_SENTINEL];
+ /*
+ * Data required by the Finished messages.
+ * In TLS1.2 and earlier, the data is the verify_data.
+ * In TLS1.3, the data is the finished_key used to calculate the verify_data.
+ *
+ * The data will be different for the client and server.
+ * The length of the data will be the same for the client and server.
+ * The length of the data depends on protocol version and cipher suite.
+ */
uint8_t server_finished[S2N_TLS_SECRET_LEN];
uint8_t client_finished[S2N_TLS_SECRET_LEN];
+ uint8_t finished_len;
/* Which message-order affecting features are enabled */
uint32_t handshake_type;
@@ -170,6 +180,9 @@ struct s2n_handshake {
/* Set to 1 if the RSA verification failed */
unsigned rsa_failed:1;
+
+ /* Indicates that this is a renegotiation handshake */
+ unsigned renegotiation:1;
};
/* Only used in our test cases. */
@@ -186,6 +199,8 @@ int s2n_create_wildcard_hostname(struct s2n_stuffer *hostname, struct s2n_stuffe
struct s2n_cert_chain_and_key *s2n_get_compatible_cert_chain_and_key(struct s2n_connection *conn, const s2n_pkey_type cert_type);
S2N_RESULT s2n_negotiate_until_message(struct s2n_connection *conn, s2n_blocked_status *blocked, message_type_t end_message);
S2N_RESULT s2n_handshake_validate(const struct s2n_handshake *s2n_handshake);
+S2N_RESULT s2n_handshake_set_finished_len(struct s2n_connection *conn, uint8_t len);
+bool s2n_handshake_is_renegotiation(struct s2n_connection *conn);
/* s2n_handshake_io */
int s2n_conn_set_handshake_type(struct s2n_connection *conn);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
index 641bebe6ca..4e1737e2dc 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
@@ -1289,7 +1289,7 @@ static int s2n_handshake_read_io(struct s2n_connection *conn)
*# SHOULD be ignored by the client if it arrives in the middle of a handshake.
*/
if (message_type == TLS_HELLO_REQUEST) {
- POSIX_GUARD(s2n_client_hello_request_recv(conn));
+ POSIX_GUARD_RESULT(s2n_client_hello_request_validate(conn));
POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
continue;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
index 7801920563..9ae3039f4b 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
@@ -49,7 +49,7 @@ int s2n_post_handshake_recv(struct s2n_connection *conn)
POSIX_GUARD_RESULT(s2n_tls13_server_nst_recv(conn, &post_handshake_stuffer));
break;
case TLS_HELLO_REQUEST:
- POSIX_GUARD(s2n_client_hello_request_recv(conn));
+ POSIX_GUARD_RESULT(s2n_client_hello_request_recv(conn));
break;
case TLS_CLIENT_HELLO:
case TLS_SERVER_HELLO:
diff --git a/contrib/restricted/aws/s2n/tls/s2n_prf.c b/contrib/restricted/aws/s2n/tls/s2n_prf.c
index 043778d78a..2ff9f0c6de 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_prf.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_prf.c
@@ -621,7 +621,7 @@ static int s2n_sslv3_finished(struct s2n_connection *conn, uint8_t prefix[4], st
uint8_t *md5_digest = out;
uint8_t *sha_digest = out + MD5_DIGEST_LENGTH;
- POSIX_ENSURE_LTE(MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, sizeof(conn->handshake.client_finished));
+ POSIX_GUARD_RESULT(s2n_handshake_set_finished_len(conn, MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH));
struct s2n_hash_state *md5 = hash_workspace;
POSIX_GUARD(s2n_hash_copy(md5, &conn->handshake.hashes->md5));
@@ -659,7 +659,6 @@ static int s2n_sslv3_client_finished(struct s2n_connection *conn)
uint8_t prefix[4] = { 0x43, 0x4c, 0x4e, 0x54 };
- POSIX_ENSURE_LTE(MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, sizeof(conn->handshake.client_finished));
return s2n_sslv3_finished(conn, prefix, &conn->handshake.hashes->hash_workspace, conn->handshake.client_finished);
}
@@ -670,7 +669,6 @@ static int s2n_sslv3_server_finished(struct s2n_connection *conn)
uint8_t prefix[4] = { 0x53, 0x52, 0x56, 0x52 };
- POSIX_ENSURE_LTE(MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, sizeof(conn->handshake.server_finished));
return s2n_sslv3_finished(conn, prefix, &conn->handshake.hashes->hash_workspace, conn->handshake.server_finished);
}
@@ -693,6 +691,7 @@ int s2n_prf_client_finished(struct s2n_connection *conn)
client_finished.data = conn->handshake.client_finished;
client_finished.size = S2N_TLS_FINISHED_LEN;
+ POSIX_GUARD_RESULT(s2n_handshake_set_finished_len(conn, client_finished.size));
label.data = client_finished_label;
label.size = sizeof(client_finished_label) - 1;
@@ -750,6 +749,7 @@ int s2n_prf_server_finished(struct s2n_connection *conn)
server_finished.data = conn->handshake.server_finished;
server_finished.size = S2N_TLS_FINISHED_LEN;
+ POSIX_GUARD_RESULT(s2n_handshake_set_finished_len(conn, server_finished.size));
label.data = server_finished_label;
label.size = sizeof(server_finished_label) - 1;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c
index 88212161c8..3ec66e84b6 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c
@@ -137,6 +137,31 @@ S2N_RESULT s2n_protocol_preferences_set(struct s2n_blob *application_protocols,
return S2N_RESULT_OK;
}
+S2N_RESULT s2n_select_server_preference_protocol(struct s2n_connection *conn, struct s2n_stuffer *server_list,
+ struct s2n_blob *client_list)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(server_list);
+ RESULT_ENSURE_REF(client_list);
+
+ while(s2n_stuffer_data_available(server_list) > 0) {
+ struct s2n_blob protocol = { 0 };
+ RESULT_ENSURE_OK(s2n_protocol_preferences_read(server_list, &protocol), S2N_ERR_BAD_MESSAGE);
+
+ bool match_found = false;
+ RESULT_ENSURE_OK(s2n_protocol_preferences_contain(client_list, &protocol, &match_found), S2N_ERR_BAD_MESSAGE);
+
+ if (match_found) {
+ RESULT_ENSURE_LT(protocol.size, sizeof(conn->application_protocol));
+ RESULT_CHECKED_MEMCPY(conn->application_protocol, protocol.data, protocol.size);
+ conn->application_protocol[protocol.size] = '\0';
+ return S2N_RESULT_OK;
+ }
+ }
+
+ return S2N_RESULT_OK;
+}
+
int s2n_config_set_protocol_preferences(struct s2n_config *config, const char *const *protocols, int protocol_count)
{
POSIX_GUARD_RESULT(s2n_protocol_preferences_set(&config->application_protocols, protocols, protocol_count));
diff --git a/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.h
index 421dfae6a7..327249e80b 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.h
@@ -21,3 +21,5 @@
S2N_RESULT s2n_protocol_preferences_read(struct s2n_stuffer *protocol_preferences, struct s2n_blob *protocol);
S2N_RESULT s2n_protocol_preferences_contain(struct s2n_blob *protocol_preferences, struct s2n_blob *protocol, bool *contains);
+S2N_RESULT s2n_select_server_preference_protocol(struct s2n_connection *conn, struct s2n_stuffer *server_list,
+ struct s2n_blob *client_list);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c b/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c
new file mode 100644
index 0000000000..f8bf49ddf8
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c
@@ -0,0 +1,125 @@
+/*
+ * 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 "tls/s2n_renegotiate.h"
+
+#include "error/s2n_errno.h"
+#include "stuffer/s2n_stuffer.h"
+#include "tls/s2n_connection.h"
+#include "utils/s2n_safety.h"
+
+/*
+ * Prepare a connection to be reused for a second handshake.
+ *
+ * s2n-tls was not originally designed to support renegotiation.
+ * s2n_connection is a very large structure with configuration fields set by the application
+ * mixed in with internal state fields set by the handshake.
+ * Ensuring all existing internal state fields (and any new fields added) are safe to reuse for
+ * a renegotiated handshake would be extremely prone to errors.
+ * For safety, we instead wipe the entire connection and only restore fields we know we need
+ * in order to continue sending and receiving encrypted data.
+ *
+ * Any configuration fields set by the application will need to be set by the application again.
+ */
+int s2n_renegotiate_wipe(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+
+ /* We use this method to reset both clients and servers when testing.
+ * However, outside of tests, it should only be called for client connections
+ * because we only support renegotiation for clients.
+ */
+ POSIX_ENSURE(conn->mode == S2N_CLIENT || s2n_in_unit_test(), S2N_ERR_NO_RENEGOTIATION);
+
+ /* Best effort check for pending input or output data.
+ * This method should not be called until the application has stopped sending and receiving.
+ * Saving partial read or parital write state would complicate this problem.
+ */
+ POSIX_ENSURE(s2n_stuffer_data_available(&conn->header_in) == 0, S2N_ERR_INVALID_STATE);
+ POSIX_ENSURE(s2n_stuffer_data_available(&conn->in) == 0, S2N_ERR_INVALID_STATE);
+ POSIX_ENSURE(s2n_stuffer_data_available(&conn->out) == 0, S2N_ERR_INVALID_STATE);
+
+ /* Save the crypto parameters.
+ * We need to continue encrypting / decrypting with the old secure parameters.
+ */
+ DEFER_CLEANUP(struct s2n_crypto_parameters *secure_crypto_params = conn->secure,
+ s2n_crypto_parameters_free);
+ conn->secure = NULL;
+
+ /* Save the fragment length so we continue properly fragmenting our records
+ * until a new fragment length is chosen.
+ */
+ uint16_t max_frag_len = conn->max_outgoing_fragment_length;
+
+ /* Save the protocol versions.
+ * Various checks when sending and receiving records rely on the protocol version. */
+ uint8_t actual_protocol_version = conn->actual_protocol_version;
+ uint8_t server_protocol_version = conn->server_protocol_version;
+ uint8_t client_protocol_version = conn->client_protocol_version;
+ POSIX_ENSURE(actual_protocol_version < S2N_TLS13, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
+
+ /* Save byte tracking.
+ * This isn't strictly necessary, but potentially useful. */
+ uint64_t wire_bytes_in = conn->wire_bytes_in;
+ uint64_t wire_bytes_out = conn->wire_bytes_out;
+
+ /* Save io settings */
+ bool send_managed = conn->managed_send_io;
+ s2n_send_fn *send_fn = conn->send;
+ void *send_ctx = conn->send_io_context;
+ bool recv_managed = conn->managed_recv_io;
+ s2n_recv_fn *recv_fn = conn->recv;
+ void *recv_ctx = conn->recv_io_context;
+ /* Treat IO as unmanaged, since we don't want to clean it up yet */
+ conn->managed_send_io = false;
+ conn->managed_recv_io = false;
+
+ /* Save the secure_renegotiation flag.
+ * This flag should always be true, since we don't support insecure renegotiation,
+ * but copying its value seems safer than just setting it to 'true'.
+ */
+ bool secure_renegotiation = conn->secure_renegotiation;
+ POSIX_ENSURE(secure_renegotiation, S2N_ERR_NO_RENEGOTIATION);
+
+ POSIX_GUARD(s2n_connection_wipe(conn));
+
+ /* Setup the new crypto parameters.
+ * The new handshake will negotiate new secure crypto parameters,
+ * so the current secure crypto parameters become the initial crypto parameters.
+ */
+ POSIX_GUARD_RESULT(s2n_crypto_parameters_free(&conn->initial));
+ conn->initial = secure_crypto_params;
+ ZERO_TO_DISABLE_DEFER_CLEANUP(secure_crypto_params);
+ conn->client = conn->initial;
+ conn->server = conn->initial;
+
+ /* Restore saved values */
+ POSIX_GUARD_RESULT(s2n_connection_set_max_fragment_length(conn, max_frag_len));
+ conn->actual_protocol_version = actual_protocol_version;
+ conn->server_protocol_version = server_protocol_version;
+ conn->client_protocol_version = client_protocol_version;
+ conn->wire_bytes_in = wire_bytes_in;
+ conn->wire_bytes_out = wire_bytes_out;
+ conn->managed_send_io = send_managed;
+ conn->send = send_fn;
+ conn->send_io_context = send_ctx;
+ conn->managed_recv_io = recv_managed;
+ conn->recv = recv_fn;
+ conn->recv_io_context = recv_ctx;
+ conn->secure_renegotiation = secure_renegotiation;
+
+ conn->handshake.renegotiation = true;
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_renegotiate.h b/contrib/restricted/aws/s2n/tls/s2n_renegotiate.h
new file mode 100644
index 0000000000..9e11e6e892
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_renegotiate.h
@@ -0,0 +1,25 @@
+/*
+ * 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
+
+struct s2n_connection;
+struct s2n_config;
+
+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);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_resume.c b/contrib/restricted/aws/s2n/tls/s2n_resume.c
index 6f0bd07858..3d79e28dce 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_resume.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_resume.c
@@ -213,7 +213,7 @@ static int s2n_client_serialize_resumption_state(struct s2n_connection *conn, st
}
static S2N_RESULT s2n_tls12_client_deserialize_session_state(struct s2n_connection *conn, struct s2n_stuffer *from)
-{
+{
RESULT_ENSURE_REF(conn);
RESULT_ENSURE_REF(from);
@@ -695,7 +695,7 @@ struct s2n_ticket_key *s2n_get_ticket_encrypt_decrypt_key(struct s2n_config *con
/* This function is used in s2n_decrypt_session_ticket in order for s2n to
* find the matching key that was used for encryption.
*/
-struct s2n_ticket_key *s2n_find_ticket_key(struct s2n_config *config, const uint8_t *name)
+struct s2n_ticket_key *s2n_find_ticket_key(struct s2n_config *config, const uint8_t name[S2N_TICKET_KEY_NAME_LEN])
{
uint64_t now;
struct s2n_ticket_key *ticket_key = NULL;
@@ -785,7 +785,7 @@ int s2n_decrypt_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *
DEFER_CLEANUP(struct s2n_session_key aes_ticket_key = {0}, s2n_session_key_free);
struct s2n_blob aes_key_blob = {0};
- uint8_t key_name[S2N_TICKET_KEY_NAME_LEN];
+ uint8_t key_name[S2N_TICKET_KEY_NAME_LEN] = { 0 };
uint8_t iv_data[S2N_TLS_GCM_IV_LEN] = { 0 };
struct s2n_blob iv = { 0 };
@@ -796,7 +796,7 @@ int s2n_decrypt_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *
POSIX_GUARD(s2n_blob_init(&aad_blob, aad_data, sizeof(aad_data)));
struct s2n_stuffer aad = {0};
- POSIX_GUARD(s2n_stuffer_read_bytes(from, key_name, S2N_TICKET_KEY_NAME_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(from, key_name, s2n_array_len(key_name)));
key = s2n_find_ticket_key(conn->config, key_name);
@@ -819,7 +819,7 @@ int s2n_decrypt_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *
uint8_t *en_blob_data = s2n_stuffer_raw_read(from, en_blob_size);
POSIX_ENSURE_REF(en_blob_data);
POSIX_GUARD(s2n_blob_init(&en_blob, en_blob_data, en_blob_size));
- POSIX_GUARD(s2n_aes256_gcm.io.aead.decrypt(&aes_ticket_key, &iv, &aad_blob, &en_blob, &en_blob));
+ POSIX_GUARD(s2n_aes256_gcm.io.aead.decrypt(&aes_ticket_key, &iv, &aad_blob, &en_blob, &en_blob));
struct s2n_blob state_blob = { 0 };
uint32_t state_blob_size = en_blob_size - S2N_TLS_GCM_TAG_LEN;
@@ -857,7 +857,7 @@ int s2n_decrypt_session_cache(struct s2n_connection *conn, struct s2n_stuffer *f
struct s2n_session_key aes_ticket_key = {0};
struct s2n_blob aes_key_blob = {0};
- uint8_t key_name[S2N_TICKET_KEY_NAME_LEN] = {0};
+ uint8_t key_name[S2N_TICKET_KEY_NAME_LEN] = { 0 };
uint8_t iv_data[S2N_TLS_GCM_IV_LEN] = { 0 };
struct s2n_blob iv = {0};
@@ -877,12 +877,12 @@ int s2n_decrypt_session_cache(struct s2n_connection *conn, struct s2n_stuffer *f
struct s2n_blob en_blob = {0};
POSIX_GUARD(s2n_blob_init(&en_blob, en_data, sizeof(en_data)));
- POSIX_GUARD(s2n_stuffer_read_bytes(from, key_name, S2N_TICKET_KEY_NAME_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(from, key_name, s2n_array_len(key_name)));
key = s2n_find_ticket_key(conn->config, key_name);
/* Key has expired; do full handshake with New Session Ticket (NST) */
- S2N_ERROR_IF(!key, S2N_ERR_KEY_USED_IN_SESSION_TICKET_NOT_FOUND);
+ POSIX_ENSURE(key != NULL, S2N_ERR_KEY_USED_IN_SESSION_TICKET_NOT_FOUND);
POSIX_GUARD(s2n_stuffer_read(from, &iv));
diff --git a/contrib/restricted/aws/s2n/tls/s2n_resume.h b/contrib/restricted/aws/s2n/tls/s2n_resume.h
index 326307acf9..55e70705eb 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_resume.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_resume.h
@@ -73,7 +73,7 @@ struct s2n_session_ticket {
uint32_t session_lifetime;
};
-extern struct s2n_ticket_key *s2n_find_ticket_key(struct s2n_config *config, const uint8_t *name);
+extern struct s2n_ticket_key *s2n_find_ticket_key(struct s2n_config *config, const uint8_t name[S2N_TICKET_KEY_NAME_LEN]);
extern int s2n_encrypt_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *to);
extern int s2n_decrypt_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *from);
extern int s2n_encrypt_session_cache(struct s2n_connection *conn, struct s2n_stuffer *to);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_send.c b/contrib/restricted/aws/s2n/tls/s2n_send.c
index 6f31935ceb..e0f51683c3 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_send.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_send.c
@@ -19,6 +19,7 @@
#include "error/s2n_errno.h"
+#include "tls/s2n_alerts.h"
#include "tls/s2n_cipher_suites.h"
#include "tls/s2n_connection.h"
#include "tls/s2n_handshake.h"
@@ -103,7 +104,7 @@ int s2n_flush(struct s2n_connection *conn, s2n_blocked_status *blocked)
alert.size = 2;
POSIX_GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
POSIX_GUARD(s2n_stuffer_rewrite(&conn->reader_alert_out));
- conn->closing = 1;
+ POSIX_GUARD_RESULT(s2n_alerts_close_if_fatal(conn, &alert));
/* Actually write it ... */
goto WRITE;
@@ -116,7 +117,7 @@ int s2n_flush(struct s2n_connection *conn, s2n_blocked_status *blocked)
alert.size = 2;
POSIX_GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
POSIX_GUARD(s2n_stuffer_rewrite(&conn->writer_alert_out));
- conn->closing = 1;
+ POSIX_GUARD_RESULT(s2n_alerts_close_if_fatal(conn, &alert));
/* Actually write it ... */
goto WRITE;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_finished.c b/contrib/restricted/aws/s2n/tls/s2n_server_finished.c
index 05c553799f..02d73ac4aa 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_finished.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_finished.c
@@ -26,58 +26,67 @@
#include "utils/s2n_safety.h"
-int s2n_server_finished_recv(struct s2n_connection *conn)
+S2N_RESULT s2n_finished_recv(struct s2n_connection *conn, uint8_t *local_verify_data)
{
- uint8_t *our_version;
- int length = S2N_TLS_FINISHED_LEN;
- our_version = conn->handshake.server_finished;
+ RESULT_ENSURE_REF(conn);
+ uint8_t length = conn->handshake.finished_len;
+ /* Recalculate length to ensure that we're validating the right number of bytes */
if (conn->actual_protocol_version == S2N_SSLv3) {
- length = S2N_SSL_FINISHED_LEN;
+ RESULT_ENSURE_EQ(length, S2N_SSL_FINISHED_LEN);
+ } else {
+ RESULT_ENSURE_EQ(length, S2N_TLS_FINISHED_LEN);
}
- uint8_t *their_version = s2n_stuffer_raw_read(&conn->handshake.io, length);
- POSIX_ENSURE_REF(their_version);
-
- S2N_ERROR_IF(!s2n_constant_time_equals(our_version, their_version, length), S2N_ERR_BAD_MESSAGE);
+ uint8_t *peer_verify_data = s2n_stuffer_raw_read(&conn->handshake.io, length);
+ RESULT_ENSURE_REF(peer_verify_data);
- return 0;
+ RESULT_ENSURE(s2n_constant_time_equals(local_verify_data, peer_verify_data, length), S2N_ERR_BAD_MESSAGE);
+ return S2N_RESULT_OK;
}
-int s2n_server_finished_send(struct s2n_connection *conn)
+S2N_RESULT s2n_finished_send(struct s2n_connection *conn, uint8_t *seq_num, uint8_t *verify_data)
{
- POSIX_ENSURE_REF(conn);
- POSIX_ENSURE_REF(conn->secure);
+ RESULT_ENSURE_REF(conn);
- uint8_t *our_version;
- int length = S2N_TLS_FINISHED_LEN;
+ struct s2n_blob seq = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&seq, seq_num, S2N_TLS_SEQUENCE_NUM_LEN));
+ RESULT_GUARD_POSIX(s2n_blob_zero(&seq));
- /* Compute the finished message */
- POSIX_GUARD(s2n_prf_server_finished(conn));
+ uint8_t length = conn->handshake.finished_len;
+ RESULT_ENSURE_GT(length, 0);
- our_version = conn->handshake.server_finished;
+ RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&conn->handshake.io, verify_data, length));
+ return S2N_RESULT_OK;
+}
- if (conn->actual_protocol_version == S2N_SSLv3) {
- length = S2N_SSL_FINISHED_LEN;
- }
+int s2n_server_finished_recv(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+ uint8_t *verify_data = conn->handshake.server_finished;
+ POSIX_GUARD_RESULT(s2n_finished_recv(conn, verify_data));
+ return S2N_SUCCESS;
+}
- POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, our_version, length));
+int s2n_server_finished_send(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
- /* Zero the sequence number */
- struct s2n_blob seq = {.data = conn->secure->server_sequence_number,.size = S2N_TLS_SEQUENCE_NUM_LEN };
- POSIX_GUARD(s2n_blob_zero(&seq));
+ uint8_t *verify_data = conn->handshake.server_finished;
+ uint8_t *seq_num = conn->secure->server_sequence_number;
+ POSIX_GUARD(s2n_prf_server_finished(conn));
+ POSIX_GUARD_RESULT(s2n_finished_send(conn, seq_num, verify_data));
- /* Update the secure state to active, and point the client at the active state */
+ POSIX_ENSURE_REF(conn->secure);
conn->server = conn->secure;
if (s2n_connection_is_session_resumed(conn)) {
POSIX_GUARD(s2n_prf_key_expansion(conn));
}
- return 0;
+ return S2N_SUCCESS;
}
-
int s2n_tls13_server_finished_recv(struct s2n_connection *conn) {
POSIX_ENSURE_EQ(conn->actual_protocol_version, S2N_TLS13);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_hello.c b/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
index 4962dfb3b2..b500a718a1 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
@@ -179,6 +179,7 @@ static int s2n_server_hello_parse(struct s2n_connection *conn)
}
if (conn->server_protocol_version >= S2N_TLS13) {
+ POSIX_ENSURE(!conn->handshake.renegotiation, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
/**
*= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.3
diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c
index 3158c0df92..ce1eab6986 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c
@@ -214,7 +214,7 @@ int s2n_choose_sig_scheme_from_peer_preference_list(struct s2n_connection *conn,
}
/* SignatureScheme preference list was first added in TLS 1.2. It will be empty in older TLS versions. */
- if (peer_wire_prefs != NULL && peer_wire_prefs->len > 0) {
+ if (conn->actual_protocol_version >= S2N_TLS12 && peer_wire_prefs != NULL && peer_wire_prefs->len > 0) {
/* Use a best effort approach to selecting a signature scheme matching client's preferences */
POSIX_GUARD(s2n_choose_sig_scheme(conn, peer_wire_prefs, &chosen_scheme));
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls.h b/contrib/restricted/aws/s2n/tls/s2n_tls.h
index 7f17c8bc7c..ca398b92b2 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls.h
@@ -24,7 +24,8 @@ extern uint8_t s2n_unknown_protocol_version;
extern uint8_t s2n_highest_protocol_version;
extern int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * more);
-int s2n_client_hello_request_recv(struct s2n_connection *conn);
+S2N_RESULT s2n_client_hello_request_validate(struct s2n_connection *conn);
+S2N_RESULT s2n_client_hello_request_recv(struct s2n_connection *conn);
extern int s2n_client_hello_send(struct s2n_connection *conn);
extern int s2n_client_hello_recv(struct s2n_connection *conn);
extern int s2n_establish_session(struct s2n_connection *conn);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
index 103590c122..95f398d566 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
@@ -193,9 +193,11 @@ static S2N_RESULT s2n_derive_secret_without_context(struct s2n_connection *conn,
*# finished_key =
*# HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
**/
-S2N_RESULT s2n_tls13_compute_finished_key(s2n_hmac_algorithm hmac_alg,
+static S2N_RESULT s2n_tls13_compute_finished_key(struct s2n_connection *conn,
const struct s2n_blob *base_key, struct s2n_blob *output)
{
+ RESULT_GUARD(s2n_handshake_set_finished_len(conn, output->size));
+
/*
* TODO: We should be able to reuse the prf_work_space rather
* than allocating a new HMAC every time.
@@ -203,7 +205,7 @@ S2N_RESULT s2n_tls13_compute_finished_key(s2n_hmac_algorithm hmac_alg,
DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
RESULT_GUARD_POSIX(s2n_hmac_new(&hmac_state));
- RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac_state, hmac_alg,
+ RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac_state, CONN_HMAC_ALG(conn),
base_key, &s2n_tls13_label_finished, &(struct s2n_blob){0}, output));
return S2N_RESULT_OK;
}
@@ -378,7 +380,7 @@ static S2N_RESULT s2n_derive_client_handshake_traffic_secret(struct s2n_connecti
*# The key used to compute the Finished message is computed from the
*# Base Key defined in Section 4.4 using HKDF (see Section 7.1).
*/
- RESULT_GUARD(s2n_tls13_compute_finished_key(CONN_HMAC_ALG(conn),
+ RESULT_GUARD(s2n_tls13_compute_finished_key(conn,
output, &CONN_FINISHED(conn, client)));
return S2N_RESULT_OK;
@@ -407,7 +409,7 @@ static S2N_RESULT s2n_derive_server_handshake_traffic_secret(struct s2n_connecti
*# The key used to compute the Finished message is computed from the
*# Base Key defined in Section 4.4 using HKDF (see Section 7.1).
*/
- RESULT_GUARD(s2n_tls13_compute_finished_key(CONN_HMAC_ALG(conn),
+ RESULT_GUARD(s2n_tls13_compute_finished_key(conn,
output, &CONN_FINISHED(conn, server)));
return S2N_RESULT_OK;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h b/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
index 26b2458cd3..435ab7ee26 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
@@ -96,6 +96,12 @@
#define TLS_EXTENSION_CERT_AUTHORITIES 47
#define TLS_EXTENSION_RENEGOTIATION_INFO 65281
+/* The NPN extension was never standardized, therefore there is no official
+ * iana value. However, Openssl does have a chosen value for this extension
+ * and that is what is used here.
+*/
+#define TLS_EXTENSION_NPN 13172
+
/* TLS 1.3 extensions from https://tools.ietf.org/html/rfc8446#section-4.2 */
#define TLS_EXTENSION_EARLY_DATA 42
#define TLS_EXTENSION_SUPPORTED_VERSIONS 43
diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
index 39f24eacd3..ca6dd8aede 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
@@ -286,40 +286,41 @@ static uint8_t s2n_verify_host_information(struct s2n_x509_validator *validator,
return verified;
}
-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) {
+static S2N_RESULT s2n_x509_validator_read_asn1_cert(struct s2n_stuffer *cert_chain_in_stuffer, struct s2n_blob *asn1_cert) {
+ uint32_t certificate_size = 0;
+
+ 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);
+
+ asn1_cert->size = certificate_size;
+ asn1_cert->data = s2n_stuffer_raw_read(cert_chain_in_stuffer, certificate_size);
+ RESULT_ENSURE_REF(asn1_cert->data);
+
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_x509_validator_read_cert_chain(struct s2n_x509_validator *validator, struct s2n_connection *conn,
+ uint8_t *cert_chain_in, uint32_t cert_chain_len) {
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);
+ DEFER_CLEANUP(struct s2n_stuffer cert_chain_in_stuffer = { 0 }, s2n_stuffer_free);
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};
-
X509 *server_cert = NULL;
- DEFER_CLEANUP(struct s2n_pkey public_key = {0}, s2n_pkey_free);
- s2n_pkey_zero_init(&public_key);
-
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;
-
- 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 asn1_cert = { 0 };
+ RESULT_GUARD(s2n_x509_validator_read_asn1_cert(&cert_chain_in_stuffer, &asn1_cert));
- struct s2n_blob asn1cert = {0};
- asn1cert.size = certificate_size;
- asn1cert.data = s2n_stuffer_raw_read(&cert_chain_in_stuffer, certificate_size);
- RESULT_ENSURE_REF(asn1cert.data);
-
- const uint8_t *data = asn1cert.data;
+ const uint8_t *data = asn1_cert.data;
/* the cert is der encoded, just convert it. */
- server_cert = d2i_X509(NULL, &data, asn1cert.size);
+ server_cert = d2i_X509(NULL, &data, asn1_cert.size);
RESULT_ENSURE_REF(server_cert);
/* add the cert to the chain. */
@@ -334,21 +335,10 @@ S2N_RESULT s2n_x509_validator_validate_cert_chain(struct s2n_x509_validator *val
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) {
- 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 };
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) {
- first_certificate_extensions = parsed_extensions_list;
- }
}
}
@@ -357,41 +347,114 @@ S2N_RESULT s2n_x509_validator_validate_cert_chain(struct s2n_x509_validator *val
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);
- RESULT_ENSURE_REF(leaf);
- if (conn->verify_host_fn) {
- RESULT_ENSURE(s2n_verify_host_information(validator, conn, leaf), S2N_ERR_CERT_UNTRUSTED);
- }
+ return S2N_RESULT_OK;
+}
- 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);
+static S2N_RESULT s2n_x509_validator_process_cert_chain(struct s2n_x509_validator *validator, struct s2n_connection *conn,
+ uint8_t *cert_chain_in, uint32_t cert_chain_len) {
+ RESULT_ENSURE(validator->state == INIT, S2N_ERR_INVALID_CERT_STATE);
- X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(validator->store_ctx);
- X509_VERIFY_PARAM_set_depth(param, validator->max_chain_depth);
+ RESULT_GUARD(s2n_x509_validator_read_cert_chain(validator, conn, cert_chain_in, cert_chain_len));
- uint64_t current_sys_time = 0;
- conn->config->wall_clock(conn->config->sys_clock_ctx, &current_sys_time);
+ if (validator->skip_cert_validation) {
+ return S2N_RESULT_OK;
+ }
- /* this wants seconds not nanoseconds */
- time_t current_time = (time_t)(current_sys_time / 1000000000);
- X509_STORE_CTX_set_time(validator->store_ctx, 0, current_time);
+ X509 *leaf = sk_X509_value(validator->cert_chain_from_wire, 0);
+ RESULT_ENSURE_REF(leaf);
- 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);
- }
+ if (conn->verify_host_fn) {
+ RESULT_ENSURE(s2n_verify_host_information(validator, conn, leaf), 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);
+
+ validator->state = READY_TO_VERIFY;
+
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_x509_validator_verify_cert_chain(struct s2n_x509_validator *validator, struct s2n_connection *conn) {
+ RESULT_ENSURE(validator->state == READY_TO_VERIFY, S2N_ERR_INVALID_CERT_STATE);
+
+ X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(validator->store_ctx);
+ X509_VERIFY_PARAM_set_depth(param, validator->max_chain_depth);
+
+ uint64_t current_sys_time = 0;
+ conn->config->wall_clock(conn->config->sys_clock_ctx, &current_sys_time);
+
+ /* this wants seconds not nanoseconds */
+ time_t current_time = (time_t)(current_sys_time / 1000000000);
+ X509_STORE_CTX_set_time(validator->store_ctx, 0, current_time);
+
+ 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);
}
+ }
+
+ validator->state = VALIDATED;
+
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_x509_validator_read_leaf_info(struct s2n_connection *conn, uint8_t *cert_chain_in, uint32_t cert_chain_len,
+ struct s2n_pkey *public_key, s2n_pkey_type *pkey_type, s2n_parsed_extensions_list *first_certificate_extensions) {
+ 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);
+
+ 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));
+
+ struct s2n_blob asn1_cert = { 0 };
+ RESULT_GUARD(s2n_x509_validator_read_asn1_cert(&cert_chain_in_stuffer, &asn1_cert));
+
+ RESULT_ENSURE(s2n_asn1der_to_public_key_and_type(public_key, pkey_type, &asn1_cert) == 0,
+ S2N_ERR_CERT_UNTRUSTED);
- validator->state = VALIDATED;
+ /* 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 };
+ RESULT_GUARD_POSIX(s2n_extension_list_parse(&cert_chain_in_stuffer, &parsed_extensions_list));
+
+ *first_certificate_extensions = parsed_extensions_list;
}
+ return S2N_RESULT_OK;
+}
+
+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) {
+ RESULT_ENSURE(validator->state == INIT, S2N_ERR_INVALID_CERT_STATE);
+
+ if (validator->state == INIT) {
+ RESULT_GUARD(s2n_x509_validator_process_cert_chain(validator, conn, cert_chain_in, cert_chain_len));
+ }
+
+ if (validator->state == READY_TO_VERIFY) {
+ RESULT_GUARD(s2n_x509_validator_verify_cert_chain(validator, conn));
+ }
+
+ DEFER_CLEANUP(struct s2n_pkey public_key = { 0 }, s2n_pkey_free);
+ s2n_pkey_zero_init(&public_key);
+ s2n_parsed_extensions_list first_certificate_extensions = { 0 };
+ RESULT_GUARD(s2n_x509_validator_read_leaf_info(conn, cert_chain_in, cert_chain_len, &public_key, pkey_type,
+ &first_certificate_extensions));
+
if (conn->actual_protocol_version >= S2N_TLS13) {
+ /* Only process certificate extensions received in the first certificate. Extensions received in all other
+ * certificates are ignored.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.4.2
+ *# If an extension applies to the entire chain, it SHOULD be included in
+ *# the first CertificateEntry.
+ */
RESULT_GUARD_POSIX(s2n_extension_list_process(S2N_EXTENSION_LIST_CERTIFICATE, conn, &first_certificate_extensions));
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
index 55b0956fa1..c1f379f8e9 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
@@ -32,6 +32,7 @@
typedef enum {
UNINIT,
INIT,
+ READY_TO_VERIFY,
VALIDATED,
OCSP_VALIDATED,
} validator_state;
diff --git a/contrib/restricted/aws/s2n/utils/s2n_array.c b/contrib/restricted/aws/s2n/utils/s2n_array.c
index 0a7f185fc2..1df7f1e101 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_array.c
+++ b/contrib/restricted/aws/s2n/utils/s2n_array.c
@@ -121,9 +121,11 @@ S2N_RESULT s2n_array_insert(struct s2n_array *array, uint32_t idx, void **elemen
/* If we are adding at an existing index, slide everything down. */
if (idx < array->len) {
+ uint32_t size = 0;
+ RESULT_GUARD_POSIX(s2n_mul_overflow(array->len - idx, array->element_size, &size));
memmove(array->mem.data + array->element_size * (idx + 1),
array->mem.data + array->element_size * idx,
- (array->len - idx) * array->element_size);
+ size);
}
*element = array->mem.data + array->element_size * idx;
@@ -141,9 +143,11 @@ S2N_RESULT s2n_array_remove(struct s2n_array *array, uint32_t idx)
/* If the removed element is the last one, no need to move anything.
* Otherwise, shift everything down */
if (idx != array->len - 1) {
+ uint32_t size = 0;
+ RESULT_GUARD_POSIX(s2n_mul_overflow(array->len - idx - 1, array->element_size, &size));
memmove(array->mem.data + array->element_size * idx,
array->mem.data + array->element_size * (idx + 1),
- (array->len - idx - 1) * array->element_size);
+ size);
}
array->len--;
diff --git a/contrib/restricted/aws/s2n/utils/s2n_init.c b/contrib/restricted/aws/s2n/utils/s2n_init.c
index 1195b3b450..a6d8219a54 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_init.c
+++ b/contrib/restricted/aws/s2n/utils/s2n_init.c
@@ -48,6 +48,12 @@ int s2n_disable_atexit(void) {
int s2n_init(void)
{
+ /* USAGE-GUIDE says s2n_init MUST NOT be called more than once
+ * Public documentation for API states s2n_init should only be called once
+ * https://github.com/aws/s2n-tls/issues/3446 is a result of not enforcing this
+ */
+ POSIX_ENSURE(!initialized, S2N_ERR_INITIALIZED);
+
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.
@@ -89,11 +95,16 @@ 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_libcrypto_cleanup()) &&
+ bool cleaned_up =
+ s2n_result_is_ok(s2n_cipher_suites_cleanup()) &&
s2n_result_is_ok(s2n_rand_cleanup_thread()) &&
s2n_result_is_ok(s2n_rand_cleanup()) &&
+ s2n_result_is_ok(s2n_libcrypto_cleanup()) &&
s2n_result_is_ok(s2n_locking_cleanup()) &&
(s2n_mem_cleanup() == S2N_SUCCESS);
+
+ initialized = !cleaned_up;
+ return cleaned_up;
}
int s2n_cleanup(void)
@@ -105,12 +116,15 @@ int s2n_cleanup(void)
/* If this is the main thread and atexit cleanup is disabled,
* perform final cleanup now */
if (pthread_equal(pthread_self(), main_thread) && !atexit_cleanup) {
+ /* some cleanups are not idempotent (rand_cleanup, mem_cleanup) so protect */
+ POSIX_ENSURE(initialized, S2N_ERR_NOT_INITIALIZED);
POSIX_ENSURE(s2n_cleanup_atexit_impl(), S2N_ERR_ATEXIT);
}
+
return 0;
}
static void s2n_cleanup_atexit(void)
{
- s2n_cleanup_atexit_impl();
+ (void)s2n_cleanup_atexit_impl();
}