aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2023-10-23 21:53:30 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2023-10-23 22:17:19 +0300
commit185aad3f5de6274260a161e58d92312d91813770 (patch)
tree39b2a93a9a649bffaaea9e405b00ceeea0d13c11 /contrib/restricted
parenta14514f8c6ab647d334ae41253e65f69ee9b5fa6 (diff)
downloadydb-185aad3f5de6274260a161e58d92312d91813770.tar.gz
Update contrib/restricted/aws/s2n to 1.3.54
Diffstat (limited to 'contrib/restricted')
-rw-r--r--contrib/restricted/aws/s2n/CMakeLists.darwin-x86_64.txt16
-rw-r--r--contrib/restricted/aws/s2n/CMakeLists.linux-aarch64.txt18
-rw-r--r--contrib/restricted/aws/s2n/CMakeLists.linux-x86_64.txt18
-rw-r--r--contrib/restricted/aws/s2n/CMakeLists.windows-x86_64.txt16
-rw-r--r--contrib/restricted/aws/s2n/LICENSE2
-rw-r--r--contrib/restricted/aws/s2n/README.md59
-rw-r--r--contrib/restricted/aws/s2n/api/s2n.h223
-rw-r--r--contrib/restricted/aws/s2n/api/unstable/crl.h74
-rw-r--r--contrib/restricted/aws/s2n/api/unstable/ktls.h115
-rw-r--r--contrib/restricted/aws/s2n/api/unstable/npn.h50
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_aes_gcm.c72
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_cipher.h4
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_dhe.c25
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c5
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_hkdf.c214
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_hkdf.h12
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_hmac.c31
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_hmac.h2
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_ktls_crypto.h63
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c11
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h2
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.c25
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.h5
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_rsa.c5
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c72
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c7
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h2
-rw-r--r--contrib/restricted/aws/s2n/error/s2n_errno.c34
-rw-r--r--contrib/restricted/aws/s2n/error/s2n_errno.h48
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_kem.c75
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_evp.c (renamed from contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_512_evp.c)69
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_evp.h (renamed from contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_512_evp.h)6
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/s2n_pq.c66
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/s2n_pq.h9
-rw-r--r--contrib/restricted/aws/s2n/stuffer/s2n_stuffer_file.c29
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.c18
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.h1
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.c28
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.h4
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c12
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c16
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_alerts.c159
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_alerts.h7
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c41
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c11
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_cert.c54
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_hello.c73
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.c24
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.h7
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection.c124
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection.h47
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_early_data_io.c4
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c14
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake_io.c6
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kem.c177
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kem.h40
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c44
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h7
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_key_log.c5
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_key_update.c23
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_ktls.c241
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_ktls.h48
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_ktls_io.c473
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_ktls_parameters.h63
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_post_handshake.c5
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_prf.c403
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_prf.h38
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_quic_support.h1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_record_read.c15
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_record_write.c5
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_recv.c55
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_renegotiate.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_resume.c62
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_security_policies.c73
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_security_policies.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_send.c51
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_hello.c3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_shutdown.c125
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c48
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c110
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h12
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_x509_validator.c210
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_x509_validator.h5
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_asn1_time.c306
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_atomic.c60
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_atomic.h42
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_ensure.c13
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_ensure.h31
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_init.c11
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_init.h20
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_io.c40
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_io.h (renamed from contrib/restricted/aws/s2n/utils/s2n_asn1_time.h)27
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_mem.c8
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_mem.h5
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_random.c97
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_safety.c22
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_safety.h10
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_safety_macros.h30
-rw-r--r--contrib/restricted/aws/s2n/ya.make22
106 files changed, 3883 insertions, 1351 deletions
diff --git a/contrib/restricted/aws/s2n/CMakeLists.darwin-x86_64.txt b/contrib/restricted/aws/s2n/CMakeLists.darwin-x86_64.txt
index 92490cff9a..5a2ac247d2 100644
--- a/contrib/restricted/aws/s2n/CMakeLists.darwin-x86_64.txt
+++ b/contrib/restricted/aws/s2n/CMakeLists.darwin-x86_64.txt
@@ -9,13 +9,21 @@
add_library(restricted-aws-s2n)
target_compile_options(restricted-aws-s2n PRIVATE
+ -DS2N_ATOMIC_SUPPORTED
+ -DS2N_CLOEXEC_SUPPORTED
+ -DS2N_CLOEXEC_XOPEN_SUPPORTED
-DS2N_CLONE_SUPPORTED
+ -DS2N_DIAGNOSTICS_POP_SUPPORTED
+ -DS2N_DIAGNOSTICS_PUSH_SUPPORTED
+ -DS2N_EXECINFO_AVAILABLE
-DS2N_FALL_THROUGH_SUPPORTED
+ -DS2N_KYBER512R3_AVX2_BMI2_SUPPORTED
+ -DS2N_KYBER512R3_M256_INTRINSICS_SUPPORTED
-DS2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH
-DS2N_LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX
-DS2N_LIBCRYPTO_SUPPORTS_EVP_RC4
+ -DS2N_LIBCRYPTO_SUPPORTS_FLAG_NO_CHECK_TIME
-DS2N_MADVISE_SUPPORTED
- -DS2N_PLATFORM_SUPPORTS_KTLS
-DS2N___RESTRICT__SUPPORTED
-DS2N_STACKTRACE
-DS2N_CPUID_AVAILABLE
@@ -74,7 +82,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_polyvec.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_reduce.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_symmetric-shake.c
- ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_512_evp.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_evp.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_pq_random.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.c
@@ -160,6 +168,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_key_log.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_key_update.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ktls.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ktls_io.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_next_protocol.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
@@ -198,11 +207,12 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_array.c
- ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_asn1_time.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_atomic.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_blob.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_ensure.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_fork_detection.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_init.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_io.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_map.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_mem.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_random.c
diff --git a/contrib/restricted/aws/s2n/CMakeLists.linux-aarch64.txt b/contrib/restricted/aws/s2n/CMakeLists.linux-aarch64.txt
index cdf09bc64e..d6d351561d 100644
--- a/contrib/restricted/aws/s2n/CMakeLists.linux-aarch64.txt
+++ b/contrib/restricted/aws/s2n/CMakeLists.linux-aarch64.txt
@@ -9,15 +9,25 @@
add_library(restricted-aws-s2n)
target_compile_options(restricted-aws-s2n PRIVATE
+ -DS2N_ATOMIC_SUPPORTED
+ -DS2N_CLOEXEC_SUPPORTED
+ -DS2N_CLOEXEC_XOPEN_SUPPORTED
-DS2N_CLONE_SUPPORTED
+ -DS2N_DIAGNOSTICS_POP_SUPPORTED
+ -DS2N_DIAGNOSTICS_PUSH_SUPPORTED
+ -DS2N_EXECINFO_AVAILABLE
-DS2N_FALL_THROUGH_SUPPORTED
+ -DS2N_KYBER512R3_AVX2_BMI2_SUPPORTED
+ -DS2N_KYBER512R3_M256_INTRINSICS_SUPPORTED
-DS2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH
-DS2N_LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX
-DS2N_LIBCRYPTO_SUPPORTS_EVP_RC4
+ -DS2N_LIBCRYPTO_SUPPORTS_FLAG_NO_CHECK_TIME
-DS2N_MADVISE_SUPPORTED
- -DS2N_PLATFORM_SUPPORTS_KTLS
-DS2N___RESTRICT__SUPPORTED
-DS2N_FEATURES_AVAILABLE
+ -DS2N_LINUX_SENDFILE
+ -DS2N_KTLS_SUPPORTED
-DS2N_STACKTRACE
$<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
)
@@ -69,7 +79,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_polyvec.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_reduce.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_symmetric-shake.c
- ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_512_evp.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_evp.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_pq_random.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.c
@@ -155,6 +165,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_key_log.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_key_update.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ktls.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ktls_io.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_next_protocol.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
@@ -193,11 +204,12 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_array.c
- ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_asn1_time.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_atomic.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_blob.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_ensure.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_fork_detection.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_init.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_io.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_map.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_mem.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_random.c
diff --git a/contrib/restricted/aws/s2n/CMakeLists.linux-x86_64.txt b/contrib/restricted/aws/s2n/CMakeLists.linux-x86_64.txt
index 0f11eb8486..c982e3ec5d 100644
--- a/contrib/restricted/aws/s2n/CMakeLists.linux-x86_64.txt
+++ b/contrib/restricted/aws/s2n/CMakeLists.linux-x86_64.txt
@@ -9,15 +9,25 @@
add_library(restricted-aws-s2n)
target_compile_options(restricted-aws-s2n PRIVATE
+ -DS2N_ATOMIC_SUPPORTED
+ -DS2N_CLOEXEC_SUPPORTED
+ -DS2N_CLOEXEC_XOPEN_SUPPORTED
-DS2N_CLONE_SUPPORTED
+ -DS2N_DIAGNOSTICS_POP_SUPPORTED
+ -DS2N_DIAGNOSTICS_PUSH_SUPPORTED
+ -DS2N_EXECINFO_AVAILABLE
-DS2N_FALL_THROUGH_SUPPORTED
+ -DS2N_KYBER512R3_AVX2_BMI2_SUPPORTED
+ -DS2N_KYBER512R3_M256_INTRINSICS_SUPPORTED
-DS2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH
-DS2N_LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX
-DS2N_LIBCRYPTO_SUPPORTS_EVP_RC4
+ -DS2N_LIBCRYPTO_SUPPORTS_FLAG_NO_CHECK_TIME
-DS2N_MADVISE_SUPPORTED
- -DS2N_PLATFORM_SUPPORTS_KTLS
-DS2N___RESTRICT__SUPPORTED
-DS2N_FEATURES_AVAILABLE
+ -DS2N_LINUX_SENDFILE
+ -DS2N_KTLS_SUPPORTED
-DS2N_STACKTRACE
-DS2N_CPUID_AVAILABLE
-DS2N_KYBER512R3_AVX2_BMI2
@@ -76,7 +86,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_polyvec.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_reduce.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_symmetric-shake.c
- ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_512_evp.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_evp.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_pq_random.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.c
@@ -162,6 +172,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_key_log.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_key_update.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ktls.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ktls_io.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_next_protocol.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
@@ -200,11 +211,12 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_array.c
- ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_asn1_time.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_atomic.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_blob.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_ensure.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_fork_detection.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_init.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_io.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_map.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_mem.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_random.c
diff --git a/contrib/restricted/aws/s2n/CMakeLists.windows-x86_64.txt b/contrib/restricted/aws/s2n/CMakeLists.windows-x86_64.txt
index 584461fe50..7685f54d3f 100644
--- a/contrib/restricted/aws/s2n/CMakeLists.windows-x86_64.txt
+++ b/contrib/restricted/aws/s2n/CMakeLists.windows-x86_64.txt
@@ -9,13 +9,21 @@
add_library(restricted-aws-s2n)
target_compile_options(restricted-aws-s2n PRIVATE
+ -DS2N_ATOMIC_SUPPORTED
+ -DS2N_CLOEXEC_SUPPORTED
+ -DS2N_CLOEXEC_XOPEN_SUPPORTED
-DS2N_CLONE_SUPPORTED
+ -DS2N_DIAGNOSTICS_POP_SUPPORTED
+ -DS2N_DIAGNOSTICS_PUSH_SUPPORTED
+ -DS2N_EXECINFO_AVAILABLE
-DS2N_FALL_THROUGH_SUPPORTED
+ -DS2N_KYBER512R3_AVX2_BMI2_SUPPORTED
+ -DS2N_KYBER512R3_M256_INTRINSICS_SUPPORTED
-DS2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH
-DS2N_LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX
-DS2N_LIBCRYPTO_SUPPORTS_EVP_RC4
+ -DS2N_LIBCRYPTO_SUPPORTS_FLAG_NO_CHECK_TIME
-DS2N_MADVISE_SUPPORTED
- -DS2N_PLATFORM_SUPPORTS_KTLS
-DS2N___RESTRICT__SUPPORTED
-DS2N_STACKTRACE
-DS2N_CPUID_AVAILABLE
@@ -74,7 +82,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_polyvec.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_reduce.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/kyber_r3/kyber512r3_symmetric-shake.c
- ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_512_evp.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_evp.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/pq-crypto/s2n_pq_random.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/stuffer/s2n_stuffer.c
@@ -160,6 +168,7 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_key_log.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_key_update.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ktls.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ktls_io.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_next_protocol.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
@@ -198,11 +207,12 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_array.c
- ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_asn1_time.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_atomic.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_blob.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_ensure.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_fork_detection.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_init.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_io.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_map.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_mem.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/utils/s2n_random.c
diff --git a/contrib/restricted/aws/s2n/LICENSE b/contrib/restricted/aws/s2n/LICENSE
index 4583997a69..fb388fd473 100644
--- a/contrib/restricted/aws/s2n/LICENSE
+++ b/contrib/restricted/aws/s2n/LICENSE
@@ -205,7 +205,7 @@
============================================================================
S2N SUBCOMPONENTS:
- The s2n Project contains subcomponents with seperate copyright notices
+ The s2n Project contains subcomponents with separate copyright notices
and license terms. Your use of the source code for these subcomponents is
subject to the terms and conditions of the following licenses.
diff --git a/contrib/restricted/aws/s2n/README.md b/contrib/restricted/aws/s2n/README.md
index 64baa0db5c..414553ac97 100644
--- a/contrib/restricted/aws/s2n/README.md
+++ b/contrib/restricted/aws/s2n/README.md
@@ -14,55 +14,30 @@ s2n-tls is a C99 implementation of the TLS/SSL protocols that is designed to be
[![Join the chat at https://gitter.im/awslabs/s2n](https://badges.gitter.im/awslabs/s2n.svg)](https://gitter.im/awslabs/s2n?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Quickstart for Ubuntu
-1. Fork s2n-tls on GitHub
-2. Run the following commands on Ubuntu.
-```
-git clone https://github.com/${YOUR_GITHUB_ACCOUNT_NAME}/s2n-tls.git
-cd s2n-tls
-
-# Pick an "env" line from the codebuild/codebuild.config file and run it, in this case choose the openssl-1.1.1 with GCC 9 build
-S2N_LIBCRYPTO=openssl-1.1.1 BUILD_S2N=true TESTS=integrationv2 GCC_VERSION=9
-
-sudo codebuild/bin/s2n_install_test_dependencies.sh
-codebuild/bin/s2n_codebuild.sh
-```
-
-## Quickstart for OSX (or other platforms)
-
-If you are building on OSX, or simply don't want to execute the entire build script above, you can use build tools like Ninja.
-### OSX
-
-An example of building on OSX:
-
-```sh
-# Install required dependencies using homebrew
-brew install ninja cmake coreutils openssl@1.1
-
-# Clone the s2n-tls source repository into the `s2n-tls` directory
-git clone https://github.com/${YOUR_GITHUB_ACCOUNT_NAME}/s2n-tls.git
+```bash
+# clone s2n-tls
+git clone https://github.com/aws/s2n-tls.git
cd s2n-tls
-# Create a build directory, and build s2n-tls with debug symbols and a specific OpenSSL version.
-cmake . -Bbuild -GNinja \
- -DCMAKE_BUILD_TYPE=Debug \
- -DCMAKE_PREFIX_PATH=$(dirname $(dirname $(brew list openssl@1.1|grep libcrypto.dylib)))
-cmake --build ./build -j $(nproc)
-CTEST_PARALLEL_LEVEL=$(nproc) ninja -C build test
-```
+# install build dependencies
+sudo apt update
+sudo apt install cmake
-### Amazonlinux2
+# install a libcrypto
+sudo apt install libssl-dev
-Install dependencies with `./codebuild/bin/install_al2_dependencies.sh` after cloning.
-
-```sh
-git clone https://github.com/${YOUR_GITHUB_ACCOUNT_NAME}/s2n-tls.git
-cd s2n-tls
-cmake . -Bbuild -DCMAKE_EXE_LINKER_FLAGS="-lcrypto -lz" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-cmake --build ./build -j $(nproc)
-CTEST_PARALLEL_LEVEL=$(nproc) make -C build test
+# build s2n-tls
+cmake . -Bbuild \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX=./s2n-tls-install
+cmake --build build -j $(nproc)
+CTEST_PARALLEL_LEVEL=$(nproc) ctest --test-dir build
+cmake --install build
```
+See the [s2n-tls build documentation](docs/BUILD.md) for further guidance on building s2n-tls for your platform.
+
## Have a Question?
If you have any questions about Submitting PR's, Opening Issues, s2n-tls API usage, or something similar, we have a public chatroom available here to answer your questions: https://gitter.im/awslabs/s2n
diff --git a/contrib/restricted/aws/s2n/api/s2n.h b/contrib/restricted/aws/s2n/api/s2n.h
index 91dcc2eb43..462972e86b 100644
--- a/contrib/restricted/aws/s2n/api/s2n.h
+++ b/contrib/restricted/aws/s2n/api/s2n.h
@@ -115,6 +115,7 @@ extern "C" {
* explaining the error in English by calling s2n_strerror(s2n_errno, "EN").
* A string containing human readable error name; can be generated with `s2n_strerror_name`.
* A string containing internal debug information, including filename and line number, can be generated with `s2n_strerror_debug`.
+ * A string containing only the filename and line number can be generated with `s2n_strerror_source`.
* This string is useful to include when reporting issues to the s2n-tls development team.
*
* @warning To avoid possible confusion, s2n_errno should be cleared after processing an error: `s2n_errno = S2N_ERR_T_OK`
@@ -241,13 +242,35 @@ S2N_API extern int s2n_init(void);
S2N_API extern int s2n_cleanup(void);
/**
- * Create a new s2n_config object. This object can (and should) be associated with many connection objects.
+ * Creates a new s2n_config object. This object can (and should) be associated with many connection
+ * objects.
*
- * @returns returns a new configuration object suitable for associating certs and keys.
+ * The returned config will be initialized with default system certificates in its trust store.
+ *
+ * The returned config should be freed with `s2n_config_free()` after it's no longer in use by any
+ * connection.
+ *
+ * @returns A new configuration object suitable for configuring connections and associating certs
+ * and keys.
*/
S2N_API extern struct s2n_config *s2n_config_new(void);
/**
+ * Creates a new s2n_config object with minimal default options.
+ *
+ * This function has better performance than `s2n_config_new()` because it does not load default
+ * system certificates into the trust store by default. To add system certificates to this config,
+ * call `s2n_config_load_system_certs()`.
+ *
+ * The returned config should be freed with `s2n_config_free()` after it's no longer in use by any
+ * connection.
+ *
+ * @returns A new configuration object suitable for configuring connections and associating certs
+ * and keys.
+ */
+S2N_API extern struct s2n_config *s2n_config_new_minimal(void);
+
+/**
* Frees the memory associated with an `s2n_config` object.
*
* @param config The configuration object being freed
@@ -386,6 +409,14 @@ S2N_API extern const char *s2n_strerror_debug(int error, const char *lang);
S2N_API extern const char *s2n_strerror_name(int error);
/**
+ * Translates an s2n_error code to a filename and line number.
+ *
+ * @param error The error code to explain. Usually this is s2n_errno.
+ * @returns The error string.
+ */
+S2N_API extern const char *s2n_strerror_source(int error);
+
+/**
* Opaque stack trace structure.
*/
struct s2n_stacktrace;
@@ -534,6 +565,8 @@ typedef int (*s2n_rand_mix_callback)(void *data, uint32_t size);
* Allows the caller to override s2n-tls's entropy functions.
*
* @warning This function must be called before s2n_init().
+ *
+ * @note The overriden random callbacks will not be used when s2n-tls is operating in FIPS mode.
*
* @param rand_init_callback The s2n_rand_init_callback
* @param rand_cleanup_callback The s2n_rand_cleanup_callback
@@ -556,6 +589,7 @@ typedef enum {
S2N_EXTENSION_SIGNATURE_ALGORITHMS = 13,
S2N_EXTENSION_ALPN = 16,
S2N_EXTENSION_CERTIFICATE_TRANSPARENCY = 18,
+ S2N_EXTENSION_SUPPORTED_VERSIONS = 43,
S2N_EXTENSION_RENEGOTIATION_INFO = 65281,
} s2n_tls_extension_type;
@@ -787,8 +821,10 @@ S2N_API extern int s2n_config_set_cert_chain_and_key_defaults(struct s2n_config
/**
* Adds to the trust store from a CA file or directory containing trusted certificates.
- * To completely override those locations, call s2n_config_wipe_trust_store() before calling
- * this function.
+ *
+ * When configs are created with `s2n_config_new()`, the trust store is initialized with default
+ * system certificates. To completely override these certificates, call
+ * `s2n_config_wipe_trust_store()` before calling this function.
*
* @note The trust store will be initialized with the common locations for the host
* operating system by default.
@@ -800,10 +836,11 @@ S2N_API extern int s2n_config_set_cert_chain_and_key_defaults(struct s2n_config
S2N_API extern int s2n_config_set_verification_ca_location(struct s2n_config *config, const char *ca_pem_filename, const char *ca_dir);
/**
- * Adds a PEM to the trust store. This will allocate memory, and load PEM into the
- * Trust Store. Note that the trust store will be initialized with the common locations
- * for the host operating system by default. To completely override those locations,
- * call s2n_config_wipe_trust_store before calling this function.
+ * Adds a PEM to the trust store. This will allocate memory, and load `pem` into the trust store.
+ *
+ * When configs are created with `s2n_config_new()`, the trust store is initialized with default
+ * system certificates. To completely override these certificates, call
+ * `s2n_config_wipe_trust_store()` before calling this function.
*
* @param config The configuration object being updated
* @param pem The string value of the PEM certificate.
@@ -812,19 +849,33 @@ S2N_API extern int s2n_config_set_verification_ca_location(struct s2n_config *co
S2N_API extern int s2n_config_add_pem_to_trust_store(struct s2n_config *config, const char *pem);
/**
- * Clear the trust store.
+ * Clears the trust store of all certificates.
*
- * Note that the trust store will be initialized with the common locations for
- * the host operating system by default. To completely override those locations,
- * call this before functions like `s2n_config_set_verification_ca_location()`
- * or `s2n_config_add_pem_to_trust_store()`
+ * When configs are created with `s2n_config_new()`, the trust store is initialized with default
+ * system certificates. To completely override these certificates, call this function before
+ * functions like `s2n_config_set_verification_ca_location()` or
+ * `s2n_config_add_pem_to_trust_store()`.
*
* @param config The configuration object being updated
- *
- * @returns 0 on success and -1 on error
+ * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
*/
S2N_API extern int s2n_config_wipe_trust_store(struct s2n_config *config);
+/**
+ * Loads default system certificates into the trust store.
+ *
+ * `s2n_config_new_minimal()` doesn't load default system certificates into the config's trust
+ * store by default. If `config` was created with `s2n_config_new_minimal`, this function can be
+ * used to load system certificates into the trust store.
+ *
+ * @note This API will error if called on a config that has already loaded system certificates
+ * into its trust store, which includes all configs created with `s2n_config_new()`.
+ *
+ * @param config The configuration object being updated
+ * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
+ */
+S2N_API extern int s2n_config_load_system_certs(struct s2n_config *config);
+
typedef enum {
S2N_VERIFY_AFTER_SIGN_DISABLED,
S2N_VERIFY_AFTER_SIGN_ENABLED
@@ -934,6 +985,30 @@ S2N_API extern int s2n_config_set_verify_host_callback(struct s2n_config *config
S2N_API extern int s2n_config_set_check_stapled_ocsp_response(struct s2n_config *config, uint8_t check_ocsp);
/**
+ * Disables timestamp validation for received certificates.
+ *
+ * By default, s2n-tls checks the notBefore and notAfter fields on the certificates it receives
+ * during the handshake. If the current date is not within the range of these fields for any
+ * certificate in the chain of trust, `s2n_negotiate()` will error. This validation is in
+ * accordance with RFC 5280, section 6.1.3 a.2:
+ * https://datatracker.ietf.org/doc/html/rfc5280#section-6.1.3.
+ *
+ * This API will disable this timestamp validation, permitting negotiation with peers that send
+ * expired certificates, or certificates that are not yet considered valid.
+ *
+ * @warning Applications calling this API should seriously consider the security implications of
+ * disabling this validation. The validity period of a certificate corresponds to the range of time
+ * in which the CA is guaranteed to maintain information regarding the certificate's revocation
+ * status. As such, it may not be possible to obtain accurate revocation information for
+ * certificates with invalid timestamps. Applications disabling this validation MUST implement
+ * some external method for limiting certificate lifetime.
+ *
+ * @param config The associated connection config.
+ * @returns S2N_SUCCESS on success, S2N_FAILURE on failure.
+ */
+S2N_API extern int s2n_config_disable_x509_time_verification(struct s2n_config *config);
+
+/**
* Turns off all X.509 validation during the negotiation phase of the connection. This should only
* be used for testing or debugging purposes.
*
@@ -1456,6 +1531,31 @@ S2N_API extern int s2n_client_hello_get_session_id_length(struct s2n_client_hell
S2N_API extern int s2n_client_hello_get_session_id(struct s2n_client_hello *ch, uint8_t *out, uint32_t *out_length, uint32_t max_length);
/**
+ * Retrieves the supported groups received from the client in the supported groups extension.
+ *
+ * IANA values for each of the received supported groups are written to the provided `groups`
+ * array, and `groups_count` is set to the number of received supported groups.
+ *
+ * `groups_count_max` should be set to the maximum capacity of the `groups` array. If
+ * `groups_count_max` is less than the number of received supported groups, this function will
+ * error. To determine how large `groups` should be in advance, use
+ * `s2n_client_hello_get_extension_length()` with the S2N_EXTENSION_SUPPORTED_GROUPS extension
+ * type, and divide the value by 2.
+ *
+ * If no supported groups extension was received from the peer, or the received supported groups
+ * extension is malformed, this function will error.
+ *
+ * @param ch A pointer to the ClientHello. Can be retrieved from a connection via
+ * `s2n_connection_get_client_hello()`.
+ * @param groups The array to populate with the received supported groups.
+ * @param groups_count_max The maximum number of supported groups that can fit in the `groups` array.
+ * @param groups_count Returns the number of received supported groups.
+ * @returns S2N_SUCCESS on success. S2N_FAILURE on failure.
+ */
+S2N_API extern int s2n_client_hello_get_supported_groups(struct s2n_client_hello *ch, uint16_t *groups,
+ uint16_t groups_count_max, uint16_t *groups_count);
+
+/**
* Sets the file descriptor for a s2n connection.
*
* @warning If the read end of the pipe is closed unexpectedly, writing to the pipe will raise a SIGPIPE signal.
@@ -1794,8 +1894,11 @@ typedef enum {
* rejects the client certificate, the client may later receive an alert while calling s2n_recv,
* potentially after already having sent application data with s2n_send.
*
+ * See the following example for guidance on calling `s2n_negotiate()`:
+ * https://github.com/aws/s2n-tls/blob/main/docs/examples/s2n_negotiate.c
+ *
* @param conn A pointer to the s2n_connection object
- * @param blocked A pointer which will be set to the blocked status.
+ * @param blocked A pointer which will be set to the blocked status if an `S2N_ERR_T_BLOCKED` error is returned.
* @returns S2N_SUCCESS if the handshake completed. S2N_FAILURE if the handshake encountered an error or is blocked.
*/
S2N_API extern int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked);
@@ -1806,37 +1909,28 @@ S2N_API extern int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status
*
* @note Partial writes are possible not just for non-blocking I/O, but also for connections aborted while active.
* @note Unlike OpenSSL, repeated calls to s2n_send() should not duplicate the original parameters, but should
- * update `buf` and `size` per the indication of size written. For example;
- * ```c
- * s2n_blocked_status blocked;
- * int written = 0;
- * char data[10];
- * do {
- * int w = s2n_send(conn, data + written, 10 - written, &blocked);
- * if (w < 0) {
- * break;
- * }
- * written += w;
- * } while (blocked != S2N_NOT_BLOCKED);
- * ```
+ * update `buf` and `size` per the indication of size written.
+ *
+ * See the following example for guidance on calling `s2n_send()`:
+ * https://github.com/aws/s2n-tls/blob/main/docs/examples/s2n_send.c
*
* @param conn A pointer to the s2n_connection object
* @param buf A pointer to a buffer that s2n will write data from
* @param size The size of buf
- * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate()
+ * @param blocked A pointer which will be set to the blocked status if an `S2N_ERR_T_BLOCKED` error is returned.
* @returns The number of bytes written, and may indicate a partial write
*/
S2N_API extern ssize_t s2n_send(struct s2n_connection *conn, const void *buf, ssize_t size, s2n_blocked_status *blocked);
/**
- * Works in the same way as s2n_sendv_with_offset() except that the latter's `offs` parameter is implicitly assumed to be 0.
- * Therefore in the partial write case, the caller would have to make sure that `bufs` and `count` fields are modified in a way that takes
+ * Works in the same way as s2n_sendv_with_offset() but with the `offs` parameter implicitly assumed to be 0.
+ * Therefore in the partial write case, the caller would have to make sure that the `bufs` and `count` fields are modified in a way that takes
* the partial writes into account.
*
* @param conn A pointer to the s2n_connection object
* @param bufs A pointer to a vector of buffers that s2n will write data from.
* @param count The number of buffers in `bufs`
- * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate()
+ * @param blocked A pointer which will be set to the blocked status if an `S2N_ERR_T_BLOCKED` error is returned.
* @returns The number of bytes written, and may indicate a partial write.
*/
S2N_API extern ssize_t s2n_sendv(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, s2n_blocked_status *blocked);
@@ -1846,29 +1940,16 @@ S2N_API extern ssize_t s2n_sendv(struct s2n_connection *conn, const struct iovec
*
* @note Partial writes are possible not just for non-blocking I/O, but also for connections aborted while active.
*
- * @note Unlike OpenSSL, repeated calls to s2n_sendv_with_offset() should not duplicate the original parameters, but should update `bufs` and `count` per the indication of size written. For example;
- *
- * ```c
- * s2n_blocked_status blocked;
- * int written = 0;
- * char data[10];
- * struct iovec iov[1];
- * iov[0].iov_base = data;
- * iov[0].iov_len = 10;
- * do {
- * int w = s2n_sendv_with_offset(conn, iov, 1, written, &blocked);
- * if (w < 0) {
- * break;
- * }
- * written += w;
- * } while (blocked != S2N_NOT_BLOCKED);
- * ```
+ * @note Unlike OpenSSL, repeated calls to s2n_sendv_with_offset() should not duplicate the original parameters, but should update `bufs` and `count` per the indication of size written.
+ *
+ * See the following example for guidance on calling `s2n_sendv_with_offset()`:
+ * https://github.com/aws/s2n-tls/blob/main/docs/examples/s2n_send.c
*
* @param conn A pointer to the s2n_connection object
* @param bufs A pointer to a vector of buffers that s2n will write data from.
* @param count The number of buffers in `bufs`
* @param offs The write cursor offset. This should be updated as data is written. See the example code.
- * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate()
+ * @param blocked A pointer which will be set to the blocked status if an `S2N_ERR_T_BLOCKED` error is returned.
* @returns The number of bytes written, and may indicate a partial write.
*/
S2N_API extern ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, ssize_t offs, s2n_blocked_status *blocked);
@@ -1877,24 +1958,15 @@ S2N_API extern ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const
* Decrypts and reads **size* to `buf` data from the associated
* connection.
*
- * @note Unlike OpenSSL, repeated calls to `s2n_recv` should not duplicate the original parameters, but should update `buf` and `size` per the indication of size read. For example;
- * ```c
- * s2n_blocked_status blocked;
- * int bytes_read = 0;
- * char data[10];
- * do {
- * int r = s2n_recv(conn, data + bytes_read, 10 - bytes_read, &blocked);
- * if (r < 0) {
- * break;
- * }
- * bytes_read += r;
- * } while (blocked != S2N_NOT_BLOCKED);
- * ```
+ * @note Unlike OpenSSL, repeated calls to `s2n_recv` should not duplicate the original parameters, but should update `buf` and `size` per the indication of size read.
+ *
+ * See the following example for guidance on calling `s2n_recv()`:
+ * https://github.com/aws/s2n-tls/blob/main/docs/examples/s2n_recv.c
*
* @param conn A pointer to the s2n_connection object
* @param buf A pointer to a buffer that s2n will place read data into.
* @param size Size of `buf`
- * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate()
+ * @param blocked A pointer which will be set to the blocked status if an `S2N_ERR_T_BLOCKED` error is returned.
* @returns number of bytes read. 0 if the connection was shutdown by peer.
*/
S2N_API extern ssize_t s2n_recv(struct s2n_connection *conn, void *buf, ssize_t size, s2n_blocked_status *blocked);
@@ -1968,7 +2040,7 @@ S2N_API extern int s2n_connection_free(struct s2n_connection *conn);
* * The s2n_connection handle can be freed via s2n_connection_free() or reused via s2n_connection_wipe()
*
* @param conn A pointer to the s2n_connection object
- * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate()
+ * @param blocked A pointer which will be set to the blocked status if an `S2N_ERR_T_BLOCKED` error is returned.
* @returns S2N_SUCCESS on success. S2N_FAILURE on failure
*/
S2N_API extern int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked);
@@ -1996,7 +2068,7 @@ S2N_API extern int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status
* the read side of the underlying transport.
*
* @param conn A pointer to the s2n_connection object
- * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate()
+ * @param blocked A pointer which will be set to the blocked status if an `S2N_ERR_T_BLOCKED` error is returned.
* @returns S2N_SUCCESS on success. S2N_FAILURE on failure
*/
S2N_API extern int s2n_shutdown_send(struct s2n_connection *conn, s2n_blocked_status *blocked);
@@ -2173,6 +2245,9 @@ S2N_API extern int s2n_session_ticket_get_lifetime(struct s2n_session_ticket *ti
/**
* De-serializes the session state and updates the connection accordingly.
*
+ * If this method fails, the connection should not be affected: calling s2n_negotiate
+ * with the connection should simply result in a full handshake.
+ *
* @param conn A pointer to the s2n_connection object
* @param session A pointer to a buffer of size `length`
* @param length The size of the `session` buffer
@@ -2796,6 +2871,20 @@ S2N_API extern int s2n_connection_client_cert_used(struct s2n_connection *conn);
S2N_API extern const char *s2n_connection_get_cipher(struct s2n_connection *conn);
/**
+ * Provides access to the TLS-Exporter functionality.
+ *
+ * See https://datatracker.ietf.org/doc/html/rfc5705 and https://www.rfc-editor.org/rfc/rfc8446.
+ *
+ * @note This is currently only available with TLS 1.3 connections which have finished a handshake.
+ *
+ * @param conn A pointer to the connection
+ * @returns A POSIX error signal. If an error was returned, the value contained in `output` should be considered invalid.
+ */
+S2N_API extern int s2n_connection_tls_exporter(struct s2n_connection *conn,
+ const uint8_t *label, uint32_t label_length, const uint8_t *context, uint32_t context_length,
+ uint8_t *output, uint32_t output_length);
+
+/**
* Returns the IANA value for the connection's negotiated cipher suite.
*
* The value is returned in the form of `first,second`, in order to closely match
diff --git a/contrib/restricted/aws/s2n/api/unstable/crl.h b/contrib/restricted/aws/s2n/api/unstable/crl.h
index aafd141517..0e0388c0c9 100644
--- a/contrib/restricted/aws/s2n/api/unstable/crl.h
+++ b/contrib/restricted/aws/s2n/api/unstable/crl.h
@@ -169,3 +169,77 @@ S2N_API int s2n_crl_lookup_set(struct s2n_crl_lookup *lookup, struct s2n_crl *cr
* @return S2N_SUCCESS on success, S2N_FAILURE on failure.
*/
S2N_API int s2n_crl_lookup_ignore(struct s2n_crl_lookup *lookup);
+
+struct s2n_cert_validation_info;
+
+/**
+ * A callback which can be implemented to perform additional validation on received certificates.
+ *
+ * The cert validation callback is invoked after receiving and validating the peer's certificate chain. The callback
+ * can be used by clients to validate server certificates, or by servers to validate client certificates in the case of
+ * mutual auth. Note that any validation performed by applications in the callback is in addition to the certificate
+ * validation already performed by s2n-tls.
+ *
+ * Applications can use either of the following APIs from within the callback to retrieve the peer's certificate chain
+ * and perform validation before proceeding with the handshake:
+ * - `s2n_connection_get_peer_cert_chain()`
+ * - `s2n_connection_get_client_cert_chain()`
+ *
+ * If the validation performed in the callback is successful, `s2n_cert_validation_accept()` MUST be called to allow
+ * `s2n_negotiate()` to continue the handshake. If the validation is unsuccessful, `s2n_cert_validation_reject()`
+ * MUST be called, which will cause `s2n_negotiate()` to error. The behavior of `s2n_negotiate()` is undefined if
+ * neither `s2n_cert_validation_accept()` or `s2n_cert_validation_reject()` are called.
+ *
+ * The `info` parameter is passed to the callback in order to call APIs specific to the cert validation callback, like
+ * `s2n_cert_validation_accept()` and `s2n_cert_validation_reject()`. The `info` argument is only valid for the
+ * lifetime of the callback, and must not be used after the callback has finished.
+ *
+ * After calling `s2n_cert_validation_reject()`, `s2n_negotiate()` will fail with a protocol error indicating that
+ * the cert has been rejected from the callback. If more information regarding an application's custom validation
+ * failure is required, consider adding an error code field to the custom connection context. See
+ * `s2n_connection_set_ctx()` and `s2n_connection_get_ctx()` for how to set and retrieve custom connection contexts.
+ *
+ * @param conn The connection object from which the callback was invoked.
+ * @param info The cert validation info object used to call cert validation APIs.
+ * @param context Application data provided to the callback function via `s2n_config_set_cert_validation_cb()`.
+ * @returns 0 on success, -1 on failure.
+ */
+typedef int (*s2n_cert_validation_callback)(struct s2n_connection *conn, struct s2n_cert_validation_info *info,
+ void *context);
+
+/**
+ * Sets a callback to perform additional validation on received certificates.
+ *
+ * @param config The associated connection config.
+ * @param callback The cert validation callback to set.
+ * @param context Optional application data passed to the callback function.
+ * @returns S2N_SUCCESS on success, S2N_FAILURE on failure.
+ */
+S2N_API int s2n_config_set_cert_validation_cb(struct s2n_config *config, s2n_cert_validation_callback callback,
+ void *context);
+
+/**
+ * Indicates that the validation performed in the cert validation callback was successful.
+ *
+ * `s2n_cert_validation_accept()` should be called from within the cert validation callback to allow `s2n_negotiate()`
+ * to continue the handshake.
+ *
+ * This function must not be called outside of the cert validation callback.
+ *
+ * @param info The cert validation info object for the associated callback.
+ * @returns S2N_SUCCESS on success, S2N_FAILURE on failure.
+ */
+S2N_API int s2n_cert_validation_accept(struct s2n_cert_validation_info *info);
+
+/**
+ * Indicates that the validation performed in the cert validation callback was unsuccessful.
+ *
+ * `s2n_cert_validation_reject()` should be called from within the cert validation callback to cause `s2n_negotiate()`
+ * to error.
+ *
+ * This function must not be called outside of the cert validation callback.
+ *
+ * @param info The cert validation info object for the associated callback.
+ * @returns S2N_SUCCESS on success, S2N_FAILURE on failure.
+ */
+S2N_API int s2n_cert_validation_reject(struct s2n_cert_validation_info *info);
diff --git a/contrib/restricted/aws/s2n/api/unstable/ktls.h b/contrib/restricted/aws/s2n/api/unstable/ktls.h
new file mode 100644
index 0000000000..f963130fe6
--- /dev/null
+++ b/contrib/restricted/aws/s2n/api/unstable/ktls.h
@@ -0,0 +1,115 @@
+/*
+* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License").
+* You may not use this file except in compliance with the License.
+* A copy of the License is located at
+*
+* http://aws.amazon.com/apache2.0
+*
+* or in the "license" file accompanying this file. This file is distributed
+* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+* express or implied. See the License for the specific language governing
+* permissions and limitations under the License.
+*/
+
+#pragma once
+
+#include <s2n.h>
+
+/**
+ * @file ktls.h
+ *
+ * The following APIs enable applications to use kernel TLS (kTLS), meaning that
+ * encrypting and decrypting TLS records is handled by the kernel rather than by
+ * the s2n-tls library.
+ *
+ * The kTLS APIs are currently considered unstable. kTLS is a relatively new
+ * feature with limited and volatile support from different kernels and hardware.
+ *
+ * Currently, s2n-tls supports ktls for only very limited scenarios:
+ * - You must be using Linux. We have not tested with other kernels.
+ * - Your kernel must support kTLS. For Linux, versions >4.13 should support kTLS.
+ * - The TLS kernel module must be enabled. While some environments enable the
+ * module by default, most will require you to run `sudo modprobe tls`.
+ * - You must negotiate TLS1.2. TLS1.3 support is blocked on kernel support for
+ * TLS KeyUpdate messages.
+ * - You must negotiate AES128-GCM, which is the most preferred cipher suite
+ * in the "default" security policy. Other ciphers are supported by the kernel,
+ * but not implemented in s2n-tls yet.
+ */
+
+/**
+ * Enables sending using kTLS on a given connection.
+ *
+ * See above for the limitations on when kTLS can be enabled. Additionally,
+ * s2n_connection_ktls_enable_send must be called after the handshake completes.
+ * It may be called after some application data is sent and received without kTLS,
+ * but there must be no pending application data that requires flushing. If these
+ * requirements are not met, enabling kTLS will fail with an error.
+ *
+ * After kTLS is enabled for sending, s2n_send, s2n_sendv, and s2n_sendv_with_offset
+ * will use kTLS. kTLS should result in memory and CPU savings. s2n_sendfile will
+ * also become available.
+ *
+ * For applications using kTLS to avoid copying or allocating memory, s2n_sendv
+ * should be preferred over s2n_sendv_with_offset. For s2n_sendv_with_offset,
+ * s2n-tls may need to copy the provided iovec array to apply the offset, and may
+ * need to allocate memory to copy large (>16) iovec arrays.
+ *
+ * If kTLS is enabled for sending, s2n_connection_get_wire_bytes_out will always
+ * return 0 instead of an accurate count.
+ *
+ * @warning Due to the uncertainty around kTLS support, the signature of this
+ * method is likely to change before kTLS is marked as stable.
+ *
+ * @param conn A pointer to the connection.
+ * @returns S2N_SUCCESS if kTLS is successfully enabled. If kTlS is not successfully
+ * enabled, returns S2N_FAILURE but the connection may proceed without kTLS.
+ */
+S2N_API int s2n_connection_ktls_enable_send(struct s2n_connection *conn);
+
+/**
+ * Enables receiving using kTLS on a given connection.
+ *
+ * See above for the limitations on when kTLS can be enabled. Additionally,
+ * s2n_connection_ktls_enable_recv must be called after the handshake completes.
+ * It may be called after some application data is sent and received without kTLS,
+ * but there must be no buffered application data that requires draining. If these
+ * requirements are not met, enabling kTLS will fail with an error.
+ *
+ * After kTLS is enabled for receiving, s2n_recv will use kTLS. This may result
+ * in memory and CPU savings, but currently will still buffer and copy application data.
+ * We will further optimize s2n_recv for kTLS in the future.
+ *
+ * If kTLS is enabled for receiving, s2n_connection_get_wire_bytes_in will always
+ * return 0 instead of an accurate count.
+ *
+ * @warning Due to the uncertainty around kTLS support, the signature of this
+ * method is likely to change before kTLS is marked as stable.
+ *
+ * @param conn A pointer to the connection.
+ * @returns S2N_SUCCESS if kTLS is successfully enabled. If kTlS is not successfully
+ * enabled, returns S2N_FAILURE but the connection may proceed without kTLS.
+ */
+S2N_API int s2n_connection_ktls_enable_recv(struct s2n_connection *conn);
+
+/**
+ * Sends the contents of a file as application data.
+ *
+ * s2n_sendfile should be more efficient than s2n_send because the copy between
+ * the file and the write socket happens inside the kernel.
+ *
+ * This method is only supported if kTLS is enabled for sending.
+ *
+ * @param conn A pointer to the connection.
+ * @param fd The file descriptor to read from. It must be opened for reading and
+ * support mmap-like operations (i.e., it cannot be a socket).
+ * @param offset The offset in the file to begin reading at.
+ * @param count The maximum number of bytes to read from the file.
+ * @param bytes_written Will be set to the number of bytes written if successful.
+ * @param blocked Will be set to the blocked status if an `S2N_ERR_T_BLOCKED` error is returned.
+ * @returns S2N_SUCCESS if any bytes are successfully written, S2N_FAILURE otherwise.
+ */
+S2N_API int s2n_sendfile(struct s2n_connection *conn, int fd, off_t offset, size_t count,
+ size_t *bytes_written, s2n_blocked_status *blocked);
diff --git a/contrib/restricted/aws/s2n/api/unstable/npn.h b/contrib/restricted/aws/s2n/api/unstable/npn.h
new file mode 100644
index 0000000000..f3667fcb34
--- /dev/null
+++ b/contrib/restricted/aws/s2n/api/unstable/npn.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#pragma once
+
+#include <s2n.h>
+
+/**
+ * @file npn.h
+ *
+ * The Next Protocol Negotiation Extension, or NPN, was an RFC proposal to
+ * negotiate an application protocol. This proposal was never standardized, and
+ * it was eventually replaced with the ALPN Extension. However, an early draft
+ * version of the NPN Extension was implemented in Openssl.
+ * Now, OpenSSL clients and servers may require this extension in order to connect.
+ *
+ * s2n-tls supports NPN to make it easier for users whose peers require this
+ * extension, but s2n-tls does NOT recommend its use. The specific draft version
+ * supported is https://datatracker.ietf.org/doc/html/draft-agl-tls-nextprotoneg-03,
+ * which provides interoperability with OpenSSL.
+ */
+
+/**
+ * Turns on support for the NPN extension.
+ *
+ * This will allow an s2n-tls client to send the NPN extension and an s2n-tls
+ * server to respond to receiving the NPN extension. However, if their peer
+ * also indicates support for the ALPN extension, s2n-tls will prefer that.
+ *
+ * Use s2n_config_append_protocol_preference() to set up a list of supported protocols.
+ * After the negotiation for the connection has completed, the agreed-upon protocol
+ * can be retrieved with s2n_get_application_protocol().
+ *
+ * @param config A pointer to the config object
+ * @param enable Set to true to enable. Set to false to disable.
+ * @returns S2N_SUCCESS on success, S2N_FAILURE on error.
+ */
+S2N_API int s2n_config_set_npn(struct s2n_config *config, bool enable);
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_aes_gcm.c b/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_aes_gcm.c
index 5fb83b3df7..0d7a8f2d84 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_aes_gcm.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_aead_cipher_aes_gcm.c
@@ -17,6 +17,7 @@
#include <openssl/evp.h>
#include "crypto/s2n_cipher.h"
+#include "crypto/s2n_ktls_crypto.h"
#include "tls/s2n_crypto.h"
#include "utils/s2n_blob.h"
#include "utils/s2n_safety.h"
@@ -376,6 +377,74 @@ static int s2n_aead_cipher_aes_gcm_destroy_key(struct s2n_session_key *key)
#endif
+static S2N_RESULT s2n_aead_cipher_aes128_gcm_set_ktls_info(struct s2n_ktls_crypto_info_inputs *in,
+ struct s2n_ktls_crypto_info *out)
+{
+ RESULT_ENSURE_REF(in);
+ RESULT_ENSURE_REF(out);
+
+ s2n_ktls_crypto_info_tls12_aes_gcm_128 *crypto_info = &out->ciphers.aes_gcm_128;
+ crypto_info->info.version = TLS_1_2_VERSION;
+ crypto_info->info.cipher_type = TLS_CIPHER_AES_GCM_128;
+
+ RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size);
+ RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key));
+
+ RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->iv.size);
+ RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data, sizeof(crypto_info->iv));
+
+ RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size);
+ RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq));
+
+ /* The salt is a prefix of the IV
+ *
+ *= https://www.rfc-editor.org/rfc/rfc4106#section-4
+ *# The salt field is a four-octet value that is assigned at the
+ *# beginning of the security association, and then remains constant
+ *# for the life of the security association.
+ */
+ RESULT_ENSURE_LTE(sizeof(crypto_info->salt), in->iv.size);
+ RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, sizeof(crypto_info->salt));
+
+ RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info,
+ sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_128)));
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_aead_cipher_aes256_gcm_set_ktls_info(
+ struct s2n_ktls_crypto_info_inputs *in, struct s2n_ktls_crypto_info *out)
+{
+ RESULT_ENSURE_REF(in);
+ RESULT_ENSURE_REF(out);
+
+ s2n_ktls_crypto_info_tls12_aes_gcm_256 *crypto_info = &out->ciphers.aes_gcm_256;
+ crypto_info->info.version = TLS_1_2_VERSION;
+ crypto_info->info.cipher_type = TLS_CIPHER_AES_GCM_256;
+
+ RESULT_ENSURE_LTE(sizeof(crypto_info->key), in->key.size);
+ RESULT_CHECKED_MEMCPY(crypto_info->key, in->key.data, sizeof(crypto_info->key));
+
+ RESULT_ENSURE_LTE(sizeof(crypto_info->iv), in->iv.size);
+ RESULT_CHECKED_MEMCPY(crypto_info->iv, in->iv.data, sizeof(crypto_info->iv));
+
+ RESULT_ENSURE_LTE(sizeof(crypto_info->rec_seq), in->seq.size);
+ RESULT_CHECKED_MEMCPY(crypto_info->rec_seq, in->seq.data, sizeof(crypto_info->rec_seq));
+
+ /* The salt is a prefix of the IV
+ *
+ *= https://www.rfc-editor.org/rfc/rfc4106#section-4
+ *# The salt field is a four-octet value that is assigned at the
+ *# beginning of the security association, and then remains constant
+ *# for the life of the security association.
+ */
+ RESULT_ENSURE_LTE(sizeof(crypto_info->salt), in->iv.size);
+ RESULT_CHECKED_MEMCPY(crypto_info->salt, in->iv.data, sizeof(crypto_info->salt));
+
+ RESULT_GUARD_POSIX(s2n_blob_init(&out->value, (uint8_t *) (void *) crypto_info,
+ sizeof(s2n_ktls_crypto_info_tls12_aes_gcm_256)));
+ return S2N_RESULT_OK;
+}
+
const struct s2n_cipher s2n_aes128_gcm = {
.key_material_size = S2N_TLS_AES_128_GCM_KEY_LEN,
.type = S2N_AEAD,
@@ -390,7 +459,7 @@ const struct s2n_cipher s2n_aes128_gcm = {
.set_encryption_key = s2n_aead_cipher_aes128_gcm_set_encryption_key,
.set_decryption_key = s2n_aead_cipher_aes128_gcm_set_decryption_key,
.destroy_key = s2n_aead_cipher_aes_gcm_destroy_key,
- .ktls_supported = true,
+ .set_ktls_info = s2n_aead_cipher_aes128_gcm_set_ktls_info,
};
const struct s2n_cipher s2n_aes256_gcm = {
@@ -407,6 +476,7 @@ const struct s2n_cipher s2n_aes256_gcm = {
.set_encryption_key = s2n_aead_cipher_aes256_gcm_set_encryption_key,
.set_decryption_key = s2n_aead_cipher_aes256_gcm_set_decryption_key,
.destroy_key = s2n_aead_cipher_aes_gcm_destroy_key,
+ .set_ktls_info = s2n_aead_cipher_aes256_gcm_set_ktls_info,
};
/* TLS 1.3 GCM ciphers */
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_cipher.h b/contrib/restricted/aws/s2n/crypto/s2n_cipher.h
index 18ac7cdccf..47c724ea63 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_cipher.h
+++ b/contrib/restricted/aws/s2n/crypto/s2n_cipher.h
@@ -23,6 +23,7 @@
#include <openssl/rsa.h>
#include "crypto/s2n_crypto.h"
+#include "crypto/s2n_ktls_crypto.h"
#include "utils/s2n_blob.h"
#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
@@ -81,12 +82,13 @@ struct s2n_cipher {
struct s2n_composite_cipher comp;
} io;
uint8_t key_material_size;
- bool ktls_supported;
uint8_t (*is_available)(void);
int (*init)(struct s2n_session_key *key);
int (*set_decryption_key)(struct s2n_session_key *key, struct s2n_blob *in);
int (*set_encryption_key)(struct s2n_session_key *key, struct s2n_blob *in);
int (*destroy_key)(struct s2n_session_key *key);
+ S2N_RESULT (*set_ktls_info)(struct s2n_ktls_crypto_info_inputs *inputs,
+ struct s2n_ktls_crypto_info *crypto_info);
};
int s2n_session_key_alloc(struct s2n_session_key *key);
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_dhe.c b/contrib/restricted/aws/s2n/crypto/s2n_dhe.c
index aa5b629c09..da8f845e3b 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_dhe.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_dhe.c
@@ -138,24 +138,29 @@ int s2n_pkcs3_to_dh_params(struct s2n_dh_params *dh_params, struct s2n_blob *pkc
{
POSIX_ENSURE_REF(dh_params);
POSIX_PRECONDITION(s2n_blob_validate(pkcs3));
+ DEFER_CLEANUP(struct s2n_dh_params temp_dh_params = { 0 }, s2n_dh_params_free);
uint8_t *original_ptr = pkcs3->data;
- dh_params->dh = d2i_DHparams(NULL, (const unsigned char **) (void *) &pkcs3->data, pkcs3->size);
- POSIX_GUARD(s2n_check_p_g_dh_params(dh_params));
- if (pkcs3->data && (pkcs3->data - original_ptr != pkcs3->size)) {
- DH_free(dh_params->dh);
- POSIX_BAIL(S2N_ERR_INVALID_PKCS3);
+ temp_dh_params.dh = d2i_DHparams(NULL, (const unsigned char **) (void *) &pkcs3->data, pkcs3->size);
+
+ POSIX_GUARD(s2n_check_p_g_dh_params(&temp_dh_params));
+
+ if (pkcs3->data) {
+ POSIX_ENSURE_GTE(pkcs3->data, original_ptr);
+ POSIX_ENSURE((uint32_t) (pkcs3->data - original_ptr) == pkcs3->size, S2N_ERR_INVALID_PKCS3);
}
+
pkcs3->data = original_ptr;
/* Require at least 2048 bits for the DH size */
- if (DH_size(dh_params->dh) < S2N_MIN_DH_PRIME_SIZE_BYTES) {
- DH_free(dh_params->dh);
- POSIX_BAIL(S2N_ERR_DH_TOO_SMALL);
- }
+ POSIX_ENSURE(DH_size(temp_dh_params.dh) >= S2N_MIN_DH_PRIME_SIZE_BYTES, S2N_ERR_DH_TOO_SMALL);
/* Check the generator and prime */
- POSIX_GUARD(s2n_dh_params_check(dh_params));
+ POSIX_GUARD(s2n_dh_params_check(&temp_dh_params));
+
+ dh_params->dh = temp_dh_params.dh;
+
+ ZERO_TO_DISABLE_DEFER_CLEANUP(temp_dh_params);
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c
index e4da43f7f0..2761f93327 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c
@@ -40,13 +40,12 @@ EC_KEY *s2n_unsafe_ecdsa_get_non_const(const struct s2n_ecdsa_key *ecdsa_key)
{
PTR_ENSURE_REF(ecdsa_key);
- /* pragma gcc diagnostic was added in gcc 4.6 */
-#if defined(__clang__) || S2N_GCC_VERSION_AT_LEAST(4, 6, 0)
+#ifdef S2N_DIAGNOSTICS_PUSH_SUPPORTED
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
#endif
EC_KEY *out_ec_key = (EC_KEY *) ecdsa_key->ec_key;
-#if defined(__clang__) || S2N_GCC_VERSION_AT_LEAST(4, 6, 0)
+#ifdef S2N_DIAGNOSTICS_POP_SUPPORTED
#pragma GCC diagnostic pop
#endif
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hkdf.c b/contrib/restricted/aws/s2n/crypto/s2n_hkdf.c
index dd666ae653..da5a16ad3f 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_hkdf.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_hkdf.c
@@ -13,8 +13,9 @@
* permissions and limitations under the License.
*/
-#include <stdio.h>
+#include "crypto/s2n_hkdf.h"
+#include "crypto/s2n_fips.h"
#include "crypto/s2n_hmac.h"
#include "error/s2n_errno.h"
#include "stuffer/s2n_stuffer.h"
@@ -22,28 +23,43 @@
#include "utils/s2n_mem.h"
#include "utils/s2n_safety.h"
+#ifdef S2N_LIBCRYPTO_SUPPORTS_HKDF
+ #error #include <openssl/hkdf.h>
+#endif
+
#define MAX_DIGEST_SIZE 64 /* Current highest is SHA512 */
#define MAX_HKDF_ROUNDS 255
/* Reference: RFC 5869 */
-int s2n_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
+struct s2n_hkdf_impl {
+ int (*hkdf)(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
+ const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output);
+ int (*hkdf_extract)(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
+ const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key);
+ int (*hkdf_expand)(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *pseudo_rand_key,
+ const struct s2n_blob *info, struct s2n_blob *output);
+};
+
+static int s2n_custom_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key)
{
- uint8_t hmac_size;
+ uint8_t hmac_size = 0;
POSIX_GUARD(s2n_hmac_digest_size(alg, &hmac_size));
+ POSIX_ENSURE(hmac_size <= pseudo_rand_key->size, S2N_ERR_HKDF_OUTPUT_SIZE);
pseudo_rand_key->size = hmac_size;
+
POSIX_GUARD(s2n_hmac_init(hmac, alg, salt->data, salt->size));
POSIX_GUARD(s2n_hmac_update(hmac, key->data, key->size));
POSIX_GUARD(s2n_hmac_digest(hmac, pseudo_rand_key->data, pseudo_rand_key->size));
POSIX_GUARD(s2n_hmac_reset(hmac));
- return 0;
+ return S2N_SUCCESS;
}
-static int s2n_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *pseudo_rand_key,
- const struct s2n_blob *info, struct s2n_blob *output)
+static int s2n_custom_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg,
+ const struct s2n_blob *pseudo_rand_key, const struct s2n_blob *info, struct s2n_blob *output)
{
uint8_t prev[MAX_DIGEST_SIZE] = { 0 };
@@ -56,7 +72,8 @@ static int s2n_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg,
total_rounds++;
}
- S2N_ERROR_IF(total_rounds > MAX_HKDF_ROUNDS || total_rounds == 0, S2N_ERR_HKDF_OUTPUT_SIZE);
+ POSIX_ENSURE(total_rounds > 0, S2N_ERR_HKDF_OUTPUT_SIZE);
+ POSIX_ENSURE(total_rounds <= MAX_HKDF_ROUNDS, S2N_ERR_HKDF_OUTPUT_SIZE);
for (uint32_t curr_round = 1; curr_round <= total_rounds; curr_round++) {
uint32_t cat_len;
@@ -80,21 +97,167 @@ static int s2n_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg,
POSIX_GUARD(s2n_hmac_reset(hmac));
}
- return 0;
+ return S2N_SUCCESS;
+}
+
+static int s2n_custom_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
+ const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output)
+{
+ uint8_t prk_pad[MAX_DIGEST_SIZE] = { 0 };
+ struct s2n_blob pseudo_rand_key = { 0 };
+ POSIX_GUARD(s2n_blob_init(&pseudo_rand_key, prk_pad, sizeof(prk_pad)));
+
+ POSIX_GUARD(s2n_custom_hkdf_extract(hmac, alg, salt, key, &pseudo_rand_key));
+ POSIX_GUARD(s2n_custom_hkdf_expand(hmac, alg, &pseudo_rand_key, info, output));
+
+ return S2N_SUCCESS;
+}
+
+const struct s2n_hkdf_impl s2n_custom_hkdf_impl = {
+ .hkdf = &s2n_custom_hkdf,
+ .hkdf_extract = &s2n_custom_hkdf_extract,
+ .hkdf_expand = &s2n_custom_hkdf_expand,
+};
+
+#ifdef S2N_LIBCRYPTO_SUPPORTS_HKDF
+static int s2n_libcrypto_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
+ const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key)
+{
+ const EVP_MD *digest = NULL;
+ POSIX_GUARD_RESULT(s2n_hmac_md_from_alg(alg, &digest));
+
+ /* The out_len argument of HKDF_extract is set to the number of bytes written to out_key, and
+ * is not used to ensure that out_key is large enough to contain the PRK. Ensure that the PRK
+ * output will fit in the blob.
+ */
+ uint8_t hmac_size = 0;
+ POSIX_GUARD(s2n_hmac_digest_size(alg, &hmac_size));
+ POSIX_ENSURE(hmac_size <= pseudo_rand_key->size, S2N_ERR_HKDF_OUTPUT_SIZE);
+
+ size_t bytes_written = 0;
+ POSIX_GUARD_OSSL(HKDF_extract(pseudo_rand_key->data, &bytes_written, digest, key->data, key->size,
+ salt->data, salt->size),
+ S2N_ERR_HKDF);
+
+ /* HKDF_extract updates the out_len argument based on the digest size. Update the blob's size based on this. */
+ POSIX_ENSURE_LTE(bytes_written, pseudo_rand_key->size);
+ pseudo_rand_key->size = bytes_written;
+
+ return S2N_SUCCESS;
+}
+
+static int s2n_libcrypto_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg,
+ const struct s2n_blob *pseudo_rand_key, const struct s2n_blob *info, struct s2n_blob *output)
+{
+ POSIX_ENSURE(output->size > 0, S2N_ERR_HKDF_OUTPUT_SIZE);
+
+ const EVP_MD *digest = NULL;
+ POSIX_GUARD_RESULT(s2n_hmac_md_from_alg(alg, &digest));
+
+ POSIX_GUARD_OSSL(HKDF_expand(output->data, output->size, digest, pseudo_rand_key->data, pseudo_rand_key->size,
+ info->data, info->size),
+ S2N_ERR_HKDF);
+
+ return S2N_SUCCESS;
+}
+
+static int s2n_libcrypto_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
+ const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output)
+{
+ POSIX_ENSURE(output->size > 0, S2N_ERR_HKDF_OUTPUT_SIZE);
+
+ const EVP_MD *digest = NULL;
+ POSIX_GUARD_RESULT(s2n_hmac_md_from_alg(alg, &digest));
+
+ POSIX_GUARD_OSSL(HKDF(output->data, output->size, digest, key->data, key->size, salt->data, salt->size,
+ info->data, info->size),
+ S2N_ERR_HKDF);
+
+ return S2N_SUCCESS;
+}
+#else
+static int s2n_libcrypto_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
+ const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key)
+{
+ POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
+}
+
+static int s2n_libcrypto_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg,
+ const struct s2n_blob *pseudo_rand_key, const struct s2n_blob *info, struct s2n_blob *output)
+{
+ POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
+}
+
+static int s2n_libcrypto_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
+ const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output)
+{
+ POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
+}
+#endif /* S2N_LIBCRYPTO_SUPPORTS_HKDF */
+
+const struct s2n_hkdf_impl s2n_libcrypto_hkdf_impl = {
+ .hkdf = &s2n_libcrypto_hkdf,
+ .hkdf_extract = &s2n_libcrypto_hkdf_extract,
+ .hkdf_expand = &s2n_libcrypto_hkdf_expand,
+};
+
+static const struct s2n_hkdf_impl *s2n_get_hkdf_implementation()
+{
+ /* By default, s2n-tls uses a custom HKDF implementation. When operating in FIPS mode, the
+ * FIPS-validated libcrypto implementation is used instead, if an implementation is provided.
+ */
+ if (s2n_is_in_fips_mode() && s2n_libcrypto_supports_hkdf()) {
+ return &s2n_libcrypto_hkdf_impl;
+ }
+
+ return &s2n_custom_hkdf_impl;
+}
+
+int s2n_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
+ const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key)
+{
+ POSIX_ENSURE_REF(hmac);
+ POSIX_ENSURE_REF(salt);
+ POSIX_ENSURE_REF(key);
+ POSIX_ENSURE_REF(pseudo_rand_key);
+
+ const struct s2n_hkdf_impl *hkdf_implementation = s2n_get_hkdf_implementation();
+ POSIX_ENSURE_REF(hkdf_implementation);
+
+ POSIX_GUARD(hkdf_implementation->hkdf_extract(hmac, alg, salt, key, pseudo_rand_key));
+
+ return S2N_SUCCESS;
+}
+
+static int s2n_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *pseudo_rand_key,
+ const struct s2n_blob *info, struct s2n_blob *output)
+{
+ POSIX_ENSURE_REF(hmac);
+ POSIX_ENSURE_REF(pseudo_rand_key);
+ POSIX_ENSURE_REF(info);
+ POSIX_ENSURE_REF(output);
+
+ const struct s2n_hkdf_impl *hkdf_implementation = s2n_get_hkdf_implementation();
+ POSIX_ENSURE_REF(hkdf_implementation);
+
+ POSIX_GUARD(hkdf_implementation->hkdf_expand(hmac, alg, pseudo_rand_key, info, output));
+
+ return S2N_SUCCESS;
}
int s2n_hkdf_expand_label(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *secret, const struct s2n_blob *label,
const struct s2n_blob *context, struct s2n_blob *output)
{
+ POSIX_ENSURE_REF(label);
+ POSIX_ENSURE_REF(context);
+ POSIX_ENSURE_REF(output);
+
/* Per RFC8446: 7.1, a HKDF label is a 2 byte length field, and two 1...255 byte arrays with a one byte length field each. */
uint8_t hkdf_label_buf[2 + 256 + 256];
struct s2n_blob hkdf_label_blob = { 0 };
struct s2n_stuffer hkdf_label = { 0 };
- /* RFC8446 specifies that labels must be 12 characters or less, to avoid
- ** incurring two hash rounds.
- */
- POSIX_ENSURE_LTE(label->size, 12);
+ POSIX_ENSURE_LTE(label->size, S2N_MAX_HKDF_EXPAND_LABEL_LENGTH);
POSIX_GUARD(s2n_blob_init(&hkdf_label_blob, hkdf_label_buf, sizeof(hkdf_label_buf)));
POSIX_GUARD(s2n_stuffer_init(&hkdf_label, &hkdf_label_blob));
@@ -108,18 +271,31 @@ int s2n_hkdf_expand_label(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, c
hkdf_label_blob.size = s2n_stuffer_data_available(&hkdf_label);
POSIX_GUARD(s2n_hkdf_expand(hmac, alg, secret, &hkdf_label_blob, output));
- return 0;
+ return S2N_SUCCESS;
}
int s2n_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output)
{
- uint8_t prk_pad[MAX_DIGEST_SIZE];
- struct s2n_blob pseudo_rand_key = { 0 };
- POSIX_GUARD(s2n_blob_init(&pseudo_rand_key, prk_pad, sizeof(prk_pad)));
+ POSIX_ENSURE_REF(hmac);
+ POSIX_ENSURE_REF(salt);
+ POSIX_ENSURE_REF(key);
+ POSIX_ENSURE_REF(info);
+ POSIX_ENSURE_REF(output);
- POSIX_GUARD(s2n_hkdf_extract(hmac, alg, salt, key, &pseudo_rand_key));
- POSIX_GUARD(s2n_hkdf_expand(hmac, alg, &pseudo_rand_key, info, output));
+ const struct s2n_hkdf_impl *hkdf_implementation = s2n_get_hkdf_implementation();
+ POSIX_ENSURE_REF(hkdf_implementation);
- return 0;
+ POSIX_GUARD(hkdf_implementation->hkdf(hmac, alg, salt, key, info, output));
+
+ return S2N_SUCCESS;
+}
+
+bool s2n_libcrypto_supports_hkdf()
+{
+#ifdef S2N_LIBCRYPTO_SUPPORTS_HKDF
+ return true;
+#else
+ return false;
+#endif
}
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hkdf.h b/contrib/restricted/aws/s2n/crypto/s2n_hkdf.h
index cb9424e7d7..8dc53636e7 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_hkdf.h
+++ b/contrib/restricted/aws/s2n/crypto/s2n_hkdf.h
@@ -20,6 +20,16 @@
#include "crypto/s2n_hmac.h"
#include "utils/s2n_blob.h"
+/*
+ * Label structure is `opaque label<7..255> = "tls13 " + Label` per RFC8446.
+ * So, we have 255-sizeof("tls13 ") = 249, the maximum label length.
+ *
+ * Note that all labels defined by RFC 8446 are <12 characters, which
+ * avoids an extra hash iteration. However, the exporter functionality
+ * (s2n_connection_tls_exporter) allows for longer labels.
+ */
+#define S2N_MAX_HKDF_EXPAND_LABEL_LENGTH 249
+
int s2n_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output);
@@ -28,3 +38,5 @@ int s2n_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const
int s2n_hkdf_expand_label(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *secret, const struct s2n_blob *label,
const struct s2n_blob *context, struct s2n_blob *output);
+
+bool s2n_libcrypto_supports_hkdf();
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hmac.c b/contrib/restricted/aws/s2n/crypto/s2n_hmac.c
index d2bb4e6684..20be85ffee 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_hmac.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_hmac.c
@@ -396,3 +396,34 @@ int s2n_hmac_restore_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s
POSIX_POSTCONDITION(s2n_hmac_state_validate(hmac));
return S2N_SUCCESS;
}
+
+S2N_RESULT s2n_hmac_md_from_alg(s2n_hmac_algorithm alg, const EVP_MD **md)
+{
+ RESULT_ENSURE_REF(md);
+
+ switch (alg) {
+ case S2N_HMAC_SSLv3_MD5:
+ case S2N_HMAC_MD5:
+ *md = EVP_md5();
+ break;
+ case S2N_HMAC_SSLv3_SHA1:
+ case S2N_HMAC_SHA1:
+ *md = EVP_sha1();
+ break;
+ case S2N_HMAC_SHA224:
+ *md = EVP_sha224();
+ break;
+ case S2N_HMAC_SHA256:
+ *md = EVP_sha256();
+ break;
+ case S2N_HMAC_SHA384:
+ *md = EVP_sha384();
+ break;
+ case S2N_HMAC_SHA512:
+ *md = EVP_sha512();
+ break;
+ default:
+ RESULT_BAIL(S2N_ERR_P_HASH_INVALID_ALGORITHM);
+ }
+ return S2N_RESULT_OK;
+}
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hmac.h b/contrib/restricted/aws/s2n/crypto/s2n_hmac.h
index fe532ca5c8..81b96c06ea 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_hmac.h
+++ b/contrib/restricted/aws/s2n/crypto/s2n_hmac.h
@@ -77,3 +77,5 @@ int s2n_hmac_reset(struct s2n_hmac_state *state);
int s2n_hmac_copy(struct s2n_hmac_state *to, struct s2n_hmac_state *from);
int s2n_hmac_save_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac);
int s2n_hmac_restore_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac);
+
+S2N_RESULT s2n_hmac_md_from_alg(s2n_hmac_algorithm alg, const EVP_MD **md);
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_ktls_crypto.h b/contrib/restricted/aws/s2n/crypto/s2n_ktls_crypto.h
new file mode 100644
index 0000000000..b665e913fe
--- /dev/null
+++ b/contrib/restricted/aws/s2n/crypto/s2n_ktls_crypto.h
@@ -0,0 +1,63 @@
+/*
+ * 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 "utils/s2n_blob.h"
+
+/* clang-format off */
+#if defined(S2N_KTLS_SUPPORTED)
+ #include <linux/tls.h>
+
+ typedef struct tls12_crypto_info_aes_gcm_128 s2n_ktls_crypto_info_tls12_aes_gcm_128;
+ typedef struct tls12_crypto_info_aes_gcm_256 s2n_ktls_crypto_info_tls12_aes_gcm_256;
+#else
+ #define TLS_1_2_VERSION 0
+
+ #define TLS_CIPHER_AES_GCM_128 0
+ typedef struct s2n_ktls_crypto_info_stub s2n_ktls_crypto_info_tls12_aes_gcm_128;
+ #define TLS_CIPHER_AES_GCM_256 0
+ typedef struct s2n_ktls_crypto_info_stub s2n_ktls_crypto_info_tls12_aes_gcm_256;
+#endif
+/* clang-format on */
+
+/* To avoid compile-time errors, this must contain every field that we reference
+ * from any crypto_info. However, it is only a placeholder-- it should never
+ * actually be used.
+ */
+struct s2n_ktls_crypto_info_stub {
+ struct {
+ uint8_t version;
+ uint8_t cipher_type;
+ } info;
+ uint8_t iv[1];
+ uint8_t key[1];
+ uint8_t salt[1];
+ uint8_t rec_seq[1];
+};
+
+struct s2n_ktls_crypto_info {
+ struct s2n_blob value;
+ union {
+ s2n_ktls_crypto_info_tls12_aes_gcm_128 aes_gcm_128;
+ s2n_ktls_crypto_info_tls12_aes_gcm_256 aes_gcm_256;
+ } ciphers;
+};
+
+struct s2n_ktls_crypto_info_inputs {
+ struct s2n_blob iv;
+ struct s2n_blob key;
+ struct s2n_blob seq;
+};
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c
index d92da10a08..9e40500da6 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.c
@@ -118,7 +118,7 @@ bool s2n_libcrypto_is_awslc()
#endif
}
-static uint64_t s2n_libcrypto_awslc_api_version(void)
+uint64_t s2n_libcrypto_awslc_api_version(void)
{
#if defined(OPENSSL_IS_AWSLC)
return AWSLC_API_VERSION;
@@ -191,3 +191,12 @@ unsigned long s2n_get_openssl_version(void)
{
return OPENSSL_VERSION_NUMBER;
}
+
+bool s2n_libcrypto_supports_flag_no_check_time()
+{
+#ifdef S2N_LIBCRYPTO_SUPPORTS_FLAG_NO_CHECK_TIME
+ return true;
+#else
+ return false;
+#endif
+}
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h
index 34d9ef2aac..9e7aff882b 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h
+++ b/contrib/restricted/aws/s2n/crypto/s2n_libcrypto.h
@@ -18,3 +18,5 @@
#include "utils/s2n_result.h"
S2N_RESULT s2n_libcrypto_validate_runtime(void);
+
+bool s2n_libcrypto_supports_flag_no_check_time();
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.c b/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.c
index f0909fd897..bc659e28a8 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.c
@@ -17,10 +17,25 @@
#include "api/s2n.h"
-int s2n_openssl_x509_stack_pop_free(STACK_OF(X509) **cert_chain)
+S2N_CLEANUP_RESULT s2n_openssl_x509_stack_pop_free(STACK_OF(X509) **cert_chain)
{
- if (*cert_chain != NULL) {
- sk_X509_pop_free(*cert_chain, X509_free);
- }
- return S2N_SUCCESS;
+ RESULT_ENSURE_REF(*cert_chain);
+ sk_X509_pop_free(*cert_chain, X509_free);
+ *cert_chain = NULL;
+ return S2N_RESULT_OK;
+}
+
+S2N_CLEANUP_RESULT s2n_openssl_asn1_time_free_pointer(ASN1_GENERALIZEDTIME **time_ptr)
+{
+ /* The ANS1_*TIME structs are just typedef wrappers around ASN1_STRING
+ *
+ * The ASN1_TIME, ASN1_UTCTIME and ASN1_GENERALIZEDTIME structures are
+ * represented as an ASN1_STRING internally and can be freed up using
+ * ASN1_STRING_free().
+ * https://www.openssl.org/docs/man1.1.1/man3/ASN1_TIME_to_tm.html
+ */
+ RESULT_ENSURE_REF(*time_ptr);
+ ASN1_STRING_free((ASN1_STRING *) *time_ptr);
+ *time_ptr = NULL;
+ return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.h b/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.h
index 1eb2069054..aac6d87315 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.h
+++ b/contrib/restricted/aws/s2n/crypto/s2n_openssl_x509.h
@@ -15,6 +15,7 @@
#pragma once
+#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <stdint.h>
@@ -22,4 +23,6 @@
DEFINE_POINTER_CLEANUP_FUNC(X509 *, X509_free);
-int s2n_openssl_x509_stack_pop_free(STACK_OF(X509) **cert_chain);
+S2N_CLEANUP_RESULT s2n_openssl_x509_stack_pop_free(STACK_OF(X509) **cert_chain);
+
+S2N_CLEANUP_RESULT s2n_openssl_asn1_time_free_pointer(ASN1_GENERALIZEDTIME **time);
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_rsa.c b/contrib/restricted/aws/s2n/crypto/s2n_rsa.c
index 9fc1d4b5ca..96ce8f4140 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_rsa.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_rsa.c
@@ -36,13 +36,12 @@ RSA *s2n_unsafe_rsa_get_non_const(const struct s2n_rsa_key *rsa_key)
{
PTR_ENSURE_REF(rsa_key);
- /* pragma gcc diagnostic was added in gcc 4.6 */
-#if defined(__clang__) || S2N_GCC_VERSION_AT_LEAST(4, 6, 0)
+#ifdef S2N_DIAGNOSTICS_PUSH_SUPPORTED
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
#endif
RSA *out_rsa_key = (RSA *) rsa_key->rsa;
-#if defined(__clang__) || S2N_GCC_VERSION_AT_LEAST(4, 6, 0)
+#ifdef S2N_DIAGNOSTICS_POP_SUPPORTED
#pragma GCC diagnostic pop
#endif
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c b/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c
index 4c4bc14914..30be7e6a43 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_stream_cipher_rc4.c
@@ -21,60 +21,28 @@
#include "utils/s2n_blob.h"
#include "utils/s2n_safety.h"
-#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
- #error #include "openssl/provider.h"
-DEFINE_POINTER_CLEANUP_FUNC(OSSL_LIB_CTX *, OSSL_LIB_CTX_free);
-#endif
-
-static EVP_CIPHER *s2n_rc4_cipher = NULL;
-
-S2N_RESULT s2n_rc4_init()
-{
- /* In Openssl-3.0, RC4 is only available from the "legacy" provider,
- * which is not loaded in the default library context.
- */
-#if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_RC4) && S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
- DEFER_CLEANUP(OSSL_LIB_CTX *lib_ctx = OSSL_LIB_CTX_new(), OSSL_LIB_CTX_free_pointer);
- RESULT_ENSURE_REF(lib_ctx);
- RESULT_ENSURE_REF(OSSL_PROVIDER_load(lib_ctx, "legacy"));
- s2n_rc4_cipher = EVP_CIPHER_fetch(lib_ctx, "rc4", "provider=legacy");
- RESULT_ENSURE_REF(s2n_rc4_cipher);
-#endif
- return S2N_RESULT_OK;
-}
-
-S2N_RESULT s2n_rc4_cleanup()
+static const EVP_CIPHER *s2n_evp_rc4()
{
-#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
- EVP_CIPHER_free(s2n_rc4_cipher);
+#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_RC4
+ return EVP_rc4();
+#else
+ return NULL;
#endif
- return S2N_RESULT_OK;
}
-static S2N_RESULT s2n_get_rc4_cipher(const EVP_CIPHER **cipher)
+static uint8_t s2n_stream_cipher_rc4_available()
{
- RESULT_ENSURE_REF(cipher);
- *cipher = NULL;
if (s2n_is_in_fips_mode()) {
- *cipher = NULL;
- } else if (s2n_rc4_cipher) {
- *cipher = s2n_rc4_cipher;
-#if S2N_LIBCRYPTO_SUPPORTS_EVP_RC4
- } else {
- *cipher = EVP_rc4();
-#endif
+ return 0;
}
- RESULT_ENSURE(*cipher, S2N_ERR_UNIMPLEMENTED);
- return S2N_RESULT_OK;
-}
-
-static uint8_t s2n_stream_cipher_rc4_available()
-{
- const EVP_CIPHER *cipher = NULL;
- if (s2n_result_is_ok(s2n_get_rc4_cipher(&cipher)) && cipher) {
- return 1;
+ /* RC4 MIGHT be available in Openssl-3.0, depending on whether or not the
+ * "legacy" provider is loaded. However, for simplicity, assume that RC4
+ * is unavailable.
+ */
+ if (S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)) {
+ return 0;
}
- return 0;
+ return (s2n_evp_rc4() ? 1 : 0);
}
static int s2n_stream_cipher_rc4_encrypt(struct s2n_session_key *key, struct s2n_blob *in, struct s2n_blob *out)
@@ -106,11 +74,7 @@ static int s2n_stream_cipher_rc4_decrypt(struct s2n_session_key *key, struct s2n
static int s2n_stream_cipher_rc4_set_encryption_key(struct s2n_session_key *key, struct s2n_blob *in)
{
POSIX_ENSURE_EQ(in->size, 16);
-
- const EVP_CIPHER *evp_rc4 = NULL;
- POSIX_GUARD_RESULT(s2n_get_rc4_cipher(&evp_rc4));
-
- POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, evp_rc4, NULL, in->data, NULL), S2N_ERR_KEY_INIT);
+ POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, s2n_evp_rc4(), NULL, in->data, NULL), S2N_ERR_KEY_INIT);
return S2N_SUCCESS;
}
@@ -118,11 +82,7 @@ static int s2n_stream_cipher_rc4_set_encryption_key(struct s2n_session_key *key,
static int s2n_stream_cipher_rc4_set_decryption_key(struct s2n_session_key *key, struct s2n_blob *in)
{
POSIX_ENSURE_EQ(in->size, 16);
-
- const EVP_CIPHER *evp_rc4 = NULL;
- POSIX_GUARD_RESULT(s2n_get_rc4_cipher(&evp_rc4));
-
- POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, evp_rc4, NULL, in->data, NULL), S2N_ERR_KEY_INIT);
+ POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, s2n_evp_rc4(), NULL, in->data, NULL), S2N_ERR_KEY_INIT);
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c
index 3b5c284080..91d7aae5e0 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c
@@ -37,7 +37,7 @@
* [x] server_handshake_traffic_secret
* [x] client_application_traffic_secret_0
* [x] server_application_traffic_secret_0
- * [ ] exporter_master_secret
+ * [x] exporter_master_secret
* [x] resumption_master_secret
*
* The TLS 1.3 key generation can be divided into 3 phases
@@ -80,6 +80,11 @@ S2N_BLOB_LABEL(s2n_tls13_label_traffic_secret_key, "key")
S2N_BLOB_LABEL(s2n_tls13_label_traffic_secret_iv, "iv")
/*
+ * TLS 1.3 Exporter label
+ */
+S2N_BLOB_LABEL(s2n_tls13_label_exporter, "exporter")
+
+/*
* TLS 1.3 Finished label
*/
S2N_BLOB_LABEL(s2n_tls13_label_finished, "finished")
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h
index 5bd7455dc2..ac96ceb51f 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h
+++ b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h
@@ -70,6 +70,8 @@ extern const struct s2n_blob s2n_tls13_label_resumption_master_secret;
extern const struct s2n_blob s2n_tls13_label_finished;
+extern const struct s2n_blob s2n_tls13_label_exporter;
+
/* Traffic secret labels */
extern const struct s2n_blob s2n_tls13_label_traffic_secret_key;
diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.c b/contrib/restricted/aws/s2n/error/s2n_errno.c
index 8730c39011..fbe52416b5 100644
--- a/contrib/restricted/aws/s2n/error/s2n_errno.c
+++ b/contrib/restricted/aws/s2n/error/s2n_errno.c
@@ -30,7 +30,7 @@
#endif
__thread int s2n_errno;
-__thread const char *s2n_debug_str;
+__thread struct s2n_debug_info _s2n_debug_info = { .debug_str = "", .source = "" };
/**
* Returns the address of the thread-local `s2n_errno` variable
@@ -96,10 +96,12 @@ static const char *no_such_error = "Internal s2n error";
ERR_ENTRY(S2N_ERR_RECORD_LIMIT, "TLS record limit reached") \
ERR_ENTRY(S2N_ERR_CERT_UNTRUSTED, "Certificate is untrusted") \
ERR_ENTRY(S2N_ERR_CERT_REVOKED, "Certificate has been revoked by the CA") \
+ ERR_ENTRY(S2N_ERR_CERT_NOT_YET_VALID, "Certificate is not yet valid") \
ERR_ENTRY(S2N_ERR_CERT_EXPIRED, "Certificate has expired") \
ERR_ENTRY(S2N_ERR_CERT_TYPE_UNSUPPORTED, "Certificate Type is unsupported") \
ERR_ENTRY(S2N_ERR_CERT_INVALID, "Certificate is invalid") \
ERR_ENTRY(S2N_ERR_CERT_MAX_CHAIN_DEPTH_EXCEEDED, "The maximum certificate chain depth has been exceeded") \
+ ERR_ENTRY(S2N_ERR_CERT_REJECTED, "Certificate failed custom application validation") \
ERR_ENTRY(S2N_ERR_CRL_LOOKUP_FAILED, "No CRL could be found for the corresponding certificate") \
ERR_ENTRY(S2N_ERR_CRL_SIGNATURE, "The signature of the CRL is invalid") \
ERR_ENTRY(S2N_ERR_CRL_ISSUER, "Unable to get the CRL issuer certificate") \
@@ -138,6 +140,7 @@ static const char *no_such_error = "Internal s2n error";
ERR_ENTRY(S2N_ERR_HASH_INVALID_ALGORITHM, "invalid hash algorithm") \
ERR_ENTRY(S2N_ERR_PRF_INVALID_ALGORITHM, "invalid prf hash algorithm") \
ERR_ENTRY(S2N_ERR_PRF_INVALID_SEED, "invalid prf seeds provided") \
+ ERR_ENTRY(S2N_ERR_PRF_DERIVE, "error deriving a secret from the PRF") \
ERR_ENTRY(S2N_ERR_P_HASH_INVALID_ALGORITHM, "invalid p_hash algorithm") \
ERR_ENTRY(S2N_ERR_P_HASH_INIT_FAILED, "error initializing p_hash") \
ERR_ENTRY(S2N_ERR_P_HASH_UPDATE_FAILED, "error updating p_hash") \
@@ -145,6 +148,7 @@ static const char *no_such_error = "Internal s2n error";
ERR_ENTRY(S2N_ERR_P_HASH_WIPE_FAILED, "error wiping p_hash") \
ERR_ENTRY(S2N_ERR_HMAC_INVALID_ALGORITHM, "invalid HMAC algorithm") \
ERR_ENTRY(S2N_ERR_HKDF_OUTPUT_SIZE, "invalid HKDF output size") \
+ ERR_ENTRY(S2N_ERR_HKDF, "error generating HKDF output") \
ERR_ENTRY(S2N_ERR_ALERT_PRESENT, "TLS alert is already pending") \
ERR_ENTRY(S2N_ERR_HANDSHAKE_STATE, "Invalid handshake state encountered") \
ERR_ENTRY(S2N_ERR_SHUTDOWN_PAUSED, "s2n_shutdown() called while paused") \
@@ -212,6 +216,7 @@ static const char *no_such_error = "Internal s2n error";
ERR_ENTRY(S2N_ERR_SEND_SIZE, "Retried s2n_send() size is invalid") \
ERR_ENTRY(S2N_ERR_CORK_SET_ON_UNMANAGED, "Attempt to set connection cork management on unmanaged IO") \
ERR_ENTRY(S2N_ERR_UNRECOGNIZED_EXTENSION, "TLS extension not recognized") \
+ ERR_ENTRY(S2N_ERR_EXTENSION_NOT_RECEIVED, "The TLS extension was not received") \
ERR_ENTRY(S2N_ERR_INVALID_SCT_LIST, "SCT list is invalid") \
ERR_ENTRY(S2N_ERR_INVALID_OCSP_RESPONSE, "OCSP response is invalid") \
ERR_ENTRY(S2N_ERR_UPDATING_EXTENSION, "Updating extension data failed") \
@@ -288,6 +293,15 @@ static const char *no_such_error = "Internal s2n error";
ERR_ENTRY(S2N_ERR_INTERNAL_LIBCRYPTO_ERROR, "An internal error has occurred in the libcrypto API") \
ERR_ENTRY(S2N_ERR_NO_RENEGOTIATION, "Only secure, server-initiated renegotiation is supported") \
ERR_ENTRY(S2N_ERR_APP_DATA_BLOCKED, "Blocked on application data during handshake") \
+ ERR_ENTRY(S2N_ERR_KTLS_MANAGED_IO, "kTLS cannot be enabled while custom I/O is configured for the connection") \
+ ERR_ENTRY(S2N_ERR_HANDSHAKE_NOT_COMPLETE, "Operation is only allowed after the handshake is complete") \
+ ERR_ENTRY(S2N_ERR_KTLS_UNSUPPORTED_PLATFORM, "kTLS is unsupported on this platform") \
+ ERR_ENTRY(S2N_ERR_KTLS_UNSUPPORTED_CONN, "kTLS is unsupported for this connection") \
+ ERR_ENTRY(S2N_ERR_KTLS_ENABLE, "An error occurred when attempting to enable kTLS on socket. Ensure the 'tls' kernel module is enabled.") \
+ ERR_ENTRY(S2N_ERR_KTLS_BAD_CMSG, "Error handling cmsghdr.") \
+ ERR_ENTRY(S2N_ERR_ATOMIC, "Atomic operations in this environment would require locking") \
+ ERR_ENTRY(S2N_ERR_TEST_ASSERTION, "Test assertion failed") \
+ ERR_ENTRY(S2N_ERR_KTLS_RENEG, "kTLS does not support secure renegotiation") \
/* clang-format on */
#define ERR_STR_CASE(ERR, str) \
@@ -366,7 +380,17 @@ const char *s2n_strerror_debug(int error, const char *lang)
return s2n_strerror(error, lang);
}
- return s2n_debug_str;
+ return _s2n_debug_info.debug_str;
+}
+
+const char *s2n_strerror_source(int error)
+{
+ /* No error, just return the no error string */
+ if (error == S2N_ERR_OK) {
+ return s2n_strerror(error, "EN");
+ }
+
+ return _s2n_debug_info.source;
}
int s2n_error_get_type(int error)
@@ -388,6 +412,12 @@ int s2n_stack_traces_enabled_set(bool newval)
return S2N_SUCCESS;
}
+void s2n_debug_info_reset(void)
+{
+ _s2n_debug_info.debug_str = "";
+ _s2n_debug_info.source = "";
+}
+
#ifdef S2N_STACKTRACE
#define MAX_BACKTRACE_DEPTH 20
diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.h b/contrib/restricted/aws/s2n/error/s2n_errno.h
index 6955266945..1ff5070717 100644
--- a/contrib/restricted/aws/s2n/error/s2n_errno.h
+++ b/contrib/restricted/aws/s2n/error/s2n_errno.h
@@ -17,6 +17,7 @@
#include <stdbool.h>
#include <stdio.h>
+#include <string.h>
#include "api/s2n.h"
#include "utils/s2n_ensure.h"
@@ -109,10 +110,12 @@ typedef enum {
S2N_ERR_RECORD_LIMIT,
S2N_ERR_CERT_UNTRUSTED,
S2N_ERR_CERT_REVOKED,
+ S2N_ERR_CERT_NOT_YET_VALID,
S2N_ERR_CERT_EXPIRED,
S2N_ERR_CERT_TYPE_UNSUPPORTED,
S2N_ERR_CERT_INVALID,
S2N_ERR_CERT_MAX_CHAIN_DEPTH_EXCEEDED,
+ S2N_ERR_CERT_REJECTED,
S2N_ERR_CRL_LOOKUP_FAILED,
S2N_ERR_CRL_SIGNATURE,
S2N_ERR_CRL_ISSUER,
@@ -165,6 +168,7 @@ typedef enum {
S2N_ERR_HASH_INVALID_ALGORITHM,
S2N_ERR_PRF_INVALID_ALGORITHM,
S2N_ERR_PRF_INVALID_SEED,
+ S2N_ERR_PRF_DERIVE,
S2N_ERR_P_HASH_INVALID_ALGORITHM,
S2N_ERR_P_HASH_INIT_FAILED,
S2N_ERR_P_HASH_UPDATE_FAILED,
@@ -172,6 +176,7 @@ typedef enum {
S2N_ERR_P_HASH_WIPE_FAILED,
S2N_ERR_HMAC_INVALID_ALGORITHM,
S2N_ERR_HKDF_OUTPUT_SIZE,
+ S2N_ERR_HKDF,
S2N_ERR_ALERT_PRESENT,
S2N_ERR_HANDSHAKE_STATE,
S2N_ERR_SHUTDOWN_PAUSED,
@@ -226,6 +231,7 @@ typedef enum {
S2N_ERR_LIBCRYPTO_VERSION_NUMBER_MISMATCH,
S2N_ERR_LIBCRYPTO_VERSION_NAME_MISMATCH,
S2N_ERR_OSSL_PROVIDER,
+ S2N_ERR_TEST_ASSERTION,
S2N_ERR_T_INTERNAL_END,
/* S2N_ERR_T_USAGE */
@@ -253,6 +259,7 @@ typedef enum {
S2N_ERR_SEND_SIZE,
S2N_ERR_CORK_SET_ON_UNMANAGED,
S2N_ERR_UNRECOGNIZED_EXTENSION,
+ S2N_ERR_EXTENSION_NOT_RECEIVED,
S2N_ERR_INVALID_SCT_LIST,
S2N_ERR_INVALID_OCSP_RESPONSE,
S2N_ERR_UPDATING_EXTENSION,
@@ -304,22 +311,48 @@ typedef enum {
S2N_ERR_SECRET_SCHEDULE_STATE,
S2N_ERR_CERT_OWNERSHIP,
S2N_ERR_INTERNAL_LIBCRYPTO_ERROR,
+ S2N_ERR_HANDSHAKE_NOT_COMPLETE,
+ S2N_ERR_KTLS_MANAGED_IO,
+ S2N_ERR_KTLS_UNSUPPORTED_PLATFORM,
+ S2N_ERR_KTLS_UNSUPPORTED_CONN,
+ S2N_ERR_KTLS_ENABLE,
+ S2N_ERR_KTLS_BAD_CMSG,
+ S2N_ERR_KTLS_RENEG,
+ S2N_ERR_ATOMIC,
S2N_ERR_T_USAGE_END,
} s2n_error;
#define S2N_DEBUG_STR_LEN 128
-extern __thread const char *s2n_debug_str;
+
+struct s2n_debug_info {
+ const char *debug_str;
+ const char *source;
+};
+
+extern __thread struct s2n_debug_info _s2n_debug_info;
#define TO_STRING(s) #s
#define STRING_(s) TO_STRING(s)
#define STRING__LINE__ STRING_(__LINE__)
-#define _S2N_DEBUG_LINE "Error encountered in " __FILE__ ":" STRING__LINE__
-#define _S2N_ERROR(x) \
- do { \
- s2n_debug_str = _S2N_DEBUG_LINE; \
- s2n_errno = (x); \
- s2n_calculate_stacktrace(); \
+/* gets the basename of a file path */
+/* _S2N_EXTRACT_BASENAME("Error encountered in /path/to/my/file.c") -> "file.c" */
+#if !(defined(CBMC) || defined(__TIMING_CONTRACTS__))
+ #define _S2N_RSPLIT(subject, c) (strrchr((subject), c) ? strrchr((subject), c) + 1 : (subject))
+ #define _S2N_EXTRACT_BASENAME(path) _S2N_RSPLIT((path) + strlen(_S2N_DEBUG_LINE_PREFIX), '/')
+#else
+ #define _S2N_EXTRACT_BASENAME(path) path
+#endif
+
+#define _S2N_DEBUG_LINE_PREFIX "Error encountered in "
+#define _S2N_DEBUG_LINE _S2N_DEBUG_LINE_PREFIX __FILE__ ":" STRING__LINE__
+
+#define _S2N_ERROR(x) \
+ do { \
+ _s2n_debug_info.debug_str = _S2N_DEBUG_LINE; \
+ _s2n_debug_info.source = _S2N_EXTRACT_BASENAME(_s2n_debug_info.debug_str); \
+ s2n_errno = (x); \
+ s2n_calculate_stacktrace(); \
} while (0)
#define S2N_ERROR_PRESERVE_ERRNO() \
do { \
@@ -362,3 +395,4 @@ int s2n_calculate_stacktrace(void);
int s2n_print_stacktrace(FILE *fptr);
int s2n_free_stacktrace(void);
int s2n_get_stacktrace(struct s2n_stacktrace *trace);
+void s2n_debug_info_reset(void);
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 06c86ccad2..c04fabeee9 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
@@ -1,13 +1,14 @@
#include <stddef.h>
#include <stdint.h>
-#include "kyber512r3_params.h"
-#include "kyber512r3_symmetric.h"
+
#include "kyber512r3_indcpa.h"
#include "kyber512r3_indcpa_avx2.h"
+#include "kyber512r3_params.h"
+#include "kyber512r3_symmetric.h"
+#include "pq-crypto/s2n_pq.h"
+#include "pq-crypto/s2n_pq_random.h"
#include "tls/s2n_kem.h"
#include "utils/s2n_safety.h"
-#include "pq-crypto/s2n_pq_random.h"
-#include "pq-crypto/s2n_pq.h"
S2N_ENSURE_PORTABLE_OPTIMIZATIONS
@@ -24,24 +25,24 @@ S2N_ENSURE_PORTABLE_OPTIMIZATIONS
*
* Returns 0 (success)
**************************************************/
-int s2n_kyber_512_r3_crypto_kem_keypair(uint8_t *pk, uint8_t *sk)
+int s2n_kyber_512_r3_crypto_kem_keypair(const struct s2n_kem *kem, uint8_t *pk, uint8_t *sk)
{
POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
#if defined(S2N_KYBER512R3_AVX2_BMI2)
if (s2n_kyber512r3_is_avx2_bmi2_enabled()) {
POSIX_GUARD(indcpa_keypair_avx2(pk, sk));
- }else
+ } else
#endif
{
POSIX_GUARD(indcpa_keypair(pk, sk));
}
-
- for(size_t i = 0; i < S2N_KYBER_512_R3_INDCPA_PUBLICKEYBYTES; i++) {
+
+ for (size_t i = 0; i < S2N_KYBER_512_R3_INDCPA_PUBLICKEYBYTES; i++) {
sk[i + S2N_KYBER_512_R3_INDCPA_SECRETKEYBYTES] = pk[i];
}
- sha3_256(sk+S2N_KYBER_512_R3_SECRET_KEY_BYTES-2*S2N_KYBER_512_R3_SYMBYTES, pk, S2N_KYBER_512_R3_PUBLIC_KEY_BYTES);
+ sha3_256(sk + S2N_KYBER_512_R3_SECRET_KEY_BYTES - 2 * S2N_KYBER_512_R3_SYMBYTES, pk, S2N_KYBER_512_R3_PUBLIC_KEY_BYTES);
/* Value z for pseudo-random output on reject */
- POSIX_GUARD_RESULT(s2n_get_random_bytes(sk+S2N_KYBER_512_R3_SECRET_KEY_BYTES-S2N_KYBER_512_R3_SYMBYTES, S2N_KYBER_512_R3_SYMBYTES));
+ POSIX_GUARD_RESULT(s2n_get_random_bytes(sk + S2N_KYBER_512_R3_SECRET_KEY_BYTES - S2N_KYBER_512_R3_SYMBYTES, S2N_KYBER_512_R3_SYMBYTES));
return S2N_SUCCESS;
}
@@ -60,35 +61,36 @@ int s2n_kyber_512_r3_crypto_kem_keypair(uint8_t *pk, uint8_t *sk)
*
* Returns 0 (success)
**************************************************/
-int s2n_kyber_512_r3_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk)
+int s2n_kyber_512_r3_crypto_kem_enc(const struct s2n_kem *kem, uint8_t *ct, uint8_t *ss,
+ const uint8_t *pk)
{
POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
- uint8_t buf[2*S2N_KYBER_512_R3_SYMBYTES];
+ uint8_t buf[2 * S2N_KYBER_512_R3_SYMBYTES];
/* Will contain key, coins */
- uint8_t kr[2*S2N_KYBER_512_R3_SYMBYTES];
+ uint8_t kr[2 * S2N_KYBER_512_R3_SYMBYTES];
POSIX_GUARD_RESULT(s2n_get_random_bytes(buf, S2N_KYBER_512_R3_SYMBYTES));
/* Don't release system RNG output */
sha3_256(buf, buf, S2N_KYBER_512_R3_SYMBYTES);
/* Multitarget countermeasure for coins + contributory KEM */
- sha3_256(buf+S2N_KYBER_512_R3_SYMBYTES, pk, S2N_KYBER_512_R3_PUBLIC_KEY_BYTES);
- sha3_512(kr, buf, 2*S2N_KYBER_512_R3_SYMBYTES);
+ sha3_256(buf + S2N_KYBER_512_R3_SYMBYTES, pk, S2N_KYBER_512_R3_PUBLIC_KEY_BYTES);
+ sha3_512(kr, buf, 2 * S2N_KYBER_512_R3_SYMBYTES);
/* coins are in kr+S2N_KYBER_512_R3_SYMBYTES */
#if defined(S2N_KYBER512R3_AVX2_BMI2)
if (s2n_kyber512r3_is_avx2_bmi2_enabled()) {
- indcpa_enc_avx2(ct, buf, pk, kr+S2N_KYBER_512_R3_SYMBYTES);
- }else
+ indcpa_enc_avx2(ct, buf, pk, kr + S2N_KYBER_512_R3_SYMBYTES);
+ } else
#endif
{
- indcpa_enc(ct, buf, pk, kr+S2N_KYBER_512_R3_SYMBYTES);
+ indcpa_enc(ct, buf, pk, kr + S2N_KYBER_512_R3_SYMBYTES);
}
-
+
/* overwrite coins in kr with H(c) */
- sha3_256(kr+S2N_KYBER_512_R3_SYMBYTES, ct, S2N_KYBER_512_R3_CIPHERTEXT_BYTES);
+ sha3_256(kr + S2N_KYBER_512_R3_SYMBYTES, ct, S2N_KYBER_512_R3_CIPHERTEXT_BYTES);
/* hash concatenation of pre-k and H(c) to k */
- shake256(ss, S2N_KYBER_512_R3_SSBYTES, kr, 2*S2N_KYBER_512_R3_SYMBYTES);
+ shake256(ss, S2N_KYBER_512_R3_SSBYTES, kr, 2 * S2N_KYBER_512_R3_SYMBYTES);
return S2N_SUCCESS;
}
@@ -109,52 +111,53 @@ int s2n_kyber_512_r3_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk)
*
* On failure, ss will contain a pseudo-random value.
**************************************************/
-int s2n_kyber_512_r3_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk)
+int s2n_kyber_512_r3_crypto_kem_dec(const struct s2n_kem *kem, uint8_t *ss, const uint8_t *ct,
+ const uint8_t *sk)
{
POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
- uint8_t buf[2*S2N_KYBER_512_R3_SYMBYTES];
+ uint8_t buf[2 * S2N_KYBER_512_R3_SYMBYTES];
/* Will contain key, coins */
- uint8_t kr[2*S2N_KYBER_512_R3_SYMBYTES];
+ uint8_t kr[2 * S2N_KYBER_512_R3_SYMBYTES];
uint8_t cmp[S2N_KYBER_512_R3_CIPHERTEXT_BYTES];
- const uint8_t *pk = sk+S2N_KYBER_512_R3_INDCPA_SECRETKEYBYTES;
+ const uint8_t *pk = sk + S2N_KYBER_512_R3_INDCPA_SECRETKEYBYTES;
#if defined(S2N_KYBER512R3_AVX2_BMI2)
if (s2n_kyber512r3_is_avx2_bmi2_enabled()) {
indcpa_dec_avx2(buf, ct, sk);
- }else
+ } else
#endif
{
indcpa_dec(buf, ct, sk);
}
-
+
/* Multitarget countermeasure for coins + contributory KEM */
- for(size_t i = 0; i < S2N_KYBER_512_R3_SYMBYTES; i++) {
+ for (size_t i = 0; i < S2N_KYBER_512_R3_SYMBYTES; i++) {
buf[S2N_KYBER_512_R3_SYMBYTES + i] = sk[S2N_KYBER_512_R3_SECRET_KEY_BYTES - 2 * S2N_KYBER_512_R3_SYMBYTES + i];
}
- sha3_512(kr, buf, 2*S2N_KYBER_512_R3_SYMBYTES);
+ sha3_512(kr, buf, 2 * S2N_KYBER_512_R3_SYMBYTES);
/* coins are in kr+S2N_KYBER_512_R3_SYMBYTES */
#if defined(S2N_KYBER512R3_AVX2_BMI2)
if (s2n_kyber512r3_is_avx2_bmi2_enabled()) {
- indcpa_enc_avx2(cmp, buf, pk, kr+S2N_KYBER_512_R3_SYMBYTES);
- }else
+ indcpa_enc_avx2(cmp, buf, pk, kr + S2N_KYBER_512_R3_SYMBYTES);
+ } else
#endif
{
- indcpa_enc(cmp, buf, pk, kr+S2N_KYBER_512_R3_SYMBYTES);
+ indcpa_enc(cmp, buf, pk, kr + S2N_KYBER_512_R3_SYMBYTES);
}
-
+
/* If ct and cmp are equal (dont_copy = 1), decryption has succeeded and we do NOT overwrite pre-k below.
* If ct and cmp are not equal (dont_copy = 0), decryption fails and we do overwrite pre-k. */
int dont_copy = s2n_constant_time_equals(ct, cmp, S2N_KYBER_512_R3_CIPHERTEXT_BYTES);
/* overwrite coins in kr with H(c) */
- sha3_256(kr+S2N_KYBER_512_R3_SYMBYTES, ct, S2N_KYBER_512_R3_CIPHERTEXT_BYTES);
+ sha3_256(kr + S2N_KYBER_512_R3_SYMBYTES, ct, S2N_KYBER_512_R3_CIPHERTEXT_BYTES);
/* Overwrite pre-k with z on re-encryption failure */
- POSIX_GUARD(s2n_constant_time_copy_or_dont(kr, sk+S2N_KYBER_512_R3_SECRET_KEY_BYTES-S2N_KYBER_512_R3_SYMBYTES,
+ POSIX_GUARD(s2n_constant_time_copy_or_dont(kr, sk + S2N_KYBER_512_R3_SECRET_KEY_BYTES - S2N_KYBER_512_R3_SYMBYTES,
S2N_KYBER_512_R3_SYMBYTES, dont_copy));
/* hash concatenation of pre-k and H(c) to k */
- shake256(ss, S2N_KYBER_512_R3_SSBYTES, kr, 2*S2N_KYBER_512_R3_SYMBYTES);
+ shake256(ss, S2N_KYBER_512_R3_SSBYTES, kr, 2 * S2N_KYBER_512_R3_SYMBYTES);
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_512_evp.c b/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_evp.c
index 7a389162ed..534751a461 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_512_evp.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_evp.c
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-#include "s2n_kyber_512_evp.h"
+#include "s2n_kyber_evp.h"
#include <openssl/evp.h>
#include <stddef.h>
@@ -23,70 +23,85 @@
#include "utils/s2n_safety.h"
#include "utils/s2n_safety_macros.h"
-#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER512) && !defined(S2N_NO_PQ)
+#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER) && !defined(S2N_NO_PQ)
DEFINE_POINTER_CLEANUP_FUNC(EVP_PKEY *, EVP_PKEY_free);
DEFINE_POINTER_CLEANUP_FUNC(EVP_PKEY_CTX *, EVP_PKEY_CTX_free);
-int s2n_kyber_512_evp_generate_keypair(uint8_t *public_key, uint8_t *secret_key) {
+int s2n_kyber_evp_generate_keypair(IN const struct s2n_kem *kem, OUT uint8_t *public_key,
+ OUT uint8_t *secret_key)
+{
DEFER_CLEANUP(EVP_PKEY_CTX *kyber_pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_KEM, NULL), EVP_PKEY_CTX_free_pointer);
POSIX_GUARD_PTR(kyber_pkey_ctx);
- POSIX_GUARD_OSSL(EVP_PKEY_CTX_kem_set_params(kyber_pkey_ctx, NID_KYBER512_R3), S2N_ERR_PQ_CRYPTO);
+ POSIX_GUARD_OSSL(EVP_PKEY_CTX_kem_set_params(kyber_pkey_ctx, kem->kem_nid), S2N_ERR_PQ_CRYPTO);
POSIX_GUARD_OSSL(EVP_PKEY_keygen_init(kyber_pkey_ctx), S2N_ERR_PQ_CRYPTO);
DEFER_CLEANUP(EVP_PKEY *kyber_pkey = NULL, EVP_PKEY_free_pointer);
POSIX_GUARD_OSSL(EVP_PKEY_keygen(kyber_pkey_ctx, &kyber_pkey), S2N_ERR_PQ_CRYPTO);
+ POSIX_GUARD_PTR(kyber_pkey);
- size_t public_key_size = S2N_KYBER_512_R3_PUBLIC_KEY_BYTES;
- size_t secret_key_size = S2N_KYBER_512_R3_SECRET_KEY_BYTES;
+ size_t public_key_size = kem->public_key_length;
POSIX_GUARD_OSSL(EVP_PKEY_get_raw_public_key(kyber_pkey, public_key, &public_key_size), S2N_ERR_PQ_CRYPTO);
- POSIX_GUARD_OSSL(EVP_PKEY_get_raw_private_key(kyber_pkey, secret_key, &secret_key_size), S2N_ERR_PQ_CRYPTO);
+ POSIX_ENSURE_EQ(kem->public_key_length, public_key_size);
+ size_t private_key_size = kem->private_key_length;
+ POSIX_GUARD_OSSL(EVP_PKEY_get_raw_private_key(kyber_pkey, secret_key, &private_key_size), S2N_ERR_PQ_CRYPTO);
+ POSIX_ENSURE_EQ(kem->private_key_length, private_key_size);
return S2N_SUCCESS;
}
-int s2n_kyber_512_evp_encapsulate(uint8_t *ciphertext, uint8_t *shared_secret,
- const uint8_t *public_key) {
- size_t public_key_size = S2N_KYBER_512_R3_PUBLIC_KEY_BYTES;
- DEFER_CLEANUP(EVP_PKEY *kyber_pkey = EVP_PKEY_kem_new_raw_public_key(NID_KYBER512_R3, public_key, public_key_size), EVP_PKEY_free_pointer);
+int s2n_kyber_evp_encapsulate(IN const struct s2n_kem *kem, OUT uint8_t *ciphertext, OUT uint8_t *shared_secret,
+ IN const uint8_t *public_key)
+{
+ DEFER_CLEANUP(EVP_PKEY *kyber_pkey = EVP_PKEY_kem_new_raw_public_key(kem->kem_nid, public_key, kem->public_key_length), EVP_PKEY_free_pointer);
POSIX_GUARD_PTR(kyber_pkey);
DEFER_CLEANUP(EVP_PKEY_CTX *kyber_pkey_ctx = EVP_PKEY_CTX_new(kyber_pkey, NULL), EVP_PKEY_CTX_free_pointer);
POSIX_GUARD_PTR(kyber_pkey_ctx);
- size_t cipher_text_size = S2N_KYBER_512_R3_CIPHERTEXT_BYTES;
- size_t shared_secret_size = S2N_KYBER_512_R3_SHARED_SECRET_BYTES;
- POSIX_GUARD_OSSL(EVP_PKEY_encapsulate(kyber_pkey_ctx, ciphertext, &cipher_text_size, shared_secret,
- &shared_secret_size), S2N_ERR_PQ_CRYPTO);
+ size_t ciphertext_size = kem->ciphertext_length;
+ size_t shared_secret_size = kem->shared_secret_key_length;
+ POSIX_GUARD_OSSL(EVP_PKEY_encapsulate(kyber_pkey_ctx, ciphertext, &ciphertext_size, shared_secret,
+ &shared_secret_size),
+ S2N_ERR_PQ_CRYPTO);
+ POSIX_ENSURE_EQ(kem->ciphertext_length, ciphertext_size);
+ POSIX_ENSURE_EQ(kem->shared_secret_key_length, shared_secret_size);
+
return S2N_SUCCESS;
}
-int s2n_kyber_512_evp_decapsulate(uint8_t *shared_secret, const uint8_t *ciphertext,
- const uint8_t *secret_key) {
- size_t secret_key_size = S2N_KYBER_512_R3_SECRET_KEY_BYTES;
- DEFER_CLEANUP(EVP_PKEY *kyber_pkey = EVP_PKEY_kem_new_raw_secret_key(NID_KYBER512_R3, secret_key, secret_key_size), EVP_PKEY_free_pointer);
+int s2n_kyber_evp_decapsulate(IN const struct s2n_kem *kem, OUT uint8_t *shared_secret, IN const uint8_t *ciphertext,
+ IN const uint8_t *private_key)
+{
+ DEFER_CLEANUP(EVP_PKEY *kyber_pkey = EVP_PKEY_kem_new_raw_secret_key(kem->kem_nid, private_key, kem->private_key_length), EVP_PKEY_free_pointer);
POSIX_GUARD_PTR(kyber_pkey);
DEFER_CLEANUP(EVP_PKEY_CTX *kyber_pkey_ctx = EVP_PKEY_CTX_new(kyber_pkey, NULL), EVP_PKEY_CTX_free_pointer);
POSIX_GUARD_PTR(kyber_pkey_ctx);
- size_t shared_secret_size = S2N_KYBER_512_R3_SHARED_SECRET_BYTES;
- POSIX_GUARD_OSSL(EVP_PKEY_decapsulate(kyber_pkey_ctx, shared_secret, &shared_secret_size, (uint8_t *) ciphertext,
- S2N_KYBER_512_R3_CIPHERTEXT_BYTES), S2N_ERR_PQ_CRYPTO);
+ size_t shared_secret_size = kem->shared_secret_key_length;
+ POSIX_GUARD_OSSL(EVP_PKEY_decapsulate(kyber_pkey_ctx, shared_secret, &shared_secret_size,
+ (uint8_t *) ciphertext, kem->ciphertext_length),
+ S2N_ERR_PQ_CRYPTO);
+ POSIX_ENSURE_EQ(kem->shared_secret_key_length, shared_secret_size);
+
return S2N_SUCCESS;
}
#else
-int s2n_kyber_512_evp_generate_keypair(OUT uint8_t *public_key, OUT uint8_t *secret_key) {
+int s2n_kyber_512_evp_generate_keypair(IN const struct s2n_kem *kem, OUT uint8_t *public_key, OUT uint8_t *secret_key)
+{
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
}
-int s2n_kyber_512_evp_encapsulate(OUT uint8_t *ciphertext, OUT uint8_t *shared_secret,
- IN const uint8_t *public_key) {
+int s2n_kyber_512_evp_encapsulate(IN const struct s2n_kem *kem, OUT uint8_t *ciphertext, OUT uint8_t *shared_secret,
+ IN const uint8_t *public_key)
+{
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
}
-int s2n_kyber_512_evp_decapsulate(OUT uint8_t *shared_secret, IN const uint8_t *ciphertext,
- IN const uint8_t *secret_key) {
+int s2n_kyber_512_evp_decapsulate(IN const struct s2n_kem *kem, OUT uint8_t *shared_secret, IN const uint8_t *ciphertext,
+ IN const uint8_t *secret_key)
+{
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
}
#endif
diff --git a/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_512_evp.h b/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_evp.h
index 1a62a7cc92..f624f4436c 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_512_evp.h
+++ b/contrib/restricted/aws/s2n/pq-crypto/s2n_kyber_evp.h
@@ -17,6 +17,6 @@
#include "tls/s2n_kem.h"
-int s2n_kyber_512_evp_generate_keypair(OUT uint8_t *public_key, OUT uint8_t *private_key);
-int s2n_kyber_512_evp_encapsulate(OUT uint8_t *ciphertext, OUT uint8_t *shared_secret, IN const uint8_t *public_key);
-int s2n_kyber_512_evp_decapsulate(OUT uint8_t *shared_secret, IN const uint8_t *ciphertext, IN const uint8_t *private_key);
+int s2n_kyber_evp_generate_keypair(IN const struct s2n_kem *kem, OUT uint8_t *public_key, OUT uint8_t *private_key);
+int s2n_kyber_evp_encapsulate(IN const struct s2n_kem *kem, OUT uint8_t *ciphertext, OUT uint8_t *shared_secret, IN const uint8_t *public_key);
+int s2n_kyber_evp_decapsulate(IN const struct s2n_kem *kem, OUT uint8_t *shared_secret, IN const uint8_t *ciphertext, IN const uint8_t *private_key);
diff --git a/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.c b/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.c
index abaf8f2d65..8f21439b13 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.c
@@ -16,28 +16,29 @@
#include "s2n_pq.h"
#include "crypto/s2n_openssl.h"
-#include "s2n_kyber_512_evp.h"
+#include "s2n_kyber_evp.h"
static bool kyber512r3_avx2_bmi2_enabled = false;
#if defined(S2N_CPUID_AVAILABLE)
-/* https://en.wikipedia.org/wiki/CPUID */
-#include <cpuid.h>
+ /* https://en.wikipedia.org/wiki/CPUID */
+ #include <cpuid.h>
-#define PROCESSOR_INFO_AND_FEATURES 1
-#define EXTENDED_FEATURES_LEAF 7
-#define EXTENDED_FEATURES_SUBLEAF_ZERO 0
+ #define PROCESSOR_INFO_AND_FEATURES 1
+ #define EXTENDED_FEATURES_LEAF 7
+ #define EXTENDED_FEATURES_SUBLEAF_ZERO 0
-/* The cpuid.h header included with older versions of gcc and
+ /* The cpuid.h header included with older versions of gcc and
* clang doesn't include definitions for bit_ADX, bit_BMI2, or
* __get_cpuid_count(). */
-#if !defined(bit_BMI2)
- #define bit_BMI2 (1 << 8)
-#endif
+ #if !defined(bit_BMI2)
+ #define bit_BMI2 (1 << 8)
+ #endif
-#define EBX_BIT_AVX2 (1 << 5)
+ #define EBX_BIT_AVX2 (1 << 5)
-bool s2n_get_cpuid_count(uint32_t leaf, uint32_t sub_leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
+bool s2n_get_cpuid_count(uint32_t leaf, uint32_t sub_leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+{
/* 0x80000000 probes for extended cpuid info */
uint32_t max_level = __get_cpuid_max(leaf & 0x80000000, 0);
@@ -50,7 +51,8 @@ bool s2n_get_cpuid_count(uint32_t leaf, uint32_t sub_leaf, uint32_t *eax, uint32
}
/* https://en.wikipedia.org/wiki/Bit_manipulation_instruction_set#BMI2_(Bit_Manipulation_Instruction_Set_2) */
-bool s2n_cpu_supports_bmi2() {
+bool s2n_cpu_supports_bmi2()
+{
uint32_t eax, ebx, ecx, edx;
if (!s2n_get_cpuid_count(EXTENDED_FEATURES_LEAF, EXTENDED_FEATURES_SUBLEAF_ZERO, &eax, &ebx, &ecx, &edx)) {
return false;
@@ -59,7 +61,8 @@ bool s2n_cpu_supports_bmi2() {
return (ebx & bit_BMI2);
}
-bool s2n_cpu_supports_avx2() {
+bool s2n_cpu_supports_avx2()
+{
uint32_t eax, ebx, ecx, edx;
if (!s2n_get_cpuid_count(EXTENDED_FEATURES_LEAF, EXTENDED_FEATURES_SUBLEAF_ZERO, &eax, &ebx, &ecx, &edx)) {
return false;
@@ -68,29 +71,32 @@ bool s2n_cpu_supports_avx2() {
return (ebx & EBX_BIT_AVX2);
}
-bool s2n_cpu_supports_kyber512r3_avx2_bmi2() {
-#if defined(S2N_KYBER512R3_AVX2_BMI2)
+bool s2n_cpu_supports_kyber512r3_avx2_bmi2()
+{
+ #if defined(S2N_KYBER512R3_AVX2_BMI2)
return s2n_cpu_supports_bmi2() && s2n_cpu_supports_avx2();
-#else
+ #else
return false;
-#endif
+ #endif
}
#else /* defined(S2N_CPUID_AVAILABLE) */
/* If CPUID is not available, we cannot perform necessary run-time checks. */
-bool s2n_cpu_supports_kyber512r3_avx2_bmi2() {
+bool s2n_cpu_supports_kyber512r3_avx2_bmi2()
+{
return false;
}
#endif /* defined(S2N_CPUID_AVAILABLE) */
-
-bool s2n_kyber512r3_is_avx2_bmi2_enabled() {
+bool s2n_kyber512r3_is_avx2_bmi2_enabled()
+{
return kyber512r3_avx2_bmi2_enabled;
}
-bool s2n_pq_is_enabled() {
+bool s2n_pq_is_enabled()
+{
#if defined(S2N_NO_PQ)
return false;
#else
@@ -99,28 +105,32 @@ bool s2n_pq_is_enabled() {
#endif
}
-bool s2n_libcrypto_supports_kyber_512() {
-#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER512)
+bool s2n_libcrypto_supports_kyber()
+{
+#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER)
return true;
#else
return false;
#endif
}
-S2N_RESULT s2n_disable_kyber512r3_opt_avx2_bmi2() {
+S2N_RESULT s2n_disable_kyber512r3_opt_avx2_bmi2()
+{
kyber512r3_avx2_bmi2_enabled = false;
return S2N_RESULT_OK;
}
-S2N_RESULT s2n_try_enable_kyber512r3_opt_avx2_bmi2() {
+S2N_RESULT s2n_try_enable_kyber512r3_opt_avx2_bmi2()
+{
if (s2n_pq_is_enabled() && s2n_cpu_supports_kyber512r3_avx2_bmi2()) {
kyber512r3_avx2_bmi2_enabled = true;
}
return S2N_RESULT_OK;
}
-S2N_RESULT s2n_pq_init() {
+S2N_RESULT s2n_pq_init()
+{
RESULT_ENSURE_OK(s2n_try_enable_kyber512r3_opt_avx2_bmi2(), S2N_ERR_SAFETY);
-
+
return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.h b/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.h
index 6ac074dc49..edba33138f 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.h
+++ b/contrib/restricted/aws/s2n/pq-crypto/s2n_pq.h
@@ -16,15 +16,16 @@
#pragma once
#include <stdbool.h>
-#include "utils/s2n_result.h"
-#include "utils/s2n_safety.h"
+
#include "crypto/s2n_fips.h"
#include "pq-crypto/s2n_pq_asm.h"
+#include "utils/s2n_result.h"
+#include "utils/s2n_safety.h"
bool s2n_kyber512r3_is_avx2_bmi2_enabled(void);
S2N_RESULT s2n_try_enable_kyber512r3_opt_avx2_bmi2(void);
S2N_RESULT s2n_disable_kyber512r3_opt_avx2_bmi2(void);
-
+
bool s2n_pq_is_enabled(void);
-bool s2n_libcrypto_supports_kyber_512(void);
+bool s2n_libcrypto_supports_kyber(void);
S2N_RESULT s2n_pq_init(void);
diff --git a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_file.c b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_file.c
index a41564d54b..045c42c4b0 100644
--- a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_file.c
+++ b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_file.c
@@ -22,6 +22,7 @@
#include "error/s2n_errno.h"
#include "stuffer/s2n_stuffer.h"
+#include "utils/s2n_io.h"
#include "utils/s2n_safety.h"
int s2n_stuffer_recv_from_fd(struct s2n_stuffer *stuffer, const int rfd, const uint32_t len, uint32_t *bytes_written)
@@ -35,13 +36,12 @@ int s2n_stuffer_recv_from_fd(struct s2n_stuffer *stuffer, const int rfd, const u
stuffer->write_cursor -= len;
ssize_t r = 0;
- do {
- POSIX_ENSURE(stuffer->blob.data && (r >= 0 || errno == EINTR), S2N_ERR_READ);
- r = read(rfd, stuffer->blob.data + stuffer->write_cursor, len);
- } while (r < 0);
+ POSIX_ENSURE(stuffer->blob.data, S2N_ERR_READ);
+ S2N_IO_RETRY_EINTR(r, read(rfd, stuffer->blob.data + stuffer->write_cursor, len));
+ POSIX_ENSURE(r >= 0, S2N_ERR_READ);
/* Record just how many bytes we have written */
- POSIX_ENSURE(r <= UINT32_MAX, S2N_ERR_INTEGER_OVERFLOW);
+ POSIX_ENSURE((size_t) r <= UINT32_MAX, S2N_ERR_INTEGER_OVERFLOW);
POSIX_GUARD(s2n_stuffer_skip_write(stuffer, (uint32_t) r));
if (bytes_written != NULL) {
*bytes_written = r;
@@ -60,12 +60,11 @@ int s2n_stuffer_send_to_fd(struct s2n_stuffer *stuffer, const int wfd, const uin
stuffer->read_cursor -= len;
ssize_t w = 0;
- do {
- POSIX_ENSURE(stuffer->blob.data && (w >= 0 || errno == EINTR), S2N_ERR_WRITE);
- w = write(wfd, stuffer->blob.data + stuffer->read_cursor, len);
- } while (w < 0);
+ POSIX_ENSURE(stuffer->blob.data, S2N_ERR_WRITE);
+ S2N_IO_RETRY_EINTR(w, write(wfd, stuffer->blob.data + stuffer->read_cursor, len));
+ POSIX_ENSURE(w >= 0, S2N_ERR_WRITE);
- POSIX_ENSURE(w <= UINT32_MAX - stuffer->read_cursor, S2N_ERR_INTEGER_OVERFLOW);
+ POSIX_ENSURE((size_t) w <= UINT32_MAX - stuffer->read_cursor, S2N_ERR_INTEGER_OVERFLOW);
stuffer->read_cursor += w;
if (bytes_sent != NULL) {
*bytes_sent = w;
@@ -81,7 +80,7 @@ int s2n_stuffer_alloc_ro_from_fd(struct s2n_stuffer *stuffer, int rfd)
POSIX_ENSURE(fstat(rfd, &st) >= 0, S2N_ERR_FSTAT);
POSIX_ENSURE_GT(st.st_size, 0);
- POSIX_ENSURE_LTE(st.st_size, UINT32_MAX);
+ POSIX_ENSURE_LTE((uint64_t) st.st_size, UINT32_MAX);
uint8_t *map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, rfd, 0);
POSIX_ENSURE(map != MAP_FAILED, S2N_ERR_MMAP);
@@ -95,12 +94,10 @@ int s2n_stuffer_alloc_ro_from_file(struct s2n_stuffer *stuffer, const char *file
{
POSIX_ENSURE_MUT(stuffer);
POSIX_ENSURE_REF(file);
- int fd;
- do {
- fd = open(file, O_RDONLY);
- POSIX_ENSURE(fd >= 0 || errno == EINTR, S2N_ERR_OPEN);
- } while (fd < 0);
+ int fd = 0;
+ S2N_IO_RETRY_EINTR(fd, open(file, O_RDONLY));
+ POSIX_ENSURE(fd >= 0, S2N_ERR_OPEN);
int r = s2n_stuffer_alloc_ro_from_fd(stuffer, fd);
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.c
index 1b59001d39..55de6956ee 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.c
@@ -451,24 +451,6 @@ static int s2n_client_key_share_recv(struct s2n_connection *conn, struct s2n_stu
/* Old-style extension functions -- remove after extensions refactor is complete */
-uint32_t s2n_extensions_client_key_share_size(struct s2n_connection *conn)
-{
- POSIX_ENSURE_REF(conn);
-
- const struct s2n_ecc_preferences *ecc_pref = NULL;
- POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- POSIX_ENSURE_REF(ecc_pref);
-
- uint32_t s2n_client_key_share_extension_size = S2N_SIZE_OF_EXTENSION_TYPE
- + S2N_SIZE_OF_EXTENSION_DATA_SIZE
- + S2N_SIZE_OF_CLIENT_SHARES_SIZE;
-
- s2n_client_key_share_extension_size += S2N_SIZE_OF_KEY_SHARE_SIZE + S2N_SIZE_OF_NAMED_GROUP;
- s2n_client_key_share_extension_size += ecc_pref->ecc_curves[0]->share_size;
-
- return s2n_client_key_share_extension_size;
-}
-
int s2n_extensions_client_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
return s2n_extension_recv(&s2n_client_key_share_extension, conn, extension);
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.h
index 9da85e789c..fd570f0c28 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.h
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.h
@@ -22,4 +22,3 @@ extern const s2n_extension_type s2n_client_key_share_extension;
/* Old-style extension functions -- remove after extensions refactor is complete */
int s2n_extensions_client_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
-uint32_t s2n_extensions_client_key_share_size(struct s2n_connection *conn);
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.c
index 4f7e3e12c4..5694f0d878 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.c
@@ -78,6 +78,25 @@ static int s2n_client_supported_groups_send(struct s2n_connection *conn, struct
return S2N_SUCCESS;
}
+S2N_RESULT s2n_supported_groups_parse_count(struct s2n_stuffer *extension, uint16_t *count)
+{
+ RESULT_ENSURE_REF(count);
+ *count = 0;
+ RESULT_ENSURE_REF(extension);
+
+ uint16_t supported_groups_list_size = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(extension, &supported_groups_list_size));
+
+ RESULT_ENSURE(supported_groups_list_size <= s2n_stuffer_data_available(extension),
+ S2N_ERR_INVALID_PARSED_EXTENSIONS);
+ RESULT_ENSURE(supported_groups_list_size % S2N_SUPPORTED_GROUP_SIZE == 0,
+ S2N_ERR_INVALID_PARSED_EXTENSIONS);
+
+ *count = supported_groups_list_size / S2N_SUPPORTED_GROUP_SIZE;
+
+ return S2N_RESULT_OK;
+}
+
/* Populates the appropriate index of either the mutually_supported_curves or
* mutually_supported_kem_groups array based on the received IANA ID. Will
* ignore unrecognized IANA IDs (and return success). */
@@ -165,15 +184,14 @@ static int s2n_client_supported_groups_recv(struct s2n_connection *conn, struct
POSIX_ENSURE_REF(conn);
POSIX_ENSURE_REF(extension);
- uint16_t size_of_all;
- POSIX_GUARD(s2n_stuffer_read_uint16(extension, &size_of_all));
- if (size_of_all > s2n_stuffer_data_available(extension) || (size_of_all % sizeof(uint16_t))) {
+ uint16_t supported_groups_count = 0;
+ if (s2n_result_is_error(s2n_supported_groups_parse_count(extension, &supported_groups_count))) {
/* Malformed length, ignore the extension */
return S2N_SUCCESS;
}
- for (size_t i = 0; i < (size_of_all / sizeof(uint16_t)); i++) {
- uint16_t iana_id;
+ for (size_t i = 0; i < supported_groups_count; i++) {
+ uint16_t iana_id = 0;
POSIX_GUARD(s2n_stuffer_read_uint16(extension, &iana_id));
POSIX_GUARD(s2n_client_supported_groups_recv_iana_id(conn, iana_id));
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.h
index 322ac14813..1033c514dd 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.h
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.h
@@ -19,8 +19,12 @@
#include "tls/extensions/s2n_extension_type.h"
#include "tls/s2n_connection.h"
+#define S2N_SUPPORTED_GROUP_SIZE 2
+
extern const s2n_extension_type s2n_client_supported_groups_extension;
bool s2n_extension_should_send_if_ecc_enabled(struct s2n_connection *conn);
+S2N_RESULT s2n_supported_groups_parse_count(struct s2n_stuffer *extension, uint16_t *count);
+
/* Old-style extension functions -- remove after extensions refactor is complete */
int s2n_recv_client_supported_groups(struct s2n_connection *conn, struct s2n_stuffer *extension);
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c
index ae003c8fc8..d5e6c87742 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c
@@ -64,9 +64,17 @@ static int s2n_ec_point_format_send(struct s2n_connection *conn, struct s2n_stuf
static int s2n_ec_point_format_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- /**
- * Only uncompressed points are supported by the server and the client must include it in
+ /* Only uncompressed points are supported by the server and the client must include it in
* the extension. Just skip the extension.
+ *
+ *= https://tools.ietf.org/rfc/rfc8422#section-5.1.2
+ *= type=exception
+ *= reason=Incorrect implementations exist in the wild. Skipping validation.
+ *# If the client sends the extension and the extension does not contain
+ *# the uncompressed point format, and the client has used the Supported
+ *# Groups extension to indicate support for any of the curves defined in
+ *# this specification, then the server MUST abort the handshake and
+ *# return an illegal_parameter alert.
*/
conn->ec_point_formats = 1;
return S2N_SUCCESS;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c
index 2062ffa58e..41c9f7a5de 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c
@@ -38,8 +38,20 @@ const s2n_extension_type s2n_psk_key_exchange_modes_extension = {
static bool s2n_psk_key_exchange_modes_should_send(struct s2n_connection *conn)
{
- /* Only send a psk_key_exchange_modes extension if psks available */
- return conn->psk_params.psk_list.len > 0;
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.9
+ *# Servers MUST NOT select a key exchange mode that is not listed by the
+ *# client. This extension also restricts the modes for use with PSK
+ *# resumption.
+ *
+ * The RFC is ambiguous about whether the psk_kx_modes extension should be
+ * sent in the first flight of messages, but we choose to do so for
+ * interoperability with other TLS implementations.
+ * https://github.com/aws/s2n-tls/issues/4124
+ * The final check for psk_list.len > 0 is necessary because external
+ * PSKs are used without setting `use_tickets` to true.
+ */
+ return conn->config->use_tickets || conn->psk_params.psk_list.len > 0;
}
static int s2n_psk_key_exchange_modes_send(struct s2n_connection *conn, struct s2n_stuffer *out)
diff --git a/contrib/restricted/aws/s2n/tls/s2n_alerts.c b/contrib/restricted/aws/s2n/tls/s2n_alerts.c
index 1ca06577d5..a61d1462b6 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_alerts.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_alerts.c
@@ -23,12 +23,10 @@
#include "tls/s2n_record.h"
#include "tls/s2n_resume.h"
#include "tls/s2n_tls_parameters.h"
+#include "utils/s2n_atomic.h"
#include "utils/s2n_blob.h"
#include "utils/s2n_safety.h"
-#define S2N_TLS_ALERT_LEVEL_WARNING 1
-#define S2N_TLS_ALERT_LEVEL_FATAL 2
-
#define S2N_ALERT_CASE(error, alert_code) \
case (error): \
*alert = (alert_code); \
@@ -104,10 +102,12 @@ static S2N_RESULT s2n_translate_protocol_error_to_alert(int error_code, uint8_t
S2N_NO_ALERT(S2N_ERR_RECORD_LIMIT);
S2N_NO_ALERT(S2N_ERR_CERT_UNTRUSTED);
S2N_NO_ALERT(S2N_ERR_CERT_REVOKED);
+ S2N_NO_ALERT(S2N_ERR_CERT_NOT_YET_VALID);
S2N_NO_ALERT(S2N_ERR_CERT_EXPIRED);
S2N_NO_ALERT(S2N_ERR_CERT_TYPE_UNSUPPORTED);
S2N_NO_ALERT(S2N_ERR_CERT_INVALID);
S2N_NO_ALERT(S2N_ERR_CERT_MAX_CHAIN_DEPTH_EXCEEDED);
+ S2N_NO_ALERT(S2N_ERR_CERT_REJECTED);
S2N_NO_ALERT(S2N_ERR_CRL_LOOKUP_FAILED);
S2N_NO_ALERT(S2N_ERR_CRL_SIGNATURE);
S2N_NO_ALERT(S2N_ERR_CRL_ISSUER);
@@ -143,6 +143,11 @@ static bool s2n_alerts_supported(struct s2n_connection *conn)
return !s2n_connection_is_quic_enabled(conn);
}
+/* In TLS1.3 all Alerts
+ *= https://tools.ietf.org/rfc/rfc8446#section-6
+ *# MUST be treated as error alerts when received
+ *# regardless of the AlertLevel in the message.
+ */
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
@@ -158,20 +163,6 @@ static bool s2n_process_as_warning(struct s2n_connection *conn, uint8_t level, u
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->write_closing = 1;
- return S2N_RESULT_OK;
-}
-
int s2n_error_get_alert(int error, uint8_t *alert)
{
int error_type = s2n_error_get_type(error);
@@ -220,8 +211,8 @@ int s2n_process_alert_fragment(struct s2n_connection *conn)
if (s2n_stuffer_data_available(&conn->alert_in) == 2) {
/* Close notifications are handled as shutdowns */
if (conn->alert_in_data[1] == S2N_TLS_ALERT_CLOSE_NOTIFY) {
- conn->read_closed = 1;
- conn->close_notify_received = true;
+ s2n_atomic_flag_set(&conn->read_closed);
+ s2n_atomic_flag_set(&conn->close_notify_received);
return 0;
}
@@ -236,8 +227,13 @@ int s2n_process_alert_fragment(struct s2n_connection *conn)
conn->config->cache_delete(conn, conn->config->cache_delete_data, conn->session_id, conn->session_id_len);
}
- /* All other alerts are treated as fatal errors */
+ /* All other alerts are treated as fatal errors.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-6
+ *# Unknown Alert types MUST be treated as error alerts.
+ */
POSIX_GUARD_RESULT(s2n_connection_set_closed(conn));
+ s2n_atomic_flag_set(&conn->error_alert_received);
POSIX_BAIL(S2N_ERR_ALERT);
}
}
@@ -245,64 +241,25 @@ int s2n_process_alert_fragment(struct s2n_connection *conn)
return 0;
}
-int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn)
-{
- POSIX_ENSURE_REF(conn);
-
- uint8_t alert[2];
- alert[0] = S2N_TLS_ALERT_LEVEL_WARNING;
- alert[1] = S2N_TLS_ALERT_CLOSE_NOTIFY;
-
- struct s2n_blob out = { 0 };
- POSIX_GUARD(s2n_blob_init(&out, alert, sizeof(alert)));
-
- /* If there is an alert pending, do nothing */
- if (s2n_stuffer_data_available(&conn->writer_alert_out)) {
- return S2N_SUCCESS;
- }
-
- if (!s2n_alerts_supported(conn)) {
- return S2N_SUCCESS;
- }
-
- POSIX_GUARD(s2n_stuffer_write(&conn->writer_alert_out, &out));
-
- return S2N_SUCCESS;
-}
-
-static int s2n_queue_reader_alert(struct s2n_connection *conn, uint8_t level, uint8_t error_code)
+static S2N_RESULT s2n_queue_reader_alert(struct s2n_connection *conn, s2n_tls_alert_code code)
{
- POSIX_ENSURE_REF(conn);
-
- uint8_t alert[2];
- alert[0] = level;
- alert[1] = error_code;
-
- struct s2n_blob out = { 0 };
- POSIX_GUARD(s2n_blob_init(&out, alert, sizeof(alert)));
-
- /* If there is an alert pending, do nothing */
- if (s2n_stuffer_data_available(&conn->reader_alert_out)) {
- return S2N_SUCCESS;
- }
-
- if (!s2n_alerts_supported(conn)) {
- return S2N_SUCCESS;
+ RESULT_ENSURE_REF(conn);
+ if (!conn->reader_alert_out) {
+ conn->reader_alert_out = code;
}
-
- POSIX_GUARD(s2n_stuffer_write(&conn->reader_alert_out, &out));
-
- return S2N_SUCCESS;
+ return S2N_RESULT_OK;
}
int s2n_queue_reader_unsupported_protocol_version_alert(struct s2n_connection *conn)
{
- return s2n_queue_reader_alert(conn, S2N_TLS_ALERT_LEVEL_FATAL, S2N_TLS_ALERT_PROTOCOL_VERSION);
+ POSIX_GUARD_RESULT(s2n_queue_reader_alert(conn, S2N_TLS_ALERT_PROTOCOL_VERSION));
+ return S2N_SUCCESS;
}
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);
+ POSIX_GUARD_RESULT(s2n_queue_reader_alert(conn, S2N_TLS_ALERT_HANDSHAKE_FAILURE));
+ return S2N_SUCCESS;
}
S2N_RESULT s2n_queue_reader_no_renegotiation_alert(struct s2n_connection *conn)
@@ -315,10 +272,72 @@ S2N_RESULT s2n_queue_reader_no_renegotiation_alert(struct s2n_connection *conn)
*# handshake_failure alert.
**/
if (s2n_connection_get_protocol_version(conn) == S2N_SSLv3) {
- RESULT_GUARD_POSIX(s2n_queue_reader_alert(conn, S2N_TLS_ALERT_LEVEL_FATAL, S2N_TLS_ALERT_HANDSHAKE_FAILURE));
+ RESULT_GUARD_POSIX(s2n_queue_reader_handshake_failure_alert(conn));
+ RESULT_BAIL(S2N_ERR_BAD_MESSAGE);
+ }
+
+ if (!conn->reader_warning_out) {
+ conn->reader_warning_out = S2N_TLS_ALERT_NO_RENEGOTIATION;
+ }
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_alerts_write_error_or_close_notify(struct s2n_connection *conn)
+{
+ if (!s2n_alerts_supported(conn)) {
+ return S2N_RESULT_OK;
+ }
+
+ /*
+ *= https://tools.ietf.org/rfc/rfc8446#section-6.2
+ *= type=exception
+ *= reason=Specific alerts could expose a side-channel attack vector.
+ *# The phrases "terminate the connection with an X
+ *# alert" and "abort the handshake with an X alert" mean that the
+ *# implementation MUST send alert X if it sends any alert.
+ *
+ * By default, s2n-tls sends a generic close_notify alert, even in
+ * response to fatal errors. This is done to avoid potential
+ * side-channel attacks since specific alerts could reveal information
+ * about why the error occured.
+ */
+ uint8_t code = S2N_TLS_ALERT_CLOSE_NOTIFY;
+ uint8_t level = S2N_TLS_ALERT_LEVEL_WARNING;
+
+ /* s2n-tls sends a very small subset of more specific error alerts.
+ * Since either the reader or the writer can produce one of these alerts,
+ * but only a single alert can be reported, we prioritize writer alerts.
+ */
+ if (conn->writer_alert_out) {
+ code = conn->writer_alert_out;
+ level = S2N_TLS_ALERT_LEVEL_FATAL;
+ } else if (conn->reader_alert_out) {
+ code = conn->reader_alert_out;
+ level = S2N_TLS_ALERT_LEVEL_FATAL;
+ }
+
+ struct s2n_blob alert = { 0 };
+ uint8_t alert_bytes[] = { level, code };
+ RESULT_GUARD_POSIX(s2n_blob_init(&alert, alert_bytes, sizeof(alert_bytes)));
+
+ RESULT_GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
+ conn->alert_sent = true;
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_alerts_write_warning(struct s2n_connection *conn)
+{
+ if (!s2n_alerts_supported(conn)) {
return S2N_RESULT_OK;
}
- RESULT_GUARD_POSIX(s2n_queue_reader_alert(conn, S2N_TLS_ALERT_LEVEL_WARNING, S2N_TLS_ALERT_NO_RENEGOTIATION));
+ uint8_t code = conn->reader_warning_out;
+ uint8_t level = S2N_TLS_ALERT_LEVEL_WARNING;
+
+ struct s2n_blob alert = { 0 };
+ uint8_t alert_bytes[] = { level, code };
+ RESULT_GUARD_POSIX(s2n_blob_init(&alert, alert_bytes, sizeof(alert_bytes)));
+
+ RESULT_GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
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 d745ce3033..910296eb97 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_alerts.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_alerts.h
@@ -19,6 +19,9 @@
#include "tls/s2n_connection.h"
+#define S2N_TLS_ALERT_LEVEL_WARNING 1
+#define S2N_TLS_ALERT_LEVEL_FATAL 2
+
typedef enum {
/*
*= https://tools.ietf.org/rfc/rfc8446#section-6
@@ -103,8 +106,8 @@ typedef enum {
} s2n_tls_alert_code;
int s2n_process_alert_fragment(struct s2n_connection *conn);
-int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn);
int s2n_queue_reader_unsupported_protocol_version_alert(struct s2n_connection *conn);
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);
+S2N_RESULT s2n_alerts_write_error_or_close_notify(struct s2n_connection *conn);
+S2N_RESULT s2n_alerts_write_warning(struct s2n_connection *conn);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
index 2187c9fb2d..cd3406d2a9 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
@@ -1850,6 +1850,47 @@ const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_26 = {
.allow_chacha20_boosting = false,
};
+/* Same as 2021_05_26 except:
+ *
+ * 1. TLSv1.2 Kyber KEM cipher suites are removed
+ * 2. AES 256 is preferred for TLS 1.3
+ * 3. AES 128 is preferred for TLS 1.2 which has no PQ support in PQ-TLS-1-3-2023-06-01
+ */
+struct s2n_cipher_suite *cipher_suites_pq_tls_1_3_2023_06_01[] = {
+ S2N_TLS13_CIPHER_SUITES_20190801,
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_3des_ede_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_dhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_3_2023_06_01 = {
+ .count = s2n_array_len(cipher_suites_pq_tls_1_3_2023_06_01),
+ .suites = cipher_suites_pq_tls_1_3_2023_06_01,
+ .allow_chacha20_boosting = false,
+};
+
struct s2n_cipher_suite *cipher_suites_kms_fips_tls_1_2_2018_10[] = {
&s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
&s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h
index 38e4e4e594..a9f1830c82 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h
@@ -128,5 +128,6 @@ extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05
extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_24;
extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_25;
extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_26;
+extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_3_2023_06_01;
extern const struct s2n_cipher_preferences cipher_preferences_null;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
index d20325270b..2ea3632493 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
@@ -971,9 +971,6 @@ int s2n_crypto_disable_init(void)
/* Determines cipher suite availability and selects record algorithms */
int s2n_cipher_suites_init(void)
{
- /* RC4 requires some extra setup */
- POSIX_GUARD_RESULT(s2n_rc4_init());
-
const int num_cipher_suites = s2n_array_len(s2n_all_cipher_suites);
for (int i = 0; i < num_cipher_suites; i++) {
struct s2n_cipher_suite *cur_suite = s2n_all_cipher_suites[i];
@@ -1054,10 +1051,6 @@ S2N_RESULT s2n_cipher_suites_cleanup(void)
* cleanup in later versions */
#endif
}
-
- /* RC4 requires some extra cleanup */
- RESULT_GUARD(s2n_rc4_cleanup());
-
return S2N_RESULT_OK;
}
@@ -1179,7 +1172,7 @@ bool s2n_cipher_suite_uses_chacha20_alg(struct s2n_cipher_suite *cipher_suite)
return cipher_suite && cipher_suite->record_alg && cipher_suite->record_alg->cipher == &s2n_chacha20_poly1305;
}
-/* Iff the server has enabled allow_chacha20_boosting and the client has a chacha20 cipher suite as its most
+/* Iff the server has enabled allow_chacha20_boosting and the client has a chacha20 cipher suite as its most
* preferred cipher suite, then we have mutual chacha20 boosting support.
*/
static S2N_RESULT s2n_validate_chacha20_boosting(const struct s2n_cipher_preferences *cipher_preferences, const uint8_t *wire,
@@ -1254,7 +1247,7 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire,
* other cipher suites.
*
* If no mutually supported cipher suites are found, we choose one with a version
- * too high for the current connection (higher_vers_match).
+ * too high for the current connection (higher_vers_match).
*/
for (size_t i = 0; i < cipher_preferences->count; i++) {
const uint8_t *ours = cipher_preferences->suites[i]->iana_value;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
index 7fe87dd991..21447d8127 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
@@ -22,6 +22,7 @@
#include "crypto/s2n_hmac.h"
#include "tls/s2n_connection.h"
#include "tls/s2n_crypto.h"
+#include "tls/s2n_kem_preferences.h"
#include "tls/s2n_tls_parameters.h"
/* Key exchange flags that can be OR'ed */
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_cert.c b/contrib/restricted/aws/s2n/tls/s2n_client_cert.c
index d541537c54..ec50ed7835 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_cert.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_cert.c
@@ -51,23 +51,29 @@
* So in order to store / return the certificates in the same format as in TLS1.2,
* we need to first strip out the extensions.
*/
-static S2N_RESULT s2n_client_cert_chain_store(struct s2n_connection *conn, struct s2n_blob *client_cert_chain)
+static S2N_RESULT s2n_client_cert_chain_store(struct s2n_connection *conn,
+ struct s2n_blob *raw_cert_chain)
{
RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(raw_cert_chain);
+
+ /* There shouldn't already be a client cert chain, but free just in case */
+ RESULT_GUARD_POSIX(s2n_free(&conn->handshake_params.client_cert_chain));
/* Earlier versions are a basic copy */
if (conn->actual_protocol_version < S2N_TLS13) {
- RESULT_GUARD_POSIX(s2n_dup(client_cert_chain, &conn->handshake_params.client_cert_chain));
+ RESULT_GUARD_POSIX(s2n_dup(raw_cert_chain, &conn->handshake_params.client_cert_chain));
return S2N_RESULT_OK;
}
+ DEFER_CLEANUP(struct s2n_blob output = { 0 }, s2n_free);
+ RESULT_GUARD_POSIX(s2n_realloc(&output, raw_cert_chain->size));
+
struct s2n_stuffer cert_chain_in = { 0 };
- RESULT_GUARD_POSIX(s2n_stuffer_init(&cert_chain_in, client_cert_chain));
- RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&cert_chain_in, client_cert_chain->size));
+ RESULT_GUARD_POSIX(s2n_stuffer_init_written(&cert_chain_in, raw_cert_chain));
struct s2n_stuffer cert_chain_out = { 0 };
- RESULT_GUARD_POSIX(s2n_realloc(&conn->handshake_params.client_cert_chain, client_cert_chain->size));
- RESULT_GUARD_POSIX(s2n_stuffer_init(&cert_chain_out, &conn->handshake_params.client_cert_chain));
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&cert_chain_out, &output));
uint32_t cert_size = 0;
uint16_t extensions_size = 0;
@@ -86,7 +92,10 @@ static S2N_RESULT s2n_client_cert_chain_store(struct s2n_connection *conn, struc
/* We will have allocated more memory than actually necessary.
* If this becomes a problem, we should consider reallocing the correct amount of memory here.
*/
- conn->handshake_params.client_cert_chain.size = s2n_stuffer_data_available(&cert_chain_out);
+ output.size = s2n_stuffer_data_available(&cert_chain_out);
+
+ conn->handshake_params.client_cert_chain = output;
+ ZERO_TO_DISABLE_DEFER_CLEANUP(output);
return S2N_RESULT_OK;
}
@@ -99,34 +108,35 @@ int s2n_client_cert_recv(struct s2n_connection *conn)
}
struct s2n_stuffer *in = &conn->handshake.io;
- struct s2n_blob client_cert_chain = { 0 };
-
- POSIX_GUARD(s2n_stuffer_read_uint24(in, &client_cert_chain.size));
- S2N_ERROR_IF(client_cert_chain.size > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE);
-
- if (client_cert_chain.size == 0) {
+ uint32_t cert_chain_size = 0;
+ POSIX_GUARD(s2n_stuffer_read_uint24(in, &cert_chain_size));
+ POSIX_ENSURE(cert_chain_size <= s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE);
+ if (cert_chain_size == 0) {
POSIX_GUARD(s2n_conn_set_handshake_no_client_cert(conn));
- return 0;
+ return S2N_SUCCESS;
}
- client_cert_chain.data = s2n_stuffer_raw_read(in, client_cert_chain.size);
- POSIX_ENSURE_REF(client_cert_chain.data);
+ uint8_t *cert_chain_data = s2n_stuffer_raw_read(in, cert_chain_size);
+ POSIX_ENSURE_REF(cert_chain_data);
- s2n_cert_public_key public_key;
- POSIX_GUARD(s2n_pkey_zero_init(&public_key));
+ struct s2n_blob cert_chain = { 0 };
+ POSIX_GUARD(s2n_blob_init(&cert_chain, cert_chain_data, cert_chain_size));
+ POSIX_ENSURE(s2n_result_is_ok(s2n_client_cert_chain_store(conn, &cert_chain)),
+ S2N_ERR_BAD_MESSAGE);
- s2n_pkey_type pkey_type;
+ s2n_cert_public_key public_key = { 0 };
+ POSIX_GUARD(s2n_pkey_zero_init(&public_key));
/* Determine the Cert Type, Verify the Cert, and extract the Public Key */
- POSIX_GUARD_RESULT(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, conn, client_cert_chain.data,
- client_cert_chain.size, &pkey_type, &public_key));
+ s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN;
+ POSIX_GUARD_RESULT(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, conn, cert_chain_data,
+ cert_chain_size, &pkey_type, &public_key));
conn->handshake_params.client_cert_pkey_type = pkey_type;
POSIX_GUARD(s2n_pkey_setup_for_type(&public_key, pkey_type));
POSIX_GUARD(s2n_pkey_check_key_exists(&public_key));
- POSIX_GUARD_RESULT(s2n_client_cert_chain_store(conn, &client_cert_chain));
conn->handshake_params.client_public_key = public_key;
return S2N_SUCCESS;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
index 4e3c33ed30..cbc7cbe4ba 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
@@ -20,11 +20,13 @@
#include <sys/param.h>
#include <time.h>
+#include "api/unstable/fingerprint.h"
#include "crypto/s2n_fips.h"
#include "crypto/s2n_hash.h"
#include "crypto/s2n_rsa_signing.h"
#include "error/s2n_errno.h"
#include "stuffer/s2n_stuffer.h"
+#include "tls/extensions/s2n_client_supported_groups.h"
#include "tls/extensions/s2n_extension_list.h"
#include "tls/extensions/s2n_server_key_share.h"
#include "tls/s2n_alerts.h"
@@ -42,7 +44,7 @@
struct s2n_client_hello *s2n_connection_get_client_hello(struct s2n_connection *conn)
{
- if (conn->client_hello.callback_invoked != 1) {
+ if (conn->client_hello.parsed != 1) {
return NULL;
}
@@ -243,16 +245,26 @@ static S2N_RESULT s2n_client_hello_verify_for_retry(struct s2n_connection *conn,
verify_len),
S2N_ERR_BAD_MESSAGE);
- /*
- * We need to verify the client random separately
- * because we erase it from the client hello during parsing.
- * Compare the old value to the current value.
+ /* In the past, the s2n-tls client updated the client hello in ways not
+ * allowed by RFC8446: https://github.com/aws/s2n-tls/pull/3311
+ * Although the issue was addressed, its existence means that old versions
+ * of the s2n-tls client will fail this validation.
+ *
+ * So to avoid breaking old s2n-tls clients, we do not enforce this validation
+ * outside of tests. We continue to enforce it during tests to avoid regressions.
*/
- RESULT_ENSURE(s2n_constant_time_equals(
- previous_client_random,
- conn->handshake_params.client_random,
- S2N_TLS_RANDOM_DATA_LEN),
- S2N_ERR_BAD_MESSAGE);
+ if (s2n_in_test()) {
+ /*
+ * We need to verify the client random separately
+ * because we erase it from the client hello during parsing.
+ * Compare the old value to the current value.
+ */
+ RESULT_ENSURE(s2n_constant_time_equals(
+ previous_client_random,
+ conn->handshake_params.client_random,
+ S2N_TLS_RANDOM_DATA_LEN),
+ S2N_ERR_BAD_MESSAGE);
+ }
/*
* Now enforce that the extensions also exactly match,
@@ -447,6 +459,11 @@ int s2n_parse_client_hello(struct s2n_connection *conn)
* https://tools.ietf.org/rfc/rfc8446#section-9.1
* A TLS-compliant application MUST support key exchange with secp256r1 (NIST P-256)
* and SHOULD support key exchange with X25519 [RFC7748]
+ *
+ *= https://tools.ietf.org/rfc/rfc4492#section-4
+ *# A client that proposes ECC cipher suites may choose not to include these extensions.
+ *# In this case, the server is free to choose any one of the elliptic curves or point formats listed in Section 5.
+ *
*/
const struct s2n_ecc_preferences *ecc_pref = NULL;
POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
@@ -622,6 +639,7 @@ int s2n_client_hello_recv(struct s2n_connection *conn)
/* Only parse the ClientHello once */
if (!conn->client_hello.parsed) {
POSIX_GUARD(s2n_parse_client_hello(conn));
+ /* Mark the collected client hello as available when parsing is done and before the client hello callback */
conn->client_hello.parsed = true;
}
@@ -631,7 +649,7 @@ int s2n_client_hello_recv(struct s2n_connection *conn)
* callback state may have been cleared while parsing the second ClientHello.
*/
if (!conn->client_hello.callback_invoked && !IS_HELLO_RETRY_HANDSHAKE(conn)) {
- /* Mark the collected client hello as available when parsing is done and before the client hello callback */
+ /* Mark the client hello callback as invoked to avoid calling it again. */
conn->client_hello.callback_invoked = true;
/* Call client_hello_cb if exists, letting application to modify s2n_connection or swap s2n_config */
@@ -846,7 +864,7 @@ int s2n_client_hello_get_parsed_extension(s2n_tls_extension_type extension_type,
POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type, &extension_type_id));
s2n_parsed_extension *found_parsed_extension = &parsed_extension_list->parsed_extensions[extension_type_id];
- POSIX_ENSURE_REF(found_parsed_extension->extension.data);
+ POSIX_ENSURE(found_parsed_extension->extension.data, S2N_ERR_EXTENSION_NOT_RECEIVED);
POSIX_ENSURE(found_parsed_extension->extension_type == extension_type, S2N_ERR_INVALID_PARSED_EXTENSIONS);
*parsed_extension = found_parsed_extension;
@@ -954,3 +972,34 @@ int s2n_client_hello_has_extension(struct s2n_client_hello *ch, uint16_t extensi
}
return S2N_SUCCESS;
}
+
+int s2n_client_hello_get_supported_groups(struct s2n_client_hello *ch, uint16_t *groups,
+ uint16_t groups_count_max, uint16_t *groups_count_out)
+{
+ POSIX_ENSURE_REF(groups_count_out);
+ *groups_count_out = 0;
+ POSIX_ENSURE_REF(ch);
+ POSIX_ENSURE_REF(groups);
+
+ s2n_parsed_extension *supported_groups_extension = NULL;
+ POSIX_GUARD(s2n_client_hello_get_parsed_extension(S2N_EXTENSION_SUPPORTED_GROUPS, &ch->extensions, &supported_groups_extension));
+ POSIX_ENSURE_REF(supported_groups_extension);
+
+ struct s2n_stuffer extension_stuffer = { 0 };
+ POSIX_GUARD(s2n_stuffer_init_written(&extension_stuffer, &supported_groups_extension->extension));
+
+ uint16_t supported_groups_count = 0;
+ POSIX_GUARD_RESULT(s2n_supported_groups_parse_count(&extension_stuffer, &supported_groups_count));
+ POSIX_ENSURE(supported_groups_count <= groups_count_max, S2N_ERR_INSUFFICIENT_MEM_SIZE);
+
+ for (size_t i = 0; i < supported_groups_count; i++) {
+ /* s2n_stuffer_read_uint16 is used to read each of the supported groups in network-order
+ * endianness.
+ */
+ POSIX_GUARD(s2n_stuffer_read_uint16(&extension_stuffer, &groups[i]));
+ }
+
+ *groups_count_out = supported_groups_count;
+
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.c b/contrib/restricted/aws/s2n/tls/s2n_config.c
index 80c56247aa..d9542f4765 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_config.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_config.c
@@ -16,6 +16,7 @@
#include <strings.h>
#include <time.h>
+#include "api/unstable/npn.h"
#include "crypto/s2n_certificate.h"
#include "crypto/s2n_fips.h"
#include "crypto/s2n_hkdf.h"
@@ -217,7 +218,7 @@ struct s2n_config *s2n_fetch_default_config(void)
int s2n_config_set_unsafe_for_testing(struct s2n_config *config)
{
- S2N_ERROR_IF(!S2N_IN_TEST, S2N_ERR_NOT_IN_UNIT_TEST);
+ POSIX_ENSURE(s2n_in_test(), S2N_ERR_NOT_IN_TEST);
config->client_cert_auth_type = S2N_CERT_AUTH_NONE;
config->check_ocsp = 0;
config->disable_x509_validation = 1;
@@ -450,6 +451,13 @@ int s2n_config_set_check_stapled_ocsp_response(struct s2n_config *config, uint8_
return 0;
}
+int s2n_config_disable_x509_time_verification(struct s2n_config *config)
+{
+ POSIX_ENSURE_REF(config);
+ config->disable_x509_time_validation = true;
+ return S2N_SUCCESS;
+}
+
int s2n_config_disable_x509_verification(struct s2n_config *config)
{
POSIX_ENSURE_REF(config);
@@ -518,11 +526,15 @@ static int s2n_config_add_cert_chain_and_key_impl(struct s2n_config *config, str
{
POSIX_ENSURE_REF(config->domain_name_to_cert_map);
POSIX_ENSURE_REF(cert_key_pair);
+
s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pair);
config->is_rsa_cert_configured |= (cert_type == S2N_PKEY_TYPE_RSA);
+
POSIX_GUARD(s2n_config_build_domain_name_to_cert_map(config, cert_key_pair));
if (!config->default_certs_are_explicit) {
+ POSIX_ENSURE(cert_type >= 0, S2N_ERR_CERT_TYPE_UNSUPPORTED);
+ POSIX_ENSURE(cert_type < S2N_CERT_TYPE_COUNT, S2N_ERR_CERT_TYPE_UNSUPPORTED);
/* Attempt to auto set default based on ordering. ie: first RSA cert is the default, first ECDSA cert is the
* default, etc. */
if (config->default_certs_by_type.certs[cert_type] == NULL) {
@@ -1116,3 +1128,13 @@ int s2n_config_set_recv_multi_record(struct s2n_config *config, bool enabled)
return S2N_SUCCESS;
}
+
+int s2n_config_set_cert_validation_cb(struct s2n_config *config, s2n_cert_validation_callback cb, void *ctx)
+{
+ POSIX_ENSURE_REF(config);
+
+ config->cert_validation_cb = cb;
+ config->cert_validation_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 176d6a16e5..3b4cbf49ed 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_config.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_config.h
@@ -66,6 +66,7 @@ struct s2n_config {
/* if this is FALSE, server will ignore client's Maximum Fragment Length request */
unsigned accept_mfl : 1;
unsigned check_ocsp : 1;
+ unsigned disable_x509_time_validation : 1;
unsigned disable_x509_validation : 1;
unsigned max_verify_cert_chain_depth_set : 1;
/* Whether to add dss cert type during a server certificate request.
@@ -152,6 +153,9 @@ struct s2n_config {
s2n_crl_lookup_callback crl_lookup_cb;
void *crl_lookup_ctx;
+ s2n_cert_validation_callback cert_validation_cb;
+ void *cert_validation_ctx;
+
/* Application supplied callback to resolve domain name conflicts when loading certs. */
s2n_cert_tiebreak_callback cert_tiebreak_cb;
@@ -193,9 +197,6 @@ struct s2n_config {
s2n_renegotiate_request_cb renegotiate_request_cb;
};
-struct s2n_config *s2n_config_new_minimal(void);
-int s2n_config_load_system_certs(struct s2n_config *config);
-
S2N_CLEANUP_RESULT s2n_config_ptr_free(struct s2n_config **config);
int s2n_config_defaults_init(void);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.c b/contrib/restricted/aws/s2n/tls/s2n_connection.c
index 07768e2075..5d499cbbd1 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection.c
@@ -43,8 +43,10 @@
#include "tls/s2n_security_policies.h"
#include "tls/s2n_tls.h"
#include "tls/s2n_tls_parameters.h"
+#include "utils/s2n_atomic.h"
#include "utils/s2n_blob.h"
#include "utils/s2n_compiler.h"
+#include "utils/s2n_io.h"
#include "utils/s2n_mem.h"
#include "utils/s2n_random.h"
#include "utils/s2n_safety.h"
@@ -80,14 +82,6 @@ struct s2n_connection *s2n_connection_new(s2n_mode mode)
PTR_GUARD_POSIX(s2n_stuffer_init(&conn->alert_in, &blob));
blob = (struct s2n_blob){ 0 };
- PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->reader_alert_out_data, S2N_ALERT_LENGTH));
- PTR_GUARD_POSIX(s2n_stuffer_init(&conn->reader_alert_out, &blob));
-
- blob = (struct s2n_blob){ 0 };
- PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->writer_alert_out_data, S2N_ALERT_LENGTH));
- PTR_GUARD_POSIX(s2n_stuffer_init(&conn->writer_alert_out, &blob));
-
- blob = (struct s2n_blob){ 0 };
PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->ticket_ext_data, S2N_TLS12_TICKET_SIZE_IN_BYTES));
PTR_GUARD_POSIX(s2n_stuffer_init(&conn->client_ticket_to_decrypt, &blob));
@@ -359,6 +353,8 @@ int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *co
* However, the s2n_config_set_verification_ca_location behavior predates client authentication
* support for OCSP stapling, so could only affect whether clients requested OCSP stapling. We
* therefore only have to maintain the legacy behavior for clients, not servers.
+ *
+ * Note: The Rust bindings do not maintain the legacy behavior.
*/
conn->request_ocsp_status = config->ocsp_status_requested_by_user;
if (config->ocsp_status_requested_by_s2n && conn->mode == S2N_CLIENT) {
@@ -456,8 +452,6 @@ int s2n_connection_wipe(struct s2n_connection *conn)
int mode = conn->mode;
struct s2n_config *config = conn->config;
struct s2n_stuffer alert_in = { 0 };
- struct s2n_stuffer reader_alert_out = { 0 };
- struct s2n_stuffer writer_alert_out = { 0 };
struct s2n_stuffer client_ticket_to_decrypt = { 0 };
struct s2n_stuffer handshake_io = { 0 };
struct s2n_stuffer header_in = { 0 };
@@ -493,8 +487,6 @@ int s2n_connection_wipe(struct s2n_connection *conn)
/* Wipe all of the sensitive stuff */
POSIX_GUARD(s2n_connection_wipe_keys(conn));
POSIX_GUARD(s2n_stuffer_wipe(&conn->alert_in));
- POSIX_GUARD(s2n_stuffer_wipe(&conn->reader_alert_out));
- POSIX_GUARD(s2n_stuffer_wipe(&conn->writer_alert_out));
POSIX_GUARD(s2n_stuffer_wipe(&conn->client_ticket_to_decrypt));
POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
POSIX_GUARD(s2n_stuffer_wipe(&conn->post_handshake.in));
@@ -535,29 +527,24 @@ int s2n_connection_wipe(struct s2n_connection *conn)
conn->data_for_verify_host = NULL;
/* Clone the stuffers */
- /* ignore gcc 4.7 address warnings because dest is allocated on the stack */
- /* pragma gcc diagnostic was added in gcc 4.6 */
-#if S2N_GCC_VERSION_AT_LEAST(4, 6, 0)
+ /* ignore address warnings because dest is allocated on the stack */
+#ifdef S2N_DIAGNOSTICS_PUSH_SUPPORTED
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
#endif
POSIX_CHECKED_MEMCPY(&alert_in, &conn->alert_in, sizeof(struct s2n_stuffer));
- POSIX_CHECKED_MEMCPY(&reader_alert_out, &conn->reader_alert_out, sizeof(struct s2n_stuffer));
- POSIX_CHECKED_MEMCPY(&writer_alert_out, &conn->writer_alert_out, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&client_ticket_to_decrypt, &conn->client_ticket_to_decrypt, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&handshake_io, &conn->handshake.io, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&header_in, &conn->header_in, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&in, &conn->in, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&out, &conn->out, sizeof(struct s2n_stuffer));
-#if S2N_GCC_VERSION_AT_LEAST(4, 6, 0)
+#ifdef S2N_DIAGNOSTICS_POP_SUPPORTED
#pragma GCC diagnostic pop
#endif
POSIX_GUARD(s2n_connection_zero(conn, mode, config));
POSIX_CHECKED_MEMCPY(&conn->alert_in, &alert_in, sizeof(struct s2n_stuffer));
- POSIX_CHECKED_MEMCPY(&conn->reader_alert_out, &reader_alert_out, sizeof(struct s2n_stuffer));
- POSIX_CHECKED_MEMCPY(&conn->writer_alert_out, &writer_alert_out, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->client_ticket_to_decrypt, &client_ticket_to_decrypt, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->handshake.io, &handshake_io, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->header_in, &header_in, sizeof(struct s2n_stuffer));
@@ -867,11 +854,17 @@ int s2n_connection_use_corked_io(struct s2n_connection *conn)
uint64_t s2n_connection_get_wire_bytes_in(struct s2n_connection *conn)
{
+ if (conn->ktls_recv_enabled) {
+ return 0;
+ }
return conn->wire_bytes_in;
}
uint64_t s2n_connection_get_wire_bytes_out(struct s2n_connection *conn)
{
+ if (conn->ktls_send_enabled) {
+ return 0;
+ }
return conn->wire_bytes_out;
}
@@ -1076,21 +1069,37 @@ int s2n_connection_set_blinding(struct s2n_connection *conn, s2n_blinding blindi
#define ONE_S INT64_C(1000000000)
#define TEN_S INT64_C(10000000000)
-uint64_t s2n_connection_get_delay(struct s2n_connection *conn)
+static S2N_RESULT s2n_connection_get_delay_impl(struct s2n_connection *conn, uint64_t *delay)
{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(delay);
+
if (!conn->delay) {
- return 0;
+ *delay = 0;
+ return S2N_RESULT_OK;
}
- uint64_t elapsed;
- /* This will cast -1 to max uint64_t */
- POSIX_GUARD_RESULT(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed));
+ uint64_t elapsed = 0;
+ RESULT_GUARD(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed));
if (elapsed > conn->delay) {
- return 0;
+ *delay = 0;
+ return S2N_RESULT_OK;
}
- return conn->delay - elapsed;
+ *delay = conn->delay - elapsed;
+
+ return S2N_RESULT_OK;
+}
+
+uint64_t s2n_connection_get_delay(struct s2n_connection *conn)
+{
+ uint64_t delay = 0;
+ if (s2n_result_is_ok(s2n_connection_get_delay_impl(conn, &delay))) {
+ return delay;
+ } else {
+ return UINT64_MAX;
+ }
}
static S2N_RESULT s2n_connection_kill(struct s2n_connection *conn)
@@ -1152,6 +1161,7 @@ S2N_CLEANUP_RESULT s2n_connection_apply_error_blinding(struct s2n_connection **c
*
* We may want to someday add an explicit error type for these errors.
*/
+ case S2N_ERR_CLOSED:
case S2N_ERR_CANCELLED:
case S2N_ERR_CIPHER_NOT_SUPPORTED:
case S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED:
@@ -1169,8 +1179,8 @@ S2N_CLEANUP_RESULT s2n_connection_apply_error_blinding(struct s2n_connection **c
S2N_RESULT s2n_connection_set_closed(struct s2n_connection *conn)
{
RESULT_ENSURE_REF(conn);
- conn->read_closed = 1;
- conn->write_closed = 1;
+ s2n_atomic_flag_set(&conn->read_closed);
+ s2n_atomic_flag_set(&conn->write_closed);
return S2N_RESULT_OK;
}
@@ -1258,11 +1268,9 @@ int s2n_connection_recv_stuffer(struct s2n_stuffer *stuffer, struct s2n_connecti
POSIX_GUARD(s2n_stuffer_reserve_space(stuffer, len));
int r = 0;
- do {
- errno = 0;
- r = conn->recv(conn->recv_io_context, stuffer->blob.data + stuffer->write_cursor, len);
- S2N_ERROR_IF(r < 0 && errno != EINTR, S2N_ERR_RECV_STUFFER_FROM_CONN);
- } while (r < 0);
+ S2N_IO_RETRY_EINTR(r,
+ conn->recv(conn->recv_io_context, stuffer->blob.data + stuffer->write_cursor, len));
+ POSIX_ENSURE(r >= 0, S2N_ERR_RECV_STUFFER_FROM_CONN);
/* Record just how many bytes we have written */
POSIX_GUARD(s2n_stuffer_skip_write(stuffer, r));
@@ -1280,14 +1288,12 @@ int s2n_connection_send_stuffer(struct s2n_stuffer *stuffer, struct s2n_connecti
S2N_ERROR_IF(s2n_stuffer_data_available(stuffer) < len, S2N_ERR_STUFFER_OUT_OF_DATA);
int w = 0;
- do {
- errno = 0;
- w = conn->send(conn->send_io_context, stuffer->blob.data + stuffer->read_cursor, len);
- if (w < 0 && errno == EPIPE) {
- conn->write_fd_broken = 1;
- }
- S2N_ERROR_IF(w < 0 && errno != EINTR, S2N_ERR_SEND_STUFFER_TO_CONN);
- } while (w < 0);
+ S2N_IO_RETRY_EINTR(w,
+ conn->send(conn->send_io_context, stuffer->blob.data + stuffer->read_cursor, len));
+ if (w < 0 && errno == EPIPE) {
+ conn->write_fd_broken = 1;
+ }
+ POSIX_ENSURE(w >= 0, S2N_ERR_SEND_STUFFER_TO_CONN);
POSIX_GUARD(s2n_stuffer_skip_read(stuffer, w));
return w;
@@ -1346,10 +1352,15 @@ int s2n_connection_get_peer_cert_chain(const struct s2n_connection *conn, struct
{
POSIX_ENSURE_REF(conn);
POSIX_ENSURE_REF(cert_chain_and_key);
+ POSIX_ENSURE_REF(cert_chain_and_key->cert_chain);
+
+ /* Ensure that cert_chain_and_key is empty BEFORE we modify it in any way.
+ * That includes before tying its cert_chain to DEFER_CLEANUP.
+ */
+ POSIX_ENSURE(cert_chain_and_key->cert_chain->head == NULL, S2N_ERR_INVALID_ARGUMENT);
DEFER_CLEANUP(struct s2n_cert_chain *cert_chain = cert_chain_and_key->cert_chain, s2n_cert_chain_free_pointer);
struct s2n_cert **insert = &cert_chain->head;
- POSIX_ENSURE(*insert == NULL, S2N_ERR_INVALID_ARGUMENT);
const struct s2n_x509_validator *validator = &conn->x509_validator;
POSIX_ENSURE_REF(validator);
@@ -1548,7 +1559,9 @@ bool s2n_connection_check_io_status(struct s2n_connection *conn, s2n_io_status s
return false;
}
- const bool is_full_duplex = !conn->read_closed && !conn->write_closed;
+ bool read_closed = s2n_atomic_flag_test(&conn->read_closed);
+ bool write_closed = s2n_atomic_flag_test(&conn->write_closed);
+ bool full_duplex = !read_closed && !write_closed;
/*
*= https://tools.ietf.org/rfc/rfc8446#section-6.1
@@ -1562,22 +1575,33 @@ bool s2n_connection_check_io_status(struct s2n_connection *conn, s2n_io_status s
case S2N_IO_WRITABLE:
case S2N_IO_READABLE:
case S2N_IO_FULL_DUPLEX:
- return is_full_duplex;
+ return full_duplex;
case S2N_IO_CLOSED:
- return !is_full_duplex;
+ return !full_duplex;
}
}
switch (status) {
case S2N_IO_WRITABLE:
- return !conn->write_closed;
+ return !write_closed;
case S2N_IO_READABLE:
- return !conn->read_closed;
+ return !read_closed;
case S2N_IO_FULL_DUPLEX:
- return is_full_duplex;
+ return full_duplex;
case S2N_IO_CLOSED:
- return conn->read_closed && conn->write_closed;
+ return read_closed && write_closed;
}
return false;
}
+
+S2N_RESULT s2n_connection_get_secure_cipher(struct s2n_connection *conn, const struct s2n_cipher **cipher)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(cipher);
+ RESULT_ENSURE_REF(conn->secure);
+ RESULT_ENSURE_REF(conn->secure->cipher_suite);
+ RESULT_ENSURE_REF(conn->secure->cipher_suite->record_alg);
+ *cipher = conn->secure->cipher_suite->record_alg->cipher;
+ return S2N_RESULT_OK;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.h b/contrib/restricted/aws/s2n/tls/s2n_connection.h
index e177889b63..87938a85ee 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection.h
@@ -39,6 +39,7 @@
#include "tls/s2n_security_policies.h"
#include "tls/s2n_tls_parameters.h"
#include "tls/s2n_x509_validator.h"
+#include "utils/s2n_atomic.h"
#include "utils/s2n_mem.h"
#include "utils/s2n_timer.h"
@@ -66,9 +67,6 @@ struct s2n_connection {
/* Connection can be used by a QUIC implementation */
unsigned quic_enabled : 1;
- /* Determines if we're currently sending or receiving in s2n_shutdown */
- unsigned close_notify_queued : 1;
-
/* s2n does not support renegotiation.
* RFC5746 Section 4.3 suggests servers implement a minimal version of the
* renegotiation_info extension even if renegotiation is not supported.
@@ -96,9 +94,6 @@ struct s2n_connection {
unsigned managed_send_io : 1;
unsigned managed_recv_io : 1;
- /* Key update data */
- unsigned key_update_pending : 1;
-
/* Early data supported by caller.
* If a caller does not use any APIs that support early data,
* do not negotiate early data.
@@ -113,9 +108,6 @@ struct s2n_connection {
* even when setting a new config. */
unsigned psk_mode_overridden : 1;
- /* Have we received a close notify alert from the peer. */
- unsigned close_notify_received : 1;
-
/* Connection negotiated an EMS */
unsigned ems_negotiated : 1;
@@ -267,18 +259,17 @@ struct s2n_connection {
uint8_t alert_in_data[S2N_ALERT_LENGTH];
struct s2n_stuffer alert_in;
- /* An alert may be partially written in the outbound
- * direction, so we keep this as a small 2 byte queue.
- *
- * We keep separate queues for alerts generated by
- * readers (a response to an alert from a peer) and writers (an
- * intentional shutdown) so that the s2n reader and writer
- * can be separate duplex I/O threads.
+ /* Both readers and writers can trigger alerts.
+ * We prioritize writer alerts over reader alerts.
*/
- uint8_t reader_alert_out_data[S2N_ALERT_LENGTH];
- uint8_t writer_alert_out_data[S2N_ALERT_LENGTH];
- struct s2n_stuffer reader_alert_out;
- struct s2n_stuffer writer_alert_out;
+ uint8_t writer_alert_out;
+ uint8_t reader_alert_out;
+ uint8_t reader_warning_out;
+ bool alert_sent;
+
+ /* Receiving error or close_notify alerts changes the behavior of s2n_shutdown_send */
+ s2n_atomic_flag error_alert_received;
+ s2n_atomic_flag close_notify_received;
/* Our handshake state machine */
struct s2n_handshake handshake;
@@ -316,14 +307,11 @@ struct s2n_connection {
uint64_t wire_bytes_out;
uint64_t early_data_bytes;
- /* Is the connection open or closed?
- *
- * We use C's only atomic type as an error requires shutting down both read
- * and write, so both the reader and writer threads may access both fields.
+ /* Either the reader or the writer can trigger both sides of the connection
+ * to close in response to a fatal error.
*/
- sig_atomic_t read_closed;
- sig_atomic_t write_closing;
- sig_atomic_t write_closed;
+ s2n_atomic_flag read_closed;
+ s2n_atomic_flag write_closed;
/* TLS extension data */
char server_name[S2N_MAX_SERVER_NAME + 1];
@@ -391,6 +379,10 @@ struct s2n_connection {
uint32_t server_keying_material_lifetime;
struct s2n_post_handshake post_handshake;
+ /* Both the reader and writer can set key_update_pending.
+ * The writer clears it after a KeyUpdate is sent.
+ */
+ s2n_atomic_flag key_update_pending;
};
S2N_CLEANUP_RESULT s2n_connection_ptr_free(struct s2n_connection **s2n_connection);
@@ -429,3 +421,4 @@ int s2n_connection_get_client_cert_chain(struct s2n_connection *conn, uint8_t **
int s2n_connection_get_peer_cert_chain(const struct s2n_connection *conn, struct s2n_cert_chain_and_key *cert_chain_and_key);
uint8_t s2n_connection_get_protocol_version(const struct s2n_connection *conn);
S2N_RESULT s2n_connection_set_max_fragment_length(struct s2n_connection *conn, uint16_t length);
+S2N_RESULT s2n_connection_get_secure_cipher(struct s2n_connection *conn, const struct s2n_cipher **cipher);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c b/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c
index 8c7730b829..b99ce78823 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c
@@ -146,9 +146,11 @@ static bool s2n_early_data_can_continue(struct s2n_connection *conn)
&& remaining_early_data_size > 0;
}
-S2N_RESULT s2n_send_early_data_impl(struct s2n_connection *conn, const uint8_t *data, ssize_t data_len,
+S2N_RESULT s2n_send_early_data_impl(struct s2n_connection *conn, const uint8_t *data, ssize_t data_len_signed,
ssize_t *data_sent, s2n_blocked_status *blocked)
{
+ RESULT_ENSURE_GTE(data_len_signed, 0);
+ size_t data_len = data_len_signed;
RESULT_ENSURE_REF(conn);
RESULT_ENSURE_REF(blocked);
*blocked = S2N_NOT_BLOCKED;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c
index 8781afcc55..3c923d0f99 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c
@@ -33,6 +33,15 @@ const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20200310[] = {
&s2n_ecc_curve_secp384r1,
};
+/* Curve p256 is at the top of the list in order to minimize HRR */
+const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20230623[] = {
+ &s2n_ecc_curve_secp256r1,
+#if EVP_APIS_SUPPORTED
+ &s2n_ecc_curve_x25519,
+#endif
+ &s2n_ecc_curve_secp384r1,
+};
+
/*
* These curves were chosen based on the following specification:
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-52r2.pdf
@@ -71,6 +80,11 @@ const struct s2n_ecc_preferences s2n_ecc_preferences_20200310 = {
.ecc_curves = s2n_ecc_pref_list_20200310,
};
+const struct s2n_ecc_preferences s2n_ecc_preferences_20230623 = {
+ .count = s2n_array_len(s2n_ecc_pref_list_20230623),
+ .ecc_curves = s2n_ecc_pref_list_20230623,
+};
+
const struct s2n_ecc_preferences s2n_ecc_preferences_default_fips = {
.count = s2n_array_len(s2n_ecc_pref_list_default_fips),
.ecc_curves = s2n_ecc_pref_list_default_fips,
diff --git a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h
index 988991755a..9f84772359 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h
@@ -27,6 +27,7 @@ struct s2n_ecc_preferences {
};
extern const struct s2n_ecc_preferences s2n_ecc_preferences_20140601;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_20200310;
+extern const struct s2n_ecc_preferences s2n_ecc_preferences_20230623;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_default_fips;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_20201021;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_20210816;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
index 6bc5d16d12..79cbd6a5e2 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
@@ -1046,7 +1046,7 @@ int s2n_conn_set_handshake_type(struct s2n_connection *conn)
if (conn->config->use_tickets) {
if (conn->session_ticket_status == S2N_DECRYPT_TICKET) {
- /* We reuse the session if a valid TLS12 ticket is provided.
+ /* We reuse the session if a valid TLS12 ticket is provided.
* Otherwise, we will perform a full handshake and then generate
* a new session ticket. */
if (s2n_decrypt_session_ticket(conn, &conn->client_ticket_to_decrypt) == S2N_SUCCESS) {
@@ -1639,7 +1639,7 @@ int s2n_negotiate_impl(struct s2n_connection *conn, s2n_blocked_status *blocked)
/* Non-retryable write error. The peer might have sent an alert. Try and read it. */
const int write_errno = errno;
const int write_s2n_errno = s2n_errno;
- const char *write_s2n_debug_str = s2n_debug_str;
+ struct s2n_debug_info write_s2n_debug_info = _s2n_debug_info;
if (s2n_handshake_read_io(conn) < 0 && s2n_errno == S2N_ERR_ALERT) {
/* s2n_handshake_read_io has set s2n_errno */
@@ -1648,7 +1648,7 @@ int s2n_negotiate_impl(struct s2n_connection *conn, s2n_blocked_status *blocked)
/* Let the write error take precedence if we didn't read an alert. */
errno = write_errno;
s2n_errno = write_s2n_errno;
- s2n_debug_str = write_s2n_debug_str;
+ _s2n_debug_info = write_s2n_debug_info;
S2N_ERROR_PRESERVE_ERRNO();
}
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem.c b/contrib/restricted/aws/s2n/tls/s2n_kem.c
index 8f75289004..8a72597daf 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kem.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_kem.c
@@ -15,7 +15,7 @@
#include "tls/s2n_kem.h"
-#include "pq-crypto/s2n_kyber_512_evp.h"
+#include "pq-crypto/s2n_kyber_evp.h"
#include "pq-crypto/s2n_pq.h"
#include "stuffer/s2n_stuffer.h"
#include "tls/extensions/s2n_key_share.h"
@@ -23,19 +23,61 @@
#include "utils/s2n_mem.h"
#include "utils/s2n_safety.h"
+/* If S2N_NO_PQ is set or linked libcrypto doesn't support Kyber, bail on KEM calls.
+ * These should never be called.
+ */
+int s2n_kyber_kem_keypair_not_supported(IN const struct s2n_kem *kem, OUT uint8_t *pk, OUT uint8_t *sk)
+{
+ POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
+}
+int s2n_kyber_kem_enc_not_supported(IN const struct s2n_kem *kem, OUT uint8_t *ct, OUT uint8_t *ss,
+ IN const uint8_t *pk)
+{
+ POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
+}
+int s2n_kyber_kem_dec_not_supported(IN const struct s2n_kem *kem, OUT uint8_t *ss, IN const uint8_t *ct,
+ IN const uint8_t *sk)
+{
+ POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
+}
+
+#if defined(S2N_NO_PQ)
+/* If S2N_NO_PQ was defined at compile time, the PQ KEM code will have been entirely excluded
+ * from compilation. We define stubs of these functions here to error if they are called. */
+int s2n_kyber_512_r3_crypto_kem_keypair(IN const struct s2n_kem *kem, OUT uint8_t *pk, OUT uint8_t *sk)
+{
+ return s2n_kyber_kem_keypair_not_supported(kem, pk, sk);
+}
+int s2n_kyber_512_r3_crypto_kem_enc(IN const struct s2n_kem *kem, OUT uint8_t *ct, OUT uint8_t *ss,
+ IN const uint8_t *pk)
+{
+ return s2n_kyber_kem_enc_not_supported(kem, ct, ss, pk);
+}
+int s2n_kyber_512_r3_crypto_kem_dec(IN const struct s2n_kem *kem, OUT uint8_t *ss, IN const uint8_t *ct,
+ IN const uint8_t *sk)
+{
+ return s2n_kyber_kem_dec_not_supported(kem, ss, ct, sk);
+}
+#endif
+
/* The KEM IDs and names come from https://tools.ietf.org/html/draft-campagna-tls-bike-sike-hybrid */
const struct s2n_kem s2n_kyber_512_r3 = {
.name = "kyber512r3",
+#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER)
+ .kem_nid = NID_KYBER512_R3,
+#else
+ .kem_nid = NID_undef,
+#endif
.kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_KYBER_512_R3,
.public_key_length = S2N_KYBER_512_R3_PUBLIC_KEY_BYTES,
.private_key_length = S2N_KYBER_512_R3_SECRET_KEY_BYTES,
.shared_secret_key_length = S2N_KYBER_512_R3_SHARED_SECRET_BYTES,
.ciphertext_length = S2N_KYBER_512_R3_CIPHERTEXT_BYTES,
-#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER512)
- .generate_keypair = &s2n_kyber_512_evp_generate_keypair,
- .encapsulate = &s2n_kyber_512_evp_encapsulate,
- .decapsulate = &s2n_kyber_512_evp_decapsulate,
+#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER) && !defined(S2N_NO_PQ)
+ .generate_keypair = &s2n_kyber_evp_generate_keypair,
+ .encapsulate = &s2n_kyber_evp_encapsulate,
+ .decapsulate = &s2n_kyber_evp_decapsulate,
#else
.generate_keypair = &s2n_kyber_512_r3_crypto_kem_keypair,
.encapsulate = &s2n_kyber_512_r3_crypto_kem_enc,
@@ -43,16 +85,62 @@ const struct s2n_kem s2n_kyber_512_r3 = {
#endif
};
-const struct s2n_kem *kyber_kems[] = {
+const struct s2n_kem s2n_kyber_768_r3 = {
+ .name = "kyber768r3",
+#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER)
+ .kem_nid = NID_KYBER768_R3,
+#else
+ .kem_nid = NID_undef,
+#endif
+ .kem_extension_id = 0, /* This is not used in TLS 1.2's KEM extension */
+ .public_key_length = S2N_KYBER_768_R3_PUBLIC_KEY_BYTES,
+ .private_key_length = S2N_KYBER_768_R3_SECRET_KEY_BYTES,
+ .shared_secret_key_length = S2N_KYBER_768_R3_SHARED_SECRET_BYTES,
+ .ciphertext_length = S2N_KYBER_768_R3_CIPHERTEXT_BYTES,
+#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER) && !defined(S2N_NO_PQ)
+ .generate_keypair = &s2n_kyber_evp_generate_keypair,
+ .encapsulate = &s2n_kyber_evp_encapsulate,
+ .decapsulate = &s2n_kyber_evp_decapsulate,
+#else
+ .generate_keypair = &s2n_kyber_kem_keypair_not_supported,
+ .encapsulate = &s2n_kyber_kem_enc_not_supported,
+ .decapsulate = &s2n_kyber_kem_dec_not_supported,
+#endif
+};
+
+const struct s2n_kem s2n_kyber_1024_r3 = {
+ .name = "kyber1024r3",
+#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER)
+ .kem_nid = NID_KYBER1024_R3,
+#else
+ .kem_nid = NID_undef,
+#endif
+ .kem_extension_id = 0, /* This is not used in TLS 1.2's KEM extension */
+ .public_key_length = S2N_KYBER_1024_R3_PUBLIC_KEY_BYTES,
+ .private_key_length = S2N_KYBER_1024_R3_SECRET_KEY_BYTES,
+ .shared_secret_key_length = S2N_KYBER_1024_R3_SHARED_SECRET_BYTES,
+ .ciphertext_length = S2N_KYBER_1024_R3_CIPHERTEXT_BYTES,
+#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER) && !defined(S2N_NO_PQ)
+ .generate_keypair = &s2n_kyber_evp_generate_keypair,
+ .encapsulate = &s2n_kyber_evp_encapsulate,
+ .decapsulate = &s2n_kyber_evp_decapsulate,
+#else
+ .generate_keypair = &s2n_kyber_kem_keypair_not_supported,
+ .encapsulate = &s2n_kyber_kem_enc_not_supported,
+ .decapsulate = &s2n_kyber_kem_dec_not_supported,
+#endif
+};
+
+const struct s2n_kem *tls12_kyber_kems[] = {
&s2n_kyber_512_r3,
};
-const struct s2n_iana_to_kem kem_mapping[3] = {
+const struct s2n_iana_to_kem kem_mapping[1] = {
{
.iana_value = { TLS_ECDHE_KYBER_RSA_WITH_AES_256_GCM_SHA384 },
- .kems = kyber_kems,
- .kem_count = s2n_array_len(kyber_kems),
- }
+ .kems = tls12_kyber_kems,
+ .kem_count = s2n_array_len(tls12_kyber_kems),
+ },
};
/* Specific assignments of KEM group IDs and names have not yet been
@@ -60,7 +148,9 @@ const struct s2n_iana_to_kem kem_mapping[3] = {
* community to use values in the proposed reserved range defined in
* https://tools.ietf.org/html/draft-stebila-tls-hybrid-design.
* Values for interoperability are defined in
- * https://github.com/open-quantum-safe/openssl/blob/OQS-OpenSSL_1_1_1-stable/oqs-template/oqs-kem-info.md
+ * https://github.com/open-quantum-safe/oqs-provider/blob/main/oqs-template/oqs-kem-info.md
+ * and
+ * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
*
* The structure of the hybrid share is:
* size of ECC key share (2 bytes)
@@ -74,16 +164,40 @@ const struct s2n_kem_group s2n_secp256r1_kyber_512_r3 = {
.kem = &s2n_kyber_512_r3,
};
-#if EVP_APIS_SUPPORTED
+const struct s2n_kem_group s2n_secp256r1_kyber_768_r3 = {
+ .name = "SecP256r1Kyber768Draft00",
+ .iana_id = TLS_PQ_KEM_GROUP_ID_SECP256R1_KYBER_768_R3,
+ .curve = &s2n_ecc_curve_secp256r1,
+ .kem = &s2n_kyber_768_r3,
+};
+
+const struct s2n_kem_group s2n_secp384r1_kyber_768_r3 = {
+ .name = "secp384r1_kyber-768-r3",
+ .iana_id = TLS_PQ_KEM_GROUP_ID_SECP384R1_KYBER_768_R3,
+ .curve = &s2n_ecc_curve_secp384r1,
+ .kem = &s2n_kyber_768_r3,
+};
+
+const struct s2n_kem_group s2n_secp521r1_kyber_1024_r3 = {
+ .name = "secp521r1_kyber-1024-r3",
+ .iana_id = TLS_PQ_KEM_GROUP_ID_SECP521R1_KYBER_1024_R3,
+ .curve = &s2n_ecc_curve_secp521r1,
+ .kem = &s2n_kyber_1024_r3,
+};
+
const struct s2n_kem_group s2n_x25519_kyber_512_r3 = {
.name = "x25519_kyber-512-r3",
.iana_id = TLS_PQ_KEM_GROUP_ID_X25519_KYBER_512_R3,
.curve = &s2n_ecc_curve_x25519,
.kem = &s2n_kyber_512_r3,
};
-#else
-const struct s2n_kem_group s2n_x25519_kyber_512_r3 = { 0 };
-#endif
+
+const struct s2n_kem_group s2n_x25519_kyber_768_r3 = {
+ .name = "X25519Kyber768Draft00",
+ .iana_id = TLS_PQ_KEM_GROUP_ID_X25519_KYBER_768_R3,
+ .curve = &s2n_ecc_curve_x25519,
+ .kem = &s2n_kyber_768_r3,
+};
const struct s2n_kem_group *ALL_SUPPORTED_KEM_GROUPS[S2N_SUPPORTED_KEM_GROUPS_COUNT] = {
&s2n_secp256r1_kyber_512_r3,
@@ -91,6 +205,15 @@ const struct s2n_kem_group *ALL_SUPPORTED_KEM_GROUPS[S2N_SUPPORTED_KEM_GROUPS_CO
#if EVP_APIS_SUPPORTED
&s2n_x25519_kyber_512_r3,
#endif
+/* Kyber 768+ is only available from libcrypto */
+#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER)
+ &s2n_secp256r1_kyber_768_r3,
+ &s2n_secp384r1_kyber_768_r3,
+ &s2n_secp521r1_kyber_1024_r3,
+#endif
+#if EVP_APIS_SUPPORTED && defined(S2N_LIBCRYPTO_SUPPORTS_KYBER)
+ &s2n_x25519_kyber_768_r3,
+#endif
};
/* Helper safety macro to call the NIST PQ KEM functions. The NIST
@@ -110,7 +233,7 @@ S2N_RESULT s2n_kem_generate_keypair(struct s2n_kem_params *kem_params)
/* Need to save the private key for decapsulation */
RESULT_GUARD_POSIX(s2n_realloc(&kem_params->private_key, kem->private_key_length));
- GUARD_PQ_AS_RESULT(kem->generate_keypair(kem_params->public_key.data, kem_params->private_key.data));
+ GUARD_PQ_AS_RESULT(kem->generate_keypair(kem, kem_params->public_key.data, kem_params->private_key.data));
return S2N_RESULT_OK;
}
@@ -131,7 +254,7 @@ S2N_RESULT s2n_kem_encapsulate(struct s2n_kem_params *kem_params, struct s2n_blo
/* Need to save the shared secret for key derivation */
RESULT_GUARD_POSIX(s2n_alloc(&(kem_params->shared_secret), kem->shared_secret_key_length));
- GUARD_PQ_AS_RESULT(kem->encapsulate(ciphertext->data, kem_params->shared_secret.data, kem_params->public_key.data));
+ GUARD_PQ_AS_RESULT(kem->encapsulate(kem, ciphertext->data, kem_params->shared_secret.data, kem_params->public_key.data));
return S2N_RESULT_OK;
}
@@ -152,7 +275,7 @@ S2N_RESULT s2n_kem_decapsulate(struct s2n_kem_params *kem_params, const struct s
/* Need to save the shared secret for key derivation */
RESULT_GUARD_POSIX(s2n_alloc(&(kem_params->shared_secret), kem->shared_secret_key_length));
- GUARD_PQ_AS_RESULT(kem->decapsulate(kem_params->shared_secret.data, ciphertext->data, kem_params->private_key.data));
+ GUARD_PQ_AS_RESULT(kem->decapsulate(kem, kem_params->shared_secret.data, ciphertext->data, kem_params->private_key.data));
return S2N_RESULT_OK;
}
@@ -373,21 +496,3 @@ int s2n_kem_recv_ciphertext(struct s2n_stuffer *in, struct s2n_kem_params *kem_p
return S2N_SUCCESS;
}
-
-#if defined(S2N_NO_PQ)
-/* If S2N_NO_PQ was defined at compile time, the PQ KEM code will have been entirely excluded
- * from compilation. We define stubs of these functions here to error if they are called. */
-/* kyber512r3 */
-int s2n_kyber_512_r3_crypto_kem_keypair(OUT uint8_t *pk, OUT uint8_t *sk)
-{
- POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
-}
-int s2n_kyber_512_r3_crypto_kem_enc(OUT uint8_t *ct, OUT uint8_t *ss, IN const uint8_t *pk)
-{
- POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
-}
-int s2n_kyber_512_r3_crypto_kem_dec(OUT uint8_t *ss, IN const uint8_t *ct, IN const uint8_t *sk)
-{
- POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
-}
-#endif
diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem.h b/contrib/restricted/aws/s2n/tls/s2n_kem.h
index 4387c4a280..0f83c12ba2 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kem.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_kem.h
@@ -33,15 +33,16 @@ typedef uint16_t kem_ciphertext_key_size;
struct s2n_kem {
const char *name;
+ int kem_nid;
const kem_extension_size kem_extension_id;
const kem_public_key_size public_key_length;
const kem_private_key_size private_key_length;
const kem_shared_secret_size shared_secret_key_length;
const kem_ciphertext_key_size ciphertext_length;
/* NIST Post Quantum KEM submissions require the following API for compatibility */
- int (*generate_keypair)(OUT uint8_t *public_key, OUT uint8_t *private_key);
- int (*encapsulate)(OUT uint8_t *ciphertext, OUT uint8_t *shared_secret, IN const uint8_t *public_key);
- int (*decapsulate)(OUT uint8_t *shared_secret, IN const uint8_t *ciphertext, IN const uint8_t *private_key);
+ int (*generate_keypair)(IN const struct s2n_kem *kem, OUT uint8_t *public_key, OUT uint8_t *private_key);
+ int (*encapsulate)(IN const struct s2n_kem *kem, OUT uint8_t *ciphertext, OUT uint8_t *shared_secret, IN const uint8_t *public_key);
+ int (*decapsulate)(IN const struct s2n_kem *kem, OUT uint8_t *shared_secret, IN const uint8_t *ciphertext, IN const uint8_t *private_key);
};
struct s2n_kem_params {
@@ -74,9 +75,16 @@ struct s2n_kem_group_params {
};
extern const struct s2n_kem s2n_kyber_512_r3;
+extern const struct s2n_kem s2n_kyber_768_r3;
+extern const struct s2n_kem s2n_kyber_1024_r3;
/* x25519 based tls13_kem_groups require EVP_APIS_SUPPORTED */
-#if EVP_APIS_SUPPORTED
+/* Kyber758+ requires S2N_LIBCRYPTO_SUPPORTS_KYBER */
+#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER) && EVP_APIS_SUPPORTED
+ #define S2N_SUPPORTED_KEM_GROUPS_COUNT 6
+#elif defined(S2N_LIBCRYPTO_SUPPORTS_KYBER) && !EVP_APIS_SUPPORTED
+ #define S2N_SUPPORTED_KEM_GROUPS_COUNT 4
+#elif !defined(S2N_LIBCRYPTO_SUPPORTS_KYBER) && EVP_APIS_SUPPORTED
#define S2N_SUPPORTED_KEM_GROUPS_COUNT 2
#else
#define S2N_SUPPORTED_KEM_GROUPS_COUNT 1
@@ -84,11 +92,15 @@ extern const struct s2n_kem s2n_kyber_512_r3;
extern const struct s2n_kem_group *ALL_SUPPORTED_KEM_GROUPS[S2N_SUPPORTED_KEM_GROUPS_COUNT];
-/* secp256r1 KEM Groups */
+/* NIST curve KEM Groups */
extern const struct s2n_kem_group s2n_secp256r1_kyber_512_r3;
+extern const struct s2n_kem_group s2n_secp256r1_kyber_768_r3;
+extern const struct s2n_kem_group s2n_secp384r1_kyber_768_r3;
+extern const struct s2n_kem_group s2n_secp521r1_kyber_1024_r3;
/* x25519 KEM Groups */
extern const struct s2n_kem_group s2n_x25519_kyber_512_r3;
+extern const struct s2n_kem_group s2n_x25519_kyber_768_r3;
S2N_RESULT s2n_kem_generate_keypair(struct s2n_kem_params *kem_params);
S2N_RESULT s2n_kem_encapsulate(struct s2n_kem_params *kem_params, struct s2n_blob *ciphertext);
@@ -137,6 +149,18 @@ int s2n_kem_recv_ciphertext(struct s2n_stuffer *in, struct s2n_kem_params *kem_p
#define S2N_KYBER_512_R3_SECRET_KEY_BYTES 1632
#define S2N_KYBER_512_R3_CIPHERTEXT_BYTES 768
#define S2N_KYBER_512_R3_SHARED_SECRET_BYTES 32
-int s2n_kyber_512_r3_crypto_kem_keypair(OUT uint8_t *pk, OUT uint8_t *sk);
-int s2n_kyber_512_r3_crypto_kem_enc(OUT uint8_t *ct, OUT uint8_t *ss, IN const uint8_t *pk);
-int s2n_kyber_512_r3_crypto_kem_dec(OUT uint8_t *ss, IN const uint8_t *ct, IN const uint8_t *sk);
+int s2n_kyber_512_r3_crypto_kem_keypair(IN const struct s2n_kem *kem, OUT uint8_t *pk, OUT uint8_t *sk);
+int s2n_kyber_512_r3_crypto_kem_enc(IN const struct s2n_kem *kem, OUT uint8_t *ct, OUT uint8_t *ss, IN const uint8_t *pk);
+int s2n_kyber_512_r3_crypto_kem_dec(IN const struct s2n_kem *kem, OUT uint8_t *ss, IN const uint8_t *ct, IN const uint8_t *sk);
+
+/* kyber768r3 */
+#define S2N_KYBER_768_R3_PUBLIC_KEY_BYTES 1184
+#define S2N_KYBER_768_R3_SECRET_KEY_BYTES 2400
+#define S2N_KYBER_768_R3_CIPHERTEXT_BYTES 1088
+#define S2N_KYBER_768_R3_SHARED_SECRET_BYTES 32
+
+/* kyber1024r3 */
+#define S2N_KYBER_1024_R3_PUBLIC_KEY_BYTES 1568
+#define S2N_KYBER_1024_R3_SECRET_KEY_BYTES 3168
+#define S2N_KYBER_1024_R3_CIPHERTEXT_BYTES 1568
+#define S2N_KYBER_1024_R3_SHARED_SECRET_BYTES 32
diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c
index fe0c17e2c4..21b92d37c4 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c
@@ -15,31 +15,63 @@
#include "tls/s2n_kem_preferences.h"
-const struct s2n_kem *pq_kems_r3_2021_05[1] = {
+const struct s2n_kem *pq_kems_r3_2021_05[] = {
/* Round 3 Algorithms */
&s2n_kyber_512_r3,
};
-const struct s2n_kem_group *pq_kem_groups_r3[] = {
+const struct s2n_kem_group *pq_kem_groups_r3_2021_05[] = {
#if EVP_APIS_SUPPORTED
&s2n_x25519_kyber_512_r3,
#endif
&s2n_secp256r1_kyber_512_r3,
};
+const struct s2n_kem_group *pq_kem_groups_r3_2023_06[] = {
+#if defined(S2N_LIBCRYPTO_SUPPORTS_KYBER)
+ &s2n_secp256r1_kyber_768_r3,
+ #if EVP_APIS_SUPPORTED
+ &s2n_x25519_kyber_768_r3,
+ #endif
+ &s2n_secp384r1_kyber_768_r3,
+ &s2n_secp521r1_kyber_1024_r3,
+#endif
+ &s2n_secp256r1_kyber_512_r3,
+#if EVP_APIS_SUPPORTED
+ &s2n_x25519_kyber_512_r3,
+#endif
+};
+
const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2021_05 = {
.kem_count = s2n_array_len(pq_kems_r3_2021_05),
.kems = pq_kems_r3_2021_05,
- .tls13_kem_group_count = s2n_array_len(pq_kem_groups_r3),
- .tls13_kem_groups = pq_kem_groups_r3,
+ .tls13_kem_group_count = s2n_array_len(pq_kem_groups_r3_2021_05),
+ .tls13_kem_groups = pq_kem_groups_r3_2021_05,
.tls13_pq_hybrid_draft_revision = 0
};
const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2023_01 = {
.kem_count = s2n_array_len(pq_kems_r3_2021_05),
.kems = pq_kems_r3_2021_05,
- .tls13_kem_group_count = s2n_array_len(pq_kem_groups_r3),
- .tls13_kem_groups = pq_kem_groups_r3,
+ .tls13_kem_group_count = s2n_array_len(pq_kem_groups_r3_2021_05),
+ .tls13_kem_groups = pq_kem_groups_r3_2021_05,
+ .tls13_pq_hybrid_draft_revision = 5
+};
+
+/* TLS 1.3 specifies KEMS via SupportedGroups extension, not TLS 1.2's KEM-specific extension. */
+const struct s2n_kem_preferences kem_preferences_pq_tls_1_3_2023_06 = {
+ .kem_count = 0,
+ .kems = NULL,
+ .tls13_kem_group_count = s2n_array_len(pq_kem_groups_r3_2023_06),
+ .tls13_kem_groups = pq_kem_groups_r3_2023_06,
+ .tls13_pq_hybrid_draft_revision = 5
+};
+
+const struct s2n_kem_preferences kem_preferences_all = {
+ .kem_count = s2n_array_len(pq_kems_r3_2021_05),
+ .kems = pq_kems_r3_2021_05,
+ .tls13_kem_group_count = s2n_array_len(pq_kem_groups_r3_2023_06),
+ .tls13_kem_groups = pq_kem_groups_r3_2023_06,
.tls13_pq_hybrid_draft_revision = 5
};
diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h
index 7ed785df7c..884b6234aa 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h
@@ -39,12 +39,15 @@ struct s2n_kem_preferences {
uint8_t tls13_pq_hybrid_draft_revision;
};
-extern const struct s2n_kem *pq_kems_r3_2021_05[1];
+extern const struct s2n_kem *pq_kems_r3_2021_05[];
-extern const struct s2n_kem_group *pq_kem_groups_r3[];
+extern const struct s2n_kem_group *pq_kem_groups_r3_2021_05[];
+extern const struct s2n_kem_group *pq_kem_groups_r3_2023_06[];
extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2021_05;
extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2023_01;
+extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_3_2023_06;
+extern const struct s2n_kem_preferences kem_preferences_all;
extern const struct s2n_kem_preferences kem_preferences_null;
bool s2n_kem_preferences_includes_tls13_kem_group(const struct s2n_kem_preferences *kem_preferences,
diff --git a/contrib/restricted/aws/s2n/tls/s2n_key_log.c b/contrib/restricted/aws/s2n/tls/s2n_key_log.c
index 0ea0ed182f..75ef3db618 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_key_log.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_key_log.c
@@ -84,6 +84,7 @@ S2N_RESULT s2n_key_log_tls13_secret(struct s2n_connection *conn, const struct s2
const uint8_t server_handshake_label[] = "SERVER_HANDSHAKE_TRAFFIC_SECRET ";
const uint8_t client_traffic_label[] = "CLIENT_TRAFFIC_SECRET_0 ";
const uint8_t server_traffic_label[] = "SERVER_TRAFFIC_SECRET_0 ";
+ const uint8_t exporter_secret_label[] = "EXPORTER_SECRET ";
const uint8_t *label = NULL;
uint8_t label_size = 0;
@@ -109,6 +110,10 @@ S2N_RESULT s2n_key_log_tls13_secret(struct s2n_connection *conn, const struct s2
label = server_traffic_label;
label_size = sizeof(server_traffic_label) - 1;
break;
+ case S2N_EXPORTER_SECRET:
+ label = exporter_secret_label;
+ label_size = sizeof(exporter_secret_label) - 1;
+ break;
default:
/* Ignore the secret types we don't understand */
return S2N_RESULT_OK;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_key_update.c b/contrib/restricted/aws/s2n/tls/s2n_key_update.c
index c5990484bb..67d759cb91 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_key_update.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_key_update.c
@@ -21,11 +21,21 @@
#include "tls/s2n_record.h"
#include "tls/s2n_tls.h"
#include "tls/s2n_tls13_handshake.h"
+#include "utils/s2n_atomic.h"
#include "utils/s2n_safety.h"
+static keyupdate_request key_update_request_val = S2N_KEY_UPDATE_NOT_REQUESTED;
+
int s2n_key_update_write(struct s2n_blob *out);
int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequence_number);
+S2N_RESULT s2n_set_key_update_request_for_testing(keyupdate_request request)
+{
+ RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
+ key_update_request_val = request;
+ return S2N_RESULT_OK;
+}
+
int s2n_key_update_recv(struct s2n_connection *conn, struct s2n_stuffer *request)
{
POSIX_ENSURE_REF(conn);
@@ -36,7 +46,9 @@ int s2n_key_update_recv(struct s2n_connection *conn, struct s2n_stuffer *request
POSIX_GUARD(s2n_stuffer_read_uint8(request, &key_update_request));
S2N_ERROR_IF(key_update_request != S2N_KEY_UPDATE_NOT_REQUESTED && key_update_request != S2N_KEY_UPDATE_REQUESTED,
S2N_ERR_BAD_MESSAGE);
- conn->key_update_pending = key_update_request;
+ if (key_update_request == S2N_KEY_UPDATE_REQUESTED) {
+ s2n_atomic_flag_set(&conn->key_update_pending);
+ }
/* Update peer's key since a key_update was received */
if (conn->mode == S2N_CLIENT) {
@@ -52,6 +64,7 @@ int s2n_key_update_send(struct s2n_connection *conn, s2n_blocked_status *blocked
{
POSIX_ENSURE_REF(conn);
POSIX_ENSURE_REF(conn->secure);
+ POSIX_ENSURE_GTE(conn->actual_protocol_version, S2N_TLS13);
struct s2n_blob sequence_number = { 0 };
if (conn->mode == S2N_CLIENT) {
@@ -62,7 +75,7 @@ int s2n_key_update_send(struct s2n_connection *conn, s2n_blocked_status *blocked
POSIX_GUARD(s2n_check_record_limit(conn, &sequence_number));
- if (conn->key_update_pending) {
+ if (s2n_atomic_flag_test(&conn->key_update_pending)) {
/* Flush any buffered records to ensure an empty output buffer.
*
* This is important when buffering multiple records because we don't:
@@ -84,8 +97,8 @@ int s2n_key_update_send(struct s2n_connection *conn, s2n_blocked_status *blocked
/* Update encryption key */
POSIX_GUARD(s2n_update_application_traffic_keys(conn, conn->mode, SENDING));
- conn->key_update_pending = false;
+ s2n_atomic_flag_clear(&conn->key_update_pending);
POSIX_GUARD(s2n_flush(conn, blocked));
}
@@ -102,7 +115,7 @@ int s2n_key_update_write(struct s2n_blob *out)
POSIX_GUARD(s2n_stuffer_write_uint24(&key_update_stuffer, S2N_KEY_UPDATE_LENGTH));
/* s2n currently does not require peers to update their encryption keys. */
- POSIX_GUARD(s2n_stuffer_write_uint8(&key_update_stuffer, S2N_KEY_UPDATE_NOT_REQUESTED));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&key_update_stuffer, key_update_request_val));
return S2N_SUCCESS;
}
@@ -129,7 +142,7 @@ int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequenc
* This should always trigger on "==", but we use ">=" just in case.
*/
if (next_seq_num >= conn->secure->cipher_suite->record_alg->encryption_limit) {
- conn->key_update_pending = true;
+ s2n_atomic_flag_set(&conn->key_update_pending);
}
return S2N_SUCCESS;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_ktls.c b/contrib/restricted/aws/s2n/tls/s2n_ktls.c
index 81b72bf4e6..ad25fd4bd6 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_ktls.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_ktls.c
@@ -15,11 +15,250 @@
#include "tls/s2n_ktls.h"
+#include "crypto/s2n_ktls_crypto.h"
+#include "tls/s2n_prf.h"
+#include "tls/s2n_tls.h"
+
+/* Used for overriding setsockopt calls in testing */
+s2n_setsockopt_fn s2n_setsockopt = setsockopt;
+
+S2N_RESULT s2n_ktls_set_setsockopt_cb(s2n_setsockopt_fn cb)
+{
+ RESULT_ENSURE(s2n_in_test(), S2N_ERR_NOT_IN_TEST);
+ s2n_setsockopt = cb;
+ return S2N_RESULT_OK;
+}
+
bool s2n_ktls_is_supported_on_platform()
{
-#ifdef S2N_PLATFORM_SUPPORTS_KTLS
+#if defined(S2N_KTLS_SUPPORTED)
return true;
#else
return false;
#endif
}
+
+static int s2n_ktls_disabled_read(void *io_context, uint8_t *buf, uint32_t len)
+{
+ POSIX_BAIL(S2N_ERR_IO);
+}
+
+static S2N_RESULT s2n_ktls_validate(struct s2n_connection *conn, s2n_ktls_mode ktls_mode)
+{
+ RESULT_ENSURE_REF(conn);
+ const struct s2n_config *config = conn->config;
+ RESULT_ENSURE_REF(config);
+
+ RESULT_ENSURE(s2n_ktls_is_supported_on_platform(), S2N_ERR_KTLS_UNSUPPORTED_PLATFORM);
+
+ /* kTLS enable should only be called once the handshake has completed. */
+ RESULT_ENSURE(is_handshake_complete(conn), S2N_ERR_HANDSHAKE_NOT_COMPLETE);
+
+ /* TODO support TLS 1.3
+ *
+ * TLS 1.3 support requires sending the KeyUpdate message when the cryptographic
+ * key usage limits are met. However, this is currently only possible by applying a
+ * kernel patch to support this functionality.
+ */
+ RESULT_ENSURE(conn->actual_protocol_version == S2N_TLS12, S2N_ERR_KTLS_UNSUPPORTED_CONN);
+
+ /* Check if the cipher supports kTLS */
+ const struct s2n_cipher *cipher = NULL;
+ RESULT_GUARD(s2n_connection_get_secure_cipher(conn, &cipher));
+ RESULT_ENSURE_REF(cipher);
+ RESULT_ENSURE(cipher->set_ktls_info, S2N_ERR_KTLS_UNSUPPORTED_CONN);
+
+ /* Renegotiation requires updating the keys, which kTLS doesn't currently support.
+ *
+ * Setting the renegotiation callback doesn't guarantee that a client will
+ * attempt to renegotiate. The callback can also be used to send warning alerts
+ * signaling that renegotiation was rejected. However, we can provide applications
+ * with a clearer signal earlier by preventing them from enabling ktls on a
+ * connection that MIGHT require renegotiation. We can relax this restriction
+ * later if necessary.
+ */
+ bool may_receive_hello_request = s2n_result_is_ok(s2n_client_hello_request_validate(conn));
+ bool may_renegotiate = may_receive_hello_request && config->renegotiate_request_cb;
+ RESULT_ENSURE(!may_renegotiate, S2N_ERR_KTLS_RENEG);
+
+ /* kTLS I/O functionality is managed by s2n-tls. kTLS cannot be enabled if the
+ * application sets custom I/O (managed_send_io == false means application has
+ * set custom I/O).
+ */
+ switch (ktls_mode) {
+ case S2N_KTLS_MODE_SEND:
+ RESULT_ENSURE(conn->managed_send_io, S2N_ERR_KTLS_MANAGED_IO);
+ /* The output stuffer should be empty before enabling kTLS. */
+ RESULT_ENSURE(s2n_stuffer_data_available(&conn->out) == 0, S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
+ break;
+ case S2N_KTLS_MODE_RECV:
+ RESULT_ENSURE(conn->managed_recv_io, S2N_ERR_KTLS_MANAGED_IO);
+ /* The input stuffer should be empty before enabling kTLS. */
+ RESULT_ENSURE(s2n_stuffer_data_available(&conn->in) == 0, S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
+ break;
+ default:
+ RESULT_BAIL(S2N_ERR_SAFETY);
+ break;
+ }
+
+ return S2N_RESULT_OK;
+}
+
+/* Enabling kTLS preserves the original *io_context; making this functions
+ * safe to call even after kTLS has been enabled on the connection.
+ *
+ * Retrieving fd assumes that the connection is using socket IO and has the
+ * send_io_context set. While kTLS overrides IO and essentially disables
+ * the socket conn->send function callback, it doesn't modify the
+ * send_io_context. */
+S2N_RESULT s2n_ktls_get_file_descriptor(struct s2n_connection *conn, s2n_ktls_mode ktls_mode, int *fd)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(fd);
+
+ if (ktls_mode == S2N_KTLS_MODE_RECV) {
+ RESULT_GUARD_POSIX(s2n_connection_get_read_fd(conn, fd));
+ } else if (ktls_mode == S2N_KTLS_MODE_SEND) {
+ RESULT_GUARD_POSIX(s2n_connection_get_write_fd(conn, fd));
+ }
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_ktls_get_io_mode(s2n_ktls_mode ktls_mode, int *tls_tx_rx_mode)
+{
+ RESULT_ENSURE_REF(tls_tx_rx_mode);
+
+ if (ktls_mode == S2N_KTLS_MODE_SEND) {
+ *tls_tx_rx_mode = S2N_TLS_TX;
+ } else {
+ *tls_tx_rx_mode = S2N_TLS_RX;
+ }
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_ktls_crypto_info_init(struct s2n_connection *conn, s2n_ktls_mode ktls_mode,
+ struct s2n_ktls_crypto_info *crypto_info)
+{
+ RESULT_ENSURE_REF(conn);
+ struct s2n_crypto_parameters *secure = conn->secure;
+ RESULT_ENSURE_REF(secure);
+
+ /* In order to avoid storing the encryption keys on the connection, we instead
+ * regenerate them when required by ktls.
+ *
+ * s2n_key_material also includes an IV, but we should use the IV stored
+ * on the connection instead. Some record algorithms (like CBC) mutate the
+ * "implicit_iv" when writing records, so the IV may change after generation.
+ */
+ struct s2n_key_material key_material = { 0 };
+ RESULT_GUARD(s2n_prf_generate_key_material(conn, &key_material));
+
+ bool is_sending_key = (ktls_mode == S2N_KTLS_MODE_SEND);
+ s2n_mode key_mode = (is_sending_key) ? conn->mode : S2N_PEER_MODE(conn->mode);
+
+ struct s2n_ktls_crypto_info_inputs inputs = { 0 };
+ if (key_mode == S2N_CLIENT) {
+ inputs.key = key_material.client_key;
+ RESULT_GUARD_POSIX(s2n_blob_init(&inputs.iv,
+ secure->client_implicit_iv, sizeof(secure->client_implicit_iv)));
+ RESULT_GUARD_POSIX(s2n_blob_init(&inputs.seq,
+ secure->client_sequence_number, sizeof(secure->client_sequence_number)));
+ } else {
+ inputs.key = key_material.server_key;
+ RESULT_GUARD_POSIX(s2n_blob_init(&inputs.iv,
+ secure->server_implicit_iv, sizeof(secure->server_implicit_iv)));
+ RESULT_GUARD_POSIX(s2n_blob_init(&inputs.seq,
+ secure->server_sequence_number, sizeof(secure->server_sequence_number)));
+ }
+
+ const struct s2n_cipher *cipher = NULL;
+ RESULT_GUARD(s2n_connection_get_secure_cipher(conn, &cipher));
+ RESULT_ENSURE_REF(cipher);
+ RESULT_ENSURE_REF(cipher->set_ktls_info);
+ RESULT_GUARD(cipher->set_ktls_info(&inputs, crypto_info));
+
+ return S2N_RESULT_OK;
+}
+
+/* This method intentionally returns void because it may NOT perform any fallible
+ * operations. See s2n_connection_ktls_enable.
+ */
+void s2n_ktls_configure_connection(struct s2n_connection *conn, s2n_ktls_mode ktls_mode)
+{
+ if (conn == NULL) {
+ return;
+ }
+ if (ktls_mode == S2N_KTLS_MODE_SEND) {
+ conn->ktls_send_enabled = true;
+ conn->send = s2n_ktls_send_cb;
+ } else {
+ conn->ktls_recv_enabled = true;
+ conn->recv = s2n_ktls_disabled_read;
+ }
+}
+
+static S2N_RESULT s2n_connection_ktls_enable(struct s2n_connection *conn, s2n_ktls_mode ktls_mode)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_GUARD(s2n_ktls_validate(conn, ktls_mode));
+
+ int fd = 0;
+ RESULT_GUARD(s2n_ktls_get_file_descriptor(conn, ktls_mode, &fd));
+
+ /* This call doesn't actually enable ktls or modify the IO behavior of the socket.
+ * Instead, this is just a prerequisite for calling setsockopt with SOL_TLS.
+ *
+ * We intentionally ignore the result of this call. It may fail because ktls
+ * is not supported, but it might also fail because ktls has already been enabled
+ * for the socket. If SOL_TLS isn't enabled on the socket, our next call to
+ * setsockopt with SOL_TLS will also fail, and we DO check that result.
+ */
+ s2n_setsockopt(fd, S2N_SOL_TCP, S2N_TCP_ULP, S2N_TLS_ULP_NAME, S2N_TLS_ULP_NAME_SIZE);
+
+ int tls_tx_rx_mode = 0;
+ RESULT_GUARD(s2n_ktls_get_io_mode(ktls_mode, &tls_tx_rx_mode));
+
+ struct s2n_ktls_crypto_info crypto_info = { 0 };
+ RESULT_GUARD(s2n_ktls_crypto_info_init(conn, ktls_mode, &crypto_info));
+
+ /* If this call succeeds, then ktls is enabled for that io mode and will be offloaded */
+ int ret = s2n_setsockopt(fd, S2N_SOL_TLS, tls_tx_rx_mode, crypto_info.value.data, crypto_info.value.size);
+ RESULT_ENSURE(ret == 0, S2N_ERR_KTLS_ENABLE);
+
+ /* At this point, ktls is enabled on the socket for the requested IO mode.
+ * No further fallible operations may be performed, or else the caller may
+ * incorrectly assume that enabling ktls failed and they should therefore
+ * fall back to using application layer TLS.
+ *
+ * That means no calls to RESULT_ENSURE, RESULT_GUARD, etc. after this point.
+ */
+
+ s2n_ktls_configure_connection(conn, ktls_mode);
+ return S2N_RESULT_OK;
+}
+
+int s2n_connection_ktls_enable_send(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+
+ /* If already enabled then return success */
+ if (conn->ktls_send_enabled) {
+ return S2N_SUCCESS;
+ }
+
+ POSIX_GUARD_RESULT(s2n_connection_ktls_enable(conn, S2N_KTLS_MODE_SEND));
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_ktls_enable_recv(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+
+ /* If already enabled then return success */
+ if (conn->ktls_recv_enabled) {
+ return S2N_SUCCESS;
+ }
+
+ POSIX_GUARD_RESULT(s2n_connection_ktls_enable(conn, S2N_KTLS_MODE_RECV));
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_ktls.h b/contrib/restricted/aws/s2n/tls/s2n_ktls.h
index 5e2de31955..c41a0796d2 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_ktls.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_ktls.h
@@ -15,21 +15,57 @@
#pragma once
-#include "tls/s2n_config.h"
+#include <sys/socket.h>
+
+#include "api/unstable/ktls.h"
+#include "tls/s2n_connection.h"
+/* Define headers needed to enable and use kTLS.
+ *
+ * The inline header definitions are required to compile kTLS specific code.
+ * kTLS has been tested on linux. For all other platforms, kTLS is marked as
+ * unsupported, and will return an unsupported error.
+ */
+#include "tls/s2n_ktls_parameters.h"
/* A set of kTLS configurations representing the combination of sending
* and receiving.
*/
typedef enum {
- /* Disable kTLS. */
- S2N_KTLS_MODE_DISABLED,
/* Enable kTLS for the send socket. */
S2N_KTLS_MODE_SEND,
/* Enable kTLS for the receive socket. */
S2N_KTLS_MODE_RECV,
- /* Enable kTLS for both receive and send sockets. */
- S2N_KTLS_MODE_DUPLEX,
} s2n_ktls_mode;
-int s2n_config_set_ktls_mode(struct s2n_config *config, s2n_ktls_mode ktls_mode);
bool s2n_ktls_is_supported_on_platform();
+S2N_RESULT s2n_ktls_get_file_descriptor(struct s2n_connection *conn, s2n_ktls_mode ktls_mode, int *fd);
+
+int s2n_ktls_send_cb(void *io_context, const uint8_t *buf, uint32_t len);
+S2N_RESULT s2n_ktls_sendmsg(void *io_context, uint8_t record_type, const struct iovec *msg_iov,
+ size_t msg_iovlen, s2n_blocked_status *blocked, size_t *bytes_written);
+S2N_RESULT s2n_ktls_recvmsg(void *io_context, uint8_t *record_type, uint8_t *buf,
+ size_t buf_len, s2n_blocked_status *blocked, size_t *bytes_read);
+
+ssize_t s2n_ktls_sendv_with_offset(struct s2n_connection *conn, const struct iovec *bufs,
+ ssize_t count, ssize_t offs, s2n_blocked_status *blocked);
+int s2n_ktls_record_writev(struct s2n_connection *conn, uint8_t content_type,
+ const struct iovec *in, int in_count, size_t offs, size_t to_write);
+int s2n_ktls_read_full_record(struct s2n_connection *conn, uint8_t *record_type);
+
+/* Testing */
+typedef int (*s2n_setsockopt_fn)(int socket, int level, int option_name, const void *option_value,
+ socklen_t option_len);
+S2N_RESULT s2n_ktls_set_setsockopt_cb(s2n_setsockopt_fn cb);
+typedef ssize_t (*s2n_ktls_sendmsg_fn)(void *io_context, const struct msghdr *msg);
+typedef ssize_t (*s2n_ktls_recvmsg_fn)(void *io_context, struct msghdr *msg);
+S2N_RESULT s2n_ktls_set_sendmsg_cb(struct s2n_connection *conn, s2n_ktls_sendmsg_fn send_cb,
+ void *send_ctx);
+S2N_RESULT s2n_ktls_set_recvmsg_cb(struct s2n_connection *conn, s2n_ktls_recvmsg_fn recv_cb,
+ void *recv_ctx);
+void s2n_ktls_configure_connection(struct s2n_connection *conn, s2n_ktls_mode ktls_mode);
+
+/* These functions will be part of the public API. */
+int s2n_connection_ktls_enable_send(struct s2n_connection *conn);
+int s2n_connection_ktls_enable_recv(struct s2n_connection *conn);
+int s2n_sendfile(struct s2n_connection *conn, int in_fd, off_t offset, size_t count,
+ size_t *bytes_written, s2n_blocked_status *blocked);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_ktls_io.c b/contrib/restricted/aws/s2n/tls/s2n_ktls_io.c
new file mode 100644
index 0000000000..12ee729d87
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_ktls_io.c
@@ -0,0 +1,473 @@
+/*
+ * 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.
+ */
+
+#if defined(__FreeBSD__) || defined(__APPLE__)
+ /* https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
+ * The POSIX standard does not define the CMSG_LEN and CMSG_SPACE macros. FreeBSD
+ * and APPLE check and disable these macros if the _POSIX_C_SOURCE flag is set.
+ *
+ * Since s2n-tls already unsets the _POSIX_C_SOURCE in other files and is not
+ * POSIX compliant, we continue the pattern here.
+ */
+ #undef _POSIX_C_SOURCE
+#endif
+#include <sys/socket.h>
+
+#ifdef S2N_LINUX_SENDFILE
+ #include <sys/sendfile.h>
+#endif
+
+#include "error/s2n_errno.h"
+#include "tls/s2n_ktls.h"
+#include "tls/s2n_tls.h"
+#include "utils/s2n_io.h"
+#include "utils/s2n_result.h"
+#include "utils/s2n_safety.h"
+#include "utils/s2n_socket.h"
+
+/* record_type is of type uint8_t */
+#define S2N_KTLS_RECORD_TYPE_SIZE (sizeof(uint8_t))
+#define S2N_KTLS_CONTROL_BUFFER_SIZE (CMSG_SPACE(S2N_KTLS_RECORD_TYPE_SIZE))
+
+#define S2N_MAX_STACK_IOVECS 16
+#define S2N_MAX_STACK_IOVECS_MEM (S2N_MAX_STACK_IOVECS * sizeof(struct iovec))
+
+/* Used to override sendmsg and recvmsg for testing. */
+static ssize_t s2n_ktls_default_sendmsg(void *io_context, const struct msghdr *msg);
+static ssize_t s2n_ktls_default_recvmsg(void *io_context, struct msghdr *msg);
+s2n_ktls_sendmsg_fn s2n_sendmsg_fn = s2n_ktls_default_sendmsg;
+s2n_ktls_recvmsg_fn s2n_recvmsg_fn = s2n_ktls_default_recvmsg;
+
+S2N_RESULT s2n_ktls_set_sendmsg_cb(struct s2n_connection *conn, s2n_ktls_sendmsg_fn send_cb,
+ void *send_ctx)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(send_ctx);
+ RESULT_ENSURE(s2n_in_test(), S2N_ERR_NOT_IN_TEST);
+ conn->send_io_context = send_ctx;
+ s2n_sendmsg_fn = send_cb;
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_ktls_set_recvmsg_cb(struct s2n_connection *conn, s2n_ktls_recvmsg_fn recv_cb,
+ void *recv_ctx)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(recv_ctx);
+ RESULT_ENSURE(s2n_in_test(), S2N_ERR_NOT_IN_TEST);
+ conn->recv_io_context = recv_ctx;
+ s2n_recvmsg_fn = recv_cb;
+ return S2N_RESULT_OK;
+}
+
+static ssize_t s2n_ktls_default_recvmsg(void *io_context, struct msghdr *msg)
+{
+ POSIX_ENSURE_REF(io_context);
+ POSIX_ENSURE_REF(msg);
+
+ const struct s2n_socket_read_io_context *peer_socket_ctx = io_context;
+ POSIX_ENSURE_REF(peer_socket_ctx);
+ int fd = peer_socket_ctx->fd;
+
+ return recvmsg(fd, msg, 0);
+}
+
+static ssize_t s2n_ktls_default_sendmsg(void *io_context, const struct msghdr *msg)
+{
+ POSIX_ENSURE_REF(io_context);
+ POSIX_ENSURE_REF(msg);
+
+ const struct s2n_socket_write_io_context *peer_socket_ctx = io_context;
+ POSIX_ENSURE_REF(peer_socket_ctx);
+ int fd = peer_socket_ctx->fd;
+
+ return sendmsg(fd, msg, 0);
+}
+
+S2N_RESULT s2n_ktls_set_control_data(struct msghdr *msg, char *buf, size_t buf_size,
+ int cmsg_type, uint8_t record_type)
+{
+ RESULT_ENSURE_REF(msg);
+ RESULT_ENSURE_REF(buf);
+
+ /*
+ * https://man7.org/linux/man-pages/man3/cmsg.3.html
+ * To create ancillary data, first initialize the msg_controllen
+ * member of the msghdr with the length of the control message
+ * buffer.
+ */
+ msg->msg_control = buf;
+ msg->msg_controllen = buf_size;
+
+ /*
+ * https://man7.org/linux/man-pages/man3/cmsg.3.html
+ * Use CMSG_FIRSTHDR() on the msghdr to get the first
+ * control message and CMSG_NXTHDR() to get all subsequent ones.
+ */
+ struct cmsghdr *hdr = CMSG_FIRSTHDR(msg);
+ RESULT_ENSURE_REF(hdr);
+
+ /*
+ * https://man7.org/linux/man-pages/man3/cmsg.3.html
+ * In each control message, initialize cmsg_len (with CMSG_LEN()), the
+ * other cmsghdr header fields, and the data portion using
+ * CMSG_DATA().
+ */
+ hdr->cmsg_len = CMSG_LEN(S2N_KTLS_RECORD_TYPE_SIZE);
+ hdr->cmsg_level = S2N_SOL_TLS;
+ hdr->cmsg_type = cmsg_type;
+ *CMSG_DATA(hdr) = record_type;
+
+ /*
+ * https://man7.org/linux/man-pages/man3/cmsg.3.html
+ * Finally, the msg_controllen field of the msghdr
+ * should be set to the sum of the CMSG_SPACE() of the length of all
+ * control messages in the buffer
+ */
+ RESULT_ENSURE_GTE(msg->msg_controllen, CMSG_SPACE(S2N_KTLS_RECORD_TYPE_SIZE));
+ msg->msg_controllen = CMSG_SPACE(S2N_KTLS_RECORD_TYPE_SIZE);
+
+ return S2N_RESULT_OK;
+}
+
+/* Expect to receive a single cmsghdr containing the TLS record_type.
+ *
+ * s2n-tls allocates enough space to receive a single cmsghdr. Since this is
+ * used to get the record_type when receiving over kTLS (enabled via
+ * `s2n_connection_ktls_enable_recv`), the application should not configure
+ * the socket to receive additional control messages. In the event s2n-tls
+ * can not retrieve the record_type, it is safer to drop the record.
+ */
+S2N_RESULT s2n_ktls_get_control_data(struct msghdr *msg, int cmsg_type, uint8_t *record_type)
+{
+ RESULT_ENSURE_REF(msg);
+ RESULT_ENSURE_REF(record_type);
+
+ /* https://man7.org/linux/man-pages/man3/recvmsg.3p.html
+ * MSG_CTRUNC Control data was truncated.
+ */
+ if (msg->msg_flags & MSG_CTRUNC) {
+ RESULT_BAIL(S2N_ERR_KTLS_BAD_CMSG);
+ }
+
+ /*
+ * https://man7.org/linux/man-pages/man3/cmsg.3.html
+ * To create ancillary data, first initialize the msg_controllen
+ * member of the msghdr with the length of the control message
+ * buffer.
+ */
+ RESULT_ENSURE(msg->msg_control, S2N_ERR_SAFETY);
+ RESULT_ENSURE(msg->msg_controllen >= CMSG_SPACE(S2N_KTLS_RECORD_TYPE_SIZE), S2N_ERR_SAFETY);
+
+ /* https://man7.org/linux/man-pages/man3/cmsg.3.html
+ * Use CMSG_FIRSTHDR() on the msghdr to get the first
+ * control message and CMSG_NXTHDR() to get all subsequent ones.
+ */
+ struct cmsghdr *hdr = CMSG_FIRSTHDR(msg);
+ RESULT_ENSURE(hdr, S2N_ERR_KTLS_BAD_CMSG);
+
+ /*
+ * https://man7.org/linux/man-pages/man3/cmsg.3.html
+ * In each control message, initialize cmsg_len (with CMSG_LEN()), the
+ * other cmsghdr header fields, and the data portion using
+ * CMSG_DATA().
+ */
+ RESULT_ENSURE(hdr->cmsg_level == S2N_SOL_TLS, S2N_ERR_KTLS_BAD_CMSG);
+ RESULT_ENSURE(hdr->cmsg_type == cmsg_type, S2N_ERR_KTLS_BAD_CMSG);
+ RESULT_ENSURE(hdr->cmsg_len == CMSG_LEN(S2N_KTLS_RECORD_TYPE_SIZE), S2N_ERR_KTLS_BAD_CMSG);
+ *record_type = *CMSG_DATA(hdr);
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_ktls_sendmsg(void *io_context, uint8_t record_type, const struct iovec *msg_iov,
+ size_t msg_iovlen, s2n_blocked_status *blocked, size_t *bytes_written)
+{
+ RESULT_ENSURE_REF(bytes_written);
+ RESULT_ENSURE_REF(blocked);
+ RESULT_ENSURE(msg_iov != NULL || msg_iovlen == 0, S2N_ERR_NULL);
+
+ *blocked = S2N_BLOCKED_ON_WRITE;
+ *bytes_written = 0;
+
+ struct msghdr msg = {
+ /* msghdr requires a non-const iovec. This is safe because s2n-tls does
+ * not modify msg_iov after this point.
+ */
+ .msg_iov = (struct iovec *) (uintptr_t) msg_iov,
+ .msg_iovlen = msg_iovlen,
+ };
+
+ char control_data[S2N_KTLS_CONTROL_BUFFER_SIZE] = { 0 };
+ RESULT_GUARD(s2n_ktls_set_control_data(&msg, control_data, sizeof(control_data),
+ S2N_TLS_SET_RECORD_TYPE, record_type));
+
+ ssize_t result = 0;
+ S2N_IO_RETRY_EINTR(result, s2n_sendmsg_fn(io_context, &msg));
+ RESULT_GUARD(s2n_io_check_write_result(result));
+
+ *blocked = S2N_NOT_BLOCKED;
+ *bytes_written = result;
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_ktls_recvmsg(void *io_context, uint8_t *record_type, uint8_t *buf,
+ size_t buf_len, s2n_blocked_status *blocked, size_t *bytes_read)
+{
+ RESULT_ENSURE_REF(record_type);
+ RESULT_ENSURE_REF(bytes_read);
+ RESULT_ENSURE_REF(blocked);
+ RESULT_ENSURE_REF(buf);
+ /* Ensure that buf_len is > 0 since trying to receive 0 bytes does not
+ * make sense and a return value of `0` from recvmsg is treated as EOF.
+ */
+ RESULT_ENSURE_GT(buf_len, 0);
+
+ *blocked = S2N_BLOCKED_ON_READ;
+ *record_type = 0;
+ *bytes_read = 0;
+ struct iovec msg_iov = {
+ .iov_base = buf,
+ .iov_len = buf_len
+ };
+ struct msghdr msg = {
+ .msg_iov = &msg_iov,
+ .msg_iovlen = 1,
+ };
+
+ /*
+ * https://man7.org/linux/man-pages/man3/cmsg.3.html
+ * To create ancillary data, first initialize the msg_controllen
+ * member of the msghdr with the length of the control message
+ * buffer.
+ */
+ char control_data[S2N_KTLS_CONTROL_BUFFER_SIZE] = { 0 };
+ msg.msg_controllen = sizeof(control_data);
+ msg.msg_control = control_data;
+
+ ssize_t result = 0;
+ S2N_IO_RETRY_EINTR(result, s2n_recvmsg_fn(io_context, &msg));
+ RESULT_GUARD(s2n_io_check_read_result(result));
+
+ RESULT_GUARD(s2n_ktls_get_control_data(&msg, S2N_TLS_GET_RECORD_TYPE, record_type));
+
+ *blocked = S2N_NOT_BLOCKED;
+ *bytes_read = result;
+ return S2N_RESULT_OK;
+}
+
+/* The iovec array `bufs` is constant and owned by the application.
+ *
+ * However, we need to apply the given offset to `bufs`. That may involve
+ * updating the iov_base and iov_len of entries in `bufs` to reflect the bytes
+ * already sent. Because `bufs` is constant, we need to instead copy `bufs` and
+ * modify the copy.
+ *
+ * Since one of the primary benefits of kTLS is that we avoid buffering application
+ * data and can pass application data as-is to the kernel, we try to limit the
+ * situations where we need to copy `bufs` and use stack memory where possible.
+ *
+ * Note: We are copying an array of iovecs here, NOT the scattered application
+ * data the iovecs reference. On Linux, the maximum data copied would be
+ * 1024 (IOV_MAX on Linux) * 16 (sizeof(struct iovec)) = ~16KB.
+ *
+ * To avoid any copies when using a large number of iovecs, applications should
+ * call s2n_sendv instead of s2n_sendv_with_offset.
+ */
+static S2N_RESULT s2n_ktls_update_bufs_with_offset(const struct iovec **bufs, size_t *count,
+ size_t offs, struct s2n_blob *mem)
+{
+ RESULT_ENSURE_REF(bufs);
+ RESULT_ENSURE_REF(count);
+ RESULT_ENSURE(*bufs != NULL || *count == 0, S2N_ERR_NULL);
+ RESULT_ENSURE_REF(mem);
+
+ size_t skipped = 0;
+ while (offs > 0) {
+ /* If we need to skip more iovecs than actually exist,
+ * then the offset is too large and therefore invalid.
+ */
+ RESULT_ENSURE(skipped < *count, S2N_ERR_INVALID_ARGUMENT);
+
+ size_t iov_len = (*bufs)[skipped].iov_len;
+
+ /* This is the last iovec affected by the offset. */
+ if (offs < iov_len) {
+ break;
+ }
+
+ offs -= iov_len;
+ skipped++;
+ }
+
+ *count = (*count) - skipped;
+ if (*count == 0) {
+ return S2N_RESULT_OK;
+ }
+
+ *bufs = &(*bufs)[skipped];
+ if (offs == 0) {
+ return S2N_RESULT_OK;
+ }
+
+ size_t size = (*count) * (sizeof(struct iovec));
+ /* If possible, use the existing stack memory in `mem` for the copy.
+ * Otherwise, we need to allocate sufficient new heap memory. */
+ if (size > mem->size) {
+ RESULT_GUARD_POSIX(s2n_alloc(mem, size));
+ }
+
+ struct iovec *new_bufs = (struct iovec *) (void *) mem->data;
+ RESULT_CHECKED_MEMCPY(new_bufs, *bufs, size);
+ new_bufs[0].iov_base = (uint8_t *) new_bufs[0].iov_base + offs;
+ new_bufs[0].iov_len = new_bufs[0].iov_len - offs;
+ *bufs = new_bufs;
+
+ return S2N_RESULT_OK;
+}
+
+ssize_t s2n_ktls_sendv_with_offset(struct s2n_connection *conn, const struct iovec *bufs,
+ ssize_t count_in, ssize_t offs_in, s2n_blocked_status *blocked)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE(count_in >= 0, S2N_ERR_INVALID_ARGUMENT);
+ size_t count = count_in;
+ POSIX_ENSURE(offs_in >= 0, S2N_ERR_INVALID_ARGUMENT);
+ size_t offs = offs_in;
+
+ DEFER_CLEANUP(struct s2n_blob new_bufs = { 0 }, s2n_free_or_wipe);
+ uint8_t new_bufs_mem[S2N_MAX_STACK_IOVECS_MEM] = { 0 };
+ POSIX_GUARD(s2n_blob_init(&new_bufs, new_bufs_mem, sizeof(new_bufs_mem)));
+ if (offs > 0) {
+ POSIX_GUARD_RESULT(s2n_ktls_update_bufs_with_offset(&bufs, &count, offs, &new_bufs));
+ }
+
+ size_t bytes_written = 0;
+ POSIX_GUARD_RESULT(s2n_ktls_sendmsg(conn->send_io_context, TLS_APPLICATION_DATA,
+ bufs, count, blocked, &bytes_written));
+ return bytes_written;
+}
+
+int s2n_ktls_send_cb(void *io_context, const uint8_t *buf, uint32_t len)
+{
+ POSIX_ENSURE_REF(io_context);
+ POSIX_ENSURE_REF(buf);
+
+ /* For now, all control records are assumed to be alerts.
+ * We can set the record_type on the io_context in the future.
+ */
+ const uint8_t record_type = TLS_ALERT;
+
+ const struct iovec iov = {
+ .iov_base = (void *) (uintptr_t) buf,
+ .iov_len = len,
+ };
+ s2n_blocked_status blocked = S2N_NOT_BLOCKED;
+ size_t bytes_written = 0;
+
+ POSIX_GUARD_RESULT(s2n_ktls_sendmsg(io_context, record_type, &iov, 1,
+ &blocked, &bytes_written));
+
+ POSIX_ENSURE_LTE(bytes_written, len);
+ return bytes_written;
+}
+
+int s2n_ktls_record_writev(struct s2n_connection *conn, uint8_t content_type,
+ const struct iovec *in, int in_count, size_t offs, size_t to_write)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE(in_count > 0, S2N_ERR_INVALID_ARGUMENT);
+ size_t count = in_count;
+ POSIX_ENSURE_REF(in);
+
+ /* Currently, ktls only supports sending alerts.
+ * To also support handshake messages, we would need a way to track record_type.
+ * We could add a field to the send io context.
+ */
+ POSIX_ENSURE(content_type == TLS_ALERT, S2N_ERR_UNIMPLEMENTED);
+
+ /* When stuffers automatically resize, they allocate a potentially large
+ * chunk of memory to avoid repeated resizes.
+ * Since ktls only uses conn->out for control messages (alerts and eventually
+ * handshake messages), we expect infrequent small writes with conn->out
+ * freed in between. Since we're therefore more concerned with the size of
+ * the allocation than the frequency, use a more accurate size for each write.
+ */
+ POSIX_GUARD(s2n_stuffer_resize_if_empty(&conn->out, to_write));
+
+ POSIX_GUARD(s2n_stuffer_writev_bytes(&conn->out, in, count, offs, to_write));
+ return to_write;
+}
+
+int s2n_sendfile(struct s2n_connection *conn, int in_fd, off_t offset, size_t count,
+ size_t *bytes_written, s2n_blocked_status *blocked)
+{
+ POSIX_ENSURE_REF(blocked);
+ *blocked = S2N_BLOCKED_ON_WRITE;
+ POSIX_ENSURE_REF(bytes_written);
+ *bytes_written = 0;
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE(conn->ktls_send_enabled, S2N_ERR_KTLS_UNSUPPORTED_CONN);
+
+ int out_fd = 0;
+ POSIX_GUARD_RESULT(s2n_ktls_get_file_descriptor(conn, S2N_KTLS_MODE_SEND, &out_fd));
+
+#ifdef S2N_LINUX_SENDFILE
+ /* https://man7.org/linux/man-pages/man2/sendfile.2.html */
+ ssize_t result = 0;
+ S2N_IO_RETRY_EINTR(result, sendfile(out_fd, in_fd, &offset, count));
+ POSIX_GUARD_RESULT(s2n_io_check_write_result(result));
+ *bytes_written = result;
+#else
+ POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
+#endif
+
+ *blocked = S2N_NOT_BLOCKED;
+ return S2N_SUCCESS;
+}
+
+int s2n_ktls_read_full_record(struct s2n_connection *conn, uint8_t *record_type)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(record_type);
+
+ /* If any unread data remains in conn->in, it must be application data that
+ * couldn't be returned due to the size of the application's provided buffer.
+ */
+ if (s2n_stuffer_data_available(&conn->in)) {
+ *record_type = TLS_APPLICATION_DATA;
+ return S2N_SUCCESS;
+ }
+
+ POSIX_GUARD(s2n_stuffer_resize_if_empty(&conn->in, S2N_DEFAULT_FRAGMENT_LENGTH));
+
+ struct s2n_stuffer record_stuffer = conn->in;
+ size_t len = s2n_stuffer_space_remaining(&record_stuffer);
+ uint8_t *buf = s2n_stuffer_raw_write(&record_stuffer, len);
+ POSIX_ENSURE_REF(buf);
+
+ s2n_blocked_status blocked = S2N_NOT_BLOCKED;
+ size_t bytes_read = 0;
+
+ /* Since recvmsg is responsible for decrypting the record in ktls,
+ * we apply blinding to the recvmsg call.
+ */
+ s2n_result result = s2n_ktls_recvmsg(conn->recv_io_context, record_type,
+ buf, len, &blocked, &bytes_read);
+ WITH_ERROR_BLINDING(conn, POSIX_GUARD_RESULT(result));
+
+ POSIX_GUARD(s2n_stuffer_skip_write(&conn->in, bytes_read));
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_ktls_parameters.h b/contrib/restricted/aws/s2n/tls/s2n_ktls_parameters.h
new file mode 100644
index 0000000000..c3f1482c4f
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_ktls_parameters.h
@@ -0,0 +1,63 @@
+/*
+ * 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
+
+/*
+ * Linux doesn't expose kTLS headers in its uapi. Its possible to get these headers
+ * via glibc but support can vary depending on the version of glibc on the host.
+ * Instead we define linux specific values inline.
+ *
+ * - https://elixir.bootlin.com/linux/v6.3.8/A/ident/TCP_ULP
+ * - https://elixir.bootlin.com/linux/v6.3.8/A/ident/SOL_TCP
+ */
+
+#if defined(S2N_KTLS_SUPPORTED)
+ #include <linux/tls.h>
+
+ /* socket definitions */
+ #define S2N_TCP_ULP 31 /* Attach a ULP to a TCP connection. */
+ #define S2N_SOL_TCP 6 /* TCP level */
+ #define S2N_SOL_TLS 282
+
+ /* We typically only define values not available in the linux uapi. However,
+ * only TLS_TX is defined in the first version of kTLS. Since calling setsockopt
+ * with TLS_RX fails and is non destructive, define both TX and RX to keep the
+ * definitions co-located and avoid extra ifdefs.
+ * https://github.com/torvalds/linux/blob/3c4d7559159bfe1e3b94df3a657b2cda3a34e218/include/uapi/linux/tls.h#L43
+ */
+ #define S2N_TLS_TX 1
+ #define S2N_TLS_RX 2
+
+ #define S2N_TLS_SET_RECORD_TYPE TLS_SET_RECORD_TYPE
+ #define S2N_TLS_GET_RECORD_TYPE TLS_GET_RECORD_TYPE
+#else
+ /* For unsupported platforms 0-init (array of size 1) all values. */
+
+ /* socket definitions */
+ #define S2N_TCP_ULP 0
+ #define S2N_SOL_TCP 0
+ #define S2N_SOL_TLS 0
+
+ #define S2N_TLS_TX 0
+ #define S2N_TLS_RX 0
+
+ #define S2N_TLS_SET_RECORD_TYPE 0
+ #define S2N_TLS_GET_RECORD_TYPE 0
+#endif
+
+/* Common */
+#define S2N_TLS_ULP_NAME "tls"
+#define S2N_TLS_ULP_NAME_SIZE sizeof(S2N_TLS_ULP_NAME)
diff --git a/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
index 1693ee60d9..2e479785e8 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
@@ -187,6 +187,11 @@ int s2n_post_handshake_send(struct s2n_connection *conn, s2n_blocked_status *blo
{
POSIX_ENSURE_REF(conn);
+ /* Currently, we only support TLS1.3 post-handshake messages. */
+ if (conn->actual_protocol_version < S2N_TLS13) {
+ return S2N_SUCCESS;
+ }
+
POSIX_GUARD_RESULT(s2n_post_handshake_write_records(conn, blocked));
POSIX_GUARD(s2n_key_update_send(conn, blocked));
diff --git a/contrib/restricted/aws/s2n/tls/s2n_prf.c b/contrib/restricted/aws/s2n/tls/s2n_prf.c
index 325968cff4..3e912453c5 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_prf.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_prf.c
@@ -29,11 +29,92 @@
#include "stuffer/s2n_stuffer.h"
#include "tls/s2n_cipher_suites.h"
#include "tls/s2n_connection.h"
+#include "tls/s2n_crypto_constants.h"
#include "tls/s2n_tls.h"
#include "utils/s2n_blob.h"
#include "utils/s2n_mem.h"
#include "utils/s2n_safety.h"
+S2N_RESULT s2n_key_material_init(struct s2n_key_material *key_material, struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(key_material);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->secure);
+ RESULT_ENSURE_REF(conn->secure->cipher_suite);
+ RESULT_ENSURE_REF(conn->secure->cipher_suite->record_alg);
+ const struct s2n_cipher *cipher = conn->secure->cipher_suite->record_alg->cipher;
+ RESULT_ENSURE_REF(cipher);
+
+ uint8_t mac_size = 0;
+ uint32_t key_size = 0;
+ uint32_t iv_size = 0;
+
+ /* MAC size */
+ if (cipher->type == S2N_COMPOSITE) {
+ mac_size = cipher->io.comp.mac_key_size;
+ } else {
+ RESULT_GUARD_POSIX(s2n_hmac_digest_size(conn->secure->cipher_suite->record_alg->hmac_alg, &mac_size));
+ }
+
+ /* KEY size */
+ key_size = cipher->key_material_size;
+
+ /* Only AEAD ciphers have implicit IVs for TLS >= 1.1 */
+ if (conn->actual_protocol_version <= S2N_TLS10 || cipher->type == S2N_AEAD) {
+ /* IV size */
+ switch (cipher->type) {
+ case S2N_AEAD:
+ iv_size = cipher->io.aead.fixed_iv_size;
+ break;
+ case S2N_CBC:
+ iv_size = cipher->io.cbc.block_size;
+ break;
+ case S2N_COMPOSITE:
+ iv_size = cipher->io.comp.block_size;
+ break;
+ /* No-op for stream ciphers */
+ default:
+ break;
+ }
+ }
+
+ struct s2n_stuffer key_material_stuffer = { 0 };
+ struct s2n_blob key_material_blob = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&key_material_blob, key_material->key_block, sizeof(key_material->key_block)));
+ RESULT_GUARD_POSIX(s2n_stuffer_init_written(&key_material_stuffer, &key_material_blob));
+
+ /* initialize key_material blobs; incrementing ptr to point to the next slice of memory */
+ uint8_t *ptr = NULL;
+ /* MAC */
+ ptr = s2n_stuffer_raw_read(&key_material_stuffer, mac_size);
+ RESULT_ENSURE_REF(ptr);
+ RESULT_GUARD_POSIX(s2n_blob_init(&key_material->client_mac, ptr, mac_size));
+
+ ptr = s2n_stuffer_raw_read(&key_material_stuffer, mac_size);
+ RESULT_ENSURE_REF(ptr);
+ RESULT_GUARD_POSIX(s2n_blob_init(&key_material->server_mac, ptr, mac_size));
+
+ /* KEY */
+ ptr = s2n_stuffer_raw_read(&key_material_stuffer, key_size);
+ RESULT_ENSURE_REF(ptr);
+ RESULT_GUARD_POSIX(s2n_blob_init(&key_material->client_key, ptr, key_size));
+
+ ptr = s2n_stuffer_raw_read(&key_material_stuffer, key_size);
+ RESULT_ENSURE_REF(ptr);
+ RESULT_GUARD_POSIX(s2n_blob_init(&key_material->server_key, ptr, key_size));
+
+ /* IV */
+ ptr = s2n_stuffer_raw_read(&key_material_stuffer, iv_size);
+ RESULT_ENSURE_REF(ptr);
+ RESULT_GUARD_POSIX(s2n_blob_init(&key_material->client_iv, ptr, iv_size));
+
+ ptr = s2n_stuffer_raw_read(&key_material_stuffer, iv_size);
+ RESULT_ENSURE_REF(ptr);
+ RESULT_GUARD_POSIX(s2n_blob_init(&key_material->server_iv, ptr, iv_size));
+
+ return S2N_RESULT_OK;
+}
+
static int s2n_sslv3_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct s2n_blob *seed_a,
struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out)
{
@@ -96,35 +177,6 @@ static int s2n_sslv3_prf(struct s2n_connection *conn, struct s2n_blob *secret, s
return 0;
}
-static int s2n_init_md_from_hmac_alg(struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg)
-{
- switch (alg) {
- case S2N_HMAC_SSLv3_MD5:
- case S2N_HMAC_MD5:
- ws->p_hash.evp_hmac.evp_digest.md = EVP_md5();
- break;
- case S2N_HMAC_SSLv3_SHA1:
- case S2N_HMAC_SHA1:
- ws->p_hash.evp_hmac.evp_digest.md = EVP_sha1();
- break;
- case S2N_HMAC_SHA224:
- ws->p_hash.evp_hmac.evp_digest.md = EVP_sha224();
- break;
- case S2N_HMAC_SHA256:
- ws->p_hash.evp_hmac.evp_digest.md = EVP_sha256();
- break;
- case S2N_HMAC_SHA384:
- ws->p_hash.evp_hmac.evp_digest.md = EVP_sha384();
- break;
- case S2N_HMAC_SHA512:
- ws->p_hash.evp_hmac.evp_digest.md = EVP_sha512();
- break;
- default:
- POSIX_BAIL(S2N_ERR_P_HASH_INVALID_ALGORITHM);
- }
- return S2N_SUCCESS;
-}
-
#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
static int s2n_evp_pkey_p_hash_alloc(struct s2n_prf_working_space *ws)
{
@@ -152,7 +204,7 @@ static int s2n_evp_pkey_p_hash_digest_init(struct s2n_prf_working_space *ws)
static int s2n_evp_pkey_p_hash_init(struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg, struct s2n_blob *secret)
{
/* Initialize the message digest */
- POSIX_GUARD(s2n_init_md_from_hmac_alg(ws, alg));
+ POSIX_GUARD_RESULT(s2n_hmac_md_from_alg(alg, &ws->p_hash.evp_hmac.evp_digest.md));
/* Initialize the mac key using the provided secret */
POSIX_ENSURE_REF(ws->p_hash.evp_hmac.ctx.evp_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, secret->data, secret->size));
@@ -240,7 +292,7 @@ static int s2n_evp_hmac_p_hash_alloc(struct s2n_prf_working_space *ws)
static int s2n_evp_hmac_p_hash_init(struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg, struct s2n_blob *secret)
{
/* Figure out the correct EVP_MD from s2n_hmac_algorithm */
- POSIX_GUARD(s2n_init_md_from_hmac_alg(ws, alg));
+ POSIX_GUARD_RESULT(s2n_hmac_md_from_alg(alg, &ws->p_hash.evp_hmac.evp_digest.md));
/* Initialize the mac and digest */
POSIX_GUARD_OSSL(HMAC_Init_ex(ws->p_hash.evp_hmac.ctx.hmac_ctx, secret->data, secret->size, ws->p_hash.evp_hmac.evp_digest.md, NULL), S2N_ERR_P_HASH_INIT_FAILED);
@@ -459,43 +511,145 @@ S2N_RESULT s2n_prf_free(struct s2n_connection *conn)
return S2N_RESULT_OK;
}
-static int s2n_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct s2n_blob *label, struct s2n_blob *seed_a,
- struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out)
+bool s2n_libcrypto_supports_tls_prf()
{
- POSIX_ENSURE_REF(conn);
- POSIX_ENSURE_REF(secret);
- POSIX_ENSURE_REF(conn->prf_space);
- POSIX_ENSURE_REF(conn->secure);
-
- /* seed_a is always required, seed_b is optional, if seed_c is provided seed_b must also be provided */
- S2N_ERROR_IF(seed_a == NULL, S2N_ERR_PRF_INVALID_SEED);
- S2N_ERROR_IF(seed_b == NULL && seed_c != NULL, S2N_ERR_PRF_INVALID_SEED);
-
- if (conn->actual_protocol_version == S2N_SSLv3) {
- return s2n_sslv3_prf(conn, secret, seed_a, seed_b, seed_c, out);
- }
+#if S2N_LIBCRYPTO_SUPPORTS_TLS_PRF
+ return true;
+#else
+ return false;
+#endif
+}
+S2N_RESULT s2n_custom_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct s2n_blob *label,
+ struct s2n_blob *seed_a, struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out)
+{
/* We zero the out blob because p_hash works by XOR'ing with the existing
* buffer. This is a little convoluted but means we can avoid dynamic memory
* allocation. When we call p_hash once (in the TLS1.2 case) it will produce
* the right values. When we call it twice in the regular case, the two
* outputs will be XORd just ass the TLS 1.0 and 1.1 RFCs require.
*/
- POSIX_GUARD(s2n_blob_zero(out));
+ RESULT_GUARD_POSIX(s2n_blob_zero(out));
if (conn->actual_protocol_version == S2N_TLS12) {
- return s2n_p_hash(conn->prf_space, conn->secure->cipher_suite->prf_alg, secret, label, seed_a, seed_b,
- seed_c, out);
+ RESULT_GUARD_POSIX(s2n_p_hash(conn->prf_space, conn->secure->cipher_suite->prf_alg, secret, label, seed_a,
+ seed_b, seed_c, out));
+ return S2N_RESULT_OK;
}
struct s2n_blob half_secret = { 0 };
- POSIX_GUARD(s2n_blob_init(&half_secret, secret->data, (secret->size + 1) / 2));
+ RESULT_GUARD_POSIX(s2n_blob_init(&half_secret, secret->data, (secret->size + 1) / 2));
- POSIX_GUARD(s2n_p_hash(conn->prf_space, S2N_HMAC_MD5, &half_secret, label, seed_a, seed_b, seed_c, out));
+ RESULT_GUARD_POSIX(s2n_p_hash(conn->prf_space, S2N_HMAC_MD5, &half_secret, label, seed_a, seed_b, seed_c, out));
half_secret.data += secret->size - half_secret.size;
- POSIX_GUARD(s2n_p_hash(conn->prf_space, S2N_HMAC_SHA1, &half_secret, label, seed_a, seed_b, seed_c, out));
+ RESULT_GUARD_POSIX(s2n_p_hash(conn->prf_space, S2N_HMAC_SHA1, &half_secret, label, seed_a, seed_b, seed_c, out));
- return 0;
+ return S2N_RESULT_OK;
+}
+
+#if S2N_LIBCRYPTO_SUPPORTS_TLS_PRF
+
+/* The AWSLC TLS PRF API is exported in all AWSLC versions. However, in the AWSLC FIPS branch, this
+ * API is defined in a private header:
+ * https://github.com/aws/aws-lc/blob/d251b365b73a6e6acff6ee634aa8f077f23cdea4/crypto/fipsmodule/tls/internal.h#L27
+ *
+ * AWSLC has committed to this API definition, and the API has been added to a public header in the
+ * main branch: https://github.com/aws/aws-lc/pull/1033. As such, this API is forward-declared in
+ * order to make it accessible to s2n-tls when linked to AWSLC-FIPS.
+ */
+int CRYPTO_tls1_prf(const EVP_MD *digest,
+ uint8_t *out, size_t out_len,
+ const uint8_t *secret, size_t secret_len,
+ const char *label, size_t label_len,
+ const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len);
+
+S2N_RESULT s2n_libcrypto_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct s2n_blob *label,
+ struct s2n_blob *seed_a, struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out)
+{
+ const EVP_MD *digest = NULL;
+ if (conn->actual_protocol_version < S2N_TLS12) {
+ /* md5_sha1 is a digest that indicates both MD5 and SHA1 should be used in the PRF calculation.
+ * This is needed for pre-TLS12 PRFs.
+ */
+ digest = EVP_md5_sha1();
+ } else {
+ RESULT_GUARD(s2n_hmac_md_from_alg(conn->secure->cipher_suite->prf_alg, &digest));
+ }
+ RESULT_ENSURE_REF(digest);
+
+ DEFER_CLEANUP(struct s2n_stuffer seed_b_stuffer = { 0 }, s2n_stuffer_free);
+ size_t seed_b_len = 0;
+ uint8_t *seed_b_data = NULL;
+
+ if (seed_b != NULL) {
+ struct s2n_blob seed_b_blob = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&seed_b_blob, seed_b->data, seed_b->size));
+ RESULT_GUARD_POSIX(s2n_stuffer_init_written(&seed_b_stuffer, &seed_b_blob));
+
+ if (seed_c != NULL) {
+ /* The AWSLC TLS PRF implementation only provides two seed arguments. If three seeds
+ * were provided, pass in the third seed by concatenating it with the second seed.
+ */
+ RESULT_GUARD_POSIX(s2n_stuffer_alloc(&seed_b_stuffer, seed_b->size + seed_c->size));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&seed_b_stuffer, seed_b->data, seed_b->size));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&seed_b_stuffer, seed_c->data, seed_c->size));
+ }
+
+ seed_b_len = s2n_stuffer_data_available(&seed_b_stuffer);
+ seed_b_data = s2n_stuffer_raw_read(&seed_b_stuffer, seed_b_len);
+ RESULT_ENSURE_REF(seed_b_data);
+ }
+
+ RESULT_GUARD_OSSL(CRYPTO_tls1_prf(digest,
+ out->data, out->size,
+ secret->data, secret->size,
+ (const char *) label->data, label->size,
+ seed_a->data, seed_a->size,
+ seed_b_data, seed_b_len),
+ S2N_ERR_PRF_DERIVE);
+
+ return S2N_RESULT_OK;
+}
+#else
+S2N_RESULT s2n_libcrypto_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct s2n_blob *label,
+ struct s2n_blob *seed_a, struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out)
+{
+ RESULT_BAIL(S2N_ERR_UNIMPLEMENTED);
+}
+#endif /* S2N_LIBCRYPTO_SUPPORTS_TLS_PRF */
+
+int s2n_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct s2n_blob *label, struct s2n_blob *seed_a,
+ struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->secure);
+ POSIX_ENSURE_REF(conn->secure->cipher_suite);
+ POSIX_ENSURE_REF(conn->prf_space);
+ POSIX_ENSURE_REF(secret);
+ POSIX_ENSURE_REF(label);
+ POSIX_ENSURE_REF(out);
+
+ /* seed_a is always required, seed_b is optional, if seed_c is provided seed_b must also be provided */
+ POSIX_ENSURE(seed_a != NULL, S2N_ERR_PRF_INVALID_SEED);
+ POSIX_ENSURE(S2N_IMPLIES(seed_c != NULL, seed_b != NULL), S2N_ERR_PRF_INVALID_SEED);
+
+ if (conn->actual_protocol_version == S2N_SSLv3) {
+ POSIX_GUARD(s2n_sslv3_prf(conn, secret, seed_a, seed_b, seed_c, out));
+ return S2N_SUCCESS;
+ }
+
+ /* By default, s2n-tls uses a custom PRF implementation. When operating in FIPS mode, the
+ * FIPS-validated libcrypto implementation is used instead, if an implementation is provided.
+ */
+ if (s2n_is_in_fips_mode() && s2n_libcrypto_supports_tls_prf()) {
+ POSIX_GUARD_RESULT(s2n_libcrypto_prf(conn, secret, label, seed_a, seed_b, seed_c, out));
+ return S2N_SUCCESS;
+ }
+
+ POSIX_GUARD_RESULT(s2n_custom_prf(conn, secret, label, seed_a, seed_b, seed_c, out));
+
+ return S2N_SUCCESS;
}
int s2n_tls_prf_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret)
@@ -801,91 +955,102 @@ int s2n_prf_server_finished(struct s2n_connection *conn)
return s2n_prf(conn, &master_secret, &label, &md5, &sha, NULL, &server_finished);
}
-static int s2n_prf_make_client_key(struct s2n_connection *conn, struct s2n_stuffer *key_material)
+static int s2n_prf_make_client_key(struct s2n_connection *conn, struct s2n_key_material *key_material)
{
POSIX_ENSURE_REF(conn);
POSIX_ENSURE_REF(conn->secure);
-
- struct s2n_blob client_key = { 0 };
- client_key.size = conn->secure->cipher_suite->record_alg->cipher->key_material_size;
- client_key.data = s2n_stuffer_raw_read(key_material, client_key.size);
- POSIX_ENSURE_REF(client_key.data);
+ POSIX_ENSURE_REF(conn->secure->cipher_suite);
+ POSIX_ENSURE_REF(conn->secure->cipher_suite->record_alg);
+ const struct s2n_cipher *cipher = conn->secure->cipher_suite->record_alg->cipher;
+ POSIX_ENSURE_REF(cipher);
+ POSIX_ENSURE_REF(cipher->set_encryption_key);
+ POSIX_ENSURE_REF(cipher->set_decryption_key);
if (conn->mode == S2N_CLIENT) {
- POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure->client_key, &client_key));
+ POSIX_GUARD(cipher->set_encryption_key(&conn->secure->client_key, &key_material->client_key));
} else {
- POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure->client_key, &client_key));
+ POSIX_GUARD(cipher->set_decryption_key(&conn->secure->client_key, &key_material->client_key));
}
return 0;
}
-static int s2n_prf_make_server_key(struct s2n_connection *conn, struct s2n_stuffer *key_material)
+static int s2n_prf_make_server_key(struct s2n_connection *conn, struct s2n_key_material *key_material)
{
POSIX_ENSURE_REF(conn);
POSIX_ENSURE_REF(conn->secure);
-
- struct s2n_blob server_key = { 0 };
- server_key.size = conn->secure->cipher_suite->record_alg->cipher->key_material_size;
- server_key.data = s2n_stuffer_raw_read(key_material, server_key.size);
- POSIX_ENSURE_REF(server_key.data);
+ POSIX_ENSURE_REF(conn->secure->cipher_suite);
+ POSIX_ENSURE_REF(conn->secure->cipher_suite->record_alg);
+ const struct s2n_cipher *cipher = conn->secure->cipher_suite->record_alg->cipher;
+ POSIX_ENSURE_REF(cipher);
+ POSIX_ENSURE_REF(cipher->set_encryption_key);
+ POSIX_ENSURE_REF(cipher->set_decryption_key);
if (conn->mode == S2N_SERVER) {
- POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure->server_key, &server_key));
+ POSIX_GUARD(cipher->set_encryption_key(&conn->secure->server_key, &key_material->server_key));
} else {
- POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure->server_key, &server_key));
+ POSIX_GUARD(cipher->set_decryption_key(&conn->secure->server_key, &key_material->server_key));
}
return 0;
}
-int s2n_prf_key_expansion(struct s2n_connection *conn)
+S2N_RESULT s2n_prf_generate_key_material(struct s2n_connection *conn, struct s2n_key_material *key_material)
{
- POSIX_ENSURE_REF(conn);
- POSIX_ENSURE_REF(conn->secure);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(key_material);
struct s2n_blob client_random = { 0 };
- POSIX_GUARD(s2n_blob_init(&client_random, conn->handshake_params.client_random, sizeof(conn->handshake_params.client_random)));
+ RESULT_GUARD_POSIX(s2n_blob_init(&client_random, conn->handshake_params.client_random, sizeof(conn->handshake_params.client_random)));
struct s2n_blob server_random = { 0 };
- POSIX_GUARD(s2n_blob_init(&server_random, conn->handshake_params.server_random, sizeof(conn->handshake_params.server_random)));
+ RESULT_GUARD_POSIX(s2n_blob_init(&server_random, conn->handshake_params.server_random, sizeof(conn->handshake_params.server_random)));
struct s2n_blob master_secret = { 0 };
- POSIX_GUARD(s2n_blob_init(&master_secret, conn->secrets.version.tls12.master_secret, sizeof(conn->secrets.version.tls12.master_secret)));
- struct s2n_blob label, out;
+ RESULT_GUARD_POSIX(s2n_blob_init(&master_secret, conn->secrets.version.tls12.master_secret, sizeof(conn->secrets.version.tls12.master_secret)));
+
+ struct s2n_blob label = { 0 };
uint8_t key_expansion_label[] = "key expansion";
- uint8_t key_block[S2N_MAX_KEY_BLOCK_LEN];
+ RESULT_GUARD_POSIX(s2n_blob_init(&label, key_expansion_label, sizeof(key_expansion_label) - 1));
- label.data = key_expansion_label;
- label.size = sizeof(key_expansion_label) - 1;
- POSIX_GUARD(s2n_blob_init(&out, key_block, sizeof(key_block)));
+ RESULT_GUARD(s2n_key_material_init(key_material, conn));
+ struct s2n_blob prf_out = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&prf_out, key_material->key_block, sizeof(key_material->key_block)));
+ RESULT_GUARD_POSIX(s2n_prf(conn, &master_secret, &label, &server_random, &client_random, NULL, &prf_out));
- struct s2n_stuffer key_material = { 0 };
- POSIX_GUARD(s2n_prf(conn, &master_secret, &label, &server_random, &client_random, NULL, &out));
- POSIX_GUARD(s2n_stuffer_init(&key_material, &out));
- POSIX_GUARD(s2n_stuffer_write(&key_material, &out));
+ return S2N_RESULT_OK;
+}
- POSIX_ENSURE(conn->secure->cipher_suite->available, S2N_ERR_PRF_INVALID_ALGORITHM);
- POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->client_key));
- POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->server_key));
+int s2n_prf_key_expansion(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->secure);
+ struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite;
+ POSIX_ENSURE_REF(cipher_suite);
+ POSIX_ENSURE_REF(cipher_suite->record_alg);
+ const struct s2n_cipher *cipher = cipher_suite->record_alg->cipher;
+ POSIX_ENSURE_REF(cipher);
- /* Check that we have a valid MAC and key size */
- uint8_t mac_size;
- if (conn->secure->cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) {
- mac_size = conn->secure->cipher_suite->record_alg->cipher->io.comp.mac_key_size;
- } else {
- POSIX_GUARD(s2n_hmac_digest_size(conn->secure->cipher_suite->record_alg->hmac_alg, &mac_size));
- }
+ struct s2n_key_material key_material = { 0 };
+ POSIX_GUARD_RESULT(s2n_prf_generate_key_material(conn, &key_material));
+
+ POSIX_ENSURE(cipher_suite->available, S2N_ERR_PRF_INVALID_ALGORITHM);
+ POSIX_GUARD(cipher->init(&conn->secure->client_key));
+ POSIX_GUARD(cipher->init(&conn->secure->server_key));
/* Seed the client MAC */
- uint8_t *client_mac_write_key = s2n_stuffer_raw_read(&key_material, mac_size);
- POSIX_ENSURE_REF(client_mac_write_key);
POSIX_GUARD(s2n_hmac_reset(&conn->secure->client_record_mac));
- POSIX_GUARD(s2n_hmac_init(&conn->secure->client_record_mac, conn->secure->cipher_suite->record_alg->hmac_alg, client_mac_write_key, mac_size));
+ POSIX_GUARD(s2n_hmac_init(
+ &conn->secure->client_record_mac,
+ cipher_suite->record_alg->hmac_alg,
+ key_material.client_mac.data,
+ key_material.client_mac.size));
/* Seed the server MAC */
- uint8_t *server_mac_write_key = s2n_stuffer_raw_read(&key_material, mac_size);
- POSIX_ENSURE_REF(server_mac_write_key);
POSIX_GUARD(s2n_hmac_reset(&conn->secure->server_record_mac));
- POSIX_GUARD(s2n_hmac_init(&conn->secure->server_record_mac, conn->secure->cipher_suite->record_alg->hmac_alg, server_mac_write_key, mac_size));
+ POSIX_GUARD(s2n_hmac_init(
+ &conn->secure->server_record_mac,
+ conn->secure->cipher_suite->record_alg->hmac_alg,
+ key_material.server_mac.data,
+ key_material.server_mac.size));
/* Make the client key */
POSIX_GUARD(s2n_prf_make_client_key(conn, &key_material));
@@ -893,41 +1058,19 @@ int s2n_prf_key_expansion(struct s2n_connection *conn)
/* Make the server key */
POSIX_GUARD(s2n_prf_make_server_key(conn, &key_material));
- /* Composite CBC does MAC inside the cipher, pass it the MAC key.
+ /* Composite CBC does MAC inside the cipher, pass it the MAC key.
* Must happen after setting encryption/decryption keys.
*/
- if (conn->secure->cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) {
- POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->io.comp.set_mac_write_key(&conn->secure->server_key, server_mac_write_key, mac_size));
- POSIX_GUARD(conn->secure->cipher_suite->record_alg->cipher->io.comp.set_mac_write_key(&conn->secure->client_key, client_mac_write_key, mac_size));
- }
-
- /* TLS >= 1.1 has no implicit IVs for non AEAD ciphers */
- if (conn->actual_protocol_version > S2N_TLS10 && conn->secure->cipher_suite->record_alg->cipher->type != S2N_AEAD) {
- return 0;
- }
-
- uint32_t implicit_iv_size = 0;
- switch (conn->secure->cipher_suite->record_alg->cipher->type) {
- case S2N_AEAD:
- implicit_iv_size = conn->secure->cipher_suite->record_alg->cipher->io.aead.fixed_iv_size;
- break;
- case S2N_CBC:
- implicit_iv_size = conn->secure->cipher_suite->record_alg->cipher->io.cbc.block_size;
- break;
- case S2N_COMPOSITE:
- implicit_iv_size = conn->secure->cipher_suite->record_alg->cipher->io.comp.block_size;
- break;
- /* No-op for stream ciphers */
- default:
- break;
+ if (cipher->type == S2N_COMPOSITE) {
+ POSIX_GUARD(cipher->io.comp.set_mac_write_key(&conn->secure->client_key, key_material.client_mac.data, key_material.client_mac.size));
+ POSIX_GUARD(cipher->io.comp.set_mac_write_key(&conn->secure->server_key, key_material.server_mac.data, key_material.server_mac.size));
}
- struct s2n_blob client_implicit_iv = { 0 };
- POSIX_GUARD(s2n_blob_init(&client_implicit_iv, conn->secure->client_implicit_iv, implicit_iv_size));
- struct s2n_blob server_implicit_iv = { 0 };
- POSIX_GUARD(s2n_blob_init(&server_implicit_iv, conn->secure->server_implicit_iv, implicit_iv_size));
- POSIX_GUARD(s2n_stuffer_read(&key_material, &client_implicit_iv));
- POSIX_GUARD(s2n_stuffer_read(&key_material, &server_implicit_iv));
+ /* set IV */
+ POSIX_ENSURE_EQ(key_material.client_iv.size, key_material.server_iv.size);
+ POSIX_ENSURE_LTE(key_material.client_iv.size, S2N_TLS_MAX_IV_LEN);
+ POSIX_CHECKED_MEMCPY(conn->secure->client_implicit_iv, key_material.client_iv.data, key_material.client_iv.size);
+ POSIX_CHECKED_MEMCPY(conn->secure->server_implicit_iv, key_material.server_iv.data, key_material.server_iv.size);
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_prf.h b/contrib/restricted/aws/s2n/tls/s2n_prf.h
index dae7e10da1..2db2db5e2e 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_prf.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_prf.h
@@ -25,6 +25,12 @@
/* Enough to support TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, 2*SHA384_DIGEST_LEN + 2*AES256_KEY_SIZE */
#define S2N_MAX_KEY_BLOCK_LEN 160
+#if defined(OPENSSL_IS_AWSLC)
+ #define S2N_LIBCRYPTO_SUPPORTS_TLS_PRF 1
+#else
+ #define S2N_LIBCRYPTO_SUPPORTS_TLS_PRF 0
+#endif
+
union p_hash_state {
struct s2n_hmac_state s2n_hmac;
struct s2n_evp_hmac_state evp_hmac;
@@ -48,17 +54,49 @@ struct s2n_p_hash_hmac {
int (*free)(struct s2n_prf_working_space *ws);
};
+/* TLS key expansion results in an array of contiguous data which is then
+ * interpreted as the MAC, KEY and IV for the client and server.
+ *
+ * The following is the memory layout of the key material:
+ *
+ * [ CLIENT_MAC, SERVER_MAC, CLIENT_KEY, SERVER_KEY, CLIENT_IV, SERVER_IV ]
+ */
+struct s2n_key_material {
+ /* key material data resulting from key expansion */
+ uint8_t key_block[S2N_MAX_KEY_BLOCK_LEN];
+
+ /* pointers into data representing specific key information */
+ struct s2n_blob client_mac;
+ struct s2n_blob server_mac;
+ struct s2n_blob client_key;
+ struct s2n_blob server_key;
+ struct s2n_blob client_iv;
+ struct s2n_blob server_iv;
+};
+
+S2N_RESULT s2n_key_material_init(struct s2n_key_material *key_material, struct s2n_connection *conn);
+
#include "tls/s2n_connection.h"
S2N_RESULT s2n_prf_new(struct s2n_connection *conn);
S2N_RESULT s2n_prf_wipe(struct s2n_connection *conn);
S2N_RESULT s2n_prf_free(struct s2n_connection *conn);
+int s2n_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct s2n_blob *label, struct s2n_blob *seed_a,
+ struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out);
int s2n_prf_calculate_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret);
int s2n_tls_prf_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret);
int s2n_hybrid_prf_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret);
S2N_RESULT s2n_tls_prf_extended_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret, struct s2n_blob *session_hash, struct s2n_blob *sha1_hash);
S2N_RESULT s2n_prf_get_digest_for_ems(struct s2n_connection *conn, struct s2n_blob *message, s2n_hash_algorithm hash_alg, struct s2n_blob *output);
+S2N_RESULT s2n_prf_generate_key_material(struct s2n_connection *conn, struct s2n_key_material *key_material);
int s2n_prf_key_expansion(struct s2n_connection *conn);
int s2n_prf_server_finished(struct s2n_connection *conn);
int s2n_prf_client_finished(struct s2n_connection *conn);
+
+bool s2n_libcrypto_supports_tls_prf();
+
+S2N_RESULT s2n_custom_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct s2n_blob *label,
+ struct s2n_blob *seed_a, struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out);
+S2N_RESULT s2n_libcrypto_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct s2n_blob *label,
+ struct s2n_blob *seed_a, struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_quic_support.h b/contrib/restricted/aws/s2n/tls/s2n_quic_support.h
index a6ffe68235..04e8165e4e 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_quic_support.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_quic_support.h
@@ -56,6 +56,7 @@ typedef enum {
S2N_SERVER_HANDSHAKE_TRAFFIC_SECRET,
S2N_CLIENT_APPLICATION_TRAFFIC_SECRET,
S2N_SERVER_APPLICATION_TRAFFIC_SECRET,
+ S2N_EXPORTER_SECRET,
} s2n_secret_type_t;
/*
diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_read.c b/contrib/restricted/aws/s2n/tls/s2n_record_read.c
index 552b6b2aae..484570e103 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_record_read.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_record_read.c
@@ -106,12 +106,19 @@ int s2n_record_header_parse(
S2N_ERROR_IF(conn->actual_protocol_version_established && MIN(conn->actual_protocol_version, S2N_TLS12) /* check against legacy record version (1.2) in tls 1.3 */
!= version,
S2N_ERR_BAD_MESSAGE);
- POSIX_GUARD(s2n_stuffer_read_uint16(in, fragment_length));
- /* Some servers send fragments that are above the maximum length. (e.g.
- * Openssl 1.0.1, so we don't check if the fragment length is >
- * S2N_TLS_MAXIMUM_FRAGMENT_LENGTH. The on-the-wire max is 65k
+ /* Some servers send fragments that are above the maximum length (e.g.
+ * Openssl 1.0.1), so we don't check if the fragment length is >
+ * S2N_TLS_MAXIMUM_FRAGMENT_LENGTH. We allow up to 2^16.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-5.1
+ *= type=exception
+ *= reason=Incorrect implementations exist in the wild. Ignoring instead.
+ *# The length MUST NOT exceed 2^14 bytes. An
+ *# endpoint that receives a record that exceeds this length MUST
+ *# terminate the connection with a "record_overflow" alert.
*/
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, fragment_length));
POSIX_GUARD(s2n_stuffer_reread(in));
return 0;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_write.c b/contrib/restricted/aws/s2n/tls/s2n_record_write.c
index 9a3ed93fd3..dd115a3ca2 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_record_write.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_record_write.c
@@ -24,6 +24,7 @@
#include "tls/s2n_cipher_suites.h"
#include "tls/s2n_connection.h"
#include "tls/s2n_crypto.h"
+#include "tls/s2n_ktls.h"
#include "tls/s2n_record.h"
#include "utils/s2n_blob.h"
#include "utils/s2n_random.h"
@@ -247,6 +248,10 @@ static inline int s2n_record_encrypt(
int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const struct iovec *in, int in_count, size_t offs, size_t to_write)
{
+ if (conn->ktls_send_enabled) {
+ return s2n_ktls_record_writev(conn, content_type, in, in_count, offs, to_write);
+ }
+
struct s2n_blob iv = { 0 };
uint8_t padding = 0;
uint16_t block_size = 0;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_recv.c b/contrib/restricted/aws/s2n/tls/s2n_recv.c
index 0f6256844f..691c2e2daa 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_recv.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_recv.c
@@ -26,11 +26,13 @@
#include "tls/s2n_alerts.h"
#include "tls/s2n_connection.h"
#include "tls/s2n_handshake.h"
+#include "tls/s2n_ktls.h"
#include "tls/s2n_post_handshake.h"
#include "tls/s2n_record.h"
#include "tls/s2n_resume.h"
#include "tls/s2n_tls.h"
#include "utils/s2n_blob.h"
+#include "utils/s2n_io.h"
#include "utils/s2n_safety.h"
#include "utils/s2n_socket.h"
@@ -42,14 +44,9 @@ S2N_RESULT s2n_read_in_bytes(struct s2n_connection *conn, struct s2n_stuffer *ou
errno = 0;
int r = s2n_connection_recv_stuffer(output, conn, remaining);
if (r == 0) {
- conn->read_closed = 1;
- RESULT_BAIL(S2N_ERR_CLOSED);
- } else if (r < 0) {
- if (errno == EWOULDBLOCK || errno == EAGAIN) {
- RESULT_BAIL(S2N_ERR_IO_BLOCKED);
- }
- RESULT_BAIL(S2N_ERR_IO);
+ s2n_atomic_flag_set(&conn->read_closed);
}
+ RESULT_GUARD(s2n_io_check_read_result(r));
conn->wire_bytes_in += r;
}
@@ -60,6 +57,10 @@ int s2n_read_full_record(struct s2n_connection *conn, uint8_t *record_type, int
{
*isSSLv2 = 0;
+ if (conn->ktls_recv_enabled) {
+ return s2n_ktls_read_full_record(conn, record_type);
+ }
+
/* If the record has already been decrypted, then leave it alone */
if (conn->in_status == PLAINTEXT) {
/* Only application data packets count as plaintext */
@@ -108,12 +109,25 @@ int s2n_read_full_record(struct s2n_connection *conn, uint8_t *record_type, int
return 0;
}
-ssize_t s2n_recv_impl(struct s2n_connection *conn, void *buf, ssize_t size, s2n_blocked_status *blocked)
+ssize_t s2n_recv_impl(struct s2n_connection *conn, void *buf, ssize_t size_signed, s2n_blocked_status *blocked)
{
+ POSIX_ENSURE_GTE(size_signed, 0);
+ size_t size = size_signed;
ssize_t bytes_read = 0;
struct s2n_blob out = { 0 };
POSIX_GUARD(s2n_blob_init(&out, (uint8_t *) buf, 0));
+ /*
+ * Set the `blocked` status to BLOCKED_ON_READ by default
+ *
+ * The only case in which it should be updated is on a successful read into the provided buffer.
+ *
+ * Unfortunately, the current `blocked` behavior has become ossified by buggy applications that ignore
+ * error types and only read `blocked`. As such, it's very important to avoid changing how this value is updated
+ * as it could break applications.
+ */
+ *blocked = S2N_BLOCKED_ON_READ;
+
if (!s2n_connection_check_io_status(conn, S2N_IO_READABLE)) {
/*
*= https://tools.ietf.org/rfc/rfc8446#6.1
@@ -127,13 +141,11 @@ ssize_t s2n_recv_impl(struct s2n_connection *conn, void *buf, ssize_t size, s2n_
*# closed, the TLS implementation MUST receive a "close_notify" alert
*# before indicating end-of-data to the application layer.
*/
- POSIX_ENSURE(conn->close_notify_received, S2N_ERR_CLOSED);
+ POSIX_ENSURE(s2n_atomic_flag_test(&conn->close_notify_received), S2N_ERR_CLOSED);
*blocked = S2N_NOT_BLOCKED;
return 0;
}
- *blocked = S2N_BLOCKED_ON_READ;
-
POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_UNSUPPORTED_WITH_QUIC);
POSIX_GUARD_RESULT(s2n_early_data_validate_recv(conn));
@@ -142,17 +154,9 @@ ssize_t s2n_recv_impl(struct s2n_connection *conn, void *buf, ssize_t size, s2n_
uint8_t record_type;
int r = s2n_read_full_record(conn, &record_type, &isSSLv2);
if (r < 0) {
- /* Don't propagate the error if we already read some bytes.
- * We'll report S2N_ERR_CLOSED on the next call.
- */
- if (s2n_errno == S2N_ERR_CLOSED && bytes_read) {
- return bytes_read;
- }
-
- /* Don't propagate the error if we already read some bytes */
- if (s2n_errno == S2N_ERR_IO_BLOCKED && bytes_read) {
- s2n_errno = S2N_ERR_OK;
- return bytes_read;
+ /* Don't propagate the error if we already read some bytes. */
+ if (bytes_read && (s2n_errno == S2N_ERR_CLOSED || s2n_errno == S2N_ERR_IO_BLOCKED)) {
+ break;
}
/* If we get here, it's an error condition */
@@ -226,6 +230,13 @@ ssize_t s2n_recv_impl(struct s2n_connection *conn, void *buf, ssize_t size, s2n_
}
}
+ /* Due to the history of this API, some applications depend on the blocked status to know if
+ * the connection's `in` stuffer was completely cleared. This behavior needs to be preserved.
+ *
+ * Moving forward, applications should instead use `s2n_peek`, which accomplishes the same thing
+ * without conflating being blocked on reading from the OS socket vs blocked on the application's
+ * buffer size.
+ */
if (s2n_stuffer_data_available(&conn->in) == 0) {
*blocked = S2N_NOT_BLOCKED;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c b/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c
index f930390d79..84765e4472 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_renegotiate.c
@@ -36,6 +36,8 @@ S2N_RESULT s2n_renegotiate_validate(struct s2n_connection *conn)
RESULT_ENSURE(conn->mode == S2N_CLIENT, S2N_ERR_NO_RENEGOTIATION);
RESULT_ENSURE(conn->secure_renegotiation, S2N_ERR_NO_RENEGOTIATION);
RESULT_ENSURE(conn->handshake.renegotiation, S2N_ERR_INVALID_STATE);
+ RESULT_ENSURE(!conn->ktls_send_enabled, S2N_ERR_KTLS_RENEG);
+ RESULT_ENSURE(!conn->ktls_recv_enabled, S2N_ERR_KTLS_RENEG);
return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_resume.c b/contrib/restricted/aws/s2n/tls/s2n_resume.c
index c667020017..d5f10b7ad0 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_resume.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_resume.c
@@ -122,7 +122,7 @@ static S2N_RESULT s2n_tls13_serialize_resumption_state(struct s2n_connection *co
RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(out, conn->secure->cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
RESULT_GUARD_POSIX(s2n_stuffer_write_uint64(out, current_time));
RESULT_GUARD_POSIX(s2n_stuffer_write_uint32(out, ticket_fields->ticket_age_add));
- RESULT_ENSURE_LTE(ticket_fields->session_secret.size, UINT8_MAX);
+ RESULT_ENSURE_INCLUSIVE_RANGE(1, ticket_fields->session_secret.size, UINT8_MAX);
RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, ticket_fields->session_secret.size));
RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(out, ticket_fields->session_secret.data, ticket_fields->session_secret.size));
RESULT_GUARD(s2n_tls13_serialize_keying_material_expiration(conn, current_time, out));
@@ -228,27 +228,53 @@ static int s2n_client_serialize_resumption_state(struct s2n_connection *conn, st
return 0;
}
-static S2N_RESULT s2n_tls12_client_deserialize_session_state(struct s2n_connection *conn, struct s2n_stuffer *from)
+static S2N_RESULT s2n_tls12_client_deserialize_session_state(struct s2n_connection *conn,
+ struct s2n_blob *ticket, struct s2n_stuffer *from)
{
RESULT_ENSURE_REF(conn);
RESULT_ENSURE_REF(from);
- RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &conn->resume_protocol_version));
+ /* Operate on a copy of the connection to avoid mutating the connection on
+ * failure. We have tests in s2n_resume_test.c that prove this level of copy
+ * is sufficient.
+ */
+ struct s2n_crypto_parameters *secure = conn->secure;
+ RESULT_ENSURE_REF(secure);
+ struct s2n_connection temp_conn = *conn;
+ struct s2n_crypto_parameters temp_secure = *secure;
+ temp_conn.secure = &temp_secure;
+
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &temp_conn.resume_protocol_version));
uint8_t *cipher_suite_wire = s2n_stuffer_raw_read(from, S2N_TLS_CIPHER_SUITE_LEN);
RESULT_ENSURE_REF(cipher_suite_wire);
- RESULT_GUARD_POSIX(s2n_set_cipher_as_client(conn, cipher_suite_wire));
+ RESULT_GUARD_POSIX(s2n_set_cipher_as_client(&temp_conn, cipher_suite_wire));
uint64_t then = 0;
RESULT_GUARD_POSIX(s2n_stuffer_read_uint64(from, &then));
- RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(from, conn->secrets.version.tls12.master_secret, S2N_TLS_SECRET_LEN));
+ RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(from, temp_conn.secrets.version.tls12.master_secret,
+ S2N_TLS_SECRET_LEN));
if (s2n_stuffer_data_available(from)) {
uint8_t ems_negotiated = 0;
RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &ems_negotiated));
- conn->ems_negotiated = ems_negotiated;
+ temp_conn.ems_negotiated = ems_negotiated;
+ }
+
+ DEFER_CLEANUP(struct s2n_blob client_ticket = { 0 }, s2n_free);
+ if (ticket) {
+ RESULT_GUARD_POSIX(s2n_dup(ticket, &client_ticket));
}
+
+ /* Finally, actually update the connection */
+ RESULT_GUARD_POSIX(s2n_free(&conn->client_ticket));
+ *secure = temp_secure;
+ *conn = temp_conn;
+ conn->secure = secure;
+ conn->client_ticket = client_ticket;
+ ZERO_TO_DISABLE_DEFER_CLEANUP(client_ticket);
+
return S2N_RESULT_OK;
}
@@ -337,7 +363,8 @@ static S2N_RESULT s2n_tls13_deserialize_session_state(struct s2n_connection *con
return S2N_RESULT_OK;
}
-S2N_RESULT s2n_deserialize_resumption_state(struct s2n_connection *conn, struct s2n_blob *psk_identity, struct s2n_stuffer *from)
+S2N_RESULT s2n_deserialize_resumption_state(struct s2n_connection *conn,
+ struct s2n_blob *ticket, struct s2n_stuffer *from)
{
RESULT_ENSURE_REF(conn);
RESULT_ENSURE_REF(from);
@@ -349,16 +376,10 @@ S2N_RESULT s2n_deserialize_resumption_state(struct s2n_connection *conn, struct
if (conn->mode == S2N_SERVER) {
RESULT_GUARD_POSIX(s2n_tls12_deserialize_resumption_state(conn, from));
} else {
- RESULT_GUARD(s2n_tls12_client_deserialize_session_state(conn, from));
+ RESULT_GUARD(s2n_tls12_client_deserialize_session_state(conn, ticket, from));
}
} else if (format == S2N_SERIALIZED_FORMAT_TLS13_V1) {
- RESULT_GUARD(s2n_tls13_deserialize_session_state(conn, psk_identity, from));
- if (conn->mode == S2N_CLIENT) {
- /* Free the client_ticket after setting a psk on the connection.
- * This prevents s2n_connection_get_session from returning a TLS1.3
- * ticket before a ticket has been received from the server. */
- RESULT_GUARD_POSIX(s2n_free(&conn->client_ticket));
- }
+ RESULT_GUARD(s2n_tls13_deserialize_session_state(conn, ticket, from));
} else {
RESULT_BAIL(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
}
@@ -386,18 +407,19 @@ static int s2n_client_deserialize_with_session_id(struct s2n_connection *conn, s
static int s2n_client_deserialize_with_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *from)
{
- uint16_t session_ticket_len;
+ uint16_t session_ticket_len = 0;
POSIX_GUARD(s2n_stuffer_read_uint16(from, &session_ticket_len));
if (session_ticket_len == 0 || session_ticket_len > s2n_stuffer_data_available(from)) {
POSIX_BAIL(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
}
- POSIX_GUARD(s2n_realloc(&conn->client_ticket, session_ticket_len));
- POSIX_GUARD(s2n_stuffer_read(from, &conn->client_ticket));
-
- POSIX_GUARD_RESULT(s2n_deserialize_resumption_state(conn, &conn->client_ticket, from));
+ struct s2n_blob session_ticket = { 0 };
+ uint8_t *session_ticket_bytes = s2n_stuffer_raw_read(from, session_ticket_len);
+ POSIX_ENSURE_REF(session_ticket_bytes);
+ POSIX_GUARD(s2n_blob_init(&session_ticket, session_ticket_bytes, session_ticket_len));
+ POSIX_GUARD_RESULT(s2n_deserialize_resumption_state(conn, &session_ticket, from));
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
index 40c410b92b..f4cf3c042d 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
@@ -369,6 +369,46 @@ const struct s2n_security_policy security_policy_aws_crt_sdk_tls_13 = {
.ecc_preferences = &s2n_ecc_preferences_20200310,
};
+const struct s2n_security_policy security_policy_aws_crt_sdk_ssl_v3_06_23 = {
+ .minimum_protocol_version = S2N_SSLv3,
+ .cipher_preferences = &cipher_preferences_aws_crt_sdk_ssl_v3,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20230623,
+};
+
+const struct s2n_security_policy security_policy_aws_crt_sdk_tls_10_06_23 = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_aws_crt_sdk_default,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20230623,
+};
+
+const struct s2n_security_policy security_policy_aws_crt_sdk_tls_11_06_23 = {
+ .minimum_protocol_version = S2N_TLS11,
+ .cipher_preferences = &cipher_preferences_aws_crt_sdk_default,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20230623,
+};
+
+const struct s2n_security_policy security_policy_aws_crt_sdk_tls_12_06_23 = {
+ .minimum_protocol_version = S2N_TLS12,
+ .cipher_preferences = &cipher_preferences_aws_crt_sdk_default,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20230623,
+};
+
+const struct s2n_security_policy security_policy_aws_crt_sdk_tls_13_06_23 = {
+ .minimum_protocol_version = S2N_TLS13,
+ .cipher_preferences = &cipher_preferences_aws_crt_sdk_tls_13,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20230623,
+};
+
const struct s2n_security_policy security_policy_kms_tls_1_0_2018_10 = {
.minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &cipher_preferences_kms_tls_1_0_2018_10,
@@ -385,6 +425,14 @@ const struct s2n_security_policy security_policy_kms_tls_1_0_2021_08 = {
.ecc_preferences = &s2n_ecc_preferences_20200310,
};
+const struct s2n_security_policy security_policy_kms_tls_1_2_2023_06 = {
+ .minimum_protocol_version = S2N_TLS12,
+ .cipher_preferences = &cipher_preferences_kms_tls_1_0_2021_08,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2019_06 = {
.minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &cipher_preferences_kms_pq_tls_1_0_2019_06,
@@ -559,6 +607,14 @@ const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_10 = {
.ecc_preferences = &s2n_ecc_preferences_20200310,
};
+const struct s2n_security_policy security_policy_pq_tls_1_3_2023_06_01 = {
+ .minimum_protocol_version = S2N_TLS12,
+ .cipher_preferences = &cipher_preferences_pq_tls_1_3_2023_06_01,
+ .kem_preferences = &kem_preferences_pq_tls_1_3_2023_06,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20201021,
+};
+
const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10 = {
.minimum_protocol_version = S2N_TLS12,
.cipher_preferences = &cipher_preferences_kms_fips_tls_1_2_2018_10,
@@ -767,7 +823,7 @@ const struct s2n_security_policy security_policy_rfc9151 = {
const struct s2n_security_policy security_policy_test_all = {
.minimum_protocol_version = S2N_SSLv3,
.cipher_preferences = &cipher_preferences_test_all,
- .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05,
+ .kem_preferences = &kem_preferences_all,
.signature_preferences = &s2n_signature_preferences_20201021,
.ecc_preferences = &s2n_ecc_preferences_test_all,
};
@@ -865,14 +921,21 @@ struct s2n_security_policy_selection security_policy_selection[] = {
{ .version = "CloudFront-TLS-1-1-2016-Legacy", .security_policy = &security_policy_cloudfront_tls_1_1_2016_legacy, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "CloudFront-TLS-1-2-2018-Legacy", .security_policy = &security_policy_cloudfront_tls_1_2_2018_legacy, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "CloudFront-TLS-1-2-2019-Legacy", .security_policy = &security_policy_cloudfront_tls_1_2_2019_legacy, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
+ /* CRT allows users to choose the minimal TLS protocol they want to negotiate with. This translates to 5 different security policies in s2n */
{ .version = "AWS-CRT-SDK-SSLv3.0", .security_policy = &security_policy_aws_crt_sdk_ssl_v3, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "AWS-CRT-SDK-TLSv1.0", .security_policy = &security_policy_aws_crt_sdk_tls_10, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "AWS-CRT-SDK-TLSv1.1", .security_policy = &security_policy_aws_crt_sdk_tls_11, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "AWS-CRT-SDK-TLSv1.2", .security_policy = &security_policy_aws_crt_sdk_tls_12, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "AWS-CRT-SDK-TLSv1.3", .security_policy = &security_policy_aws_crt_sdk_tls_13, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
+ { .version = "AWS-CRT-SDK-SSLv3.0-2023", .security_policy = &security_policy_aws_crt_sdk_ssl_v3_06_23, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
+ { .version = "AWS-CRT-SDK-TLSv1.0-2023", .security_policy = &security_policy_aws_crt_sdk_tls_10_06_23, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
+ { .version = "AWS-CRT-SDK-TLSv1.1-2023", .security_policy = &security_policy_aws_crt_sdk_tls_11_06_23, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
+ { .version = "AWS-CRT-SDK-TLSv1.2-2023", .security_policy = &security_policy_aws_crt_sdk_tls_12_06_23, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
+ { .version = "AWS-CRT-SDK-TLSv1.3-2023", .security_policy = &security_policy_aws_crt_sdk_tls_13_06_23, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
/* KMS TLS Policies*/
{ .version = "KMS-TLS-1-0-2018-10", .security_policy = &security_policy_kms_tls_1_0_2018_10, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "KMS-TLS-1-0-2021-08", .security_policy = &security_policy_kms_tls_1_0_2021_08, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
+ { .version = "KMS-TLS-1-2-2023-06", .security_policy = &security_policy_kms_tls_1_2_2023_06, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "KMS-FIPS-TLS-1-2-2018-10", .security_policy = &security_policy_kms_fips_tls_1_2_2018_10, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "KMS-FIPS-TLS-1-2-2021-08", .security_policy = &security_policy_kms_fips_tls_1_2_2021_08, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "KMS-PQ-TLS-1-0-2019-06", .security_policy = &security_policy_kms_pq_tls_1_0_2019_06, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
@@ -896,6 +959,7 @@ struct s2n_security_policy_selection security_policy_selection[] = {
{ .version = "PQ-TLS-1-2-2023-04-08", .security_policy = &security_policy_pq_tls_1_2_2023_04_08, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "PQ-TLS-1-2-2023-04-09", .security_policy = &security_policy_pq_tls_1_2_2023_04_09, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "PQ-TLS-1-2-2023-04-10", .security_policy = &security_policy_pq_tls_1_2_2023_04_10, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
+ { .version = "PQ-TLS-1-3-2023-06-01", .security_policy = &security_policy_pq_tls_1_3_2023_06_01, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "20140601", .security_policy = &security_policy_20140601, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "20141001", .security_policy = &security_policy_20141001, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "20150202", .security_policy = &security_policy_20150202, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
@@ -1026,7 +1090,7 @@ int s2n_security_policies_init()
security_policy_selection[i].ecc_extension_required = 1;
}
- if (s2n_cipher_suite_requires_pq_extension(cipher)) {
+ if (s2n_cipher_suite_requires_pq_extension(cipher) && kem_preference->kem_count > 0) {
security_policy_selection[i].pq_kem_extension_required = 1;
}
}
@@ -1074,6 +1138,11 @@ bool s2n_pq_kem_is_extension_required(const struct s2n_security_policy *security
}
}
+ /* Preferences with no KEMs for the TLS 1.2 PQ KEM extension do not require that extension. */
+ if (security_policy->kem_preferences && security_policy->kem_preferences->kem_count == 0) {
+ return false;
+ }
+
/* If cipher preference is not in the official list, compute the result */
const struct s2n_cipher_preferences *cipher_preferences = security_policy->cipher_preferences;
if (cipher_preferences == NULL) {
diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
index 367aeeb8c1..17d8b79149 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
@@ -150,6 +150,7 @@ extern const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_07;
extern const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_08;
extern const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_09;
extern const struct s2n_security_policy security_policy_pq_tls_1_2_2023_04_10;
+extern const struct s2n_security_policy security_policy_pq_tls_1_3_2023_06_01;
extern const struct s2n_security_policy security_policy_cloudfront_upstream;
extern const struct s2n_security_policy security_policy_cloudfront_upstream_tls10;
@@ -165,6 +166,7 @@ extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2021;
extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2021_chacha20_boosted;
extern const struct s2n_security_policy security_policy_kms_tls_1_0_2018_10;
+extern const struct s2n_security_policy security_policy_kms_tls_1_2_2023_06;
extern const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10;
extern const struct s2n_security_policy security_policy_20190120;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_send.c b/contrib/restricted/aws/s2n/tls/s2n_send.c
index 4fea390c88..a9ec8aa0d8 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_send.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_send.c
@@ -24,9 +24,11 @@
#include "tls/s2n_cipher_suites.h"
#include "tls/s2n_connection.h"
#include "tls/s2n_handshake.h"
+#include "tls/s2n_ktls.h"
#include "tls/s2n_post_handshake.h"
#include "tls/s2n_record.h"
#include "utils/s2n_blob.h"
+#include "utils/s2n_io.h"
#include "utils/s2n_safety.h"
/*
@@ -80,57 +82,24 @@ bool s2n_should_flush(struct s2n_connection *conn, ssize_t total_message_size)
int s2n_flush(struct s2n_connection *conn, s2n_blocked_status *blocked)
{
- int w;
-
*blocked = S2N_BLOCKED_ON_WRITE;
/* Write any data that's already pending */
-WRITE:
while (s2n_stuffer_data_available(&conn->out)) {
errno = 0;
- w = s2n_connection_send_stuffer(&conn->out, conn, s2n_stuffer_data_available(&conn->out));
- if (w < 0) {
- if (errno == EWOULDBLOCK || errno == EAGAIN) {
- POSIX_BAIL(S2N_ERR_IO_BLOCKED);
- }
- POSIX_BAIL(S2N_ERR_IO);
- }
+ int w = s2n_connection_send_stuffer(&conn->out, conn, s2n_stuffer_data_available(&conn->out));
+ POSIX_GUARD_RESULT(s2n_io_check_write_result(w));
conn->wire_bytes_out += w;
}
-
- if (conn->write_closing) {
- conn->write_closed = 1;
- }
POSIX_GUARD(s2n_stuffer_rewrite(&conn->out));
- /* If there's an alert pending out, send that */
- if (s2n_stuffer_data_available(&conn->reader_alert_out) == 2) {
- struct s2n_blob alert = { 0 };
- alert.data = conn->reader_alert_out.blob.data;
- alert.size = 2;
- POSIX_GUARD_RESULT(s2n_record_write(conn, TLS_ALERT, &alert));
- POSIX_GUARD(s2n_stuffer_rewrite(&conn->reader_alert_out));
- POSIX_GUARD_RESULT(s2n_alerts_close_if_fatal(conn, &alert));
-
- /* Actually write it ... */
- goto WRITE;
- }
-
- /* Do the same for writer driven alerts */
- if (s2n_stuffer_data_available(&conn->writer_alert_out) == 2) {
- struct s2n_blob alert = { 0 };
- alert.data = conn->writer_alert_out.blob.data;
- alert.size = 2;
- POSIX_GUARD_RESULT(s2n_record_write(conn, TLS_ALERT, &alert));
- POSIX_GUARD(s2n_stuffer_rewrite(&conn->writer_alert_out));
- POSIX_GUARD_RESULT(s2n_alerts_close_if_fatal(conn, &alert));
-
- /* Actually write it ... */
- goto WRITE;
+ if (conn->reader_warning_out) {
+ POSIX_GUARD_RESULT(s2n_alerts_write_warning(conn));
+ conn->reader_warning_out = 0;
+ POSIX_GUARD(s2n_flush(conn, blocked));
}
*blocked = S2N_NOT_BLOCKED;
-
return 0;
}
@@ -145,6 +114,10 @@ ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iov
/* Flush any pending I/O */
POSIX_GUARD(s2n_flush(conn, blocked));
+ if (conn->ktls_send_enabled) {
+ return s2n_ktls_sendv_with_offset(conn, bufs, count, offs, blocked);
+ }
+
/* Acknowledge consumed and flushed user data as sent */
user_data_sent = conn->current_user_data_consumed;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_hello.c b/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
index b95d0157f9..70f8bf14e6 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
@@ -193,6 +193,9 @@ static int s2n_server_hello_parse(struct s2n_connection *conn)
conn->actual_protocol_version = conn->server_protocol_version;
POSIX_GUARD(s2n_set_cipher_as_client(conn, cipher_suite_wire));
+
+ /* Erase TLS 1.2 client session ticket which might have been set for session resumption */
+ POSIX_GUARD(s2n_free(&conn->client_ticket));
} else {
conn->server_protocol_version = legacy_version;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c b/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c
index 2f8166def3..e922a1dffc 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c
@@ -111,6 +111,7 @@ int s2n_server_nst_send(struct s2n_connection *conn)
S2N_RESULT s2n_tls13_server_nst_send(struct s2n_connection *conn, s2n_blocked_status *blocked)
{
RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_GTE(conn->actual_protocol_version, S2N_TLS13);
/* Usually tickets are sent immediately after the handshake.
* If possible, reuse the handshake IO stuffer before it's wiped.
@@ -121,7 +122,7 @@ S2N_RESULT s2n_tls13_server_nst_send(struct s2n_connection *conn, s2n_blocked_st
*/
struct s2n_stuffer *nst_stuffer = &conn->handshake.io;
- if (conn->mode != S2N_SERVER || conn->actual_protocol_version < S2N_TLS13 || !conn->config->use_tickets) {
+ if (conn->mode != S2N_SERVER || !conn->config->use_tickets) {
return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_shutdown.c b/contrib/restricted/aws/s2n/tls/s2n_shutdown.c
index c02ead0b02..6086322a15 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_shutdown.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_shutdown.c
@@ -17,105 +17,100 @@
#include "tls/s2n_alerts.h"
#include "tls/s2n_connection.h"
#include "tls/s2n_tls.h"
+#include "utils/s2n_atomic.h"
#include "utils/s2n_safety.h"
-typedef enum {
- S2N_SHUTDOWN_RDWR,
- S2N_SHUTDOWN_WR,
-} s2n_shutdown_how;
-
-static bool s2n_error_alert_received(struct s2n_connection *conn)
+static bool s2n_shutdown_expect_close_notify(struct s2n_connection *conn)
{
- /* We don't check s2n_connection_get_alert() or s2n_stuffer_data_available()
- * because of https://github.com/aws/s2n-tls/issues/3933.
- * We need to check if the stuffer contains an alert, regardless of its
- * read state.
- */
- if (conn->alert_in.write_cursor == 0) {
+ /* No close_notify expected if we already received an error instead */
+ if (s2n_atomic_flag_test(&conn->error_alert_received)) {
return false;
}
- /* Verify that the stuffer doesn't just contain a close_notify alert */
- if (conn->close_notify_received) {
+
+ /* No close_notify expected if we sent an error instead of a close_notify */
+ if (conn->writer_alert_out || conn->reader_alert_out) {
return false;
}
- return true;
-}
-static bool s2n_error_alert_sent(struct s2n_connection *conn)
-{
- /* Sending an alert always sets conn->write_closing: see s2n_flush() */
- if (!conn->write_closing) {
+ /* The purpose of the peer responding to our close_notify
+ * with its own close_notify is to prevent application data truncation.
+ * However, application data is not a concern during the handshake.
+ *
+ * Additionally, decrypting alerts sent during the handshake can be error prone
+ * due to different encryption keys and may lead to unnecessary error reporting
+ * and unnecessary blinding.
+ */
+ if (!s2n_handshake_is_complete(conn)) {
return false;
}
- /* Verify that the alert sent wasn't just a close_notify */
- if (conn->close_notify_queued) {
+
+ /* QUIC does not use TLS alerts */
+ if (conn->quic_enabled) {
return false;
}
+
return true;
}
-int s2n_shutdown_impl(struct s2n_connection *conn, s2n_shutdown_how how,
- s2n_blocked_status *blocked)
+int s2n_shutdown_send(struct s2n_connection *conn, s2n_blocked_status *blocked)
{
POSIX_ENSURE_REF(conn);
POSIX_ENSURE_REF(blocked);
+ *blocked = S2N_NOT_BLOCKED;
- /* Treat this call as a no-op if already wiped */
+ /* Treat this call as a no-op if already wiped.
+ * This should probably be an error, but wasn't in the past so is left as-is
+ * for backwards compatibility.
+ */
if (conn->send == NULL && conn->recv == NULL) {
return S2N_SUCCESS;
}
- /* Treat this call as a no-op if an error alert was already received.
- * Error alerts close the connection without any exchange of close_notify alerts. */
- if (s2n_error_alert_received(conn)) {
+ /* Flush any outstanding data */
+ s2n_atomic_flag_set(&conn->write_closed);
+ POSIX_GUARD(s2n_flush(conn, blocked));
+
+ /* For a connection closed due to receiving an alert, we don't send anything. */
+ if (s2n_atomic_flag_test(&conn->error_alert_received)) {
+ return S2N_SUCCESS;
+ }
+
+ /* If we've already sent an alert, don't send another. */
+ if (conn->alert_sent) {
return S2N_SUCCESS;
}
/* Enforce blinding.
* If an application is using self-service blinding, ensure that they have
- * waited the required time before triggering the close_notify alert.
+ * waited the required time before triggering any alerts.
*/
uint64_t elapsed = 0;
POSIX_GUARD_RESULT(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed));
S2N_ERROR_IF(elapsed < conn->delay, S2N_ERR_SHUTDOWN_PAUSED);
- /* Flush any outstanding data or alerts */
- POSIX_GUARD(s2n_flush(conn, blocked));
-
- /* Error alerts close the connection without any exchange of close_notify alerts.
- * We need to check after flushing to account for any pending alerts.
- */
- if (s2n_error_alert_sent(conn)) {
- conn->read_closed = 1;
- return S2N_SUCCESS;
- }
-
/**
*= https://tools.ietf.org/rfc/rfc8446#section-6.1
*# Each party MUST send a "close_notify" alert before closing its write
*# side of the connection, unless it has already sent some error alert.
*/
- if (!conn->close_notify_queued) {
- POSIX_GUARD(s2n_queue_writer_close_alert_warning(conn));
- conn->close_notify_queued = 1;
- POSIX_GUARD(s2n_flush(conn, blocked));
- }
+ POSIX_GUARD_RESULT(s2n_alerts_write_error_or_close_notify(conn));
+ POSIX_GUARD(s2n_flush(conn, blocked));
+ return S2N_SUCCESS;
+}
- /* If we're only closing the write side, then we've succeeded. */
- if (how == S2N_SHUTDOWN_WR) {
- return S2N_SUCCESS;
- }
+int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(blocked);
+ *blocked = S2N_NOT_BLOCKED;
- /*
- * The purpose of the peer responding to our close_notify
- * with its own close_notify is to prevent application data truncation.
- * However, application data is not a concern during the handshake.
- *
- * Additionally, decrypting alerts sent during the handshake can be error prone
- * due to different encryption keys and may lead to unnecessary error reporting
- * and unnecessary blinding.
+ /* If necessary, send an alert to indicate shutdown. */
+ POSIX_GUARD(s2n_shutdown_send(conn, blocked));
+
+ /* If we don't expect a close_notify from our peer,
+ * just ensure that the connection is marked closed.
*/
- if (!s2n_handshake_is_complete(conn)) {
+ if (!s2n_shutdown_expect_close_notify(conn)) {
POSIX_GUARD_RESULT(s2n_connection_set_closed(conn));
*blocked = S2N_NOT_BLOCKED;
return S2N_SUCCESS;
@@ -125,7 +120,7 @@ int s2n_shutdown_impl(struct s2n_connection *conn, s2n_shutdown_how how,
uint8_t record_type = 0;
int isSSLv2 = false;
*blocked = S2N_BLOCKED_ON_READ;
- while (!conn->close_notify_received) {
+ while (!s2n_atomic_flag_test(&conn->close_notify_received)) {
POSIX_GUARD(s2n_read_full_record(conn, &record_type, &isSSLv2));
POSIX_ENSURE(!isSSLv2, S2N_ERR_BAD_MESSAGE);
if (record_type == TLS_ALERT) {
@@ -141,15 +136,3 @@ int s2n_shutdown_impl(struct s2n_connection *conn, s2n_shutdown_how how,
*blocked = S2N_NOT_BLOCKED;
return S2N_SUCCESS;
}
-
-int s2n_shutdown_send(struct s2n_connection *conn, s2n_blocked_status *blocked)
-{
- POSIX_GUARD(s2n_shutdown_impl(conn, S2N_SHUTDOWN_WR, blocked));
- return S2N_SUCCESS;
-}
-
-int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked)
-{
- POSIX_GUARD(s2n_shutdown_impl(conn, S2N_SHUTDOWN_RDWR, blocked));
- return S2N_SUCCESS;
-}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c
index 4dfaf37cd7..00c7dfcfd7 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c
@@ -165,19 +165,6 @@ int s2n_get_and_validate_negotiated_signature_scheme(struct s2n_connection *conn
}
}
- /* We require an exact match in TLS 1.3, but all previous versions can fall back to the default SignatureScheme.
- * This means that an s2n client will accept the default SignatureScheme from a TLS server, even if the client did
- * not send it in it's ClientHello. This pre-TLS1.3 behavior is an intentional choice to maximize support. */
- struct s2n_signature_scheme default_scheme = { 0 };
- POSIX_GUARD(s2n_choose_default_sig_scheme(conn, &default_scheme, S2N_PEER_MODE(conn->mode)));
-
- if ((conn->actual_protocol_version <= S2N_TLS12)
- && (s2n_signature_scheme_valid_to_accept(conn, &default_scheme) == S2N_SUCCESS)
- && (actual_iana_val == default_scheme.iana_value)) {
- *chosen_sig_scheme = default_scheme;
- return S2N_SUCCESS;
- }
-
POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_SCHEME);
}
@@ -198,15 +185,42 @@ int s2n_choose_default_sig_scheme(struct s2n_connection *conn, struct s2n_signat
/* Default our signature digest algorithms.
* For >=TLS 1.2 this default may be overridden by the signature_algorithms extension.
*/
+ const struct s2n_signature_scheme *default_sig_scheme = &s2n_rsa_pkcs1_md5_sha1;
if (auth_method == S2N_AUTHENTICATION_ECDSA) {
- *sig_scheme_out = s2n_ecdsa_sha1;
+ default_sig_scheme = &s2n_ecdsa_sha1;
} else if (conn->actual_protocol_version >= S2N_TLS12) {
- *sig_scheme_out = s2n_rsa_pkcs1_sha1;
+ default_sig_scheme = &s2n_rsa_pkcs1_sha1;
+ }
+
+ if (conn->actual_protocol_version < S2N_TLS12) {
+ /* Before TLS1.2, signature algorithms were fixed, not chosen / negotiated. */
+ *sig_scheme_out = *default_sig_scheme;
+ return S2N_SUCCESS;
} else {
- *sig_scheme_out = s2n_rsa_pkcs1_md5_sha1;
+ /* If we attempt to negotiate a default in TLS1.2, we should ensure that
+ * default is allowed by the local security policy.
+ */
+ const struct s2n_signature_preferences *signature_preferences = NULL;
+ POSIX_GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
+ POSIX_ENSURE_REF(signature_preferences);
+ for (size_t i = 0; i < signature_preferences->count; i++) {
+ if (signature_preferences->signature_schemes[i]->iana_value == default_sig_scheme->iana_value) {
+ *sig_scheme_out = *default_sig_scheme;
+ return S2N_SUCCESS;
+ }
+ }
+ /* We cannot bail with an error here because existing logic assumes
+ * that this method should always succeed and calls it even when no default
+ * is actually necessary.
+ * If no valid default exists, set an unusable, invalid empty scheme.
+ */
+ *sig_scheme_out = (struct s2n_signature_scheme){
+ .hash_alg = S2N_HASH_NONE,
+ .sig_alg = S2N_SIGNATURE_ANONYMOUS,
+ };
+ return S2N_SUCCESS;
}
- return S2N_SUCCESS;
}
int s2n_choose_sig_scheme_from_peer_preference_list(struct s2n_connection *conn, struct s2n_sig_scheme_list *peer_wire_prefs,
diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c
index bbea03abd9..3c2e17d48b 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c
@@ -148,6 +148,7 @@ const struct s2n_signature_scheme s2n_ecdsa_secp521r1_sha512 = {
.iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SECP521R1_SHA512,
.hash_alg = S2N_HASH_SHA512,
.sig_alg = S2N_SIGNATURE_ECDSA,
+ .libcrypto_nid = NID_ecdsa_with_SHA512,
.signature_curve = &s2n_ecc_curve_secp521r1, /* Hardcoded as of TLS 1.3 */
.minimum_protocol_version = S2N_TLS13,
};
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c
index 26c523be87..0589cb72c7 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c
@@ -158,6 +158,7 @@ int s2n_update_application_traffic_keys(struct s2n_connection *conn, s2n_mode mo
{
POSIX_ENSURE_REF(conn);
POSIX_ENSURE_REF(conn->secure);
+ POSIX_ENSURE_GTE(conn->actual_protocol_version, S2N_TLS13);
/* get tls13 key context */
s2n_tls13_connection_keys(keys, conn);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
index 3914a04461..12a3b79f9f 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
@@ -219,6 +219,20 @@ static S2N_RESULT s2n_tls13_compute_finished_key(struct s2n_connection *conn,
return S2N_RESULT_OK;
}
+static S2N_RESULT s2n_call_secret_callbacks(struct s2n_connection *conn,
+ const struct s2n_blob *secret, s2n_secret_type_t secret_type)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(secret);
+
+ if (conn->secret_cb && (s2n_connection_is_quic_enabled(conn) || s2n_in_unit_test())) {
+ RESULT_GUARD_POSIX(conn->secret_cb(conn->secret_cb_context, conn, secret_type,
+ secret->data, secret->size));
+ }
+ s2n_result_ignore(s2n_key_log_tls13_secret(conn, secret, secret_type));
+ return S2N_RESULT_OK;
+}
+
static S2N_RESULT s2n_trigger_secret_callbacks(struct s2n_connection *conn,
const struct s2n_blob *secret, s2n_extract_secret_type_t secret_type, s2n_mode mode)
{
@@ -232,11 +246,7 @@ static S2N_RESULT s2n_trigger_secret_callbacks(struct s2n_connection *conn,
};
s2n_secret_type_t callback_secret_type = conversions[secret_type][mode];
- if (conn->secret_cb && (s2n_connection_is_quic_enabled(conn) || s2n_in_unit_test())) {
- RESULT_GUARD_POSIX(conn->secret_cb(conn->secret_cb_context, conn, callback_secret_type,
- secret->data, secret->size));
- }
- s2n_result_ignore(s2n_key_log_tls13_secret(conn, secret, callback_secret_type));
+ RESULT_GUARD(s2n_call_secret_callbacks(conn, secret, callback_secret_type));
return S2N_RESULT_OK;
}
@@ -520,6 +530,31 @@ S2N_RESULT s2n_derive_resumption_master_secret(struct s2n_connection *conn)
return S2N_RESULT_OK;
}
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# |
+ *# +-----> Derive-Secret(., "exp master",
+ *# | ClientHello...server Finished)
+ *# | = exporter_master_secret
+ */
+S2N_RESULT s2n_derive_exporter_master_secret(struct s2n_connection *conn, struct s2n_blob *secret)
+{
+ RESULT_ENSURE_REF(conn);
+ /* Secret derivation requires these fields to be non-null. */
+ RESULT_ENSURE_REF(conn->secure);
+ RESULT_ENSURE_REF(conn->secure->cipher_suite);
+
+ RESULT_GUARD(s2n_derive_secret_with_context(conn,
+ S2N_MASTER_SECRET,
+ &s2n_tls13_label_exporter_master_secret,
+ SERVER_FINISHED,
+ secret));
+
+ RESULT_GUARD(s2n_call_secret_callbacks(conn, secret, S2N_EXPORTER_SECRET));
+
+ return S2N_RESULT_OK;
+}
+
static s2n_result (*extract_methods[])(struct s2n_connection *conn) = {
[S2N_EARLY_SECRET] = &s2n_extract_early_secret_for_schedule,
[S2N_HANDSHAKE_SECRET] = &s2n_extract_handshake_secret,
@@ -636,6 +671,8 @@ S2N_RESULT s2n_tls13_secrets_update(struct s2n_connection *conn)
S2N_CLIENT, &CONN_SECRET(conn, client_app_secret)));
RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_MASTER_SECRET,
S2N_SERVER, &CONN_SECRET(conn, server_app_secret)));
+ RESULT_GUARD(s2n_derive_exporter_master_secret(conn,
+ &CONN_SECRET(conn, exporter_master_secret)));
break;
case CLIENT_FINISHED:
RESULT_GUARD(s2n_calculate_transcript_digest(conn));
@@ -671,3 +708,66 @@ S2N_RESULT s2n_tls13_secrets_get(struct s2n_connection *conn, s2n_extract_secret
RESULT_ENSURE_GT(secret->size, 0);
return S2N_RESULT_OK;
}
+
+/*
+ *= https://www.rfc-editor.org/rfc/rfc8446#section-7.5
+ *# The exporter value is computed as:
+ *#
+ *# TLS-Exporter(label, context_value, key_length) =
+ *# HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
+ *# "exporter", Hash(context_value), key_length)
+ */
+int s2n_connection_tls_exporter(struct s2n_connection *conn,
+ const uint8_t *label_in, uint32_t label_length,
+ const uint8_t *context, uint32_t context_length,
+ uint8_t *output_in, uint32_t output_length)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(output_in);
+ POSIX_ENSURE_REF(label_in);
+ POSIX_ENSURE_REF(context);
+ POSIX_ENSURE(s2n_connection_get_protocol_version(conn) == S2N_TLS13, S2N_ERR_INVALID_STATE);
+
+ POSIX_ENSURE(is_handshake_complete(conn), S2N_ERR_HANDSHAKE_NOT_COMPLETE);
+ POSIX_ENSURE_REF(conn->secure);
+ POSIX_ENSURE_REF(conn->secure->cipher_suite);
+ s2n_hmac_algorithm hmac_alg = conn->secure->cipher_suite->prf_alg;
+
+ uint8_t label_bytes[S2N_MAX_HKDF_EXPAND_LABEL_LENGTH] = { 0 };
+ struct s2n_blob label = { 0 };
+ POSIX_ENSURE_LTE(label_length, sizeof(label_bytes));
+ POSIX_CHECKED_MEMCPY(label_bytes, label_in, label_length);
+ POSIX_GUARD(s2n_blob_init(&label, label_bytes, label_length));
+
+ uint8_t derived_secret_bytes[S2N_MAX_DIGEST_LEN] = { 0 };
+ struct s2n_blob derived_secret = { 0 };
+ POSIX_ENSURE_LTE(s2n_get_hash_len(CONN_HMAC_ALG(conn)), S2N_MAX_DIGEST_LEN);
+ POSIX_GUARD(s2n_blob_init(&derived_secret,
+ derived_secret_bytes, s2n_get_hash_len(CONN_HMAC_ALG(conn))));
+ POSIX_GUARD_RESULT(s2n_derive_secret(hmac_alg, &CONN_SECRET(conn, exporter_master_secret),
+ &label, &EMPTY_CONTEXT(hmac_alg), &derived_secret));
+
+ DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
+ POSIX_GUARD(s2n_hmac_new(&hmac_state));
+
+ DEFER_CLEANUP(struct s2n_hash_state hash = { 0 }, s2n_hash_free);
+ POSIX_GUARD(s2n_hash_new(&hash));
+
+ s2n_hash_algorithm hash_alg = { 0 };
+ POSIX_GUARD(s2n_hmac_hash_alg(hmac_alg, &hash_alg));
+ uint8_t digest_bytes[S2N_MAX_DIGEST_LEN] = { 0 };
+ struct s2n_blob digest = { 0 };
+ POSIX_ENSURE_LTE(s2n_get_hash_len(CONN_HMAC_ALG(conn)), S2N_MAX_DIGEST_LEN);
+ POSIX_GUARD(s2n_blob_init(&digest, digest_bytes, s2n_get_hash_len(CONN_HMAC_ALG(conn))));
+
+ POSIX_GUARD(s2n_hash_init(&hash, hash_alg));
+ POSIX_GUARD(s2n_hash_update(&hash, context, context_length));
+ POSIX_GUARD(s2n_hash_digest(&hash, digest.data, digest.size));
+
+ struct s2n_blob output = { 0 };
+ POSIX_GUARD(s2n_blob_init(&output, output_in, output_length));
+ POSIX_GUARD(s2n_hkdf_expand_label(&hmac_state, hmac_alg,
+ &derived_secret, &s2n_tls13_label_exporter, &digest, &output));
+
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.h b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.h
index b99f76df8f..5f6cd140be 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.h
@@ -40,6 +40,7 @@ struct s2n_tls13_secrets {
uint8_t client_app_secret[S2N_TLS13_SECRET_MAX_LEN];
uint8_t server_app_secret[S2N_TLS13_SECRET_MAX_LEN];
uint8_t resumption_master_secret[S2N_TLS13_SECRET_MAX_LEN];
+ uint8_t exporter_master_secret[S2N_TLS13_SECRET_MAX_LEN];
s2n_extract_secret_type_t extract_secret_type;
};
@@ -53,3 +54,4 @@ S2N_RESULT s2n_tls13_secrets_clean(struct s2n_connection *conn);
S2N_RESULT s2n_derive_binder_key(struct s2n_psk *psk, struct s2n_blob *output);
S2N_RESULT s2n_derive_resumption_master_secret(struct s2n_connection *conn);
+S2N_RESULT s2n_derive_exporter_master_secret(struct s2n_connection *conn, struct s2n_blob *output);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h b/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
index e0187fdf3b..cb565aa307 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
@@ -65,9 +65,15 @@
/* TLS 1.3 hybrid post-quantum definitions are from the proposed reserved range defined
* in https://tools.ietf.org/html/draft-stebila-tls-hybrid-design. Values for interoperability are defined in
- * https://github.com/open-quantum-safe/openssl/blob/OQS-OpenSSL_1_1_1-stable/oqs-template/oqs-kem-info.md */
-#define TLS_PQ_KEM_GROUP_ID_X25519_KYBER_512_R3 0x2F39
-#define TLS_PQ_KEM_GROUP_ID_SECP256R1_KYBER_512_R3 0x2F3A
+ * https://github.com/open-quantum-safe/oqs-provider/blob/main/oqs-template/oqs-kem-info.md and
+ * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
+ */
+#define TLS_PQ_KEM_GROUP_ID_X25519_KYBER_512_R3 0x2F39
+#define TLS_PQ_KEM_GROUP_ID_SECP256R1_KYBER_512_R3 0x2F3A
+#define TLS_PQ_KEM_GROUP_ID_SECP384R1_KYBER_768_R3 0x2F3C
+#define TLS_PQ_KEM_GROUP_ID_SECP521R1_KYBER_1024_R3 0x2F3D
+#define TLS_PQ_KEM_GROUP_ID_X25519_KYBER_768_R3 0x6399
+#define TLS_PQ_KEM_GROUP_ID_SECP256R1_KYBER_768_R3 0x639A
/* From https://tools.ietf.org/html/rfc7507 */
#define TLS_FALLBACK_SCSV 0x56, 0x00
diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
index 791ae3bd80..ec37e7c864 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
@@ -19,13 +19,13 @@
#include <openssl/x509.h>
#include <sys/socket.h>
+#include "crypto/s2n_libcrypto.h"
#include "crypto/s2n_openssl.h"
#include "crypto/s2n_openssl_x509.h"
#include "tls/extensions/s2n_extension_list.h"
#include "tls/s2n_config.h"
#include "tls/s2n_connection.h"
#include "tls/s2n_crl.h"
-#include "utils/s2n_asn1_time.h"
#include "utils/s2n_result.h"
#include "utils/s2n_rfc5952.h"
#include "utils/s2n_safety.h"
@@ -34,6 +34,7 @@
#include <openssl/ocsp.h>
DEFINE_POINTER_CLEANUP_FUNC(OCSP_RESPONSE *, OCSP_RESPONSE_free);
DEFINE_POINTER_CLEANUP_FUNC(OCSP_BASICRESP *, OCSP_BASICRESP_free);
+
#endif
#ifndef X509_V_FLAG_PARTIAL_CHAIN
@@ -42,7 +43,21 @@ DEFINE_POINTER_CLEANUP_FUNC(OCSP_BASICRESP *, OCSP_BASICRESP_free);
#define DEFAULT_MAX_CHAIN_DEPTH 7
/* Time used by default for nextUpdate if none provided in OCSP: 1 hour since thisUpdate. */
-#define DEFAULT_OCSP_NEXT_UPDATE_PERIOD 3600000000000
+#define DEFAULT_OCSP_NEXT_UPDATE_PERIOD 3600
+
+/* s2n's internal clock measures epoch-nanoseconds stored with a uint64_t. The
+ * maximum representable timestamp is Sunday, July 21, 2554. time_t measures
+ * epoch-seconds in a int64_t or int32_t (platform dependent). If time_t is an
+ * int32_t, the maximum representable timestamp is January 19, 2038.
+ *
+ * This means that converting from the internal clock to a time_t is not safe,
+ * because the internal clock might hold a value that is too large to represent
+ * in a time_t. This constant represents the largest internal clock value that
+ * can be safely represented as a time_t.
+ */
+#define MAX_32_TIMESTAMP_NANOS 2147483647 * ONE_SEC_IN_NANOS
+
+#define OSSL_VERIFY_CALLBACK_IGNORE_ERROR 1
DEFINE_POINTER_CLEANUP_FUNC(STACK_OF(X509_CRL) *, sk_X509_CRL_free);
DEFINE_POINTER_CLEANUP_FUNC(STACK_OF(GENERAL_NAME) *, GENERAL_NAMES_free);
@@ -413,7 +428,7 @@ static S2N_RESULT s2n_x509_validator_read_cert_chain(struct s2n_x509_validator *
/* the cert is der encoded, just convert it. */
server_cert = d2i_X509(NULL, &data, asn1_cert.size);
- RESULT_ENSURE_REF(server_cert);
+ RESULT_ENSURE(server_cert, S2N_ERR_CERT_INVALID);
/* add the cert to the chain. */
if (!sk_X509_push(validator->cert_chain_from_wire, server_cert)) {
@@ -474,6 +489,74 @@ static S2N_RESULT s2n_x509_validator_process_cert_chain(struct s2n_x509_validato
return S2N_RESULT_OK;
}
+static S2N_RESULT s2n_x509_validator_set_no_check_time_flag(struct s2n_x509_validator *validator)
+{
+ RESULT_ENSURE_REF(validator);
+ RESULT_ENSURE_REF(validator->store_ctx);
+
+ X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(validator->store_ctx);
+ RESULT_ENSURE_REF(param);
+
+#ifdef S2N_LIBCRYPTO_SUPPORTS_FLAG_NO_CHECK_TIME
+ RESULT_GUARD_OSSL(X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_NO_CHECK_TIME),
+ S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
+#else
+ RESULT_BAIL(S2N_ERR_UNIMPLEMENTED);
+#endif
+
+ return S2N_RESULT_OK;
+}
+
+int s2n_disable_time_validation_ossl_verify_callback(int default_ossl_ret, X509_STORE_CTX *ctx)
+{
+ int err = X509_STORE_CTX_get_error(ctx);
+ switch (err) {
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ return OSSL_VERIFY_CALLBACK_IGNORE_ERROR;
+ default:
+ break;
+ }
+
+ /* If CRL validation is enabled, setting the time validation verify callback will override the
+ * CRL verify callback. The CRL verify callback is manually triggered to work around this
+ * issue.
+ *
+ * The CRL verify callback ignores validation errors exclusively for CRL timestamp fields. So,
+ * if CRL validation isn't enabled, the CRL verify callback is a no-op.
+ */
+ return s2n_crl_ossl_verify_callback(default_ossl_ret, ctx);
+}
+
+static S2N_RESULT s2n_x509_validator_disable_time_validation(struct s2n_connection *conn,
+ struct s2n_x509_validator *validator)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->config);
+ RESULT_ENSURE_REF(validator);
+ RESULT_ENSURE_REF(validator->store_ctx);
+
+ /* Setting an X509_STORE verify callback is not recommended with AWS-LC:
+ * https://github.com/aws/aws-lc/blob/aa90e509f2e940916fbe9fdd469a4c90c51824f6/include/openssl/x509.h#L2980-L2990
+ *
+ * If the libcrypto supports the ability to disable time validation with an X509_VERIFY_PARAM
+ * NO_CHECK_TIME flag, this method is preferred.
+ *
+ * However, older versions of AWS-LC and OpenSSL 1.0.2 do not support this flag. In this case,
+ * an X509_STORE verify callback is used. This is acceptable in older versions of AWS-LC
+ * because the versions are fixed, and updates to AWS-LC will not break the callback
+ * implementation.
+ */
+ if (s2n_libcrypto_supports_flag_no_check_time()) {
+ RESULT_GUARD(s2n_x509_validator_set_no_check_time_flag(validator));
+ } else {
+ X509_STORE_CTX_set_verify_cb(validator->store_ctx,
+ s2n_disable_time_validation_ossl_verify_callback);
+ }
+
+ 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);
@@ -501,17 +584,31 @@ static S2N_RESULT s2n_x509_validator_verify_cert_chain(struct s2n_x509_validator
S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
}
- uint64_t current_sys_time = 0;
- RESULT_GUARD(s2n_config_wall_clock(conn->config, &current_sys_time));
+ /* Disabling time validation may set a NO_CHECK_TIME flag on the X509_STORE_CTX. Calling
+ * X509_STORE_CTX_set_time will override this flag. To prevent this, X509_STORE_CTX_set_time is
+ * only called if time validation is enabled.
+ */
+ if (conn->config->disable_x509_time_validation) {
+ RESULT_GUARD(s2n_x509_validator_disable_time_validation(conn, validator));
+ } else {
+ uint64_t current_sys_time = 0;
+ RESULT_GUARD(s2n_config_wall_clock(conn->config, &current_sys_time));
+ if (sizeof(time_t) == 4) {
+ /* cast value to uint64_t to prevent overflow errors */
+ RESULT_ENSURE_LTE(current_sys_time, (uint64_t) MAX_32_TIMESTAMP_NANOS);
+ }
- /* 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);
+ /* this wants seconds not nanoseconds */
+ time_t current_time = (time_t) (current_sys_time / ONE_SEC_IN_NANOS);
+ 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_NOT_YET_VALID:
+ RESULT_BAIL(S2N_ERR_CERT_NOT_YET_VALID);
case X509_V_ERR_CERT_HAS_EXPIRED:
RESULT_BAIL(S2N_ERR_CERT_EXPIRED);
case X509_V_ERR_CERT_REVOKED:
@@ -565,6 +662,9 @@ static S2N_RESULT s2n_x509_validator_read_leaf_info(struct s2n_connection *conn,
S2N_RESULT s2n_x509_validator_validate_cert_chain(struct s2n_x509_validator *validator, struct s2n_connection *conn,
uint8_t *cert_chain_in, uint32_t cert_chain_len, s2n_pkey_type *pkey_type, struct s2n_pkey *public_key_out)
{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->config);
+
switch (validator->state) {
case INIT:
break;
@@ -600,6 +700,14 @@ S2N_RESULT s2n_x509_validator_validate_cert_chain(struct s2n_x509_validator *val
RESULT_GUARD_POSIX(s2n_extension_list_process(S2N_EXTENSION_LIST_CERTIFICATE, conn, &first_certificate_extensions));
}
+ if (conn->config->cert_validation_cb) {
+ struct s2n_cert_validation_info info = { 0 };
+ RESULT_ENSURE(conn->config->cert_validation_cb(conn, &info, conn->config->cert_validation_ctx) >= S2N_SUCCESS,
+ S2N_ERR_CANCELLED);
+ RESULT_ENSURE(info.finished, S2N_ERR_INVALID_STATE);
+ RESULT_ENSURE(info.accepted, S2N_ERR_CERT_REJECTED);
+ }
+
*public_key_out = public_key;
/* Reset the old struct, so we don't clean up public_key_out */
@@ -674,29 +782,69 @@ S2N_RESULT s2n_x509_validator_validate_cert_stapled_ocsp_response(struct s2n_x50
OCSP_CERTID *cert_id = OCSP_cert_to_id(EVP_sha1(), subject, issuer);
RESULT_ENSURE_REF(cert_id);
+ /**
+ *= https://www.rfc-editor.org/rfc/rfc6960.html#section-2.4
+ *#
+ *# thisUpdate The most recent time at which the status being
+ *# indicated is known by the responder to have been
+ *# correct.
+ *#
+ *# nextUpdate The time at or before which newer information will be
+ *# available about the status of the certificate.
+ **/
ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd;
/* Actual verification of the response */
const int ocsp_resp_find_status_res = OCSP_resp_find_status(basic_response, cert_id, &status, &reason, &revtime, &thisupd, &nextupd);
OCSP_CERTID_free(cert_id);
RESULT_GUARD_OSSL(ocsp_resp_find_status_res, S2N_ERR_CERT_UNTRUSTED);
- uint64_t this_update = 0;
- RESULT_GUARD(s2n_asn1_time_to_nano_since_epoch_ticks((const char *) thisupd->data,
- (uint32_t) thisupd->length, &this_update));
+ uint64_t current_sys_time_nanoseconds = 0;
+ RESULT_GUARD(s2n_config_wall_clock(conn->config, &current_sys_time_nanoseconds));
+ if (sizeof(time_t) == 4) {
+ /* cast value to uint64_t to prevent overflow errors */
+ RESULT_ENSURE_LTE(current_sys_time_nanoseconds, (uint64_t) MAX_32_TIMESTAMP_NANOS);
+ }
+ /* convert the current_sys_time (which is in nanoseconds) to seconds */
+ time_t current_sys_time_seconds = (time_t) (current_sys_time_nanoseconds / ONE_SEC_IN_NANOS);
+
+ DEFER_CLEANUP(ASN1_GENERALIZEDTIME *current_sys_time = ASN1_GENERALIZEDTIME_set(NULL, current_sys_time_seconds), s2n_openssl_asn1_time_free_pointer);
+ RESULT_ENSURE_REF(current_sys_time);
- uint64_t next_update = 0;
+ /**
+ * It is fine to use ASN1_TIME functions with ASN1_GENERALIZEDTIME structures
+ * From openssl documentation:
+ * It is recommended that functions starting with ASN1_TIME be used instead
+ * of those starting with ASN1_UTCTIME or ASN1_GENERALIZEDTIME. The
+ * functions starting with ASN1_UTCTIME and ASN1_GENERALIZEDTIME act only on
+ * that specific time format. The functions starting with ASN1_TIME will
+ * operate on either format.
+ * https://www.openssl.org/docs/man1.1.1/man3/ASN1_TIME_to_generalizedtime.html
+ *
+ * ASN1_TIME_compare has a much nicer API, but is not available in Openssl
+ * 1.0.1, so we use ASN1_TIME_diff.
+ */
+ int pday = 0;
+ int psec = 0;
+ RESULT_GUARD_OSSL(ASN1_TIME_diff(&pday, &psec, thisupd, current_sys_time), S2N_ERR_CERT_UNTRUSTED);
+ /* ensure that current_time is after or the same as "this update" */
+ RESULT_ENSURE(pday >= 0 && psec >= 0, S2N_ERR_CERT_INVALID);
+
+ /* ensure that current_time is before or the same as "next update" */
if (nextupd) {
- RESULT_GUARD(s2n_asn1_time_to_nano_since_epoch_ticks((const char *) nextupd->data,
- (uint32_t) nextupd->length, &next_update));
+ RESULT_GUARD_OSSL(ASN1_TIME_diff(&pday, &psec, current_sys_time, nextupd), S2N_ERR_CERT_UNTRUSTED);
+ RESULT_ENSURE(pday >= 0 && psec >= 0, S2N_ERR_CERT_EXPIRED);
} else {
- next_update = this_update + DEFAULT_OCSP_NEXT_UPDATE_PERIOD;
+ /**
+ * if nextupd isn't present, assume that nextupd is
+ * DEFAULT_OCSP_NEXT_UPDATE_PERIOD after thisupd. This means that if the
+ * current time is more than DEFAULT_OCSP_NEXT_UPDATE_PERIOD
+ * seconds ahead of thisupd, we consider it invalid. We already compared
+ * current_sys_time to thisupd, so reuse those values
+ */
+ uint64_t seconds_after_thisupd = pday * (3600 * 24) + psec;
+ RESULT_ENSURE(seconds_after_thisupd < DEFAULT_OCSP_NEXT_UPDATE_PERIOD, S2N_ERR_CERT_EXPIRED);
}
- uint64_t current_time = 0;
- RESULT_GUARD(s2n_config_wall_clock(conn->config, &current_time));
- RESULT_ENSURE(current_time >= this_update, S2N_ERR_CERT_INVALID);
- RESULT_ENSURE(current_time <= next_update, S2N_ERR_CERT_EXPIRED);
-
switch (status) {
case V_OCSP_CERTSTATUS_GOOD:
validator->state = OCSP_VALIDATED;
@@ -795,3 +943,25 @@ bool s2n_x509_validator_is_cert_chain_validated(const struct s2n_x509_validator
{
return validator && (validator->state == VALIDATED || validator->state == OCSP_VALIDATED);
}
+
+int s2n_cert_validation_accept(struct s2n_cert_validation_info *info)
+{
+ POSIX_ENSURE_REF(info);
+ POSIX_ENSURE(!info->finished, S2N_ERR_INVALID_STATE);
+
+ info->finished = true;
+ info->accepted = true;
+
+ return S2N_SUCCESS;
+}
+
+int s2n_cert_validation_reject(struct s2n_cert_validation_info *info)
+{
+ POSIX_ENSURE_REF(info);
+ POSIX_ENSURE(!info->finished, S2N_ERR_INVALID_STATE);
+
+ info->finished = true;
+ info->accepted = false;
+
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
index 5f5e113421..8ca2d624d4 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
@@ -66,6 +66,11 @@ struct s2n_x509_validator {
struct s2n_array *crl_lookup_list;
};
+struct s2n_cert_validation_info {
+ unsigned finished : 1;
+ unsigned accepted : 1;
+};
+
/** Some libcrypto implementations do not support OCSP validation. Returns 1 if supported, 0 otherwise. */
uint8_t s2n_x509_ocsp_stapling_supported(void);
diff --git a/contrib/restricted/aws/s2n/utils/s2n_asn1_time.c b/contrib/restricted/aws/s2n/utils/s2n_asn1_time.c
deleted file mode 100644
index c958c977cf..0000000000
--- a/contrib/restricted/aws/s2n/utils/s2n_asn1_time.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * 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 "utils/s2n_asn1_time.h"
-
-#include <ctype.h>
-#include <time.h>
-
-#include "utils/s2n_result.h"
-#include "utils/s2n_safety.h"
-
-typedef enum parser_state {
- ON_YEAR_DIGIT_1 = 0,
- ON_YEAR_DIGIT_2,
- ON_YEAR_DIGIT_3,
- ON_YEAR_DIGIT_4,
- ON_MONTH_DIGIT_1,
- ON_MONTH_DIGIT_2,
- ON_DAY_DIGIT_1,
- ON_DAY_DIGIT_2,
- ON_HOUR_DIGIT_1,
- ON_HOUR_DIGIT_2,
- ON_MINUTE_DIGIT_1,
- ON_MINUTE_DIGIT_2,
- ON_SECOND_DIGIT_1,
- ON_SECOND_DIGIT_2,
- ON_SUBSECOND,
- ON_TIMEZONE,
- ON_OFFSET_HOURS_DIGIT_1,
- ON_OFFSET_HOURS_DIGIT_2,
- ON_OFFSET_MINUTES_DIGIT_1,
- ON_OFFSET_MINUTES_DIGIT_2,
- FINISHED,
- PARSE_ERROR
-} parser_state;
-
-static inline long get_gmt_offset(struct tm *t)
-{
-/* See: https://sourceware.org/git/?p=glibc.git;a=blob;f=include/features.h;h=ba272078cf2263ec88e039fda7524c136a4a7953;hb=HEAD */
-#if defined(__USE_MISC) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
- || defined(__ANDROID__) || defined(ANDROID) || defined(__APPLE__) && defined(__MACH__)
- return t->tm_gmtoff;
-#else
- return t->tm_gmtoff;
-#endif
-}
-
-static inline void get_current_timesettings(long *gmt_offset, int *is_dst)
-{
- struct tm time_ptr = { 0 };
- time_t raw_time;
- time(&raw_time);
- localtime_r(&raw_time, &time_ptr);
- *gmt_offset = get_gmt_offset(&time_ptr);
- *is_dst = time_ptr.tm_isdst;
-}
-
-#define PARSE_DIGIT(c, d) \
- do { \
- RESULT_ENSURE(isdigit(c), S2N_ERR_SAFETY); \
- d = c - '0'; \
- } while (0)
-
-/* this is just a standard state machine for ASN1 date format... nothing special.
- * just do a character at a time and change the state per character encountered.
- * when finished the above time structure should be filled in along with some
- * crazy timezone info we'll need shortly afterwards.*/
-static S2N_RESULT process_state(parser_state *state, char current_char, struct parser_args *args)
-{
- switch (*state) {
- case ON_YEAR_DIGIT_1:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_year = args->current_digit;
- *state = ON_YEAR_DIGIT_2;
- return S2N_RESULT_OK;
- case ON_YEAR_DIGIT_2:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_year = args->time.tm_year * 10 + args->current_digit;
- *state = ON_YEAR_DIGIT_3;
- return S2N_RESULT_OK;
- case ON_YEAR_DIGIT_3:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_year = args->time.tm_year * 10 + args->current_digit;
- *state = ON_YEAR_DIGIT_4;
- return S2N_RESULT_OK;
- case ON_YEAR_DIGIT_4:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_year = args->time.tm_year * 10 + args->current_digit;
- args->time.tm_year -= 1900;
- if (args->time.tm_year < 0) {
- return S2N_RESULT_ERROR;
- }
-
- *state = ON_MONTH_DIGIT_1;
- return S2N_RESULT_OK;
- case ON_MONTH_DIGIT_1:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_mon = args->current_digit;
- *state = ON_MONTH_DIGIT_2;
- return S2N_RESULT_OK;
- case ON_MONTH_DIGIT_2:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_mon = args->time.tm_mon * 10 + args->current_digit;
- args->time.tm_mon -= 1;
-
- if (args->time.tm_mon < 0 || args->time.tm_mon > 11) {
- return S2N_RESULT_ERROR;
- }
-
- *state = ON_DAY_DIGIT_1;
- return S2N_RESULT_OK;
- case ON_DAY_DIGIT_1:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_mday = args->current_digit;
- *state = ON_DAY_DIGIT_2;
- return S2N_RESULT_OK;
- case ON_DAY_DIGIT_2:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_mday = args->time.tm_mday * 10 + args->current_digit;
-
- if (args->time.tm_mday < 0 || args->time.tm_mday > 31) {
- return S2N_RESULT_ERROR;
- }
-
- *state = ON_HOUR_DIGIT_1;
- return S2N_RESULT_OK;
- case ON_HOUR_DIGIT_1:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_hour = args->current_digit;
- *state = ON_HOUR_DIGIT_2;
- return S2N_RESULT_OK;
- case ON_HOUR_DIGIT_2:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_hour = args->time.tm_hour * 10 + args->current_digit;
-
- if (args->time.tm_hour < 0 || args->time.tm_hour > 23) {
- return S2N_RESULT_ERROR;
- }
-
- *state = ON_MINUTE_DIGIT_1;
- return S2N_RESULT_OK;
- case ON_MINUTE_DIGIT_1:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_min = args->current_digit;
- *state = ON_MINUTE_DIGIT_2;
- return S2N_RESULT_OK;
- case ON_MINUTE_DIGIT_2:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_min = args->time.tm_min * 10 + args->current_digit;
-
- if (args->time.tm_min < 0 || args->time.tm_min > 59) {
- return S2N_RESULT_ERROR;
- }
-
- *state = ON_SECOND_DIGIT_1;
- return S2N_RESULT_OK;
- case ON_SECOND_DIGIT_1:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_sec = args->current_digit;
- *state = ON_SECOND_DIGIT_2;
- return S2N_RESULT_OK;
- case ON_SECOND_DIGIT_2:
- PARSE_DIGIT(current_char, args->current_digit);
- args->time.tm_sec = args->time.tm_sec * 10 + args->current_digit;
-
- if (args->time.tm_sec < 0 || args->time.tm_sec > 59) {
- return S2N_RESULT_ERROR;
- }
-
- *state = ON_SUBSECOND;
- return S2N_RESULT_OK;
- case ON_SUBSECOND:
- if (current_char == '.' || isdigit(current_char)) {
- *state = ON_SUBSECOND;
- return S2N_RESULT_OK;
- }
- FALL_THROUGH;
- case ON_TIMEZONE:
- if (current_char == 'Z' || current_char == 'z') {
- args->local_time_assumed = 0;
- *state = FINISHED;
- return S2N_RESULT_OK;
- } else if (current_char == '-') {
- args->local_time_assumed = 0;
- args->offset_negative = 1;
- *state = ON_OFFSET_HOURS_DIGIT_1;
- return S2N_RESULT_OK;
- } else if (current_char == '+') {
- args->local_time_assumed = 0;
- args->offset_negative = 0;
- *state = ON_OFFSET_HOURS_DIGIT_1;
- return S2N_RESULT_OK;
- }
-
- return S2N_RESULT_ERROR;
- case ON_OFFSET_HOURS_DIGIT_1:
- PARSE_DIGIT(current_char, args->current_digit);
- args->offset_hours = args->current_digit;
- *state = ON_OFFSET_HOURS_DIGIT_2;
- return S2N_RESULT_OK;
- case ON_OFFSET_HOURS_DIGIT_2:
- PARSE_DIGIT(current_char, args->current_digit);
- args->offset_hours = args->offset_hours * 10 + args->current_digit;
-
- if (args->offset_hours < 0 || args->offset_hours > 23) {
- return S2N_RESULT_ERROR;
- }
-
- *state = ON_OFFSET_MINUTES_DIGIT_1;
- return S2N_RESULT_OK;
- case ON_OFFSET_MINUTES_DIGIT_1:
- PARSE_DIGIT(current_char, args->current_digit);
- args->offset_minutes = args->current_digit;
- *state = ON_OFFSET_MINUTES_DIGIT_2;
- return S2N_RESULT_OK;
- case ON_OFFSET_MINUTES_DIGIT_2:
- PARSE_DIGIT(current_char, args->current_digit);
- args->offset_minutes = args->offset_minutes * 10 + args->current_digit;
-
- if (args->offset_minutes < 0 || args->offset_minutes > 23) {
- return S2N_RESULT_ERROR;
- }
-
- *state = FINISHED;
- return S2N_RESULT_OK;
- default:
- return S2N_RESULT_ERROR;
- }
-}
-
-S2N_RESULT s2n_asn1_time_to_nano_since_epoch_ticks(const char *asn1_time, uint32_t len, uint64_t *ticks)
-{
- /* figure out if we are on something other than UTC since timegm is not supported everywhere. */
- long gmt_offset_current = 0;
- int is_dst = 0;
- get_current_timesettings(&gmt_offset_current, &is_dst);
-
- uint32_t str_len = len;
- parser_state state = ON_YEAR_DIGIT_1;
-
- struct parser_args args = {
- .time = {
- .tm_hour = 0,
- .tm_isdst = -1,
- .tm_mday = 0,
- .tm_min = 0,
- .tm_mon = 0,
- .tm_sec = 0,
- .tm_wday = 0,
- .tm_yday = 0,
- .tm_year = 0,
- },
- .current_digit = 0,
- .local_time_assumed = 1,
- .offset_hours = 0,
- .offset_minutes = 0,
- .offset_negative = 0
- };
-
- size_t current_pos = 0;
-
- while (state < FINISHED && current_pos < str_len) {
- char current_char = asn1_time[current_pos];
- RESULT_ENSURE_OK(process_state(&state, current_char, &args), S2N_ERR_INVALID_ARGUMENT);
- current_pos++;
- }
-
- /* state on subsecond means no timezone info was found and we assume local time */
- RESULT_ENSURE(state == FINISHED || state == ON_SUBSECOND, S2N_ERR_INVALID_ARGUMENT);
-
- time_t clock_data = mktime(&args.time);
- RESULT_ENSURE_GTE(clock_data, 0);
-
- /* ASN1 + and - is in format HHMM. We need to convert it to seconds for the adjustment */
- long gmt_offset = (args.offset_hours * 3600) + (args.offset_minutes * 60);
-
- if (args.offset_negative) {
- gmt_offset = 0 - gmt_offset;
- }
-
- /* if we detected UTC is being used (please always use UTC), we need to add the detected timezone on the local
- * machine back to the offset. Also, the offset includes an offset for daylight savings time. When the time being parsed
- * and the local time are on different sides of the dst barrier, the offset has to be adjusted to account for it. */
- if (!args.local_time_assumed) {
- gmt_offset -= gmt_offset_current;
- gmt_offset -= args.time.tm_isdst != is_dst ? (args.time.tm_isdst - is_dst) * 3600 : 0;
- }
-
- RESULT_ENSURE_GTE(clock_data, gmt_offset);
-
- /* convert to nanoseconds and add the timezone offset. */
- *ticks = ((uint64_t) clock_data - gmt_offset) * 1000000000;
- return S2N_RESULT_OK;
-}
diff --git a/contrib/restricted/aws/s2n/utils/s2n_atomic.c b/contrib/restricted/aws/s2n/utils/s2n_atomic.c
new file mode 100644
index 0000000000..cd2597cd0f
--- /dev/null
+++ b/contrib/restricted/aws/s2n/utils/s2n_atomic.c
@@ -0,0 +1,60 @@
+/*
+ * 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 "utils/s2n_atomic.h"
+
+#include <signal.h>
+
+#include "utils/s2n_safety.h"
+
+static sig_atomic_t set_val = true;
+static sig_atomic_t clear_val = false;
+
+S2N_RESULT s2n_atomic_init()
+{
+#if S2N_ATOMIC_SUPPORTED && S2N_THREAD_SANITIZER
+ RESULT_ENSURE(__atomic_always_lock_free(sizeof(s2n_atomic_flag), NULL), S2N_ERR_ATOMIC);
+#endif
+ return S2N_RESULT_OK;
+}
+
+void s2n_atomic_flag_set(s2n_atomic_flag *var)
+{
+#if S2N_ATOMIC_SUPPORTED && S2N_THREAD_SANITIZER
+ __atomic_store(&var->val, &set_val, __ATOMIC_RELAXED);
+#else
+ var->val = set_val;
+#endif
+}
+
+void s2n_atomic_flag_clear(s2n_atomic_flag *var)
+{
+#if S2N_ATOMIC_SUPPORTED && S2N_THREAD_SANITIZER
+ __atomic_store(&var->val, &clear_val, __ATOMIC_RELAXED);
+#else
+ var->val = clear_val;
+#endif
+}
+
+bool s2n_atomic_flag_test(s2n_atomic_flag *var)
+{
+#if S2N_ATOMIC_SUPPORTED && S2N_THREAD_SANITIZER
+ sig_atomic_t result = 0;
+ __atomic_load(&var->val, &result, __ATOMIC_RELAXED);
+ return result;
+#else
+ return var->val;
+#endif
+}
diff --git a/contrib/restricted/aws/s2n/utils/s2n_atomic.h b/contrib/restricted/aws/s2n/utils/s2n_atomic.h
new file mode 100644
index 0000000000..014dc43dd3
--- /dev/null
+++ b/contrib/restricted/aws/s2n/utils/s2n_atomic.h
@@ -0,0 +1,42 @@
+/*
+ * 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 <signal.h>
+
+#include "utils/s2n_result.h"
+
+/* s2n-tls allows s2n_send and s2n_recv to be called concurrently.
+ * There are a handful of values that both methods need to access.
+ * However, C99 has no concept of concurrency, so provides no atomic data types.
+ */
+
+/* Wrap the underlying value in a struct to encourage developers to only use
+ * the provided atomic methods.
+ */
+typedef struct {
+ /* Traditionally, s2n-tls uses sig_atomic_t for its weak guarantee of
+ * atomicity for interrupts.
+ */
+ sig_atomic_t val;
+} s2n_atomic_flag;
+
+/* These methods use compiler atomic built-ins if available and lock-free, but otherwise
+ * rely on setting / clearing a small value generally being atomic in practice.
+ */
+S2N_RESULT s2n_atomic_init();
+void s2n_atomic_flag_set(s2n_atomic_flag *var);
+void s2n_atomic_flag_clear(s2n_atomic_flag *var);
+bool s2n_atomic_flag_test(s2n_atomic_flag *var);
diff --git a/contrib/restricted/aws/s2n/utils/s2n_ensure.c b/contrib/restricted/aws/s2n/utils/s2n_ensure.c
index ccaf013309..5824f9b618 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_ensure.c
+++ b/contrib/restricted/aws/s2n/utils/s2n_ensure.c
@@ -15,14 +15,13 @@
#include "utils/s2n_safety.h"
-void *s2n_ensure_memcpy_trace(void *restrict to, const void *restrict from, size_t size, const char *debug_str)
+void *s2n_ensure_memcpy_trace(void *restrict to, const void *restrict from, size_t size)
{
- if (to == NULL || from == NULL) {
- s2n_errno = S2N_ERR_NULL;
- s2n_debug_str = debug_str;
- return NULL;
- }
+ PTR_ENSURE_REF(to);
+ PTR_ENSURE_REF(from);
/* use memmove instead of memcpy since it'll handle overlapping regions and not result in UB */
- return memmove(to, from, size);
+ void *result = memmove(to, from, size);
+ PTR_ENSURE_REF(result);
+ return result;
}
diff --git a/contrib/restricted/aws/s2n/utils/s2n_ensure.h b/contrib/restricted/aws/s2n/utils/s2n_ensure.h
index 54b208a35b..c072d93e95 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_ensure.h
+++ b/contrib/restricted/aws/s2n/utils/s2n_ensure.h
@@ -60,13 +60,13 @@
#define __S2N_ENSURE_POSTCONDITION(result) (s2n_likely(s2n_result_is_ok(result)) ? S2N_RESULT_OK : S2N_RESULT_ERROR)
#endif
-#define __S2N_ENSURE_SAFE_MEMCPY(d, s, n, guard) \
- do { \
- __typeof(n) __tmp_n = (n); \
- if (s2n_likely(__tmp_n)) { \
- void *r = s2n_ensure_memcpy_trace((d), (s), (__tmp_n), _S2N_DEBUG_LINE); \
- guard(r); \
- } \
+#define __S2N_ENSURE_SAFE_MEMCPY(d, s, n, guard) \
+ do { \
+ __typeof(n) __tmp_n = (n); \
+ if (s2n_likely(__tmp_n)) { \
+ void *r = s2n_ensure_memcpy_trace((d), (s), (__tmp_n)); \
+ guard(r); \
+ } \
} while (0)
#define __S2N_ENSURE_SAFE_MEMSET(d, c, n, guard) \
@@ -79,6 +79,17 @@
} \
} while (0)
+#if defined(S2N_DIAGNOSTICS_PUSH_SUPPORTED) && defined(S2N_DIAGNOSTICS_POP_SUPPORTED)
+ #define __S2N_ENSURE_CHECKED_RETURN(v) \
+ do { \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic error \"-Wconversion\"") return v; \
+ _Pragma("GCC diagnostic pop") \
+ } while (0)
+#else
+ #define __S2N_ENSURE_CHECKED_RETURN(v) return v
+#endif
+
/**
* `restrict` is a part of the c99 standard and will work with any C compiler. If you're trying to
* compile with a C++ compiler `restrict` is invalid. However some C++ compilers support the behavior
@@ -92,9 +103,9 @@
*
*/
#if defined(S2N___RESTRICT__SUPPORTED)
-void *s2n_ensure_memcpy_trace(void *__restrict__ to, const void *__restrict__ from, size_t size, const char *debug_str);
+void *s2n_ensure_memcpy_trace(void *__restrict__ to, const void *__restrict__ from, size_t size);
#else
-void *s2n_ensure_memcpy_trace(void *restrict to, const void *restrict from, size_t size, const char *debug_str);
+void *s2n_ensure_memcpy_trace(void *restrict to, const void *restrict from, size_t size);
#endif
/**
@@ -141,7 +152,7 @@ void *s2n_ensure_memcpy_trace(void *restrict to, const void *restrict from, size
*/
#ifdef CBMC
#define CONTRACT_ASSIGNS(...) __CPROVER_assigns(__VA_ARGS__)
- #define CONTRACT_ASSIGNS_ERR(...) CONTRACT_ASSIGNS(__VA_ARGS__, s2n_debug_str, s2n_errno)
+ #define CONTRACT_ASSIGNS_ERR(...) CONTRACT_ASSIGNS(__VA_ARGS__, _s2n_debug_info, s2n_errno)
#define CONTRACT_REQUIRES(...) __CPROVER_requires(__VA_ARGS__)
#define CONTRACT_ENSURES(...) __CPROVER_ensures(__VA_ARGS__)
#define CONTRACT_INVARIANT(...) __CPROVER_loop_invariant(__VA_ARGS__)
diff --git a/contrib/restricted/aws/s2n/utils/s2n_init.c b/contrib/restricted/aws/s2n/utils/s2n_init.c
index 420ebf0e88..0347ae12ec 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_init.c
+++ b/contrib/restricted/aws/s2n/utils/s2n_init.c
@@ -57,6 +57,11 @@ int s2n_init(void)
POSIX_ENSURE(!initialized, S2N_ERR_INITIALIZED);
main_thread = pthread_self();
+
+ if (getenv("S2N_INTEG_TEST")) {
+ POSIX_GUARD(s2n_in_integ_test_set(true));
+ }
+
/* Should run before any init method that calls libcrypto methods
* to ensure we don't try to call methods that don't exist.
* It doesn't require any locks since it only deals with values that
@@ -74,6 +79,7 @@ int s2n_init(void)
POSIX_GUARD(s2n_extension_type_init());
POSIX_GUARD_RESULT(s2n_pq_init());
POSIX_GUARD_RESULT(s2n_tls13_empty_transcripts_init());
+ POSIX_GUARD_RESULT(s2n_atomic_init());
if (atexit_cleanup) {
POSIX_ENSURE_OK(atexit(s2n_cleanup_atexit), S2N_ERR_ATEXIT);
@@ -127,3 +133,8 @@ static void s2n_cleanup_atexit(void)
{
(void) s2n_cleanup_atexit_impl();
}
+
+bool s2n_is_initialized(void)
+{
+ return initialized;
+}
diff --git a/contrib/restricted/aws/s2n/utils/s2n_init.h b/contrib/restricted/aws/s2n/utils/s2n_init.h
new file mode 100644
index 0000000000..a8a91161b5
--- /dev/null
+++ b/contrib/restricted/aws/s2n/utils/s2n_init.h
@@ -0,0 +1,20 @@
+/*
+ * 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
+
+int s2n_init(void);
+int s2n_cleanup(void);
+bool s2n_is_initialized(void);
diff --git a/contrib/restricted/aws/s2n/utils/s2n_io.c b/contrib/restricted/aws/s2n/utils/s2n_io.c
new file mode 100644
index 0000000000..9fd85883d3
--- /dev/null
+++ b/contrib/restricted/aws/s2n/utils/s2n_io.c
@@ -0,0 +1,40 @@
+/*
+ * 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 "utils/s2n_io.h"
+
+#include <errno.h>
+
+#include "utils/s2n_safety.h"
+
+S2N_RESULT s2n_io_check_write_result(ssize_t result)
+{
+ if (result < 0) {
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ RESULT_BAIL(S2N_ERR_IO_BLOCKED);
+ }
+ RESULT_BAIL(S2N_ERR_IO);
+ }
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_io_check_read_result(ssize_t result)
+{
+ RESULT_GUARD(s2n_io_check_write_result(result));
+ if (result == 0) {
+ RESULT_BAIL(S2N_ERR_CLOSED);
+ }
+ return S2N_RESULT_OK;
+}
diff --git a/contrib/restricted/aws/s2n/utils/s2n_asn1_time.h b/contrib/restricted/aws/s2n/utils/s2n_io.h
index 1a30e1c4d6..332c35d5b7 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_asn1_time.h
+++ b/contrib/restricted/aws/s2n/utils/s2n_io.h
@@ -12,25 +12,18 @@
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
-
#pragma once
-#include <stdint.h>
-#include <time.h>
-
#include "utils/s2n_result.h"
-struct parser_args {
- uint8_t offset_negative;
- uint8_t local_time_assumed;
- uint8_t current_digit;
- long offset_hours;
- long offset_minutes;
- struct tm time;
-};
-
-/**
- * Converts an asn1 formatted time string to ticks since epoch in nanoseconds.
- * ticks is an output parameter. Returns 0 on success and -1 on failure.
+/* While we shouldn't need to reset errno before executing `action`,
+ * we do so just in case action doesn't set errno properly on failure.
*/
-S2N_RESULT s2n_asn1_time_to_nano_since_epoch_ticks(const char *asn1_time, uint32_t len, uint64_t *ticks);
+#define S2N_IO_RETRY_EINTR(result, action) \
+ do { \
+ errno = 0; \
+ result = action; \
+ } while (result < 0 && errno == EINTR)
+
+S2N_RESULT s2n_io_check_write_result(ssize_t result);
+S2N_RESULT s2n_io_check_read_result(ssize_t result);
diff --git a/contrib/restricted/aws/s2n/utils/s2n_mem.c b/contrib/restricted/aws/s2n/utils/s2n_mem.c
index 1650a4b2b6..c5fa06c3a0 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_mem.c
+++ b/contrib/restricted/aws/s2n/utils/s2n_mem.c
@@ -18,9 +18,11 @@
#include <features.h>
#endif
+#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/mman.h>
+#include <sys/param.h>
#include <unistd.h>
#include "error/s2n_errno.h"
@@ -51,8 +53,8 @@ static int s2n_mem_init_impl(void)
POSIX_ENSURE_GT(sysconf_rc, 0);
/* page_size must be a valid uint32 */
- POSIX_ENSURE_LTE(sysconf_rc, UINT32_MAX);
-
+ long max_page_size = MIN(UINT32_MAX, LONG_MAX);
+ POSIX_ENSURE_LTE(sysconf_rc, max_page_size);
page_size = (uint32_t) sysconf_rc;
if (getenv("S2N_DONT_MLOCK") || s2n_in_unit_test()) {
@@ -230,6 +232,8 @@ int s2n_free_object(uint8_t **p_data, uint32_t size)
int s2n_dup(struct s2n_blob *from, struct s2n_blob *to)
{
POSIX_ENSURE(initialized, S2N_ERR_NOT_INITIALIZED);
+ POSIX_ENSURE_REF(to);
+ POSIX_ENSURE_REF(from);
POSIX_ENSURE_EQ(to->size, 0);
POSIX_ENSURE_EQ(to->data, NULL);
POSIX_ENSURE_NE(from->size, 0);
diff --git a/contrib/restricted/aws/s2n/utils/s2n_mem.h b/contrib/restricted/aws/s2n/utils/s2n_mem.h
index adccd6b4bf..a66b90ed5b 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_mem.h
+++ b/contrib/restricted/aws/s2n/utils/s2n_mem.h
@@ -23,6 +23,11 @@ int s2n_mem_init(void);
bool s2n_mem_is_init(void);
uint32_t s2n_mem_get_page_size(void);
int s2n_mem_cleanup(void);
+
+/*
+ * Generally, s2n_realloc is preferred over s2n_alloc. This is because calling
+ * s2n_alloc on a blob that already has memory allocated will leak memory.
+*/
int s2n_alloc(struct s2n_blob *b, uint32_t size);
int s2n_realloc(struct s2n_blob *b, uint32_t size);
int s2n_free(struct s2n_blob *b);
diff --git a/contrib/restricted/aws/s2n/utils/s2n_random.c b/contrib/restricted/aws/s2n/utils/s2n_random.c
index 70b02eff7f..3b0552cde1 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_random.c
+++ b/contrib/restricted/aws/s2n/utils/s2n_random.c
@@ -13,8 +13,39 @@
* permissions and limitations under the License.
*/
+/*
+ * _XOPEN_SOURCE is needed for resolving the constant O_CLOEXEC in some
+ * environments. We use _XOPEN_SOURCE instead of _GNU_SOURCE because
+ * _GNU_SOURCE is not portable and breaks when attempting to build rust
+ * bindings on MacOS.
+ *
+ * https://man7.org/linux/man-pages/man2/open.2.html
+ * The O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW flags are not
+ * specified in POSIX.1-2001, but are specified in POSIX.1-2008.
+ * Since glibc 2.12, one can obtain their definitions by defining
+ * either _POSIX_C_SOURCE with a value greater than or equal to
+ * 200809L or _XOPEN_SOURCE with a value greater than or equal to
+ * 700. In glibc 2.11 and earlier, one obtains the definitions by
+ * defining _GNU_SOURCE.
+ *
+ * We use two feature probes to detect the need to perform this workaround.
+ * It is only applied if we can't get CLOEXEC without it and the build doesn't
+ * fail with _XOPEN_SOURCE being defined.
+ *
+ * # Relevent Links
+ *
+ * - POSIX.1-2017: https://pubs.opengroup.org/onlinepubs/9699919799
+ * - https://stackoverflow.com/a/5724485
+ * - https://stackoverflow.com/a/5583764
+ */
+#if !defined(S2N_CLOEXEC_SUPPORTED) && defined(S2N_CLOEXEC_XOPEN_SUPPORTED) && !defined(_XOPEN_SOURCE)
+ #define _XOPEN_SOURCE 700
+ #include <fcntl.h>
+ #undef _XOPEN_SOURCE
+#else
+ #include <fcntl.h>
+#endif
#include <errno.h>
-#include <fcntl.h>
#include <limits.h>
#include <openssl/engine.h>
#include <openssl/rand.h>
@@ -34,9 +65,11 @@
#include "api/s2n.h"
#include "crypto/s2n_drbg.h"
+#include "crypto/s2n_fips.h"
#include "error/s2n_errno.h"
#include "stuffer/s2n_stuffer.h"
#include "utils/s2n_fork_detection.h"
+#include "utils/s2n_init.h"
#include "utils/s2n_mem.h"
#include "utils/s2n_random.h"
#include "utils/s2n_result.h"
@@ -44,6 +77,12 @@
#define ENTROPY_SOURCE "/dev/urandom"
+#if defined(O_CLOEXEC)
+ #define ENTROPY_FLAGS O_RDONLY | O_CLOEXEC
+#else
+ #define ENTROPY_FLAGS O_RDONLY
+#endif
+
/* See https://en.wikipedia.org/wiki/CPUID */
#define RDRAND_ECX_FLAG 0x40000000
@@ -66,6 +105,8 @@ struct s2n_rand_state {
static pthread_key_t s2n_per_thread_rand_state_key;
/* Needed to ensure key is initialized only once */
static pthread_once_t s2n_per_thread_rand_state_key_once = PTHREAD_ONCE_INIT;
+/* Tracks if call to pthread_key_create failed */
+static int pthread_key_create_result;
static __thread struct s2n_rand_state s2n_per_thread_rand_state = {
.cached_fork_generation_number = 0,
@@ -135,6 +176,14 @@ S2N_RESULT s2n_get_mix_entropy(struct s2n_blob *blob)
return S2N_RESULT_OK;
}
+/* Deletes pthread key at process-exit */
+static void __attribute__((destructor)) s2n_drbg_rand_state_key_cleanup(void)
+{
+ if (s2n_is_initialized()) {
+ pthread_key_delete(s2n_per_thread_rand_state_key);
+ }
+}
+
static void s2n_drbg_destructor(void *_unused_argument)
{
(void) _unused_argument;
@@ -144,7 +193,9 @@ static void s2n_drbg_destructor(void *_unused_argument)
static void s2n_drbg_make_rand_state_key(void)
{
- (void) pthread_key_create(&s2n_per_thread_rand_state_key, s2n_drbg_destructor);
+ /* We can't return the output of pthread_key_create due to the parameter constraints of pthread_once.
+ * Here we store the result in a global variable that will be error checked later. */
+ pthread_key_create_result = pthread_key_create(&s2n_per_thread_rand_state_key, s2n_drbg_destructor);
}
static S2N_RESULT s2n_init_drbgs(void)
@@ -157,6 +208,7 @@ static S2N_RESULT s2n_init_drbgs(void)
RESULT_GUARD_POSIX(s2n_blob_init(&private, s2n_private_drbg, sizeof(s2n_private_drbg)));
RESULT_ENSURE(pthread_once(&s2n_per_thread_rand_state_key_once, s2n_drbg_make_rand_state_key) == 0, S2N_ERR_DRBG);
+ RESULT_ENSURE_EQ(pthread_key_create_result, 0);
RESULT_GUARD(s2n_drbg_instantiate(&s2n_per_thread_rand_state.public_drbg, &public, S2N_AES_128_CTR_NO_DF_PR));
RESULT_GUARD(s2n_drbg_instantiate(&s2n_per_thread_rand_state.private_drbg, &private, S2N_AES_256_CTR_NO_DF_PR));
@@ -206,9 +258,19 @@ static S2N_RESULT s2n_ensure_uniqueness(void)
return S2N_RESULT_OK;
}
-static S2N_RESULT s2n_get_random_data(struct s2n_blob *out_blob,
- struct s2n_drbg *drbg_state)
+static S2N_RESULT s2n_get_libcrypto_random_data(struct s2n_blob *out_blob)
+{
+ RESULT_GUARD_PTR(out_blob);
+ RESULT_GUARD_OSSL(RAND_bytes(out_blob->data, out_blob->size), S2N_ERR_DRBG);
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_get_custom_random_data(struct s2n_blob *out_blob, struct s2n_drbg *drbg_state)
{
+ RESULT_GUARD_PTR(out_blob);
+ RESULT_GUARD_PTR(drbg_state);
+
+ RESULT_ENSURE(!s2n_is_in_fips_mode(), S2N_ERR_DRBG);
RESULT_GUARD(s2n_ensure_initialized_drbgs());
RESULT_GUARD(s2n_ensure_uniqueness());
@@ -228,6 +290,22 @@ static S2N_RESULT s2n_get_random_data(struct s2n_blob *out_blob,
return S2N_RESULT_OK;
}
+static S2N_RESULT s2n_get_random_data(struct s2n_blob *blob, struct s2n_drbg *drbg_state)
+{
+ /* By default, s2n-tls uses a custom random implementation to generate random data for the TLS
+ * handshake. When operating in FIPS mode, the FIPS-validated libcrypto implementation is used
+ * instead.
+ */
+ if (s2n_is_in_fips_mode()) {
+ RESULT_GUARD(s2n_get_libcrypto_random_data(blob));
+ return S2N_RESULT_OK;
+ }
+
+ RESULT_GUARD(s2n_get_custom_random_data(blob, drbg_state));
+
+ return S2N_RESULT_OK;
+}
+
S2N_RESULT s2n_get_public_random_data(struct s2n_blob *blob)
{
RESULT_GUARD(s2n_get_random_data(blob, &s2n_per_thread_rand_state.public_drbg));
@@ -375,7 +453,7 @@ RAND_METHOD s2n_openssl_rand_method = {
static int s2n_rand_init_impl(void)
{
OPEN:
- entropy_fd = open(ENTROPY_SOURCE, O_RDONLY);
+ entropy_fd = open(ENTROPY_SOURCE, ENTROPY_FLAGS);
if (entropy_fd == -1) {
if (errno == EINTR) {
goto OPEN;
@@ -397,6 +475,10 @@ S2N_RESULT s2n_rand_init(void)
RESULT_GUARD(s2n_ensure_initialized_drbgs());
#if S2N_LIBCRYPTO_SUPPORTS_CUSTOM_RAND
+ if (s2n_is_in_fips_mode()) {
+ return S2N_RESULT_OK;
+ }
+
/* Create an engine */
ENGINE *e = ENGINE_new();
@@ -466,6 +548,11 @@ S2N_RESULT s2n_rand_cleanup_thread(void)
s2n_per_thread_rand_state.drbgs_initialized = false;
+ /* Unset the thread-local destructor */
+ if (s2n_is_initialized()) {
+ pthread_setspecific(s2n_per_thread_rand_state_key, NULL);
+ }
+
return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/utils/s2n_safety.c b/contrib/restricted/aws/s2n/utils/s2n_safety.c
index f6f200777e..6b2457b00b 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_safety.c
+++ b/contrib/restricted/aws/s2n/utils/s2n_safety.c
@@ -157,19 +157,31 @@ int s2n_constant_time_pkcs1_unpad_or_dont(uint8_t *dst, const uint8_t *src, uint
return 0;
}
-static bool s_s2n_in_unit_test = false;
+static bool s2n_in_unit_test_value = false;
+static bool s2n_in_integ_test_value = false;
-bool s2n_in_unit_test()
+int s2n_in_unit_test_set(bool is_unit)
{
- return s_s2n_in_unit_test;
+ s2n_in_unit_test_value = is_unit;
+ return S2N_SUCCESS;
}
-int s2n_in_unit_test_set(bool newval)
+int s2n_in_integ_test_set(bool is_integ)
{
- s_s2n_in_unit_test = newval;
+ s2n_in_integ_test_value = is_integ;
return S2N_SUCCESS;
}
+bool s2n_in_unit_test()
+{
+ return s2n_in_unit_test_value;
+}
+
+bool s2n_in_test()
+{
+ return s2n_in_unit_test_value || s2n_in_integ_test_value;
+}
+
int s2n_align_to(uint32_t initial, uint32_t alignment, uint32_t *out)
{
POSIX_ENSURE_REF(out);
diff --git a/contrib/restricted/aws/s2n/utils/s2n_safety.h b/contrib/restricted/aws/s2n/utils/s2n_safety.h
index f095529733..f69e7574ea 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_safety.h
+++ b/contrib/restricted/aws/s2n/utils/s2n_safety.h
@@ -39,14 +39,10 @@
#define FALL_THROUGH ((void) 0)
#endif
-/* Returns `true` if s2n is in unit test mode, `false` otherwise */
+int s2n_in_unit_test_set(bool is_unit);
+int s2n_in_integ_test_set(bool is_integ);
bool s2n_in_unit_test();
-
-/* Sets whether s2n is in unit test mode */
-int s2n_in_unit_test_set(bool newval);
-
-#define S2N_IN_INTEG_TEST (getenv("S2N_INTEG_TEST") != NULL)
-#define S2N_IN_TEST (s2n_in_unit_test() || S2N_IN_INTEG_TEST)
+bool s2n_in_test();
/* Returns 1 if a and b are equal, in constant time */
bool s2n_constant_time_equals(const uint8_t* a, const uint8_t* b, const uint32_t len);
diff --git a/contrib/restricted/aws/s2n/utils/s2n_safety_macros.h b/contrib/restricted/aws/s2n/utils/s2n_safety_macros.h
index fb71ef21ee..33e5133dca 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_safety_macros.h
+++ b/contrib/restricted/aws/s2n/utils/s2n_safety_macros.h
@@ -40,7 +40,7 @@
/**
* Sets the global `s2n_errno` to `error` and returns with an `S2N_RESULT_ERROR`
*/
-#define RESULT_BAIL(error) do { _S2N_ERROR((error)); return S2N_RESULT_ERROR; } while (0)
+#define RESULT_BAIL(error) do { _S2N_ERROR((error)); __S2N_ENSURE_CHECKED_RETURN(S2N_RESULT_ERROR); } while (0)
/**
* Ensures the `condition` is `true`, otherwise the function will `RESULT_BAIL` with `error`
@@ -161,7 +161,7 @@
* * The size of the data pointed to by both the `destination` and `source` parameters,
* shall be at least `len` bytes.
*/
-#define RESULT_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), RESULT_GUARD_PTR)
+#define RESULT_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), RESULT_ENSURE_REF)
/**
* Performs a safer memset
@@ -180,7 +180,7 @@
/**
* Ensures `s2n_result_is_ok(result)`, otherwise the function will return `S2N_RESULT_ERROR`
*/
-#define RESULT_GUARD(result) __S2N_ENSURE(s2n_result_is_ok(result), return S2N_RESULT_ERROR)
+#define RESULT_GUARD(result) __S2N_ENSURE(s2n_result_is_ok(result), __S2N_ENSURE_CHECKED_RETURN(S2N_RESULT_ERROR))
/**
* Ensures `result == _OSSL_SUCCESS`, otherwise the function will `RESULT_BAIL` with `error`
@@ -190,21 +190,21 @@
/**
* Ensures `(result) > S2N_FAILURE`, otherwise the function will return `S2N_RESULT_ERROR`
*/
-#define RESULT_GUARD_POSIX(result) __S2N_ENSURE((result) > S2N_FAILURE, return S2N_RESULT_ERROR)
+#define RESULT_GUARD_POSIX(result) __S2N_ENSURE((result) > S2N_FAILURE, __S2N_ENSURE_CHECKED_RETURN(S2N_RESULT_ERROR))
/**
* Ensures `(result) != NULL`, otherwise the function will return `S2N_RESULT_ERROR`
*
* Does not set s2n_errno to S2N_ERR_NULL, so is NOT a direct replacement for RESULT_ENSURE_REF.
*/
-#define RESULT_GUARD_PTR(result) __S2N_ENSURE((result) != NULL, return S2N_RESULT_ERROR)
+#define RESULT_GUARD_PTR(result) __S2N_ENSURE((result) != NULL, __S2N_ENSURE_CHECKED_RETURN(S2N_RESULT_ERROR))
/**
* DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
*
* Sets the global `s2n_errno` to `error` and returns with an `S2N_FAILURE`
*/
-#define POSIX_BAIL(error) do { _S2N_ERROR((error)); return S2N_FAILURE; } while (0)
+#define POSIX_BAIL(error) do { _S2N_ERROR((error)); __S2N_ENSURE_CHECKED_RETURN(S2N_FAILURE); } while (0)
/**
* DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
@@ -357,7 +357,7 @@
* * The size of the data pointed to by both the `destination` and `source` parameters,
* shall be at least `len` bytes.
*/
-#define POSIX_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), POSIX_GUARD_PTR)
+#define POSIX_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), POSIX_ENSURE_REF)
/**
* DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
@@ -380,7 +380,7 @@
*
* Ensures `(result) > S2N_FAILURE`, otherwise the function will return `S2N_FAILURE`
*/
-#define POSIX_GUARD(result) __S2N_ENSURE((result) > S2N_FAILURE, return S2N_FAILURE)
+#define POSIX_GUARD(result) __S2N_ENSURE((result) > S2N_FAILURE, __S2N_ENSURE_CHECKED_RETURN(S2N_FAILURE))
/**
* DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
@@ -394,7 +394,7 @@
*
* Ensures `s2n_result_is_ok(result)`, otherwise the function will return `S2N_FAILURE`
*/
-#define POSIX_GUARD_RESULT(result) __S2N_ENSURE(s2n_result_is_ok(result), return S2N_FAILURE)
+#define POSIX_GUARD_RESULT(result) __S2N_ENSURE(s2n_result_is_ok(result), __S2N_ENSURE_CHECKED_RETURN(S2N_FAILURE))
/**
* DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
@@ -403,14 +403,14 @@
*
* Does not set s2n_errno to S2N_ERR_NULL, so is NOT a direct replacement for POSIX_ENSURE_REF.
*/
-#define POSIX_GUARD_PTR(result) __S2N_ENSURE((result) != NULL, return S2N_FAILURE)
+#define POSIX_GUARD_PTR(result) __S2N_ENSURE((result) != NULL, __S2N_ENSURE_CHECKED_RETURN(S2N_FAILURE))
/**
* DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
*
* Sets the global `s2n_errno` to `error` and returns with an `NULL`
*/
-#define PTR_BAIL(error) do { _S2N_ERROR((error)); return NULL; } while (0)
+#define PTR_BAIL(error) do { _S2N_ERROR((error)); __S2N_ENSURE_CHECKED_RETURN(NULL); } while (0)
/**
* DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
@@ -563,7 +563,7 @@
* * The size of the data pointed to by both the `destination` and `source` parameters,
* shall be at least `len` bytes.
*/
-#define PTR_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), PTR_GUARD)
+#define PTR_CHECKED_MEMCPY(destination, source, len) __S2N_ENSURE_SAFE_MEMCPY((destination), (source), (len), PTR_ENSURE_REF)
/**
* DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
@@ -586,7 +586,7 @@
*
* Ensures `(result) != NULL`, otherwise the function will return `NULL`
*/
-#define PTR_GUARD(result) __S2N_ENSURE((result) != NULL, return NULL)
+#define PTR_GUARD(result) __S2N_ENSURE((result) != NULL, __S2N_ENSURE_CHECKED_RETURN(NULL))
/**
* DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
@@ -600,12 +600,12 @@
*
* Ensures `s2n_result_is_ok(result)`, otherwise the function will return `NULL`
*/
-#define PTR_GUARD_RESULT(result) __S2N_ENSURE(s2n_result_is_ok(result), return NULL)
+#define PTR_GUARD_RESULT(result) __S2N_ENSURE(s2n_result_is_ok(result), __S2N_ENSURE_CHECKED_RETURN(NULL))
/**
* DEPRECATED: all methods (except those in s2n.h) should return s2n_result.
*
* Ensures `(result) > S2N_FAILURE`, otherwise the function will return `NULL`
*/
-#define PTR_GUARD_POSIX(result) __S2N_ENSURE((result) > S2N_FAILURE, return NULL)
+#define PTR_GUARD_POSIX(result) __S2N_ENSURE((result) > S2N_FAILURE, __S2N_ENSURE_CHECKED_RETURN(NULL))
diff --git a/contrib/restricted/aws/s2n/ya.make b/contrib/restricted/aws/s2n/ya.make
index 478bbee602..8de78874c1 100644
--- a/contrib/restricted/aws/s2n/ya.make
+++ b/contrib/restricted/aws/s2n/ya.make
@@ -12,9 +12,9 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-VERSION(1.3.44)
+VERSION(1.3.54)
-ORIGINAL_SOURCE(https://github.com/aws/s2n-tls/archive/v1.3.44.tar.gz)
+ORIGINAL_SOURCE(https://github.com/aws/s2n-tls/archive/v1.3.54.tar.gz)
PEERDIR(
contrib/libs/openssl
@@ -30,19 +30,29 @@ NO_COMPILER_WARNINGS()
NO_RUNTIME()
CFLAGS(
+ -DS2N_ATOMIC_SUPPORTED
+ -DS2N_CLOEXEC_SUPPORTED
+ -DS2N_CLOEXEC_XOPEN_SUPPORTED
-DS2N_CLONE_SUPPORTED
+ -DS2N_DIAGNOSTICS_POP_SUPPORTED
+ -DS2N_DIAGNOSTICS_PUSH_SUPPORTED
+ -DS2N_EXECINFO_AVAILABLE
-DS2N_FALL_THROUGH_SUPPORTED
+ -DS2N_KYBER512R3_AVX2_BMI2_SUPPORTED
+ -DS2N_KYBER512R3_M256_INTRINSICS_SUPPORTED
-DS2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH
-DS2N_LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX
-DS2N_LIBCRYPTO_SUPPORTS_EVP_RC4
+ -DS2N_LIBCRYPTO_SUPPORTS_FLAG_NO_CHECK_TIME
-DS2N_MADVISE_SUPPORTED
- -DS2N_PLATFORM_SUPPORTS_KTLS
-DS2N___RESTRICT__SUPPORTED
)
IF (OS_LINUX)
CFLAGS(
-DS2N_FEATURES_AVAILABLE
+ -DS2N_LINUX_SENDFILE
+ -DS2N_KTLS_SUPPORTED
)
ENDIF()
@@ -114,7 +124,7 @@ SRCS(
pq-crypto/kyber_r3/kyber512r3_polyvec.c
pq-crypto/kyber_r3/kyber512r3_reduce.c
pq-crypto/kyber_r3/kyber512r3_symmetric-shake.c
- pq-crypto/s2n_kyber_512_evp.c
+ pq-crypto/s2n_kyber_evp.c
pq-crypto/s2n_pq.c
pq-crypto/s2n_pq_random.c
stuffer/s2n_stuffer.c
@@ -200,6 +210,7 @@ SRCS(
tls/s2n_key_log.c
tls/s2n_key_update.c
tls/s2n_ktls.c
+ tls/s2n_ktls_io.c
tls/s2n_next_protocol.c
tls/s2n_ocsp_stapling.c
tls/s2n_post_handshake.c
@@ -238,11 +249,12 @@ SRCS(
tls/s2n_tls13_secrets.c
tls/s2n_x509_validator.c
utils/s2n_array.c
- utils/s2n_asn1_time.c
+ utils/s2n_atomic.c
utils/s2n_blob.c
utils/s2n_ensure.c
utils/s2n_fork_detection.c
utils/s2n_init.c
+ utils/s2n_io.c
utils/s2n_map.c
utils/s2n_mem.c
utils/s2n_random.c