aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws
diff options
context:
space:
mode:
authorarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-03-02 12:50:27 +0300
committerarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-03-02 12:50:27 +0300
commitd0f80d5e60d77854f9d6262a59a7349e2b21f9d2 (patch)
tree01f1e033ce5519d96b7d6a83718221dcb8021eec /contrib/restricted/aws
parent26286f616cee657612a9d820be6da2cdbd4de0ef (diff)
downloadydb-d0f80d5e60d77854f9d6262a59a7349e2b21f9d2.tar.gz
intermediate changes
ref:40ac71fae6ea311a73473cf4297ca93bf27559c3
Diffstat (limited to 'contrib/restricted/aws')
-rw-r--r--contrib/restricted/aws/s2n/.yandex_meta/devtools.copyrights.report4
-rw-r--r--contrib/restricted/aws/s2n/.yandex_meta/devtools.licenses.report4
-rw-r--r--contrib/restricted/aws/s2n/CMakeLists.txt2
-rw-r--r--contrib/restricted/aws/s2n/api/s2n.h9
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c18
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_fips.h4
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_hash.c27
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_hmac.c124
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_hmac.h5
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_pkey.c17
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_pkey.h5
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_rsa.c106
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c11
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c59
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h6
-rw-r--r--contrib/restricted/aws/s2n/error/s2n_errno.c16
-rw-r--r--contrib/restricted/aws/s2n/error/s2n_errno.h4
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/bike_r1/bike_r1_kem.c5
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/bike_r2/bike_r2_kem.c5
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_90s_r2/kyber_90s_r2_kem.c4
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/kyber_r2/kyber_r2_kem.c4
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c6
-rw-r--r--contrib/restricted/aws/s2n/pq-crypto/sike_r2/sike_r2_kem.c4
-rw-r--r--contrib/restricted/aws/s2n/stuffer/s2n_stuffer_network_order.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.c23
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c9
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c214
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.c10
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c9
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h1
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c4
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c83
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.h22
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c10
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c92
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.h20
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_async_pkey.c6
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_auth_selection.c13
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c19
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h5
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c41
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h7
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_hello.c8
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c17
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.c11
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection.h8
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake_io.c92
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kem.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c4
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h5
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kex.c244
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kex.h25
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_psk.c135
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_psk.h48
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_recv.c11
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_security_policies.c26
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_security_policies.h3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_send.c11
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c6
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c18
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c18
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h22
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_annotations.h2
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_result.h5
-rw-r--r--contrib/restricted/aws/s2n/utils/s2n_safety.c4
-rw-r--r--contrib/restricted/aws/s2n/ya.make6
72 files changed, 1312 insertions, 471 deletions
diff --git a/contrib/restricted/aws/s2n/.yandex_meta/devtools.copyrights.report b/contrib/restricted/aws/s2n/.yandex_meta/devtools.copyrights.report
index 4e2f77d918..c6657ea2b7 100644
--- a/contrib/restricted/aws/s2n/.yandex_meta/devtools.copyrights.report
+++ b/contrib/restricted/aws/s2n/.yandex_meta/devtools.copyrights.report
@@ -187,6 +187,8 @@ BELONGS ya.make
tls/extensions/s2n_extension_type_lists.h [2:2]
tls/extensions/s2n_key_share.c [2:2]
tls/extensions/s2n_key_share.h [2:2]
+ tls/extensions/s2n_psk_key_exchange_modes.c [2:2]
+ tls/extensions/s2n_psk_key_exchange_modes.h [2:2]
tls/extensions/s2n_quic_transport_params.c [2:2]
tls/extensions/s2n_quic_transport_params.h [2:2]
tls/extensions/s2n_server_alpn.c [2:2]
@@ -197,6 +199,8 @@ BELONGS ya.make
tls/extensions/s2n_server_key_share.h [2:2]
tls/extensions/s2n_server_max_fragment_length.c [2:2]
tls/extensions/s2n_server_max_fragment_length.h [2:2]
+ tls/extensions/s2n_server_psk.c [2:2]
+ tls/extensions/s2n_server_psk.h [2:2]
tls/extensions/s2n_server_renegotiation_info.c [2:2]
tls/extensions/s2n_server_renegotiation_info.h [2:2]
tls/extensions/s2n_server_sct_list.c [2:2]
diff --git a/contrib/restricted/aws/s2n/.yandex_meta/devtools.licenses.report b/contrib/restricted/aws/s2n/.yandex_meta/devtools.licenses.report
index 2411f3a704..42c940cc02 100644
--- a/contrib/restricted/aws/s2n/.yandex_meta/devtools.licenses.report
+++ b/contrib/restricted/aws/s2n/.yandex_meta/devtools.licenses.report
@@ -363,6 +363,8 @@ BELONGS ya.make
tls/extensions/s2n_extension_type_lists.h [4:13]
tls/extensions/s2n_key_share.c [4:13]
tls/extensions/s2n_key_share.h [4:13]
+ tls/extensions/s2n_psk_key_exchange_modes.c [4:13]
+ tls/extensions/s2n_psk_key_exchange_modes.h [4:13]
tls/extensions/s2n_quic_transport_params.c [4:13]
tls/extensions/s2n_quic_transport_params.h [4:13]
tls/extensions/s2n_server_alpn.c [4:13]
@@ -373,6 +375,8 @@ BELONGS ya.make
tls/extensions/s2n_server_key_share.h [4:13]
tls/extensions/s2n_server_max_fragment_length.c [4:13]
tls/extensions/s2n_server_max_fragment_length.h [4:13]
+ tls/extensions/s2n_server_psk.c [4:13]
+ tls/extensions/s2n_server_psk.h [4:13]
tls/extensions/s2n_server_renegotiation_info.c [4:13]
tls/extensions/s2n_server_renegotiation_info.h [4:13]
tls/extensions/s2n_server_sct_list.c [4:13]
diff --git a/contrib/restricted/aws/s2n/CMakeLists.txt b/contrib/restricted/aws/s2n/CMakeLists.txt
index 2c5722b2de..cf54c00743 100644
--- a/contrib/restricted/aws/s2n/CMakeLists.txt
+++ b/contrib/restricted/aws/s2n/CMakeLists.txt
@@ -132,11 +132,13 @@ target_sources(restricted-aws-s2n PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_max_fragment_length.c
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_sct_list.c
${CMAKE_SOURCE_DIR}/contrib/restricted/aws/s2n/tls/extensions/s2n_server_server_name.c
diff --git a/contrib/restricted/aws/s2n/api/s2n.h b/contrib/restricted/aws/s2n/api/s2n.h
index 55a3ccf4bc..0dfa21bf26 100644
--- a/contrib/restricted/aws/s2n/api/s2n.h
+++ b/contrib/restricted/aws/s2n/api/s2n.h
@@ -51,6 +51,15 @@ extern "C" {
S2N_API
extern __thread int s2n_errno;
+/**
+ * Returns the address of the thread-local `s2n_errno` variable
+ *
+ * This function can be used instead of trying to resolve `s2n_errno` directly
+ * in runtimes where thread-local variables may not be easily accessible.
+ */
+S2N_API
+extern int *s2n_errno_location();
+
typedef enum {
S2N_ERR_T_OK=0,
S2N_ERR_T_IO,
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c
index d1d37d1bee..240f0f87b1 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_ecdsa.c
@@ -22,6 +22,7 @@
#include "utils/s2n_blob.h"
#include "utils/s2n_mem.h"
#include "utils/s2n_random.h"
+#include "utils/s2n_result.h"
#include "utils/s2n_safety.h"
#include "crypto/s2n_ecdsa.h"
@@ -30,12 +31,19 @@
#include "crypto/s2n_openssl.h"
#include "crypto/s2n_pkey.h"
-int s2n_ecdsa_der_signature_size(const struct s2n_pkey *pkey)
+S2N_RESULT s2n_ecdsa_der_signature_size(const struct s2n_pkey *pkey, uint32_t *size_out)
{
+ ENSURE_REF(pkey);
+ ENSURE_REF(size_out);
+
const struct s2n_ecdsa_key *ecdsa_key = &pkey->key.ecdsa_key;
- notnull_check(ecdsa_key->ec_key);
+ ENSURE_REF(ecdsa_key->ec_key);
+
+ const int size = ECDSA_size(ecdsa_key->ec_key);
+ GUARD_AS_RESULT(size);
+ *size_out = size;
- return ECDSA_size(ecdsa_key->ec_key);
+ return S2N_RESULT_OK;
}
static int s2n_ecdsa_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig_alg,
@@ -102,7 +110,9 @@ static int s2n_ecdsa_keys_match(const struct s2n_pkey *pub, const struct s2n_pke
GUARD(s2n_hash_update(&state_in, input, sizeof(input)));
GUARD(s2n_hash_update(&state_out, input, sizeof(input)));
- GUARD(s2n_alloc(&signature, s2n_ecdsa_der_signature_size(priv)));
+ uint32_t size = 0;
+ GUARD_AS_POSIX(s2n_ecdsa_der_signature_size(priv, &size));
+ GUARD(s2n_alloc(&signature, size));
GUARD(s2n_ecdsa_sign(priv, S2N_SIGNATURE_ECDSA, &state_in, &signature));
GUARD(s2n_ecdsa_verify(pub, S2N_SIGNATURE_ECDSA, &state_out, &signature));
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_fips.h b/contrib/restricted/aws/s2n/crypto/s2n_fips.h
index 23c3ea4bd0..e0644f4080 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_fips.h
+++ b/contrib/restricted/aws/s2n/crypto/s2n_fips.h
@@ -13,6 +13,10 @@
* permissions and limitations under the License.
*/
+#include <stdbool.h>
+
+#include "api/s2n.h"
+
#pragma once
extern int s2n_fips_init(void);
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hash.c b/contrib/restricted/aws/s2n/crypto/s2n_hash.c
index 0a3ad28130..27a9358438 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_hash.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_hash.c
@@ -22,27 +22,9 @@
#include "utils/s2n_safety.h"
-int s2n_hash_hmac_alg(s2n_hash_algorithm hash_alg, s2n_hmac_algorithm *out)
-{
- ENSURE_POSIX(S2N_MEM_IS_READABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION);
- switch(hash_alg) {
- case S2N_HASH_NONE: *out = S2N_HMAC_NONE; break;
- case S2N_HASH_MD5: *out = S2N_HMAC_MD5; break;
- case S2N_HASH_SHA1: *out = S2N_HMAC_SHA1; break;
- case S2N_HASH_SHA224: *out = S2N_HMAC_SHA224; break;
- case S2N_HASH_SHA256: *out = S2N_HMAC_SHA256; break;
- case S2N_HASH_SHA384: *out = S2N_HMAC_SHA384; break;
- case S2N_HASH_SHA512: *out = S2N_HMAC_SHA512; break;
- case S2N_HASH_MD5_SHA1: /* Fall through ... */
- default:
- S2N_ERROR(S2N_ERR_HASH_INVALID_ALGORITHM);
- }
- return S2N_SUCCESS;
-}
-
int s2n_hash_digest_size(s2n_hash_algorithm alg, uint8_t *out)
{
- notnull_check(out);
+ ENSURE_POSIX(S2N_MEM_IS_WRITABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION);
switch (alg) {
case S2N_HASH_NONE: *out = 0; break;
case S2N_HASH_MD5: *out = MD5_DIGEST_LENGTH; break;
@@ -63,7 +45,7 @@ int s2n_hash_digest_size(s2n_hash_algorithm alg, uint8_t *out)
* If this ever becomes untrue, this would require fixing*/
int s2n_hash_block_size(s2n_hash_algorithm alg, uint64_t *block_size)
{
- ENSURE_POSIX(S2N_MEM_IS_READABLE(block_size, sizeof(*block_size)), S2N_ERR_PRECONDITION_VIOLATION);
+ ENSURE_POSIX(S2N_MEM_IS_WRITABLE(block_size, sizeof(*block_size)), S2N_ERR_PRECONDITION_VIOLATION);
switch(alg) {
case S2N_HASH_NONE: *block_size = 64; break;
case S2N_HASH_MD5: *block_size = 64; break;
@@ -523,7 +505,6 @@ int s2n_hash_new(struct s2n_hash_state *state)
S2N_RESULT s2n_hash_state_validate(struct s2n_hash_state *state)
{
ENSURE_REF(state);
- ENSURE_REF(state->hash_impl);
return S2N_RESULT_OK;
}
@@ -623,7 +604,7 @@ int s2n_hash_free(struct s2n_hash_state *state)
int s2n_hash_get_currently_in_hash_total(struct s2n_hash_state *state, uint64_t *out)
{
PRECONDITION_POSIX(s2n_hash_state_validate(state));
- ENSURE_POSIX(S2N_MEM_IS_READABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION);
+ ENSURE_POSIX(S2N_MEM_IS_WRITABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION);
ENSURE_POSIX(state->is_ready_for_input, S2N_ERR_HASH_NOT_READY);
*out = state->currently_in_hash;
@@ -635,7 +616,7 @@ int s2n_hash_get_currently_in_hash_total(struct s2n_hash_state *state, uint64_t
int s2n_hash_const_time_get_currently_in_hash_block(struct s2n_hash_state *state, uint64_t *out)
{
PRECONDITION_POSIX(s2n_hash_state_validate(state));
- ENSURE_POSIX(S2N_MEM_IS_READABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION);
+ ENSURE_POSIX(S2N_MEM_IS_WRITABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION);
ENSURE_POSIX(state->is_ready_for_input, S2N_ERR_HASH_NOT_READY);
uint64_t hash_block_size;
GUARD(s2n_hash_block_size(state->alg, &hash_block_size));
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hmac.c b/contrib/restricted/aws/s2n/crypto/s2n_hmac.c
index 8f5acf045a..2689545abb 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_hmac.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_hmac.c
@@ -28,9 +28,27 @@
#include <stdint.h>
+int s2n_hash_hmac_alg(s2n_hash_algorithm hash_alg, s2n_hmac_algorithm *out)
+{
+ ENSURE_POSIX(S2N_MEM_IS_WRITABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION);
+ switch(hash_alg) {
+ case S2N_HASH_NONE: *out = S2N_HMAC_NONE; break;
+ case S2N_HASH_MD5: *out = S2N_HMAC_MD5; break;
+ case S2N_HASH_SHA1: *out = S2N_HMAC_SHA1; break;
+ case S2N_HASH_SHA224: *out = S2N_HMAC_SHA224; break;
+ case S2N_HASH_SHA256: *out = S2N_HMAC_SHA256; break;
+ case S2N_HASH_SHA384: *out = S2N_HMAC_SHA384; break;
+ case S2N_HASH_SHA512: *out = S2N_HMAC_SHA512; break;
+ case S2N_HASH_MD5_SHA1: /* Fall through ... */
+ default:
+ S2N_ERROR(S2N_ERR_HASH_INVALID_ALGORITHM);
+ }
+ return S2N_SUCCESS;
+}
int s2n_hmac_hash_alg(s2n_hmac_algorithm hmac_alg, s2n_hash_algorithm *out)
{
+ ENSURE_POSIX(S2N_MEM_IS_WRITABLE(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION);
switch(hmac_alg) {
case S2N_HMAC_NONE: *out = S2N_HASH_NONE; break;
case S2N_HMAC_MD5: *out = S2N_HASH_MD5; break;
@@ -44,7 +62,7 @@ int s2n_hmac_hash_alg(s2n_hmac_algorithm hmac_alg, s2n_hash_algorithm *out)
default:
S2N_ERROR(S2N_ERR_HMAC_INVALID_ALGORITHM);
}
- return 0;
+ return S2N_SUCCESS;
}
int s2n_hmac_digest_size(s2n_hmac_algorithm hmac_alg, uint8_t *out)
@@ -52,33 +70,27 @@ int s2n_hmac_digest_size(s2n_hmac_algorithm hmac_alg, uint8_t *out)
s2n_hash_algorithm hash_alg;
GUARD(s2n_hmac_hash_alg(hmac_alg, &hash_alg));
GUARD(s2n_hash_digest_size(hash_alg, out));
- return 0;
+ return S2N_SUCCESS;
}
/* Return 1 if hmac algorithm is available, 0 otherwise. */
-int s2n_hmac_is_available(s2n_hmac_algorithm hmac_alg)
+bool s2n_hmac_is_available(s2n_hmac_algorithm hmac_alg)
{
- int is_available = 0;
switch(hmac_alg) {
case S2N_HMAC_MD5:
case S2N_HMAC_SSLv3_MD5:
case S2N_HMAC_SSLv3_SHA1:
/* Set is_available to 0 if in FIPS mode, as MD5/SSLv3 algs are not available in FIPS mode. */
- is_available = !s2n_is_in_fips_mode();
- break;
- case S2N_HMAC_NONE:
+ return !s2n_is_in_fips_mode();
+ case S2N_HMAC_NONE:
case S2N_HMAC_SHA1:
case S2N_HMAC_SHA224:
case S2N_HMAC_SHA256:
case S2N_HMAC_SHA384:
case S2N_HMAC_SHA512:
- is_available = 1;
- break;
- default:
- S2N_ERROR(S2N_ERR_HMAC_INVALID_ALGORITHM);
+ return true;
}
-
- return is_available;
+ return false;
}
static int s2n_sslv3_mac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm alg, const void *key, uint32_t klen)
@@ -97,13 +109,13 @@ static int s2n_sslv3_mac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm a
GUARD(s2n_hash_update(&state->outer_just_key, key, klen));
GUARD(s2n_hash_update(&state->outer_just_key, state->xor_pad, state->xor_pad_size));
- return 0;
+ return S2N_SUCCESS;
}
static int s2n_tls_hmac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm alg, const void *key, uint32_t klen)
{
memset(&state->xor_pad, 0, sizeof(state->xor_pad));
-
+
if (klen > state->xor_pad_size) {
GUARD(s2n_hash_update(&state->outer, key, klen));
GUARD(s2n_hash_digest(&state->outer, state->digest_pad, state->digest_size));
@@ -124,11 +136,12 @@ static int s2n_tls_hmac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm al
}
GUARD(s2n_hash_update(&state->outer_just_key, state->xor_pad, state->xor_pad_size));
- return 0;
+ return S2N_SUCCESS;
}
int s2n_hmac_xor_pad_size(s2n_hmac_algorithm hmac_alg, uint16_t *xor_pad_size)
{
+ ENSURE_POSIX(S2N_MEM_IS_WRITABLE(xor_pad_size, sizeof(*xor_pad_size)), S2N_ERR_PRECONDITION_VIOLATION);
switch(hmac_alg) {
case S2N_HMAC_NONE: *xor_pad_size = 64; break;
case S2N_HMAC_MD5: *xor_pad_size = 64; break;
@@ -142,11 +155,12 @@ int s2n_hmac_xor_pad_size(s2n_hmac_algorithm hmac_alg, uint16_t *xor_pad_size)
default:
S2N_ERROR(S2N_ERR_HMAC_INVALID_ALGORITHM);
}
- return 0;
+ return S2N_SUCCESS;
}
int s2n_hmac_hash_block_size(s2n_hmac_algorithm hmac_alg, uint16_t *block_size)
{
+ ENSURE_POSIX(S2N_MEM_IS_WRITABLE(block_size, sizeof(*block_size)), S2N_ERR_PRECONDITION_VIOLATION);
switch(hmac_alg) {
case S2N_HMAC_NONE: *block_size = 64; break;
case S2N_HMAC_MD5: *block_size = 64; break;
@@ -160,21 +174,33 @@ int s2n_hmac_hash_block_size(s2n_hmac_algorithm hmac_alg, uint16_t *block_size)
default:
S2N_ERROR(S2N_ERR_HMAC_INVALID_ALGORITHM);
}
- return 0;
+ return S2N_SUCCESS;
}
int s2n_hmac_new(struct s2n_hmac_state *state)
{
+ ENSURE_POSIX_REF(state);
GUARD(s2n_hash_new(&state->inner));
GUARD(s2n_hash_new(&state->inner_just_key));
GUARD(s2n_hash_new(&state->outer));
GUARD(s2n_hash_new(&state->outer_just_key));
+ POSTCONDITION_POSIX(s2n_hmac_state_validate(state));
+ return S2N_SUCCESS;
+}
- return 0;
+S2N_RESULT s2n_hmac_state_validate(struct s2n_hmac_state *state)
+{
+ ENSURE_REF(state);
+ GUARD_RESULT(s2n_hash_state_validate(&state->inner));
+ GUARD_RESULT(s2n_hash_state_validate(&state->inner_just_key));
+ GUARD_RESULT(s2n_hash_state_validate(&state->outer));
+ GUARD_RESULT(s2n_hash_state_validate(&state->outer_just_key));
+ return S2N_RESULT_OK;
}
int s2n_hmac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm alg, const void *key, uint32_t klen)
{
+ notnull_check(state);
if (!s2n_hmac_is_available(alg)) {
/* Prevent hmacs from being used if they are not available. */
S2N_ERROR(S2N_ERR_HMAC_INVALID_ALGORITHM);
@@ -212,20 +238,22 @@ int s2n_hmac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm alg, const vo
memset(&state->xor_pad, 0, sizeof(state->xor_pad));
GUARD(s2n_hmac_reset(state));
- return 0;
+ return S2N_SUCCESS;
}
int s2n_hmac_update(struct s2n_hmac_state *state, const void *in, uint32_t size)
{
+ PRECONDITION_POSIX(s2n_hmac_state_validate(state));
+ ENSURE_POSIX(state->hash_block_size != 0, S2N_ERR_PRECONDITION_VIOLATION);
/* Keep track of how much of the current hash block is full
*
* Why the 4294949760 constant in this code? 4294949760 is the highest 32-bit
* value that is congruent to 0 modulo all of our HMAC block sizes, that is also
* at least 16k smaller than 2^32. It therefore has no effect on the mathematical
* result, and no valid record size can cause it to overflow.
- *
+ *
* The value was found with the following python code;
- *
+ *
* x = (2 ** 32) - (2 ** 14)
* while True:
* if x % 40 | x % 48 | x % 64 | x % 128 == 0:
@@ -238,7 +266,10 @@ int s2n_hmac_update(struct s2n_hmac_state *state, const void *in, uint32_t size)
* input. On some platforms, including Intel, the operation can take a
* smaller number of cycles if the input is "small".
*/
- state->currently_in_hash_block += (4294949760 + size) % state->hash_block_size;
+ const uint32_t HIGHEST_32_BIT = 4294949760;
+ ENSURE_POSIX(size <= (UINT32_MAX - HIGHEST_32_BIT), S2N_ERR_INTEGER_OVERFLOW);
+ uint32_t value = (HIGHEST_32_BIT + size) % state->hash_block_size;
+ GUARD(s2n_add_overflow(state->currently_in_hash_block, value, &state->currently_in_hash_block));
state->currently_in_hash_block %= state->hash_block_size;
return s2n_hash_update(&state->inner, in, size);
@@ -246,6 +277,7 @@ int s2n_hmac_update(struct s2n_hmac_state *state, const void *in, uint32_t size)
int s2n_hmac_digest(struct s2n_hmac_state *state, void *out, uint32_t size)
{
+ PRECONDITION_POSIX(s2n_hmac_state_validate(state));
GUARD(s2n_hash_digest(&state->inner, state->digest_pad, state->digest_size));
GUARD(s2n_hash_copy(&state->outer, &state->outer_just_key));
GUARD(s2n_hash_update(&state->outer, state->digest_pad, state->digest_size));
@@ -267,8 +299,8 @@ int s2n_hmac_digest_two_compression_rounds(struct s2n_hmac_state *state, void *o
* 17 bytes if the block size is 128.
*/
const uint8_t space_left = (state->hash_block_size == 128) ? 17 : 9;
- if (state->currently_in_hash_block > (state->hash_block_size - space_left)) {
- return 0;
+ if ((int64_t)state->currently_in_hash_block > (state->hash_block_size - space_left)) {
+ return S2N_SUCCESS;
}
/* Can't reuse a hash after it has been finalized, so reset and push another block in */
@@ -280,32 +312,40 @@ int s2n_hmac_digest_two_compression_rounds(struct s2n_hmac_state *state, void *o
int s2n_hmac_free(struct s2n_hmac_state *state)
{
- GUARD(s2n_hash_free(&state->inner));
- GUARD(s2n_hash_free(&state->inner_just_key));
- GUARD(s2n_hash_free(&state->outer));
- GUARD(s2n_hash_free(&state->outer_just_key));
+ if (state) {
+ GUARD(s2n_hash_free(&state->inner));
+ GUARD(s2n_hash_free(&state->inner_just_key));
+ GUARD(s2n_hash_free(&state->outer));
+ GUARD(s2n_hash_free(&state->outer_just_key));
+ }
- return 0;
+ return S2N_SUCCESS;
}
int s2n_hmac_reset(struct s2n_hmac_state *state)
{
+ PRECONDITION_POSIX(s2n_hmac_state_validate(state));
+ ENSURE_POSIX(state->hash_block_size != 0, S2N_ERR_PRECONDITION_VIOLATION);
GUARD(s2n_hash_copy(&state->inner, &state->inner_just_key));
-
+
uint64_t bytes_in_hash;
GUARD(s2n_hash_get_currently_in_hash_total(&state->inner, &bytes_in_hash));
+ bytes_in_hash %= state->hash_block_size;
+ ENSURE_POSIX(bytes_in_hash <= UINT32_MAX, S2N_ERR_INTEGER_OVERFLOW);
/* The length of the key is not private, so don't need to do tricky math here */
- state->currently_in_hash_block = bytes_in_hash % state->hash_block_size;
- return 0;
+ state->currently_in_hash_block = bytes_in_hash;
+ return S2N_SUCCESS;
}
int s2n_hmac_digest_verify(const void *a, const void *b, uint32_t len)
{
- return 0 - !s2n_constant_time_equals(a, b, len);
+ return S2N_SUCCESS - !s2n_constant_time_equals(a, b, len);
}
int s2n_hmac_copy(struct s2n_hmac_state *to, struct s2n_hmac_state *from)
{
+ PRECONDITION_POSIX(s2n_hmac_state_validate(to));
+ PRECONDITION_POSIX(s2n_hmac_state_validate(from));
/* memcpy cannot be used on s2n_hmac_state as the underlying s2n_hash implementation's
* copy must be used. This is enforced when the s2n_hash implementation is s2n_evp_hash.
*/
@@ -323,28 +363,34 @@ int s2n_hmac_copy(struct s2n_hmac_state *to, struct s2n_hmac_state *from)
memcpy_check(to->xor_pad, from->xor_pad, sizeof(to->xor_pad));
memcpy_check(to->digest_pad, from->digest_pad, sizeof(to->digest_pad));
-
- return 0;
+ POSTCONDITION_POSIX(s2n_hmac_state_validate(to));
+ POSTCONDITION_POSIX(s2n_hmac_state_validate(from));
+ return S2N_SUCCESS;
}
-/* Preserve the handlers for hmac state pointers to avoid re-allocation
+/* Preserve the handlers for hmac state pointers to avoid re-allocation
* Only valid if the HMAC is in EVP mode
*/
int s2n_hmac_save_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac)
{
+ ENSURE_POSIX_REF(backup);
+ PRECONDITION_POSIX(s2n_hmac_state_validate(hmac));
backup->inner = hmac->inner.digest.high_level;
backup->inner_just_key = hmac->inner_just_key.digest.high_level;
backup->outer = hmac->outer.digest.high_level;
backup->outer_just_key = hmac->outer_just_key.digest.high_level;
- return 0;
+ return S2N_SUCCESS;
}
int s2n_hmac_restore_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac)
{
+ ENSURE_POSIX_REF(backup);
+ PRECONDITION_POSIX(s2n_hmac_state_validate(hmac));
hmac->inner.digest.high_level = backup->inner;
hmac->inner_just_key.digest.high_level = backup->inner_just_key;
hmac->outer.digest.high_level = backup->outer;
hmac->outer_just_key.digest.high_level = backup->outer_just_key;
- return 0;
+ POSTCONDITION_POSIX(s2n_hmac_state_validate(hmac));
+ return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_hmac.h b/contrib/restricted/aws/s2n/crypto/s2n_hmac.h
index b54966f8c3..34f8314b2d 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_hmac.h
+++ b/contrib/restricted/aws/s2n/crypto/s2n_hmac.h
@@ -60,11 +60,12 @@ struct s2n_hmac_evp_backup {
};
extern int s2n_hmac_digest_size(s2n_hmac_algorithm alg, uint8_t *out);
-extern int s2n_hmac_is_available(s2n_hmac_algorithm alg);
+extern bool s2n_hmac_is_available(s2n_hmac_algorithm alg);
extern int s2n_hmac_hash_alg(s2n_hmac_algorithm hmac_alg, s2n_hash_algorithm *out);
extern int s2n_hash_hmac_alg(s2n_hash_algorithm hash_alg, s2n_hmac_algorithm *out);
extern int s2n_hmac_new(struct s2n_hmac_state *state);
+S2N_RESULT s2n_hmac_state_validate(struct s2n_hmac_state *state);
extern int s2n_hmac_init(struct s2n_hmac_state *state, s2n_hmac_algorithm alg, const void *key, uint32_t klen);
extern int s2n_hmac_update(struct s2n_hmac_state *state, const void *in, uint32_t size);
extern int s2n_hmac_digest(struct s2n_hmac_state *state, void *out, uint32_t size);
@@ -75,5 +76,3 @@ extern int s2n_hmac_reset(struct s2n_hmac_state *state);
extern int s2n_hmac_copy(struct s2n_hmac_state *to, struct s2n_hmac_state *from);
extern int s2n_hmac_save_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac);
extern int s2n_hmac_restore_evp_hash_state(struct s2n_hmac_evp_backup* backup, struct s2n_hmac_state* hmac);
-
-
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_pkey.c b/contrib/restricted/aws/s2n/crypto/s2n_pkey.c
index 9123e88080..69c0c25178 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_pkey.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_pkey.c
@@ -21,8 +21,11 @@
#include "crypto/s2n_rsa_pss.h"
#include "crypto/s2n_pkey.h"
+#include "utils/s2n_result.h"
#include "utils/s2n_safety.h"
+#define S2N_MAX_ALLOWED_CERT_TRAILING_BYTES 3
+
int s2n_pkey_zero_init(struct s2n_pkey *pkey)
{
pkey->pkey = NULL;
@@ -61,11 +64,15 @@ int s2n_pkey_check_key_exists(const struct s2n_pkey *pkey)
return pkey->check_key(pkey);
}
-int s2n_pkey_size(const struct s2n_pkey *pkey)
+S2N_RESULT s2n_pkey_size(const struct s2n_pkey *pkey, uint32_t *size_out)
{
- notnull_check(pkey->size);
+ ENSURE_REF(pkey);
+ ENSURE_REF(pkey->size);
+ ENSURE_REF(size_out);
+
+ GUARD_RESULT(pkey->size(pkey, size_out));
- return pkey->size(pkey);
+ return S2N_RESULT_OK;
}
int s2n_pkey_sign(const struct s2n_pkey *pkey, s2n_signature_algorithm sig_alg,
@@ -185,10 +192,10 @@ int s2n_asn1der_to_public_key_and_type(struct s2n_pkey *pub_key, s2n_pkey_type *
/* If cert parsing is successful, d2i_X509 increments *cert_to_parse to the byte following the parsed data */
uint32_t parsed_len = cert_to_parse - asn1der->data;
- /* Some TLS clients in the wild send one extra trailing byte after the Certificate.
+ /* Some TLS clients in the wild send extra trailing bytes after the Certificate.
* Allow this in s2n for backwards compatibility with existing clients. */
uint32_t trailing_bytes = asn1der->size - parsed_len;
- ENSURE_POSIX(trailing_bytes <= 1, S2N_ERR_DECODE_CERTIFICATE);
+ ENSURE_POSIX(trailing_bytes <= S2N_MAX_ALLOWED_CERT_TRAILING_BYTES, S2N_ERR_DECODE_CERTIFICATE);
DEFER_CLEANUP(EVP_PKEY *evp_public_key = X509_get_pubkey(cert), EVP_PKEY_free_pointer);
S2N_ERROR_IF(evp_public_key == NULL, S2N_ERR_DECODE_CERTIFICATE);
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_pkey.h b/contrib/restricted/aws/s2n/crypto/s2n_pkey.h
index 1da8f785c6..0edc9f662e 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_pkey.h
+++ b/contrib/restricted/aws/s2n/crypto/s2n_pkey.h
@@ -23,6 +23,7 @@
#include "crypto/s2n_rsa.h"
#include "utils/s2n_blob.h"
+#include "utils/s2n_result.h"
/* Public/Private Key Type */
typedef enum {
@@ -43,7 +44,7 @@ struct s2n_pkey {
} key;
EVP_PKEY *pkey;
- int (*size)(const struct s2n_pkey *key);
+ S2N_RESULT (*size)(const struct s2n_pkey *key, uint32_t *size_out);
int (*sign)(const struct s2n_pkey *priv_key, s2n_signature_algorithm sig_alg,
struct s2n_hash_state *digest, struct s2n_blob *signature);
int (*verify)(const struct s2n_pkey *pub_key, s2n_signature_algorithm sig_alg,
@@ -59,7 +60,7 @@ int s2n_pkey_zero_init(struct s2n_pkey *pkey);
int s2n_pkey_setup_for_type(struct s2n_pkey *pkey, s2n_pkey_type pkey_type);
int s2n_pkey_check_key_exists(const struct s2n_pkey *pkey);
-int s2n_pkey_size(const struct s2n_pkey *pkey);
+S2N_RESULT s2n_pkey_size(const struct s2n_pkey *pkey, uint32_t *size_out);
int s2n_pkey_sign(const struct s2n_pkey *pkey, s2n_signature_algorithm sig_alg,
struct s2n_hash_state *digest, struct s2n_blob *signature);
int s2n_pkey_verify(const struct s2n_pkey *pkey, s2n_signature_algorithm sig_alg,
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_rsa.c b/contrib/restricted/aws/s2n/crypto/s2n_rsa.c
index 38eba11e0b..cfce3054bf 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_rsa.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_rsa.c
@@ -13,51 +13,57 @@
* permissions and limitations under the License.
*/
+#include "crypto/s2n_rsa.h"
+
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <stdint.h>
-#include "error/s2n_errno.h"
-
-#include "stuffer/s2n_stuffer.h"
-
-#include "crypto/s2n_hash.h"
#include "crypto/s2n_drbg.h"
-#include "crypto/s2n_rsa.h"
-#include "crypto/s2n_rsa_signing.h"
+#include "crypto/s2n_hash.h"
#include "crypto/s2n_pkey.h"
-
-#include "utils/s2n_safety.h"
-#include "utils/s2n_random.h"
+#include "crypto/s2n_rsa_signing.h"
+#include "error/s2n_errno.h"
+#include "stuffer/s2n_stuffer.h"
#include "utils/s2n_blob.h"
+#include "utils/s2n_random.h"
+#include "utils/s2n_result.h"
+#include "utils/s2n_safety.h"
-static int s2n_rsa_modulus_check(RSA *rsa)
+static S2N_RESULT s2n_rsa_modulus_check(RSA *rsa)
{
- /* RSA was made opaque starting in Openssl 1.1.0 */
- #if S2N_OPENSSL_VERSION_AT_LEAST(1,1,0) && !defined(LIBRESSL_VERSION_NUMBER)
- const BIGNUM *n = NULL;
- /* RSA still owns the memory for n */
- RSA_get0_key(rsa, &n, NULL, NULL);
- notnull_check(n);
- #else
- notnull_check(rsa->n);
- #endif
- return 0;
+/* RSA was made opaque starting in Openssl 1.1.0 */
+#if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0) && !defined(LIBRESSL_VERSION_NUMBER)
+ const BIGNUM *n = NULL;
+ /* RSA still owns the memory for n */
+ RSA_get0_key(rsa, &n, NULL, NULL);
+ ENSURE_REF(n);
+#else
+ ENSURE_REF(rsa->n);
+#endif
+ return S2N_RESULT_OK;
}
-static int s2n_rsa_encrypted_size(const struct s2n_pkey *key)
+static S2N_RESULT s2n_rsa_encrypted_size(const struct s2n_pkey *key, uint32_t *size_out)
{
+ ENSURE_REF(key);
+ ENSURE_REF(size_out);
+
const struct s2n_rsa_key *rsa_key = &key->key.rsa_key;
- notnull_check(rsa_key->rsa);
- GUARD(s2n_rsa_modulus_check(rsa_key->rsa));
+ ENSURE_REF(rsa_key->rsa);
+ GUARD_RESULT(s2n_rsa_modulus_check(rsa_key->rsa));
- return RSA_size(rsa_key->rsa);
+ const int size = RSA_size(rsa_key->rsa);
+ GUARD_AS_RESULT(size);
+ *size_out = size;
+
+ return S2N_RESULT_OK;
}
-static int s2n_rsa_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig_alg,
- struct s2n_hash_state *digest, struct s2n_blob *signature)
+static int s2n_rsa_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig_alg, struct s2n_hash_state *digest,
+ struct s2n_blob *signature)
{
- switch(sig_alg) {
+ switch (sig_alg) {
case S2N_SIGNATURE_RSA:
return s2n_rsa_pkcs1v15_sign(priv, digest, signature);
case S2N_SIGNATURE_RSA_PSS_RSAE:
@@ -69,10 +75,10 @@ static int s2n_rsa_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig
return S2N_SUCCESS;
}
-static int s2n_rsa_verify(const struct s2n_pkey *pub, s2n_signature_algorithm sig_alg,
- struct s2n_hash_state *digest, struct s2n_blob *signature)
+static int s2n_rsa_verify(const struct s2n_pkey *pub, s2n_signature_algorithm sig_alg, struct s2n_hash_state *digest,
+ struct s2n_blob *signature)
{
- switch(sig_alg) {
+ switch (sig_alg) {
case S2N_SIGNATURE_RSA:
return s2n_rsa_pkcs1v15_verify(pub, digest, signature);
case S2N_SIGNATURE_RSA_PSS_RSAE:
@@ -86,10 +92,13 @@ static int s2n_rsa_verify(const struct s2n_pkey *pub, s2n_signature_algorithm si
static int s2n_rsa_encrypt(const struct s2n_pkey *pub, struct s2n_blob *in, struct s2n_blob *out)
{
- S2N_ERROR_IF(out->size < s2n_rsa_encrypted_size(pub), S2N_ERR_NOMEM);
+ uint32_t size = 0;
+ GUARD_AS_POSIX(s2n_rsa_encrypted_size(pub, &size));
+ S2N_ERROR_IF(out->size < size, S2N_ERR_NOMEM);
const s2n_rsa_public_key *key = &pub->key.rsa_key;
- int r = RSA_public_encrypt(in->size, (unsigned char *)in->data, (unsigned char *)out->data, key->rsa, RSA_PKCS1_PADDING);
+ int r = RSA_public_encrypt(in->size, ( unsigned char * )in->data, ( unsigned char * )out->data, key->rsa,
+ RSA_PKCS1_PADDING);
S2N_ERROR_IF(r != out->size, S2N_ERR_SIZE_MISMATCH);
return 0;
@@ -97,17 +106,18 @@ static int s2n_rsa_encrypt(const struct s2n_pkey *pub, struct s2n_blob *in, stru
static int s2n_rsa_decrypt(const struct s2n_pkey *priv, struct s2n_blob *in, struct s2n_blob *out)
{
- unsigned char intermediate[4096];
- const int expected_size = s2n_rsa_encrypted_size(priv);
+ unsigned char intermediate[ 4096 ];
+ uint32_t expected_size = 0;
+
+ GUARD_AS_POSIX(s2n_rsa_encrypted_size(priv, &expected_size));
- GUARD(expected_size);
S2N_ERROR_IF(expected_size > sizeof(intermediate), S2N_ERR_NOMEM);
S2N_ERROR_IF(out->size > sizeof(intermediate), S2N_ERR_NOMEM);
GUARD_AS_POSIX(s2n_get_public_random_data(out));
const s2n_rsa_private_key *key = &priv->key.rsa_key;
- int r = RSA_private_decrypt(in->size, (unsigned char *)in->data, intermediate, key->rsa, RSA_NO_PADDING);
+ int r = RSA_private_decrypt(in->size, ( unsigned char * )in->data, intermediate, key->rsa, RSA_NO_PADDING);
S2N_ERROR_IF(r != expected_size, S2N_ERR_SIZE_MISMATCH);
s2n_constant_time_pkcs1_unpad_or_dont(out->data, intermediate, r, out->size);
@@ -117,14 +127,14 @@ static int s2n_rsa_decrypt(const struct s2n_pkey *priv, struct s2n_blob *in, str
static int s2n_rsa_keys_match(const struct s2n_pkey *pub, const struct s2n_pkey *priv)
{
- uint8_t plain_inpad[36] = {1}, plain_outpad[36] = {0}, encpad[8192];
+ uint8_t plain_inpad[ 36 ] = { 1 }, plain_outpad[ 36 ] = { 0 }, encpad[ 8192 ];
struct s2n_blob plain_in = { 0 }, plain_out = { 0 }, enc = { 0 };
plain_in.data = plain_inpad;
plain_in.size = sizeof(plain_inpad);
enc.data = encpad;
- enc.size = s2n_rsa_encrypted_size(pub);
+ GUARD_AS_POSIX(s2n_rsa_encrypted_size(pub, &enc.size));
lte_check(enc.size, sizeof(encpad));
GUARD(s2n_rsa_encrypt(pub, &plain_in, &enc));
@@ -140,9 +150,7 @@ static int s2n_rsa_keys_match(const struct s2n_pkey *pub, const struct s2n_pkey
static int s2n_rsa_key_free(struct s2n_pkey *pkey)
{
struct s2n_rsa_key *rsa_key = &pkey->key.rsa_key;
- if (rsa_key->rsa == NULL) {
- return 0;
- }
+ if (rsa_key->rsa == NULL) { return 0; }
RSA_free(rsa_key->rsa);
rsa_key->rsa = NULL;
@@ -177,13 +185,13 @@ int s2n_evp_pkey_to_rsa_private_key(s2n_rsa_private_key *rsa_key, EVP_PKEY *evp_
int s2n_rsa_pkey_init(struct s2n_pkey *pkey)
{
- pkey->size = &s2n_rsa_encrypted_size;
- pkey->sign = &s2n_rsa_sign;
- pkey->verify = &s2n_rsa_verify;
- pkey->encrypt = &s2n_rsa_encrypt;
- pkey->decrypt = &s2n_rsa_decrypt;
- pkey->match = &s2n_rsa_keys_match;
- pkey->free = &s2n_rsa_key_free;
+ pkey->size = &s2n_rsa_encrypted_size;
+ pkey->sign = &s2n_rsa_sign;
+ pkey->verify = &s2n_rsa_verify;
+ pkey->encrypt = &s2n_rsa_encrypt;
+ pkey->decrypt = &s2n_rsa_decrypt;
+ pkey->match = &s2n_rsa_keys_match;
+ pkey->free = &s2n_rsa_key_free;
pkey->check_key = &s2n_rsa_check_key_exists;
return 0;
}
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c b/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c
index 1bb444b25c..98fbd6ad23 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_rsa_pss.c
@@ -41,12 +41,17 @@ int s2n_is_rsa_pss_certs_supported()
#if RSA_PSS_CERTS_SUPPORTED
-static int s2n_rsa_pss_size(const struct s2n_pkey *key)
+static S2N_RESULT s2n_rsa_pss_size(const struct s2n_pkey *key, uint32_t *size_out)
{
- notnull_check(key);
+ ENSURE_REF(key);
+ ENSURE_REF(size_out);
/* For more info, see: https://www.openssl.org/docs/man1.1.0/man3/EVP_PKEY_size.html */
- return EVP_PKEY_size(key->pkey);
+ const int size = EVP_PKEY_size(key->pkey);
+ GUARD_AS_RESULT(size);
+ *size_out = size;
+
+ return S2N_RESULT_OK;
}
static int s2n_rsa_is_private_key(RSA *rsa_key)
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c
index 978ce2431e..1b472937ad 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c
+++ b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.c
@@ -41,7 +41,7 @@
* [x] client_application_traffic_secret_0
* [x] server_application_traffic_secret_0
* [ ] exporter_master_secret
- * [ ] resumption_master_secret
+ * [x] resumption_master_secret
*
* The TLS 1.3 key generation can be divided into 3 phases
* 1. early secrets
@@ -74,6 +74,7 @@ S2N_BLOB_LABEL(s2n_tls13_label_server_application_traffic_secret, "s ap traffic"
S2N_BLOB_LABEL(s2n_tls13_label_exporter_master_secret, "exp master")
S2N_BLOB_LABEL(s2n_tls13_label_resumption_master_secret, "res master")
+S2N_BLOB_LABEL(s2n_tls13_label_session_ticket_secret, "resumption")
/*
* Traffic secret labels
@@ -172,14 +173,21 @@ int s2n_tls13_derive_binder_key(struct s2n_tls13_keys *keys, struct s2n_psk *psk
/*
* Derives early secrets
*/
-int s2n_tls13_derive_early_secrets(struct s2n_tls13_keys *keys)
+int s2n_tls13_derive_early_secrets(struct s2n_tls13_keys *keys, struct s2n_psk *psk)
{
notnull_check(keys);
- s2n_tls13_key_blob(psk_ikm, keys->size); /* in 1-RTT, PSK is 0-filled of key length */
-
/* Early Secret */
- GUARD(s2n_hkdf_extract(&keys->hmac, keys->hmac_algorithm, &zero_length_blob, &psk_ikm, &keys->extract_secret));
+ if (psk == NULL) {
+ /* in 1-RTT, PSK is 0-filled of key length */
+ s2n_tls13_key_blob(psk_ikm, keys->size);
+
+ GUARD(s2n_hkdf_extract(&keys->hmac, keys->hmac_algorithm, &zero_length_blob, &psk_ikm, &keys->extract_secret));
+ } else {
+ /* Sanity check that an early secret exists */
+ ne_check(psk->early_secret.size, 0);
+ keys->extract_secret = psk->early_secret;
+ }
/* client_early_traffic_secret and early_exporter_master_secret can be derived here */
@@ -189,7 +197,7 @@ int s2n_tls13_derive_early_secrets(struct s2n_tls13_keys *keys)
GUARD(s2n_hkdf_expand_label(&keys->hmac, keys->hmac_algorithm, &keys->extract_secret,
&s2n_tls13_label_derived_secret, &message_digest, &keys->derive_secret));
- return 0;
+ return S2N_SUCCESS;
}
/*
@@ -336,3 +344,42 @@ int s2n_tls13_update_application_traffic_secret(struct s2n_tls13_keys *keys, str
return 0;
}
+
+int s2n_tls13_derive_resumption_master_secret(struct s2n_tls13_keys *keys, struct s2n_hash_state *hashes, struct s2n_blob *secret_blob)
+{
+ notnull_check(keys);
+ notnull_check(hashes);
+ notnull_check(secret_blob);
+
+ /* Sanity check that input hash is of expected type */
+ ENSURE_POSIX(keys->hash_algorithm == hashes->alg, S2N_ERR_HASH_INVALID_ALGORITHM);
+
+ s2n_tls13_key_blob(message_digest, keys->size);
+
+ /* Copy the hashes into the message_digest */
+ DEFER_CLEANUP(struct s2n_hash_state hkdf_hash_copy, s2n_hash_free);
+ GUARD(s2n_hash_new(&hkdf_hash_copy));
+ GUARD(s2n_hash_copy(&hkdf_hash_copy, hashes));
+ GUARD(s2n_hash_digest(&hkdf_hash_copy, message_digest.data, message_digest.size));
+
+ /* Derive master session resumption from master secret */
+ GUARD(s2n_hkdf_expand_label(&keys->hmac, keys->hmac_algorithm, &keys->extract_secret,
+ &s2n_tls13_label_resumption_master_secret, &message_digest, secret_blob));
+
+ return S2N_SUCCESS;
+}
+
+S2N_RESULT s2n_tls13_derive_session_ticket_secret(struct s2n_tls13_keys *keys, struct s2n_blob *resumption_secret,
+ struct s2n_blob *ticket_nonce, struct s2n_blob *secret_blob)
+{
+ ENSURE_REF(keys);
+ ENSURE_REF(resumption_secret);
+ ENSURE_REF(ticket_nonce);
+ ENSURE_REF(secret_blob);
+
+ /* Derive session ticket secret from master session resumption secret */
+ GUARD_AS_RESULT(s2n_hkdf_expand_label(&keys->hmac, keys->hmac_algorithm, resumption_secret,
+ &s2n_tls13_label_session_ticket_secret, ticket_nonce, secret_blob));
+
+ return S2N_RESULT_OK;
+}
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h
index c572f6edfd..cf4e6185f4 100644
--- a/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h
+++ b/contrib/restricted/aws/s2n/crypto/s2n_tls13_keys.h
@@ -74,7 +74,7 @@ extern const struct s2n_blob s2n_tls13_label_traffic_secret_iv;
int s2n_tls13_keys_init(struct s2n_tls13_keys *handshake, s2n_hmac_algorithm alg);
int s2n_tls13_keys_free(struct s2n_tls13_keys *keys);
int s2n_tls13_derive_binder_key(struct s2n_tls13_keys *keys, struct s2n_psk *psk);
-int s2n_tls13_derive_early_secrets(struct s2n_tls13_keys *handshake);
+int s2n_tls13_derive_early_secrets(struct s2n_tls13_keys *handshake, struct s2n_psk *psk);
int s2n_tls13_derive_handshake_secrets(struct s2n_tls13_keys *handshake,
const struct s2n_blob *ecdhe,
struct s2n_hash_state *client_server_hello_hash,
@@ -87,3 +87,7 @@ int s2n_tls13_derive_traffic_keys(struct s2n_tls13_keys *handshake, struct s2n_b
int s2n_tls13_derive_finished_key(struct s2n_tls13_keys *keys, struct s2n_blob *secret_key, struct s2n_blob *output_finish_key);
int s2n_tls13_calculate_finished_mac(struct s2n_tls13_keys *keys, struct s2n_blob *finished_key, struct s2n_hash_state *hash_state, struct s2n_blob *finished_verify);
int s2n_tls13_update_application_traffic_secret(struct s2n_tls13_keys *keys, struct s2n_blob *old_secret, struct s2n_blob *new_secret);
+
+int s2n_tls13_derive_resumption_master_secret(struct s2n_tls13_keys *keys, struct s2n_hash_state *hashes, struct s2n_blob *secret_blob);
+S2N_RESULT s2n_tls13_derive_session_ticket_secret(struct s2n_tls13_keys *keys, struct s2n_blob *resumption_secret,
+ struct s2n_blob *ticket_nonce, struct s2n_blob *secret_blob);
diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.c b/contrib/restricted/aws/s2n/error/s2n_errno.c
index 14c5450d96..1fcc1b6634 100644
--- a/contrib/restricted/aws/s2n/error/s2n_errno.c
+++ b/contrib/restricted/aws/s2n/error/s2n_errno.c
@@ -31,6 +31,14 @@
__thread int s2n_errno;
__thread const char *s2n_debug_str;
+/**
+ * Returns the address of the thread-local `s2n_errno` variable
+ */
+int *s2n_errno_location()
+{
+ return &s2n_errno;
+}
+
static const char *no_such_language = "Language is not supported for error translation";
static const char *no_such_error = "Internal s2n error";
@@ -215,7 +223,6 @@ static const char *no_such_error = "Internal s2n error";
ERR_ENTRY(S2N_ERR_SESSION_TICKET_NOT_SUPPORTED, "Session ticket not supported for this connection") \
ERR_ENTRY(S2N_ERR_OCSP_NOT_SUPPORTED, "OCSP stapling was requested, but is not supported") \
ERR_ENTRY(S2N_ERR_INVALID_SIGNATURE_ALGORITHMS_PREFERENCES, "Invalid signature algorithms preferences version") \
- ERR_ENTRY(S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS, "PQ KEMs are disallowed while in FIPS mode") \
ERR_ENTRY(S2N_RSA_PSS_NOT_SUPPORTED, "RSA-PSS signing not supported by underlying libcrypto implementation") \
ERR_ENTRY(S2N_ERR_MAX_INNER_PLAINTEXT_SIZE, "Inner plaintext size exceeds limit") \
ERR_ENTRY(S2N_ERR_INVALID_ECC_PREFERENCES, "Invalid ecc curves preferences version") \
@@ -235,9 +242,12 @@ static const char *no_such_error = "Internal s2n error";
ERR_ENTRY(S2N_ERR_ASYNC_APPLY_WHILE_INVOKING, "Async private key operation cannot consumed inside async pkey callback") \
ERR_ENTRY(S2N_ERR_ASYNC_ALREADY_APPLIED, "Async operation was already applied to connection, cannot apply it again") \
ERR_ENTRY(S2N_ERR_INVALID_HELLO_RETRY, "Invalid hello retry request") \
- ERR_ENTRY(S2N_ERR_INVALID_STATE, "Invalid state, this is the result of invalid use of an API. Check the API documentation for the function that raised this error for more info.") \
+ ERR_ENTRY(S2N_ERR_INVALID_STATE, "Invalid state, this is the result of invalid use of an API. Check the API documentation for the function that raised this error for more info") \
ERR_ENTRY(S2N_ERR_UNSUPPORTED_WITH_QUIC, "Functionality not supported when running with QUIC support enabled") \
- ERR_ENTRY(S2N_ERR_PQ_CRYPTO, "An error occurred in a post-quantum crypto function.") \
+ ERR_ENTRY(S2N_ERR_PQ_CRYPTO, "An error occurred in a post-quantum crypto function") \
+ ERR_ENTRY(S2N_ERR_PQ_DISABLED, "Post-quantum crypto is disabled") \
+ ERR_ENTRY(S2N_ERR_DUPLICATE_PSK_IDENTITIES, "The list of pre-shared keys provided contains duplicate psk identities") \
+ ERR_ENTRY(S2N_ERR_REENTRANCY, "Original execution must complete before method can be called again") \
/* clang-format on */
diff --git a/contrib/restricted/aws/s2n/error/s2n_errno.h b/contrib/restricted/aws/s2n/error/s2n_errno.h
index 9151feabd3..1c5afb8f2b 100644
--- a/contrib/restricted/aws/s2n/error/s2n_errno.h
+++ b/contrib/restricted/aws/s2n/error/s2n_errno.h
@@ -111,7 +111,6 @@ typedef enum {
S2N_ERR_BAD_KEY_SHARE,
S2N_ERR_CANCELLED,
S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED,
- S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS,
S2N_ERR_MAX_INNER_PLAINTEXT_SIZE,
S2N_ERR_RECORD_STUFFER_SIZE,
S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE,
@@ -200,6 +199,7 @@ typedef enum {
S2N_ERR_ASYNC_MORE_THAN_ONE,
S2N_ERR_INVALID_STATE,
S2N_ERR_PQ_CRYPTO,
+ S2N_ERR_PQ_DISABLED,
S2N_ERR_T_INTERNAL_END,
/* S2N_ERR_T_USAGE */
@@ -261,6 +261,8 @@ typedef enum {
S2N_ERR_ASYNC_APPLY_WHILE_INVOKING,
S2N_ERR_ASYNC_ALREADY_APPLIED,
S2N_ERR_UNSUPPORTED_WITH_QUIC,
+ S2N_ERR_DUPLICATE_PSK_IDENTITIES,
+ S2N_ERR_REENTRANCY,
S2N_ERR_T_USAGE_END,
} s2n_error;
diff --git a/contrib/restricted/aws/s2n/pq-crypto/bike_r1/bike_r1_kem.c b/contrib/restricted/aws/s2n/pq-crypto/bike_r1/bike_r1_kem.c
index cb566d7435..21b0b6f5a3 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/bike_r1/bike_r1_kem.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/bike_r1/bike_r1_kem.c
@@ -13,6 +13,7 @@
#include "parallel_hash.h"
#include "sampling.h"
#include "tls/s2n_kem.h"
+#include "pq-crypto/s2n_pq.h"
_INLINE_ void
split_e(OUT split_e_t *splitted_e, IN const e_t *e)
@@ -155,6 +156,8 @@ get_ss(OUT ss_t *out, IN const e_t *e)
int
BIKE1_L1_R1_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk)
{
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
+
// Convert to this implementation types
pk_t *l_pk = (pk_t *)pk;
@@ -211,6 +214,7 @@ BIKE1_L1_R1_crypto_kem_enc(OUT unsigned char * ct,
IN const unsigned char *pk)
{
DMSG(" Enter crypto_kem_enc.\n");
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
// Convert to this implementation types
const pk_t *l_pk = (const pk_t *)pk;
@@ -265,6 +269,7 @@ BIKE1_L1_R1_crypto_kem_dec(OUT unsigned char * ss,
IN const unsigned char *sk)
{
DMSG(" Enter crypto_kem_dec.\n");
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
// Convert to this implementation types
const ct_t *l_ct = (const ct_t *)ct;
diff --git a/contrib/restricted/aws/s2n/pq-crypto/bike_r2/bike_r2_kem.c b/contrib/restricted/aws/s2n/pq-crypto/bike_r2/bike_r2_kem.c
index 3539827d14..8f29f3add9 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/bike_r2/bike_r2_kem.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/bike_r2/bike_r2_kem.c
@@ -11,6 +11,7 @@
#include "sampling.h"
#include "sha.h"
#include "tls/s2n_kem.h"
+#include "pq-crypto/s2n_pq.h"
_INLINE_ void
split_e(OUT split_e_t *splitted_e, IN const e_t *e)
@@ -211,6 +212,8 @@ get_ss(OUT ss_t *out, IN const r_t *in0, IN const r_t *in1, IN const ct_t *ct)
int
BIKE1_L1_R2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk)
{
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
+
notnull_check(sk);
notnull_check(pk);
@@ -283,6 +286,7 @@ BIKE1_L1_R2_crypto_kem_enc(OUT unsigned char * ct,
IN const unsigned char *pk)
{
DMSG(" Enter crypto_kem_enc.\n");
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
// Convert to the types that are used by this implementation
const pk_t *l_pk = (const pk_t *)pk;
@@ -323,6 +327,7 @@ BIKE1_L1_R2_crypto_kem_dec(OUT unsigned char * ss,
IN const unsigned char *sk)
{
DMSG(" Enter crypto_kem_dec.\n");
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
// Convert to the types used by this implementation
const ct_t *l_ct = (const ct_t *)ct;
diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_90s_r2/kyber_90s_r2_kem.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_90s_r2/kyber_90s_r2_kem.c
index ff28dd0351..9de3c1daef 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/kyber_90s_r2/kyber_90s_r2_kem.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_90s_r2/kyber_90s_r2_kem.c
@@ -6,6 +6,7 @@
#include "../s2n_pq_random.h"
#include "utils/s2n_safety.h"
#include "tls/s2n_kem.h"
+#include "pq-crypto/s2n_pq.h"
#include <stdlib.h>
@@ -21,6 +22,7 @@
* Returns 0 (success)
**************************************************/
int kyber_512_90s_r2_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
size_t i;
PQCLEAN_KYBER51290S_CLEAN_indcpa_keypair(pk, sk);
for (i = 0; i < KYBER_INDCPA_PUBLICKEYBYTES; i++) {
@@ -44,6 +46,7 @@ int kyber_512_90s_r2_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
* Returns 0 (success)
**************************************************/
int kyber_512_90s_r2_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
uint8_t kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */
uint8_t buf[2 * KYBER_SYMBYTES];
@@ -75,6 +78,7 @@ int kyber_512_90s_r2_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk)
* On failure, ss will contain a pseudo-random value.
**************************************************/
int kyber_512_90s_r2_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
size_t i;
uint8_t fail;
uint8_t cmp[KYBER_CIPHERTEXTBYTES];
diff --git a/contrib/restricted/aws/s2n/pq-crypto/kyber_r2/kyber_r2_kem.c b/contrib/restricted/aws/s2n/pq-crypto/kyber_r2/kyber_r2_kem.c
index d9b64d4336..9871084bb4 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/kyber_r2/kyber_r2_kem.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/kyber_r2/kyber_r2_kem.c
@@ -6,6 +6,7 @@
#include "../s2n_pq_random.h"
#include "utils/s2n_safety.h"
#include "tls/s2n_kem.h"
+#include "pq-crypto/s2n_pq.h"
#include <stdlib.h>
@@ -21,6 +22,7 @@
* Returns 0 (success)
**************************************************/
int kyber_512_r2_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
size_t i;
PQCLEAN_KYBER512_CLEAN_indcpa_keypair(pk, sk);
for (i = 0; i < KYBER_INDCPA_PUBLICKEYBYTES; i++) {
@@ -44,6 +46,7 @@ int kyber_512_r2_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
* Returns 0 (success)
**************************************************/
int kyber_512_r2_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
uint8_t kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */
uint8_t buf[2 * KYBER_SYMBYTES];
@@ -75,6 +78,7 @@ int kyber_512_r2_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) {
* On failure, ss will contain a pseudo-random value.
**************************************************/
int kyber_512_r2_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) {
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
size_t i;
uint8_t fail;
uint8_t cmp[KYBER_CIPHERTEXTBYTES];
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c
index 858676fe67..3122eb6539 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r1/sike_r1_kem.c
@@ -10,11 +10,13 @@
#include "pq-crypto/s2n_pq_random.h"
#include "utils/s2n_safety.h"
#include "tls/s2n_kem.h"
+#include "pq-crypto/s2n_pq.h"
int SIKE_P503_r1_crypto_kem_keypair(unsigned char *pk, unsigned char *sk)
{ // SIKE's key generation
// Outputs: secret key sk (SIKE_P503_R1_SECRET_KEY_BYTES = MSG_BYTES + SECRETKEY_B_BYTES + SIKE_P503_R1_PUBLIC_KEY_BYTES bytes)
// public key pk (SIKE_P503_R1_PUBLIC_KEY_BYTES bytes)
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
digit_t _sk[SECRETKEY_B_BYTES/sizeof(digit_t)];
@@ -38,6 +40,8 @@ int SIKE_P503_r1_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsi
// Input: public key pk (SIKE_P503_R1_PUBLIC_KEY_BYTES bytes)
// Outputs: shared secret ss (SIKE_P503_R1_SHARED_SECRET_BYTES bytes)
// ciphertext message ct (SIKE_P503_R1_CIPHERTEXT_BYTES = SIKE_P503_R1_PUBLIC_KEY_BYTES + MSG_BYTES bytes)
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
+
const uint16_t G = 0;
const uint16_t H = 1;
const uint16_t P = 2;
@@ -78,6 +82,8 @@ int SIKE_P503_r1_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, cons
// Input: secret key sk (SIKE_P503_R1_SECRET_KEY_BYTES = MSG_BYTES + SECRETKEY_B_BYTES + SIKE_P503_R1_PUBLIC_KEY_BYTES bytes)
// ciphertext message ct (SIKE_P503_R1_CIPHERTEXT_BYTES = SIKE_P503_R1_PUBLIC_KEY_BYTES + MSG_BYTES bytes)
// Outputs: shared secret ss (SIKE_P503_R1_SHARED_SECRET_BYTES bytes)
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
+
const uint16_t G = 0;
const uint16_t H = 1;
const uint16_t P = 2;
diff --git a/contrib/restricted/aws/s2n/pq-crypto/sike_r2/sike_r2_kem.c b/contrib/restricted/aws/s2n/pq-crypto/sike_r2/sike_r2_kem.c
index 453e3b4690..7768ad3650 100644
--- a/contrib/restricted/aws/s2n/pq-crypto/sike_r2/sike_r2_kem.c
+++ b/contrib/restricted/aws/s2n/pq-crypto/sike_r2/sike_r2_kem.c
@@ -9,11 +9,13 @@
#include "fips202.h"
#include "utils/s2n_safety.h"
#include "tls/s2n_kem.h"
+#include "pq-crypto/s2n_pq.h"
int SIKE_P434_r2_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) {
// SIKE's key generation
// Outputs: secret key sk (CRYPTO_SECRETKEYBYTES = MSG_BYTES + SECRETKEY_B_BYTES + CRYPTO_PUBLICKEYBYTES bytes)
// public key pk (CRYPTO_PUBLICKEYBYTES bytes)
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
digit_t _sk[(SECRETKEY_B_BYTES / sizeof(digit_t)) + 1];
@@ -37,6 +39,7 @@ int SIKE_P434_r2_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsi
// Input: public key pk (CRYPTO_PUBLICKEYBYTES bytes)
// Outputs: shared secret ss (CRYPTO_BYTES bytes)
// ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = CRYPTO_PUBLICKEYBYTES + MSG_BYTES bytes)
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
union {
unsigned char b[SECRETKEY_A_BYTES];
@@ -75,6 +78,7 @@ int SIKE_P434_r2_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, cons
// Input: secret key sk (CRYPTO_SECRETKEYBYTES = MSG_BYTES + SECRETKEY_B_BYTES + CRYPTO_PUBLICKEYBYTES bytes)
// ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = CRYPTO_PUBLICKEYBYTES + MSG_BYTES bytes)
// Outputs: shared secret ss (CRYPTO_BYTES bytes)
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
union {
unsigned char b[SECRETKEY_A_BYTES];
diff --git a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_network_order.c b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_network_order.c
index f30c10e82f..eb75409b6a 100644
--- a/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_network_order.c
+++ b/contrib/restricted/aws/s2n/stuffer/s2n_stuffer_network_order.c
@@ -28,7 +28,7 @@ int s2n_stuffer_write_network_order(struct s2n_stuffer *stuffer, const uint64_t
uint8_t *data = stuffer->blob.data + stuffer->write_cursor - length;
for (int i = 0; i < length; i++) {
- S2N_INVARIENT(i <= length);
+ S2N_INVARIANT(i <= length);
uint8_t shift = (length - i - 1) * CHAR_BIT;
data[i] = (input >> (shift)) & UINT8_MAX;
}
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 97797cc054..178f2e9c1d 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
@@ -22,7 +22,7 @@
#include "stuffer/s2n_stuffer.h"
#include "utils/s2n_safety.h"
#include "tls/s2n_tls13.h"
-#include "crypto/s2n_fips.h"
+#include "pq-crypto/s2n_pq.h"
#define S2N_IS_KEY_SHARE_LIST_EMPTY(preferred_key_shares) (preferred_key_shares & 1)
#define S2N_IS_KEY_SHARE_REQUESTED(preferred_key_shares, i) ((preferred_key_shares >> (i + 1)) & 1)
@@ -107,8 +107,8 @@ static int s2n_generate_pq_hybrid_key_share(struct s2n_stuffer *out, struct s2n_
notnull_check(out);
notnull_check(kem_group_params);
- /* This function should never be called when in FIPS mode */
- ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
+ /* This function should never be called when PQ is disabled */
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
const struct s2n_kem_group *kem_group = kem_group_params->kem_group;
notnull_check(kem_group);
@@ -144,8 +144,8 @@ static int s2n_generate_default_pq_hybrid_key_share(struct s2n_connection *conn,
notnull_check(conn);
notnull_check(out);
- /* Client should skip sending PQ groups/key shares if in FIPS mode */
- if (s2n_is_in_fips_mode()) {
+ /* Client should skip sending PQ groups/key shares if PQ is disabled */
+ if (!s2n_pq_is_enabled()) {
return S2N_SUCCESS;
}
@@ -227,9 +227,9 @@ static int s2n_send_hrr_pq_hybrid_keyshare(struct s2n_connection *conn, struct s
notnull_check(conn);
notnull_check(out);
- /* If in FIPS mode, the client should not have sent any PQ IDs
+ /* If PQ is disabled, the client should not have sent any PQ IDs
* in the supported_groups list of the initial ClientHello */
- ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
const struct s2n_kem_preferences *kem_pref = NULL;
GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
@@ -377,7 +377,10 @@ static int s2n_client_key_share_recv_pq_hybrid(struct s2n_connection *conn, stru
GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
notnull_check(kem_pref);
- ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
+ /* Ignore key share if PQ is not enabled */
+ if (!s2n_pq_is_enabled()) {
+ return S2N_SUCCESS;
+ }
const struct s2n_kem_group *kem_group = NULL;
struct s2n_kem_group_params *client_kem_group_params = NULL;
@@ -476,9 +479,7 @@ static int s2n_client_key_share_recv(struct s2n_connection *conn, struct s2n_stu
/* Try to parse the share as ECC, then as PQ/hybrid; will ignore
* shares for unrecognized groups. */
GUARD(s2n_client_key_share_recv_ecc(conn, &key_share, named_group, &match_found));
- if (!s2n_is_in_fips_mode()) {
- GUARD(s2n_client_key_share_recv_pq_hybrid(conn, &key_share, named_group, &match_found));
- }
+ GUARD(s2n_client_key_share_recv_pq_hybrid(conn, &key_share, named_group, &match_found));
}
/* If there were no matching key shares, then we received an empty key share extension
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c
index 450e293299..83c4c8f1d0 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c
@@ -21,6 +21,7 @@
#include "tls/s2n_security_policies.h"
#include "tls/s2n_tls.h"
#include "tls/s2n_tls_parameters.h"
+#include "pq-crypto/s2n_pq.h"
#include "utils/s2n_safety.h"
@@ -41,7 +42,8 @@ static bool s2n_client_pq_kem_should_send(struct s2n_connection *conn)
{
const struct s2n_security_policy *security_policy;
return s2n_connection_get_security_policy(conn, &security_policy) == S2N_SUCCESS
- && s2n_pq_kem_is_extension_required(security_policy);
+ && s2n_pq_kem_is_extension_required(security_policy)
+ && s2n_pq_is_enabled();
}
static int s2n_client_pq_kem_send(struct s2n_connection *conn, struct s2n_stuffer *out)
@@ -63,6 +65,11 @@ static int s2n_client_pq_kem_recv(struct s2n_connection *conn, struct s2n_stuffe
uint16_t size_of_all;
struct s2n_blob *proposed_kems = &conn->secure.client_pq_kem_extension;
+ /* Ignore extension if PQ is disabled */
+ if (!s2n_pq_is_enabled()) {
+ return S2N_SUCCESS;
+ }
+
GUARD(s2n_stuffer_read_uint16(extension, &size_of_all));
if (size_of_all > s2n_stuffer_data_available(extension) || size_of_all % sizeof(kem_extension_size)) {
/* Malformed length, ignore the extension */
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c
index 6e058d4392..d457829022 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c
@@ -18,14 +18,17 @@
#include "crypto/s2n_hash.h"
#include "tls/s2n_tls.h"
+#include "tls/s2n_psk.h"
#include "tls/s2n_tls_parameters.h"
+#include "tls/extensions/s2n_client_psk.h"
+#include "utils/s2n_bitmap.h"
#include "utils/s2n_safety.h"
#define SIZE_OF_BINDER_SIZE sizeof(uint8_t)
#define SIZE_OF_BINDER_LIST_SIZE sizeof(uint16_t)
+#define MAX_NUM_OF_PSK_IDENTITIES 100
-static bool s2n_client_psk_should_send(struct s2n_connection *conn);
static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out);
static int s2n_client_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
@@ -38,10 +41,35 @@ const s2n_extension_type s2n_client_psk_extension = {
.if_missing = s2n_extension_noop_if_missing,
};
-static bool s2n_client_psk_should_send(struct s2n_connection *conn)
+bool s2n_client_psk_should_send(struct s2n_connection *conn)
{
- return conn && s2n_connection_get_protocol_version(conn) >= S2N_TLS13
- && conn->psk_params.psk_list.len;
+ if (conn == NULL) {
+ return false;
+ }
+
+ if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
+ return false;
+ }
+
+ /* If this is NOT the second ClientHello after a retry, then all PSKs are viable.
+ * Send the extension if any PSKs are configured.
+ */
+ if (!s2n_is_hello_retry_handshake(conn)) {
+ return conn->psk_params.psk_list.len > 0;
+ }
+
+ /* If this is the second ClientHello after a retry, then only PSKs that match the cipher suite
+ * are viable. Only send the extension if at least one configured PSK matches the cipher suite.
+ */
+ for (size_t i = 0; i < conn->psk_params.psk_list.len; i++) {
+ struct s2n_psk *psk = NULL;
+ if (s2n_result_is_ok(s2n_array_get(&conn->psk_params.psk_list, i, (void**) &psk))
+ && psk != NULL
+ && conn->secure.cipher_suite->prf_alg == psk->hmac_alg) {
+ return true;
+ }
+ }
+ return false;
}
static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out)
@@ -61,6 +89,16 @@ static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *
GUARD_AS_POSIX(s2n_array_get(psk_list, i, (void**) &psk));
notnull_check(psk);
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.1.4
+ *# In addition, in its updated ClientHello, the client SHOULD NOT offer
+ *# any pre-shared keys associated with a hash other than that of the
+ *# selected cipher suite.
+ */
+ if (s2n_is_hello_retry_handshake(conn) && conn->secure.cipher_suite->prf_alg != psk->hmac_alg) {
+ continue;
+ }
+
/* Write the identity */
GUARD(s2n_stuffer_write_uint16(out, psk->identity.size));
GUARD(s2n_stuffer_write(out, &psk->identity));
@@ -68,7 +106,7 @@ static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *
/* Calculate binder size */
uint8_t hash_size = 0;
- GUARD(s2n_hash_digest_size(psk->hash_alg, &hash_size));
+ GUARD(s2n_hmac_digest_size(psk->hmac_alg, &hash_size));
binder_list_size += hash_size + SIZE_OF_BINDER_SIZE;
}
@@ -121,44 +159,104 @@ static S2N_RESULT s2n_match_psk_identity(struct s2n_array *known_psks, const str
return S2N_RESULT_OK;
}
+static S2N_RESULT s2n_select_psk_identity(struct s2n_connection *conn, struct s2n_psk_identity *identities, size_t identities_length)
+{
+ ENSURE_REF(conn);
+ ENSURE_REF(identities);
+
+ struct s2n_array *known_psks = &conn->psk_params.psk_list;
+ conn->psk_params.chosen_psk = NULL;
+
+ for (size_t i = 0; i < identities_length; i++) {
+ struct s2n_blob wire_identity = { 0 };
+ GUARD_AS_RESULT(s2n_blob_init(&wire_identity, identities[i].data, identities[i].length));
+
+ struct s2n_psk *local_match = NULL;
+ GUARD_RESULT(s2n_match_psk_identity(known_psks, &wire_identity, &local_match));
+
+ /* When a local match is found we do not end this loop early in an attempt
+ * to keep the server's known identities a secret and hide its ordering.
+ */
+ if (local_match != NULL && conn->psk_params.chosen_psk == NULL) {
+ conn->psk_params.chosen_psk_wire_index = i;
+ conn->psk_params.chosen_psk = local_match;
+ }
+ }
+
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_count_psk_identities(struct s2n_stuffer *input, uint16_t *identity_count)
+{
+ ENSURE_REF(input);
+ ENSURE_REF(identity_count);
+
+ const size_t obfuscated_ticket_age_size = sizeof(uint32_t);
+
+ *identity_count = 0;
+ while (s2n_stuffer_data_available(input) > 0) {
+ uint16_t identity_size = 0;
+ GUARD_AS_RESULT(s2n_stuffer_read_uint16(input, &identity_size));
+ GUARD_AS_RESULT(s2n_stuffer_skip_read(input, identity_size));
+ GUARD_AS_RESULT(s2n_stuffer_skip_read(input, obfuscated_ticket_age_size));
+ (*identity_count)++;
+ }
+ GUARD_AS_RESULT(s2n_stuffer_reread(input));
+ return S2N_RESULT_OK;
+}
+
static S2N_RESULT s2n_client_psk_recv_identity_list(struct s2n_connection *conn, struct s2n_stuffer *wire_identities_in)
{
ENSURE_REF(conn);
ENSURE_REF(wire_identities_in);
- uint8_t wire_index = 0;
+ uint16_t identities_count = 0;
+ GUARD_RESULT(s2n_count_psk_identities(wire_identities_in, &identities_count));
+ ENSURE_GT(identities_count, 0);
+ ENSURE_LTE(identities_count, MAX_NUM_OF_PSK_IDENTITIES);
+
+ DEFER_CLEANUP(struct s2n_blob wire_identities_blob = { 0 }, s2n_free);
+ GUARD_AS_RESULT(s2n_alloc(&wire_identities_blob, identities_count * sizeof(struct s2n_psk_identity)));
+ struct s2n_psk_identity *wire_identities = (struct s2n_psk_identity*)(void*) wire_identities_blob.data;
+
+ uint16_t wire_index = 0;
while (s2n_stuffer_data_available(wire_identities_in) > 0) {
uint16_t identity_size = 0;
GUARD_AS_RESULT(s2n_stuffer_read_uint16(wire_identities_in, &identity_size));
+ ENSURE_GT(identity_size, 0);
- uint8_t *identity_data;
- ENSURE_REF(identity_data = s2n_stuffer_raw_read(wire_identities_in, identity_size));
+ uint8_t *identity_data = s2n_stuffer_raw_read(wire_identities_in, identity_size);
+ ENSURE_REF(identity_data);
- struct s2n_blob identity = { 0 };
- GUARD_AS_RESULT(s2n_blob_init(&identity, identity_data, identity_size));
+ wire_identities[wire_index].data = identity_data;
+ wire_identities[wire_index].length = identity_size;
- /* TODO: Validate obfuscated_ticket_age when using session tickets:
- * https://github.com/awslabs/s2n/issues/2417
- *
- * "For identities established externally, an obfuscated_ticket_age of 0 SHOULD be
- * used, and servers MUST ignore the value."
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11
+ *# For identities established externally, an obfuscated_ticket_age of 0 SHOULD be
+ *# used, and servers MUST ignore the value.
*/
uint32_t obfuscated_ticket_age = 0;
GUARD_AS_RESULT(s2n_stuffer_read_uint32(wire_identities_in, &obfuscated_ticket_age));
- /* TODO: Implement the callback to choose a PSK: https://github.com/awslabs/s2n/issues/2397
- *
- * When we don't have a callback configured to choose a PSK, we should fall back to accepting
- * the first PSK identity that also exists in our list of supported PSKs. */
- GUARD_RESULT(s2n_match_psk_identity(&conn->psk_params.psk_list, &identity, &conn->psk_params.chosen_psk));
-
- if (conn->psk_params.chosen_psk) {
- conn->psk_params.chosen_psk_wire_index = wire_index;
- return S2N_RESULT_OK;
- }
-
wire_index++;
}
+
+ if (conn->config->psk_selection_cb) {
+ GUARD_AS_RESULT(conn->config->psk_selection_cb(conn, wire_identities, identities_count,
+ &conn->psk_params.chosen_psk_wire_index));
+ struct s2n_blob chosen_wire_identity = { 0 };
+ GUARD_AS_RESULT(s2n_blob_init(&chosen_wire_identity,
+ wire_identities[conn->psk_params.chosen_psk_wire_index].data,
+ wire_identities[conn->psk_params.chosen_psk_wire_index].length));
+ GUARD_RESULT(s2n_match_psk_identity(&conn->psk_params.psk_list, &chosen_wire_identity, &conn->psk_params.chosen_psk));
+ } else {
+ GUARD_RESULT(s2n_select_psk_identity(conn, wire_identities, identities_count));
+ }
+
+ ENSURE_LT(conn->psk_params.chosen_psk_wire_index, identities_count);
+ ENSURE_REF(conn->psk_params.chosen_psk);
+
return S2N_RESULT_OK;
}
@@ -168,7 +266,7 @@ static S2N_RESULT s2n_client_psk_recv_binder_list(struct s2n_connection *conn, s
ENSURE_REF(conn);
ENSURE_REF(wire_binders_in);
- uint8_t wire_index = 0;
+ uint16_t wire_index = 0;
while (s2n_stuffer_data_available(wire_binders_in) > 0) {
uint8_t wire_binder_size = 0;
GUARD_AS_RESULT(s2n_stuffer_read_uint8(wire_binders_in, &wire_binder_size));
@@ -246,26 +344,66 @@ int s2n_client_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extensi
return S2N_SUCCESS;
}
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11
+ *# The "pre_shared_key" extension MUST be the last extension in the
+ *# ClientHello (this facilitates implementation as described below).
+ *# Servers MUST check that it is the last extension and otherwise fail
+ *# the handshake with an "illegal_parameter" alert.
+ */
+ s2n_extension_type_id psk_ext_id;
+ GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_PRE_SHARED_KEY, &psk_ext_id));
+ ne_check(conn->client_hello.extensions.count, 0);
+ uint16_t last_wire_index = conn->client_hello.extensions.count - 1;
+ uint16_t extension_wire_index = conn->client_hello.extensions.parsed_extensions[psk_ext_id].wire_index;
+ ENSURE_POSIX(extension_wire_index == last_wire_index, S2N_ERR_UNSUPPORTED_EXTENSION);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.9
+ *# If clients offer "pre_shared_key" without a "psk_key_exchange_modes" extension,
+ *# servers MUST abort the handshake.
+ *
+ * We can safely do this check here because s2n_client_psk is
+ * required to be the last extension sent in the list.
+ */
+ s2n_extension_type_id psk_ke_mode_ext_id;
+ GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES, &psk_ke_mode_ext_id));
+ ENSURE_POSIX(S2N_CBIT_TEST(conn->extension_requests_received, psk_ke_mode_ext_id), S2N_ERR_MISSING_EXTENSION);
+
+ if (conn->psk_params.psk_ke_mode == S2N_PSK_DHE_KE) {
+ s2n_extension_type_id key_share_ext_id;
+ GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_KEY_SHARE, &key_share_ext_id));
+ /* A key_share extension must have been received in order to use a pre-shared key
+ * in (EC)DHE key exchange mode.
+ */
+ ENSURE_POSIX(S2N_CBIT_TEST(conn->extension_requests_received, key_share_ext_id), S2N_ERR_MISSING_EXTENSION);
+ } else {
+ /* s2n currently only supports pre-shared keys in (EC)DHE key exchange mode. If we receive keys with any other
+ * exchange mode we fall back to a full handshake.
+ */
+ return S2N_SUCCESS;
+ }
+
if (s2n_result_is_error(s2n_client_psk_recv_identities(conn, extension))) {
- /* https://tools.ietf.org/html/rfc8446#section-4.2.11:
- * "If no acceptable PSKs are found, the server SHOULD perform a non-PSK
- * handshake if possible."
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11
+ *# If no acceptable PSKs are found, the server SHOULD perform a non-PSK
+ *# handshake if possible.
*/
conn->psk_params.chosen_psk = NULL;
}
if (conn->psk_params.chosen_psk) {
- /* https://tools.ietf.org/html/rfc8446#section-4.2.11:
- * "Prior to accepting PSK key establishment, the server MUST validate
- * the corresponding binder value. If this value is not present or does
- * not validate, the server MUST abort the handshake."
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11
+ *# Prior to accepting PSK key establishment, the server MUST validate
+ *# the corresponding binder value (see Section 4.2.11.2 below). If this
+ *# value is not present or does not validate, the server MUST abort the
+ *# handshake.
*/
GUARD_AS_POSIX(s2n_client_psk_recv_binders(conn, extension));
}
- /* At this point, we have either chosen a PSK or fallen back to a full handshake.
- * Wipe any PSKs not chosen. */
- GUARD_AS_POSIX(s2n_psk_parameters_free_unused_psks(&conn->psk_params));
-
+ /* At this point, we have either chosen a PSK or fallen back to a full handshake. */
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h
index a317ace2bc..1fdabff50d 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h
@@ -20,3 +20,5 @@
#include "stuffer/s2n_stuffer.h"
extern const s2n_extension_type s2n_client_psk_extension;
+
+bool s2n_client_psk_should_send(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 9c1bf71092..4cb2f9e3c5 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
@@ -24,7 +24,7 @@
#include "tls/s2n_security_policies.h"
#include "utils/s2n_safety.h"
-#include "crypto/s2n_fips.h"
+#include "pq-crypto/s2n_pq.h"
#include "tls/s2n_tls13.h"
static int s2n_client_supported_groups_send(struct s2n_connection *conn, struct s2n_stuffer *out);
@@ -63,7 +63,7 @@ static int s2n_client_supported_groups_send(struct s2n_connection *conn, struct
GUARD(s2n_stuffer_reserve_uint16(out, &group_list_len));
/* Send KEM groups list first */
- if (s2n_connection_get_protocol_version(conn) >= S2N_TLS13 && !s2n_is_in_fips_mode()) {
+ if (s2n_connection_get_protocol_version(conn) >= S2N_TLS13 && s2n_pq_is_enabled()) {
for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) {
GUARD(s2n_stuffer_write_uint16(out, kem_pref->tls13_kem_groups[i]->iana_id));
}
@@ -97,8 +97,8 @@ static int s2n_client_supported_groups_recv_iana_id(struct s2n_connection *conn,
}
}
- /* Return early if in FIPS mode, or if TLS 1.3 is disabled, so as to ignore PQ IDs */
- if (s2n_is_in_fips_mode() || s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
+ /* Return early if PQ is disabled, or if TLS version is less than 1.3, so as to ignore PQ IDs */
+ if (!s2n_pq_is_enabled() || s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
return S2N_SUCCESS;
}
@@ -135,7 +135,7 @@ static int s2n_choose_supported_group(struct s2n_connection *conn) {
conn->secure.server_kem_group_params.kem_params.kem = NULL;
conn->secure.server_ecc_evp_params.negotiated_curve = NULL;
- /* Prefer to negotiate hybrid PQ over ECC. If in FIPS mode, we will never choose a
+ /* Prefer to negotiate hybrid PQ over ECC. If PQ is disabled, we will never choose a
* PQ group because the mutually_supported_kem_groups array will not have been
* populated with anything. */
for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) {
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c
index 81c9e9bf5a..5188535bf4 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c
@@ -120,9 +120,10 @@ int s2n_extension_list_process(s2n_extension_list_id list_type, struct s2n_conne
return S2N_SUCCESS;
}
-static int s2n_extension_parse(struct s2n_stuffer *in, s2n_parsed_extension *parsed_extensions)
+static int s2n_extension_parse(struct s2n_stuffer *in, s2n_parsed_extension *parsed_extensions, uint16_t *wire_index)
{
notnull_check(parsed_extensions);
+ notnull_check(wire_index);
uint16_t extension_type;
ENSURE_POSIX(s2n_stuffer_read_uint16(in, &extension_type) == S2N_SUCCESS,
@@ -149,7 +150,9 @@ static int s2n_extension_parse(struct s2n_stuffer *in, s2n_parsed_extension *par
/* Fill in parsed extension */
parsed_extension->extension_type = extension_type;
+ parsed_extension->wire_index = *wire_index;
GUARD(s2n_blob_init(&parsed_extension->extension, extension_data, extension_size));
+ (*wire_index)++;
return S2N_SUCCESS;
}
@@ -176,9 +179,11 @@ int s2n_extension_list_parse(struct s2n_stuffer *in, s2n_parsed_extensions_list
GUARD(s2n_stuffer_init(&extensions_stuffer, &parsed_extension_list->raw));
GUARD(s2n_stuffer_skip_write(&extensions_stuffer, total_extensions_size));
+ uint16_t wire_index = 0;
while (s2n_stuffer_data_available(&extensions_stuffer)) {
- GUARD(s2n_extension_parse(&extensions_stuffer, parsed_extension_list->parsed_extensions));
+ GUARD(s2n_extension_parse(&extensions_stuffer, parsed_extension_list->parsed_extensions, &wire_index));
}
+ parsed_extension_list->count = wire_index;
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h
index 35582e5638..dcf7c9da9b 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h
@@ -23,11 +23,13 @@
typedef struct {
uint16_t extension_type;
struct s2n_blob extension;
+ uint16_t wire_index;
} s2n_parsed_extension;
typedef struct {
s2n_parsed_extension parsed_extensions[S2N_PARSED_EXTENSIONS_COUNT];
struct s2n_blob raw; /* Needed by some ClientHello APIs */
+ uint16_t count;
} s2n_parsed_extensions_list;
typedef enum {
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h
index 674c8e63dd..3c95af639f 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h
@@ -61,6 +61,7 @@ static const uint16_t s2n_supported_extensions[] = {
TLS_EXTENSION_KEY_SHARE,
TLS_EXTENSION_COOKIE,
TLS_QUIC_TRANSPORT_PARAMETERS,
+ TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES,
TLS_EXTENSION_PRE_SHARED_KEY,
};
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c
index ed4c196f59..5395366a6c 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c
@@ -31,6 +31,7 @@
#include "tls/extensions/s2n_client_supported_groups.h"
#include "tls/extensions/s2n_client_pq_kem.h"
#include "tls/extensions/s2n_client_psk.h"
+#include "tls/extensions/s2n_psk_key_exchange_modes.h"
#include "tls/extensions/s2n_client_renegotiation_info.h"
#include "tls/extensions/s2n_ec_point_format.h"
#include "tls/extensions/s2n_quic_transport_params.h"
@@ -45,6 +46,7 @@
#include "tls/extensions/s2n_server_signature_algorithms.h"
#include "tls/extensions/s2n_server_supported_versions.h"
#include "tls/extensions/s2n_server_key_share.h"
+#include "tls/extensions/s2n_server_psk.h"
static const s2n_extension_type *const client_hello_extensions[] = {
&s2n_client_supported_versions_extension,
@@ -62,6 +64,7 @@ static const s2n_extension_type *const client_hello_extensions[] = {
&s2n_client_renegotiation_info_extension,
&s2n_client_cookie_extension,
&s2n_quic_transport_parameters_extension,
+ &s2n_psk_key_exchange_modes_extension,
&s2n_client_psk_extension /* MUST be last */
};
@@ -81,6 +84,7 @@ static const s2n_extension_type *const tls13_server_hello_extensions[] = {
&s2n_server_supported_versions_extension,
&s2n_server_key_share_extension,
&s2n_server_cookie_extension,
+ &s2n_server_psk_extension, /* MUST appear after keyshare extension */
};
static const s2n_extension_type *const encrypted_extensions[] = {
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
new file mode 100644
index 0000000000..67b1904b6b
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c
@@ -0,0 +1,83 @@
+/*
+ * 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 <sys/param.h>
+#include <stdint.h>
+
+#include "tls/s2n_tls_parameters.h"
+#include "tls/extensions/s2n_client_psk.h"
+#include "utils/s2n_safety.h"
+
+#define PSK_KEY_EXCHANGE_MODE_SIZE sizeof(uint8_t)
+
+static bool s2n_psk_key_exchange_modes_should_send(struct s2n_connection *conn);
+static int s2n_psk_key_exchange_modes_send(struct s2n_connection *conn, struct s2n_stuffer *out);
+static int s2n_psk_key_exchange_modes_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
+
+const s2n_extension_type s2n_psk_key_exchange_modes_extension = {
+ .iana_value = TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES,
+ .is_response = false,
+ .send = s2n_psk_key_exchange_modes_send,
+ .recv = s2n_psk_key_exchange_modes_recv,
+ .should_send = s2n_psk_key_exchange_modes_should_send,
+ .if_missing = s2n_extension_noop_if_missing,
+};
+
+static bool s2n_psk_key_exchange_modes_should_send(struct s2n_connection *conn)
+{
+ /* Only send a psk_key_exchange_modes extension if a psk extension is also being sent */
+ return s2n_client_psk_should_send(conn);
+}
+
+static int s2n_psk_key_exchange_modes_send(struct s2n_connection *conn, struct s2n_stuffer *out)
+{
+ notnull_check(conn);
+
+ GUARD(s2n_stuffer_write_uint8(out, PSK_KEY_EXCHANGE_MODE_SIZE));
+
+ /* s2n currently only supports pre-shared keys with (EC)DHE key establishment */
+ GUARD(s2n_stuffer_write_uint8(out, TLS_PSK_DHE_KE_MODE));
+
+ return S2N_SUCCESS;
+}
+
+static int s2n_psk_key_exchange_modes_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
+{
+ notnull_check(conn);
+
+ if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
+ return S2N_SUCCESS;
+ }
+
+ uint8_t psk_ke_mode_list_len;
+ GUARD(s2n_stuffer_read_uint8(extension, &psk_ke_mode_list_len));
+ if (psk_ke_mode_list_len > s2n_stuffer_data_available(extension)) {
+ /* Malformed length, ignore the extension */
+ return S2N_SUCCESS;
+ }
+
+ for (size_t i = 0; i < psk_ke_mode_list_len; i++) {
+ uint8_t wire_psk_ke_mode;
+ GUARD(s2n_stuffer_read_uint8(extension, &wire_psk_ke_mode));
+
+ /* s2n currently only supports pre-shared keys with (EC)DHE key establishment */
+ if (wire_psk_ke_mode == TLS_PSK_DHE_KE_MODE) {
+ conn->psk_params.psk_ke_mode = S2N_PSK_DHE_KE;
+ return S2N_SUCCESS;
+ }
+ }
+
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.h
new file mode 100644
index 0000000000..3c64f64489
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#pragma once
+
+#include "tls/extensions/s2n_extension_type.h"
+#include "tls/s2n_connection.h"
+#include "stuffer/s2n_stuffer.h"
+
+extern const s2n_extension_type s2n_psk_key_exchange_modes_extension;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c
index af112de0f4..eb0ead255a 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c
@@ -20,7 +20,7 @@
#include "utils/s2n_safety.h"
-#include "crypto/s2n_fips.h"
+#include "pq-crypto/s2n_pq.h"
static int s2n_server_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out);
static int s2n_server_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
@@ -38,7 +38,7 @@ static int s2n_server_key_share_generate_pq_hybrid(struct s2n_connection *conn,
notnull_check(out);
notnull_check(conn);
- ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
struct s2n_kem_group_params *server_kem_group_params = &conn->secure.server_kem_group_params;
@@ -71,7 +71,7 @@ static int s2n_server_key_share_generate_pq_hybrid(struct s2n_connection *conn,
int s2n_server_key_share_send_check_pq_hybrid(struct s2n_connection *conn) {
notnull_check(conn);
- ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
notnull_check(conn->secure.server_kem_group_params.kem_group);
notnull_check(conn->secure.server_kem_group_params.kem_params.kem);
@@ -167,9 +167,9 @@ static int s2n_server_key_share_recv_pq_hybrid(struct s2n_connection *conn, uint
notnull_check(conn);
notnull_check(extension);
- /* If in FIPS mode, the client should not have sent any PQ IDs
+ /* If PQ is disabled, the client should not have sent any PQ IDs
* in the supported_groups list of the initial ClientHello */
- ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
const struct s2n_kem_preferences *kem_pref = NULL;
GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c
new file mode 100644
index 0000000000..cb930b17a4
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c
@@ -0,0 +1,92 @@
+/*
+ * 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 <sys/param.h>
+#include <stdint.h>
+
+#include "tls/s2n_tls.h"
+#include "tls/extensions/s2n_server_psk.h"
+
+#include "utils/s2n_safety.h"
+#include "utils/s2n_bitmap.h"
+
+static bool s2n_server_psk_should_send(struct s2n_connection *conn);
+static int s2n_server_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out);
+static int s2n_server_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
+
+const s2n_extension_type s2n_server_psk_extension = {
+ .iana_value = TLS_EXTENSION_PRE_SHARED_KEY,
+ .is_response = true,
+ .send = s2n_server_psk_send,
+ .recv = s2n_server_psk_recv,
+ .should_send = s2n_server_psk_should_send,
+ .if_missing = s2n_extension_noop_if_missing,
+};
+
+static bool s2n_server_psk_should_send(struct s2n_connection *conn)
+{
+ /* Only send a server pre_shared_key extension if a chosen PSK is set on the connection */
+ return conn && s2n_connection_get_protocol_version(conn) >= S2N_TLS13
+ && conn->psk_params.chosen_psk;
+}
+
+static int s2n_server_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out)
+{
+ notnull_check(conn);
+
+ /* Send the index of the chosen PSK that is stored on the connection. */
+ GUARD(s2n_stuffer_write_uint16(out, conn->psk_params.chosen_psk_wire_index));
+
+ return S2N_SUCCESS;
+}
+
+static int s2n_server_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
+{
+ notnull_check(conn);
+
+ if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
+ return S2N_SUCCESS;
+ }
+
+ /* Currently in s2n, only (EC)DHE key exchange mode is supported.
+ * Any other mode selected by the server is invalid because it was not offered by the client.
+ * A key_share extension MUST have been received in order to use a pre-shared key in (EC)DHE key exchange mode.
+ */
+ s2n_extension_type_id key_share_ext_id;
+ GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_KEY_SHARE, &key_share_ext_id));
+ ENSURE_POSIX(S2N_CBIT_TEST(conn->extension_requests_received, key_share_ext_id), S2N_ERR_MISSING_EXTENSION);
+
+ /* From RFC section: https://tools.ietf.org/html/rfc8446#section-4.2.8.1
+ * Any future values that are allocated must ensure that the transmitted protocol messages
+ * unambiguously identify which mode was selected by the server; at present, this is
+ * indicated by the presence of the "key_share" in the ServerHello.
+ */
+ conn->psk_params.psk_ke_mode = S2N_PSK_DHE_KE;
+
+ uint16_t chosen_psk_wire_index = 0;
+ GUARD(s2n_stuffer_read_uint16(extension, &chosen_psk_wire_index));
+
+ /* From RFC section: https://tools.ietf.org/html/rfc8446#section-4.2.11
+ * Clients MUST verify that the server's selected_identity is within the
+ * range supplied by the client.
+ */
+ ENSURE_POSIX(chosen_psk_wire_index < conn->psk_params.psk_list.len, S2N_ERR_INVALID_ARGUMENT);
+ conn->psk_params.chosen_psk_wire_index = chosen_psk_wire_index;
+
+ GUARD_AS_POSIX(s2n_array_get(&conn->psk_params.psk_list, conn->psk_params.chosen_psk_wire_index,
+ (void **)&conn->psk_params.chosen_psk));
+
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.h
new file mode 100644
index 0000000000..d6956e9dbf
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.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
+
+#include "tls/extensions/s2n_extension_type.h"
+
+extern const s2n_extension_type s2n_server_psk_extension;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c
index 15c539da6b..d1960eac69 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c
@@ -262,7 +262,8 @@ S2N_RESULT s2n_async_pkey_sign_sync(struct s2n_connection *conn, s2n_signature_a
const struct s2n_pkey *pkey = conn->handshake_params.our_chain_and_key->private_key;
DEFER_CLEANUP(struct s2n_blob signed_content = { 0 }, s2n_free);
- uint32_t maximum_signature_length = s2n_pkey_size(pkey);
+ uint32_t maximum_signature_length = 0;
+ GUARD_RESULT(s2n_pkey_size(pkey, &maximum_signature_length));
GUARD_AS_RESULT(s2n_alloc(&signed_content, maximum_signature_length));
GUARD_AS_RESULT(s2n_pkey_sign(pkey, sig_alg, digest, &signed_content));
@@ -378,7 +379,8 @@ S2N_RESULT s2n_async_pkey_sign_perform(struct s2n_async_pkey_op *op, s2n_cert_pr
struct s2n_async_pkey_sign_data *sign = &op->op.sign;
- uint32_t maximum_signature_length = s2n_pkey_size(pkey);
+ uint32_t maximum_signature_length = 0;
+ GUARD_RESULT(s2n_pkey_size(pkey, &maximum_signature_length));
GUARD_AS_RESULT(s2n_alloc(&sign->signature, maximum_signature_length));
GUARD_AS_RESULT(s2n_pkey_sign(pkey, sign->sig_alg, &sign->digest, &sign->signature));
diff --git a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c
index 2d5070e32e..33404c811b 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c
@@ -130,11 +130,15 @@ static int s2n_certs_exist_for_sig_scheme(struct s2n_connection *conn, const str
static int s2n_certs_exist_for_auth_method(struct s2n_connection *conn, s2n_authentication_method auth_method)
{
+ if (auth_method == S2N_AUTHENTICATION_METHOD_SENTINEL) {
+ return S2N_SUCCESS;
+ }
+
s2n_authentication_method auth_method_for_cert_type;
for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
GUARD(s2n_get_auth_method_for_cert_type(i, &auth_method_for_cert_type));
- if (auth_method != S2N_AUTHENTICATION_METHOD_SENTINEL && auth_method != auth_method_for_cert_type) {
+ if (auth_method != auth_method_for_cert_type) {
continue;
}
@@ -145,11 +149,10 @@ static int s2n_certs_exist_for_auth_method(struct s2n_connection *conn, s2n_auth
S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED);
}
-/* A cipher suite is valid if:
- * - At least one compatible cert is configured
+/* TLS1.3 ciphers are always valid, as they don't include an auth method.
*
- * TLS1.3 ciphers are valid if ANY certs are configured, as authentication
- * method is not tied to cipher suites in TLS1.3.
+ * A pre-TLS1.3 cipher suite is valid if:
+ * - At least one compatible cert is configured
*
* This method is called by the server when choosing a cipher suite.
*/
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
index 4343b88f00..67893009b1 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
@@ -989,6 +989,21 @@ const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2019 =
.suites = cipher_suites_cloudfront_tls_1_2_2019,
};
+struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_2_2021[] = {
+ S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716,
+ &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_chacha20_poly1305_sha256,
+ &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256
+};
+
+const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2021 = {
+ .count = s2n_array_len(cipher_suites_cloudfront_tls_1_2_2021),
+ .suites = cipher_suites_cloudfront_tls_1_2_2021,
+};
+
struct s2n_cipher_suite *cipher_suites_kms_tls_1_0_2018_10[] = {
&s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
&s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
@@ -1007,8 +1022,6 @@ const struct s2n_cipher_preferences cipher_preferences_kms_tls_1_0_2018_10 = {
.suites = cipher_suites_kms_tls_1_0_2018_10,
};
-#if !defined(S2N_NO_PQ)
-
struct s2n_cipher_suite *cipher_suites_kms_pq_tls_1_0_2019_06[] = {
&s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
&s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384,
@@ -1108,8 +1121,6 @@ const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2020_12 = {
.suites = cipher_suites_pq_tls_1_0_2020_12,
};
-#endif
-
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 b70fa55922..8dabb707ff 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h
@@ -76,6 +76,7 @@ extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0
extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_1_2016;
extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2018;
extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2019;
+extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2021;
/* CloudFront viewer facing legacy TLS 1.2 policies */
extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_ssl_v_3_legacy;
@@ -87,8 +88,6 @@ extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2
extern const struct s2n_cipher_preferences cipher_preferences_kms_tls_1_0_2018_10;
-#if !defined(S2N_NO_PQ)
-
extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2019_06;
extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2020_02;
extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2020_07;
@@ -96,8 +95,6 @@ extern const struct s2n_cipher_preferences cipher_preferences_pq_sike_test_tls_1
extern const struct s2n_cipher_preferences cipher_preferences_pq_sike_test_tls_1_0_2020_02;
extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2020_12;
-#endif
-
extern const struct s2n_cipher_preferences cipher_preferences_kms_fips_tls_1_2_2018_10;
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 f3597ee3c2..ea478e27b8 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
@@ -29,6 +29,7 @@
#include "tls/s2n_tls13.h"
#include "utils/s2n_safety.h"
#include "tls/s2n_psk.h"
+#include "pq-crypto/s2n_pq.h"
/*************************
* S2n Record Algorithms *
@@ -809,11 +810,9 @@ static struct s2n_cipher_suite *s2n_all_cipher_suites[] = {
&s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA8 */
&s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */
&s2n_dhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xAA */
-#if !defined(S2N_NO_PQ)
&s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x04 */
&s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x08 */
&s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x0C */
-#endif
};
/* All supported ciphers. Exposed for integration testing. */
@@ -859,11 +858,9 @@ static struct s2n_cipher_suite *s2n_all_tls12_cipher_suites[] = {
&s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA8 */
&s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */
&s2n_dhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xAA */
-#if !defined(S2N_NO_PQ)
&s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x04 */
&s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x08 */
&s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x0C */
-#endif
};
const struct s2n_cipher_preferences cipher_preferences_test_all_tls12 = {
@@ -1019,6 +1016,12 @@ int s2n_cipher_suites_init(void)
}
}
+ /* Mark PQ cipher suites as unavailable if PQ is disabled */
+ if (s2n_kex_includes(cur_suite->key_exchange_alg, &s2n_kem) && !s2n_pq_is_enabled()) {
+ cur_suite->available = 0;
+ cur_suite->record_alg = NULL;
+ }
+
/* Initialize SSLv3 cipher suite if SSLv3 utilizes a different record algorithm */
if (cur_suite->sslv3_record_alg && cur_suite->sslv3_record_alg->cipher->is_available()) {
struct s2n_blob cur_suite_mem = { .data = (uint8_t *) cur_suite, .size = sizeof(struct s2n_cipher_suite) };
@@ -1103,6 +1106,15 @@ int s2n_set_cipher_as_client(struct s2n_connection *conn, uint8_t wire[S2N_TLS_C
cipher_suite = s2n_cipher_suite_from_wire(wire);
ENSURE_POSIX(cipher_suite != NULL, S2N_ERR_CIPHER_NOT_SUPPORTED);
+ /* From RFC section: https://tools.ietf.org/html/rfc8446#section-4.2.11:
+ * Client MUST verify that the server selected a cipher suite indicating a Hash
+ * associated with the chosen PSK if it exists.
+ * */
+ if (conn->psk_params.chosen_psk) {
+ ENSURE_POSIX(cipher_suite->prf_alg == conn->psk_params.chosen_psk->hmac_alg,
+ S2N_ERR_CIPHER_NOT_SUPPORTED);
+ }
+
/* Verify cipher suite sent in server hello is the same as sent in hello retry */
if (s2n_is_hello_retry_handshake(conn) && !s2n_is_hello_retry_message(conn)) {
ENSURE_POSIX(conn->secure.cipher_suite->iana_value == cipher_suite->iana_value, S2N_ERR_CIPHER_NOT_SUPPORTED);
@@ -1210,24 +1222,25 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire,
/* TLS 1.3 does not include key exchange in cipher suites */
if (match->minimum_required_tls_version < S2N_TLS13) {
/* If the kex is not supported continue to the next candidate */
- if (!s2n_kex_supported(match, conn)) {
+ bool kex_supported = false;
+ GUARD_AS_POSIX(s2n_kex_supported(match, conn, &kex_supported));
+ if (!kex_supported) {
continue;
}
/* If the kex is not configured correctly continue to the next candidate */
- if (s2n_configure_kex(match, conn)) {
+ if (s2n_result_is_error(s2n_configure_kex(match, conn))) {
continue;
}
}
- /* For TLS1.3 when PSKs are present, the server must consider the hash algorithm associated with the chosen PSK
- * when choosing a cipher suite. Server MUST reject any cipher suite without a matching hash algorithm and
- * continue to the next candidate.
- * */
- if (conn->actual_protocol_version >= S2N_TLS13 && conn->psk_params.chosen_psk != NULL) {
- s2n_hmac_algorithm chosen_psk_hmac_alg = { 0 };
- GUARD(s2n_hash_hmac_alg(conn->psk_params.chosen_psk->hash_alg, &chosen_psk_hmac_alg));
- if (match->prf_alg != chosen_psk_hmac_alg) {
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11
+ *# The server MUST ensure that it selects a compatible PSK
+ *# (if any) and cipher suite.
+ **/
+ if (conn->psk_params.chosen_psk != NULL) {
+ if (match->prf_alg != conn->psk_params.chosen_psk->hmac_alg) {
continue;
}
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
index 009f13471b..2bee39ec4c 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
@@ -31,14 +31,9 @@
#define S2N_KEY_EXCHANGE_ECC 0x04 /* Elliptic curve cryptography */
#define S2N_MAX_POSSIBLE_RECORD_ALGS 2
-#if !defined(S2N_NO_PQ)
-#define S2N_PQ_CIPHER_SUITE_COUNT 3
-#else
-#define S2N_PQ_CIPHER_SUITE_COUNT 0
-#endif
/* Kept up-to-date by s2n_cipher_suite_match_test */
-#define S2N_CIPHER_SUITE_COUNT (36 + S2N_PQ_CIPHER_SUITE_COUNT)
+#define S2N_CIPHER_SUITE_COUNT 39
/* Record algorithm flags that can be OR'ed */
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c b/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c
index a218c13c18..b11150c48c 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c
@@ -76,7 +76,8 @@ int s2n_client_cert_verify_send(struct s2n_connection *conn)
struct s2n_cert_chain_and_key *cert_chain_and_key = conn->handshake_params.our_chain_and_key;
DEFER_CLEANUP(struct s2n_blob signature = {0}, s2n_free);
- uint32_t max_signature_size = s2n_pkey_size(cert_chain_and_key->private_key);
+ uint32_t max_signature_size = 0;
+ GUARD_AS_POSIX(s2n_pkey_size(cert_chain_and_key->private_key, &max_signature_size));
GUARD(s2n_alloc(&signature, max_signature_size));
GUARD(s2n_pkey_sign(cert_chain_and_key->private_key, chosen_sig_scheme.sig_alg, &conn->handshake.ccv_hash_copy, &signature));
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
index 15bf12c525..b03cda1491 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
@@ -285,6 +285,12 @@ int s2n_process_client_hello(struct s2n_connection *conn)
/* Now choose the ciphers we have certs for. */
GUARD(s2n_set_cipher_as_tls_server(conn, client_hello->cipher_suites.data, client_hello->cipher_suites.size / 2));
+ /* If we're using a PSK, we don't need to choose a signature algorithm or certificate,
+ * because no additional auth is required. */
+ if (conn->psk_params.chosen_psk != NULL) {
+ return S2N_SUCCESS;
+ }
+
/* And set the signature and hash algorithm used for key exchange signatures */
GUARD(s2n_choose_sig_scheme_from_peer_preference_list(conn,
&conn->handshake_params.client_sig_hash_algs,
@@ -293,7 +299,7 @@ int s2n_process_client_hello(struct s2n_connection *conn)
/* And finally, set the certs specified by the final auth + sig_alg combo. */
GUARD(s2n_select_certs_for_server_auth(conn, &conn->handshake_params.our_chain_and_key));
- return 0;
+ return S2N_SUCCESS;
}
int s2n_client_hello_recv(struct s2n_connection *conn)
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c b/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c
index 99510d8628..1428e177b2 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c
@@ -37,7 +37,7 @@
#define get_client_hello_protocol_version(conn) (conn->client_hello_version == S2N_SSLv2 ? conn->client_protocol_version : conn->client_hello_version)
-typedef int s2n_kex_client_key_method(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key);
+typedef S2N_RESULT s2n_kex_client_key_method(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key);
typedef void *s2n_stuffer_action(struct s2n_stuffer *stuffer, uint32_t data_len);
static int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rsa_failed, struct s2n_blob *shared_key);
@@ -58,10 +58,10 @@ static int s2n_hybrid_client_action(struct s2n_connection *conn, struct s2n_blob
const uint32_t start_cursor = *cursor;
DEFER_CLEANUP(struct s2n_blob shared_key_0 = {0}, s2n_free);
- GUARD(kex_method(hybrid_kex_0, conn, &shared_key_0));
+ GUARD_AS_POSIX(kex_method(hybrid_kex_0, conn, &shared_key_0));
struct s2n_blob *shared_key_1 = &(conn->secure.kem_params.shared_secret);
- GUARD(kex_method(hybrid_kex_1, conn, shared_key_1));
+ GUARD_AS_POSIX(kex_method(hybrid_kex_1, conn, shared_key_1));
const uint32_t end_cursor = *cursor;
gte_check(end_cursor, start_cursor);
@@ -81,7 +81,7 @@ static int s2n_hybrid_client_action(struct s2n_connection *conn, struct s2n_blob
static int s2n_calculate_keys(struct s2n_connection *conn, struct s2n_blob *shared_key)
{
/* Turn the pre-master secret into a master secret */
- GUARD(s2n_kex_tls_prf(conn->secure.cipher_suite->key_exchange_alg, conn, shared_key));
+ GUARD_AS_POSIX(s2n_kex_tls_prf(conn->secure.cipher_suite->key_exchange_alg, conn, shared_key));
/* Erase the pre-master secret */
GUARD(s2n_blob_zero(shared_key));
if (shared_key->allocated) {
@@ -216,7 +216,7 @@ int s2n_client_key_recv(struct s2n_connection *conn)
const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg;
struct s2n_blob shared_key = {0};
- GUARD(s2n_kex_client_key_recv(key_exchange, conn, &shared_key));
+ GUARD_AS_POSIX(s2n_kex_client_key_recv(key_exchange, conn, &shared_key));
GUARD(s2n_calculate_keys(conn, &shared_key));
return 0;
@@ -260,8 +260,9 @@ int s2n_rsa_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared
*/
memcpy_check(conn->secure.rsa_premaster_secret, client_hello_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN);
- int encrypted_size = s2n_pkey_size(&conn->secure.server_public_key);
- S2N_ERROR_IF(encrypted_size < 0 || encrypted_size > 0xffff, S2N_ERR_SIZE_MISMATCH);
+ uint32_t encrypted_size = 0;
+ GUARD_AS_POSIX(s2n_pkey_size(&conn->secure.server_public_key, &encrypted_size));
+ S2N_ERROR_IF(encrypted_size > 0xffff, S2N_ERR_SIZE_MISMATCH);
if (conn->actual_protocol_version > S2N_SSLv3) {
GUARD(s2n_stuffer_write_uint16(&conn->handshake.io, encrypted_size));
@@ -311,7 +312,7 @@ int s2n_client_key_send(struct s2n_connection *conn)
const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg;
struct s2n_blob shared_key = {0};
- GUARD(s2n_kex_client_key_send(key_exchange, conn, &shared_key));
+ GUARD_AS_POSIX(s2n_kex_client_key_send(key_exchange, conn, &shared_key));
GUARD(s2n_calculate_keys(conn, &shared_key));
return 0;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.c b/contrib/restricted/aws/s2n/tls/s2n_config.c
index 51a974f8c7..db3a8819bc 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_config.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_config.c
@@ -123,6 +123,7 @@ static int s2n_config_init(struct s2n_config *config)
config->max_verify_cert_chain_depth_set = 0;
config->cert_tiebreak_cb = NULL;
config->async_pkey_cb = NULL;
+ config->psk_selection_cb = NULL;
config->cert_req_dss_legacy_compat_enabled = 0;
GUARD(s2n_config_setup_default(config));
@@ -858,3 +859,13 @@ int s2n_config_enable_cert_req_dss_legacy_compat(struct s2n_config *config)
config->cert_req_dss_legacy_compat_enabled = 1;
return S2N_SUCCESS;
}
+
+int s2n_config_set_psk_selection_callback(struct s2n_connection *conn, s2n_psk_selection_callback cb)
+{
+ notnull_check(conn);
+ notnull_check(cb);
+
+ conn->config->psk_selection_cb = cb;
+
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.h b/contrib/restricted/aws/s2n/tls/s2n_config.h
index be8baf1da1..c5edf02418 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_config.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_config.h
@@ -22,6 +22,7 @@
#include "tls/s2n_x509_validator.h"
#include "utils/s2n_blob.h"
#include "utils/s2n_set.h"
+#include "tls/s2n_psk.h"
#define S2N_MAX_TICKET_KEYS 48
#define S2N_MAX_TICKET_KEY_HASHES 500 /* 10KB */
@@ -101,6 +102,7 @@ struct s2n_config {
uint16_t max_verify_cert_chain_depth;
s2n_async_pkey_fn async_pkey_cb;
+ s2n_psk_selection_callback psk_selection_cb;
};
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 ae23da2439..f2393fd2a1 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection.c
@@ -452,7 +452,7 @@ int s2n_connection_free(struct s2n_connection *conn)
{
GUARD(s2n_connection_wipe_keys(conn));
GUARD(s2n_connection_free_keys(conn));
- GUARD(s2n_psk_parameters_free(&conn->psk_params));
+ GUARD_AS_POSIX(s2n_psk_parameters_wipe(&conn->psk_params));
GUARD(s2n_prf_free(conn));
diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.h b/contrib/restricted/aws/s2n/tls/s2n_connection.h
index 5ba5667fc2..9864111db1 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection.h
@@ -307,6 +307,8 @@ struct s2n_connection {
uint8_t ticket_ext_data[S2N_TICKET_SIZE_IN_BYTES];
struct s2n_stuffer client_ticket_to_decrypt;
+ uint8_t resumption_master_secret[S2N_TLS13_SECRET_MAX_LEN];
+
/* application protocols overridden */
struct s2n_blob application_protocols_overridden;
@@ -323,6 +325,12 @@ struct s2n_connection {
* Setting and manipulating this value requires security_policy to be configured prior.
* */
uint8_t preferred_key_shares;
+
+ /* Flags to prevent users from calling methods recursively.
+ * This can be an easy mistake to make when implementing send/receive callbacks.
+ */
+ bool send_in_use;
+ bool recv_in_use;
};
int s2n_connection_is_managed_corked(const struct s2n_connection *s2n_connection);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
index ad53a33938..5b78ef79c6 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
@@ -357,8 +357,6 @@ static message_type_t handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_LENGTH]
/*
* This selection of handshakes resembles the standard set, but with changes made to support tls1.3.
*
- * These are just the basic handshakes. At the moment hello retries, session resumption, and early data are not supported.
- *
* The CHANGE_CIPHER_SPEC messages are included only for middlebox compatibility.
* See https://tools.ietf.org/html/rfc8446#appendix-D.4
*/
@@ -373,6 +371,38 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L
HELLO_RETRY_MSG
},
+ [NEGOTIATED] = {
+ CLIENT_HELLO,
+ SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
+ CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
+ [NEGOTIATED | MIDDLEBOX_COMPAT] = {
+ CLIENT_HELLO,
+ SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
+ CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
+ [NEGOTIATED | HELLO_RETRY_REQUEST] = {
+ CLIENT_HELLO,
+ HELLO_RETRY_MSG,
+ CLIENT_HELLO,
+ SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
+ CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
+ [NEGOTIATED | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT] = {
+ CLIENT_HELLO,
+ HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
+ CLIENT_CHANGE_CIPHER_SPEC, CLIENT_HELLO,
+ SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
+ CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
[NEGOTIATED | FULL_HANDSHAKE] = {
CLIENT_HELLO,
SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
@@ -593,10 +623,10 @@ bool s2n_is_hello_retry_handshake(struct s2n_connection *conn)
return conn->handshake.handshake_type & HELLO_RETRY_REQUEST;
}
-int s2n_conn_set_handshake_type(struct s2n_connection *conn)
-{
+static S2N_RESULT s2n_conn_set_tls13_handshake_type(struct s2n_connection *conn) {
+ ENSURE_REF(conn);
+
if (conn->handshake.handshake_type & HELLO_RETRY_REQUEST) {
- ENSURE_POSIX(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_INVALID_HELLO_RETRY);
conn->handshake.handshake_type = HELLO_RETRY_REQUEST;
} else {
conn->handshake.handshake_type = INITIAL;
@@ -605,26 +635,53 @@ int s2n_conn_set_handshake_type(struct s2n_connection *conn)
/* A handshake type has been negotiated */
conn->handshake.handshake_type |= NEGOTIATED;
+ if (conn->psk_params.chosen_psk == NULL) {
+ conn->handshake.handshake_type |= FULL_HANDSHAKE;
+ }
+
s2n_cert_auth_type client_cert_auth_type;
- GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
+ GUARD_AS_RESULT(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
- if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED) {
+ if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED
+ && conn->handshake.handshake_type & FULL_HANDSHAKE) {
/* If we're a client, and Client Auth is REQUIRED, then the Client must expect the CLIENT_CERT_REQ Message */
conn->handshake.handshake_type |= CLIENT_AUTH;
- } else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE) {
+ } else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE
+ && conn->handshake.handshake_type & FULL_HANDSHAKE) {
/* If we're a server, and Client Auth is REQUIRED or OPTIONAL, then the server must send the CLIENT_CERT_REQ Message*/
conn->handshake.handshake_type |= CLIENT_AUTH;
}
+ /* Use middlebox compatibility mode for TLS1.3 by default.
+ * For now, only disable it when QUIC support is enabled. */
+ if (!conn->config->quic_enabled) {
+ conn->handshake.handshake_type |= MIDDLEBOX_COMPAT;
+ }
+
+ return S2N_RESULT_OK;
+}
+
+int s2n_conn_set_handshake_type(struct s2n_connection *conn)
+{
if (IS_TLS13_HANDSHAKE(conn)) {
- /* Use middlebox compatibility mode for TLS1.3 by default.
- * For now, only disable it when QUIC support is enabled. */
- if (!conn->config->quic_enabled) {
- conn->handshake.handshake_type |= MIDDLEBOX_COMPAT;
- }
- conn->handshake.handshake_type |= FULL_HANDSHAKE;
+ GUARD_AS_POSIX(s2n_conn_set_tls13_handshake_type(conn));
+ return S2N_SUCCESS;
+ }
- return 0;
+ S2N_ERROR_IF(conn->handshake.handshake_type & HELLO_RETRY_REQUEST, S2N_ERR_INVALID_HELLO_RETRY);
+
+ /* A handshake type has been negotiated */
+ conn->handshake.handshake_type = NEGOTIATED;
+
+ s2n_cert_auth_type client_cert_auth_type;
+ GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
+
+ if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED) {
+ /* If we're a client, and Client Auth is REQUIRED, then the Client must expect the CLIENT_CERT_REQ Message */
+ conn->handshake.handshake_type |= CLIENT_AUTH;
+ } else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE) {
+ /* If we're a server, and Client Auth is REQUIRED or OPTIONAL, then the server must send the CLIENT_CERT_REQ Message*/
+ conn->handshake.handshake_type |= CLIENT_AUTH;
}
if (conn->config->use_tickets) {
@@ -667,7 +724,9 @@ skip_cache_lookup:
/* If we get this far, it's a full handshake */
conn->handshake.handshake_type |= FULL_HANDSHAKE;
- if (s2n_kex_is_ephemeral(conn->secure.cipher_suite->key_exchange_alg)) {
+ bool is_ephemeral = false;
+ GUARD_AS_POSIX(s2n_kex_is_ephemeral(conn->secure.cipher_suite->key_exchange_alg, &is_ephemeral));
+ if (is_ephemeral) {
conn->handshake.handshake_type |= TLS12_PERFECT_FORWARD_SECRECY;
}
@@ -1032,6 +1091,7 @@ static int s2n_handshake_read_io(struct s2n_connection *conn)
if (conn->mode == S2N_CLIENT
&& client_cert_auth_type == S2N_CERT_AUTH_OPTIONAL
&& message_type == TLS_CERT_REQ) {
+ ENSURE_POSIX(conn->handshake.handshake_type & FULL_HANDSHAKE, S2N_ERR_HANDSHAKE_STATE);
conn->handshake.handshake_type |= CLIENT_AUTH;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem.c b/contrib/restricted/aws/s2n/tls/s2n_kem.c
index 4ddbbc8683..aef1665918 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kem.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_kem.c
@@ -480,7 +480,7 @@ int s2n_kem_recv_ciphertext(struct s2n_stuffer *in, struct s2n_kem_params *kem_p
}
#if defined(S2N_NO_PQ)
-/* IF S2N_NO_PQ was defined at compile time, the PQ KEM code will have been entirely excluded
+/* 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. */
/* sikep503r1 */
int SIKE_P503_r1_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c
index 4b9290c418..3e3fa71323 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c
@@ -15,8 +15,6 @@
#include "tls/s2n_kem_preferences.h"
-#if !defined(S2N_NO_PQ)
-
/* Extension list for round 1 PQ KEMs, in order of preference */
const struct s2n_kem *pq_kems_r1[2] = {
&s2n_bike1_l1_r1,
@@ -112,8 +110,6 @@ const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2020_12 = {
.tls13_kem_groups = pq_kem_groups_r2,
};
-#endif
-
const struct s2n_kem_preferences kem_preferences_null = {
.kem_count = 0,
.kems = NULL,
diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h
index e6226bb8f3..cad4f39c8e 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h
@@ -29,8 +29,6 @@ struct s2n_kem_preferences {
const struct s2n_kem_group **tls13_kem_groups;
};
-#if !defined(S2N_NO_PQ)
-
extern const struct s2n_kem *pq_kems_r1[2];
extern const struct s2n_kem *pq_kems_r2r1[4];
extern const struct s2n_kem *pq_kems_r2r1_2020_07[5];
@@ -45,9 +43,6 @@ extern const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2020_07;
extern const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2019_11;
extern const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2020_02;
extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2020_12;
-
-#endif
-
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_kex.c b/contrib/restricted/aws/s2n/tls/s2n_kex.c
index d01a25faef..b9fb9800ad 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kex.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_kex.c
@@ -14,7 +14,7 @@
*/
#include "tls/s2n_kex.h"
-#include "crypto/s2n_fips.h"
+#include "pq-crypto/s2n_pq.h"
#include "tls/s2n_cipher_preferences.h"
#include "tls/s2n_cipher_suites.h"
#include "tls/s2n_client_key_exchange.h"
@@ -24,44 +24,65 @@
#include "tls/s2n_tls.h"
#include "utils/s2n_safety.h"
-static int s2n_check_rsa_key(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
+static S2N_RESULT s2n_check_rsa_key(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- return s2n_get_compatible_cert_chain_and_key(conn, S2N_PKEY_TYPE_RSA) != NULL;
+ ENSURE_REF(cipher_suite);
+ ENSURE_REF(conn);
+ ENSURE_REF(is_supported);
+
+ *is_supported = s2n_get_compatible_cert_chain_and_key(conn, S2N_PKEY_TYPE_RSA) != NULL;
+
+ return S2N_RESULT_OK;
}
-static int s2n_check_dhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
+static S2N_RESULT s2n_check_dhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- return conn->config->dhparams != NULL;
+ ENSURE_REF(cipher_suite);
+ ENSURE_REF(conn);
+ ENSURE_REF(conn->config);
+ ENSURE_REF(is_supported);
+
+ *is_supported = conn->config->dhparams != NULL;
+
+ return S2N_RESULT_OK;
}
-static int s2n_check_ecdhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
+static S2N_RESULT s2n_check_ecdhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- return conn->secure.server_ecc_evp_params.negotiated_curve != NULL;
+ ENSURE_REF(cipher_suite);
+ ENSURE_REF(conn);
+ ENSURE_REF(is_supported);
+
+ *is_supported = conn->secure.server_ecc_evp_params.negotiated_curve != NULL;
+
+ return S2N_RESULT_OK;
}
-static int s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
+static S2N_RESULT s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- notnull_check(conn);
- /* There is no support for PQ KEMs while in FIPS mode */
- if (s2n_is_in_fips_mode()) {
- return 0;
- }
+ ENSURE_REF(cipher_suite);
+ ENSURE_REF(conn);
+ ENSURE_REF(is_supported);
+
+ /* If any of the necessary conditions are not met, we will return early and indicate KEM is not supported. */
+ *is_supported = false;
const struct s2n_kem_preferences *kem_preferences = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences));
- notnull_check(kem_preferences);
+ GUARD_AS_RESULT(s2n_connection_get_kem_preferences(conn, &kem_preferences));
+ ENSURE_REF(kem_preferences);
- if (kem_preferences->kem_count == 0) {
- return 0;
+ if (!s2n_pq_is_enabled() || kem_preferences->kem_count == 0) {
+ return S2N_RESULT_OK;
}
const struct s2n_iana_to_kem *supported_params = NULL;
- /* If the cipher suite has no supported KEMs return false */
- if (s2n_cipher_suite_to_kem(cipher_suite->iana_value, &supported_params) != 0) {
- return 0;
+ if (s2n_cipher_suite_to_kem(cipher_suite->iana_value, &supported_params) != S2N_SUCCESS) {
+ return S2N_RESULT_OK;
}
+
+ ENSURE_REF(supported_params);
if (supported_params->kem_count == 0) {
- return 0;
+ return S2N_RESULT_OK;
}
struct s2n_blob *client_kem_pref_list = &(conn->secure.client_pq_kem_extension);
@@ -69,60 +90,71 @@ static int s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n
if (client_kem_pref_list == NULL || client_kem_pref_list->data == NULL) {
/* If the client did not send a PQ KEM extension, then the server can pick its preferred parameter */
if (s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems,
- kem_preferences->kem_count, &chosen_kem)
- != 0) {
- return 0;
+ kem_preferences->kem_count, &chosen_kem) != S2N_SUCCESS) {
+ return S2N_RESULT_OK;
}
} else {
/* If the client did send a PQ KEM extension, then the server must find a mutually supported parameter. */
if (s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, client_kem_pref_list, kem_preferences->kems,
- kem_preferences->kem_count, &chosen_kem)
- != 0) {
- return 0;
+ kem_preferences->kem_count, &chosen_kem) != S2N_SUCCESS) {
+ return S2N_RESULT_OK;
}
}
- return chosen_kem != NULL;
+ *is_supported = chosen_kem != NULL;
+ return S2N_RESULT_OK;
}
-static int s2n_configure_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
+static S2N_RESULT s2n_configure_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
{
- notnull_check(conn);
- /* There is no support for PQ KEMs while in FIPS mode */
- S2N_ERROR_IF(s2n_is_in_fips_mode(), S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
+ ENSURE_REF(cipher_suite);
+ ENSURE_REF(conn);
+
+ ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
const struct s2n_kem_preferences *kem_preferences = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences));
- notnull_check(kem_preferences);
+ GUARD_AS_RESULT(s2n_connection_get_kem_preferences(conn, &kem_preferences));
+ ENSURE_REF(kem_preferences);
struct s2n_blob *proposed_kems = &(conn->secure.client_pq_kem_extension);
const struct s2n_kem *chosen_kem = NULL;
if (proposed_kems == NULL || proposed_kems->data == NULL) {
/* If the client did not send a PQ KEM extension, then the server can pick its preferred parameter */
- GUARD(s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems,
- kem_preferences->kem_count, &chosen_kem));
+ GUARD_AS_RESULT(s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems,
+ kem_preferences->kem_count, &chosen_kem));
} else {
/* If the client did send a PQ KEM extension, then the server must find a mutually supported parameter. */
- GUARD(s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, proposed_kems, kem_preferences->kems,
- kem_preferences->kem_count, &chosen_kem));
+ GUARD_AS_RESULT(s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, proposed_kems, kem_preferences->kems,
+ kem_preferences->kem_count, &chosen_kem));
}
conn->secure.kem_params.kem = chosen_kem;
- return 0;
+ return S2N_RESULT_OK;
}
-static int s2n_no_op_configure(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
+static S2N_RESULT s2n_no_op_configure(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
{
- return 0;
+ return S2N_RESULT_OK;
}
-static int s2n_check_hybrid_ecdhe_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
+static S2N_RESULT s2n_check_hybrid_ecdhe_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- return s2n_check_ecdhe(cipher_suite, conn) && s2n_check_kem(cipher_suite, conn);
+ ENSURE_REF(cipher_suite);
+ ENSURE_REF(conn);
+ ENSURE_REF(is_supported);
+
+ bool ecdhe_supported = false;
+ bool kem_supported = false;
+ GUARD_RESULT(s2n_check_ecdhe(cipher_suite, conn, &ecdhe_supported));
+ GUARD_RESULT(s2n_check_kem(cipher_suite, conn, &kem_supported));
+
+ *is_supported = ecdhe_supported && kem_supported;
+
+ return S2N_RESULT_OK;
}
const struct s2n_kex s2n_kem = {
- .is_ephemeral = 1,
+ .is_ephemeral = true,
.connection_supported = &s2n_check_kem,
.configure_connection = &s2n_configure_kem,
.server_key_recv_read_data = &s2n_kem_server_key_recv_read_data,
@@ -133,7 +165,7 @@ const struct s2n_kex s2n_kem = {
};
const struct s2n_kex s2n_rsa = {
- .is_ephemeral = 0,
+ .is_ephemeral = false,
.connection_supported = &s2n_check_rsa_key,
.configure_connection = &s2n_no_op_configure,
.server_key_recv_read_data = NULL,
@@ -145,7 +177,7 @@ const struct s2n_kex s2n_rsa = {
};
const struct s2n_kex s2n_dhe = {
- .is_ephemeral = 1,
+ .is_ephemeral = true,
.connection_supported = &s2n_check_dhe,
.configure_connection = &s2n_no_op_configure,
.server_key_recv_read_data = &s2n_dhe_server_key_recv_read_data,
@@ -157,7 +189,7 @@ const struct s2n_kex s2n_dhe = {
};
const struct s2n_kex s2n_ecdhe = {
- .is_ephemeral = 1,
+ .is_ephemeral = true,
.connection_supported = &s2n_check_ecdhe,
.configure_connection = &s2n_no_op_configure,
.server_key_recv_read_data = &s2n_ecdhe_server_key_recv_read_data,
@@ -169,7 +201,7 @@ const struct s2n_kex s2n_ecdhe = {
};
const struct s2n_kex s2n_hybrid_ecdhe_kem = {
- .is_ephemeral = 1,
+ .is_ephemeral = true,
.hybrid = { &s2n_ecdhe, &s2n_kem },
.connection_supported = &s2n_check_hybrid_ecdhe_kem,
.configure_connection = &s2n_configure_kem,
@@ -181,66 +213,112 @@ const struct s2n_kex s2n_hybrid_ecdhe_kem = {
.prf = &s2n_hybrid_prf_master_secret,
};
-int s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
+S2N_RESULT s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- /* Don't return -1 from notnull_check because that might allow a improperly configured kex to be marked as "supported" */
- return cipher_suite->key_exchange_alg->connection_supported != NULL && cipher_suite->key_exchange_alg->connection_supported(cipher_suite, conn);
+ ENSURE_REF(cipher_suite);
+ ENSURE_REF(cipher_suite->key_exchange_alg);
+ ENSURE_REF(cipher_suite->key_exchange_alg->connection_supported);
+ ENSURE_REF(conn);
+ ENSURE_REF(is_supported);
+
+ GUARD_RESULT(cipher_suite->key_exchange_alg->connection_supported(cipher_suite, conn, is_supported));
+
+ return S2N_RESULT_OK;
}
-int s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
+S2N_RESULT s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
{
- notnull_check(cipher_suite);
- notnull_check(cipher_suite->key_exchange_alg);
- notnull_check(cipher_suite->key_exchange_alg->configure_connection);
- return cipher_suite->key_exchange_alg->configure_connection(cipher_suite, conn);
+ ENSURE_REF(cipher_suite);
+ ENSURE_REF(cipher_suite->key_exchange_alg);
+ ENSURE_REF(cipher_suite->key_exchange_alg->configure_connection);
+ ENSURE_REF(conn);
+
+ GUARD_RESULT(cipher_suite->key_exchange_alg->configure_connection(cipher_suite, conn));
+
+ return S2N_RESULT_OK;
}
-int s2n_kex_is_ephemeral(const struct s2n_kex *kex)
+S2N_RESULT s2n_kex_is_ephemeral(const struct s2n_kex *kex, bool *is_ephemeral)
{
- notnull_check(kex);
- return kex->is_ephemeral;
+ ENSURE_REF(kex);
+ ENSURE_REF(is_ephemeral);
+
+ *is_ephemeral = kex->is_ephemeral;
+
+ return S2N_RESULT_OK;
}
-int s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data)
+S2N_RESULT s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data)
{
- notnull_check(kex);
- notnull_check(kex->server_key_recv_parse_data);
- return kex->server_key_recv_parse_data(conn, raw_server_data);
+ ENSURE_REF(kex);
+ ENSURE_REF(kex->server_key_recv_parse_data);
+ ENSURE_REF(conn);
+ ENSURE_REF(raw_server_data);
+
+ GUARD_AS_RESULT(kex->server_key_recv_parse_data(conn, raw_server_data));
+
+ return S2N_RESULT_OK;
}
-int s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data)
+S2N_RESULT s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify,
+ struct s2n_kex_raw_server_data *raw_server_data)
{
- notnull_check(kex);
- notnull_check(kex->server_key_recv_read_data);
- return kex->server_key_recv_read_data(conn, data_to_verify, raw_server_data);
+ ENSURE_REF(kex);
+ ENSURE_REF(kex->server_key_recv_read_data);
+ ENSURE_REF(conn);
+ ENSURE_REF(data_to_verify);
+
+ GUARD_AS_RESULT(kex->server_key_recv_read_data(conn, data_to_verify, raw_server_data));
+
+ return S2N_RESULT_OK;
}
-int s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign)
+S2N_RESULT s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign)
{
- notnull_check(kex);
- notnull_check(kex->server_key_send);
- return kex->server_key_send(conn, data_to_sign);
+ ENSURE_REF(kex);
+ ENSURE_REF(kex->server_key_send);
+ ENSURE_REF(conn);
+ ENSURE_REF(data_to_sign);
+
+ GUARD_AS_RESULT(kex->server_key_send(conn, data_to_sign));
+
+ return S2N_RESULT_OK;
}
-int s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key)
+S2N_RESULT s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key)
{
- notnull_check(kex);
- notnull_check(kex->client_key_recv);
- return kex->client_key_recv(conn, shared_key);
+ ENSURE_REF(kex);
+ ENSURE_REF(kex->client_key_recv);
+ ENSURE_REF(conn);
+ ENSURE_REF(shared_key);
+
+ GUARD_AS_RESULT(kex->client_key_recv(conn, shared_key));
+
+ return S2N_RESULT_OK;
}
-int s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key)
+S2N_RESULT s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key)
{
- notnull_check(kex);
- notnull_check(kex->client_key_send);
- return kex->client_key_send(conn, shared_key);
+ ENSURE_REF(kex);
+ ENSURE_REF(kex->client_key_send);
+ ENSURE_REF(conn);
+ ENSURE_REF(shared_key);
+
+ GUARD_AS_RESULT(kex->client_key_send(conn, shared_key));
+
+ return S2N_RESULT_OK;
}
-int s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret)
+S2N_RESULT s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret)
{
- notnull_check(kex);
- notnull_check(kex->prf);
- return kex->prf(conn, premaster_secret);
+ ENSURE_REF(kex);
+ ENSURE_REF(kex->prf);
+ ENSURE_REF(conn);
+ ENSURE_REF(premaster_secret);
+
+ GUARD_AS_RESULT(kex->prf(conn, premaster_secret));
+
+ return S2N_RESULT_OK;
}
bool s2n_kex_includes(const struct s2n_kex *kex, const struct s2n_kex *query)
diff --git a/contrib/restricted/aws/s2n/tls/s2n_kex.h b/contrib/restricted/aws/s2n/tls/s2n_kex.h
index 587cde5d63..e65392cce7 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kex.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_kex.h
@@ -18,13 +18,14 @@
#include <stdint.h>
#include "tls/s2n_connection.h"
#include "tls/s2n_kex_data.h"
+#include "utils/s2n_result.h"
struct s2n_kex {
- uint8_t is_ephemeral;
+ bool is_ephemeral;
const struct s2n_kex *hybrid[2];
- int (*connection_supported)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn);
- int (*configure_connection)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn);
+ S2N_RESULT (*connection_supported)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported);
+ S2N_RESULT (*configure_connection)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn);
int (*server_key_recv_read_data)(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *kex_data);
int (*server_key_recv_parse_data)(struct s2n_connection *conn, struct s2n_kex_raw_server_data *kex_data);
int (*server_key_send)(struct s2n_connection *conn, struct s2n_blob *data_to_sign);
@@ -39,17 +40,17 @@ extern const struct s2n_kex s2n_dhe;
extern const struct s2n_kex s2n_ecdhe;
extern const struct s2n_kex s2n_hybrid_ecdhe_kem;
-extern int s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn);
-extern int s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn);
-extern int s2n_kex_is_ephemeral(const struct s2n_kex *kex);
+extern S2N_RESULT s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported);
+extern S2N_RESULT s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn);
+extern S2N_RESULT s2n_kex_is_ephemeral(const struct s2n_kex *kex, bool *is_ephemeral);
-extern int s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify,
+extern S2N_RESULT s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify,
struct s2n_kex_raw_server_data *raw_server_data);
-extern int s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data);
-extern int s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign);
-extern int s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key);
-extern int s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key);
+extern S2N_RESULT s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data);
+extern S2N_RESULT s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign);
+extern S2N_RESULT s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key);
+extern S2N_RESULT s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key);
-extern int s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret);
+extern S2N_RESULT s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret);
extern bool s2n_kex_includes(const struct s2n_kex *kex, const struct s2n_kex *query);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_psk.c b/contrib/restricted/aws/s2n/tls/s2n_psk.c
index 2d764a00ed..59d4d75158 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_psk.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_psk.c
@@ -16,7 +16,6 @@
#include "crypto/s2n_tls13_keys.h"
#include "tls/s2n_handshake.h"
-#include "tls/s2n_psk.h"
#include "tls/s2n_tls13_handshake.h"
#include "tls/s2n_tls.h"
@@ -31,7 +30,7 @@ int s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type)
notnull_check(psk);
memset_check(psk, 0, sizeof(struct s2n_psk));
- psk->hash_alg = S2N_HASH_SHA256;
+ psk->hmac_alg = S2N_HMAC_SHA256;
psk->type = type;
return S2N_SUCCESS;
@@ -78,48 +77,25 @@ S2N_RESULT s2n_psk_parameters_init(struct s2n_psk_parameters *params)
return S2N_RESULT_OK;
}
-S2N_RESULT s2n_psk_parameters_free_unused_psks(struct s2n_psk_parameters *params)
+S2N_CLEANUP_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params)
{
ENSURE_REF(params);
+
for (size_t i = 0; i < params->psk_list.len; i++) {
struct s2n_psk *psk;
GUARD_RESULT(s2n_array_get(&params->psk_list, i, (void**)&psk));
-
- if(psk == params->chosen_psk) {
- continue;
- }
GUARD_AS_RESULT(s2n_psk_free(psk));
}
- return S2N_RESULT_OK;
-}
-
-S2N_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params)
-{
- ENSURE_REF(params);
-
- /* Free all PSKs */
- GUARD_RESULT(s2n_psk_parameters_free_unused_psks(params));
- GUARD_AS_RESULT(s2n_psk_free(params->chosen_psk));
-
- struct s2n_blob psk_list_mem = params->psk_list.mem;
- s2n_result result = s2n_psk_parameters_init(params);
- params->psk_list.mem = psk_list_mem;
+ GUARD_AS_RESULT(s2n_free(&params->psk_list.mem));
+ GUARD_RESULT(s2n_psk_parameters_init(params));
- return result;
-}
-
-int s2n_psk_parameters_free(struct s2n_psk_parameters *params)
-{
- notnull_check(params);
- GUARD_AS_POSIX(s2n_psk_parameters_wipe(params));
- GUARD(s2n_free(&params->psk_list.mem));
- return S2N_SUCCESS;
+ return S2N_RESULT_OK;
}
/* The binder hash is computed by hashing the concatenation of the current transcript
* and a partial ClientHello that does not include the binders themselves.
*/
-int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hash_algorithm hash_alg,
+int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hmac_algorithm hmac_alg,
const struct s2n_blob *partial_client_hello, struct s2n_blob *output_binder_hash)
{
notnull_check(partial_client_hello);
@@ -128,6 +104,9 @@ int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hash_algorith
/* Retrieve the current transcript.
* The current transcript will be empty unless this handshake included a HelloRetryRequest. */
struct s2n_hash_state current_hash_state = {0};
+
+ s2n_hash_algorithm hash_alg;
+ GUARD(s2n_hmac_hash_alg(hmac_alg, &hash_alg));
GUARD(s2n_handshake_get_hash_state(conn, hash_alg, &current_hash_state));
/* Copy the current transcript to avoid modifying the original. */
@@ -144,20 +123,6 @@ int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hash_algorith
return S2N_SUCCESS;
}
-static int s2n_tls13_keys_init_with_psk(struct s2n_tls13_keys *keys, struct s2n_psk *psk)
-{
- notnull_check(keys);
-
- keys->hash_algorithm = psk->hash_alg;
- GUARD(s2n_hash_hmac_alg(keys->hash_algorithm, &keys->hmac_algorithm));
- GUARD(s2n_hash_digest_size(keys->hash_algorithm, &keys->size));
- GUARD(s2n_blob_init(&keys->extract_secret, keys->extract_secret_bytes, keys->size));
- GUARD(s2n_blob_init(&keys->derive_secret, keys->derive_secret_bytes, keys->size));
- GUARD(s2n_hmac_new(&keys->hmac));
-
- return S2N_SUCCESS;
-}
-
/* The binder is computed in the same way as the Finished message
* (https://tools.ietf.org/html/rfc8446#section-4.4.4) but with the BaseKey being the binder_key
* derived via the key schedule from the corresponding PSK which is being offered
@@ -171,7 +136,7 @@ int s2n_psk_calculate_binder(struct s2n_psk *psk, const struct s2n_blob *binder_
notnull_check(output_binder);
DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free);
- GUARD(s2n_tls13_keys_init_with_psk(&psk_keys, psk));
+ GUARD(s2n_tls13_keys_init(&psk_keys, psk->hmac_alg));
eq_check(binder_hash->size, psk_keys.size);
eq_check(output_binder->size, psk_keys.size);
@@ -200,12 +165,12 @@ int s2n_psk_verify_binder(struct s2n_connection *conn, struct s2n_psk *psk,
notnull_check(binder_to_verify);
DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free);
- GUARD(s2n_tls13_keys_init_with_psk(&psk_keys, psk));
+ GUARD(s2n_tls13_keys_init(&psk_keys, psk->hmac_alg));
eq_check(binder_to_verify->size, psk_keys.size);
/* Calculate the binder hash from the transcript */
s2n_tls13_key_blob(binder_hash, psk_keys.size);
- GUARD(s2n_psk_calculate_binder_hash(conn, psk->hash_alg, partial_client_hello, &binder_hash));
+ GUARD(s2n_psk_calculate_binder_hash(conn, psk->hmac_alg, partial_client_hello, &binder_hash));
/* Calculate the expected binder from the binder hash */
s2n_tls13_key_blob(expected_binder, psk_keys.size);
@@ -257,13 +222,25 @@ static S2N_RESULT s2n_psk_write_binder_list(struct s2n_connection *conn, const s
GUARD_RESULT(s2n_array_get(psk_list, i, (void**) &psk));
ENSURE_REF(psk);
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.1.4
+ *# In addition, in its updated ClientHello, the client SHOULD NOT offer
+ *# any pre-shared keys associated with a hash other than that of the
+ *# selected cipher suite. This allows the client to avoid having to
+ *# compute partial hash transcripts for multiple hashes in the second
+ *# ClientHello.
+ */
+ if (s2n_is_hello_retry_handshake(conn) && conn->secure.cipher_suite->prf_alg != psk->hmac_alg) {
+ continue;
+ }
+
/* Retrieve or calculate the binder hash. */
- struct s2n_blob *binder_hash = &binder_hashes[psk->hash_alg];
+ struct s2n_blob *binder_hash = &binder_hashes[psk->hmac_alg];
if (binder_hash->size == 0) {
uint8_t hash_size = 0;
- GUARD_AS_RESULT(s2n_hash_digest_size(psk->hash_alg, &hash_size));
- GUARD_AS_RESULT(s2n_blob_init(binder_hash, binder_hashes_data[psk->hash_alg], hash_size));
- GUARD_AS_RESULT(s2n_psk_calculate_binder_hash(conn, psk->hash_alg, partial_client_hello, binder_hash));
+ GUARD_AS_RESULT(s2n_hmac_digest_size(psk->hmac_alg, &hash_size));
+ GUARD_AS_RESULT(s2n_blob_init(binder_hash, binder_hashes_data[psk->hmac_alg], hash_size));
+ GUARD_AS_RESULT(s2n_psk_calculate_binder_hash(conn, psk->hmac_alg, partial_client_hello, binder_hash));
}
GUARD_RESULT(s2n_psk_write_binder(conn, psk, binder_hash, out));
@@ -300,3 +277,57 @@ S2N_RESULT s2n_finish_psk_extension(struct s2n_connection *conn)
GUARD_RESULT(s2n_psk_write_binder_list(conn, &partial_client_hello, client_hello));
return S2N_RESULT_OK;
}
+
+static S2N_RESULT s2n_psk_set_hmac(struct s2n_psk *psk, s2n_psk_hmac psk_hmac_alg)
+{
+ switch(psk_hmac_alg) {
+ case S2N_PSK_HMAC_SHA224: psk->hmac_alg = S2N_HMAC_SHA224; break;
+ case S2N_PSK_HMAC_SHA256: psk->hmac_alg = S2N_HMAC_SHA256; break;
+ case S2N_PSK_HMAC_SHA384: psk->hmac_alg = S2N_HMAC_SHA384; break;
+ default:
+ BAIL(S2N_ERR_HMAC_INVALID_ALGORITHM);
+ }
+ return S2N_RESULT_OK;
+}
+
+int s2n_connection_set_external_psks(struct s2n_connection *conn, struct s2n_external_psk *psk_vec, size_t psk_vec_length)
+{
+ ENSURE_POSIX_REF(conn);
+ ENSURE_POSIX_REF(psk_vec);
+
+ /* Remove all previously-set external psks */
+ /* The loop iterates from len to 1 instead of from len-1 to 0 to avoid size_t underflowing */
+ for (size_t i = conn->psk_params.psk_list.len; i > 0; i--) {
+ size_t i_index = i - 1;
+ struct s2n_psk *psk = NULL;
+ GUARD_AS_POSIX(s2n_array_get(&conn->psk_params.psk_list, i_index, (void**) &psk));
+ ENSURE_POSIX_REF(psk);
+ if (psk->type == S2N_PSK_TYPE_EXTERNAL) {
+ GUARD(s2n_psk_free(psk));
+ GUARD_AS_POSIX(s2n_array_remove(&conn->psk_params.psk_list, i_index));
+ }
+ }
+
+ for (size_t i = 0; i < psk_vec_length; i++) {
+ /* Check for duplicate identities */
+ size_t array_len = conn->psk_params.psk_list.len;
+ for (size_t j = 0; j < array_len; j++) {
+ struct s2n_psk *psk = NULL;
+ GUARD_AS_POSIX(s2n_array_get(&conn->psk_params.psk_list, j, (void**) &psk));
+ ENSURE_POSIX_REF(psk);
+ if (psk->identity.size == psk_vec[i].identity_length) {
+ ENSURE_POSIX(memcmp(psk->identity.data, psk_vec[i].identity, psk->identity.size) != 0, S2N_ERR_DUPLICATE_PSK_IDENTITIES);
+ }
+ }
+
+ struct s2n_psk *new_psk = NULL;
+ GUARD_AS_POSIX(s2n_array_pushback(&conn->psk_params.psk_list, (void**) &new_psk));
+ ENSURE_POSIX_REF(new_psk);
+ GUARD(s2n_psk_init(new_psk, S2N_PSK_TYPE_EXTERNAL));
+ GUARD(s2n_psk_new_identity(new_psk, psk_vec[i].identity, psk_vec[i].identity_length));
+ GUARD(s2n_psk_new_secret(new_psk, psk_vec[i].secret, psk_vec[i].secret_length));
+ GUARD_AS_POSIX(s2n_psk_set_hmac(new_psk, psk_vec[i].hmac));
+ }
+
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_psk.h b/contrib/restricted/aws/s2n/tls/s2n_psk.h
index a805eaddfa..6d7052c876 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_psk.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_psk.h
@@ -17,7 +17,7 @@
#include <s2n.h>
-#include "crypto/s2n_hash.h"
+#include "crypto/s2n_hmac.h"
#include "utils/s2n_array.h"
#include "utils/s2n_blob.h"
#include "utils/s2n_result.h"
@@ -27,37 +27,71 @@ typedef enum {
S2N_PSK_TYPE_EXTERNAL,
} s2n_psk_type;
+typedef enum {
+ S2N_PSK_KE_UNKNOWN = 0,
+ S2N_PSK_KE,
+ S2N_PSK_DHE_KE,
+} s2n_psk_key_exchange_mode;
+
+typedef enum {
+ S2N_PSK_HMAC_SHA224 = 0,
+ S2N_PSK_HMAC_SHA256,
+ S2N_PSK_HMAC_SHA384,
+} s2n_psk_hmac;
+
+struct s2n_external_psk {
+ uint8_t *identity;
+ size_t identity_length;
+ uint8_t *secret;
+ size_t secret_length;
+ s2n_psk_hmac hmac;
+};
+
struct s2n_psk {
s2n_psk_type type;
struct s2n_blob identity;
struct s2n_blob secret;
- s2n_hash_algorithm hash_alg;
+ s2n_hmac_algorithm hmac_alg;
uint32_t obfuscated_ticket_age;
struct s2n_blob early_secret;
};
+struct s2n_psk_identity {
+ uint8_t *data;
+ uint16_t length;
+};
+
struct s2n_psk_parameters {
struct s2n_array psk_list;
uint16_t binder_list_size;
- uint8_t chosen_psk_wire_index;
+ uint16_t chosen_psk_wire_index;
struct s2n_psk *chosen_psk;
+ s2n_psk_key_exchange_mode psk_ke_mode;
};
+/* This function will be labeled S2N_API and become a publicly visible api once we release the psk API. */
+int s2n_connection_set_external_psks(struct s2n_connection *conn, struct s2n_external_psk *psk_vec, size_t psk_vec_length);
+
int s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type);
int s2n_psk_new_identity(struct s2n_psk *psk, const uint8_t *identity, size_t identity_size);
int s2n_psk_new_secret(struct s2n_psk *psk, const uint8_t *secret, size_t secret_size);
int s2n_psk_free(struct s2n_psk *psk);
S2N_RESULT s2n_psk_parameters_init(struct s2n_psk_parameters *params);
-S2N_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params);
-S2N_RESULT s2n_psk_parameters_free_unused_psks(struct s2n_psk_parameters *params);
-int s2n_psk_parameters_free(struct s2n_psk_parameters *params);
+S2N_CLEANUP_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params);
S2N_RESULT s2n_finish_psk_extension(struct s2n_connection *conn);
-int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hash_algorithm hash_alg,
+int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hmac_algorithm hmac_alg,
const struct s2n_blob *partial_client_hello, struct s2n_blob *output_binder_hash);
int s2n_psk_calculate_binder(struct s2n_psk *psk, const struct s2n_blob *binder_hash,
struct s2n_blob *output_binder);
int s2n_psk_verify_binder(struct s2n_connection *conn, struct s2n_psk *psk,
const struct s2n_blob *partial_client_hello, struct s2n_blob *binder_to_verify);
+
+typedef int (*s2n_psk_selection_callback)(struct s2n_connection *conn,
+ struct s2n_psk_identity *identities, size_t identities_length,
+ uint16_t *chosen_wire_index);
+/* This function will be labeled S2N_API and become a publicly visible api once we release the psk API. */
+int s2n_config_set_psk_selection_callback(struct s2n_connection *conn, s2n_psk_selection_callback cb);
+
diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c b/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c
index 2c2c8df1f1..87207d3723 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c
@@ -71,7 +71,7 @@ int s2n_record_parse_aead(
GUARD(s2n_stuffer_write_bytes(&iv_stuffer, four_zeroes, 4));
GUARD(s2n_stuffer_write_bytes(&iv_stuffer, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
for (int i = 0; i < cipher_suite->record_alg->cipher->io.aead.fixed_iv_size; i++) {
- S2N_INVARIENT(i <= cipher_suite->record_alg->cipher->io.aead.fixed_iv_size);
+ S2N_INVARIANT(i <= cipher_suite->record_alg->cipher->io.aead.fixed_iv_size);
aad_iv[i] = aad_iv[i] ^ implicit_iv[i];
}
} else {
diff --git a/contrib/restricted/aws/s2n/tls/s2n_recv.c b/contrib/restricted/aws/s2n/tls/s2n_recv.c
index 8d0d04d4f0..8aa34e6d06 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_recv.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_recv.c
@@ -117,7 +117,7 @@ int s2n_read_full_record(struct s2n_connection *conn, uint8_t * record_type, int
return 0;
}
-ssize_t s2n_recv(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, s2n_blocked_status * blocked)
{
ssize_t bytes_read = 0;
struct s2n_blob out = {.data = (uint8_t *) buf };
@@ -204,6 +204,15 @@ ssize_t s2n_recv(struct s2n_connection * conn, void *buf, ssize_t size, s2n_bloc
return bytes_read;
}
+ssize_t s2n_recv(struct s2n_connection * conn, void *buf, ssize_t size, s2n_blocked_status * blocked)
+{
+ ENSURE_POSIX(!conn->recv_in_use, S2N_ERR_REENTRANCY);
+ conn->recv_in_use = true;
+ ssize_t result = s2n_recv_impl(conn, buf, size, blocked);
+ conn->recv_in_use = false;
+ return result;
+}
+
uint32_t s2n_peek(struct s2n_connection *conn) {
return s2n_stuffer_data_available(&conn->in);
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
index 2daa495369..388fb25b56 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
@@ -224,6 +224,14 @@ const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2019 = {
.ecc_preferences = &s2n_ecc_preferences_20200310,
};
+const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2021 = {
+ .minimum_protocol_version = S2N_TLS12,
+ .cipher_preferences = &cipher_preferences_cloudfront_tls_1_2_2021,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
/* CloudFront viewer facing legacy TLS 1.2 policies */
const struct s2n_security_policy security_policy_cloudfront_ssl_v_3_legacy = {
.minimum_protocol_version = S2N_SSLv3,
@@ -281,8 +289,6 @@ const struct s2n_security_policy security_policy_kms_tls_1_0_2018_10 = {
.ecc_preferences = &s2n_ecc_preferences_20140601,
};
-#if !defined(S2N_NO_PQ)
-
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,
@@ -331,7 +337,6 @@ const struct s2n_security_policy security_policy_pq_tls_1_0_2020_12 = {
.ecc_preferences = &s2n_ecc_preferences_20200310,
};
-#endif
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,
@@ -463,11 +468,7 @@ const struct s2n_security_policy security_policy_20201021 = {
const struct s2n_security_policy security_policy_test_all = {
.minimum_protocol_version = S2N_SSLv3,
.cipher_preferences = &cipher_preferences_test_all,
-#if !defined(S2N_NO_PQ)
.kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_07,
-#else
- .kem_preferences = &kem_preferences_null,
-#endif
.signature_preferences = &s2n_signature_preferences_20201021,
.ecc_preferences = &s2n_ecc_preferences_test_all,
};
@@ -475,11 +476,7 @@ const struct s2n_security_policy security_policy_test_all = {
const struct s2n_security_policy security_policy_test_all_tls12 = {
.minimum_protocol_version = S2N_SSLv3,
.cipher_preferences = &cipher_preferences_test_all_tls12,
-#if !defined(S2N_NO_PQ)
.kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_07,
-#else
- .kem_preferences = &kem_preferences_null,
-#endif
.signature_preferences = &s2n_signature_preferences_20201021,
.ecc_preferences = &s2n_ecc_preferences_20201021,
};
@@ -488,8 +485,8 @@ const struct s2n_security_policy security_policy_test_all_fips = {
.minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &cipher_preferences_test_all_fips,
.kem_preferences = &kem_preferences_null,
- .signature_preferences = &s2n_signature_preferences_20140601,
- .ecc_preferences = &s2n_ecc_preferences_20140601,
+ .signature_preferences = &s2n_signature_preferences_20201021,
+ .ecc_preferences = &s2n_ecc_preferences_20201021,
};
const struct s2n_security_policy security_policy_test_all_ecdsa = {
@@ -558,6 +555,7 @@ struct s2n_security_policy_selection security_policy_selection[] = {
{ .version="CloudFront-TLS-1-1-2016", .security_policy=&security_policy_cloudfront_tls_1_1_2016, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="CloudFront-TLS-1-2-2018", .security_policy=&security_policy_cloudfront_tls_1_2_2018, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="CloudFront-TLS-1-2-2019", .security_policy=&security_policy_cloudfront_tls_1_2_2019, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="CloudFront-TLS-1-2-2021", .security_policy=&security_policy_cloudfront_tls_1_2_2021, .ecc_extension_required=0, .pq_kem_extension_required=0 },
/* CloudFront Legacy (TLS 1.2) policies */
{ .version="CloudFront-SSL-v-3-Legacy", .security_policy=&security_policy_cloudfront_ssl_v_3_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="CloudFront-TLS-1-0-2014-Legacy", .security_policy=&security_policy_cloudfront_tls_1_0_2014_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 },
@@ -566,14 +564,12 @@ struct s2n_security_policy_selection security_policy_selection[] = {
{ .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 },
{ .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 },
-#if !defined(S2N_NO_PQ)
{ .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 },
{ .version="KMS-PQ-TLS-1-0-2020-02", .security_policy=&security_policy_kms_pq_tls_1_0_2020_02, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="KMS-PQ-TLS-1-0-2020-07", .security_policy=&security_policy_kms_pq_tls_1_0_2020_07, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="PQ-SIKE-TEST-TLS-1-0-2019-11", .security_policy=&security_policy_pq_sike_test_tls_1_0_2019_11, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="PQ-SIKE-TEST-TLS-1-0-2020-02", .security_policy=&security_policy_pq_sike_test_tls_1_0_2020_02, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="PQ-TLS-1-0-2020-12", .security_policy=&security_policy_pq_tls_1_0_2020_12, .ecc_extension_required=0, .pq_kem_extension_required=0 },
-#endif
{ .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="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 },
diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
index ab71889ad7..f724eb1934 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
@@ -79,14 +79,12 @@ extern const struct s2n_security_policy security_policy_elb_fs_1_2_2019_08;
extern const struct s2n_security_policy security_policy_elb_fs_1_1_2019_08;
extern const struct s2n_security_policy security_policy_elb_fs_1_2_res_2019_08;
-#if !defined(S2N_NO_PQ)
extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2019_06;
extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_02;
extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_07;
extern const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2019_11;
extern const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2020_02;
extern const struct s2n_security_policy security_policy_pq_tls_1_0_2020_12;
-#endif
extern const struct s2n_security_policy security_policy_cloudfront_upstream;
extern const struct s2n_security_policy security_policy_cloudfront_upstream_tls10;
@@ -97,6 +95,7 @@ extern const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2016;
extern const struct s2n_security_policy security_policy_cloudfront_tls_1_1_2016;
extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2018;
extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2019;
+extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2021;
extern const struct s2n_security_policy security_policy_kms_tls_1_0_2018_10;
extern const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_send.c b/contrib/restricted/aws/s2n/tls/s2n_send.c
index c9f9cf89d6..4f59054845 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_send.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_send.c
@@ -88,7 +88,7 @@ int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * blocked)
return 0;
}
-ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, ssize_t offs, s2n_blocked_status *blocked)
+ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, ssize_t offs, s2n_blocked_status *blocked)
{
ssize_t user_data_sent, total_size = 0;
@@ -203,6 +203,15 @@ ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *b
return total_size;
}
+ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, ssize_t offs, s2n_blocked_status *blocked)
+{
+ ENSURE_POSIX(!conn->send_in_use, S2N_ERR_REENTRANCY);
+ conn->send_in_use = true;
+ ssize_t result = s2n_sendv_with_offset_impl(conn, bufs, count, offs, blocked);
+ conn->send_in_use = false;
+ return result;
+}
+
ssize_t s2n_sendv(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, s2n_blocked_status *blocked)
{
return s2n_sendv_with_offset(conn, bufs, count, 0, blocked);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c b/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c
index f35c5a0016..a6dda9edf8 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c
@@ -22,7 +22,7 @@
#include "tls/s2n_tls13.h"
#include "tls/s2n_tls13_handshake.h"
#include "utils/s2n_safety.h"
-#include "crypto/s2n_fips.h"
+#include "pq-crypto/s2n_pq.h"
/* From RFC5246 7.4.1.2. */
#define S2N_TLS_COMPRESSION_METHOD_NULL 0
@@ -107,9 +107,9 @@ int s2n_server_hello_retry_recv(struct s2n_connection *conn)
}
if (kem_group != NULL) {
- /* If in FIPS mode, the client should not have sent any PQ IDs
+ /* If PQ is disabled, the client should not have sent any PQ IDs
* in the supported_groups list of the initial ClientHello */
- ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
+ ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) {
if (kem_pref->tls13_kem_groups[i] == kem_group) {
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c b/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c
index 2169f7c5e2..9116868110 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c
@@ -49,7 +49,7 @@ int s2n_server_key_recv(struct s2n_connection *conn)
/* Read the KEX data */
struct s2n_kex_raw_server_data kex_data = {0};
- GUARD(s2n_kex_server_key_recv_read_data(key_exchange, conn, &data_to_verify, &kex_data));
+ GUARD_AS_POSIX(s2n_kex_server_key_recv_read_data(key_exchange, conn, &data_to_verify, &kex_data));
/* Add common signature data */
struct s2n_signature_scheme active_sig_scheme;
@@ -81,7 +81,7 @@ int s2n_server_key_recv(struct s2n_connection *conn)
GUARD(s2n_pkey_free(&conn->secure.server_public_key));
/* Parse the KEX data into whatever form needed and save it to the connection object */
- GUARD(s2n_kex_server_key_recv_parse_data(key_exchange, conn, &kex_data));
+ GUARD_AS_POSIX(s2n_kex_server_key_recv_parse_data(key_exchange, conn, &kex_data));
return 0;
}
@@ -209,10 +209,10 @@ int s2n_hybrid_server_key_recv_read_data(struct s2n_connection *conn, struct s2n
notnull_check(total_data_to_verify->data);
struct s2n_blob data_to_verify_0 = {0};
- GUARD(s2n_kex_server_key_recv_read_data(hybrid_kex_0, conn, &data_to_verify_0, raw_server_data));
+ GUARD_AS_POSIX(s2n_kex_server_key_recv_read_data(hybrid_kex_0, conn, &data_to_verify_0, raw_server_data));
struct s2n_blob data_to_verify_1 = {0};
- GUARD(s2n_kex_server_key_recv_read_data(hybrid_kex_1, conn, &data_to_verify_1, raw_server_data));
+ GUARD_AS_POSIX(s2n_kex_server_key_recv_read_data(hybrid_kex_1, conn, &data_to_verify_1, raw_server_data));
total_data_to_verify->size = data_to_verify_0.size + data_to_verify_1.size;
return 0;
@@ -226,8 +226,8 @@ int s2n_hybrid_server_key_recv_parse_data(struct s2n_connection *conn, struct s2
const struct s2n_kex *hybrid_kex_0 = kex->hybrid[0];
const struct s2n_kex *hybrid_kex_1 = kex->hybrid[1];
- GUARD(s2n_kex_server_key_recv_parse_data(hybrid_kex_0, conn, raw_server_data));
- GUARD(s2n_kex_server_key_recv_parse_data(hybrid_kex_1, conn, raw_server_data));
+ GUARD_AS_POSIX(s2n_kex_server_key_recv_parse_data(hybrid_kex_0, conn, raw_server_data));
+ GUARD_AS_POSIX(s2n_kex_server_key_recv_parse_data(hybrid_kex_1, conn, raw_server_data));
return 0;
}
@@ -241,7 +241,7 @@ int s2n_server_key_send(struct s2n_connection *conn)
struct s2n_blob data_to_sign = {0};
/* Call the negotiated key exchange method to send it's data */
- GUARD(s2n_kex_server_key_send(key_exchange, conn, &data_to_sign));
+ GUARD_AS_POSIX(s2n_kex_server_key_send(key_exchange, conn, &data_to_sign));
/* Add common signature data */
if (conn->actual_protocol_version == S2N_TLS12) {
@@ -315,10 +315,10 @@ int s2n_hybrid_server_key_send(struct s2n_connection *conn, struct s2n_blob *tot
notnull_check(total_data_to_sign->data);
struct s2n_blob data_to_verify_0 = {0};
- GUARD(s2n_kex_server_key_send(hybrid_kex_0, conn, &data_to_verify_0));
+ GUARD_AS_POSIX(s2n_kex_server_key_send(hybrid_kex_0, conn, &data_to_verify_0));
struct s2n_blob data_to_verify_1 = {0};
- GUARD(s2n_kex_server_key_send(hybrid_kex_1, conn, &data_to_verify_1));
+ GUARD_AS_POSIX(s2n_kex_server_key_send(hybrid_kex_1, conn, &data_to_verify_1));
total_data_to_sign->size = data_to_verify_0.size + data_to_verify_1.size;
return 0;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c
index fe000814e7..4382c02382 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c
@@ -189,7 +189,9 @@ int s2n_tls13_handle_handshake_secrets(struct s2n_connection *conn)
GUARD(s2n_tls13_compute_shared_secret(conn, &shared_secret));
/* derive early secrets */
- GUARD(s2n_tls13_derive_early_secrets(&secrets));
+ GUARD(s2n_tls13_derive_early_secrets(&secrets, conn->psk_params.chosen_psk));
+ /* since early secrets have been computed, PSKs are no longer needed and can be cleaned up */
+ GUARD_AS_POSIX(s2n_psk_parameters_wipe(&conn->psk_params));
/* produce handshake secrets */
s2n_stack_blob(client_hs_secret, secrets.size, S2N_TLS13_SECRET_MAX_LEN);
@@ -315,6 +317,19 @@ static int s2n_tls13_handle_master_secret(struct s2n_connection *conn)
return S2N_SUCCESS;
}
+static int s2n_tls13_handle_resumption_master_secret(struct s2n_connection *conn)
+{
+ s2n_tls13_connection_keys(keys, conn);
+
+ struct s2n_hash_state hash_state = {0};
+ GUARD(s2n_handshake_get_hash_state(conn, keys.hash_algorithm, &hash_state));
+
+ struct s2n_blob resumption_master_secret = {0};
+ GUARD(s2n_blob_init(&resumption_master_secret, conn->resumption_master_secret, keys.size));
+ GUARD(s2n_tls13_derive_resumption_master_secret(&keys, &hash_state, &resumption_master_secret));
+ return S2N_SUCCESS;
+}
+
int s2n_tls13_handle_secrets(struct s2n_connection *conn)
{
notnull_check(conn);
@@ -341,6 +356,7 @@ int s2n_tls13_handle_secrets(struct s2n_connection *conn)
GUARD(s2n_tls13_handle_application_secret(conn, S2N_SERVER));
}
GUARD(s2n_tls13_handle_application_secret(conn, S2N_CLIENT));
+ GUARD(s2n_tls13_handle_resumption_master_secret(conn));
break;
default:
break;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h b/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
index 1980a69138..7bce43d0b2 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
@@ -106,12 +106,22 @@
#define TLS_EXTENSION_RENEGOTIATION_INFO 65281
/* TLS 1.3 extensions from https://tools.ietf.org/html/rfc8446#section-4.2 */
-#define TLS_EXTENSION_SUPPORTED_VERSIONS 43
-#define TLS_EXTENSION_COOKIE 44
-#define TLS_EXTENSION_KEY_SHARE 51
-
-/* QUIC-TLS extension from https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-8.2 */
-#define TLS_QUIC_TRANSPORT_PARAMETERS 65535
+#define TLS_EXTENSION_SUPPORTED_VERSIONS 43
+#define TLS_EXTENSION_COOKIE 44
+#define TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES 45
+#define TLS_EXTENSION_KEY_SHARE 51
+
+/* TLS 1.3 pre-shared key exchange modes from https://tools.ietf.org/html/rfc8446#section-4.2.9 */
+#define TLS_PSK_KE_MODE 0
+#define TLS_PSK_DHE_KE_MODE 1
+
+/**
+ *= https://tools.ietf.org/id/draft-ietf-quic-tls-32.txt#8.2
+ *# enum {
+ *# quic_transport_parameters(0xffa5), (65535)
+ *# } ExtensionType;
+ */
+#define TLS_QUIC_TRANSPORT_PARAMETERS 0xffa5
/* TLS Signature Algorithms - RFC 5246 7.4.1.4.1 */
/* https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16 */
diff --git a/contrib/restricted/aws/s2n/utils/s2n_annotations.h b/contrib/restricted/aws/s2n/utils/s2n_annotations.h
index 4a004c92a1..0d6c01dd05 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_annotations.h
+++ b/contrib/restricted/aws/s2n/utils/s2n_annotations.h
@@ -16,4 +16,4 @@
/* For compilation purposes, these annotations are no-ops */
#define S2N_PUBLIC_INPUT(__a)
-#define S2N_INVARIENT(__a)
+#define S2N_INVARIANT(__a)
diff --git a/contrib/restricted/aws/s2n/utils/s2n_result.h b/contrib/restricted/aws/s2n/utils/s2n_result.h
index 9a1b3ed13a..c135c55074 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_result.h
+++ b/contrib/restricted/aws/s2n/utils/s2n_result.h
@@ -44,5 +44,10 @@ S2N_RESULT_MUST_USE bool s2n_result_is_error(s2n_result result);
/* used in function declarations to signal function fallibility */
#define S2N_RESULT S2N_RESULT_MUST_USE s2n_result
+/* The DEFER_CLEANUP macro discards the result of its cleanup function.
+ * We need a version of s2n_result which can be ignored.
+ */
+#define S2N_CLEANUP_RESULT s2n_result
+
/* converts the S2N_RESULT into posix error codes */
#define S2N_RESULT_TO_POSIX( x ) (s2n_result_is_ok(x) ? S2N_SUCCESS : S2N_FAILURE)
diff --git a/contrib/restricted/aws/s2n/utils/s2n_safety.c b/contrib/restricted/aws/s2n/utils/s2n_safety.c
index d786c4d852..13c741b3ec 100644
--- a/contrib/restricted/aws/s2n/utils/s2n_safety.c
+++ b/contrib/restricted/aws/s2n/utils/s2n_safety.c
@@ -60,6 +60,8 @@ bool s2n_constant_time_equals(const uint8_t * a, const uint8_t * b, const uint32
S2N_PUBLIC_INPUT(a);
S2N_PUBLIC_INPUT(b);
S2N_PUBLIC_INPUT(len);
+ ENSURE_POSIX((a == NULL) || S2N_MEM_IS_READABLE(a, len), S2N_ERR_SAFETY);
+ ENSURE_POSIX((b == NULL) || S2N_MEM_IS_READABLE(b, len), S2N_ERR_SAFETY);
if (len != 0 && (a == NULL || b == NULL)) {
return false;
@@ -69,7 +71,7 @@ bool s2n_constant_time_equals(const uint8_t * a, const uint8_t * b, const uint32
for (int i = 0; i < len; i++) {
/* Invariants must hold for each execution of the loop
* and at loop exit, hence the <= */
- S2N_INVARIENT(i <= len);
+ S2N_INVARIANT(i <= len);
xor |= a[i] ^ b[i];
}
diff --git a/contrib/restricted/aws/s2n/ya.make b/contrib/restricted/aws/s2n/ya.make
index f216afee82..f6de16d8f0 100644
--- a/contrib/restricted/aws/s2n/ya.make
+++ b/contrib/restricted/aws/s2n/ya.make
@@ -7,9 +7,9 @@ OWNER(
g:cpp-contrib
)
-VERSION(0.10.23)
+VERSION(0.10.26)
-ORIGINAL_SOURCE(https://github.com/aws/s2n-tls/archive/v0.10.23.tar.gz)
+ORIGINAL_SOURCE(https://github.com/aws/s2n-tls/archive/v0.10.26.tar.gz)
LICENSE(
Apache-2.0 AND
@@ -162,11 +162,13 @@ SRCS(
tls/extensions/s2n_extension_type.c
tls/extensions/s2n_extension_type_lists.c
tls/extensions/s2n_key_share.c
+ tls/extensions/s2n_psk_key_exchange_modes.c
tls/extensions/s2n_quic_transport_params.c
tls/extensions/s2n_server_alpn.c
tls/extensions/s2n_server_certificate_status.c
tls/extensions/s2n_server_key_share.c
tls/extensions/s2n_server_max_fragment_length.c
+ tls/extensions/s2n_server_psk.c
tls/extensions/s2n_server_renegotiation_info.c
tls/extensions/s2n_server_sct_list.c
tls/extensions/s2n_server_server_name.c