aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/s2n/tls
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.ru>2022-05-10 22:16:03 +0300
committerthegeorg <thegeorg@yandex-team.ru>2022-05-10 22:16:03 +0300
commit09c71d918d4d0b0ebf67e1ab41aa90ddf587a3f2 (patch)
treedd44d2cb68e2845c2d4c367b66893f3e043a6e8e /contrib/restricted/aws/s2n/tls
parent5eb4a8a2d487411924e1d1b27c454223dcf35005 (diff)
downloadydb-09c71d918d4d0b0ebf67e1ab41aa90ddf587a3f2.tar.gz
Update contrib/restricted/aws/s2n to 1.3.12
ref:f8279d764b4c00974a63543a1364c91e2b81b7a6
Diffstat (limited to 'contrib/restricted/aws/s2n/tls')
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c60
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_early_data_indication.c186
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_ems.c63
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.c467
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_max_frag_len.c24
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c14
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c321
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_server_name.c37
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_session_ticket.c12
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_status_request.c8
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.c78
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.c25
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.c28
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_early_data_indication.h22
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c4
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_ems.h21
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c70
-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.c83
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h4
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c42
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.c34
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.h3
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_nst_early_data_indication.c80
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c20
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.c27
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c20
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c44
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_early_data_indication.c106
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_ems.c74
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.c257
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_max_fragment_length.c34
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c24
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c6
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_sct_list.c14
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_server_name.c4
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_session_ticket.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_status_request.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.c17
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.c16
-rw-r--r--contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_aead.c107
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_alerts.c160
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_alerts.h78
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_async_pkey.c445
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_async_pkey.h22
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_auth_selection.c64
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_auth_selection.h1
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cbc.c31
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_change_cipher_spec.c20
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c635
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h30
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c162
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h9
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_cert.c103
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c72
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_finished.c36
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_hello.c440
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_hello.h15
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_hello_request.c40
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c130
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.c391
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_config.h53
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection.c1215
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection.h143
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c112
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.h36
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_crypto.h38
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_early_data.c435
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_early_data.h63
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_early_data_io.c275
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c15
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_encrypted_extensions.c12
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_establish_session.c13
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake.c160
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake.h123
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake_hashes.c126
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake_hashes.h44
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake_io.c660
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake_transcript.c69
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake_type.c73
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_handshake_type.h90
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_internal.h57
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kem.c328
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kem.h62
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c64
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_kex.c156
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_key_log.c174
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_key_log.h27
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_key_update.c52
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_key_update.h2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c2
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_post_handshake.c71
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_prf.c655
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_prf.h27
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c141
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.h23
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_psk.c597
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_psk.h68
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_quic_support.c54
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_quic_support.h21
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_record.h53
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_record_read.c43
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c39
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_record_read_cbc.c54
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_record_read_composite.c38
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_record_read_stream.c38
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_record_write.c185
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_recv.c61
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_resume.c741
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_resume.h39
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_security_policies.c357
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_security_policies.h22
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_send.c40
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_cert.c24
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_cert_request.c59
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_extensions.c22
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_finished.c38
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_hello.c149
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c76
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c156
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c357
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_shutdown.c23
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c117
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.h6
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c18
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h3
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls.h6
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13.c81
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13.h11
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.c70
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c357
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.h6
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.c328
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.h22
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c626
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.h55
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls_digest_preferences.h38
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h69
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_x509_validator.c103
-rw-r--r--contrib/restricted/aws/s2n/tls/s2n_x509_validator.h22
145 files changed, 11405 insertions, 4841 deletions
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c
index e66b7c0478..b7fd2678ed 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c
@@ -19,6 +19,7 @@
#include "tls/extensions/s2n_client_alpn.h"
#include "tls/extensions/s2n_extension_type.h"
+#include "tls/s2n_protocol_preferences.h"
#include "tls/s2n_tls.h"
#include "tls/s2n_tls_parameters.h"
@@ -48,11 +49,11 @@ static bool s2n_client_alpn_should_send(struct s2n_connection *conn)
static int s2n_client_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
struct s2n_blob *client_app_protocols;
- GUARD(s2n_connection_get_protocol_preferences(conn, &client_app_protocols));
- notnull_check(client_app_protocols);
+ POSIX_GUARD(s2n_connection_get_protocol_preferences(conn, &client_app_protocols));
+ POSIX_ENSURE_REF(client_app_protocols);
- GUARD(s2n_stuffer_write_uint16(out, client_app_protocols->size));
- GUARD(s2n_stuffer_write(out, client_app_protocols));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, client_app_protocols->size));
+ POSIX_GUARD(s2n_stuffer_write(out, client_app_protocols));
return S2N_SUCCESS;
}
@@ -60,18 +61,17 @@ static int s2n_client_alpn_send(struct s2n_connection *conn, struct s2n_stuffer
static int s2n_client_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
uint16_t size_of_all;
- struct s2n_stuffer client_protos = {0};
struct s2n_stuffer server_protos = {0};
struct s2n_blob *server_app_protocols;
- GUARD(s2n_connection_get_protocol_preferences(conn, &server_app_protocols));
+ POSIX_GUARD(s2n_connection_get_protocol_preferences(conn, &server_app_protocols));
if (!server_app_protocols->size) {
/* No protocols configured, nothing to do */
return S2N_SUCCESS;
}
- GUARD(s2n_stuffer_read_uint16(extension, &size_of_all));
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &size_of_all));
if (size_of_all > s2n_stuffer_data_available(extension) || size_of_all < 3) {
/* Malformed length, ignore the extension */
return S2N_SUCCESS;
@@ -80,38 +80,26 @@ static int s2n_client_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer
struct s2n_blob client_app_protocols = { 0 };
client_app_protocols.size = size_of_all;
client_app_protocols.data = s2n_stuffer_raw_read(extension, size_of_all);
- notnull_check(client_app_protocols.data);
+ POSIX_ENSURE_REF(client_app_protocols.data);
/* Find a matching protocol */
- GUARD(s2n_stuffer_init(&client_protos, &client_app_protocols));
- GUARD(s2n_stuffer_write(&client_protos, &client_app_protocols));
- GUARD(s2n_stuffer_init(&server_protos, server_app_protocols));
- GUARD(s2n_stuffer_write(&server_protos, server_app_protocols));
-
- while (s2n_stuffer_data_available(&server_protos)) {
- uint8_t length;
- uint8_t server_protocol[255];
- GUARD(s2n_stuffer_read_uint8(&server_protos, &length));
- GUARD(s2n_stuffer_read_bytes(&server_protos, server_protocol, length));
-
- while (s2n_stuffer_data_available(&client_protos)) {
- uint8_t client_length;
- GUARD(s2n_stuffer_read_uint8(&client_protos, &client_length));
- S2N_ERROR_IF(client_length > s2n_stuffer_data_available(&client_protos), S2N_ERR_BAD_MESSAGE);
- if (client_length != length) {
- GUARD(s2n_stuffer_skip_read(&client_protos, client_length));
- } else {
- uint8_t client_protocol[255];
- GUARD(s2n_stuffer_read_bytes(&client_protos, client_protocol, client_length));
- if (memcmp(client_protocol, server_protocol, client_length) == 0) {
- memcpy_check(conn->application_protocol, client_protocol, client_length);
- conn->application_protocol[client_length] = '\0';
- return S2N_SUCCESS;
- }
- }
+ POSIX_GUARD(s2n_stuffer_init(&server_protos, server_app_protocols));
+ POSIX_GUARD(s2n_stuffer_skip_write(&server_protos, server_app_protocols->size));
+
+ while (s2n_stuffer_data_available(&server_protos) > 0) {
+ struct s2n_blob server_protocol = { 0 };
+ POSIX_ENSURE(s2n_result_is_ok(s2n_protocol_preferences_read(&server_protos, &server_protocol)),
+ S2N_ERR_BAD_MESSAGE);
+
+ bool is_match = false;
+ POSIX_ENSURE(s2n_result_is_ok(s2n_protocol_preferences_contain(&client_app_protocols, &server_protocol, &is_match)),
+ S2N_ERR_BAD_MESSAGE);
+
+ if (is_match) {
+ POSIX_CHECKED_MEMCPY(conn->application_protocol, server_protocol.data, server_protocol.size);
+ conn->application_protocol[server_protocol.size] = '\0';
+ return S2N_SUCCESS;
}
-
- GUARD(s2n_stuffer_reread(&client_protos));
}
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_early_data_indication.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_early_data_indication.c
new file mode 100644
index 0000000000..3cfea591cd
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_early_data_indication.c
@@ -0,0 +1,186 @@
+/*
+ * 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 "api/s2n.h"
+
+#include "tls/extensions/s2n_early_data_indication.h"
+
+#include "tls/extensions/s2n_client_psk.h"
+#include "tls/s2n_cipher_suites.h"
+#include "tls/s2n_early_data.h"
+#include "tls/s2n_protocol_preferences.h"
+#include "tls/s2n_tls13.h"
+#include "utils/s2n_safety.h"
+
+/* S2N determines the handshake type after the ServerHello, but that will be
+ * too late to handle the early data + middlebox compatibility case:
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-D.4
+ *# - If not offering early data, the client sends a dummy
+ *# change_cipher_spec record (see the third paragraph of Section 5)
+ *# immediately before its second flight. This may either be before
+ *# its second ClientHello or before its encrypted handshake flight.
+ *# If offering early data, the record is placed immediately after the
+ *# first ClientHello.
+ *
+ * We need to set the handshake type flags in question during the ClientHello.
+ * This will require special [INITIAL | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS]
+ * entries in the handshake arrays.
+ */
+static S2N_RESULT s2n_setup_middlebox_compat_for_early_data(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+
+ if (s2n_is_middlebox_compat_enabled(conn)) {
+ RESULT_GUARD(s2n_handshake_type_set_tls13_flag(conn, MIDDLEBOX_COMPAT));
+ RESULT_GUARD(s2n_handshake_type_set_tls13_flag(conn, EARLY_CLIENT_CCS));
+ }
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_early_data_config_is_possible(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+
+ struct s2n_psk *first_psk = NULL;
+ RESULT_GUARD(s2n_array_get(&conn->psk_params.psk_list, 0, (void**) &first_psk));
+ RESULT_ENSURE_REF(first_psk);
+
+ struct s2n_early_data_config *early_data_config = &first_psk->early_data_config;
+
+ /* Must support early data */
+ RESULT_ENSURE_GT(early_data_config->max_early_data_size, 0);
+
+ /* Early data must require a protocol than we could negotiate */
+ RESULT_ENSURE_GTE(s2n_connection_get_protocol_version(conn), early_data_config->protocol_version);
+ RESULT_ENSURE_GTE(s2n_connection_get_protocol_version(conn), S2N_TLS13);
+
+ const struct s2n_cipher_preferences *cipher_preferences = NULL;
+ RESULT_GUARD_POSIX(s2n_connection_get_cipher_preferences(conn, &cipher_preferences));
+ RESULT_ENSURE_REF(cipher_preferences);
+
+ /* Early data must require a supported cipher */
+ bool match = false;
+ for (uint8_t i = 0; i < cipher_preferences->count; i++) {
+ if (cipher_preferences->suites[i] == early_data_config->cipher_suite) {
+ match = true;
+ break;
+ }
+ }
+ RESULT_ENSURE_EQ(match, true);
+
+ /* If early data specifies an application protocol, it must be supported by protocol preferences */
+ if (early_data_config->application_protocol.size > 0) {
+ struct s2n_blob *application_protocols = NULL;
+ RESULT_GUARD_POSIX(s2n_connection_get_protocol_preferences(conn, &application_protocols));
+ RESULT_ENSURE_REF(application_protocols);
+
+ match = false;
+ RESULT_GUARD(s2n_protocol_preferences_contain(application_protocols, &early_data_config->application_protocol, &match));
+ RESULT_ENSURE_EQ(match, true);
+ }
+
+ return S2N_RESULT_OK;
+}
+
+static bool s2n_client_early_data_indication_should_send(struct s2n_connection *conn)
+{
+ return s2n_result_is_ok(s2n_early_data_config_is_possible(conn))
+ && conn && conn->early_data_expected
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# A client MUST NOT include the
+ *# "early_data" extension in its followup ClientHello.
+ **/
+ && !s2n_is_hello_retry_handshake(conn)
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# When a PSK is used and early data is allowed for that PSK, the client
+ *# can send Application Data in its first flight of messages. If the
+ *# client opts to do so, it MUST supply both the "pre_shared_key" and
+ *# "early_data" extensions.
+ */
+ && s2n_client_psk_extension.should_send(conn);
+}
+
+static int s2n_client_early_data_indication_is_missing(struct s2n_connection *conn)
+{
+ if (conn->early_data_state != S2N_EARLY_DATA_REJECTED) {
+ POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_NOT_REQUESTED));
+ }
+ return S2N_SUCCESS;
+}
+
+/**
+ * The client version of this extension is empty, so we don't read/write any data.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# The "extension_data" field of this extension contains an
+ *# "EarlyDataIndication" value.
+ *#
+ *# struct {} Empty;
+ *#
+ *# struct {
+ *# select (Handshake.msg_type) {
+ **
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# case client_hello: Empty;
+ **
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# };
+ *# } EarlyDataIndication;
+ **/
+
+static int s2n_client_early_data_indication_send(struct s2n_connection *conn, struct s2n_stuffer *out)
+{
+ POSIX_GUARD_RESULT(s2n_setup_middlebox_compat_for_early_data(conn));
+ POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_REQUESTED));
+
+ /* Set the cipher suite for early data */
+ struct s2n_psk *first_psk = NULL;
+ POSIX_GUARD_RESULT(s2n_array_get(&conn->psk_params.psk_list, 0, (void**) &first_psk));
+ POSIX_ENSURE_REF(first_psk);
+ conn->secure.cipher_suite = first_psk->early_data_config.cipher_suite;
+
+ return S2N_SUCCESS;
+}
+
+static int s2n_client_early_data_indiction_recv(struct s2n_connection *conn, struct s2n_stuffer *in)
+{
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# A client MUST NOT include the
+ *# "early_data" extension in its followup ClientHello.
+ */
+ POSIX_ENSURE(conn->handshake.message_number == 0, S2N_ERR_UNSUPPORTED_EXTENSION);
+
+ /* Although technically we could NOT set the [MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] handshake type
+ * for the server because the server ignores the Client CCS message state, doing so would mean that
+ * the client and server state machines would be out of sync and potentially cause confusion.
+ */
+ POSIX_GUARD_RESULT(s2n_setup_middlebox_compat_for_early_data(conn));
+
+ POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_REQUESTED));
+ return S2N_SUCCESS;
+}
+
+const s2n_extension_type s2n_client_early_data_indication_extension = {
+ .iana_value = TLS_EXTENSION_EARLY_DATA,
+ .is_response = false,
+ .send = s2n_client_early_data_indication_send,
+ .recv = s2n_client_early_data_indiction_recv,
+ .should_send = s2n_client_early_data_indication_should_send,
+ .if_missing = s2n_client_early_data_indication_is_missing,
+};
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_ems.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_ems.c
new file mode 100644
index 0000000000..36ec3d339f
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_ems.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#include <sys/param.h>
+#include <stdint.h>
+
+#include "tls/s2n_tls.h"
+#include "tls/extensions/s2n_ems.h"
+
+#include "utils/s2n_safety.h"
+
+static int s2n_client_ems_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
+static bool s2n_client_ems_should_send(struct s2n_connection *conn);
+
+/**
+ *= https://tools.ietf.org/rfc/rfc7627#section-5.1
+ *#
+ *# This document defines a new TLS extension, "extended_master_secret"
+ *# (with extension type 0x0017), which is used to signal both client and
+ *# server to use the extended master secret computation. The
+ *# "extension_data" field of this extension is empty. Thus, the entire
+ *# encoding of the extension is 00 17 00 00 (in hexadecimal.)
+ **/
+const s2n_extension_type s2n_client_ems_extension = {
+ .iana_value = TLS_EXTENSION_EMS,
+ .is_response = false,
+ .send = s2n_extension_send_noop,
+ .recv = s2n_client_ems_recv,
+ .should_send = s2n_client_ems_should_send,
+ .if_missing = s2n_extension_noop_if_missing,
+};
+
+static int s2n_client_ems_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
+{
+ POSIX_ENSURE_REF(conn);
+
+ /* Read nothing. The extension just needs to exist. */
+ conn->ems_negotiated = true;
+
+ return S2N_SUCCESS;
+}
+
+static bool s2n_client_ems_should_send(struct s2n_connection *conn)
+{
+ /* Don't send this extension if the previous session did not negotiate EMS */
+ if (conn->set_session && !conn->ems_negotiated) {
+ return false;
+ } else {
+ return true;
+ }
+}
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 178f2e9c1d..6073263014 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
@@ -24,8 +24,6 @@
#include "tls/s2n_tls13.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)
/**
* Specified in https://tools.ietf.org/html/rfc8446#section-4.2.8
* "The "key_share" extension contains the endpoint's cryptographic parameters."
@@ -54,64 +52,57 @@ static int s2n_client_key_share_recv(struct s2n_connection *conn, struct s2n_stu
const s2n_extension_type s2n_client_key_share_extension = {
.iana_value = TLS_EXTENSION_KEY_SHARE,
+ .minimum_version = S2N_TLS13,
.is_response = false,
.send = s2n_client_key_share_send,
.recv = s2n_client_key_share_recv,
- .should_send = s2n_extension_send_if_tls13_connection,
+ .should_send = s2n_extension_always_send,
.if_missing = s2n_extension_noop_if_missing,
};
-static int s2n_generate_preferred_ecc_key_shares(struct s2n_connection *conn, struct s2n_stuffer *out)
+static int s2n_generate_default_ecc_key_share(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- notnull_check(conn);
- uint8_t preferred_key_shares = conn->preferred_key_shares;
- struct s2n_ecc_evp_params *ecc_evp_params = NULL;
-
+ POSIX_ENSURE_REF(conn);
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
- /* If lsb is set, skip keyshare generation for all curve */
- if (S2N_IS_KEY_SHARE_LIST_EMPTY(preferred_key_shares)) {
- return S2N_SUCCESS;
- }
+ /* We only ever send a single EC key share: either the share requested by the server
+ * during a retry, or the most preferred share according to local preferences.
+ */
+ struct s2n_ecc_evp_params *client_params = &conn->kex_params.client_ecc_evp_params;
+ if (s2n_is_hello_retry_handshake(conn)) {
+ const struct s2n_ecc_named_curve *server_curve = conn->kex_params.server_ecc_evp_params.negotiated_curve;
- for (size_t i = 0; i < ecc_pref->count; i++) {
- /* If a bit in the bitmap (minus the lsb) is set, generate keyshare for the corresponding curve */
- if (S2N_IS_KEY_SHARE_REQUESTED(preferred_key_shares, i)) {
- ecc_evp_params = &conn->secure.client_ecc_evp_params[i];
- ecc_evp_params->negotiated_curve = ecc_pref->ecc_curves[i];
- GUARD(s2n_ecdhe_parameters_send(ecc_evp_params, out));
+ /* If the server did not request a specific ECC keyshare, don't send one */
+ if (!server_curve) {
+ return S2N_SUCCESS;
}
- }
- return S2N_SUCCESS;
-}
-
-static int s2n_generate_default_ecc_key_share(struct s2n_connection *conn, struct s2n_stuffer *out)
-{
- notnull_check(conn);
- const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ /* If the server requested a new ECC keyshare, free the old one */
+ if (server_curve != client_params->negotiated_curve) {
+ POSIX_GUARD(s2n_ecc_evp_params_free(client_params));
+ }
- struct s2n_ecc_evp_params *ecc_evp_params = NULL;
- ecc_evp_params = &conn->secure.client_ecc_evp_params[0];
- ecc_evp_params->negotiated_curve = ecc_pref->ecc_curves[0];
- GUARD(s2n_ecdhe_parameters_send(ecc_evp_params, out));
+ client_params->negotiated_curve = server_curve;
+ } else {
+ client_params->negotiated_curve = ecc_pref->ecc_curves[0];
+ }
+ POSIX_GUARD(s2n_ecdhe_parameters_send(client_params, out));
return S2N_SUCCESS;
}
-static int s2n_generate_pq_hybrid_key_share(struct s2n_stuffer *out, struct s2n_kem_group_params *kem_group_params) {
- notnull_check(out);
- notnull_check(kem_group_params);
+static int s2n_generate_pq_hybrid_key_share(struct s2n_stuffer *out, struct s2n_kem_group_params *kem_group_params)
+{
+ POSIX_ENSURE_REF(out);
+ POSIX_ENSURE_REF(kem_group_params);
/* This function should never be called when PQ is disabled */
- ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
+ POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
const struct s2n_kem_group *kem_group = kem_group_params->kem_group;
- notnull_check(kem_group);
+ POSIX_ENSURE_REF(kem_group);
/* The structure of the PQ share is:
* IANA ID (2 bytes)
@@ -120,29 +111,28 @@ static int s2n_generate_pq_hybrid_key_share(struct s2n_stuffer *out, struct s2n_
* || ECC key share (variable bytes)
* || size of PQ key share (2 bytes)
* || PQ key share (variable bytes) */
- GUARD(s2n_stuffer_write_uint16(out, kem_group->iana_id));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, kem_group->iana_id));
struct s2n_stuffer_reservation total_share_size = {0};
- GUARD(s2n_stuffer_reserve_uint16(out, &total_share_size));
+ POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &total_share_size));
struct s2n_ecc_evp_params *ecc_params = &kem_group_params->ecc_params;
ecc_params->negotiated_curve = kem_group->curve;
- GUARD(s2n_stuffer_write_uint16(out, ecc_params->negotiated_curve->share_size));
- GUARD(s2n_ecc_evp_generate_ephemeral_key(ecc_params));
- GUARD(s2n_ecc_evp_write_params_point(ecc_params, out));
+ POSIX_GUARD_RESULT(s2n_ecdhe_send_public_key(ecc_params, out));
struct s2n_kem_params *kem_params = &kem_group_params->kem_params;
kem_params->kem = kem_group->kem;
- GUARD(s2n_kem_send_public_key(out, kem_params));
+ POSIX_GUARD(s2n_kem_send_public_key(out, kem_params));
- GUARD(s2n_stuffer_write_vector_size(&total_share_size));
+ POSIX_GUARD(s2n_stuffer_write_vector_size(&total_share_size));
return S2N_SUCCESS;
}
-static int s2n_generate_default_pq_hybrid_key_share(struct s2n_connection *conn, struct s2n_stuffer *out) {
- notnull_check(conn);
- notnull_check(out);
+static int s2n_generate_default_pq_hybrid_key_share(struct s2n_connection *conn, struct s2n_stuffer *out)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(out);
/* Client should skip sending PQ groups/key shares if PQ is disabled */
if (!s2n_pq_is_enabled()) {
@@ -150,206 +140,113 @@ static int s2n_generate_default_pq_hybrid_key_share(struct s2n_connection *conn,
}
const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
+ POSIX_ENSURE_REF(kem_pref);
if (kem_pref->tls13_kem_group_count == 0) {
return S2N_SUCCESS;
}
- /* We only send a single PQ key share - the highest preferred one */
- struct s2n_kem_group_params *kem_group_params = &conn->secure.client_kem_group_params[0];
- kem_group_params->kem_group = kem_pref->tls13_kem_groups[0];
-
- GUARD(s2n_generate_pq_hybrid_key_share(out, kem_group_params));
-
- return S2N_SUCCESS;
-}
-
-static int s2n_wipe_all_client_keyshares(struct s2n_connection *conn) {
- notnull_check(conn);
-
- const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
-
- const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
-
- for (size_t i = 0; i < ecc_pref->count; i++) {
- GUARD(s2n_ecc_evp_params_free(&conn->secure.client_ecc_evp_params[i]));
- conn->secure.client_ecc_evp_params[i].negotiated_curve = NULL;
- }
-
- for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) {
- GUARD(s2n_kem_group_free(&conn->secure.client_kem_group_params[i]));
- conn->secure.client_kem_group_params[i].kem_group = NULL;
- conn->secure.client_kem_group_params[i].kem_params.kem = NULL;
- conn->secure.client_kem_group_params[i].ecc_params.negotiated_curve = NULL;
- }
-
- return S2N_SUCCESS;
-}
-
-static int s2n_send_hrr_ecc_keyshare(struct s2n_connection *conn, struct s2n_stuffer *out)
-{
- notnull_check(conn);
- const struct s2n_ecc_named_curve *server_negotiated_curve = NULL;
- struct s2n_ecc_evp_params *ecc_evp_params = NULL;
-
- const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
-
- server_negotiated_curve = conn->secure.server_ecc_evp_params.negotiated_curve;
- ENSURE_POSIX(server_negotiated_curve != NULL, S2N_ERR_BAD_KEY_SHARE);
- ENSURE_POSIX(s2n_ecc_preferences_includes_curve(ecc_pref, server_negotiated_curve->iana_id),
- S2N_ERR_INVALID_HELLO_RETRY);
+ /* We only ever send a single PQ key share: either the share requested by the server
+ * during a retry, or the most preferred share according to local preferences.
+ */
+ struct s2n_kem_group_params *client_params = &conn->kex_params.client_kem_group_params;
+ if (s2n_is_hello_retry_handshake(conn)) {
+ const struct s2n_kem_group *server_group = conn->kex_params.server_kem_group_params.kem_group;
- for (size_t i = 0; i < ecc_pref->count; i++) {
- if (ecc_pref->ecc_curves[i]->iana_id == server_negotiated_curve->iana_id) {
- ecc_evp_params = &conn->secure.client_ecc_evp_params[i];
- ENSURE_POSIX(ecc_evp_params->evp_pkey == NULL, S2N_ERR_INVALID_HELLO_RETRY);
+ /* If the server did not request a specific PQ keyshare, don't send one */
+ if (!server_group) {
+ return S2N_SUCCESS;
}
- }
-
- /* None of the previously generated keyshares were selected for negotiation, so wipe them */
- GUARD(s2n_wipe_all_client_keyshares(conn));
- /* Generate the keyshare for the server negotiated curve */
- ecc_evp_params->negotiated_curve = server_negotiated_curve;
- GUARD(s2n_ecdhe_parameters_send(ecc_evp_params, out));
-
- return S2N_SUCCESS;
-}
-
-static int s2n_send_hrr_pq_hybrid_keyshare(struct s2n_connection *conn, struct s2n_stuffer *out) {
- notnull_check(conn);
- notnull_check(out);
-
- /* 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_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
- const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
-
- const struct s2n_kem_group *server_negotiated_kem_group = conn->secure.server_kem_group_params.kem_group;
- ENSURE_POSIX(server_negotiated_kem_group != NULL, S2N_ERR_INVALID_HELLO_RETRY);
- ENSURE_POSIX(s2n_kem_preferences_includes_tls13_kem_group(kem_pref, server_negotiated_kem_group->iana_id),
- S2N_ERR_INVALID_HELLO_RETRY);
- struct s2n_kem_group_params *kem_group_params = NULL;
-
- for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) {
- if (kem_pref->tls13_kem_groups[i]->iana_id == server_negotiated_kem_group->iana_id) {
- kem_group_params = &conn->secure.client_kem_group_params[i];
- ENSURE_POSIX(kem_group_params->kem_group == NULL, S2N_ERR_INVALID_HELLO_RETRY);
- ENSURE_POSIX(kem_group_params->ecc_params.evp_pkey == NULL, S2N_ERR_INVALID_HELLO_RETRY);
- ENSURE_POSIX(kem_group_params->kem_params.private_key.data == NULL, S2N_ERR_INVALID_HELLO_RETRY);
+ /* If the server requested a new PQ keyshare, free the old one */
+ if (client_params->kem_group != server_group) {
+ POSIX_GUARD(s2n_kem_group_free(client_params));
}
- }
-
- /* None of the previously generated keyshares were selected for negotiation, so wipe them */
- GUARD(s2n_wipe_all_client_keyshares(conn));
- /* Generate the keyshare for the server negotiated KEM group */
- kem_group_params->kem_group = server_negotiated_kem_group;
- GUARD(s2n_generate_pq_hybrid_key_share(out, kem_group_params));
-
- return S2N_SUCCESS;
-}
-/* From https://tools.ietf.org/html/rfc8446#section-4.1.2
- * If a "key_share" extension was supplied in the HelloRetryRequest,
- * replace the list of shares with a list containing a single
- * KeyShareEntry from the indicated group.*/
-static int s2n_send_hrr_keyshare(struct s2n_connection *conn, struct s2n_stuffer *out) {
- notnull_check(conn);
- notnull_check(out);
-
- if (conn->secure.server_kem_group_params.kem_group != NULL) {
- GUARD(s2n_send_hrr_pq_hybrid_keyshare(conn, out));
+ client_params->kem_group = server_group;
} else {
- GUARD(s2n_send_hrr_ecc_keyshare(conn, out));
+ client_params->kem_group = kem_pref->tls13_kem_groups[0];
}
+ POSIX_GUARD(s2n_generate_pq_hybrid_key_share(out, client_params));
return S2N_SUCCESS;
}
-static int s2n_ecdhe_supported_curves_send(struct s2n_connection *conn, struct s2n_stuffer *out)
-{
- if (!conn->preferred_key_shares) {
- GUARD(s2n_generate_default_ecc_key_share(conn, out));
- return S2N_SUCCESS;
- }
-
- GUARD(s2n_generate_preferred_ecc_key_shares(conn, out));
- return S2N_SUCCESS;
-}
-
static int s2n_client_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
struct s2n_stuffer_reservation shares_size = {0};
- GUARD(s2n_stuffer_reserve_uint16(out, &shares_size));
+ POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &shares_size));
+ POSIX_GUARD(s2n_generate_default_pq_hybrid_key_share(conn, out));
+ POSIX_GUARD(s2n_generate_default_ecc_key_share(conn, out));
+ POSIX_GUARD(s2n_stuffer_write_vector_size(&shares_size));
- if (s2n_is_hello_retry_handshake(conn)) {
- GUARD(s2n_send_hrr_keyshare(conn, out));
- } else {
- GUARD(s2n_generate_default_pq_hybrid_key_share(conn, out));
- GUARD(s2n_ecdhe_supported_curves_send(conn, out));
- }
-
- GUARD(s2n_stuffer_write_vector_size(&shares_size));
+ /* We must have written at least one share */
+ POSIX_ENSURE(s2n_stuffer_data_available(out) > shares_size.length, S2N_ERR_BAD_KEY_SHARE);
return S2N_SUCCESS;
}
static int s2n_client_key_share_parse_ecc(struct s2n_stuffer *key_share, const struct s2n_ecc_named_curve *curve,
- struct s2n_ecc_evp_params *ecc_params) {
- notnull_check(key_share);
- notnull_check(curve);
- notnull_check(ecc_params);
+ struct s2n_ecc_evp_params *ecc_params)
+{
+ POSIX_ENSURE_REF(key_share);
+ POSIX_ENSURE_REF(curve);
+ POSIX_ENSURE_REF(ecc_params);
struct s2n_blob point_blob = { 0 };
- GUARD(s2n_ecc_evp_read_params_point(key_share, curve->share_size, &point_blob));
+ POSIX_GUARD(s2n_ecc_evp_read_params_point(key_share, curve->share_size, &point_blob));
/* Ignore curves with points we can't parse */
ecc_params->negotiated_curve = curve;
if (s2n_ecc_evp_parse_params_point(&point_blob, ecc_params) != S2N_SUCCESS) {
ecc_params->negotiated_curve = NULL;
- GUARD(s2n_ecc_evp_params_free(ecc_params));
+ POSIX_GUARD(s2n_ecc_evp_params_free(ecc_params));
}
return S2N_SUCCESS;
}
-static int s2n_client_key_share_recv_ecc(struct s2n_connection *conn, struct s2n_stuffer *key_share,
- uint16_t curve_iana_id, bool *match) {
- notnull_check(conn);
- notnull_check(key_share);
- notnull_check(match);
+static int s2n_client_key_share_recv_ecc(struct s2n_connection *conn, struct s2n_stuffer *key_share, uint16_t curve_iana_id)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(key_share);
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
+
+ struct s2n_ecc_evp_params *client_params = &conn->kex_params.client_ecc_evp_params;
const struct s2n_ecc_named_curve *curve = NULL;
- struct s2n_ecc_evp_params *client_ecc_params = NULL;
for (size_t i = 0; i < ecc_pref->count; i++) {
- if (curve_iana_id == ecc_pref->ecc_curves[i]->iana_id) {
- curve = ecc_pref->ecc_curves[i];
- client_ecc_params = &conn->secure.client_ecc_evp_params[i];
+ const struct s2n_ecc_named_curve *supported_curve = ecc_pref->ecc_curves[i];
+ POSIX_ENSURE_REF(supported_curve);
+
+ /* Stop if we reach the current highest priority share.
+ * Any share of lower priority is discarded.
+ */
+ if (client_params->negotiated_curve == supported_curve) {
break;
}
- }
- /* Ignore unsupported curves */
- if (!curve || !client_ecc_params) {
- return S2N_SUCCESS;
+ /* Skip if not supported by the client.
+ * The client must not send shares it doesn't support, but the server
+ * is not required to error if they are encountered.
+ */
+ if (!conn->kex_params.mutually_supported_curves[i]) {
+ continue;
+ }
+
+ /* Stop if we find a match */
+ if (curve_iana_id == supported_curve->iana_id) {
+ curve = supported_curve;
+ break;
+ }
}
- /* Ignore curves that we've already received material for */
- if (client_ecc_params->negotiated_curve) {
+ /* Ignore unsupported curves */
+ if (!curve) {
return S2N_SUCCESS;
}
@@ -358,47 +255,66 @@ static int s2n_client_key_share_recv_ecc(struct s2n_connection *conn, struct s2n
return S2N_SUCCESS;
}
- GUARD(s2n_client_key_share_parse_ecc(key_share, curve, client_ecc_params));
- /* negotiated_curve will be non-NULL if the key share was parsed successfully */
- if (client_ecc_params->negotiated_curve) {
- *match = true;
+ DEFER_CLEANUP(struct s2n_ecc_evp_params new_client_params = { 0 }, s2n_ecc_evp_params_free);
+
+ POSIX_GUARD(s2n_client_key_share_parse_ecc(key_share, curve, &new_client_params));
+ /* negotiated_curve will be NULL if the key share was not parsed successfully */
+ if (!new_client_params.negotiated_curve) {
+ return S2N_SUCCESS;
}
+ POSIX_GUARD(s2n_ecc_evp_params_free(client_params));
+ *client_params = new_client_params;
+
+ ZERO_TO_DISABLE_DEFER_CLEANUP(new_client_params);
return S2N_SUCCESS;
}
-static int s2n_client_key_share_recv_pq_hybrid(struct s2n_connection *conn, struct s2n_stuffer *key_share,
- uint16_t kem_group_iana_id, bool *match) {
- notnull_check(conn);
- notnull_check(key_share);
- notnull_check(match);
+static int s2n_client_key_share_recv_pq_hybrid(struct s2n_connection *conn, struct s2n_stuffer *key_share, uint16_t kem_group_iana_id)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(key_share);
const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
+ POSIX_ENSURE_REF(kem_pref);
/* Ignore key share if PQ is not enabled */
if (!s2n_pq_is_enabled()) {
return S2N_SUCCESS;
}
+ struct s2n_kem_group_params *client_params = &conn->kex_params.client_kem_group_params;
+
const struct s2n_kem_group *kem_group = NULL;
- struct s2n_kem_group_params *client_kem_group_params = NULL;
for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) {
- if (kem_group_iana_id == kem_pref->tls13_kem_groups[i]->iana_id) {
- kem_group = kem_pref->tls13_kem_groups[i];
- client_kem_group_params = &conn->secure.client_kem_group_params[i];
+ const struct s2n_kem_group *supported_group = kem_pref->tls13_kem_groups[i];
+ POSIX_ENSURE_REF(supported_group);
+
+ /* Stop if we reach the current highest priority share.
+ * Any share of lower priority is discarded.
+ */
+ if (client_params->kem_group == supported_group) {
break;
}
- }
- /* Ignore unsupported KEM groups */
- if (!kem_group || !client_kem_group_params) {
- return S2N_SUCCESS;
+ /* Skip if not supported by the client.
+ * The client must not send shares it doesn't support, but the server
+ * is not required to error if they are encountered.
+ */
+ if (!conn->kex_params.mutually_supported_kem_groups[i]) {
+ continue;
+ }
+
+ /* Stop if we find a match */
+ if (kem_group_iana_id == supported_group->iana_id) {
+ kem_group = supported_group;
+ break;
+ }
}
- /* Ignore KEM groups that we've already received material for */
- if (client_kem_group_params->kem_group) {
+ /* Ignore unsupported KEM groups */
+ if (!kem_group) {
return S2N_SUCCESS;
}
@@ -407,85 +323,86 @@ static int s2n_client_key_share_recv_pq_hybrid(struct s2n_connection *conn, stru
return S2N_SUCCESS;
}
- uint16_t ec_share_size = 0;
- GUARD(s2n_stuffer_read_uint16(key_share, &ec_share_size));
/* Ignore KEM groups with unexpected ECC share sizes */
+ uint16_t ec_share_size = 0;
+ POSIX_GUARD(s2n_stuffer_read_uint16(key_share, &ec_share_size));
if (ec_share_size != kem_group->curve->share_size) {
return S2N_SUCCESS;
}
- GUARD(s2n_client_key_share_parse_ecc(key_share, kem_group->curve, &client_kem_group_params->ecc_params));
+ DEFER_CLEANUP(struct s2n_kem_group_params new_client_params = { 0 }, s2n_kem_group_free);
+ new_client_params.kem_group = kem_group;
+
+ POSIX_GUARD(s2n_client_key_share_parse_ecc(key_share, kem_group->curve, &new_client_params.ecc_params));
/* If we were unable to parse the EC portion of the share, negotiated_curve
* will be NULL, and we should ignore the entire key share. */
- if (!client_kem_group_params->ecc_params.negotiated_curve) {
+ if (!new_client_params.ecc_params.negotiated_curve) {
return S2N_SUCCESS;
}
/* Note: the PQ share size is validated in s2n_kem_recv_public_key() */
/* Ignore groups with PQ public keys we can't parse */
- client_kem_group_params->kem_params.kem = kem_group->kem;
- if (s2n_kem_recv_public_key(key_share, &client_kem_group_params->kem_params) != S2N_SUCCESS) {
- client_kem_group_params->kem_group = NULL;
- client_kem_group_params->kem_params.kem = NULL;
- client_kem_group_params->ecc_params.negotiated_curve = NULL;
- /* s2n_kem_group_free() will free both the ECC and KEM params */
- GUARD(s2n_kem_group_free(client_kem_group_params));
+ new_client_params.kem_params.kem = kem_group->kem;
+ if (s2n_kem_recv_public_key(key_share, &new_client_params.kem_params) != S2N_SUCCESS) {
return S2N_SUCCESS;
}
- client_kem_group_params->kem_group = kem_group;
- *match = true;
+ POSIX_GUARD(s2n_kem_group_free(client_params));
+ *client_params = new_client_params;
+
+ ZERO_TO_DISABLE_DEFER_CLEANUP(new_client_params);
return S2N_SUCCESS;
}
-static int s2n_client_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) {
- notnull_check(conn);
- notnull_check(extension);
-
- if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
- return S2N_SUCCESS;
- }
-
- const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
-
- const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
+/*
+ * We chose our most preferred group of the mutually supported groups while processing the
+ * supported_groups extension. However, our true most preferred group is always the
+ * group that we already have a key share for, since retries are expensive.
+ *
+ * This method modifies our group selection based on what keyshares are available.
+ * It then stores the client keyshare for the selected group, or initiates a retry
+ * if no valid keyshares are available.
+ */
+static int s2n_client_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(extension);
uint16_t key_shares_size;
- GUARD(s2n_stuffer_read_uint16(extension, &key_shares_size));
- ENSURE_POSIX(s2n_stuffer_data_available(extension) >= key_shares_size, S2N_ERR_BAD_MESSAGE);
-
- uint16_t named_group, share_size;
- bool match_found = false;
- /* bytes_processed is declared as a uint32_t to avoid integer overflow in later calculations */
- uint32_t bytes_processed = 0;
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &key_shares_size));
+ POSIX_ENSURE(s2n_stuffer_data_available(extension) == key_shares_size, S2N_ERR_BAD_MESSAGE);
- while (bytes_processed < key_shares_size) {
- GUARD(s2n_stuffer_read_uint16(extension, &named_group));
- GUARD(s2n_stuffer_read_uint16(extension, &share_size));
+ uint16_t named_group = 0, share_size = 0;
+ struct s2n_blob key_share_blob = { 0 };
+ struct s2n_stuffer key_share = { 0 };
- ENSURE_POSIX(s2n_stuffer_data_available(extension) >= share_size, S2N_ERR_BAD_MESSAGE);
- bytes_processed += share_size + S2N_SIZE_OF_NAMED_GROUP + S2N_SIZE_OF_KEY_SHARE_SIZE;
+ uint16_t keyshare_count = 0;
+ while(s2n_stuffer_data_available(extension) > 0) {
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &named_group));
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &share_size));
+ POSIX_ENSURE(s2n_stuffer_data_available(extension) >= share_size, S2N_ERR_BAD_MESSAGE);
- struct s2n_blob key_share_blob = { .size = share_size, .data = s2n_stuffer_raw_read(extension, share_size) };
- notnull_check(key_share_blob.data);
- struct s2n_stuffer key_share = { 0 };
- GUARD(s2n_stuffer_init(&key_share, &key_share_blob));
- GUARD(s2n_stuffer_skip_write(&key_share, share_size));
+ POSIX_GUARD(s2n_blob_init(&key_share_blob,
+ s2n_stuffer_raw_read(extension, share_size), share_size));
+ POSIX_GUARD(s2n_stuffer_init(&key_share, &key_share_blob));
+ POSIX_GUARD(s2n_stuffer_skip_write(&key_share, share_size));
+ keyshare_count++;
/* 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));
- GUARD(s2n_client_key_share_recv_pq_hybrid(conn, &key_share, named_group, &match_found));
+ POSIX_GUARD(s2n_client_key_share_recv_ecc(conn, &key_share, named_group));
+ POSIX_GUARD(s2n_client_key_share_recv_pq_hybrid(conn, &key_share, named_group));
}
+ /* During a retry, the client should only have sent one keyshare */
+ POSIX_ENSURE(!s2n_is_hello_retry_handshake(conn) || keyshare_count == 1, S2N_ERR_BAD_MESSAGE);
+
/* If there were no matching key shares, then we received an empty key share extension
* or we didn't match a key share with a supported group. We should send a retry. */
- if (!match_found) {
- GUARD(s2n_set_hello_retry_required(conn));
+ struct s2n_ecc_evp_params *client_ecc_params = &conn->kex_params.client_ecc_evp_params;
+ struct s2n_kem_group_params *client_pq_params = &conn->kex_params.client_kem_group_params;
+ if (!client_pq_params->kem_group && !client_ecc_params->negotiated_curve) {
+ POSIX_GUARD(s2n_set_hello_retry_required(conn));
}
return S2N_SUCCESS;
@@ -495,11 +412,11 @@ static int s2n_client_key_share_recv(struct s2n_connection *conn, struct s2n_stu
uint32_t s2n_extensions_client_key_share_size(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
uint32_t s2n_client_key_share_extension_size = S2N_SIZE_OF_EXTENSION_TYPE
+ S2N_SIZE_OF_EXTENSION_DATA_SIZE
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_max_frag_len.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_max_frag_len.c
index 880193a1a1..df5d2e5088 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_max_frag_len.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_max_frag_len.c
@@ -52,13 +52,29 @@ static int s2n_client_max_frag_len_recv(struct s2n_connection *conn, struct s2n_
}
uint8_t mfl_code;
- GUARD(s2n_stuffer_read_uint8(extension, &mfl_code));
- if (mfl_code > S2N_TLS_MAX_FRAG_LEN_4096 || mfl_code_to_length[mfl_code] > S2N_TLS_MAXIMUM_FRAGMENT_LENGTH) {
+ POSIX_GUARD(s2n_stuffer_read_uint8(extension, &mfl_code));
+
+ /*
+ *= https://tools.ietf.org/rfc/rfc6066#section-4
+ *= type=exception
+ *= reason=For compatibility, we choose to ignore malformed extensions if they are optional
+ *# If a server receives a maximum fragment length negotiation request
+ *# for a value other than the allowed values, it MUST abort the
+ *# handshake with an "illegal_parameter" alert.
+ */
+ if (mfl_code >= s2n_array_len(mfl_code_to_length) || mfl_code_to_length[mfl_code] > S2N_TLS_MAXIMUM_FRAGMENT_LENGTH) {
return S2N_SUCCESS;
}
- conn->mfl_code = mfl_code;
- conn->max_outgoing_fragment_length = mfl_code_to_length[mfl_code];
+ /*
+ *= https://tools.ietf.org/rfc/rfc6066#section-4
+ *# Once a maximum fragment length other than 2^14 has been successfully
+ *# negotiated, the client and server MUST immediately begin fragmenting
+ *# messages (including handshake messages) to ensure that no fragment
+ *# larger than the negotiated length is sent.
+ */
+ conn->negotiated_mfl_code = mfl_code;
+ POSIX_GUARD_RESULT(s2n_connection_set_max_fragment_length(conn, mfl_code_to_length[mfl_code]));
return S2N_SUCCESS;
}
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 83c4c8f1d0..aae1fe8256 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
@@ -49,12 +49,12 @@ static bool s2n_client_pq_kem_should_send(struct s2n_connection *conn)
static int s2n_client_pq_kem_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
const struct s2n_kem_preferences *kem_preferences = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences));
- notnull_check(kem_preferences);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences));
+ POSIX_ENSURE_REF(kem_preferences);
- GUARD(s2n_stuffer_write_uint16(out, kem_preferences->kem_count * sizeof(kem_extension_size)));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, kem_preferences->kem_count * sizeof(kem_extension_size)));
for (int i = 0; i < kem_preferences->kem_count; i++) {
- GUARD(s2n_stuffer_write_uint16(out, kem_preferences->kems[i]->kem_extension_id));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, kem_preferences->kems[i]->kem_extension_id));
}
return S2N_SUCCESS;
@@ -63,14 +63,14 @@ static int s2n_client_pq_kem_send(struct s2n_connection *conn, struct s2n_stuffe
static int s2n_client_pq_kem_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
uint16_t size_of_all;
- struct s2n_blob *proposed_kems = &conn->secure.client_pq_kem_extension;
+ struct s2n_blob *proposed_kems = &conn->kex_params.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));
+ POSIX_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 */
return S2N_SUCCESS;
@@ -78,7 +78,7 @@ static int s2n_client_pq_kem_recv(struct s2n_connection *conn, struct s2n_stuffe
proposed_kems->size = size_of_all;
proposed_kems->data = s2n_stuffer_raw_read(extension, proposed_kems->size);
- notnull_check(proposed_kems->data);
+ POSIX_ENSURE_REF(proposed_kems->data);
return S2N_SUCCESS;
}
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 d457829022..f8278f36b4 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c
@@ -27,30 +27,49 @@
#define SIZE_OF_BINDER_SIZE sizeof(uint8_t)
#define SIZE_OF_BINDER_LIST_SIZE sizeof(uint16_t)
-#define MAX_NUM_OF_PSK_IDENTITIES 100
+
+/* To avoid a DoS attack triggered by decrypting too many session tickets,
+ * set a limit on the number of tickets we will attempt to decrypt before giving up.
+ * We may want to make this configurable someday, but just set a reasonable maximum for now. */
+#define MAX_REJECTED_TICKETS 3
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);
+static int s2n_client_psk_is_missing(struct s2n_connection *conn);
const s2n_extension_type s2n_client_psk_extension = {
.iana_value = TLS_EXTENSION_PRE_SHARED_KEY,
+ .minimum_version = S2N_TLS13,
.is_response = false,
.send = s2n_client_psk_send,
.recv = s2n_client_psk_recv,
.should_send = s2n_client_psk_should_send,
- .if_missing = s2n_extension_noop_if_missing,
+ .if_missing = s2n_client_psk_is_missing,
};
+int s2n_client_psk_is_missing(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+
+ /* If the PSK extension is missing, we must not have received
+ * a request for early data.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# When a PSK is used and early data is allowed for that PSK, the client
+ *# can send Application Data in its first flight of messages. If the
+ *# client opts to do so, it MUST supply both the "pre_shared_key" and
+ *# "early_data" extensions.
+ */
+ POSIX_ENSURE(conn->early_data_state != S2N_EARLY_DATA_REQUESTED, S2N_ERR_UNSUPPORTED_EXTENSION);
+ return S2N_SUCCESS;
+}
+
bool s2n_client_psk_should_send(struct s2n_connection *conn)
{
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.
*/
@@ -72,22 +91,62 @@ bool s2n_client_psk_should_send(struct s2n_connection *conn)
return false;
}
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11.1
+ *# The "obfuscated_ticket_age"
+ *# field of each PskIdentity contains an obfuscated version of the
+ *# ticket age formed by taking the age in milliseconds and adding the
+ *# "ticket_age_add" value that was included with the ticket (see
+ *# Section 4.6.1), modulo 2^32.
+*/
+static S2N_RESULT s2n_generate_obfuscated_ticket_age(struct s2n_psk *psk, uint64_t current_time, uint32_t *output)
+{
+ RESULT_ENSURE_REF(psk);
+ RESULT_ENSURE_MUT(output);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11
+ *# For identities
+ *# established externally, an obfuscated_ticket_age of 0 SHOULD be
+ *# used,
+ **/
+ if (psk->type == S2N_PSK_TYPE_EXTERNAL) {
+ *output = 0;
+ return S2N_RESULT_OK;
+ }
+
+ RESULT_ENSURE(current_time >= psk->ticket_issue_time, S2N_ERR_SAFETY);
+
+ /* Calculate ticket age */
+ uint64_t ticket_age_in_nanos = current_time - psk->ticket_issue_time;
+
+ /* Convert ticket age to milliseconds */
+ uint64_t ticket_age_in_millis = ticket_age_in_nanos / ONE_MILLISEC_IN_NANOS;
+ RESULT_ENSURE(ticket_age_in_millis <= UINT32_MAX, S2N_ERR_SAFETY);
+
+ /* Add the ticket_age_add value to the ticket age in milliseconds. The resulting uint32_t value
+ * may wrap, resulting in the modulo 2^32 operation. */
+ *output = ticket_age_in_millis + psk->ticket_age_add;
+
+ return S2N_RESULT_OK;
+}
+
static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
struct s2n_psk_parameters *psk_params = &conn->psk_params;
struct s2n_array *psk_list = &psk_params->psk_list;
struct s2n_stuffer_reservation identity_list_size;
- GUARD(s2n_stuffer_reserve_uint16(out, &identity_list_size));
+ POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &identity_list_size));
uint16_t binder_list_size = SIZE_OF_BINDER_LIST_SIZE;
for (size_t i = 0; i < psk_list->len; i++) {
struct s2n_psk *psk = NULL;
- GUARD_AS_POSIX(s2n_array_get(psk_list, i, (void**) &psk));
- notnull_check(psk);
+ POSIX_GUARD_RESULT(s2n_array_get(psk_list, i, (void**) &psk));
+ POSIX_ENSURE_REF(psk);
/**
*= https://tools.ietf.org/rfc/rfc8446#section-4.1.4
@@ -100,17 +159,23 @@ static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *
}
/* Write the identity */
- GUARD(s2n_stuffer_write_uint16(out, psk->identity.size));
- GUARD(s2n_stuffer_write(out, &psk->identity));
- GUARD(s2n_stuffer_write_uint32(out, 0));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, psk->identity.size));
+ POSIX_GUARD(s2n_stuffer_write(out, &psk->identity));
+
+ /* Write obfuscated ticket age */
+ uint32_t obfuscated_ticket_age = 0;
+ uint64_t current_time = 0;
+ POSIX_GUARD(conn->config->wall_clock(conn->config->sys_clock_ctx, &current_time));
+ POSIX_GUARD_RESULT(s2n_generate_obfuscated_ticket_age(psk, current_time, &obfuscated_ticket_age));
+ POSIX_GUARD(s2n_stuffer_write_uint32(out, obfuscated_ticket_age));
/* Calculate binder size */
uint8_t hash_size = 0;
- GUARD(s2n_hmac_digest_size(psk->hmac_alg, &hash_size));
+ POSIX_GUARD(s2n_hmac_digest_size(psk->hmac_alg, &hash_size));
binder_list_size += hash_size + SIZE_OF_BINDER_SIZE;
}
- GUARD(s2n_stuffer_write_vector_size(&identity_list_size));
+ POSIX_GUARD(s2n_stuffer_write_vector_size(&identity_list_size));
/* Calculating the binders requires a complete ClientHello, and at this point
* the extension size, extension list size, and message size are all blank.
@@ -118,231 +183,177 @@ static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *
* We'll write placeholder data to ensure the extension and extension list sizes
* are calculated correctly, then rewrite the binders with real data later. */
psk_params->binder_list_size = binder_list_size;
- GUARD(s2n_stuffer_skip_write(out, binder_list_size));
+ POSIX_GUARD(s2n_stuffer_skip_write(out, binder_list_size));
return S2N_SUCCESS;
}
-/* Match a PSK identity received from the client against the server's known PSK identities.
+/* Find the first of the server's PSK identities that matches the client's identities.
+ * This method compares all server identities to all client identities.
*
- * While both the client's offered identities and whether a match was found are public, we should make an attempt
- * to keep the server's known identities a secret. We will make comparisons to the server's identities constant
+ * While both the client's identities and whether a match was found are public, we should make an attempt
+ * to keep the server's identities a secret. We will make comparisons to the server's identities constant
* time (to hide partial matches) and not end the search early when a match is found (to hide the ordering).
*
* Keeping these comparisons constant time is not high priority. There's no known attack using these timings,
* and an attacker could probably guess the server's known identities just by observing the public identities
* sent by clients.
*/
-static S2N_RESULT s2n_match_psk_identity(struct s2n_array *known_psks, const struct s2n_blob *wire_identity,
- struct s2n_psk **match)
+static S2N_RESULT s2n_select_external_psk(struct s2n_connection *conn, struct s2n_offered_psk_list *client_identity_list)
{
- ENSURE_REF(match);
- ENSURE_REF(wire_identity);
- ENSURE_REF(known_psks);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(client_identity_list);
- *match = NULL;
-
- for (size_t i = 0; i < known_psks->len; i++) {
- struct s2n_psk *psk = NULL;
- GUARD_RESULT(s2n_array_get(known_psks, i, (void**)&psk));
- ENSURE_REF(psk);
-
- ENSURE_REF(psk->identity.data);
- ENSURE_REF(wire_identity->data);
+ struct s2n_array *server_psks = &conn->psk_params.psk_list;
+ conn->psk_params.chosen_psk = NULL;
- uint32_t compare_size = MIN(wire_identity->size, psk->identity.size);
- if (s2n_constant_time_equals(psk->identity.data, wire_identity->data, compare_size)
- & (psk->identity.size == wire_identity->size) & (!*match)) {
- *match = psk;
- }
+ for (size_t i = 0; i < server_psks->len; i++) {
+ struct s2n_psk *server_psk = NULL;
+ RESULT_GUARD(s2n_array_get(server_psks, i, (void**) &server_psk));
+ RESULT_ENSURE_REF(server_psk);
+
+ struct s2n_offered_psk client_psk = { 0 };
+ uint16_t wire_index = 0;
+
+ RESULT_GUARD_POSIX(s2n_offered_psk_list_reread(client_identity_list));
+ while(s2n_offered_psk_list_has_next(client_identity_list)) {
+ RESULT_GUARD_POSIX(s2n_offered_psk_list_next(client_identity_list, &client_psk));
+ uint16_t compare_size = MIN(client_psk.identity.size, server_psk->identity.size);
+ if (s2n_constant_time_equals(client_psk.identity.data, server_psk->identity.data, compare_size)
+ & (client_psk.identity.size == server_psk->identity.size)
+ & (conn->psk_params.chosen_psk == NULL)) {
+ conn->psk_params.chosen_psk = server_psk;
+ conn->psk_params.chosen_psk_wire_index = wire_index;
+ }
+ wire_index++;
+ };
}
+ RESULT_ENSURE_REF(conn->psk_params.chosen_psk);
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);
+static S2N_RESULT s2n_select_resumption_psk(struct s2n_connection *conn, struct s2n_offered_psk_list *client_identity_list) {
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(client_identity_list);
- struct s2n_array *known_psks = &conn->psk_params.psk_list;
+ struct s2n_offered_psk client_psk = { 0 };
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;
+ uint8_t rejected_count = 0;
+ while (s2n_offered_psk_list_has_next(client_identity_list) && (rejected_count < MAX_REJECTED_TICKETS)) {
+ RESULT_GUARD_POSIX(s2n_offered_psk_list_next(client_identity_list, &client_psk));
+ /* Select the first resumption PSK that can be decrypted */
+ if (s2n_offered_psk_list_choose_psk(client_identity_list, &client_psk) == S2N_SUCCESS) {
+ return S2N_RESULT_OK;
}
+ rejected_count++;
}
- 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;
+ RESULT_BAIL(S2N_ERR_INVALID_SESSION_TICKET);
}
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);
-
- 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);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->config);
+ RESULT_ENSURE_REF(wire_identities_in);
- uint8_t *identity_data = s2n_stuffer_raw_read(wire_identities_in, identity_size);
- ENSURE_REF(identity_data);
-
- wire_identities[wire_index].data = identity_data;
- wire_identities[wire_index].length = identity_size;
-
- /**
- *= 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));
-
- wire_index++;
- }
+ struct s2n_offered_psk_list identity_list = {
+ .conn = conn,
+ .wire_data = *wire_identities_in,
+ };
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));
+ RESULT_GUARD_POSIX(conn->config->psk_selection_cb(conn, conn->config->psk_selection_ctx, &identity_list));
+ } else if(conn->psk_params.type == S2N_PSK_TYPE_EXTERNAL) {
+ RESULT_GUARD(s2n_select_external_psk(conn, &identity_list));
+ } else if(conn->psk_params.type == S2N_PSK_TYPE_RESUMPTION) {
+ RESULT_GUARD(s2n_select_resumption_psk(conn, &identity_list));
}
- ENSURE_LT(conn->psk_params.chosen_psk_wire_index, identities_count);
- ENSURE_REF(conn->psk_params.chosen_psk);
-
+ RESULT_ENSURE_REF(conn->psk_params.chosen_psk);
return S2N_RESULT_OK;
}
static S2N_RESULT s2n_client_psk_recv_binder_list(struct s2n_connection *conn, struct s2n_blob *partial_client_hello,
struct s2n_stuffer *wire_binders_in)
{
- ENSURE_REF(conn);
- ENSURE_REF(wire_binders_in);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(wire_binders_in);
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));
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(wire_binders_in, &wire_binder_size));
uint8_t *wire_binder_data;
- ENSURE_REF(wire_binder_data = s2n_stuffer_raw_read(wire_binders_in, wire_binder_size));
+ RESULT_ENSURE_REF(wire_binder_data = s2n_stuffer_raw_read(wire_binders_in, wire_binder_size));
struct s2n_blob wire_binder = { 0 };
- GUARD_AS_RESULT(s2n_blob_init(&wire_binder, wire_binder_data, wire_binder_size));
+ RESULT_GUARD_POSIX(s2n_blob_init(&wire_binder, wire_binder_data, wire_binder_size));
if (wire_index == conn->psk_params.chosen_psk_wire_index) {
- GUARD_AS_RESULT(s2n_psk_verify_binder(conn, conn->psk_params.chosen_psk,
+ RESULT_GUARD_POSIX(s2n_psk_verify_binder(conn, conn->psk_params.chosen_psk,
partial_client_hello, &wire_binder));
return S2N_RESULT_OK;
}
wire_index++;
}
- BAIL(S2N_ERR_BAD_MESSAGE);
+ RESULT_BAIL(S2N_ERR_BAD_MESSAGE);
}
static S2N_RESULT s2n_client_psk_recv_identities(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn);
uint16_t identity_list_size = 0;
- GUARD_AS_RESULT(s2n_stuffer_read_uint16(extension, &identity_list_size));
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(extension, &identity_list_size));
uint8_t *identity_list_data;
- ENSURE_REF(identity_list_data = s2n_stuffer_raw_read(extension, identity_list_size));
+ RESULT_ENSURE_REF(identity_list_data = s2n_stuffer_raw_read(extension, identity_list_size));
struct s2n_blob identity_list_blob = { 0 };
- GUARD_AS_RESULT(s2n_blob_init(&identity_list_blob, identity_list_data, identity_list_size));
+ RESULT_GUARD_POSIX(s2n_blob_init(&identity_list_blob, identity_list_data, identity_list_size));
struct s2n_stuffer identity_list = { 0 };
- GUARD_AS_RESULT(s2n_stuffer_init(&identity_list, &identity_list_blob));
- GUARD_AS_RESULT(s2n_stuffer_skip_write(&identity_list, identity_list_blob.size));
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&identity_list, &identity_list_blob));
+ RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&identity_list, identity_list_blob.size));
return s2n_client_psk_recv_identity_list(conn, &identity_list);
}
static S2N_RESULT s2n_client_psk_recv_binders(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn);
uint16_t binder_list_size = 0;
- GUARD_AS_RESULT(s2n_stuffer_read_uint16(extension, &binder_list_size));
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(extension, &binder_list_size));
uint8_t *binder_list_data;
- ENSURE_REF(binder_list_data = s2n_stuffer_raw_read(extension, binder_list_size));
+ RESULT_ENSURE_REF(binder_list_data = s2n_stuffer_raw_read(extension, binder_list_size));
struct s2n_blob binder_list_blob = { 0 };
- GUARD_AS_RESULT(s2n_blob_init(&binder_list_blob, binder_list_data, binder_list_size));
+ RESULT_GUARD_POSIX(s2n_blob_init(&binder_list_blob, binder_list_data, binder_list_size));
struct s2n_stuffer binder_list = { 0 };
- GUARD_AS_RESULT(s2n_stuffer_init(&binder_list, &binder_list_blob));
- GUARD_AS_RESULT(s2n_stuffer_skip_write(&binder_list, binder_list_blob.size));
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&binder_list, &binder_list_blob));
+ RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&binder_list, binder_list_blob.size));
/* Record the ClientHello message up to but not including the binder list.
* This is required to calculate the binder for the chosen PSK. */
struct s2n_blob partial_client_hello = { 0 };
const struct s2n_stuffer *client_hello = &conn->handshake.io;
uint32_t binders_size = binder_list_blob.size + SIZE_OF_BINDER_LIST_SIZE;
- ENSURE_GTE(client_hello->write_cursor, binders_size);
+ RESULT_ENSURE_GTE(client_hello->write_cursor, binders_size);
uint16_t partial_client_hello_size = client_hello->write_cursor - binders_size;
- GUARD_AS_RESULT(s2n_blob_slice(&client_hello->blob, &partial_client_hello, 0, partial_client_hello_size));
+ RESULT_GUARD_POSIX(s2n_blob_slice(&client_hello->blob, &partial_client_hello, 0, partial_client_hello_size));
return s2n_client_psk_recv_binder_list(conn, &partial_client_hello, &binder_list);
}
int s2n_client_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;
- }
+ POSIX_ENSURE_REF(conn);
/**
*= https://tools.ietf.org/rfc/rfc8446#section-4.2.11
@@ -352,11 +363,11 @@ int s2n_client_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extensi
*# 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);
+ POSIX_GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_PRE_SHARED_KEY, &psk_ext_id));
+ POSIX_ENSURE_NE(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);
+ POSIX_ENSURE(extension_wire_index == last_wire_index, S2N_ERR_UNSUPPORTED_EXTENSION);
/**
*= https://tools.ietf.org/rfc/rfc8446#section-4.2.9
@@ -367,16 +378,16 @@ int s2n_client_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extensi
* 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);
+ POSIX_GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES, &psk_ke_mode_ext_id));
+ POSIX_ENSURE(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));
+ POSIX_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);
+ POSIX_ENSURE(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.
@@ -401,7 +412,7 @@ int s2n_client_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extensi
*# value is not present or does not validate, the server MUST abort the
*# handshake.
*/
- GUARD_AS_POSIX(s2n_client_psk_recv_binders(conn, extension));
+ POSIX_GUARD_RESULT(s2n_client_psk_recv_binders(conn, extension));
}
/* At this point, we have either chosen a PSK or fallen back to a full handshake. */
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.c
index 3a012f47d1..772712fda4 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.c
@@ -36,7 +36,7 @@ static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n
{
/* RFC5746 Section 3.2: The renegotiated_connection field is of zero length for the initial handshake. */
uint8_t renegotiated_connection_len;
- GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len));
+ POSIX_GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len));
S2N_ERROR_IF(s2n_stuffer_data_available(extension) || renegotiated_connection_len, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
conn->secure_renegotiation = 1;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_server_name.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_server_name.c
index 904976e4cc..0e69283a2c 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_server_name.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_server_name.c
@@ -39,47 +39,50 @@ const s2n_extension_type s2n_client_server_name_extension = {
static bool s2n_client_server_name_should_send(struct s2n_connection *conn)
{
- return conn && strlen(conn->server_name) > 0;
+ return conn && conn->server_name[0] != '\0';
}
static int s2n_client_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
struct s2n_stuffer_reservation server_name_list_size = {0};
- GUARD(s2n_stuffer_reserve_uint16(out, &server_name_list_size));
+ POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &server_name_list_size));
/* NameType, as described by RFC6066.
* host_name is currently the only possible NameType defined. */
- GUARD(s2n_stuffer_write_uint8(out, S2N_NAME_TYPE_HOST_NAME));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, S2N_NAME_TYPE_HOST_NAME));
- GUARD(s2n_stuffer_write_uint16(out, strlen(conn->server_name)));
- GUARD(s2n_stuffer_write_bytes(out, (const uint8_t *) conn->server_name, strlen(conn->server_name)));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, strlen(conn->server_name)));
+ POSIX_GUARD(s2n_stuffer_write_bytes(out, (const uint8_t *) conn->server_name, strlen(conn->server_name)));
- GUARD(s2n_stuffer_write_vector_size(&server_name_list_size));
+ POSIX_GUARD(s2n_stuffer_write_vector_size(&server_name_list_size));
return S2N_SUCCESS;
}
+/* Read the extension up to the first item in ServerNameList. Store the first entry's length in server_name_len.
+ * For now s2n ignores all subsequent items in ServerNameList.
+ */
static int s2n_client_server_name_check(struct s2n_connection *conn, struct s2n_stuffer *extension, uint16_t *server_name_len)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
uint16_t size_of_all;
- GUARD(s2n_stuffer_read_uint16(extension, &size_of_all));
- lte_check(size_of_all, s2n_stuffer_data_available(extension));
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &size_of_all));
+ POSIX_ENSURE_LTE(size_of_all, s2n_stuffer_data_available(extension));
uint8_t server_name_type;
- GUARD(s2n_stuffer_read_uint8(extension, &server_name_type));
- eq_check(server_name_type, S2N_NAME_TYPE_HOST_NAME);
+ POSIX_GUARD(s2n_stuffer_read_uint8(extension, &server_name_type));
+ POSIX_ENSURE_EQ(server_name_type, S2N_NAME_TYPE_HOST_NAME);
- GUARD(s2n_stuffer_read_uint16(extension, server_name_len));
- lt_check(*server_name_len, sizeof(conn->server_name));
- lte_check(*server_name_len, s2n_stuffer_data_available(extension));
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, server_name_len));
+ POSIX_ENSURE_LT(*server_name_len, sizeof(conn->server_name));
+ POSIX_ENSURE_LTE(*server_name_len, s2n_stuffer_data_available(extension));
return S2N_SUCCESS;
}
static int s2n_client_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
/* Exit early if we've already parsed the server name */
if (conn->server_name[0]) {
@@ -93,8 +96,8 @@ static int s2n_client_server_name_recv(struct s2n_connection *conn, struct s2n_s
}
uint8_t *server_name;
- notnull_check(server_name = s2n_stuffer_raw_read(extension, server_name_len));
- memcpy_check(conn->server_name, server_name, server_name_len);
+ POSIX_ENSURE_REF(server_name = s2n_stuffer_raw_read(extension, server_name_len));
+ POSIX_CHECKED_MEMCPY(conn->server_name, server_name, server_name_len);
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_session_ticket.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_session_ticket.c
index 96ef1b7308..ca9c5e96e7 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_session_ticket.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_session_ticket.c
@@ -17,6 +17,8 @@
#include <stdint.h>
#include "tls/extensions/s2n_client_session_ticket.h"
+
+#include "tls/extensions/s2n_client_psk.h"
#include "tls/s2n_tls.h"
#include "tls/s2n_tls_parameters.h"
#include "tls/s2n_resume.h"
@@ -38,18 +40,18 @@ const s2n_extension_type s2n_client_session_ticket_extension = {
static bool s2n_client_session_ticket_should_send(struct s2n_connection *conn)
{
- return conn->config->use_tickets;
+ return conn->config->use_tickets && !s2n_client_psk_should_send(conn);
}
static int s2n_client_session_ticket_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- GUARD(s2n_stuffer_write(out, &conn->client_ticket));
+ POSIX_GUARD(s2n_stuffer_write(out, &conn->client_ticket));
return S2N_SUCCESS;
}
static int s2n_client_session_ticket_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- if (conn->config->use_tickets != 1) {
+ if (conn->config->use_tickets != 1 || conn->actual_protocol_version > S2N_TLS12) {
/* Ignore the extension. */
return S2N_SUCCESS;
}
@@ -59,9 +61,9 @@ static int s2n_client_session_ticket_recv(struct s2n_connection *conn, struct s2
return S2N_SUCCESS;
}
- if (s2n_stuffer_data_available(extension) == S2N_TICKET_SIZE_IN_BYTES) {
+ if (s2n_stuffer_data_available(extension) == S2N_TLS12_TICKET_SIZE_IN_BYTES) {
conn->session_ticket_status = S2N_DECRYPT_TICKET;
- GUARD(s2n_stuffer_copy(extension, &conn->client_ticket_to_decrypt, S2N_TICKET_SIZE_IN_BYTES));
+ POSIX_GUARD(s2n_stuffer_copy(extension, &conn->client_ticket_to_decrypt, S2N_TLS12_TICKET_SIZE_IN_BYTES));
} else if (s2n_config_is_encrypt_decrypt_key_available(conn->config) == 1) {
conn->session_ticket_status = S2N_NEW_TICKET;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_status_request.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_status_request.c
index e5144fba8b..608e8d0a55 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_status_request.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_status_request.c
@@ -42,20 +42,20 @@ static bool s2n_client_status_request_should_send(struct s2n_connection *conn)
static int s2n_client_status_request_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- GUARD(s2n_stuffer_write_uint8(out, (uint8_t) conn->config->status_request_type));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, (uint8_t) conn->config->status_request_type));
/* responder_id_list
*
* From https://tools.ietf.org/html/rfc6066#section-8:
* A zero-length "responder_id_list" sequence has the special meaning that the responders are implicitly
* known to the server, e.g., by prior arrangement */
- GUARD(s2n_stuffer_write_uint16(out, 0));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, 0));
/* request_extensions
*
* From https://tools.ietf.org/html/rfc6066#section-8:
* A zero-length "request_extensions" value means that there are no extensions. */
- GUARD(s2n_stuffer_write_uint16(out, 0));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, 0));
return S2N_SUCCESS;
}
@@ -68,7 +68,7 @@ static int s2n_client_status_request_recv(struct s2n_connection *conn, struct s2
}
uint8_t type;
- GUARD(s2n_stuffer_read_uint8(extension, &type));
+ POSIX_GUARD(s2n_stuffer_read_uint8(extension, &type));
if (type != (uint8_t) S2N_STATUS_REQUEST_OCSP) {
/* We only support OCSP (type 1), ignore the extension */
return S2N_SUCCESS;
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 4cb2f9e3c5..1b8ead056d 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
@@ -48,33 +48,33 @@ bool s2n_extension_should_send_if_ecc_enabled(struct s2n_connection *conn)
static int s2n_client_supported_groups_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
+ POSIX_ENSURE_REF(kem_pref);
/* Group list len */
struct s2n_stuffer_reservation group_list_len = { 0 };
- GUARD(s2n_stuffer_reserve_uint16(out, &group_list_len));
+ POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &group_list_len));
/* Send KEM groups list first */
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));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, kem_pref->tls13_kem_groups[i]->iana_id));
}
}
/* Then send curve list */
for (size_t i = 0; i < ecc_pref->count; i++) {
- GUARD(s2n_stuffer_write_uint16(out, ecc_pref->ecc_curves[i]->iana_id));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, ecc_pref->ecc_curves[i]->iana_id));
}
- GUARD(s2n_stuffer_write_vector_size(&group_list_len));
+ POSIX_GUARD(s2n_stuffer_write_vector_size(&group_list_len));
return S2N_SUCCESS;
}
@@ -83,16 +83,16 @@ static int s2n_client_supported_groups_send(struct s2n_connection *conn, struct
* mutually_supported_kem_groups array based on the received IANA ID. Will
* ignore unrecognized IANA IDs (and return success). */
static int s2n_client_supported_groups_recv_iana_id(struct s2n_connection *conn, uint16_t iana_id) {
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
for (size_t i = 0; i < ecc_pref->count; i++) {
const struct s2n_ecc_named_curve *supported_curve = ecc_pref->ecc_curves[i];
if (iana_id == supported_curve->iana_id) {
- conn->secure.mutually_supported_curves[i] = supported_curve;
+ conn->kex_params.mutually_supported_curves[i] = supported_curve;
return S2N_SUCCESS;
}
}
@@ -103,13 +103,13 @@ static int s2n_client_supported_groups_recv_iana_id(struct s2n_connection *conn,
}
const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
+ POSIX_ENSURE_REF(kem_pref);
for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) {
const struct s2n_kem_group *supported_kem_group = kem_pref->tls13_kem_groups[i];
if (iana_id == supported_kem_group->iana_id) {
- conn->secure.mutually_supported_kem_groups[i] = supported_kem_group;
+ conn->kex_params.mutually_supported_kem_groups[i] = supported_kem_group;
return S2N_SUCCESS;
}
}
@@ -118,40 +118,40 @@ static int s2n_client_supported_groups_recv_iana_id(struct s2n_connection *conn,
}
static int s2n_choose_supported_group(struct s2n_connection *conn) {
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
+ POSIX_ENSURE_REF(kem_pref);
/* Ensure that only the intended group will be non-NULL (if no group is chosen, everything
* should be NULL). */
- conn->secure.server_kem_group_params.kem_group = NULL;
- conn->secure.server_kem_group_params.ecc_params.negotiated_curve = NULL;
- conn->secure.server_kem_group_params.kem_params.kem = NULL;
- conn->secure.server_ecc_evp_params.negotiated_curve = NULL;
+ conn->kex_params.server_kem_group_params.kem_group = NULL;
+ conn->kex_params.server_kem_group_params.ecc_params.negotiated_curve = NULL;
+ conn->kex_params.server_kem_group_params.kem_params.kem = NULL;
+ conn->kex_params.server_ecc_evp_params.negotiated_curve = NULL;
/* 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++) {
- const struct s2n_kem_group *candidate_kem_group = conn->secure.mutually_supported_kem_groups[i];
+ const struct s2n_kem_group *candidate_kem_group = conn->kex_params.mutually_supported_kem_groups[i];
if (candidate_kem_group != NULL) {
- conn->secure.server_kem_group_params.kem_group = candidate_kem_group;
- conn->secure.server_kem_group_params.ecc_params.negotiated_curve = candidate_kem_group->curve;
- conn->secure.server_kem_group_params.kem_params.kem = candidate_kem_group->kem;
+ conn->kex_params.server_kem_group_params.kem_group = candidate_kem_group;
+ conn->kex_params.server_kem_group_params.ecc_params.negotiated_curve = candidate_kem_group->curve;
+ conn->kex_params.server_kem_group_params.kem_params.kem = candidate_kem_group->kem;
return S2N_SUCCESS;
}
}
for (size_t i = 0; i < ecc_pref->count; i++) {
- const struct s2n_ecc_named_curve *candidate_curve = conn->secure.mutually_supported_curves[i];
+ const struct s2n_ecc_named_curve *candidate_curve = conn->kex_params.mutually_supported_curves[i];
if (candidate_curve != NULL) {
- conn->secure.server_ecc_evp_params.negotiated_curve = candidate_curve;
+ conn->kex_params.server_ecc_evp_params.negotiated_curve = candidate_curve;
return S2N_SUCCESS;
}
}
@@ -160,11 +160,11 @@ static int s2n_choose_supported_group(struct s2n_connection *conn) {
}
static int s2n_client_supported_groups_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) {
- notnull_check(conn);
- notnull_check(extension);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(extension);
uint16_t size_of_all;
- GUARD(s2n_stuffer_read_uint16(extension, &size_of_all));
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &size_of_all));
if (size_of_all > s2n_stuffer_data_available(extension) || (size_of_all % sizeof(uint16_t))) {
/* Malformed length, ignore the extension */
return S2N_SUCCESS;
@@ -172,11 +172,11 @@ static int s2n_client_supported_groups_recv(struct s2n_connection *conn, struct
for (size_t i = 0; i < (size_of_all / sizeof(uint16_t)); i++) {
uint16_t iana_id;
- GUARD(s2n_stuffer_read_uint16(extension, &iana_id));
- GUARD(s2n_client_supported_groups_recv_iana_id(conn, iana_id));
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &iana_id));
+ POSIX_GUARD(s2n_client_supported_groups_recv_iana_id(conn, iana_id));
}
- GUARD(s2n_choose_supported_group(conn));
+ POSIX_GUARD(s2n_choose_supported_group(conn));
return S2N_SUCCESS;
}
@@ -185,12 +185,12 @@ static int s2n_client_supported_groups_recv(struct s2n_connection *conn, struct
int s2n_extensions_client_supported_groups_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- GUARD(s2n_extension_send(&s2n_client_supported_groups_extension, conn, out));
+ POSIX_GUARD(s2n_extension_send(&s2n_client_supported_groups_extension, conn, out));
/* The original send method also sent ec point formats. To avoid breaking
* anything, I'm going to let it continue writing point formats.
*/
- GUARD(s2n_extension_send(&s2n_client_ec_point_format_extension, conn, out));
+ POSIX_GUARD(s2n_extension_send(&s2n_client_ec_point_format_extension, conn, out));
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.c
index d0ec8cb329..bbc37e475a 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.c
@@ -59,15 +59,16 @@ const s2n_extension_type s2n_client_supported_versions_extension = {
static int s2n_client_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
uint8_t highest_supported_version = conn->client_protocol_version;
- uint8_t minimum_supported_version;
- GUARD(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version));
+ uint8_t minimum_supported_version = s2n_unknown_protocol_version;
+ POSIX_GUARD_RESULT(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version));
+ POSIX_ENSURE(highest_supported_version >= minimum_supported_version, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
uint8_t version_list_length = highest_supported_version - minimum_supported_version + 1;
- GUARD(s2n_stuffer_write_uint8(out, version_list_length * S2N_TLS_PROTOCOL_VERSION_LEN));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, version_list_length * S2N_TLS_PROTOCOL_VERSION_LEN));
for (uint8_t i = highest_supported_version; i >= minimum_supported_version; i--) {
- GUARD(s2n_stuffer_write_uint8(out, i / 10));
- GUARD(s2n_stuffer_write_uint8(out, i % 10));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, i / 10));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, i % 10));
}
return S2N_SUCCESS;
@@ -75,11 +76,11 @@ static int s2n_client_supported_versions_send(struct s2n_connection *conn, struc
static int s2n_extensions_client_supported_versions_process(struct s2n_connection *conn, struct s2n_stuffer *extension) {
uint8_t highest_supported_version = conn->server_protocol_version;
- uint8_t minimum_supported_version;
- GUARD(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version));
+ uint8_t minimum_supported_version = s2n_unknown_protocol_version;
+ POSIX_GUARD_RESULT(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version));
uint8_t size_of_version_list;
- GUARD(s2n_stuffer_read_uint8(extension, &size_of_version_list));
+ POSIX_GUARD(s2n_stuffer_read_uint8(extension, &size_of_version_list));
S2N_ERROR_IF(size_of_version_list != s2n_stuffer_data_available(extension), S2N_ERR_BAD_MESSAGE);
S2N_ERROR_IF(size_of_version_list % S2N_TLS_PROTOCOL_VERSION_LEN != 0, S2N_ERR_BAD_MESSAGE);
@@ -88,7 +89,7 @@ static int s2n_extensions_client_supported_versions_process(struct s2n_connectio
for (int i = 0; i < size_of_version_list; i += S2N_TLS_PROTOCOL_VERSION_LEN) {
uint8_t client_version_parts[S2N_TLS_PROTOCOL_VERSION_LEN];
- GUARD(s2n_stuffer_read_bytes(extension, client_version_parts, S2N_TLS_PROTOCOL_VERSION_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(extension, client_version_parts, S2N_TLS_PROTOCOL_VERSION_LEN));
/* If the client version is outside of our supported versions, then ignore the value.
* S2N does not support SSLv2 except for upgrading connections. Since this extension is
@@ -127,7 +128,7 @@ static int s2n_client_supported_versions_recv(struct s2n_connection *conn, struc
if (s2n_extensions_client_supported_versions_process(conn, in) < 0) {
s2n_queue_reader_unsupported_protocol_version_alert(conn);
- S2N_ERROR(S2N_ERR_BAD_MESSAGE);
+ POSIX_BAIL(S2N_ERR_BAD_MESSAGE);
}
return S2N_SUCCESS;
}
@@ -135,8 +136,8 @@ static int s2n_client_supported_versions_recv(struct s2n_connection *conn, struc
/* Old-style extension functions -- remove after extensions refactor is complete */
int s2n_extensions_client_supported_versions_size(struct s2n_connection *conn) {
- uint8_t minimum_supported_version;
- GUARD(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version));
+ uint8_t minimum_supported_version = s2n_unknown_protocol_version;
+ POSIX_GUARD_RESULT(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version));
uint8_t highest_supported_version = conn->client_protocol_version;
uint8_t version_list_length = highest_supported_version - minimum_supported_version + 1;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.c
index 7e8885bc0b..18940d7191 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.c
@@ -22,6 +22,7 @@
const s2n_extension_type s2n_client_cookie_extension = {
.iana_value = TLS_EXTENSION_COOKIE,
+ .minimum_version = S2N_TLS13,
.is_response = true,
.send = s2n_extension_send_noop,
.recv = s2n_extension_recv_noop,
@@ -35,6 +36,7 @@ static int s2n_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *exte
const s2n_extension_type s2n_server_cookie_extension = {
.iana_value = TLS_EXTENSION_COOKIE,
+ .minimum_version = S2N_TLS13,
.is_response = false,
.send = s2n_cookie_send,
.recv = s2n_cookie_recv,
@@ -44,33 +46,29 @@ const s2n_extension_type s2n_server_cookie_extension = {
static bool s2n_cookie_should_send(struct s2n_connection *conn)
{
- return s2n_extension_send_if_tls13_connection(conn)
- && conn && s2n_stuffer_data_available(&conn->cookie_stuffer) > 0;
+ return conn && s2n_stuffer_data_available(&conn->cookie_stuffer) > 0;
}
static int s2n_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
uint16_t cookie_size = s2n_stuffer_data_available(&conn->cookie_stuffer);
- GUARD(s2n_stuffer_write_uint16(out, cookie_size));
- GUARD(s2n_stuffer_copy(&conn->cookie_stuffer, out, cookie_size));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, cookie_size));
+ POSIX_GUARD(s2n_stuffer_copy(&conn->cookie_stuffer, out, cookie_size));
return S2N_SUCCESS;
}
static int s2n_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- notnull_check(conn);
- if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
- return S2N_SUCCESS;
- }
+ POSIX_ENSURE_REF(conn);
uint16_t cookie_len;
- GUARD(s2n_stuffer_read_uint16(extension, &cookie_len));
- ENSURE_POSIX(s2n_stuffer_data_available(extension) == cookie_len, S2N_ERR_BAD_MESSAGE);
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &cookie_len));
+ POSIX_ENSURE(s2n_stuffer_data_available(extension) == cookie_len, S2N_ERR_BAD_MESSAGE);
- GUARD(s2n_stuffer_wipe(&conn->cookie_stuffer));
- GUARD(s2n_stuffer_resize(&conn->cookie_stuffer, cookie_len));
- GUARD(s2n_stuffer_copy(extension, &conn->cookie_stuffer, cookie_len));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->cookie_stuffer));
+ POSIX_GUARD(s2n_stuffer_resize(&conn->cookie_stuffer, cookie_len));
+ POSIX_GUARD(s2n_stuffer_copy(extension, &conn->cookie_stuffer, cookie_len));
return S2N_SUCCESS;
}
@@ -78,7 +76,7 @@ static int s2n_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *exte
int s2n_extensions_cookie_size(struct s2n_connection *conn)
{
- GUARD(s2n_stuffer_reread(&conn->cookie_stuffer));
+ POSIX_GUARD(s2n_stuffer_reread(&conn->cookie_stuffer));
if (s2n_stuffer_data_available(&conn->cookie_stuffer) == 0) {
return 0;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_early_data_indication.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_early_data_indication.h
new file mode 100644
index 0000000000..8e78c11cba
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_early_data_indication.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"
+
+extern const s2n_extension_type s2n_client_early_data_indication_extension;
+extern const s2n_extension_type s2n_server_early_data_indication_extension;
+extern const s2n_extension_type s2n_nst_early_data_indication_extension;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c
index cb720581a6..00d0a240f9 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c
@@ -54,10 +54,10 @@ static bool s2n_server_ec_point_format_should_send(struct s2n_connection *conn)
static int s2n_ec_point_format_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
/* Point format list len. We only support one. */
- GUARD(s2n_stuffer_write_uint8(out, 1));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, 1));
/* Only allow uncompressed format */
- GUARD(s2n_stuffer_write_uint8(out, TLS_EC_POINT_FORMAT_UNCOMPRESSED));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, TLS_EC_POINT_FORMAT_UNCOMPRESSED));
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_ems.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_ems.h
new file mode 100644
index 0000000000..7478332c34
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_ems.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#pragma once
+
+#include "tls/extensions/s2n_extension_type.h"
+
+extern const s2n_extension_type s2n_client_ems_extension;
+extern const s2n_extension_type s2n_server_ems_extension;
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 5188535bf4..25000e56a9 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c
@@ -17,7 +17,7 @@
#include "s2n_extension_type.h"
#include "s2n_extension_type_lists.h"
-#include <s2n.h>
+#include "api/s2n.h"
#include "error/s2n_errno.h"
#include "utils/s2n_safety.h"
@@ -29,46 +29,46 @@ static const s2n_parsed_extension empty_parsed_extensions[S2N_PARSED_EXTENSIONS_
int s2n_extension_list_send(s2n_extension_list_id list_type, struct s2n_connection *conn, struct s2n_stuffer *out)
{
s2n_extension_type_list *extension_type_list;
- GUARD(s2n_extension_type_list_get(list_type, &extension_type_list));
+ POSIX_GUARD(s2n_extension_type_list_get(list_type, &extension_type_list));
struct s2n_stuffer_reservation total_extensions_size = {0};
- GUARD(s2n_stuffer_reserve_uint16(out, &total_extensions_size));
+ POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &total_extensions_size));
for (int i = 0; i < extension_type_list->count; i++) {
- GUARD(s2n_extension_send(extension_type_list->extension_types[i], conn, out));
+ POSIX_GUARD(s2n_extension_send(extension_type_list->extension_types[i], conn, out));
}
- GUARD(s2n_stuffer_write_vector_size(&total_extensions_size));
+ POSIX_GUARD(s2n_stuffer_write_vector_size(&total_extensions_size));
return S2N_SUCCESS;
}
int s2n_extension_list_recv(s2n_extension_list_id list_type, struct s2n_connection *conn, struct s2n_stuffer *in)
{
s2n_parsed_extensions_list parsed_extension_list = { 0 };
- GUARD(s2n_extension_list_parse(in, &parsed_extension_list));
- GUARD(s2n_extension_list_process(list_type, conn, &parsed_extension_list));
+ POSIX_GUARD(s2n_extension_list_parse(in, &parsed_extension_list));
+ POSIX_GUARD(s2n_extension_list_process(list_type, conn, &parsed_extension_list));
return S2N_SUCCESS;
}
static int s2n_extension_process_impl(const s2n_extension_type *extension_type, s2n_extension_type_id extension_id,
struct s2n_connection *conn, s2n_parsed_extension *parsed_extensions)
{
- notnull_check(extension_type);
- notnull_check(parsed_extensions);
+ POSIX_ENSURE_REF(extension_type);
+ POSIX_ENSURE_REF(parsed_extensions);
if (s2n_parsed_extension_is_empty(&parsed_extensions[extension_id])) {
- GUARD(s2n_extension_is_missing(extension_type, conn));
+ POSIX_GUARD(s2n_extension_is_missing(extension_type, conn));
return S2N_SUCCESS;
}
- ENSURE_POSIX(parsed_extensions[extension_id].extension_type == extension_type->iana_value,
+ POSIX_ENSURE(parsed_extensions[extension_id].extension_type == extension_type->iana_value,
S2N_ERR_INVALID_PARSED_EXTENSIONS);
struct s2n_stuffer extension_stuffer;
- GUARD(s2n_stuffer_init(&extension_stuffer, &parsed_extensions[extension_id].extension));
- GUARD(s2n_stuffer_skip_write(&extension_stuffer, parsed_extensions[extension_id].extension.size));
+ POSIX_GUARD(s2n_stuffer_init(&extension_stuffer, &parsed_extensions[extension_id].extension));
+ POSIX_GUARD(s2n_stuffer_skip_write(&extension_stuffer, parsed_extensions[extension_id].extension.size));
- GUARD(s2n_extension_recv(extension_type, conn, &extension_stuffer));
+ POSIX_GUARD(s2n_extension_recv(extension_type, conn, &extension_stuffer));
return S2N_SUCCESS;
}
@@ -76,11 +76,11 @@ static int s2n_extension_process_impl(const s2n_extension_type *extension_type,
int s2n_extension_process(const s2n_extension_type *extension_type, struct s2n_connection *conn,
s2n_parsed_extensions_list *parsed_extension_list)
{
- notnull_check(parsed_extension_list);
- notnull_check(extension_type);
+ POSIX_ENSURE_REF(parsed_extension_list);
+ POSIX_ENSURE_REF(extension_type);
s2n_extension_type_id extension_id;
- GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id));
+ POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id));
int result = s2n_extension_process_impl(extension_type, extension_id, conn, parsed_extension_list->parsed_extensions);
@@ -94,13 +94,13 @@ int s2n_extension_process(const s2n_extension_type *extension_type, struct s2n_c
int s2n_extension_list_process(s2n_extension_list_id list_type, struct s2n_connection *conn,
s2n_parsed_extensions_list *parsed_extension_list)
{
- notnull_check(parsed_extension_list);
+ POSIX_ENSURE_REF(parsed_extension_list);
s2n_extension_type_list *extension_type_list;
- GUARD(s2n_extension_type_list_get(list_type, &extension_type_list));
+ POSIX_GUARD(s2n_extension_type_list_get(list_type, &extension_type_list));
for (int i = 0; i < extension_type_list->count; i++) {
- GUARD(s2n_extension_process(extension_type_list->extension_types[i],
+ POSIX_GUARD(s2n_extension_process(extension_type_list->extension_types[i],
conn, parsed_extension_list));
}
@@ -122,19 +122,19 @@ int s2n_extension_list_process(s2n_extension_list_id list_type, struct s2n_conne
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);
+ POSIX_ENSURE_REF(parsed_extensions);
+ POSIX_ENSURE_REF(wire_index);
uint16_t extension_type;
- ENSURE_POSIX(s2n_stuffer_read_uint16(in, &extension_type) == S2N_SUCCESS,
+ POSIX_ENSURE(s2n_stuffer_read_uint16(in, &extension_type) == S2N_SUCCESS,
S2N_ERR_BAD_MESSAGE);
uint16_t extension_size;
- ENSURE_POSIX(s2n_stuffer_read_uint16(in, &extension_size) == S2N_SUCCESS,
+ POSIX_ENSURE(s2n_stuffer_read_uint16(in, &extension_size) == S2N_SUCCESS,
S2N_ERR_BAD_MESSAGE);
uint8_t *extension_data = s2n_stuffer_raw_read(in, extension_size);
- ENSURE_POSIX(extension_data != NULL, S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE(extension_data != NULL, S2N_ERR_BAD_MESSAGE);
s2n_extension_type_id extension_id;
if (s2n_extension_supported_iana_value_to_id(extension_type, &extension_id) != S2N_SUCCESS) {
@@ -145,13 +145,13 @@ static int s2n_extension_parse(struct s2n_stuffer *in, s2n_parsed_extension *par
s2n_parsed_extension *parsed_extension = &parsed_extensions[extension_id];
/* Error if extension is a duplicate */
- ENSURE_POSIX(s2n_parsed_extension_is_empty(parsed_extension),
+ POSIX_ENSURE(s2n_parsed_extension_is_empty(parsed_extension),
S2N_ERR_DUPLICATE_EXTENSION);
/* 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));
+ POSIX_GUARD(s2n_blob_init(&parsed_extension->extension, extension_data, extension_size));
(*wire_index)++;
return S2N_SUCCESS;
@@ -159,10 +159,10 @@ static int s2n_extension_parse(struct s2n_stuffer *in, s2n_parsed_extension *par
int s2n_extension_list_parse(struct s2n_stuffer *in, s2n_parsed_extensions_list *parsed_extension_list)
{
- notnull_check(in);
- notnull_check(parsed_extension_list);
+ POSIX_ENSURE_REF(in);
+ POSIX_ENSURE_REF(parsed_extension_list);
- memset_check((s2n_parsed_extension*) parsed_extension_list->parsed_extensions,
+ POSIX_CHECKED_MEMSET((s2n_parsed_extension*) parsed_extension_list->parsed_extensions,
0, sizeof(parsed_extension_list->parsed_extensions));
uint16_t total_extensions_size;
@@ -171,17 +171,17 @@ int s2n_extension_list_parse(struct s2n_stuffer *in, s2n_parsed_extensions_list
}
uint8_t *extensions_data = s2n_stuffer_raw_read(in, total_extensions_size);
- ENSURE_POSIX(extensions_data != NULL, S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE(extensions_data != NULL, S2N_ERR_BAD_MESSAGE);
- GUARD(s2n_blob_init(&parsed_extension_list->raw, extensions_data, total_extensions_size));
+ POSIX_GUARD(s2n_blob_init(&parsed_extension_list->raw, extensions_data, total_extensions_size));
struct s2n_stuffer extensions_stuffer;
- GUARD(s2n_stuffer_init(&extensions_stuffer, &parsed_extension_list->raw));
- GUARD(s2n_stuffer_skip_write(&extensions_stuffer, total_extensions_size));
+ POSIX_GUARD(s2n_stuffer_init(&extensions_stuffer, &parsed_extension_list->raw));
+ POSIX_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, &wire_index));
+ POSIX_GUARD(s2n_extension_parse(&extensions_stuffer, parsed_extension_list->parsed_extensions, &wire_index));
}
parsed_extension_list->count = wire_index;
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 dcf7c9da9b..a26eb3a89c 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h
@@ -34,11 +34,13 @@ typedef struct {
typedef enum {
S2N_EXTENSION_LIST_CLIENT_HELLO = 0,
+ S2N_EXTENSION_LIST_HELLO_RETRY_REQUEST,
S2N_EXTENSION_LIST_SERVER_HELLO_DEFAULT,
S2N_EXTENSION_LIST_SERVER_HELLO_TLS13,
S2N_EXTENSION_LIST_ENCRYPTED_EXTENSIONS,
S2N_EXTENSION_LIST_CERT_REQ,
S2N_EXTENSION_LIST_CERTIFICATE,
+ S2N_EXTENSION_LIST_NST,
S2N_EXTENSION_LIST_EMPTY,
S2N_EXTENSION_LIST_IDS_COUNT,
} s2n_extension_list_id;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c
index 040c57a16c..1c808f1d8c 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-#include <s2n.h>
+#include "api/s2n.h"
#include "error/s2n_errno.h"
#include "tls/extensions/s2n_extension_type.h"
@@ -72,7 +72,7 @@ s2n_extension_type_id s2n_extension_iana_value_to_id(const uint16_t iana_value)
int s2n_extension_supported_iana_value_to_id(const uint16_t iana_value, s2n_extension_type_id *internal_id)
{
- notnull_check(internal_id);
+ POSIX_ENSURE_REF(internal_id);
*internal_id = s2n_extension_iana_value_to_id(iana_value);
S2N_ERROR_IF(*internal_id == s2n_unsupported_extension, S2N_ERR_UNRECOGNIZED_EXTENSION);
@@ -81,13 +81,13 @@ int s2n_extension_supported_iana_value_to_id(const uint16_t iana_value, s2n_exte
int s2n_extension_send(const s2n_extension_type *extension_type, struct s2n_connection *conn, struct s2n_stuffer *out)
{
- notnull_check(extension_type);
- notnull_check(extension_type->should_send);
- notnull_check(extension_type->send);
- notnull_check(conn);
+ POSIX_ENSURE_REF(extension_type);
+ POSIX_ENSURE_REF(extension_type->should_send);
+ POSIX_ENSURE_REF(extension_type->send);
+ POSIX_ENSURE_REF(conn);
s2n_extension_type_id extension_id;
- GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id));
+ POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id));
/* Do not send response if request not received. */
if (extension_type->is_response &&
@@ -95,23 +95,28 @@ int s2n_extension_send(const s2n_extension_type *extension_type, struct s2n_conn
return S2N_SUCCESS;
}
+ /* Do not send an extension that is not valid for the protocol version */
+ if (extension_type->minimum_version > conn->actual_protocol_version) {
+ return S2N_SUCCESS;
+ }
+
/* Check if we need to send. Some extensions are only sent if specific conditions are met. */
if (!extension_type->should_send(conn)) {
return S2N_SUCCESS;
}
/* Write extension type */
- GUARD(s2n_stuffer_write_uint16(out, extension_type->iana_value));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, extension_type->iana_value));
/* Reserve space for extension size */
struct s2n_stuffer_reservation extension_size_bytes = {0};
- GUARD(s2n_stuffer_reserve_uint16(out, &extension_size_bytes));
+ POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &extension_size_bytes));
/* Write extension data */
- GUARD(extension_type->send(conn, out));
+ POSIX_GUARD(extension_type->send(conn, out));
/* Record extension size */
- GUARD(s2n_stuffer_write_vector_size(&extension_size_bytes));
+ POSIX_GUARD(s2n_stuffer_write_vector_size(&extension_size_bytes));
/* Set request bit flag */
if (!extension_type->is_response) {
@@ -123,20 +128,37 @@ int s2n_extension_send(const s2n_extension_type *extension_type, struct s2n_conn
int s2n_extension_recv(const s2n_extension_type *extension_type, struct s2n_connection *conn, struct s2n_stuffer *in)
{
- notnull_check(extension_type);
- notnull_check(extension_type->recv);
- notnull_check(conn);
+ POSIX_ENSURE_REF(extension_type);
+ POSIX_ENSURE_REF(extension_type->recv);
+ POSIX_ENSURE_REF(conn);
s2n_extension_type_id extension_id;
- GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id));
-
- /* Do not accept a response if we did not send a request */
- if(extension_type->is_response &&
+ POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id));
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2
+ *# Implementations MUST NOT send extension responses if the remote
+ *# endpoint did not send the corresponding extension requests, with the
+ *# exception of the "cookie" extension in the HelloRetryRequest. Upon
+ *# receiving such an extension, an endpoint MUST abort the handshake
+ *# with an "unsupported_extension" alert.
+ *
+ *= https://tools.ietf.org/rfc/rfc7627#section-5.3
+ *# If the original session did not use the "extended_master_secret"
+ *# extension but the new ServerHello contains the extension, the
+ *# client MUST abort the handshake.
+ **/
+ if (extension_type->is_response &&
!S2N_CBIT_TEST(conn->extension_requests_sent, extension_id)) {
- S2N_ERROR(S2N_ERR_UNSUPPORTED_EXTENSION);
+ POSIX_BAIL(S2N_ERR_UNSUPPORTED_EXTENSION);
}
- GUARD(extension_type->recv(conn, in));
+ /* Do not process an extension not valid for the protocol version */
+ if (extension_type->minimum_version > conn->actual_protocol_version) {
+ return S2N_SUCCESS;
+ }
+
+ POSIX_GUARD(extension_type->recv(conn, in));
/* Set request bit flag */
if (!extension_type->is_response) {
@@ -148,12 +170,12 @@ int s2n_extension_recv(const s2n_extension_type *extension_type, struct s2n_conn
int s2n_extension_is_missing(const s2n_extension_type *extension_type, struct s2n_connection *conn)
{
- notnull_check(extension_type);
- notnull_check(extension_type->if_missing);
- notnull_check(conn);
+ POSIX_ENSURE_REF(extension_type);
+ POSIX_ENSURE_REF(extension_type->if_missing);
+ POSIX_ENSURE_REF(conn);
s2n_extension_type_id extension_id;
- GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id));
+ POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type->iana_value, &extension_id));
/* Do not consider an extension missing if we did not send a request */
if(extension_type->is_response &&
@@ -161,19 +183,24 @@ int s2n_extension_is_missing(const s2n_extension_type *extension_type, struct s2
return S2N_SUCCESS;
}
- GUARD(extension_type->if_missing(conn));
+ /* Do not consider an extension missing if it is not valid for the protocol version */
+ if (extension_type->minimum_version > conn->actual_protocol_version) {
+ return S2N_SUCCESS;
+ }
+
+ POSIX_GUARD(extension_type->if_missing(conn));
return S2N_SUCCESS;
}
int s2n_extension_send_unimplemented(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- S2N_ERROR(S2N_ERR_UNIMPLEMENTED);
+ POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
}
int s2n_extension_recv_unimplemented(struct s2n_connection *conn, struct s2n_stuffer *in)
{
- S2N_ERROR(S2N_ERR_UNIMPLEMENTED);
+ POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
}
int s2n_extension_send_noop(struct s2n_connection *conn, struct s2n_stuffer *out)
@@ -203,7 +230,7 @@ bool s2n_extension_send_if_tls13_connection(struct s2n_connection *conn)
int s2n_extension_error_if_missing(struct s2n_connection *conn)
{
- S2N_ERROR(S2N_ERR_MISSING_EXTENSION);
+ POSIX_BAIL(S2N_ERR_MISSING_EXTENSION);
}
int s2n_extension_noop_if_missing(struct s2n_connection *conn)
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 3c95af639f..f3ccf58730 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h
@@ -22,6 +22,7 @@
#define S2N_EXTENSION_TYPE_FIELD_LENGTH 2
#define S2N_EXTENSION_LENGTH_FIELD_LENGTH 2
+#define S2N_EXTENSION_HEADER_LENGTH (S2N_EXTENSION_TYPE_FIELD_LENGTH + S2N_EXTENSION_LENGTH_FIELD_LENGTH)
/* The number of extensions supported by S2N */
#define S2N_SUPPORTED_EXTENSIONS_COUNT (sizeof(s2n_supported_extensions) / sizeof(s2n_supported_extensions[0]))
@@ -34,6 +35,7 @@ struct s2n_connection;
typedef struct {
uint16_t iana_value;
unsigned is_response:1;
+ uint16_t minimum_version;
int (*send) (struct s2n_connection *conn, struct s2n_stuffer *out);
int (*recv) (struct s2n_connection *conn, struct s2n_stuffer *in);
@@ -63,6 +65,8 @@ static const uint16_t s2n_supported_extensions[] = {
TLS_QUIC_TRANSPORT_PARAMETERS,
TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES,
TLS_EXTENSION_PRE_SHARED_KEY,
+ TLS_EXTENSION_EARLY_DATA,
+ TLS_EXTENSION_EMS,
};
typedef char s2n_extension_bitfield[S2N_SUPPORTED_EXTENSIONS_BITFIELD_LEN];
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.c
index 5395366a6c..ba749a4e87 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
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-#include <s2n.h>
+#include "api/s2n.h"
#include "tls/extensions/s2n_extension_type_lists.h"
#include "tls/s2n_connection.h"
@@ -31,6 +31,8 @@
#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_ems.h"
+#include "tls/extensions/s2n_early_data_indication.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"
@@ -50,7 +52,13 @@
static const s2n_extension_type *const client_hello_extensions[] = {
&s2n_client_supported_versions_extension,
+
+ /* We MUST process key_share after supported_groups,
+ * because we need to choose the keyshare based on the
+ * mutually supported groups. */
+ &s2n_client_supported_groups_extension,
&s2n_client_key_share_extension,
+
&s2n_client_signature_algorithms_extension,
&s2n_client_server_name_extension,
&s2n_client_alpn_extension,
@@ -58,13 +66,14 @@ static const s2n_extension_type *const client_hello_extensions[] = {
&s2n_client_sct_list_extension,
&s2n_client_max_frag_len_extension,
&s2n_client_session_ticket_extension,
- &s2n_client_supported_groups_extension,
&s2n_client_ec_point_format_extension,
&s2n_client_pq_kem_extension,
&s2n_client_renegotiation_info_extension,
&s2n_client_cookie_extension,
&s2n_quic_transport_parameters_extension,
&s2n_psk_key_exchange_modes_extension,
+ &s2n_client_early_data_indication_extension,
+ &s2n_client_ems_extension,
&s2n_client_psk_extension /* MUST be last */
};
@@ -78,6 +87,24 @@ static const s2n_extension_type *const tls12_server_hello_extensions[] = {
&s2n_server_sct_list_extension,
&s2n_server_max_fragment_length_extension,
&s2n_server_session_ticket_extension,
+ &s2n_server_ems_extension,
+};
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.1.4
+ *# The
+ *# HelloRetryRequest extensions defined in this specification are:
+ *#
+ *# - supported_versions (see Section 4.2.1)
+ *#
+ *# - cookie (see Section 4.2.2)
+ *#
+ *# - key_share (see Section 4.2.8)
+ */
+static const s2n_extension_type *const hello_retry_request_extensions[] = {
+ &s2n_server_supported_versions_extension,
+ &s2n_server_cookie_extension,
+ &s2n_server_key_share_extension,
};
static const s2n_extension_type *const tls13_server_hello_extensions[] = {
@@ -92,6 +119,7 @@ static const s2n_extension_type *const encrypted_extensions[] = {
&s2n_server_max_fragment_length_extension,
&s2n_server_alpn_extension,
&s2n_quic_transport_parameters_extension,
+ &s2n_server_early_data_indication_extension,
};
static const s2n_extension_type *const cert_req_extensions[] = {
@@ -103,22 +131,28 @@ static const s2n_extension_type *const certificate_extensions[] = {
&s2n_server_sct_list_extension,
};
+static const s2n_extension_type *const nst_extensions[] = {
+ &s2n_nst_early_data_indication_extension,
+};
+
#define S2N_EXTENSION_LIST(list) { .extension_types = (list), .count = s2n_array_len(list) }
static s2n_extension_type_list extension_lists[] = {
[S2N_EXTENSION_LIST_CLIENT_HELLO] = S2N_EXTENSION_LIST(client_hello_extensions),
+ [S2N_EXTENSION_LIST_HELLO_RETRY_REQUEST] = S2N_EXTENSION_LIST(hello_retry_request_extensions),
[S2N_EXTENSION_LIST_SERVER_HELLO_DEFAULT] = S2N_EXTENSION_LIST(tls12_server_hello_extensions),
[S2N_EXTENSION_LIST_SERVER_HELLO_TLS13] = S2N_EXTENSION_LIST(tls13_server_hello_extensions),
[S2N_EXTENSION_LIST_ENCRYPTED_EXTENSIONS] = S2N_EXTENSION_LIST(encrypted_extensions),
[S2N_EXTENSION_LIST_CERT_REQ] = S2N_EXTENSION_LIST(cert_req_extensions),
[S2N_EXTENSION_LIST_CERTIFICATE] = S2N_EXTENSION_LIST(certificate_extensions),
+ [S2N_EXTENSION_LIST_NST] = S2N_EXTENSION_LIST(nst_extensions),
[S2N_EXTENSION_LIST_EMPTY] = { .extension_types = NULL, .count = 0 },
};
int s2n_extension_type_list_get(s2n_extension_list_id list_type, s2n_extension_type_list **extension_list)
{
- notnull_check(extension_list);
- lt_check(list_type, s2n_array_len(extension_lists));
+ POSIX_ENSURE_REF(extension_list);
+ POSIX_ENSURE_LT(list_type, s2n_array_len(extension_lists));
*extension_list = &extension_lists[list_type];
return S2N_SUCCESS;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.c
index a91dbfd30b..6b3f144b3a 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.c
@@ -17,17 +17,33 @@
#include "tls/s2n_tls.h"
#include "utils/s2n_safety.h"
-int s2n_ecdhe_parameters_send(struct s2n_ecc_evp_params *ecc_evp_params, struct s2n_stuffer *out)
+/* Generate and write an ecc point.
+ * This is used to write the ecc portion of PQ hybrid keyshares, which does NOT include the curve id.
+ */
+S2N_RESULT s2n_ecdhe_send_public_key(struct s2n_ecc_evp_params *ecc_evp_params, struct s2n_stuffer *out)
{
- notnull_check(out);
- notnull_check(ecc_evp_params);
- notnull_check(ecc_evp_params->negotiated_curve);
+ RESULT_ENSURE_REF(ecc_evp_params);
+ RESULT_ENSURE_REF(ecc_evp_params->negotiated_curve);
+
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint16(out, ecc_evp_params->negotiated_curve->share_size));
+ if (ecc_evp_params->evp_pkey == NULL) {
+ RESULT_GUARD_POSIX(s2n_ecc_evp_generate_ephemeral_key(ecc_evp_params));
+ }
+ RESULT_GUARD_POSIX(s2n_ecc_evp_write_params_point(ecc_evp_params, out));
+
+ return S2N_RESULT_OK;
+}
- GUARD(s2n_stuffer_write_uint16(out, ecc_evp_params->negotiated_curve->iana_id));
- GUARD(s2n_stuffer_write_uint16(out, ecc_evp_params->negotiated_curve->share_size));
+/* Generate and write an ecc point and its corresponding curve id.
+ * This is used to write ecc keyshares for the client and server key_share extensions.
+ */
+int s2n_ecdhe_parameters_send(struct s2n_ecc_evp_params *ecc_evp_params, struct s2n_stuffer *out)
+{
+ POSIX_ENSURE_REF(ecc_evp_params);
+ POSIX_ENSURE_REF(ecc_evp_params->negotiated_curve);
- GUARD(s2n_ecc_evp_generate_ephemeral_key(ecc_evp_params));
- GUARD(s2n_ecc_evp_write_params_point(ecc_evp_params, out));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, ecc_evp_params->negotiated_curve->iana_id));
+ POSIX_GUARD_RESULT(s2n_ecdhe_send_public_key(ecc_evp_params, out));
- return 0;
+ return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.h
index f621d76b52..daa464c2bd 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.h
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.h
@@ -25,4 +25,5 @@
#define S2N_SIZE_OF_NAMED_GROUP 2
#define S2N_SIZE_OF_KEY_SHARE_SIZE 2
-extern int s2n_ecdhe_parameters_send(struct s2n_ecc_evp_params *ecc_evp_params, struct s2n_stuffer *out);
+S2N_RESULT s2n_ecdhe_send_public_key(struct s2n_ecc_evp_params *ecc_evp_params, struct s2n_stuffer *out);
+int s2n_ecdhe_parameters_send(struct s2n_ecc_evp_params *ecc_evp_params, struct s2n_stuffer *out);
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_nst_early_data_indication.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_nst_early_data_indication.c
new file mode 100644
index 0000000000..0f149ec2fe
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_nst_early_data_indication.c
@@ -0,0 +1,80 @@
+/*
+ * 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 "api/s2n.h"
+
+#include "tls/extensions/s2n_early_data_indication.h"
+
+#include "stuffer/s2n_stuffer.h"
+#include "tls/s2n_connection.h"
+#include "tls/s2n_early_data.h"
+#include "utils/s2n_safety.h"
+
+static bool s2n_nst_early_data_indication_should_send(struct s2n_connection *conn)
+{
+ uint32_t server_max_early_data = 0;
+ return s2n_result_is_ok(s2n_early_data_get_server_max_size(conn, &server_max_early_data))
+ && server_max_early_data > 0;
+}
+
+/**
+ * The client version of this extension is empty, so we don't read/write any data.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# The "extension_data" field of this extension contains an
+ *# "EarlyDataIndication" value.
+ *#
+ *# struct {} Empty;
+ *#
+ *# struct {
+ *# select (Handshake.msg_type) {
+ *# case new_session_ticket: uint32 max_early_data_size;
+ **
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# };
+ *# } EarlyDataIndication;
+ **/
+
+static int s2n_nst_early_data_indication_send(struct s2n_connection *conn, struct s2n_stuffer *out)
+{
+ uint32_t server_max_early_data = 0;
+ POSIX_GUARD_RESULT(s2n_early_data_get_server_max_size(conn, &server_max_early_data));
+ POSIX_GUARD(s2n_stuffer_write_uint32(out, server_max_early_data));
+ return S2N_SUCCESS;
+}
+
+static int s2n_nst_early_data_indiction_recv(struct s2n_connection *conn, struct s2n_stuffer *in)
+{
+ POSIX_ENSURE_REF(conn);
+ uint32_t server_max_early_data = 0;
+ POSIX_GUARD(s2n_stuffer_read_uint32(in, &server_max_early_data));
+ POSIX_GUARD(s2n_connection_set_server_max_early_data_size(conn, server_max_early_data));
+ return S2N_SUCCESS;
+}
+
+static int s2n_nst_early_data_indication_missing(struct s2n_connection *conn)
+{
+ POSIX_GUARD(s2n_connection_set_server_max_early_data_size(conn, 0));
+ return S2N_SUCCESS;
+}
+
+const s2n_extension_type s2n_nst_early_data_indication_extension = {
+ .iana_value = TLS_EXTENSION_EARLY_DATA,
+ .is_response = false,
+ .send = s2n_nst_early_data_indication_send,
+ .recv = s2n_nst_early_data_indiction_recv,
+ .should_send = s2n_nst_early_data_indication_should_send,
+ .if_missing = s2n_nst_early_data_indication_missing,
+};
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c
index 67b1904b6b..e66a552772 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_psk_key_exchange_modes.c
@@ -18,16 +18,16 @@
#include "tls/s2n_tls_parameters.h"
#include "tls/extensions/s2n_client_psk.h"
+#include "tls/extensions/s2n_psk_key_exchange_modes.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,
+ .minimum_version = S2N_TLS13,
.is_response = false,
.send = s2n_psk_key_exchange_modes_send,
.recv = s2n_psk_key_exchange_modes_recv,
@@ -43,26 +43,22 @@ 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)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
- GUARD(s2n_stuffer_write_uint8(out, PSK_KEY_EXCHANGE_MODE_SIZE));
+ POSIX_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));
+ POSIX_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;
- }
+ POSIX_ENSURE_REF(conn);
uint8_t psk_ke_mode_list_len;
- GUARD(s2n_stuffer_read_uint8(extension, &psk_ke_mode_list_len));
+ POSIX_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;
@@ -70,7 +66,7 @@ static int s2n_psk_key_exchange_modes_recv(struct s2n_connection *conn, struct s
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));
+ POSIX_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) {
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
index 3c64f64489..74c1fe9797 100644
--- 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
@@ -19,4 +19,6 @@
#include "tls/s2n_connection.h"
#include "stuffer/s2n_stuffer.h"
+#define PSK_KEY_EXCHANGE_MODE_SIZE sizeof(uint8_t)
+
extern const s2n_extension_type s2n_psk_key_exchange_modes_extension;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.c
index 56f17abc3b..ab84388e7a 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.c
@@ -31,44 +31,45 @@
static bool s2n_quic_transport_params_should_send(struct s2n_connection *conn)
{
- return conn && conn->config && conn->config->quic_enabled;
+ return s2n_connection_is_quic_enabled(conn);
}
static int s2n_quic_transport_params_if_missing(struct s2n_connection *conn)
{
- notnull_check(conn);
- notnull_check(conn->config);
- ENSURE_POSIX(!conn->config->quic_enabled, S2N_ERR_MISSING_EXTENSION);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->config);
+ POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_MISSING_EXTENSION);
return S2N_SUCCESS;
}
static int s2n_quic_transport_params_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- notnull_check(conn);
- notnull_check(out);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(out);
if (conn->our_quic_transport_parameters.size) {
- GUARD(s2n_stuffer_write(out, &conn->our_quic_transport_parameters));
+ POSIX_GUARD(s2n_stuffer_write(out, &conn->our_quic_transport_parameters));
}
return S2N_SUCCESS;
}
static int s2n_quic_transport_params_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- notnull_check(conn);
- notnull_check(extension);
- notnull_check(conn->config);
- ENSURE_POSIX(conn->config->quic_enabled, S2N_ERR_UNSUPPORTED_EXTENSION);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(extension);
+ POSIX_ENSURE_REF(conn->config);
+ POSIX_ENSURE(s2n_connection_is_quic_enabled(conn), S2N_ERR_UNSUPPORTED_EXTENSION);
if (s2n_stuffer_data_available(extension)) {
- GUARD(s2n_alloc(&conn->peer_quic_transport_parameters, s2n_stuffer_data_available(extension)));
- GUARD(s2n_stuffer_read(extension, &conn->peer_quic_transport_parameters));
+ POSIX_GUARD(s2n_alloc(&conn->peer_quic_transport_parameters, s2n_stuffer_data_available(extension)));
+ POSIX_GUARD(s2n_stuffer_read(extension, &conn->peer_quic_transport_parameters));
}
return S2N_SUCCESS;
}
const s2n_extension_type s2n_quic_transport_parameters_extension = {
.iana_value = TLS_QUIC_TRANSPORT_PARAMETERS,
+ .minimum_version = S2N_TLS13,
.is_response = false,
.send = s2n_quic_transport_params_send,
.recv = s2n_quic_transport_params_recv,
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c
index a1f5ac17cf..9e6dee2136 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c
@@ -42,39 +42,39 @@ static bool s2n_alpn_should_send(struct s2n_connection *conn)
static int s2n_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
const uint8_t application_protocol_len = strlen(conn->application_protocol);
/* Size of protocol name list */
- GUARD(s2n_stuffer_write_uint16(out, application_protocol_len + sizeof(uint8_t)));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, application_protocol_len + sizeof(uint8_t)));
/* Single entry in protocol name list */
- GUARD(s2n_stuffer_write_uint8(out, application_protocol_len));
- GUARD(s2n_stuffer_write_bytes(out, (uint8_t *) conn->application_protocol, application_protocol_len));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, application_protocol_len));
+ POSIX_GUARD(s2n_stuffer_write_bytes(out, (uint8_t *) conn->application_protocol, application_protocol_len));
return S2N_SUCCESS;
}
static int s2n_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
uint16_t size_of_all;
- GUARD(s2n_stuffer_read_uint16(extension, &size_of_all));
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &size_of_all));
if (size_of_all > s2n_stuffer_data_available(extension) || size_of_all < 3) {
/* ignore invalid extension size */
return S2N_SUCCESS;
}
uint8_t protocol_len;
- GUARD(s2n_stuffer_read_uint8(extension, &protocol_len));
- lt_check(protocol_len, s2n_array_len(conn->application_protocol));
+ POSIX_GUARD(s2n_stuffer_read_uint8(extension, &protocol_len));
+ POSIX_ENSURE_LT(protocol_len, s2n_array_len(conn->application_protocol));
uint8_t *protocol = s2n_stuffer_raw_read(extension, protocol_len);
- notnull_check(protocol);
+ POSIX_ENSURE_REF(protocol);
/* copy the first protocol name */
- memcpy_check(conn->application_protocol, protocol, protocol_len);
+ POSIX_CHECKED_MEMCPY(conn->application_protocol, protocol, protocol_len);
conn->application_protocol[protocol_len] = '\0';
return S2N_SUCCESS;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c
index 486835689c..05063011c7 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.c
@@ -44,37 +44,53 @@ static bool s2n_tls13_server_status_request_should_send(struct s2n_connection *c
int s2n_server_certificate_status_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
struct s2n_blob *ocsp_status = &conn->handshake_params.our_chain_and_key->ocsp_status;
- notnull_check(ocsp_status);
+ POSIX_ENSURE_REF(ocsp_status);
- GUARD(s2n_stuffer_write_uint8(out, (uint8_t) S2N_STATUS_REQUEST_OCSP));
- GUARD(s2n_stuffer_write_uint24(out, ocsp_status->size));
- GUARD(s2n_stuffer_write(out, ocsp_status));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, (uint8_t) S2N_STATUS_REQUEST_OCSP));
+ POSIX_GUARD(s2n_stuffer_write_uint24(out, ocsp_status->size));
+ POSIX_GUARD(s2n_stuffer_write(out, ocsp_status));
return S2N_SUCCESS;
}
int s2n_server_certificate_status_recv(struct s2n_connection *conn, struct s2n_stuffer *in)
{
- notnull_check(conn);
-
+ POSIX_ENSURE_REF(conn);
+ /**
+ *= https://tools.ietf.org/rfc/rfc6066#section-8
+ *# struct {
+ *# CertificateStatusType status_type;
+ *# select (status_type) {
+ *# case ocsp: OCSPResponse;
+ *# } response;
+ *# } CertificateStatus;
+ *#
+ *# opaque OCSPResponse<1..2^24-1>;
+ *#
+ *# An "ocsp_response" contains a complete, DER-encoded OCSP response
+ *# (using the ASN.1 type OCSPResponse defined in [RFC2560]). Only one
+ *# OCSP response may be sent.
+ **/
uint8_t type;
- GUARD(s2n_stuffer_read_uint8(in, &type));
+ POSIX_GUARD(s2n_stuffer_read_uint8(in, &type));
if (type != S2N_STATUS_REQUEST_OCSP) {
/* We only support OCSP */
return S2N_SUCCESS;
}
+ conn->status_type = S2N_STATUS_REQUEST_OCSP;
uint32_t status_size;
- GUARD(s2n_stuffer_read_uint24(in, &status_size));
- lte_check(status_size, s2n_stuffer_data_available(in));
+ POSIX_GUARD(s2n_stuffer_read_uint24(in, &status_size));
+ POSIX_ENSURE_LTE(status_size, s2n_stuffer_data_available(in));
- GUARD(s2n_realloc(&conn->status_response, status_size));
- GUARD(s2n_stuffer_read_bytes(in, conn->status_response.data, status_size));
+ POSIX_GUARD(s2n_realloc(&conn->status_response, status_size));
+ POSIX_GUARD(s2n_stuffer_read_bytes(in, conn->status_response.data, status_size));
- GUARD(s2n_x509_validator_validate_cert_stapled_ocsp_response(
- &conn->x509_validator, conn, conn->status_response.data, conn->status_response.size));
+ POSIX_ENSURE(s2n_x509_validator_validate_cert_stapled_ocsp_response(
+ &conn->x509_validator, conn, conn->status_response.data, conn->status_response.size) == S2N_CERT_OK,
+ S2N_ERR_CERT_UNTRUSTED);
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_early_data_indication.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_early_data_indication.c
new file mode 100644
index 0000000000..80a8143a81
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_early_data_indication.c
@@ -0,0 +1,106 @@
+/*
+ * 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 "api/s2n.h"
+
+#include "tls/extensions/s2n_early_data_indication.h"
+
+#include "tls/s2n_connection.h"
+#include "tls/s2n_early_data.h"
+#include "tls/s2n_handshake.h"
+#include "utils/s2n_safety.h"
+
+static bool s2n_server_early_data_indication_should_send(struct s2n_connection *conn)
+{
+ return conn && conn->early_data_state == S2N_EARLY_DATA_ACCEPTED;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# A server which receives an "early_data" extension MUST behave in one
+ *# of three ways:
+ *#
+ *# - Ignore the extension and return a regular 1-RTT response.
+ **/
+static int s2n_server_early_data_indication_is_missing(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+ if (conn->early_data_state == S2N_EARLY_DATA_REQUESTED) {
+ POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_REJECTED));
+ }
+ return S2N_SUCCESS;
+}
+
+/**
+ * The server version of this extension is empty, so we don't read/write any data.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# The "extension_data" field of this extension contains an
+ *# "EarlyDataIndication" value.
+ *#
+ *# struct {} Empty;
+ *#
+ *# struct {
+ *# select (Handshake.msg_type) {
+ **
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# case encrypted_extensions: Empty;
+ *# };
+ *# } EarlyDataIndication;
+ **/
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# A server which receives an "early_data" extension MUST behave in one
+ *# of three ways:
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# - Return its own "early_data" extension in EncryptedExtensions,
+ *# indicating that it intends to process the early data.
+ **/
+
+static int s2n_server_early_data_indication_send(struct s2n_connection *conn, struct s2n_stuffer *out)
+{
+ return S2N_SUCCESS;
+}
+
+static int s2n_server_early_data_indication_recv(struct s2n_connection *conn, struct s2n_stuffer *in)
+{
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# If any of these checks fail, the server MUST NOT respond with the
+ *# extension
+ **/
+ POSIX_ENSURE(s2n_early_data_is_valid_for_connection(conn), S2N_ERR_EARLY_DATA_NOT_ALLOWED);
+
+ POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_ACCEPTED));
+
+ /* The client does not know for sure whether the server accepted early data until it receives
+ * this extension as part of the EncryptedExtensions message, after the handshake type has
+ * already been calculated. We'll need to manually update the handshake type.
+ */
+ conn->handshake.handshake_type |= WITH_EARLY_DATA;
+
+ return S2N_SUCCESS;
+}
+
+const s2n_extension_type s2n_server_early_data_indication_extension = {
+ .iana_value = TLS_EXTENSION_EARLY_DATA,
+ .is_response = true,
+ .send = s2n_server_early_data_indication_send,
+ .recv = s2n_server_early_data_indication_recv,
+ .should_send = s2n_server_early_data_indication_should_send,
+ .if_missing = s2n_server_early_data_indication_is_missing,
+};
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_ems.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_ems.c
new file mode 100644
index 0000000000..06f0474d8d
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_ems.c
@@ -0,0 +1,74 @@
+/*
+ * 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_ems.h"
+
+#include "utils/s2n_safety.h"
+
+static int s2n_server_ems_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
+static bool s2n_server_ems_should_send(struct s2n_connection *conn);
+static int s2n_server_ems_if_missing(struct s2n_connection *conn);
+
+/**
+ *= https://tools.ietf.org/rfc/rfc7627#section-5.1
+ *#
+ *# This document defines a new TLS extension, "extended_master_secret"
+ *# (with extension type 0x0017), which is used to signal both client and
+ *# server to use the extended master secret computation. The
+ *# "extension_data" field of this extension is empty. Thus, the entire
+ *# encoding of the extension is 00 17 00 00 (in hexadecimal.)
+ **/
+const s2n_extension_type s2n_server_ems_extension = {
+ .iana_value = TLS_EXTENSION_EMS,
+ .is_response = true,
+ .send = s2n_extension_send_noop,
+ .recv = s2n_server_ems_recv,
+ .should_send = s2n_server_ems_should_send,
+ .if_missing = s2n_server_ems_if_missing,
+};
+
+static int s2n_server_ems_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
+{
+ POSIX_ENSURE_REF(conn);
+
+ /* Read nothing. The extension just needs to exist. */
+ conn->ems_negotiated = true;
+
+ return S2N_SUCCESS;
+}
+
+static bool s2n_server_ems_should_send(struct s2n_connection *conn)
+{
+ return conn && conn->actual_protocol_version < S2N_TLS13;
+}
+
+static int s2n_server_ems_if_missing(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc7627#section-5.3
+ *# If the original session used the extension but the new ServerHello
+ *# does not contain the extension, the client MUST abort the
+ *# handshake.
+ **/
+ POSIX_ENSURE(!conn->ems_negotiated, S2N_ERR_MISSING_EXTENSION);
+
+ return S2N_SUCCESS;
+}
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 eb0ead255a..46f5deb1d5 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
@@ -27,115 +27,105 @@ static int s2n_server_key_share_recv(struct s2n_connection *conn, struct s2n_stu
const s2n_extension_type s2n_server_key_share_extension = {
.iana_value = TLS_EXTENSION_KEY_SHARE,
+ .minimum_version = S2N_TLS13,
.is_response = false,
.send = s2n_server_key_share_send,
.recv = s2n_server_key_share_recv,
- .should_send = s2n_extension_send_if_tls13_connection,
+ .should_send = s2n_extension_always_send,
.if_missing = s2n_extension_noop_if_missing,
};
static int s2n_server_key_share_generate_pq_hybrid(struct s2n_connection *conn, struct s2n_stuffer *out) {
- notnull_check(out);
- notnull_check(conn);
+ POSIX_ENSURE_REF(out);
+ POSIX_ENSURE_REF(conn);
- ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
+ POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
- struct s2n_kem_group_params *server_kem_group_params = &conn->secure.server_kem_group_params;
+ struct s2n_kem_group_params *server_kem_group_params = &conn->kex_params.server_kem_group_params;
- notnull_check(server_kem_group_params->kem_group);
- GUARD(s2n_stuffer_write_uint16(out, server_kem_group_params->kem_group->iana_id));
+ POSIX_ENSURE_REF(server_kem_group_params->kem_group);
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, server_kem_group_params->kem_group->iana_id));
struct s2n_stuffer_reservation total_share_size = { 0 };
- GUARD(s2n_stuffer_reserve_uint16(out, &total_share_size));
+ POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &total_share_size));
struct s2n_ecc_evp_params *server_ecc_params = &server_kem_group_params->ecc_params;
- notnull_check(server_ecc_params->negotiated_curve);
- GUARD(s2n_stuffer_write_uint16(out, server_ecc_params->negotiated_curve->share_size));
- GUARD(s2n_ecc_evp_generate_ephemeral_key(server_ecc_params));
- GUARD(s2n_ecc_evp_write_params_point(server_ecc_params, out));
-
- notnull_check(conn->secure.chosen_client_kem_group_params);
- struct s2n_kem_params *client_kem_params = &conn->secure.chosen_client_kem_group_params->kem_params;
- notnull_check(client_kem_params->public_key.data);
+ POSIX_ENSURE_REF(server_ecc_params->negotiated_curve);
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, server_ecc_params->negotiated_curve->share_size));
+ POSIX_GUARD(s2n_ecc_evp_generate_ephemeral_key(server_ecc_params));
+ POSIX_GUARD(s2n_ecc_evp_write_params_point(server_ecc_params, out));
+
+ struct s2n_kem_params *client_kem_params = &conn->kex_params.client_kem_group_params.kem_params;
+ POSIX_ENSURE_REF(client_kem_params->public_key.data);
/* s2n_kem_send_ciphertext() will generate the PQ shared secret and use
* the client's public key to encapsulate; the PQ shared secret will be
* stored in client_kem_params, and will be used during the hybrid shared
* secret derivation. */
- GUARD(s2n_kem_send_ciphertext(out, client_kem_params));
+ POSIX_GUARD(s2n_kem_send_ciphertext(out, client_kem_params));
- GUARD(s2n_stuffer_write_vector_size(&total_share_size));
+ POSIX_GUARD(s2n_stuffer_write_vector_size(&total_share_size));
return S2N_SUCCESS;
}
/* Check that client has sent a corresponding key share for the server's KEM group */
int s2n_server_key_share_send_check_pq_hybrid(struct s2n_connection *conn) {
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
- ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
+ POSIX_ENSURE(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);
- notnull_check(conn->secure.server_kem_group_params.ecc_params.negotiated_curve);
+ POSIX_ENSURE_REF(conn->kex_params.server_kem_group_params.kem_group);
+ POSIX_ENSURE_REF(conn->kex_params.server_kem_group_params.kem_params.kem);
+ POSIX_ENSURE_REF(conn->kex_params.server_kem_group_params.ecc_params.negotiated_curve);
- const struct s2n_kem_group *server_kem_group = conn->secure.server_kem_group_params.kem_group;
+ const struct s2n_kem_group *server_kem_group = conn->kex_params.server_kem_group_params.kem_group;
const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
+ POSIX_ENSURE_REF(kem_pref);
- ENSURE_POSIX(s2n_kem_preferences_includes_tls13_kem_group(kem_pref, server_kem_group->iana_id),
+ POSIX_ENSURE(s2n_kem_preferences_includes_tls13_kem_group(kem_pref, server_kem_group->iana_id),
S2N_ERR_KEM_UNSUPPORTED_PARAMS);
- struct s2n_kem_group_params *client_params = conn->secure.chosen_client_kem_group_params;
- notnull_check(client_params);
-
- ENSURE_POSIX(client_params->kem_group == server_kem_group, S2N_ERR_BAD_KEY_SHARE);
+ struct s2n_kem_group_params *client_params = &conn->kex_params.client_kem_group_params;
+ POSIX_ENSURE(client_params->kem_group == server_kem_group, S2N_ERR_BAD_KEY_SHARE);
- ENSURE_POSIX(client_params->ecc_params.negotiated_curve == server_kem_group->curve, S2N_ERR_BAD_KEY_SHARE);
- ENSURE_POSIX(client_params->ecc_params.evp_pkey != NULL, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(client_params->ecc_params.negotiated_curve == server_kem_group->curve, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(client_params->ecc_params.evp_pkey != NULL, S2N_ERR_BAD_KEY_SHARE);
- ENSURE_POSIX(client_params->kem_params.kem == server_kem_group->kem, S2N_ERR_BAD_KEY_SHARE);
- ENSURE_POSIX(client_params->kem_params.public_key.size == server_kem_group->kem->public_key_length, S2N_ERR_BAD_KEY_SHARE);
- ENSURE_POSIX(client_params->kem_params.public_key.data != NULL, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(client_params->kem_params.kem == server_kem_group->kem, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(client_params->kem_params.public_key.size == server_kem_group->kem->public_key_length, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(client_params->kem_params.public_key.data != NULL, S2N_ERR_BAD_KEY_SHARE);
return S2N_SUCCESS;
}
/* Check that client has sent a corresponding key share for the server's EC curve */
int s2n_server_key_share_send_check_ecdhe(struct s2n_connection *conn) {
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
- const struct s2n_ecc_named_curve *server_curve = conn->secure.server_ecc_evp_params.negotiated_curve;
- notnull_check(server_curve);
+ const struct s2n_ecc_named_curve *server_curve = conn->kex_params.server_ecc_evp_params.negotiated_curve;
+ POSIX_ENSURE_REF(server_curve);
- struct s2n_ecc_evp_params *client_params = NULL;
- for (size_t i = 0; i < ecc_pref->count; i++) {
- if (server_curve == ecc_pref->ecc_curves[i]) {
- client_params = &conn->secure.client_ecc_evp_params[i];
- break;
- }
- }
-
- notnull_check(client_params);
- ENSURE_POSIX(client_params->negotiated_curve == server_curve, S2N_ERR_BAD_KEY_SHARE);
- ENSURE_POSIX(client_params->evp_pkey != NULL, S2N_ERR_BAD_KEY_SHARE);
+ struct s2n_ecc_evp_params *client_params = &conn->kex_params.client_ecc_evp_params;
+ POSIX_ENSURE(client_params->negotiated_curve == server_curve, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(client_params->evp_pkey != NULL, S2N_ERR_BAD_KEY_SHARE);
return S2N_SUCCESS;
}
static int s2n_server_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out) {
- notnull_check(conn);
- notnull_check(out);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(out);
- const struct s2n_ecc_named_curve *curve = conn->secure.server_ecc_evp_params.negotiated_curve;
- const struct s2n_kem_group *kem_group = conn->secure.server_kem_group_params.kem_group;
+ const struct s2n_ecc_named_curve *curve = conn->kex_params.server_ecc_evp_params.negotiated_curve;
+ const struct s2n_kem_group *kem_group = conn->kex_params.server_kem_group_params.kem_group;
/* Boolean XOR: exactly one of {server_curve, server_kem_group} should be non-null. */
- ENSURE_POSIX((curve == NULL) != (kem_group == NULL), S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
+ POSIX_ENSURE((curve == NULL) != (kem_group == NULL), S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
/* Retry requests only require the selected named group, not an actual share.
* https://tools.ietf.org/html/rfc8446#section-4.2.8 */
@@ -147,16 +137,16 @@ static int s2n_server_key_share_send(struct s2n_connection *conn, struct s2n_stu
named_group_id = kem_group->iana_id;
}
- GUARD(s2n_stuffer_write_uint16(out, named_group_id));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, named_group_id));
return S2N_SUCCESS;
}
if (curve != NULL) {
- GUARD(s2n_server_key_share_send_check_ecdhe(conn));
- GUARD(s2n_ecdhe_parameters_send(&conn->secure.server_ecc_evp_params, out));
+ POSIX_GUARD(s2n_server_key_share_send_check_ecdhe(conn));
+ POSIX_GUARD(s2n_ecdhe_parameters_send(&conn->kex_params.server_ecc_evp_params, out));
} else {
- GUARD(s2n_server_key_share_send_check_pq_hybrid(conn));
- GUARD(s2n_server_key_share_generate_pq_hybrid(conn, out));
+ POSIX_GUARD(s2n_server_key_share_send_check_pq_hybrid(conn));
+ POSIX_GUARD(s2n_server_key_share_generate_pq_hybrid(conn, out));
}
return S2N_SUCCESS;
@@ -164,20 +154,20 @@ static int s2n_server_key_share_send(struct s2n_connection *conn, struct s2n_stu
static int s2n_server_key_share_recv_pq_hybrid(struct s2n_connection *conn, uint16_t named_group_iana,
struct s2n_stuffer *extension) {
- notnull_check(conn);
- notnull_check(extension);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(extension);
/* 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_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
+ POSIX_ENSURE(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));
- notnull_check(kem_pref);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
+ POSIX_ENSURE_REF(kem_pref);
/* This check should have been done higher up, but including it here as well for extra defense.
* Uses S2N_ERR_ECDHE_UNSUPPORTED_CURVE for backward compatibility. */
- ENSURE_POSIX(s2n_kem_preferences_includes_tls13_kem_group(kem_pref, named_group_iana), S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
+ POSIX_ENSURE(s2n_kem_preferences_includes_tls13_kem_group(kem_pref, named_group_iana), S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
size_t kem_group_index = 0;
for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) {
@@ -187,7 +177,7 @@ static int s2n_server_key_share_recv_pq_hybrid(struct s2n_connection *conn, uint
}
}
- struct s2n_kem_group_params *server_kem_group_params = &conn->secure.server_kem_group_params;
+ struct s2n_kem_group_params *server_kem_group_params = &conn->kex_params.server_kem_group_params;
server_kem_group_params->kem_group = kem_pref->tls13_kem_groups[kem_group_index];
server_kem_group_params->kem_params.kem = kem_pref->tls13_kem_groups[kem_group_index]->kem;
server_kem_group_params->ecc_params.negotiated_curve = kem_pref->tls13_kem_groups[kem_group_index]->curve;
@@ -200,29 +190,26 @@ static int s2n_server_key_share_recv_pq_hybrid(struct s2n_connection *conn, uint
}
/* Ensure that the server's key share corresponds with a key share previously sent by the client */
- ENSURE_POSIX(conn->secure.client_kem_group_params[kem_group_index].kem_params.private_key.data != NULL,
- S2N_ERR_BAD_KEY_SHARE);
- ENSURE_POSIX(conn->secure.client_kem_group_params[kem_group_index].ecc_params.evp_pkey != NULL,
- S2N_ERR_BAD_KEY_SHARE);
- notnull_check(conn->secure.client_kem_group_params[kem_group_index].kem_group);
- eq_check(conn->secure.client_kem_group_params[kem_group_index].kem_group->iana_id, named_group_iana);
- conn->secure.chosen_client_kem_group_params = &conn->secure.client_kem_group_params[kem_group_index];
+ struct s2n_kem_group_params *client_kem_group_params = &conn->kex_params.client_kem_group_params;
+ POSIX_ENSURE(client_kem_group_params->kem_params.private_key.data, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(client_kem_group_params->ecc_params.evp_pkey, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(client_kem_group_params->kem_group == server_kem_group_params->kem_group, S2N_ERR_BAD_KEY_SHARE);
uint16_t received_total_share_size;
- GUARD(s2n_stuffer_read_uint16(extension, &received_total_share_size));
- ENSURE_POSIX(received_total_share_size == server_kem_group_params->kem_group->server_share_size, S2N_ERR_BAD_KEY_SHARE);
- ENSURE_POSIX(s2n_stuffer_data_available(extension) == received_total_share_size, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &received_total_share_size));
+ POSIX_ENSURE(received_total_share_size == server_kem_group_params->kem_group->server_share_size, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(s2n_stuffer_data_available(extension) == received_total_share_size, S2N_ERR_BAD_KEY_SHARE);
/* Parse ECC key share */
uint16_t ecc_share_size;
struct s2n_blob point_blob;
- GUARD(s2n_stuffer_read_uint16(extension, &ecc_share_size));
- ENSURE_POSIX(s2n_ecc_evp_read_params_point(extension, ecc_share_size, &point_blob) == S2N_SUCCESS, S2N_ERR_BAD_KEY_SHARE);
- ENSURE_POSIX(s2n_ecc_evp_parse_params_point(&point_blob, &server_kem_group_params->ecc_params) == S2N_SUCCESS, S2N_ERR_BAD_KEY_SHARE);
- ENSURE_POSIX(server_kem_group_params->ecc_params.evp_pkey != NULL, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &ecc_share_size));
+ POSIX_ENSURE(s2n_ecc_evp_read_params_point(extension, ecc_share_size, &point_blob) == S2N_SUCCESS, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(s2n_ecc_evp_parse_params_point(&point_blob, &server_kem_group_params->ecc_params) == S2N_SUCCESS, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(server_kem_group_params->ecc_params.evp_pkey != NULL, S2N_ERR_BAD_KEY_SHARE);
/* Parse the PQ KEM key share */
- ENSURE_POSIX(s2n_kem_recv_ciphertext(extension, &conn->secure.chosen_client_kem_group_params->kem_params) == S2N_SUCCESS,
+ POSIX_ENSURE(s2n_kem_recv_ciphertext(extension, &conn->kex_params.client_kem_group_params.kem_params) == S2N_SUCCESS,
S2N_ERR_BAD_KEY_SHARE);
return S2N_SUCCESS;
@@ -230,15 +217,15 @@ static int s2n_server_key_share_recv_pq_hybrid(struct s2n_connection *conn, uint
static int s2n_server_key_share_recv_ecc(struct s2n_connection *conn, uint16_t named_group_iana,
struct s2n_stuffer *extension) {
- notnull_check(conn);
- notnull_check(extension);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(extension);
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
/* This check should have been done higher up, but including it here as well for extra defense. */
- ENSURE_POSIX(s2n_ecc_preferences_includes_curve(ecc_pref, named_group_iana),
+ POSIX_ENSURE(s2n_ecc_preferences_includes_curve(ecc_pref, named_group_iana),
S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
size_t supported_curve_index = 0;
@@ -250,7 +237,7 @@ static int s2n_server_key_share_recv_ecc(struct s2n_connection *conn, uint16_t n
}
}
- struct s2n_ecc_evp_params *server_ecc_evp_params = &conn->secure.server_ecc_evp_params;
+ struct s2n_ecc_evp_params *server_ecc_evp_params = &conn->kex_params.server_ecc_evp_params;
server_ecc_evp_params->negotiated_curve = ecc_pref->ecc_curves[supported_curve_index];
/* If this is a HelloRetryRequest, we won't have a key share. We just have the selected group.
@@ -259,12 +246,14 @@ static int s2n_server_key_share_recv_ecc(struct s2n_connection *conn, uint16_t n
return S2N_SUCCESS;
}
- /* Key share not sent by client */
- S2N_ERROR_IF(conn->secure.client_ecc_evp_params[supported_curve_index].evp_pkey == NULL, S2N_ERR_BAD_KEY_SHARE);
+ /* Verify key share sent by client */
+ struct s2n_ecc_evp_params *client_ecc_evp_params = &conn->kex_params.client_ecc_evp_params;
+ POSIX_ENSURE(client_ecc_evp_params->negotiated_curve == server_ecc_evp_params->negotiated_curve, S2N_ERR_BAD_KEY_SHARE);
+ POSIX_ENSURE(client_ecc_evp_params->evp_pkey, S2N_ERR_BAD_KEY_SHARE);
uint16_t share_size;
S2N_ERROR_IF(s2n_stuffer_data_available(extension) < sizeof(share_size), S2N_ERR_BAD_KEY_SHARE);
- GUARD(s2n_stuffer_read_uint16(extension, &share_size));
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &share_size));
S2N_ERROR_IF(s2n_stuffer_data_available(extension) < share_size, S2N_ERR_BAD_KEY_SHARE);
/* Proceed to parse share */
@@ -286,31 +275,27 @@ static int s2n_server_key_share_recv_ecc(struct s2n_connection *conn, uint16_t n
*/
static int s2n_server_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
- return S2N_SUCCESS;
- }
-
- notnull_check(conn);
- notnull_check(extension);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(extension);
uint16_t negotiated_named_group_iana = 0;
S2N_ERROR_IF(s2n_stuffer_data_available(extension) < sizeof(negotiated_named_group_iana), S2N_ERR_BAD_KEY_SHARE);
- GUARD(s2n_stuffer_read_uint16(extension, &negotiated_named_group_iana));
+ POSIX_GUARD(s2n_stuffer_read_uint16(extension, &negotiated_named_group_iana));
const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
+ POSIX_ENSURE_REF(kem_pref);
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
if (s2n_ecc_preferences_includes_curve(ecc_pref, negotiated_named_group_iana)) {
- GUARD(s2n_server_key_share_recv_ecc(conn, negotiated_named_group_iana, extension));
+ POSIX_GUARD(s2n_server_key_share_recv_ecc(conn, negotiated_named_group_iana, extension));
} else if (s2n_kem_preferences_includes_tls13_kem_group(kem_pref, negotiated_named_group_iana)) {
- GUARD(s2n_server_key_share_recv_pq_hybrid(conn, negotiated_named_group_iana, extension));
+ POSIX_GUARD(s2n_server_key_share_recv_pq_hybrid(conn, negotiated_named_group_iana, extension));
} else {
- S2N_ERROR(S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
+ POSIX_BAIL(S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
}
return S2N_SUCCESS;
@@ -318,15 +303,15 @@ static int s2n_server_key_share_recv(struct s2n_connection *conn, struct s2n_stu
/* Selects highest priority mutually supported key share, or indicates need for HRR */
int s2n_extensions_server_key_share_select(struct s2n_connection *conn) {
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
+ POSIX_ENSURE_REF(kem_pref);
/* Boolean XOR check. When receiving the supported_groups extension, s2n server
* should (exclusively) set either server_curve or server_kem_group based on the
@@ -335,44 +320,38 @@ int s2n_extensions_server_key_share_select(struct s2n_connection *conn) {
* groups; key negotiation is not possible and the handshake should be aborted
* without sending HRR. (The case of both being non-NULL should never occur, and
* is an error.) */
- const struct s2n_ecc_named_curve *server_curve = conn->secure.server_ecc_evp_params.negotiated_curve;
- const struct s2n_kem_group *server_kem_group = conn->secure.server_kem_group_params.kem_group;
- ENSURE_POSIX((server_curve == NULL) != (server_kem_group == NULL), S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
+ const struct s2n_ecc_named_curve *server_curve = conn->kex_params.server_ecc_evp_params.negotiated_curve;
+ const struct s2n_kem_group *server_kem_group = conn->kex_params.server_kem_group_params.kem_group;
+ POSIX_ENSURE((server_curve == NULL) != (server_kem_group == NULL), S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
/* To avoid extra round trips, we prefer to negotiate a group for which we have already
* received a key share (even if it is different than the group previously chosen). In
* general, we prefer to negotiate PQ over ECDHE; however, if both client and server
* support PQ, but the client sent only EC key shares, then we will negotiate ECHDE. */
- for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) {
- if (conn->secure.mutually_supported_kem_groups[i] && conn->secure.client_kem_group_params[i].kem_group) {
- notnull_check(conn->secure.client_kem_group_params[i].ecc_params.negotiated_curve);
- notnull_check(conn->secure.client_kem_group_params[i].kem_params.kem);
+ if (conn->kex_params.client_kem_group_params.kem_group) {
+ POSIX_ENSURE_REF(conn->kex_params.client_kem_group_params.ecc_params.negotiated_curve);
+ POSIX_ENSURE_REF(conn->kex_params.client_kem_group_params.kem_params.kem);
- conn->secure.server_kem_group_params.kem_group = conn->secure.client_kem_group_params[i].kem_group;
- conn->secure.server_kem_group_params.ecc_params.negotiated_curve = conn->secure.client_kem_group_params[i].ecc_params.negotiated_curve;
- conn->secure.server_kem_group_params.kem_params.kem = conn->secure.client_kem_group_params[i].kem_params.kem;
- conn->secure.chosen_client_kem_group_params = &conn->secure.client_kem_group_params[i];
+ conn->kex_params.server_kem_group_params.kem_group = conn->kex_params.client_kem_group_params.kem_group;
+ conn->kex_params.server_kem_group_params.ecc_params.negotiated_curve = conn->kex_params.client_kem_group_params.ecc_params.negotiated_curve;
+ conn->kex_params.server_kem_group_params.kem_params.kem = conn->kex_params.client_kem_group_params.kem_params.kem;
- conn->secure.server_ecc_evp_params.negotiated_curve = NULL;
- return S2N_SUCCESS;
- }
+ conn->kex_params.server_ecc_evp_params.negotiated_curve = NULL;
+ return S2N_SUCCESS;
}
- for (size_t i = 0; i < ecc_pref->count; i++) {
- if (conn->secure.mutually_supported_curves[i] && conn->secure.client_ecc_evp_params[i].negotiated_curve) {
- conn->secure.server_ecc_evp_params.negotiated_curve = conn->secure.client_ecc_evp_params[i].negotiated_curve;
-
- conn->secure.server_kem_group_params.kem_group = NULL;
- conn->secure.server_kem_group_params.ecc_params.negotiated_curve = NULL;
- conn->secure.server_kem_group_params.kem_params.kem = NULL;
- conn->secure.chosen_client_kem_group_params = NULL;
- return S2N_SUCCESS;
- }
+ if (conn->kex_params.client_ecc_evp_params.negotiated_curve) {
+ conn->kex_params.server_ecc_evp_params.negotiated_curve = conn->kex_params.client_ecc_evp_params.negotiated_curve;
+
+ conn->kex_params.server_kem_group_params.kem_group = NULL;
+ conn->kex_params.server_kem_group_params.ecc_params.negotiated_curve = NULL;
+ conn->kex_params.server_kem_group_params.kem_params.kem = NULL;
+ return S2N_SUCCESS;
}
/* Server and client have mutually supported groups, but the client did not send key
* shares for any of them. Send HRR indicating the server's preference. */
- GUARD(s2n_set_hello_retry_required(conn));
+ POSIX_GUARD(s2n_set_hello_retry_required(conn));
return S2N_SUCCESS;
}
@@ -389,7 +368,7 @@ int s2n_extensions_server_key_share_select(struct s2n_connection *conn) {
*/
int s2n_extensions_server_key_share_send_size(struct s2n_connection *conn)
{
- const struct s2n_ecc_named_curve* curve = conn->secure.server_ecc_evp_params.negotiated_curve;
+ const struct s2n_ecc_named_curve* curve = conn->kex_params.server_ecc_evp_params.negotiated_curve;
int key_share_size = S2N_SIZE_OF_EXTENSION_TYPE
+ S2N_SIZE_OF_EXTENSION_DATA_SIZE
+ S2N_SIZE_OF_NAMED_GROUP;
@@ -422,7 +401,7 @@ int s2n_extensions_server_key_share_send(struct s2n_connection *conn, struct s2n
/*
* Client receives a Server Hello key share.
*
- * If the curve is supported, conn->secure.server_ecc_evp_params will be set.
+ * If the curve is supported, conn->kex_params.server_ecc_evp_params will be set.
*/
int s2n_extensions_server_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_max_fragment_length.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_max_fragment_length.c
index 69b1530e54..e55e3f21e5 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_max_fragment_length.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_max_fragment_length.c
@@ -13,12 +13,15 @@
* permissions and limitations under the License.
*/
+#include <sys/param.h>
+
#include "error/s2n_errno.h"
#include "stuffer/s2n_stuffer.h"
#include "utils/s2n_safety.h"
+#include "tls/s2n_tls.h"
#include "tls/s2n_tls_parameters.h"
#include "tls/s2n_connection.h"
@@ -39,23 +42,42 @@ const s2n_extension_type s2n_server_max_fragment_length_extension = {
static bool s2n_max_fragment_length_should_send(struct s2n_connection *conn)
{
- return conn && conn->mfl_code != S2N_TLS_MAX_FRAG_LEN_EXT_NONE;
+ return conn && conn->negotiated_mfl_code != S2N_TLS_MAX_FRAG_LEN_EXT_NONE;
}
static int s2n_max_fragment_length_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- notnull_check(conn);
- GUARD(s2n_stuffer_write_uint8(out, conn->mfl_code));
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, conn->negotiated_mfl_code));
return S2N_SUCCESS;
}
static int s2n_max_fragment_length_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- notnull_check(conn);
- notnull_check(conn->config);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->config);
uint8_t mfl_code;
- GUARD(s2n_stuffer_read_uint8(extension, &mfl_code));
+ POSIX_GUARD(s2n_stuffer_read_uint8(extension, &mfl_code));
+
+ /*
+ *= https://tools.ietf.org/rfc/rfc6066#section-4
+ *# Similarly, if a client
+ *# receives a maximum fragment length negotiation response that differs
+ *# from the length it requested, it MUST also abort the handshake with
+ *# an "illegal_parameter" alert.
+ */
S2N_ERROR_IF(mfl_code != conn->config->mfl_code, S2N_ERR_MAX_FRAG_LEN_MISMATCH);
+
+ /*
+ *= https://tools.ietf.org/rfc/rfc6066#section-4
+ *# Once a maximum fragment length other than 2^14 has been successfully
+ *# negotiated, the client and server MUST immediately begin fragmenting
+ *# messages (including handshake messages) to ensure that no fragment
+ *# larger than the negotiated length is sent.
+ */
+ conn->negotiated_mfl_code = mfl_code;
+ POSIX_GUARD_RESULT(s2n_connection_set_max_fragment_length(conn, conn->max_outgoing_fragment_length));
+
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c
index cb930b17a4..9a36caff9f 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_psk.c
@@ -28,6 +28,7 @@ static int s2n_server_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *
const s2n_extension_type s2n_server_psk_extension = {
.iana_value = TLS_EXTENSION_PRE_SHARED_KEY,
+ .minimum_version = S2N_TLS13,
.is_response = true,
.send = s2n_server_psk_send,
.recv = s2n_server_psk_recv,
@@ -38,35 +39,30 @@ const s2n_extension_type s2n_server_psk_extension = {
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;
+ return conn && conn->psk_params.chosen_psk;
}
static int s2n_server_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(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));
+ POSIX_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;
- }
+ POSIX_ENSURE_REF(conn);
/* 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);
+ POSIX_GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_KEY_SHARE, &key_share_ext_id));
+ POSIX_ENSURE(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
@@ -76,16 +72,16 @@ static int s2n_server_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *
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));
+ POSIX_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);
+ POSIX_ENSURE(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,
+ POSIX_GUARD_RESULT(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_renegotiation_info.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c
index aac791c43c..6da5481ec9 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c
@@ -45,7 +45,7 @@ static bool s2n_renegotiation_info_should_send(struct s2n_connection *conn)
static int s2n_renegotiation_info_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
/* renegotiated_connection length. Zero since we don't support renegotiation. */
- GUARD(s2n_stuffer_write_uint8(out, 0));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, 0));
return S2N_SUCCESS;
}
@@ -55,11 +55,11 @@ static int s2n_renegotiation_info_recv(struct s2n_connection *conn, struct s2n_s
* the "renegotiated_connection" field is zero, and if it is not, MUST
* abort the handshake. */
uint8_t renegotiated_connection_len;
- GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len));
+ POSIX_GUARD(s2n_stuffer_read_uint8(extension, &renegotiated_connection_len));
S2N_ERROR_IF(s2n_stuffer_data_available(extension), S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
S2N_ERROR_IF(renegotiated_connection_len, S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
conn->secure_renegotiation = 1;
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_sct_list.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_sct_list.c
index 8a8158aecf..cf28bef52b 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_sct_list.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_sct_list.c
@@ -41,27 +41,27 @@ static bool s2n_server_sct_list_should_send(struct s2n_connection *conn)
int s2n_server_sct_list_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
struct s2n_blob *sct_list = &conn->handshake_params.our_chain_and_key->sct_list;
- notnull_check(sct_list);
- GUARD(s2n_stuffer_write(out, sct_list));
+ POSIX_ENSURE_REF(sct_list);
+ POSIX_GUARD(s2n_stuffer_write(out, sct_list));
return S2N_SUCCESS;
}
int s2n_server_sct_list_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
struct s2n_blob sct_list;
size_t data_available = s2n_stuffer_data_available(extension);
- GUARD(s2n_blob_init(&sct_list,
+ POSIX_GUARD(s2n_blob_init(&sct_list,
s2n_stuffer_raw_read(extension, data_available),
data_available));
- notnull_check(sct_list.data);
+ POSIX_ENSURE_REF(sct_list.data);
- GUARD(s2n_dup(&sct_list, &conn->ct_response));
+ POSIX_GUARD(s2n_dup(&sct_list, &conn->ct_response));
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_server_name.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_server_name.c
index 158a9eae6c..239c84f1fb 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_server_name.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_server_name.c
@@ -33,7 +33,7 @@ const s2n_extension_type s2n_server_server_name_extension = {
static bool s2n_server_name_should_send(struct s2n_connection *conn)
{
- return conn && conn->server_name_used && !s2n_connection_is_session_resumed(conn);
+ return conn && conn->server_name_used && !IS_RESUMPTION_HANDSHAKE(conn);
}
static int s2n_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out)
@@ -44,7 +44,7 @@ static int s2n_server_name_send(struct s2n_connection *conn, struct s2n_stuffer
static int s2n_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
/* Read nothing. The extension just needs to exist. */
conn->server_name_used = 1;
return S2N_SUCCESS;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_session_ticket.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_session_ticket.c
index 74875f05a6..d4c9bf019f 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_session_ticket.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_session_ticket.c
@@ -40,7 +40,7 @@ static bool s2n_session_ticket_should_send(struct s2n_connection *conn)
static int s2n_session_ticket_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
/* Read nothing. The extension just needs to exist. */
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
conn->session_ticket_status = S2N_NEW_TICKET;
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_status_request.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_status_request.c
index 7003bf46ba..c73b5c32a4 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_status_request.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_status_request.c
@@ -39,7 +39,7 @@ static bool s2n_server_status_request_should_send(struct s2n_connection *conn)
int s2n_server_status_request_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
/* Read nothing. The extension just needs to exist. */
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
conn->status_type = S2N_STATUS_REQUEST_OCSP;
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.c
index cd0fb015dc..53e387d8cc 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.c
@@ -52,8 +52,8 @@ const s2n_extension_type s2n_server_supported_versions_extension = {
static int s2n_server_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
- GUARD(s2n_stuffer_write_uint8(out, conn->server_protocol_version / 10));
- GUARD(s2n_stuffer_write_uint8(out, conn->server_protocol_version % 10));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, conn->server_protocol_version / 10));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, conn->server_protocol_version % 10));
return S2N_SUCCESS;
}
@@ -61,17 +61,18 @@ static int s2n_server_supported_versions_send(struct s2n_connection *conn, struc
static int s2n_extensions_server_supported_versions_process(struct s2n_connection *conn, struct s2n_stuffer *extension)
{
uint8_t highest_supported_version = conn->client_protocol_version;
- uint8_t minimum_supported_version;
- GUARD(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version));
+ uint8_t minimum_supported_version = s2n_unknown_protocol_version;
+ POSIX_GUARD_RESULT(s2n_connection_get_minimum_supported_version(conn, &minimum_supported_version));
+ POSIX_ENSURE(highest_supported_version >= minimum_supported_version, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
uint8_t server_version_parts[S2N_TLS_PROTOCOL_VERSION_LEN];
- GUARD(s2n_stuffer_read_bytes(extension, server_version_parts, S2N_TLS_PROTOCOL_VERSION_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(extension, server_version_parts, S2N_TLS_PROTOCOL_VERSION_LEN));
uint16_t server_version = (server_version_parts[0] * 10) + server_version_parts[1];
- gte_check(server_version, S2N_TLS13);
- lte_check(server_version, highest_supported_version);
- gte_check(server_version, minimum_supported_version);
+ POSIX_ENSURE_GTE(server_version, S2N_TLS13);
+ POSIX_ENSURE_LTE(server_version, highest_supported_version);
+ POSIX_ENSURE_GTE(server_version, minimum_supported_version);
conn->server_protocol_version = server_version;
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.c
index d02b3f920d..3f77789e31 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.c
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.c
@@ -21,11 +21,19 @@
#include "utils/s2n_safety.h"
-int s2n_connection_get_minimum_supported_version(struct s2n_connection *conn, uint8_t *min_version)
+S2N_RESULT s2n_connection_get_minimum_supported_version(struct s2n_connection *conn, uint8_t *min_version)
{
- const struct s2n_security_policy *security_policy;
- GUARD(s2n_connection_get_security_policy(conn, &security_policy));
+ RESULT_ENSURE_REF(min_version);
+
+ const struct s2n_security_policy *security_policy = NULL;
+ RESULT_GUARD_POSIX(s2n_connection_get_security_policy(conn, &security_policy));
+ RESULT_ENSURE_REF(security_policy);
*min_version = security_policy->minimum_protocol_version;
- return 0;
+ /* QUIC requires >= TLS1.3 */
+ if (s2n_connection_is_quic_enabled(conn)) {
+ *min_version = MAX(*min_version, S2N_TLS13);
+ }
+
+ return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.h
index 613830c347..6c1fdcea76 100644
--- a/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.h
+++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.h
@@ -18,4 +18,4 @@
#include "tls/s2n_connection.h"
#include "stuffer/s2n_stuffer.h"
-extern int s2n_connection_get_minimum_supported_version(struct s2n_connection *conn, uint8_t *min_version);
+S2N_RESULT s2n_connection_get_minimum_supported_version(struct s2n_connection *conn, uint8_t *min_version);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_aead.c b/contrib/restricted/aws/s2n/tls/s2n_aead.c
index b7a0b23160..16bbee133b 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_aead.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_aead.c
@@ -18,61 +18,88 @@
#include "utils/s2n_safety.h"
#include "utils/s2n_mem.h"
+#include "tls/s2n_connection.h"
#include "tls/s2n_record.h"
/* Derive the AAD for an AEAD mode cipher suite from the connection state, per
* RFC 5246 section 6.2.3.3 */
-S2N_RESULT s2n_aead_aad_init(const struct s2n_connection *conn, uint8_t * sequence_number, uint8_t content_type, uint16_t record_length, struct s2n_stuffer *ad)
+S2N_RESULT s2n_aead_aad_init(const struct s2n_connection *conn, uint8_t * sequence_number, uint8_t content_type, uint16_t record_length, struct s2n_blob *ad)
{
+ RESULT_ENSURE_REF(ad);
+ RESULT_ENSURE_GTE(ad->size, S2N_TLS_MAX_AAD_LEN);
+
+ uint8_t *data = ad->data;
+ RESULT_GUARD_PTR(data);
+
/* ad = seq_num || record_type || version || length */
- GUARD_AS_RESULT(s2n_stuffer_write_bytes(ad, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
- GUARD_AS_RESULT(s2n_stuffer_write_uint8(ad, content_type));
- GUARD_AS_RESULT(s2n_stuffer_write_uint8(ad, conn->actual_protocol_version / 10));
- GUARD_AS_RESULT(s2n_stuffer_write_uint8(ad, conn->actual_protocol_version % 10));
- GUARD_AS_RESULT(s2n_stuffer_write_uint16(ad, record_length));
+ size_t idx = 0;
+ for(; idx < S2N_TLS_SEQUENCE_NUM_LEN; idx++) {
+ data[idx] = sequence_number[idx];
+ }
+
+ data[idx++] = content_type;
+ data[idx++] = conn->actual_protocol_version / 10;
+ data[idx++] = conn->actual_protocol_version % 10;
+ data[idx++] = record_length >> 8;
+ data[idx++] = record_length & UINT8_MAX;
+
+ /* Double check no overflow */
+ RESULT_ENSURE_LTE(idx, ad->size);
return S2N_RESULT_OK;
}
/* Prepares an AAD (additional authentication data) for a TLS 1.3 AEAD record */
-S2N_RESULT s2n_tls13_aead_aad_init(uint16_t record_length, uint8_t tag_length, struct s2n_stuffer *additional_data)
+S2N_RESULT s2n_tls13_aead_aad_init(uint16_t record_length, uint8_t tag_length, struct s2n_blob *additional_data)
{
- ENSURE_GT(tag_length, 0);
- ENSURE_REF(additional_data);
-
- /*
- * tls1.3 additional_data = opaque_type || legacy_record_version || length
- *
- * https://tools.ietf.org/html/rfc8446#section-5.2
- *
- * opaque_type: The outer opaque_type field of a TLSCiphertext record
- * is always set to the value 23 (application_data) for outward
- * compatibility with middleboxes accustomed to parsing previous
- * versions of TLS. The actual content type of the record is found
- * in TLSInnerPlaintext.type after decryption.
- * legacy_record_version: The legacy_record_version field is always
- * 0x0303. TLS 1.3 TLSCiphertexts are not generated until after
- * TLS 1.3 has been negotiated, so there are no historical
- * compatibility concerns where other values might be received. Note
- * that the handshake protocol, including the ClientHello and
- * ServerHello messages, authenticates the protocol version, so this
- * value is redundant.
- * length: The length (in bytes) of the following
- * TLSCiphertext.encrypted_record, which is the sum of the lengths of
- * the content and the padding, plus one for the inner content type,
- * plus any expansion added by the AEAD algorithm. The length
- * MUST NOT exceed 2^14 + 256 bytes. An endpoint that receives a
- * record that exceeds this length MUST terminate the connection with
- * a "record_overflow" alert.
+ RESULT_ENSURE_GT(tag_length, 0);
+ RESULT_ENSURE_REF(additional_data);
+ RESULT_ENSURE_GTE(additional_data->size, S2N_TLS13_AAD_LEN);
+
+ uint8_t *data = additional_data->data;
+ RESULT_GUARD_PTR(data);
+
+ size_t idx = 0;
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-5.2
+ *# opaque_type: The outer opaque_type field of a TLSCiphertext record
+ *# is always set to the value 23 (application_data) for outward
+ *# compatibility with middleboxes accustomed to parsing previous
+ *# versions of TLS. The actual content type of the record is found
+ *# in TLSInnerPlaintext.type after decryption.
+ **/
+ data[idx++] = TLS_APPLICATION_DATA;
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-5.2
+ *# legacy_record_version: The legacy_record_version field is always
+ *# 0x0303. TLS 1.3 TLSCiphertexts are not generated until after
+ *# TLS 1.3 has been negotiated, so there are no historical
+ *# compatibility concerns where other values might be received. Note
+ *# that the handshake protocol, including the ClientHello and
+ *# ServerHello messages, authenticates the protocol version, so this
+ *# value is redundant.
*/
+ data[idx++] = 0x03;
+ data[idx++] = 0x03;
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-5.2
+ *# length: The length (in bytes) of the following
+ *# TLSCiphertext.encrypted_record, which is the sum of the lengths of
+ *# the content and the padding, plus one for the inner content type,
+ *# plus any expansion added by the AEAD algorithm. The length
+ *# MUST NOT exceed 2^14 + 256 bytes. An endpoint that receives a
+ *# record that exceeds this length MUST terminate the connection with
+ *# a "record_overflow" alert.
+ */
uint16_t length = record_length + tag_length;
- ENSURE(length <= (1 << 14) + 256, S2N_ERR_RECORD_LIMIT);
-
- GUARD_AS_RESULT(s2n_stuffer_write_uint8(additional_data, TLS_APPLICATION_DATA)); /* fixed to 0x17 */
- GUARD_AS_RESULT(s2n_stuffer_write_uint8(additional_data, 3)); /* TLS record layer */
- GUARD_AS_RESULT(s2n_stuffer_write_uint8(additional_data, 3)); /* version fixed at 1.2 (0x0303) */
- GUARD_AS_RESULT(s2n_stuffer_write_uint16(additional_data, length));
+ RESULT_ENSURE(length <= (1 << 14) + 256, S2N_ERR_RECORD_LIMIT);
+ data[idx++] = length >> 8;
+ data[idx++] = length & UINT8_MAX;
+ /* Double check no overflow */
+ RESULT_ENSURE_LTE(idx, additional_data->size);
return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_alerts.c b/contrib/restricted/aws/s2n/tls/s2n_alerts.c
index 79f14f3214..c745a0d193 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_alerts.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_alerts.c
@@ -27,40 +27,101 @@
#include "utils/s2n_safety.h"
#include "utils/s2n_blob.h"
-#define S2N_TLS_ALERT_CLOSE_NOTIFY 0
-#define S2N_TLS_ALERT_UNEXPECTED_MSG 10
-#define S2N_TLS_ALERT_BAD_RECORD_MAC 20
-#define S2N_TLS_ALERT_DECRYPT_FAILED 21
-#define S2N_TLS_ALERT_RECORD_OVERFLOW 22
-#define S2N_TLS_ALERT_DECOMP_FAILED 30
-#define S2N_TLS_ALERT_HANDSHAKE_FAILURE 40
-#define S2N_TLS_ALERT_NO_CERTIFICATE 41
-#define S2N_TLS_ALERT_BAD_CERTIFICATE 42
-#define S2N_TLS_ALERT_UNSUPPORTED_CERT 43
-#define S2N_TLS_ALERT_CERT_REVOKED 44
-#define S2N_TLS_ALERT_CERT_EXPIRED 45
-#define S2N_TLS_ALERT_CERT_UNKNOWN 46
-#define S2N_TLS_ALERT_ILLEGAL_PARAMETER 47
-#define S2N_TLS_ALERT_UNKNOWN_CA 48
-#define S2N_TLS_ALERT_ACCESS_DENIED 49
-#define S2N_TLS_ALERT_DECODE_ERROR 50
-#define S2N_TLS_ALERT_DECRYPT_ERROR 51
-#define S2N_TLS_ALERT_EXPORT_RESTRICTED 60
-#define S2N_TLS_ALERT_PROTOCOL_VERSION 70
-#define S2N_TLS_ALERT_INSUFFICIENT_SECURITY 71
-#define S2N_TLS_ALERT_INTERNAL_ERROR 80
-#define S2N_TLS_ALERT_USER_CANCELED 90
-#define S2N_TLS_ALERT_NO_RENEGOTIATION 100
-#define S2N_TLS_ALERT_UNSUPPORTED_EXTENSION 110
-
#define S2N_TLS_ALERT_LEVEL_WARNING 1
#define S2N_TLS_ALERT_LEVEL_FATAL 2
+#define S2N_ALERT_CASE(error, alert_code) \
+ case (error): \
+ *alert = (alert_code); \
+ return S2N_RESULT_OK
+
+#define S2N_NO_ALERT(error) \
+ case (error): \
+ RESULT_BAIL(S2N_ERR_NO_ALERT)
+
+static S2N_RESULT s2n_translate_protocol_error_to_alert(int error_code, uint8_t *alert)
+{
+ RESULT_ENSURE_REF(alert);
+
+ switch(error_code) {
+ S2N_ALERT_CASE(S2N_ERR_MISSING_EXTENSION, S2N_TLS_ALERT_MISSING_EXTENSION);
+
+ /* TODO: The ERR_BAD_MESSAGE -> ALERT_UNEXPECTED_MESSAGE mapping
+ * isn't always correct. Sometimes s2n-tls uses ERR_BAD_MESSAGE
+ * to indicate S2N_TLS_ALERT_ILLEGAL_PARAMETER instead.
+ * We'll want to add a new error to distinguish between the two usages:
+ * our errors should be equally or more specific than alerts, not less.
+ */
+ S2N_ALERT_CASE(S2N_ERR_BAD_MESSAGE, S2N_TLS_ALERT_UNEXPECTED_MESSAGE);
+
+ /* TODO: Add mappings for other protocol errors.
+ */
+ S2N_NO_ALERT(S2N_ERR_ENCRYPT);
+ S2N_NO_ALERT(S2N_ERR_DECRYPT);
+ S2N_NO_ALERT(S2N_ERR_KEY_INIT);
+ S2N_NO_ALERT(S2N_ERR_KEY_DESTROY);
+ S2N_NO_ALERT(S2N_ERR_DH_SERIALIZING);
+ S2N_NO_ALERT(S2N_ERR_DH_SHARED_SECRET);
+ S2N_NO_ALERT(S2N_ERR_DH_WRITING_PUBLIC_KEY);
+ S2N_NO_ALERT(S2N_ERR_DH_FAILED_SIGNING);
+ S2N_NO_ALERT(S2N_ERR_DH_COPYING_PARAMETERS);
+ S2N_NO_ALERT(S2N_ERR_DH_GENERATING_PARAMETERS);
+ S2N_NO_ALERT(S2N_ERR_CIPHER_NOT_SUPPORTED);
+ S2N_NO_ALERT(S2N_ERR_NO_APPLICATION_PROTOCOL);
+ S2N_NO_ALERT(S2N_ERR_FALLBACK_DETECTED);
+ S2N_NO_ALERT(S2N_ERR_HASH_DIGEST_FAILED);
+ S2N_NO_ALERT(S2N_ERR_HASH_INIT_FAILED);
+ S2N_NO_ALERT(S2N_ERR_HASH_UPDATE_FAILED);
+ S2N_NO_ALERT(S2N_ERR_HASH_COPY_FAILED);
+ S2N_NO_ALERT(S2N_ERR_HASH_WIPE_FAILED);
+ S2N_NO_ALERT(S2N_ERR_HASH_NOT_READY);
+ S2N_NO_ALERT(S2N_ERR_ALLOW_MD5_FOR_FIPS_FAILED);
+ S2N_NO_ALERT(S2N_ERR_DECODE_CERTIFICATE);
+ S2N_NO_ALERT(S2N_ERR_DECODE_PRIVATE_KEY);
+ S2N_NO_ALERT(S2N_ERR_INVALID_HELLO_RETRY);
+ S2N_NO_ALERT(S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
+ S2N_NO_ALERT(S2N_ERR_INVALID_SIGNATURE_SCHEME);
+ S2N_NO_ALERT(S2N_ERR_CBC_VERIFY);
+ S2N_NO_ALERT(S2N_ERR_DH_COPYING_PUBLIC_KEY);
+ S2N_NO_ALERT(S2N_ERR_SIGN);
+ S2N_NO_ALERT(S2N_ERR_VERIFY_SIGNATURE);
+ S2N_NO_ALERT(S2N_ERR_ECDHE_GEN_KEY);
+ S2N_NO_ALERT(S2N_ERR_ECDHE_SHARED_SECRET);
+ S2N_NO_ALERT(S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
+ S2N_NO_ALERT(S2N_ERR_ECDSA_UNSUPPORTED_CURVE);
+ S2N_NO_ALERT(S2N_ERR_ECDHE_SERIALIZING);
+ S2N_NO_ALERT(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
+ S2N_NO_ALERT(S2N_ERR_SHUTDOWN_RECORD_TYPE);
+ S2N_NO_ALERT(S2N_ERR_SHUTDOWN_CLOSED);
+ S2N_NO_ALERT(S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO);
+ S2N_NO_ALERT(S2N_ERR_RECORD_LIMIT);
+ S2N_NO_ALERT(S2N_ERR_CERT_UNTRUSTED);
+ S2N_NO_ALERT(S2N_ERR_CERT_TYPE_UNSUPPORTED);
+ S2N_NO_ALERT(S2N_ERR_INVALID_MAX_FRAG_LEN);
+ S2N_NO_ALERT(S2N_ERR_MAX_FRAG_LEN_MISMATCH);
+ S2N_NO_ALERT(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
+ S2N_NO_ALERT(S2N_ERR_BAD_KEY_SHARE);
+ S2N_NO_ALERT(S2N_ERR_CANCELLED);
+ S2N_NO_ALERT(S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
+ S2N_NO_ALERT(S2N_ERR_MAX_INNER_PLAINTEXT_SIZE);
+ S2N_NO_ALERT(S2N_ERR_RECORD_STUFFER_SIZE);
+ S2N_NO_ALERT(S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE);
+ S2N_NO_ALERT(S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
+ S2N_NO_ALERT(S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
+ S2N_NO_ALERT(S2N_ERR_UNSUPPORTED_EXTENSION);
+ S2N_NO_ALERT(S2N_ERR_DUPLICATE_EXTENSION);
+ S2N_NO_ALERT(S2N_ERR_MAX_EARLY_DATA_SIZE);
+ S2N_NO_ALERT(S2N_ERR_EARLY_DATA_TRIAL_DECRYPT);
+ }
+
+ RESULT_BAIL(S2N_ERR_UNIMPLEMENTED);
+}
+
static bool s2n_alerts_supported(struct s2n_connection *conn)
{
/* If running in QUIC mode, QUIC handles alerting.
* S2N should not send or receive alerts. */
- return conn && conn->config && !conn->config->quic_enabled;
+ return !s2n_connection_is_quic_enabled(conn);
}
static bool s2n_handle_as_warning(struct s2n_connection *conn, uint8_t level, uint8_t type)
@@ -78,12 +139,38 @@ static bool s2n_handle_as_warning(struct s2n_connection *conn, uint8_t level, ui
return type == S2N_TLS_ALERT_USER_CANCELED;
}
+int s2n_error_get_alert(int error, uint8_t *alert)
+{
+ int error_type = s2n_error_get_type(error);
+
+ POSIX_ENSURE_REF(alert);
+
+ switch(error_type) {
+ case S2N_ERR_T_OK:
+ case S2N_ERR_T_CLOSED:
+ case S2N_ERR_T_BLOCKED:
+ case S2N_ERR_T_USAGE:
+ case S2N_ERR_T_ALERT:
+ POSIX_BAIL(S2N_ERR_NO_ALERT);
+ break;
+ case S2N_ERR_T_PROTO:
+ POSIX_GUARD_RESULT(s2n_translate_protocol_error_to_alert(error, alert));
+ break;
+ case S2N_ERR_T_IO:
+ case S2N_ERR_T_INTERNAL:
+ *alert = S2N_TLS_ALERT_INTERNAL_ERROR;
+ break;
+ }
+
+ return S2N_SUCCESS;
+}
+
int s2n_process_alert_fragment(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
S2N_ERROR_IF(s2n_stuffer_data_available(&conn->in) == 0, S2N_ERR_BAD_MESSAGE);
S2N_ERROR_IF(s2n_stuffer_data_available(&conn->alert_in) == 2, S2N_ERR_ALERT_PRESENT);
- ENSURE_POSIX(s2n_alerts_supported(conn), S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE(s2n_alerts_supported(conn), S2N_ERR_BAD_MESSAGE);
while (s2n_stuffer_data_available(&conn->in)) {
uint8_t bytes_required = 2;
@@ -95,19 +182,20 @@ int s2n_process_alert_fragment(struct s2n_connection *conn)
int bytes_to_read = MIN(bytes_required, s2n_stuffer_data_available(&conn->in));
- GUARD(s2n_stuffer_copy(&conn->in, &conn->alert_in, bytes_to_read));
+ POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->alert_in, bytes_to_read));
if (s2n_stuffer_data_available(&conn->alert_in) == 2) {
/* Close notifications are handled as shutdowns */
if (conn->alert_in_data[1] == S2N_TLS_ALERT_CLOSE_NOTIFY) {
conn->closed = 1;
+ conn->close_notify_received = true;
return 0;
}
/* Ignore warning-level alerts if we're in warning-tolerant mode */
if (s2n_handle_as_warning(conn, conn->alert_in_data[0], conn->alert_in_data[1])) {
- GUARD(s2n_stuffer_wipe(&conn->alert_in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->alert_in));
return 0;
}
@@ -118,7 +206,7 @@ int s2n_process_alert_fragment(struct s2n_connection *conn)
/* All other alerts are treated as fatal errors */
conn->closed = 1;
- S2N_ERROR(S2N_ERR_ALERT);
+ POSIX_BAIL(S2N_ERR_ALERT);
}
}
@@ -127,7 +215,7 @@ int s2n_process_alert_fragment(struct s2n_connection *conn)
int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
uint8_t alert[2];
alert[0] = S2N_TLS_ALERT_LEVEL_WARNING;
@@ -144,7 +232,7 @@ int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn)
return S2N_SUCCESS;
}
- GUARD(s2n_stuffer_write(&conn->writer_alert_out, &out));
+ POSIX_GUARD(s2n_stuffer_write(&conn->writer_alert_out, &out));
conn->close_notify_queued = 1;
return S2N_SUCCESS;
@@ -152,7 +240,7 @@ int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn)
static int s2n_queue_reader_alert(struct s2n_connection *conn, uint8_t level, uint8_t error_code)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
uint8_t alert[2];
alert[0] = level;
@@ -169,7 +257,7 @@ static int s2n_queue_reader_alert(struct s2n_connection *conn, uint8_t level, ui
return S2N_SUCCESS;
}
- GUARD(s2n_stuffer_write(&conn->reader_alert_out, &out));
+ POSIX_GUARD(s2n_stuffer_write(&conn->reader_alert_out, &out));
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_alerts.h b/contrib/restricted/aws/s2n/tls/s2n_alerts.h
index 694c64068c..da735db9d8 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_alerts.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_alerts.h
@@ -19,6 +19,84 @@
#include "tls/s2n_connection.h"
+typedef enum {
+ /*
+ *= https://tools.ietf.org/rfc/rfc8446#section-6
+ *# enum {
+ *# close_notify(0),
+ *# unexpected_message(10),
+ *# bad_record_mac(20),
+ *# record_overflow(22),
+ *# handshake_failure(40),
+ */
+ S2N_TLS_ALERT_CLOSE_NOTIFY = 0,
+ S2N_TLS_ALERT_UNEXPECTED_MESSAGE = 10,
+ S2N_TLS_ALERT_BAD_RECORD_MAC = 20,
+ S2N_TLS_ALERT_RECORD_OVERFLOW = 22,
+ S2N_TLS_ALERT_HANDSHAKE_FAILURE = 40,
+ /*
+ *= https://tools.ietf.org/rfc/rfc8446#section-6
+ *# bad_certificate(42),
+ *# unsupported_certificate(43),
+ *# certificate_revoked(44),
+ *# certificate_expired(45),
+ *# certificate_unknown(46),
+ */
+ S2N_TLS_ALERT_BAD_CERTIFICATE = 42,
+ S2N_TLS_ALERT_UNSUPPORTED_CERTIFICATE = 43,
+ S2N_TLS_ALERT_CERTIFICATE_REVOKED = 44,
+ S2N_TLS_ALERT_CERTIFICATE_EXPIRED = 45,
+ S2N_TLS_ALERT_CERTIFICATE_UNKNOWN = 46,
+ /*
+ *= https://tools.ietf.org/rfc/rfc8446#section-6
+ *# illegal_parameter(47),
+ *# unknown_ca(48),
+ *# access_denied(49),
+ *# decode_error(50),
+ *# decrypt_error(51),
+ */
+ S2N_TLS_ALERT_ILLEGAL_PARAMETER = 47,
+ S2N_TLS_ALERT_UNKNOWN_CA = 48,
+ S2N_TLS_ALERT_ACCESS_DENIED = 49,
+ S2N_TLS_ALERT_DECODE_ERROR = 50,
+ S2N_TLS_ALERT_DECRYPT_ERROR = 51,
+ /*
+ *= https://tools.ietf.org/rfc/rfc8446#section-6
+ *# protocol_version(70),
+ *# insufficient_security(71),
+ *# internal_error(80),
+ *# inappropriate_fallback(86),
+ *# user_canceled(90),
+ */
+ S2N_TLS_ALERT_PROTOCOL_VERSION = 70,
+ S2N_TLS_ALERT_INSUFFICIENT_SECURITY = 71,
+ S2N_TLS_ALERT_INTERNAL_ERROR = 80,
+ S2N_TLS_ALERT_INAPPROPRIATE_FALLBACK = 86,
+ S2N_TLS_ALERT_USER_CANCELED = 90,
+ /*
+ *= https://tools.ietf.org/rfc/rfc8446#section-6
+ *# missing_extension(109),
+ *# unsupported_extension(110),
+ *# unrecognized_name(112),
+ *# bad_certificate_status_response(113),
+ *# unknown_psk_identity(115),
+ */
+ S2N_TLS_ALERT_MISSING_EXTENSION = 109,
+ S2N_TLS_ALERT_UNSUPPORTED_EXTENSION = 110,
+ S2N_TLS_ALERT_UNRECOGNIZED_NAME = 112,
+ S2N_TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE = 113,
+ S2N_TLS_ALERT_UNKNOWN_PSK_IDENTITY = 115,
+ /*
+ *= https://tools.ietf.org/rfc/rfc8446#section-6
+ *# certificate_required(116),
+ *# no_application_protocol(120),
+ *# (255)
+ *# } AlertDescription;
+ */
+ S2N_TLS_ALERT_CERTIFICATE_REQUIRED = 116,
+ S2N_TLS_ALERT_NO_APPLICATION_PROTOCOL = 120,
+} s2n_tls_alert_code;
+
extern int s2n_process_alert_fragment(struct s2n_connection *conn);
extern int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn);
extern int s2n_queue_reader_unsupported_protocol_version_alert(struct s2n_connection *conn);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c
index d1960eac69..062324db57 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c
@@ -17,7 +17,7 @@
#include "crypto/s2n_hash.h"
#include "crypto/s2n_signature.h"
#include "error/s2n_errno.h"
-#include "s2n.h"
+#include "api/s2n.h"
#include "tls/s2n_connection.h"
#include "tls/s2n_handshake.h"
#include "utils/s2n_blob.h"
@@ -25,8 +25,6 @@
#include "utils/s2n_result.h"
#include "utils/s2n_safety.h"
-typedef enum { S2N_ASYNC_DECRYPT, S2N_ASYNC_SIGN } s2n_async_pkey_op_type;
-
struct s2n_async_pkey_decrypt_data {
s2n_async_pkey_decrypt_complete on_complete;
struct s2n_blob encrypted;
@@ -44,6 +42,7 @@ struct s2n_async_pkey_sign_data {
struct s2n_async_pkey_op {
s2n_async_pkey_op_type type;
struct s2n_connection *conn;
+ s2n_async_pkey_validation_mode validation_mode;
unsigned complete : 1;
unsigned applied : 1;
union {
@@ -55,6 +54,9 @@ struct s2n_async_pkey_op {
struct s2n_async_pkey_op_actions {
S2N_RESULT (*perform)(struct s2n_async_pkey_op *op, s2n_cert_private_key *pkey);
S2N_RESULT (*apply)(struct s2n_async_pkey_op *op, struct s2n_connection *conn);
+ S2N_RESULT (*get_input_size)(struct s2n_async_pkey_op *op, uint32_t *data_len);
+ S2N_RESULT (*get_input)(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len);
+ S2N_RESULT (*set_output)(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len);
S2N_RESULT (*free)(struct s2n_async_pkey_op *op);
};
@@ -76,25 +78,37 @@ static S2N_RESULT s2n_async_pkey_decrypt_sync(struct s2n_connection *conn, struc
static S2N_RESULT s2n_async_pkey_decrypt_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *pkey);
static S2N_RESULT s2n_async_pkey_decrypt_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn);
+static S2N_RESULT s2n_async_pkey_get_input_size_decrypt(struct s2n_async_pkey_op *op, uint32_t *data_len);
+static S2N_RESULT s2n_async_pkey_get_input_decrypt(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len);
+static S2N_RESULT s2n_async_pkey_op_set_output_decrypt(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len);
static S2N_RESULT s2n_async_pkey_decrypt_free(struct s2n_async_pkey_op *op);
static S2N_RESULT s2n_async_pkey_sign_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *pkey);
static S2N_RESULT s2n_async_pkey_sign_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn);
+static S2N_RESULT s2n_async_pkey_get_input_size_sign(struct s2n_async_pkey_op *op, uint32_t *data_len);
+static S2N_RESULT s2n_async_pkey_get_input_sign(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len);
+static S2N_RESULT s2n_async_pkey_op_set_output_sign(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len);
static S2N_RESULT s2n_async_pkey_sign_free(struct s2n_async_pkey_op *op);
static const struct s2n_async_pkey_op_actions s2n_async_pkey_decrypt_op = { .perform = &s2n_async_pkey_decrypt_perform,
.apply = &s2n_async_pkey_decrypt_apply,
+ .get_input_size = &s2n_async_pkey_get_input_size_decrypt,
+ .get_input = &s2n_async_pkey_get_input_decrypt,
+ .set_output = &s2n_async_pkey_op_set_output_decrypt,
.free = &s2n_async_pkey_decrypt_free };
static const struct s2n_async_pkey_op_actions s2n_async_pkey_sign_op = { .perform = &s2n_async_pkey_sign_perform,
.apply = &s2n_async_pkey_sign_apply,
+ .get_input_size = &s2n_async_pkey_get_input_size_sign,
+ .get_input = &s2n_async_pkey_get_input_sign,
+ .set_output = &s2n_async_pkey_op_set_output_sign,
.free = &s2n_async_pkey_sign_free };
DEFINE_POINTER_CLEANUP_FUNC(struct s2n_async_pkey_op *, s2n_async_pkey_op_free);
static S2N_RESULT s2n_async_get_actions(s2n_async_pkey_op_type type, const struct s2n_async_pkey_op_actions **actions)
{
- ENSURE_REF(actions);
+ RESULT_ENSURE_REF(actions);
switch (type) {
case S2N_ASYNC_DECRYPT:
@@ -111,13 +125,13 @@ static S2N_RESULT s2n_async_get_actions(s2n_async_pkey_op_type type, const struc
static S2N_RESULT s2n_async_pkey_op_allocate(struct s2n_async_pkey_op **op)
{
- ENSURE_REF(op);
- ENSURE(*op == NULL, S2N_ERR_SAFETY);
+ RESULT_ENSURE_REF(op);
+ RESULT_ENSURE(*op == NULL, S2N_ERR_SAFETY);
/* allocate memory */
DEFER_CLEANUP(struct s2n_blob mem = {0}, s2n_free);
- GUARD_AS_RESULT(s2n_alloc(&mem, sizeof(struct s2n_async_pkey_op)));
- GUARD_AS_RESULT(s2n_blob_zero(&mem));
+ RESULT_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_async_pkey_op)));
+ RESULT_GUARD_POSIX(s2n_blob_zero(&mem));
*op = (void *) mem.data;
if (s2n_blob_init(&mem, NULL, 0) != S2N_SUCCESS) {
@@ -130,70 +144,82 @@ static S2N_RESULT s2n_async_pkey_op_allocate(struct s2n_async_pkey_op **op)
S2N_RESULT s2n_async_pkey_decrypt(struct s2n_connection *conn, struct s2n_blob *encrypted,
struct s2n_blob *init_decrypted, s2n_async_pkey_decrypt_complete on_complete)
{
- ENSURE_REF(conn);
- ENSURE_REF(encrypted);
- ENSURE_REF(init_decrypted);
- ENSURE_REF(on_complete);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(encrypted);
+ RESULT_ENSURE_REF(init_decrypted);
+ RESULT_ENSURE_REF(on_complete);
if (conn->config->async_pkey_cb) {
- GUARD_RESULT(s2n_async_pkey_decrypt_async(conn, encrypted, init_decrypted, on_complete));
+ RESULT_GUARD(s2n_async_pkey_decrypt_async(conn, encrypted, init_decrypted, on_complete));
} else {
- GUARD_RESULT(s2n_async_pkey_decrypt_sync(conn, encrypted, init_decrypted, on_complete));
+ RESULT_GUARD(s2n_async_pkey_decrypt_sync(conn, encrypted, init_decrypted, on_complete));
}
return S2N_RESULT_OK;
}
+S2N_RESULT s2n_async_cb_execute(struct s2n_connection *conn, struct s2n_async_pkey_op **owned_op)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(owned_op);
+ RESULT_ENSURE(conn->handshake.async_state == S2N_ASYNC_NOT_INVOKED, S2N_ERR_ASYNC_MORE_THAN_ONE);
+
+ /* The callback now owns the operation, meaning we can't free it.
+ * Wipe our version and pass a copy to the callback.
+ */
+ struct s2n_async_pkey_op *unowned_op = *owned_op;
+ ZERO_TO_DISABLE_DEFER_CLEANUP(*owned_op);
+
+ conn->handshake.async_state = S2N_ASYNC_INVOKED;
+ RESULT_ENSURE(conn->config->async_pkey_cb(conn, unowned_op) == S2N_SUCCESS, S2N_ERR_ASYNC_CALLBACK_FAILED);
+
+ /*
+ * If the callback already completed the operation, continue.
+ * Otherwise, we need to block s2n_negotiate and wait for the operation to complete.
+ */
+ if (conn->handshake.async_state == S2N_ASYNC_COMPLETE) {
+ return S2N_RESULT_OK;
+ }
+ RESULT_BAIL(S2N_ERR_ASYNC_BLOCKED);
+}
+
S2N_RESULT s2n_async_pkey_decrypt_async(struct s2n_connection *conn, struct s2n_blob *encrypted,
struct s2n_blob *init_decrypted, s2n_async_pkey_decrypt_complete on_complete)
{
- ENSURE_REF(conn);
- ENSURE_REF(encrypted);
- ENSURE_REF(init_decrypted);
- ENSURE_REF(on_complete);
- ENSURE(conn->handshake.async_state == S2N_ASYNC_NOT_INVOKED, S2N_ERR_ASYNC_MORE_THAN_ONE);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(encrypted);
+ RESULT_ENSURE_REF(init_decrypted);
+ RESULT_ENSURE_REF(on_complete);
DEFER_CLEANUP(struct s2n_async_pkey_op *op = NULL, s2n_async_pkey_op_free_pointer);
- GUARD_RESULT(s2n_async_pkey_op_allocate(&op));
+ RESULT_GUARD(s2n_async_pkey_op_allocate(&op));
op->type = S2N_ASYNC_DECRYPT;
op->conn = conn;
+ op->validation_mode = conn->config->async_pkey_validation_mode;
struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
decrypt->on_complete = on_complete;
- GUARD_AS_RESULT(s2n_dup(encrypted, &decrypt->encrypted));
- GUARD_AS_RESULT(s2n_dup(init_decrypted, &decrypt->decrypted));
-
- /* Block the handshake and set async state to invoking to block async states */
- GUARD_AS_RESULT(s2n_conn_set_handshake_read_block(conn));
- conn->handshake.async_state = S2N_ASYNC_INVOKING_CALLBACK;
-
- /* Move op to tmp to avoid DEFER_CLEANUP freeing the op, as it will be owned by callback */
- struct s2n_async_pkey_op *tmp_op = op;
- op = NULL;
-
- ENSURE(conn->config->async_pkey_cb(conn, tmp_op) == S2N_SUCCESS, S2N_ERR_ASYNC_CALLBACK_FAILED);
+ RESULT_GUARD_POSIX(s2n_dup(encrypted, &decrypt->encrypted));
+ RESULT_GUARD_POSIX(s2n_dup(init_decrypted, &decrypt->decrypted));
- /* Set state to waiting to allow op to be consumed by connection */
- conn->handshake.async_state = S2N_ASYNC_INVOKED_WAITING;
-
- /* Return an async blocked error to drop out of s2n_negotiate loop */
- BAIL(S2N_ERR_ASYNC_BLOCKED);
+ RESULT_GUARD(s2n_async_cb_execute(conn, &op));
+ return S2N_RESULT_OK;
}
S2N_RESULT s2n_async_pkey_decrypt_sync(struct s2n_connection *conn, struct s2n_blob *encrypted,
struct s2n_blob *init_decrypted, s2n_async_pkey_decrypt_complete on_complete)
{
- ENSURE_REF(conn);
- ENSURE_REF(encrypted);
- ENSURE_REF(init_decrypted);
- ENSURE_REF(on_complete);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(encrypted);
+ RESULT_ENSURE_REF(init_decrypted);
+ RESULT_ENSURE_REF(on_complete);
const struct s2n_pkey *pkey = conn->handshake_params.our_chain_and_key->private_key;
bool rsa_failed = s2n_pkey_decrypt(pkey, encrypted, init_decrypted) != S2N_SUCCESS;
- GUARD_AS_RESULT(on_complete(conn, rsa_failed, init_decrypted));
+ RESULT_GUARD_POSIX(on_complete(conn, rsa_failed, init_decrypted));
return S2N_RESULT_OK;
}
@@ -201,14 +227,14 @@ S2N_RESULT s2n_async_pkey_decrypt_sync(struct s2n_connection *conn, struct s2n_b
S2N_RESULT s2n_async_pkey_sign(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
struct s2n_hash_state *digest, s2n_async_pkey_sign_complete on_complete)
{
- ENSURE_REF(conn);
- ENSURE_REF(digest);
- ENSURE_REF(on_complete);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(digest);
+ RESULT_ENSURE_REF(on_complete);
if (conn->config->async_pkey_cb) {
- GUARD_RESULT(s2n_async_pkey_sign_async(conn, sig_alg, digest, on_complete));
+ RESULT_GUARD(s2n_async_pkey_sign_async(conn, sig_alg, digest, on_complete));
} else {
- GUARD_RESULT(s2n_async_pkey_sign_sync(conn, sig_alg, digest, on_complete));
+ RESULT_GUARD(s2n_async_pkey_sign_sync(conn, sig_alg, digest, on_complete));
}
return S2N_RESULT_OK;
@@ -217,73 +243,60 @@ S2N_RESULT s2n_async_pkey_sign(struct s2n_connection *conn, s2n_signature_algori
S2N_RESULT s2n_async_pkey_sign_async(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
struct s2n_hash_state *digest, s2n_async_pkey_sign_complete on_complete)
{
- ENSURE_REF(conn);
- ENSURE_REF(digest);
- ENSURE_REF(on_complete);
- ENSURE(conn->handshake.async_state == S2N_ASYNC_NOT_INVOKED, S2N_ERR_ASYNC_MORE_THAN_ONE);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(digest);
+ RESULT_ENSURE_REF(on_complete);
DEFER_CLEANUP(struct s2n_async_pkey_op *op = NULL, s2n_async_pkey_op_free_pointer);
- GUARD_RESULT(s2n_async_pkey_op_allocate(&op));
+ RESULT_GUARD(s2n_async_pkey_op_allocate(&op));
op->type = S2N_ASYNC_SIGN;
op->conn = conn;
+ op->validation_mode = conn->config->async_pkey_validation_mode;
struct s2n_async_pkey_sign_data *sign = &op->op.sign;
sign->on_complete = on_complete;
sign->sig_alg = sig_alg;
- GUARD_AS_RESULT(s2n_hash_new(&sign->digest));
- GUARD_AS_RESULT(s2n_hash_copy(&sign->digest, digest));
-
- /* Block the handshake and set async state to invoking to block async states */
- GUARD_AS_RESULT(s2n_conn_set_handshake_read_block(conn));
- conn->handshake.async_state = S2N_ASYNC_INVOKING_CALLBACK;
-
- /* Move op to tmp to avoid DEFER_CLEANUP freeing the op, as it will be owned by callback */
- struct s2n_async_pkey_op *tmp_op = op;
- op = NULL;
+ RESULT_GUARD_POSIX(s2n_hash_new(&sign->digest));
+ RESULT_GUARD_POSIX(s2n_hash_copy(&sign->digest, digest));
- ENSURE(conn->config->async_pkey_cb(conn, tmp_op) == S2N_SUCCESS, S2N_ERR_ASYNC_CALLBACK_FAILED);
-
- /* Set state to waiting to allow op to be consumed by connection */
- conn->handshake.async_state = S2N_ASYNC_INVOKED_WAITING;
-
- /* Return an async blocked error to drop out of s2n_negotiate loop */
- BAIL(S2N_ERR_ASYNC_BLOCKED);
+ RESULT_GUARD(s2n_async_cb_execute(conn, &op));
+ return S2N_RESULT_OK;
}
S2N_RESULT s2n_async_pkey_sign_sync(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
struct s2n_hash_state *digest, s2n_async_pkey_sign_complete on_complete)
{
- ENSURE_REF(conn);
- ENSURE_REF(digest);
- ENSURE_REF(on_complete);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(digest);
+ RESULT_ENSURE_REF(on_complete);
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 = 0;
- GUARD_RESULT(s2n_pkey_size(pkey, &maximum_signature_length));
- GUARD_AS_RESULT(s2n_alloc(&signed_content, maximum_signature_length));
+ RESULT_GUARD(s2n_pkey_size(pkey, &maximum_signature_length));
+ RESULT_GUARD_POSIX(s2n_alloc(&signed_content, maximum_signature_length));
- GUARD_AS_RESULT(s2n_pkey_sign(pkey, sig_alg, digest, &signed_content));
+ RESULT_GUARD_POSIX(s2n_pkey_sign(pkey, sig_alg, digest, &signed_content));
- GUARD_AS_RESULT(on_complete(conn, &signed_content));
+ RESULT_GUARD_POSIX(on_complete(conn, &signed_content));
return S2N_RESULT_OK;
}
int s2n_async_pkey_op_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *key)
{
- ENSURE_POSIX_REF(op);
- ENSURE_POSIX_REF(key);
- ENSURE_POSIX(!op->complete, S2N_ERR_ASYNC_ALREADY_PERFORMED);
+ POSIX_ENSURE_REF(op);
+ POSIX_ENSURE_REF(key);
+ POSIX_ENSURE(!op->complete, S2N_ERR_ASYNC_ALREADY_PERFORMED);
const struct s2n_async_pkey_op_actions *actions = NULL;
- GUARD_AS_POSIX(s2n_async_get_actions(op->type, &actions));
- notnull_check(actions);
+ POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
+ POSIX_ENSURE_REF(actions);
- GUARD_AS_POSIX(actions->perform(op, key));
+ POSIX_GUARD_RESULT(actions->perform(op, key));
op->complete = true;
@@ -292,52 +305,51 @@ int s2n_async_pkey_op_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key
int s2n_async_pkey_op_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn)
{
- ENSURE_POSIX_REF(op);
- ENSURE_POSIX_REF(conn);
- ENSURE_POSIX(op->complete, S2N_ERR_ASYNC_NOT_PERFORMED);
- ENSURE_POSIX(!op->applied, S2N_ERR_ASYNC_ALREADY_APPLIED);
+ POSIX_ENSURE_REF(op);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE(op->complete, S2N_ERR_ASYNC_NOT_PERFORMED);
+ POSIX_ENSURE(!op->applied, S2N_ERR_ASYNC_ALREADY_APPLIED);
/* We could have just used op->conn and removed a conn argument, but we want caller
* to be explicit about connection it wants to resume. Plus this gives more
* protections in cases if caller frees connection object and then tries to resume
* the connection. */
- ENSURE_POSIX(op->conn == conn, S2N_ERR_ASYNC_WRONG_CONNECTION);
- ENSURE_POSIX(conn->handshake.async_state != S2N_ASYNC_INVOKING_CALLBACK, S2N_ERR_ASYNC_APPLY_WHILE_INVOKING);
- ENSURE_POSIX(conn->handshake.async_state == S2N_ASYNC_INVOKED_WAITING, S2N_ERR_ASYNC_WRONG_CONNECTION);
+ POSIX_ENSURE(op->conn == conn, S2N_ERR_ASYNC_WRONG_CONNECTION);
+ POSIX_ENSURE(conn->handshake.async_state == S2N_ASYNC_INVOKED, S2N_ERR_ASYNC_WRONG_CONNECTION);
const struct s2n_async_pkey_op_actions *actions = NULL;
- GUARD_AS_POSIX(s2n_async_get_actions(op->type, &actions));
- notnull_check(actions);
+ POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
+ POSIX_ENSURE_REF(actions);
- GUARD_AS_POSIX(actions->apply(op, conn));
+ POSIX_GUARD_RESULT(actions->apply(op, conn));
op->applied = true;
- conn->handshake.async_state = S2N_ASYNC_INVOKED_COMPLETE;
+ conn->handshake.async_state = S2N_ASYNC_COMPLETE;
/* Free up the decrypt/sign structs to avoid storing secrets for too long */
- GUARD_AS_POSIX(actions->free(op));
+ POSIX_GUARD_RESULT(actions->free(op));
return S2N_SUCCESS;
}
int s2n_async_pkey_op_free(struct s2n_async_pkey_op *op)
{
- ENSURE_POSIX_REF(op);
+ POSIX_ENSURE_REF(op);
const struct s2n_async_pkey_op_actions *actions = NULL;
- GUARD_AS_POSIX(s2n_async_get_actions(op->type, &actions));
- notnull_check(actions);
+ POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
+ POSIX_ENSURE_REF(actions);
/* If applied the decrypt/sign structs were released in apply call */
- if (!op->applied) { GUARD_AS_POSIX(actions->free(op)); }
+ if (!op->applied) { POSIX_GUARD_RESULT(actions->free(op)); }
- GUARD_POSIX(s2n_free_object(( uint8_t ** )&op, sizeof(struct s2n_async_pkey_op)));
+ POSIX_GUARD(s2n_free_object(( uint8_t ** )&op, sizeof(struct s2n_async_pkey_op)));
return S2N_SUCCESS;
}
S2N_RESULT s2n_async_pkey_decrypt_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *pkey)
{
- ENSURE_REF(op);
- ENSURE_REF(pkey);
+ RESULT_ENSURE_REF(op);
+ RESULT_ENSURE_REF(pkey);
struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
@@ -348,66 +360,259 @@ S2N_RESULT s2n_async_pkey_decrypt_perform(struct s2n_async_pkey_op *op, s2n_cert
S2N_RESULT s2n_async_pkey_decrypt_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn)
{
- ENSURE_REF(op);
- ENSURE_REF(conn);
+ RESULT_ENSURE_REF(op);
+ RESULT_ENSURE_REF(conn);
struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
- GUARD_AS_RESULT(decrypt->on_complete(conn, decrypt->rsa_failed, &decrypt->decrypted));
+ RESULT_GUARD_POSIX(decrypt->on_complete(conn, decrypt->rsa_failed, &decrypt->decrypted));
return S2N_RESULT_OK;
}
S2N_RESULT s2n_async_pkey_decrypt_free(struct s2n_async_pkey_op *op)
{
- ENSURE_REF(op);
+ RESULT_ENSURE_REF(op);
struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
- GUARD_AS_RESULT(s2n_blob_zero(&decrypt->decrypted));
- GUARD_AS_RESULT(s2n_blob_zero(&decrypt->encrypted));
- GUARD_AS_RESULT(s2n_free(&decrypt->decrypted));
- GUARD_AS_RESULT(s2n_free(&decrypt->encrypted));
+ RESULT_GUARD_POSIX(s2n_blob_zero(&decrypt->decrypted));
+ RESULT_GUARD_POSIX(s2n_blob_zero(&decrypt->encrypted));
+ RESULT_GUARD_POSIX(s2n_free(&decrypt->decrypted));
+ RESULT_GUARD_POSIX(s2n_free(&decrypt->encrypted));
return S2N_RESULT_OK;
}
S2N_RESULT s2n_async_pkey_sign_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *pkey)
{
- ENSURE_REF(op);
- ENSURE_REF(pkey);
+ RESULT_ENSURE_REF(op);
+ RESULT_ENSURE_REF(op->conn);
+ RESULT_ENSURE_REF(op->conn->config);
+ RESULT_ENSURE_REF(pkey);
struct s2n_async_pkey_sign_data *sign = &op->op.sign;
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));
+ RESULT_GUARD(s2n_pkey_size(pkey, &maximum_signature_length));
+ RESULT_GUARD_POSIX(s2n_alloc(&sign->signature, maximum_signature_length));
- GUARD_AS_RESULT(s2n_pkey_sign(pkey, sign->sig_alg, &sign->digest, &sign->signature));
+ /* If validation mode is S2N_ASYNC_PKEY_VALIDATION_STRICT
+ * then use local hash copy to sign the signature */
+ if (op->validation_mode == S2N_ASYNC_PKEY_VALIDATION_STRICT) {
+ DEFER_CLEANUP(struct s2n_hash_state hash_state_copy, s2n_hash_free);
+ RESULT_GUARD_POSIX(s2n_hash_new(&hash_state_copy));
+ RESULT_GUARD_POSIX(s2n_hash_copy(&hash_state_copy, &sign->digest));
+
+ RESULT_GUARD_POSIX(s2n_pkey_sign(pkey, sign->sig_alg, &hash_state_copy, &sign->signature));
+ } else {
+ RESULT_GUARD_POSIX(s2n_pkey_sign(pkey, sign->sig_alg, &sign->digest, &sign->signature));
+ }
return S2N_RESULT_OK;
}
S2N_RESULT s2n_async_pkey_sign_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn)
{
- ENSURE_REF(op);
- ENSURE_REF(conn);
+ RESULT_ENSURE_REF(op);
+ RESULT_ENSURE_REF(conn);
struct s2n_async_pkey_sign_data *sign = &op->op.sign;
- GUARD_AS_RESULT(sign->on_complete(conn, &sign->signature));
+ /* Perform signature validation only if validation feature is opt in */
+ if (op->validation_mode == S2N_ASYNC_PKEY_VALIDATION_STRICT) {
+ RESULT_GUARD(s2n_async_pkey_verify_signature(conn, sign->sig_alg, &sign->digest, &sign->signature));
+ }
+
+ RESULT_GUARD_POSIX(sign->on_complete(conn, &sign->signature));
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_async_pkey_verify_signature(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
+ struct s2n_hash_state *digest, struct s2n_blob *signature) {
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->handshake_params.our_chain_and_key);
+ RESULT_ENSURE_REF(digest);
+ RESULT_ENSURE_REF(signature);
+
+ /* Parse public key for the cert */
+ DEFER_CLEANUP(struct s2n_pkey public_key = {0}, s2n_pkey_free);
+ s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN;
+ RESULT_GUARD_POSIX(s2n_asn1der_to_public_key_and_type(&public_key, &pkey_type,
+ &conn->handshake_params.our_chain_and_key->cert_chain->head->raw));
+ RESULT_ENSURE(s2n_pkey_verify(&public_key, sig_alg, digest, signature) == S2N_SUCCESS, S2N_ERR_VERIFY_SIGNATURE);
return S2N_RESULT_OK;
}
S2N_RESULT s2n_async_pkey_sign_free(struct s2n_async_pkey_op *op)
{
- ENSURE_REF(op);
+ RESULT_ENSURE_REF(op);
+
+ struct s2n_async_pkey_sign_data *sign = &op->op.sign;
+
+ RESULT_GUARD_POSIX(s2n_hash_free(&sign->digest));
+ RESULT_GUARD_POSIX(s2n_free(&sign->signature));
+
+ return S2N_RESULT_OK;
+}
+
+int s2n_async_pkey_op_set_validation_mode(struct s2n_async_pkey_op *op, s2n_async_pkey_validation_mode mode)
+{
+ POSIX_ENSURE_REF(op);
+
+ switch(mode) {
+ case S2N_ASYNC_PKEY_VALIDATION_FAST:
+ case S2N_ASYNC_PKEY_VALIDATION_STRICT:
+ op->validation_mode = mode;
+ return S2N_SUCCESS;
+ }
+
+ POSIX_BAIL(S2N_ERR_INVALID_ARGUMENT);
+}
+
+int s2n_async_pkey_op_get_op_type(struct s2n_async_pkey_op *op, s2n_async_pkey_op_type *type)
+{
+ POSIX_ENSURE_REF(op);
+ POSIX_ENSURE_REF(type);
+
+ *type = op->type;
+
+ return S2N_SUCCESS;
+}
+
+int s2n_async_pkey_op_get_input_size(struct s2n_async_pkey_op *op, uint32_t *data_len)
+{
+ POSIX_ENSURE_REF(op);
+ POSIX_ENSURE_REF(data_len);
+
+ const struct s2n_async_pkey_op_actions *actions = NULL;
+ POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
+ POSIX_ENSURE_REF(actions);
+
+ POSIX_GUARD_RESULT(actions->get_input_size(op, data_len));
+
+ return S2N_SUCCESS;
+}
+
+static S2N_RESULT s2n_async_pkey_get_input_size_decrypt(struct s2n_async_pkey_op *op, uint32_t *data_len)
+{
+ RESULT_ENSURE_REF(op);
+ RESULT_ENSURE_REF(data_len);
+
+ struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
+ struct s2n_blob *in = &decrypt->encrypted;
+
+ *data_len = in->size;
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_async_pkey_get_input_size_sign(struct s2n_async_pkey_op *op, uint32_t *data_len)
+{
+ RESULT_ENSURE_REF(op);
+ RESULT_ENSURE_REF(data_len);
+
+ struct s2n_async_pkey_sign_data *sign = &op->op.sign;
+ struct s2n_hash_state *digest = &sign->digest;
+
+ uint8_t digest_length = 0;
+ RESULT_GUARD_POSIX(s2n_hash_digest_size(digest->alg, &digest_length));
+
+ *data_len = digest_length;
+
+ return S2N_RESULT_OK;
+}
+
+int s2n_async_pkey_op_get_input(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len)
+{
+ POSIX_ENSURE_REF(op);
+ POSIX_ENSURE_REF(data);
+
+ const struct s2n_async_pkey_op_actions *actions = NULL;
+ POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
+ POSIX_ENSURE_REF(actions);
+
+ POSIX_GUARD_RESULT(actions->get_input(op, data, data_len));
+
+ return S2N_SUCCESS;
+}
+
+static S2N_RESULT s2n_async_pkey_get_input_decrypt(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len)
+{
+ RESULT_ENSURE_REF(op);
+ RESULT_ENSURE_REF(data);
+
+ struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
+ struct s2n_blob *in = &decrypt->encrypted;
+
+ RESULT_ENSURE_LTE(in->size, data_len);
+
+ RESULT_CHECKED_MEMCPY(data, in->data, in->size);
+
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_async_pkey_get_input_sign(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len)
+{
+ RESULT_ENSURE_REF(op);
+ RESULT_ENSURE_REF(data);
+
+ struct s2n_async_pkey_sign_data *sign = &op->op.sign;
+
+ DEFER_CLEANUP(struct s2n_hash_state digest_copy = { 0 }, s2n_hash_free);
+ RESULT_GUARD_POSIX(s2n_hash_new(&digest_copy));
+ RESULT_GUARD_POSIX(s2n_hash_copy(&digest_copy, &sign->digest));
+
+ uint8_t digest_length = 0;
+
+ RESULT_GUARD_POSIX(s2n_hash_digest_size(digest_copy.alg, &digest_length));
+
+ RESULT_ENSURE_LTE(digest_length, data_len);
+ RESULT_GUARD_POSIX(s2n_hash_digest(&digest_copy, data, digest_length));
+
+ return S2N_RESULT_OK;
+}
+
+int s2n_async_pkey_op_set_output(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len)
+{
+ POSIX_ENSURE_REF(op);
+ POSIX_ENSURE_REF(data);
+
+ const struct s2n_async_pkey_op_actions *actions = NULL;
+ POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
+ POSIX_ENSURE_REF(actions);
+
+ POSIX_GUARD_RESULT(actions->set_output(op, data, data_len));
+ op->complete = true;
+
+ return S2N_SUCCESS;
+}
+
+static S2N_RESULT s2n_async_pkey_op_set_output_decrypt(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len)
+{
+ RESULT_ENSURE_REF(op);
+ RESULT_ENSURE_REF(data);
+
+ struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
+ struct s2n_blob *out = &decrypt->decrypted;
+
+ RESULT_GUARD_POSIX(s2n_realloc(out, data_len));
+ RESULT_CHECKED_MEMCPY(out->data, data, data_len);
+
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_async_pkey_op_set_output_sign(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len)
+{
+ RESULT_ENSURE_REF(op);
+ RESULT_ENSURE_REF(data);
struct s2n_async_pkey_sign_data *sign = &op->op.sign;
+ struct s2n_blob *sigcopy = &sign->signature;
- GUARD_AS_RESULT(s2n_hash_free(&sign->digest));
- GUARD_AS_RESULT(s2n_free(&sign->signature));
+ RESULT_GUARD_POSIX(s2n_realloc(sigcopy, data_len));
+ RESULT_CHECKED_MEMCPY(sigcopy->data, data, data_len);
return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.h b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.h
index 2ef8386d2f..631a186a9a 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.h
@@ -32,19 +32,17 @@ struct s2n_async_pkey_op;
#define S2N_ASYNC_PKEY_GUARD(conn) \
do { \
__typeof(conn) __tmp_conn = (conn); \
- GUARD_NONNULL(__tmp_conn); \
+ POSIX_GUARD_PTR(__tmp_conn); \
switch (conn->handshake.async_state) { \
case S2N_ASYNC_NOT_INVOKED: \
break; \
\
- case S2N_ASYNC_INVOKING_CALLBACK: \
- case S2N_ASYNC_INVOKED_WAITING: \
- BAIL_POSIX(S2N_ERR_ASYNC_BLOCKED); \
+ case S2N_ASYNC_INVOKED: \
+ POSIX_BAIL(S2N_ERR_ASYNC_BLOCKED); \
\
- case S2N_ASYNC_INVOKED_COMPLETE: \
+ case S2N_ASYNC_COMPLETE: \
/* clean up state and return a success from handler */ \
__tmp_conn->handshake.async_state = S2N_ASYNC_NOT_INVOKED; \
- GUARD(s2n_conn_clear_handshake_read_block(__tmp_conn)); \
return S2N_SUCCESS; \
} \
} while (0)
@@ -56,15 +54,23 @@ struct s2n_async_pkey_op;
* call, we use a macro which directly returns the result of s2n_async* operation forcing compiler to error out on
* unreachable code and forcing developer to use on_complete function instead */
#define S2N_ASYNC_PKEY_DECRYPT(conn, encrypted, init_decrypted, on_complete) \
- return S2N_RESULT_TO_POSIX(s2n_async_pkey_decrypt(conn, encrypted, init_decrypted, on_complete));
+ return s2n_result_is_ok(s2n_async_pkey_decrypt(conn, encrypted, init_decrypted, on_complete)) ? S2N_SUCCESS : S2N_FAILURE;
#define S2N_ASYNC_PKEY_SIGN(conn, sig_alg, digest, on_complete) \
- return S2N_RESULT_TO_POSIX(s2n_async_pkey_sign(conn, sig_alg, digest, on_complete));
+ return s2n_result_is_ok(s2n_async_pkey_sign(conn, sig_alg, digest, on_complete)) ? S2N_SUCCESS : S2N_FAILURE;
int s2n_async_pkey_op_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *key);
int s2n_async_pkey_op_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn);
int s2n_async_pkey_op_free(struct s2n_async_pkey_op *op);
+int s2n_async_pkey_op_get_op_type(struct s2n_async_pkey_op *op, s2n_async_pkey_op_type *type);
+int s2n_async_pkey_op_get_input_size(struct s2n_async_pkey_op *op, uint32_t *data_len);
+int s2n_async_pkey_op_get_input(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len);
+int s2n_async_pkey_op_set_output(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len);
+int s2n_async_pkey_op_set_validation_mode(struct s2n_async_pkey_op *op, s2n_async_pkey_validation_mode mode);
+
+S2N_RESULT s2n_async_pkey_verify_signature(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
+ struct s2n_hash_state *digest, struct s2n_blob *signature);
S2N_RESULT s2n_async_pkey_decrypt(struct s2n_connection *conn, struct s2n_blob *encrypted, struct s2n_blob *init_decrypted,
s2n_async_pkey_decrypt_complete on_complete);
S2N_RESULT s2n_async_pkey_sign(struct s2n_connection *conn, s2n_signature_algorithm sig_alg, struct s2n_hash_state *digest,
diff --git a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c
index 33404c811b..eb132cc642 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c
@@ -40,7 +40,7 @@
* TLS1.2 cipher suites.
*/
-static int s2n_get_auth_method_for_cert_type(s2n_pkey_type cert_type, s2n_authentication_method *auth_method)
+int s2n_get_auth_method_for_cert_type(s2n_pkey_type cert_type, s2n_authentication_method *auth_method)
{
switch(cert_type) {
case S2N_PKEY_TYPE_RSA:
@@ -52,9 +52,9 @@ static int s2n_get_auth_method_for_cert_type(s2n_pkey_type cert_type, s2n_authen
return S2N_SUCCESS;
case S2N_PKEY_TYPE_UNKNOWN:
case S2N_PKEY_TYPE_SENTINEL:
- S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED);
+ POSIX_BAIL(S2N_ERR_CERT_TYPE_UNSUPPORTED);
}
- S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED);
+ POSIX_BAIL(S2N_ERR_CERT_TYPE_UNSUPPORTED);
}
static int s2n_get_cert_type_for_sig_alg(s2n_signature_algorithm sig_alg, s2n_pkey_type *cert_type)
@@ -71,17 +71,17 @@ static int s2n_get_cert_type_for_sig_alg(s2n_signature_algorithm sig_alg, s2n_pk
*cert_type = S2N_PKEY_TYPE_RSA_PSS;
return S2N_SUCCESS;
case S2N_SIGNATURE_ANONYMOUS:
- S2N_ERROR(S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
+ POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
}
- S2N_ERROR(S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
+ POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
}
static int s2n_is_sig_alg_valid_for_cipher_suite(s2n_signature_algorithm sig_alg, struct s2n_cipher_suite *cipher_suite)
{
- notnull_check(cipher_suite);
+ POSIX_ENSURE_REF(cipher_suite);
s2n_pkey_type cert_type_for_sig_alg;
- GUARD(s2n_get_cert_type_for_sig_alg(sig_alg, &cert_type_for_sig_alg));
+ POSIX_GUARD(s2n_get_cert_type_for_sig_alg(sig_alg, &cert_type_for_sig_alg));
/* Non-ephemeral key exchange methods require encryption, and RSA-PSS certificates
* do not support encryption.
@@ -90,7 +90,7 @@ static int s2n_is_sig_alg_valid_for_cipher_suite(s2n_signature_algorithm sig_alg
* algorithm that requires RSA-PSS certificates is not valid.
*/
if (cipher_suite->key_exchange_alg != NULL && !cipher_suite->key_exchange_alg->is_ephemeral) {
- ne_check(cert_type_for_sig_alg, S2N_PKEY_TYPE_RSA_PSS);
+ POSIX_ENSURE_NE(cert_type_for_sig_alg, S2N_PKEY_TYPE_RSA_PSS);
}
/* If a cipher suite includes an auth method, then the signature algorithm
@@ -98,8 +98,8 @@ static int s2n_is_sig_alg_valid_for_cipher_suite(s2n_signature_algorithm sig_alg
*/
if (cipher_suite->auth_method != S2N_AUTHENTICATION_METHOD_SENTINEL) {
s2n_authentication_method auth_method_for_sig_alg;
- GUARD(s2n_get_auth_method_for_cert_type(cert_type_for_sig_alg, &auth_method_for_sig_alg));
- eq_check(cipher_suite->auth_method, auth_method_for_sig_alg);
+ POSIX_GUARD(s2n_get_auth_method_for_cert_type(cert_type_for_sig_alg, &auth_method_for_sig_alg));
+ POSIX_ENSURE_EQ(cipher_suite->auth_method, auth_method_for_sig_alg);
}
return S2N_SUCCESS;
@@ -107,22 +107,22 @@ static int s2n_is_sig_alg_valid_for_cipher_suite(s2n_signature_algorithm sig_alg
static int s2n_certs_exist_for_sig_scheme(struct s2n_connection *conn, const struct s2n_signature_scheme *sig_scheme)
{
- notnull_check(sig_scheme);
+ POSIX_ENSURE_REF(sig_scheme);
s2n_pkey_type cert_type;
- GUARD(s2n_get_cert_type_for_sig_alg(sig_scheme->sig_alg, &cert_type));
+ POSIX_GUARD(s2n_get_cert_type_for_sig_alg(sig_scheme->sig_alg, &cert_type));
/* A valid cert must exist for the authentication method. */
struct s2n_cert_chain_and_key *cert = s2n_get_compatible_cert_chain_and_key(conn, cert_type);
- notnull_check(cert);
+ POSIX_ENSURE_REF(cert);
/* For sig_algs that include a curve, the group must also match. */
if (sig_scheme->signature_curve != NULL) {
- notnull_check(cert->private_key);
- notnull_check(cert->cert_chain);
- notnull_check(cert->cert_chain->head);
- eq_check(cert->cert_chain->head->pkey_type, S2N_PKEY_TYPE_ECDSA);
- GUARD(s2n_ecdsa_pkey_matches_curve(&cert->private_key->key.ecdsa_key, sig_scheme->signature_curve));
+ POSIX_ENSURE_REF(cert->private_key);
+ POSIX_ENSURE_REF(cert->cert_chain);
+ POSIX_ENSURE_REF(cert->cert_chain->head);
+ POSIX_ENSURE_EQ(cert->cert_chain->head->pkey_type, S2N_PKEY_TYPE_ECDSA);
+ POSIX_ENSURE_EQ(cert->cert_chain->head->ec_curve_nid, sig_scheme->signature_curve->libcrypto_nid);
}
return S2N_SUCCESS;
@@ -136,7 +136,7 @@ static int s2n_certs_exist_for_auth_method(struct s2n_connection *conn, s2n_auth
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));
+ POSIX_GUARD(s2n_get_auth_method_for_cert_type(i, &auth_method_for_cert_type));
if (auth_method != auth_method_for_cert_type) {
continue;
@@ -146,7 +146,7 @@ static int s2n_certs_exist_for_auth_method(struct s2n_connection *conn, s2n_auth
return S2N_SUCCESS;
}
}
- S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED);
+ POSIX_BAIL(S2N_ERR_CERT_TYPE_UNSUPPORTED);
}
/* TLS1.3 ciphers are always valid, as they don't include an auth method.
@@ -158,9 +158,9 @@ static int s2n_certs_exist_for_auth_method(struct s2n_connection *conn, s2n_auth
*/
int s2n_is_cipher_suite_valid_for_auth(struct s2n_connection *conn, struct s2n_cipher_suite *cipher_suite)
{
- notnull_check(cipher_suite);
+ POSIX_ENSURE_REF(cipher_suite);
- GUARD(s2n_certs_exist_for_auth_method(conn, cipher_suite->auth_method));
+ POSIX_GUARD(s2n_certs_exist_for_auth_method(conn, cipher_suite->auth_method));
return S2N_SUCCESS;
}
@@ -174,17 +174,17 @@ int s2n_is_cipher_suite_valid_for_auth(struct s2n_connection *conn, struct s2n_c
*/
int s2n_is_sig_scheme_valid_for_auth(struct s2n_connection *conn, const struct s2n_signature_scheme *sig_scheme)
{
- notnull_check(conn);
- notnull_check(sig_scheme);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(sig_scheme);
struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite;
- notnull_check(cipher_suite);
+ POSIX_ENSURE_REF(cipher_suite);
- GUARD(s2n_certs_exist_for_sig_scheme(conn, sig_scheme));
+ POSIX_GUARD(s2n_certs_exist_for_sig_scheme(conn, sig_scheme));
/* For the client side, signature algorithm does not need to match the cipher suite. */
if (conn->mode == S2N_SERVER) {
- GUARD(s2n_is_sig_alg_valid_for_cipher_suite(sig_scheme->sig_alg, cipher_suite));
+ POSIX_GUARD(s2n_is_sig_alg_valid_for_cipher_suite(sig_scheme->sig_alg, cipher_suite));
}
return S2N_SUCCESS;
}
@@ -200,11 +200,11 @@ int s2n_is_sig_scheme_valid_for_auth(struct s2n_connection *conn, const struct s
*/
int s2n_is_cert_type_valid_for_auth(struct s2n_connection *conn, s2n_pkey_type cert_type)
{
- notnull_check(conn);
- notnull_check(conn->secure.cipher_suite);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite);
s2n_authentication_method auth_method;
- GUARD(s2n_get_auth_method_for_cert_type(cert_type, &auth_method));
+ POSIX_GUARD(s2n_get_auth_method_for_cert_type(cert_type, &auth_method));
if (conn->secure.cipher_suite->auth_method != S2N_AUTHENTICATION_METHOD_SENTINEL) {
S2N_ERROR_IF(auth_method != conn->secure.cipher_suite->auth_method, S2N_ERR_CERT_TYPE_UNSUPPORTED);
@@ -219,10 +219,10 @@ int s2n_is_cert_type_valid_for_auth(struct s2n_connection *conn, s2n_pkey_type c
*/
int s2n_select_certs_for_server_auth(struct s2n_connection *conn, struct s2n_cert_chain_and_key **chosen_certs)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
s2n_pkey_type cert_type;
- GUARD(s2n_get_cert_type_for_sig_alg(conn->secure.conn_sig_scheme.sig_alg, &cert_type));
+ POSIX_GUARD(s2n_get_cert_type_for_sig_alg(conn->handshake_params.conn_sig_scheme.sig_alg, &cert_type));
*chosen_certs = s2n_get_compatible_cert_chain_and_key(conn, cert_type);
S2N_ERROR_IF(*chosen_certs == NULL, S2N_ERR_CERT_TYPE_UNSUPPORTED);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.h b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.h
index 370f00c4f8..b52736d7f6 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.h
@@ -20,6 +20,7 @@
#include "crypto/s2n_certificate.h"
#include "crypto/s2n_signature.h"
+int s2n_get_auth_method_for_cert_type(s2n_pkey_type cert_type, s2n_authentication_method *auth_method);
int s2n_is_cipher_suite_valid_for_auth(struct s2n_connection *conn, struct s2n_cipher_suite *cipher_suite);
int s2n_is_sig_scheme_valid_for_auth(struct s2n_connection *conn, const struct s2n_signature_scheme *sig_scheme);
int s2n_is_cert_type_valid_for_auth(struct s2n_connection *conn, s2n_pkey_type cert_type);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cbc.c b/contrib/restricted/aws/s2n/tls/s2n_cbc.c
index b2ae713e8e..401ab76072 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cbc.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_cbc.c
@@ -23,6 +23,7 @@
#include "crypto/s2n_hmac.h"
+#include "tls/s2n_connection.h"
#include "tls/s2n_record.h"
/* A TLS CBC record looks like ..
@@ -47,18 +48,12 @@
*/
int s2n_verify_cbc(struct s2n_connection *conn, struct s2n_hmac_state *hmac, struct s2n_blob *decrypted)
{
- /* Set up MAC copy workspace */
- struct s2n_hmac_state *copy = &conn->client->record_mac_copy_workspace;
- if (conn->mode == S2N_CLIENT) {
- copy = &conn->server->record_mac_copy_workspace;
- }
-
uint8_t mac_digest_size;
- GUARD(s2n_hmac_digest_size(hmac->alg, &mac_digest_size));
+ POSIX_GUARD(s2n_hmac_digest_size(hmac->alg, &mac_digest_size));
/* The record has to be at least big enough to contain the MAC,
* plus the padding length byte */
- gt_check(decrypted->size, mac_digest_size);
+ POSIX_ENSURE_GT(decrypted->size, mac_digest_size);
int payload_and_padding_size = decrypted->size - mac_digest_size;
@@ -68,18 +63,22 @@ int s2n_verify_cbc(struct s2n_connection *conn, struct s2n_hmac_state *hmac, str
int payload_length = MAX(payload_and_padding_size - padding_length - 1, 0);
/* Update the MAC */
- GUARD(s2n_hmac_update(hmac, decrypted->data, payload_length));
- GUARD(s2n_hmac_copy(copy, hmac));
+ POSIX_GUARD(s2n_hmac_update(hmac, decrypted->data, payload_length));
+ int currently_in_hash_block = hmac->currently_in_hash_block;
/* Check the MAC */
uint8_t check_digest[S2N_MAX_DIGEST_LEN];
- lte_check(mac_digest_size, sizeof(check_digest));
- GUARD(s2n_hmac_digest_two_compression_rounds(hmac, check_digest, mac_digest_size));
+ POSIX_ENSURE_LTE(mac_digest_size, sizeof(check_digest));
+ POSIX_GUARD(s2n_hmac_digest_two_compression_rounds(hmac, check_digest, mac_digest_size));
int mismatches = s2n_constant_time_equals(decrypted->data + payload_length, check_digest, mac_digest_size) ^ 1;
- /* Compute a MAC on the rest of the data so that we perform the same number of hash operations */
- GUARD(s2n_hmac_update(copy, decrypted->data + payload_length + mac_digest_size, decrypted->size - payload_length - mac_digest_size - 1));
+ /* Compute a MAC on the rest of the data so that we perform the same number of hash operations.
+ * Include the partial hash block from the first MAC to ensure we use the same number of blocks.
+ */
+ POSIX_GUARD(s2n_hmac_reset(hmac));
+ POSIX_GUARD(s2n_hmac_update(hmac, decrypted->data, currently_in_hash_block));
+ POSIX_GUARD(s2n_hmac_update(hmac, decrypted->data + payload_length + mac_digest_size, decrypted->size - payload_length - mac_digest_size - 1));
/* SSLv3 doesn't specify what the padding should actually be */
if (conn->actual_protocol_version == S2N_SSLv3) {
@@ -90,13 +89,11 @@ int s2n_verify_cbc(struct s2n_connection *conn, struct s2n_hmac_state *hmac, str
int check = MIN(255, (payload_and_padding_size - 1));
int cutoff = check - padding_length;
- for (int i = 0, j = decrypted->size - 1 - check; i < check && j < decrypted->size; i++, j++) {
+ for (uint32_t i = 0, j = decrypted->size - 1 - check; i < check && j < decrypted->size; i++, j++) {
uint8_t mask = ~(0xff << ((i >= cutoff) * 8));
mismatches |= (decrypted->data[j] ^ padding_length) & mask;
}
- GUARD(s2n_hmac_reset(copy));
-
S2N_ERROR_IF(mismatches, S2N_ERR_CBC_VERIFY);
return 0;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_change_cipher_spec.c b/contrib/restricted/aws/s2n/tls/s2n_change_cipher_spec.c
index 19caaa96a1..99dfdfb22a 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_change_cipher_spec.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_change_cipher_spec.c
@@ -32,7 +32,7 @@ int s2n_basic_ccs_recv(struct s2n_connection *conn)
{
uint8_t type;
- GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &type));
+ POSIX_GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &type));
S2N_ERROR_IF(type != CHANGE_CIPHER_SPEC_TYPE, S2N_ERR_BAD_MESSAGE);
return 0;
@@ -40,14 +40,14 @@ int s2n_basic_ccs_recv(struct s2n_connection *conn)
int s2n_client_ccs_recv(struct s2n_connection *conn)
{
- GUARD(s2n_basic_ccs_recv(conn));
+ POSIX_GUARD(s2n_basic_ccs_recv(conn));
/* Zero the sequence number */
struct s2n_blob seq = {.data = conn->secure.client_sequence_number,.size = sizeof(conn->secure.client_sequence_number) };
- GUARD(s2n_blob_zero(&seq));
+ POSIX_GUARD(s2n_blob_zero(&seq));
/* Compute the finished message */
- GUARD(s2n_prf_client_finished(conn));
+ POSIX_GUARD(s2n_prf_client_finished(conn));
/* Update the client to use the cipher-suite */
conn->client = &conn->secure;
@@ -55,21 +55,21 @@ int s2n_client_ccs_recv(struct s2n_connection *conn)
/* Flush any partial alert messages that were pending.
* If we don't do this, an attacker can inject a 1-byte alert message into the handshake
* and cause later, valid alerts to be processed incorrectly. */
- GUARD(s2n_stuffer_wipe(&conn->alert_in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->alert_in));
return 0;
}
int s2n_server_ccs_recv(struct s2n_connection *conn)
{
- GUARD(s2n_basic_ccs_recv(conn));
+ POSIX_GUARD(s2n_basic_ccs_recv(conn));
/* Zero the sequence number */
struct s2n_blob seq = {.data = conn->secure.server_sequence_number,.size = sizeof(conn->secure.server_sequence_number) };
- GUARD(s2n_blob_zero(&seq));
+ POSIX_GUARD(s2n_blob_zero(&seq));
/* Compute the finished message */
- GUARD(s2n_prf_server_finished(conn));
+ POSIX_GUARD(s2n_prf_server_finished(conn));
/* Update the secure state to active, and point the client at the active state */
conn->server = &conn->secure;
@@ -77,14 +77,14 @@ int s2n_server_ccs_recv(struct s2n_connection *conn)
/* Flush any partial alert messages that were pending.
* If we don't do this, an attacker can inject a 1-byte alert message into the handshake
* and cause later, valid alerts to be processed incorrectly. */
- GUARD(s2n_stuffer_wipe(&conn->alert_in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->alert_in));
return 0;
}
int s2n_ccs_send(struct s2n_connection *conn)
{
- GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, CHANGE_CIPHER_SPEC_TYPE));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, CHANGE_CIPHER_SPEC_TYPE));
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
index 67893009b1..10407f487a 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c
@@ -14,7 +14,7 @@
*/
#include "tls/s2n_cipher_preferences.h"
-#include <s2n.h>
+#include "api/s2n.h"
#include <stdint.h>
#include <strings.h>
#include "tls/s2n_config.h"
@@ -57,6 +57,31 @@ const struct s2n_cipher_preferences cipher_preferences_20190801 = {
.suites = cipher_suites_20190801,
};
+/* Same as 20190801, but with ECDSA for TLS 1.2 added */
+struct s2n_cipher_suite *cipher_suites_20210831[] = {
+ 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,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha
+};
+
+const struct s2n_cipher_preferences cipher_preferences_20210831 = {
+ .count = s2n_array_len(cipher_suites_20210831),
+ .suites = cipher_suites_20210831,
+};
+
/* s2n's list of cipher suites, in order of preference, as of 2014-06-01 */
struct s2n_cipher_suite *cipher_suites_20140601[] = {
&s2n_dhe_rsa_with_aes_128_cbc_sha256,
@@ -311,6 +336,110 @@ const struct s2n_cipher_preferences cipher_preferences_20190214 = {
.suites = cipher_suites_20190214,
};
+/* 20190214 with aes-gcm prioritized above aes-cbc */
+struct s2n_cipher_suite *cipher_suites_20190214_gcm[] = {
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_3des_ede_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_dhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_20190214_gcm = {
+ .count = s2n_array_len(cipher_suites_20190214_gcm),
+ .suites = cipher_suites_20190214_gcm,
+};
+
+/* Same as cipher_suites_20190214, but with TLS 1.3 Ciphers */
+struct s2n_cipher_suite *cipher_suites_20210825[] = {
+ S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_3des_ede_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_dhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_20210825 = {
+ .count = s2n_array_len(cipher_suites_20210825),
+ .suites = cipher_suites_20210825,
+};
+
+/* Same as cipher_suites_20190214_gcm, but with TLS 1.3 Ciphers */
+struct s2n_cipher_suite *cipher_suites_20210825_gcm[] = {
+ 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_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_3des_ede_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_dhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_20210825_gcm = {
+ .count = s2n_array_len(cipher_suites_20210825_gcm),
+ .suites = cipher_suites_20210825_gcm,
+};
+
struct s2n_cipher_suite *cipher_suites_null[] = {
&s2n_null_cipher_suite
};
@@ -348,6 +477,34 @@ const struct s2n_cipher_preferences cipher_preferences_20170328 = {
.suites = cipher_suites_20170328,
};
+/* Equivalent to cipher_suites_20170328 with aes-gcm prioritized above aes-cbc */
+struct s2n_cipher_suite *cipher_suites_20170328_gcm[] = {
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_3des_ede_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_dhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_20170328_gcm = {
+ .count = s2n_array_len(cipher_suites_20170328_gcm),
+ .suites = cipher_suites_20170328_gcm,
+};
+
/* Preferences optimized for FIPS compatibility. */
struct s2n_cipher_suite *cipher_suites_20170405[] = {
&s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
@@ -368,6 +525,26 @@ const struct s2n_cipher_preferences cipher_preferences_20170405 = {
.suites = cipher_suites_20170405,
};
+/* Preferences optimized for FIPS compatibility with GCM prioritized */
+struct s2n_cipher_suite *cipher_suites_20170405_gcm[] = {
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_3des_ede_cbc_sha,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_20170405_gcm = {
+ .count = s2n_array_len(cipher_suites_20170405_gcm),
+ .suites = cipher_suites_20170405_gcm,
+};
+
/* Equivalent to cipher_suite_20160411 with 3DES removed.
* Make a CBC cipher #1 to avoid negotiating GCM with buggy Java clients. */
struct s2n_cipher_suite *cipher_suites_20170718[] = {
@@ -390,6 +567,27 @@ const struct s2n_cipher_preferences cipher_preferences_20170718 = {
.suites = cipher_suites_20170718,
};
+/* Equivalent to cipher_suites_20170718 with aes-gcm prioritized above aes-cbc */
+struct s2n_cipher_suite *cipher_suites_20170718_gcm[] = {
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_20170718_gcm = {
+ .count = s2n_array_len(cipher_suites_20170718_gcm),
+ .suites = cipher_suites_20170718_gcm,
+};
+
struct s2n_cipher_suite *cipher_suites_elb_security_policy_2015_04[] = {
&s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
&s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
@@ -1004,6 +1202,79 @@ const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2021 =
.suites = cipher_suites_cloudfront_tls_1_2_2021,
};
+/* Based on cipher_preferences_cloudfront_tls_1_0_2016, but with ordering changed and AES256-SHA256, DES-CBC3-SHA, and
+ * RC4-MD5 added for compatibility. */
+struct s2n_cipher_suite *cipher_suites_aws_crt_sdk_ssl_v3[] = {
+ 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,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_3des_ede_cbc_sha,
+ &s2n_rsa_with_rc4_128_md5
+};
+
+const struct s2n_cipher_preferences cipher_preferences_aws_crt_sdk_ssl_v3 = {
+ .count = s2n_array_len(cipher_suites_aws_crt_sdk_ssl_v3),
+ .suites = cipher_suites_aws_crt_sdk_ssl_v3,
+};
+
+/* Based on cipher_preferences_cloudfront_tls_1_0_2016, but with ordering changed and AES256-SHA256 added for
+ * compatibility. */
+struct s2n_cipher_suite *cipher_suites_aws_crt_sdk_default[] = {
+ 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,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_aws_crt_sdk_default = {
+ .count = s2n_array_len(cipher_suites_aws_crt_sdk_default),
+ .suites = cipher_suites_aws_crt_sdk_default,
+};
+
+struct s2n_cipher_suite *cipher_suites_aws_crt_sdk_tls_13[] = {
+ S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716
+};
+
+const struct s2n_cipher_preferences cipher_preferences_aws_crt_sdk_tls_13 = {
+ .count = s2n_array_len(cipher_suites_aws_crt_sdk_tls_13),
+ .suites = cipher_suites_aws_crt_sdk_tls_13,
+};
+
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,
@@ -1022,6 +1293,26 @@ const struct s2n_cipher_preferences cipher_preferences_kms_tls_1_0_2018_10 = {
.suites = cipher_suites_kms_tls_1_0_2018_10,
};
+
+struct s2n_cipher_suite *cipher_suites_kms_tls_1_0_2021_08[] = {
+ S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_3des_ede_cbc_sha,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_kms_tls_1_0_2021_08 = {
+ .count = s2n_array_len(cipher_suites_kms_tls_1_0_2021_08),
+ .suites = cipher_suites_kms_tls_1_0_2021_08,
+};
+
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,
@@ -1077,7 +1368,7 @@ const struct s2n_cipher_preferences cipher_preferences_pq_sike_test_tls_1_0_2020
.suites = cipher_suites_pq_sike_test_tls_1_0_2019_11,
};
-/* Includes Both Round 2 and Round 1 PQ Ciphers */
+/* Includes Kyber, BIKE, and SIKE PQ Ciphers */
struct s2n_cipher_suite *cipher_suites_kms_pq_tls_1_0_2020_07[] = {
&s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384,
&s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
@@ -1121,6 +1412,306 @@ const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2020_12 = {
.suites = cipher_suites_pq_tls_1_0_2020_12,
};
+/* Same as ELBSecurityPolicy-TLS-1-1-2017-01, but with PQ Ciphers appended to top of preference list */
+struct s2n_cipher_suite *cipher_suites_pq_tls_1_1_2021_05_17[] = {
+ &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_1_2021_05_17 = {
+ .count = s2n_array_len(cipher_suites_pq_tls_1_1_2021_05_17),
+ .suites = cipher_suites_pq_tls_1_1_2021_05_17,
+};
+
+/* Same as cipher_preferences_20190214, but with PQ Ciphers appended to top of preference list */
+struct s2n_cipher_suite *cipher_suites_pq_tls_1_0_2021_05_18[] = {
+ &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_3des_ede_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_dhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_18 = {
+ .count = s2n_array_len(cipher_suites_pq_tls_1_0_2021_05_18),
+ .suites = cipher_suites_pq_tls_1_0_2021_05_18,
+};
+
+/* Same as ELBSecurityPolicy-2016-08, but with PQ Ciphers appended to top of preference list */
+struct s2n_cipher_suite *cipher_suites_pq_tls_1_0_2021_05_19[] = {
+ &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_19 = {
+ .count = s2n_array_len(cipher_suites_pq_tls_1_0_2021_05_19),
+ .suites = cipher_suites_pq_tls_1_0_2021_05_19,
+};
+
+/* Same as ELBSecurityPolicy-TLS-1-1-2017-01, but with TLS 1.3 and PQ Ciphers appended to top of preference list */
+struct s2n_cipher_suite *cipher_suites_pq_tls_1_1_2021_05_21[] = {
+ /* TLS 1.3 Ciphers don't specify their Key exchange method, allowing for Hybrid PQ KEMs to be negotiated separately */
+ S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716,
+ &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_1_2021_05_21 = {
+ .count = s2n_array_len(cipher_suites_pq_tls_1_1_2021_05_21),
+ .suites = cipher_suites_pq_tls_1_1_2021_05_21,
+};
+
+/* Same as cipher_preferences_20190214, but with TLS 1.3 and PQ Ciphers appended to top of preference list */
+struct s2n_cipher_suite *cipher_suites_pq_tls_1_0_2021_05_22[] = {
+ /* TLS 1.3 Ciphers don't specify their Key exchange method, allowing for Hybrid PQ KEMs to be negotiated separately */
+ S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716,
+ &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_3des_ede_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_dhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_22 = {
+ .count = s2n_array_len(cipher_suites_pq_tls_1_0_2021_05_22),
+ .suites = cipher_suites_pq_tls_1_0_2021_05_22,
+};
+
+/* Same as ELBSecurityPolicy-2016-08, but with TLS 1.3 and PQ Ciphers appended to top of preference list */
+struct s2n_cipher_suite *cipher_suites_pq_tls_1_0_2021_05_23[] = {
+ /* TLS 1.3 Ciphers don't specify their Key exchange method, allowing for Hybrid PQ KEMs to be negotiated separately */
+ S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716,
+ &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_23 = {
+ .count = s2n_array_len(cipher_suites_pq_tls_1_0_2021_05_23),
+ .suites = cipher_suites_pq_tls_1_0_2021_05_23,
+};
+
+/* Same as cipher_preferences_kms_pq_tls_1_0_2020_07, but with TLS 1.3 appended to top of preference list */
+struct s2n_cipher_suite *cipher_suites_pq_tls_1_0_2021_05_24[] = {
+ /* TLS 1.3 Ciphers don't specify their Key exchange method, allowing for Hybrid PQ KEMs to be negotiated separately */
+ S2N_TLS13_CIPHER_SUITES_20190801,
+ &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_3des_ede_cbc_sha,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_24 = {
+ .count = s2n_array_len(cipher_suites_pq_tls_1_0_2021_05_24),
+ .suites = cipher_suites_pq_tls_1_0_2021_05_24,
+};
+
+/* Same as 20190214_gcm, but with PQ Ciphers appended to top of preference list */
+struct s2n_cipher_suite *cipher_suites_pq_tls_1_0_2021_05_25[] = {
+ &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_3des_ede_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_dhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_25 = {
+ .count = s2n_array_len(cipher_suites_pq_tls_1_0_2021_05_25),
+ .suites = cipher_suites_pq_tls_1_0_2021_05_25,
+};
+
+/* Same as 20190214_gcm, but with TLS 1.3 and PQ Ciphers appended to top of preference list */
+struct s2n_cipher_suite *cipher_suites_pq_tls_1_0_2021_05_26[] = {
+ /* TLS 1.3 Ciphers don't specify their Key exchange method, allowing for Hybrid PQ KEMs to be negotiated separately */
+ S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716,
+ &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_rsa_with_aes_128_gcm_sha256,
+ &s2n_rsa_with_aes_256_gcm_sha384,
+ &s2n_rsa_with_aes_128_cbc_sha,
+ &s2n_rsa_with_aes_128_cbc_sha256,
+ &s2n_rsa_with_aes_256_cbc_sha,
+ &s2n_rsa_with_aes_256_cbc_sha256,
+ &s2n_rsa_with_3des_ede_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_dhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_26 = {
+ .count = s2n_array_len(cipher_suites_pq_tls_1_0_2021_05_26),
+ .suites = cipher_suites_pq_tls_1_0_2021_05_26,
+};
+
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,
@@ -1135,4 +1726,44 @@ const struct s2n_cipher_preferences cipher_preferences_kms_fips_tls_1_2_2018_10
.suites = cipher_suites_kms_fips_tls_1_2_2018_10,
};
+struct s2n_cipher_suite *cipher_suites_kms_fips_tls_1_2_2021_08[] = {
+ &s2n_tls13_aes_128_gcm_sha256,
+ &s2n_tls13_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_256_cbc_sha256,
+ &s2n_dhe_rsa_with_aes_128_cbc_sha256,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_kms_fips_tls_1_2_2021_08 = {
+ .count = s2n_array_len(cipher_suites_kms_fips_tls_1_2_2021_08),
+ .suites = cipher_suites_kms_fips_tls_1_2_2021_08,
+};
+
+struct s2n_cipher_suite *cipher_suites_20210816[] = {
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_20210816 = {
+ .count = s2n_array_len(cipher_suites_20210816),
+ .suites = cipher_suites_20210816,
+};
+
+struct s2n_cipher_suite *cipher_suites_20210816_gcm[] = {
+ &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
+ &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
+ &s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
+};
+
+const struct s2n_cipher_preferences cipher_preferences_20210816_gcm = {
+ .count = s2n_array_len(cipher_suites_20210816_gcm),
+ .suites = cipher_suites_20210816_gcm,
+};
+
/* clang-format on */
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h
index 8dabb707ff..7156c68185 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h
@@ -35,13 +35,23 @@ extern const struct s2n_cipher_preferences cipher_preferences_20160804;
extern const struct s2n_cipher_preferences cipher_preferences_20160824;
extern const struct s2n_cipher_preferences cipher_preferences_20170210;
extern const struct s2n_cipher_preferences cipher_preferences_20170328;
+extern const struct s2n_cipher_preferences cipher_preferences_20170328_gcm;
extern const struct s2n_cipher_preferences cipher_preferences_20170405;
+extern const struct s2n_cipher_preferences cipher_preferences_20170405_gcm;
extern const struct s2n_cipher_preferences cipher_preferences_20170718;
+extern const struct s2n_cipher_preferences cipher_preferences_20170718_gcm;
extern const struct s2n_cipher_preferences cipher_preferences_20190214;
+extern const struct s2n_cipher_preferences cipher_preferences_20190214_gcm;
extern const struct s2n_cipher_preferences cipher_preferences_20190801;
extern const struct s2n_cipher_preferences cipher_preferences_20190120;
extern const struct s2n_cipher_preferences cipher_preferences_20190121;
extern const struct s2n_cipher_preferences cipher_preferences_20190122;
+extern const struct s2n_cipher_preferences cipher_preferences_20210816;
+extern const struct s2n_cipher_preferences cipher_preferences_20210816_gcm;
+extern const struct s2n_cipher_preferences cipher_preferences_20210825;
+extern const struct s2n_cipher_preferences cipher_preferences_20210825_gcm;
+extern const struct s2n_cipher_preferences cipher_preferences_20210831;
+
extern const struct s2n_cipher_preferences cipher_preferences_test_all;
extern const struct s2n_cipher_preferences cipher_preferences_test_all_tls12;
@@ -86,15 +96,31 @@ extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_1
extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2018_legacy;
extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2019_legacy;
-extern const struct s2n_cipher_preferences cipher_preferences_kms_tls_1_0_2018_10;
+/* AWS Common Runtime Cipher Preferences */
+extern const struct s2n_cipher_preferences cipher_preferences_aws_crt_sdk_ssl_v3;
+extern const struct s2n_cipher_preferences cipher_preferences_aws_crt_sdk_default;
+extern const struct s2n_cipher_preferences cipher_preferences_aws_crt_sdk_tls_13;
+/* AWS KMS Cipher Preferences */
+extern const struct s2n_cipher_preferences cipher_preferences_kms_tls_1_0_2018_10;
+extern const struct s2n_cipher_preferences cipher_preferences_kms_tls_1_0_2021_08;
+extern const struct s2n_cipher_preferences cipher_preferences_kms_fips_tls_1_2_2018_10;
+extern const struct s2n_cipher_preferences cipher_preferences_kms_fips_tls_1_2_2021_08;
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;
extern const struct s2n_cipher_preferences cipher_preferences_pq_sike_test_tls_1_0_2019_11;
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;
+extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_1_2021_05_17;
+extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_18;
+extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_19;
+extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_1_2021_05_21;
+extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_22;
+extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_23;
+extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_24;
+extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_25;
+extern const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_0_2021_05_26;
-extern const struct s2n_cipher_preferences cipher_preferences_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 ea478e27b8..cf82b7c6f4 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c
@@ -263,7 +263,7 @@ struct s2n_cipher_suite s2n_rsa_with_3des_ede_cbc_sha = /* 0x00,0x0A */ {
struct s2n_cipher_suite s2n_dhe_rsa_with_3des_ede_cbc_sha = /* 0x00,0x16 */ {
.available = 0,
- .name = "EDH-RSA-DES-CBC3-SHA",
+ .name = "DHE-RSA-DES-CBC3-SHA",
.iana_value = { TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA },
.key_exchange_alg = &s2n_dhe,
.auth_method = S2N_AUTHENTICATION_RSA,
@@ -994,6 +994,14 @@ const struct s2n_cipher_preferences cipher_preferences_test_all_tls13 = {
.suites = s2n_all_tls13_cipher_suites,
};
+static bool should_init_crypto = true;
+static bool crypto_initialized = false;
+int s2n_crypto_disable_init(void) {
+ POSIX_ENSURE(!crypto_initialized, S2N_ERR_INITIALIZED);
+ should_init_crypto = false;
+ return S2N_SUCCESS;
+}
+
/* Determines cipher suite availability and selects record algorithms */
int s2n_cipher_suites_init(void)
{
@@ -1026,7 +1034,7 @@ int s2n_cipher_suites_init(void)
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) };
struct s2n_blob new_suite_mem = { 0 };
- GUARD(s2n_dup(&cur_suite_mem, &new_suite_mem));
+ POSIX_GUARD(s2n_dup(&cur_suite_mem, &new_suite_mem));
struct s2n_cipher_suite *new_suite = (struct s2n_cipher_suite *)(void *)new_suite_mem.data;
new_suite->available = 1;
@@ -1037,14 +1045,18 @@ int s2n_cipher_suites_init(void)
}
}
+ if (should_init_crypto) {
#if !S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)
- /*https://wiki.openssl.org/index.php/Manual:OpenSSL_add_all_algorithms(3)*/
- OpenSSL_add_all_algorithms();
+ /*https://wiki.openssl.org/index.php/Manual:OpenSSL_add_all_algorithms(3)*/
+ OpenSSL_add_all_algorithms();
#else
- OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
#endif
+ }
- return 0;
+ crypto_initialized = true;
+
+ return S2N_SUCCESS;
}
/* Reset any selected record algorithms */
@@ -1058,96 +1070,93 @@ int s2n_cipher_suites_cleanup(void)
/* Release custom SSLv3 cipher suites */
if (cur_suite->sslv3_cipher_suite != cur_suite) {
- GUARD(s2n_free_object((uint8_t **)&cur_suite->sslv3_cipher_suite, sizeof(struct s2n_cipher_suite)));
+ POSIX_GUARD(s2n_free_object((uint8_t **)&cur_suite->sslv3_cipher_suite, sizeof(struct s2n_cipher_suite)));
}
cur_suite->sslv3_cipher_suite = NULL;
}
+ if (should_init_crypto) {
#if !S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)
- /*https://wiki.openssl.org/index.php/Manual:OpenSSL_add_all_algorithms(3)*/
- EVP_cleanup();
+ /*https://wiki.openssl.org/index.php/Manual:OpenSSL_add_all_algorithms(3)*/
+ EVP_cleanup();
- /* per the reqs here https://www.openssl.org/docs/man1.1.0/crypto/OPENSSL_init_crypto.html we don't explicitly call
- * cleanup in later versions */
+ /* per the reqs here https://www.openssl.org/docs/man1.1.0/crypto/OPENSSL_init_crypto.html we don't explicitly call
+ * cleanup in later versions */
#endif
+ }
return 0;
}
-struct s2n_cipher_suite *s2n_cipher_suite_from_wire(const uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN])
+S2N_RESULT s2n_cipher_suite_from_iana(const uint8_t iana[static S2N_TLS_CIPHER_SUITE_LEN], struct s2n_cipher_suite **cipher_suite)
{
+ RESULT_ENSURE_REF(cipher_suite);
+ *cipher_suite = NULL;
+ RESULT_ENSURE_REF(iana);
+
int low = 0;
- int top = (sizeof(s2n_all_cipher_suites) / sizeof(struct s2n_cipher_suite *)) - 1;
+ int top = s2n_array_len(s2n_all_cipher_suites) - 1;
+
/* Perform a textbook binary search */
while (low <= top) {
/* Check in the middle */
- int mid = low + ((top - low) / 2);
- int m = memcmp(s2n_all_cipher_suites[mid]->iana_value, cipher_suite, 2);
+ size_t mid = low + ((top - low) / 2);
+ int m = memcmp(s2n_all_cipher_suites[mid]->iana_value, iana, S2N_TLS_CIPHER_SUITE_LEN);
if (m == 0) {
- return s2n_all_cipher_suites[mid];
+ *cipher_suite = s2n_all_cipher_suites[mid];
+ return S2N_RESULT_OK;
} else if (m > 0) {
top = mid - 1;
} else if (m < 0) {
low = mid + 1;
}
}
-
- return NULL;
+ RESULT_BAIL(S2N_ERR_CIPHER_NOT_SUPPORTED);
}
int s2n_set_cipher_as_client(struct s2n_connection *conn, uint8_t wire[S2N_TLS_CIPHER_SUITE_LEN])
{
- notnull_check(conn);
- notnull_check(conn->secure.cipher_suite);
- struct s2n_cipher_suite *cipher_suite;
-
- /* See if the cipher is one we support */
- 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.
- * */
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite);
+
+ const struct s2n_security_policy *security_policy;
+ POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
+ POSIX_ENSURE_REF(security_policy);
+
+ struct s2n_cipher_suite *cipher_suite = NULL;
+ for (size_t i = 0; i < security_policy->cipher_preferences->count; i++) {
+ const uint8_t *ours = security_policy->cipher_preferences->suites[i]->iana_value;
+ if (memcmp(wire, ours, S2N_TLS_CIPHER_SUITE_LEN) == 0) {
+ cipher_suite = security_policy->cipher_preferences->suites[i];
+ break;
+ }
+ }
+ POSIX_ENSURE(cipher_suite != NULL, S2N_ERR_CIPHER_NOT_SUPPORTED);
+ POSIX_ENSURE(cipher_suite->available, S2N_ERR_CIPHER_NOT_SUPPORTED);
+
+ /** Clients MUST verify
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.11
+ *# that the server selected a cipher suite
+ *# indicating a Hash associated with the PSK
+ **/
if (conn->psk_params.chosen_psk) {
- ENSURE_POSIX(cipher_suite->prf_alg == conn->psk_params.chosen_psk->hmac_alg,
+ POSIX_ENSURE(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);
+ POSIX_ENSURE(conn->secure.cipher_suite->iana_value == cipher_suite->iana_value, S2N_ERR_CIPHER_NOT_SUPPORTED);
return S2N_SUCCESS;
}
- conn->secure.cipher_suite = cipher_suite;
-
- /* Verify the cipher was part of the originally offered list */
- const struct s2n_cipher_preferences *cipher_prefs;
- GUARD(s2n_connection_get_cipher_preferences(conn, &cipher_prefs));
-
- uint8_t found = 0;
-
- for (int i = 0; i < cipher_prefs->count; i++ ) {
- /* The client sends all "available" ciphers in the preference list to the server.
- The server must pick one of the ciphers offered by the client. */
- if (cipher_prefs->suites[i]->available) {
- const uint8_t *server_iana_value = conn->secure.cipher_suite->iana_value;
- const uint8_t *client_iana_value = cipher_prefs->suites[i]->iana_value;
-
- if (memcmp(server_iana_value, client_iana_value, S2N_TLS_CIPHER_SUITE_LEN) == 0) {
- found = 1;
- break;
- }
- }
- }
- S2N_ERROR_IF(found != 1, S2N_ERR_CIPHER_NOT_SUPPORTED);
+ conn->secure.cipher_suite = cipher_suite;
/* For SSLv3 use SSLv3-specific ciphers */
if (conn->actual_protocol_version == S2N_SSLv3) {
conn->secure.cipher_suite = conn->secure.cipher_suite->sslv3_cipher_suite;
- notnull_check(conn->secure.cipher_suite);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite);
}
return 0;
@@ -1155,7 +1164,7 @@ int s2n_set_cipher_as_client(struct s2n_connection *conn, uint8_t wire[S2N_TLS_C
static int s2n_wire_ciphers_contain(const uint8_t *match, const uint8_t *wire, uint32_t count, uint32_t cipher_suite_len)
{
- for (int i = 0; i < count; i++) {
+ for (uint32_t i = 0; i < count; i++) {
const uint8_t *theirs = wire + (i * cipher_suite_len) + (cipher_suite_len - S2N_TLS_CIPHER_SUITE_LEN);
if (!memcmp(match, theirs, S2N_TLS_CIPHER_SUITE_LEN)) {
@@ -1179,7 +1188,7 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire,
uint8_t fallback_scsv[S2N_TLS_CIPHER_SUITE_LEN] = { TLS_FALLBACK_SCSV };
if (s2n_wire_ciphers_contain(fallback_scsv, wire, count, cipher_suite_len)) {
conn->closed = 1;
- S2N_ERROR(S2N_ERR_FALLBACK_DETECTED);
+ POSIX_BAIL(S2N_ERR_FALLBACK_DETECTED);
}
}
@@ -1189,7 +1198,7 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire,
}
const struct s2n_security_policy *security_policy;
- GUARD(s2n_connection_get_security_policy(conn, &security_policy));
+ POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
/* s2n supports only server order */
for (int i = 0; i < security_policy->cipher_preferences->count; i++) {
@@ -1197,7 +1206,7 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire,
if (s2n_wire_ciphers_contain(ours, wire, count, cipher_suite_len)) {
/* We have a match */
- struct s2n_cipher_suite *match = s2n_cipher_suite_from_wire(ours);
+ struct s2n_cipher_suite *match = security_policy->cipher_preferences->suites[i];
/* Never use TLS1.3 ciphers on a pre-TLS1.3 connection, and vice versa */
if ((conn->actual_protocol_version >= S2N_TLS13) != (match->minimum_required_tls_version >= S2N_TLS13)) {
@@ -1223,7 +1232,7 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire,
if (match->minimum_required_tls_version < S2N_TLS13) {
/* If the kex is not supported continue to the next candidate */
bool kex_supported = false;
- GUARD_AS_POSIX(s2n_kex_supported(match, conn, &kex_supported));
+ POSIX_GUARD_RESULT(s2n_kex_supported(match, conn, &kex_supported));
if (!kex_supported) {
continue;
}
@@ -1264,7 +1273,7 @@ static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire,
return S2N_SUCCESS;
}
- S2N_ERROR(S2N_ERR_CIPHER_NOT_SUPPORTED);
+ POSIX_BAIL(S2N_ERR_CIPHER_NOT_SUPPORTED);
}
int s2n_set_cipher_as_sslv2_server(struct s2n_connection *conn, uint8_t *wire, uint16_t count)
@@ -1276,3 +1285,34 @@ int s2n_set_cipher_as_tls_server(struct s2n_connection *conn, uint8_t *wire, uin
{
return s2n_set_cipher_as_server(conn, wire, count, S2N_TLS_CIPHER_SUITE_LEN);
}
+
+bool s2n_cipher_suite_requires_ecc_extension(struct s2n_cipher_suite *cipher)
+{
+ if(!cipher) {
+ return false;
+ }
+
+ /* TLS1.3 does not include key exchange algorithms in its cipher suites,
+ * but the elliptic curves extension is always required. */
+ if (cipher->minimum_required_tls_version >= S2N_TLS13) {
+ return true;
+ }
+
+ if (s2n_kex_includes(cipher->key_exchange_alg, &s2n_ecdhe)) {
+ return true;
+ }
+
+ return false;
+}
+
+bool s2n_cipher_suite_requires_pq_extension(struct s2n_cipher_suite *cipher)
+{
+ if(!cipher) {
+ return false;
+ }
+
+ if (s2n_kex_includes(cipher->key_exchange_alg, &s2n_kem)) {
+ return true;
+ }
+ return false;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
index 2bee39ec4c..74a388a9b4 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h
@@ -32,10 +32,9 @@
#define S2N_MAX_POSSIBLE_RECORD_ALGS 2
-/* Kept up-to-date by s2n_cipher_suite_match_test */
+/* Kept up-to-date by s2n_cipher_suite_test */
#define S2N_CIPHER_SUITE_COUNT 39
-
/* Record algorithm flags that can be OR'ed */
#define S2N_TLS12_AES_GCM_AEAD_NONCE 0x01
#define S2N_TLS12_CHACHA_POLY_AEAD_NONCE 0x02
@@ -84,6 +83,8 @@ extern const struct s2n_record_algorithm s2n_record_alg_aes256_sha384;
extern const struct s2n_record_algorithm s2n_record_alg_aes128_gcm;
extern const struct s2n_record_algorithm s2n_record_alg_aes256_gcm;
extern const struct s2n_record_algorithm s2n_record_alg_chacha20_poly1305;
+extern const struct s2n_record_algorithm s2n_tls13_record_alg_aes128_gcm;
+extern const struct s2n_record_algorithm s2n_tls13_record_alg_chacha20_poly1305;
struct s2n_cipher_suite {
/* Is there an implementation available? Set in s2n_cipher_suites_init() */
@@ -161,7 +162,9 @@ extern struct s2n_cipher_suite s2n_tls13_chacha20_poly1305_sha256;
extern int s2n_cipher_suites_init(void);
extern int s2n_cipher_suites_cleanup(void);
-extern struct s2n_cipher_suite *s2n_cipher_suite_from_wire(const uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN]);
+S2N_RESULT s2n_cipher_suite_from_iana(const uint8_t iana[S2N_TLS_CIPHER_SUITE_LEN], struct s2n_cipher_suite **cipher_suite);
extern int s2n_set_cipher_as_client(struct s2n_connection *conn, uint8_t wire[S2N_TLS_CIPHER_SUITE_LEN]);
extern int s2n_set_cipher_as_sslv2_server(struct s2n_connection *conn, uint8_t * wire, uint16_t count);
extern int s2n_set_cipher_as_tls_server(struct s2n_connection *conn, uint8_t * wire, uint16_t count);
+bool s2n_cipher_suite_requires_ecc_extension(struct s2n_cipher_suite *cipher);
+bool s2n_cipher_suite_requires_pq_extension(struct s2n_cipher_suite *cipher);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_cert.c b/contrib/restricted/aws/s2n/tls/s2n_client_cert.c
index 7dde226788..757b13430d 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_cert.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_cert.c
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-#include <s2n.h>
+#include "api/s2n.h"
#include "crypto/s2n_certificate.h"
#include "error/s2n_errno.h"
@@ -27,32 +27,97 @@
#include "utils/s2n_blob.h"
#include "utils/s2n_safety.h"
+/* In TLS1.2, the certificate list is just an opaque vector of certificates:
+ *
+ * opaque ASN.1Cert<1..2^24-1>;
+ *
+ * struct {
+ * ASN.1Cert certificate_list<0..2^24-1>;
+ * } Certificate;
+ *
+ * This construction allowed us to store the entire certificate_list blob
+ * and return it from the s2n_connection_get_client_cert_chain method for
+ * customers to examine.
+ *
+ * However, TLS1.3 introduced per-certificate extensions:
+ *
+ * struct {
+ * opaque cert_data<1..2^24-1>;
+ * ----> Extension extensions<0..2^16-1>; <----
+ * } CertificateEntry;
+ *
+ * struct {
+ * opaque certificate_request_context<0..2^8-1>;
+ * CertificateEntry certificate_list<0..2^24-1>;
+ * } Certificate;
+ *
+ * So in order to store / return the certificates in the same format as in TLS1.2,
+ * we need to first strip out the extensions.
+ */
+static S2N_RESULT s2n_client_cert_chain_store(struct s2n_connection *conn, struct s2n_blob *client_cert_chain)
+{
+ RESULT_ENSURE_REF(conn);
+
+ /* Earlier versions are a basic copy */
+ if (conn->actual_protocol_version < S2N_TLS13) {
+ RESULT_GUARD_POSIX(s2n_dup(client_cert_chain, &conn->handshake_params.client_cert_chain));
+ return S2N_RESULT_OK;
+ }
+
+ struct s2n_stuffer cert_chain_in = { 0 };
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&cert_chain_in, client_cert_chain));
+ RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&cert_chain_in, client_cert_chain->size));
+
+ struct s2n_stuffer cert_chain_out = { 0 };
+ RESULT_GUARD_POSIX(s2n_realloc(&conn->handshake_params.client_cert_chain, client_cert_chain->size));
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&cert_chain_out, &conn->handshake_params.client_cert_chain));
+
+ uint32_t cert_size = 0;
+ uint16_t extensions_size = 0;
+ while(s2n_stuffer_data_available(&cert_chain_in)) {
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint24(&cert_chain_in, &cert_size));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint24(&cert_chain_out, cert_size));
+ RESULT_GUARD_POSIX(s2n_stuffer_copy(&cert_chain_in, &cert_chain_out, cert_size));
+
+ /* The new TLS1.3 format includes extensions, which we must skip.
+ * Customers will not expect TLS extensions in a DER-encoded certificate.
+ */
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(&cert_chain_in, &extensions_size));
+ RESULT_GUARD_POSIX(s2n_stuffer_skip_read(&cert_chain_in, extensions_size));
+ }
+
+ /* We will have allocated more memory than actually necessary.
+ * If this becomes a problem, we should consider reallocing the correct amount of memory here.
+ */
+ conn->handshake_params.client_cert_chain.size = s2n_stuffer_data_available(&cert_chain_out);
+ return S2N_RESULT_OK;
+}
int s2n_client_cert_recv(struct s2n_connection *conn)
{
if (conn->actual_protocol_version == S2N_TLS13) {
uint8_t certificate_request_context_len;
- GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &certificate_request_context_len));
+ POSIX_GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &certificate_request_context_len));
S2N_ERROR_IF(certificate_request_context_len != 0,S2N_ERR_BAD_MESSAGE);
}
struct s2n_stuffer *in = &conn->handshake.io;
struct s2n_blob client_cert_chain = {0};
- GUARD(s2n_stuffer_read_uint24(in, &client_cert_chain.size));
+ POSIX_GUARD(s2n_stuffer_read_uint24(in, &client_cert_chain.size));
S2N_ERROR_IF(client_cert_chain.size > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE);
if (client_cert_chain.size == 0) {
- GUARD(s2n_conn_set_handshake_no_client_cert(conn));
+ POSIX_GUARD(s2n_conn_set_handshake_no_client_cert(conn));
return 0;
}
client_cert_chain.data = s2n_stuffer_raw_read(in, client_cert_chain.size);
- notnull_check(client_cert_chain.data);
+ POSIX_ENSURE_REF(client_cert_chain.data);
s2n_cert_public_key public_key;
- GUARD(s2n_pkey_zero_init(&public_key));
+ POSIX_GUARD(s2n_pkey_zero_init(&public_key));
s2n_pkey_type pkey_type;
@@ -61,14 +126,14 @@ int s2n_client_cert_recv(struct s2n_connection *conn)
client_cert_chain.data, client_cert_chain.size,
&pkey_type, &public_key) != S2N_CERT_OK, S2N_ERR_CERT_UNTRUSTED);
- conn->secure.client_cert_pkey_type = pkey_type;
- GUARD(s2n_pkey_setup_for_type(&public_key, pkey_type));
-
- GUARD(s2n_pkey_check_key_exists(&public_key));
- GUARD(s2n_dup(&client_cert_chain, &conn->secure.client_cert_chain));
- conn->secure.client_public_key = public_key;
+ conn->handshake_params.client_cert_pkey_type = pkey_type;
+ POSIX_GUARD(s2n_pkey_setup_for_type(&public_key, pkey_type));
- return 0;
+ POSIX_GUARD(s2n_pkey_check_key_exists(&public_key));
+ POSIX_GUARD_RESULT(s2n_client_cert_chain_store(conn, &client_cert_chain));
+ conn->handshake_params.client_public_key = public_key;
+
+ return S2N_SUCCESS;
}
@@ -76,7 +141,7 @@ int s2n_client_cert_send(struct s2n_connection *conn)
{
struct s2n_cert_chain_and_key *chain_and_key = conn->handshake_params.our_chain_and_key;
- if (conn->actual_protocol_version == S2N_TLS13) {
+ if (conn->actual_protocol_version >= S2N_TLS13) {
/* If this message is in response to a CertificateRequest, the value of
* certificate_request_context in that message.
* https://tools.ietf.org/html/rfc8446#section-4.4.2
@@ -85,15 +150,15 @@ int s2n_client_cert_send(struct s2n_connection *conn)
* https://tools.ietf.org/html/rfc8446#section-4.3.2
*/
uint8_t certificate_request_context_len = 0;
- GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, certificate_request_context_len));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, certificate_request_context_len));
}
if (chain_and_key == NULL) {
- GUARD(s2n_conn_set_handshake_no_client_cert(conn));
- GUARD(s2n_send_empty_cert_chain(&conn->handshake.io));
+ POSIX_GUARD(s2n_conn_set_handshake_no_client_cert(conn));
+ POSIX_GUARD(s2n_send_empty_cert_chain(&conn->handshake.io));
return 0;
}
- GUARD(s2n_send_cert_chain(conn, &conn->handshake.io, chain_and_key));
- return 0;
+ POSIX_GUARD(s2n_send_cert_chain(conn, &conn->handshake.io, chain_and_key));
+ return S2N_SUCCESS;
}
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 b11150c48c..5327b5bc7e 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-#include <s2n.h>
+#include "api/s2n.h"
#include "error/s2n_errno.h"
@@ -25,68 +25,78 @@
#include "stuffer/s2n_stuffer.h"
#include "utils/s2n_safety.h"
+#include "tls/s2n_async_pkey.h"
+static int s2n_client_cert_verify_send_complete(struct s2n_connection *conn, struct s2n_blob *signature);
int s2n_client_cert_verify_recv(struct s2n_connection *conn)
{
+ POSIX_ENSURE_REF(conn);
+ struct s2n_handshake_hashes *hashes = conn->handshake.hashes;
+ POSIX_ENSURE_REF(hashes);
+
struct s2n_stuffer *in = &conn->handshake.io;
- struct s2n_signature_scheme chosen_sig_scheme = s2n_rsa_pkcs1_md5_sha1;
+ struct s2n_signature_scheme *chosen_sig_scheme = &conn->handshake_params.client_cert_sig_scheme;
- if(conn->actual_protocol_version >= S2N_TLS12){
+ if (conn->actual_protocol_version < S2N_TLS12) {
+ POSIX_GUARD(s2n_choose_default_sig_scheme(conn, chosen_sig_scheme, S2N_CLIENT));
+ } else {
/* Verify the SigScheme picked by the Client was in the preference list we sent (or is the default SigScheme) */
- GUARD(s2n_get_and_validate_negotiated_signature_scheme(conn, in, &chosen_sig_scheme));
+ POSIX_GUARD(s2n_get_and_validate_negotiated_signature_scheme(conn, in, chosen_sig_scheme));
}
+
uint16_t signature_size;
struct s2n_blob signature = {0};
- GUARD(s2n_stuffer_read_uint16(in, &signature_size));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &signature_size));
signature.size = signature_size;
signature.data = s2n_stuffer_raw_read(in, signature.size);
- notnull_check(signature.data);
+ POSIX_ENSURE_REF(signature.data);
/* Use a copy of the hash state since the verify digest computation may modify the running hash state we need later. */
- struct s2n_hash_state hash_state = {0};
- GUARD(s2n_handshake_get_hash_state(conn, chosen_sig_scheme.hash_alg, &hash_state));
- GUARD(s2n_hash_copy(&conn->handshake.ccv_hash_copy, &hash_state));
+ struct s2n_hash_state *hash_state = &hashes->hash_workspace;
+ POSIX_GUARD_RESULT(s2n_handshake_copy_hash_state(conn, chosen_sig_scheme->hash_alg, hash_state));
/* Verify the signature */
- GUARD(s2n_pkey_verify(&conn->secure.client_public_key, chosen_sig_scheme.sig_alg, &conn->handshake.ccv_hash_copy, &signature));
+ POSIX_GUARD(s2n_pkey_verify(&conn->handshake_params.client_public_key, chosen_sig_scheme->sig_alg, hash_state, &signature));
/* Client certificate has been verified. Minimize required handshake hash algs */
- GUARD(s2n_conn_update_required_handshake_hashes(conn));
+ POSIX_GUARD(s2n_conn_update_required_handshake_hashes(conn));
- return 0;
+ return S2N_SUCCESS;
}
int s2n_client_cert_verify_send(struct s2n_connection *conn)
{
- struct s2n_stuffer *out = &conn->handshake.io;
+ POSIX_ENSURE_REF(conn);
+ struct s2n_handshake_hashes *hashes = conn->handshake.hashes;
+ POSIX_ENSURE_REF(hashes);
- struct s2n_signature_scheme chosen_sig_scheme = s2n_rsa_pkcs1_md5_sha1;
+ S2N_ASYNC_PKEY_GUARD(conn);
+ struct s2n_stuffer *out = &conn->handshake.io;
- if (conn->actual_protocol_version >= S2N_TLS12) {
- chosen_sig_scheme = conn->secure.client_cert_sig_scheme;
- GUARD(s2n_stuffer_write_uint16(out, conn->secure.client_cert_sig_scheme.iana_value));
+ struct s2n_signature_scheme *chosen_sig_scheme = &conn->handshake_params.client_cert_sig_scheme;
+ if (conn->actual_protocol_version < S2N_TLS12) {
+ POSIX_GUARD(s2n_choose_default_sig_scheme(conn, chosen_sig_scheme, S2N_CLIENT));
+ } else {
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, conn->handshake_params.client_cert_sig_scheme.iana_value));
}
/* Use a copy of the hash state since the verify digest computation may modify the running hash state we need later. */
- struct s2n_hash_state hash_state = {0};
- GUARD(s2n_handshake_get_hash_state(conn, chosen_sig_scheme.hash_alg, &hash_state));
- GUARD(s2n_hash_copy(&conn->handshake.ccv_hash_copy, &hash_state));
+ struct s2n_hash_state *hash_state = &hashes->hash_workspace;
+ POSIX_GUARD_RESULT(s2n_handshake_copy_hash_state(conn, chosen_sig_scheme->hash_alg, hash_state));
- 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 = 0;
- GUARD_AS_POSIX(s2n_pkey_size(cert_chain_and_key->private_key, &max_signature_size));
- GUARD(s2n_alloc(&signature, max_signature_size));
+ S2N_ASYNC_PKEY_SIGN(conn, chosen_sig_scheme->sig_alg, hash_state, s2n_client_cert_verify_send_complete);
+}
- GUARD(s2n_pkey_sign(cert_chain_and_key->private_key, chosen_sig_scheme.sig_alg, &conn->handshake.ccv_hash_copy, &signature));
+static int s2n_client_cert_verify_send_complete(struct s2n_connection *conn, struct s2n_blob *signature)
+{
+ struct s2n_stuffer *out = &conn->handshake.io;
- GUARD(s2n_stuffer_write_uint16(out, signature.size));
- GUARD(s2n_stuffer_write(out, &signature));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, signature->size));
+ POSIX_GUARD(s2n_stuffer_write(out, signature));
/* Client certificate has been verified. Minimize required handshake hash algs */
- GUARD(s2n_conn_update_required_handshake_hashes(conn));
+ POSIX_GUARD(s2n_conn_update_required_handshake_hashes(conn));
- return 0;
+ return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_finished.c b/contrib/restricted/aws/s2n/tls/s2n_client_finished.c
index cc85970145..871e7db15f 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_finished.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_finished.c
@@ -30,7 +30,7 @@ int s2n_client_finished_recv(struct s2n_connection *conn)
uint8_t *our_version;
our_version = conn->handshake.client_finished;
uint8_t *their_version = s2n_stuffer_raw_read(&conn->handshake.io, S2N_TLS_FINISHED_LEN);
- notnull_check(their_version);
+ POSIX_ENSURE_REF(their_version);
S2N_ERROR_IF(!s2n_constant_time_equals(our_version, their_version, S2N_TLS_FINISHED_LEN) || conn->handshake.rsa_failed, S2N_ERR_BAD_MESSAGE);
@@ -40,25 +40,25 @@ int s2n_client_finished_recv(struct s2n_connection *conn)
int s2n_client_finished_send(struct s2n_connection *conn)
{
uint8_t *our_version;
- GUARD(s2n_prf_client_finished(conn));
+ POSIX_GUARD(s2n_prf_client_finished(conn));
struct s2n_blob seq = {.data = conn->secure.client_sequence_number,.size = sizeof(conn->secure.client_sequence_number) };
- GUARD(s2n_blob_zero(&seq));
+ POSIX_GUARD(s2n_blob_zero(&seq));
our_version = conn->handshake.client_finished;
/* Update the server to use the cipher suite */
conn->client = &conn->secure;
if (conn->actual_protocol_version == S2N_SSLv3) {
- GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, our_version, S2N_SSL_FINISHED_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, our_version, S2N_SSL_FINISHED_LEN));
} else {
- GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, our_version, S2N_TLS_FINISHED_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, our_version, S2N_TLS_FINISHED_LEN));
}
return 0;
}
int s2n_tls13_client_finished_recv(struct s2n_connection *conn) {
- eq_check(conn->actual_protocol_version, S2N_TLS13);
+ POSIX_ENSURE_EQ(conn->actual_protocol_version, S2N_TLS13);
uint8_t length = s2n_stuffer_data_available(&conn->handshake.io);
S2N_ERROR_IF(length == 0, S2N_ERR_BAD_MESSAGE);
@@ -71,40 +71,42 @@ int s2n_tls13_client_finished_recv(struct s2n_connection *conn) {
s2n_tls13_connection_keys(keys, conn);
/* get transcript hash */
- struct s2n_hash_state hash_state = {0};
- GUARD(s2n_handshake_get_hash_state(conn, keys.hash_algorithm, &hash_state));
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+ struct s2n_hash_state *hash_state = &conn->handshake.hashes->hash_workspace;
+ POSIX_GUARD_RESULT(s2n_handshake_copy_hash_state(conn, keys.hash_algorithm, hash_state));
struct s2n_blob finished_key = {0};
- GUARD(s2n_blob_init(&finished_key, conn->handshake.client_finished, keys.size));
+ POSIX_GUARD(s2n_blob_init(&finished_key, conn->handshake.client_finished, keys.size));
s2n_tls13_key_blob(client_finished_mac, keys.size);
- GUARD(s2n_tls13_calculate_finished_mac(&keys, &finished_key, &hash_state, &client_finished_mac));
+ POSIX_GUARD(s2n_tls13_calculate_finished_mac(&keys, &finished_key, hash_state, &client_finished_mac));
- GUARD(s2n_tls13_mac_verify(&keys, &client_finished_mac, &wire_finished_mac));
+ POSIX_GUARD(s2n_tls13_mac_verify(&keys, &client_finished_mac, &wire_finished_mac));
return 0;
}
int s2n_tls13_client_finished_send(struct s2n_connection *conn) {
- eq_check(conn->actual_protocol_version, S2N_TLS13);
+ POSIX_ENSURE_EQ(conn->actual_protocol_version, S2N_TLS13);
/* get tls13 keys */
s2n_tls13_connection_keys(keys, conn);
/* get transcript hash */
- struct s2n_hash_state hash_state = {0};
- GUARD(s2n_handshake_get_hash_state(conn, keys.hash_algorithm, &hash_state));
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+ struct s2n_hash_state *hash_state = &conn->handshake.hashes->hash_workspace;
+ POSIX_GUARD_RESULT(s2n_handshake_copy_hash_state(conn, keys.hash_algorithm, hash_state));
/* look up finished secret key */
struct s2n_blob finished_key = {0};
- GUARD(s2n_blob_init(&finished_key, conn->handshake.client_finished, keys.size));
+ POSIX_GUARD(s2n_blob_init(&finished_key, conn->handshake.client_finished, keys.size));
/* generate the hashed message authenticated code */
s2n_stack_blob(client_finished_mac, keys.size, S2N_TLS13_SECRET_MAX_LEN);
- GUARD(s2n_tls13_calculate_finished_mac(&keys, &finished_key, &hash_state, &client_finished_mac));
+ POSIX_GUARD(s2n_tls13_calculate_finished_mac(&keys, &finished_key, hash_state, &client_finished_mac));
/* write to handshake io */
- GUARD(s2n_stuffer_write(&conn->handshake.io, &client_finished_mac));
+ POSIX_GUARD(s2n_stuffer_write(&conn->handshake.io, &client_finished_mac));
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
index b03cda1491..0bcec3501a 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c
@@ -21,8 +21,8 @@
#include "crypto/s2n_fips.h"
#include "error/s2n_errno.h"
-
#include "crypto/s2n_hash.h"
+#include "crypto/s2n_rsa_signing.h"
#include "tls/extensions/s2n_extension_list.h"
#include "tls/extensions/s2n_server_key_share.h"
@@ -33,9 +33,9 @@
#include "tls/s2n_connection.h"
#include "tls/s2n_client_hello.h"
#include "tls/s2n_alerts.h"
+#include "tls/s2n_handshake_type.h"
#include "tls/s2n_signature_algorithms.h"
#include "tls/s2n_tls.h"
-#include "tls/s2n_tls_digest_preferences.h"
#include "tls/s2n_security_policies.h"
#include "stuffer/s2n_stuffer.h"
@@ -45,7 +45,7 @@
#include "utils/s2n_safety.h"
struct s2n_client_hello *s2n_connection_get_client_hello(struct s2n_connection *conn) {
- if (conn->client_hello.parsed != 1) {
+ if (conn->client_hello.callback_invoked != 1) {
return NULL;
}
@@ -58,8 +58,8 @@ static uint32_t min_size(struct s2n_blob *blob, uint32_t max_length) {
static S2N_RESULT s2n_generate_client_session_id(struct s2n_connection *conn)
{
- ENSURE_REF(conn);
- ENSURE_REF(conn->config);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->config);
/* Session id already generated - no-op */
if (conn->session_id_len) {
@@ -71,115 +71,135 @@ static S2N_RESULT s2n_generate_client_session_id(struct s2n_connection *conn)
return S2N_RESULT_OK;
}
- /* Generate the session id for TLS1.3 if in middlebox compatibility mode.
- * For now, we default to middlebox compatibility mode unless using QUIC. */
- if (conn->config->quic_enabled) {
+ /* Only generate the session id for TLS1.3 if in middlebox compatibility mode */
+ if (conn->client_protocol_version >= S2N_TLS13 && !s2n_is_middlebox_compat_enabled(conn)) {
return S2N_RESULT_OK;
}
struct s2n_blob session_id = {0};
- GUARD_AS_RESULT(s2n_blob_init(&session_id, conn->session_id, S2N_TLS_SESSION_ID_MAX_LEN));
- GUARD_RESULT(s2n_get_public_random_data(&session_id));
+ RESULT_GUARD_POSIX(s2n_blob_init(&session_id, conn->session_id, S2N_TLS_SESSION_ID_MAX_LEN));
+ RESULT_GUARD(s2n_get_public_random_data(&session_id));
conn->session_id_len = S2N_TLS_SESSION_ID_MAX_LEN;
return S2N_RESULT_OK;
}
ssize_t s2n_client_hello_get_raw_message_length(struct s2n_client_hello *ch) {
- notnull_check(ch);
+ POSIX_ENSURE_REF(ch);
return ch->raw_message.blob.size;
}
ssize_t s2n_client_hello_get_raw_message(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length)
{
- notnull_check(ch);
- notnull_check(out);
+ POSIX_ENSURE_REF(ch);
+ POSIX_ENSURE_REF(out);
uint32_t len = min_size(&ch->raw_message.blob, max_length);
struct s2n_stuffer *raw_message = &ch->raw_message;
- GUARD(s2n_stuffer_reread(raw_message));
- GUARD(s2n_stuffer_read_bytes(raw_message, out, len));
+ POSIX_GUARD(s2n_stuffer_reread(raw_message));
+ POSIX_GUARD(s2n_stuffer_read_bytes(raw_message, out, len));
return len;
}
ssize_t s2n_client_hello_get_cipher_suites_length(struct s2n_client_hello *ch) {
- notnull_check(ch);
+ POSIX_ENSURE_REF(ch);
return ch->cipher_suites.size;
}
+int s2n_client_hello_cb_done(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->config);
+ POSIX_ENSURE(conn->config->client_hello_cb_mode ==
+ S2N_CLIENT_HELLO_CB_NONBLOCKING, S2N_ERR_INVALID_STATE);
+ POSIX_ENSURE(conn->client_hello.callback_invoked == 1, S2N_ERR_ASYNC_NOT_PERFORMED);
+ POSIX_ENSURE(conn->client_hello.parsed == 1, S2N_ERR_INVALID_STATE);
+
+ conn->client_hello.callback_async_blocked = 0;
+ conn->client_hello.callback_async_done = 1;
+
+ return S2N_SUCCESS;
+}
+
ssize_t s2n_client_hello_get_cipher_suites(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length)
{
- notnull_check(ch);
- notnull_check(out);
- notnull_check(ch->cipher_suites.data);
+ POSIX_ENSURE_REF(ch);
+ POSIX_ENSURE_REF(out);
+ POSIX_ENSURE_REF(ch->cipher_suites.data);
uint32_t len = min_size(&ch->cipher_suites, max_length);
- memcpy_check(out, &ch->cipher_suites.data, len);
+ POSIX_CHECKED_MEMCPY(out, ch->cipher_suites.data, len);
return len;
}
ssize_t s2n_client_hello_get_extensions_length(struct s2n_client_hello *ch) {
- notnull_check(ch);
+ POSIX_ENSURE_REF(ch);
return ch->extensions.raw.size;
}
ssize_t s2n_client_hello_get_extensions(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length)
{
- notnull_check(ch);
- notnull_check(out);
- notnull_check(ch->extensions.raw.data);
+ POSIX_ENSURE_REF(ch);
+ POSIX_ENSURE_REF(out);
+ POSIX_ENSURE_REF(ch->extensions.raw.data);
uint32_t len = min_size(&ch->extensions.raw, max_length);
- memcpy_check(out, &ch->extensions.raw.data, len);
+ POSIX_CHECKED_MEMCPY(out, ch->extensions.raw.data, len);
return len;
}
int s2n_client_hello_free(struct s2n_client_hello *client_hello)
{
- notnull_check(client_hello);
+ POSIX_ENSURE_REF(client_hello);
- GUARD(s2n_stuffer_free(&client_hello->raw_message));
+ POSIX_GUARD(s2n_stuffer_free(&client_hello->raw_message));
/* These point to data in the raw_message stuffer,
so we don't need to free them */
client_hello->cipher_suites.data = NULL;
client_hello->extensions.raw.data = NULL;
+ /* clean the CH nonblocking callback flags
+ * incase we are preparing for CH retry */
+ client_hello->callback_async_blocked = 0;
+ client_hello->callback_async_done = 0;
+ client_hello->parsed = 0;
+
return 0;
}
int s2n_collect_client_hello(struct s2n_connection *conn, struct s2n_stuffer *source)
{
- notnull_check(conn);
- notnull_check(source);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(source);
uint32_t size = s2n_stuffer_data_available(source);
S2N_ERROR_IF(size == 0, S2N_ERR_BAD_MESSAGE);
struct s2n_client_hello *ch = &conn->client_hello;
- GUARD(s2n_stuffer_resize(&ch->raw_message, size));
- GUARD(s2n_stuffer_copy(source, &ch->raw_message, size));
+ POSIX_GUARD(s2n_stuffer_resize(&ch->raw_message, size));
+ POSIX_GUARD(s2n_stuffer_copy(source, &ch->raw_message, size));
return 0;
}
-static int s2n_parse_client_hello(struct s2n_connection *conn)
+int s2n_parse_client_hello(struct s2n_connection *conn)
{
- notnull_check(conn);
- GUARD(s2n_collect_client_hello(conn, &conn->handshake.io));
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD(s2n_collect_client_hello(conn, &conn->handshake.io));
if (conn->client_hello_version == S2N_SSLv2) {
- GUARD(s2n_sslv2_client_hello_recv(conn));
+ POSIX_GUARD(s2n_sslv2_client_hello_recv(conn));
return S2N_SUCCESS;
}
@@ -189,8 +209,8 @@ static int s2n_parse_client_hello(struct s2n_connection *conn)
uint8_t client_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN];
- GUARD(s2n_stuffer_read_bytes(in, client_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
- GUARD(s2n_stuffer_erase_and_read_bytes(in, conn->secure.client_random, S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(in, client_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
+ POSIX_GUARD(s2n_stuffer_erase_and_read_bytes(in, conn->handshake_params.client_random, S2N_TLS_RANDOM_DATA_LEN));
/* Protocol version in the ClientHello is fixed at 0x0303(TLS 1.2) for
* future versions of TLS. Therefore, we will negotiate down if a client sends
@@ -199,51 +219,58 @@ static int s2n_parse_client_hello(struct s2n_connection *conn)
conn->client_protocol_version = MIN((client_protocol_version[0] * 10) + client_protocol_version[1], S2N_TLS12);
conn->client_hello_version = conn->client_protocol_version;
- GUARD(s2n_stuffer_read_uint8(in, &conn->session_id_len));
+ POSIX_GUARD(s2n_stuffer_read_uint8(in, &conn->session_id_len));
S2N_ERROR_IF(conn->session_id_len > S2N_TLS_SESSION_ID_MAX_LEN || conn->session_id_len > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE);
-
- GUARD(s2n_stuffer_read_bytes(in, conn->session_id, conn->session_id_len));
+ POSIX_GUARD(s2n_blob_init(&client_hello->session_id, s2n_stuffer_raw_read(in, conn->session_id_len), conn->session_id_len));
+ POSIX_CHECKED_MEMCPY(conn->session_id, client_hello->session_id.data, conn->session_id_len);
uint16_t cipher_suites_length = 0;
- GUARD(s2n_stuffer_read_uint16(in, &cipher_suites_length));
- ENSURE_POSIX(cipher_suites_length > 0, S2N_ERR_BAD_MESSAGE);
- ENSURE_POSIX(cipher_suites_length % S2N_TLS_CIPHER_SUITE_LEN == 0, S2N_ERR_BAD_MESSAGE);
-
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &cipher_suites_length));
+ POSIX_ENSURE(cipher_suites_length > 0, S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE(cipher_suites_length % S2N_TLS_CIPHER_SUITE_LEN == 0, S2N_ERR_BAD_MESSAGE);
+
client_hello->cipher_suites.size = cipher_suites_length;
client_hello->cipher_suites.data = s2n_stuffer_raw_read(in, cipher_suites_length);
- notnull_check(client_hello->cipher_suites.data);
+ POSIX_ENSURE_REF(client_hello->cipher_suites.data);
/* Don't choose the cipher yet, read the extensions first */
uint8_t num_compression_methods = 0;
- GUARD(s2n_stuffer_read_uint8(in, &num_compression_methods));
- GUARD(s2n_stuffer_skip_read(in, num_compression_methods));
+ POSIX_GUARD(s2n_stuffer_read_uint8(in, &num_compression_methods));
+ POSIX_GUARD(s2n_stuffer_skip_read(in, num_compression_methods));
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
-
- /* This is going to be our fallback if the client has no preference. */
- /* A TLS-compliant application MUST support key exchange with secp256r1 (NIST P-256) */
- /* and SHOULD support key exchange with X25519 [RFC7748]. */
- /* - https://tools.ietf.org/html/rfc8446#section-9.1 */
- conn->secure.server_ecc_evp_params.negotiated_curve = &s2n_ecc_curve_secp256r1;
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
+ POSIX_ENSURE_GT(ecc_pref->count, 0);
+
+ if (s2n_ecc_preferences_includes_curve(ecc_pref, TLS_EC_CURVE_SECP_256_R1)) {
+ /* This is going to be our fallback if the client has no preference. */
+ /* A TLS-compliant application MUST support key exchange with secp256r1 (NIST P-256) */
+ /* and SHOULD support key exchange with X25519 [RFC7748]. */
+ /* - https://tools.ietf.org/html/rfc8446#section-9.1 */
+ conn->kex_params.server_ecc_evp_params.negotiated_curve = &s2n_ecc_curve_secp256r1;
+ } else {
+ /* P-256 is the preferred fallback option. These prefs don't support it, so choose whatever curve is first. */
+ conn->kex_params.server_ecc_evp_params.negotiated_curve = ecc_pref->ecc_curves[0];
+ }
- GUARD(s2n_extension_list_parse(in, &conn->client_hello.extensions));
+ POSIX_GUARD(s2n_extension_list_parse(in, &conn->client_hello.extensions));
return S2N_SUCCESS;
}
int s2n_process_client_hello(struct s2n_connection *conn)
{
+ POSIX_ENSURE_REF(conn);
+
/* Client hello is parsed and config is finalized.
* Negotiate protocol version, cipher suite, ALPN, select a cert, etc. */
struct s2n_client_hello *client_hello = &conn->client_hello;
const struct s2n_security_policy *security_policy;
- GUARD(s2n_connection_get_security_policy(conn, &security_policy));
+ POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
- /* Ensure that highest supported version is set correctly */
- if (!s2n_security_policy_supports_tls13(security_policy)) {
+ if (!s2n_connection_supports_tls13(conn) || !s2n_security_policy_supports_tls13(security_policy)) {
conn->server_protocol_version = MIN(conn->server_protocol_version, S2N_TLS12);
conn->actual_protocol_version = MIN(conn->server_protocol_version, S2N_TLS12);
}
@@ -252,11 +279,11 @@ int s2n_process_client_hello(struct s2n_connection *conn)
* To keep the version in client_hello intact for the extension retrieval APIs, process a copy instead.
*/
s2n_parsed_extensions_list copy_of_parsed_extensions = conn->client_hello.extensions;
- GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_CLIENT_HELLO, conn, &copy_of_parsed_extensions));
+ POSIX_GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_CLIENT_HELLO, conn, &copy_of_parsed_extensions));
/* After parsing extensions, select a curve and corresponding keyshare to use */
if (conn->actual_protocol_version >= S2N_TLS13) {
- GUARD(s2n_extensions_server_key_share_select(conn));
+ POSIX_GUARD(s2n_extensions_server_key_share_select(conn));
}
/* for pre TLS 1.3 connections, protocol selection is not done in supported_versions extensions, so do it here */
@@ -265,25 +292,19 @@ int s2n_process_client_hello(struct s2n_connection *conn)
}
if (conn->client_protocol_version < security_policy->minimum_protocol_version) {
- GUARD(s2n_queue_reader_unsupported_protocol_version_alert(conn));
- S2N_ERROR(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
+ POSIX_GUARD(s2n_queue_reader_unsupported_protocol_version_alert(conn));
+ POSIX_BAIL(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
}
- if (conn->config->quic_enabled) {
- ENSURE_POSIX(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
-
- /* In TLS1.3, legacy_session_id is only set to indicate middlebox compatability mode.
- * When running with QUIC, S2N does not support middlebox compatability mode.
- * https://tools.ietf.org/html/draft-ietf-quic-tls-32#section-8.4
- */
- ENSURE_POSIX(conn->session_id_len == 0, S2N_ERR_BAD_MESSAGE);
+ if (s2n_connection_is_quic_enabled(conn)) {
+ POSIX_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
}
/* Find potential certificate matches before we choose the cipher. */
- GUARD(s2n_conn_find_name_matching_certs(conn));
+ POSIX_GUARD(s2n_conn_find_name_matching_certs(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));
+ POSIX_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. */
@@ -292,58 +313,104 @@ int s2n_process_client_hello(struct s2n_connection *conn)
}
/* And set the signature and hash algorithm used for key exchange signatures */
- GUARD(s2n_choose_sig_scheme_from_peer_preference_list(conn,
+ POSIX_GUARD(s2n_choose_sig_scheme_from_peer_preference_list(conn,
&conn->handshake_params.client_sig_hash_algs,
- &conn->secure.conn_sig_scheme));
+ &conn->handshake_params.conn_sig_scheme));
/* 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));
+ POSIX_GUARD(s2n_select_certs_for_server_auth(conn, &conn->handshake_params.our_chain_and_key));
return S2N_SUCCESS;
}
+static S2N_RESULT s2n_client_hello_process_cb_response(struct s2n_connection *conn, int rc)
+{
+ if (rc < 0) {
+ goto fail;
+ }
+ switch(conn->config->client_hello_cb_mode) {
+ case S2N_CLIENT_HELLO_CB_BLOCKING : {
+ if(rc) {
+ conn->server_name_used = 1;
+ }
+ return S2N_RESULT_OK;
+ }
+ case S2N_CLIENT_HELLO_CB_NONBLOCKING : {
+ if (conn->client_hello.callback_async_done) {
+ return S2N_RESULT_OK;
+ }
+ conn->client_hello.callback_async_blocked = 1;
+ RESULT_BAIL(S2N_ERR_ASYNC_BLOCKED);
+ }
+ }
+fail:
+ /* rc < 0 */
+ RESULT_GUARD_POSIX(s2n_queue_reader_handshake_failure_alert(conn));
+ RESULT_BAIL(S2N_ERR_CANCELLED);
+}
+
+bool s2n_client_hello_invoke_callback(struct s2n_connection *conn) {
+ /* Invoke only if the callback has not been called or if polling mode is enabled */
+ bool invoke = !conn->client_hello.callback_invoked || conn->config->client_hello_cb_enable_poll;
+ /*
+ * The callback should not be called if this client_hello is in response to a hello retry.
+ */
+ return invoke && !IS_HELLO_RETRY_HANDSHAKE(conn);
+}
+
int s2n_client_hello_recv(struct s2n_connection *conn)
{
- /* Parse client hello */
- GUARD(s2n_parse_client_hello(conn));
+ if (conn->config->client_hello_cb_enable_poll == 0) {
+ POSIX_ENSURE(conn->client_hello.callback_async_blocked == 0, S2N_ERR_ASYNC_BLOCKED);
+ }
- /* If the CLIENT_HELLO has already been parsed, then we should not call
- * the client_hello_cb a second time. */
if (conn->client_hello.parsed == 0) {
- /* Mark the collected client hello as available when parsing is done and before the client hello callback */
+ /* Parse client hello */
+ POSIX_GUARD(s2n_parse_client_hello(conn));
conn->client_hello.parsed = 1;
+ }
+ /* Call the client_hello_cb once unless polling is enabled. */
+ if (s2n_client_hello_invoke_callback(conn)) {
+ /* Mark the collected client hello as available when parsing is done and before the client hello callback */
+ conn->client_hello.callback_invoked = 1;
/* Call client_hello_cb if exists, letting application to modify s2n_connection or swap s2n_config */
if (conn->config->client_hello_cb) {
int rc = conn->config->client_hello_cb(conn, conn->config->client_hello_cb_ctx);
- if (rc < 0) {
- GUARD(s2n_queue_reader_handshake_failure_alert(conn));
- S2N_ERROR(S2N_ERR_CANCELLED);
- }
- if (rc) {
- conn->server_name_used = 1;
- }
+ POSIX_GUARD_RESULT(s2n_client_hello_process_cb_response(conn, rc));
}
}
if (conn->client_hello_version != S2N_SSLv2) {
- GUARD(s2n_process_client_hello(conn));
+ POSIX_GUARD(s2n_process_client_hello(conn));
}
return 0;
}
+S2N_RESULT s2n_cipher_suite_validate_available(struct s2n_connection *conn, struct s2n_cipher_suite *cipher)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(cipher);
+ RESULT_ENSURE_EQ(cipher->available, true);
+ RESULT_ENSURE_LTE(cipher->minimum_required_tls_version, conn->client_protocol_version);
+ if (s2n_connection_is_quic_enabled(conn)) {
+ RESULT_ENSURE_GTE(cipher->minimum_required_tls_version, S2N_TLS13);
+ }
+ return S2N_RESULT_OK;
+}
+
int s2n_client_hello_send(struct s2n_connection *conn)
{
+ POSIX_ENSURE_REF(conn);
+
const struct s2n_security_policy *security_policy;
- GUARD(s2n_connection_get_security_policy(conn, &security_policy));
+ POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
const struct s2n_cipher_preferences *cipher_preferences = security_policy->cipher_preferences;
- notnull_check(cipher_preferences);
+ POSIX_ENSURE_REF(cipher_preferences);
- /* Check whether cipher preference supports TLS 1.3. If it doesn't,
- our highest supported version is S2N_TLS12 */
- if (!s2n_security_policy_supports_tls13(security_policy)) {
+ if (!s2n_connection_supports_tls13(conn) || !s2n_security_policy_supports_tls13(security_policy)) {
conn->client_protocol_version = MIN(conn->client_protocol_version, S2N_TLS12);
conn->actual_protocol_version = MIN(conn->actual_protocol_version, S2N_TLS12);
}
@@ -353,61 +420,74 @@ int s2n_client_hello_send(struct s2n_connection *conn)
uint8_t client_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN] = {0};
struct s2n_blob b = {0};
- GUARD(s2n_blob_init(&b, conn->secure.client_random, S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_GUARD(s2n_blob_init(&b, conn->handshake_params.client_random, S2N_TLS_RANDOM_DATA_LEN));
/* Create the client random data */
- GUARD(s2n_stuffer_init(&client_random, &b));
+ POSIX_GUARD(s2n_stuffer_init(&client_random, &b));
struct s2n_blob r = {0};
- GUARD(s2n_blob_init(&r, s2n_stuffer_raw_write(&client_random, S2N_TLS_RANDOM_DATA_LEN), S2N_TLS_RANDOM_DATA_LEN));
- notnull_check(r.data);
- GUARD_AS_POSIX(s2n_get_public_random_data(&r));
+ POSIX_GUARD(s2n_blob_init(&r, s2n_stuffer_raw_write(&client_random, S2N_TLS_RANDOM_DATA_LEN), S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_ENSURE_REF(r.data);
+ POSIX_GUARD_RESULT(s2n_get_public_random_data(&r));
uint8_t reported_protocol_version = MIN(conn->client_protocol_version, S2N_TLS12);
client_protocol_version[0] = reported_protocol_version / 10;
client_protocol_version[1] = reported_protocol_version % 10;
conn->client_hello_version = reported_protocol_version;
- GUARD(s2n_stuffer_write_bytes(out, client_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
- GUARD(s2n_stuffer_copy(&client_random, out, S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(out, client_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
+ POSIX_GUARD(s2n_stuffer_copy(&client_random, out, S2N_TLS_RANDOM_DATA_LEN));
- GUARD_AS_POSIX(s2n_generate_client_session_id(conn));
- GUARD(s2n_stuffer_write_uint8(out, conn->session_id_len));
+ POSIX_GUARD_RESULT(s2n_generate_client_session_id(conn));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, conn->session_id_len));
if (conn->session_id_len > 0) {
- GUARD(s2n_stuffer_write_bytes(out, conn->session_id, conn->session_id_len));
+ POSIX_GUARD(s2n_stuffer_write_bytes(out, conn->session_id, conn->session_id_len));
}
/* Reserve space for size of the list of available ciphers */
struct s2n_stuffer_reservation available_cipher_suites_size;
- GUARD(s2n_stuffer_reserve_uint16(out, &available_cipher_suites_size));
+ POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &available_cipher_suites_size));
/* Now, write the IANA values of every available cipher suite in our list */
+ struct s2n_cipher_suite *cipher = NULL;
+ bool legacy_renegotiation_signal_required = false;
for (int i = 0; i < security_policy->cipher_preferences->count; i++ ) {
- if (cipher_preferences->suites[i]->available &&
- cipher_preferences->suites[i]->minimum_required_tls_version <= conn->client_protocol_version) {
- GUARD(s2n_stuffer_write_bytes(out, security_policy->cipher_preferences->suites[i]->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
+ cipher = cipher_preferences->suites[i];
+ if (s2n_result_is_error(s2n_cipher_suite_validate_available(conn, cipher))) {
+ continue;
+ }
+ if (cipher->minimum_required_tls_version < S2N_TLS13) {
+ legacy_renegotiation_signal_required = true;
}
+ POSIX_GUARD(s2n_stuffer_write_bytes(out, cipher->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
}
- /* Lastly, write TLS_EMPTY_RENEGOTIATION_INFO_SCSV so that server knows it's an initial handshake (RFC5746 Section 3.4) */
- uint8_t renegotiation_info_scsv[S2N_TLS_CIPHER_SUITE_LEN] = { TLS_EMPTY_RENEGOTIATION_INFO_SCSV };
- GUARD(s2n_stuffer_write_bytes(out, renegotiation_info_scsv, S2N_TLS_CIPHER_SUITE_LEN));
+ if (legacy_renegotiation_signal_required) {
+ /* Lastly, write TLS_EMPTY_RENEGOTIATION_INFO_SCSV so that server knows it's an initial handshake (RFC5746 Section 3.4) */
+ uint8_t renegotiation_info_scsv[S2N_TLS_CIPHER_SUITE_LEN] = { TLS_EMPTY_RENEGOTIATION_INFO_SCSV };
+ POSIX_GUARD(s2n_stuffer_write_bytes(out, renegotiation_info_scsv, S2N_TLS_CIPHER_SUITE_LEN));
+ }
/* Write size of the list of available ciphers */
- GUARD(s2n_stuffer_write_vector_size(&available_cipher_suites_size));
+ POSIX_GUARD(s2n_stuffer_write_vector_size(&available_cipher_suites_size));
/* Zero compression methods */
- GUARD(s2n_stuffer_write_uint8(out, 1));
- GUARD(s2n_stuffer_write_uint8(out, 0));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, 1));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, 0));
/* Write the extensions */
- GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_CLIENT_HELLO, conn, out));
+ POSIX_GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_CLIENT_HELLO, conn, out));
/* Once the message is complete, finish calculating the PSK binders.
*
* The PSK binders require all the sizes in the ClientHello to be written correctly,
* including the extension size and extension list size, and therefore have
* to be calculated AFTER we finish writing the entire extension list. */
- GUARD_AS_POSIX(s2n_finish_psk_extension(conn));
+ POSIX_GUARD_RESULT(s2n_finish_psk_extension(conn));
+
+ /* If early data was not requested as part of the ClientHello, it never will be. */
+ if (conn->early_data_state == S2N_UNKNOWN_EARLY_DATA_STATE) {
+ POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_NOT_REQUESTED));
+ }
return S2N_SUCCESS;
}
@@ -419,54 +499,53 @@ int s2n_sslv2_client_hello_recv(struct s2n_connection *conn)
struct s2n_stuffer *in = &client_hello->raw_message;
const struct s2n_security_policy *security_policy;
- GUARD(s2n_connection_get_security_policy(conn, &security_policy));
+ POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
if (conn->client_protocol_version < security_policy->minimum_protocol_version) {
- GUARD(s2n_queue_reader_unsupported_protocol_version_alert(conn));
- S2N_ERROR(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
+ POSIX_GUARD(s2n_queue_reader_unsupported_protocol_version_alert(conn));
+ POSIX_BAIL(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
}
conn->actual_protocol_version = MIN(conn->client_protocol_version, conn->server_protocol_version);
/* We start 5 bytes into the record */
uint16_t cipher_suites_length;
- GUARD(s2n_stuffer_read_uint16(in, &cipher_suites_length));
- ENSURE_POSIX(cipher_suites_length > 0, S2N_ERR_BAD_MESSAGE);
- ENSURE_POSIX(cipher_suites_length % S2N_SSLv2_CIPHER_SUITE_LEN == 0, S2N_ERR_BAD_MESSAGE);
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &cipher_suites_length));
+ POSIX_ENSURE(cipher_suites_length > 0, S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE(cipher_suites_length % S2N_SSLv2_CIPHER_SUITE_LEN == 0, S2N_ERR_BAD_MESSAGE);
uint16_t session_id_length;
- GUARD(s2n_stuffer_read_uint16(in, &session_id_length));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &session_id_length));
uint16_t challenge_length;
- GUARD(s2n_stuffer_read_uint16(in, &challenge_length));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &challenge_length));
S2N_ERROR_IF(challenge_length > S2N_TLS_RANDOM_DATA_LEN, S2N_ERR_BAD_MESSAGE);
client_hello->cipher_suites.size = cipher_suites_length;
client_hello->cipher_suites.data = s2n_stuffer_raw_read(in, cipher_suites_length);
- notnull_check(client_hello->cipher_suites.data);
+ POSIX_ENSURE_REF(client_hello->cipher_suites.data);
/* Find potential certificate matches before we choose the cipher. */
- GUARD(s2n_conn_find_name_matching_certs(conn));
+ POSIX_GUARD(s2n_conn_find_name_matching_certs(conn));
- GUARD(s2n_set_cipher_as_sslv2_server(conn, client_hello->cipher_suites.data, client_hello->cipher_suites.size / S2N_SSLv2_CIPHER_SUITE_LEN));
- GUARD(s2n_choose_default_sig_scheme(conn, &conn->secure.conn_sig_scheme));
- GUARD(s2n_select_certs_for_server_auth(conn, &conn->handshake_params.our_chain_and_key));
+ POSIX_GUARD(s2n_set_cipher_as_sslv2_server(conn, client_hello->cipher_suites.data, client_hello->cipher_suites.size / S2N_SSLv2_CIPHER_SUITE_LEN));
+ POSIX_GUARD(s2n_choose_default_sig_scheme(conn, &conn->handshake_params.conn_sig_scheme, S2N_SERVER));
+ POSIX_GUARD(s2n_select_certs_for_server_auth(conn, &conn->handshake_params.our_chain_and_key));
S2N_ERROR_IF(session_id_length > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE);
+ POSIX_GUARD(s2n_blob_init(&client_hello->session_id, s2n_stuffer_raw_read(in, session_id_length), session_id_length));
if (session_id_length > 0 && session_id_length <= S2N_TLS_SESSION_ID_MAX_LEN) {
- GUARD(s2n_stuffer_read_bytes(in, conn->session_id, session_id_length));
+ POSIX_CHECKED_MEMCPY(conn->session_id, client_hello->session_id.data, session_id_length);
conn->session_id_len = (uint8_t) session_id_length;
- } else {
- GUARD(s2n_stuffer_skip_read(in, session_id_length));
}
struct s2n_blob b = {0};
- GUARD(s2n_blob_init(&b, conn->secure.client_random, S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_GUARD(s2n_blob_init(&b, conn->handshake_params.client_random, S2N_TLS_RANDOM_DATA_LEN));
b.data += S2N_TLS_RANDOM_DATA_LEN - challenge_length;
b.size -= S2N_TLS_RANDOM_DATA_LEN - challenge_length;
- GUARD(s2n_stuffer_read(in, &b));
+ POSIX_GUARD(s2n_stuffer_read(in, &b));
return 0;
}
@@ -474,15 +553,15 @@ int s2n_sslv2_client_hello_recv(struct s2n_connection *conn)
static int s2n_client_hello_get_parsed_extension(s2n_tls_extension_type extension_type,
s2n_parsed_extensions_list *parsed_extension_list, s2n_parsed_extension **parsed_extension)
{
- notnull_check(parsed_extension_list);
- notnull_check(parsed_extension);
+ POSIX_ENSURE_REF(parsed_extension_list);
+ POSIX_ENSURE_REF(parsed_extension);
s2n_extension_type_id extension_type_id;
- GUARD(s2n_extension_supported_iana_value_to_id(extension_type, &extension_type_id));
+ POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type, &extension_type_id));
s2n_parsed_extension *found_parsed_extension = &parsed_extension_list->parsed_extensions[extension_type_id];
- notnull_check(found_parsed_extension->extension.data);
- ENSURE_POSIX(found_parsed_extension->extension_type == extension_type, S2N_ERR_INVALID_PARSED_EXTENSIONS);
+ POSIX_ENSURE_REF(found_parsed_extension->extension.data);
+ POSIX_ENSURE(found_parsed_extension->extension_type == extension_type, S2N_ERR_INVALID_PARSED_EXTENSIONS);
*parsed_extension = found_parsed_extension;
return S2N_SUCCESS;
@@ -490,7 +569,7 @@ static int s2n_client_hello_get_parsed_extension(s2n_tls_extension_type extensio
ssize_t s2n_client_hello_get_extension_length(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type)
{
- notnull_check(ch);
+ POSIX_ENSURE_REF(ch);
s2n_parsed_extension *parsed_extension = NULL;
if (s2n_client_hello_get_parsed_extension(extension_type, &ch->extensions, &parsed_extension) != S2N_SUCCESS) {
@@ -502,8 +581,8 @@ ssize_t s2n_client_hello_get_extension_length(struct s2n_client_hello *ch, s2n_t
ssize_t s2n_client_hello_get_extension_by_id(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type, uint8_t *out, uint32_t max_length)
{
- notnull_check(ch);
- notnull_check(out);
+ POSIX_ENSURE_REF(ch);
+ POSIX_ENSURE_REF(out);
s2n_parsed_extension *parsed_extension = NULL;
if (s2n_client_hello_get_parsed_extension(extension_type, &ch->extensions, &parsed_extension) != S2N_SUCCESS) {
@@ -511,6 +590,81 @@ ssize_t s2n_client_hello_get_extension_by_id(struct s2n_client_hello *ch, s2n_tl
}
uint32_t len = min_size(&parsed_extension->extension, max_length);
- memcpy_check(out, parsed_extension->extension.data, len);
+ POSIX_CHECKED_MEMCPY(out, parsed_extension->extension.data, len);
return len;
}
+
+int s2n_client_hello_get_session_id_length(struct s2n_client_hello *ch, uint32_t *out_length)
+{
+ POSIX_ENSURE_REF(ch);
+ POSIX_ENSURE_REF(out_length);
+ *out_length = ch->session_id.size;
+ return S2N_SUCCESS;
+}
+
+int s2n_client_hello_get_session_id(struct s2n_client_hello *ch, uint8_t *out, uint32_t *out_length, uint32_t max_length)
+{
+ POSIX_ENSURE_REF(ch);
+ POSIX_ENSURE_REF(out);
+ POSIX_ENSURE_REF(out_length);
+
+ uint32_t len = min_size(&ch->session_id, max_length);
+ POSIX_CHECKED_MEMCPY(out, ch->session_id.data, len);
+ *out_length = len;
+
+ return S2N_SUCCESS;
+}
+
+static S2N_RESULT s2n_client_hello_get_raw_extension(uint16_t extension_iana,
+ struct s2n_blob *raw_extensions, struct s2n_blob *extension)
+{
+ RESULT_ENSURE_REF(raw_extensions);
+ RESULT_ENSURE_REF(extension);
+
+ *extension = (struct s2n_blob) { 0 };
+
+ struct s2n_stuffer raw_extensions_stuffer = { 0 };
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&raw_extensions_stuffer, raw_extensions));
+ RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&raw_extensions_stuffer, raw_extensions->size));
+
+ while (s2n_stuffer_data_available(&raw_extensions_stuffer) > 0) {
+ uint16_t extension_type = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(&raw_extensions_stuffer, &extension_type));
+
+ uint16_t extension_size = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(&raw_extensions_stuffer, &extension_size));
+
+ uint8_t *extension_data = s2n_stuffer_raw_read(&raw_extensions_stuffer, extension_size);
+ RESULT_ENSURE_REF(extension_data);
+
+ if (extension_iana == extension_type) {
+ RESULT_GUARD_POSIX(s2n_blob_init(extension, extension_data, extension_size));
+ return S2N_RESULT_OK;
+ }
+ }
+ return S2N_RESULT_OK;
+}
+
+int s2n_client_hello_has_extension(struct s2n_client_hello *ch, uint16_t extension_iana, bool *exists)
+{
+ POSIX_ENSURE_REF(ch);
+ POSIX_ENSURE_REF(exists);
+
+ *exists = false;
+
+ s2n_extension_type_id extension_type_id = s2n_unsupported_extension;
+ if (s2n_extension_supported_iana_value_to_id(extension_iana, &extension_type_id) == S2N_SUCCESS) {
+ s2n_parsed_extension *parsed_extension = NULL;
+ if (s2n_client_hello_get_parsed_extension(extension_iana, &ch->extensions, &parsed_extension) == S2N_SUCCESS) {
+ *exists = true;
+ }
+ return S2N_SUCCESS;
+ }
+
+ struct s2n_blob extension = { 0 };
+ POSIX_GUARD_RESULT(s2n_client_hello_get_raw_extension(extension_iana, &ch->extensions.raw, &extension));
+ if (extension.data != NULL) {
+ *exists = true;
+ }
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_hello.h b/contrib/restricted/aws/s2n/tls/s2n_client_hello.h
index 59eb0b12c7..d319bbd606 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_hello.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello.h
@@ -16,7 +16,7 @@
#pragma once
#include <stdint.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include "stuffer/s2n_stuffer.h"
#include "tls/extensions/s2n_extension_list.h"
@@ -31,7 +31,18 @@ struct s2n_client_hello {
s2n_parsed_extensions_list extensions;
struct s2n_blob cipher_suites;
-
+ struct s2n_blob session_id;
+
+ unsigned int callback_invoked:1;
+ unsigned int callback_async_blocked:1;
+ unsigned int callback_async_done:1;
+ /*
+ * Marks if the client hello has been parsed.
+ *
+ * While a client_hello is only parsed once, it is possible to parse
+ * two different client_hello during a single handshake if the server
+ * issues a hello retry.
+ */
unsigned int parsed:1;
};
diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_hello_request.c b/contrib/restricted/aws/s2n/tls/s2n_client_hello_request.c
new file mode 100644
index 0000000000..6444c87f5d
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello_request.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#include "api/s2n.h"
+
+#include "tls/s2n_connection.h"
+#include "utils/s2n_safety.h"
+
+int s2n_client_hello_request_recv(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE(conn->actual_protocol_version < S2N_TLS13, S2N_ERR_BAD_MESSAGE);
+
+ /*
+ *= https://tools.ietf.org/rfc/rfc5246#section-7.4.1.1
+ *# The HelloRequest message MAY be sent by the server at any time.
+ */
+ POSIX_ENSURE(conn->mode == S2N_CLIENT, S2N_ERR_BAD_MESSAGE);
+
+ /*
+ *= https://tools.ietf.org/rfc/rfc5246#section-7.4.1.1
+ *# This message will be ignored by the client if the client is
+ *# currently negotiating a session. This message MAY be ignored by
+ *# the client if it does not wish to renegotiate a session, or the
+ *# client may, if it wishes, respond with a no_renegotiation alert.
+ */
+ return S2N_SUCCESS;
+}
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 1428e177b2..7b669e1ba6 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c
@@ -14,7 +14,7 @@
*/
#include <sys/param.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include "error/s2n_errno.h"
@@ -24,6 +24,7 @@
#include "tls/s2n_cipher_suites.h"
#include "tls/s2n_connection.h"
#include "tls/s2n_kex.h"
+#include "tls/s2n_key_log.h"
#include "tls/s2n_resume.h"
#include "stuffer/s2n_stuffer.h"
@@ -45,35 +46,35 @@ static int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rs
static int s2n_hybrid_client_action(struct s2n_connection *conn, struct s2n_blob *combined_shared_key,
s2n_kex_client_key_method kex_method, uint32_t *cursor, s2n_stuffer_action stuffer_action)
{
- notnull_check(kex_method);
- notnull_check(stuffer_action);
+ POSIX_ENSURE_REF(kex_method);
+ POSIX_ENSURE_REF(stuffer_action);
struct s2n_stuffer *io = &conn->handshake.io;
const struct s2n_kex *hybrid_kex_0 = conn->secure.cipher_suite->key_exchange_alg->hybrid[0];
const struct s2n_kex *hybrid_kex_1 = conn->secure.cipher_suite->key_exchange_alg->hybrid[1];
/* Keep a copy to the start of the entire hybrid client key exchange message for the hybrid PRF */
- struct s2n_blob *client_key_exchange_message = &conn->secure.client_key_exchange_message;
+ struct s2n_blob *client_key_exchange_message = &conn->kex_params.client_key_exchange_message;
client_key_exchange_message->data = stuffer_action(io, 0);
- notnull_check(client_key_exchange_message->data);
+ POSIX_ENSURE_REF(client_key_exchange_message->data);
const uint32_t start_cursor = *cursor;
DEFER_CLEANUP(struct s2n_blob shared_key_0 = {0}, s2n_free);
- GUARD_AS_POSIX(kex_method(hybrid_kex_0, conn, &shared_key_0));
+ POSIX_GUARD_RESULT(kex_method(hybrid_kex_0, conn, &shared_key_0));
- struct s2n_blob *shared_key_1 = &(conn->secure.kem_params.shared_secret);
- GUARD_AS_POSIX(kex_method(hybrid_kex_1, conn, shared_key_1));
+ struct s2n_blob *shared_key_1 = &(conn->kex_params.kem_params.shared_secret);
+ POSIX_GUARD_RESULT(kex_method(hybrid_kex_1, conn, shared_key_1));
const uint32_t end_cursor = *cursor;
- gte_check(end_cursor, start_cursor);
+ POSIX_ENSURE_GTE(end_cursor, start_cursor);
client_key_exchange_message->size = end_cursor - start_cursor;
- GUARD(s2n_alloc(combined_shared_key, shared_key_0.size + shared_key_1->size));
+ POSIX_GUARD(s2n_alloc(combined_shared_key, shared_key_0.size + shared_key_1->size));
struct s2n_stuffer stuffer_combiner = {0};
- GUARD(s2n_stuffer_init(&stuffer_combiner, combined_shared_key));
- GUARD(s2n_stuffer_write(&stuffer_combiner, &shared_key_0));
- GUARD(s2n_stuffer_write(&stuffer_combiner, shared_key_1));
+ POSIX_GUARD(s2n_stuffer_init(&stuffer_combiner, combined_shared_key));
+ POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, &shared_key_0));
+ POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, shared_key_1));
- GUARD(s2n_kem_free(&conn->secure.kem_params));
+ POSIX_GUARD(s2n_kem_free(&conn->kex_params.kem_params));
return 0;
}
@@ -81,26 +82,26 @@ 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_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) {
- GUARD(s2n_free(shared_key));
- }
+ POSIX_GUARD_RESULT(s2n_kex_tls_prf(conn->secure.cipher_suite->key_exchange_alg, conn, shared_key));
+
/* Expand the keys */
- GUARD(s2n_prf_key_expansion(conn));
- /* Save the master secret in the cache */
+ POSIX_GUARD(s2n_prf_key_expansion(conn));
+ /* Save the master secret in the cache.
+ * Failing to cache the session should not affect the current handshake.
+ */
if (s2n_allowed_to_cache_connection(conn)) {
- GUARD(s2n_store_to_cache(conn));
+ s2n_result_ignore(s2n_store_to_cache(conn));
}
+ /* log the secret, if needed */
+ s2n_result_ignore(s2n_key_log_tls12_secret(conn));
return 0;
}
int s2n_rsa_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key)
{
/* Set shared_key before async guard to pass the proper shared_key to the caller upon async completion */
- notnull_check(shared_key);
- shared_key->data = conn->secure.rsa_premaster_secret;
+ POSIX_ENSURE_REF(shared_key);
+ shared_key->data = conn->secrets.tls12.rsa_premaster_secret;
shared_key->size = S2N_TLS_SECRET_LEN;
S2N_ASYNC_PKEY_GUARD(conn);
@@ -112,7 +113,7 @@ int s2n_rsa_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared
if (conn->actual_protocol_version == S2N_SSLv3) {
length = s2n_stuffer_data_available(in);
} else {
- GUARD(s2n_stuffer_read_uint16(in, &length));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &length));
}
S2N_ERROR_IF(length > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE);
@@ -127,13 +128,13 @@ int s2n_rsa_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared
/* Decrypt the pre-master secret */
struct s2n_blob encrypted = {.size = length, .data = s2n_stuffer_raw_read(in, length)};
- notnull_check(encrypted.data);
- gt_check(encrypted.size, 0);
+ POSIX_ENSURE_REF(encrypted.data);
+ POSIX_ENSURE_GT(encrypted.size, 0);
/* First: use a random pre-master secret */
- GUARD_AS_POSIX(s2n_get_private_random_data(shared_key));
- conn->secure.rsa_premaster_secret[0] = client_hello_protocol_version[0];
- conn->secure.rsa_premaster_secret[1] = client_hello_protocol_version[1];
+ POSIX_GUARD_RESULT(s2n_get_private_random_data(shared_key));
+ conn->secrets.tls12.rsa_premaster_secret[0] = client_hello_protocol_version[0];
+ conn->secrets.tls12.rsa_premaster_secret[1] = client_hello_protocol_version[1];
S2N_ASYNC_PKEY_DECRYPT(conn, &encrypted, shared_key, s2n_rsa_client_key_recv_complete);
}
@@ -143,9 +144,9 @@ int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rsa_faile
S2N_ERROR_IF(decrypted->size != S2N_TLS_SECRET_LEN, S2N_ERR_SIZE_MISMATCH);
/* Avoid copying the same buffer for the case where async pkey is not used */
- if (conn->secure.rsa_premaster_secret != decrypted->data) {
+ if (conn->secrets.tls12.rsa_premaster_secret != decrypted->data) {
/* Copy (maybe) decrypted data into shared key */
- memcpy_check(conn->secure.rsa_premaster_secret, decrypted->data, S2N_TLS_SECRET_LEN);
+ POSIX_CHECKED_MEMCPY(conn->secrets.tls12.rsa_premaster_secret, decrypted->data, S2N_TLS_SECRET_LEN);
}
/* Get client hello protocol version for comparison with decrypted data */
@@ -158,7 +159,7 @@ int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rsa_faile
/* Set rsa_failed to true, if it isn't already, if the protocol version isn't what we expect */
conn->handshake.rsa_failed |= !s2n_constant_time_equals(client_hello_protocol_version,
- conn->secure.rsa_premaster_secret, S2N_TLS_PROTOCOL_VERSION_LEN);
+ conn->secrets.tls12.rsa_premaster_secret, S2N_TLS_PROTOCOL_VERSION_LEN);
return 0;
}
@@ -168,9 +169,9 @@ int s2n_dhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared
struct s2n_stuffer *in = &conn->handshake.io;
/* Get the shared key */
- GUARD(s2n_dh_compute_shared_secret_as_server(&conn->secure.server_dh_params, in, shared_key));
+ POSIX_GUARD(s2n_dh_compute_shared_secret_as_server(&conn->kex_params.server_dh_params, in, shared_key));
/* We don't need the server params any more */
- GUARD(s2n_dh_params_free(&conn->secure.server_dh_params));
+ POSIX_GUARD(s2n_dh_params_free(&conn->kex_params.server_dh_params));
return 0;
}
@@ -179,16 +180,16 @@ int s2n_ecdhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shar
struct s2n_stuffer *in = &conn->handshake.io;
/* Get the shared key */
- GUARD(s2n_ecc_evp_compute_shared_secret_as_server(&conn->secure.server_ecc_evp_params, in, shared_key));
+ POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_as_server(&conn->kex_params.server_ecc_evp_params, in, shared_key));
/* We don't need the server params any more */
- GUARD(s2n_ecc_evp_params_free(&conn->secure.server_ecc_evp_params));
+ POSIX_GUARD(s2n_ecc_evp_params_free(&conn->kex_params.server_ecc_evp_params));
return 0;
}
int s2n_kem_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key)
{
/* s2n_kem_recv_ciphertext() writes the KEM shared secret directly to
- * conn->secure.kem_params. However, the calling function
+ * conn->kex_params.kem_params. However, the calling function
* likely expects *shared_key to point to the shared secret. We
* can't reassign *shared_key to point to kem_params.shared_secret,
* because that would require us to take struct s2n_blob **shared_key
@@ -197,10 +198,10 @@ int s2n_kem_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared
*
* So, we assert that the caller already has *shared_key pointing
* to kem_params.shared_secret. */
- notnull_check(shared_key);
- S2N_ERROR_IF(shared_key != &(conn->secure.kem_params.shared_secret), S2N_ERR_SAFETY);
+ POSIX_ENSURE_REF(shared_key);
+ S2N_ERROR_IF(shared_key != &(conn->kex_params.kem_params.shared_secret), S2N_ERR_SAFETY);
- GUARD(s2n_kem_recv_ciphertext(&(conn->handshake.io), &(conn->secure.kem_params)));
+ POSIX_GUARD(s2n_kem_recv_ciphertext(&(conn->handshake.io), &(conn->kex_params.kem_params)));
return 0;
}
@@ -214,31 +215,30 @@ int s2n_hybrid_client_key_recv(struct s2n_connection *conn, struct s2n_blob *com
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_AS_POSIX(s2n_kex_client_key_recv(key_exchange, conn, &shared_key));
+ DEFER_CLEANUP(struct s2n_blob shared_key = { 0 }, s2n_blob_zeroize_free);
+ POSIX_GUARD_RESULT(s2n_kex_client_key_recv(key_exchange, conn, &shared_key));
- GUARD(s2n_calculate_keys(conn, &shared_key));
+ POSIX_GUARD(s2n_calculate_keys(conn, &shared_key));
return 0;
}
int s2n_dhe_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key)
{
struct s2n_stuffer *out = &conn->handshake.io;
- GUARD(s2n_dh_compute_shared_secret_as_client(&conn->secure.server_dh_params, out, shared_key));
+ POSIX_GUARD(s2n_dh_compute_shared_secret_as_client(&conn->kex_params.server_dh_params, out, shared_key));
/* We don't need the server params any more */
- GUARD(s2n_dh_params_free(&conn->secure.server_dh_params));
+ POSIX_GUARD(s2n_dh_params_free(&conn->kex_params.server_dh_params));
return 0;
}
int s2n_ecdhe_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key)
{
struct s2n_stuffer *out = &conn->handshake.io;
- GUARD(s2n_ecc_evp_compute_shared_secret_as_client(&conn->secure.server_ecc_evp_params, out, shared_key));
+ POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_as_client(&conn->kex_params.server_ecc_evp_params, out, shared_key));
/* We don't need the server params any more */
- GUARD(s2n_ecc_evp_params_free(&conn->secure.server_ecc_evp_params));
+ POSIX_GUARD(s2n_ecc_evp_params_free(&conn->kex_params.server_ecc_evp_params));
return 0;
}
@@ -249,42 +249,42 @@ int s2n_rsa_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared
client_hello_protocol_version[0] = legacy_client_hello_protocol_version / 10;
client_hello_protocol_version[1] = legacy_client_hello_protocol_version % 10;
- shared_key->data = conn->secure.rsa_premaster_secret;
+ shared_key->data = conn->secrets.tls12.rsa_premaster_secret;
shared_key->size = S2N_TLS_SECRET_LEN;
- GUARD_AS_POSIX(s2n_get_private_random_data(shared_key));
+ POSIX_GUARD_RESULT(s2n_get_private_random_data(shared_key));
/* Over-write the first two bytes with the client hello version, per RFC2246/RFC4346/RFC5246 7.4.7.1.
* The latest version supported by client (as seen from the the client hello version) are <= TLS1.2
* for all clients, because TLS 1.3 clients freezes the TLS1.2 legacy version in client hello.
*/
- memcpy_check(conn->secure.rsa_premaster_secret, client_hello_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN);
+ POSIX_CHECKED_MEMCPY(conn->secrets.tls12.rsa_premaster_secret, client_hello_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN);
uint32_t encrypted_size = 0;
- GUARD_AS_POSIX(s2n_pkey_size(&conn->secure.server_public_key, &encrypted_size));
+ POSIX_GUARD_RESULT(s2n_pkey_size(&conn->handshake_params.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));
+ POSIX_GUARD(s2n_stuffer_write_uint16(&conn->handshake.io, encrypted_size));
}
struct s2n_blob encrypted = {0};
encrypted.data = s2n_stuffer_raw_write(&conn->handshake.io, encrypted_size);
encrypted.size = encrypted_size;
- notnull_check(encrypted.data);
+ POSIX_ENSURE_REF(encrypted.data);
/* Encrypt the secret and send it on */
- GUARD(s2n_pkey_encrypt(&conn->secure.server_public_key, shared_key, &encrypted));
+ POSIX_GUARD(s2n_pkey_encrypt(&conn->handshake_params.server_public_key, shared_key, &encrypted));
/* We don't need the key any more, so free it */
- GUARD(s2n_pkey_free(&conn->secure.server_public_key));
+ POSIX_GUARD(s2n_pkey_free(&conn->handshake_params.server_public_key));
return 0;
}
int s2n_kem_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key)
{
/* s2n_kem_send_ciphertext() writes the KEM shared secret directly to
- * conn->secure.kem_params. However, the calling function
+ * conn->kex_params.kem_params. However, the calling function
* likely expects *shared_key to point to the shared secret. We
* can't reassign *shared_key to point to kem_params.shared_secret,
* because that would require us to take struct s2n_blob **shared_key
@@ -293,10 +293,10 @@ int s2n_kem_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared
*
* So, we assert that the caller already has *shared_key pointing
* to kem_params.shared_secret. */
- notnull_check(shared_key);
- S2N_ERROR_IF(shared_key != &(conn->secure.kem_params.shared_secret), S2N_ERR_SAFETY);
+ POSIX_ENSURE_REF(shared_key);
+ S2N_ERROR_IF(shared_key != &(conn->kex_params.kem_params.shared_secret), S2N_ERR_SAFETY);
- GUARD(s2n_kem_send_ciphertext(&(conn->handshake.io), &(conn->secure.kem_params)));
+ POSIX_GUARD(s2n_kem_send_ciphertext(&(conn->handshake.io), &(conn->kex_params.kem_params)));
return 0;
}
@@ -310,10 +310,10 @@ int s2n_hybrid_client_key_send(struct s2n_connection *conn, struct s2n_blob *com
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};
+ DEFER_CLEANUP(struct s2n_blob shared_key = { 0 }, s2n_blob_zeroize_free);
- GUARD_AS_POSIX(s2n_kex_client_key_send(key_exchange, conn, &shared_key));
+ POSIX_GUARD_RESULT(s2n_kex_client_key_send(key_exchange, conn, &shared_key));
- GUARD(s2n_calculate_keys(conn, &shared_key));
+ POSIX_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 db3a8819bc..7c455bb642 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_config.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_config.c
@@ -22,6 +22,7 @@
#include "crypto/s2n_fips.h"
#include "tls/s2n_cipher_preferences.h"
+#include "tls/s2n_internal.h"
#include "tls/s2n_security_policies.h"
#include "tls/s2n_tls13.h"
#include "utils/s2n_safety.h"
@@ -41,7 +42,7 @@ static int monotonic_clock(void *data, uint64_t *nanoseconds)
{
struct timespec current_time = {0};
- GUARD(clock_gettime(S2N_CLOCK_HW, &current_time));
+ POSIX_GUARD(clock_gettime(S2N_CLOCK_HW, &current_time));
*nanoseconds = (uint64_t)current_time.tv_sec * 1000000000ull;
*nanoseconds += current_time.tv_nsec;
@@ -53,7 +54,7 @@ static int wall_clock(void *data, uint64_t *nanoseconds)
{
struct timespec current_time = {0};
- GUARD(clock_gettime(S2N_CLOCK_SYS, &current_time));
+ POSIX_GUARD(clock_gettime(S2N_CLOCK_SYS, &current_time));
*nanoseconds = (uint64_t)current_time.tv_sec * 1000000000ull;
*nanoseconds += current_time.tv_nsec;
@@ -67,79 +68,54 @@ static struct s2n_config s2n_default_tls13_config = {0};
static int s2n_config_setup_default(struct s2n_config *config)
{
- GUARD(s2n_config_set_cipher_preferences(config, "default"));
+ POSIX_GUARD(s2n_config_set_cipher_preferences(config, "default"));
return S2N_SUCCESS;
}
static int s2n_config_setup_tls13(struct s2n_config *config)
{
- GUARD(s2n_config_set_cipher_preferences(config, "default_tls13"));
+ POSIX_GUARD(s2n_config_set_cipher_preferences(config, "default_tls13"));
return S2N_SUCCESS;
}
static int s2n_config_setup_fips(struct s2n_config *config)
{
- GUARD(s2n_config_set_cipher_preferences(config, "default_fips"));
+ POSIX_GUARD(s2n_config_set_cipher_preferences(config, "default_fips"));
return S2N_SUCCESS;
}
static int s2n_config_init(struct s2n_config *config)
{
- config->cert_allocated = 0;
- config->dhparams = NULL;
- memset(&config->application_protocols, 0, sizeof(config->application_protocols));
config->status_request_type = S2N_STATUS_REQUEST_NONE;
config->wall_clock = wall_clock;
config->monotonic_clock = monotonic_clock;
- config->verify_host = NULL;
- config->data_for_verify_host = NULL;
- config->client_hello_cb = NULL;
- config->client_hello_cb_ctx = NULL;
- config->cache_store = NULL;
- config->cache_store_data = NULL;
- config->cache_retrieve = NULL;
- config->cache_retrieve_data = NULL;
- config->cache_delete = NULL;
- config->cache_delete_data = NULL;
config->ct_type = S2N_CT_SUPPORT_NONE;
config->mfl_code = S2N_TLS_MAX_FRAG_LEN_EXT_NONE;
config->alert_behavior = S2N_ALERT_FAIL_ON_WARNINGS;
- config->accept_mfl = 0;
config->session_state_lifetime_in_nanos = S2N_STATE_LIFETIME_IN_NANOS;
- config->use_tickets = 0;
- config->use_session_cache = 0;
- config->ticket_keys = NULL;
- config->ticket_key_hashes = NULL;
config->encrypt_decrypt_key_lifetime_in_nanos = S2N_TICKET_ENCRYPT_DECRYPT_KEY_LIFETIME_IN_NANOS;
config->decrypt_key_lifetime_in_nanos = S2N_TICKET_DECRYPT_KEY_LIFETIME_IN_NANOS;
- config->quic_enabled = 0;
+ config->async_pkey_validation_mode = S2N_ASYNC_PKEY_VALIDATION_FAST;
/* By default, only the client will authenticate the Server's Certificate. The Server does not request or
* authenticate any client certificates. */
config->client_cert_auth_type = S2N_CERT_AUTH_NONE;
config->check_ocsp = 1;
- config->disable_x509_validation = 0;
- config->max_verify_cert_chain_depth = 0;
- 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));
+
+ config->client_hello_cb_mode = S2N_CLIENT_HELLO_CB_BLOCKING;
+
+ POSIX_GUARD(s2n_config_setup_default(config));
if (s2n_use_default_tls13_config()) {
- GUARD(s2n_config_setup_tls13(config));
+ POSIX_GUARD(s2n_config_setup_tls13(config));
} else if (s2n_is_in_fips_mode()) {
- GUARD(s2n_config_setup_fips(config));
+ POSIX_GUARD(s2n_config_setup_fips(config));
}
- notnull_check(config->domain_name_to_cert_map = s2n_map_new_with_initial_capacity(1));
- GUARD_AS_POSIX(s2n_map_complete(config->domain_name_to_cert_map));
- memset(&config->default_certs_by_type, 0, sizeof(struct certs_by_type));
- config->default_certs_are_explicit = 0;
+ POSIX_GUARD_PTR(config->domain_name_to_cert_map = s2n_map_new_with_initial_capacity(1));
+ POSIX_GUARD_RESULT(s2n_map_complete(config->domain_name_to_cert_map));
s2n_x509_trust_store_init_empty(&config->trust_store);
- s2n_x509_trust_store_from_system_defaults(&config->trust_store);
+ POSIX_GUARD(s2n_x509_trust_store_from_system_defaults(&config->trust_store));
return 0;
}
@@ -149,11 +125,11 @@ static int s2n_config_cleanup(struct s2n_config *config)
s2n_x509_trust_store_wipe(&config->trust_store);
config->check_ocsp = 0;
- GUARD(s2n_config_free_session_ticket_keys(config));
- GUARD(s2n_config_free_cert_chain_and_key(config));
- GUARD(s2n_config_free_dhparams(config));
- GUARD(s2n_free(&config->application_protocols));
- GUARD_AS_POSIX(s2n_map_free(config->domain_name_to_cert_map));
+ POSIX_GUARD(s2n_config_free_session_ticket_keys(config));
+ POSIX_GUARD(s2n_config_free_cert_chain_and_key(config));
+ POSIX_GUARD(s2n_config_free_dhparams(config));
+ POSIX_GUARD(s2n_free(&config->application_protocols));
+ POSIX_GUARD_RESULT(s2n_map_free(config->domain_name_to_cert_map));
return 0;
}
@@ -162,8 +138,8 @@ static int s2n_config_update_domain_name_to_cert_map(struct s2n_config *config,
struct s2n_blob *name,
struct s2n_cert_chain_and_key *cert_key_pair)
{
- notnull_check(config);
- notnull_check(name);
+ POSIX_ENSURE_REF(config);
+ POSIX_ENSURE_REF(name);
struct s2n_map *domain_name_to_cert_map = config->domain_name_to_cert_map;
/* s2n_map does not allow zero-size key */
@@ -173,16 +149,16 @@ static int s2n_config_update_domain_name_to_cert_map(struct s2n_config *config,
s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pair);
struct s2n_blob s2n_map_value = { 0 };
bool key_found = false;
- GUARD_AS_POSIX(s2n_map_lookup(domain_name_to_cert_map, name, &s2n_map_value, &key_found));
+ POSIX_GUARD_RESULT(s2n_map_lookup(domain_name_to_cert_map, name, &s2n_map_value, &key_found));
if (!key_found) {
struct certs_by_type value = {{ 0 }};
value.certs[cert_type] = cert_key_pair;
s2n_map_value.data = (uint8_t *) &value;
s2n_map_value.size = sizeof(struct certs_by_type);
- GUARD_AS_POSIX(s2n_map_unlock(domain_name_to_cert_map));
- GUARD_AS_POSIX(s2n_map_add(domain_name_to_cert_map, name, &s2n_map_value));
- GUARD_AS_POSIX(s2n_map_complete(domain_name_to_cert_map));
+ POSIX_GUARD_RESULT(s2n_map_unlock(domain_name_to_cert_map));
+ POSIX_GUARD_RESULT(s2n_map_add(domain_name_to_cert_map, name, &s2n_map_value));
+ POSIX_GUARD_RESULT(s2n_map_complete(domain_name_to_cert_map));
} else {
struct certs_by_type *value = (void *) s2n_map_value.data;;
if (value->certs[cert_type] == NULL) {
@@ -211,21 +187,21 @@ static int s2n_config_build_domain_name_to_cert_map(struct s2n_config *config, s
{
uint32_t cn_len = 0;
- GUARD_AS_POSIX(s2n_array_num_elements(cert_key_pair->cn_names, &cn_len));
+ POSIX_GUARD_RESULT(s2n_array_num_elements(cert_key_pair->cn_names, &cn_len));
uint32_t san_len = 0;
- GUARD_AS_POSIX(s2n_array_num_elements(cert_key_pair->san_names, &san_len));
+ POSIX_GUARD_RESULT(s2n_array_num_elements(cert_key_pair->san_names, &san_len));
if (san_len == 0) {
for (uint32_t i = 0; i < cn_len; i++) {
struct s2n_blob *cn_name = NULL;
- GUARD_AS_POSIX(s2n_array_get(cert_key_pair->cn_names, i, (void **)&cn_name));
- GUARD(s2n_config_update_domain_name_to_cert_map(config, cn_name, cert_key_pair));
+ POSIX_GUARD_RESULT(s2n_array_get(cert_key_pair->cn_names, i, (void **)&cn_name));
+ POSIX_GUARD(s2n_config_update_domain_name_to_cert_map(config, cn_name, cert_key_pair));
}
} else {
for (uint32_t i = 0; i < san_len; i++) {
struct s2n_blob *san_name = NULL;
- GUARD_AS_POSIX(s2n_array_get(cert_key_pair->san_names, i, (void **)&san_name));
- GUARD(s2n_config_update_domain_name_to_cert_map(config, san_name, cert_key_pair));
+ POSIX_GUARD_RESULT(s2n_array_get(cert_key_pair->san_names, i, (void **)&san_name));
+ POSIX_GUARD(s2n_config_update_domain_name_to_cert_map(config, san_name, cert_key_pair));
}
}
@@ -255,25 +231,27 @@ int s2n_config_set_unsafe_for_testing(struct s2n_config *config)
int s2n_config_defaults_init(void)
{
- /* Set up default */
- GUARD(s2n_config_init(&s2n_default_config));
- GUARD(s2n_config_setup_default(&s2n_default_config));
-
/* Set up fips defaults */
- GUARD(s2n_config_init(&s2n_default_fips_config));
- GUARD(s2n_config_setup_fips(&s2n_default_fips_config));
+ if (s2n_is_in_fips_mode()) {
+ POSIX_GUARD(s2n_config_init(&s2n_default_fips_config));
+ POSIX_GUARD(s2n_config_setup_fips(&s2n_default_fips_config));
+ } else {
+ /* Set up default */
+ POSIX_GUARD(s2n_config_init(&s2n_default_config));
+ POSIX_GUARD(s2n_config_setup_default(&s2n_default_config));
+ }
/* Set up TLS 1.3 defaults */
- GUARD(s2n_config_init(&s2n_default_tls13_config));
- GUARD(s2n_config_setup_tls13(&s2n_default_tls13_config));
+ POSIX_GUARD(s2n_config_init(&s2n_default_tls13_config));
+ POSIX_GUARD(s2n_config_setup_tls13(&s2n_default_tls13_config));
return S2N_SUCCESS;
}
void s2n_wipe_static_configs(void)
{
- s2n_config_cleanup(&s2n_default_config);
s2n_config_cleanup(&s2n_default_fips_config);
+ s2n_config_cleanup(&s2n_default_config);
s2n_config_cleanup(&s2n_default_tls13_config);
}
@@ -282,7 +260,8 @@ struct s2n_config *s2n_config_new(void)
struct s2n_blob allocator = {0};
struct s2n_config *new_config;
- GUARD_PTR(s2n_alloc(&allocator, sizeof(struct s2n_config)));
+ PTR_GUARD_POSIX(s2n_alloc(&allocator, sizeof(struct s2n_config)));
+ PTR_GUARD_POSIX(s2n_blob_zero(&allocator));
new_config = (struct s2n_config *)(void *)allocator.data;
if (s2n_config_init(new_config) != S2N_SUCCESS) {
@@ -310,11 +289,11 @@ static int s2n_verify_unique_ticket_key_comparator(const void *a, const void *b)
int s2n_config_init_session_ticket_keys(struct s2n_config *config)
{
if (config->ticket_keys == NULL) {
- notnull_check(config->ticket_keys = s2n_set_new(sizeof(struct s2n_ticket_key), s2n_config_store_ticket_key_comparator));
+ POSIX_ENSURE_REF(config->ticket_keys = s2n_set_new(sizeof(struct s2n_ticket_key), s2n_config_store_ticket_key_comparator));
}
if (config->ticket_key_hashes == NULL) {
- notnull_check(config->ticket_key_hashes = s2n_set_new(SHA_DIGEST_LENGTH, s2n_verify_unique_ticket_key_comparator));
+ POSIX_ENSURE_REF(config->ticket_key_hashes = s2n_set_new(SHA_DIGEST_LENGTH, s2n_verify_unique_ticket_key_comparator));
}
return 0;
@@ -323,11 +302,11 @@ int s2n_config_init_session_ticket_keys(struct s2n_config *config)
int s2n_config_free_session_ticket_keys(struct s2n_config *config)
{
if (config->ticket_keys != NULL) {
- GUARD_AS_POSIX(s2n_set_free_p(&config->ticket_keys));
+ POSIX_GUARD_RESULT(s2n_set_free_p(&config->ticket_keys));
}
if (config->ticket_key_hashes != NULL) {
- GUARD_AS_POSIX(s2n_set_free_p(&config->ticket_key_hashes));
+ POSIX_GUARD_RESULT(s2n_set_free_p(&config->ticket_key_hashes));
}
return 0;
@@ -349,39 +328,47 @@ int s2n_config_free_cert_chain_and_key(struct s2n_config *config)
int s2n_config_free_dhparams(struct s2n_config *config)
{
if (config->dhparams) {
- GUARD(s2n_dh_params_free(config->dhparams));
+ POSIX_GUARD(s2n_dh_params_free(config->dhparams));
}
- GUARD(s2n_free_object((uint8_t **)&config->dhparams, sizeof(struct s2n_dh_params)));
+ POSIX_GUARD(s2n_free_object((uint8_t **)&config->dhparams, sizeof(struct s2n_dh_params)));
return 0;
}
+S2N_CLEANUP_RESULT s2n_config_ptr_free(struct s2n_config **config)
+{
+ RESULT_ENSURE_REF(config);
+ RESULT_GUARD_POSIX(s2n_config_free(*config));
+ *config = NULL;
+ return S2N_RESULT_OK;
+}
+
int s2n_config_free(struct s2n_config *config)
{
s2n_config_cleanup(config);
- GUARD(s2n_free_object((uint8_t **)&config, sizeof(struct s2n_config)));
+ POSIX_GUARD(s2n_free_object((uint8_t **)&config, sizeof(struct s2n_config)));
return 0;
}
int s2n_config_get_client_auth_type(struct s2n_config *config, s2n_cert_auth_type *client_auth_type)
{
- notnull_check(config);
- notnull_check(client_auth_type);
+ POSIX_ENSURE_REF(config);
+ POSIX_ENSURE_REF(client_auth_type);
*client_auth_type = config->client_cert_auth_type;
return 0;
}
int s2n_config_set_client_auth_type(struct s2n_config *config, s2n_cert_auth_type client_auth_type)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
config->client_cert_auth_type = client_auth_type;
return 0;
}
int s2n_config_set_ct_support_level(struct s2n_config *config, s2n_ct_support_level type)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
config->ct_type = type;
return 0;
@@ -389,7 +376,7 @@ int s2n_config_set_ct_support_level(struct s2n_config *config, s2n_ct_support_le
int s2n_config_set_alert_behavior(struct s2n_config *config, s2n_alert_behavior alert_behavior)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
switch (alert_behavior) {
case S2N_ALERT_FAIL_ON_WARNINGS:
@@ -397,7 +384,7 @@ int s2n_config_set_alert_behavior(struct s2n_config *config, s2n_alert_behavior
config->alert_behavior = alert_behavior;
break;
default:
- S2N_ERROR(S2N_ERR_INVALID_ARGUMENT);
+ POSIX_BAIL(S2N_ERR_INVALID_ARGUMENT);
}
return 0;
@@ -405,7 +392,7 @@ int s2n_config_set_alert_behavior(struct s2n_config *config, s2n_alert_behavior
int s2n_config_set_verify_host_callback(struct s2n_config *config, s2n_verify_host_fn verify_host_fn, void *data)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
config->verify_host = verify_host_fn;
config->data_for_verify_host = data;
return 0;
@@ -413,7 +400,7 @@ int s2n_config_set_verify_host_callback(struct s2n_config *config, s2n_verify_ho
int s2n_config_set_check_stapled_ocsp_response(struct s2n_config *config, uint8_t check_ocsp)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
S2N_ERROR_IF(check_ocsp && !s2n_x509_ocsp_stapling_supported(), S2N_ERR_OCSP_NOT_SUPPORTED);
config->check_ocsp = check_ocsp;
return 0;
@@ -421,7 +408,7 @@ int s2n_config_set_check_stapled_ocsp_response(struct s2n_config *config, uint8_
int s2n_config_disable_x509_verification(struct s2n_config *config)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
s2n_x509_trust_store_wipe(&config->trust_store);
config->disable_x509_validation = 1;
return 0;
@@ -429,7 +416,7 @@ int s2n_config_disable_x509_verification(struct s2n_config *config)
int s2n_config_set_max_cert_chain_depth(struct s2n_config *config, uint16_t max_depth)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
S2N_ERROR_IF(max_depth == 0, S2N_ERR_INVALID_ARGUMENT);
config->max_verify_cert_chain_depth = max_depth;
@@ -442,25 +429,34 @@ int s2n_config_set_status_request_type(struct s2n_config *config, s2n_status_req
{
S2N_ERROR_IF(type == S2N_STATUS_REQUEST_OCSP && !s2n_x509_ocsp_stapling_supported(), S2N_ERR_OCSP_NOT_SUPPORTED);
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
config->status_request_type = type;
return 0;
}
+int s2n_config_wipe_trust_store(struct s2n_config *config)
+{
+ POSIX_ENSURE_REF(config);
+
+ s2n_x509_trust_store_wipe(&config->trust_store);
+
+ return S2N_SUCCESS;
+}
+
int s2n_config_add_pem_to_trust_store(struct s2n_config *config, const char *pem)
{
- notnull_check(config);
- notnull_check(pem);
+ POSIX_ENSURE_REF(config);
+ POSIX_ENSURE_REF(pem);
- GUARD(s2n_x509_trust_store_add_pem(&config->trust_store, pem));
+ POSIX_GUARD(s2n_x509_trust_store_add_pem(&config->trust_store, pem));
return 0;
}
int s2n_config_set_verification_ca_location(struct s2n_config *config, const char *ca_pem_filename, const char *ca_dir)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
int err_code = s2n_x509_trust_store_from_ca_file(&config->trust_store, ca_pem_filename, ca_dir);
if (!err_code) {
@@ -474,9 +470,9 @@ int s2n_config_set_verification_ca_location(struct s2n_config *config, const cha
int s2n_config_add_cert_chain_and_key(struct s2n_config *config, const char *cert_chain_pem, const char *private_key_pem)
{
struct s2n_cert_chain_and_key *chain_and_key;
- notnull_check(chain_and_key = s2n_cert_chain_and_key_new());
- GUARD(s2n_cert_chain_and_key_load_pem(chain_and_key, cert_chain_pem, private_key_pem));
- GUARD(s2n_config_add_cert_chain_and_key_to_store(config, chain_and_key));
+ POSIX_ENSURE_REF(chain_and_key = s2n_cert_chain_and_key_new());
+ POSIX_GUARD(s2n_cert_chain_and_key_load_pem(chain_and_key, cert_chain_pem, private_key_pem));
+ POSIX_GUARD(s2n_config_add_cert_chain_and_key_to_store(config, chain_and_key));
config->cert_allocated = 1;
return 0;
@@ -484,26 +480,30 @@ int s2n_config_add_cert_chain_and_key(struct s2n_config *config, const char *cer
int s2n_config_add_cert_chain_and_key_to_store(struct s2n_config *config, struct s2n_cert_chain_and_key *cert_key_pair)
{
- notnull_check(config->domain_name_to_cert_map);
- notnull_check(cert_key_pair);
-
- GUARD(s2n_config_build_domain_name_to_cert_map(config, cert_key_pair));
+ POSIX_ENSURE_REF(config->domain_name_to_cert_map);
+ POSIX_ENSURE_REF(cert_key_pair);
+ s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pair);
+ config->is_rsa_cert_configured |= (cert_type == S2N_PKEY_TYPE_RSA);
+ POSIX_GUARD(s2n_config_build_domain_name_to_cert_map(config, cert_key_pair));
if (!config->default_certs_are_explicit) {
/* Attempt to auto set default based on ordering. ie: first RSA cert is the default, first ECDSA cert is the
* default, etc. */
- s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pair);
if (config->default_certs_by_type.certs[cert_type] == NULL) {
config->default_certs_by_type.certs[cert_type] = cert_key_pair;
}
}
- return 0;
+ if (s2n_pkey_check_key_exists(cert_key_pair->private_key) != S2N_SUCCESS) {
+ config->no_signing_key = true;
+ }
+
+ return S2N_SUCCESS;
}
int s2n_config_set_async_pkey_callback(struct s2n_config *config, s2n_async_pkey_fn fn)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
config->async_pkey_cb = fn;
@@ -512,7 +512,7 @@ int s2n_config_set_async_pkey_callback(struct s2n_config *config, s2n_async_pkey
int s2n_config_clear_default_certificates(struct s2n_config *config)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
config->default_certs_by_type.certs[i] = NULL;
}
@@ -523,23 +523,24 @@ int s2n_config_set_cert_chain_and_key_defaults(struct s2n_config *config,
struct s2n_cert_chain_and_key **cert_key_pairs,
uint32_t num_cert_key_pairs)
{
- notnull_check(config);
- notnull_check(cert_key_pairs);
+ POSIX_ENSURE_REF(config);
+ POSIX_ENSURE_REF(cert_key_pairs);
S2N_ERROR_IF(num_cert_key_pairs < 1 || num_cert_key_pairs > S2N_CERT_TYPE_COUNT,
S2N_ERR_NUM_DEFAULT_CERTIFICATES);
/* Validate certs being set before clearing auto-chosen defaults or previously set defaults */
struct certs_by_type new_defaults = {{ 0 }};
- for (int i = 0; i < num_cert_key_pairs; i++) {
- notnull_check(cert_key_pairs[i]);
+ for (uint32_t i = 0; i < num_cert_key_pairs; i++) {
+ POSIX_ENSURE_REF(cert_key_pairs[i]);
s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pairs[i]);
S2N_ERROR_IF(new_defaults.certs[cert_type] != NULL, S2N_ERR_MULTIPLE_DEFAULT_CERTIFICATES_PER_AUTH_TYPE);
new_defaults.certs[cert_type] = cert_key_pairs[i];
}
- GUARD(s2n_config_clear_default_certificates(config));
- for (int i = 0; i < num_cert_key_pairs; i++) {
+ POSIX_GUARD(s2n_config_clear_default_certificates(config));
+ for (uint32_t i = 0; i < num_cert_key_pairs; i++) {
s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pairs[i]);
+ config->is_rsa_cert_configured |= (cert_type == S2N_PKEY_TYPE_RSA);
config->default_certs_by_type.certs[cert_type] = cert_key_pairs[i];
}
@@ -555,7 +556,7 @@ int s2n_config_add_dhparams(struct s2n_config *config, const char *dhparams_pem)
struct s2n_blob mem = {0};
/* Allocate the memory for the chain and key struct */
- GUARD(s2n_alloc(&mem, sizeof(struct s2n_dh_params)));
+ POSIX_GUARD(s2n_alloc(&mem, sizeof(struct s2n_dh_params)));
config->dhparams = (struct s2n_dh_params *)(void *)mem.data;
if (s2n_stuffer_alloc_ro_from_string(&dhparams_in_stuffer, dhparams_pem) != S2N_SUCCESS) {
@@ -568,20 +569,20 @@ int s2n_config_add_dhparams(struct s2n_config *config, const char *dhparams_pem)
}
/* Convert pem to asn1 and asn1 to the private key */
- GUARD(s2n_stuffer_dhparams_from_pem(&dhparams_in_stuffer, &dhparams_out_stuffer));
+ POSIX_GUARD(s2n_stuffer_dhparams_from_pem(&dhparams_in_stuffer, &dhparams_out_stuffer));
dhparams_blob.size = s2n_stuffer_data_available(&dhparams_out_stuffer);
dhparams_blob.data = s2n_stuffer_raw_read(&dhparams_out_stuffer, dhparams_blob.size);
- notnull_check(dhparams_blob.data);
+ POSIX_ENSURE_REF(dhparams_blob.data);
- GUARD(s2n_pkcs3_to_dh_params(config->dhparams, &dhparams_blob));
+ POSIX_GUARD(s2n_pkcs3_to_dh_params(config->dhparams, &dhparams_blob));
return 0;
}
extern int s2n_config_set_wall_clock(struct s2n_config *config, s2n_clock_time_nanoseconds clock_fn, void *ctx)
{
- notnull_check(clock_fn);
+ POSIX_ENSURE_REF(clock_fn);
config->wall_clock = clock_fn;
config->sys_clock_ctx = ctx;
@@ -591,7 +592,7 @@ extern int s2n_config_set_wall_clock(struct s2n_config *config, s2n_clock_time_n
extern int s2n_config_set_monotonic_clock(struct s2n_config *config, s2n_clock_time_nanoseconds clock_fn, void *ctx)
{
- notnull_check(clock_fn);
+ POSIX_ENSURE_REF(clock_fn);
config->monotonic_clock = clock_fn;
config->monotonic_clock_ctx = ctx;
@@ -601,7 +602,7 @@ extern int s2n_config_set_monotonic_clock(struct s2n_config *config, s2n_clock_t
int s2n_config_set_cache_store_callback(struct s2n_config *config, s2n_cache_store_callback cache_store_callback, void *data)
{
- notnull_check(cache_store_callback);
+ POSIX_ENSURE_REF(cache_store_callback);
config->cache_store = cache_store_callback;
config->cache_store_data = data;
@@ -611,7 +612,7 @@ int s2n_config_set_cache_store_callback(struct s2n_config *config, s2n_cache_sto
int s2n_config_set_cache_retrieve_callback(struct s2n_config *config, s2n_cache_retrieve_callback cache_retrieve_callback, void *data)
{
- notnull_check(cache_retrieve_callback);
+ POSIX_ENSURE_REF(cache_retrieve_callback);
config->cache_retrieve = cache_retrieve_callback;
config->cache_retrieve_data = data;
@@ -621,7 +622,7 @@ int s2n_config_set_cache_retrieve_callback(struct s2n_config *config, s2n_cache_
int s2n_config_set_cache_delete_callback(struct s2n_config *config, s2n_cache_delete_callback cache_delete_callback, void *data)
{
- notnull_check(cache_delete_callback);
+ POSIX_ENSURE_REF(cache_delete_callback);
config->cache_delete = cache_delete_callback;
config->cache_delete_data = data;
@@ -631,25 +632,25 @@ int s2n_config_set_cache_delete_callback(struct s2n_config *config, s2n_cache_de
int s2n_config_set_extension_data(struct s2n_config *config, s2n_tls_extension_type type, const uint8_t *data, uint32_t length)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
if (s2n_config_get_num_default_certs(config) == 0) {
- S2N_ERROR(S2N_ERR_UPDATING_EXTENSION);
+ POSIX_BAIL(S2N_ERR_UPDATING_EXTENSION);
}
struct s2n_cert_chain_and_key *config_chain_and_key = s2n_config_get_single_default_cert(config);
- notnull_check(config_chain_and_key);
+ POSIX_ENSURE_REF(config_chain_and_key);
switch (type) {
case S2N_EXTENSION_CERTIFICATE_TRANSPARENCY:
{
- GUARD(s2n_cert_chain_and_key_set_sct_list(config_chain_and_key, data, length));
+ POSIX_GUARD(s2n_cert_chain_and_key_set_sct_list(config_chain_and_key, data, length));
} break;
case S2N_EXTENSION_OCSP_STAPLING:
{
- GUARD(s2n_cert_chain_and_key_set_ocsp_data(config_chain_and_key, data, length));
+ POSIX_GUARD(s2n_cert_chain_and_key_set_ocsp_data(config_chain_and_key, data, length));
} break;
default:
- S2N_ERROR(S2N_ERR_UNRECOGNIZED_EXTENSION);
+ POSIX_BAIL(S2N_ERR_UNRECOGNIZED_EXTENSION);
}
return 0;
@@ -657,15 +658,26 @@ int s2n_config_set_extension_data(struct s2n_config *config, s2n_tls_extension_t
int s2n_config_set_client_hello_cb(struct s2n_config *config, s2n_client_hello_fn client_hello_cb, void *ctx)
{
+ POSIX_ENSURE_REF(config);
+
config->client_hello_cb = client_hello_cb;
config->client_hello_cb_ctx = ctx;
-
return 0;
}
+int s2n_config_set_client_hello_cb_mode(struct s2n_config *config, s2n_client_hello_cb_mode cb_mode)
+{
+ POSIX_ENSURE_REF(config);
+ POSIX_ENSURE(cb_mode == S2N_CLIENT_HELLO_CB_BLOCKING ||
+ cb_mode == S2N_CLIENT_HELLO_CB_NONBLOCKING, S2N_ERR_INVALID_STATE);
+
+ config->client_hello_cb_mode = cb_mode;
+ return S2N_SUCCESS;
+}
+
int s2n_config_send_max_fragment_length(struct s2n_config *config, s2n_max_frag_len mfl_code)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
S2N_ERROR_IF(mfl_code > S2N_TLS_MAX_FRAG_LEN_4096, S2N_ERR_INVALID_MAX_FRAG_LEN);
@@ -676,7 +688,7 @@ int s2n_config_send_max_fragment_length(struct s2n_config *config, s2n_max_frag_
int s2n_config_accept_max_fragment_length(struct s2n_config *config)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
config->accept_mfl = 1;
@@ -686,7 +698,7 @@ int s2n_config_accept_max_fragment_length(struct s2n_config *config)
int s2n_config_set_session_state_lifetime(struct s2n_config *config,
uint64_t lifetime_in_secs)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
config->session_state_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS);
return 0;
@@ -694,7 +706,7 @@ int s2n_config_set_session_state_lifetime(struct s2n_config *config,
int s2n_config_set_session_tickets_onoff(struct s2n_config *config, uint8_t enabled)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
if (config->use_tickets == enabled) {
return 0;
@@ -702,11 +714,18 @@ int s2n_config_set_session_tickets_onoff(struct s2n_config *config, uint8_t enab
config->use_tickets = enabled;
+ if (config->initial_tickets_to_send == 0) {
+ /* Normally initial_tickets_to_send is set via s2n_config_set_initial_ticket_count.
+ * However, s2n_config_set_initial_ticket_count calls this method.
+ * So we set initial_tickets_to_send directly to avoid infinite recursion. */
+ config->initial_tickets_to_send = 1;
+ }
+
/* session ticket || session id is enabled */
if (enabled) {
- GUARD(s2n_config_init_session_ticket_keys(config));
+ POSIX_GUARD(s2n_config_init_session_ticket_keys(config));
} else if (!config->use_session_cache) {
- GUARD(s2n_config_free_session_ticket_keys(config));
+ POSIX_GUARD(s2n_config_free_session_ticket_keys(config));
}
return 0;
@@ -714,14 +733,14 @@ int s2n_config_set_session_tickets_onoff(struct s2n_config *config, uint8_t enab
int s2n_config_set_session_cache_onoff(struct s2n_config *config, uint8_t enabled)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
if (enabled && config->cache_store && config->cache_retrieve && config->cache_delete) {
- GUARD(s2n_config_init_session_ticket_keys(config));
+ POSIX_GUARD(s2n_config_init_session_ticket_keys(config));
config->use_session_cache = 1;
}
else {
if (!config->use_tickets) {
- GUARD(s2n_config_free_session_ticket_keys(config));
+ POSIX_GUARD(s2n_config_free_session_ticket_keys(config));
}
config->use_session_cache = 0;
}
@@ -731,7 +750,7 @@ int s2n_config_set_session_cache_onoff(struct s2n_config *config, uint8_t enable
int s2n_config_set_ticket_encrypt_decrypt_key_lifetime(struct s2n_config *config,
uint64_t lifetime_in_secs)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
config->encrypt_decrypt_key_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS);
return 0;
@@ -740,7 +759,7 @@ int s2n_config_set_ticket_encrypt_decrypt_key_lifetime(struct s2n_config *config
int s2n_config_set_ticket_decrypt_key_lifetime(struct s2n_config *config,
uint64_t lifetime_in_secs)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
config->decrypt_key_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS);
return 0;
@@ -751,21 +770,21 @@ int s2n_config_add_ticket_crypto_key(struct s2n_config *config,
uint8_t *key, uint32_t key_len,
uint64_t intro_time_in_seconds_from_epoch)
{
- notnull_check(config);
- notnull_check(name);
- notnull_check(key);
+ POSIX_ENSURE_REF(config);
+ POSIX_ENSURE_REF(name);
+ POSIX_ENSURE_REF(key);
/* both session ticket and session cache encryption/decryption can use the same key mechanism */
if (!config->use_tickets && !config->use_session_cache) {
return 0;
}
- GUARD(s2n_config_wipe_expired_ticket_crypto_keys(config, -1));
+ POSIX_GUARD(s2n_config_wipe_expired_ticket_crypto_keys(config, -1));
S2N_ERROR_IF(key_len == 0, S2N_ERR_INVALID_TICKET_KEY_LENGTH);
uint32_t ticket_keys_len = 0;
- GUARD_AS_POSIX(s2n_set_len(config->ticket_keys, &ticket_keys_len));
+ POSIX_GUARD_RESULT(s2n_set_len(config->ticket_keys, &ticket_keys_len));
S2N_ERROR_IF(ticket_keys_len >= S2N_MAX_TICKET_KEYS, S2N_ERR_TICKET_KEY_LIMIT);
S2N_ERROR_IF(name_len == 0 || name_len > S2N_TICKET_KEY_NAME_LEN || s2n_find_ticket_key(config, name), S2N_ERR_INVALID_TICKET_KEY_NAME_OR_NAME_LENGTH);
@@ -778,45 +797,45 @@ int s2n_config_add_ticket_crypto_key(struct s2n_config *config,
struct s2n_ticket_key *session_ticket_key;
DEFER_CLEANUP(struct s2n_blob allocator = {0}, s2n_free);
- GUARD(s2n_alloc(&allocator, sizeof(struct s2n_ticket_key)));
+ POSIX_GUARD(s2n_alloc(&allocator, sizeof(struct s2n_ticket_key)));
session_ticket_key = (struct s2n_ticket_key *) (void *) allocator.data;
DEFER_CLEANUP(struct s2n_hmac_state hmac = {0}, s2n_hmac_free);
- GUARD(s2n_hmac_new(&hmac));
- GUARD(s2n_hkdf(&hmac, S2N_HMAC_SHA256, &salt, &in_key, &info, &out_key));
+ POSIX_GUARD(s2n_hmac_new(&hmac));
+ POSIX_GUARD(s2n_hkdf(&hmac, S2N_HMAC_SHA256, &salt, &in_key, &info, &out_key));
DEFER_CLEANUP(struct s2n_hash_state hash = {0}, s2n_hash_free);
uint8_t hash_output[SHA_DIGEST_LENGTH];
- GUARD(s2n_hash_new(&hash));
- GUARD(s2n_hash_init(&hash, S2N_HASH_SHA1));
- GUARD(s2n_hash_update(&hash, out_key.data, out_key.size));
- GUARD(s2n_hash_digest(&hash, hash_output, SHA_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_new(&hash));
+ POSIX_GUARD(s2n_hash_init(&hash, S2N_HASH_SHA1));
+ POSIX_GUARD(s2n_hash_update(&hash, out_key.data, out_key.size));
+ POSIX_GUARD(s2n_hash_digest(&hash, hash_output, SHA_DIGEST_LENGTH));
- GUARD_AS_POSIX(s2n_set_len(config->ticket_keys, &ticket_keys_len));
+ POSIX_GUARD_RESULT(s2n_set_len(config->ticket_keys, &ticket_keys_len));
if (ticket_keys_len >= S2N_MAX_TICKET_KEY_HASHES) {
- GUARD_AS_POSIX(s2n_set_free_p(&config->ticket_key_hashes));
- notnull_check(config->ticket_key_hashes = s2n_set_new(SHA_DIGEST_LENGTH, s2n_verify_unique_ticket_key_comparator));
+ POSIX_GUARD_RESULT(s2n_set_free_p(&config->ticket_key_hashes));
+ POSIX_ENSURE_REF(config->ticket_key_hashes = s2n_set_new(SHA_DIGEST_LENGTH, s2n_verify_unique_ticket_key_comparator));
}
/* Insert hash key into a sorted array at known index */
- GUARD_AS_POSIX(s2n_set_add(config->ticket_key_hashes, hash_output));
+ POSIX_GUARD_RESULT(s2n_set_add(config->ticket_key_hashes, hash_output));
- memcpy_check(session_ticket_key->key_name, name, S2N_TICKET_KEY_NAME_LEN);
- memcpy_check(session_ticket_key->aes_key, out_key.data, S2N_AES256_KEY_LEN);
+ POSIX_CHECKED_MEMCPY(session_ticket_key->key_name, name, S2N_TICKET_KEY_NAME_LEN);
+ POSIX_CHECKED_MEMCPY(session_ticket_key->aes_key, out_key.data, S2N_AES256_KEY_LEN);
out_key.data = output_pad + S2N_AES256_KEY_LEN;
- memcpy_check(session_ticket_key->implicit_aad, out_key.data, S2N_TICKET_AAD_IMPLICIT_LEN);
+ POSIX_CHECKED_MEMCPY(session_ticket_key->implicit_aad, out_key.data, S2N_TICKET_AAD_IMPLICIT_LEN);
if (intro_time_in_seconds_from_epoch == 0) {
uint64_t now;
- GUARD(config->wall_clock(config->sys_clock_ctx, &now));
+ POSIX_GUARD(config->wall_clock(config->sys_clock_ctx, &now));
session_ticket_key->intro_timestamp = now;
} else {
session_ticket_key->intro_timestamp = (intro_time_in_seconds_from_epoch * ONE_SEC_IN_NANOS);
}
- GUARD(s2n_config_store_ticket_key(config, session_ticket_key));
+ POSIX_GUARD(s2n_config_store_ticket_key(config, session_ticket_key));
return 0;
}
@@ -829,7 +848,7 @@ int s2n_config_set_cert_tiebreak_callback(struct s2n_config *config, s2n_cert_ti
struct s2n_cert_chain_and_key *s2n_config_get_single_default_cert(struct s2n_config *config)
{
- notnull_check_ptr(config);
+ PTR_ENSURE_REF(config);
struct s2n_cert_chain_and_key *cert = NULL;
for (int i = S2N_CERT_TYPE_COUNT - 1; i >= 0; i--) {
@@ -842,7 +861,7 @@ struct s2n_cert_chain_and_key *s2n_config_get_single_default_cert(struct s2n_con
int s2n_config_get_num_default_certs(struct s2n_config *config)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
int num_certs = 0;
for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
if (config->default_certs_by_type.certs[i] != NULL) {
@@ -855,17 +874,67 @@ int s2n_config_get_num_default_certs(struct s2n_config *config)
int s2n_config_enable_cert_req_dss_legacy_compat(struct s2n_config *config)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(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)
+int s2n_config_set_psk_selection_callback(struct s2n_config *config, s2n_psk_selection_callback cb, void *context)
{
- notnull_check(conn);
- notnull_check(cb);
+ POSIX_ENSURE_REF(config);
+ config->psk_selection_cb = cb;
+ config->psk_selection_ctx = context;
+ return S2N_SUCCESS;
+}
+
+int s2n_config_set_key_log_cb(struct s2n_config *config, s2n_key_log_fn callback, void *ctx) {
+ POSIX_ENSURE_MUT(config);
+
+ config->key_log_cb = callback;
+ config->key_log_ctx = ctx;
+
+ return S2N_SUCCESS;
+}
+
+int s2n_config_set_async_pkey_validation_mode(struct s2n_config *config, s2n_async_pkey_validation_mode mode) {
+ POSIX_ENSURE_REF(config);
+
+ switch(mode) {
+ case S2N_ASYNC_PKEY_VALIDATION_FAST:
+ case S2N_ASYNC_PKEY_VALIDATION_STRICT:
+ config->async_pkey_validation_mode = mode;
+ return S2N_SUCCESS;
+ }
+
+ POSIX_BAIL(S2N_ERR_INVALID_ARGUMENT);
+}
+
+int s2n_config_set_ctx(struct s2n_config *config, void *ctx) {
+ POSIX_ENSURE_REF(config);
+
+ config->context = ctx;
+
+ return S2N_SUCCESS;
+}
+
+int s2n_config_get_ctx(struct s2n_config *config, void **ctx) {
+ POSIX_ENSURE_REF(config);
+ POSIX_ENSURE_REF(ctx);
+
+ *ctx = config->context;
+
+ return S2N_SUCCESS;
+}
+
+/*
+ * Set the client_hello callback behavior to polling.
+ *
+ * Polling means that the callback function can be called multiple times.
+ */
+int s2n_config_client_hello_cb_enable_poll(struct s2n_config *config) {
+ POSIX_ENSURE_REF(config);
- conn->config->psk_selection_cb = cb;
+ config->client_hello_cb_enable_poll = 1;
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.h b/contrib/restricted/aws/s2n/tls/s2n_config.h
index c5edf02418..c0068ce133 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_config.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_config.h
@@ -18,11 +18,11 @@
#include "api/s2n.h"
#include "crypto/s2n_certificate.h"
#include "crypto/s2n_dhe.h"
+#include "tls/s2n_psk.h"
#include "tls/s2n_resume.h"
#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 */
@@ -30,21 +30,37 @@
struct s2n_cipher_preferences;
struct s2n_config {
+ unsigned use_tickets:1;
+
+ /* Whether a connection can be used by a QUIC implementation.
+ * See s2n_quic_support.h */
+ unsigned quic_enabled:1;
+
unsigned cert_allocated:1;
unsigned default_certs_are_explicit:1;
- unsigned use_tickets:1;
unsigned use_session_cache:1;
/* if this is FALSE, server will ignore client's Maximum Fragment Length request */
unsigned accept_mfl:1;
unsigned check_ocsp:1;
unsigned disable_x509_validation:1;
unsigned max_verify_cert_chain_depth_set:1;
- /* Whether a connection can be used by a QUIC implementation.
- * See s2n_quic_support.h */
- unsigned quic_enabled:1;
/* Whether to add dss cert type during a server certificate request.
- * See https://github.com/awslabs/s2n/blob/main/docs/USAGE-GUIDE.md */
+ * See https://github.com/aws/s2n-tls/blob/main/docs/USAGE-GUIDE.md */
unsigned cert_req_dss_legacy_compat_enabled:1;
+ /* Whether any RSA certificates have been configured server-side to send to clients. This is needed so that the
+ * server knows whether or not to self-downgrade to TLS 1.2 if the server is compiled with Openssl 1.0.2 and does
+ * not support RSA PSS signing (which is required for TLS 1.3). */
+ unsigned is_rsa_cert_configured:1;
+ /* It's possible to use a certificate without loading the private key,
+ * but async signing must be enabled. Use this flag to enforce that restriction.
+ */
+ unsigned no_signing_key:1;
+ /*
+ * This option exists to allow for polling the client_hello callback.
+ *
+ * Note: This defaults to false to ensure backwards compatibility.
+ */
+ unsigned client_hello_cb_enable_poll:1;
struct s2n_dh_params *dhparams;
/* Needed until we can deprecate s2n_config_add_cert_chain_and_key. This is
@@ -63,6 +79,8 @@ struct s2n_config {
void *monotonic_clock_ctx;
s2n_client_hello_fn *client_hello_cb;
+ s2n_client_hello_cb_mode client_hello_cb_mode;
+
void *client_hello_cb_ctx;
uint64_t session_state_lifetime_in_nanos;
@@ -98,13 +116,36 @@ struct s2n_config {
uint8_t mfl_code;
+ uint8_t initial_tickets_to_send;
+
struct s2n_x509_trust_store trust_store;
uint16_t max_verify_cert_chain_depth;
s2n_async_pkey_fn async_pkey_cb;
+
s2n_psk_selection_callback psk_selection_cb;
+ void *psk_selection_ctx;
+
+ s2n_key_log_fn key_log_cb;
+ void *key_log_ctx;
+
+ s2n_session_ticket_fn session_ticket_cb;
+ void *session_ticket_ctx;
+
+ s2n_early_data_cb early_data_cb;
+
+ uint32_t server_max_early_data_size;
+
+ s2n_psk_mode psk_mode;
+
+ s2n_async_pkey_validation_mode async_pkey_validation_mode;
+
+ /* The user defined context associated with config */
+ void *context;
};
+S2N_CLEANUP_RESULT s2n_config_ptr_free(struct s2n_config **config);
+
int s2n_config_defaults_init(void);
extern struct s2n_config *s2n_fetch_default_config(void);
int s2n_config_set_unsafe_for_testing(struct s2n_config *config);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.c b/contrib/restricted/aws/s2n/tls/s2n_connection.c
index f2393fd2a1..cf6334164f 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection.c
@@ -19,8 +19,9 @@
#include <strings.h>
#include <time.h>
#include <unistd.h>
+#include <sys/param.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include <stdbool.h>
#include "crypto/s2n_fips.h"
@@ -34,6 +35,7 @@
#include "tls/s2n_connection_evp_digests.h"
#include "tls/s2n_handshake.h"
#include "tls/s2n_kem.h"
+#include "tls/s2n_internal.h"
#include "tls/s2n_prf.h"
#include "tls/s2n_record.h"
#include "tls/s2n_resume.h"
@@ -43,6 +45,8 @@
#include "crypto/s2n_certificate.h"
#include "crypto/s2n_cipher.h"
+#include "crypto/s2n_crypto.h"
+#include "crypto/s2n_openssl_x509.h"
#include "utils/s2n_blob.h"
#include "utils/s2n_compiler.h"
@@ -55,83 +59,13 @@
#define S2N_SET_KEY_SHARE_LIST_EMPTY(keyshares) (keyshares |= 1)
#define S2N_SET_KEY_SHARE_REQUEST(keyshares, i) (keyshares |= ( 1 << ( i + 1 )))
-static int s2n_connection_new_hashes(struct s2n_connection *conn)
-{
- /* Allocate long-term memory for the Connection's hash states */
- GUARD(s2n_hash_new(&conn->handshake.md5));
- GUARD(s2n_hash_new(&conn->handshake.sha1));
- GUARD(s2n_hash_new(&conn->handshake.sha224));
- GUARD(s2n_hash_new(&conn->handshake.sha256));
- GUARD(s2n_hash_new(&conn->handshake.sha384));
- GUARD(s2n_hash_new(&conn->handshake.sha512));
- GUARD(s2n_hash_new(&conn->handshake.md5_sha1));
- GUARD(s2n_hash_new(&conn->handshake.ccv_hash_copy));
- GUARD(s2n_hash_new(&conn->handshake.prf_md5_hash_copy));
- GUARD(s2n_hash_new(&conn->handshake.prf_sha1_hash_copy));
- GUARD(s2n_hash_new(&conn->handshake.prf_tls12_hash_copy));
- GUARD(s2n_hash_new(&conn->handshake.server_finished_copy));
- GUARD(s2n_hash_new(&conn->prf_space.ssl3.md5));
- GUARD(s2n_hash_new(&conn->prf_space.ssl3.sha1));
- GUARD(s2n_hash_new(&conn->initial.signature_hash));
- GUARD(s2n_hash_new(&conn->secure.signature_hash));
-
- return 0;
-}
-
-static int s2n_connection_init_hashes(struct s2n_connection *conn)
-{
- /* Initialize all of the Connection's hash states */
-
- if (s2n_hash_is_available(S2N_HASH_MD5)) {
- /* Only initialize hashes that use MD5 if available. */
- GUARD(s2n_hash_init(&conn->prf_space.ssl3.md5, S2N_HASH_MD5));
- }
-
-
- /* Allow MD5 for hash states that are used by the PRF. This is required
- * to comply with the TLS 1.0 and 1.1 RFCs and is approved as per
- * NIST Special Publication 800-52 Revision 1.
- */
- if (s2n_is_in_fips_mode()) {
- GUARD(s2n_hash_allow_md5_for_fips(&conn->handshake.md5));
- GUARD(s2n_hash_allow_md5_for_fips(&conn->handshake.prf_md5_hash_copy));
-
- /* Do not check s2n_hash_is_available before initialization. Allow MD5 and
- * SHA-1 for both fips and non-fips mode. This is required to perform the
- * signature checks in the CertificateVerify message in TLS 1.0 and TLS 1.1.
- * This is approved per Nist SP 800-52r1.*/
- GUARD(s2n_hash_allow_md5_for_fips(&conn->handshake.md5_sha1));
- }
-
- GUARD(s2n_hash_init(&conn->handshake.md5, S2N_HASH_MD5));
- GUARD(s2n_hash_init(&conn->handshake.prf_md5_hash_copy, S2N_HASH_MD5));
- GUARD(s2n_hash_init(&conn->handshake.md5_sha1, S2N_HASH_MD5_SHA1));
-
- GUARD(s2n_hash_init(&conn->handshake.sha1, S2N_HASH_SHA1));
- GUARD(s2n_hash_init(&conn->handshake.sha224, S2N_HASH_SHA224));
- GUARD(s2n_hash_init(&conn->handshake.sha256, S2N_HASH_SHA256));
- GUARD(s2n_hash_init(&conn->handshake.sha384, S2N_HASH_SHA384));
- GUARD(s2n_hash_init(&conn->handshake.sha512, S2N_HASH_SHA512));
- GUARD(s2n_hash_init(&conn->handshake.ccv_hash_copy, S2N_HASH_NONE));
- GUARD(s2n_hash_init(&conn->handshake.prf_tls12_hash_copy, S2N_HASH_NONE));
- GUARD(s2n_hash_init(&conn->handshake.server_finished_copy, S2N_HASH_NONE));
- GUARD(s2n_hash_init(&conn->handshake.prf_sha1_hash_copy, S2N_HASH_SHA1));
- GUARD(s2n_hash_init(&conn->prf_space.ssl3.sha1, S2N_HASH_SHA1));
- GUARD(s2n_hash_init(&conn->initial.signature_hash, S2N_HASH_NONE));
- GUARD(s2n_hash_init(&conn->secure.signature_hash, S2N_HASH_NONE));
-
- return 0;
-}
-
static int s2n_connection_new_hmacs(struct s2n_connection *conn)
{
/* Allocate long-term memory for the Connection's HMAC states */
- GUARD(s2n_hmac_new(&conn->initial.client_record_mac));
- GUARD(s2n_hmac_new(&conn->initial.server_record_mac));
- GUARD(s2n_hmac_new(&conn->initial.record_mac_copy_workspace));
- GUARD(s2n_hmac_new(&conn->secure.client_record_mac));
- GUARD(s2n_hmac_new(&conn->secure.server_record_mac));
- GUARD(s2n_hmac_new(&conn->secure.record_mac_copy_workspace));
+ POSIX_GUARD(s2n_hmac_new(&conn->initial.client_record_mac));
+ POSIX_GUARD(s2n_hmac_new(&conn->initial.server_record_mac));
+ POSIX_GUARD(s2n_hmac_new(&conn->secure.client_record_mac));
+ POSIX_GUARD(s2n_hmac_new(&conn->secure.server_record_mac));
return 0;
}
@@ -139,107 +73,92 @@ static int s2n_connection_new_hmacs(struct s2n_connection *conn)
static int s2n_connection_init_hmacs(struct s2n_connection *conn)
{
/* Initialize all of the Connection's HMAC states */
- GUARD(s2n_hmac_init(&conn->initial.client_record_mac, S2N_HMAC_NONE, NULL, 0));
- GUARD(s2n_hmac_init(&conn->initial.server_record_mac, S2N_HMAC_NONE, NULL, 0));
- GUARD(s2n_hmac_init(&conn->initial.record_mac_copy_workspace, S2N_HMAC_NONE, NULL, 0));
- GUARD(s2n_hmac_init(&conn->secure.client_record_mac, S2N_HMAC_NONE, NULL, 0));
- GUARD(s2n_hmac_init(&conn->secure.server_record_mac, S2N_HMAC_NONE, NULL, 0));
- GUARD(s2n_hmac_init(&conn->secure.record_mac_copy_workspace, S2N_HMAC_NONE, NULL, 0));
+ POSIX_GUARD(s2n_hmac_init(&conn->initial.client_record_mac, S2N_HMAC_NONE, NULL, 0));
+ POSIX_GUARD(s2n_hmac_init(&conn->initial.server_record_mac, S2N_HMAC_NONE, NULL, 0));
+ POSIX_GUARD(s2n_hmac_init(&conn->secure.client_record_mac, S2N_HMAC_NONE, NULL, 0));
+ POSIX_GUARD(s2n_hmac_init(&conn->secure.server_record_mac, S2N_HMAC_NONE, NULL, 0));
return 0;
}
+/* Allocates and initializes memory for a new connection.
+ *
+ * Since customers can reuse a connection, ensure that values on the connection are
+ * initialized in `s2n_connection_wipe` where possible. */
struct s2n_connection *s2n_connection_new(s2n_mode mode)
{
struct s2n_blob blob = {0};
- GUARD_PTR(s2n_alloc(&blob, sizeof(struct s2n_connection)));
- GUARD_PTR(s2n_blob_zero(&blob));
+ PTR_GUARD_POSIX(s2n_alloc(&blob, sizeof(struct s2n_connection)));
+ PTR_GUARD_POSIX(s2n_blob_zero(&blob));
/* Cast 'through' void to acknowledge that we are changing alignment,
* which is ok, as blob.data is always aligned.
*/
struct s2n_connection* conn = (struct s2n_connection *)(void *)blob.data;
- GUARD_PTR(s2n_connection_set_config(conn, s2n_fetch_default_config()));
+ PTR_GUARD_POSIX(s2n_connection_set_config(conn, s2n_fetch_default_config()));
+ /* `mode` is initialized here since its passed in as a parameter. */
conn->mode = mode;
- conn->blinding = S2N_BUILT_IN_BLINDING;
- conn->close_notify_queued = 0;
- conn->client_session_resumed = 0;
- conn->session_id_len = 0;
- conn->verify_host_fn = NULL;
- conn->data_for_verify_host = NULL;
- conn->verify_host_fn_overridden = 0;
- conn->data_for_verify_host = NULL;
- conn->send = NULL;
- conn->recv = NULL;
- conn->send_io_context = NULL;
- conn->recv_io_context = NULL;
- conn->managed_io = 0;
- conn->corked_io = 0;
- conn->context = NULL;
- conn->security_policy_override = NULL;
- conn->ticket_lifetime_hint = 0;
- conn->session_ticket_status = S2N_NO_TICKET;
/* Allocate the fixed-size stuffers */
blob = (struct s2n_blob) {0};
- GUARD_PTR(s2n_blob_init(&blob, conn->alert_in_data, S2N_ALERT_LENGTH));
- GUARD_PTR(s2n_stuffer_init(&conn->alert_in, &blob));
+ PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->alert_in_data, S2N_ALERT_LENGTH));
+ PTR_GUARD_POSIX(s2n_stuffer_init(&conn->alert_in, &blob));
blob = (struct s2n_blob) {0};
- GUARD_PTR(s2n_blob_init(&blob, conn->reader_alert_out_data, S2N_ALERT_LENGTH));
- GUARD_PTR(s2n_stuffer_init(&conn->reader_alert_out, &blob));
+ PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->reader_alert_out_data, S2N_ALERT_LENGTH));
+ PTR_GUARD_POSIX(s2n_stuffer_init(&conn->reader_alert_out, &blob));
blob = (struct s2n_blob) {0};
- GUARD_PTR(s2n_blob_init(&blob, conn->writer_alert_out_data, S2N_ALERT_LENGTH));
- GUARD_PTR(s2n_stuffer_init(&conn->writer_alert_out, &blob));
+ PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->writer_alert_out_data, S2N_ALERT_LENGTH));
+ PTR_GUARD_POSIX(s2n_stuffer_init(&conn->writer_alert_out, &blob));
blob = (struct s2n_blob) {0};
- GUARD_PTR(s2n_blob_init(&blob, conn->ticket_ext_data, S2N_TICKET_SIZE_IN_BYTES));
- GUARD_PTR(s2n_stuffer_init(&conn->client_ticket_to_decrypt, &blob));
+ PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->ticket_ext_data, S2N_TLS12_TICKET_SIZE_IN_BYTES));
+ PTR_GUARD_POSIX(s2n_stuffer_init(&conn->client_ticket_to_decrypt, &blob));
/* Allocate long term key memory */
- GUARD_PTR(s2n_session_key_alloc(&conn->secure.client_key));
- GUARD_PTR(s2n_session_key_alloc(&conn->secure.server_key));
- GUARD_PTR(s2n_session_key_alloc(&conn->initial.client_key));
- GUARD_PTR(s2n_session_key_alloc(&conn->initial.server_key));
+ PTR_GUARD_POSIX(s2n_session_key_alloc(&conn->secure.client_key));
+ PTR_GUARD_POSIX(s2n_session_key_alloc(&conn->secure.server_key));
+ PTR_GUARD_POSIX(s2n_session_key_alloc(&conn->initial.client_key));
+ PTR_GUARD_POSIX(s2n_session_key_alloc(&conn->initial.server_key));
/* Allocate long term hash and HMAC memory */
- GUARD_PTR(s2n_prf_new(conn));
-
- GUARD_PTR(s2n_connection_new_hashes(conn));
- GUARD_PTR(s2n_connection_init_hashes(conn));
+ PTR_GUARD_RESULT(s2n_prf_new(conn));
+ PTR_GUARD_RESULT(s2n_handshake_hashes_new(&conn->handshake.hashes));
- GUARD_PTR(s2n_connection_new_hmacs(conn));
- GUARD_PTR(s2n_connection_init_hmacs(conn));
+ PTR_GUARD_POSIX(s2n_connection_new_hmacs(conn));
+ PTR_GUARD_POSIX(s2n_connection_init_hmacs(conn));
/* Initialize the growable stuffers. Zero length at first, but the resize
* in _wipe will fix that
*/
blob = (struct s2n_blob) {0};
- GUARD_PTR(s2n_blob_init(&blob, conn->header_in_data, S2N_TLS_RECORD_HEADER_LENGTH));
- GUARD_PTR(s2n_stuffer_init(&conn->header_in, &blob));
- GUARD_PTR(s2n_stuffer_growable_alloc(&conn->out, 0));
- GUARD_PTR(s2n_stuffer_growable_alloc(&conn->in, 0));
- GUARD_PTR(s2n_stuffer_growable_alloc(&conn->handshake.io, 0));
- GUARD_PTR(s2n_stuffer_growable_alloc(&conn->client_hello.raw_message, 0));
- GUARD_PTR(s2n_connection_wipe(conn));
- GUARD_RESULT_PTR(s2n_timer_start(conn->config, &conn->write_timer));
-
- /* Initialize the cookie stuffer with zero length. If a cookie extension
- * is received, the stuffer will be resized according to the cookie length */
- GUARD_PTR(s2n_stuffer_growable_alloc(&conn->cookie_stuffer, 0));
-
+ PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->header_in_data, S2N_TLS_RECORD_HEADER_LENGTH));
+ PTR_GUARD_POSIX(s2n_stuffer_init(&conn->header_in, &blob));
+ PTR_GUARD_POSIX(s2n_stuffer_growable_alloc(&conn->out, 0));
+ PTR_GUARD_POSIX(s2n_stuffer_growable_alloc(&conn->in, 0));
+ PTR_GUARD_POSIX(s2n_stuffer_growable_alloc(&conn->handshake.io, 0));
+ PTR_GUARD_POSIX(s2n_stuffer_growable_alloc(&conn->client_hello.raw_message, 0));
+ PTR_GUARD_RESULT(s2n_timer_start(conn->config, &conn->write_timer));
+
+ /* NOTE: s2n_connection_wipe MUST be called last in this function.
+ *
+ * s2n_connection_wipe is used for initializing values but also used by customers to
+ * reset/reuse the connection. Calling it last ensures that s2n_connection_wipe is
+ * implemented correctly and safe.
+ */
+ PTR_GUARD_POSIX(s2n_connection_wipe(conn));
return conn;
}
static int s2n_connection_free_keys(struct s2n_connection *conn)
{
- GUARD(s2n_session_key_free(&conn->secure.client_key));
- GUARD(s2n_session_key_free(&conn->secure.server_key));
- GUARD(s2n_session_key_free(&conn->initial.client_key));
- GUARD(s2n_session_key_free(&conn->initial.server_key));
+ POSIX_GUARD(s2n_session_key_free(&conn->secure.client_key));
+ POSIX_GUARD(s2n_session_key_free(&conn->secure.server_key));
+ POSIX_GUARD(s2n_session_key_free(&conn->initial.client_key));
+ POSIX_GUARD(s2n_session_key_free(&conn->initial.server_key));
return 0;
}
@@ -247,35 +166,33 @@ static int s2n_connection_free_keys(struct s2n_connection *conn)
static int s2n_connection_zero(struct s2n_connection *conn, int mode, struct s2n_config *config)
{
/* Zero the whole connection structure */
- memset_check(conn, 0, sizeof(struct s2n_connection));
+ POSIX_CHECKED_MEMSET(conn, 0, sizeof(struct s2n_connection));
- conn->send = NULL;
- conn->recv = NULL;
- conn->send_io_context = NULL;
- conn->recv_io_context = NULL;
conn->mode = mode;
- conn->close_notify_queued = 0;
- conn->client_session_resumed = 0;
- conn->current_user_data_consumed = 0;
conn->initial.cipher_suite = &s2n_null_cipher_suite;
conn->secure.cipher_suite = &s2n_null_cipher_suite;
- conn->initial.kem_params.kem = NULL;
- conn->secure.kem_params.kem = NULL;
conn->server = &conn->initial;
conn->client = &conn->initial;
conn->max_outgoing_fragment_length = S2N_DEFAULT_FRAGMENT_LENGTH;
- conn->mfl_code = S2N_TLS_MAX_FRAG_LEN_EXT_NONE;
- conn->handshake.handshake_type = INITIAL;
- conn->handshake.message_number = 0;
- conn->handshake.paused = 0;
- conn->verify_host_fn = NULL;
- conn->verify_host_fn_overridden = 0;
- conn->data_for_verify_host = NULL;
+ conn->handshake.end_of_messages = APPLICATION_DATA;
s2n_connection_set_config(conn, config);
return 0;
}
+S2N_RESULT s2n_connection_wipe_all_keyshares(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+
+ RESULT_GUARD_POSIX(s2n_ecc_evp_params_free(&conn->kex_params.server_ecc_evp_params));
+ RESULT_GUARD_POSIX(s2n_ecc_evp_params_free(&conn->kex_params.client_ecc_evp_params));
+
+ RESULT_GUARD_POSIX(s2n_kem_group_free(&conn->kex_params.server_kem_group_params));
+ RESULT_GUARD_POSIX(s2n_kem_group_free(&conn->kex_params.client_kem_group_params));
+
+ return S2N_RESULT_OK;
+}
+
static int s2n_connection_wipe_keys(struct s2n_connection *conn)
{
/* Destroy any keys - we call destroy on the object as that is where
@@ -284,52 +201,22 @@ static int s2n_connection_wipe_keys(struct s2n_connection *conn)
&& conn->secure.cipher_suite->record_alg
&& conn->secure.cipher_suite->record_alg->cipher
&& conn->secure.cipher_suite->record_alg->cipher->destroy_key) {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->destroy_key(&conn->secure.client_key));
- GUARD(conn->secure.cipher_suite->record_alg->cipher->destroy_key(&conn->secure.server_key));
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->destroy_key(&conn->secure.client_key));
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->destroy_key(&conn->secure.server_key));
}
/* Free any server key received (we may not have completed a
* handshake, so this may not have been free'd yet) */
- GUARD(s2n_pkey_free(&conn->secure.server_public_key));
- GUARD(s2n_pkey_zero_init(&conn->secure.server_public_key));
- GUARD(s2n_pkey_free(&conn->secure.client_public_key));
- GUARD(s2n_pkey_zero_init(&conn->secure.client_public_key));
+ POSIX_GUARD(s2n_pkey_free(&conn->handshake_params.server_public_key));
+ POSIX_GUARD(s2n_pkey_zero_init(&conn->handshake_params.server_public_key));
+ POSIX_GUARD(s2n_pkey_free(&conn->handshake_params.client_public_key));
+ POSIX_GUARD(s2n_pkey_zero_init(&conn->handshake_params.client_public_key));
s2n_x509_validator_wipe(&conn->x509_validator);
- GUARD(s2n_dh_params_free(&conn->secure.server_dh_params));
- GUARD(s2n_ecc_evp_params_free(&conn->secure.server_ecc_evp_params));
- for (int i=0; i < S2N_ECC_EVP_SUPPORTED_CURVES_COUNT; i++) {
- GUARD(s2n_ecc_evp_params_free(&conn->secure.client_ecc_evp_params[i]));
- }
- GUARD(s2n_kem_group_free(&conn->secure.server_kem_group_params));
- for (int i = 0; i < S2N_SUPPORTED_KEM_GROUPS_COUNT; i++) {
- GUARD(s2n_kem_group_free(&conn->secure.client_kem_group_params[i]));
- }
- GUARD(s2n_kem_free(&conn->secure.kem_params));
- GUARD(s2n_free(&conn->secure.client_cert_chain));
- GUARD(s2n_free(&conn->ct_response));
-
- return 0;
-}
-
-static int s2n_connection_reset_hashes(struct s2n_connection *conn)
-{
- /* Reset all of the Connection's hash states */
- GUARD(s2n_hash_reset(&conn->handshake.md5));
- GUARD(s2n_hash_reset(&conn->handshake.sha1));
- GUARD(s2n_hash_reset(&conn->handshake.sha224));
- GUARD(s2n_hash_reset(&conn->handshake.sha256));
- GUARD(s2n_hash_reset(&conn->handshake.sha384));
- GUARD(s2n_hash_reset(&conn->handshake.sha512));
- GUARD(s2n_hash_reset(&conn->handshake.md5_sha1));
- GUARD(s2n_hash_reset(&conn->handshake.ccv_hash_copy));
- GUARD(s2n_hash_reset(&conn->handshake.prf_md5_hash_copy));
- GUARD(s2n_hash_reset(&conn->handshake.prf_sha1_hash_copy));
- GUARD(s2n_hash_reset(&conn->handshake.prf_tls12_hash_copy));
- GUARD(s2n_hash_reset(&conn->handshake.server_finished_copy));
- GUARD(s2n_hash_reset(&conn->prf_space.ssl3.md5));
- GUARD(s2n_hash_reset(&conn->prf_space.ssl3.sha1));
- GUARD(s2n_hash_reset(&conn->initial.signature_hash));
- GUARD(s2n_hash_reset(&conn->secure.signature_hash));
+ POSIX_GUARD(s2n_dh_params_free(&conn->kex_params.server_dh_params));
+ POSIX_GUARD_RESULT(s2n_connection_wipe_all_keyshares(conn));
+ POSIX_GUARD(s2n_kem_free(&conn->kex_params.kem_params));
+ POSIX_GUARD(s2n_free(&conn->handshake_params.client_cert_chain));
+ POSIX_GUARD(s2n_free(&conn->ct_response));
return 0;
}
@@ -337,66 +224,56 @@ static int s2n_connection_reset_hashes(struct s2n_connection *conn)
static int s2n_connection_reset_hmacs(struct s2n_connection *conn)
{
/* Reset all of the Connection's HMAC states */
- GUARD(s2n_hmac_reset(&conn->initial.client_record_mac));
- GUARD(s2n_hmac_reset(&conn->initial.server_record_mac));
- GUARD(s2n_hmac_reset(&conn->initial.record_mac_copy_workspace));
- GUARD(s2n_hmac_reset(&conn->secure.client_record_mac));
- GUARD(s2n_hmac_reset(&conn->secure.server_record_mac));
- GUARD(s2n_hmac_reset(&conn->secure.record_mac_copy_workspace));
+ POSIX_GUARD(s2n_hmac_reset(&conn->initial.client_record_mac));
+ POSIX_GUARD(s2n_hmac_reset(&conn->initial.server_record_mac));
+ POSIX_GUARD(s2n_hmac_reset(&conn->secure.client_record_mac));
+ POSIX_GUARD(s2n_hmac_reset(&conn->secure.server_record_mac));
return 0;
}
-static int s2n_connection_free_io_contexts(struct s2n_connection *conn)
+static int s2n_connection_free_managed_recv_io(struct s2n_connection *conn)
{
- /* Free the I/O context if it was allocated by s2n. Don't touch user-controlled contexts. */
- if (!conn->managed_io) {
- return 0;
+ POSIX_ENSURE_REF(conn);
+
+ if (conn->managed_recv_io) {
+ POSIX_GUARD(s2n_free_object((uint8_t **)&conn->recv_io_context, sizeof(struct s2n_socket_read_io_context)));
+ conn->managed_recv_io = false;
+ conn->recv = NULL;
}
+ return S2N_SUCCESS;
+}
+
+static int s2n_connection_free_managed_send_io(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
- GUARD(s2n_free_object((uint8_t **)&conn->send_io_context, sizeof(struct s2n_socket_write_io_context)));
- GUARD(s2n_free_object((uint8_t **)&conn->recv_io_context, sizeof(struct s2n_socket_read_io_context)));
+ if (conn->managed_send_io) {
+ POSIX_GUARD(s2n_free_object((uint8_t **)&conn->send_io_context, sizeof(struct s2n_socket_write_io_context)));
+ conn->managed_send_io = false;
+ conn->send = NULL;
+ }
+ return S2N_SUCCESS;
+}
- return 0;
+static int s2n_connection_free_managed_io(struct s2n_connection *conn)
+{
+ POSIX_GUARD(s2n_connection_free_managed_recv_io(conn));
+ POSIX_GUARD(s2n_connection_free_managed_send_io(conn));
+ return S2N_SUCCESS;
}
static int s2n_connection_wipe_io(struct s2n_connection *conn)
{
if (s2n_connection_is_managed_corked(conn) && conn->recv){
- GUARD(s2n_socket_read_restore(conn));
+ POSIX_GUARD(s2n_socket_read_restore(conn));
}
if (s2n_connection_is_managed_corked(conn) && conn->send){
- GUARD(s2n_socket_write_restore(conn));
+ POSIX_GUARD(s2n_socket_write_restore(conn));
}
/* Remove all I/O-related members */
- GUARD(s2n_connection_free_io_contexts(conn));
- conn->managed_io = 0;
- conn->send = NULL;
- conn->recv = NULL;
-
- return 0;
-}
-
-static int s2n_connection_free_hashes(struct s2n_connection *conn)
-{
- /* Free all of the Connection's hash states */
- GUARD(s2n_hash_free(&conn->handshake.md5));
- GUARD(s2n_hash_free(&conn->handshake.sha1));
- GUARD(s2n_hash_free(&conn->handshake.sha224));
- GUARD(s2n_hash_free(&conn->handshake.sha256));
- GUARD(s2n_hash_free(&conn->handshake.sha384));
- GUARD(s2n_hash_free(&conn->handshake.sha512));
- GUARD(s2n_hash_free(&conn->handshake.md5_sha1));
- GUARD(s2n_hash_free(&conn->handshake.ccv_hash_copy));
- GUARD(s2n_hash_free(&conn->handshake.prf_md5_hash_copy));
- GUARD(s2n_hash_free(&conn->handshake.prf_sha1_hash_copy));
- GUARD(s2n_hash_free(&conn->handshake.prf_tls12_hash_copy));
- GUARD(s2n_hash_free(&conn->handshake.server_finished_copy));
- GUARD(s2n_hash_free(&conn->prf_space.ssl3.md5));
- GUARD(s2n_hash_free(&conn->prf_space.ssl3.sha1));
- GUARD(s2n_hash_free(&conn->initial.signature_hash));
- GUARD(s2n_hash_free(&conn->secure.signature_hash));
+ POSIX_GUARD(s2n_connection_free_managed_io(conn));
return 0;
}
@@ -404,12 +281,10 @@ static int s2n_connection_free_hashes(struct s2n_connection *conn)
static int s2n_connection_free_hmacs(struct s2n_connection *conn)
{
/* Free all of the Connection's HMAC states */
- GUARD(s2n_hmac_free(&conn->initial.client_record_mac));
- GUARD(s2n_hmac_free(&conn->initial.server_record_mac));
- GUARD(s2n_hmac_free(&conn->initial.record_mac_copy_workspace));
- GUARD(s2n_hmac_free(&conn->secure.client_record_mac));
- GUARD(s2n_hmac_free(&conn->secure.server_record_mac));
- GUARD(s2n_hmac_free(&conn->secure.record_mac_copy_workspace));
+ POSIX_GUARD(s2n_hmac_free(&conn->initial.client_record_mac));
+ POSIX_GUARD(s2n_hmac_free(&conn->initial.server_record_mac));
+ POSIX_GUARD(s2n_hmac_free(&conn->secure.client_record_mac));
+ POSIX_GUARD(s2n_hmac_free(&conn->secure.server_record_mac));
return 0;
}
@@ -448,42 +323,50 @@ static uint8_t s2n_default_verify_host(const char *host_name, size_t len, void *
return 0;
}
-int s2n_connection_free(struct s2n_connection *conn)
+S2N_CLEANUP_RESULT s2n_connection_ptr_free(struct s2n_connection **conn)
{
- GUARD(s2n_connection_wipe_keys(conn));
- GUARD(s2n_connection_free_keys(conn));
- GUARD_AS_POSIX(s2n_psk_parameters_wipe(&conn->psk_params));
+ RESULT_ENSURE_REF(conn);
+ RESULT_GUARD_POSIX(s2n_connection_free(*conn));
+ *conn = NULL;
+ return S2N_RESULT_OK;
+}
- GUARD(s2n_prf_free(conn));
+int s2n_connection_free(struct s2n_connection *conn)
+{
+ POSIX_GUARD(s2n_connection_wipe_keys(conn));
+ POSIX_GUARD(s2n_connection_free_keys(conn));
+ POSIX_GUARD_RESULT(s2n_psk_parameters_wipe(&conn->psk_params));
- GUARD(s2n_connection_reset_hashes(conn));
- GUARD(s2n_connection_free_hashes(conn));
+ POSIX_GUARD_RESULT(s2n_prf_free(conn));
+ POSIX_GUARD_RESULT(s2n_handshake_hashes_free(&conn->handshake.hashes));
- GUARD(s2n_connection_reset_hmacs(conn));
- GUARD(s2n_connection_free_hmacs(conn));
+ POSIX_GUARD(s2n_connection_reset_hmacs(conn));
+ POSIX_GUARD(s2n_connection_free_hmacs(conn));
- GUARD(s2n_connection_free_io_contexts(conn));
+ POSIX_GUARD(s2n_connection_free_managed_io(conn));
- GUARD(s2n_free(&conn->client_ticket));
- GUARD(s2n_free(&conn->status_response));
- GUARD(s2n_free(&conn->our_quic_transport_parameters));
- GUARD(s2n_free(&conn->peer_quic_transport_parameters));
- GUARD(s2n_stuffer_free(&conn->in));
- GUARD(s2n_stuffer_free(&conn->out));
- GUARD(s2n_stuffer_free(&conn->handshake.io));
+ POSIX_GUARD(s2n_free(&conn->client_ticket));
+ POSIX_GUARD(s2n_free(&conn->status_response));
+ POSIX_GUARD(s2n_free(&conn->our_quic_transport_parameters));
+ POSIX_GUARD(s2n_free(&conn->peer_quic_transport_parameters));
+ POSIX_GUARD(s2n_free(&conn->server_early_data_context));
+ POSIX_GUARD(s2n_free(&conn->tls13_ticket_fields.session_secret));
+ POSIX_GUARD(s2n_stuffer_free(&conn->in));
+ POSIX_GUARD(s2n_stuffer_free(&conn->out));
+ POSIX_GUARD(s2n_stuffer_free(&conn->handshake.io));
s2n_x509_validator_wipe(&conn->x509_validator);
- GUARD(s2n_client_hello_free(&conn->client_hello));
- GUARD(s2n_free(&conn->application_protocols_overridden));
- GUARD(s2n_stuffer_free(&conn->cookie_stuffer));
- GUARD(s2n_free_object((uint8_t **)&conn, sizeof(struct s2n_connection)));
+ POSIX_GUARD(s2n_client_hello_free(&conn->client_hello));
+ POSIX_GUARD(s2n_free(&conn->application_protocols_overridden));
+ POSIX_GUARD(s2n_stuffer_free(&conn->cookie_stuffer));
+ POSIX_GUARD(s2n_free_object((uint8_t **)&conn, sizeof(struct s2n_connection)));
return 0;
}
int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *config)
{
- notnull_check(conn);
- notnull_check(config);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(config);
if (conn->config == config) {
return 0;
@@ -491,7 +374,7 @@ int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *co
/* We only support one client certificate */
if (s2n_config_get_num_default_certs(config) > 1 && conn->mode == S2N_CLIENT) {
- S2N_ERROR(S2N_ERR_TOO_MANY_CERTIFICATES);
+ POSIX_BAIL(S2N_ERR_TOO_MANY_CERTIFICATES);
}
s2n_x509_validator_wipe(&conn->x509_validator);
@@ -505,10 +388,10 @@ int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *co
int8_t dont_need_x509_validation = (conn->mode == S2N_SERVER) && (auth_type == S2N_CERT_AUTH_NONE);
if (config->disable_x509_validation || dont_need_x509_validation) {
- GUARD(s2n_x509_validator_init_no_x509_validation(&conn->x509_validator));
+ POSIX_GUARD(s2n_x509_validator_init_no_x509_validation(&conn->x509_validator));
}
else {
- GUARD(s2n_x509_validator_init(&conn->x509_validator, &config->trust_store, config->check_ocsp));
+ POSIX_GUARD(s2n_x509_validator_init(&conn->x509_validator, &config->trust_store, config->check_ocsp));
if (!conn->verify_host_fn_overridden) {
if (config->verify_host != NULL) {
conn->verify_host_fn = config->verify_host;
@@ -520,18 +403,58 @@ int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *co
}
if (config->max_verify_cert_chain_depth_set) {
- GUARD(s2n_x509_validator_set_max_chain_depth(&conn->x509_validator, config->max_verify_cert_chain_depth));
+ POSIX_GUARD(s2n_x509_validator_set_max_chain_depth(&conn->x509_validator, config->max_verify_cert_chain_depth));
}
}
+ conn->tickets_to_send = config->initial_tickets_to_send;
+
+ if (conn->psk_params.psk_list.len == 0 && !conn->psk_mode_overridden) {
+ POSIX_GUARD(s2n_connection_set_psk_mode(conn, config->psk_mode));
+ conn->psk_mode_overridden = false;
+ }
+
+ /* If at least one certificate does not have a private key configured,
+ * the config must provide an async pkey callback.
+ * The handshake could still fail if the callback doesn't offload the
+ * signature, but this at least catches configuration mistakes.
+ */
+ if (config->no_signing_key) {
+ POSIX_ENSURE(config->async_pkey_cb, S2N_ERR_NO_PRIVATE_KEY);
+ }
+
+ if (config->quic_enabled) {
+ /* If QUIC is ever enabled for a connection via the config,
+ * we should enforce that it can never be disabled by
+ * changing the config.
+ *
+ * Enabling QUIC indicates that the connection is being used by
+ * a QUIC implementation, which never changes. Disabling QUIC
+ * partially through a connection could also potentially be
+ * dangerous, as QUIC handles encryption.
+ */
+ POSIX_GUARD(s2n_connection_enable_quic(conn));
+ }
conn->config = config;
- return 0;
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_server_name_extension_used(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE(conn->mode == S2N_SERVER, S2N_ERR_INVALID_STATE);
+ POSIX_ENSURE(!(conn->handshake.client_hello_received), S2N_ERR_INVALID_STATE);
+
+ conn->server_name_used = 1;
+ return S2N_SUCCESS;
}
int s2n_connection_set_ctx(struct s2n_connection *conn, void *ctx)
{
+ POSIX_ENSURE_REF(conn);
+
conn->context = ctx;
- return 0;
+ return S2N_SUCCESS;
}
void *s2n_connection_get_ctx(struct s2n_connection *conn)
@@ -541,55 +464,51 @@ void *s2n_connection_get_ctx(struct s2n_connection *conn)
int s2n_connection_release_buffers(struct s2n_connection *conn)
{
- notnull_check(conn);
- PRECONDITION_POSIX(s2n_stuffer_validate(&conn->out));
- PRECONDITION_POSIX(s2n_stuffer_validate(&conn->in));
+ POSIX_ENSURE_REF(conn);
+ POSIX_PRECONDITION(s2n_stuffer_validate(&conn->out));
+ POSIX_PRECONDITION(s2n_stuffer_validate(&conn->in));
- ENSURE_POSIX(s2n_stuffer_is_consumed(&conn->out), S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA);
- GUARD(s2n_stuffer_resize(&conn->out, 0));
+ POSIX_ENSURE(s2n_stuffer_is_consumed(&conn->out), S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA);
+ POSIX_GUARD(s2n_stuffer_resize(&conn->out, 0));
- ENSURE_POSIX(s2n_stuffer_is_consumed(&conn->in), S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA);
- GUARD(s2n_stuffer_resize(&conn->in, 0));
+ POSIX_ENSURE(s2n_stuffer_is_consumed(&conn->in), S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA);
+ POSIX_GUARD(s2n_stuffer_resize(&conn->in, 0));
- POSTCONDITION_POSIX(s2n_stuffer_validate(&conn->out));
- POSTCONDITION_POSIX(s2n_stuffer_validate(&conn->in));
+ POSIX_POSTCONDITION(s2n_stuffer_validate(&conn->out));
+ POSIX_POSTCONDITION(s2n_stuffer_validate(&conn->in));
return S2N_SUCCESS;
}
int s2n_connection_free_handshake(struct s2n_connection *conn)
{
/* We are done with the handshake */
- GUARD(s2n_hash_reset(&conn->handshake.md5));
- GUARD(s2n_hash_reset(&conn->handshake.sha1));
- GUARD(s2n_hash_reset(&conn->handshake.sha224));
- GUARD(s2n_hash_reset(&conn->handshake.sha256));
- GUARD(s2n_hash_reset(&conn->handshake.sha384));
- GUARD(s2n_hash_reset(&conn->handshake.sha512));
- GUARD(s2n_hash_reset(&conn->handshake.md5_sha1));
- GUARD(s2n_hash_reset(&conn->handshake.ccv_hash_copy));
- GUARD(s2n_hash_reset(&conn->handshake.prf_md5_hash_copy));
- GUARD(s2n_hash_reset(&conn->handshake.prf_sha1_hash_copy));
- GUARD(s2n_hash_reset(&conn->handshake.prf_tls12_hash_copy));
- GUARD(s2n_hash_reset(&conn->handshake.server_finished_copy));
+ POSIX_GUARD_RESULT(s2n_handshake_hashes_free(&conn->handshake.hashes));
+ POSIX_GUARD_RESULT(s2n_prf_free(conn));
/* Wipe the buffers we are going to free */
- GUARD(s2n_stuffer_wipe(&conn->handshake.io));
- GUARD(s2n_stuffer_wipe(&conn->client_hello.raw_message));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->client_hello.raw_message));
/* Truncate buffers to save memory, we are done with the handshake */
- GUARD(s2n_stuffer_resize(&conn->handshake.io, 0));
- GUARD(s2n_stuffer_resize(&conn->client_hello.raw_message, 0));
+ POSIX_GUARD(s2n_stuffer_resize(&conn->handshake.io, 0));
+ POSIX_GUARD(s2n_stuffer_resize(&conn->client_hello.raw_message, 0));
/* We can free extension data we no longer need */
- GUARD(s2n_free(&conn->client_ticket));
- GUARD(s2n_free(&conn->status_response));
- GUARD(s2n_free(&conn->our_quic_transport_parameters));
- GUARD(s2n_free(&conn->application_protocols_overridden));
- GUARD(s2n_stuffer_free(&conn->cookie_stuffer));
+ POSIX_GUARD(s2n_free(&conn->client_ticket));
+ POSIX_GUARD(s2n_free(&conn->status_response));
+ POSIX_GUARD(s2n_free(&conn->our_quic_transport_parameters));
+ POSIX_GUARD(s2n_free(&conn->application_protocols_overridden));
+ POSIX_GUARD(s2n_stuffer_free(&conn->cookie_stuffer));
return 0;
}
+/* An idempotent operation which initializes values on the connection.
+ *
+ * Called in order to reuse a connection structure for a new connection. Should wipe
+ * any persistent memory, free any temporary memory, and set all fields back to their
+ * defaults.
+ */
int s2n_connection_wipe(struct s2n_connection *conn)
{
/* First make a copy of everything we'd like to save, which isn't very much. */
@@ -609,43 +528,59 @@ int s2n_connection_wipe(struct s2n_connection *conn)
struct s2n_session_key initial_server_key = {0};
struct s2n_session_key secure_client_key = {0};
struct s2n_session_key secure_server_key = {0};
- /* Parts of the PRF working space, hash states, and hmac states will be wiped. Preserve structs to avoid reallocation */
- struct s2n_connection_prf_handles prf_handles = {0};
- struct s2n_connection_hash_handles hash_handles = {0};
+ /* Parts of the hmac states will be wiped. Preserve structs to avoid reallocation */
struct s2n_connection_hmac_handles hmac_handles = {0};
+ /* Some required structures might have been freed to conserve memory between handshakes.
+ * Restore them.
+ */
+ if (!conn->handshake.hashes) {
+ POSIX_GUARD_RESULT(s2n_handshake_hashes_new(&conn->handshake.hashes));
+ }
+ POSIX_GUARD_RESULT(s2n_handshake_hashes_wipe(conn->handshake.hashes));
+ struct s2n_handshake_hashes *handshake_hashes = conn->handshake.hashes;
+ if (!conn->prf_space) {
+ POSIX_GUARD_RESULT(s2n_prf_new(conn));
+ }
+ POSIX_GUARD_RESULT(s2n_prf_wipe(conn));
+ struct s2n_prf_working_space *prf_workspace = conn->prf_space;
+
/* Wipe all of the sensitive stuff */
- GUARD(s2n_connection_wipe_keys(conn));
- GUARD(s2n_connection_reset_hashes(conn));
- GUARD(s2n_connection_reset_hmacs(conn));
- GUARD(s2n_stuffer_wipe(&conn->alert_in));
- GUARD(s2n_stuffer_wipe(&conn->reader_alert_out));
- GUARD(s2n_stuffer_wipe(&conn->writer_alert_out));
- GUARD(s2n_stuffer_wipe(&conn->client_ticket_to_decrypt));
- GUARD(s2n_stuffer_wipe(&conn->handshake.io));
- GUARD(s2n_stuffer_wipe(&conn->client_hello.raw_message));
- GUARD(s2n_stuffer_wipe(&conn->header_in));
- GUARD(s2n_stuffer_wipe(&conn->in));
- GUARD(s2n_stuffer_wipe(&conn->out));
-
- GUARD_AS_POSIX(s2n_psk_parameters_wipe(&conn->psk_params));
+ POSIX_GUARD(s2n_connection_wipe_keys(conn));
+ POSIX_GUARD(s2n_connection_reset_hmacs(conn));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->alert_in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->reader_alert_out));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->writer_alert_out));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->client_ticket_to_decrypt));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->client_hello.raw_message));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->header_in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->out));
+
+ POSIX_GUARD_RESULT(s2n_psk_parameters_wipe(&conn->psk_params));
/* Wipe the I/O-related info and restore the original socket if necessary */
- GUARD(s2n_connection_wipe_io(conn));
-
- GUARD(s2n_free(&conn->client_ticket));
- GUARD(s2n_free(&conn->status_response));
- GUARD(s2n_free(&conn->application_protocols_overridden));
- GUARD(s2n_free(&conn->our_quic_transport_parameters));
- GUARD(s2n_free(&conn->peer_quic_transport_parameters));
+ POSIX_GUARD(s2n_connection_wipe_io(conn));
+
+ POSIX_GUARD(s2n_free(&conn->client_ticket));
+ POSIX_GUARD(s2n_free(&conn->status_response));
+ POSIX_GUARD(s2n_free(&conn->application_protocols_overridden));
+ POSIX_GUARD(s2n_free(&conn->our_quic_transport_parameters));
+ POSIX_GUARD(s2n_free(&conn->peer_quic_transport_parameters));
+ POSIX_GUARD(s2n_free(&conn->server_early_data_context));
+ POSIX_GUARD(s2n_free(&conn->tls13_ticket_fields.session_secret));
+ /* TODO: Simplify cookie_stuffer implementation.
+ * https://github.com/aws/s2n-tls/issues/3287 */
+ POSIX_GUARD(s2n_stuffer_free(&conn->cookie_stuffer));
/* Allocate memory for handling handshakes */
- GUARD(s2n_stuffer_resize(&conn->handshake.io, S2N_LARGE_RECORD_LENGTH));
+ POSIX_GUARD(s2n_stuffer_resize(&conn->handshake.io, S2N_LARGE_RECORD_LENGTH));
/* Truncate the message buffers to save memory, we will dynamically resize it as needed */
- GUARD(s2n_stuffer_resize(&conn->client_hello.raw_message, 0));
- GUARD(s2n_stuffer_resize(&conn->in, 0));
- GUARD(s2n_stuffer_resize(&conn->out, 0));
+ POSIX_GUARD(s2n_stuffer_resize(&conn->client_hello.raw_message, 0));
+ POSIX_GUARD(s2n_stuffer_resize(&conn->in, 0));
+ POSIX_GUARD(s2n_stuffer_resize(&conn->out, 0));
/* Remove context associated with connection */
conn->context = NULL;
@@ -660,53 +595,51 @@ int s2n_connection_wipe(struct s2n_connection *conn)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
#endif
- memcpy_check(&alert_in, &conn->alert_in, sizeof(struct s2n_stuffer));
- memcpy_check(&reader_alert_out, &conn->reader_alert_out, sizeof(struct s2n_stuffer));
- memcpy_check(&writer_alert_out, &conn->writer_alert_out, sizeof(struct s2n_stuffer));
- memcpy_check(&client_ticket_to_decrypt, &conn->client_ticket_to_decrypt, sizeof(struct s2n_stuffer));
- memcpy_check(&handshake_io, &conn->handshake.io, sizeof(struct s2n_stuffer));
- memcpy_check(&client_hello_raw_message, &conn->client_hello.raw_message, sizeof(struct s2n_stuffer));
- memcpy_check(&header_in, &conn->header_in, sizeof(struct s2n_stuffer));
- memcpy_check(&in, &conn->in, sizeof(struct s2n_stuffer));
- memcpy_check(&out, &conn->out, sizeof(struct s2n_stuffer));
- memcpy_check(&initial_client_key, &conn->initial.client_key, sizeof(struct s2n_session_key));
- memcpy_check(&initial_server_key, &conn->initial.server_key, sizeof(struct s2n_session_key));
- memcpy_check(&secure_client_key, &conn->secure.client_key, sizeof(struct s2n_session_key));
- memcpy_check(&secure_server_key, &conn->secure.server_key, sizeof(struct s2n_session_key));
- GUARD(s2n_connection_save_prf_state(&prf_handles, conn));
- GUARD(s2n_connection_save_hash_state(&hash_handles, conn));
- GUARD(s2n_connection_save_hmac_state(&hmac_handles, conn));
+ POSIX_CHECKED_MEMCPY(&alert_in, &conn->alert_in, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&reader_alert_out, &conn->reader_alert_out, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&writer_alert_out, &conn->writer_alert_out, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&client_ticket_to_decrypt, &conn->client_ticket_to_decrypt, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&handshake_io, &conn->handshake.io, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&client_hello_raw_message, &conn->client_hello.raw_message, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&header_in, &conn->header_in, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&in, &conn->in, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&out, &conn->out, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&initial_client_key, &conn->initial.client_key, sizeof(struct s2n_session_key));
+ POSIX_CHECKED_MEMCPY(&initial_server_key, &conn->initial.server_key, sizeof(struct s2n_session_key));
+ POSIX_CHECKED_MEMCPY(&secure_client_key, &conn->secure.client_key, sizeof(struct s2n_session_key));
+ POSIX_CHECKED_MEMCPY(&secure_server_key, &conn->secure.server_key, sizeof(struct s2n_session_key));
+ POSIX_GUARD(s2n_connection_save_hmac_state(&hmac_handles, conn));
#if S2N_GCC_VERSION_AT_LEAST(4,6,0)
#pragma GCC diagnostic pop
#endif
- GUARD(s2n_connection_zero(conn, mode, config));
-
- memcpy_check(&conn->alert_in, &alert_in, sizeof(struct s2n_stuffer));
- memcpy_check(&conn->reader_alert_out, &reader_alert_out, sizeof(struct s2n_stuffer));
- memcpy_check(&conn->writer_alert_out, &writer_alert_out, sizeof(struct s2n_stuffer));
- memcpy_check(&conn->client_ticket_to_decrypt, &client_ticket_to_decrypt, sizeof(struct s2n_stuffer));
- memcpy_check(&conn->handshake.io, &handshake_io, sizeof(struct s2n_stuffer));
- memcpy_check(&conn->client_hello.raw_message, &client_hello_raw_message, sizeof(struct s2n_stuffer));
- memcpy_check(&conn->header_in, &header_in, sizeof(struct s2n_stuffer));
- memcpy_check(&conn->in, &in, sizeof(struct s2n_stuffer));
- memcpy_check(&conn->out, &out, sizeof(struct s2n_stuffer));
- memcpy_check(&conn->initial.client_key, &initial_client_key, sizeof(struct s2n_session_key));
- memcpy_check(&conn->initial.server_key, &initial_server_key, sizeof(struct s2n_session_key));
- memcpy_check(&conn->secure.client_key, &secure_client_key, sizeof(struct s2n_session_key));
- memcpy_check(&conn->secure.server_key, &secure_server_key, sizeof(struct s2n_session_key));
- GUARD(s2n_connection_restore_prf_state(conn, &prf_handles));
- GUARD(s2n_connection_restore_hash_state(conn, &hash_handles));
- GUARD(s2n_connection_restore_hmac_state(conn, &hmac_handles));
+ POSIX_GUARD(s2n_connection_zero(conn, mode, config));
+
+ POSIX_CHECKED_MEMCPY(&conn->alert_in, &alert_in, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&conn->reader_alert_out, &reader_alert_out, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&conn->writer_alert_out, &writer_alert_out, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&conn->client_ticket_to_decrypt, &client_ticket_to_decrypt, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&conn->handshake.io, &handshake_io, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&conn->client_hello.raw_message, &client_hello_raw_message, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&conn->header_in, &header_in, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&conn->in, &in, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&conn->out, &out, sizeof(struct s2n_stuffer));
+ POSIX_CHECKED_MEMCPY(&conn->initial.client_key, &initial_client_key, sizeof(struct s2n_session_key));
+ POSIX_CHECKED_MEMCPY(&conn->initial.server_key, &initial_server_key, sizeof(struct s2n_session_key));
+ POSIX_CHECKED_MEMCPY(&conn->secure.client_key, &secure_client_key, sizeof(struct s2n_session_key));
+ POSIX_CHECKED_MEMCPY(&conn->secure.server_key, &secure_server_key, sizeof(struct s2n_session_key));
+ POSIX_GUARD(s2n_connection_restore_hmac_state(conn, &hmac_handles));
+ conn->handshake.hashes = handshake_hashes;
+ conn->prf_space = prf_workspace;
/* Re-initialize hash and hmac states */
- GUARD(s2n_connection_init_hashes(conn));
- GUARD(s2n_connection_init_hmacs(conn));
+ POSIX_GUARD(s2n_connection_init_hmacs(conn));
- GUARD_AS_POSIX(s2n_psk_parameters_init(&conn->psk_params));
+ POSIX_GUARD_RESULT(s2n_psk_parameters_init(&conn->psk_params));
+ conn->server_keying_material_lifetime = ONE_WEEK_IN_SEC;
/* Require all handshakes hashes. This set can be reduced as the handshake progresses. */
- GUARD(s2n_handshake_require_all_hashes(&conn->handshake));
+ POSIX_GUARD(s2n_handshake_require_all_hashes(&conn->handshake));
if (conn->mode == S2N_SERVER) {
/* Start with the highest protocol version so that the highest common protocol version can be selected */
@@ -723,142 +656,157 @@ int s2n_connection_wipe(struct s2n_connection *conn)
conn->actual_protocol_version = s2n_highest_protocol_version;
}
+ /* Initialize remaining values */
+ conn->blinding = S2N_BUILT_IN_BLINDING;
+ conn->session_ticket_status = S2N_NO_TICKET;
+ /* Initialize the cookie stuffer with zero length. If a cookie extension
+ * is received, the stuffer will be resized according to the cookie length */
+ POSIX_GUARD(s2n_stuffer_growable_alloc(&conn->cookie_stuffer, 0));
+
return 0;
}
int s2n_connection_set_recv_ctx(struct s2n_connection *conn, void *ctx)
{
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD(s2n_connection_free_managed_recv_io(conn));
conn->recv_io_context = ctx;
- return 0;
+ return S2N_SUCCESS;
}
int s2n_connection_set_send_ctx(struct s2n_connection *conn, void *ctx)
{
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD(s2n_connection_free_managed_send_io(conn));
conn->send_io_context = ctx;
- return 0;
+ return S2N_SUCCESS;
}
int s2n_connection_set_recv_cb(struct s2n_connection *conn, s2n_recv_fn recv)
{
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD(s2n_connection_free_managed_recv_io(conn));
conn->recv = recv;
- return 0;
+ return S2N_SUCCESS;
}
int s2n_connection_set_send_cb(struct s2n_connection *conn, s2n_send_fn send)
{
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD(s2n_connection_free_managed_send_io(conn));
conn->send = send;
- return 0;
+ return S2N_SUCCESS;
}
int s2n_connection_get_client_cert_chain(struct s2n_connection *conn, uint8_t **der_cert_chain_out, uint32_t *cert_chain_len)
{
- notnull_check(conn);
- notnull_check(der_cert_chain_out);
- notnull_check(cert_chain_len);
- notnull_check(conn->secure.client_cert_chain.data);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(der_cert_chain_out);
+ POSIX_ENSURE_REF(cert_chain_len);
+ POSIX_ENSURE_REF(conn->handshake_params.client_cert_chain.data);
- *der_cert_chain_out = conn->secure.client_cert_chain.data;
- *cert_chain_len = conn->secure.client_cert_chain.size;
+ *der_cert_chain_out = conn->handshake_params.client_cert_chain.data;
+ *cert_chain_len = conn->handshake_params.client_cert_chain.size;
return 0;
}
int s2n_connection_get_cipher_preferences(struct s2n_connection *conn, const struct s2n_cipher_preferences **cipher_preferences)
{
- notnull_check(conn);
- notnull_check(conn->config);
- notnull_check(cipher_preferences);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->config);
+ POSIX_ENSURE_REF(cipher_preferences);
if (conn->security_policy_override != NULL) {
*cipher_preferences = conn->security_policy_override->cipher_preferences;
} else if (conn->config->security_policy != NULL) {
*cipher_preferences = conn->config->security_policy->cipher_preferences;
} else {
- S2N_ERROR(S2N_ERR_INVALID_CIPHER_PREFERENCES);
+ POSIX_BAIL(S2N_ERR_INVALID_CIPHER_PREFERENCES);
}
- notnull_check(*cipher_preferences);
+ POSIX_ENSURE_REF(*cipher_preferences);
return 0;
}
int s2n_connection_get_security_policy(struct s2n_connection *conn, const struct s2n_security_policy **security_policy)
{
- notnull_check(conn);
- notnull_check(conn->config);
- notnull_check(security_policy);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->config);
+ POSIX_ENSURE_REF(security_policy);
if (conn->security_policy_override != NULL) {
*security_policy = conn->security_policy_override;
} else if (conn->config->security_policy != NULL) {
*security_policy = conn->config->security_policy;
} else {
- S2N_ERROR(S2N_ERR_INVALID_SECURITY_POLICY);
+ POSIX_BAIL(S2N_ERR_INVALID_SECURITY_POLICY);
}
- notnull_check(*security_policy);
+ POSIX_ENSURE_REF(*security_policy);
return 0;
}
int s2n_connection_get_kem_preferences(struct s2n_connection *conn, const struct s2n_kem_preferences **kem_preferences)
{
- notnull_check(conn);
- notnull_check(conn->config);
- notnull_check(kem_preferences);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->config);
+ POSIX_ENSURE_REF(kem_preferences);
if (conn->security_policy_override != NULL) {
*kem_preferences = conn->security_policy_override->kem_preferences;
} else if (conn->config->security_policy != NULL) {
*kem_preferences = conn->config->security_policy->kem_preferences;
} else {
- S2N_ERROR(S2N_ERR_INVALID_KEM_PREFERENCES);
+ POSIX_BAIL(S2N_ERR_INVALID_KEM_PREFERENCES);
}
- notnull_check(*kem_preferences);
+ POSIX_ENSURE_REF(*kem_preferences);
return 0;
}
int s2n_connection_get_signature_preferences(struct s2n_connection *conn, const struct s2n_signature_preferences **signature_preferences)
{
- notnull_check(conn);
- notnull_check(conn->config);
- notnull_check(signature_preferences);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->config);
+ POSIX_ENSURE_REF(signature_preferences);
if (conn->security_policy_override != NULL) {
*signature_preferences = conn->security_policy_override->signature_preferences;
} else if (conn->config->security_policy != NULL) {
*signature_preferences = conn->config->security_policy->signature_preferences;
} else {
- S2N_ERROR(S2N_ERR_INVALID_SIGNATURE_ALGORITHMS_PREFERENCES);
+ POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_ALGORITHMS_PREFERENCES);
}
- notnull_check(*signature_preferences);
+ POSIX_ENSURE_REF(*signature_preferences);
return 0;
}
int s2n_connection_get_ecc_preferences(struct s2n_connection *conn, const struct s2n_ecc_preferences **ecc_preferences)
{
- notnull_check(conn);
- notnull_check(conn->config);
- notnull_check(ecc_preferences);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->config);
+ POSIX_ENSURE_REF(ecc_preferences);
if (conn->security_policy_override != NULL) {
*ecc_preferences = conn->security_policy_override->ecc_preferences;
} else if (conn->config->security_policy != NULL) {
*ecc_preferences = conn->config->security_policy->ecc_preferences;
} else {
- S2N_ERROR(S2N_ERR_INVALID_ECC_PREFERENCES);
+ POSIX_BAIL(S2N_ERR_INVALID_ECC_PREFERENCES);
}
- notnull_check(*ecc_preferences);
+ POSIX_ENSURE_REF(*ecc_preferences);
return 0;
}
int s2n_connection_get_protocol_preferences(struct s2n_connection *conn, struct s2n_blob **protocol_preferences)
{
- notnull_check(conn);
- notnull_check(protocol_preferences);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(protocol_preferences);
*protocol_preferences = NULL;
if (conn->application_protocols_overridden.size > 0) {
@@ -867,18 +815,19 @@ int s2n_connection_get_protocol_preferences(struct s2n_connection *conn, struct
*protocol_preferences = &conn->config->application_protocols;
}
- notnull_check(*protocol_preferences);
+ POSIX_ENSURE_REF(*protocol_preferences);
return 0;
}
int s2n_connection_get_client_auth_type(struct s2n_connection *conn, s2n_cert_auth_type *client_cert_auth_type)
{
- notnull_check(conn);
- notnull_check(client_cert_auth_type);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(client_cert_auth_type);
if (conn->client_cert_auth_type_overridden) {
*client_cert_auth_type = conn->client_cert_auth_type;
} else {
+ POSIX_ENSURE_REF(conn->config);
*client_cert_auth_type = conn->config->client_cert_auth_type;
}
@@ -897,42 +846,55 @@ int s2n_connection_set_read_fd(struct s2n_connection *conn, int rfd)
struct s2n_blob ctx_mem = {0};
struct s2n_socket_read_io_context *peer_socket_ctx;
- GUARD(s2n_alloc(&ctx_mem, sizeof(struct s2n_socket_read_io_context)));
- GUARD(s2n_blob_zero(&ctx_mem));
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD(s2n_alloc(&ctx_mem, sizeof(struct s2n_socket_read_io_context)));
+ POSIX_GUARD(s2n_blob_zero(&ctx_mem));
peer_socket_ctx = (struct s2n_socket_read_io_context *)(void *)ctx_mem.data;
peer_socket_ctx->fd = rfd;
- s2n_connection_set_recv_cb(conn, s2n_socket_read);
- s2n_connection_set_recv_ctx(conn, peer_socket_ctx);
- conn->managed_io = 1;
+ POSIX_GUARD(s2n_connection_set_recv_cb(conn, s2n_socket_read));
+ POSIX_GUARD(s2n_connection_set_recv_ctx(conn, peer_socket_ctx));
+ conn->managed_recv_io = true;
/* This is only needed if the user is using corked io.
* Take the snapshot in case optimized io is enabled after setting the fd.
*/
- GUARD(s2n_socket_read_snapshot(conn));
+ POSIX_GUARD(s2n_socket_read_snapshot(conn));
return 0;
}
+int s2n_connection_get_read_fd(struct s2n_connection *conn, int *readfd)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(readfd);
+ POSIX_ENSURE((conn->managed_recv_io && conn->recv_io_context), S2N_ERR_INVALID_STATE);
+
+ const struct s2n_socket_read_io_context *peer_socket_ctx = conn->recv_io_context;
+ *readfd = peer_socket_ctx->fd;
+ return S2N_SUCCESS;
+}
+
int s2n_connection_set_write_fd(struct s2n_connection *conn, int wfd)
{
struct s2n_blob ctx_mem = {0};
struct s2n_socket_write_io_context *peer_socket_ctx;
- GUARD(s2n_alloc(&ctx_mem, sizeof(struct s2n_socket_write_io_context)));
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD(s2n_alloc(&ctx_mem, sizeof(struct s2n_socket_write_io_context)));
peer_socket_ctx = (struct s2n_socket_write_io_context *)(void *)ctx_mem.data;
peer_socket_ctx->fd = wfd;
- s2n_connection_set_send_cb(conn, s2n_socket_write);
- s2n_connection_set_send_ctx(conn, peer_socket_ctx);
- conn->managed_io = 1;
+ POSIX_GUARD(s2n_connection_set_send_cb(conn, s2n_socket_write));
+ POSIX_GUARD(s2n_connection_set_send_ctx(conn, peer_socket_ctx));
+ conn->managed_send_io = true;
/* This is only needed if the user is using corked io.
* Take the snapshot in case optimized io is enabled after setting the fd.
*/
- GUARD(s2n_socket_write_snapshot(conn));
+ POSIX_GUARD(s2n_socket_write_snapshot(conn));
uint8_t ipv6;
if (0 == s2n_socket_is_ipv6(wfd, &ipv6)) {
@@ -944,19 +906,29 @@ int s2n_connection_set_write_fd(struct s2n_connection *conn, int wfd)
return 0;
}
+int s2n_connection_get_write_fd(struct s2n_connection *conn, int *writefd)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(writefd);
+ POSIX_ENSURE((conn->managed_send_io && conn->send_io_context), S2N_ERR_INVALID_STATE);
+
+ const struct s2n_socket_write_io_context *peer_socket_ctx = conn->send_io_context;
+ *writefd = peer_socket_ctx->fd;
+ return S2N_SUCCESS;
+}
int s2n_connection_set_fd(struct s2n_connection *conn, int fd)
{
- GUARD(s2n_connection_set_read_fd(conn, fd));
- GUARD(s2n_connection_set_write_fd(conn, fd));
+ POSIX_GUARD(s2n_connection_set_read_fd(conn, fd));
+ POSIX_GUARD(s2n_connection_set_write_fd(conn, fd));
return 0;
}
int s2n_connection_use_corked_io(struct s2n_connection *conn)
{
- if (!conn->managed_io) {
- /* Caller shouldn't be trying to set s2n IO corked on non-s2n-managed IO */
- S2N_ERROR(S2N_ERR_CORK_SET_ON_UNMANAGED);
- }
+ POSIX_ENSURE_REF(conn);
+
+ /* Caller shouldn't be trying to set s2n IO corked on non-s2n-managed IO */
+ POSIX_ENSURE(conn->managed_send_io, S2N_ERR_CORK_SET_ON_UNMANAGED);
conn->corked_io = 1;
return 0;
@@ -974,79 +946,106 @@ uint64_t s2n_connection_get_wire_bytes_out(struct s2n_connection *conn)
const char *s2n_connection_get_cipher(struct s2n_connection *conn)
{
- notnull_check_ptr(conn);
- notnull_check_ptr(conn->secure.cipher_suite);
+ PTR_ENSURE_REF(conn);
+ PTR_ENSURE_REF(conn->secure.cipher_suite);
return conn->secure.cipher_suite->name;
}
+int s2n_connection_get_cipher_iana_value(struct s2n_connection *conn, uint8_t *first, uint8_t *second)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite);
+ POSIX_ENSURE_MUT(first);
+ POSIX_ENSURE_MUT(second);
+
+ /* ensure we've negotiated a cipher suite */
+ POSIX_ENSURE(
+ memcmp(
+ conn->secure.cipher_suite->iana_value,
+ s2n_null_cipher_suite.iana_value,
+ sizeof(s2n_null_cipher_suite.iana_value)
+ ) != 0,
+ S2N_ERR_INVALID_STATE
+ );
+
+ const uint8_t *iana_value = conn->secure.cipher_suite->iana_value;
+ *first = iana_value[0];
+ *second = iana_value[1];
+
+ return S2N_SUCCESS;
+}
+
const char *s2n_connection_get_curve(struct s2n_connection *conn)
{
- notnull_check_ptr(conn);
+ PTR_ENSURE_REF(conn);
- if (!conn->secure.server_ecc_evp_params.negotiated_curve) {
- return "NONE";
+ if (conn->kex_params.server_ecc_evp_params.negotiated_curve) {
+ /* TLS1.3 currently only uses ECC groups. */
+ if (conn->actual_protocol_version >= S2N_TLS13 || s2n_kex_includes(conn->secure.cipher_suite->key_exchange_alg, &s2n_ecdhe)) {
+ return conn->kex_params.server_ecc_evp_params.negotiated_curve->name;
+ }
}
- return conn->secure.server_ecc_evp_params.negotiated_curve->name;
+ return "NONE";
}
const char *s2n_connection_get_kem_name(struct s2n_connection *conn)
{
- notnull_check_ptr(conn);
+ PTR_ENSURE_REF(conn);
- if (!conn->secure.kem_params.kem) {
+ if (!conn->kex_params.kem_params.kem) {
return "NONE";
}
- return conn->secure.kem_params.kem->name;
+ return conn->kex_params.kem_params.kem->name;
}
const char *s2n_connection_get_kem_group_name(struct s2n_connection *conn)
{
- notnull_check_ptr(conn);
+ PTR_ENSURE_REF(conn);
- if (!conn->secure.chosen_client_kem_group_params || !conn->secure.chosen_client_kem_group_params->kem_group) {
+ if (conn->actual_protocol_version < S2N_TLS13 || !conn->kex_params.client_kem_group_params.kem_group) {
return "NONE";
}
- return conn->secure.chosen_client_kem_group_params->kem_group->name;
+ return conn->kex_params.client_kem_group_params.kem_group->name;
}
int s2n_connection_get_client_protocol_version(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
return conn->client_protocol_version;
}
int s2n_connection_get_server_protocol_version(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
return conn->server_protocol_version;
}
int s2n_connection_get_actual_protocol_version(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
return conn->actual_protocol_version;
}
int s2n_connection_get_client_hello_version(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
return conn->client_hello_version;
}
int s2n_connection_client_cert_used(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
- if ((conn->handshake.handshake_type & CLIENT_AUTH) && is_handshake_complete(conn)) {
- if (conn->handshake.handshake_type & NO_CLIENT_CERT) {
+ if (IS_CLIENT_AUTH_HANDSHAKE(conn) && is_handshake_complete(conn)) {
+ if (IS_CLIENT_AUTH_NO_CERT(conn)) {
return 0;
}
return 1;
@@ -1056,41 +1055,41 @@ int s2n_connection_client_cert_used(struct s2n_connection *conn)
int s2n_connection_get_alert(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
S2N_ERROR_IF(s2n_stuffer_data_available(&conn->alert_in) != 2, S2N_ERR_NO_ALERT);
uint8_t alert_code = 0;
- GUARD(s2n_stuffer_read_uint8(&conn->alert_in, &alert_code));
- GUARD(s2n_stuffer_read_uint8(&conn->alert_in, &alert_code));
+ POSIX_GUARD(s2n_stuffer_read_uint8(&conn->alert_in, &alert_code));
+ POSIX_GUARD(s2n_stuffer_read_uint8(&conn->alert_in, &alert_code));
return alert_code;
}
int s2n_set_server_name(struct s2n_connection *conn, const char *server_name)
{
- notnull_check(conn);
- notnull_check(server_name);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(server_name);
S2N_ERROR_IF(conn->mode != S2N_CLIENT, S2N_ERR_CLIENT_MODE);
int len = strlen(server_name);
S2N_ERROR_IF(len > S2N_MAX_SERVER_NAME, S2N_ERR_SERVER_NAME_TOO_LONG);
- memcpy_check(conn->server_name, server_name, len);
+ POSIX_CHECKED_MEMCPY(conn->server_name, server_name, len);
return 0;
}
const char *s2n_get_server_name(struct s2n_connection *conn)
{
- notnull_check_ptr(conn);
+ PTR_ENSURE_REF(conn);
if (conn->server_name[0]) {
return conn->server_name;
}
- GUARD_PTR(s2n_extension_process(&s2n_client_server_name_extension, conn, &conn->client_hello.extensions));
+ PTR_GUARD_POSIX(s2n_extension_process(&s2n_client_server_name_extension, conn, &conn->client_hello.extensions));
if (!conn->server_name[0]) {
return NULL;
@@ -1101,7 +1100,7 @@ const char *s2n_get_server_name(struct s2n_connection *conn)
const char *s2n_get_application_protocol(struct s2n_connection *conn)
{
- notnull_check_ptr(conn);
+ PTR_ENSURE_REF(conn);
if (strlen(conn->application_protocol) == 0) {
return NULL;
@@ -1112,27 +1111,31 @@ const char *s2n_get_application_protocol(struct s2n_connection *conn)
int s2n_connection_get_session_id_length(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
+ /* Stateful session resumption in TLS1.3 using session id is not yet supported. */
+ if (conn->actual_protocol_version >= S2N_TLS13) {
+ return 0;
+ }
return conn->session_id_len;
}
int s2n_connection_get_session_id(struct s2n_connection *conn, uint8_t *session_id, size_t max_length)
{
- notnull_check(conn);
- notnull_check(session_id);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(session_id);
int session_id_len = s2n_connection_get_session_id_length(conn);
S2N_ERROR_IF(session_id_len > max_length, S2N_ERR_SESSION_ID_TOO_LONG);
- memcpy_check(session_id, conn->session_id, session_id_len);
+ POSIX_CHECKED_MEMCPY(session_id, conn->session_id, session_id_len);
return session_id_len;
}
int s2n_connection_set_blinding(struct s2n_connection *conn, s2n_blinding blinding)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
conn->blinding = blinding;
return 0;
@@ -1149,7 +1152,7 @@ uint64_t s2n_connection_get_delay(struct s2n_connection *conn)
uint64_t elapsed;
/* This will cast -1 to max uint64_t */
- GUARD_AS_POSIX(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed));
+ POSIX_GUARD_RESULT(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed));
if (elapsed > conn->delay) {
return 0;
@@ -1158,9 +1161,53 @@ uint64_t s2n_connection_get_delay(struct s2n_connection *conn)
return conn->delay - elapsed;
}
+S2N_CLEANUP_RESULT s2n_connection_apply_error_blinding(struct s2n_connection **conn)
+{
+ RESULT_ENSURE_REF(conn);
+ if (*conn == NULL) {
+ return S2N_RESULT_OK;
+ }
+
+ int error_code = s2n_errno;
+ int error_type = s2n_error_get_type(error_code);
+
+ switch(error_type) {
+ case S2N_ERR_T_OK:
+ /* Ignore no error */
+ return S2N_RESULT_OK;
+ case S2N_ERR_T_BLOCKED:
+ /* All blocking errors are retriable and should trigger no further action. */
+ return S2N_RESULT_OK;
+ default:
+ break;
+ }
+
+ switch(error_code) {
+ /* Don't invoke blinding on some of the common errors.
+ *
+ * Be careful adding new errors here. Disabling blinding for an
+ * error that can be triggered by secret / encrypted values can
+ * potentially lead to a side channel attack.
+ *
+ * We may want to someday add an explicit error type for these errors.
+ */
+ case S2N_ERR_CANCELLED:
+ case S2N_ERR_CIPHER_NOT_SUPPORTED:
+ case S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED:
+ (*conn)->closed = 1;
+ break;
+ default:
+ /* Apply blinding to all other errors */
+ RESULT_GUARD_POSIX(s2n_connection_kill(*conn));
+ break;
+ }
+
+ return S2N_RESULT_OK;
+}
+
int s2n_connection_kill(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
conn->closed = 1;
@@ -1169,12 +1216,12 @@ int s2n_connection_kill(struct s2n_connection *conn)
/* Keep track of the delay so that it can be enforced */
uint64_t rand_delay = 0;
- GUARD_AS_POSIX(s2n_public_random(max - min, &rand_delay));
+ POSIX_GUARD_RESULT(s2n_public_random(max - min, &rand_delay));
conn->delay = min + rand_delay;
/* Restart the write timer */
- GUARD_AS_POSIX(s2n_timer_start(conn->config, &conn->write_timer));
+ POSIX_GUARD_RESULT(s2n_timer_start(conn->config, &conn->write_timer));
if (conn->blinding == S2N_BUILT_IN_BLINDING) {
struct timespec sleep_time = {.tv_sec = conn->delay / ONE_S,.tv_nsec = conn->delay % ONE_S };
@@ -1191,38 +1238,56 @@ int s2n_connection_kill(struct s2n_connection *conn)
const uint8_t *s2n_connection_get_ocsp_response(struct s2n_connection *conn, uint32_t * length)
{
- notnull_check_ptr(conn);
- notnull_check_ptr(length);
+ PTR_ENSURE_REF(conn);
+ PTR_ENSURE_REF(length);
*length = conn->status_response.size;
return conn->status_response.data;
}
-int s2n_connection_prefer_throughput(struct s2n_connection *conn)
+S2N_RESULT s2n_connection_set_max_fragment_length(struct s2n_connection *conn, uint16_t max_frag_length)
{
- notnull_check(conn);
+ RESULT_ENSURE_REF(conn);
- if (!conn->mfl_code) {
- conn->max_outgoing_fragment_length = S2N_LARGE_FRAGMENT_LENGTH;
+ if (conn->negotiated_mfl_code) {
+ /* Respect the upper limit agreed on with the peer */
+ RESULT_ENSURE_LT(conn->negotiated_mfl_code, s2n_array_len(mfl_code_to_length));
+ conn->max_outgoing_fragment_length = MIN(mfl_code_to_length[conn->negotiated_mfl_code], max_frag_length);
+ } else {
+ conn->max_outgoing_fragment_length = max_frag_length;
}
- return 0;
+ /* If no buffer has been initialized yet, no need to resize.
+ * The standard I/O logic will handle initializing the buffer.
+ */
+ if (s2n_stuffer_is_freed(&conn->out)) {
+ return S2N_RESULT_OK;
+ }
+
+ uint16_t max_wire_record_size = 0;
+ RESULT_GUARD(s2n_record_max_write_size(conn, conn->max_outgoing_fragment_length, &max_wire_record_size));
+ if ((conn->out.blob.size < max_wire_record_size)) {
+ RESULT_GUARD_POSIX(s2n_realloc(&conn->out.blob, max_wire_record_size));
+ }
+
+ return S2N_RESULT_OK;
}
-int s2n_connection_prefer_low_latency(struct s2n_connection *conn)
+int s2n_connection_prefer_throughput(struct s2n_connection *conn)
{
- notnull_check(conn);
-
- if (!conn->mfl_code) {
- conn->max_outgoing_fragment_length = S2N_SMALL_FRAGMENT_LENGTH;
- }
+ POSIX_GUARD_RESULT(s2n_connection_set_max_fragment_length(conn, S2N_LARGE_FRAGMENT_LENGTH));
+ return S2N_SUCCESS;
+}
- return 0;
+int s2n_connection_prefer_low_latency(struct s2n_connection *conn)
+{
+ POSIX_GUARD_RESULT(s2n_connection_set_max_fragment_length(conn, S2N_SMALL_FRAGMENT_LENGTH));
+ return S2N_SUCCESS;
}
int s2n_connection_set_dynamic_record_threshold(struct s2n_connection *conn, uint32_t resize_threshold, uint16_t timeout_threshold)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
S2N_ERROR_IF(resize_threshold > S2N_TLS_MAX_RESIZE_THRESHOLD, S2N_ERR_INVALID_DYNAMIC_THRESHOLD);
conn->dynamic_record_resize_threshold = resize_threshold;
@@ -1231,7 +1296,7 @@ int s2n_connection_set_dynamic_record_threshold(struct s2n_connection *conn, uin
}
int s2n_connection_set_verify_host_callback(struct s2n_connection *conn, s2n_verify_host_fn verify_host_fn, void *data) {
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
conn->verify_host_fn = verify_host_fn;
conn->data_for_verify_host = data;
@@ -1242,9 +1307,9 @@ int s2n_connection_set_verify_host_callback(struct s2n_connection *conn, s2n_ver
int s2n_connection_recv_stuffer(struct s2n_stuffer *stuffer, struct s2n_connection *conn, uint32_t len)
{
- notnull_check(conn->recv);
+ POSIX_ENSURE_REF(conn->recv);
/* Make sure we have enough space to write */
- GUARD(s2n_stuffer_reserve_space(stuffer, len));
+ POSIX_GUARD(s2n_stuffer_reserve_space(stuffer, len));
int r = 0;
do {
@@ -1254,16 +1319,16 @@ int s2n_connection_recv_stuffer(struct s2n_stuffer *stuffer, struct s2n_connecti
} while (r < 0);
/* Record just how many bytes we have written */
- GUARD(s2n_stuffer_skip_write(stuffer, r));
+ POSIX_GUARD(s2n_stuffer_skip_write(stuffer, r));
return r;
}
int s2n_connection_send_stuffer(struct s2n_stuffer *stuffer, struct s2n_connection *conn, uint32_t len)
{
- notnull_check(conn);
- notnull_check(conn->send);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->send);
if (conn->write_fd_broken) {
- S2N_ERROR(S2N_ERR_SEND_STUFFER_TO_CONN);
+ POSIX_BAIL(S2N_ERR_SEND_STUFFER_TO_CONN);
}
/* Make sure we even have the data */
S2N_ERROR_IF(s2n_stuffer_data_available(stuffer) < len, S2N_ERR_STUFFER_OUT_OF_DATA);
@@ -1278,15 +1343,15 @@ int s2n_connection_send_stuffer(struct s2n_stuffer *stuffer, struct s2n_connecti
S2N_ERROR_IF(w < 0 && errno != EINTR, S2N_ERR_SEND_STUFFER_TO_CONN);
} while (w < 0);
- GUARD(s2n_stuffer_skip_read(stuffer, w));
+ POSIX_GUARD(s2n_stuffer_skip_read(stuffer, w));
return w;
}
int s2n_connection_is_managed_corked(const struct s2n_connection *s2n_connection)
{
- notnull_check(s2n_connection);
+ POSIX_ENSURE_REF(s2n_connection);
- return (s2n_connection->managed_io && s2n_connection->corked_io);
+ return (s2n_connection->managed_send_io && s2n_connection->corked_io);
}
const uint8_t *s2n_connection_get_sct_list(struct s2n_connection *conn, uint32_t *length)
@@ -1302,14 +1367,14 @@ const uint8_t *s2n_connection_get_sct_list(struct s2n_connection *conn, uint32_t
int s2n_connection_is_client_auth_enabled(struct s2n_connection *s2n_connection)
{
s2n_cert_auth_type auth_type;
- GUARD(s2n_connection_get_client_auth_type(s2n_connection, &auth_type));
+ POSIX_GUARD(s2n_connection_get_client_auth_type(s2n_connection, &auth_type));
return (auth_type != S2N_CERT_AUTH_NONE);
}
struct s2n_cert_chain_and_key *s2n_connection_get_selected_cert(struct s2n_connection *conn)
{
- notnull_check_ptr(conn);
+ PTR_ENSURE_REF(conn);
return conn->handshake_params.our_chain_and_key;
}
@@ -1329,26 +1394,168 @@ uint8_t s2n_connection_get_protocol_version(const struct s2n_connection *conn)
return conn->server_protocol_version;
}
-int s2n_connection_set_keyshare_by_name_for_testing(struct s2n_connection *conn, const char* curve_name)
+DEFINE_POINTER_CLEANUP_FUNC(struct s2n_cert_chain *, s2n_cert_chain_free);
+
+int s2n_connection_get_peer_cert_chain(const struct s2n_connection *conn, struct s2n_cert_chain_and_key *cert_chain_and_key)
{
- ENSURE_POSIX(S2N_IN_TEST, S2N_ERR_NOT_IN_TEST);
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(cert_chain_and_key);
+
+ DEFER_CLEANUP(struct s2n_cert_chain *cert_chain = cert_chain_and_key->cert_chain, s2n_cert_chain_free_pointer);
+ struct s2n_cert **insert = &cert_chain->head;
+ POSIX_ENSURE(*insert == NULL, S2N_ERR_INVALID_ARGUMENT);
+
+ const struct s2n_x509_validator *validator = &conn->x509_validator;
+ POSIX_ENSURE_REF(validator);
+ POSIX_ENSURE(s2n_x509_validator_is_cert_chain_validated(validator), S2N_ERR_CERT_NOT_VALIDATED);
+
+ /* X509_STORE_CTX_get1_chain() returns a validated cert chain if a previous call to X509_verify_cert() was successful.
+ * X509_STORE_CTX_get0_chain() is a better API because it doesn't return a copy. But it's not available for Openssl 1.0.2.
+ * See the comments here:
+ * https://www.openssl.org/docs/man1.0.2/man3/X509_STORE_CTX_get1_chain.html
+ */
+ DEFER_CLEANUP(STACK_OF(X509) *cert_chain_validated = X509_STORE_CTX_get1_chain(validator->store_ctx),
+ s2n_openssl_x509_stack_pop_free);
+ POSIX_ENSURE_REF(cert_chain_validated);
+
+ for (size_t cert_idx = 0; cert_idx < sk_X509_num(cert_chain_validated); cert_idx++) {
+ X509 *cert = sk_X509_value(cert_chain_validated, cert_idx);
+ POSIX_ENSURE_REF(cert);
+ DEFER_CLEANUP(uint8_t *cert_data = NULL, s2n_crypto_free);
+ int cert_size = i2d_X509(cert, &cert_data);
+ POSIX_ENSURE_GT(cert_size, 0);
- if (!strcmp(curve_name, "none")) {
- S2N_SET_KEY_SHARE_LIST_EMPTY(conn->preferred_key_shares);
- return S2N_SUCCESS;
+ struct s2n_blob mem = { 0 };
+ POSIX_GUARD(s2n_alloc(&mem, sizeof(struct s2n_cert)));
+
+ struct s2n_cert *new_node = (struct s2n_cert *)(void *)mem.data;
+ POSIX_ENSURE_REF(new_node);
+
+ new_node->next = NULL;
+ *insert = new_node;
+ insert = &new_node->next;
+
+ POSIX_GUARD(s2n_alloc(&new_node->raw, cert_size));
+ POSIX_CHECKED_MEMCPY(new_node->raw.data, cert_data, cert_size);
}
- const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ ZERO_TO_DISABLE_DEFER_CLEANUP(cert_chain);
- for (size_t i = 0; i < ecc_pref->count; i++) {
- if (!strcmp(ecc_pref->ecc_curves[i]->name, curve_name)) {
- S2N_SET_KEY_SHARE_REQUEST(conn->preferred_key_shares, i);
- return S2N_SUCCESS;
- }
+ return S2N_SUCCESS;
+}
+
+static S2N_RESULT s2n_signature_scheme_to_tls_iana(struct s2n_signature_scheme *sig_scheme, s2n_tls_hash_algorithm *converted_scheme)
+{
+ RESULT_ENSURE_REF(sig_scheme);
+ RESULT_ENSURE_REF(converted_scheme);
+
+ switch (sig_scheme->hash_alg) {
+ case S2N_HASH_MD5:
+ *converted_scheme = S2N_TLS_HASH_MD5;
+ break;
+ case S2N_HASH_SHA1:
+ *converted_scheme = S2N_TLS_HASH_SHA1;
+ break;
+ case S2N_HASH_SHA224:
+ *converted_scheme = S2N_TLS_HASH_SHA224;
+ break;
+ case S2N_HASH_SHA256:
+ *converted_scheme = S2N_TLS_HASH_SHA256;
+ break;
+ case S2N_HASH_SHA384:
+ *converted_scheme = S2N_TLS_HASH_SHA384;
+ break;
+ case S2N_HASH_SHA512:
+ *converted_scheme = S2N_TLS_HASH_SHA512;
+ break;
+ case S2N_HASH_MD5_SHA1:
+ *converted_scheme = S2N_TLS_HASH_MD5_SHA1;
+ break;
+ default:
+ *converted_scheme = S2N_TLS_HASH_NONE;
+ break;
+ }
+
+ return S2N_RESULT_OK;
+}
+
+int s2n_connection_get_selected_digest_algorithm(struct s2n_connection *conn, s2n_tls_hash_algorithm *converted_scheme)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(converted_scheme);
+
+ POSIX_GUARD_RESULT(s2n_signature_scheme_to_tls_iana(&conn->handshake_params.conn_sig_scheme, converted_scheme));
+
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_get_selected_client_cert_digest_algorithm(struct s2n_connection *conn, s2n_tls_hash_algorithm *converted_scheme)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(converted_scheme);
+
+ POSIX_GUARD_RESULT(s2n_signature_scheme_to_tls_iana(&conn->handshake_params.client_cert_sig_scheme, converted_scheme));
+ return S2N_SUCCESS;
+}
+
+static S2N_RESULT s2n_signature_scheme_to_signature_algorithm(struct s2n_signature_scheme *sig_scheme, s2n_tls_signature_algorithm *converted_scheme)
+{
+ RESULT_ENSURE_REF(sig_scheme);
+ RESULT_ENSURE_REF(converted_scheme);
+
+ switch (sig_scheme->sig_alg) {
+ case S2N_SIGNATURE_RSA:
+ *converted_scheme = S2N_TLS_SIGNATURE_RSA;
+ break;
+ case S2N_SIGNATURE_ECDSA:
+ *converted_scheme = S2N_TLS_SIGNATURE_ECDSA;
+ break;
+ case S2N_SIGNATURE_RSA_PSS_RSAE:
+ *converted_scheme = S2N_TLS_SIGNATURE_RSA_PSS_RSAE;
+ break;
+ case S2N_SIGNATURE_RSA_PSS_PSS:
+ *converted_scheme = S2N_TLS_SIGNATURE_RSA_PSS_PSS;
+ break;
+ default:
+ *converted_scheme = S2N_TLS_SIGNATURE_ANONYMOUS;
+ break;
}
- S2N_ERROR(S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
+ return S2N_RESULT_OK;
+}
+
+int s2n_connection_get_selected_signature_algorithm(struct s2n_connection *conn, s2n_tls_signature_algorithm *converted_scheme)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(converted_scheme);
+
+ POSIX_GUARD_RESULT(s2n_signature_scheme_to_signature_algorithm(&conn->handshake_params.conn_sig_scheme, converted_scheme));
+
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_get_selected_client_cert_signature_algorithm(struct s2n_connection *conn, s2n_tls_signature_algorithm *converted_scheme)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(converted_scheme);
+
+ POSIX_GUARD_RESULT(s2n_signature_scheme_to_signature_algorithm(&conn->handshake_params.client_cert_sig_scheme, converted_scheme));
+
+ return S2N_SUCCESS;
+}
+
+/*
+ * Gets the config set on the connection.
+ */
+int s2n_connection_get_config(struct s2n_connection *conn, struct s2n_config **config) {
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(config);
+
+ if (s2n_fetch_default_config() == conn->config) {
+ POSIX_BAIL(S2N_ERR_NULL);
+ }
+
+ *config = conn->config;
+
+ return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.h b/contrib/restricted/aws/s2n/tls/s2n_connection.h
index 9864111db1..0332241d63 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection.h
@@ -16,7 +16,7 @@
#pragma once
#include <errno.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include <signal.h>
#include <stdint.h>
@@ -25,15 +25,17 @@
#include "tls/s2n_client_hello.h"
#include "tls/s2n_config.h"
#include "tls/s2n_crypto.h"
+#include "tls/s2n_early_data.h"
+#include "tls/s2n_ecc_preferences.h"
#include "tls/s2n_handshake.h"
+#include "tls/s2n_kem_preferences.h"
+#include "tls/s2n_key_update.h"
#include "tls/s2n_prf.h"
#include "tls/s2n_quic_support.h"
+#include "tls/s2n_record.h"
+#include "tls/s2n_security_policies.h"
#include "tls/s2n_tls_parameters.h"
#include "tls/s2n_x509_validator.h"
-#include "tls/s2n_key_update.h"
-#include "tls/s2n_kem_preferences.h"
-#include "tls/s2n_ecc_preferences.h"
-#include "tls/s2n_security_policies.h"
#include "crypto/s2n_hash.h"
#include "crypto/s2n_hmac.h"
@@ -43,6 +45,8 @@
#define S2N_TLS_PROTOCOL_VERSION_LEN 2
+#define S2N_PEER_MODE(our_mode) ((our_mode + 1) % 2)
+
#define is_handshake_complete(conn) (APPLICATION_DATA == s2n_conn_get_current_message_type(conn))
typedef enum {
@@ -52,39 +56,17 @@ typedef enum {
} s2n_session_ticket_status;
struct s2n_connection {
- /* The configuration (cert, key .. etc ) */
- struct s2n_config *config;
-
- /* Overrides Security Policy in config if non-null */
- const struct s2n_security_policy *security_policy_override;
-
- /* The user defined context associated with connection */
- void *context;
-
- /* The user defined secret callback and context */
- s2n_secret_cb secret_cb;
- void *secret_cb_context;
-
- /* The send and receive callbacks don't have to be the same (e.g. two pipes) */
- s2n_send_fn *send;
- s2n_recv_fn *recv;
-
- /* The context passed to the I/O callbacks */
- void *send_io_context;
- void *recv_io_context;
-
- /* Has the user set their own I/O callbacks or is this connection using the
- * default socket-based I/O set by s2n */
- uint8_t managed_io;
-
/* Is this connection using CORK/SO_RCVLOWAT optimizations? Only valid when the connection is using
- * managed_io
+ * managed_send_io
*/
unsigned corked_io:1;
/* Session resumption indicator on client side */
unsigned client_session_resumed:1;
+ /* Connection can be used by a QUIC implementation */
+ unsigned quic_enabled:1;
+
/* Determines if we're currently sending or receiving in s2n_shutdown */
unsigned close_notify_queued:1;
@@ -110,6 +92,58 @@ struct s2n_connection {
/* If write fd is broken */
unsigned write_fd_broken:1;
+ /* Has the user set their own I/O callbacks or is this connection using the
+ * default socket-based I/O set by s2n */
+ unsigned managed_send_io:1;
+ unsigned managed_recv_io:1;
+
+ /* Key update data */
+ unsigned key_update_pending:1;
+
+ /* Early data supported by caller.
+ * If a caller does not use any APIs that support early data,
+ * do not negotiate early data.
+ */
+ unsigned early_data_expected:1;
+
+ /* Connection overrides server_max_early_data_size */
+ unsigned server_max_early_data_size_overridden:1;
+
+ /* Connection overrides psk_mode.
+ * This means that the connection will keep the existing value of psk_params->type,
+ * even when setting a new config. */
+ unsigned psk_mode_overridden:1;
+
+ /* Have we received a close notify alert from the peer. */
+ unsigned close_notify_received:1;
+
+ /* Connection negotiated an EMS */
+ unsigned ems_negotiated:1;
+
+ /* Connection successfully set a ticket on the connection */
+ unsigned set_session:1;
+
+ /* The configuration (cert, key .. etc ) */
+ struct s2n_config *config;
+
+ /* Overrides Security Policy in config if non-null */
+ const struct s2n_security_policy *security_policy_override;
+
+ /* The user defined context associated with connection */
+ void *context;
+
+ /* The user defined secret callback and context */
+ s2n_secret_cb secret_cb;
+ void *secret_cb_context;
+
+ /* The send and receive callbacks don't have to be the same (e.g. two pipes) */
+ s2n_send_fn *send;
+ s2n_recv_fn *recv;
+
+ /* The context passed to the I/O callbacks */
+ void *send_io_context;
+ void *recv_io_context;
+
/* Track request extensions to ensure correct response extension behavior.
*
* We need to track client and server extensions separately because some
@@ -156,11 +190,15 @@ struct s2n_connection {
/* Our crypto parameters */
struct s2n_crypto_parameters initial;
struct s2n_crypto_parameters secure;
+ union s2n_secrets secrets;
/* Which set is the client/server actually using? */
struct s2n_crypto_parameters *client;
struct s2n_crypto_parameters *server;
+ /* Contains parameters needed to negotiate a shared secret */
+ struct s2n_kex_parameters kex_params;
+
/* Contains parameters needed during the handshake phase */
struct s2n_handshake_parameters handshake_params;
@@ -168,7 +206,7 @@ struct s2n_connection {
struct s2n_psk_parameters psk_params;
/* The PRF needs some storage elements to work with */
- struct s2n_prf_working_space prf_space;
+ struct s2n_prf_working_space *prf_space;
/* Whether to use client_cert_auth_type stored in s2n_config or in this s2n_connection.
*
@@ -241,12 +279,14 @@ struct s2n_connection {
/* number of bytes consumed during application activity */
uint64_t active_application_bytes_consumed;
- /* Negotiated TLS extension Maximum Fragment Length code */
- uint8_t mfl_code;
+ /* Negotiated TLS extension Maximum Fragment Length code.
+ * If set, the client and server have both agreed to fragment their records to the given length. */
+ uint8_t negotiated_mfl_code;
/* Keep some accounting on each connection */
uint64_t wire_bytes_in;
uint64_t wire_bytes_out;
+ uint64_t early_data_bytes;
/* Is the connection open or closed ? We use C's only
* atomic type as both the reader and the writer threads
@@ -302,37 +342,36 @@ struct s2n_connection {
s2n_session_ticket_status session_ticket_status;
struct s2n_blob client_ticket;
uint32_t ticket_lifetime_hint;
+ struct s2n_ticket_fields tls13_ticket_fields;
/* Session ticket extension from client to attempt to decrypt as the server. */
- uint8_t ticket_ext_data[S2N_TICKET_SIZE_IN_BYTES];
+ uint8_t ticket_ext_data[S2N_TLS12_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;
/* Cookie extension data */
struct s2n_stuffer cookie_stuffer;
- /* Key update data */
- unsigned key_update_pending:1;
-
- /* Bitmap to represent preferred list of keyshare for client to generate and send keyshares in the ClientHello message.
- * The least significant bit (lsb), if set, indicates that the client must send an empty keyshare list.
- * Each bit value in the bitmap indiciates the corresponding curve in the ecc_preferences list for which a key share needs to be generated.
- * The order of the curves represented in the bitmap is obtained from the security_policy->ecc_preferences.
- * 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.
+ * This can be an easy mistake to make when implementing callbacks.
*/
bool send_in_use;
bool recv_in_use;
+ bool negotiate_in_use;
+
+ uint16_t tickets_to_send;
+ uint16_t tickets_sent;
+
+ s2n_early_data_state early_data_state;
+ uint32_t server_max_early_data_size;
+ struct s2n_blob server_early_data_context;
+ uint32_t server_keying_material_lifetime;
};
+S2N_CLEANUP_RESULT s2n_connection_ptr_free(struct s2n_connection **s2n_connection);
+
int s2n_connection_is_managed_corked(const struct s2n_connection *s2n_connection);
int s2n_connection_is_client_auth_enabled(struct s2n_connection *s2n_connection);
@@ -343,6 +382,8 @@ int s2n_connection_kill(struct s2n_connection *conn);
int s2n_connection_send_stuffer(struct s2n_stuffer *stuffer, struct s2n_connection *conn, uint32_t len);
int s2n_connection_recv_stuffer(struct s2n_stuffer *stuffer, struct s2n_connection *conn, uint32_t len);
+S2N_RESULT s2n_connection_wipe_all_keyshares(struct s2n_connection *conn);
+
int s2n_connection_get_cipher_preferences(struct s2n_connection *conn, const struct s2n_cipher_preferences **cipher_preferences);
int s2n_connection_get_security_policy(struct s2n_connection *conn, const struct s2n_security_policy **security_policy);
int s2n_connection_get_kem_preferences(struct s2n_connection *conn, const struct s2n_kem_preferences **kem_preferences);
@@ -352,6 +393,6 @@ int s2n_connection_get_protocol_preferences(struct s2n_connection *conn, struct
int s2n_connection_set_client_auth_type(struct s2n_connection *conn, s2n_cert_auth_type cert_auth_type);
int s2n_connection_get_client_auth_type(struct s2n_connection *conn, s2n_cert_auth_type *client_cert_auth_type);
int s2n_connection_get_client_cert_chain(struct s2n_connection *conn, uint8_t **der_cert_chain_out, uint32_t *cert_chain_len);
+int s2n_connection_get_peer_cert_chain(const struct s2n_connection *conn, struct s2n_cert_chain_and_key *cert_chain_and_key);
uint8_t s2n_connection_get_protocol_version(const struct s2n_connection *conn);
-/* `none` keyword represents a list of empty keyshares */
-int s2n_connection_set_keyshare_by_name_for_testing(struct s2n_connection *conn, const char* curve_name);
+S2N_RESULT s2n_connection_set_max_fragment_length(struct s2n_connection *conn, uint16_t length);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c b/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c
index f7c08dc594..856ca79f89 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c
@@ -18,109 +18,15 @@
#include "utils/s2n_safety.h"
/* On s2n_connection_wipe, save all pointers to OpenSSL EVP digest structs in a temporary
- * s2n_connection_prf_handles struct to avoid re-allocation after zeroing the connection struct.
- * Do not store any additional hash/HMAC state as it is unnecessary and excessive copying would impact performance.
- */
-int s2n_connection_save_prf_state(struct s2n_connection_prf_handles *prf_handles, struct s2n_connection *conn)
-{
- /* Preserve only the handlers for TLS PRF p_hash pointers to avoid re-allocation */
- GUARD(s2n_hmac_save_evp_hash_state(&prf_handles->p_hash_s2n_hmac, &conn->prf_space.tls.p_hash.s2n_hmac));
- prf_handles->p_hash_evp_hmac = conn->prf_space.tls.p_hash.evp_hmac;
-
- return 0;
-}
-
-/* On s2n_connection_wipe, save all pointers to OpenSSL EVP digest structs in a temporary
- * s2n_connection_hash_handles struct to avoid re-allocation after zeroing the connection struct.
- * Do not store any additional hash state as it is unnecessary and excessive copying would impact performance.
- */
-int s2n_connection_save_hash_state(struct s2n_connection_hash_handles *hash_handles, struct s2n_connection *conn)
-{
- /* Preserve only the handlers for handshake hash state pointers to avoid re-allocation */
- hash_handles->md5 = conn->handshake.md5.digest.high_level;
- hash_handles->sha1 = conn->handshake.sha1.digest.high_level;
- hash_handles->sha224 = conn->handshake.sha224.digest.high_level;
- hash_handles->sha256 = conn->handshake.sha256.digest.high_level;
- hash_handles->sha384 = conn->handshake.sha384.digest.high_level;
- hash_handles->sha512 = conn->handshake.sha512.digest.high_level;
- hash_handles->md5_sha1 = conn->handshake.md5_sha1.digest.high_level;
- hash_handles->ccv_hash_copy = conn->handshake.ccv_hash_copy.digest.high_level;
- hash_handles->prf_md5_hash_copy = conn->handshake.prf_md5_hash_copy.digest.high_level;
- hash_handles->prf_sha1_hash_copy = conn->handshake.prf_sha1_hash_copy.digest.high_level;
- hash_handles->prf_tls12_hash_copy = conn->handshake.prf_tls12_hash_copy.digest.high_level;
- hash_handles->server_finished_copy = conn->handshake.server_finished_copy.digest.high_level;
-
- /* Preserve only the handlers for SSLv3 PRF hash state pointers to avoid re-allocation */
- hash_handles->prf_md5 = conn->prf_space.ssl3.md5.digest.high_level;
- hash_handles->prf_sha1 = conn->prf_space.ssl3.sha1.digest.high_level;
-
- /* Preserve only the handlers for initial signature hash state pointers to avoid re-allocation */
- hash_handles->initial_signature_hash = conn->initial.signature_hash.digest.high_level;
-
- /* Preserve only the handlers for secure signature hash state pointers to avoid re-allocation */
- hash_handles->secure_signature_hash = conn->secure.signature_hash.digest.high_level;
-
- return 0;
-}
-
-/* On s2n_connection_wipe, save all pointers to OpenSSL EVP digest structs in a temporary
* s2n_connection_hmac_handles struct to avoid re-allocation after zeroing the connection struct.
* Do not store any additional HMAC state as it is unnecessary and excessive copying would impact performance.
*/
int s2n_connection_save_hmac_state(struct s2n_connection_hmac_handles *hmac_handles, struct s2n_connection *conn)
{
- GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->initial_client, &conn->initial.client_record_mac));
- GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->initial_server, &conn->initial.server_record_mac));
- GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->initial_client_copy, &conn->initial.record_mac_copy_workspace));
- GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->secure_client, &conn->secure.client_record_mac));
- GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->secure_server, &conn->secure.server_record_mac));
- GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->secure_client_copy, &conn->secure.record_mac_copy_workspace));
- return 0;
-}
-
-/* On s2n_connection_wipe, restore all pointers to OpenSSL EVP digest structs after zeroing the connection struct
- * to avoid re-allocation. Do not store any additional hash/HMAC state as it is unnecessary and excessive copying
- * would impact performance.
- */
-int s2n_connection_restore_prf_state(struct s2n_connection *conn, struct s2n_connection_prf_handles *prf_handles)
-{
- /* Restore s2n_connection handlers for TLS PRF p_hash */
- GUARD(s2n_hmac_restore_evp_hash_state(&prf_handles->p_hash_s2n_hmac, &conn->prf_space.tls.p_hash.s2n_hmac));
- conn->prf_space.tls.p_hash.evp_hmac = prf_handles->p_hash_evp_hmac;
-
- return 0;
-}
-
-/* On s2n_connection_wipe, restore all pointers to OpenSSL EVP digest structs after zeroing the connection struct
- * to avoid re-allocation. Do not store any additional hash state as it is unnecessary and excessive copying
- * would impact performance.
- */
-int s2n_connection_restore_hash_state(struct s2n_connection *conn, struct s2n_connection_hash_handles *hash_handles)
-{
- /* Restore s2n_connection handlers for handshake hash states */
- conn->handshake.md5.digest.high_level = hash_handles->md5;
- conn->handshake.sha1.digest.high_level = hash_handles->sha1;
- conn->handshake.sha224.digest.high_level = hash_handles->sha224;
- conn->handshake.sha256.digest.high_level = hash_handles->sha256;
- conn->handshake.sha384.digest.high_level = hash_handles->sha384;
- conn->handshake.sha512.digest.high_level = hash_handles->sha512;
- conn->handshake.md5_sha1.digest.high_level = hash_handles->md5_sha1;
- conn->handshake.ccv_hash_copy.digest.high_level = hash_handles->ccv_hash_copy;
- conn->handshake.prf_md5_hash_copy.digest.high_level = hash_handles->prf_md5_hash_copy;
- conn->handshake.prf_sha1_hash_copy.digest.high_level = hash_handles->prf_sha1_hash_copy;
- conn->handshake.prf_tls12_hash_copy.digest.high_level = hash_handles->prf_tls12_hash_copy;
- conn->handshake.server_finished_copy.digest.high_level = hash_handles->server_finished_copy;
-
- /* Restore s2n_connection handlers for SSLv3 PRF hash states */
- conn->prf_space.ssl3.md5.digest.high_level = hash_handles->prf_md5;
- conn->prf_space.ssl3.sha1.digest.high_level = hash_handles->prf_sha1;
-
- /* Restore s2n_connection handlers for initial signature hash states */
- conn->initial.signature_hash.digest.high_level = hash_handles->initial_signature_hash;
-
- /* Restore s2n_connection handlers for secure signature hash states */
- conn->secure.signature_hash.digest.high_level = hash_handles->secure_signature_hash;
-
+ POSIX_GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->initial_client, &conn->initial.client_record_mac));
+ POSIX_GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->initial_server, &conn->initial.server_record_mac));
+ POSIX_GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->secure_client, &conn->secure.client_record_mac));
+ POSIX_GUARD(s2n_hmac_save_evp_hash_state(&hmac_handles->secure_server, &conn->secure.server_record_mac));
return 0;
}
@@ -130,11 +36,9 @@ int s2n_connection_restore_hash_state(struct s2n_connection *conn, struct s2n_co
*/
int s2n_connection_restore_hmac_state(struct s2n_connection *conn, struct s2n_connection_hmac_handles *hmac_handles)
{
- GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->initial_client, &conn->initial.client_record_mac));
- GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->initial_server, &conn->initial.server_record_mac));
- GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->initial_client_copy, &conn->initial.record_mac_copy_workspace));
- GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->secure_client, &conn->secure.client_record_mac));
- GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->secure_server, &conn->secure.server_record_mac));
- GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->secure_client_copy, &conn->secure.record_mac_copy_workspace));
+ POSIX_GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->initial_client, &conn->initial.client_record_mac));
+ POSIX_GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->initial_server, &conn->initial.server_record_mac));
+ POSIX_GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->secure_client, &conn->secure.client_record_mac));
+ POSIX_GUARD(s2n_hmac_restore_evp_hash_state(&hmac_handles->secure_server, &conn->secure.server_record_mac));
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.h b/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.h
index 80e16823ba..e94e19d010 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.h
@@ -20,38 +20,6 @@
#include "crypto/s2n_hash.h"
-struct s2n_connection_prf_handles {
- /* TLS PRF HMAC p_hash */
- struct s2n_hmac_evp_backup p_hash_s2n_hmac;
-
- /* TLS PRF EVP p_hash */
- struct s2n_evp_hmac_state p_hash_evp_hmac;
-};
-
-struct s2n_connection_hash_handles {
- /* Handshake hash states */
- struct s2n_hash_evp_digest md5;
- struct s2n_hash_evp_digest sha1;
- struct s2n_hash_evp_digest sha224;
- struct s2n_hash_evp_digest sha256;
- struct s2n_hash_evp_digest sha384;
- struct s2n_hash_evp_digest sha512;
- struct s2n_hash_evp_digest md5_sha1;
- struct s2n_hash_evp_digest ccv_hash_copy;
- struct s2n_hash_evp_digest prf_md5_hash_copy;
- struct s2n_hash_evp_digest prf_sha1_hash_copy;
- struct s2n_hash_evp_digest prf_tls12_hash_copy;
- struct s2n_hash_evp_digest server_finished_copy;
- struct s2n_hash_evp_digest prf_md5;
-
- /* SSLv3 PRF hash states */
- struct s2n_hash_evp_digest prf_sha1;
-
- /* Initial signature hash states */
- struct s2n_hash_evp_digest initial_signature_hash;
- struct s2n_hash_evp_digest secure_signature_hash;
-};
-
/* Allocationg new EVP structs is expensive, so we back them up here and reuse them */
struct s2n_connection_hmac_handles {
struct s2n_hmac_evp_backup initial_client;
@@ -62,9 +30,5 @@ struct s2n_connection_hmac_handles {
struct s2n_hmac_evp_backup secure_server;
};
-extern int s2n_connection_save_prf_state(struct s2n_connection_prf_handles *prf_handles, struct s2n_connection *conn);
-extern int s2n_connection_save_hash_state(struct s2n_connection_hash_handles *hash_handles, struct s2n_connection *conn);
extern int s2n_connection_save_hmac_state(struct s2n_connection_hmac_handles *hmac_handles, struct s2n_connection *conn);
-extern int s2n_connection_restore_prf_state(struct s2n_connection *conn, struct s2n_connection_prf_handles *prf_handles);
-extern int s2n_connection_restore_hash_state(struct s2n_connection *conn, struct s2n_connection_hash_handles *hash_handles);
extern int s2n_connection_restore_hmac_state(struct s2n_connection *conn, struct s2n_connection_hmac_handles *hmac_handles);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_crypto.h b/contrib/restricted/aws/s2n/tls/s2n_crypto.h
index 515165c09d..de6c18b332 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_crypto.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_crypto.h
@@ -19,6 +19,7 @@
#include "tls/s2n_signature_scheme.h"
#include "tls/s2n_crypto_constants.h"
#include "tls/s2n_kem.h"
+#include "tls/s2n_tls13_secrets.h"
#include "crypto/s2n_certificate.h"
#include "crypto/s2n_cipher.h"
@@ -30,44 +31,37 @@
#include "crypto/s2n_dhe.h"
#include "crypto/s2n_ecc_evp.h"
-struct s2n_crypto_parameters {
- struct s2n_pkey server_public_key;
- struct s2n_pkey client_public_key;
+struct s2n_kex_parameters {
struct s2n_dh_params server_dh_params;
struct s2n_ecc_evp_params server_ecc_evp_params;
const struct s2n_ecc_named_curve *mutually_supported_curves[S2N_ECC_EVP_SUPPORTED_CURVES_COUNT];
- struct s2n_ecc_evp_params client_ecc_evp_params[S2N_ECC_EVP_SUPPORTED_CURVES_COUNT];
+ struct s2n_ecc_evp_params client_ecc_evp_params;
struct s2n_kem_group_params server_kem_group_params;
- struct s2n_kem_group_params *chosen_client_kem_group_params;
- struct s2n_kem_group_params client_kem_group_params[S2N_SUPPORTED_KEM_GROUPS_COUNT];
+ struct s2n_kem_group_params client_kem_group_params;
const struct s2n_kem_group *mutually_supported_kem_groups[S2N_SUPPORTED_KEM_GROUPS_COUNT];
struct s2n_kem_params kem_params;
struct s2n_blob client_key_exchange_message;
struct s2n_blob client_pq_kem_extension;
+};
- struct s2n_signature_scheme conn_sig_scheme;
-
- struct s2n_blob client_cert_chain;
- s2n_pkey_type client_cert_pkey_type;
+struct s2n_tls12_secrets {
+ uint8_t rsa_premaster_secret[S2N_TLS_SECRET_LEN];
+ uint8_t master_secret[S2N_TLS_SECRET_LEN];
+};
- struct s2n_signature_scheme client_cert_sig_scheme;
+union s2n_secrets {
+ struct s2n_tls12_secrets tls12;
+ struct s2n_tls13_secrets tls13;
+};
+struct s2n_crypto_parameters {
struct s2n_cipher_suite *cipher_suite;
struct s2n_session_key client_key;
struct s2n_session_key server_key;
-
- uint8_t rsa_premaster_secret[S2N_TLS_SECRET_LEN];
- uint8_t master_secret[S2N_TLS_SECRET_LEN];
- uint8_t client_random[S2N_TLS_RANDOM_DATA_LEN];
- uint8_t server_random[S2N_TLS_RANDOM_DATA_LEN];
- uint8_t client_implicit_iv[S2N_TLS_MAX_IV_LEN];
- uint8_t server_implicit_iv[S2N_TLS_MAX_IV_LEN];
- uint8_t client_app_secret[S2N_TLS13_SECRET_MAX_LEN];
- uint8_t server_app_secret[S2N_TLS13_SECRET_MAX_LEN];
- struct s2n_hash_state signature_hash;
struct s2n_hmac_state client_record_mac;
struct s2n_hmac_state server_record_mac;
- struct s2n_hmac_state record_mac_copy_workspace;
+ uint8_t client_implicit_iv[S2N_TLS_MAX_IV_LEN];
+ uint8_t server_implicit_iv[S2N_TLS_MAX_IV_LEN];
uint8_t client_sequence_number[S2N_TLS_SEQUENCE_NUM_LEN];
uint8_t server_sequence_number[S2N_TLS_SEQUENCE_NUM_LEN];
};
diff --git a/contrib/restricted/aws/s2n/tls/s2n_early_data.c b/contrib/restricted/aws/s2n/tls/s2n_early_data.c
new file mode 100644
index 0000000000..102ceed334
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_early_data.c
@@ -0,0 +1,435 @@
+/*
+ * 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 "tls/s2n_early_data.h"
+
+#include "tls/s2n_connection.h"
+#include "tls/s2n_cipher_suites.h"
+#include "tls/s2n_psk.h"
+#include "utils/s2n_safety.h"
+#include "utils/s2n_mem.h"
+
+const s2n_early_data_state valid_previous_states[] = {
+ [S2N_EARLY_DATA_REQUESTED] = S2N_UNKNOWN_EARLY_DATA_STATE,
+ [S2N_EARLY_DATA_NOT_REQUESTED] = S2N_UNKNOWN_EARLY_DATA_STATE,
+ [S2N_EARLY_DATA_REJECTED] = S2N_EARLY_DATA_REQUESTED,
+ [S2N_EARLY_DATA_ACCEPTED] = S2N_EARLY_DATA_REQUESTED,
+ [S2N_END_OF_EARLY_DATA] = S2N_EARLY_DATA_ACCEPTED,
+};
+
+S2N_RESULT s2n_connection_set_early_data_state(struct s2n_connection *conn, s2n_early_data_state next_state)
+{
+ RESULT_ENSURE_REF(conn);
+ if (conn->early_data_state == next_state) {
+ return S2N_RESULT_OK;
+ }
+ RESULT_ENSURE(next_state < S2N_EARLY_DATA_STATES_COUNT, S2N_ERR_INVALID_EARLY_DATA_STATE);
+ RESULT_ENSURE(next_state != S2N_UNKNOWN_EARLY_DATA_STATE, S2N_ERR_INVALID_EARLY_DATA_STATE);
+ RESULT_ENSURE(conn->early_data_state == valid_previous_states[next_state], S2N_ERR_INVALID_EARLY_DATA_STATE);
+ conn->early_data_state = next_state;
+ return S2N_RESULT_OK;
+}
+
+int s2n_connection_set_early_data_expected(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+ conn->early_data_expected = true;
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_set_end_of_early_data(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+ conn->early_data_expected = false;
+ return S2N_SUCCESS;
+}
+
+static S2N_RESULT s2n_early_data_validate(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# In order to accept early data, the server MUST have accepted a PSK
+ *# cipher suite and selected the first key offered in the client's
+ *# "pre_shared_key" extension.
+ **/
+ RESULT_ENSURE_REF(conn->psk_params.chosen_psk);
+ RESULT_ENSURE_EQ(conn->psk_params.chosen_psk_wire_index, 0);
+
+ struct s2n_early_data_config *config = &conn->psk_params.chosen_psk->early_data_config;
+ RESULT_ENSURE_GT(config->max_early_data_size, 0);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# In addition, it MUST verify that the
+ *# following values are the same as those associated with the
+ *# selected PSK:
+ *#
+ *# - The TLS version number
+ **/
+ RESULT_ENSURE_EQ(config->protocol_version, s2n_connection_get_protocol_version(conn));
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# - The selected cipher suite
+ **/
+ RESULT_ENSURE_EQ(config->cipher_suite, conn->secure.cipher_suite);
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# - The selected ALPN [RFC7301] protocol, if any
+ **/
+ const size_t app_protocol_size = strlen(conn->application_protocol);
+ if (app_protocol_size > 0 || config->application_protocol.size > 0) {
+ RESULT_ENSURE_EQ(config->application_protocol.size, app_protocol_size + 1 /* null-terminating char */);
+ RESULT_ENSURE_EQ(memcmp(config->application_protocol.data, conn->application_protocol, app_protocol_size), 0);
+ }
+
+ return S2N_RESULT_OK;
+}
+
+bool s2n_early_data_is_valid_for_connection(struct s2n_connection *conn)
+{
+ return s2n_result_is_ok(s2n_early_data_validate(conn));
+}
+
+S2N_RESULT s2n_early_data_accept_or_reject(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ if (conn->early_data_state != S2N_EARLY_DATA_REQUESTED) {
+ return S2N_RESULT_OK;
+ }
+
+ if (conn->handshake.early_data_async_state.conn) {
+ RESULT_BAIL(S2N_ERR_ASYNC_BLOCKED);
+ }
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# If any of these checks fail, the server MUST NOT respond with the
+ *# extension
+ **/
+ if (!s2n_early_data_is_valid_for_connection(conn)) {
+ RESULT_GUARD(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_REJECTED));
+ return S2N_RESULT_OK;
+ }
+
+ /* Even if the connection is valid for early data, the client can't consider
+ * early data accepted until the server sends the early data indication. */
+ if (conn->mode == S2N_CLIENT) {
+ return S2N_RESULT_OK;
+ }
+
+ /* The server should reject early data if the application is not prepared to handle it. */
+ if (!conn->early_data_expected) {
+ RESULT_GUARD(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_REJECTED));
+ return S2N_RESULT_OK;
+ }
+
+ /* If early data would otherwise be accepted, let the application apply any additional restrictions.
+ * For example, an application could use this callback to implement anti-replay protections.
+ *
+ * This callback can be either synchronous or asynchronous. The handshake will not proceed until
+ * the application either accepts or rejects early data.
+ */
+ RESULT_ENSURE_REF(conn->config);
+ if (conn->config->early_data_cb) {
+ conn->handshake.early_data_async_state.conn = conn;
+ RESULT_GUARD_POSIX(conn->config->early_data_cb(conn, &conn->handshake.early_data_async_state));
+ if (conn->early_data_state == S2N_EARLY_DATA_REQUESTED) {
+ RESULT_BAIL(S2N_ERR_ASYNC_BLOCKED);
+ }
+ } else {
+ RESULT_GUARD(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_ACCEPTED));
+ }
+ return S2N_RESULT_OK;
+}
+
+int s2n_config_set_server_max_early_data_size(struct s2n_config *config, uint32_t max_early_data_size)
+{
+ POSIX_ENSURE_REF(config);
+ config->server_max_early_data_size = max_early_data_size;
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_set_server_max_early_data_size(struct s2n_connection *conn, uint32_t max_early_data_size)
+{
+ POSIX_ENSURE_REF(conn);
+ conn->server_max_early_data_size = max_early_data_size;
+ conn->server_max_early_data_size_overridden = true;
+ return S2N_SUCCESS;
+}
+
+S2N_RESULT s2n_early_data_get_server_max_size(struct s2n_connection *conn, uint32_t *max_early_data_size)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(max_early_data_size);
+ if (conn->server_max_early_data_size_overridden) {
+ *max_early_data_size = conn->server_max_early_data_size;
+ } else {
+ RESULT_ENSURE_REF(conn->config);
+ *max_early_data_size = conn->config->server_max_early_data_size;
+ }
+ return S2N_RESULT_OK;
+}
+
+int s2n_connection_set_server_early_data_context(struct s2n_connection *conn, const uint8_t *context, uint16_t context_size)
+{
+ POSIX_ENSURE_REF(conn);
+ if (context_size > 0) {
+ POSIX_ENSURE_REF(context);
+ }
+
+ POSIX_GUARD(s2n_realloc(&conn->server_early_data_context, context_size));
+ POSIX_CHECKED_MEMCPY(conn->server_early_data_context.data, context, context_size);
+ return S2N_SUCCESS;
+}
+
+S2N_CLEANUP_RESULT s2n_early_data_config_free(struct s2n_early_data_config *config)
+{
+ if (config == NULL) {
+ return S2N_RESULT_OK;
+ }
+ RESULT_GUARD_POSIX(s2n_free(&config->application_protocol));
+ RESULT_GUARD_POSIX(s2n_free(&config->context));
+ return S2N_RESULT_OK;
+}
+
+int s2n_psk_configure_early_data(struct s2n_psk *psk, uint32_t max_early_data_size,
+ uint8_t cipher_suite_first_byte, uint8_t cipher_suite_second_byte)
+{
+ POSIX_ENSURE_REF(psk);
+
+ const uint8_t cipher_suite_iana[] = { cipher_suite_first_byte, cipher_suite_second_byte };
+ struct s2n_cipher_suite *cipher_suite = NULL;
+ POSIX_GUARD_RESULT(s2n_cipher_suite_from_iana(cipher_suite_iana, &cipher_suite));
+ POSIX_ENSURE_REF(cipher_suite);
+ POSIX_ENSURE(cipher_suite->prf_alg == psk->hmac_alg, S2N_ERR_INVALID_ARGUMENT);
+
+ psk->early_data_config.max_early_data_size = max_early_data_size;
+ psk->early_data_config.protocol_version = S2N_TLS13;
+ psk->early_data_config.cipher_suite = cipher_suite;
+ return S2N_SUCCESS;
+}
+
+int s2n_psk_set_application_protocol(struct s2n_psk *psk, const uint8_t *application_protocol, uint8_t size)
+{
+ POSIX_ENSURE_REF(psk);
+ if (size > 0) {
+ POSIX_ENSURE_REF(application_protocol);
+ }
+ struct s2n_blob *protocol_blob = &psk->early_data_config.application_protocol;
+ POSIX_GUARD(s2n_realloc(protocol_blob, size));
+ POSIX_CHECKED_MEMCPY(protocol_blob->data, application_protocol, size);
+ return S2N_SUCCESS;
+}
+
+int s2n_psk_set_early_data_context(struct s2n_psk *psk, const uint8_t *context, uint16_t size)
+{
+ POSIX_ENSURE_REF(psk);
+ if (size > 0) {
+ POSIX_ENSURE_REF(context);
+ }
+ struct s2n_blob *context_blob = &psk->early_data_config.context;
+ POSIX_GUARD(s2n_realloc(context_blob, size));
+ POSIX_CHECKED_MEMCPY(context_blob->data, context, size);
+ return S2N_SUCCESS;
+}
+
+S2N_RESULT s2n_early_data_config_clone(struct s2n_psk *new_psk, struct s2n_early_data_config *old_config)
+{
+ RESULT_ENSURE_REF(old_config);
+ RESULT_ENSURE_REF(new_psk);
+
+ struct s2n_early_data_config config_copy = new_psk->early_data_config;
+
+ /* Copy all fields from the old_config EXCEPT the blobs, which we need to reallocate. */
+ new_psk->early_data_config = *old_config;
+ new_psk->early_data_config.application_protocol = config_copy.application_protocol;
+ new_psk->early_data_config.context = config_copy.context;
+
+ /* Clone / realloc blobs */
+ RESULT_GUARD_POSIX(s2n_psk_set_application_protocol(new_psk, old_config->application_protocol.data,
+ old_config->application_protocol.size));
+ RESULT_GUARD_POSIX(s2n_psk_set_early_data_context(new_psk, old_config->context.data,
+ old_config->context.size));
+
+ return S2N_RESULT_OK;
+}
+
+int s2n_connection_get_early_data_status(struct s2n_connection *conn, s2n_early_data_status_t *status)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(status);
+
+ switch(conn->early_data_state) {
+ case S2N_EARLY_DATA_STATES_COUNT:
+ break;
+ case S2N_EARLY_DATA_NOT_REQUESTED:
+ *status = S2N_EARLY_DATA_STATUS_NOT_REQUESTED;
+ return S2N_SUCCESS;
+ case S2N_EARLY_DATA_REJECTED:
+ *status = S2N_EARLY_DATA_STATUS_REJECTED;
+ return S2N_SUCCESS;
+ case S2N_END_OF_EARLY_DATA:
+ *status = S2N_EARLY_DATA_STATUS_END;
+ return S2N_SUCCESS;
+ case S2N_UNKNOWN_EARLY_DATA_STATE:
+ case S2N_EARLY_DATA_REQUESTED:
+ case S2N_EARLY_DATA_ACCEPTED:
+ *status = S2N_EARLY_DATA_STATUS_OK;
+ return S2N_SUCCESS;
+ }
+ POSIX_BAIL(S2N_ERR_INVALID_EARLY_DATA_STATE);
+}
+
+static S2N_RESULT s2n_get_remaining_early_data_bytes(struct s2n_connection *conn, uint32_t *early_data_allowed)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(early_data_allowed);
+ *early_data_allowed = 0;
+
+ uint32_t max_early_data_size = 0;
+ RESULT_GUARD_POSIX(s2n_connection_get_max_early_data_size(conn, &max_early_data_size));
+
+ RESULT_ENSURE(max_early_data_size >= conn->early_data_bytes, S2N_ERR_MAX_EARLY_DATA_SIZE);
+ *early_data_allowed = (max_early_data_size - conn->early_data_bytes);
+
+ return S2N_RESULT_OK;
+}
+
+int s2n_connection_get_remaining_early_data_size(struct s2n_connection *conn, uint32_t *allowed_early_data_size)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(allowed_early_data_size);
+ *allowed_early_data_size = 0;
+
+ switch(conn->early_data_state) {
+ case S2N_EARLY_DATA_STATES_COUNT:
+ case S2N_EARLY_DATA_NOT_REQUESTED:
+ case S2N_EARLY_DATA_REJECTED:
+ case S2N_END_OF_EARLY_DATA:
+ *allowed_early_data_size = 0;
+ break;
+ case S2N_UNKNOWN_EARLY_DATA_STATE:
+ case S2N_EARLY_DATA_REQUESTED:
+ case S2N_EARLY_DATA_ACCEPTED:
+ POSIX_GUARD_RESULT(s2n_get_remaining_early_data_bytes(conn, allowed_early_data_size));
+ break;
+ }
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_get_max_early_data_size(struct s2n_connection *conn, uint32_t *max_early_data_size)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(max_early_data_size);
+ *max_early_data_size = 0;
+
+ uint32_t server_max_early_data_size = 0;
+ POSIX_GUARD_RESULT(s2n_early_data_get_server_max_size(conn, &server_max_early_data_size));
+
+ if (conn->psk_params.psk_list.len == 0) {
+ /* This method may be called by the server before loading its PSKs.
+ * The server can load its PSKs during the handshake, either via the PSK selection callback
+ * or by receiving a stateless session ticket.
+ *
+ * Before that happens, we should make an optimistic assumption of the early data size.
+ * That way, the max early data size always decreases (for example, it won't go from 0 -> UINT32_MAX
+ * after receiving a PSK in the ClientHello).
+ */
+ if (conn->mode == S2N_SERVER && !IS_NEGOTIATED(conn)) {
+ *max_early_data_size = server_max_early_data_size;
+ }
+ return S2N_SUCCESS;
+ }
+
+ struct s2n_psk *first_psk = NULL;
+ POSIX_GUARD_RESULT(s2n_array_get(&conn->psk_params.psk_list, 0, (void**) &first_psk));
+ POSIX_ENSURE_REF(first_psk);
+ *max_early_data_size = first_psk->early_data_config.max_early_data_size;
+
+ /* For the server, we should use the minimum of the limit retrieved from the ticket
+ * and the current limit being set for new tickets.
+ *
+ * This is defensive: even if more early data was previously allowed, the server may not be
+ * willing or able to handle that much early data now.
+ *
+ * We don't do this for external PSKs because the server has intentionally set the limit
+ * while setting up this connection, not during a previous connection.
+ */
+ if (conn->mode == S2N_SERVER && first_psk->type == S2N_PSK_TYPE_RESUMPTION) {
+ *max_early_data_size = MIN(*max_early_data_size, server_max_early_data_size);
+ }
+
+ return S2N_SUCCESS;
+}
+
+int s2n_config_set_early_data_cb(struct s2n_config *config, s2n_early_data_cb cb)
+{
+ POSIX_ENSURE_REF(config);
+ config->early_data_cb = cb;
+ return S2N_SUCCESS;
+}
+
+int s2n_offered_early_data_get_context_length(struct s2n_offered_early_data *early_data, uint16_t *context_len)
+{
+ POSIX_ENSURE_REF(context_len);
+ POSIX_ENSURE_REF(early_data);
+ struct s2n_connection *conn = early_data->conn;
+
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->psk_params.chosen_psk);
+ struct s2n_early_data_config *early_data_config = &conn->psk_params.chosen_psk->early_data_config;
+
+ *context_len = early_data_config->context.size;
+
+ return S2N_SUCCESS;
+}
+
+int s2n_offered_early_data_get_context(struct s2n_offered_early_data *early_data, uint8_t *context, uint16_t max_len)
+{
+ POSIX_ENSURE_REF(context);
+ POSIX_ENSURE_REF(early_data);
+ struct s2n_connection *conn = early_data->conn;
+
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->psk_params.chosen_psk);
+ struct s2n_early_data_config *early_data_config = &conn->psk_params.chosen_psk->early_data_config;
+
+ POSIX_ENSURE(early_data_config->context.size <= max_len, S2N_ERR_INSUFFICIENT_MEM_SIZE);
+ POSIX_CHECKED_MEMCPY(context, early_data_config->context.data, early_data_config->context.size);
+
+ return S2N_SUCCESS;
+}
+
+int s2n_offered_early_data_reject(struct s2n_offered_early_data *early_data)
+{
+ POSIX_ENSURE_REF(early_data);
+ struct s2n_connection *conn = early_data->conn;
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_REJECTED));
+ return S2N_SUCCESS;
+}
+
+int s2n_offered_early_data_accept(struct s2n_offered_early_data *early_data)
+{
+ POSIX_ENSURE_REF(early_data);
+ struct s2n_connection *conn = early_data->conn;
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_ACCEPTED));
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_early_data.h b/contrib/restricted/aws/s2n/tls/s2n_early_data.h
new file mode 100644
index 0000000000..eae7f84367
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_early_data.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#pragma once
+
+#include "api/s2n.h"
+
+#include "tls/s2n_crypto_constants.h"
+#include "utils/s2n_blob.h"
+#include "utils/s2n_result.h"
+
+struct s2n_psk;
+
+typedef enum {
+ S2N_UNKNOWN_EARLY_DATA_STATE = 0,
+ S2N_EARLY_DATA_REQUESTED,
+ S2N_EARLY_DATA_NOT_REQUESTED,
+ S2N_EARLY_DATA_ACCEPTED,
+ S2N_EARLY_DATA_REJECTED,
+ S2N_END_OF_EARLY_DATA,
+ S2N_EARLY_DATA_STATES_COUNT
+} s2n_early_data_state;
+
+S2N_RESULT s2n_connection_set_early_data_state(struct s2n_connection *conn, s2n_early_data_state state);
+
+struct s2n_early_data_config {
+ uint32_t max_early_data_size;
+ uint8_t protocol_version;
+ struct s2n_cipher_suite *cipher_suite;
+ struct s2n_blob application_protocol;
+ struct s2n_blob context;
+};
+S2N_CLEANUP_RESULT s2n_early_data_config_free(struct s2n_early_data_config *config);
+S2N_RESULT s2n_early_data_config_clone(struct s2n_psk *new_psk, struct s2n_early_data_config *old_config);
+
+struct s2n_offered_early_data {
+ struct s2n_connection *conn;
+};
+
+bool s2n_early_data_is_valid_for_connection(struct s2n_connection *conn);
+S2N_RESULT s2n_early_data_accept_or_reject(struct s2n_connection *conn);
+
+S2N_RESULT s2n_early_data_get_server_max_size(struct s2n_connection *conn, uint32_t *max_early_data_size);
+
+S2N_RESULT s2n_early_data_record_bytes(struct s2n_connection *conn, ssize_t data_len);
+S2N_RESULT s2n_early_data_validate_send(struct s2n_connection *conn, uint32_t bytes_to_send);
+S2N_RESULT s2n_early_data_validate_recv(struct s2n_connection *conn);
+bool s2n_early_data_is_trial_decryption_allowed(struct s2n_connection *conn, uint8_t record_type);
+
+int s2n_connection_set_early_data_expected(struct s2n_connection *conn);
+int s2n_connection_set_end_of_early_data(struct s2n_connection *conn);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c b/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c
new file mode 100644
index 0000000000..1f3d9a9750
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_early_data_io.c
@@ -0,0 +1,275 @@
+/*
+ * 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 "tls/s2n_early_data.h"
+
+#include "tls/s2n_connection.h"
+#include "utils/s2n_safety.h"
+#include "utils/s2n_mem.h"
+
+int s2n_end_of_early_data_send(struct s2n_connection *conn)
+{
+ if (conn->early_data_expected) {
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
+ POSIX_BAIL(S2N_ERR_EARLY_DATA_BLOCKED);
+ }
+
+ POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_END_OF_EARLY_DATA));
+ return S2N_SUCCESS;
+}
+
+int s2n_end_of_early_data_recv(struct s2n_connection *conn)
+{
+ POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_BAD_MESSAGE);
+ POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_END_OF_EARLY_DATA));
+ return S2N_SUCCESS;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# If the client attempts a 0-RTT handshake but the server
+ *# rejects it, the server will generally not have the 0-RTT record
+ *# protection keys and must instead use trial decryption (either with
+ *# the 1-RTT handshake keys or by looking for a cleartext ClientHello in
+ *# the case of a HelloRetryRequest) to find the first non-0-RTT message.
+ */
+bool s2n_early_data_is_trial_decryption_allowed(struct s2n_connection *conn, uint8_t record_type)
+{
+ return conn && (conn->early_data_state == S2N_EARLY_DATA_REJECTED)
+ && record_type == TLS_APPLICATION_DATA
+ /* Only servers receive early data. */
+ && (conn->mode == S2N_SERVER)
+ /* Early data is only expected during the handshake. */
+ && (s2n_conn_get_current_message_type(conn) != APPLICATION_DATA);
+}
+
+static bool s2n_is_early_data_io(struct s2n_connection *conn)
+{
+ if (s2n_conn_get_current_message_type(conn) == APPLICATION_DATA) {
+ return false;
+ }
+
+ /* It would be more accurate to not include this check.
+ * However, before the early data feature was added, s2n_send and s2n_recv
+ * did not verify that they were being called after a complete handshake.
+ * Enforcing that broke several S2N tests, and might have broken customers too.
+ *
+ * Therefore, only consider this early data if the customer has indicated that
+ * they are aware of early data, either because early data is currently expected
+ * or early data is in a state that indicates that early data was previously expected.
+ */
+ if (conn->early_data_expected
+ || (conn->mode == S2N_CLIENT && conn->early_data_state == S2N_EARLY_DATA_REQUESTED)
+ || conn->early_data_state == S2N_EARLY_DATA_ACCEPTED
+ || conn->early_data_state == S2N_END_OF_EARLY_DATA) {
+ return true;
+ }
+ return false;
+}
+
+S2N_RESULT s2n_early_data_record_bytes(struct s2n_connection *conn, ssize_t data_len)
+{
+ RESULT_ENSURE_REF(conn);
+ if (!s2n_is_early_data_io(conn)) {
+ return S2N_RESULT_OK;
+ }
+
+ /* Ensure the bytes read are within the bounds of what we can actually record. */
+ if (data_len > (UINT64_MAX - conn->early_data_bytes)) {
+ conn->early_data_bytes = UINT64_MAX;
+ RESULT_BAIL(S2N_ERR_INTEGER_OVERFLOW);
+ }
+
+ /* Record the early data bytes read, even if they exceed the max_early_data_size.
+ * This will ensure that if this method is called again, it will fail again:
+ * Once we receive too many bytes, we can't proceed with the connection. */
+ conn->early_data_bytes += data_len;
+
+ uint32_t max_early_data_size = 0;
+ RESULT_GUARD_POSIX(s2n_connection_get_max_early_data_size(conn, &max_early_data_size));
+ RESULT_ENSURE(conn->early_data_bytes <= max_early_data_size, S2N_ERR_MAX_EARLY_DATA_SIZE);
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_early_data_validate_send(struct s2n_connection *conn, uint32_t bytes_to_send)
+{
+ RESULT_ENSURE_REF(conn);
+ if (!s2n_is_early_data_io(conn)) {
+ return S2N_RESULT_OK;
+ }
+
+ RESULT_ENSURE(conn->early_data_expected, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
+ RESULT_ENSURE(conn->mode == S2N_CLIENT, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
+ RESULT_ENSURE(conn->early_data_state == S2N_EARLY_DATA_REQUESTED
+ || conn->early_data_state == S2N_EARLY_DATA_ACCEPTED, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
+
+ uint32_t allowed_early_data_size = 0;
+ RESULT_GUARD_POSIX(s2n_connection_get_remaining_early_data_size(conn, &allowed_early_data_size));
+ RESULT_ENSURE(bytes_to_send <= allowed_early_data_size, S2N_ERR_MAX_EARLY_DATA_SIZE);
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_early_data_validate_recv(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ if (!s2n_is_early_data_io(conn)) {
+ return S2N_RESULT_OK;
+ }
+
+ RESULT_ENSURE(conn->early_data_expected, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
+ RESULT_ENSURE(conn->mode == S2N_SERVER, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
+ RESULT_ENSURE(conn->early_data_state == S2N_EARLY_DATA_ACCEPTED, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
+ RESULT_ENSURE(s2n_conn_get_current_message_type(conn) == END_OF_EARLY_DATA, S2N_ERR_EARLY_DATA_NOT_ALLOWED);
+ return S2N_RESULT_OK;
+}
+
+static bool s2n_early_data_can_continue(struct s2n_connection *conn)
+{
+ uint32_t remaining_early_data_size = 0;
+ return s2n_connection_get_remaining_early_data_size(conn, &remaining_early_data_size) >= S2N_SUCCESS
+ && remaining_early_data_size > 0;
+}
+
+S2N_RESULT s2n_send_early_data_impl(struct s2n_connection *conn, const uint8_t *data, ssize_t data_len,
+ ssize_t *data_sent, s2n_blocked_status *blocked)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(blocked);
+ *blocked = S2N_NOT_BLOCKED;
+ RESULT_ENSURE_REF(data_sent);
+ *data_sent = 0;
+
+ RESULT_ENSURE(conn->mode == S2N_CLIENT, S2N_ERR_SERVER_MODE);
+ RESULT_ENSURE(s2n_connection_supports_tls13(conn), S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
+
+ if (!s2n_early_data_can_continue(conn)) {
+ return S2N_RESULT_OK;
+ }
+
+ /* Attempt to make progress in the handshake even if s2n_send eventually fails.
+ * We only care about the result of this call if it would prevent us from calling s2n_send. */
+ int negotiate_result = s2n_negotiate(conn, blocked);
+ if (negotiate_result < S2N_SUCCESS) {
+ if (s2n_error_get_type(s2n_errno) != S2N_ERR_T_BLOCKED) {
+ return S2N_RESULT_ERROR;
+ } else if (*blocked != S2N_BLOCKED_ON_EARLY_DATA && *blocked != S2N_BLOCKED_ON_READ) {
+ return S2N_RESULT_ERROR;
+ }
+ }
+ /* Save the error status for later */
+ int negotiate_error = s2n_errno;
+ s2n_blocked_status negotiate_blocked = *blocked;
+
+ /* Attempt to send the early data.
+ * We only care about the result of this call if it fails. */
+ uint32_t early_data_to_send = 0;
+ RESULT_GUARD_POSIX(s2n_connection_get_remaining_early_data_size(conn, &early_data_to_send));
+ early_data_to_send = MIN(data_len, early_data_to_send);
+ if (early_data_to_send) {
+ ssize_t send_result = s2n_send(conn, data, early_data_to_send, blocked);
+ RESULT_GUARD_POSIX(send_result);
+ *data_sent = send_result;
+ }
+ *blocked = S2N_NOT_BLOCKED;
+
+ /* Since the send was successful, report the result of the original negotiate call.
+ * If we got this far, the result must have been success or a blocking error. */
+ if (negotiate_result < S2N_SUCCESS) {
+ RESULT_ENSURE_EQ(s2n_error_get_type(negotiate_error), S2N_ERR_T_BLOCKED);
+ if (negotiate_blocked == S2N_BLOCKED_ON_EARLY_DATA) {
+ return S2N_RESULT_OK;
+ } else if (s2n_early_data_can_continue(conn)) {
+ *blocked = negotiate_blocked;
+ RESULT_BAIL(negotiate_error);
+ } else {
+ return S2N_RESULT_OK;
+ }
+ }
+ return S2N_RESULT_OK;
+}
+
+int s2n_send_early_data(struct s2n_connection *conn, const uint8_t *data, ssize_t data_len,
+ ssize_t *data_sent, s2n_blocked_status *blocked)
+{
+ POSIX_ENSURE_REF(conn);
+
+ /* Calling this method indicates that we expect early data. */
+ POSIX_GUARD(s2n_connection_set_early_data_expected(conn));
+
+ s2n_result result = s2n_send_early_data_impl(conn, data, data_len, data_sent, blocked);
+
+ /* Unless s2n_send_early_data is called again (undoing this), we are done sending early data.
+ * If s2n_negotiate is called next, we could send the EndOfEarlyData message. */
+ POSIX_GUARD(s2n_connection_set_end_of_early_data(conn));
+
+ POSIX_GUARD_RESULT(result);
+ return S2N_SUCCESS;
+}
+
+S2N_RESULT s2n_recv_early_data_impl(struct s2n_connection *conn, uint8_t *data, ssize_t max_data_len,
+ ssize_t *data_received, s2n_blocked_status *blocked)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(blocked);
+ *blocked = S2N_NOT_BLOCKED;
+ RESULT_ENSURE_REF(data_received);
+ *data_received = 0;
+
+ RESULT_ENSURE(conn->mode == S2N_SERVER, S2N_ERR_CLIENT_MODE);
+
+ if (!s2n_early_data_can_continue(conn)) {
+ return S2N_RESULT_OK;
+ }
+
+ while(s2n_negotiate(conn, blocked) < S2N_SUCCESS) {
+ if (s2n_error_get_type(s2n_errno) != S2N_ERR_T_BLOCKED) {
+ return S2N_RESULT_ERROR;
+ } else if (max_data_len <= *data_received) {
+ return S2N_RESULT_ERROR;
+ } else if (*blocked != S2N_BLOCKED_ON_EARLY_DATA) {
+ if (s2n_early_data_can_continue(conn)) {
+ return S2N_RESULT_ERROR;
+ } else {
+ *blocked = S2N_NOT_BLOCKED;
+ return S2N_RESULT_OK;
+ }
+ }
+
+ ssize_t recv_result = s2n_recv(conn, data + *data_received,
+ max_data_len - *data_received, blocked);
+ RESULT_GUARD_POSIX(recv_result);
+ *data_received += recv_result;
+ }
+ return S2N_RESULT_OK;
+}
+
+int s2n_recv_early_data(struct s2n_connection *conn, uint8_t *data, ssize_t max_data_len,
+ ssize_t *data_received, s2n_blocked_status *blocked)
+{
+ /* Calling this method indicates that we expect early data. */
+ POSIX_GUARD(s2n_connection_set_early_data_expected(conn));
+
+ s2n_result result = s2n_recv_early_data_impl(conn, data, max_data_len, data_received, blocked);
+
+ /* Unless s2n_recv_early_data is called again (undoing this), we are done accepting early data. */
+ POSIX_GUARD(s2n_connection_set_end_of_early_data(conn));
+
+ POSIX_GUARD_RESULT(result);
+ return S2N_SUCCESS;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c
index 12db371abb..f1632a0a53 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-#include <s2n.h>
+#include "api/s2n.h"
#include "tls/s2n_ecc_preferences.h"
#include "tls/s2n_connection.h"
@@ -39,6 +39,10 @@ const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20201021[] = {
&s2n_ecc_curve_secp521r1,
};
+const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20210816[] = {
+ &s2n_ecc_curve_secp384r1,
+};
+
const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_test_all[] = {
#if EVP_APIS_SUPPORTED
&s2n_ecc_curve_x25519,
@@ -63,6 +67,11 @@ const struct s2n_ecc_preferences s2n_ecc_preferences_20201021 = {
.ecc_curves = s2n_ecc_pref_list_20201021,
};
+const struct s2n_ecc_preferences s2n_ecc_preferences_20210816 = {
+ .count = s2n_array_len(s2n_ecc_pref_list_20210816),
+ .ecc_curves = s2n_ecc_pref_list_20210816,
+};
+
const struct s2n_ecc_preferences s2n_ecc_preferences_test_all = {
.count = s2n_array_len(s2n_ecc_pref_list_test_all),
.ecc_curves = s2n_ecc_pref_list_test_all,
@@ -80,7 +89,7 @@ int s2n_check_ecc_preferences_curves_list(const struct s2n_ecc_preferences *ecc_
for (int i = 0; i < ecc_preferences->count; i++) {
const struct s2n_ecc_named_curve *named_curve = ecc_preferences->ecc_curves[i];
int curve_found = 0;
- for (int j = 0; j < s2n_all_supported_curves_list_len; j++) {
+ for (size_t j = 0; j < s2n_all_supported_curves_list_len; j++) {
if (named_curve->iana_id == s2n_all_supported_curves_list[j]->iana_id) {
curve_found = 1;
break;
@@ -88,7 +97,7 @@ int s2n_check_ecc_preferences_curves_list(const struct s2n_ecc_preferences *ecc_
}
check *= curve_found;
if (check == 0) {
- S2N_ERROR(S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
+ POSIX_BAIL(S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
}
}
return S2N_SUCCESS;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h
index 96afa8051a..564d722726 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h
@@ -15,7 +15,7 @@
#pragma once
-#include <s2n.h>
+#include "api/s2n.h"
#include <strings.h>
#include <stdbool.h>
@@ -28,6 +28,7 @@ struct s2n_ecc_preferences {
extern const struct s2n_ecc_preferences s2n_ecc_preferences_20140601;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_20200310;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_20201021;
+extern const struct s2n_ecc_preferences s2n_ecc_preferences_20210816;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_test_all;
extern const struct s2n_ecc_preferences s2n_ecc_preferences_null;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_encrypted_extensions.c b/contrib/restricted/aws/s2n/tls/s2n_encrypted_extensions.c
index d61d7c1b2d..9f47acd8fd 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_encrypted_extensions.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_encrypted_extensions.c
@@ -36,20 +36,20 @@
int s2n_encrypted_extensions_send(struct s2n_connection *conn)
{
- notnull_check(conn);
- ENSURE_POSIX(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_BAD_MESSAGE);
struct s2n_stuffer *out = &conn->handshake.io;
- GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_ENCRYPTED_EXTENSIONS, conn, out));
+ POSIX_GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_ENCRYPTED_EXTENSIONS, conn, out));
return S2N_SUCCESS;
}
int s2n_encrypted_extensions_recv(struct s2n_connection *conn)
{
- notnull_check(conn);
- ENSURE_POSIX(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_BAD_MESSAGE);
struct s2n_stuffer *in = &conn->handshake.io;
- GUARD(s2n_extension_list_recv(S2N_EXTENSION_LIST_ENCRYPTED_EXTENSIONS, conn, in));
+ POSIX_GUARD(s2n_extension_list_recv(S2N_EXTENSION_LIST_ENCRYPTED_EXTENSIONS, conn, in));
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_establish_session.c b/contrib/restricted/aws/s2n/tls/s2n_establish_session.c
index e61b9f2850..18c4fcc8bf 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_establish_session.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_establish_session.c
@@ -14,7 +14,7 @@
*/
#include <stdint.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include "error/s2n_errno.h"
@@ -32,24 +32,21 @@
* provided session ID in its cache. */
int s2n_establish_session(struct s2n_connection *conn)
{
- GUARD(s2n_conn_set_handshake_read_block(conn));
-
/* Start by receiving and processing the entire CLIENT_HELLO message */
if (!conn->handshake.client_hello_received) {
- GUARD(s2n_client_hello_recv(conn));
+ POSIX_GUARD(s2n_client_hello_recv(conn));
conn->handshake.client_hello_received = 1;
}
- GUARD(s2n_conn_set_handshake_type(conn));
+ POSIX_GUARD_RESULT(s2n_early_data_accept_or_reject(conn));
+ POSIX_GUARD(s2n_conn_set_handshake_type(conn));
if (conn->client_hello_version != S2N_SSLv2)
{
/* We've selected the parameters for the handshake, update the required hashes for this connection */
- GUARD(s2n_conn_update_required_handshake_hashes(conn));
+ POSIX_GUARD(s2n_conn_update_required_handshake_hashes(conn));
}
- GUARD(s2n_conn_clear_handshake_read_block(conn));
-
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_handshake.c
index 922cd67c2b..eb46950ebe 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_handshake.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake.c
@@ -32,13 +32,13 @@ int s2n_handshake_write_header(struct s2n_stuffer *out, uint8_t message_type)
S2N_ERROR_IF(s2n_stuffer_data_available(out), S2N_ERR_HANDSHAKE_STATE);
/* Write the message header */
- GUARD(s2n_stuffer_write_uint8(out, message_type));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, message_type));
/* Leave the length blank for now */
uint16_t length = 0;
- GUARD(s2n_stuffer_write_uint24(out, length));
+ POSIX_GUARD(s2n_stuffer_write_uint24(out, length));
- return 0;
+ return S2N_SUCCESS;
}
int s2n_handshake_finish_header(struct s2n_stuffer *out)
@@ -49,12 +49,12 @@ int s2n_handshake_finish_header(struct s2n_stuffer *out)
uint16_t payload = length - TLS_HANDSHAKE_HEADER_LENGTH;
/* Write the message header */
- GUARD(s2n_stuffer_rewrite(out));
- GUARD(s2n_stuffer_skip_write(out, 1));
- GUARD(s2n_stuffer_write_uint24(out, payload));
- GUARD(s2n_stuffer_skip_write(out, payload));
+ POSIX_GUARD(s2n_stuffer_rewrite(out));
+ POSIX_GUARD(s2n_stuffer_skip_write(out, 1));
+ POSIX_GUARD(s2n_stuffer_write_uint24(out, payload));
+ POSIX_GUARD(s2n_stuffer_skip_write(out, payload));
- return 0;
+ return S2N_SUCCESS;
}
int s2n_handshake_parse_header(struct s2n_connection *conn, uint8_t * message_type, uint32_t * length)
@@ -62,85 +62,73 @@ int s2n_handshake_parse_header(struct s2n_connection *conn, uint8_t * message_ty
S2N_ERROR_IF(s2n_stuffer_data_available(&conn->handshake.io) < TLS_HANDSHAKE_HEADER_LENGTH, S2N_ERR_SIZE_MISMATCH);
/* read the message header */
- GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, message_type));
- GUARD(s2n_stuffer_read_uint24(&conn->handshake.io, length));
+ POSIX_GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, message_type));
+ POSIX_GUARD(s2n_stuffer_read_uint24(&conn->handshake.io, length));
- return 0;
+ return S2N_SUCCESS;
}
static int s2n_handshake_get_hash_state_ptr(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, struct s2n_hash_state **hash_state)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->handshake.hashes);
switch (hash_alg) {
case S2N_HASH_MD5:
- *hash_state = &conn->handshake.md5;
+ *hash_state = &conn->handshake.hashes->md5;
break;
case S2N_HASH_SHA1:
- *hash_state = &conn->handshake.sha1;
+ *hash_state = &conn->handshake.hashes->sha1;
break;
case S2N_HASH_SHA224:
- *hash_state = &conn->handshake.sha224;
+ *hash_state = &conn->handshake.hashes->sha224;
break;
case S2N_HASH_SHA256:
- *hash_state = &conn->handshake.sha256;
+ *hash_state = &conn->handshake.hashes->sha256;
break;
case S2N_HASH_SHA384:
- *hash_state = &conn->handshake.sha384;
+ *hash_state = &conn->handshake.hashes->sha384;
break;
case S2N_HASH_SHA512:
- *hash_state = &conn->handshake.sha512;
+ *hash_state = &conn->handshake.hashes->sha512;
break;
case S2N_HASH_MD5_SHA1:
- *hash_state = &conn->handshake.md5_sha1;
+ *hash_state = &conn->handshake.hashes->md5_sha1;
break;
default:
- S2N_ERROR(S2N_ERR_HASH_INVALID_ALGORITHM);
+ POSIX_BAIL(S2N_ERR_HASH_INVALID_ALGORITHM);
break;
}
- return 0;
+ return S2N_SUCCESS;
}
-int s2n_handshake_reset_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg)
+S2N_RESULT s2n_handshake_reset_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg)
{
- struct s2n_hash_state *hash_state_ptr = NULL;
- GUARD(s2n_handshake_get_hash_state_ptr(conn, hash_alg, &hash_state_ptr));
-
- GUARD(s2n_hash_reset(hash_state_ptr));
-
- return 0;
+ struct s2n_hash_state *hash_state = NULL;
+ RESULT_GUARD_POSIX(s2n_handshake_get_hash_state_ptr(conn, hash_alg, &hash_state));
+ RESULT_GUARD_POSIX(s2n_hash_reset(hash_state));
+ return S2N_RESULT_OK;
}
-/* Copy the current hash state into the caller supplied pointer.
- * NOTE: If the underlying digest implementation is using the EVP API
- * then a pointer to the EVP ctx and md is copied. So you are actually
- * taking a reference, not a value.
- * Before using the hash_state returned by this function you must
- * use s2n_hash_copy() to avoid modifying the underlying value.
- */
-int s2n_handshake_get_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, struct s2n_hash_state *hash_state)
+S2N_RESULT s2n_handshake_copy_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, struct s2n_hash_state *copy)
{
- notnull_check(hash_state);
-
- struct s2n_hash_state *hash_state_ptr = NULL;
- GUARD(s2n_handshake_get_hash_state_ptr(conn, hash_alg, &hash_state_ptr));
-
- *hash_state = *hash_state_ptr;
-
- return 0;
+ struct s2n_hash_state *hash_state = NULL;
+ RESULT_GUARD_POSIX(s2n_handshake_get_hash_state_ptr(conn, hash_alg, &hash_state));
+ RESULT_GUARD_POSIX(s2n_hash_copy(copy, hash_state));
+ return S2N_RESULT_OK;
}
int s2n_handshake_require_all_hashes(struct s2n_handshake *handshake)
{
memset(handshake->required_hash_algs, 1, sizeof(handshake->required_hash_algs));
- return 0;
+ return S2N_SUCCESS;
}
static int s2n_handshake_require_hash(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg)
{
handshake->required_hash_algs[hash_alg] = 1;
- return 0;
+ return S2N_SUCCESS;
}
uint8_t s2n_handshake_is_hash_required(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg)
@@ -161,12 +149,12 @@ int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn)
message_type_t handshake_message = s2n_conn_get_current_message_type(conn);
const uint8_t client_cert_verify_done = (handshake_message >= CLIENT_CERT_VERIFY) ? 1 : 0;
s2n_cert_auth_type client_cert_auth_type;
- GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
+ POSIX_GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
/* If client authentication is possible, all hashes are needed until we're past CLIENT_CERT_VERIFY. */
if ((client_cert_auth_type != S2N_CERT_AUTH_NONE) && !client_cert_verify_done) {
- GUARD(s2n_handshake_require_all_hashes(&conn->handshake));
- return 0;
+ POSIX_GUARD(s2n_handshake_require_all_hashes(&conn->handshake));
+ return S2N_SUCCESS;
}
/* We don't need all of the hashes. Set the hash alg(s) required for the PRF */
@@ -174,8 +162,8 @@ int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn)
case S2N_SSLv3:
case S2N_TLS10:
case S2N_TLS11:
- GUARD(s2n_handshake_require_hash(&conn->handshake, S2N_HASH_MD5));
- GUARD(s2n_handshake_require_hash(&conn->handshake, S2N_HASH_SHA1));
+ POSIX_GUARD(s2n_handshake_require_hash(&conn->handshake, S2N_HASH_MD5));
+ POSIX_GUARD(s2n_handshake_require_hash(&conn->handshake, S2N_HASH_SHA1));
break;
case S2N_TLS12:
/* fall through */
@@ -184,13 +172,13 @@ int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn)
/* For TLS 1.2 and TLS 1.3, the cipher suite defines the PRF hash alg */
s2n_hmac_algorithm prf_alg = conn->secure.cipher_suite->prf_alg;
s2n_hash_algorithm hash_alg;
- GUARD(s2n_hmac_hash_alg(prf_alg, &hash_alg));
- GUARD(s2n_handshake_require_hash(&conn->handshake, hash_alg));
+ POSIX_GUARD(s2n_hmac_hash_alg(prf_alg, &hash_alg));
+ POSIX_GUARD(s2n_handshake_require_hash(&conn->handshake, hash_alg));
break;
}
}
- return 0;
+ return S2N_SUCCESS;
}
/*
@@ -216,20 +204,20 @@ int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn)
int s2n_create_wildcard_hostname(struct s2n_stuffer *hostname_stuffer, struct s2n_stuffer *output)
{
/* Find the end of the first label */
- GUARD(s2n_stuffer_skip_to_char(hostname_stuffer, '.'));
+ POSIX_GUARD(s2n_stuffer_skip_to_char(hostname_stuffer, '.'));
/* No first label found */
if (s2n_stuffer_data_available(hostname_stuffer) == 0) {
- return 0;
+ return S2N_SUCCESS;
}
/* Slap a single wildcard character to be the first label in output */
- GUARD(s2n_stuffer_write_uint8(output, '*'));
+ POSIX_GUARD(s2n_stuffer_write_uint8(output, '*'));
/* Simply copy the rest of the input to the output. */
- GUARD(s2n_stuffer_copy(hostname_stuffer, output, s2n_stuffer_data_available(hostname_stuffer)));
+ POSIX_GUARD(s2n_stuffer_copy(hostname_stuffer, output, s2n_stuffer_data_available(hostname_stuffer)));
- return 0;
+ return S2N_SUCCESS;
}
static int s2n_find_cert_matches(struct s2n_map *domain_name_to_cert_map,
@@ -239,7 +227,7 @@ static int s2n_find_cert_matches(struct s2n_map *domain_name_to_cert_map,
{
struct s2n_blob map_value;
bool key_found = false;
- GUARD_AS_POSIX(s2n_map_lookup(domain_name_to_cert_map, dns_name, &map_value, &key_found));
+ POSIX_GUARD_RESULT(s2n_map_lookup(domain_name_to_cert_map, dns_name, &map_value, &key_found));
if (key_found) {
struct certs_by_type *value = (void *) map_value.data;
for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
@@ -248,7 +236,7 @@ static int s2n_find_cert_matches(struct s2n_map *domain_name_to_cert_map,
*match_exists = 1;
}
- return 0;
+ return S2N_SUCCESS;
}
/* Find certificates that match the ServerName TLS extension sent by the client.
@@ -261,21 +249,21 @@ static int s2n_find_cert_matches(struct s2n_map *domain_name_to_cert_map,
int s2n_conn_find_name_matching_certs(struct s2n_connection *conn)
{
if (!s2n_server_received_server_name(conn)) {
- return 0;
+ return S2N_SUCCESS;
}
const char *name = conn->server_name;
struct s2n_blob hostname_blob = { .data = (uint8_t *) (uintptr_t) name, .size = strlen(name) };
- lte_check(hostname_blob.size, S2N_MAX_SERVER_NAME);
+ POSIX_ENSURE_LTE(hostname_blob.size, S2N_MAX_SERVER_NAME);
char normalized_hostname[S2N_MAX_SERVER_NAME + 1] = { 0 };
- memcpy_check(normalized_hostname, hostname_blob.data, hostname_blob.size);
+ POSIX_CHECKED_MEMCPY(normalized_hostname, hostname_blob.data, hostname_blob.size);
struct s2n_blob normalized_name = { .data = (uint8_t *) normalized_hostname, .size = hostname_blob.size };
- GUARD(s2n_blob_char_to_lower(&normalized_name));
+ POSIX_GUARD(s2n_blob_char_to_lower(&normalized_name));
struct s2n_stuffer normalized_hostname_stuffer;
- GUARD(s2n_stuffer_init(&normalized_hostname_stuffer, &normalized_name));
- GUARD(s2n_stuffer_skip_write(&normalized_hostname_stuffer, normalized_name.size));
+ POSIX_GUARD(s2n_stuffer_init(&normalized_hostname_stuffer, &normalized_name));
+ POSIX_GUARD(s2n_stuffer_skip_write(&normalized_hostname_stuffer, normalized_name.size));
/* Find the exact matches for the ServerName */
- GUARD(s2n_find_cert_matches(conn->config->domain_name_to_cert_map,
+ POSIX_GUARD(s2n_find_cert_matches(conn->config->domain_name_to_cert_map,
&normalized_name,
conn->handshake_params.exact_sni_matches,
&(conn->handshake_params.exact_sni_match_exists)));
@@ -285,18 +273,18 @@ int s2n_conn_find_name_matching_certs(struct s2n_connection *conn)
char wildcard_hostname[S2N_MAX_SERVER_NAME + 1] = { 0 };
struct s2n_blob wildcard_blob = { .data = (uint8_t *) wildcard_hostname, .size = sizeof(wildcard_hostname) };
struct s2n_stuffer wildcard_stuffer;
- GUARD(s2n_stuffer_init(&wildcard_stuffer, &wildcard_blob));
- GUARD(s2n_create_wildcard_hostname(&normalized_hostname_stuffer, &wildcard_stuffer));
+ POSIX_GUARD(s2n_stuffer_init(&wildcard_stuffer, &wildcard_blob));
+ POSIX_GUARD(s2n_create_wildcard_hostname(&normalized_hostname_stuffer, &wildcard_stuffer));
const uint32_t wildcard_len = s2n_stuffer_data_available(&wildcard_stuffer);
/* Couldn't create a valid wildcard from the input */
if (wildcard_len == 0) {
- return 0;
+ return S2N_SUCCESS;
}
/* The client's SNI is wildcardified, do an exact match against the set of server certs. */
wildcard_blob.size = wildcard_len;
- GUARD(s2n_find_cert_matches(conn->config->domain_name_to_cert_map,
+ POSIX_GUARD(s2n_find_cert_matches(conn->config->domain_name_to_cert_map,
&wildcard_blob,
conn->handshake_params.wc_sni_matches,
&(conn->handshake_params.wc_sni_match_exists)));
@@ -309,7 +297,7 @@ int s2n_conn_find_name_matching_certs(struct s2n_connection *conn)
|| conn->handshake_params.exact_sni_match_exists
|| conn->handshake_params.wc_sni_match_exists;
- return 0;
+ return S2N_SUCCESS;
}
/* Find the optimal certificate of a specific type.
@@ -329,3 +317,29 @@ struct s2n_cert_chain_and_key *s2n_get_compatible_cert_chain_and_key(struct s2n_
return conn->config->default_certs_by_type.certs[cert_type];
}
}
+
+/* This method will work when testing S2N, and for the EndOfEarlyData message.
+ *
+ * However, it will NOT work for arbitrary message types when potentially receiving records
+ * that contain multiple messages, like when talking to a non-S2N TLS implementation. If the "end_message"
+ * is not the first message in a multi-message record, negotiation will not stop.
+ * (This is not an issue for EndOfEarlyData because encryption and message order requirements force
+ * EndOfEarlyData to always be the first and only handshake message in its handshake record)
+ */
+S2N_RESULT s2n_negotiate_until_message(struct s2n_connection *conn, s2n_blocked_status *blocked, message_type_t end_message)
+{
+ RESULT_ENSURE_REF(conn);
+ conn->handshake.end_of_messages = end_message;
+ int r = s2n_negotiate(conn, blocked);
+ conn->handshake.end_of_messages = APPLICATION_DATA;
+ RESULT_GUARD_POSIX(r);
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_handshake_validate(const struct s2n_handshake *s2n_handshake)
+{
+ RESULT_ENSURE_REF(s2n_handshake);
+ RESULT_DEBUG_ENSURE(s2n_handshake->handshake_type < 256, S2N_ERR_SAFETY);
+ RESULT_DEBUG_ENSURE(s2n_handshake->message_number >= 0 && s2n_handshake->message_number < 32, S2N_ERR_SAFETY);
+ return S2N_RESULT_OK;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake.h b/contrib/restricted/aws/s2n/tls/s2n_handshake.h
index cb871889e4..5b73d1f626 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_handshake.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake.h
@@ -16,9 +16,11 @@
#pragma once
#include <stdint.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include "tls/s2n_crypto.h"
+#include "tls/s2n_handshake_hashes.h"
+#include "tls/s2n_handshake_type.h"
#include "tls/s2n_signature_algorithms.h"
#include "tls/s2n_tls_parameters.h"
@@ -32,6 +34,7 @@
#define TLS_CLIENT_HELLO 1
#define TLS_SERVER_HELLO 2
#define TLS_SERVER_NEW_SESSION_TICKET 4
+#define TLS_END_OF_EARLY_DATA 5
#define TLS_ENCRYPTED_EXTENSIONS 8
#define TLS_CERTIFICATE 11
#define TLS_SERVER_KEY 12
@@ -67,23 +70,33 @@ typedef enum {
ENCRYPTED_EXTENSIONS,
SERVER_CERT_VERIFY,
HELLO_RETRY_MSG,
+ END_OF_EARLY_DATA,
APPLICATION_DATA,
} message_type_t;
typedef enum {
S2N_ASYNC_NOT_INVOKED = 0,
- S2N_ASYNC_INVOKING_CALLBACK,
- S2N_ASYNC_INVOKED_WAITING,
- S2N_ASYNC_INVOKED_COMPLETE,
+ S2N_ASYNC_INVOKED,
+ S2N_ASYNC_COMPLETE,
} s2n_async_state;
struct s2n_handshake_parameters {
+ /* Public keys for server / client */
+ struct s2n_pkey server_public_key;
+ struct s2n_pkey client_public_key;
+ struct s2n_blob client_cert_chain;
+ s2n_pkey_type client_cert_pkey_type;
+
/* Signature/hash algorithm pairs offered by the client in the signature_algorithms extension */
struct s2n_sig_scheme_list client_sig_hash_algs;
+ /* Signature scheme chosen by the server */
+ struct s2n_signature_scheme conn_sig_scheme;
/* Signature/hash algorithm pairs offered by the server in the certificate request */
struct s2n_sig_scheme_list server_sig_hash_algs;
+ /* Signature scheme chosen by the client */
+ struct s2n_signature_scheme client_cert_sig_scheme;
/* The cert chain we will send the peer. */
struct s2n_cert_chain_and_key *our_chain_and_key;
@@ -114,28 +127,15 @@ struct s2n_handshake_parameters {
struct s2n_cert_chain_and_key *wc_sni_matches[S2N_CERT_TYPE_COUNT];
uint8_t exact_sni_match_exists;
uint8_t wc_sni_match_exists;
+
+ uint8_t client_random[S2N_TLS_RANDOM_DATA_LEN];
+ uint8_t server_random[S2N_TLS_RANDOM_DATA_LEN];
};
struct s2n_handshake {
struct s2n_stuffer io;
- struct s2n_hash_state md5;
- struct s2n_hash_state sha1;
- struct s2n_hash_state sha224;
- struct s2n_hash_state sha256;
- struct s2n_hash_state sha384;
- struct s2n_hash_state sha512;
- struct s2n_hash_state md5_sha1;
-
- /* A copy of the handshake messages hash used to validate the CertificateVerify message */
- struct s2n_hash_state ccv_hash_copy;
-
- /* Used for SSLv3, TLS 1.0, and TLS 1.1 PRFs */
- struct s2n_hash_state prf_md5_hash_copy;
- struct s2n_hash_state prf_sha1_hash_copy;
- /*Used for TLS 1.2 PRF */
- struct s2n_hash_state prf_tls12_hash_copy;
- struct s2n_hash_state server_finished_copy;
+ struct s2n_handshake_hashes *hashes;
/* Hash algorithms required for this handshake. The set of required hashes can be reduced as session parameters are
* negotiated, i.e. cipher suite and protocol version.
@@ -145,53 +145,23 @@ struct s2n_handshake {
uint8_t server_finished[S2N_TLS_SECRET_LEN];
uint8_t client_finished[S2N_TLS_SECRET_LEN];
- /* Handshake type is a bitset, with the following
- bit positions */
+ /* Which message-order affecting features are enabled */
uint32_t handshake_type;
-/* Has the handshake been negotiated yet? */
-#define INITIAL 0x00
-#define NEGOTIATED 0x01
-#define IS_NEGOTIATED( type ) ( (type) & NEGOTIATED )
-
-/* Handshake is a full handshake */
-#define FULL_HANDSHAKE 0x02
-#define IS_FULL_HANDSHAKE( type ) ( (type) & FULL_HANDSHAKE )
-#define IS_RESUMPTION_HANDSHAKE( type ) ( !IS_FULL_HANDSHAKE( (type) ) && IS_NEGOTIATED ( (type) ) )
-
-/* Handshake uses perfect forward secrecy */
-#define TLS12_PERFECT_FORWARD_SECRECY 0x04
-
-/* Handshake needs OCSP status message */
-#define OCSP_STATUS 0x08
-#define IS_OCSP_STAPLED( type ) ( ( (type) & OCSP_STATUS ) != 0 )
-
-/* Handshake should request a Client Certificate */
-#define CLIENT_AUTH 0x10
-#define IS_CLIENT_AUTH_HANDSHAKE( type ) ( (type) & CLIENT_AUTH )
-
-/* Session Resumption via session-tickets */
-#define WITH_SESSION_TICKET 0x20
-#define IS_ISSUING_NEW_SESSION_TICKET( type ) ( (type) & WITH_SESSION_TICKET )
-
-/* Handshake requested a Client Certificate but did not get one */
-#define NO_CLIENT_CERT 0x40
-#define IS_CLIENT_AUTH_NO_CERT( type ) ( IS_CLIENT_AUTH_HANDSHAKE( (type) ) && ( (type) & NO_CLIENT_CERT) )
-
-/* A HelloRetryRequest was needed to proceed with the handshake */
-#define HELLO_RETRY_REQUEST 0x80
-
-/* Disguise a TLS1.3 handshake as a TLS1.2 handshake for backwards compatibility
- * with some middleboxes: https://tools.ietf.org/html/rfc8446#appendix-D.4 */
-#define MIDDLEBOX_COMPAT 0x100
-#define IS_MIDDLEBOX_COMPAT_MODE( type ) ( (type) & MIDDLEBOX_COMPAT )
-
/* Which handshake message number are we processing */
int message_number;
+ /* Last message in the handshake. Unless using early data or testing,
+ * should always be APPLICATION_DATA. */
+ message_type_t end_of_messages;
+
/* State of the async pkey operation during handshake */
s2n_async_state async_state;
+ /* State of the async early data callback.
+ * If not initialized, then the callback has not been triggered yet. */
+ struct s2n_offered_early_data early_data_async_state;
+
/* Indicates the CLIENT_HELLO message has been completely received */
unsigned client_hello_received:1;
@@ -202,19 +172,28 @@ struct s2n_handshake {
unsigned rsa_failed:1;
};
-extern message_type_t s2n_conn_get_current_message_type(struct s2n_connection *conn);
-extern int s2n_conn_set_handshake_type(struct s2n_connection *conn);
-extern int s2n_conn_set_handshake_no_client_cert(struct s2n_connection *conn);
-extern int s2n_conn_set_handshake_read_block(struct s2n_connection *conn);
-extern int s2n_conn_clear_handshake_read_block(struct s2n_connection *conn);
-extern int s2n_handshake_require_all_hashes(struct s2n_handshake *handshake);
-extern uint8_t s2n_handshake_is_hash_required(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg);
-extern int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn);
-extern int s2n_handshake_get_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, struct s2n_hash_state *hash_state);
-extern int s2n_handshake_reset_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg);
-extern int s2n_conn_find_name_matching_certs(struct s2n_connection *conn);
-extern int s2n_create_wildcard_hostname(struct s2n_stuffer *hostname, struct s2n_stuffer *output);
+/* Only used in our test cases. */
+message_type_t s2n_conn_get_current_message_type(struct s2n_connection *conn);
+
+/* s2n_handshake */
+int s2n_handshake_require_all_hashes(struct s2n_handshake *handshake);
+uint8_t s2n_handshake_is_hash_required(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg);
+int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn);
+S2N_RESULT s2n_handshake_copy_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, struct s2n_hash_state *hash_state);
+S2N_RESULT s2n_handshake_reset_hash_state(struct s2n_connection *conn, s2n_hash_algorithm hash_alg);
+int s2n_conn_find_name_matching_certs(struct s2n_connection *conn);
+int s2n_create_wildcard_hostname(struct s2n_stuffer *hostname, struct s2n_stuffer *output);
struct s2n_cert_chain_and_key *s2n_get_compatible_cert_chain_and_key(struct s2n_connection *conn, const s2n_pkey_type cert_type);
+S2N_RESULT s2n_negotiate_until_message(struct s2n_connection *conn, s2n_blocked_status *blocked, message_type_t end_message);
+S2N_RESULT s2n_handshake_validate(const struct s2n_handshake *s2n_handshake);
+
+/* s2n_handshake_io */
+int s2n_conn_set_handshake_type(struct s2n_connection *conn);
+int s2n_conn_set_handshake_no_client_cert(struct s2n_connection *conn);
+
+/* s2n_handshake_transcript */
int s2n_conn_update_handshake_hashes(struct s2n_connection *conn, struct s2n_blob *data);
+
+/* s2n_quic_support */
S2N_RESULT s2n_quic_read_handshake_message(struct s2n_connection *conn, uint8_t *message_type);
S2N_RESULT s2n_quic_write_handshake_message(struct s2n_connection *conn, struct s2n_blob *in);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_hashes.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_hashes.c
new file mode 100644
index 0000000000..c3c727af81
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_hashes.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#include "tls/s2n_handshake_hashes.h"
+
+#include "crypto/s2n_fips.h"
+#include "tls/s2n_connection.h"
+#include "utils/s2n_blob.h"
+#include "utils/s2n_mem.h"
+#include "utils/s2n_safety.h"
+
+static S2N_RESULT s2n_handshake_hashes_new_hashes(struct s2n_handshake_hashes *hashes)
+{
+ RESULT_ENSURE_REF(hashes);
+ RESULT_GUARD_POSIX(s2n_hash_new(&hashes->md5));
+ RESULT_GUARD_POSIX(s2n_hash_new(&hashes->sha1));
+ RESULT_GUARD_POSIX(s2n_hash_new(&hashes->sha224));
+ RESULT_GUARD_POSIX(s2n_hash_new(&hashes->sha256));
+ RESULT_GUARD_POSIX(s2n_hash_new(&hashes->sha384));
+ RESULT_GUARD_POSIX(s2n_hash_new(&hashes->sha512));
+ RESULT_GUARD_POSIX(s2n_hash_new(&hashes->md5_sha1));
+ RESULT_GUARD_POSIX(s2n_hash_new(&hashes->hash_workspace));
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_handshake_hashes_reset_hashes(struct s2n_handshake_hashes *hashes)
+{
+ RESULT_ENSURE_REF(hashes);
+ RESULT_GUARD_POSIX(s2n_hash_reset(&hashes->md5));
+ RESULT_GUARD_POSIX(s2n_hash_reset(&hashes->sha1));
+ RESULT_GUARD_POSIX(s2n_hash_reset(&hashes->sha224));
+ RESULT_GUARD_POSIX(s2n_hash_reset(&hashes->sha256));
+ RESULT_GUARD_POSIX(s2n_hash_reset(&hashes->sha384));
+ RESULT_GUARD_POSIX(s2n_hash_reset(&hashes->sha512));
+ RESULT_GUARD_POSIX(s2n_hash_reset(&hashes->md5_sha1));
+ RESULT_GUARD_POSIX(s2n_hash_reset(&hashes->hash_workspace));
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_handshake_hashes_free_hashes(struct s2n_handshake_hashes *hashes)
+{
+ if (!hashes) {
+ return S2N_RESULT_OK;
+ }
+ RESULT_GUARD_POSIX(s2n_hash_free(&hashes->md5));
+ RESULT_GUARD_POSIX(s2n_hash_free(&hashes->sha1));
+ RESULT_GUARD_POSIX(s2n_hash_free(&hashes->sha224));
+ RESULT_GUARD_POSIX(s2n_hash_free(&hashes->sha256));
+ RESULT_GUARD_POSIX(s2n_hash_free(&hashes->sha384));
+ RESULT_GUARD_POSIX(s2n_hash_free(&hashes->sha512));
+ RESULT_GUARD_POSIX(s2n_hash_free(&hashes->md5_sha1));
+ RESULT_GUARD_POSIX(s2n_hash_free(&hashes->hash_workspace));
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_handshake_hashes_init_hashes(struct s2n_handshake_hashes *hashes)
+{
+ /* Allow MD5 for hash states that are used by the PRF. This is required
+ * to comply with the TLS 1.0 and 1.1 RFCs and is approved as per
+ * NIST Special Publication 800-52 Revision 1.
+ */
+ if (s2n_is_in_fips_mode()) {
+ RESULT_GUARD_POSIX(s2n_hash_allow_md5_for_fips(&hashes->md5));
+ RESULT_GUARD_POSIX(s2n_hash_allow_md5_for_fips(&hashes->hash_workspace));
+
+ /* Do not check s2n_hash_is_available before initialization. Allow MD5 and
+ * SHA-1 for both fips and non-fips mode. This is required to perform the
+ * signature checks in the CertificateVerify message in TLS 1.0 and TLS 1.1.
+ * This is approved per Nist SP 800-52r1.*/
+ RESULT_GUARD_POSIX(s2n_hash_allow_md5_for_fips(&hashes->md5_sha1));
+ }
+
+ RESULT_GUARD_POSIX(s2n_hash_init(&hashes->md5, S2N_HASH_MD5));
+ RESULT_GUARD_POSIX(s2n_hash_init(&hashes->sha1, S2N_HASH_SHA1));
+ RESULT_GUARD_POSIX(s2n_hash_init(&hashes->sha224, S2N_HASH_SHA224));
+ RESULT_GUARD_POSIX(s2n_hash_init(&hashes->sha256, S2N_HASH_SHA256));
+ RESULT_GUARD_POSIX(s2n_hash_init(&hashes->sha384, S2N_HASH_SHA384));
+ RESULT_GUARD_POSIX(s2n_hash_init(&hashes->sha512, S2N_HASH_SHA512));
+ RESULT_GUARD_POSIX(s2n_hash_init(&hashes->md5_sha1, S2N_HASH_MD5_SHA1));
+ RESULT_GUARD_POSIX(s2n_hash_init(&hashes->hash_workspace, S2N_HASH_NONE));
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_handshake_hashes_new(struct s2n_handshake_hashes **hashes)
+{
+ RESULT_ENSURE_REF(hashes);
+ RESULT_ENSURE_EQ(*hashes, NULL);
+
+ DEFER_CLEANUP(struct s2n_blob data = { 0 }, s2n_free);
+ RESULT_GUARD_POSIX(s2n_realloc(&data, sizeof(struct s2n_handshake_hashes)));
+ RESULT_GUARD_POSIX(s2n_blob_zero(&data));
+ *hashes = (struct s2n_handshake_hashes*)(void*) data.data;
+ ZERO_TO_DISABLE_DEFER_CLEANUP(data);
+
+ RESULT_GUARD(s2n_handshake_hashes_new_hashes(*hashes));
+ RESULT_GUARD(s2n_handshake_hashes_init_hashes(*hashes));
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_handshake_hashes_wipe(struct s2n_handshake_hashes *hashes)
+{
+ RESULT_GUARD(s2n_handshake_hashes_reset_hashes(hashes));
+ return S2N_RESULT_OK;
+}
+
+S2N_CLEANUP_RESULT s2n_handshake_hashes_free(struct s2n_handshake_hashes **hashes)
+{
+ RESULT_ENSURE_REF(hashes);
+ RESULT_GUARD(s2n_handshake_hashes_free_hashes(*hashes));
+ RESULT_GUARD_POSIX(s2n_free_object((uint8_t**) hashes, sizeof(struct s2n_handshake_hashes)));
+ return S2N_RESULT_OK;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_hashes.h b/contrib/restricted/aws/s2n/tls/s2n_handshake_hashes.h
new file mode 100644
index 0000000000..22d157deb4
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_hashes.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#pragma once
+
+#include "api/s2n.h"
+
+#include "crypto/s2n_hash.h"
+#include "crypto/s2n_tls13_keys.h"
+
+struct s2n_handshake_hashes {
+ struct s2n_hash_state md5;
+ struct s2n_hash_state sha1;
+ struct s2n_hash_state sha224;
+ struct s2n_hash_state sha256;
+ struct s2n_hash_state sha384;
+ struct s2n_hash_state sha512;
+ struct s2n_hash_state md5_sha1;
+
+ /* TLS1.3 requires transcript hash digests to calculate secrets.
+ */
+ uint8_t transcript_hash_digest[S2N_TLS13_SECRET_MAX_LEN];
+
+ /* To avoid allocating memory for hash objects, we reuse one temporary hash object.
+ * Do NOT rely on this hash state maintaining its value outside of the current context.
+ */
+ struct s2n_hash_state hash_workspace;
+};
+
+S2N_RESULT s2n_handshake_hashes_new(struct s2n_handshake_hashes **hashes);
+S2N_RESULT s2n_handshake_hashes_wipe(struct s2n_handshake_hashes *hashes);
+S2N_CLEANUP_RESULT s2n_handshake_hashes_free(struct s2n_handshake_hashes **hashes);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
index 5b78ef79c6..3c490212a7 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c
@@ -16,7 +16,7 @@
#include <sys/param.h>
#include <errno.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include "error/s2n_errno.h"
@@ -31,14 +31,16 @@
#include "tls/s2n_tls.h"
#include "tls/s2n_tls13.h"
#include "tls/s2n_tls13_handshake.h"
+#include "tls/s2n_tls13_key_schedule.h"
#include "tls/s2n_kex.h"
+#include "tls/s2n_post_handshake.h"
#include "stuffer/s2n_stuffer.h"
#include "utils/s2n_safety.h"
#include "utils/s2n_socket.h"
#include "utils/s2n_random.h"
-#include "utils/s2n_str.h"
+#include "utils/s2n_bitmap.h"
/* clang-format off */
struct s2n_handshake_action {
@@ -51,13 +53,13 @@ struct s2n_handshake_action {
static int s2n_always_fail_send(struct s2n_connection *conn)
{
/* This state should never be sending a handshake message. */
- S2N_ERROR(S2N_ERR_HANDSHAKE_UNREACHABLE);
+ POSIX_BAIL(S2N_ERR_HANDSHAKE_UNREACHABLE);
}
static int s2n_always_fail_recv(struct s2n_connection *conn)
{
/* This state should never have an incoming handshake message. */
- S2N_ERROR(S2N_ERR_HANDSHAKE_UNREACHABLE);
+ POSIX_BAIL(S2N_ERR_HANDSHAKE_UNREACHABLE);
}
/* Client and Server handlers for each message type we support.
@@ -100,6 +102,7 @@ static struct s2n_handshake_action tls13_state_machine[] = {
[CLIENT_CERT] = {TLS_HANDSHAKE, TLS_CERTIFICATE, 'C', {s2n_client_cert_recv, s2n_client_cert_send}},
[CLIENT_CERT_VERIFY] = {TLS_HANDSHAKE, TLS_CERT_VERIFY, 'C', {s2n_tls13_cert_verify_recv, s2n_tls13_cert_verify_send}},
[CLIENT_FINISHED] = {TLS_HANDSHAKE, TLS_FINISHED, 'C', {s2n_tls13_client_finished_recv, s2n_tls13_client_finished_send}},
+ [END_OF_EARLY_DATA] = {TLS_HANDSHAKE, TLS_END_OF_EARLY_DATA, 'C', {s2n_end_of_early_data_recv, s2n_end_of_early_data_send}},
/* Not used by TLS1.3, except to maintain middlebox compatibility */
[CLIENT_CHANGE_CIPHER_SPEC] = {TLS_CHANGE_CIPHER_SPEC, 0, 'C', {s2n_basic_ccs_recv, s2n_ccs_send}},
@@ -129,12 +132,10 @@ static const char *message_names[] = {
MESSAGE_NAME_ENTRY(SERVER_CHANGE_CIPHER_SPEC),
MESSAGE_NAME_ENTRY(SERVER_FINISHED),
MESSAGE_NAME_ENTRY(HELLO_RETRY_MSG),
+ MESSAGE_NAME_ENTRY(END_OF_EARLY_DATA),
MESSAGE_NAME_ENTRY(APPLICATION_DATA),
};
-/* Maximum number of valid handshakes */
-#define S2N_HANDSHAKES_COUNT 512
-
/* Maximum number of messages in a handshake */
#define S2N_MAX_HANDSHAKE_LENGTH 32
@@ -366,11 +367,21 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L
SERVER_HELLO
},
+ [INITIAL | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
+ CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
+ SERVER_HELLO
+ },
+
[INITIAL | HELLO_RETRY_REQUEST] = {
CLIENT_HELLO,
HELLO_RETRY_MSG
},
+ [INITIAL | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
+ CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
+ HELLO_RETRY_MSG
+ },
+
[NEGOTIATED] = {
CLIENT_HELLO,
SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
@@ -378,6 +389,13 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L
APPLICATION_DATA
},
+ [NEGOTIATED | WITH_EARLY_DATA] = {
+ CLIENT_HELLO,
+ SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
+ END_OF_EARLY_DATA, CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
[NEGOTIATED | MIDDLEBOX_COMPAT] = {
CLIENT_HELLO,
SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
@@ -385,6 +403,27 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L
APPLICATION_DATA
},
+ [NEGOTIATED | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
+ CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
+ SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
+ CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
+ [NEGOTIATED | MIDDLEBOX_COMPAT | WITH_EARLY_DATA] = {
+ CLIENT_HELLO,
+ SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
+ CLIENT_CHANGE_CIPHER_SPEC, END_OF_EARLY_DATA, CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
+ [NEGOTIATED | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS | WITH_EARLY_DATA] = {
+ CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
+ SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_FINISHED,
+ END_OF_EARLY_DATA, CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
[NEGOTIATED | HELLO_RETRY_REQUEST] = {
CLIENT_HELLO,
HELLO_RETRY_MSG,
@@ -403,6 +442,15 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L
APPLICATION_DATA
},
+ [NEGOTIATED | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
+ CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
+ HELLO_RETRY_MSG, SERVER_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,
@@ -417,6 +465,13 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L
APPLICATION_DATA
},
+ [NEGOTIATED | FULL_HANDSHAKE | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
+ CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
+ SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
+ CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
[NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST] = {
CLIENT_HELLO,
HELLO_RETRY_MSG,
@@ -435,6 +490,15 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L
APPLICATION_DATA
},
+ [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
+ CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
+ HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
+ CLIENT_HELLO,
+ SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
+ CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
[NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH] = {
CLIENT_HELLO,
HELLO_RETRY_MSG,
@@ -453,6 +517,15 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L
APPLICATION_DATA
},
+ [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
+ CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
+ HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
+ CLIENT_HELLO,
+ SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
+ CLIENT_CERT, CLIENT_CERT_VERIFY, CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
[NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH | NO_CLIENT_CERT] = {
CLIENT_HELLO,
HELLO_RETRY_MSG,
@@ -471,6 +544,15 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L
APPLICATION_DATA
},
+ [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH | NO_CLIENT_CERT | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
+ CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
+ HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC,
+ CLIENT_HELLO,
+ SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
+ CLIENT_CERT, CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
[NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH] = {
CLIENT_HELLO,
SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
@@ -485,6 +567,13 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L
APPLICATION_DATA
},
+ [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
+ CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
+ SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
+ CLIENT_CERT, CLIENT_CERT_VERIFY, CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
+
[NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT] = {
CLIENT_HELLO,
SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
@@ -498,22 +587,38 @@ static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_L
CLIENT_CHANGE_CIPHER_SPEC, CLIENT_CERT, CLIENT_FINISHED,
APPLICATION_DATA
},
+
+ [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS] = {
+ CLIENT_HELLO, CLIENT_CHANGE_CIPHER_SPEC,
+ SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED,
+ CLIENT_CERT, CLIENT_FINISHED,
+ APPLICATION_DATA
+ },
};
/* clang-format on */
-#define MAX_HANDSHAKE_TYPE_LEN 152
+#define MAX_HANDSHAKE_TYPE_LEN 123
static char handshake_type_str[S2N_HANDSHAKES_COUNT][MAX_HANDSHAKE_TYPE_LEN] = {0};
-static const char* handshake_type_names[] = {
+static const char* tls12_handshake_type_names[] = {
"NEGOTIATED|",
"FULL_HANDSHAKE|",
+ "CLIENT_AUTH|",
+ "NO_CLIENT_CERT|",
"TLS12_PERFECT_FORWARD_SECRECY|",
"OCSP_STATUS|",
- "CLIENT_AUTH|",
"WITH_SESSION_TICKET|",
+};
+
+static const char* tls13_handshake_type_names[] = {
+ "NEGOTIATED|",
+ "FULL_HANDSHAKE|",
+ "CLIENT_AUTH|",
"NO_CLIENT_CERT|",
"HELLO_RETRY_REQUEST|",
"MIDDLEBOX_COMPAT|",
+ "WITH_EARLY_DATA|",
+ "EARLY_CLIENT_CCS|",
};
#define IS_TLS13_HANDSHAKE( conn ) ((conn)->actual_protocol_version == S2N_TLS13)
@@ -533,7 +638,7 @@ static const char* handshake_type_names[] = {
#define CONNECTION_WRITER( conn ) (conn->mode == S2N_CLIENT ? 'C' : 'S')
#define CONNECTION_IS_WRITER( conn ) (ACTIVE_STATE(conn).writer == CONNECTION_WRITER(conn))
-/* Used in our test cases */
+/* Only used in our test cases. */
message_type_t s2n_conn_get_current_message_type(struct s2n_connection *conn)
{
return ACTIVE_MESSAGE(conn);
@@ -556,37 +661,37 @@ static int s2n_advance_message(struct s2n_connection *conn)
}
/* Set TCP_QUICKACK to avoid artificial delay during the handshake */
- GUARD(s2n_socket_quickack(conn));
+ POSIX_GUARD(s2n_socket_quickack(conn));
/* If optimized io hasn't been enabled or if the caller started out with a corked socket,
* we don't mess with it
*/
if (!conn->corked_io || s2n_socket_was_corked(conn)) {
- return 0;
+ return S2N_SUCCESS;
}
/* Are we changing I/O directions */
if (ACTIVE_STATE(conn).writer == previous_writer || ACTIVE_STATE(conn).writer == 'A') {
- return 0;
+ return S2N_SUCCESS;
}
/* We're the new writer */
if (ACTIVE_STATE(conn).writer == this_mode) {
if (s2n_connection_is_managed_corked(conn)) {
/* Set TCP_CORK/NOPUSH */
- GUARD(s2n_socket_write_cork(conn));
+ POSIX_GUARD(s2n_socket_write_cork(conn));
}
- return 0;
+ return S2N_SUCCESS;
}
/* We're the new reader, or we reached the "B" writer stage indicating that
we're at the application data stage - uncork the data */
if (s2n_connection_is_managed_corked(conn)) {
- GUARD(s2n_socket_write_uncork(conn));
+ POSIX_GUARD(s2n_socket_write_uncork(conn));
}
- return 0;
+ return S2N_SUCCESS;
}
int s2n_generate_new_client_session_id(struct s2n_connection *conn)
@@ -595,104 +700,149 @@ int s2n_generate_new_client_session_id(struct s2n_connection *conn)
struct s2n_blob session_id = { .data = conn->session_id, .size = S2N_TLS_SESSION_ID_MAX_LEN };
/* Generate a new session id */
- GUARD_AS_POSIX(s2n_get_public_random_data(&session_id));
+ POSIX_GUARD_RESULT(s2n_get_public_random_data(&session_id));
conn->session_id_len = S2N_TLS_SESSION_ID_MAX_LEN;
}
- return 0;
+ return S2N_SUCCESS;
}
/* Lets the server flag whether a HelloRetryRequest is needed while processing extensions */
int s2n_set_hello_retry_required(struct s2n_connection *conn)
{
- notnull_check(conn);
-
- ENSURE_POSIX(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_INVALID_HELLO_RETRY);
- conn->handshake.handshake_type |= HELLO_RETRY_REQUEST;
+ POSIX_ENSURE_REF(conn);
+
+ POSIX_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_INVALID_HELLO_RETRY);
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_tls13_flag(conn, HELLO_RETRY_REQUEST));
+
+ /* HelloRetryRequests also indicate rejection of early data.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# A server which receives an "early_data" extension MUST behave in one
+ *# of three ways:
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# - Request that the client send another ClientHello by responding
+ *# with a HelloRetryRequest.
+ **/
+ if (conn->early_data_state == S2N_EARLY_DATA_REQUESTED) {
+ POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_REJECTED));
+ }
return S2N_SUCCESS;
}
bool s2n_is_hello_retry_message(struct s2n_connection *conn)
{
- return (ACTIVE_MESSAGE(conn) == HELLO_RETRY_MSG);
+ return (conn != NULL &&
+ s2n_result_is_ok(s2n_handshake_validate(&(conn->handshake))) &&
+ ACTIVE_MESSAGE(conn) == HELLO_RETRY_MSG);
}
bool s2n_is_hello_retry_handshake(struct s2n_connection *conn)
{
- return conn->handshake.handshake_type & HELLO_RETRY_REQUEST;
+ return IS_HELLO_RETRY_HANDSHAKE(conn);
}
static S2N_RESULT s2n_conn_set_tls13_handshake_type(struct s2n_connection *conn) {
- ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn);
- if (conn->handshake.handshake_type & HELLO_RETRY_REQUEST) {
- conn->handshake.handshake_type = HELLO_RETRY_REQUEST;
- } else {
- conn->handshake.handshake_type = INITIAL;
- }
+ /* Most handshake type flags should be reset before we calculate the handshake type,
+ * in order to handle changes during retries.
+ * However, flags that have already affected the message order must be kept to avoid
+ * rewriting the past.
+ */
+ conn->handshake.handshake_type &= (HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT | EARLY_CLIENT_CCS);
/* A handshake type has been negotiated */
- conn->handshake.handshake_type |= NEGOTIATED;
+ RESULT_GUARD(s2n_handshake_type_set_flag(conn, NEGOTIATED));
if (conn->psk_params.chosen_psk == NULL) {
- conn->handshake.handshake_type |= FULL_HANDSHAKE;
+ RESULT_GUARD(s2n_handshake_type_set_flag(conn, FULL_HANDSHAKE));
+ }
+
+ if (conn->early_data_state == S2N_EARLY_DATA_ACCEPTED) {
+ conn->handshake.handshake_type |= WITH_EARLY_DATA;
}
s2n_cert_auth_type client_cert_auth_type;
- GUARD_AS_RESULT(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
+ RESULT_GUARD_POSIX(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED
- && conn->handshake.handshake_type & FULL_HANDSHAKE) {
+ && IS_FULL_HANDSHAKE(conn)) {
/* 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;
+ RESULT_GUARD(s2n_handshake_type_set_flag(conn, CLIENT_AUTH));
} else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE
- && conn->handshake.handshake_type & FULL_HANDSHAKE) {
+ && IS_FULL_HANDSHAKE(conn)) {
/* 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;
+ RESULT_GUARD(s2n_handshake_type_set_flag(conn, 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;
+ if (s2n_is_middlebox_compat_enabled(conn)) {
+ RESULT_GUARD(s2n_handshake_type_set_tls13_flag(conn, MIDDLEBOX_COMPAT));
}
return S2N_RESULT_OK;
}
+static S2N_RESULT s2n_validate_ems_status(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+
+ s2n_extension_type_id ems_ext_id = 0;
+ RESULT_GUARD_POSIX(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_EMS, &ems_ext_id));
+ bool ems_extension_recv = S2N_CBIT_TEST(conn->extension_requests_received, ems_ext_id);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc7627#section-5.3
+ *# If the original session used the "extended_master_secret"
+ *# extension but the new ClientHello does not contain it, the server
+ *# MUST abort the abbreviated handshake.
+ **/
+ if (conn->ems_negotiated) {
+ RESULT_ENSURE(ems_extension_recv, S2N_ERR_MISSING_EXTENSION);
+ }
+
+ /* Since we're discarding the resumption ticket, ignore EMS value from the ticket */
+ conn->ems_negotiated = ems_extension_recv;
+
+ return S2N_RESULT_OK;
+}
+
int s2n_conn_set_handshake_type(struct s2n_connection *conn)
{
if (IS_TLS13_HANDSHAKE(conn)) {
- GUARD_AS_POSIX(s2n_conn_set_tls13_handshake_type(conn));
+ POSIX_GUARD_RESULT(s2n_conn_set_tls13_handshake_type(conn));
return S2N_SUCCESS;
}
- S2N_ERROR_IF(conn->handshake.handshake_type & HELLO_RETRY_REQUEST, S2N_ERR_INVALID_HELLO_RETRY);
+ POSIX_GUARD_RESULT(s2n_handshake_type_reset(conn));
/* A handshake type has been negotiated */
- conn->handshake.handshake_type = NEGOTIATED;
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, NEGOTIATED));
s2n_cert_auth_type client_cert_auth_type;
- GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
+ POSIX_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;
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, 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;
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, CLIENT_AUTH));
}
if (conn->config->use_tickets) {
if (conn->session_ticket_status == S2N_DECRYPT_TICKET) {
- if (!s2n_decrypt_session_ticket(conn)) {
- return 0;
+ if (s2n_decrypt_session_ticket(conn, &conn->client_ticket_to_decrypt) == S2N_SUCCESS) {
+ return S2N_SUCCESS;
}
+ POSIX_GUARD_RESULT(s2n_validate_ems_status(conn));
+
if (s2n_config_is_encrypt_decrypt_key_available(conn->config) == 1) {
conn->session_ticket_status = S2N_NEW_TICKET;
- conn->handshake.handshake_type |= WITH_SESSION_TICKET;
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, WITH_SESSION_TICKET));
}
/* If a session ticket is presented by the client, then skip lookup in Session ID server cache */
@@ -700,7 +850,7 @@ int s2n_conn_set_handshake_type(struct s2n_connection *conn)
}
if (conn->session_ticket_status == S2N_NEW_TICKET) {
- conn->handshake.handshake_type |= WITH_SESSION_TICKET;
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, WITH_SESSION_TICKET));
}
}
@@ -708,92 +858,92 @@ int s2n_conn_set_handshake_type(struct s2n_connection *conn)
* Client sent in the ClientHello. */
if (conn->actual_protocol_version <= S2N_TLS12 && conn->mode == S2N_SERVER && s2n_allowed_to_cache_connection(conn)) {
int r = s2n_resume_from_cache(conn);
- if (r == S2N_SUCCESS || (r < 0 && S2N_ERROR_IS_BLOCKING(s2n_errno))) {
+ if (r == S2N_SUCCESS || (r < S2N_SUCCESS && S2N_ERROR_IS_BLOCKING(s2n_errno))) {
return r;
}
+ POSIX_GUARD_RESULT(s2n_validate_ems_status(conn));
}
skip_cache_lookup:
if (conn->mode == S2N_CLIENT && conn->client_session_resumed == 1) {
- return 0;
+ return S2N_SUCCESS;
}
/* If we're doing full handshake, generate a new session id. */
- GUARD(s2n_generate_new_client_session_id(conn));
+ POSIX_GUARD(s2n_generate_new_client_session_id(conn));
/* If we get this far, it's a full handshake */
- conn->handshake.handshake_type |= FULL_HANDSHAKE;
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, FULL_HANDSHAKE));
bool is_ephemeral = false;
- GUARD_AS_POSIX(s2n_kex_is_ephemeral(conn->secure.cipher_suite->key_exchange_alg, &is_ephemeral));
+ POSIX_GUARD_RESULT(s2n_kex_is_ephemeral(conn->secure.cipher_suite->key_exchange_alg, &is_ephemeral));
if (is_ephemeral) {
- conn->handshake.handshake_type |= TLS12_PERFECT_FORWARD_SECRECY;
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, TLS12_PERFECT_FORWARD_SECRECY));
}
if (s2n_server_can_send_ocsp(conn) || s2n_server_sent_ocsp(conn)) {
- conn->handshake.handshake_type |= OCSP_STATUS;
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, OCSP_STATUS));
}
- return 0;
+ return S2N_SUCCESS;
}
int s2n_conn_set_handshake_no_client_cert(struct s2n_connection *conn)
{
s2n_cert_auth_type client_cert_auth_type;
- GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
+ POSIX_GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
S2N_ERROR_IF(client_cert_auth_type != S2N_CERT_AUTH_OPTIONAL, S2N_ERR_BAD_MESSAGE);
- conn->handshake.handshake_type |= NO_CLIENT_CERT;
-
- return 0;
-}
-
-int s2n_conn_set_handshake_read_block(struct s2n_connection *conn)
-{
- notnull_check(conn);
-
- conn->handshake.paused = 1;
-
- return 0;
-}
-
-int s2n_conn_clear_handshake_read_block(struct s2n_connection *conn)
-{
- notnull_check(conn);
-
- conn->handshake.paused = 0;
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, NO_CLIENT_CERT));
- return 0;
+ return S2N_SUCCESS;
}
const char *s2n_connection_get_last_message_name(struct s2n_connection *conn)
{
- notnull_check_ptr(conn);
-
+ PTR_ENSURE_REF(conn);
+ PTR_GUARD_RESULT(s2n_handshake_validate(&(conn->handshake)));
return message_names[ACTIVE_MESSAGE(conn)];
}
const char *s2n_connection_get_handshake_type_name(struct s2n_connection *conn)
{
- notnull_check_ptr(conn);
+ PTR_ENSURE_REF(conn);
+ PTR_PRECONDITION(s2n_handshake_validate(&(conn->handshake)));
- int handshake_type = conn->handshake.handshake_type;
+ uint32_t handshake_type = conn->handshake.handshake_type;
if (handshake_type == INITIAL) {
return "INITIAL";
}
+ const char** handshake_type_names = tls13_handshake_type_names;
+ size_t handshake_type_names_len = s2n_array_len(tls13_handshake_type_names);
+ if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
+ handshake_type_names = tls12_handshake_type_names;
+ handshake_type_names_len = s2n_array_len(tls12_handshake_type_names);
+ }
+
if (handshake_type_str[handshake_type][0] != '\0') {
return handshake_type_str[handshake_type];
}
- /* Compute handshake_type_str[handshake_type] */
+ /* Compute handshake_type_str[handshake_type] by concatenating
+ * each applicable handshake_type.
+ *
+ * Unit tests enforce that the elements of handshake_type_str are always
+ * long enough to contain the longest possible valid handshake_type, but
+ * for safety we still handle the case where we need to truncate.
+ */
char *p = handshake_type_str[handshake_type];
- char *end = p + sizeof(handshake_type_str[0]);
-
- for (int i = 0; i < s2n_array_len(handshake_type_names); ++i) {
+ size_t remaining = sizeof(handshake_type_str[0]);
+ for (size_t i = 0; i < handshake_type_names_len; i++) {
if (handshake_type & (1 << i)) {
- p = s2n_strcpy(p, end, handshake_type_names[i]);
+ size_t bytes_to_copy = MIN(remaining, strlen(handshake_type_names[i]));
+ PTR_CHECKED_MEMCPY(p, handshake_type_names[i], bytes_to_copy);
+ p[bytes_to_copy] = '\0';
+ p += bytes_to_copy;
+ remaining -= bytes_to_copy;
}
}
@@ -820,11 +970,11 @@ static int s2n_handshake_write_io(struct s2n_connection *conn)
*/
if (s2n_stuffer_is_wiped(&conn->handshake.io)) {
if (record_type == TLS_HANDSHAKE) {
- GUARD(s2n_handshake_write_header(&conn->handshake.io, ACTIVE_STATE(conn).message_type));
+ POSIX_GUARD(s2n_handshake_write_header(&conn->handshake.io, ACTIVE_STATE(conn).message_type));
}
- GUARD(ACTIVE_STATE(conn).handler[conn->mode] (conn));
+ POSIX_GUARD(ACTIVE_STATE(conn).handler[conn->mode] (conn));
if (record_type == TLS_HANDSHAKE) {
- GUARD(s2n_handshake_finish_header(&conn->handshake.io));
+ POSIX_GUARD(s2n_handshake_finish_header(&conn->handshake.io));
}
}
@@ -832,38 +982,39 @@ static int s2n_handshake_write_io(struct s2n_connection *conn)
struct s2n_blob out = {0};
while (s2n_stuffer_data_available(&conn->handshake.io) > 0) {
uint16_t max_payload_size = 0;
- GUARD_AS_POSIX(s2n_record_max_write_payload_size(conn, &max_payload_size));
+ POSIX_GUARD_RESULT(s2n_record_max_write_payload_size(conn, &max_payload_size));
out.size = MIN(s2n_stuffer_data_available(&conn->handshake.io), max_payload_size);
out.data = s2n_stuffer_raw_read(&conn->handshake.io, out.size);
- notnull_check(out.data);
+ POSIX_ENSURE_REF(out.data);
- if (conn->config->quic_enabled) {
- GUARD_AS_POSIX(s2n_quic_write_handshake_message(conn, &out));
+ if (s2n_connection_is_quic_enabled(conn)) {
+ POSIX_GUARD_RESULT(s2n_quic_write_handshake_message(conn, &out));
} else {
- GUARD(s2n_record_write(conn, record_type, &out));
+ POSIX_GUARD(s2n_record_write(conn, record_type, &out));
}
/* MD5 and SHA sum the handshake data too */
if (record_type == TLS_HANDSHAKE) {
- GUARD(s2n_conn_update_handshake_hashes(conn, &out));
+ POSIX_GUARD(s2n_conn_update_handshake_hashes(conn, &out));
}
/* Actually send the record. We could block here. Assume the caller will call flush before coming back. */
- GUARD(s2n_flush(conn, &blocked));
+ POSIX_GUARD(s2n_flush(conn, &blocked));
}
/* We're done sending the last record, reset everything */
- GUARD(s2n_stuffer_wipe(&conn->out));
- GUARD(s2n_stuffer_wipe(&conn->handshake.io));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->out));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
/* Update the secrets, if necessary */
- GUARD(s2n_tls13_handle_secrets(conn));
+ POSIX_GUARD_RESULT(s2n_tls13_secrets_update(conn));
+ POSIX_GUARD_RESULT(s2n_tls13_key_schedule_update(conn));
/* Advance the state machine */
- GUARD(s2n_advance_message(conn));
+ POSIX_GUARD(s2n_advance_message(conn));
- return 0;
+ return S2N_SUCCESS;
}
/*
@@ -880,16 +1031,16 @@ static int s2n_read_full_handshake_message(struct s2n_connection *conn, uint8_t
* what we can and then continue to the next record read iteration.
*/
if (s2n_stuffer_data_available(&conn->in) < (TLS_HANDSHAKE_HEADER_LENGTH - current_handshake_data)) {
- GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, s2n_stuffer_data_available(&conn->in)));
+ POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, s2n_stuffer_data_available(&conn->in)));
return 1;
}
/* Get the remainder of the header */
- GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, (TLS_HANDSHAKE_HEADER_LENGTH - current_handshake_data)));
+ POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, (TLS_HANDSHAKE_HEADER_LENGTH - current_handshake_data)));
}
uint32_t handshake_message_length;
- GUARD(s2n_handshake_parse_header(conn, message_type, &handshake_message_length));
+ POSIX_GUARD(s2n_handshake_parse_header(conn, message_type, &handshake_message_length));
S2N_ERROR_IF(handshake_message_length > S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH, S2N_ERR_BAD_MESSAGE);
@@ -897,7 +1048,7 @@ static int s2n_read_full_handshake_message(struct s2n_connection *conn, uint8_t
bytes_to_take = MIN(bytes_to_take, s2n_stuffer_data_available(&conn->in));
/* If the record is handshake data, add it to the handshake buffer */
- GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, bytes_to_take));
+ POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, bytes_to_take));
/* If we have the whole handshake message, then success */
if (s2n_stuffer_data_available(&conn->handshake.io) == handshake_message_length) {
@@ -905,7 +1056,7 @@ static int s2n_read_full_handshake_message(struct s2n_connection *conn, uint8_t
}
/* We don't have the whole message, so we'll need to go again */
- GUARD(s2n_stuffer_reread(&conn->handshake.io));
+ POSIX_GUARD(s2n_stuffer_reread(&conn->handshake.io));
return 1;
}
@@ -915,18 +1066,18 @@ static int s2n_handshake_conn_update_hashes(struct s2n_connection *conn)
uint8_t message_type;
uint32_t handshake_message_length;
- GUARD(s2n_stuffer_reread(&conn->handshake.io));
- GUARD(s2n_handshake_parse_header(conn, &message_type, &handshake_message_length));
+ POSIX_GUARD(s2n_stuffer_reread(&conn->handshake.io));
+ POSIX_GUARD(s2n_handshake_parse_header(conn, &message_type, &handshake_message_length));
struct s2n_blob handshake_record = {0};
handshake_record.data = conn->handshake.io.blob.data;
handshake_record.size = TLS_HANDSHAKE_HEADER_LENGTH + handshake_message_length;
- notnull_check(handshake_record.data);
+ POSIX_ENSURE_REF(handshake_record.data);
/* MD5 and SHA sum the handshake data too */
- GUARD(s2n_conn_update_handshake_hashes(conn, &handshake_record));
+ POSIX_GUARD(s2n_conn_update_handshake_hashes(conn, &handshake_record));
- return 0;
+ return S2N_SUCCESS;
}
static int s2n_handshake_handle_sslv2(struct s2n_connection *conn)
@@ -935,60 +1086,64 @@ static int s2n_handshake_handle_sslv2(struct s2n_connection *conn)
/* Add the message to our handshake hashes */
struct s2n_blob hashed = {.data = conn->header_in.blob.data + 2,.size = 3 };
- GUARD(s2n_conn_update_handshake_hashes(conn, &hashed));
+ POSIX_GUARD(s2n_conn_update_handshake_hashes(conn, &hashed));
hashed.data = conn->in.blob.data;
hashed.size = s2n_stuffer_data_available(&conn->in);
- GUARD(s2n_conn_update_handshake_hashes(conn, &hashed));
+ POSIX_GUARD(s2n_conn_update_handshake_hashes(conn, &hashed));
/* Handle an SSLv2 client hello */
- GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, s2n_stuffer_data_available(&conn->in)));
+ POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, s2n_stuffer_data_available(&conn->in)));
/* Set the client hello version */
conn->client_hello_version = S2N_SSLv2;
/* Execute the state machine handler */
int r = ACTIVE_STATE(conn).handler[conn->mode](conn);
- GUARD(s2n_stuffer_wipe(&conn->handshake.io));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
/* We're done with the record, wipe it */
- GUARD(s2n_stuffer_wipe(&conn->header_in));
- GUARD(s2n_stuffer_wipe(&conn->in));
- if (r < 0) {
- /* Don't invoke blinding on some of the common errors */
- switch (s2n_errno) {
- case S2N_ERR_CANCELLED:
- case S2N_ERR_CIPHER_NOT_SUPPORTED:
- case S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED:
- conn->closed = 1;
- break;
- case S2N_ERR_IO_BLOCKED:
- case S2N_ERR_ASYNC_BLOCKED:
- /* A blocking condition is retryable, so we should return without killing the connection. */
- S2N_ERROR_PRESERVE_ERRNO();
- break;
- default:
- GUARD(s2n_connection_kill(conn));
- }
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->header_in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
- return r;
- }
+ WITH_ERROR_BLINDING(conn, POSIX_GUARD(r));
conn->in_status = ENCRYPTED;
/* Advance the state machine */
- GUARD(s2n_advance_message(conn));
+ POSIX_GUARD(s2n_advance_message(conn));
- return 0;
+ return S2N_SUCCESS;
}
static int s2n_try_delete_session_cache(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
if (s2n_allowed_to_cache_connection(conn) > 0) {
conn->config->cache_delete(conn, conn->config->cache_delete_data, conn->session_id, conn->session_id_len);
}
- return 0;
+ return S2N_SUCCESS;
+}
+
+static S2N_RESULT s2n_wipe_record(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_GUARD_POSIX(s2n_stuffer_wipe(&conn->header_in));
+ RESULT_GUARD_POSIX(s2n_stuffer_wipe(&conn->in));
+ conn->in_status = ENCRYPTED;
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_finish_read(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+
+ RESULT_GUARD_POSIX(s2n_handshake_conn_update_hashes(conn));
+ RESULT_GUARD_POSIX(s2n_stuffer_wipe(&conn->handshake.io));
+ RESULT_GUARD(s2n_tls13_secrets_update(conn));
+ RESULT_GUARD(s2n_tls13_key_schedule_update(conn));
+ RESULT_GUARD_POSIX(s2n_advance_message(conn));
+ return S2N_RESULT_OK;
}
/* Reading is a little more complicated than writing as the TLS RFCs allow content
@@ -1006,61 +1161,84 @@ static int s2n_handshake_read_io(struct s2n_connection *conn)
/* Fill conn->in stuffer necessary for the handshake.
* If using TCP, read a record. If using QUIC, read a message. */
- if (conn->config->quic_enabled) {
+ if (s2n_connection_is_quic_enabled(conn)) {
record_type = TLS_HANDSHAKE;
- GUARD_AS_POSIX(s2n_quic_read_handshake_message(conn, &message_type));
+ POSIX_GUARD_RESULT(s2n_quic_read_handshake_message(conn, &message_type));
} else {
- GUARD(s2n_read_full_record(conn, &record_type, &isSSLv2));
+ int r = s2n_read_full_record(conn, &record_type, &isSSLv2);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# If the client attempts a 0-RTT handshake but the server
+ *# rejects it, the server will generally not have the 0-RTT record
+ *# protection keys and must instead use trial decryption (either with
+ *# the 1-RTT handshake keys or by looking for a cleartext ClientHello in
+ *# the case of a HelloRetryRequest) to find the first non-0-RTT message.
+ *#
+ *# If the server chooses to accept the "early_data" extension, then it
+ *# MUST comply with the same error-handling requirements specified for
+ *# all records when processing early data records. Specifically, if the
+ *# server fails to decrypt a 0-RTT record following an accepted
+ *# "early_data" extension, it MUST terminate the connection with a
+ *# "bad_record_mac" alert as per Section 5.2.
+ */
+ if ((r < S2N_SUCCESS) && (s2n_errno == S2N_ERR_EARLY_DATA_TRIAL_DECRYPT)) {
+ POSIX_GUARD(s2n_stuffer_reread(&conn->in));
+ POSIX_GUARD_RESULT(s2n_early_data_record_bytes(conn, s2n_stuffer_data_available(&conn->in)));
+ POSIX_GUARD_RESULT(s2n_wipe_record(conn));
+ return S2N_SUCCESS;
+ }
+ POSIX_GUARD(r);
}
if (isSSLv2) {
S2N_ERROR_IF(record_type != SSLv2_CLIENT_HELLO, S2N_ERR_BAD_MESSAGE);
- GUARD(s2n_handshake_handle_sslv2(conn));
+ POSIX_GUARD(s2n_handshake_handle_sslv2(conn));
}
/* Now we have a record, but it could be a partial fragment of a message, or it might
* contain several messages.
*/
- S2N_ERROR_IF(record_type == TLS_APPLICATION_DATA, S2N_ERR_BAD_MESSAGE);
- if (record_type == TLS_CHANGE_CIPHER_SPEC) {
+
+ if (record_type == TLS_APPLICATION_DATA) {
+ POSIX_ENSURE(conn->early_data_expected, S2N_ERR_BAD_MESSAGE);
+ POSIX_GUARD_RESULT(s2n_early_data_validate_recv(conn));
+ POSIX_BAIL(S2N_ERR_EARLY_DATA_BLOCKED);
+ } else if (record_type == TLS_CHANGE_CIPHER_SPEC) {
/* TLS1.3 can receive unexpected CCS messages at any point in the handshake
* due to a peer operating in middlebox compatibility mode.
* However, when operating in QUIC mode, S2N should not accept ANY CCS messages,
* including these unexpected ones.*/
- if (!IS_TLS13_HANDSHAKE(conn) || conn->config->quic_enabled) {
- ENSURE_POSIX(EXPECTED_RECORD_TYPE(conn) == TLS_CHANGE_CIPHER_SPEC, S2N_ERR_BAD_MESSAGE);
- ENSURE_POSIX(!CONNECTION_IS_WRITER(conn), S2N_ERR_BAD_MESSAGE);
+ if (!IS_TLS13_HANDSHAKE(conn) || s2n_connection_is_quic_enabled(conn)) {
+ POSIX_ENSURE(EXPECTED_RECORD_TYPE(conn) == TLS_CHANGE_CIPHER_SPEC, S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE(!CONNECTION_IS_WRITER(conn), S2N_ERR_BAD_MESSAGE);
}
S2N_ERROR_IF(s2n_stuffer_data_available(&conn->in) != 1, S2N_ERR_BAD_MESSAGE);
- GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, s2n_stuffer_data_available(&conn->in)));
- GUARD(CCS_STATE(conn).handler[conn->mode] (conn));
- GUARD(s2n_stuffer_wipe(&conn->handshake.io));
+ POSIX_GUARD(s2n_stuffer_copy(&conn->in, &conn->handshake.io, s2n_stuffer_data_available(&conn->in)));
+ POSIX_GUARD(CCS_STATE(conn).handler[conn->mode] (conn));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
/* We're done with the record, wipe it */
- GUARD(s2n_stuffer_wipe(&conn->header_in));
- GUARD(s2n_stuffer_wipe(&conn->in));
- conn->in_status = ENCRYPTED;
+ POSIX_GUARD_RESULT(s2n_wipe_record(conn));
/* Advance the state machine if this was an expected message */
if (EXPECTED_RECORD_TYPE(conn) == TLS_CHANGE_CIPHER_SPEC && !CONNECTION_IS_WRITER(conn)) {
- GUARD(s2n_advance_message(conn));
+ POSIX_GUARD(s2n_advance_message(conn));
}
- return 0;
+ return S2N_SUCCESS;
} else if (record_type != TLS_HANDSHAKE) {
if (record_type == TLS_ALERT) {
- GUARD(s2n_process_alert_fragment(conn));
+ POSIX_GUARD(s2n_process_alert_fragment(conn));
}
/* Ignore record types that we don't support */
/* We're done with the record, wipe it */
- GUARD(s2n_stuffer_wipe(&conn->header_in));
- GUARD(s2n_stuffer_wipe(&conn->in));
- conn->in_status = ENCRYPTED;
- return 0;
+ POSIX_GUARD_RESULT(s2n_wipe_record(conn));
+ return S2N_SUCCESS;
}
/* Record is a handshake message */
@@ -1070,29 +1248,27 @@ static int s2n_handshake_read_io(struct s2n_connection *conn)
/* We're done with negotiating but we have trailing data in this record. Bail on the handshake. */
S2N_ERROR_IF(EXPECTED_RECORD_TYPE(conn) == TLS_APPLICATION_DATA, S2N_ERR_BAD_MESSAGE);
int r;
- GUARD((r = s2n_read_full_handshake_message(conn, &message_type)));
+ POSIX_GUARD((r = s2n_read_full_handshake_message(conn, &message_type)));
/* Do we need more data? This happens for message fragmentation */
if (r == 1) {
/* Break out of this inner loop, but since we're not changing the state, the
* outer loop in s2n_handshake_io() will read another record.
*/
- GUARD(s2n_stuffer_wipe(&conn->header_in));
- GUARD(s2n_stuffer_wipe(&conn->in));
- conn->in_status = ENCRYPTED;
- return 0;
+ POSIX_GUARD_RESULT(s2n_wipe_record(conn));
+ return S2N_SUCCESS;
}
s2n_cert_auth_type client_cert_auth_type;
- GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
+ POSIX_GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
/* If we're a Client, and received a ClientCertRequest message, and ClientAuth
* is set to optional, then switch the State Machine that we're using to expect the ClientCertRequest. */
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;
+ POSIX_ENSURE(IS_FULL_HANDSHAKE(conn), S2N_ERR_HANDSHAKE_STATE);
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, CLIENT_AUTH));
}
/* According to rfc6066 section 8, server may choose not to send "CertificateStatus" message even if it has
@@ -1100,55 +1276,35 @@ static int s2n_handshake_read_io(struct s2n_connection *conn)
if (conn->mode == S2N_CLIENT
&& EXPECTED_MESSAGE_TYPE(conn) == TLS_SERVER_CERT_STATUS
&& message_type != TLS_SERVER_CERT_STATUS) {
- conn->handshake.handshake_type &= ~OCSP_STATUS;
+ POSIX_GUARD_RESULT(s2n_handshake_type_unset_tls12_flag(conn, OCSP_STATUS));
}
- ENSURE_POSIX(record_type == EXPECTED_RECORD_TYPE(conn), S2N_ERR_BAD_MESSAGE);
- ENSURE_POSIX(message_type == EXPECTED_MESSAGE_TYPE(conn), S2N_ERR_BAD_MESSAGE);
- ENSURE_POSIX(!CONNECTION_IS_WRITER(conn), S2N_ERR_BAD_MESSAGE);
-
- /* Call the relevant handler */
- r = ACTIVE_STATE(conn).handler[conn->mode] (conn);
-
- /* Don't update handshake hashes until after the handler has executed since some handlers need to read the
- * hash values before they are updated. */
- GUARD(s2n_handshake_conn_update_hashes(conn));
-
- GUARD(s2n_stuffer_wipe(&conn->handshake.io));
-
- if (r < 0) {
- /* Don't invoke blinding on some of the common errors */
- switch (s2n_errno) {
- case S2N_ERR_CANCELLED:
- case S2N_ERR_CIPHER_NOT_SUPPORTED:
- case S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED:
- conn->closed = 1;
- break;
- case S2N_ERR_IO_BLOCKED:
- case S2N_ERR_ASYNC_BLOCKED:
- /* A blocking condition is retryable, so we should return without killing the connection. */
- S2N_ERROR_PRESERVE_ERRNO();
- break;
- default:
- GUARD(s2n_connection_kill(conn));
- }
-
- return r;
+ /*
+ *= https://tools.ietf.org/rfc/rfc5246#section-7.4
+ *# The one message that is not bound by these ordering rules
+ *# is the HelloRequest message, which can be sent at any time, but which
+ *# SHOULD be ignored by the client if it arrives in the middle of a handshake.
+ */
+ if (message_type == TLS_HELLO_REQUEST) {
+ POSIX_GUARD(s2n_client_hello_request_recv(conn));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
+ continue;
}
- /* Update the secrets, if necessary */
- GUARD(s2n_tls13_handle_secrets(conn));
+ POSIX_ENSURE(record_type == EXPECTED_RECORD_TYPE(conn), S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE(message_type == EXPECTED_MESSAGE_TYPE(conn), S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE(!CONNECTION_IS_WRITER(conn), S2N_ERR_BAD_MESSAGE);
+
+ /* Call the relevant handler */
+ WITH_ERROR_BLINDING(conn, POSIX_GUARD(ACTIVE_STATE(conn).handler[conn->mode] (conn)));
/* Advance the state machine */
- GUARD(s2n_advance_message(conn));
+ POSIX_GUARD_RESULT(s2n_finish_read(conn));
}
/* We're done with the record, wipe it */
- GUARD(s2n_stuffer_wipe(&conn->header_in));
- GUARD(s2n_stuffer_wipe(&conn->in));
- conn->in_status = ENCRYPTED;
-
- return 0;
+ POSIX_GUARD_RESULT(s2n_wipe_record(conn));
+ return S2N_SUCCESS;
}
static int s2n_handle_retry_state(struct s2n_connection *conn)
@@ -1160,66 +1316,66 @@ static int s2n_handle_retry_state(struct s2n_connection *conn)
s2n_errno = S2N_ERR_OK;
const int r = ACTIVE_STATE(conn).handler[conn->mode] (conn);
- if (r < 0 && S2N_ERROR_IS_BLOCKING(s2n_errno)) {
+ if (r < S2N_SUCCESS && S2N_ERROR_IS_BLOCKING(s2n_errno)) {
/* If the handler is still waiting for data, return control to the caller. */
S2N_ERROR_PRESERVE_ERRNO();
}
+ /* Resume the handshake */
+ conn->handshake.paused = false;
+
if (!CONNECTION_IS_WRITER(conn)) {
/* We're done parsing the record, reset everything */
- GUARD(s2n_stuffer_wipe(&conn->header_in));
- GUARD(s2n_stuffer_wipe(&conn->in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->header_in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
conn->in_status = ENCRYPTED;
}
- if (r < 0) {
- /* There is some other problem and we should kill the connection. */
- if (conn->session_id_len) {
- s2n_try_delete_session_cache(conn);
- }
-
- GUARD(s2n_connection_kill(conn));
- S2N_ERROR_PRESERVE_ERRNO();
- }
-
if (CONNECTION_IS_WRITER(conn)) {
+ POSIX_GUARD(r);
+
/* If we're the writer and handler just finished, update the record header if
* needed and let the s2n_handshake_write_io write the data to the socket */
if (EXPECTED_RECORD_TYPE(conn) == TLS_HANDSHAKE) {
- GUARD(s2n_handshake_finish_header(&conn->handshake.io));
+ POSIX_GUARD(s2n_handshake_finish_header(&conn->handshake.io));
}
} else {
+ if (r < S2N_SUCCESS && conn->session_id_len) {
+ s2n_try_delete_session_cache(conn);
+ }
+ WITH_ERROR_BLINDING(conn, POSIX_GUARD(r));
+
/* The read handler processed the record successfully, we are done with this
* record. Advance the state machine. */
- GUARD(s2n_advance_message(conn));
+ POSIX_GUARD_RESULT(s2n_finish_read(conn));
}
- return 0;
+ return S2N_SUCCESS;
}
-int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked)
+int s2n_negotiate_impl(struct s2n_connection *conn, s2n_blocked_status *blocked)
{
- notnull_check(conn);
- notnull_check(blocked);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(blocked);
- while (ACTIVE_STATE(conn).writer != 'B') {
+ while (ACTIVE_STATE(conn).writer != 'B' && ACTIVE_MESSAGE(conn) != conn->handshake.end_of_messages) {
errno = 0;
s2n_errno = S2N_ERR_OK;
/* Flush any pending I/O or alert messages */
- GUARD(s2n_flush(conn, blocked));
+ POSIX_GUARD(s2n_flush(conn, blocked));
/* If the handshake was paused, retry the current message */
if (conn->handshake.paused) {
*blocked = S2N_BLOCKED_ON_APPLICATION_INPUT;
- GUARD(s2n_handle_retry_state(conn));
+ POSIX_GUARD(s2n_handle_retry_state(conn));
}
if (CONNECTION_IS_WRITER(conn)) {
*blocked = S2N_BLOCKED_ON_WRITE;
const int write_result = s2n_handshake_write_io(conn);
- if (write_result < 0) {
+ if (write_result < S2N_SUCCESS) {
if (!S2N_ERROR_IS_BLOCKING(s2n_errno)) {
/* Non-retryable write error. The peer might have sent an alert. Try and read it. */
const int write_errno = errno;
@@ -1240,6 +1396,9 @@ int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked)
if (s2n_errno == S2N_ERR_ASYNC_BLOCKED) {
*blocked = S2N_BLOCKED_ON_APPLICATION_INPUT;
+ conn->handshake.paused = true;
+ } else if (s2n_errno == S2N_ERR_EARLY_DATA_BLOCKED) {
+ *blocked = S2N_BLOCKED_ON_EARLY_DATA;
}
S2N_ERROR_PRESERVE_ERRNO();
@@ -1248,7 +1407,7 @@ int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked)
*blocked = S2N_BLOCKED_ON_READ;
const int read_result = s2n_handshake_read_io(conn);
- if (read_result < 0) {
+ if (read_result < S2N_SUCCESS) {
/* One blocking condition is waiting on the session resumption cache. */
/* So we don't want to delete anything if we are blocked. */
if (!S2N_ERROR_IS_BLOCKING(s2n_errno) && conn->session_id_len) {
@@ -1257,19 +1416,38 @@ int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked)
if (s2n_errno == S2N_ERR_ASYNC_BLOCKED) {
*blocked = S2N_BLOCKED_ON_APPLICATION_INPUT;
+ conn->handshake.paused = true;
+ } else if (s2n_errno == S2N_ERR_EARLY_DATA_BLOCKED) {
+ *blocked = S2N_BLOCKED_ON_EARLY_DATA;
}
S2N_ERROR_PRESERVE_ERRNO();
}
}
- /* If the handshake has just ended, free up memory */
if (ACTIVE_STATE(conn).writer == 'B') {
- GUARD(s2n_stuffer_resize(&conn->handshake.io, 0));
+ /* Clean up handshake secrets */
+ POSIX_GUARD_RESULT(s2n_tls13_secrets_clean(conn));
+
+ /* Send any pending post-handshake messages */
+ POSIX_GUARD(s2n_post_handshake_send(conn, blocked));
+
+ /* If the handshake has just ended, free up memory */
+ POSIX_GUARD(s2n_stuffer_resize(&conn->handshake.io, 0));
}
}
*blocked = S2N_NOT_BLOCKED;
- return 0;
+ return S2N_SUCCESS;
+}
+
+int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE(!conn->negotiate_in_use, S2N_ERR_REENTRANCY);
+ conn->negotiate_in_use = true;
+ int result = s2n_negotiate_impl(conn, blocked);
+ conn->negotiate_in_use = false;
+ return result;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_transcript.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_transcript.c
index 7c6c3dffb6..d0eb448f41 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_handshake_transcript.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_transcript.c
@@ -24,21 +24,12 @@
/* Length of the synthetic message header */
#define MESSAGE_HASH_HEADER_LENGTH 4
-static int s2n_tls13_conn_copy_server_finished_hash(struct s2n_connection *conn) {
- notnull_check(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));
- GUARD(s2n_hash_copy(&conn->handshake.server_finished_copy, &hash_state));
-
- return 0;
-}
-
int s2n_conn_update_handshake_hashes(struct s2n_connection *conn, struct s2n_blob *data)
{
- notnull_check(conn);
- notnull_check(data);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(data);
+ struct s2n_handshake_hashes *hashes = conn->handshake.hashes;
+ POSIX_ENSURE_REF(hashes);
if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_MD5)) {
/* The handshake MD5 hash state will fail the s2n_hash_is_available() check
@@ -47,11 +38,11 @@ int s2n_conn_update_handshake_hashes(struct s2n_connection *conn, struct s2n_blo
* PRF, which is required to comply with the TLS 1.0 and 1.1 RFCs and is approved
* as per NIST Special Publication 800-52 Revision 1.
*/
- GUARD(s2n_hash_update(&conn->handshake.md5, data->data, data->size));
+ POSIX_GUARD(s2n_hash_update(&hashes->md5, data->data, data->size));
}
if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA1)) {
- GUARD(s2n_hash_update(&conn->handshake.sha1, data->data, data->size));
+ POSIX_GUARD(s2n_hash_update(&hashes->sha1, data->data, data->size));
}
const uint8_t md5_sha1_required = (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_MD5) &&
@@ -63,33 +54,26 @@ int s2n_conn_update_handshake_hashes(struct s2n_connection *conn, struct s2n_blo
* CertificateVerify message and the PRF. NIST SP 800-52r1 approves use
* of MD5_SHA1 for these use cases (see footnotes 15 and 20, and section
* 3.3.2) */
- GUARD(s2n_hash_update(&conn->handshake.md5_sha1, data->data, data->size));
+ POSIX_GUARD(s2n_hash_update(&hashes->md5_sha1, data->data, data->size));
}
if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA224)) {
- GUARD(s2n_hash_update(&conn->handshake.sha224, data->data, data->size));
+ POSIX_GUARD(s2n_hash_update(&hashes->sha224, data->data, data->size));
}
if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA256)) {
- GUARD(s2n_hash_update(&conn->handshake.sha256, data->data, data->size));
+ POSIX_GUARD(s2n_hash_update(&hashes->sha256, data->data, data->size));
}
if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA384)) {
- GUARD(s2n_hash_update(&conn->handshake.sha384, data->data, data->size));
+ POSIX_GUARD(s2n_hash_update(&hashes->sha384, data->data, data->size));
}
if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA512)) {
- GUARD(s2n_hash_update(&conn->handshake.sha512, data->data, data->size));
+ POSIX_GUARD(s2n_hash_update(&hashes->sha512, data->data, data->size));
}
- /* Copy the CLIENT_HELLO -> SERVER_FINISHED hash.
- * TLS1.3 will need it later to calculate the application secrets. */
- if (s2n_connection_get_protocol_version(conn) >= S2N_TLS13 &&
- s2n_conn_get_current_message_type(conn) == SERVER_FINISHED) {
- GUARD(s2n_tls13_conn_copy_server_finished_hash(conn));
- }
-
- return 0;
+ return S2N_SUCCESS;
}
/* When a HelloRetryRequest message is used, the hash transcript needs to be recreated.
@@ -99,7 +83,9 @@ int s2n_conn_update_handshake_hashes(struct s2n_connection *conn, struct s2n_blo
*/
int s2n_server_hello_retry_recreate_transcript(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
+ struct s2n_handshake_hashes *hashes = conn->handshake.hashes;
+ POSIX_ENSURE_REF(hashes);
s2n_tls13_connection_keys(keys, conn);
uint8_t hash_digest_length = keys.size;
@@ -110,27 +96,22 @@ int s2n_server_hello_retry_recreate_transcript(struct s2n_connection *conn)
msghdr[MESSAGE_HASH_HEADER_LENGTH - 1] = hash_digest_length;
/* Grab the current transcript hash to use as the ClientHello1 value. */
- struct s2n_hash_state hash_state, client_hello1_hash;
- uint8_t client_hello1_digest_out[S2N_MAX_DIGEST_LEN];
- GUARD(s2n_handshake_get_hash_state(conn, keys.hash_algorithm, &hash_state));
-
- GUARD(s2n_hash_new(&client_hello1_hash));
- GUARD(s2n_hash_copy(&client_hello1_hash, &hash_state));
- GUARD(s2n_hash_digest(&client_hello1_hash, client_hello1_digest_out, hash_digest_length));
- GUARD(s2n_hash_free(&client_hello1_hash));
+ struct s2n_hash_state *client_hello1_hash = &hashes->hash_workspace;
+ uint8_t client_hello1_digest_out[S2N_MAX_DIGEST_LEN] = { 0 };
+ POSIX_GUARD_RESULT(s2n_handshake_copy_hash_state(conn, keys.hash_algorithm, client_hello1_hash));
+ POSIX_GUARD(s2n_hash_digest(client_hello1_hash, client_hello1_digest_out, hash_digest_length));
/* Step 1: Reset the hash state */
- GUARD(s2n_handshake_reset_hash_state(conn, keys.hash_algorithm));
+ POSIX_GUARD_RESULT(s2n_handshake_reset_hash_state(conn, keys.hash_algorithm));
/* Step 2: Update the transcript with the synthetic message */
struct s2n_blob msg_blob = {0};
- GUARD(s2n_blob_init(&msg_blob, msghdr, MESSAGE_HASH_HEADER_LENGTH));
- GUARD(s2n_conn_update_handshake_hashes(conn, &msg_blob));
+ POSIX_GUARD(s2n_blob_init(&msg_blob, msghdr, MESSAGE_HASH_HEADER_LENGTH));
+ POSIX_GUARD(s2n_conn_update_handshake_hashes(conn, &msg_blob));
/* Step 3: Update the transcript with the ClientHello1 hash */
- GUARD(s2n_blob_init(&msg_blob, client_hello1_digest_out, hash_digest_length));
- GUARD(s2n_conn_update_handshake_hashes(conn, &msg_blob));
+ POSIX_GUARD(s2n_blob_init(&msg_blob, client_hello1_digest_out, hash_digest_length));
+ POSIX_GUARD(s2n_conn_update_handshake_hashes(conn, &msg_blob));
- return 0;
+ return S2N_SUCCESS;
}
-
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_type.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_type.c
new file mode 100644
index 0000000000..1ba27a3684
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_type.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#include "tls/s2n_connection.h"
+#include "tls/s2n_handshake_type.h"
+#include "utils/s2n_safety.h"
+
+S2N_RESULT s2n_handshake_type_set_flag(struct s2n_connection *conn, s2n_handshake_type_flag flag)
+{
+ RESULT_ENSURE_REF(conn);
+ conn->handshake.handshake_type |= flag;
+ return S2N_RESULT_OK;
+}
+
+bool s2n_handshake_type_check_flag(struct s2n_connection *conn, s2n_handshake_type_flag flag)
+{
+ return conn && (conn->handshake.handshake_type & flag);
+}
+
+S2N_RESULT s2n_handshake_type_set_tls12_flag(struct s2n_connection *conn, s2n_tls12_handshake_type_flag flag)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE(s2n_connection_get_protocol_version(conn) < S2N_TLS13, S2N_ERR_HANDSHAKE_STATE);
+ conn->handshake.handshake_type |= flag;
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_handshake_type_unset_tls12_flag(struct s2n_connection *conn, s2n_tls12_handshake_type_flag flag)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE(s2n_connection_get_protocol_version(conn) < S2N_TLS13, S2N_ERR_HANDSHAKE_STATE);
+ conn->handshake.handshake_type &= ~(flag);
+ return S2N_RESULT_OK;
+}
+
+bool s2n_handshake_type_check_tls12_flag(struct s2n_connection *conn, s2n_tls12_handshake_type_flag flag)
+{
+ return conn && s2n_connection_get_protocol_version(conn) < S2N_TLS13
+ && (conn->handshake.handshake_type & flag);
+}
+
+S2N_RESULT s2n_handshake_type_set_tls13_flag(struct s2n_connection *conn, s2n_tls13_handshake_type_flag flag)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE(s2n_connection_get_protocol_version(conn) >= S2N_TLS13, S2N_ERR_HANDSHAKE_STATE);
+ conn->handshake.handshake_type |= flag;
+ return S2N_RESULT_OK;
+}
+
+bool s2n_handshake_type_check_tls13_flag(struct s2n_connection *conn, s2n_tls13_handshake_type_flag flag)
+{
+ return s2n_connection_get_protocol_version(conn) >= S2N_TLS13
+ && (conn->handshake.handshake_type & flag);
+}
+
+S2N_RESULT s2n_handshake_type_reset(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ conn->handshake.handshake_type = 0;
+ return S2N_RESULT_OK;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_type.h b/contrib/restricted/aws/s2n/tls/s2n_handshake_type.h
new file mode 100644
index 0000000000..2163457eb9
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_type.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#pragma once
+
+#include "utils/s2n_result.h"
+
+/* Maximum number of valid handshakes */
+#define S2N_HANDSHAKES_COUNT 256
+
+#define IS_NEGOTIATED(conn) \
+ ( s2n_handshake_type_check_flag(conn, NEGOTIATED) )
+
+#define IS_FULL_HANDSHAKE(conn) \
+ ( s2n_handshake_type_check_flag(conn, FULL_HANDSHAKE) )
+
+#define IS_RESUMPTION_HANDSHAKE(conn) \
+ ( !IS_FULL_HANDSHAKE(conn) && IS_NEGOTIATED(conn) )
+
+#define IS_CLIENT_AUTH_HANDSHAKE(conn) \
+ ( s2n_handshake_type_check_flag(conn, CLIENT_AUTH) )
+
+#define IS_CLIENT_AUTH_NO_CERT(conn) \
+ ( IS_CLIENT_AUTH_HANDSHAKE(conn) && s2n_handshake_type_check_flag(conn, NO_CLIENT_CERT) )
+
+#define IS_TLS12_PERFECT_FORWARD_SECRECY_HANDSHAKE(conn) \
+ ( s2n_handshake_type_check_tls12_flag(conn, TLS12_PERFECT_FORWARD_SECRECY) )
+
+#define IS_OCSP_STAPLED(conn) \
+ ( s2n_handshake_type_check_tls12_flag(conn, OCSP_STATUS) )
+
+#define IS_ISSUING_NEW_SESSION_TICKET(conn) \
+ ( s2n_handshake_type_check_tls12_flag(conn, WITH_SESSION_TICKET) )
+
+#define IS_HELLO_RETRY_HANDSHAKE(conn) \
+ ( s2n_handshake_type_check_tls13_flag(conn, HELLO_RETRY_REQUEST) )
+
+#define IS_MIDDLEBOX_COMPAT_MODE(conn) \
+ ( s2n_handshake_type_check_tls13_flag(conn, MIDDLEBOX_COMPAT) )
+
+#define WITH_EARLY_DATA(conn) \
+ ( s2n_handshake_type_check_tls13_flag(conn, WITH_EARLY_DATA) )
+
+#define WITH_EARLY_CLIENT_CCS(conn) \
+ ( s2n_handshake_type_check_tls13_flag(conn, EARLY_CLIENT_CCS) )
+
+typedef enum {
+ INITIAL = 0,
+ NEGOTIATED = 1,
+ FULL_HANDSHAKE = 2,
+ CLIENT_AUTH = 4,
+ NO_CLIENT_CERT = 8,
+} s2n_handshake_type_flag;
+
+S2N_RESULT s2n_handshake_type_set_flag(struct s2n_connection *conn, s2n_handshake_type_flag flag);
+bool s2n_handshake_type_check_flag(struct s2n_connection *conn, s2n_handshake_type_flag flag);
+
+typedef enum {
+ TLS12_PERFECT_FORWARD_SECRECY = 16,
+ OCSP_STATUS = 32,
+ WITH_SESSION_TICKET = 64,
+} s2n_tls12_handshake_type_flag;
+
+S2N_RESULT s2n_handshake_type_set_tls12_flag(struct s2n_connection *conn, s2n_tls12_handshake_type_flag flag);
+S2N_RESULT s2n_handshake_type_unset_tls12_flag(struct s2n_connection *conn, s2n_tls12_handshake_type_flag flag);
+bool s2n_handshake_type_check_tls12_flag(struct s2n_connection *conn, s2n_tls12_handshake_type_flag flag);
+
+typedef enum {
+ HELLO_RETRY_REQUEST = 16,
+ MIDDLEBOX_COMPAT = 32,
+ WITH_EARLY_DATA = 64,
+ EARLY_CLIENT_CCS = 128,
+} s2n_tls13_handshake_type_flag;
+
+S2N_RESULT s2n_handshake_type_set_tls13_flag(struct s2n_connection *conn, s2n_tls13_handshake_type_flag flag);
+bool s2n_handshake_type_check_tls13_flag(struct s2n_connection *conn, s2n_tls13_handshake_type_flag flag);
+
+S2N_RESULT s2n_handshake_type_reset(struct s2n_connection *conn);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_internal.h b/contrib/restricted/aws/s2n/tls/s2n_internal.h
new file mode 100644
index 0000000000..5728188f30
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_internal.h
@@ -0,0 +1,57 @@
+/*
+ * 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
+
+#if ((__GNUC__ >= 4) || defined(__clang__)) && defined(S2N_EXPORTS)
+# define S2N_PRIVATE_API __attribute__((visibility("default")))
+#else
+# define S2N_PRIVATE_API
+#endif /* __GNUC__ >= 4 || defined(__clang__) */
+
+
+#include <stdint.h>
+
+/*
+ * Internal APIs.
+ *
+ * These APIs change the behavior of S2N in potentially dangerous ways and should only be
+ * used for testing purposes. All Internal APIs are subject to change without notice.
+ */
+
+struct s2n_config;
+struct s2n_connection;
+
+/*
+ * Gets the config set on the connection.
+ *
+ * This function will return a pointer to the config set by `s2n_connection_set_config`.
+ * It will return NULL prior to `s2n_connection_set_config` being called and a config
+ * being set by the application.
+ *
+ * Caution: A config can be associated with multiple connections and should not be
+ * modified after it has been built. Doing so is undefined behavior.
+ */
+S2N_PRIVATE_API
+extern int s2n_connection_get_config(struct s2n_connection *conn, struct s2n_config **config);
+
+/*
+ * Enable polling the async client_hello callback to make progress.
+ *
+ * `s2n_negotiate` must be called multiple times to poll the callback function
+ * and make progress.
+ */
+S2N_PRIVATE_API
+extern int s2n_config_client_hello_cb_enable_poll(struct s2n_config *config);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem.c b/contrib/restricted/aws/s2n/tls/s2n_kem.c
index aef1665918..8566502ccb 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kem.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_kem.c
@@ -46,6 +46,18 @@ const struct s2n_kem s2n_bike1_l1_r2 = {
.decapsulate = &BIKE1_L1_R2_crypto_kem_dec,
};
+const struct s2n_kem s2n_bike_l1_r3 = {
+ .name = "BIKEr3-Level1",
+ .kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_BIKE1_L1_R3,
+ .public_key_length = BIKE_L1_R3_PUBLIC_KEY_BYTES,
+ .private_key_length = BIKE_L1_R3_SECRET_KEY_BYTES,
+ .shared_secret_key_length = BIKE_L1_R3_SHARED_SECRET_BYTES,
+ .ciphertext_length = BIKE_L1_R3_CIPHERTEXT_BYTES,
+ .generate_keypair = &BIKE_L1_R3_crypto_kem_keypair,
+ .encapsulate = &BIKE_L1_R3_crypto_kem_enc,
+ .decapsulate = &BIKE_L1_R3_crypto_kem_dec,
+};
+
const struct s2n_kem s2n_sike_p503_r1 = {
.name = "SIKEp503r1-KEM",
.kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_SIKE_P503_R1,
@@ -58,18 +70,6 @@ const struct s2n_kem s2n_sike_p503_r1 = {
.decapsulate = &SIKE_P503_r1_crypto_kem_dec,
};
-const struct s2n_kem s2n_sike_p434_r2 = {
- .name = "SIKEp434r2-KEM",
- .kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_SIKE_P434_R2,
- .public_key_length = SIKE_P434_R2_PUBLIC_KEY_BYTES,
- .private_key_length = SIKE_P434_R2_SECRET_KEY_BYTES,
- .shared_secret_key_length = SIKE_P434_R2_SHARED_SECRET_BYTES,
- .ciphertext_length = SIKE_P434_R2_CIPHERTEXT_BYTES,
- .generate_keypair = &SIKE_P434_r2_crypto_kem_keypair,
- .encapsulate = &SIKE_P434_r2_crypto_kem_enc,
- .decapsulate = &SIKE_P434_r2_crypto_kem_dec,
-};
-
const struct s2n_kem s2n_kyber_512_r2 = {
.name = "kyber512r2",
.kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_KYBER_512_R2,
@@ -94,23 +94,49 @@ const struct s2n_kem s2n_kyber_512_90s_r2 = {
.decapsulate = &kyber_512_90s_r2_crypto_kem_dec,
};
+const struct s2n_kem s2n_kyber_512_r3 = {
+ .name = "kyber512r3",
+ .kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_KYBER_512_R3,
+ .public_key_length = S2N_KYBER_512_R3_PUBLIC_KEY_BYTES,
+ .private_key_length = S2N_KYBER_512_R3_SECRET_KEY_BYTES,
+ .shared_secret_key_length = S2N_KYBER_512_R3_SHARED_SECRET_BYTES,
+ .ciphertext_length = S2N_KYBER_512_R3_CIPHERTEXT_BYTES,
+ .generate_keypair = &s2n_kyber_512_r3_crypto_kem_keypair,
+ .encapsulate = &s2n_kyber_512_r3_crypto_kem_enc,
+ .decapsulate = &s2n_kyber_512_r3_crypto_kem_dec,
+};
+
+const struct s2n_kem s2n_sike_p434_r3 = {
+ .name = "SIKEp434r3-KEM",
+ .kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_SIKE_P434_R3,
+ .public_key_length = S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES,
+ .private_key_length = S2N_SIKE_P434_R3_SECRET_KEY_BYTES,
+ .shared_secret_key_length = S2N_SIKE_P434_R3_SHARED_SECRET_BYTES,
+ .ciphertext_length = S2N_SIKE_P434_R3_CIPHERTEXT_BYTES,
+ .generate_keypair = &s2n_sike_p434_r3_crypto_kem_keypair,
+ .encapsulate = &s2n_sike_p434_r3_crypto_kem_enc,
+ .decapsulate = &s2n_sike_p434_r3_crypto_kem_dec,
+};
+
/* These lists should be kept up to date with the above KEMs. Order in the lists
* does not matter. Adding a KEM to these lists will not automatically enable
* support for the KEM extension - that must be added via the KEM preferences &
* security policies. These lists are applicable only to PQ-TLS 1.2. */
const struct s2n_kem *bike_kems[] = {
&s2n_bike1_l1_r1,
- &s2n_bike1_l1_r2
+ &s2n_bike1_l1_r2,
+ &s2n_bike_l1_r3
};
const struct s2n_kem *sike_kems[] = {
&s2n_sike_p503_r1,
- &s2n_sike_p434_r2,
+ &s2n_sike_p434_r3,
};
const struct s2n_kem *kyber_kems[] = {
&s2n_kyber_512_r2,
&s2n_kyber_512_90s_r2,
+ &s2n_kyber_512_r3,
};
const struct s2n_iana_to_kem kem_mapping[3] = {
@@ -136,26 +162,25 @@ const struct s2n_iana_to_kem kem_mapping[3] = {
* community to use values in the proposed reserved range defined in
* https://tools.ietf.org/html/draft-stebila-tls-hybrid-design.
* Values for interoperability are defined in
- * https://docs.google.com/spreadsheets/d/12YarzaNv3XQNLnvDsWLlRKwtZFhRrDdWf36YlzwrPeg/edit#gid=0.
+ * https://github.com/open-quantum-safe/openssl/blob/OQS-OpenSSL_1_1_1-stable/oqs-template/oqs-kem-info.md
*
* The structure of the hybrid share is:
* size of ECC key share (2 bytes)
* || ECC key share (variable bytes)
* || size of PQ key share (2 bytes)
* || PQ key share (variable bytes) */
-const struct s2n_kem_group s2n_secp256r1_sike_p434_r2 = {
- .name = "secp256r1_sike-p434-r2",
- .iana_id = TLS_PQ_KEM_GROUP_ID_SECP256R1_SIKE_P434_R2,
+const struct s2n_kem_group s2n_secp256r1_sike_p434_r3 = {
+ .name = "secp256r1_sike-p434-r3",
+ .iana_id = TLS_PQ_KEM_GROUP_ID_SECP256R1_SIKE_P434_R3,
.client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) +
- (S2N_SIZE_OF_KEY_SHARE_SIZE + SIKE_P434_R2_PUBLIC_KEY_BYTES),
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES),
.server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) +
- (S2N_SIZE_OF_KEY_SHARE_SIZE + SIKE_P434_R2_CIPHERTEXT_BYTES),
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + S2N_SIKE_P434_R3_CIPHERTEXT_BYTES),
.curve = &s2n_ecc_curve_secp256r1,
- .kem = &s2n_sike_p434_r2,
+ .kem = &s2n_sike_p434_r3,
};
const struct s2n_kem_group s2n_secp256r1_bike1_l1_r2 = {
- /* The name string follows the convention in the above google doc */
.name = "secp256r1_bike-1l1fo-r2",
.iana_id = TLS_PQ_KEM_GROUP_ID_SECP256R1_BIKE1_L1_R2,
.client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) +
@@ -177,20 +202,41 @@ const struct s2n_kem_group s2n_secp256r1_kyber_512_r2 = {
.kem = &s2n_kyber_512_r2,
};
+const struct s2n_kem_group s2n_secp256r1_bike_l1_r3 = {
+ .name = "secp256r1_bike-l1-r3",
+ .iana_id = TLS_PQ_KEM_GROUP_ID_SECP256R1_BIKE_L1_R3,
+ .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) +
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE_L1_R3_PUBLIC_KEY_BYTES),
+ .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) +
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE_L1_R3_CIPHERTEXT_BYTES),
+ .curve = &s2n_ecc_curve_secp256r1,
+ .kem = &s2n_bike_l1_r3,
+};
+
+const struct s2n_kem_group s2n_secp256r1_kyber_512_r3 = {
+ .name = "secp256r1_kyber-512-r3",
+ .iana_id = TLS_PQ_KEM_GROUP_ID_SECP256R1_KYBER_512_R3,
+ .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) +
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + S2N_KYBER_512_R3_PUBLIC_KEY_BYTES),
+ .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) +
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + S2N_KYBER_512_R3_CIPHERTEXT_BYTES),
+ .curve = &s2n_ecc_curve_secp256r1,
+ .kem = &s2n_kyber_512_r3,
+};
+
#if EVP_APIS_SUPPORTED
-const struct s2n_kem_group s2n_x25519_sike_p434_r2 = {
- .name = "x25519_sike-p434-r2",
- .iana_id = TLS_PQ_KEM_GROUP_ID_X25519_SIKE_P434_R2,
+const struct s2n_kem_group s2n_x25519_sike_p434_r3 = {
+ .name = "x25519_sike-p434-r3",
+ .iana_id = TLS_PQ_KEM_GROUP_ID_X25519_SIKE_P434_R3,
.client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) +
- (S2N_SIZE_OF_KEY_SHARE_SIZE + SIKE_P434_R2_PUBLIC_KEY_BYTES),
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES),
.server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) +
- (S2N_SIZE_OF_KEY_SHARE_SIZE + SIKE_P434_R2_CIPHERTEXT_BYTES),
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + S2N_SIKE_P434_R3_CIPHERTEXT_BYTES),
.curve = &s2n_ecc_curve_x25519,
- .kem = &s2n_sike_p434_r2,
+ .kem = &s2n_sike_p434_r3,
};
const struct s2n_kem_group s2n_x25519_bike1_l1_r2 = {
- /* The name string follows the convention in the above google doc */
.name = "x25519_bike-1l1fo-r2",
.iana_id = TLS_PQ_KEM_GROUP_ID_X25519_BIKE1_L1_R2,
.client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) +
@@ -211,28 +257,70 @@ const struct s2n_kem_group s2n_x25519_kyber_512_r2 = {
.curve = &s2n_ecc_curve_x25519,
.kem = &s2n_kyber_512_r2,
};
+
+const struct s2n_kem_group s2n_x25519_bike_l1_r3 = {
+ .name = "x25519_bike-l1-r3",
+ .iana_id = TLS_PQ_KEM_GROUP_ID_X25519_BIKE_L1_R3,
+ .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) +
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE_L1_R3_PUBLIC_KEY_BYTES),
+ .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) +
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE_L1_R3_CIPHERTEXT_BYTES),
+ .curve = &s2n_ecc_curve_x25519,
+ .kem = &s2n_bike_l1_r3,
+};
+
+const struct s2n_kem_group s2n_x25519_kyber_512_r3 = {
+ .name = "x25519_kyber-512-r3",
+ .iana_id = TLS_PQ_KEM_GROUP_ID_X25519_KYBER_512_R3,
+ .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) +
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + S2N_KYBER_512_R3_PUBLIC_KEY_BYTES),
+ .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) +
+ (S2N_SIZE_OF_KEY_SHARE_SIZE + S2N_KYBER_512_R3_CIPHERTEXT_BYTES),
+ .curve = &s2n_ecc_curve_x25519,
+ .kem = &s2n_kyber_512_r3,
+};
+
+
#else
-const struct s2n_kem_group s2n_x25519_sike_p434_r2 = { 0 };
const struct s2n_kem_group s2n_x25519_bike1_l1_r2 = { 0 };
const struct s2n_kem_group s2n_x25519_kyber_512_r2 = { 0 };
+const struct s2n_kem_group s2n_x25519_sike_p434_r3 = { 0 };
+const struct s2n_kem_group s2n_x25519_bike_l1_r3 = { 0 };
+const struct s2n_kem_group s2n_x25519_kyber_512_r3 = { 0 };
#endif
+const struct s2n_kem_group* ALL_SUPPORTED_KEM_GROUPS[S2N_SUPPORTED_KEM_GROUPS_COUNT] = {
+ &s2n_secp256r1_bike_l1_r3,
+ &s2n_secp256r1_sike_p434_r3,
+ &s2n_secp256r1_kyber_512_r3,
+ &s2n_secp256r1_bike1_l1_r2,
+ &s2n_secp256r1_kyber_512_r2,
+/* x25519 based tls13_kem_groups require EVP_APIS_SUPPORTED */
+#if EVP_APIS_SUPPORTED
+ &s2n_x25519_bike_l1_r3,
+ &s2n_x25519_sike_p434_r3,
+ &s2n_x25519_kyber_512_r3,
+ &s2n_x25519_bike1_l1_r2,
+ &s2n_x25519_kyber_512_r2
+#endif
+};
+
/* Helper safety macro to call the NIST PQ KEM functions. The NIST
* functions may return any non-zero value to indicate failure. */
-#define GUARD_PQ_AS_RESULT(x) ENSURE((x) == 0, S2N_ERR_PQ_CRYPTO)
+#define GUARD_PQ_AS_RESULT(x) RESULT_ENSURE((x) == 0, S2N_ERR_PQ_CRYPTO)
S2N_RESULT s2n_kem_generate_keypair(struct s2n_kem_params *kem_params)
{
- ENSURE_REF(kem_params);
- ENSURE_REF(kem_params->kem);
+ RESULT_ENSURE_REF(kem_params);
+ RESULT_ENSURE_REF(kem_params->kem);
const struct s2n_kem *kem = kem_params->kem;
- ENSURE_REF(kem->generate_keypair);
+ RESULT_ENSURE_REF(kem->generate_keypair);
- ENSURE_REF(kem_params->public_key.data);
- ENSURE(kem_params->public_key.size == kem->public_key_length, S2N_ERR_SAFETY);
+ RESULT_ENSURE_REF(kem_params->public_key.data);
+ RESULT_ENSURE(kem_params->public_key.size == kem->public_key_length, S2N_ERR_SAFETY);
/* Need to save the private key for decapsulation */
- GUARD_AS_RESULT(s2n_alloc(&kem_params->private_key, kem->private_key_length));
+ RESULT_GUARD_POSIX(s2n_realloc(&kem_params->private_key, kem->private_key_length));
GUARD_PQ_AS_RESULT(kem->generate_keypair(kem_params->public_key.data, kem_params->private_key.data));
return S2N_RESULT_OK;
@@ -240,20 +328,20 @@ S2N_RESULT s2n_kem_generate_keypair(struct s2n_kem_params *kem_params)
S2N_RESULT s2n_kem_encapsulate(struct s2n_kem_params *kem_params, struct s2n_blob *ciphertext)
{
- ENSURE_REF(kem_params);
- ENSURE_REF(kem_params->kem);
+ RESULT_ENSURE_REF(kem_params);
+ RESULT_ENSURE_REF(kem_params->kem);
const struct s2n_kem *kem = kem_params->kem;
- ENSURE_REF(kem->encapsulate);
+ RESULT_ENSURE_REF(kem->encapsulate);
- ENSURE(kem_params->public_key.size == kem->public_key_length, S2N_ERR_SAFETY);
- ENSURE_REF(kem_params->public_key.data);
+ RESULT_ENSURE(kem_params->public_key.size == kem->public_key_length, S2N_ERR_SAFETY);
+ RESULT_ENSURE_REF(kem_params->public_key.data);
- ENSURE_REF(ciphertext);
- ENSURE_REF(ciphertext->data);
- ENSURE(ciphertext->size == kem->ciphertext_length, S2N_ERR_SAFETY);
+ RESULT_ENSURE_REF(ciphertext);
+ RESULT_ENSURE_REF(ciphertext->data);
+ RESULT_ENSURE(ciphertext->size == kem->ciphertext_length, S2N_ERR_SAFETY);
/* Need to save the shared secret for key derivation */
- GUARD_AS_RESULT(s2n_alloc(&(kem_params->shared_secret), kem->shared_secret_key_length));
+ RESULT_GUARD_POSIX(s2n_alloc(&(kem_params->shared_secret), kem->shared_secret_key_length));
GUARD_PQ_AS_RESULT(kem->encapsulate(ciphertext->data, kem_params->shared_secret.data, kem_params->public_key.data));
return S2N_RESULT_OK;
@@ -261,20 +349,20 @@ S2N_RESULT s2n_kem_encapsulate(struct s2n_kem_params *kem_params, struct s2n_blo
S2N_RESULT s2n_kem_decapsulate(struct s2n_kem_params *kem_params, const struct s2n_blob *ciphertext)
{
- ENSURE_REF(kem_params);
- ENSURE_REF(kem_params->kem);
+ RESULT_ENSURE_REF(kem_params);
+ RESULT_ENSURE_REF(kem_params->kem);
const struct s2n_kem *kem = kem_params->kem;
- ENSURE_REF(kem->decapsulate);
+ RESULT_ENSURE_REF(kem->decapsulate);
- ENSURE(kem_params->private_key.size == kem->private_key_length, S2N_ERR_SAFETY);
- ENSURE_REF(kem_params->private_key.data);
+ RESULT_ENSURE(kem_params->private_key.size == kem->private_key_length, S2N_ERR_SAFETY);
+ RESULT_ENSURE_REF(kem_params->private_key.data);
- ENSURE_REF(ciphertext);
- ENSURE_REF(ciphertext->data);
- ENSURE(ciphertext->size == kem->ciphertext_length, S2N_ERR_SAFETY);
+ RESULT_ENSURE_REF(ciphertext);
+ RESULT_ENSURE_REF(ciphertext->data);
+ RESULT_ENSURE(ciphertext->size == kem->ciphertext_length, S2N_ERR_SAFETY);
/* Need to save the shared secret for key derivation */
- GUARD_AS_RESULT(s2n_alloc(&(kem_params->shared_secret), kem->shared_secret_key_length));
+ RESULT_GUARD_POSIX(s2n_alloc(&(kem_params->shared_secret), kem->shared_secret_key_length));
GUARD_PQ_AS_RESULT(kem->decapsulate(kem_params->shared_secret.data, ciphertext->data, kem_params->private_key.data));
return S2N_RESULT_OK;
@@ -283,7 +371,7 @@ S2N_RESULT s2n_kem_decapsulate(struct s2n_kem_params *kem_params, const struct s
static int s2n_kem_check_kem_compatibility(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN], const struct s2n_kem *candidate_kem,
uint8_t *kem_is_compatible) {
const struct s2n_iana_to_kem *compatible_kems = NULL;
- GUARD(s2n_cipher_suite_to_kem(iana_value, &compatible_kems));
+ POSIX_GUARD(s2n_cipher_suite_to_kem(iana_value, &compatible_kems));
for (uint8_t i = 0; i < compatible_kems->kem_count; i++) {
if (candidate_kem->kem_extension_id == compatible_kems->kems[i]->kem_extension_id) {
@@ -299,8 +387,8 @@ static int s2n_kem_check_kem_compatibility(const uint8_t iana_value[S2N_TLS_CIPH
int s2n_choose_kem_with_peer_pref_list(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN], struct s2n_blob *client_kem_ids,
const struct s2n_kem *server_kem_pref_list[], const uint8_t num_server_supported_kems, const struct s2n_kem **chosen_kem) {
struct s2n_stuffer client_kem_ids_stuffer = {0};
- GUARD(s2n_stuffer_init(&client_kem_ids_stuffer, client_kem_ids));
- GUARD(s2n_stuffer_write(&client_kem_ids_stuffer, client_kem_ids));
+ POSIX_GUARD(s2n_stuffer_init(&client_kem_ids_stuffer, client_kem_ids));
+ POSIX_GUARD(s2n_stuffer_write(&client_kem_ids_stuffer, client_kem_ids));
/* Each KEM ID is 2 bytes */
uint8_t num_client_candidate_kems = client_kem_ids->size / 2;
@@ -309,7 +397,7 @@ int s2n_choose_kem_with_peer_pref_list(const uint8_t iana_value[S2N_TLS_CIPHER_S
const struct s2n_kem *candidate_server_kem = (server_kem_pref_list[i]);
uint8_t server_kem_is_compatible = 0;
- GUARD(s2n_kem_check_kem_compatibility(iana_value, candidate_server_kem, &server_kem_is_compatible));
+ POSIX_GUARD(s2n_kem_check_kem_compatibility(iana_value, candidate_server_kem, &server_kem_is_compatible));
if (!server_kem_is_compatible) {
continue;
@@ -317,25 +405,25 @@ int s2n_choose_kem_with_peer_pref_list(const uint8_t iana_value[S2N_TLS_CIPHER_S
for (uint8_t j = 0; j < num_client_candidate_kems; j++) {
kem_extension_size candidate_client_kem_id;
- GUARD(s2n_stuffer_read_uint16(&client_kem_ids_stuffer, &candidate_client_kem_id));
+ POSIX_GUARD(s2n_stuffer_read_uint16(&client_kem_ids_stuffer, &candidate_client_kem_id));
if (candidate_server_kem->kem_extension_id == candidate_client_kem_id) {
*chosen_kem = candidate_server_kem;
return S2N_SUCCESS;
}
}
- GUARD(s2n_stuffer_reread(&client_kem_ids_stuffer));
+ POSIX_GUARD(s2n_stuffer_reread(&client_kem_ids_stuffer));
}
/* Client and server did not propose any mutually supported KEMs compatible with the ciphersuite */
- S2N_ERROR(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
+ POSIX_BAIL(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
}
int s2n_choose_kem_without_peer_pref_list(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN], const struct s2n_kem *server_kem_pref_list[],
const uint8_t num_server_supported_kems, const struct s2n_kem **chosen_kem) {
for (uint8_t i = 0; i < num_server_supported_kems; i++) {
uint8_t kem_is_compatible = 0;
- GUARD(s2n_kem_check_kem_compatibility(iana_value, server_kem_pref_list[i], &kem_is_compatible));
+ POSIX_GUARD(s2n_kem_check_kem_compatibility(iana_value, server_kem_pref_list[i], &kem_is_compatible));
if (kem_is_compatible) {
*chosen_kem = server_kem_pref_list[i];
return S2N_SUCCESS;
@@ -343,23 +431,23 @@ int s2n_choose_kem_without_peer_pref_list(const uint8_t iana_value[S2N_TLS_CIPHE
}
/* The server preference list did not contain any KEM extensions compatible with the ciphersuite */
- S2N_ERROR(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
+ POSIX_BAIL(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
}
int s2n_kem_free(struct s2n_kem_params *kem_params)
{
if (kem_params != NULL) {
- GUARD(s2n_blob_zeroize_free(&kem_params->private_key));
- GUARD(s2n_blob_zeroize_free(&kem_params->public_key));
- GUARD(s2n_blob_zeroize_free(&kem_params->shared_secret));
+ POSIX_GUARD(s2n_blob_zeroize_free(&kem_params->private_key));
+ POSIX_GUARD(s2n_blob_zeroize_free(&kem_params->public_key));
+ POSIX_GUARD(s2n_blob_zeroize_free(&kem_params->shared_secret));
}
return S2N_SUCCESS;
}
int s2n_kem_group_free(struct s2n_kem_group_params *kem_group_params) {
if (kem_group_params != NULL) {
- GUARD(s2n_kem_free(&kem_group_params->kem_params));
- GUARD(s2n_ecc_evp_params_free(&kem_group_params->ecc_params));
+ POSIX_GUARD(s2n_kem_free(&kem_group_params->kem_params));
+ POSIX_GUARD(s2n_ecc_evp_params_free(&kem_group_params->ecc_params));
}
return S2N_SUCCESS;
}
@@ -372,7 +460,7 @@ int s2n_cipher_suite_to_kem(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN],
return S2N_SUCCESS;
}
}
- S2N_ERROR(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
+ POSIX_BAIL(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
}
int s2n_get_kem_from_extension_id(kem_extension_size kem_id, const struct s2n_kem **kem) {
@@ -388,26 +476,26 @@ int s2n_get_kem_from_extension_id(kem_extension_size kem_id, const struct s2n_ke
}
}
- S2N_ERROR(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
+ POSIX_BAIL(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
}
int s2n_kem_send_public_key(struct s2n_stuffer *out, struct s2n_kem_params *kem_params) {
- notnull_check(out);
- notnull_check(kem_params);
- notnull_check(kem_params->kem);
+ POSIX_ENSURE_REF(out);
+ POSIX_ENSURE_REF(kem_params);
+ POSIX_ENSURE_REF(kem_params->kem);
const struct s2n_kem *kem = kem_params->kem;
- GUARD(s2n_stuffer_write_uint16(out, kem->public_key_length));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, kem->public_key_length));
/* We don't need to store the public key after sending it.
* We write it directly to *out. */
kem_params->public_key.data = s2n_stuffer_raw_write(out, kem->public_key_length);
- notnull_check(kem_params->public_key.data);
+ POSIX_ENSURE_REF(kem_params->public_key.data);
kem_params->public_key.size = kem->public_key_length;
/* Saves the private key in kem_params */
- GUARD_AS_POSIX(s2n_kem_generate_keypair(kem_params));
+ POSIX_GUARD_RESULT(s2n_kem_generate_keypair(kem_params));
/* After using s2n_stuffer_raw_write() above to write the public
* key to the stuffer, we want to ensure that kem_params->public_key.data
@@ -420,61 +508,61 @@ int s2n_kem_send_public_key(struct s2n_stuffer *out, struct s2n_kem_params *kem_
}
int s2n_kem_recv_public_key(struct s2n_stuffer *in, struct s2n_kem_params *kem_params) {
- notnull_check(in);
- notnull_check(kem_params);
- notnull_check(kem_params->kem);
+ POSIX_ENSURE_REF(in);
+ POSIX_ENSURE_REF(kem_params);
+ POSIX_ENSURE_REF(kem_params->kem);
const struct s2n_kem *kem = kem_params->kem;
kem_public_key_size public_key_length;
- GUARD(s2n_stuffer_read_uint16(in, &public_key_length));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &public_key_length));
S2N_ERROR_IF(public_key_length != kem->public_key_length, S2N_ERR_BAD_MESSAGE);
/* Alloc memory for the public key; the peer receiving it will need it
* later during the handshake to encapsulate the shared secret. */
- GUARD(s2n_alloc(&(kem_params->public_key), public_key_length));
- GUARD(s2n_stuffer_read_bytes(in, kem_params->public_key.data, public_key_length));
+ POSIX_GUARD(s2n_alloc(&(kem_params->public_key), public_key_length));
+ POSIX_GUARD(s2n_stuffer_read_bytes(in, kem_params->public_key.data, public_key_length));
return S2N_SUCCESS;
}
int s2n_kem_send_ciphertext(struct s2n_stuffer *out, struct s2n_kem_params *kem_params) {
- notnull_check(out);
- notnull_check(kem_params);
- notnull_check(kem_params->kem);
- notnull_check(kem_params->public_key.data);
+ POSIX_ENSURE_REF(out);
+ POSIX_ENSURE_REF(kem_params);
+ POSIX_ENSURE_REF(kem_params->kem);
+ POSIX_ENSURE_REF(kem_params->public_key.data);
const struct s2n_kem *kem = kem_params->kem;
- GUARD(s2n_stuffer_write_uint16(out, kem->ciphertext_length));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, kem->ciphertext_length));
/* Ciphertext will get written to *out */
struct s2n_blob ciphertext = {.data = s2n_stuffer_raw_write(out, kem->ciphertext_length), .size = kem->ciphertext_length};
- notnull_check(ciphertext.data);
+ POSIX_ENSURE_REF(ciphertext.data);
/* Saves the shared secret in kem_params */
- GUARD_AS_POSIX(s2n_kem_encapsulate(kem_params, &ciphertext));
+ POSIX_GUARD_RESULT(s2n_kem_encapsulate(kem_params, &ciphertext));
return S2N_SUCCESS;
}
int s2n_kem_recv_ciphertext(struct s2n_stuffer *in, struct s2n_kem_params *kem_params) {
- notnull_check(in);
- notnull_check(kem_params);
- notnull_check(kem_params->kem);
- notnull_check(kem_params->private_key.data);
+ POSIX_ENSURE_REF(in);
+ POSIX_ENSURE_REF(kem_params);
+ POSIX_ENSURE_REF(kem_params->kem);
+ POSIX_ENSURE_REF(kem_params->private_key.data);
const struct s2n_kem *kem = kem_params->kem;
kem_ciphertext_key_size ciphertext_length;
- GUARD(s2n_stuffer_read_uint16(in, &ciphertext_length));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &ciphertext_length));
S2N_ERROR_IF(ciphertext_length != kem->ciphertext_length, S2N_ERR_BAD_MESSAGE);
const struct s2n_blob ciphertext = {.data = s2n_stuffer_raw_read(in, ciphertext_length), .size = ciphertext_length};
- notnull_check(ciphertext.data);
+ POSIX_ENSURE_REF(ciphertext.data);
/* Saves the shared secret in kem_params */
- GUARD_AS_POSIX(s2n_kem_decapsulate(kem_params, &ciphertext));
+ POSIX_GUARD_RESULT(s2n_kem_decapsulate(kem_params, &ciphertext));
return S2N_SUCCESS;
}
@@ -483,27 +571,35 @@ int s2n_kem_recv_ciphertext(struct s2n_stuffer *in, struct s2n_kem_params *kem_p
/* 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); }
-int SIKE_P503_r1_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-int SIKE_P503_r1_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-/* sikep434r2 */
-int SIKE_P434_r2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-int SIKE_P434_r2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-int SIKE_P434_r2_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
+int SIKE_P503_r1_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int SIKE_P503_r1_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int SIKE_P503_r1_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
/* bike1l1r1 */
-int BIKE1_L1_R1_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-int BIKE1_L1_R1_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-int BIKE1_L1_R1_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
+int BIKE1_L1_R1_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int BIKE1_L1_R1_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int BIKE1_L1_R1_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
/* bike1l1r2*/
-int BIKE1_L1_R2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-int BIKE1_L1_R2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-int BIKE1_L1_R2_crypto_kem_dec(OUT unsigned char * ss, IN const unsigned char *ct, IN const unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
+int BIKE1_L1_R2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int BIKE1_L1_R2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int BIKE1_L1_R2_crypto_kem_dec(OUT unsigned char * ss, IN const unsigned char *ct, IN const unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+/* bike1l1r3*/
+int BIKE_L1_R3_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int BIKE_L1_R3_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int BIKE_L1_R3_crypto_kem_dec(OUT unsigned char * ss, IN const unsigned char *ct, IN const unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
/* kyber512r2 */
-int kyber_512_r2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-int kyber_512_r2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-int kyber_512_r2_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
+int kyber_512_r2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int kyber_512_r2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int kyber_512_r2_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
/* kyber512r2 90's version*/
-int kyber_512_90s_r2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-int kyber_512_90s_r2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
-int kyber_512_90s_r2_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk) { BAIL_POSIX(S2N_ERR_UNIMPLEMENTED); }
+int kyber_512_90s_r2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int kyber_512_90s_r2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int kyber_512_90s_r2_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+/* kyber512r3 */
+int s2n_kyber_512_r3_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int s2n_kyber_512_r3_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int s2n_kyber_512_r3_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+/* sikep434r3 */
+int s2n_sike_p434_r3_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int s2n_sike_p434_r3_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
+int s2n_sike_p434_r3_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk) { POSIX_BAIL(S2N_ERR_UNIMPLEMENTED); }
#endif
diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem.h b/contrib/restricted/aws/s2n/tls/s2n_kem.h
index ddea9d09ca..ca6ab90cf3 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kem.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_kem.h
@@ -73,25 +73,37 @@ struct s2n_kem_group_params {
extern const struct s2n_kem s2n_bike1_l1_r1;
extern const struct s2n_kem s2n_bike1_l1_r2;
+extern const struct s2n_kem s2n_bike_l1_r3;
extern const struct s2n_kem s2n_sike_p503_r1;
-extern const struct s2n_kem s2n_sike_p434_r2;
extern const struct s2n_kem s2n_kyber_512_r2;
extern const struct s2n_kem s2n_kyber_512_90s_r2;
+extern const struct s2n_kem s2n_kyber_512_r3;
+extern const struct s2n_kem s2n_sike_p434_r3;
/* x25519 based tls13_kem_groups require EVP_APIS_SUPPORTED */
#if EVP_APIS_SUPPORTED
-#define S2N_SUPPORTED_KEM_GROUPS_COUNT 6
+#define S2N_SUPPORTED_KEM_GROUPS_COUNT 10
#else
-#define S2N_SUPPORTED_KEM_GROUPS_COUNT 3
+#define S2N_SUPPORTED_KEM_GROUPS_COUNT 5
#endif
-extern const struct s2n_kem_group s2n_secp256r1_sike_p434_r2;
+extern const struct s2n_kem_group* ALL_SUPPORTED_KEM_GROUPS[S2N_SUPPORTED_KEM_GROUPS_COUNT];
+
+/* secp256r1 KEM Groups */
+extern const struct s2n_kem_group s2n_secp256r1_bike_l1_r3;
+extern const struct s2n_kem_group s2n_secp256r1_sike_p434_r3;
+extern const struct s2n_kem_group s2n_secp256r1_kyber_512_r3;
extern const struct s2n_kem_group s2n_secp256r1_bike1_l1_r2;
extern const struct s2n_kem_group s2n_secp256r1_kyber_512_r2;
-extern const struct s2n_kem_group s2n_x25519_sike_p434_r2;
+
+/* x25519 KEM Groups */
+extern const struct s2n_kem_group s2n_x25519_bike_l1_r3;
+extern const struct s2n_kem_group s2n_x25519_sike_p434_r3;
+extern const struct s2n_kem_group s2n_x25519_kyber_512_r3;
extern const struct s2n_kem_group s2n_x25519_bike1_l1_r2;
extern const struct s2n_kem_group s2n_x25519_kyber_512_r2;
+
extern S2N_RESULT s2n_kem_generate_keypair(struct s2n_kem_params *kem_params);
extern S2N_RESULT s2n_kem_encapsulate(struct s2n_kem_params *kem_params, struct s2n_blob *ciphertext);
extern S2N_RESULT s2n_kem_decapsulate(struct s2n_kem_params *kem_params, const struct s2n_blob *ciphertext);
@@ -141,16 +153,7 @@ int SIKE_P503_r1_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk
int SIKE_P503_r1_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk);
int SIKE_P503_r1_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk);
-/* sikep434r2 */
-#define SIKE_P434_R2_PUBLIC_KEY_BYTES 330
-#define SIKE_P434_R2_SECRET_KEY_BYTES 374
-#define SIKE_P434_R2_CIPHERTEXT_BYTES 346
-#define SIKE_P434_R2_SHARED_SECRET_BYTES 16
-int SIKE_P434_r2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk);
-int SIKE_P434_r2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk);
-int SIKE_P434_r2_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk);
-
-/* bike1l1r1 */
+/* bike1_l1_r1 */
#define BIKE1_L1_R1_SECRET_KEY_BYTES 3110
#define BIKE1_L1_R1_PUBLIC_KEY_BYTES 2542
#define BIKE1_L1_R1_CIPHERTEXT_BYTES 2542
@@ -159,7 +162,7 @@ int BIKE1_L1_R1_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk)
int BIKE1_L1_R1_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk);
int BIKE1_L1_R1_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk);
-/* bike1l1r2 */
+/* bike1_l1_r2 */
#define BIKE1_L1_R2_SECRET_KEY_BYTES 6460
#define BIKE1_L1_R2_PUBLIC_KEY_BYTES 2946
#define BIKE1_L1_R2_CIPHERTEXT_BYTES 2946
@@ -168,6 +171,15 @@ int BIKE1_L1_R2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk)
int BIKE1_L1_R2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk);
int BIKE1_L1_R2_crypto_kem_dec(OUT unsigned char * ss, IN const unsigned char *ct, IN const unsigned char *sk);
+/* bike_l1_r3 */
+#define BIKE_L1_R3_SECRET_KEY_BYTES 5223
+#define BIKE_L1_R3_PUBLIC_KEY_BYTES 1541
+#define BIKE_L1_R3_CIPHERTEXT_BYTES 1573
+#define BIKE_L1_R3_SHARED_SECRET_BYTES 32
+int BIKE_L1_R3_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk);
+int BIKE_L1_R3_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk);
+int BIKE_L1_R3_crypto_kem_dec(OUT unsigned char * ss, IN const unsigned char *ct, IN const unsigned char *sk);
+
/* kyber512r2 (the defined constants are identical for both regular and 90's version) */
#define KYBER_512_R2_PUBLIC_KEY_BYTES 800
#define KYBER_512_R2_SECRET_KEY_BYTES 1632
@@ -179,3 +191,21 @@ int kyber_512_r2_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *c
int kyber_512_90s_r2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk);
int kyber_512_90s_r2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk);
int kyber_512_90s_r2_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk);
+
+/* kyber512r3 */
+#define S2N_KYBER_512_R3_PUBLIC_KEY_BYTES 800
+#define S2N_KYBER_512_R3_SECRET_KEY_BYTES 1632
+#define S2N_KYBER_512_R3_CIPHERTEXT_BYTES 768
+#define S2N_KYBER_512_R3_SHARED_SECRET_BYTES 32
+int s2n_kyber_512_r3_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk);
+int s2n_kyber_512_r3_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk);
+int s2n_kyber_512_r3_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk);
+
+/* sikep434r3 */
+#define S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES 330
+#define S2N_SIKE_P434_R3_SECRET_KEY_BYTES 374
+#define S2N_SIKE_P434_R3_CIPHERTEXT_BYTES 346
+#define S2N_SIKE_P434_R3_SHARED_SECRET_BYTES 16
+int s2n_sike_p434_r3_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk);
+int s2n_sike_p434_r3_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk);
+int s2n_sike_p434_r3_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c
index 3e3fa71323..24ce8cb49e 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c
@@ -21,18 +21,35 @@ const struct s2n_kem *pq_kems_r1[2] = {
&s2n_sike_p503_r1,
};
-/* Extension list for round 2 and round 1 PQ KEMs, in order of preference */
+/* Extension list for round 2 and round 1 PQ KEMs, in order of preference.
+ * s2n_sike_p434_r3 is compatible with, and has replaced, s2n_sike_p434_r2. */
const struct s2n_kem *pq_kems_r2r1[4] = {
&s2n_bike1_l1_r2,
- &s2n_sike_p434_r2,
+ &s2n_sike_p434_r3,
&s2n_bike1_l1_r1,
&s2n_sike_p503_r1,
};
+/* s2n_sike_p434_r3 is compatible with, and has replaced, s2n_sike_p434_r2. */
const struct s2n_kem *pq_kems_r2r1_2020_07[5] = {
&s2n_kyber_512_r2,
&s2n_bike1_l1_r2,
- &s2n_sike_p434_r2,
+ &s2n_sike_p434_r3,
+ &s2n_bike1_l1_r1,
+ &s2n_sike_p503_r1,
+};
+
+const struct s2n_kem *pq_kems_r3r2r1_2021_05[7] = {
+ /* Round 3 Algorithms */
+ &s2n_kyber_512_r3,
+ &s2n_bike_l1_r3,
+
+ /* Round 2 Algorithms */
+ &s2n_kyber_512_r2,
+ &s2n_bike1_l1_r2,
+ &s2n_sike_p434_r3,
+
+ /* Round 1 Algorithms */
&s2n_bike1_l1_r1,
&s2n_sike_p503_r1,
};
@@ -43,24 +60,48 @@ const struct s2n_kem *pq_kems_sike_r1[1] = {
};
/* Extension list for SIKE P434 Round 2 and SIKE P503 Round 1 only (for testing),
- * in order of preference */
+ * in order of preference. s2n_sike_p434_r3 is compatible with, and has replaced,
+ * s2n_sike_p434_r2. */
const struct s2n_kem *pq_kems_sike_r2r1[2] = {
- &s2n_sike_p434_r2,
+ &s2n_sike_p434_r3,
&s2n_sike_p503_r1,
};
+/* sike_p434_r3 has replaced sike_p434_r2 in all KEM groups */
const struct s2n_kem_group *pq_kem_groups_r2[] = {
#if EVP_APIS_SUPPORTED
&s2n_x25519_kyber_512_r2,
&s2n_secp256r1_kyber_512_r2,
&s2n_x25519_bike1_l1_r2,
&s2n_secp256r1_bike1_l1_r2,
- &s2n_x25519_sike_p434_r2,
- &s2n_secp256r1_sike_p434_r2,
+ &s2n_x25519_sike_p434_r3,
+ &s2n_secp256r1_sike_p434_r3,
+#else
+ &s2n_secp256r1_kyber_512_r2,
+ &s2n_secp256r1_bike1_l1_r2,
+ &s2n_secp256r1_sike_p434_r3,
+#endif
+};
+
+
+const struct s2n_kem_group *pq_kem_groups_r3r2[] = {
+#if EVP_APIS_SUPPORTED
+ &s2n_x25519_kyber_512_r3,
+ &s2n_secp256r1_kyber_512_r3,
+ &s2n_x25519_bike_l1_r3,
+ &s2n_secp256r1_bike_l1_r3,
+ &s2n_x25519_kyber_512_r2,
+ &s2n_secp256r1_kyber_512_r2,
+ &s2n_x25519_bike1_l1_r2,
+ &s2n_secp256r1_bike1_l1_r2,
+ &s2n_x25519_sike_p434_r3,
+ &s2n_secp256r1_sike_p434_r3,
#else
+ &s2n_secp256r1_kyber_512_r3,
+ &s2n_secp256r1_bike_l1_r3,
&s2n_secp256r1_kyber_512_r2,
&s2n_secp256r1_bike1_l1_r2,
- &s2n_secp256r1_sike_p434_r2,
+ &s2n_secp256r1_sike_p434_r3,
#endif
};
@@ -110,6 +151,13 @@ const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2020_12 = {
.tls13_kem_groups = pq_kem_groups_r2,
};
+const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2021_05 = {
+ .kem_count = s2n_array_len(pq_kems_r3r2r1_2021_05),
+ .kems = pq_kems_r3r2r1_2021_05,
+ .tls13_kem_group_count = s2n_array_len(pq_kem_groups_r3r2),
+ .tls13_kem_groups = pq_kem_groups_r3r2,
+};
+
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 cad4f39c8e..73f86a10a1 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h
@@ -34,8 +34,10 @@ extern const struct s2n_kem *pq_kems_r2r1[4];
extern const struct s2n_kem *pq_kems_r2r1_2020_07[5];
extern const struct s2n_kem *pq_kems_sike_r1[1];
extern const struct s2n_kem *pq_kems_sike_r2r1[2];
+extern const struct s2n_kem *pq_kems_r3r2r1_2021_05[7];
extern const struct s2n_kem_group *pq_kem_groups_r2[];
+extern const struct s2n_kem_group *pq_kem_groups_r3r2[];
extern const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2019_06;
extern const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2020_02;
@@ -43,6 +45,7 @@ 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;
+extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2021_05;
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 b9fb9800ad..d4429ad2f8 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_kex.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_kex.c
@@ -26,9 +26,9 @@
static S2N_RESULT s2n_check_rsa_key(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- ENSURE_REF(cipher_suite);
- ENSURE_REF(conn);
- ENSURE_REF(is_supported);
+ RESULT_ENSURE_REF(cipher_suite);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(is_supported);
*is_supported = s2n_get_compatible_cert_chain_and_key(conn, S2N_PKEY_TYPE_RSA) != NULL;
@@ -37,10 +37,10 @@ static S2N_RESULT s2n_check_rsa_key(const struct s2n_cipher_suite *cipher_suite,
static S2N_RESULT s2n_check_dhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- ENSURE_REF(cipher_suite);
- ENSURE_REF(conn);
- ENSURE_REF(conn->config);
- ENSURE_REF(is_supported);
+ RESULT_ENSURE_REF(cipher_suite);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->config);
+ RESULT_ENSURE_REF(is_supported);
*is_supported = conn->config->dhparams != NULL;
@@ -49,27 +49,27 @@ static S2N_RESULT s2n_check_dhe(const struct s2n_cipher_suite *cipher_suite, str
static S2N_RESULT s2n_check_ecdhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- ENSURE_REF(cipher_suite);
- ENSURE_REF(conn);
- ENSURE_REF(is_supported);
+ RESULT_ENSURE_REF(cipher_suite);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(is_supported);
- *is_supported = conn->secure.server_ecc_evp_params.negotiated_curve != NULL;
+ *is_supported = conn->kex_params.server_ecc_evp_params.negotiated_curve != NULL;
return S2N_RESULT_OK;
}
static S2N_RESULT s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- ENSURE_REF(cipher_suite);
- ENSURE_REF(conn);
- ENSURE_REF(is_supported);
+ RESULT_ENSURE_REF(cipher_suite);
+ RESULT_ENSURE_REF(conn);
+ RESULT_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_AS_RESULT(s2n_connection_get_kem_preferences(conn, &kem_preferences));
- ENSURE_REF(kem_preferences);
+ RESULT_GUARD_POSIX(s2n_connection_get_kem_preferences(conn, &kem_preferences));
+ RESULT_ENSURE_REF(kem_preferences);
if (!s2n_pq_is_enabled() || kem_preferences->kem_count == 0) {
return S2N_RESULT_OK;
@@ -80,12 +80,12 @@ static S2N_RESULT s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, str
return S2N_RESULT_OK;
}
- ENSURE_REF(supported_params);
+ RESULT_ENSURE_REF(supported_params);
if (supported_params->kem_count == 0) {
return S2N_RESULT_OK;
}
- struct s2n_blob *client_kem_pref_list = &(conn->secure.client_pq_kem_extension);
+ struct s2n_blob *client_kem_pref_list = &(conn->kex_params.client_pq_kem_extension);
const struct s2n_kem *chosen_kem = NULL;
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 */
@@ -107,28 +107,28 @@ static S2N_RESULT s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, str
static S2N_RESULT s2n_configure_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
{
- ENSURE_REF(cipher_suite);
- ENSURE_REF(conn);
+ RESULT_ENSURE_REF(cipher_suite);
+ RESULT_ENSURE_REF(conn);
- ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
+ RESULT_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
const struct s2n_kem_preferences *kem_preferences = NULL;
- GUARD_AS_RESULT(s2n_connection_get_kem_preferences(conn, &kem_preferences));
- ENSURE_REF(kem_preferences);
+ RESULT_GUARD_POSIX(s2n_connection_get_kem_preferences(conn, &kem_preferences));
+ RESULT_ENSURE_REF(kem_preferences);
- struct s2n_blob *proposed_kems = &(conn->secure.client_pq_kem_extension);
+ struct s2n_blob *proposed_kems = &(conn->kex_params.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_AS_RESULT(s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems,
+ RESULT_GUARD_POSIX(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_AS_RESULT(s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, proposed_kems, kem_preferences->kems,
+ RESULT_GUARD_POSIX(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;
+ conn->kex_params.kem_params.kem = chosen_kem;
return S2N_RESULT_OK;
}
@@ -139,14 +139,14 @@ static S2N_RESULT s2n_no_op_configure(const struct s2n_cipher_suite *cipher_suit
static S2N_RESULT s2n_check_hybrid_ecdhe_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- ENSURE_REF(cipher_suite);
- ENSURE_REF(conn);
- ENSURE_REF(is_supported);
+ RESULT_ENSURE_REF(cipher_suite);
+ RESULT_ENSURE_REF(conn);
+ RESULT_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));
+ RESULT_GUARD(s2n_check_ecdhe(cipher_suite, conn, &ecdhe_supported));
+ RESULT_GUARD(s2n_check_kem(cipher_suite, conn, &kem_supported));
*is_supported = ecdhe_supported && kem_supported;
@@ -173,7 +173,7 @@ const struct s2n_kex s2n_rsa = {
.server_key_send = NULL,
.client_key_recv = &s2n_rsa_client_key_recv,
.client_key_send = &s2n_rsa_client_key_send,
- .prf = &s2n_tls_prf_master_secret,
+ .prf = &s2n_prf_calculate_master_secret,
};
const struct s2n_kex s2n_dhe = {
@@ -185,7 +185,7 @@ const struct s2n_kex s2n_dhe = {
.server_key_send = &s2n_dhe_server_key_send,
.client_key_recv = &s2n_dhe_client_key_recv,
.client_key_send = &s2n_dhe_client_key_send,
- .prf = &s2n_tls_prf_master_secret,
+ .prf = &s2n_prf_calculate_master_secret,
};
const struct s2n_kex s2n_ecdhe = {
@@ -197,7 +197,7 @@ const struct s2n_kex s2n_ecdhe = {
.server_key_send = &s2n_ecdhe_server_key_send,
.client_key_recv = &s2n_ecdhe_client_key_recv,
.client_key_send = &s2n_ecdhe_client_key_send,
- .prf = &s2n_tls_prf_master_secret,
+ .prf = &s2n_prf_calculate_master_secret,
};
const struct s2n_kex s2n_hybrid_ecdhe_kem = {
@@ -215,33 +215,33 @@ const struct s2n_kex s2n_hybrid_ecdhe_kem = {
S2N_RESULT s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn, bool *is_supported)
{
- 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);
+ RESULT_ENSURE_REF(cipher_suite);
+ RESULT_ENSURE_REF(cipher_suite->key_exchange_alg);
+ RESULT_ENSURE_REF(cipher_suite->key_exchange_alg->connection_supported);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(is_supported);
- GUARD_RESULT(cipher_suite->key_exchange_alg->connection_supported(cipher_suite, conn, is_supported));
+ RESULT_GUARD(cipher_suite->key_exchange_alg->connection_supported(cipher_suite, conn, is_supported));
return S2N_RESULT_OK;
}
S2N_RESULT s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn)
{
- ENSURE_REF(cipher_suite);
- ENSURE_REF(cipher_suite->key_exchange_alg);
- ENSURE_REF(cipher_suite->key_exchange_alg->configure_connection);
- ENSURE_REF(conn);
+ RESULT_ENSURE_REF(cipher_suite);
+ RESULT_ENSURE_REF(cipher_suite->key_exchange_alg);
+ RESULT_ENSURE_REF(cipher_suite->key_exchange_alg->configure_connection);
+ RESULT_ENSURE_REF(conn);
- GUARD_RESULT(cipher_suite->key_exchange_alg->configure_connection(cipher_suite, conn));
+ RESULT_GUARD(cipher_suite->key_exchange_alg->configure_connection(cipher_suite, conn));
return S2N_RESULT_OK;
}
S2N_RESULT s2n_kex_is_ephemeral(const struct s2n_kex *kex, bool *is_ephemeral)
{
- ENSURE_REF(kex);
- ENSURE_REF(is_ephemeral);
+ RESULT_ENSURE_REF(kex);
+ RESULT_ENSURE_REF(is_ephemeral);
*is_ephemeral = kex->is_ephemeral;
@@ -250,12 +250,12 @@ S2N_RESULT s2n_kex_is_ephemeral(const struct s2n_kex *kex, bool *is_ephemeral)
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)
{
- ENSURE_REF(kex);
- ENSURE_REF(kex->server_key_recv_parse_data);
- ENSURE_REF(conn);
- ENSURE_REF(raw_server_data);
+ RESULT_ENSURE_REF(kex);
+ RESULT_ENSURE_REF(kex->server_key_recv_parse_data);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(raw_server_data);
- GUARD_AS_RESULT(kex->server_key_recv_parse_data(conn, raw_server_data));
+ RESULT_GUARD_POSIX(kex->server_key_recv_parse_data(conn, raw_server_data));
return S2N_RESULT_OK;
}
@@ -263,60 +263,60 @@ S2N_RESULT s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct
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)
{
- ENSURE_REF(kex);
- ENSURE_REF(kex->server_key_recv_read_data);
- ENSURE_REF(conn);
- ENSURE_REF(data_to_verify);
+ RESULT_ENSURE_REF(kex);
+ RESULT_ENSURE_REF(kex->server_key_recv_read_data);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(data_to_verify);
- GUARD_AS_RESULT(kex->server_key_recv_read_data(conn, data_to_verify, raw_server_data));
+ RESULT_GUARD_POSIX(kex->server_key_recv_read_data(conn, data_to_verify, raw_server_data));
return S2N_RESULT_OK;
}
S2N_RESULT s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign)
{
- ENSURE_REF(kex);
- ENSURE_REF(kex->server_key_send);
- ENSURE_REF(conn);
- ENSURE_REF(data_to_sign);
+ RESULT_ENSURE_REF(kex);
+ RESULT_ENSURE_REF(kex->server_key_send);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(data_to_sign);
- GUARD_AS_RESULT(kex->server_key_send(conn, data_to_sign));
+ RESULT_GUARD_POSIX(kex->server_key_send(conn, data_to_sign));
return S2N_RESULT_OK;
}
S2N_RESULT s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key)
{
- ENSURE_REF(kex);
- ENSURE_REF(kex->client_key_recv);
- ENSURE_REF(conn);
- ENSURE_REF(shared_key);
+ RESULT_ENSURE_REF(kex);
+ RESULT_ENSURE_REF(kex->client_key_recv);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(shared_key);
- GUARD_AS_RESULT(kex->client_key_recv(conn, shared_key));
+ RESULT_GUARD_POSIX(kex->client_key_recv(conn, shared_key));
return S2N_RESULT_OK;
}
S2N_RESULT s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key)
{
- ENSURE_REF(kex);
- ENSURE_REF(kex->client_key_send);
- ENSURE_REF(conn);
- ENSURE_REF(shared_key);
+ RESULT_ENSURE_REF(kex);
+ RESULT_ENSURE_REF(kex->client_key_send);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(shared_key);
- GUARD_AS_RESULT(kex->client_key_send(conn, shared_key));
+ RESULT_GUARD_POSIX(kex->client_key_send(conn, shared_key));
return S2N_RESULT_OK;
}
S2N_RESULT s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret)
{
- ENSURE_REF(kex);
- ENSURE_REF(kex->prf);
- ENSURE_REF(conn);
- ENSURE_REF(premaster_secret);
+ RESULT_ENSURE_REF(kex);
+ RESULT_ENSURE_REF(kex->prf);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(premaster_secret);
- GUARD_AS_RESULT(kex->prf(conn, premaster_secret));
+ RESULT_GUARD_POSIX(kex->prf(conn, premaster_secret));
return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_key_log.c b/contrib/restricted/aws/s2n/tls/s2n_key_log.c
new file mode 100644
index 0000000000..d8eb3dd465
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_key_log.c
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+/**
+ * This module implements key logging as defined by the NSS Key Log Format
+ *
+ * See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
+ *
+ * This key log file is a series of lines. Comment lines begin with a sharp
+ * character ('#') and are ignored. Secrets follow the format
+ * <Label> <space> <ClientRandom> <space> <Secret> where:
+ *
+ * <Label> describes the following secret.
+ * <ClientRandom> is 32 bytes Random value from the Client Hello message, encoded as 64 hexadecimal characters.
+ * <Secret> depends on the Label (see below).
+ *
+ * The following labels are defined, followed by a description of the secret:
+ *
+ * RSA: 48 bytes for the premaster secret, encoded as 96 hexadecimal characters (removed in NSS 3.34)
+ * CLIENT_RANDOM: 48 bytes for the master secret, encoded as 96 hexadecimal characters (for SSL 3.0, TLS 1.0, 1.1 and 1.2)
+ * CLIENT_EARLY_TRAFFIC_SECRET: the hex-encoded early traffic secret for the client side (for TLS 1.3)
+ * CLIENT_HANDSHAKE_TRAFFIC_SECRET: the hex-encoded handshake traffic secret for the client side (for TLS 1.3)
+ * SERVER_HANDSHAKE_TRAFFIC_SECRET: the hex-encoded handshake traffic secret for the server side (for TLS 1.3)
+ * CLIENT_TRAFFIC_SECRET_0: the first hex-encoded application traffic secret for the client side (for TLS 1.3)
+ * SERVER_TRAFFIC_SECRET_0: the first hex-encoded application traffic secret for the server side (for TLS 1.3)
+ * EARLY_EXPORTER_SECRET: the hex-encoded early exporter secret (for TLS 1.3).
+ * EXPORTER_SECRET: the hex-encoded exporter secret (for TLS 1.3)
+ */
+
+#include "api/s2n.h"
+#include "tls/s2n_config.h"
+#include "tls/s2n_connection.h"
+#include "tls/s2n_crypto_constants.h"
+#include "tls/s2n_quic_support.h" /* this currently holds the s2n_secret_type_t enum */
+#include "utils/s2n_blob.h"
+#include "utils/s2n_safety.h"
+
+/* hex requires 2 chars per byte */
+#define HEX_ENCODING_SIZE 2
+
+S2N_RESULT s2n_key_log_hex_encode(struct s2n_stuffer *output, uint8_t *bytes, size_t len)
+{
+ RESULT_ENSURE_MUT(output);
+ RESULT_ENSURE_REF(bytes);
+
+ const uint8_t chars[] = "0123456789abcdef";
+
+ for (size_t i = 0; i < len; i++) {
+ uint8_t upper = bytes[i] >> 4;
+ uint8_t lower = bytes[i] & 0x0f;
+
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(output, chars[upper]));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(output, chars[lower]));
+ }
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_key_log_tls13_secret(struct s2n_connection *conn, const struct s2n_blob *secret, s2n_secret_type_t secret_type)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->config);
+ RESULT_ENSURE_REF(secret);
+
+ /* only emit keys if the callback has been set */
+ if (!conn->config->key_log_cb) {
+ return S2N_RESULT_OK;
+ }
+
+ const uint8_t client_early_traffic_label[] = "CLIENT_EARLY_TRAFFIC_SECRET ";
+ const uint8_t client_handshake_label[] = "CLIENT_HANDSHAKE_TRAFFIC_SECRET ";
+ const uint8_t server_handshake_label[] = "SERVER_HANDSHAKE_TRAFFIC_SECRET ";
+ const uint8_t client_traffic_label[] = "CLIENT_TRAFFIC_SECRET_0 ";
+ const uint8_t server_traffic_label[] = "SERVER_TRAFFIC_SECRET_0 ";
+
+ const uint8_t *label = NULL;
+ uint8_t label_size = 0;
+
+ switch (secret_type) {
+ case S2N_CLIENT_EARLY_TRAFFIC_SECRET:
+ label = client_early_traffic_label;
+ label_size = sizeof(client_early_traffic_label) - 1;
+ break;
+ case S2N_CLIENT_HANDSHAKE_TRAFFIC_SECRET:
+ label = client_handshake_label;
+ label_size = sizeof(client_handshake_label) - 1;
+ break;
+ case S2N_SERVER_HANDSHAKE_TRAFFIC_SECRET:
+ label = server_handshake_label;
+ label_size = sizeof(server_handshake_label) - 1;
+ break;
+ case S2N_CLIENT_APPLICATION_TRAFFIC_SECRET:
+ label = client_traffic_label;
+ label_size = sizeof(client_traffic_label) - 1;
+ break;
+ case S2N_SERVER_APPLICATION_TRAFFIC_SECRET:
+ label = server_traffic_label;
+ label_size = sizeof(server_traffic_label) - 1;
+ break;
+ default:
+ /* Ignore the secret types we don't understand */
+ return S2N_RESULT_OK;
+ }
+
+ const uint8_t len
+ = label_size
+ + S2N_TLS_RANDOM_DATA_LEN * HEX_ENCODING_SIZE
+ + 1 /* SPACE */
+ + secret->size * HEX_ENCODING_SIZE;
+
+ DEFER_CLEANUP(struct s2n_stuffer output, s2n_stuffer_free);
+ RESULT_GUARD_POSIX(s2n_stuffer_alloc(&output, len));
+
+ RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&output, label, label_size));
+ RESULT_GUARD(s2n_key_log_hex_encode(&output, conn->handshake_params.client_random, S2N_TLS_RANDOM_DATA_LEN));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(&output, ' '));
+ RESULT_GUARD(s2n_key_log_hex_encode(&output, secret->data, secret->size));
+
+ uint8_t *data = s2n_stuffer_raw_read(&output, len);
+ RESULT_ENSURE_REF(data);
+
+ conn->config->key_log_cb(conn->config->key_log_ctx, conn, data, len);
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_key_log_tls12_secret(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->config);
+
+ /* only emit keys if the callback has been set */
+ if (!conn->config->key_log_cb) {
+ return S2N_RESULT_OK;
+ }
+
+ /* CLIENT_RANDOM: 48 bytes for the master secret, encoded as 96 hexadecimal characters (for SSL 3.0, TLS 1.0, 1.1 and 1.2) */
+ const uint8_t label[] = "CLIENT_RANDOM ";
+ const uint8_t label_size = sizeof(label) - 1;
+
+ const uint8_t len
+ = label_size
+ + S2N_TLS_RANDOM_DATA_LEN * HEX_ENCODING_SIZE
+ + 1 /* SPACE */
+ + S2N_TLS_SECRET_LEN * HEX_ENCODING_SIZE;
+
+ DEFER_CLEANUP(struct s2n_stuffer output, s2n_stuffer_free);
+ RESULT_GUARD_POSIX(s2n_stuffer_alloc(&output, len));
+
+ RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&output, label, label_size));
+ RESULT_GUARD(s2n_key_log_hex_encode(&output, conn->handshake_params.client_random, S2N_TLS_RANDOM_DATA_LEN));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(&output, ' '));
+ RESULT_GUARD(s2n_key_log_hex_encode(&output, conn->secrets.tls12.master_secret, S2N_TLS_SECRET_LEN));
+
+ uint8_t *data = s2n_stuffer_raw_read(&output, len);
+ RESULT_ENSURE_REF(data);
+
+ conn->config->key_log_cb(conn->config->key_log_ctx, conn, data, len);
+
+ return S2N_RESULT_OK;
+}
+
diff --git a/contrib/restricted/aws/s2n/tls/s2n_key_log.h b/contrib/restricted/aws/s2n/tls/s2n_key_log.h
new file mode 100644
index 0000000000..d804d21c4c
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_key_log.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#pragma once
+
+#include "api/s2n.h"
+#include "stuffer/s2n_stuffer.h"
+#include "tls/s2n_quic_support.h"
+#include "utils/s2n_blob.h"
+#include "utils/s2n_safety.h"
+
+S2N_RESULT s2n_key_log_hex_encode(struct s2n_stuffer *output, uint8_t *bytes, size_t len);
+S2N_RESULT s2n_key_log_tls12_secret(struct s2n_connection *conn);
+S2N_RESULT s2n_key_log_tls13_secret(struct s2n_connection *conn, const struct s2n_blob *secret, s2n_secret_type_t secret_type);
+
diff --git a/contrib/restricted/aws/s2n/tls/s2n_key_update.c b/contrib/restricted/aws/s2n/tls/s2n_key_update.c
index 6f63e02b38..86e933a1ac 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_key_update.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_key_update.c
@@ -19,6 +19,7 @@
#include "tls/s2n_key_update.h"
#include "tls/s2n_tls13_handshake.h"
#include "tls/s2n_record.h"
+#include "tls/s2n_tls.h"
#include "crypto/s2n_sequence.h"
@@ -30,52 +31,55 @@ int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequenc
int s2n_key_update_recv(struct s2n_connection *conn, struct s2n_stuffer *request)
{
- notnull_check(conn);
- ENSURE_POSIX(!conn->config->quic_enabled, S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_BAD_MESSAGE);
uint8_t key_update_request;
- GUARD(s2n_stuffer_read_uint8(request, &key_update_request));
+ POSIX_GUARD(s2n_stuffer_read_uint8(request, &key_update_request));
S2N_ERROR_IF(key_update_request != S2N_KEY_UPDATE_NOT_REQUESTED && key_update_request != S2N_KEY_UPDATE_REQUESTED,
S2N_ERR_BAD_MESSAGE);
conn->key_update_pending = key_update_request;
/* Update peer's key since a key_update was received */
if (conn->mode == S2N_CLIENT){
- GUARD(s2n_update_application_traffic_keys(conn, S2N_SERVER, RECEIVING));
+ POSIX_GUARD(s2n_update_application_traffic_keys(conn, S2N_SERVER, RECEIVING));
} else {
- GUARD(s2n_update_application_traffic_keys(conn, S2N_CLIENT, RECEIVING));
+ POSIX_GUARD(s2n_update_application_traffic_keys(conn, S2N_CLIENT, RECEIVING));
}
return S2N_SUCCESS;
}
-int s2n_key_update_send(struct s2n_connection *conn)
+int s2n_key_update_send(struct s2n_connection *conn, s2n_blocked_status *blocked)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
struct s2n_blob sequence_number = {0};
if (conn->mode == S2N_CLIENT) {
- GUARD(s2n_blob_init(&sequence_number, conn->secure.client_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
+ POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure.client_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
} else {
- GUARD(s2n_blob_init(&sequence_number, conn->secure.server_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
+ POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure.server_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
}
- GUARD(s2n_check_record_limit(conn, &sequence_number));
+ POSIX_GUARD(s2n_check_record_limit(conn, &sequence_number));
if (conn->key_update_pending) {
uint8_t key_update_data[S2N_KEY_UPDATE_MESSAGE_SIZE];
struct s2n_blob key_update_blob = {0};
- GUARD(s2n_blob_init(&key_update_blob, key_update_data, sizeof(key_update_data)));
+ POSIX_GUARD(s2n_blob_init(&key_update_blob, key_update_data, sizeof(key_update_data)));
/* Write key update message */
- GUARD(s2n_key_update_write(&key_update_blob));
+ POSIX_GUARD(s2n_key_update_write(&key_update_blob));
/* Encrypt the message */
- GUARD(s2n_record_write(conn, TLS_HANDSHAKE, &key_update_blob));
+ POSIX_GUARD(s2n_record_write(conn, TLS_HANDSHAKE, &key_update_blob));
/* Update encryption key */
- GUARD(s2n_update_application_traffic_keys(conn, conn->mode, SENDING));
+ POSIX_GUARD(s2n_update_application_traffic_keys(conn, conn->mode, SENDING));
conn->key_update_pending = false;
+
+ POSIX_GUARD(s2n_flush(conn, blocked));
}
return S2N_SUCCESS;
@@ -83,28 +87,28 @@ int s2n_key_update_send(struct s2n_connection *conn)
int s2n_key_update_write(struct s2n_blob *out)
{
- notnull_check(out);
+ POSIX_ENSURE_REF(out);
struct s2n_stuffer key_update_stuffer = {0};
- GUARD(s2n_stuffer_init(&key_update_stuffer, out));
- GUARD(s2n_stuffer_write_uint8(&key_update_stuffer, TLS_KEY_UPDATE));
- GUARD(s2n_stuffer_write_uint24(&key_update_stuffer, S2N_KEY_UPDATE_LENGTH));
+ POSIX_GUARD(s2n_stuffer_init(&key_update_stuffer, out));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&key_update_stuffer, TLS_KEY_UPDATE));
+ POSIX_GUARD(s2n_stuffer_write_uint24(&key_update_stuffer, S2N_KEY_UPDATE_LENGTH));
/* s2n currently does not require peers to update their encryption keys. */
- GUARD(s2n_stuffer_write_uint8(&key_update_stuffer, S2N_KEY_UPDATE_NOT_REQUESTED));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&key_update_stuffer, S2N_KEY_UPDATE_NOT_REQUESTED));
return S2N_SUCCESS;
}
int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequence_number)
{
- notnull_check(conn);
- notnull_check(sequence_number);
- notnull_check(conn->secure.cipher_suite);
- notnull_check(conn->secure.cipher_suite->record_alg);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(sequence_number);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite->record_alg);
uint64_t output = 0;
- GUARD(s2n_sequence_number_to_uint64(sequence_number, &output));
+ POSIX_GUARD(s2n_sequence_number_to_uint64(sequence_number, &output));
if (output + 1 > conn->secure.cipher_suite->record_alg->encryption_limit) {
conn->key_update_pending = true;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_key_update.h b/contrib/restricted/aws/s2n/tls/s2n_key_update.h
index 20ac48411c..859cd11506 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_key_update.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_key_update.h
@@ -31,4 +31,4 @@ typedef enum {
} keyupdate_request;
int s2n_key_update_recv(struct s2n_connection *conn, struct s2n_stuffer *request);
-int s2n_key_update_send(struct s2n_connection *conn);
+int s2n_key_update_send(struct s2n_connection *conn, s2n_blocked_status *blocked);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c b/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c
index 7ad96a4d31..441fdff27e 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c
@@ -28,7 +28,7 @@
int s2n_server_status_send(struct s2n_connection *conn)
{
if (s2n_server_can_send_ocsp(conn)) {
- GUARD(s2n_server_certificate_status_send(conn, &conn->handshake.io));
+ POSIX_GUARD(s2n_server_certificate_status_send(conn, &conn->handshake.io));
}
return 0;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
index 34594576db..7801920563 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c
@@ -20,38 +20,56 @@
#include "tls/s2n_tls.h"
#include "utils/s2n_safety.h"
-/* TLS 1.3 introducted several post handshake messages. This function currently only
- * supports parsing for the KeyUpdate message. Once the other post-handshake messages
- * have been implemented, this function can be altered to include the other messages.
- */
int s2n_post_handshake_recv(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
uint8_t post_handshake_id;
uint32_t message_length;
- S2N_ERROR_IF(conn->actual_protocol_version != S2N_TLS13, S2N_ERR_BAD_MESSAGE);
- GUARD(s2n_stuffer_read_uint8(&conn->in, &post_handshake_id));
- GUARD(s2n_stuffer_read_uint24(&conn->in, &message_length));
+ while(s2n_stuffer_data_available(&conn->in)) {
+ POSIX_GUARD(s2n_stuffer_read_uint8(&conn->in, &post_handshake_id));
+ POSIX_GUARD(s2n_stuffer_read_uint24(&conn->in, &message_length));
- struct s2n_blob post_handshake_blob = {0};
- uint8_t *message_data = s2n_stuffer_raw_read(&conn->in, message_length);
- notnull_check(message_data);
- GUARD(s2n_blob_init(&post_handshake_blob, message_data, message_length));
+ struct s2n_blob post_handshake_blob = { 0 };
+ uint8_t *message_data = s2n_stuffer_raw_read(&conn->in, message_length);
+ POSIX_ENSURE_REF(message_data);
+ POSIX_GUARD(s2n_blob_init(&post_handshake_blob, message_data, message_length));
- struct s2n_stuffer post_handshake_stuffer = {0};
- GUARD(s2n_stuffer_init(&post_handshake_stuffer, &post_handshake_blob));
- GUARD(s2n_stuffer_skip_write(&post_handshake_stuffer, message_length));
+ struct s2n_stuffer post_handshake_stuffer = { 0 };
+ POSIX_GUARD(s2n_stuffer_init(&post_handshake_stuffer, &post_handshake_blob));
+ POSIX_GUARD(s2n_stuffer_skip_write(&post_handshake_stuffer, message_length));
- switch (post_handshake_id)
- {
- case TLS_KEY_UPDATE:
- GUARD(s2n_key_update_recv(conn, &post_handshake_stuffer));
- break;
- default:
- /* Ignore all other messages */
- break;
+ switch (post_handshake_id)
+ {
+ case TLS_KEY_UPDATE:
+ POSIX_GUARD(s2n_key_update_recv(conn, &post_handshake_stuffer));
+ break;
+ case TLS_SERVER_NEW_SESSION_TICKET:
+ POSIX_GUARD_RESULT(s2n_tls13_server_nst_recv(conn, &post_handshake_stuffer));
+ break;
+ case TLS_HELLO_REQUEST:
+ POSIX_GUARD(s2n_client_hello_request_recv(conn));
+ break;
+ case TLS_CLIENT_HELLO:
+ case TLS_SERVER_HELLO:
+ case TLS_END_OF_EARLY_DATA:
+ case TLS_ENCRYPTED_EXTENSIONS:
+ case TLS_CERTIFICATE:
+ case TLS_SERVER_KEY:
+ case TLS_CERT_REQ:
+ case TLS_SERVER_HELLO_DONE:
+ case TLS_CERT_VERIFY:
+ case TLS_CLIENT_KEY:
+ case TLS_FINISHED:
+ case TLS_SERVER_CERT_STATUS:
+ /* All other known handshake messages should be rejected */
+ POSIX_BAIL(S2N_ERR_BAD_MESSAGE);
+ break;
+ default:
+ /* Ignore all other messages */
+ break;
+ }
}
return S2N_SUCCESS;
@@ -59,11 +77,10 @@ int s2n_post_handshake_recv(struct s2n_connection *conn)
int s2n_post_handshake_send(struct s2n_connection *conn, s2n_blocked_status *blocked)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
- GUARD(s2n_key_update_send(conn));
- GUARD(s2n_flush(conn, blocked));
- GUARD(s2n_stuffer_rewrite(&conn->out));
+ POSIX_GUARD(s2n_key_update_send(conn, blocked));
+ POSIX_GUARD_RESULT(s2n_tls13_server_nst_send(conn, blocked));
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_prf.c b/contrib/restricted/aws/s2n/tls/s2n_prf.c
index fbfffb5fad..1096eb6c82 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_prf.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_prf.c
@@ -14,6 +14,7 @@
*/
#include <sys/param.h>
+#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <string.h>
@@ -23,6 +24,7 @@
#include "tls/s2n_cipher_suites.h"
#include "tls/s2n_connection.h"
#include "tls/s2n_prf.h"
+#include "tls/s2n_tls.h"
#include "stuffer/s2n_stuffer.h"
@@ -35,44 +37,51 @@
#include "utils/s2n_blob.h"
#include "utils/s2n_mem.h"
-static int s2n_sslv3_prf(struct s2n_prf_working_space *ws, struct s2n_blob *secret, struct s2n_blob *seed_a,
+static int s2n_sslv3_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct s2n_blob *seed_a,
struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out)
{
- struct s2n_hash_state *md5 = &ws->ssl3.md5;
- struct s2n_hash_state *sha1 = &ws->ssl3.sha1;
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+ struct s2n_hash_state *workspace = &conn->handshake.hashes->hash_workspace;
uint32_t outputlen = out->size;
uint8_t *output = out->data;
uint8_t iteration = 1;
+ uint8_t md5_digest[MD5_DIGEST_LENGTH] = { 0 }, sha_digest[SHA_DIGEST_LENGTH] = { 0 };
+
uint8_t A = 'A';
while (outputlen) {
- GUARD(s2n_hash_reset(sha1));
+ struct s2n_hash_state *sha1 = workspace;
+ POSIX_GUARD(s2n_hash_reset(sha1));
+ POSIX_GUARD(s2n_hash_init(sha1, S2N_HASH_SHA1));
for (int i = 0; i < iteration; i++) {
- GUARD(s2n_hash_update(sha1, &A, 1));
+ POSIX_GUARD(s2n_hash_update(sha1, &A, 1));
}
- GUARD(s2n_hash_update(sha1, secret->data, secret->size));
- GUARD(s2n_hash_update(sha1, seed_a->data, seed_a->size));
+ POSIX_GUARD(s2n_hash_update(sha1, secret->data, secret->size));
+ POSIX_GUARD(s2n_hash_update(sha1, seed_a->data, seed_a->size));
if (seed_b) {
- GUARD(s2n_hash_update(sha1, seed_b->data, seed_b->size));
+ POSIX_GUARD(s2n_hash_update(sha1, seed_b->data, seed_b->size));
if (seed_c) {
- GUARD(s2n_hash_update(sha1, seed_c->data, seed_c->size));
+ POSIX_GUARD(s2n_hash_update(sha1, seed_c->data, seed_c->size));
}
}
- GUARD(s2n_hash_digest(sha1, ws->ssl3.sha1_digest, sizeof(ws->ssl3.sha1_digest)));
+ POSIX_GUARD(s2n_hash_digest(sha1, sha_digest, sizeof(sha_digest)));
- GUARD(s2n_hash_reset(md5));
- GUARD(s2n_hash_update(md5, secret->data, secret->size));
- GUARD(s2n_hash_update(md5, ws->ssl3.sha1_digest, sizeof(ws->ssl3.sha1_digest)));
- GUARD(s2n_hash_digest(md5, ws->ssl3.md5_digest, sizeof(ws->ssl3.md5_digest)));
+ struct s2n_hash_state *md5 = workspace;
+ POSIX_GUARD(s2n_hash_reset(md5));
+ POSIX_GUARD(s2n_hash_init(md5, S2N_HASH_MD5));
+ POSIX_GUARD(s2n_hash_update(md5, secret->data, secret->size));
+ POSIX_GUARD(s2n_hash_update(md5, sha_digest, sizeof(sha_digest)));
+ POSIX_GUARD(s2n_hash_digest(md5, md5_digest, sizeof(md5_digest)));
- uint32_t bytes_to_copy = MIN(outputlen, sizeof(ws->ssl3.md5_digest));
+ uint32_t bytes_to_copy = MIN(outputlen, sizeof(md5_digest));
- memcpy_check(output, ws->ssl3.md5_digest, bytes_to_copy);
+ POSIX_CHECKED_MEMCPY(output, md5_digest, bytes_to_copy);
outputlen -= bytes_to_copy;
output += bytes_to_copy;
@@ -82,129 +91,201 @@ static int s2n_sslv3_prf(struct s2n_prf_working_space *ws, struct s2n_blob *secr
iteration++;
}
- GUARD(s2n_hash_reset(md5));
- GUARD(s2n_hash_reset(sha1));
-
return 0;
}
+static int s2n_init_md_from_hmac_alg(struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg){
+ switch (alg) {
+ case S2N_HMAC_SSLv3_MD5:
+ case S2N_HMAC_MD5:
+ ws->p_hash.evp_hmac.evp_digest.md = EVP_md5();
+ break;
+ case S2N_HMAC_SSLv3_SHA1:
+ case S2N_HMAC_SHA1:
+ ws->p_hash.evp_hmac.evp_digest.md = EVP_sha1();
+ break;
+ case S2N_HMAC_SHA224:
+ ws->p_hash.evp_hmac.evp_digest.md = EVP_sha224();
+ break;
+ case S2N_HMAC_SHA256:
+ ws->p_hash.evp_hmac.evp_digest.md = EVP_sha256();
+ break;
+ case S2N_HMAC_SHA384:
+ ws->p_hash.evp_hmac.evp_digest.md = EVP_sha384();
+ break;
+ case S2N_HMAC_SHA512:
+ ws->p_hash.evp_hmac.evp_digest.md = EVP_sha512();
+ break;
+ default:
+ POSIX_BAIL(S2N_ERR_P_HASH_INVALID_ALGORITHM);
+ }
+ return S2N_SUCCESS;
+}
+
#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
-static int s2n_evp_hmac_p_hash_new(struct s2n_prf_working_space *ws)
+static int s2n_evp_pkey_p_hash_alloc(struct s2n_prf_working_space *ws)
{
- notnull_check(ws->tls.p_hash.evp_hmac.evp_digest.ctx = S2N_EVP_MD_CTX_NEW());
+ POSIX_ENSURE_REF(ws->p_hash.evp_hmac.evp_digest.ctx = S2N_EVP_MD_CTX_NEW());
return 0;
}
-static int s2n_evp_hmac_p_hash_digest_init(struct s2n_prf_working_space *ws)
+static int s2n_evp_pkey_p_hash_digest_init(struct s2n_prf_working_space *ws)
{
- notnull_check(ws->tls.p_hash.evp_hmac.evp_digest.md);
- notnull_check(ws->tls.p_hash.evp_hmac.evp_digest.ctx);
- notnull_check(ws->tls.p_hash.evp_hmac.mac_key);
+ POSIX_ENSURE_REF(ws->p_hash.evp_hmac.evp_digest.md);
+ POSIX_ENSURE_REF(ws->p_hash.evp_hmac.evp_digest.ctx);
+ POSIX_ENSURE_REF(ws->p_hash.evp_hmac.ctx.evp_pkey);
/* Ignore the MD5 check when in FIPS mode to comply with the TLS 1.0 RFC */
if (s2n_is_in_fips_mode()) {
- GUARD(s2n_digest_allow_md5_for_fips(&ws->tls.p_hash.evp_hmac.evp_digest));
+ POSIX_GUARD(s2n_digest_allow_md5_for_fips(&ws->p_hash.evp_hmac.evp_digest));
}
- GUARD_OSSL(EVP_DigestSignInit(ws->tls.p_hash.evp_hmac.evp_digest.ctx, NULL, ws->tls.p_hash.evp_hmac.evp_digest.md, NULL, ws->tls.p_hash.evp_hmac.mac_key),
+ POSIX_GUARD_OSSL(EVP_DigestSignInit(ws->p_hash.evp_hmac.evp_digest.ctx, NULL, ws->p_hash.evp_hmac.evp_digest.md, NULL, ws->p_hash.evp_hmac.ctx.evp_pkey),
S2N_ERR_P_HASH_INIT_FAILED);
return 0;
}
-static int s2n_evp_hmac_p_hash_init(struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg, struct s2n_blob *secret)
+static int s2n_evp_pkey_p_hash_init(struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg, struct s2n_blob *secret)
{
/* Initialize the message digest */
- switch (alg) {
- case S2N_HMAC_SSLv3_MD5:
- case S2N_HMAC_MD5:
- ws->tls.p_hash.evp_hmac.evp_digest.md = EVP_md5();
- break;
- case S2N_HMAC_SSLv3_SHA1:
- case S2N_HMAC_SHA1:
- ws->tls.p_hash.evp_hmac.evp_digest.md = EVP_sha1();
- break;
- case S2N_HMAC_SHA224:
- ws->tls.p_hash.evp_hmac.evp_digest.md = EVP_sha224();
- break;
- case S2N_HMAC_SHA256:
- ws->tls.p_hash.evp_hmac.evp_digest.md = EVP_sha256();
- break;
- case S2N_HMAC_SHA384:
- ws->tls.p_hash.evp_hmac.evp_digest.md = EVP_sha384();
- break;
- case S2N_HMAC_SHA512:
- ws->tls.p_hash.evp_hmac.evp_digest.md = EVP_sha512();
- break;
- default:
- S2N_ERROR(S2N_ERR_P_HASH_INVALID_ALGORITHM);
- }
+ POSIX_GUARD(s2n_init_md_from_hmac_alg(ws, alg));
/* Initialize the mac key using the provided secret */
- notnull_check(ws->tls.p_hash.evp_hmac.mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, secret->data, secret->size));
+ POSIX_ENSURE_REF(ws->p_hash.evp_hmac.ctx.evp_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, secret->data, secret->size));
/* Initialize the message digest context with the above message digest and mac key */
- return s2n_evp_hmac_p_hash_digest_init(ws);
+ return s2n_evp_pkey_p_hash_digest_init(ws);
}
-static int s2n_evp_hmac_p_hash_update(struct s2n_prf_working_space *ws, const void *data, uint32_t size)
+static int s2n_evp_pkey_p_hash_update(struct s2n_prf_working_space *ws, const void *data, uint32_t size)
{
- GUARD_OSSL(EVP_DigestSignUpdate(ws->tls.p_hash.evp_hmac.evp_digest.ctx, data, (size_t)size), S2N_ERR_P_HASH_UPDATE_FAILED);
+ POSIX_GUARD_OSSL(EVP_DigestSignUpdate(ws->p_hash.evp_hmac.evp_digest.ctx, data, (size_t)size), S2N_ERR_P_HASH_UPDATE_FAILED);
return 0;
}
-static int s2n_evp_hmac_p_hash_digest(struct s2n_prf_working_space *ws, void *digest, uint32_t size)
+static int s2n_evp_pkey_p_hash_final(struct s2n_prf_working_space *ws, void *digest, uint32_t size)
{
/* EVP_DigestSign API's require size_t data structures */
size_t digest_size = size;
- GUARD_OSSL(EVP_DigestSignFinal(ws->tls.p_hash.evp_hmac.evp_digest.ctx, (unsigned char *)digest, &digest_size), S2N_ERR_P_HASH_FINAL_FAILED);
+ POSIX_GUARD_OSSL(EVP_DigestSignFinal(ws->p_hash.evp_hmac.evp_digest.ctx, (unsigned char *)digest, &digest_size), S2N_ERR_P_HASH_FINAL_FAILED);
return 0;
}
-static int s2n_evp_hmac_p_hash_wipe(struct s2n_prf_working_space *ws)
+static int s2n_evp_pkey_p_hash_wipe(struct s2n_prf_working_space *ws)
{
- GUARD_OSSL(S2N_EVP_MD_CTX_RESET(ws->tls.p_hash.evp_hmac.evp_digest.ctx), S2N_ERR_P_HASH_WIPE_FAILED);
+ POSIX_GUARD_OSSL(S2N_EVP_MD_CTX_RESET(ws->p_hash.evp_hmac.evp_digest.ctx), S2N_ERR_P_HASH_WIPE_FAILED);
return 0;
}
-static int s2n_evp_hmac_p_hash_reset(struct s2n_prf_working_space *ws)
+static int s2n_evp_pkey_p_hash_reset(struct s2n_prf_working_space *ws)
{
- GUARD(s2n_evp_hmac_p_hash_wipe(ws));
+ POSIX_GUARD(s2n_evp_pkey_p_hash_wipe(ws));
- return s2n_evp_hmac_p_hash_digest_init(ws);
+ /*
+ * On some cleanup paths s2n_evp_pkey_p_hash_reset can be called before s2n_evp_pkey_p_hash_init so there is nothing
+ * to reset.
+ */
+ if (ws->p_hash.evp_hmac.ctx.evp_pkey == NULL) {
+ return S2N_SUCCESS;
+ }
+ return s2n_evp_pkey_p_hash_digest_init(ws);
}
-static int s2n_evp_hmac_p_hash_cleanup(struct s2n_prf_working_space *ws)
+static int s2n_evp_pkey_p_hash_cleanup(struct s2n_prf_working_space *ws)
{
/* Prepare the workspace md_ctx for the next p_hash */
- GUARD(s2n_evp_hmac_p_hash_wipe(ws));
+ POSIX_GUARD(s2n_evp_pkey_p_hash_wipe(ws));
/* Free mac key - PKEYs cannot be reused */
- notnull_check(ws->tls.p_hash.evp_hmac.mac_key);
- EVP_PKEY_free(ws->tls.p_hash.evp_hmac.mac_key);
- ws->tls.p_hash.evp_hmac.mac_key = NULL;
+ POSIX_ENSURE_REF(ws->p_hash.evp_hmac.ctx.evp_pkey);
+ EVP_PKEY_free(ws->p_hash.evp_hmac.ctx.evp_pkey);
+ ws->p_hash.evp_hmac.ctx.evp_pkey = NULL;
return 0;
}
-static int s2n_evp_hmac_p_hash_free(struct s2n_prf_working_space *ws)
+static int s2n_evp_pkey_p_hash_free(struct s2n_prf_working_space *ws)
{
- notnull_check(ws->tls.p_hash.evp_hmac.evp_digest.ctx);
- S2N_EVP_MD_CTX_FREE(ws->tls.p_hash.evp_hmac.evp_digest.ctx);
- ws->tls.p_hash.evp_hmac.evp_digest.ctx = NULL;
+ POSIX_ENSURE_REF(ws->p_hash.evp_hmac.evp_digest.ctx);
+ S2N_EVP_MD_CTX_FREE(ws->p_hash.evp_hmac.evp_digest.ctx);
+ ws->p_hash.evp_hmac.evp_digest.ctx = NULL;
return 0;
}
-static const struct s2n_p_hash_hmac s2n_evp_hmac = {
- .alloc = &s2n_evp_hmac_p_hash_new,
+static const struct s2n_p_hash_hmac s2n_evp_pkey_p_hash_hmac = {
+ .alloc = &s2n_evp_pkey_p_hash_alloc,
+ .init = &s2n_evp_pkey_p_hash_init,
+ .update = &s2n_evp_pkey_p_hash_update,
+ .final = &s2n_evp_pkey_p_hash_final,
+ .reset = &s2n_evp_pkey_p_hash_reset,
+ .cleanup = &s2n_evp_pkey_p_hash_cleanup,
+ .free = &s2n_evp_pkey_p_hash_free,
+};
+#else
+static int s2n_evp_hmac_p_hash_alloc(struct s2n_prf_working_space *ws)
+{
+ POSIX_ENSURE_REF(ws->p_hash.evp_hmac.ctx.hmac_ctx = HMAC_CTX_new());
+ return S2N_SUCCESS;
+}
+
+static int s2n_evp_hmac_p_hash_init(struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg, struct s2n_blob *secret)
+{
+ /* Figure out the correct EVP_MD from s2n_hmac_algorithm */
+ POSIX_GUARD(s2n_init_md_from_hmac_alg(ws, alg));
+
+ /* Initialize the mac and digest */
+ POSIX_GUARD_OSSL(HMAC_Init_ex(ws->p_hash.evp_hmac.ctx.hmac_ctx, secret->data, secret->size, ws->p_hash.evp_hmac.evp_digest.md, NULL), S2N_ERR_P_HASH_INIT_FAILED);
+ return S2N_SUCCESS;
+}
+
+static int s2n_evp_hmac_p_hash_update(struct s2n_prf_working_space *ws, const void *data, uint32_t size)
+{
+ POSIX_GUARD_OSSL(HMAC_Update(ws->p_hash.evp_hmac.ctx.hmac_ctx, data, (size_t)size), S2N_ERR_P_HASH_UPDATE_FAILED);
+ return S2N_SUCCESS;
+}
+
+static int s2n_evp_hmac_p_hash_final(struct s2n_prf_working_space *ws, void *digest, uint32_t size)
+{
+ /* HMAC_Final API's require size_t data structures */
+ unsigned int digest_size = size;
+ POSIX_GUARD_OSSL(HMAC_Final(ws->p_hash.evp_hmac.ctx.hmac_ctx, (unsigned char *)digest, &digest_size), S2N_ERR_P_HASH_FINAL_FAILED);
+ return S2N_SUCCESS;
+}
+
+static int s2n_evp_hmac_p_hash_reset(struct s2n_prf_working_space *ws)
+{
+ POSIX_ENSURE_REF(ws);
+ if (ws->p_hash.evp_hmac.evp_digest.md == NULL) {
+ return S2N_SUCCESS;
+ }
+ POSIX_GUARD_OSSL(HMAC_Init_ex(ws->p_hash.evp_hmac.ctx.hmac_ctx, NULL, 0, ws->p_hash.evp_hmac.evp_digest.md, NULL), S2N_ERR_P_HASH_INIT_FAILED);
+ return S2N_SUCCESS;
+}
+
+static int s2n_evp_hmac_p_hash_cleanup(struct s2n_prf_working_space *ws)
+{
+ /* Prepare the workspace md_ctx for the next p_hash */
+ HMAC_CTX_reset(ws->p_hash.evp_hmac.ctx.hmac_ctx);
+ return S2N_SUCCESS;
+}
+
+static int s2n_evp_hmac_p_hash_free(struct s2n_prf_working_space *ws)
+{
+ HMAC_CTX_free(ws->p_hash.evp_hmac.ctx.hmac_ctx);
+ return S2N_SUCCESS;
+}
+
+static const struct s2n_p_hash_hmac s2n_evp_hmac_p_hash_hmac = {
+ .alloc = &s2n_evp_hmac_p_hash_alloc,
.init = &s2n_evp_hmac_p_hash_init,
.update = &s2n_evp_hmac_p_hash_update,
- .final = &s2n_evp_hmac_p_hash_digest,
+ .final = &s2n_evp_hmac_p_hash_final,
.reset = &s2n_evp_hmac_p_hash_reset,
.cleanup = &s2n_evp_hmac_p_hash_cleanup,
.free = &s2n_evp_hmac_p_hash_free,
@@ -213,29 +294,35 @@ static const struct s2n_p_hash_hmac s2n_evp_hmac = {
static int s2n_hmac_p_hash_new(struct s2n_prf_working_space *ws)
{
- GUARD(s2n_hmac_new(&ws->tls.p_hash.s2n_hmac));
+ POSIX_GUARD(s2n_hmac_new(&ws->p_hash.s2n_hmac));
- return s2n_hmac_init(&ws->tls.p_hash.s2n_hmac, S2N_HMAC_NONE, NULL, 0);
+ return s2n_hmac_init(&ws->p_hash.s2n_hmac, S2N_HMAC_NONE, NULL, 0);
}
static int s2n_hmac_p_hash_init(struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg, struct s2n_blob *secret)
{
- return s2n_hmac_init(&ws->tls.p_hash.s2n_hmac, alg, secret->data, secret->size);
+ return s2n_hmac_init(&ws->p_hash.s2n_hmac, alg, secret->data, secret->size);
}
static int s2n_hmac_p_hash_update(struct s2n_prf_working_space *ws, const void *data, uint32_t size)
{
- return s2n_hmac_update(&ws->tls.p_hash.s2n_hmac, data, size);
+ return s2n_hmac_update(&ws->p_hash.s2n_hmac, data, size);
}
static int s2n_hmac_p_hash_digest(struct s2n_prf_working_space *ws, void *digest, uint32_t size)
{
- return s2n_hmac_digest(&ws->tls.p_hash.s2n_hmac, digest, size);
+ return s2n_hmac_digest(&ws->p_hash.s2n_hmac, digest, size);
}
static int s2n_hmac_p_hash_reset(struct s2n_prf_working_space *ws)
{
- return s2n_hmac_reset(&ws->tls.p_hash.s2n_hmac);
+ /* If we actually initialized s2n_hmac, wipe it.
+ * A valid, initialized s2n_hmac_state will have a valid block size.
+ */
+ if (ws->p_hash.s2n_hmac.hash_block_size != 0) {
+ return s2n_hmac_reset(&ws->p_hash.s2n_hmac);
+ }
+ return S2N_SUCCESS;
}
static int s2n_hmac_p_hash_cleanup(struct s2n_prf_working_space *ws)
@@ -245,10 +332,10 @@ static int s2n_hmac_p_hash_cleanup(struct s2n_prf_working_space *ws)
static int s2n_hmac_p_hash_free(struct s2n_prf_working_space *ws)
{
- return s2n_hmac_free(&ws->tls.p_hash.s2n_hmac);
+ return s2n_hmac_free(&ws->p_hash.s2n_hmac);
}
-static const struct s2n_p_hash_hmac s2n_hmac = {
+static const struct s2n_p_hash_hmac s2n_internal_p_hash_hmac = {
.alloc = &s2n_hmac_p_hash_new,
.init = &s2n_hmac_p_hash_init,
.update = &s2n_hmac_p_hash_update,
@@ -258,103 +345,129 @@ static const struct s2n_p_hash_hmac s2n_hmac = {
.free = &s2n_hmac_p_hash_free,
};
+const struct s2n_p_hash_hmac *s2n_get_hmac_implementation() {
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+ return s2n_is_in_fips_mode() ? &s2n_evp_hmac_p_hash_hmac : &s2n_internal_p_hash_hmac;
+#else
+ return s2n_is_in_fips_mode() ? &s2n_evp_pkey_p_hash_hmac : &s2n_internal_p_hash_hmac;
+#endif
+}
+
static int s2n_p_hash(struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg, struct s2n_blob *secret, struct s2n_blob *label,
struct s2n_blob *seed_a, struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out)
{
uint8_t digest_size;
- GUARD(s2n_hmac_digest_size(alg, &digest_size));
+ POSIX_GUARD(s2n_hmac_digest_size(alg, &digest_size));
- const struct s2n_p_hash_hmac *hmac = ws->tls.p_hash_hmac_impl;
+ const struct s2n_p_hash_hmac *hmac = s2n_get_hmac_implementation();
/* First compute hmac(secret + A(0)) */
- GUARD(hmac->init(ws, alg, secret));
- GUARD(hmac->update(ws, label->data, label->size));
- GUARD(hmac->update(ws, seed_a->data, seed_a->size));
+ POSIX_GUARD(hmac->init(ws, alg, secret));
+ POSIX_GUARD(hmac->update(ws, label->data, label->size));
+ POSIX_GUARD(hmac->update(ws, seed_a->data, seed_a->size));
if (seed_b) {
- GUARD(hmac->update(ws, seed_b->data, seed_b->size));
+ POSIX_GUARD(hmac->update(ws, seed_b->data, seed_b->size));
if (seed_c) {
- GUARD(hmac->update(ws, seed_c->data, seed_c->size));
+ POSIX_GUARD(hmac->update(ws, seed_c->data, seed_c->size));
}
}
- GUARD(hmac->final(ws, ws->tls.digest0, digest_size));
+ POSIX_GUARD(hmac->final(ws, ws->digest0, digest_size));
uint32_t outputlen = out->size;
uint8_t *output = out->data;
while (outputlen) {
/* Now compute hmac(secret + A(N - 1) + seed) */
- GUARD(hmac->reset(ws));
- GUARD(hmac->update(ws, ws->tls.digest0, digest_size));
+ POSIX_GUARD(hmac->reset(ws));
+ POSIX_GUARD(hmac->update(ws, ws->digest0, digest_size));
/* Add the label + seed and compute this round's A */
- GUARD(hmac->update(ws, label->data, label->size));
- GUARD(hmac->update(ws, seed_a->data, seed_a->size));
+ POSIX_GUARD(hmac->update(ws, label->data, label->size));
+ POSIX_GUARD(hmac->update(ws, seed_a->data, seed_a->size));
if (seed_b) {
- GUARD(hmac->update(ws, seed_b->data, seed_b->size));
+ POSIX_GUARD(hmac->update(ws, seed_b->data, seed_b->size));
if (seed_c) {
- GUARD(hmac->update(ws, seed_c->data, seed_c->size));
+ POSIX_GUARD(hmac->update(ws, seed_c->data, seed_c->size));
}
}
- GUARD(hmac->final(ws, ws->tls.digest1, digest_size));
+ POSIX_GUARD(hmac->final(ws, ws->digest1, digest_size));
uint32_t bytes_to_xor = MIN(outputlen, digest_size);
- for (int i = 0; i < bytes_to_xor; i++) {
- *output ^= ws->tls.digest1[i];
+ for (uint32_t i = 0; i < bytes_to_xor; i++) {
+ *output ^= ws->digest1[i];
output++;
outputlen--;
}
/* Stash a digest of A(N), in A(N), for the next round */
- GUARD(hmac->reset(ws));
- GUARD(hmac->update(ws, ws->tls.digest0, digest_size));
- GUARD(hmac->final(ws, ws->tls.digest0, digest_size));
+ POSIX_GUARD(hmac->reset(ws));
+ POSIX_GUARD(hmac->update(ws, ws->digest0, digest_size));
+ POSIX_GUARD(hmac->final(ws, ws->digest0, digest_size));
}
- GUARD(hmac->cleanup(ws));
+ POSIX_GUARD(hmac->cleanup(ws));
return 0;
}
-const struct s2n_p_hash_hmac *s2n_get_hmac_implementation() {
-#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
- return &s2n_hmac;
-#else
- return s2n_is_in_fips_mode() ? &s2n_evp_hmac : &s2n_hmac;
-#endif
+S2N_RESULT s2n_prf_new(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_EQ(conn->prf_space, NULL);
+
+ DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
+ RESULT_GUARD_POSIX(s2n_realloc(&mem, sizeof(struct s2n_prf_working_space)));
+ RESULT_GUARD_POSIX(s2n_blob_zero(&mem));
+ conn->prf_space = (struct s2n_prf_working_space*)(void*) mem.data;
+ ZERO_TO_DISABLE_DEFER_CLEANUP(mem);
+
+ /* Allocate the hmac state */
+ const struct s2n_p_hash_hmac *hmac_impl = s2n_get_hmac_implementation();
+ RESULT_GUARD_POSIX(hmac_impl->alloc(conn->prf_space));
+ return S2N_RESULT_OK;
}
-int s2n_prf_new(struct s2n_connection *conn)
+S2N_RESULT s2n_prf_wipe(struct s2n_connection *conn)
{
- /* Set p_hash_hmac_impl on initial prf creation.
- * When in FIPS mode, the EVP API's must be used for the p_hash HMAC.
- */
- conn->prf_space.tls.p_hash_hmac_impl = s2n_get_hmac_implementation();
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->prf_space);
+
+ const struct s2n_p_hash_hmac *hmac_impl = s2n_get_hmac_implementation();
+ RESULT_GUARD_POSIX(hmac_impl->reset(conn->prf_space));
- return conn->prf_space.tls.p_hash_hmac_impl->alloc(&conn->prf_space);
+ return S2N_RESULT_OK;
}
-int s2n_prf_free(struct s2n_connection *conn)
+S2N_RESULT s2n_prf_free(struct s2n_connection *conn)
{
- /* Ensure that p_hash_hmac_impl is set, as it may have been reset for prf_space on s2n_connection_wipe.
- * When in FIPS mode, the EVP API's must be used for the p_hash HMAC.
- */
- conn->prf_space.tls.p_hash_hmac_impl = s2n_get_hmac_implementation();
+ RESULT_ENSURE_REF(conn);
+ if (conn->prf_space == NULL) {
+ return S2N_RESULT_OK;
+ }
- return conn->prf_space.tls.p_hash_hmac_impl->free(&conn->prf_space);
+ const struct s2n_p_hash_hmac *hmac_impl = s2n_get_hmac_implementation();
+ RESULT_GUARD_POSIX(hmac_impl->free(conn->prf_space));
+
+ RESULT_GUARD_POSIX(s2n_free_object((uint8_t **) &conn->prf_space, sizeof(struct s2n_prf_working_space)));
+ return S2N_RESULT_OK;
}
static int s2n_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct s2n_blob *label, struct s2n_blob *seed_a,
struct s2n_blob *seed_b, struct s2n_blob *seed_c, struct s2n_blob *out)
{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(secret);
+ POSIX_ENSURE_REF(conn->prf_space);
+
/* seed_a is always required, seed_b is optional, if seed_c is provided seed_b must also be provided */
S2N_ERROR_IF(seed_a == NULL, S2N_ERR_PRF_INVALID_SEED);
S2N_ERROR_IF(seed_b == NULL && seed_c != NULL, S2N_ERR_PRF_INVALID_SEED);
if (conn->actual_protocol_version == S2N_SSLv3) {
- return s2n_sslv3_prf(&conn->prf_space, secret, seed_a, seed_b, seed_c, out);
+ return s2n_sslv3_prf(conn, secret, seed_a, seed_b, seed_c, out);
}
/* We zero the out blob because p_hash works by XOR'ing with the existing
@@ -363,32 +476,27 @@ static int s2n_prf(struct s2n_connection *conn, struct s2n_blob *secret, struct
* the right values. When we call it twice in the regular case, the two
* outputs will be XORd just ass the TLS 1.0 and 1.1 RFCs require.
*/
- GUARD(s2n_blob_zero(out));
-
- /* Ensure that p_hash_hmac_impl is set, as it may have been reset for prf_space on s2n_connection_wipe.
- * When in FIPS mode, the EVP API's must be used for the p_hash HMAC.
- */
- conn->prf_space.tls.p_hash_hmac_impl = s2n_get_hmac_implementation();
-
+ POSIX_GUARD(s2n_blob_zero(out));
+
if (conn->actual_protocol_version == S2N_TLS12) {
- return s2n_p_hash(&conn->prf_space, conn->secure.cipher_suite->prf_alg, secret, label, seed_a, seed_b,
+ return s2n_p_hash(conn->prf_space, conn->secure.cipher_suite->prf_alg, secret, label, seed_a, seed_b,
seed_c, out);
}
struct s2n_blob half_secret = {.data = secret->data,.size = (secret->size + 1) / 2 };
- GUARD(s2n_p_hash(&conn->prf_space, S2N_HMAC_MD5, &half_secret, label, seed_a, seed_b, seed_c, out));
+ POSIX_GUARD(s2n_p_hash(conn->prf_space, S2N_HMAC_MD5, &half_secret, label, seed_a, seed_b, seed_c, out));
half_secret.data += secret->size - half_secret.size;
- GUARD(s2n_p_hash(&conn->prf_space, S2N_HMAC_SHA1, &half_secret, label, seed_a, seed_b, seed_c, out));
+ POSIX_GUARD(s2n_p_hash(conn->prf_space, S2N_HMAC_SHA1, &half_secret, label, seed_a, seed_b, seed_c, out));
return 0;
}
int s2n_tls_prf_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret)
{
- struct s2n_blob client_random = {.size = sizeof(conn->secure.client_random), .data = conn->secure.client_random};
- struct s2n_blob server_random = {.size = sizeof(conn->secure.server_random), .data = conn->secure.server_random};
- struct s2n_blob master_secret = {.size = sizeof(conn->secure.master_secret), .data = conn->secure.master_secret};
+ struct s2n_blob client_random = {.size = sizeof(conn->handshake_params.client_random), .data = conn->handshake_params.client_random};
+ struct s2n_blob server_random = {.size = sizeof(conn->handshake_params.server_random), .data = conn->handshake_params.server_random};
+ struct s2n_blob master_secret = {.size = sizeof(conn->secrets.tls12.master_secret), .data = conn->secrets.tls12.master_secret};
uint8_t master_secret_label[] = "master secret";
struct s2n_blob label = {.size = sizeof(master_secret_label) - 1, .data = master_secret_label};
@@ -398,18 +506,103 @@ int s2n_tls_prf_master_secret(struct s2n_connection *conn, struct s2n_blob *prem
int s2n_hybrid_prf_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret)
{
- struct s2n_blob client_random = {.size = sizeof(conn->secure.client_random), .data = conn->secure.client_random};
- struct s2n_blob server_random = {.size = sizeof(conn->secure.server_random), .data = conn->secure.server_random};
- struct s2n_blob master_secret = {.size = sizeof(conn->secure.master_secret), .data = conn->secure.master_secret};
+ struct s2n_blob client_random = {.size = sizeof(conn->handshake_params.client_random), .data = conn->handshake_params.client_random};
+ struct s2n_blob server_random = {.size = sizeof(conn->handshake_params.server_random), .data = conn->handshake_params.server_random};
+ struct s2n_blob master_secret = {.size = sizeof(conn->secrets.tls12.master_secret), .data = conn->secrets.tls12.master_secret};
uint8_t master_secret_label[] = "hybrid master secret";
struct s2n_blob label = {.size = sizeof(master_secret_label) - 1, .data = master_secret_label};
- return s2n_prf(conn, premaster_secret, &label, &client_random, &server_random, &conn->secure.client_key_exchange_message, &master_secret);
+ return s2n_prf(conn, premaster_secret, &label, &client_random, &server_random, &conn->kex_params.client_key_exchange_message, &master_secret);
}
-static int s2n_sslv3_finished(struct s2n_connection *conn, uint8_t prefix[4], struct s2n_hash_state *md5, struct s2n_hash_state *sha1, uint8_t * out)
+int s2n_prf_calculate_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret)
{
+ POSIX_ENSURE_REF(conn);
+
+ POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(conn), CLIENT_KEY);
+
+ if(!conn->ems_negotiated) {
+ POSIX_GUARD(s2n_tls_prf_master_secret(conn, premaster_secret));
+ return S2N_SUCCESS;
+ }
+
+ /* Only the client writes the Client Key Exchange message */
+ if (conn->mode == S2N_CLIENT) {
+ POSIX_GUARD(s2n_handshake_finish_header(&conn->handshake.io));
+ }
+ struct s2n_stuffer client_key_message = conn->handshake.io;
+ POSIX_GUARD(s2n_stuffer_reread(&client_key_message));
+ uint32_t client_key_message_size = s2n_stuffer_data_available(&client_key_message);
+ struct s2n_blob client_key_blob = { 0 };
+ POSIX_GUARD(s2n_blob_init(&client_key_blob, client_key_message.blob.data, client_key_message_size));
+
+ uint8_t data[S2N_MAX_DIGEST_LEN] = { 0 };
+ struct s2n_blob digest = { 0 };
+ POSIX_GUARD(s2n_blob_init(&digest, data, sizeof(data)));
+ if (conn->actual_protocol_version < S2N_TLS12) {
+ uint8_t sha1_data[S2N_MAX_DIGEST_LEN] = { 0 };
+ struct s2n_blob sha1_digest = { 0 };
+ POSIX_GUARD(s2n_blob_init(&sha1_digest, sha1_data, sizeof(sha1_data)));
+ POSIX_GUARD_RESULT(s2n_prf_get_digest_for_ems(conn, &client_key_blob, S2N_HASH_MD5, &digest));
+ POSIX_GUARD_RESULT(s2n_prf_get_digest_for_ems(conn, &client_key_blob, S2N_HASH_SHA1, &sha1_digest));
+ POSIX_GUARD_RESULT(s2n_tls_prf_extended_master_secret(conn, premaster_secret, &digest, &sha1_digest));
+ } else {
+ s2n_hmac_algorithm prf_alg = conn->secure.cipher_suite->prf_alg;
+ s2n_hash_algorithm hash_alg = 0;
+ POSIX_GUARD(s2n_hmac_hash_alg(prf_alg, &hash_alg));
+ POSIX_GUARD_RESULT(s2n_prf_get_digest_for_ems(conn, &client_key_blob, hash_alg, &digest));
+ POSIX_GUARD_RESULT(s2n_tls_prf_extended_master_secret(conn, premaster_secret, &digest, NULL));
+ }
+ return S2N_SUCCESS;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc7627#section-4
+ *# When the extended master secret extension is negotiated in a full
+ *# handshake, the "master_secret" is computed as
+ *#
+ *# master_secret = PRF(pre_master_secret, "extended master secret",
+ *# session_hash)
+ *# [0..47];
+ */
+S2N_RESULT s2n_tls_prf_extended_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret, struct s2n_blob *session_hash, struct s2n_blob *sha1_hash)
+{
+ struct s2n_blob extended_master_secret = {.size = sizeof(conn->secrets.tls12.master_secret), .data = conn->secrets.tls12.master_secret};
+
+ uint8_t extended_master_secret_label[] = "extended master secret";
+ /* Subtract one from the label size to remove the "\0" */
+ struct s2n_blob label = {.size = sizeof(extended_master_secret_label) - 1, .data = extended_master_secret_label};
+
+ RESULT_GUARD_POSIX(s2n_prf(conn, premaster_secret, &label, session_hash, sha1_hash, NULL, &extended_master_secret));
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_prf_get_digest_for_ems(struct s2n_connection *conn, struct s2n_blob *message, s2n_hash_algorithm hash_alg, struct s2n_blob *output)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->handshake.hashes);
+ RESULT_ENSURE_REF(output);
+
+ struct s2n_hash_state *hash_state = &conn->handshake.hashes->hash_workspace;
+ RESULT_GUARD(s2n_handshake_copy_hash_state(conn, hash_alg, hash_state));
+ RESULT_GUARD_POSIX(s2n_hash_update(hash_state, message->data, message->size));
+
+ uint8_t digest_size = 0;
+ RESULT_GUARD_POSIX(s2n_hash_digest_size(hash_alg, &digest_size));
+ RESULT_ENSURE_GTE(output->size, digest_size);
+ RESULT_GUARD_POSIX(s2n_hash_digest(hash_state, output->data, digest_size));
+ output->size = digest_size;
+
+ return S2N_RESULT_OK;
+}
+
+static int s2n_sslv3_finished(struct s2n_connection *conn, uint8_t prefix[4], struct s2n_hash_state *hash_workspace, uint8_t * out)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+
uint8_t xorpad1[48] =
{ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
@@ -421,55 +614,64 @@ static int s2n_sslv3_finished(struct s2n_connection *conn, uint8_t prefix[4], st
uint8_t *md5_digest = out;
uint8_t *sha_digest = out + MD5_DIGEST_LENGTH;
- lte_check(MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, sizeof(conn->handshake.client_finished));
-
- GUARD(s2n_hash_update(md5, prefix, 4));
- GUARD(s2n_hash_update(md5, conn->secure.master_secret, sizeof(conn->secure.master_secret)));
- GUARD(s2n_hash_update(md5, xorpad1, 48));
- GUARD(s2n_hash_digest(md5, md5_digest, MD5_DIGEST_LENGTH));
- GUARD(s2n_hash_reset(md5));
- GUARD(s2n_hash_update(md5, conn->secure.master_secret, sizeof(conn->secure.master_secret)));
- GUARD(s2n_hash_update(md5, xorpad2, 48));
- GUARD(s2n_hash_update(md5, md5_digest, MD5_DIGEST_LENGTH));
- GUARD(s2n_hash_digest(md5, md5_digest, MD5_DIGEST_LENGTH));
- GUARD(s2n_hash_reset(md5));
-
- GUARD(s2n_hash_update(sha1, prefix, 4));
- GUARD(s2n_hash_update(sha1, conn->secure.master_secret, sizeof(conn->secure.master_secret)));
- GUARD(s2n_hash_update(sha1, xorpad1, 40));
- GUARD(s2n_hash_digest(sha1, sha_digest, SHA_DIGEST_LENGTH));
- GUARD(s2n_hash_reset(sha1));
- GUARD(s2n_hash_update(sha1, conn->secure.master_secret, sizeof(conn->secure.master_secret)));
- GUARD(s2n_hash_update(sha1, xorpad2, 40));
- GUARD(s2n_hash_update(sha1, sha_digest, SHA_DIGEST_LENGTH));
- GUARD(s2n_hash_digest(sha1, sha_digest, SHA_DIGEST_LENGTH));
- GUARD(s2n_hash_reset(sha1));
+ POSIX_ENSURE_LTE(MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, sizeof(conn->handshake.client_finished));
+
+ struct s2n_hash_state *md5 = hash_workspace;
+ POSIX_GUARD(s2n_hash_copy(md5, &conn->handshake.hashes->md5));
+ POSIX_GUARD(s2n_hash_update(md5, prefix, 4));
+ POSIX_GUARD(s2n_hash_update(md5, conn->secrets.tls12.master_secret, sizeof(conn->secrets.tls12.master_secret)));
+ POSIX_GUARD(s2n_hash_update(md5, xorpad1, 48));
+ POSIX_GUARD(s2n_hash_digest(md5, md5_digest, MD5_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_reset(md5));
+ POSIX_GUARD(s2n_hash_update(md5, conn->secrets.tls12.master_secret, sizeof(conn->secrets.tls12.master_secret)));
+ POSIX_GUARD(s2n_hash_update(md5, xorpad2, 48));
+ POSIX_GUARD(s2n_hash_update(md5, md5_digest, MD5_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_digest(md5, md5_digest, MD5_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_reset(md5));
+
+ struct s2n_hash_state *sha1 = hash_workspace;
+ POSIX_GUARD(s2n_hash_copy(sha1, &conn->handshake.hashes->sha1));
+ POSIX_GUARD(s2n_hash_update(sha1, prefix, 4));
+ POSIX_GUARD(s2n_hash_update(sha1, conn->secrets.tls12.master_secret, sizeof(conn->secrets.tls12.master_secret)));
+ POSIX_GUARD(s2n_hash_update(sha1, xorpad1, 40));
+ POSIX_GUARD(s2n_hash_digest(sha1, sha_digest, SHA_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_reset(sha1));
+ POSIX_GUARD(s2n_hash_update(sha1, conn->secrets.tls12.master_secret, sizeof(conn->secrets.tls12.master_secret)));
+ POSIX_GUARD(s2n_hash_update(sha1, xorpad2, 40));
+ POSIX_GUARD(s2n_hash_update(sha1, sha_digest, SHA_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_digest(sha1, sha_digest, SHA_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_reset(sha1));
return 0;
}
static int s2n_sslv3_client_finished(struct s2n_connection *conn)
{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+
uint8_t prefix[4] = { 0x43, 0x4c, 0x4e, 0x54 };
- lte_check(MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, sizeof(conn->handshake.client_finished));
- GUARD(s2n_hash_copy(&conn->handshake.prf_md5_hash_copy, &conn->handshake.md5));
- GUARD(s2n_hash_copy(&conn->handshake.prf_sha1_hash_copy, &conn->handshake.sha1));
- return s2n_sslv3_finished(conn, prefix, &conn->handshake.prf_md5_hash_copy, &conn->handshake.prf_sha1_hash_copy, conn->handshake.client_finished);
+ POSIX_ENSURE_LTE(MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, sizeof(conn->handshake.client_finished));
+ return s2n_sslv3_finished(conn, prefix, &conn->handshake.hashes->hash_workspace, conn->handshake.client_finished);
}
static int s2n_sslv3_server_finished(struct s2n_connection *conn)
{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+
uint8_t prefix[4] = { 0x53, 0x52, 0x56, 0x52 };
- lte_check(MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, sizeof(conn->handshake.server_finished));
- GUARD(s2n_hash_copy(&conn->handshake.prf_md5_hash_copy, &conn->handshake.md5));
- GUARD(s2n_hash_copy(&conn->handshake.prf_sha1_hash_copy, &conn->handshake.sha1));
- return s2n_sslv3_finished(conn, prefix, &conn->handshake.prf_md5_hash_copy, &conn->handshake.prf_sha1_hash_copy, conn->handshake.server_finished);
+ POSIX_ENSURE_LTE(MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, sizeof(conn->handshake.server_finished));
+ return s2n_sslv3_finished(conn, prefix, &conn->handshake.hashes->hash_workspace, conn->handshake.server_finished);
}
int s2n_prf_client_finished(struct s2n_connection *conn)
{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+
struct s2n_blob master_secret, md5, sha;
uint8_t md5_digest[MD5_DIGEST_LENGTH];
uint8_t sha_digest[SHA384_DIGEST_LENGTH];
@@ -486,35 +688,35 @@ int s2n_prf_client_finished(struct s2n_connection *conn)
label.data = client_finished_label;
label.size = sizeof(client_finished_label) - 1;
- master_secret.data = conn->secure.master_secret;
- master_secret.size = sizeof(conn->secure.master_secret);
+ master_secret.data = conn->secrets.tls12.master_secret;
+ master_secret.size = sizeof(conn->secrets.tls12.master_secret);
if (conn->actual_protocol_version == S2N_TLS12) {
switch (conn->secure.cipher_suite->prf_alg) {
case S2N_HMAC_SHA256:
- GUARD(s2n_hash_copy(&conn->handshake.prf_tls12_hash_copy, &conn->handshake.sha256));
- GUARD(s2n_hash_digest(&conn->handshake.prf_tls12_hash_copy, sha_digest, SHA256_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_copy(&conn->handshake.hashes->hash_workspace, &conn->handshake.hashes->sha256));
+ POSIX_GUARD(s2n_hash_digest(&conn->handshake.hashes->hash_workspace, sha_digest, SHA256_DIGEST_LENGTH));
sha.size = SHA256_DIGEST_LENGTH;
break;
case S2N_HMAC_SHA384:
- GUARD(s2n_hash_copy(&conn->handshake.prf_tls12_hash_copy, &conn->handshake.sha384));
- GUARD(s2n_hash_digest(&conn->handshake.prf_tls12_hash_copy, sha_digest, SHA384_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_copy(&conn->handshake.hashes->hash_workspace, &conn->handshake.hashes->sha384));
+ POSIX_GUARD(s2n_hash_digest(&conn->handshake.hashes->hash_workspace, sha_digest, SHA384_DIGEST_LENGTH));
sha.size = SHA384_DIGEST_LENGTH;
break;
default:
- S2N_ERROR(S2N_ERR_PRF_INVALID_ALGORITHM);
+ POSIX_BAIL(S2N_ERR_PRF_INVALID_ALGORITHM);
}
sha.data = sha_digest;
return s2n_prf(conn, &master_secret, &label, &sha, NULL, NULL, &client_finished);
}
- GUARD(s2n_hash_copy(&conn->handshake.prf_md5_hash_copy, &conn->handshake.md5));
- GUARD(s2n_hash_copy(&conn->handshake.prf_sha1_hash_copy, &conn->handshake.sha1));
-
- GUARD(s2n_hash_digest(&conn->handshake.prf_md5_hash_copy, md5_digest, MD5_DIGEST_LENGTH));
- GUARD(s2n_hash_digest(&conn->handshake.prf_sha1_hash_copy, sha_digest, SHA_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_copy(&conn->handshake.hashes->hash_workspace, &conn->handshake.hashes->md5));
+ POSIX_GUARD(s2n_hash_digest(&conn->handshake.hashes->hash_workspace, md5_digest, MD5_DIGEST_LENGTH));
md5.data = md5_digest;
md5.size = MD5_DIGEST_LENGTH;
+
+ POSIX_GUARD(s2n_hash_copy(&conn->handshake.hashes->hash_workspace, &conn->handshake.hashes->sha1));
+ POSIX_GUARD(s2n_hash_digest(&conn->handshake.hashes->hash_workspace, sha_digest, SHA_DIGEST_LENGTH));
sha.data = sha_digest;
sha.size = SHA_DIGEST_LENGTH;
@@ -523,6 +725,9 @@ int s2n_prf_client_finished(struct s2n_connection *conn)
int s2n_prf_server_finished(struct s2n_connection *conn)
{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+
struct s2n_blob master_secret, md5, sha;
uint8_t md5_digest[MD5_DIGEST_LENGTH];
uint8_t sha_digest[SHA384_DIGEST_LENGTH];
@@ -539,35 +744,35 @@ int s2n_prf_server_finished(struct s2n_connection *conn)
label.data = server_finished_label;
label.size = sizeof(server_finished_label) - 1;
- master_secret.data = conn->secure.master_secret;
- master_secret.size = sizeof(conn->secure.master_secret);
+ master_secret.data = conn->secrets.tls12.master_secret;
+ master_secret.size = sizeof(conn->secrets.tls12.master_secret);
if (conn->actual_protocol_version == S2N_TLS12) {
switch (conn->secure.cipher_suite->prf_alg) {
case S2N_HMAC_SHA256:
- GUARD(s2n_hash_copy(&conn->handshake.prf_tls12_hash_copy, &conn->handshake.sha256));
- GUARD(s2n_hash_digest(&conn->handshake.prf_tls12_hash_copy, sha_digest, SHA256_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_copy(&conn->handshake.hashes->hash_workspace, &conn->handshake.hashes->sha256));
+ POSIX_GUARD(s2n_hash_digest(&conn->handshake.hashes->hash_workspace, sha_digest, SHA256_DIGEST_LENGTH));
sha.size = SHA256_DIGEST_LENGTH;
break;
case S2N_HMAC_SHA384:
- GUARD(s2n_hash_copy(&conn->handshake.prf_tls12_hash_copy, &conn->handshake.sha384));
- GUARD(s2n_hash_digest(&conn->handshake.prf_tls12_hash_copy, sha_digest, SHA384_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_copy(&conn->handshake.hashes->hash_workspace, &conn->handshake.hashes->sha384));
+ POSIX_GUARD(s2n_hash_digest(&conn->handshake.hashes->hash_workspace, sha_digest, SHA384_DIGEST_LENGTH));
sha.size = SHA384_DIGEST_LENGTH;
break;
default:
- S2N_ERROR(S2N_ERR_PRF_INVALID_ALGORITHM);
+ POSIX_BAIL(S2N_ERR_PRF_INVALID_ALGORITHM);
}
sha.data = sha_digest;
return s2n_prf(conn, &master_secret, &label, &sha, NULL, NULL, &server_finished);
}
- GUARD(s2n_hash_copy(&conn->handshake.prf_md5_hash_copy, &conn->handshake.md5));
- GUARD(s2n_hash_copy(&conn->handshake.prf_sha1_hash_copy, &conn->handshake.sha1));
-
- GUARD(s2n_hash_digest(&conn->handshake.prf_md5_hash_copy, md5_digest, MD5_DIGEST_LENGTH));
- GUARD(s2n_hash_digest(&conn->handshake.prf_sha1_hash_copy, sha_digest, SHA_DIGEST_LENGTH));
+ POSIX_GUARD(s2n_hash_copy(&conn->handshake.hashes->hash_workspace, &conn->handshake.hashes->md5));
+ POSIX_GUARD(s2n_hash_digest(&conn->handshake.hashes->hash_workspace, md5_digest, MD5_DIGEST_LENGTH));
md5.data = md5_digest;
md5.size = MD5_DIGEST_LENGTH;
+
+ POSIX_GUARD(s2n_hash_copy(&conn->handshake.hashes->hash_workspace, &conn->handshake.hashes->sha1));
+ POSIX_GUARD(s2n_hash_digest(&conn->handshake.hashes->hash_workspace, sha_digest, SHA_DIGEST_LENGTH));
sha.data = sha_digest;
sha.size = SHA_DIGEST_LENGTH;
@@ -579,12 +784,12 @@ static int s2n_prf_make_client_key(struct s2n_connection *conn, struct s2n_stuff
struct s2n_blob client_key = {0};
client_key.size = conn->secure.cipher_suite->record_alg->cipher->key_material_size;
client_key.data = s2n_stuffer_raw_read(key_material, client_key.size);
- notnull_check(client_key.data);
+ POSIX_ENSURE_REF(client_key.data);
if (conn->mode == S2N_CLIENT) {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure.client_key, &client_key));
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure.client_key, &client_key));
} else {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure.client_key, &client_key));
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure.client_key, &client_key));
}
return 0;
@@ -595,12 +800,12 @@ static int s2n_prf_make_server_key(struct s2n_connection *conn, struct s2n_stuff
struct s2n_blob server_key = {0};
server_key.size = conn->secure.cipher_suite->record_alg->cipher->key_material_size;
server_key.data = s2n_stuffer_raw_read(key_material, server_key.size);
- notnull_check(server_key.data);
+ POSIX_ENSURE_REF(server_key.data);
if (conn->mode == S2N_SERVER) {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure.server_key, &server_key));
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure.server_key, &server_key));
} else {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure.server_key, &server_key));
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure.server_key, &server_key));
}
return 0;
@@ -608,58 +813,58 @@ static int s2n_prf_make_server_key(struct s2n_connection *conn, struct s2n_stuff
int s2n_prf_key_expansion(struct s2n_connection *conn)
{
- struct s2n_blob client_random = {.data = conn->secure.client_random,.size = sizeof(conn->secure.client_random) };
- struct s2n_blob server_random = {.data = conn->secure.server_random,.size = sizeof(conn->secure.server_random) };
- struct s2n_blob master_secret = {.data = conn->secure.master_secret,.size = sizeof(conn->secure.master_secret) };
+ struct s2n_blob client_random = {.data = conn->handshake_params.client_random,.size = sizeof(conn->handshake_params.client_random) };
+ struct s2n_blob server_random = {.data = conn->handshake_params.server_random,.size = sizeof(conn->handshake_params.server_random) };
+ struct s2n_blob master_secret = {.data = conn->secrets.tls12.master_secret,.size = sizeof(conn->secrets.tls12.master_secret) };
struct s2n_blob label, out;
uint8_t key_expansion_label[] = "key expansion";
uint8_t key_block[S2N_MAX_KEY_BLOCK_LEN];
label.data = key_expansion_label;
label.size = sizeof(key_expansion_label) - 1;
- GUARD(s2n_blob_init(&out, key_block, sizeof(key_block)));
+ POSIX_GUARD(s2n_blob_init(&out, key_block, sizeof(key_block)));
struct s2n_stuffer key_material = {0};
- GUARD(s2n_prf(conn, &master_secret, &label, &server_random, &client_random, NULL, &out));
- GUARD(s2n_stuffer_init(&key_material, &out));
- GUARD(s2n_stuffer_write(&key_material, &out));
+ POSIX_GUARD(s2n_prf(conn, &master_secret, &label, &server_random, &client_random, NULL, &out));
+ POSIX_GUARD(s2n_stuffer_init(&key_material, &out));
+ POSIX_GUARD(s2n_stuffer_write(&key_material, &out));
- ENSURE_POSIX(conn->secure.cipher_suite->available, S2N_ERR_PRF_INVALID_ALGORITHM);
- GUARD(conn->secure.cipher_suite->record_alg->cipher->init(&conn->secure.client_key));
- GUARD(conn->secure.cipher_suite->record_alg->cipher->init(&conn->secure.server_key));
+ POSIX_ENSURE(conn->secure.cipher_suite->available, S2N_ERR_PRF_INVALID_ALGORITHM);
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->init(&conn->secure.client_key));
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->init(&conn->secure.server_key));
/* Check that we have a valid MAC and key size */
uint8_t mac_size;
if (conn->secure.cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) {
mac_size = conn->secure.cipher_suite->record_alg->cipher->io.comp.mac_key_size;
} else {
- GUARD(s2n_hmac_digest_size(conn->secure.cipher_suite->record_alg->hmac_alg, &mac_size));
+ POSIX_GUARD(s2n_hmac_digest_size(conn->secure.cipher_suite->record_alg->hmac_alg, &mac_size));
}
/* Seed the client MAC */
uint8_t *client_mac_write_key = s2n_stuffer_raw_read(&key_material, mac_size);
- notnull_check(client_mac_write_key);
- GUARD(s2n_hmac_reset(&conn->secure.client_record_mac));
- GUARD(s2n_hmac_init(&conn->secure.client_record_mac, conn->secure.cipher_suite->record_alg->hmac_alg, client_mac_write_key, mac_size));
+ POSIX_ENSURE_REF(client_mac_write_key);
+ POSIX_GUARD(s2n_hmac_reset(&conn->secure.client_record_mac));
+ POSIX_GUARD(s2n_hmac_init(&conn->secure.client_record_mac, conn->secure.cipher_suite->record_alg->hmac_alg, client_mac_write_key, mac_size));
/* Seed the server MAC */
uint8_t *server_mac_write_key = s2n_stuffer_raw_read(&key_material, mac_size);
- notnull_check(server_mac_write_key);
- GUARD(s2n_hmac_reset(&conn->secure.server_record_mac));
- GUARD(s2n_hmac_init(&conn->secure.server_record_mac, conn->secure.cipher_suite->record_alg->hmac_alg, server_mac_write_key, mac_size));
+ POSIX_ENSURE_REF(server_mac_write_key);
+ POSIX_GUARD(s2n_hmac_reset(&conn->secure.server_record_mac));
+ POSIX_GUARD(s2n_hmac_init(&conn->secure.server_record_mac, conn->secure.cipher_suite->record_alg->hmac_alg, server_mac_write_key, mac_size));
/* Make the client key */
- GUARD(s2n_prf_make_client_key(conn, &key_material));
+ POSIX_GUARD(s2n_prf_make_client_key(conn, &key_material));
/* Make the server key */
- GUARD(s2n_prf_make_server_key(conn, &key_material));
+ POSIX_GUARD(s2n_prf_make_server_key(conn, &key_material));
/* Composite CBC does MAC inside the cipher, pass it the MAC key.
* Must happen after setting encryption/decryption keys.
*/
if (conn->secure.cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->io.comp.set_mac_write_key(&conn->secure.server_key, server_mac_write_key, mac_size));
- GUARD(conn->secure.cipher_suite->record_alg->cipher->io.comp.set_mac_write_key(&conn->secure.client_key, client_mac_write_key, mac_size));
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->io.comp.set_mac_write_key(&conn->secure.server_key, server_mac_write_key, mac_size));
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->io.comp.set_mac_write_key(&conn->secure.client_key, client_mac_write_key, mac_size));
}
/* TLS >= 1.1 has no implicit IVs for non AEAD ciphers */
@@ -685,8 +890,8 @@ int s2n_prf_key_expansion(struct s2n_connection *conn)
struct s2n_blob client_implicit_iv = {.data = conn->secure.client_implicit_iv,.size = implicit_iv_size };
struct s2n_blob server_implicit_iv = {.data = conn->secure.server_implicit_iv,.size = implicit_iv_size };
- GUARD(s2n_stuffer_read(&key_material, &client_implicit_iv));
- GUARD(s2n_stuffer_read(&key_material, &server_implicit_iv));
+ POSIX_GUARD(s2n_stuffer_read(&key_material, &client_implicit_iv));
+ POSIX_GUARD(s2n_stuffer_read(&key_material, &server_implicit_iv));
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_prf.h b/contrib/restricted/aws/s2n/tls/s2n_prf.h
index a3679436b2..cdf8414328 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_prf.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_prf.h
@@ -26,25 +26,15 @@
/* Enough to support TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, 2*SHA384_DIGEST_LEN + 2*AES256_KEY_SIZE */
#define S2N_MAX_KEY_BLOCK_LEN 160
-struct p_hash_state {
+union p_hash_state {
struct s2n_hmac_state s2n_hmac;
struct s2n_evp_hmac_state evp_hmac;
};
struct s2n_prf_working_space {
- struct {
- const struct s2n_p_hash_hmac *p_hash_hmac_impl;
- struct p_hash_state p_hash;
- uint8_t digest0[S2N_MAX_DIGEST_LEN];
- uint8_t digest1[S2N_MAX_DIGEST_LEN];
- } tls;
-
- struct {
- struct s2n_hash_state md5;
- struct s2n_hash_state sha1;
- uint8_t md5_digest[MD5_DIGEST_LENGTH];
- uint8_t sha1_digest[SHA_DIGEST_LENGTH];
- } ssl3;
+ union p_hash_state p_hash;
+ uint8_t digest0[S2N_MAX_DIGEST_LEN];
+ uint8_t digest1[S2N_MAX_DIGEST_LEN];
};
/* The s2n p_hash implementation is abstracted to allow for separate implementations, using
@@ -61,10 +51,15 @@ struct s2n_p_hash_hmac {
#include "tls/s2n_connection.h"
-extern int s2n_prf_new(struct s2n_connection *conn);
-extern int s2n_prf_free(struct s2n_connection *conn);
+S2N_RESULT s2n_prf_new(struct s2n_connection *conn);
+S2N_RESULT s2n_prf_wipe(struct s2n_connection *conn);
+S2N_RESULT s2n_prf_free(struct s2n_connection *conn);
+
+int s2n_prf_calculate_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret);
extern int s2n_tls_prf_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret);
extern int s2n_hybrid_prf_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret);
+S2N_RESULT s2n_tls_prf_extended_master_secret(struct s2n_connection *conn, struct s2n_blob *premaster_secret, struct s2n_blob *session_hash, struct s2n_blob *sha1_hash);
+S2N_RESULT s2n_prf_get_digest_for_ems(struct s2n_connection *conn, struct s2n_blob *message, s2n_hash_algorithm hash_alg, struct s2n_blob *output);
extern int s2n_prf_key_expansion(struct s2n_connection *conn);
extern int s2n_prf_server_finished(struct s2n_connection *conn);
extern int s2n_prf_client_finished(struct s2n_connection *conn);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c
index e0157f4ae4..88212161c8 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c
@@ -17,39 +17,146 @@
#include "error/s2n_errno.h"
#include "utils/s2n_safety.h"
-int s2n_blob_set_protocol_preferences(struct s2n_blob *application_protocols, const char *const *protocols, int protocol_count)
+S2N_RESULT s2n_protocol_preferences_read(struct s2n_stuffer *protocol_preferences, struct s2n_blob *protocol)
{
- struct s2n_stuffer protocol_stuffer = {0};
+ RESULT_ENSURE_REF(protocol_preferences);
+ RESULT_ENSURE_REF(protocol);
- GUARD(s2n_free(application_protocols));
+ uint8_t length = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(protocol_preferences, &length));
+ RESULT_ENSURE_GT(length, 0);
+ uint8_t *data = s2n_stuffer_raw_read(protocol_preferences, length);
+ RESULT_ENSURE_REF(data);
+
+ RESULT_GUARD_POSIX(s2n_blob_init(protocol, data, length));
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_protocol_preferences_contain(struct s2n_blob *protocol_preferences, struct s2n_blob *protocol, bool *contains)
+{
+ RESULT_ENSURE_REF(contains);
+ *contains = false;
+ RESULT_ENSURE_REF(protocol_preferences);
+ RESULT_ENSURE_REF(protocol);
+
+ struct s2n_stuffer app_protocols_stuffer = { 0 };
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&app_protocols_stuffer, protocol_preferences));
+ RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&app_protocols_stuffer, protocol_preferences->size));
+
+ while (s2n_stuffer_data_available(&app_protocols_stuffer) > 0) {
+ struct s2n_blob match_against = { 0 };
+ RESULT_GUARD(s2n_protocol_preferences_read(&app_protocols_stuffer, &match_against));
+
+ if (match_against.size == protocol->size && memcmp(match_against.data, protocol->data, protocol->size) == 0) {
+ *contains = true;
+ return S2N_RESULT_OK;
+ }
+ }
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_protocol_preferences_append(struct s2n_blob *application_protocols, const uint8_t *protocol, uint8_t protocol_len)
+{
+ RESULT_ENSURE_MUT(application_protocols);
+ RESULT_ENSURE_REF(protocol);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc7301#section-3.1
+ *# Empty strings
+ *# MUST NOT be included and byte strings MUST NOT be truncated.
+ */
+ RESULT_ENSURE(protocol_len != 0, S2N_ERR_INVALID_APPLICATION_PROTOCOL);
+
+ uint32_t prev_len = application_protocols->size;
+ uint32_t new_len = prev_len + /* len prefix */ 1 + protocol_len;
+ RESULT_ENSURE(new_len <= UINT16_MAX, S2N_ERR_INVALID_APPLICATION_PROTOCOL);
+
+ RESULT_GUARD_POSIX(s2n_realloc(application_protocols, new_len));
+
+ struct s2n_stuffer protocol_stuffer = { 0 };
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&protocol_stuffer, application_protocols));
+ RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&protocol_stuffer, prev_len));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(&protocol_stuffer, protocol_len));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&protocol_stuffer, protocol, protocol_len));
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_protocol_preferences_set(struct s2n_blob *application_protocols, const char *const *protocols, int protocol_count)
+{
+ RESULT_ENSURE_MUT(application_protocols);
+
+ /* NULL value indicates no preference so free the previous blob */
if (protocols == NULL || protocol_count == 0) {
- /* NULL value indicates no preference, so nothing to do */
- return 0;
+ RESULT_GUARD_POSIX(s2n_free(application_protocols));
+ return S2N_RESULT_OK;
}
- GUARD(s2n_stuffer_growable_alloc(&protocol_stuffer, 256));
- for (int i = 0; i < protocol_count; i++) {
+ DEFER_CLEANUP(struct s2n_blob new_protocols = { 0 }, s2n_free);
+
+ /* Allocate enough space to avoid a reallocation for every entry
+ *
+ * We assume that each protocol is most likely 8 bytes or less.
+ * If it ends up being larger, we will expand the blob automatically
+ * in the append method.
+ */
+ RESULT_GUARD_POSIX(s2n_realloc(&new_protocols, protocol_count * 8));
+
+ /* set the size back to 0 so we start at the beginning.
+ * s2n_realloc will just update the size field here
+ */
+ RESULT_GUARD_POSIX(s2n_realloc(&new_protocols, 0));
+
+ for (size_t i = 0; i < protocol_count; i++) {
+ const uint8_t * protocol = (const uint8_t *)protocols[i];
size_t length = strlen(protocols[i]);
- uint8_t protocol[255];
- S2N_ERROR_IF(length > 255 || (s2n_stuffer_data_available(&protocol_stuffer) + length + 1) > 65535, S2N_ERR_APPLICATION_PROTOCOL_TOO_LONG);
- memcpy_check(protocol, protocols[i], length);
- GUARD(s2n_stuffer_write_uint8(&protocol_stuffer, length));
- GUARD(s2n_stuffer_write_bytes(&protocol_stuffer, protocol, length));
+ /**
+ *= https://tools.ietf.org/rfc/rfc7301#section-3.1
+ *# Empty strings
+ *# MUST NOT be included and byte strings MUST NOT be truncated.
+ */
+ RESULT_ENSURE(length < 256, S2N_ERR_INVALID_APPLICATION_PROTOCOL);
+
+ RESULT_GUARD(s2n_protocol_preferences_append(&new_protocols, protocol, (uint8_t)length));
}
- GUARD(s2n_stuffer_extract_blob(&protocol_stuffer, application_protocols));
- GUARD(s2n_stuffer_free(&protocol_stuffer));
- return 0;
+ /* now we can free the previous list since we've validated all new input */
+ RESULT_GUARD_POSIX(s2n_free(application_protocols));
+
+ /* update the connection/config application_protocols with the newly allocated blob */
+ *application_protocols = new_protocols;
+
+ /* zero out new_protocols so the DEFER_CLEANUP from above doesn't free
+ * the blob that we created and assigned to application_protocols
+ */
+ /* cppcheck-suppress unreadVariable */
+ new_protocols = (struct s2n_blob){ 0 };
+
+ return S2N_RESULT_OK;
}
int s2n_config_set_protocol_preferences(struct s2n_config *config, const char *const *protocols, int protocol_count)
{
- return s2n_blob_set_protocol_preferences(&config->application_protocols, protocols, protocol_count);
+ POSIX_GUARD_RESULT(s2n_protocol_preferences_set(&config->application_protocols, protocols, protocol_count));
+ return S2N_SUCCESS;
+}
+
+int s2n_config_append_protocol_preference(struct s2n_config *config, const uint8_t *protocol, uint8_t protocol_len)
+{
+ POSIX_GUARD_RESULT(s2n_protocol_preferences_append(&config->application_protocols, protocol, protocol_len));
+ return S2N_SUCCESS;
}
int s2n_connection_set_protocol_preferences(struct s2n_connection *conn, const char * const *protocols, int protocol_count)
{
- return s2n_blob_set_protocol_preferences(&conn->application_protocols_overridden, protocols, protocol_count);
+ POSIX_GUARD_RESULT(s2n_protocol_preferences_set(&conn->application_protocols_overridden, protocols, protocol_count));
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_append_protocol_preference(struct s2n_connection *conn, const uint8_t *protocol, uint8_t protocol_len)
+{
+ POSIX_GUARD_RESULT(s2n_protocol_preferences_append(&conn->application_protocols_overridden, protocol, protocol_len));
+ return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.h
new file mode 100644
index 0000000000..421dfae6a7
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#pragma once
+
+#include "api/s2n.h"
+
+#include "utils/s2n_result.h"
+
+S2N_RESULT s2n_protocol_preferences_read(struct s2n_stuffer *protocol_preferences, struct s2n_blob *protocol);
+S2N_RESULT s2n_protocol_preferences_contain(struct s2n_blob *protocol_preferences, struct s2n_blob *protocol, bool *contains);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_psk.c b/contrib/restricted/aws/s2n/tls/s2n_psk.c
index 59d4d75158..4aacb13d87 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_psk.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_psk.c
@@ -13,11 +13,15 @@
* permissions and limitations under the License.
*/
+#include <sys/param.h>
+
#include "crypto/s2n_tls13_keys.h"
#include "tls/s2n_handshake.h"
#include "tls/s2n_tls13_handshake.h"
#include "tls/s2n_tls.h"
+#include "tls/extensions/s2n_extension_type.h"
+#include "tls/s2n_tls13_secrets.h"
#include "utils/s2n_array.h"
#include "utils/s2n_mem.h"
@@ -25,100 +29,373 @@
#define S2N_HASH_ALG_COUNT S2N_HASH_SENTINEL
-int s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type)
+S2N_RESULT s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type)
{
- notnull_check(psk);
+ RESULT_ENSURE_MUT(psk);
- memset_check(psk, 0, sizeof(struct s2n_psk));
+ RESULT_CHECKED_MEMSET(psk, 0, sizeof(struct s2n_psk));
psk->hmac_alg = S2N_HMAC_SHA256;
psk->type = type;
- return S2N_SUCCESS;
+ return S2N_RESULT_OK;
}
-int s2n_psk_new_identity(struct s2n_psk *psk, const uint8_t *identity, size_t identity_size)
+struct s2n_psk* s2n_external_psk_new()
{
- notnull_check(psk);
+ DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
+ PTR_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_psk)));
- GUARD(s2n_realloc(&psk->identity, identity_size));
- memcpy_check(psk->identity.data, identity, identity_size);
+ struct s2n_psk *psk = (struct s2n_psk*)(void*) mem.data;
+ PTR_GUARD_RESULT(s2n_psk_init(psk, S2N_PSK_TYPE_EXTERNAL));
+
+ ZERO_TO_DISABLE_DEFER_CLEANUP(mem);
+ return psk;
+}
+
+int s2n_psk_set_identity(struct s2n_psk *psk, const uint8_t *identity, uint16_t identity_size)
+{
+ POSIX_ENSURE_REF(psk);
+ POSIX_ENSURE_REF(identity);
+ POSIX_ENSURE(identity_size != 0, S2N_ERR_INVALID_ARGUMENT);
+
+ POSIX_GUARD(s2n_realloc(&psk->identity, identity_size));
+ POSIX_CHECKED_MEMCPY(psk->identity.data, identity, identity_size);
return S2N_SUCCESS;
}
-int s2n_psk_new_secret(struct s2n_psk *psk, const uint8_t *secret, size_t secret_size)
+int s2n_psk_set_secret(struct s2n_psk *psk, const uint8_t *secret, uint16_t secret_size)
{
- notnull_check(psk);
+ POSIX_ENSURE_REF(psk);
+ POSIX_ENSURE_REF(secret);
+ POSIX_ENSURE(secret_size != 0, S2N_ERR_INVALID_ARGUMENT);
- GUARD(s2n_realloc(&psk->secret, secret_size));
- memcpy_check(psk->secret.data, secret, secret_size);
+ POSIX_GUARD(s2n_realloc(&psk->secret, secret_size));
+ POSIX_CHECKED_MEMCPY(psk->secret.data, secret, secret_size);
return S2N_SUCCESS;
}
-int s2n_psk_free(struct s2n_psk *psk)
+S2N_RESULT s2n_psk_clone(struct s2n_psk *new_psk, struct s2n_psk *original_psk)
+{
+ if (original_psk == NULL) {
+ return S2N_RESULT_OK;
+ }
+ RESULT_ENSURE_REF(new_psk);
+
+ struct s2n_psk psk_copy = *new_psk;
+
+ /* Copy all fields from the old_config EXCEPT the blobs, which we need to reallocate. */
+ *new_psk = *original_psk;
+ new_psk->identity = psk_copy.identity;
+ new_psk->secret = psk_copy.secret;
+ new_psk->early_secret = psk_copy.early_secret;
+ new_psk->early_data_config = psk_copy.early_data_config;
+
+ /* Clone / realloc blobs */
+ RESULT_GUARD_POSIX(s2n_psk_set_identity(new_psk, original_psk->identity.data, original_psk->identity.size));
+ RESULT_GUARD_POSIX(s2n_psk_set_secret(new_psk, original_psk->secret.data, original_psk->secret.size));
+ RESULT_GUARD_POSIX(s2n_realloc(&new_psk->early_secret, original_psk->early_secret.size));
+ RESULT_CHECKED_MEMCPY(new_psk->early_secret.data, original_psk->early_secret.data, original_psk->early_secret.size);
+ RESULT_GUARD(s2n_early_data_config_clone(new_psk, &original_psk->early_data_config));
+
+ return S2N_RESULT_OK;
+}
+
+S2N_CLEANUP_RESULT s2n_psk_wipe(struct s2n_psk *psk)
{
if (psk == NULL) {
- return S2N_SUCCESS;
+ return S2N_RESULT_OK;
}
- GUARD(s2n_free(&psk->early_secret));
- GUARD(s2n_free(&psk->identity));
- GUARD(s2n_free(&psk->secret));
+ RESULT_GUARD_POSIX(s2n_free(&psk->early_secret));
+ RESULT_GUARD_POSIX(s2n_free(&psk->identity));
+ RESULT_GUARD_POSIX(s2n_free(&psk->secret));
+ RESULT_GUARD(s2n_early_data_config_free(&psk->early_data_config));
- return S2N_SUCCESS;
+ return S2N_RESULT_OK;
+}
+
+int s2n_psk_free(struct s2n_psk **psk)
+{
+ if (psk == NULL) {
+ return S2N_SUCCESS;
+ }
+ POSIX_GUARD_RESULT(s2n_psk_wipe(*psk));
+ return s2n_free_object((uint8_t **) psk, sizeof(struct s2n_psk));
}
S2N_RESULT s2n_psk_parameters_init(struct s2n_psk_parameters *params)
{
- ENSURE_REF(params);
- CHECKED_MEMSET(params, 0, sizeof(struct s2n_psk_parameters));
- GUARD_RESULT(s2n_array_init(&params->psk_list, sizeof(struct s2n_psk)));
+ RESULT_ENSURE_REF(params);
+ RESULT_CHECKED_MEMSET(params, 0, sizeof(struct s2n_psk_parameters));
+ RESULT_GUARD(s2n_array_init(&params->psk_list, sizeof(struct s2n_psk)));
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_psk_offered_psk_size(struct s2n_psk *psk, uint32_t *size)
+{
+ *size = sizeof(uint16_t) /* identity size */
+ + sizeof(uint32_t) /* obfuscated ticket age */
+ + sizeof(uint8_t) /* binder size */;
+
+ RESULT_GUARD_POSIX(s2n_add_overflow(*size, psk->identity.size, size));
+
+ uint8_t binder_size = 0;
+ RESULT_GUARD_POSIX(s2n_hmac_digest_size(psk->hmac_alg, &binder_size));
+ RESULT_GUARD_POSIX(s2n_add_overflow(*size, binder_size, size));
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_psk_parameters_offered_psks_size(struct s2n_psk_parameters *params, uint32_t *size)
+{
+ RESULT_ENSURE_REF(params);
+ RESULT_ENSURE_REF(size);
+
+ *size = sizeof(uint16_t) /* identity list size */
+ + sizeof(uint16_t) /* binder list size */;
+
+ for (uint32_t i = 0; i < params->psk_list.len; i++) {
+ struct s2n_psk *psk = NULL;
+ RESULT_GUARD(s2n_array_get(&params->psk_list, i, (void**)&psk));
+ RESULT_ENSURE_REF(psk);
+
+ uint32_t psk_size = 0;
+ RESULT_GUARD(s2n_psk_offered_psk_size(psk, &psk_size));
+ RESULT_GUARD_POSIX(s2n_add_overflow(*size, psk_size, size));
+ }
return S2N_RESULT_OK;
}
S2N_CLEANUP_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params)
{
- ENSURE_REF(params);
+ RESULT_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));
- GUARD_AS_RESULT(s2n_psk_free(psk));
+ struct s2n_psk *psk = NULL;
+ RESULT_GUARD(s2n_array_get(&params->psk_list, i, (void**)&psk));
+ RESULT_GUARD(s2n_psk_wipe(psk));
+ }
+ RESULT_GUARD_POSIX(s2n_free(&params->psk_list.mem));
+ RESULT_GUARD(s2n_psk_parameters_init(params));
+
+ return S2N_RESULT_OK;
+}
+
+S2N_CLEANUP_RESULT s2n_psk_parameters_wipe_secrets(struct s2n_psk_parameters *params)
+{
+ RESULT_ENSURE_REF(params);
+
+ for (size_t i = 0; i < params->psk_list.len; i++) {
+ struct s2n_psk *psk = NULL;
+ RESULT_GUARD(s2n_array_get(&params->psk_list, i, (void**)&psk));
+ RESULT_ENSURE_REF(psk);
+ RESULT_GUARD_POSIX(s2n_free(&psk->early_secret));
+ RESULT_GUARD_POSIX(s2n_free(&psk->secret));
+ }
+
+ return S2N_RESULT_OK;
+}
+
+bool s2n_offered_psk_list_has_next(struct s2n_offered_psk_list *psk_list)
+{
+ return psk_list != NULL && s2n_stuffer_data_available(&psk_list->wire_data) > 0;
+}
+
+S2N_RESULT s2n_offered_psk_list_read_next(struct s2n_offered_psk_list *psk_list, struct s2n_offered_psk *psk)
+{
+ RESULT_ENSURE_REF(psk_list);
+ RESULT_ENSURE_REF(psk_list->conn);
+ RESULT_ENSURE_MUT(psk);
+
+ uint16_t identity_size = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(&psk_list->wire_data, &identity_size));
+ RESULT_ENSURE_GT(identity_size, 0);
+
+ uint8_t *identity_data = NULL;
+ identity_data = s2n_stuffer_raw_read(&psk_list->wire_data, identity_size);
+ RESULT_ENSURE_REF(identity_data);
+
+ /**
+ *= 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.
+ */
+ if (psk_list->conn->psk_params.type == S2N_PSK_TYPE_EXTERNAL) {
+ RESULT_GUARD_POSIX(s2n_stuffer_skip_read(&psk_list->wire_data, sizeof(uint32_t)));
+ } else {
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint32(&psk_list->wire_data, &psk->obfuscated_ticket_age));
+ }
+
+ RESULT_GUARD_POSIX(s2n_blob_init(&psk->identity, identity_data, identity_size));
+ psk->wire_index = psk_list->wire_index;
+
+ RESULT_ENSURE(psk_list->wire_index < UINT16_MAX, S2N_ERR_INTEGER_OVERFLOW);
+ psk_list->wire_index++;
+ return S2N_RESULT_OK;
+}
+
+int s2n_offered_psk_list_next(struct s2n_offered_psk_list *psk_list, struct s2n_offered_psk *psk)
+{
+ POSIX_ENSURE_REF(psk_list);
+ POSIX_ENSURE_REF(psk);
+ *psk = (struct s2n_offered_psk){ 0 };
+ POSIX_ENSURE(s2n_offered_psk_list_has_next(psk_list), S2N_ERR_STUFFER_OUT_OF_DATA);
+ POSIX_ENSURE(s2n_result_is_ok(s2n_offered_psk_list_read_next(psk_list, psk)), S2N_ERR_BAD_MESSAGE);
+ return S2N_SUCCESS;
+}
+
+int s2n_offered_psk_list_reread(struct s2n_offered_psk_list *psk_list)
+{
+ POSIX_ENSURE_REF(psk_list);
+ psk_list->wire_index = 0;
+ return s2n_stuffer_reread(&psk_list->wire_data);
+}
+
+/* Match a PSK identity received from the client against the server's known PSK identities.
+ * This method compares a single client identity to all server identities.
+ *
+ * While both the client's offered identities and whether a match was found are public, we should make an attempt
+ * to keep the server's known identities a secret. We will make comparisons to the server's identities constant
+ * time (to hide partial matches) and not end the search early when a match is found (to hide the ordering).
+ *
+ * Keeping these comparisons constant time is not high priority. There's no known attack using these timings,
+ * and an attacker could probably guess the server's known identities just by observing the public identities
+ * sent by clients.
+ */
+static S2N_RESULT s2n_match_psk_identity(struct s2n_array *known_psks, const struct s2n_blob *wire_identity,
+ struct s2n_psk **match)
+{
+ RESULT_ENSURE_REF(match);
+ RESULT_ENSURE_REF(wire_identity);
+ RESULT_ENSURE_REF(known_psks);
+ *match = NULL;
+ for (size_t i = 0; i < known_psks->len; i++) {
+ struct s2n_psk *psk = NULL;
+ RESULT_GUARD(s2n_array_get(known_psks, i, (void**)&psk));
+ RESULT_ENSURE_REF(psk);
+ RESULT_ENSURE_REF(psk->identity.data);
+ RESULT_ENSURE_REF(wire_identity->data);
+ uint32_t compare_size = MIN(wire_identity->size, psk->identity.size);
+ if (s2n_constant_time_equals(psk->identity.data, wire_identity->data, compare_size)
+ & (psk->identity.size == wire_identity->size) & (!*match)) {
+ *match = psk;
+ }
+ }
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
+ *# For PSKs provisioned via NewSessionTicket, a server MUST validate
+ *# that the ticket age for the selected PSK identity (computed by
+ *# subtracting ticket_age_add from PskIdentity.obfuscated_ticket_age
+ *# modulo 2^32) is within a small tolerance of the time since the ticket
+ *# was issued (see Section 8).
+ **/
+static S2N_RESULT s2n_validate_ticket_lifetime(struct s2n_connection *conn, uint32_t obfuscated_ticket_age, uint32_t ticket_age_add)
+{
+ RESULT_ENSURE_REF(conn);
+
+ if (conn->psk_params.type == S2N_PSK_TYPE_EXTERNAL) {
+ return S2N_RESULT_OK;
}
- GUARD_AS_RESULT(s2n_free(&params->psk_list.mem));
- GUARD_RESULT(s2n_psk_parameters_init(params));
+
+ /* Subtract the ticket_age_add value from the ticket age in milliseconds. The resulting uint32_t value
+ * may wrap, resulting in the modulo 2^32 operation. */
+ uint32_t ticket_age_in_millis = obfuscated_ticket_age - ticket_age_add;
+ uint32_t session_lifetime_in_millis = conn->config->session_state_lifetime_in_nanos / ONE_MILLISEC_IN_NANOS;
+ RESULT_ENSURE(ticket_age_in_millis < session_lifetime_in_millis, S2N_ERR_INVALID_SESSION_TICKET);
return S2N_RESULT_OK;
}
+int s2n_offered_psk_list_choose_psk(struct s2n_offered_psk_list *psk_list, struct s2n_offered_psk *psk)
+{
+ POSIX_ENSURE_REF(psk_list);
+ POSIX_ENSURE_REF(psk_list->conn);
+
+ struct s2n_psk_parameters *psk_params = &psk_list->conn->psk_params;
+ struct s2n_stuffer ticket_stuffer = { 0 };
+
+ if (!psk) {
+ psk_params->chosen_psk = NULL;
+ return S2N_SUCCESS;
+ }
+
+ if (psk_params->type == S2N_PSK_TYPE_RESUMPTION && psk_list->conn->config->use_tickets) {
+ POSIX_GUARD(s2n_stuffer_init(&ticket_stuffer, &psk->identity));
+ POSIX_GUARD(s2n_stuffer_skip_write(&ticket_stuffer, psk->identity.size));
+
+ /* s2n_decrypt_session_ticket appends a new PSK with the decrypted values. */
+ POSIX_GUARD(s2n_decrypt_session_ticket(psk_list->conn, &ticket_stuffer));
+ }
+
+ struct s2n_psk *chosen_psk = NULL;
+ POSIX_GUARD_RESULT(s2n_match_psk_identity(&psk_params->psk_list, &psk->identity, &chosen_psk));
+ POSIX_ENSURE_REF(chosen_psk);
+ POSIX_GUARD_RESULT(s2n_validate_ticket_lifetime(psk_list->conn, psk->obfuscated_ticket_age, chosen_psk->ticket_age_add));
+ psk_params->chosen_psk = chosen_psk;
+ psk_params->chosen_psk_wire_index = psk->wire_index;
+
+ return S2N_SUCCESS;
+}
+
+struct s2n_offered_psk* s2n_offered_psk_new()
+{
+ DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
+ PTR_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_offered_psk)));
+ PTR_GUARD_POSIX(s2n_blob_zero(&mem));
+
+ struct s2n_offered_psk *psk = (struct s2n_offered_psk*)(void*) mem.data;
+
+ ZERO_TO_DISABLE_DEFER_CLEANUP(mem);
+ return psk;
+}
+
+int s2n_offered_psk_free(struct s2n_offered_psk **psk)
+{
+ if (psk == NULL) {
+ return S2N_SUCCESS;
+ }
+ return s2n_free_object((uint8_t **) psk, sizeof(struct s2n_offered_psk));
+}
+
+int s2n_offered_psk_get_identity(struct s2n_offered_psk *psk, uint8_t** identity, uint16_t *size)
+{
+ POSIX_ENSURE_REF(psk);
+ POSIX_ENSURE_REF(identity);
+ POSIX_ENSURE_REF(size);
+ *identity = psk->identity.data;
+ *size = psk->identity.size;
+ return S2N_SUCCESS;
+}
+
/* 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_hmac_algorithm hmac_alg,
const struct s2n_blob *partial_client_hello, struct s2n_blob *output_binder_hash)
{
- notnull_check(partial_client_hello);
- notnull_check(output_binder_hash);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(partial_client_hello);
+ POSIX_ENSURE_REF(output_binder_hash);
+ struct s2n_handshake_hashes *hashes = conn->handshake.hashes;
+ POSIX_ENSURE_REF(hashes);
/* 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. */
- DEFER_CLEANUP(struct s2n_hash_state hash_copy, s2n_hash_free);
- GUARD(s2n_hash_new(&hash_copy));
- GUARD(s2n_hash_copy(&hash_copy, &current_hash_state));
+ s2n_hash_algorithm hash_alg = S2N_HASH_NONE;
+ struct s2n_hash_state *hash_state = &hashes->hash_workspace;
+ POSIX_GUARD(s2n_hmac_hash_alg(hmac_alg, &hash_alg));
+ POSIX_GUARD_RESULT(s2n_handshake_copy_hash_state(conn, hash_alg, hash_state));
/* Add the partial client hello to the transcript. */
- GUARD(s2n_hash_update(&hash_copy, partial_client_hello->data, partial_client_hello->size));
+ POSIX_GUARD(s2n_hash_update(hash_state, partial_client_hello->data, partial_client_hello->size));
/* Get the transcript digest */
- GUARD(s2n_hash_digest(&hash_copy, output_binder_hash->data, output_binder_hash->size));
+ POSIX_GUARD(s2n_hash_digest(hash_state, output_binder_hash->data, output_binder_hash->size));
return S2N_SUCCESS;
}
@@ -131,29 +408,26 @@ int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hmac_algorith
int s2n_psk_calculate_binder(struct s2n_psk *psk, const struct s2n_blob *binder_hash,
struct s2n_blob *output_binder)
{
- notnull_check(psk);
- notnull_check(binder_hash);
- notnull_check(output_binder);
+ POSIX_ENSURE_REF(psk);
+ POSIX_ENSURE_REF(binder_hash);
+ POSIX_ENSURE_REF(output_binder);
DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free);
- 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);
-
- /* Make sure the early secret is saved on the psk structure for later use */
- GUARD(s2n_realloc(&psk->early_secret, psk_keys.size));
- GUARD(s2n_blob_init(&psk_keys.extract_secret, psk->early_secret.data, psk_keys.size));
+ POSIX_GUARD(s2n_tls13_keys_init(&psk_keys, psk->hmac_alg));
+ POSIX_ENSURE_EQ(binder_hash->size, psk_keys.size);
+ POSIX_ENSURE_EQ(output_binder->size, psk_keys.size);
/* Derive the binder key */
- GUARD(s2n_tls13_derive_binder_key(&psk_keys, psk));
+ POSIX_GUARD_RESULT(s2n_derive_binder_key(psk, &psk_keys.derive_secret));
+ POSIX_GUARD(s2n_blob_init(&psk_keys.extract_secret, psk->early_secret.data, psk_keys.size));
struct s2n_blob *binder_key = &psk_keys.derive_secret;
/* Expand the binder key into the finished key */
s2n_tls13_key_blob(finished_key, psk_keys.size);
- GUARD(s2n_tls13_derive_finished_key(&psk_keys, binder_key, &finished_key));
+ POSIX_GUARD(s2n_tls13_derive_finished_key(&psk_keys, binder_key, &finished_key));
/* HMAC the binder hash with the binder finished key */
- GUARD(s2n_hkdf_extract(&psk_keys.hmac, psk_keys.hmac_algorithm, &finished_key, binder_hash, output_binder));
+ POSIX_GUARD(s2n_hkdf_extract(&psk_keys.hmac, psk_keys.hmac_algorithm, &finished_key, binder_hash, output_binder));
return S2N_SUCCESS;
}
@@ -161,24 +435,24 @@ int s2n_psk_calculate_binder(struct s2n_psk *psk, const struct s2n_blob *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)
{
- notnull_check(psk);
- notnull_check(binder_to_verify);
+ POSIX_ENSURE_REF(psk);
+ POSIX_ENSURE_REF(binder_to_verify);
DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free);
- GUARD(s2n_tls13_keys_init(&psk_keys, psk->hmac_alg));
- eq_check(binder_to_verify->size, psk_keys.size);
+ POSIX_GUARD(s2n_tls13_keys_init(&psk_keys, psk->hmac_alg));
+ POSIX_ENSURE_EQ(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->hmac_alg, partial_client_hello, &binder_hash));
+ POSIX_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);
- GUARD(s2n_psk_calculate_binder(psk, &binder_hash, &expected_binder));
+ POSIX_GUARD(s2n_psk_calculate_binder(psk, &binder_hash, &expected_binder));
/* Verify the expected binder matches the given binder.
* This operation must be constant time. */
- GUARD(s2n_tls13_mac_verify(&psk_keys, &expected_binder, binder_to_verify));
+ POSIX_GUARD(s2n_tls13_mac_verify(&psk_keys, &expected_binder, binder_to_verify));
return S2N_SUCCESS;
}
@@ -186,15 +460,15 @@ int s2n_psk_verify_binder(struct s2n_connection *conn, struct s2n_psk *psk,
static S2N_RESULT s2n_psk_write_binder(struct s2n_connection *conn, struct s2n_psk *psk,
const struct s2n_blob *binder_hash, struct s2n_stuffer *out)
{
- ENSURE_REF(binder_hash);
+ RESULT_ENSURE_REF(binder_hash);
struct s2n_blob binder;
uint8_t binder_data[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
- GUARD_AS_RESULT(s2n_blob_init(&binder, binder_data, binder_hash->size));
+ RESULT_GUARD_POSIX(s2n_blob_init(&binder, binder_data, binder_hash->size));
- GUARD_AS_RESULT(s2n_psk_calculate_binder(psk, binder_hash, &binder));
- GUARD_AS_RESULT(s2n_stuffer_write_uint8(out, binder.size));
- GUARD_AS_RESULT(s2n_stuffer_write(out, &binder));
+ RESULT_GUARD_POSIX(s2n_psk_calculate_binder(psk, binder_hash, &binder));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, binder.size));
+ RESULT_GUARD_POSIX(s2n_stuffer_write(out, &binder));
return S2N_RESULT_OK;
}
@@ -202,8 +476,8 @@ static S2N_RESULT s2n_psk_write_binder(struct s2n_connection *conn, struct s2n_p
static S2N_RESULT s2n_psk_write_binder_list(struct s2n_connection *conn, const struct s2n_blob *partial_client_hello,
struct s2n_stuffer *out)
{
- ENSURE_REF(conn);
- ENSURE_REF(partial_client_hello);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(partial_client_hello);
struct s2n_psk_parameters *psk_params = &conn->psk_params;
struct s2n_array *psk_list = &psk_params->psk_list;
@@ -214,13 +488,13 @@ static S2N_RESULT s2n_psk_write_binder_list(struct s2n_connection *conn, const s
struct s2n_blob binder_hashes[S2N_HASH_ALG_COUNT] = { 0 };
struct s2n_stuffer_reservation binder_list_size = { 0 };
- GUARD_AS_RESULT(s2n_stuffer_reserve_uint16(out, &binder_list_size));
+ RESULT_GUARD_POSIX(s2n_stuffer_reserve_uint16(out, &binder_list_size));
/* Write binder for every psk */
for (size_t i = 0; i < psk_list->len; i++) {
struct s2n_psk *psk = NULL;
- GUARD_RESULT(s2n_array_get(psk_list, i, (void**) &psk));
- ENSURE_REF(psk);
+ RESULT_GUARD(s2n_array_get(psk_list, i, (void**) &psk));
+ RESULT_ENSURE_REF(psk);
/**
*= https://tools.ietf.org/rfc/rfc8446#section-4.1.4
@@ -238,21 +512,21 @@ static S2N_RESULT s2n_psk_write_binder_list(struct s2n_connection *conn, const s
struct s2n_blob *binder_hash = &binder_hashes[psk->hmac_alg];
if (binder_hash->size == 0) {
uint8_t hash_size = 0;
- 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));
+ RESULT_GUARD_POSIX(s2n_hmac_digest_size(psk->hmac_alg, &hash_size));
+ RESULT_GUARD_POSIX(s2n_blob_init(binder_hash, binder_hashes_data[psk->hmac_alg], hash_size));
+ RESULT_GUARD_POSIX(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));
+ RESULT_GUARD(s2n_psk_write_binder(conn, psk, binder_hash, out));
}
- GUARD_AS_RESULT(s2n_stuffer_write_vector_size(&binder_list_size));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_vector_size(&binder_list_size));
return S2N_RESULT_OK;
}
S2N_RESULT s2n_finish_psk_extension(struct s2n_connection *conn)
{
- ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn);
if (!conn->psk_params.binder_list_size) {
return S2N_RESULT_OK;
@@ -262,72 +536,161 @@ S2N_RESULT s2n_finish_psk_extension(struct s2n_connection *conn)
struct s2n_psk_parameters *psk_params = &conn->psk_params;
/* Fill in the correct message size. */
- GUARD_AS_RESULT(s2n_handshake_finish_header(client_hello));
+ RESULT_GUARD_POSIX(s2n_handshake_finish_header(client_hello));
/* Remove the empty space allocated for the binder list.
* It was originally added to ensure the extension / extension list / message sizes
* were properly calculated. */
- GUARD_AS_RESULT(s2n_stuffer_wipe_n(client_hello, psk_params->binder_list_size));
+ RESULT_GUARD_POSIX(s2n_stuffer_wipe_n(client_hello, psk_params->binder_list_size));
/* Store the partial client hello for use in calculating the binder hash. */
struct s2n_blob partial_client_hello = { 0 };
- GUARD_AS_RESULT(s2n_blob_init(&partial_client_hello, client_hello->blob.data,
+ RESULT_GUARD_POSIX(s2n_blob_init(&partial_client_hello, client_hello->blob.data,
s2n_stuffer_data_available(client_hello)));
- GUARD_RESULT(s2n_psk_write_binder_list(conn, &partial_client_hello, client_hello));
+ RESULT_GUARD(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)
+int s2n_psk_set_hmac(struct s2n_psk *psk, s2n_psk_hmac hmac)
{
- switch(psk_hmac_alg) {
- case S2N_PSK_HMAC_SHA224: psk->hmac_alg = S2N_HMAC_SHA224; break;
+ POSIX_ENSURE_REF(psk);
+ switch(hmac) {
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);
+ POSIX_BAIL(S2N_ERR_HMAC_INVALID_ALGORITHM);
+ }
+ return S2N_SUCCESS;
+}
+
+S2N_RESULT s2n_connection_set_psk_type(struct s2n_connection *conn, s2n_psk_type type)
+{
+ RESULT_ENSURE_REF(conn);
+ if (conn->psk_params.psk_list.len != 0) {
+ RESULT_ENSURE(conn->psk_params.type == type, S2N_ERR_PSK_MODE);
}
+ conn->psk_params.type = type;
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)
+int s2n_connection_append_psk(struct s2n_connection *conn, struct s2n_psk *input_psk)
{
- ENSURE_POSIX_REF(conn);
- ENSURE_POSIX_REF(psk_vec);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(input_psk);
+ POSIX_GUARD_RESULT(s2n_connection_set_psk_type(conn, input_psk->type));
+
+ struct s2n_array *psk_list = &conn->psk_params.psk_list;
- /* 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));
- }
+ /* Check for duplicate identities */
+ for (uint32_t j = 0; j < psk_list->len; j++) {
+ struct s2n_psk *existing_psk = NULL;
+ POSIX_GUARD_RESULT(s2n_array_get(psk_list, j, (void**) &existing_psk));
+ POSIX_ENSURE_REF(existing_psk);
+
+ bool duplicate = existing_psk->identity.size == input_psk->identity.size
+ && memcmp(existing_psk->identity.data, input_psk->identity.data, existing_psk->identity.size) == 0;
+ POSIX_ENSURE(!duplicate, S2N_ERR_DUPLICATE_PSK_IDENTITIES);
}
- 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);
- }
- }
+ /* Verify the PSK list will fit in the ClientHello pre_shared_key extension */
+ if (conn->mode == S2N_CLIENT) {
+ uint32_t list_size = 0;
+ POSIX_GUARD_RESULT(s2n_psk_parameters_offered_psks_size(&conn->psk_params, &list_size));
+
+ uint32_t psk_size = 0;
+ POSIX_GUARD_RESULT(s2n_psk_offered_psk_size(input_psk, &psk_size));
+
+ POSIX_ENSURE(list_size + psk_size + S2N_EXTENSION_HEADER_LENGTH <= UINT16_MAX, S2N_ERR_OFFERED_PSKS_TOO_LONG);
+ }
+
+ DEFER_CLEANUP(struct s2n_psk new_psk = { 0 }, s2n_psk_wipe);
+ POSIX_ENSURE(s2n_result_is_ok(s2n_psk_clone(&new_psk, input_psk)), S2N_ERR_INVALID_ARGUMENT);
+ POSIX_GUARD_RESULT(s2n_array_insert_and_copy(psk_list, psk_list->len, &new_psk));
+
+ ZERO_TO_DISABLE_DEFER_CLEANUP(new_psk);
+ return S2N_SUCCESS;
+}
+
+int s2n_config_set_psk_mode(struct s2n_config *config, s2n_psk_mode mode)
+{
+ POSIX_ENSURE_REF(config);
+ config->psk_mode = mode;
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_set_psk_mode(struct s2n_connection *conn, s2n_psk_mode mode)
+{
+ POSIX_ENSURE_REF(conn);
+ s2n_psk_type type = 0;
+ switch(mode) {
+ case S2N_PSK_MODE_RESUMPTION:
+ type = S2N_PSK_TYPE_RESUMPTION;
+ break;
+ case S2N_PSK_MODE_EXTERNAL:
+ type = S2N_PSK_TYPE_EXTERNAL;
+ break;
+ default:
+ POSIX_BAIL(S2N_ERR_INVALID_ARGUMENT);
+ break;
+ }
+ POSIX_GUARD_RESULT(s2n_connection_set_psk_type(conn, type));
+ conn->psk_mode_overridden = true;
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_get_negotiated_psk_identity_length(struct s2n_connection *conn, uint16_t *identity_length)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(identity_length);
- 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));
+ struct s2n_psk *chosen_psk = conn->psk_params.chosen_psk;
+
+ if (chosen_psk == NULL) {
+ *identity_length = 0;
+ } else {
+ *identity_length = chosen_psk->identity.size;
}
return S2N_SUCCESS;
}
+
+int s2n_connection_get_negotiated_psk_identity(struct s2n_connection *conn, uint8_t *identity,
+ uint16_t max_identity_length)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(identity);
+
+ struct s2n_psk *chosen_psk = conn->psk_params.chosen_psk;
+
+ if (chosen_psk == NULL) {
+ return S2N_SUCCESS;
+ }
+
+ POSIX_ENSURE(chosen_psk->identity.size <= max_identity_length, S2N_ERR_INSUFFICIENT_MEM_SIZE);
+ POSIX_CHECKED_MEMCPY(identity, chosen_psk->identity.data, chosen_psk->identity.size);
+
+ return S2N_SUCCESS;
+}
+
+S2N_RESULT s2n_psk_validate_keying_material(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+
+ struct s2n_psk *chosen_psk = conn->psk_params.chosen_psk;
+ if (!chosen_psk || chosen_psk->type != S2N_PSK_TYPE_RESUMPTION) {
+ return S2N_RESULT_OK;
+ }
+
+ /*
+ * The minimum ticket lifetime is 1s, because ticket_lifetime is given
+ * in seconds and 0 indicates that the ticket should be immediately discarded.
+ */
+ uint32_t min_lifetime = ONE_SEC_IN_NANOS;
+
+ uint64_t current_time = 0;
+ RESULT_GUARD_POSIX(conn->config->wall_clock(conn->config->sys_clock_ctx, &current_time));
+ RESULT_ENSURE(chosen_psk->keying_material_expiration > current_time + min_lifetime, S2N_ERR_KEYING_MATERIAL_EXPIRED);
+
+ return S2N_RESULT_OK;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_psk.h b/contrib/restricted/aws/s2n/tls/s2n_psk.h
index 6d7052c876..38ac65f3ac 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_psk.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_psk.h
@@ -15,15 +15,17 @@
#pragma once
-#include <s2n.h>
+#include "api/s2n.h"
#include "crypto/s2n_hmac.h"
+#include "stuffer/s2n_stuffer.h"
+#include "tls/s2n_early_data.h"
#include "utils/s2n_array.h"
#include "utils/s2n_blob.h"
#include "utils/s2n_result.h"
typedef enum {
- S2N_PSK_TYPE_RESUMPTION,
+ S2N_PSK_TYPE_RESUMPTION = 0,
S2N_PSK_TYPE_EXTERNAL,
} s2n_psk_type;
@@ -33,52 +35,50 @@ typedef enum {
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_hmac_algorithm hmac_alg;
- uint32_t obfuscated_ticket_age;
+ uint32_t ticket_age_add;
+ uint64_t ticket_issue_time;
struct s2n_blob early_secret;
-};
+ struct s2n_early_data_config early_data_config;
-struct s2n_psk_identity {
- uint8_t *data;
- uint16_t length;
+ /* This field is used with session tickets to track the lifetime
+ * of the original full handshake across multiple tickets.
+ * See https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ */
+ uint64_t keying_material_expiration;
};
+S2N_RESULT s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type);
+S2N_CLEANUP_RESULT s2n_psk_wipe(struct s2n_psk *psk);
+S2N_RESULT s2n_psk_clone(struct s2n_psk *new_psk, struct s2n_psk *original_psk);
struct s2n_psk_parameters {
+ s2n_psk_type type;
struct s2n_array psk_list;
uint16_t binder_list_size;
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_offered_psks_size(struct s2n_psk_parameters *params, uint32_t *size);
S2N_CLEANUP_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params);
+S2N_CLEANUP_RESULT s2n_psk_parameters_wipe_secrets(struct s2n_psk_parameters *params);
+
+struct s2n_offered_psk {
+ struct s2n_blob identity;
+ uint16_t wire_index;
+ uint32_t obfuscated_ticket_age;
+};
+
+struct s2n_offered_psk_list {
+ struct s2n_connection *conn;
+ struct s2n_stuffer wire_data;
+ uint16_t wire_index;
+};
S2N_RESULT s2n_finish_psk_extension(struct s2n_connection *conn);
@@ -89,9 +89,5 @@ int s2n_psk_calculate_binder(struct s2n_psk *psk, const struct s2n_blob *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);
-
+S2N_RESULT s2n_connection_set_psk_type(struct s2n_connection *conn, s2n_psk_type type);
+S2N_RESULT s2n_psk_validate_keying_material(struct s2n_connection *conn);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_quic_support.c b/contrib/restricted/aws/s2n/tls/s2n_quic_support.c
index 226b87ee9a..bd0b44f906 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_quic_support.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_quic_support.c
@@ -37,19 +37,33 @@ S2N_RESULT s2n_read_in_bytes(struct s2n_connection *conn, struct s2n_stuffer *ou
int s2n_config_enable_quic(struct s2n_config *config)
{
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
config->quic_enabled = true;
return S2N_SUCCESS;
}
+int s2n_connection_enable_quic(struct s2n_connection *conn)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD_RESULT(s2n_connection_validate_tls13_support(conn));
+ conn->quic_enabled = true;
+ return S2N_SUCCESS;
+}
+
+bool s2n_connection_is_quic_enabled(struct s2n_connection *conn)
+{
+ return (conn && conn->quic_enabled) ||
+ (conn && conn->config && conn->config->quic_enabled);
+}
+
int s2n_connection_set_quic_transport_parameters(struct s2n_connection *conn,
const uint8_t *data_buffer, uint16_t data_len)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
- GUARD(s2n_free(&conn->our_quic_transport_parameters));
- GUARD(s2n_alloc(&conn->our_quic_transport_parameters, data_len));
- memcpy_check(conn->our_quic_transport_parameters.data, data_buffer, data_len);
+ POSIX_GUARD(s2n_free(&conn->our_quic_transport_parameters));
+ POSIX_GUARD(s2n_alloc(&conn->our_quic_transport_parameters, data_len));
+ POSIX_CHECKED_MEMCPY(conn->our_quic_transport_parameters.data, data_buffer, data_len);
return S2N_SUCCESS;
}
@@ -57,9 +71,9 @@ int s2n_connection_set_quic_transport_parameters(struct s2n_connection *conn,
int s2n_connection_get_quic_transport_parameters(struct s2n_connection *conn,
const uint8_t **data_buffer, uint16_t *data_len)
{
- notnull_check(conn);
- notnull_check(data_buffer);
- notnull_check(data_len);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(data_buffer);
+ POSIX_ENSURE_REF(data_len);
*data_buffer = conn->peer_quic_transport_parameters.data;
*data_len = conn->peer_quic_transport_parameters.size;
@@ -69,8 +83,8 @@ int s2n_connection_get_quic_transport_parameters(struct s2n_connection *conn,
int s2n_connection_set_secret_callback(struct s2n_connection *conn, s2n_secret_cb cb_func, void *ctx)
{
- notnull_check(conn);
- notnull_check(cb_func);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(cb_func);
conn->secret_cb = cb_func;
conn->secret_cb_context = ctx;
@@ -83,19 +97,19 @@ int s2n_connection_set_secret_callback(struct s2n_connection *conn, s2n_secret_c
*/
S2N_RESULT s2n_quic_read_handshake_message(struct s2n_connection *conn, uint8_t *message_type)
{
- ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn);
/* Allocate stuffer space now so that we don't have to realloc later in the handshake. */
- GUARD_AS_RESULT(s2n_stuffer_resize_if_empty(&conn->in, S2N_EXPECTED_QUIC_MESSAGE_SIZE));
+ RESULT_GUARD_POSIX(s2n_stuffer_resize_if_empty(&conn->in, S2N_EXPECTED_QUIC_MESSAGE_SIZE));
- GUARD_RESULT(s2n_read_in_bytes(conn, &conn->handshake.io, TLS_HANDSHAKE_HEADER_LENGTH));
+ RESULT_GUARD(s2n_read_in_bytes(conn, &conn->handshake.io, TLS_HANDSHAKE_HEADER_LENGTH));
uint32_t message_len;
- GUARD_AS_RESULT(s2n_handshake_parse_header(conn, message_type, &message_len));
- GUARD_AS_RESULT(s2n_stuffer_reread(&conn->handshake.io));
+ RESULT_GUARD_POSIX(s2n_handshake_parse_header(conn, message_type, &message_len));
+ RESULT_GUARD_POSIX(s2n_stuffer_reread(&conn->handshake.io));
- ENSURE(message_len < S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH, S2N_ERR_BAD_MESSAGE);
- GUARD_RESULT(s2n_read_in_bytes(conn, &conn->in, message_len));
+ RESULT_ENSURE(message_len < S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH, S2N_ERR_BAD_MESSAGE);
+ RESULT_GUARD(s2n_read_in_bytes(conn, &conn->in, message_len));
return S2N_RESULT_OK;
}
@@ -105,11 +119,11 @@ S2N_RESULT s2n_quic_read_handshake_message(struct s2n_connection *conn, uint8_t
*/
S2N_RESULT s2n_quic_write_handshake_message(struct s2n_connection *conn, struct s2n_blob *in)
{
- ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn);
/* Allocate stuffer space now so that we don't have to realloc later in the handshake. */
- GUARD_AS_RESULT(s2n_stuffer_resize_if_empty(&conn->out, S2N_EXPECTED_QUIC_MESSAGE_SIZE));
+ RESULT_GUARD_POSIX(s2n_stuffer_resize_if_empty(&conn->out, S2N_EXPECTED_QUIC_MESSAGE_SIZE));
- GUARD_AS_RESULT(s2n_stuffer_write(&conn->out, in));
+ RESULT_GUARD_POSIX(s2n_stuffer_write(&conn->out, in));
return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_quic_support.h b/contrib/restricted/aws/s2n/tls/s2n_quic_support.h
index 459e03a2fd..c64583589a 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_quic_support.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_quic_support.h
@@ -25,11 +25,13 @@
* the behavior of S2N in potentially dangerous ways and should only be used by implementations
* of the QUIC protocol.
*
- * Additionally, the QUIC RFC is not yet finalized, so all QUIC APIs are considered experimental
- * and are subject to change without notice. They should only be used for testing purposes.
+ * Additionally, all QUIC APIs are considered experimental and are subject to change without
+ * notice. They should only be used for testing purposes.
*/
S2N_API int s2n_config_enable_quic(struct s2n_config *config);
+S2N_API int s2n_connection_enable_quic(struct s2n_connection *conn);
+S2N_API bool s2n_connection_is_quic_enabled(struct s2n_connection *conn);
/*
* Set the data to be sent in the quic_transport_parameters extension.
@@ -73,4 +75,17 @@ typedef int (*s2n_secret_cb) (void* context, struct s2n_connection *conn,
* The callback function will ONLY be triggered if QUIC is enabled. This API is not intended to be
* used outside of a QUIC implementation.
*/
-int s2n_connection_set_secret_callback(struct s2n_connection *conn, s2n_secret_cb cb_func, void *ctx);
+S2N_API int s2n_connection_set_secret_callback(struct s2n_connection *conn, s2n_secret_cb cb_func, void *ctx);
+
+/*
+ * Return the TLS alert that S2N-TLS would send, if S2N-TLS sent specific alerts.
+ *
+ * S2N-TLS only sends generic close_notify alerts for security reasons, and TLS never
+ * sends alerts when used by QUIC. This method returns the alert that would have been
+ * sent if S2N-TLS sent specific alerts as defined in the protocol specifications.
+ *
+ * WARNING: this method is still considered experimental and will not always report
+ * the correct alert description. It may be used for testing and logging, but
+ * not relied on for production logic.
+ */
+S2N_API int s2n_error_get_alert(int error, uint8_t *alert);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_record.h b/contrib/restricted/aws/s2n/tls/s2n_record.h
index f5b6f27502..53aeba58bb 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_record.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_record.h
@@ -16,11 +16,56 @@
#pragma once
#include <stdint.h>
+#include "crypto/s2n_hmac.h"
+#include "stuffer/s2n_stuffer.h"
-#include "s2n_connection.h"
+#define S2N_TLS_CONTENT_TYPE_LENGTH 1
-#define TLS13_CONTENT_TYPE_LENGTH 1
+/* All versions of TLS define the record header the same:
+ * ContentType + ProtocolVersion + length
+ */
+#define S2N_TLS_RECORD_HEADER_LENGTH (S2N_TLS_CONTENT_TYPE_LENGTH + S2N_TLS_PROTOCOL_VERSION_LEN + 2)
+
+/*
+ * All versions of TLS limit the data fragment to 2^14 bytes.
+ *
+ *= https://tools.ietf.org/rfc/rfc5246#section-6.2.1
+ *# The record layer fragments information blocks into TLSPlaintext
+ *# records carrying data in chunks of 2^14 bytes or less.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-5.1
+ *# The record layer fragments information blocks into TLSPlaintext
+ *# records carrying data in chunks of 2^14 bytes or less.
+ */
+#define S2N_TLS_MAXIMUM_FRAGMENT_LENGTH (1 << 14)
+
+/* The TLS1.2 record length allows for 1024 bytes of compression expansion and
+ * 1024 bytes of encryption expansion and padding.
+ * Since S2N does not support compression, we can ignore the compression overhead.
+ */
+#define S2N_TLS12_ENCRYPTION_OVERHEAD_SIZE 1024
+#define S2N_TLS12_MAX_RECORD_LEN_FOR(frag) ((frag) + S2N_TLS12_ENCRYPTION_OVERHEAD_SIZE \
+ + S2N_TLS_RECORD_HEADER_LENGTH)
+#define S2N_TLS12_MAXIMUM_RECORD_LENGTH S2N_TLS12_MAX_RECORD_LEN_FOR(S2N_TLS_MAXIMUM_FRAGMENT_LENGTH)
+
+/*
+ *= https://tools.ietf.org/rfc/rfc8446#section-5.2
+ *# An AEAD algorithm used in TLS 1.3 MUST NOT produce an expansion
+ *# greater than 255 octets.
+ */
+#define S2N_TLS13_ENCRYPTION_OVERHEAD_SIZE 255
+#define S2N_TLS13_MAX_RECORD_LEN_FOR(frag) ((frag) + S2N_TLS_CONTENT_TYPE_LENGTH \
+ + S2N_TLS13_ENCRYPTION_OVERHEAD_SIZE \
+ + S2N_TLS_RECORD_HEADER_LENGTH)
+#define S2N_TLS13_MAXIMUM_RECORD_LENGTH S2N_TLS13_MAX_RECORD_LEN_FOR(S2N_TLS_MAXIMUM_FRAGMENT_LENGTH)
+
+/* Currently, TLS1.2 records may be larger than TLS1.3 records.
+ * If the protocol is unknown, assume TLS1.2.
+ */
+#define S2N_TLS_MAX_RECORD_LEN_FOR(frag) S2N_TLS12_MAX_RECORD_LEN_FOR(frag)
+#define S2N_TLS_MAXIMUM_RECORD_LENGTH S2N_TLS_MAX_RECORD_LEN_FOR(S2N_TLS_MAXIMUM_FRAGMENT_LENGTH)
+S2N_RESULT s2n_record_max_write_size(struct s2n_connection *conn, uint16_t max_fragment_size, uint16_t *max_record_size);
extern S2N_RESULT s2n_record_max_write_payload_size(struct s2n_connection *conn, uint16_t *max_fragment_size);
extern S2N_RESULT s2n_record_min_write_payload_size(struct s2n_connection *conn, uint16_t *payload_size);
extern int s2n_record_write(struct s2n_connection *conn, uint8_t content_type, struct s2n_blob *in);
@@ -30,5 +75,5 @@ extern int s2n_record_header_parse(struct s2n_connection *conn, uint8_t * conten
extern int s2n_tls13_parse_record_type(struct s2n_stuffer *stuffer, uint8_t * record_type);
extern int s2n_sslv2_record_header_parse(struct s2n_connection *conn, uint8_t * record_type, uint8_t * client_protocol_version, uint16_t * fragment_length);
extern int s2n_verify_cbc(struct s2n_connection *conn, struct s2n_hmac_state *hmac, struct s2n_blob *decrypted);
-extern S2N_RESULT s2n_aead_aad_init(const struct s2n_connection *conn, uint8_t * sequence_number, uint8_t content_type, uint16_t record_length, struct s2n_stuffer *ad);
-extern S2N_RESULT s2n_tls13_aead_aad_init(uint16_t record_length, uint8_t tag_length, struct s2n_stuffer *ad);
+extern S2N_RESULT s2n_aead_aad_init(const struct s2n_connection *conn, uint8_t * sequence_number, uint8_t content_type, uint16_t record_length, struct s2n_blob *ad);
+extern S2N_RESULT s2n_tls13_aead_aad_init(uint16_t record_length, uint8_t tag_length, struct s2n_blob *ad);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_read.c b/contrib/restricted/aws/s2n/tls/s2n_record_read.c
index 7b8536818e..8a1bf8836f 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_record_read.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_record_read.c
@@ -41,15 +41,16 @@ int s2n_sslv2_record_header_parse(
S2N_ERROR_IF(s2n_stuffer_data_available(in) < S2N_TLS_RECORD_HEADER_LENGTH, S2N_ERR_BAD_MESSAGE);
- GUARD(s2n_stuffer_read_uint16(in, fragment_length));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, fragment_length));
/* Adjust to account for the 3 bytes of payload data we consumed in the header */
+ POSIX_ENSURE_GTE(*fragment_length, 3);
*fragment_length -= 3;
- GUARD(s2n_stuffer_read_uint8(in, record_type));
+ POSIX_GUARD(s2n_stuffer_read_uint8(in, record_type));
uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN];
- GUARD(s2n_stuffer_read_bytes(in, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(in, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
*client_protocol_version = (protocol_version[0] * 10) + protocol_version[1];
@@ -65,10 +66,10 @@ int s2n_record_header_parse(
S2N_ERROR_IF(s2n_stuffer_data_available(in) < S2N_TLS_RECORD_HEADER_LENGTH, S2N_ERR_BAD_MESSAGE);
- GUARD(s2n_stuffer_read_uint8(in, content_type));
+ POSIX_GUARD(s2n_stuffer_read_uint8(in, content_type));
uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN];
- GUARD(s2n_stuffer_read_bytes(in, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(in, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
const uint8_t version = (protocol_version[0] * 10) + protocol_version[1];
/* https://tools.ietf.org/html/rfc5246#appendix-E.1 states that servers must accept any value {03,XX} as the record
@@ -82,13 +83,13 @@ int s2n_record_header_parse(
S2N_ERROR_IF(conn->actual_protocol_version_established &&
MIN(conn->actual_protocol_version, S2N_TLS12) /* check against legacy record version (1.2) in tls 1.3 */
!= version, S2N_ERR_BAD_MESSAGE);
- GUARD(s2n_stuffer_read_uint16(in, fragment_length));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, fragment_length));
/* Some servers send fragments that are above the maximum length. (e.g.
* Openssl 1.0.1, so we don't check if the fragment length is >
* S2N_TLS_MAXIMUM_FRAGMENT_LENGTH. The on-the-wire max is 65k
*/
- GUARD(s2n_stuffer_reread(in));
+ POSIX_GUARD(s2n_stuffer_reread(in));
return 0;
}
@@ -115,7 +116,7 @@ int s2n_record_parse(struct s2n_connection *conn)
{
uint8_t content_type;
uint16_t encrypted_length;
- GUARD(s2n_record_header_parse(conn, &content_type, &encrypted_length));
+ POSIX_GUARD(s2n_record_header_parse(conn, &content_type, &encrypted_length));
struct s2n_crypto_parameters *current_client_crypto = conn->client;
struct s2n_crypto_parameters *current_server_crypto = conn->server;
@@ -143,21 +144,27 @@ int s2n_record_parse(struct s2n_connection *conn)
conn->server = current_server_crypto;
}
+ /* The NULL stream cipher MUST NEVER be used for ApplicationData.
+ * If ApplicationData is unencrypted, we can't trust it. */
+ if (cipher_suite->record_alg->cipher == &s2n_null_cipher) {
+ POSIX_ENSURE(content_type != TLS_APPLICATION_DATA, S2N_ERR_DECRYPT);
+ }
+
switch (cipher_suite->record_alg->cipher->type) {
case S2N_AEAD:
- GUARD(s2n_record_parse_aead(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
+ POSIX_GUARD(s2n_record_parse_aead(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
break;
case S2N_CBC:
- GUARD(s2n_record_parse_cbc(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
+ POSIX_GUARD(s2n_record_parse_cbc(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
break;
case S2N_COMPOSITE:
- GUARD(s2n_record_parse_composite(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
+ POSIX_GUARD(s2n_record_parse_composite(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
break;
case S2N_STREAM:
- GUARD(s2n_record_parse_stream(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
+ POSIX_GUARD(s2n_record_parse_stream(cipher_suite, conn, content_type, encrypted_length, implicit_iv, mac, sequence_number, session_key));
break;
default:
- S2N_ERROR(S2N_ERR_CIPHER_TYPE);
+ POSIX_BAIL(S2N_ERR_CIPHER_TYPE);
break;
}
@@ -181,7 +188,7 @@ int s2n_tls13_parse_record_type(struct s2n_stuffer *stuffer, uint8_t *record_typ
S2N_ERROR_IF(bytes_left > S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH + 16, S2N_ERR_MAX_INNER_PLAINTEXT_SIZE);
/* set cursor to the end of the stuffer */
- GUARD(s2n_stuffer_skip_read(stuffer, bytes_left));
+ POSIX_GUARD(s2n_stuffer_skip_read(stuffer, bytes_left));
/* Record type should have values greater than zero.
* If zero, treat as padding, keep reading and wiping from the back
@@ -190,18 +197,18 @@ int s2n_tls13_parse_record_type(struct s2n_stuffer *stuffer, uint8_t *record_typ
*record_type = 0;
while (*record_type == 0) {
/* back the cursor by one to read off the last byte */
- GUARD(s2n_stuffer_rewind_read(stuffer, 1));
+ POSIX_GUARD(s2n_stuffer_rewind_read(stuffer, 1));
/* set the record type */
- GUARD(s2n_stuffer_read_uint8(stuffer, record_type));
+ POSIX_GUARD(s2n_stuffer_read_uint8(stuffer, record_type));
/* wipe the last byte at the end of the stuffer */
- GUARD(s2n_stuffer_wipe_n(stuffer, 1));
+ POSIX_GUARD(s2n_stuffer_wipe_n(stuffer, 1));
}
/* only the original plaintext should remain */
/* now reset the read cursor at where it should be */
- GUARD(s2n_stuffer_reread(stuffer));
+ POSIX_GUARD(s2n_stuffer_reread(stuffer));
/* Even in the incorrect case above with up to 16 extra bytes, we should never see too much data after unpadding */
S2N_ERROR_IF(s2n_stuffer_data_available(stuffer) > S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH - 1, S2N_ERR_MAX_INNER_PLAINTEXT_SIZE);
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 87207d3723..ba1d460d82 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c
@@ -46,19 +46,19 @@ int s2n_record_parse_aead(
s2n_stack_blob(aad, is_tls13_record ? S2N_TLS13_AAD_LEN : S2N_TLS_MAX_AAD_LEN, S2N_TLS_MAX_AAD_LEN);
struct s2n_blob en = {.size = encrypted_length,.data = s2n_stuffer_raw_read(&conn->in, encrypted_length) };
- notnull_check(en.data);
+ POSIX_ENSURE_REF(en.data);
/* In AEAD mode, the explicit IV is in the record */
- gte_check(en.size, cipher_suite->record_alg->cipher->io.aead.record_iv_size);
+ POSIX_ENSURE_GTE(en.size, cipher_suite->record_alg->cipher->io.aead.record_iv_size);
uint8_t aad_iv[S2N_TLS_MAX_IV_LEN] = { 0 };
struct s2n_blob iv = {.data = aad_iv,.size = sizeof(aad_iv) };
struct s2n_stuffer iv_stuffer = {0};
- GUARD(s2n_stuffer_init(&iv_stuffer, &iv));
+ POSIX_GUARD(s2n_stuffer_init(&iv_stuffer, &iv));
if (cipher_suite->record_alg->flags & S2N_TLS12_AES_GCM_AEAD_NONCE) {
/* Partially explicit nonce. See RFC 5288 Section 3 */
- GUARD(s2n_stuffer_write_bytes(&iv_stuffer, implicit_iv, cipher_suite->record_alg->cipher->io.aead.fixed_iv_size));
- GUARD(s2n_stuffer_write_bytes(&iv_stuffer, en.data, cipher_suite->record_alg->cipher->io.aead.record_iv_size));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, implicit_iv, cipher_suite->record_alg->cipher->io.aead.fixed_iv_size));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, en.data, cipher_suite->record_alg->cipher->io.aead.record_iv_size));
} else if (cipher_suite->record_alg->flags & S2N_TLS12_CHACHA_POLY_AEAD_NONCE || is_tls13_record) {
/* Fully implicit nonce.
* This is introduced with ChaChaPoly with RFC 7905 Section 2
@@ -68,14 +68,14 @@ int s2n_record_parse_aead(
* to align and xor-ed with the 96-bit IV.
**/
uint8_t four_zeroes[4] = { 0 };
- GUARD(s2n_stuffer_write_bytes(&iv_stuffer, four_zeroes, 4));
- GUARD(s2n_stuffer_write_bytes(&iv_stuffer, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, four_zeroes, 4));
+ POSIX_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_INVARIANT(i <= cipher_suite->record_alg->cipher->io.aead.fixed_iv_size);
aad_iv[i] = aad_iv[i] ^ implicit_iv[i];
}
} else {
- S2N_ERROR(S2N_ERR_INVALID_NONCE_TYPE);
+ POSIX_BAIL(S2N_ERR_INVALID_NONCE_TYPE);
}
/* Set the IV size to the amount of data written */
@@ -83,17 +83,14 @@ int s2n_record_parse_aead(
uint16_t payload_length = encrypted_length;
/* remove the AEAD overhead from the record size */
- gte_check(payload_length, cipher_suite->record_alg->cipher->io.aead.record_iv_size + cipher_suite->record_alg->cipher->io.aead.tag_size);
+ POSIX_ENSURE_GTE(payload_length, cipher_suite->record_alg->cipher->io.aead.record_iv_size + cipher_suite->record_alg->cipher->io.aead.tag_size);
payload_length -= cipher_suite->record_alg->cipher->io.aead.record_iv_size;
payload_length -= cipher_suite->record_alg->cipher->io.aead.tag_size;
- struct s2n_stuffer ad_stuffer = {0};
- GUARD(s2n_stuffer_init(&ad_stuffer, &aad));
-
if (is_tls13_record) {
- GUARD_AS_POSIX(s2n_tls13_aead_aad_init(payload_length, cipher_suite->record_alg->cipher->io.aead.tag_size, &ad_stuffer));
+ POSIX_GUARD_RESULT(s2n_tls13_aead_aad_init(payload_length, cipher_suite->record_alg->cipher->io.aead.tag_size, &aad));
} else {
- GUARD_AS_POSIX(s2n_aead_aad_init(conn, sequence_number, content_type, payload_length, &ad_stuffer));
+ POSIX_GUARD_RESULT(s2n_aead_aad_init(conn, sequence_number, content_type, payload_length, &aad));
}
/* Decrypt stuff! */
@@ -102,25 +99,25 @@ int s2n_record_parse_aead(
en.data += cipher_suite->record_alg->cipher->io.aead.record_iv_size;
/* Check that we have some data to decrypt */
- ne_check(en.size, 0);
+ POSIX_ENSURE_NE(en.size, 0);
- GUARD(cipher_suite->record_alg->cipher->io.aead.decrypt(session_key, &iv, &aad, &en, &en));
+ POSIX_GUARD(cipher_suite->record_alg->cipher->io.aead.decrypt(session_key, &iv, &aad, &en, &en));
struct s2n_blob seq = {.data = sequence_number,.size = S2N_TLS_SEQUENCE_NUM_LEN };
- GUARD(s2n_increment_sequence_number(&seq));
+ POSIX_GUARD(s2n_increment_sequence_number(&seq));
/* O.k., we've successfully read and decrypted the record, now we need to align the stuffer
* for reading the plaintext data.
*/
- GUARD(s2n_stuffer_reread(&conn->in));
- GUARD(s2n_stuffer_reread(&conn->header_in));
+ POSIX_GUARD(s2n_stuffer_reread(&conn->in));
+ POSIX_GUARD(s2n_stuffer_reread(&conn->header_in));
/* Skip the IV, if any */
if (conn->actual_protocol_version >= S2N_TLS12) {
- GUARD(s2n_stuffer_skip_read(&conn->in, cipher_suite->record_alg->cipher->io.aead.record_iv_size));
+ POSIX_GUARD(s2n_stuffer_skip_read(&conn->in, cipher_suite->record_alg->cipher->io.aead.record_iv_size));
}
/* Truncate and wipe the MAC and any padding */
- GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length));
+ POSIX_GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length));
conn->in_status = PLAINTEXT;
return 0;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_read_cbc.c b/contrib/restricted/aws/s2n/tls/s2n_record_read_cbc.c
index 9948469593..f72f090915 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_record_read_cbc.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_record_read_cbc.c
@@ -45,85 +45,85 @@ int s2n_record_parse_cbc(
/* Add the header to the HMAC */
uint8_t *header = s2n_stuffer_raw_read(&conn->header_in, S2N_TLS_RECORD_HEADER_LENGTH);
- notnull_check(header);
+ POSIX_ENSURE_REF(header);
- lte_check(cipher_suite->record_alg->cipher->io.cbc.record_iv_size, S2N_TLS_MAX_IV_LEN);
+ POSIX_ENSURE_LTE(cipher_suite->record_alg->cipher->io.cbc.record_iv_size, S2N_TLS_MAX_IV_LEN);
/* For TLS >= 1.1 the IV is in the packet */
if (conn->actual_protocol_version > S2N_TLS10) {
- GUARD(s2n_stuffer_read(&conn->in, &iv));
- gte_check(encrypted_length, iv.size);
+ POSIX_GUARD(s2n_stuffer_read(&conn->in, &iv));
+ POSIX_ENSURE_GTE(encrypted_length, iv.size);
encrypted_length -= iv.size;
}
struct s2n_blob en = {.size = encrypted_length,.data = s2n_stuffer_raw_read(&conn->in, encrypted_length) };
- notnull_check(en.data);
+ POSIX_ENSURE_REF(en.data);
uint16_t payload_length = encrypted_length;
uint8_t mac_digest_size;
- GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size));
+ POSIX_GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size));
- gte_check(payload_length, mac_digest_size);
+ POSIX_ENSURE_GTE(payload_length, mac_digest_size);
payload_length -= mac_digest_size;
/* Decrypt stuff! */
/* Check that we have some data to decrypt */
- ne_check(en.size, 0);
+ POSIX_ENSURE_NE(en.size, 0);
/* ... and that we have a multiple of the block size */
- eq_check(en.size % iv.size, 0);
+ POSIX_ENSURE_EQ(en.size % iv.size, 0);
/* Copy the last encrypted block to be the next IV */
if (conn->actual_protocol_version < S2N_TLS11) {
- memcpy_check(ivpad, en.data + en.size - iv.size, iv.size);
+ POSIX_CHECKED_MEMCPY(ivpad, en.data + en.size - iv.size, iv.size);
}
- GUARD(cipher_suite->record_alg->cipher->io.cbc.decrypt(session_key, &iv, &en, &en));
+ POSIX_GUARD(cipher_suite->record_alg->cipher->io.cbc.decrypt(session_key, &iv, &en, &en));
if (conn->actual_protocol_version < S2N_TLS11) {
- memcpy_check(implicit_iv, ivpad, iv.size);
+ POSIX_CHECKED_MEMCPY(implicit_iv, ivpad, iv.size);
}
/* Subtract the padding length */
- gt_check(en.size, 0);
+ POSIX_ENSURE_GT(en.size, 0);
uint32_t out = 0;
- GUARD(s2n_sub_overflow(payload_length, en.data[en.size - 1] + 1, &out));
+ POSIX_GUARD(s2n_sub_overflow(payload_length, en.data[en.size - 1] + 1, &out));
payload_length = out;
/* Update the MAC */
header[3] = (payload_length >> 8);
header[4] = payload_length & 0xff;
- GUARD(s2n_hmac_reset(mac));
- GUARD(s2n_hmac_update(mac, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
+ POSIX_GUARD(s2n_hmac_reset(mac));
+ POSIX_GUARD(s2n_hmac_update(mac, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
if (conn->actual_protocol_version == S2N_SSLv3) {
- GUARD(s2n_hmac_update(mac, header, 1));
- GUARD(s2n_hmac_update(mac, header + 3, 2));
+ POSIX_GUARD(s2n_hmac_update(mac, header, 1));
+ POSIX_GUARD(s2n_hmac_update(mac, header + 3, 2));
} else {
- GUARD(s2n_hmac_update(mac, header, S2N_TLS_RECORD_HEADER_LENGTH));
+ POSIX_GUARD(s2n_hmac_update(mac, header, S2N_TLS_RECORD_HEADER_LENGTH));
}
struct s2n_blob seq = {.data = sequence_number,.size = S2N_TLS_SEQUENCE_NUM_LEN };
- GUARD(s2n_increment_sequence_number(&seq));
+ POSIX_GUARD(s2n_increment_sequence_number(&seq));
- /* Padding */
+ /* Padding. This finalizes the provided HMAC. */
if (s2n_verify_cbc(conn, mac, &en) < 0) {
- GUARD(s2n_stuffer_wipe(&conn->in));
- S2N_ERROR(S2N_ERR_BAD_MESSAGE);
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
+ POSIX_BAIL(S2N_ERR_BAD_MESSAGE);
}
/* O.k., we've successfully read and decrypted the record, now we need to align the stuffer
* for reading the plaintext data.
*/
- GUARD(s2n_stuffer_reread(&conn->in));
- GUARD(s2n_stuffer_reread(&conn->header_in));
+ POSIX_GUARD(s2n_stuffer_reread(&conn->in));
+ POSIX_GUARD(s2n_stuffer_reread(&conn->header_in));
/* Skip the IV, if any */
if (conn->actual_protocol_version > S2N_TLS10) {
- GUARD(s2n_stuffer_skip_read(&conn->in, cipher_suite->record_alg->cipher->io.cbc.record_iv_size));
+ POSIX_GUARD(s2n_stuffer_skip_read(&conn->in, cipher_suite->record_alg->cipher->io.cbc.record_iv_size));
}
/* Truncate and wipe the MAC and any padding */
- GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length));
+ POSIX_GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length));
conn->in_status = PLAINTEXT;
return 0;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_read_composite.c b/contrib/restricted/aws/s2n/tls/s2n_record_read_composite.c
index 3d39bdd8c7..62b082f576 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_record_read_composite.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_record_read_composite.c
@@ -45,16 +45,16 @@ int s2n_record_parse_composite(
/* Add the header to the HMAC */
uint8_t *header = s2n_stuffer_raw_read(&conn->header_in, S2N_TLS_RECORD_HEADER_LENGTH);
- notnull_check(header);
+ POSIX_ENSURE_REF(header);
struct s2n_blob en = {.size = encrypted_length,.data = s2n_stuffer_raw_read(&conn->in, encrypted_length) };
- notnull_check(en.data);
+ POSIX_ENSURE_REF(en.data);
uint16_t payload_length = encrypted_length;
uint8_t mac_digest_size;
- GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size));
+ POSIX_GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size));
- gte_check(payload_length, mac_digest_size);
+ POSIX_ENSURE_GTE(payload_length, mac_digest_size);
payload_length -= mac_digest_size;
/* Compute non-payload parts of the MAC(seq num, type, proto vers, fragment length) for composite ciphers.
@@ -63,51 +63,51 @@ int s2n_record_parse_composite(
/* In the decrypt case, this outputs the MAC digest length:
* https://github.com/openssl/openssl/blob/master/crypto/evp/e_aes_cbc_hmac_sha1.c#L842 */
int mac_size = 0;
- GUARD(cipher_suite->record_alg->cipher->io.comp.initial_hmac(session_key, sequence_number, content_type, conn->actual_protocol_version, payload_length, &mac_size));
+ POSIX_GUARD(cipher_suite->record_alg->cipher->io.comp.initial_hmac(session_key, sequence_number, content_type, conn->actual_protocol_version, payload_length, &mac_size));
- gte_check(payload_length, mac_size);
+ POSIX_ENSURE_GTE(payload_length, mac_size);
payload_length -= mac_size;
/* Adjust payload_length for explicit IV */
if (conn->actual_protocol_version > S2N_TLS10) {
uint32_t out = 0;
- GUARD(s2n_sub_overflow(payload_length, cipher_suite->record_alg->cipher->io.comp.record_iv_size, &out));
+ POSIX_GUARD(s2n_sub_overflow(payload_length, cipher_suite->record_alg->cipher->io.comp.record_iv_size, &out));
payload_length = out;
}
/* Decrypt stuff! */
- ne_check(en.size, 0);
- eq_check(en.size % iv.size, 0);
+ POSIX_ENSURE_NE(en.size, 0);
+ POSIX_ENSURE_EQ(en.size % iv.size, 0);
/* Copy the last encrypted block to be the next IV */
- memcpy_check(ivpad, en.data + en.size - iv.size, iv.size);
+ POSIX_CHECKED_MEMCPY(ivpad, en.data + en.size - iv.size, iv.size);
/* This will: Skip the explicit IV(if applicable), decrypt the payload, verify the MAC and padding. */
- GUARD((cipher_suite->record_alg->cipher->io.comp.decrypt(session_key, &iv, &en, &en)));
+ POSIX_GUARD((cipher_suite->record_alg->cipher->io.comp.decrypt(session_key, &iv, &en, &en)));
- memcpy_check(implicit_iv, ivpad, iv.size);
+ POSIX_CHECKED_MEMCPY(implicit_iv, ivpad, iv.size);
/* Subtract the padding length */
- gt_check(en.size, 0);
+ POSIX_ENSURE_GT(en.size, 0);
uint32_t out = 0;
- GUARD(s2n_sub_overflow(payload_length, en.data[en.size - 1] + 1, &out));
+ POSIX_GUARD(s2n_sub_overflow(payload_length, en.data[en.size - 1] + 1, &out));
payload_length = out;
struct s2n_blob seq = {.data = sequence_number,.size = S2N_TLS_SEQUENCE_NUM_LEN };
- GUARD(s2n_increment_sequence_number(&seq));
+ POSIX_GUARD(s2n_increment_sequence_number(&seq));
/* O.k., we've successfully read and decrypted the record, now we need to align the stuffer
* for reading the plaintext data.
*/
- GUARD(s2n_stuffer_reread(&conn->in));
- GUARD(s2n_stuffer_reread(&conn->header_in));
+ POSIX_GUARD(s2n_stuffer_reread(&conn->in));
+ POSIX_GUARD(s2n_stuffer_reread(&conn->header_in));
/* Skip the IV, if any */
if (conn->actual_protocol_version > S2N_TLS10) {
- GUARD(s2n_stuffer_skip_read(&conn->in, cipher_suite->record_alg->cipher->io.comp.record_iv_size));
+ POSIX_GUARD(s2n_stuffer_skip_read(&conn->in, cipher_suite->record_alg->cipher->io.comp.record_iv_size));
}
/* Truncate and wipe the MAC and any padding */
- GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length));
+ POSIX_GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length));
conn->in_status = PLAINTEXT;
return 0;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_read_stream.c b/contrib/restricted/aws/s2n/tls/s2n_record_read_stream.c
index dc6d6cb93e..8145d74d6a 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_record_read_stream.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_record_read_stream.c
@@ -41,57 +41,57 @@ int s2n_record_parse_stream(
{
/* Add the header to the HMAC */
uint8_t *header = s2n_stuffer_raw_read(&conn->header_in, S2N_TLS_RECORD_HEADER_LENGTH);
- notnull_check(header);
+ POSIX_ENSURE_REF(header);
struct s2n_blob en = {.size = encrypted_length,.data = s2n_stuffer_raw_read(&conn->in, encrypted_length) };
- notnull_check(en.data);
+ POSIX_ENSURE_REF(en.data);
uint16_t payload_length = encrypted_length;
uint8_t mac_digest_size;
- GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size));
+ POSIX_GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size));
- gte_check(payload_length, mac_digest_size);
+ POSIX_ENSURE_GTE(payload_length, mac_digest_size);
payload_length -= mac_digest_size;
/* Decrypt stuff! */
- GUARD(cipher_suite->record_alg->cipher->io.stream.decrypt(session_key, &en, &en));
+ POSIX_GUARD(cipher_suite->record_alg->cipher->io.stream.decrypt(session_key, &en, &en));
/* Update the MAC */
header[3] = (payload_length >> 8);
header[4] = payload_length & 0xff;
- GUARD(s2n_hmac_reset(mac));
- GUARD(s2n_hmac_update(mac, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
+ POSIX_GUARD(s2n_hmac_reset(mac));
+ POSIX_GUARD(s2n_hmac_update(mac, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
if (conn->actual_protocol_version == S2N_SSLv3) {
- GUARD(s2n_hmac_update(mac, header, 1));
- GUARD(s2n_hmac_update(mac, header + 3, 2));
+ POSIX_GUARD(s2n_hmac_update(mac, header, 1));
+ POSIX_GUARD(s2n_hmac_update(mac, header + 3, 2));
} else {
- GUARD(s2n_hmac_update(mac, header, S2N_TLS_RECORD_HEADER_LENGTH));
+ POSIX_GUARD(s2n_hmac_update(mac, header, S2N_TLS_RECORD_HEADER_LENGTH));
}
struct s2n_blob seq = {.data = sequence_number,.size = S2N_TLS_SEQUENCE_NUM_LEN };
- GUARD(s2n_increment_sequence_number(&seq));
+ POSIX_GUARD(s2n_increment_sequence_number(&seq));
/* MAC check for streaming ciphers - no padding */
- GUARD(s2n_hmac_update(mac, en.data, payload_length));
+ POSIX_GUARD(s2n_hmac_update(mac, en.data, payload_length));
uint8_t check_digest[S2N_MAX_DIGEST_LEN];
- lte_check(mac_digest_size, sizeof(check_digest));
- GUARD(s2n_hmac_digest(mac, check_digest, mac_digest_size));
+ POSIX_ENSURE_LTE(mac_digest_size, sizeof(check_digest));
+ POSIX_GUARD(s2n_hmac_digest(mac, check_digest, mac_digest_size));
if (s2n_hmac_digest_verify(en.data + payload_length, check_digest, mac_digest_size) < 0) {
- GUARD(s2n_stuffer_wipe(&conn->in));
- S2N_ERROR(S2N_ERR_BAD_MESSAGE);
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
+ POSIX_BAIL(S2N_ERR_BAD_MESSAGE);
}
/* O.k., we've successfully read and decrypted the record, now we need to align the stuffer
* for reading the plaintext data.
*/
- GUARD(s2n_stuffer_reread(&conn->in));
- GUARD(s2n_stuffer_reread(&conn->header_in));
+ POSIX_GUARD(s2n_stuffer_reread(&conn->in));
+ POSIX_GUARD(s2n_stuffer_reread(&conn->header_in));
/* Truncate and wipe the MAC and any padding */
- GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length));
+ POSIX_GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length));
conn->in_status = PLAINTEXT;
return 0;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_write.c b/contrib/restricted/aws/s2n/tls/s2n_record_write.c
index df28a9d58e..14cda738ff 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_record_write.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_record_write.c
@@ -38,8 +38,8 @@ extern uint8_t s2n_unknown_protocol_version;
/* How much overhead does the IV, MAC, TAG and padding bytes introduce ? */
static S2N_RESULT s2n_tls_record_overhead(struct s2n_connection *conn, uint16_t *out)
{
- ENSURE_REF(conn);
- ENSURE_MUT(out);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_MUT(out);
struct s2n_crypto_parameters *active = conn->server;
if (conn->mode == S2N_CLIENT) {
@@ -47,7 +47,7 @@ static S2N_RESULT s2n_tls_record_overhead(struct s2n_connection *conn, uint16_t
}
uint8_t extra;
- GUARD_AS_RESULT(s2n_hmac_digest_size(active->cipher_suite->record_alg->hmac_alg, &extra));
+ RESULT_GUARD_POSIX(s2n_hmac_digest_size(active->cipher_suite->record_alg->hmac_alg, &extra));
if (active->cipher_suite->record_alg->cipher->type == S2N_CBC) {
/* Subtract one for the padding length byte */
@@ -73,25 +73,41 @@ static S2N_RESULT s2n_tls_record_overhead(struct s2n_connection *conn, uint16_t
*/
S2N_RESULT s2n_record_max_write_payload_size(struct s2n_connection *conn, uint16_t *max_fragment_size)
{
- ENSURE_REF(conn);
- ENSURE_MUT(max_fragment_size);
- ENSURE(conn->max_outgoing_fragment_length > 0, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_MUT(max_fragment_size);
+ RESULT_ENSURE(conn->max_outgoing_fragment_length > 0, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
*max_fragment_size = MIN(conn->max_outgoing_fragment_length, S2N_TLS_MAXIMUM_FRAGMENT_LENGTH);
return S2N_RESULT_OK;
}
+S2N_RESULT s2n_record_max_write_size(struct s2n_connection *conn, uint16_t max_fragment_size, uint16_t *max_record_size)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_MUT(max_record_size);
+
+ if(!IS_NEGOTIATED(conn)) {
+ *max_record_size = S2N_TLS_MAX_RECORD_LEN_FOR(max_fragment_size);
+ } else if (conn->actual_protocol_version < S2N_TLS13) {
+ *max_record_size = S2N_TLS12_MAX_RECORD_LEN_FOR(max_fragment_size);
+ } else {
+ *max_record_size = S2N_TLS13_MAX_RECORD_LEN_FOR(max_fragment_size);
+ }
+ return S2N_RESULT_OK;
+}
+
/* Find the largest size that will fit within an ethernet frame for a "small" payload */
S2N_RESULT s2n_record_min_write_payload_size(struct s2n_connection *conn, uint16_t *payload_size)
{
- ENSURE_REF(conn);
- ENSURE_MUT(payload_size);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_MUT(payload_size);
+
/* remove ethernet, TCP/IP and TLS header overheads */
const uint16_t min_outgoing_fragment_length = ETH_MTU - (conn->ipv6 ? IP_V6_HEADER_LENGTH : IP_V4_HEADER_LENGTH)
- TCP_HEADER_LENGTH - TCP_OPTIONS_LENGTH - S2N_TLS_RECORD_HEADER_LENGTH;
- ENSURE(min_outgoing_fragment_length <= S2N_TLS_MAXIMUM_FRAGMENT_LENGTH, S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE);
+ RESULT_ENSURE(min_outgoing_fragment_length <= S2N_TLS_MAXIMUM_FRAGMENT_LENGTH, S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE);
uint16_t size = min_outgoing_fragment_length;
const struct s2n_crypto_parameters *active = conn->mode == S2N_CLIENT ? conn->client : conn->server;
@@ -107,14 +123,20 @@ S2N_RESULT s2n_record_min_write_payload_size(struct s2n_connection *conn, uint16
size -= 1;
}
+ /* If TLS1.3, remove content type */
+ if (conn->actual_protocol_version >= S2N_TLS13) {
+ RESULT_ENSURE(size > S2N_TLS_CONTENT_TYPE_LENGTH, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
+ size -= S2N_TLS_CONTENT_TYPE_LENGTH;
+ }
+
/* subtract overheads of a TLS record */
uint16_t overhead = 0;
- GUARD_RESULT(s2n_tls_record_overhead(conn, &overhead));
- ENSURE(size > overhead, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
+ RESULT_GUARD(s2n_tls_record_overhead(conn, &overhead));
+ RESULT_ENSURE(size > overhead, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
size -= overhead;
- ENSURE(size > 0, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
- ENSURE(size <= ETH_MTU, S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE);
+ RESULT_ENSURE(size > 0, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL);
+ RESULT_ENSURE(size <= ETH_MTU, S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE);
*payload_size = size;
@@ -124,7 +146,8 @@ S2N_RESULT s2n_record_min_write_payload_size(struct s2n_connection *conn, uint16
int s2n_record_write_protocol_version(struct s2n_connection *conn)
{
uint8_t record_protocol_version = conn->actual_protocol_version;
- if (conn->server_protocol_version == s2n_unknown_protocol_version) {
+ if (conn->server_protocol_version == s2n_unknown_protocol_version
+ && conn->early_data_state != S2N_EARLY_DATA_REQUESTED) {
/* Some legacy TLS implementations can't handle records with protocol version higher than TLS1.0.
* To provide maximum compatibility, send record version as TLS1.0 if server protocol version isn't
* established yet, which happens only during ClientHello message. Note, this has no effect on
@@ -141,7 +164,7 @@ int s2n_record_write_protocol_version(struct s2n_connection *conn)
protocol_version[0] = record_protocol_version / 10;
protocol_version[1] = record_protocol_version % 10;
- GUARD(s2n_stuffer_write_bytes(&conn->out, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&conn->out, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
return 0;
}
@@ -155,34 +178,34 @@ static inline int s2n_record_encrypt(
struct s2n_blob *en,
uint8_t *implicit_iv, uint16_t block_size)
{
- notnull_check(en->data);
+ POSIX_ENSURE_REF(en->data);
switch (cipher_suite->record_alg->cipher->type) {
case S2N_STREAM:
- GUARD(cipher_suite->record_alg->cipher->io.stream.encrypt(session_key, en, en));
+ POSIX_GUARD(cipher_suite->record_alg->cipher->io.stream.encrypt(session_key, en, en));
break;
case S2N_CBC:
- GUARD(cipher_suite->record_alg->cipher->io.cbc.encrypt(session_key, iv, en, en));
+ POSIX_GUARD(cipher_suite->record_alg->cipher->io.cbc.encrypt(session_key, iv, en, en));
/* Copy the last encrypted block to be the next IV */
if (conn->actual_protocol_version < S2N_TLS11) {
- gte_check(en->size, block_size);
- memcpy_check(implicit_iv, en->data + en->size - block_size, block_size);
+ POSIX_ENSURE_GTE(en->size, block_size);
+ POSIX_CHECKED_MEMCPY(implicit_iv, en->data + en->size - block_size, block_size);
}
break;
case S2N_AEAD:
- GUARD(cipher_suite->record_alg->cipher->io.aead.encrypt(session_key, iv, aad, en, en));
+ POSIX_GUARD(cipher_suite->record_alg->cipher->io.aead.encrypt(session_key, iv, aad, en, en));
break;
case S2N_COMPOSITE:
/* This will: compute mac, append padding, append padding length, and encrypt */
- GUARD(cipher_suite->record_alg->cipher->io.comp.encrypt(session_key, iv, en, en));
+ POSIX_GUARD(cipher_suite->record_alg->cipher->io.comp.encrypt(session_key, iv, en, en));
/* Copy the last encrypted block to be the next IV */
- gte_check(en->size, block_size);
- memcpy_check(implicit_iv, en->data + en->size - block_size, block_size);
+ POSIX_ENSURE_GTE(en->size, block_size);
+ POSIX_CHECKED_MEMCPY(implicit_iv, en->data + en->size - block_size, block_size);
break;
default:
- S2N_ERROR(S2N_ERR_CIPHER_TYPE);
+ POSIX_BAIL(S2N_ERR_CIPHER_TYPE);
break;
}
@@ -218,23 +241,29 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
implicit_iv = conn->client->client_implicit_iv;
}
+ /* The NULL stream cipher MUST NEVER be used for ApplicationData.
+ * Writing ApplicationData unencrypted defeats the purpose of TLS. */
+ if (cipher_suite->record_alg->cipher == &s2n_null_cipher) {
+ POSIX_ENSURE(content_type != TLS_APPLICATION_DATA, S2N_ERR_ENCRYPT);
+ }
+
const int is_tls13_record = cipher_suite->record_alg->flags & S2N_TLS13_RECORD_AEAD_NONCE;
s2n_stack_blob(aad, is_tls13_record ? S2N_TLS13_AAD_LEN : S2N_TLS_MAX_AAD_LEN, S2N_TLS_MAX_AAD_LEN);
S2N_ERROR_IF(s2n_stuffer_data_available(&conn->out), S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING);
uint8_t mac_digest_size;
- GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size));
+ POSIX_GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size));
/* Before we do anything, we need to figure out what the length of the
* fragment is going to be.
*/
uint16_t max_write_payload_size = 0;
- GUARD_AS_POSIX(s2n_record_max_write_payload_size(conn, &max_write_payload_size));
+ POSIX_GUARD_RESULT(s2n_record_max_write_payload_size(conn, &max_write_payload_size));
const uint16_t data_bytes_to_take = MIN(to_write, max_write_payload_size);
uint16_t extra = 0;
- GUARD_AS_POSIX(s2n_tls_record_overhead(conn, &extra));
+ POSIX_GUARD_RESULT(s2n_tls_record_overhead(conn, &extra));
/* If we have padding to worry about, figure that out too */
if (cipher_suite->record_alg->cipher->type == S2N_CBC) {
@@ -247,25 +276,40 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
}
/* Start the MAC with the sequence number */
- GUARD(s2n_hmac_update(mac, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
-
- GUARD(s2n_stuffer_resize_if_empty(&conn->out, S2N_LARGE_RECORD_LENGTH));
+ POSIX_GUARD(s2n_hmac_update(mac, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
+
+ if (s2n_stuffer_is_freed(&conn->out)) {
+ /* If the output buffer has not been allocated yet, allocate enough memory to hold
+ * a record with the local maximum fragment length. Because this only occurs if the
+ * output buffer has not been allocated, it does NOT resize existing buffers.
+ *
+ * The maximum fragment length is:
+ * 1) The local default configured for new connections
+ * 2) The local value set by the user via s2n_connection_prefer_throughput()
+ * or s2n_connection_prefer_low_latency()
+ * 3) On the server, the minimum of the local value and the value negotiated with the
+ * client via the max_fragment_length extension
+ */
+ uint16_t max_wire_record_size = 0;
+ POSIX_GUARD_RESULT(s2n_record_max_write_size(conn, max_write_payload_size, &max_wire_record_size));
+ POSIX_GUARD(s2n_stuffer_growable_alloc(&conn->out, max_wire_record_size));
+ }
/* Now that we know the length, start writing the record */
- GUARD(s2n_stuffer_write_uint8(&conn->out, is_tls13_record ?
+ POSIX_GUARD(s2n_stuffer_write_uint8(&conn->out, is_tls13_record ?
/* tls 1.3 opaque type */ TLS_APPLICATION_DATA :
/* actual content_type */ content_type ));
- GUARD(s2n_record_write_protocol_version(conn));
+ POSIX_GUARD(s2n_record_write_protocol_version(conn));
/* First write a header that has the payload length, this is for the MAC */
- GUARD(s2n_stuffer_write_uint16(&conn->out, data_bytes_to_take));
+ POSIX_GUARD(s2n_stuffer_write_uint16(&conn->out, data_bytes_to_take));
if (conn->actual_protocol_version > S2N_SSLv3) {
- GUARD(s2n_hmac_update(mac, conn->out.blob.data, S2N_TLS_RECORD_HEADER_LENGTH));
+ POSIX_GUARD(s2n_hmac_update(mac, conn->out.blob.data, S2N_TLS_RECORD_HEADER_LENGTH));
} else {
/* SSLv3 doesn't include the protocol version in the MAC */
- GUARD(s2n_hmac_update(mac, conn->out.blob.data, 1));
- GUARD(s2n_hmac_update(mac, conn->out.blob.data + 3, 2));
+ POSIX_GUARD(s2n_hmac_update(mac, conn->out.blob.data, 1));
+ POSIX_GUARD(s2n_hmac_update(mac, conn->out.blob.data + 3, 2));
}
/* Compute non-payload parts of the MAC(seq num, type, proto vers, fragment length) for composite ciphers.
@@ -280,14 +324,14 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
/* Outputs number of extra bytes required for MAC and padding */
int pad_and_mac_len;
- GUARD(cipher_suite->record_alg->cipher->io.comp.initial_hmac(session_key, sequence_number, content_type, conn->actual_protocol_version,
+ POSIX_GUARD(cipher_suite->record_alg->cipher->io.comp.initial_hmac(session_key, sequence_number, content_type, conn->actual_protocol_version,
payload_and_eiv_len, &pad_and_mac_len));
extra += pad_and_mac_len;
}
/* TLS 1.3 protected record occupies one extra byte for content type */
if (is_tls13_record) {
- extra += TLS13_CONTENT_TYPE_LENGTH;
+ extra += S2N_TLS_CONTENT_TYPE_LENGTH;
}
/* Rewrite the length to be the actual fragment length */
@@ -295,48 +339,45 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
/* ensure actual_fragment_length + S2N_TLS_RECORD_HEADER_LENGTH <= max record length */
const uint16_t max_record_length = is_tls13_record ? S2N_TLS13_MAXIMUM_RECORD_LENGTH : S2N_TLS_MAXIMUM_RECORD_LENGTH;
S2N_ERROR_IF(actual_fragment_length + S2N_TLS_RECORD_HEADER_LENGTH > max_record_length, S2N_ERR_RECORD_LENGTH_TOO_LARGE);
- GUARD(s2n_stuffer_wipe_n(&conn->out, 2));
- GUARD(s2n_stuffer_write_uint16(&conn->out, actual_fragment_length));
+ POSIX_GUARD(s2n_stuffer_wipe_n(&conn->out, 2));
+ POSIX_GUARD(s2n_stuffer_write_uint16(&conn->out, actual_fragment_length));
/* If we're AEAD, write the sequence number as an IV, and generate the AAD */
if (cipher_suite->record_alg->cipher->type == S2N_AEAD) {
struct s2n_stuffer iv_stuffer = {0};
s2n_blob_init(&iv, aad_iv, sizeof(aad_iv));
- GUARD(s2n_stuffer_init(&iv_stuffer, &iv));
+ POSIX_GUARD(s2n_stuffer_init(&iv_stuffer, &iv));
if (cipher_suite->record_alg->flags & S2N_TLS12_AES_GCM_AEAD_NONCE) {
/* Partially explicit nonce. See RFC 5288 Section 3 */
- GUARD(s2n_stuffer_write_bytes(&conn->out, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
- GUARD(s2n_stuffer_write_bytes(&iv_stuffer, implicit_iv, cipher_suite->record_alg->cipher->io.aead.fixed_iv_size));
- GUARD(s2n_stuffer_write_bytes(&iv_stuffer, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&conn->out, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, implicit_iv, cipher_suite->record_alg->cipher->io.aead.fixed_iv_size));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
} else if (cipher_suite->record_alg->flags & S2N_TLS12_CHACHA_POLY_AEAD_NONCE || is_tls13_record) {
/* Fully implicit nonce. See RFC7905 Section 2 */
uint8_t four_zeroes[4] = { 0 };
- GUARD(s2n_stuffer_write_bytes(&iv_stuffer, four_zeroes, 4));
- GUARD(s2n_stuffer_write_bytes(&iv_stuffer, sequence_number, S2N_TLS_SEQUENCE_NUM_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&iv_stuffer, four_zeroes, 4));
+ POSIX_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++) {
aad_iv[i] = aad_iv[i] ^ implicit_iv[i];
}
} else {
- S2N_ERROR(S2N_ERR_INVALID_NONCE_TYPE);
+ POSIX_BAIL(S2N_ERR_INVALID_NONCE_TYPE);
}
/* Set the IV size to the amount of data written */
iv.size = s2n_stuffer_data_available(&iv_stuffer);
-
- struct s2n_stuffer ad_stuffer = {0};
- GUARD(s2n_stuffer_init(&ad_stuffer, &aad));
if (is_tls13_record) {
- GUARD_AS_POSIX(s2n_tls13_aead_aad_init(data_bytes_to_take + TLS13_CONTENT_TYPE_LENGTH, cipher_suite->record_alg->cipher->io.aead.tag_size, &ad_stuffer));
+ POSIX_GUARD_RESULT(s2n_tls13_aead_aad_init(data_bytes_to_take + S2N_TLS_CONTENT_TYPE_LENGTH, cipher_suite->record_alg->cipher->io.aead.tag_size, &aad));
} else {
- GUARD_AS_POSIX(s2n_aead_aad_init(conn, sequence_number, content_type, data_bytes_to_take, &ad_stuffer));
+ POSIX_GUARD_RESULT(s2n_aead_aad_init(conn, sequence_number, content_type, data_bytes_to_take, &aad));
}
} else if (cipher_suite->record_alg->cipher->type == S2N_CBC || cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) {
s2n_blob_init(&iv, implicit_iv, block_size);
/* For TLS1.1/1.2; write the IV with random data */
if (conn->actual_protocol_version > S2N_TLS10) {
- GUARD_AS_POSIX(s2n_get_public_random_data(&iv));
+ POSIX_GUARD_RESULT(s2n_get_public_random_data(&iv));
if (cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) {
/* Write a separate random block to the record. This will be used along with the previously generated
* iv blob to generate the final explicit_iv for this record.
@@ -353,37 +394,37 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
*/
struct s2n_blob explicit_iv_placeholder;
uint8_t zero_block[S2N_TLS_MAX_IV_LEN] = { 0 };
- GUARD(s2n_blob_init(&explicit_iv_placeholder, zero_block, block_size));
- GUARD_AS_POSIX(s2n_get_public_random_data(&explicit_iv_placeholder));
- GUARD(s2n_stuffer_write(&conn->out, &explicit_iv_placeholder));
+ POSIX_GUARD(s2n_blob_init(&explicit_iv_placeholder, zero_block, block_size));
+ POSIX_GUARD_RESULT(s2n_get_public_random_data(&explicit_iv_placeholder));
+ POSIX_GUARD(s2n_stuffer_write(&conn->out, &explicit_iv_placeholder));
} else {
/* We can write the explicit IV directly to the record for non composite CBC because
* s2n starts AES *after* the explicit IV.
*/
- GUARD(s2n_stuffer_write(&conn->out, &iv));
+ POSIX_GUARD(s2n_stuffer_write(&conn->out, &iv));
}
}
}
/* We are done with this sequence number, so we can increment it */
struct s2n_blob seq = {.data = sequence_number,.size = S2N_TLS_SEQUENCE_NUM_LEN };
- GUARD(s2n_increment_sequence_number(&seq));
+ POSIX_GUARD(s2n_increment_sequence_number(&seq));
/* Write the plaintext data */
- GUARD(s2n_stuffer_writev_bytes(&conn->out, in, in_count, offs, data_bytes_to_take));
+ POSIX_GUARD(s2n_stuffer_writev_bytes(&conn->out, in, in_count, offs, data_bytes_to_take));
void *orig_write_ptr = conn->out.blob.data + conn->out.write_cursor - data_bytes_to_take;
- GUARD(s2n_hmac_update(mac, orig_write_ptr, data_bytes_to_take));
+ POSIX_GUARD(s2n_hmac_update(mac, orig_write_ptr, data_bytes_to_take));
/* Write the digest */
uint8_t *digest = s2n_stuffer_raw_write(&conn->out, mac_digest_size);
- notnull_check(digest);
+ POSIX_ENSURE_REF(digest);
- GUARD(s2n_hmac_digest(mac, digest, mac_digest_size));
- GUARD(s2n_hmac_reset(mac));
+ POSIX_GUARD(s2n_hmac_digest(mac, digest, mac_digest_size));
+ POSIX_GUARD(s2n_hmac_reset(mac));
/* Write content type for TLS 1.3 record (RFC 8446 Section 5.2) */
if (is_tls13_record) {
- GUARD(s2n_stuffer_write_uint8(&conn->out, content_type));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&conn->out, content_type));
}
if (cipher_suite->record_alg->cipher->type == S2N_CBC) {
@@ -391,30 +432,30 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
* include an extra padding length byte, also with the value 'p'.
*/
for (int i = 0; i <= padding; i++) {
- GUARD(s2n_stuffer_write_uint8(&conn->out, padding));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&conn->out, padding));
}
}
/* Rewind to rewrite/encrypt the packet */
- GUARD(s2n_stuffer_rewrite(&conn->out));
+ POSIX_GUARD(s2n_stuffer_rewrite(&conn->out));
/* Skip the header */
- GUARD(s2n_stuffer_skip_write(&conn->out, S2N_TLS_RECORD_HEADER_LENGTH));
+ POSIX_GUARD(s2n_stuffer_skip_write(&conn->out, S2N_TLS_RECORD_HEADER_LENGTH));
uint16_t encrypted_length = data_bytes_to_take + mac_digest_size;
switch (cipher_suite->record_alg->cipher->type) {
case S2N_AEAD:
- GUARD(s2n_stuffer_skip_write(&conn->out, cipher_suite->record_alg->cipher->io.aead.record_iv_size));
+ POSIX_GUARD(s2n_stuffer_skip_write(&conn->out, cipher_suite->record_alg->cipher->io.aead.record_iv_size));
encrypted_length += cipher_suite->record_alg->cipher->io.aead.tag_size;
if (is_tls13_record) {
/* one extra byte for content type */
- encrypted_length += TLS13_CONTENT_TYPE_LENGTH;
+ encrypted_length += S2N_TLS_CONTENT_TYPE_LENGTH;
}
break;
case S2N_CBC:
if (conn->actual_protocol_version > S2N_TLS10) {
/* Leave the IV alone and unencrypted */
- GUARD(s2n_stuffer_skip_write(&conn->out, iv.size));
+ POSIX_GUARD(s2n_stuffer_skip_write(&conn->out, iv.size));
}
/* Encrypt the padding and the padding length byte too */
encrypted_length += padding + 1;
@@ -434,7 +475,7 @@ int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const s
/* Do the encryption */
struct s2n_blob en = { .size = encrypted_length, .data = s2n_stuffer_raw_write(&conn->out, encrypted_length) };
- GUARD(s2n_record_encrypt(conn, cipher_suite, session_key, &iv, &aad, &en, implicit_iv, block_size));
+ POSIX_GUARD(s2n_record_encrypt(conn, cipher_suite, session_key, &iv, &aad, &en, implicit_iv, block_size));
if (conn->actual_protocol_version == S2N_TLS13 && content_type == TLS_CHANGE_CIPHER_SPEC) {
conn->client = current_client_crypto;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_recv.c b/contrib/restricted/aws/s2n/tls/s2n_recv.c
index 8aa34e6d06..3d0907573f 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_recv.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_recv.c
@@ -20,7 +20,7 @@
#include <unistd.h>
#include <errno.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include "error/s2n_errno.h"
@@ -47,12 +47,12 @@ S2N_RESULT s2n_read_in_bytes(struct s2n_connection *conn, struct s2n_stuffer *ou
int r = s2n_connection_recv_stuffer(output, conn, remaining);
if (r == 0) {
conn->closed = 1;
- BAIL(S2N_ERR_CLOSED);
+ RESULT_BAIL(S2N_ERR_CLOSED);
} else if (r < 0) {
if (errno == EWOULDBLOCK || errno == EAGAIN) {
- BAIL(S2N_ERR_IO_BLOCKED);
+ RESULT_BAIL(S2N_ERR_IO_BLOCKED);
}
- BAIL(S2N_ERR_IO);
+ RESULT_BAIL(S2N_ERR_IO);
}
conn->wire_bytes_in += r;
}
@@ -70,10 +70,10 @@ int s2n_read_full_record(struct s2n_connection *conn, uint8_t * record_type, int
*record_type = TLS_APPLICATION_DATA;
return S2N_SUCCESS;
}
- GUARD(s2n_stuffer_resize_if_empty(&conn->in, S2N_LARGE_FRAGMENT_LENGTH));
+ POSIX_GUARD(s2n_stuffer_resize_if_empty(&conn->in, S2N_LARGE_FRAGMENT_LENGTH));
/* Read the record until we at least have a header */
- GUARD_AS_POSIX(s2n_read_in_bytes(conn, &conn->header_in, S2N_TLS_RECORD_HEADER_LENGTH));
+ POSIX_GUARD_RESULT(s2n_read_in_bytes(conn, &conn->header_in, S2N_TLS_RECORD_HEADER_LENGTH));
uint16_t fragment_length;
@@ -82,28 +82,25 @@ int s2n_read_full_record(struct s2n_connection *conn, uint8_t * record_type, int
conn->header_in.blob.data[0] &= 0x7f;
*isSSLv2 = 1;
- if (s2n_sslv2_record_header_parse(conn, record_type, &conn->client_protocol_version, &fragment_length) < 0) {
- GUARD(s2n_connection_kill(conn));
- S2N_ERROR_PRESERVE_ERRNO();
- }
+ WITH_ERROR_BLINDING(conn, POSIX_GUARD(
+ s2n_sslv2_record_header_parse(conn, record_type, &conn->client_protocol_version, &fragment_length)));
} else {
- if (s2n_record_header_parse(conn, record_type, &fragment_length) < 0) {
- GUARD(s2n_connection_kill(conn));
- S2N_ERROR_PRESERVE_ERRNO();
- }
+ WITH_ERROR_BLINDING(conn, POSIX_GUARD(
+ s2n_record_header_parse(conn, record_type, &fragment_length)));
}
/* Read enough to have the whole record */
- GUARD_AS_POSIX(s2n_read_in_bytes(conn, &conn->in, fragment_length));
+ POSIX_GUARD_RESULT(s2n_read_in_bytes(conn, &conn->in, fragment_length));
if (*isSSLv2) {
return 0;
}
/* Decrypt and parse the record */
- if (s2n_record_parse(conn) < 0) {
- GUARD(s2n_connection_kill(conn));
- S2N_ERROR_PRESERVE_ERRNO();
+ if (s2n_early_data_is_trial_decryption_allowed(conn, *record_type)) {
+ POSIX_ENSURE(s2n_record_parse(conn) >= S2N_SUCCESS, S2N_ERR_EARLY_DATA_TRIAL_DECRYPT);
+ } else {
+ WITH_ERROR_BLINDING(conn, POSIX_GUARD(s2n_record_parse(conn)));
}
/* In TLS 1.3, encrypted handshake records would appear to be of record type
@@ -111,7 +108,7 @@ int s2n_read_full_record(struct s2n_connection *conn, uint8_t * record_type, int
* is decrypted.
*/
if (conn->actual_protocol_version == S2N_TLS13 && *record_type == TLS_APPLICATION_DATA) {
- GUARD(s2n_tls13_parse_record_type(&conn->in, record_type));
+ POSIX_GUARD(s2n_tls13_parse_record_type(&conn->in, record_type));
}
return 0;
@@ -127,7 +124,8 @@ ssize_t s2n_recv_impl(struct s2n_connection * conn, void *buf, ssize_t size, s2n
}
*blocked = S2N_BLOCKED_ON_READ;
- S2N_ERROR_IF(conn->config->quic_enabled, S2N_ERR_UNSUPPORTED_WITH_QUIC);
+ POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_UNSUPPORTED_WITH_QUIC);
+ POSIX_GUARD_RESULT(s2n_early_data_validate_recv(conn));
while (size && !conn->closed) {
int isSSLv2 = 0;
@@ -163,22 +161,22 @@ ssize_t s2n_recv_impl(struct s2n_connection * conn, void *buf, ssize_t size, s2n
switch (record_type)
{
case TLS_ALERT:
- GUARD(s2n_process_alert_fragment(conn));
- GUARD(s2n_flush(conn, blocked));
+ POSIX_GUARD(s2n_process_alert_fragment(conn));
+ POSIX_GUARD(s2n_flush(conn, blocked));
break;
case TLS_HANDSHAKE:
- GUARD(s2n_post_handshake_recv(conn));
+ WITH_ERROR_BLINDING(conn, POSIX_GUARD(s2n_post_handshake_recv(conn)));
break;
}
- GUARD(s2n_stuffer_wipe(&conn->header_in));
- GUARD(s2n_stuffer_wipe(&conn->in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->header_in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
conn->in_status = ENCRYPTED;
continue;
}
out.size = MIN(size, s2n_stuffer_data_available(&conn->in));
- GUARD(s2n_stuffer_erase_and_read(&conn->in, &out));
+ POSIX_GUARD(s2n_stuffer_erase_and_read(&conn->in, &out));
bytes_read += out.size;
out.data += out.size;
@@ -186,8 +184,8 @@ ssize_t s2n_recv_impl(struct s2n_connection * conn, void *buf, ssize_t size, s2n
/* Are we ready for more encrypted data? */
if (s2n_stuffer_data_available(&conn->in) == 0) {
- GUARD(s2n_stuffer_wipe(&conn->header_in));
- GUARD(s2n_stuffer_wipe(&conn->in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->header_in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
conn->in_status = ENCRYPTED;
}
@@ -201,12 +199,13 @@ ssize_t s2n_recv_impl(struct s2n_connection * conn, void *buf, ssize_t size, s2n
*blocked = S2N_NOT_BLOCKED;
}
+ POSIX_GUARD_RESULT(s2n_early_data_record_bytes(conn, bytes_read));
return bytes_read;
}
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);
+ POSIX_ENSURE(!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;
@@ -223,14 +222,14 @@ int s2n_recv_close_notify(struct s2n_connection *conn, s2n_blocked_status * bloc
int isSSLv2;
*blocked = S2N_BLOCKED_ON_READ;
- GUARD(s2n_read_full_record(conn, &record_type, &isSSLv2));
+ POSIX_GUARD(s2n_read_full_record(conn, &record_type, &isSSLv2));
S2N_ERROR_IF(isSSLv2, S2N_ERR_BAD_MESSAGE);
S2N_ERROR_IF(record_type != TLS_ALERT, S2N_ERR_SHUTDOWN_RECORD_TYPE);
/* Only succeeds for an incoming close_notify alert */
- GUARD(s2n_process_alert_fragment(conn));
+ POSIX_GUARD(s2n_process_alert_fragment(conn));
*blocked = S2N_NOT_BLOCKED;
return 0;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_resume.c b/contrib/restricted/aws/s2n/tls/s2n_resume.c
index f4571bf042..31ba8e97a0 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_resume.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_resume.c
@@ -13,8 +13,9 @@
* permissions and limitations under the License.
*/
#include <math.h>
+#include <sys/param.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include "error/s2n_errno.h"
#include "stuffer/s2n_stuffer.h"
@@ -33,128 +34,331 @@ int s2n_allowed_to_cache_connection(struct s2n_connection *conn)
{
/* We're unable to cache connections with a Client Cert since we currently don't serialize the Client Cert,
* which means that callers won't have access to the Client's Cert if the connection is resumed. */
- if (s2n_connection_is_client_auth_enabled(conn) > 0) {
+ if (s2n_connection_is_client_auth_enabled(conn)) {
return 0;
}
struct s2n_config *config = conn->config;
- notnull_check(config);
+ POSIX_ENSURE_REF(config);
return config->use_session_cache;
}
-static int s2n_serialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *to)
+static int s2n_tls12_serialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *to)
{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(to);
+
uint64_t now;
- S2N_ERROR_IF(s2n_stuffer_space_remaining(to) < S2N_STATE_SIZE_IN_BYTES, S2N_ERR_STUFFER_IS_FULL);
+ S2N_ERROR_IF(s2n_stuffer_space_remaining(to) < S2N_TLS12_STATE_SIZE_IN_BYTES, S2N_ERR_STUFFER_IS_FULL);
/* Get the time */
- GUARD(conn->config->wall_clock(conn->config->sys_clock_ctx, &now));
+ POSIX_GUARD(conn->config->wall_clock(conn->config->sys_clock_ctx, &now));
/* Write the entry */
- GUARD(s2n_stuffer_write_uint8(to, S2N_SERIALIZED_FORMAT_VERSION));
- GUARD(s2n_stuffer_write_uint8(to, conn->actual_protocol_version));
- GUARD(s2n_stuffer_write_bytes(to, conn->secure.cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
- GUARD(s2n_stuffer_write_uint64(to, now));
- GUARD(s2n_stuffer_write_bytes(to, conn->secure.master_secret, S2N_TLS_SECRET_LEN));
+ POSIX_GUARD(s2n_stuffer_write_uint8(to, S2N_SERIALIZED_FORMAT_TLS12_V3));
+ POSIX_GUARD(s2n_stuffer_write_uint8(to, conn->actual_protocol_version));
+ POSIX_GUARD(s2n_stuffer_write_bytes(to, conn->secure.cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
+ POSIX_GUARD(s2n_stuffer_write_uint64(to, now));
+ POSIX_GUARD(s2n_stuffer_write_bytes(to, conn->secrets.tls12.master_secret, S2N_TLS_SECRET_LEN));
+ POSIX_GUARD(s2n_stuffer_write_uint8(to, conn->ems_negotiated));
- return 0;
+ return S2N_SUCCESS;
}
-static int s2n_deserialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *from)
+static S2N_RESULT s2n_tls13_serialize_keying_material_expiration(struct s2n_connection *conn,
+ uint64_t now, struct s2n_stuffer *out)
{
- uint8_t format;
- uint8_t protocol_version;
- uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN];
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(out);
+
+ if (conn->mode != S2N_SERVER) {
+ return S2N_RESULT_OK;
+ }
+
+ uint64_t expiration_timestamp = now + (conn->server_keying_material_lifetime * (uint64_t) ONE_SEC_IN_NANOS);
+
+ struct s2n_psk *chosen_psk = conn->psk_params.chosen_psk;
+ if (chosen_psk && chosen_psk->type == S2N_PSK_TYPE_RESUMPTION) {
+ expiration_timestamp = MIN(chosen_psk->keying_material_expiration, expiration_timestamp);
+ }
- S2N_ERROR_IF(s2n_stuffer_data_available(from) < S2N_STATE_SIZE_IN_BYTES, S2N_ERR_STUFFER_OUT_OF_DATA);
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint64(out, expiration_timestamp));
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_tls13_serialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *out)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(out);
- GUARD(s2n_stuffer_read_uint8(from, &format));
- S2N_ERROR_IF(format != S2N_SERIALIZED_FORMAT_VERSION, S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
+ uint64_t current_time = 0;
+ struct s2n_ticket_fields *ticket_fields = &conn->tls13_ticket_fields;
- GUARD(s2n_stuffer_read_uint8(from, &protocol_version));
+ /* Get the time */
+ RESULT_GUARD_POSIX(conn->config->wall_clock(conn->config->sys_clock_ctx, &current_time));
+
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, S2N_SERIALIZED_FORMAT_TLS13_V1));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, conn->actual_protocol_version));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(out, conn->secure.cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint64(out, current_time));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint32(out, ticket_fields->ticket_age_add));
+ RESULT_ENSURE_LTE(ticket_fields->session_secret.size, UINT8_MAX);
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, ticket_fields->session_secret.size));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(out, ticket_fields->session_secret.data, ticket_fields->session_secret.size));
+ RESULT_GUARD(s2n_tls13_serialize_keying_material_expiration(conn, current_time, out));
+
+ uint32_t server_max_early_data = 0;
+ RESULT_GUARD(s2n_early_data_get_server_max_size(conn, &server_max_early_data));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint32(out, server_max_early_data));
+ if (server_max_early_data > 0) {
+ uint8_t application_protocol_len = strlen(conn->application_protocol);
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, application_protocol_len));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(out, (uint8_t *) conn->application_protocol, application_protocol_len));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint16(out, conn->server_early_data_context.size));
+ RESULT_GUARD_POSIX(s2n_stuffer_write(out, &conn->server_early_data_context));
+ }
+
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_serialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *out)
+{
+ if(conn->actual_protocol_version < S2N_TLS13) {
+ RESULT_GUARD_POSIX(s2n_tls12_serialize_resumption_state(conn, out));
+ } else {
+ RESULT_GUARD(s2n_tls13_serialize_resumption_state(conn, out));
+ }
+ return S2N_RESULT_OK;
+}
+
+static int s2n_tls12_deserialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *from)
+{
+ uint8_t protocol_version = 0;
+ uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN] = { 0 };
+
+ S2N_ERROR_IF(s2n_stuffer_data_available(from) < S2N_TLS12_STATE_SIZE_IN_BYTES - sizeof(uint8_t), S2N_ERR_STUFFER_OUT_OF_DATA);
+
+ POSIX_GUARD(s2n_stuffer_read_uint8(from, &protocol_version));
S2N_ERROR_IF(protocol_version != conn->actual_protocol_version, S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
- GUARD(s2n_stuffer_read_bytes(from, cipher_suite, S2N_TLS_CIPHER_SUITE_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(from, cipher_suite, S2N_TLS_CIPHER_SUITE_LEN));
S2N_ERROR_IF(memcmp(conn->secure.cipher_suite->iana_value, cipher_suite, S2N_TLS_CIPHER_SUITE_LEN), S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
uint64_t now;
- GUARD(conn->config->wall_clock(conn->config->sys_clock_ctx, &now));
+ POSIX_GUARD(conn->config->wall_clock(conn->config->sys_clock_ctx, &now));
uint64_t then;
- GUARD(s2n_stuffer_read_uint64(from, &then));
+ POSIX_GUARD(s2n_stuffer_read_uint64(from, &then));
S2N_ERROR_IF(then > now, S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
S2N_ERROR_IF(now - then > conn->config->session_state_lifetime_in_nanos, S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
- /* Last but not least, put the master secret in place */
- GUARD(s2n_stuffer_read_bytes(from, conn->secure.master_secret, S2N_TLS_SECRET_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(from, conn->secrets.tls12.master_secret, S2N_TLS_SECRET_LEN));
+
+ if (s2n_stuffer_data_available(from)) {
+ uint8_t ems_negotiated = 0;
+ POSIX_GUARD(s2n_stuffer_read_uint8(from, &ems_negotiated));
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc7627#section-5.3
+ *# o If the original session did not use the "extended_master_secret"
+ *# extension but the new ClientHello contains the extension, then the
+ *# server MUST NOT perform the abbreviated handshake. Instead, it
+ *# SHOULD continue with a full handshake (as described in
+ *# Section 5.2) to negotiate a new session.
+ *#
+ *# o If the original session used the "extended_master_secret"
+ *# extension but the new ClientHello does not contain it, the server
+ *# MUST abort the abbreviated handshake.
+ **/
+ if (conn->ems_negotiated != ems_negotiated) {
+ /* The session ticket needs to have the same EMS state as the current session. If it doesn't
+ * have the same state, the current session takes the state of the session ticket and errors.
+ * If the deserialization process errors, we will use this state in a few extra checks
+ * to determine if we can fallback to a full handshake.
+ */
+ conn->ems_negotiated = ems_negotiated;
+ POSIX_BAIL(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
+ }
+ }
- return 0;
+ return S2N_SUCCESS;
}
static int s2n_client_serialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *to)
{
/* Serialize session ticket */
if (conn->config->use_tickets && conn->client_ticket.size > 0) {
- GUARD(s2n_stuffer_write_uint8(to, S2N_STATE_WITH_SESSION_TICKET));
- GUARD(s2n_stuffer_write_uint16(to, conn->client_ticket.size));
- GUARD(s2n_stuffer_write(to, &conn->client_ticket));
+ POSIX_GUARD(s2n_stuffer_write_uint8(to, S2N_STATE_WITH_SESSION_TICKET));
+ POSIX_GUARD(s2n_stuffer_write_uint16(to, conn->client_ticket.size));
+ POSIX_GUARD(s2n_stuffer_write(to, &conn->client_ticket));
} else {
/* Serialize session id */
- GUARD(s2n_stuffer_write_uint8(to, S2N_STATE_WITH_SESSION_ID));
- GUARD(s2n_stuffer_write_uint8(to, conn->session_id_len));
- GUARD(s2n_stuffer_write_bytes(to, conn->session_id, conn->session_id_len));
+ POSIX_ENSURE_LT(conn->actual_protocol_version, S2N_TLS13);
+ POSIX_GUARD(s2n_stuffer_write_uint8(to, S2N_STATE_WITH_SESSION_ID));
+ POSIX_GUARD(s2n_stuffer_write_uint8(to, conn->session_id_len));
+ POSIX_GUARD(s2n_stuffer_write_bytes(to, conn->session_id, conn->session_id_len));
}
/* Serialize session state */
- GUARD(s2n_serialize_resumption_state(conn, to));
+ POSIX_GUARD_RESULT(s2n_serialize_resumption_state(conn, to));
return 0;
}
-static int s2n_client_deserialize_session_state(struct s2n_connection *conn, struct s2n_stuffer *from)
-{
- if (s2n_stuffer_data_available(from) < S2N_STATE_SIZE_IN_BYTES) {
- S2N_ERROR(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
+static S2N_RESULT s2n_tls12_client_deserialize_session_state(struct s2n_connection *conn, struct s2n_stuffer *from)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(from);
+
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &conn->actual_protocol_version));
+
+ uint8_t *cipher_suite_wire = s2n_stuffer_raw_read(from, S2N_TLS_CIPHER_SUITE_LEN);
+ RESULT_ENSURE_REF(cipher_suite_wire);
+ RESULT_GUARD_POSIX(s2n_set_cipher_as_client(conn, cipher_suite_wire));
+
+ uint64_t then = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint64(from, &then));
+
+ RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(from, conn->secrets.tls12.master_secret, S2N_TLS_SECRET_LEN));
+
+ if (s2n_stuffer_data_available(from)) {
+ uint8_t ems_negotiated = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &ems_negotiated));
+ conn->ems_negotiated = ems_negotiated;
}
+ return S2N_RESULT_OK;
+}
- uint8_t format;
- uint64_t then;
+static S2N_RESULT s2n_validate_ticket_age(uint64_t current_time, uint64_t ticket_issue_time)
+{
+ RESULT_ENSURE(current_time >= ticket_issue_time, S2N_ERR_INVALID_SESSION_TICKET);
+ uint64_t ticket_age_in_nanos = current_time - ticket_issue_time;
+ uint64_t ticket_age_in_sec = ticket_age_in_nanos / ONE_SEC_IN_NANOS;
+ RESULT_ENSURE(ticket_age_in_sec <= ONE_WEEK_IN_SEC, S2N_ERR_INVALID_SESSION_TICKET);
+ return S2N_RESULT_OK;
+}
- GUARD(s2n_stuffer_read_uint8(from, &format));
- if (format != S2N_SERIALIZED_FORMAT_VERSION) {
- S2N_ERROR(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
+static S2N_RESULT s2n_tls13_deserialize_session_state(struct s2n_connection *conn, struct s2n_blob *psk_identity, struct s2n_stuffer *from)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(psk_identity);
+ RESULT_ENSURE_REF(from);
+
+ DEFER_CLEANUP(struct s2n_psk psk = { 0 }, s2n_psk_wipe);
+ RESULT_GUARD(s2n_psk_init(&psk, S2N_PSK_TYPE_RESUMPTION));
+ RESULT_GUARD_POSIX(s2n_psk_set_identity(&psk, psk_identity->data, psk_identity->size));
+
+ uint8_t protocol_version = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &protocol_version));
+ RESULT_ENSURE_GTE(protocol_version, S2N_TLS13);
+
+ uint8_t iana_id[S2N_TLS_CIPHER_SUITE_LEN] = { 0 };
+ RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(from, iana_id, S2N_TLS_CIPHER_SUITE_LEN));
+ struct s2n_cipher_suite *cipher_suite = NULL;
+ RESULT_GUARD(s2n_cipher_suite_from_iana(iana_id, &cipher_suite));
+ RESULT_ENSURE_REF(cipher_suite);
+ psk.hmac_alg = cipher_suite->prf_alg;
+
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint64(from, &psk.ticket_issue_time));
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ *# Clients MUST NOT cache
+ *# tickets for longer than 7 days, regardless of the ticket_lifetime,
+ *# and MAY delete tickets earlier based on local policy.
+ */
+ uint64_t current_time = 0;
+ RESULT_GUARD_POSIX(conn->config->wall_clock(conn->config->sys_clock_ctx, &current_time));
+ RESULT_GUARD(s2n_validate_ticket_age(current_time, psk.ticket_issue_time));
+
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint32(from, &psk.ticket_age_add));
+
+ uint8_t secret_len = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &secret_len));
+ RESULT_ENSURE_LTE(secret_len, S2N_TLS_SECRET_LEN);
+ uint8_t *secret_data = s2n_stuffer_raw_read(from, secret_len);
+ RESULT_ENSURE_REF(secret_data);
+ RESULT_GUARD_POSIX(s2n_psk_set_secret(&psk, secret_data, secret_len));
+
+ if (conn->mode == S2N_SERVER) {
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint64(from, &psk.keying_material_expiration));
+ RESULT_ENSURE(psk.keying_material_expiration > current_time, S2N_ERR_KEYING_MATERIAL_EXPIRED);
}
- GUARD(s2n_stuffer_read_uint8(from, &conn->actual_protocol_version));
+ uint32_t max_early_data_size = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint32(from, &max_early_data_size));
+ if (max_early_data_size > 0) {
+ RESULT_GUARD_POSIX(s2n_psk_configure_early_data(&psk, max_early_data_size,
+ iana_id[0], iana_id[1]));
+
+ uint8_t app_proto_size = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &app_proto_size));
+ uint8_t *app_proto_data = s2n_stuffer_raw_read(from, app_proto_size);
+ RESULT_ENSURE_REF(app_proto_data);
+ RESULT_GUARD_POSIX(s2n_psk_set_application_protocol(&psk, app_proto_data, app_proto_size));
+
+ uint16_t early_data_context_size = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(from, &early_data_context_size));
+ uint8_t *early_data_context_data = s2n_stuffer_raw_read(from, early_data_context_size);
+ RESULT_ENSURE_REF(early_data_context_data);
+ RESULT_GUARD_POSIX(s2n_psk_set_early_data_context(&psk, early_data_context_data, early_data_context_size));
+ }
- uint8_t *cipher_suite_wire = s2n_stuffer_raw_read(from, S2N_TLS_CIPHER_SUITE_LEN);
- notnull_check(cipher_suite_wire);
- GUARD(s2n_set_cipher_as_client(conn, cipher_suite_wire));
+ /* Make sure that this connection is configured for resumption PSKs, not external PSKs */
+ RESULT_GUARD(s2n_connection_set_psk_type(conn, S2N_PSK_TYPE_RESUMPTION));
+ /* Remove all previously-set PSKs. To keep the session ticket API behavior consistent
+ * across protocol versions, we currently only support setting a single resumption PSK. */
+ RESULT_GUARD(s2n_psk_parameters_wipe(&conn->psk_params));
+ RESULT_GUARD_POSIX(s2n_connection_append_psk(conn, &psk));
- GUARD(s2n_stuffer_read_uint64(from, &then));
+ return S2N_RESULT_OK;
+}
- /* Last but not least, put the master secret in place */
- GUARD(s2n_stuffer_read_bytes(from, conn->secure.master_secret, S2N_TLS_SECRET_LEN));
+static S2N_RESULT s2n_deserialize_resumption_state(struct s2n_connection *conn, struct s2n_blob *psk_identity, struct s2n_stuffer *from)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(from);
- return 0;
+ uint8_t format = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &format));
+
+ if (format == S2N_SERIALIZED_FORMAT_TLS12_V3) {
+ if (conn->mode == S2N_SERVER) {
+ RESULT_GUARD_POSIX(s2n_tls12_deserialize_resumption_state(conn, from));
+ } else {
+ RESULT_GUARD(s2n_tls12_client_deserialize_session_state(conn, from));
+ }
+ } else if (format == S2N_SERIALIZED_FORMAT_TLS13_V1) {
+ RESULT_GUARD(s2n_tls13_deserialize_session_state(conn, psk_identity, from));
+ if (conn->mode == S2N_CLIENT) {
+ /* Free the client_ticket after setting a psk on the connection.
+ * This prevents s2n_connection_get_session from returning a TLS1.3
+ * ticket before a ticket has been received from the server. */
+ RESULT_GUARD_POSIX(s2n_free(&conn->client_ticket));
+ }
+ } else {
+ RESULT_BAIL(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
+ }
+ conn->set_session = true;
+ return S2N_RESULT_OK;
}
static int s2n_client_deserialize_with_session_id(struct s2n_connection *conn, struct s2n_stuffer *from)
{
uint8_t session_id_len;
- GUARD(s2n_stuffer_read_uint8(from, &session_id_len));
+ POSIX_GUARD(s2n_stuffer_read_uint8(from, &session_id_len));
if (session_id_len == 0 || session_id_len > S2N_TLS_SESSION_ID_MAX_LEN
|| session_id_len > s2n_stuffer_data_available(from)) {
- S2N_ERROR(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
+ POSIX_BAIL(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
}
conn->session_id_len = session_id_len;
- GUARD(s2n_stuffer_read_bytes(from, conn->session_id, session_id_len));
+ POSIX_GUARD(s2n_stuffer_read_bytes(from, conn->session_id, session_id_len));
- GUARD(s2n_client_deserialize_session_state(conn, from));
+ POSIX_GUARD_RESULT(s2n_deserialize_resumption_state(conn, NULL, from));
return 0;
}
@@ -162,16 +366,16 @@ static int s2n_client_deserialize_with_session_id(struct s2n_connection *conn, s
static int s2n_client_deserialize_with_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *from)
{
uint16_t session_ticket_len;
- GUARD(s2n_stuffer_read_uint16(from, &session_ticket_len));
+ POSIX_GUARD(s2n_stuffer_read_uint16(from, &session_ticket_len));
if (session_ticket_len == 0 || session_ticket_len > s2n_stuffer_data_available(from)) {
- S2N_ERROR(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
+ POSIX_BAIL(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
}
- GUARD(s2n_realloc(&conn->client_ticket, session_ticket_len));
- GUARD(s2n_stuffer_read(from, &conn->client_ticket));
+ POSIX_GUARD(s2n_realloc(&conn->client_ticket, session_ticket_len));
+ POSIX_GUARD(s2n_stuffer_read(from, &conn->client_ticket));
- GUARD(s2n_client_deserialize_session_state(conn, from));
+ POSIX_GUARD_RESULT(s2n_deserialize_resumption_state(conn, &conn->client_ticket, from));
return 0;
}
@@ -179,17 +383,17 @@ static int s2n_client_deserialize_with_session_ticket(struct s2n_connection *con
static int s2n_client_deserialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *from)
{
uint8_t format;
- GUARD(s2n_stuffer_read_uint8(from, &format));
+ POSIX_GUARD(s2n_stuffer_read_uint8(from, &format));
switch (format) {
case S2N_STATE_WITH_SESSION_ID:
- GUARD(s2n_client_deserialize_with_session_id(conn, from));
+ POSIX_GUARD(s2n_client_deserialize_with_session_id(conn, from));
break;
case S2N_STATE_WITH_SESSION_TICKET:
- GUARD(s2n_client_deserialize_with_session_ticket(conn, from));
+ POSIX_GUARD(s2n_client_deserialize_with_session_ticket(conn, from));
break;
default:
- S2N_ERROR(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
+ POSIX_BAIL(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
}
return 0;
@@ -200,67 +404,67 @@ int s2n_resume_from_cache(struct s2n_connection *conn)
S2N_ERROR_IF(conn->session_id_len == 0, S2N_ERR_SESSION_ID_TOO_SHORT);
S2N_ERROR_IF(conn->session_id_len > S2N_TLS_SESSION_ID_MAX_LEN, S2N_ERR_SESSION_ID_TOO_LONG);
- uint8_t data[S2N_TICKET_SIZE_IN_BYTES] = { 0 };
+ uint8_t data[S2N_TLS12_TICKET_SIZE_IN_BYTES] = { 0 };
struct s2n_blob entry = {0};
- GUARD(s2n_blob_init(&entry, data, S2N_TICKET_SIZE_IN_BYTES));
+ POSIX_GUARD(s2n_blob_init(&entry, data, S2N_TLS12_TICKET_SIZE_IN_BYTES));
uint64_t size = entry.size;
int result = conn->config->cache_retrieve(conn, conn->config->cache_retrieve_data, conn->session_id, conn->session_id_len, entry.data, &size);
if (result == S2N_CALLBACK_BLOCKED) {
- S2N_ERROR(S2N_ERR_ASYNC_BLOCKED);
+ POSIX_BAIL(S2N_ERR_ASYNC_BLOCKED);
}
- GUARD(result);
+ POSIX_GUARD(result);
S2N_ERROR_IF(size != entry.size, S2N_ERR_SIZE_MISMATCH);
struct s2n_stuffer from = {0};
- GUARD(s2n_stuffer_init(&from, &entry));
- GUARD(s2n_stuffer_write(&from, &entry));
- GUARD(s2n_decrypt_session_cache(conn, &from));
+ POSIX_GUARD(s2n_stuffer_init(&from, &entry));
+ POSIX_GUARD(s2n_stuffer_write(&from, &entry));
+ POSIX_GUARD(s2n_decrypt_session_cache(conn, &from));
return 0;
}
-int s2n_store_to_cache(struct s2n_connection *conn)
+S2N_RESULT s2n_store_to_cache(struct s2n_connection *conn)
{
- uint8_t data[S2N_TICKET_SIZE_IN_BYTES] = { 0 };
+ uint8_t data[S2N_TLS12_TICKET_SIZE_IN_BYTES] = { 0 };
struct s2n_blob entry = {0};
- GUARD(s2n_blob_init(&entry, data, S2N_TICKET_SIZE_IN_BYTES));
+ RESULT_GUARD_POSIX(s2n_blob_init(&entry, data, S2N_TLS12_TICKET_SIZE_IN_BYTES));
struct s2n_stuffer to = {0};
/* session_id_len should always be >0 since either the Client provided a SessionId or the Server generated a new
* one for the Client */
- S2N_ERROR_IF(conn->session_id_len == 0, S2N_ERR_SESSION_ID_TOO_SHORT);
- S2N_ERROR_IF(conn->session_id_len > S2N_TLS_SESSION_ID_MAX_LEN, S2N_ERR_SESSION_ID_TOO_LONG);
+ RESULT_ENSURE(conn->session_id_len > 0, S2N_ERR_SESSION_ID_TOO_SHORT);
+ RESULT_ENSURE(conn->session_id_len <= S2N_TLS_SESSION_ID_MAX_LEN, S2N_ERR_SESSION_ID_TOO_LONG);
- GUARD(s2n_stuffer_init(&to, &entry));
- GUARD(s2n_encrypt_session_cache(conn, &to));
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&to, &entry));
+ RESULT_GUARD_POSIX(s2n_encrypt_session_cache(conn, &to));
/* Store to the cache */
conn->config->cache_store(conn, conn->config->cache_store_data, S2N_TLS_SESSION_CACHE_TTL, conn->session_id, conn->session_id_len, entry.data, entry.size);
- return 0;
+ return S2N_RESULT_OK;
}
int s2n_connection_set_session(struct s2n_connection *conn, const uint8_t *session, size_t length)
{
- notnull_check(conn);
- notnull_check(session);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(session);
DEFER_CLEANUP(struct s2n_blob session_data = {0}, s2n_free);
- GUARD(s2n_alloc(&session_data, length));
- memcpy(session_data.data, session, length);
+ POSIX_GUARD(s2n_alloc(&session_data, length));
+ POSIX_CHECKED_MEMCPY(session_data.data, session, length);
struct s2n_stuffer from = {0};
- GUARD(s2n_stuffer_init(&from, &session_data));
- GUARD(s2n_stuffer_write(&from, &session_data));
- GUARD(s2n_client_deserialize_resumption_state(conn, &from));
+ POSIX_GUARD(s2n_stuffer_init(&from, &session_data));
+ POSIX_GUARD(s2n_stuffer_write(&from, &session_data));
+ POSIX_GUARD(s2n_client_deserialize_resumption_state(conn, &from));
return 0;
}
int s2n_connection_get_session(struct s2n_connection *conn, uint8_t *session, size_t max_length)
{
- notnull_check(conn);
- notnull_check(session);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(session);
int len = s2n_connection_get_session_length(conn);
@@ -271,52 +475,93 @@ int s2n_connection_get_session(struct s2n_connection *conn, uint8_t *session, si
S2N_ERROR_IF(len > max_length, S2N_ERR_SERIALIZED_SESSION_STATE_TOO_LONG);
struct s2n_blob serialized_data = {0};
- GUARD(s2n_blob_init(&serialized_data, session, len));
- GUARD(s2n_blob_zero(&serialized_data));
+ POSIX_GUARD(s2n_blob_init(&serialized_data, session, len));
+ POSIX_GUARD(s2n_blob_zero(&serialized_data));
struct s2n_stuffer to = {0};
- GUARD(s2n_stuffer_init(&to, &serialized_data));
- GUARD(s2n_client_serialize_resumption_state(conn, &to));
+ POSIX_GUARD(s2n_stuffer_init(&to, &serialized_data));
+ POSIX_GUARD(s2n_client_serialize_resumption_state(conn, &to));
return len;
}
int s2n_connection_get_session_ticket_lifetime_hint(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
S2N_ERROR_IF(!(conn->config->use_tickets && conn->client_ticket.size > 0), S2N_ERR_SESSION_TICKET_NOT_SUPPORTED);
/* Session resumption using session ticket */
return conn->ticket_lifetime_hint;
}
-int s2n_connection_get_session_length(struct s2n_connection *conn)
+S2N_RESULT s2n_connection_get_session_state_size(struct s2n_connection *conn, size_t *state_size)
{
- /* Session resumption using session ticket "format (1) + session_ticket_len + session_ticket + session state" */
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(state_size);
+
+ if (conn->actual_protocol_version < S2N_TLS13) {
+ *state_size = S2N_TLS12_STATE_SIZE_IN_BYTES;
+ return S2N_RESULT_OK;
+ }
+
+ *state_size = S2N_TLS13_FIXED_STATE_SIZE;
+
+ uint8_t secret_size = 0;
+ RESULT_ENSURE_REF(conn->secure.cipher_suite);
+ RESULT_GUARD_POSIX(s2n_hmac_digest_size(conn->secure.cipher_suite->prf_alg, &secret_size));
+ *state_size += secret_size;
+
+ uint32_t server_max_early_data = 0;
+ RESULT_GUARD(s2n_early_data_get_server_max_size(conn, &server_max_early_data));
+ if (server_max_early_data > 0) {
+ *state_size += S2N_TLS13_FIXED_EARLY_DATA_STATE_SIZE
+ + strlen(conn->application_protocol)
+ + conn->server_early_data_context.size;
+ }
+
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_connection_get_session_length_impl(struct s2n_connection *conn, size_t *length)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->config);
+ RESULT_ENSURE_REF(length);
+ *length = 0;
+
if (conn->config->use_tickets && conn->client_ticket.size > 0) {
- return S2N_STATE_FORMAT_LEN + S2N_SESSION_TICKET_SIZE_LEN + conn->client_ticket.size + S2N_STATE_SIZE_IN_BYTES;
- } else if (conn->session_id_len > 0) {
- /* Session resumption using session id: "format (0) + session_id_len + session_id + session state" */
- return S2N_STATE_FORMAT_LEN + 1 + conn->session_id_len + S2N_STATE_SIZE_IN_BYTES;
- } else {
- return 0;
+ size_t session_state_size = 0;
+ RESULT_GUARD(s2n_connection_get_session_state_size(conn, &session_state_size));
+ *length = S2N_STATE_FORMAT_LEN + S2N_SESSION_TICKET_SIZE_LEN + conn->client_ticket.size + session_state_size;
+ } else if (conn->session_id_len > 0 && conn->actual_protocol_version < S2N_TLS13) {
+ *length = S2N_STATE_FORMAT_LEN + sizeof(conn->session_id_len) + conn->session_id_len + S2N_TLS12_STATE_SIZE_IN_BYTES;
}
+ return S2N_RESULT_OK;
+}
+
+int s2n_connection_get_session_length(struct s2n_connection *conn)
+{
+ size_t length = 0;
+ if (s2n_result_is_ok(s2n_connection_get_session_length_impl(conn, &length))) {
+ return length;
+ }
+ return 0;
}
int s2n_connection_is_session_resumed(struct s2n_connection *conn)
{
- notnull_check(conn);
- return IS_RESUMPTION_HANDSHAKE(conn->handshake.handshake_type) ? 1 : 0;
+ return conn && IS_RESUMPTION_HANDSHAKE(conn)
+ && (conn->actual_protocol_version < S2N_TLS13 || conn->psk_params.type == S2N_PSK_TYPE_RESUMPTION);
}
int s2n_connection_is_ocsp_stapled(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
if (conn->actual_protocol_version >= S2N_TLS13) {
return (s2n_server_can_send_ocsp(conn) || s2n_server_sent_ocsp(conn));
} else {
- return IS_OCSP_STAPLED(conn->handshake.handshake_type);
+ return IS_OCSP_STAPLED(conn);
}
}
@@ -324,15 +569,15 @@ int s2n_config_is_encrypt_decrypt_key_available(struct s2n_config *config)
{
uint64_t now;
struct s2n_ticket_key *ticket_key = NULL;
- GUARD(config->wall_clock(config->sys_clock_ctx, &now));
- notnull_check(config->ticket_keys);
+ POSIX_GUARD(config->wall_clock(config->sys_clock_ctx, &now));
+ POSIX_ENSURE_REF(config->ticket_keys);
uint32_t ticket_keys_len = 0;
- GUARD_AS_POSIX(s2n_set_len(config->ticket_keys, &ticket_keys_len));
+ POSIX_GUARD_RESULT(s2n_set_len(config->ticket_keys, &ticket_keys_len));
for (uint32_t i = ticket_keys_len; i > 0; i--) {
uint32_t idx = i - 1;
- GUARD_AS_POSIX(s2n_set_get(config->ticket_keys, idx, (void **)&ticket_key));
+ POSIX_GUARD_RESULT(s2n_set_get(config->ticket_keys, idx, (void **)&ticket_key));
uint64_t key_intro_time = ticket_key->intro_timestamp;
if (key_intro_time < now
@@ -359,7 +604,7 @@ int s2n_compute_weight_of_encrypt_decrypt_keys(struct s2n_config *config,
/* Compute weight of encrypt-decrypt keys */
for (int i = 0; i < num_encrypt_decrypt_keys; i++) {
- GUARD_AS_POSIX(s2n_set_get(config->ticket_keys, encrypt_decrypt_keys_index[i], (void **)&ticket_key));
+ POSIX_GUARD_RESULT(s2n_set_get(config->ticket_keys, encrypt_decrypt_keys_index[i], (void **)&ticket_key));
uint64_t key_intro_time = ticket_key->intro_timestamp;
uint64_t key_encryption_peak_time = key_intro_time + (config->encrypt_decrypt_key_lifetime_in_nanos / 2);
@@ -378,7 +623,7 @@ int s2n_compute_weight_of_encrypt_decrypt_keys(struct s2n_config *config,
/* Pick a random number in [0, 1). Using 53 bits (IEEE 754 double-precision floats). */
uint64_t random_int = 0;
- GUARD_AS_POSIX(s2n_public_random(pow(2, 53), &random_int));
+ POSIX_GUARD_RESULT(s2n_public_random(pow(2, 53), &random_int));
double random = (double)random_int / (double)pow(2, 53);
/* Compute cumulative weight of encrypt-decrypt keys */
@@ -394,7 +639,7 @@ int s2n_compute_weight_of_encrypt_decrypt_keys(struct s2n_config *config,
}
}
- S2N_ERROR(S2N_ERR_ENCRYPT_DECRYPT_KEY_SELECTION_FAILED);
+ POSIX_BAIL(S2N_ERR_ENCRYPT_DECRYPT_KEY_SELECTION_FAILED);
}
/* This function is used in s2n_encrypt_session_ticket in order for s2n to
@@ -407,15 +652,15 @@ struct s2n_ticket_key *s2n_get_ticket_encrypt_decrypt_key(struct s2n_config *con
struct s2n_ticket_key *ticket_key = NULL;
uint64_t now;
- GUARD_PTR(config->wall_clock(config->sys_clock_ctx, &now));
- notnull_check_ptr(config->ticket_keys);
+ PTR_GUARD_POSIX(config->wall_clock(config->sys_clock_ctx, &now));
+ PTR_ENSURE_REF(config->ticket_keys);
uint32_t ticket_keys_len = 0;
- GUARD_RESULT_PTR(s2n_set_len(config->ticket_keys, &ticket_keys_len));
+ PTR_GUARD_RESULT(s2n_set_len(config->ticket_keys, &ticket_keys_len));
for (uint32_t i = ticket_keys_len; i > 0; i--) {
uint32_t idx = i - 1;
- GUARD_RESULT_PTR(s2n_set_get(config->ticket_keys, idx, (void **)&ticket_key));
+ PTR_GUARD_RESULT(s2n_set_get(config->ticket_keys, idx, (void **)&ticket_key));
uint64_t key_intro_time = ticket_key->intro_timestamp;
if (key_intro_time < now
@@ -426,18 +671,18 @@ struct s2n_ticket_key *s2n_get_ticket_encrypt_decrypt_key(struct s2n_config *con
}
if (num_encrypt_decrypt_keys == 0) {
- S2N_ERROR_PTR(S2N_ERR_NO_TICKET_ENCRYPT_DECRYPT_KEY);
+ PTR_BAIL(S2N_ERR_NO_TICKET_ENCRYPT_DECRYPT_KEY);
}
if (num_encrypt_decrypt_keys == 1) {
- GUARD_RESULT_PTR(s2n_set_get(config->ticket_keys, encrypt_decrypt_keys_index[0], (void **)&ticket_key));
+ PTR_GUARD_RESULT(s2n_set_get(config->ticket_keys, encrypt_decrypt_keys_index[0], (void **)&ticket_key));
return ticket_key;
}
int8_t idx;
- GUARD_PTR(idx = s2n_compute_weight_of_encrypt_decrypt_keys(config, encrypt_decrypt_keys_index, num_encrypt_decrypt_keys, now));
+ PTR_GUARD_POSIX(idx = s2n_compute_weight_of_encrypt_decrypt_keys(config, encrypt_decrypt_keys_index, num_encrypt_decrypt_keys, now));
- GUARD_RESULT_PTR(s2n_set_get(config->ticket_keys, idx, (void **)&ticket_key));
+ PTR_GUARD_RESULT(s2n_set_get(config->ticket_keys, idx, (void **)&ticket_key));
return ticket_key;
}
@@ -448,14 +693,14 @@ struct s2n_ticket_key *s2n_find_ticket_key(struct s2n_config *config, const uint
{
uint64_t now;
struct s2n_ticket_key *ticket_key = NULL;
- GUARD_PTR(config->wall_clock(config->sys_clock_ctx, &now));
- notnull_check_ptr(config->ticket_keys);
+ PTR_GUARD_POSIX(config->wall_clock(config->sys_clock_ctx, &now));
+ PTR_ENSURE_REF(config->ticket_keys);
uint32_t ticket_keys_len = 0;
- GUARD_RESULT_PTR(s2n_set_len(config->ticket_keys, &ticket_keys_len));
+ PTR_GUARD_RESULT(s2n_set_len(config->ticket_keys, &ticket_keys_len));
for (uint32_t i = 0; i < ticket_keys_len; i++) {
- GUARD_RESULT_PTR(s2n_set_get(config->ticket_keys, i, (void **)&ticket_key));
+ PTR_GUARD_RESULT(s2n_set_get(config->ticket_keys, i, (void **)&ticket_key));
if (memcmp(ticket_key->key_name, name, S2N_TICKET_KEY_NAME_LEN) == 0) {
@@ -482,107 +727,104 @@ int s2n_encrypt_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *
uint8_t iv_data[S2N_TLS_GCM_IV_LEN] = { 0 };
struct s2n_blob iv = {0};
- GUARD(s2n_blob_init(&iv, iv_data, sizeof(iv_data)));
+ POSIX_GUARD(s2n_blob_init(&iv, iv_data, sizeof(iv_data)));
uint8_t aad_data[S2N_TICKET_AAD_LEN] = { 0 };
struct s2n_blob aad_blob = {0};
- GUARD(s2n_blob_init(&aad_blob, aad_data, sizeof(aad_data)));
+ POSIX_GUARD(s2n_blob_init(&aad_blob, aad_data, sizeof(aad_data)));
struct s2n_stuffer aad = {0};
- uint8_t s_data[S2N_STATE_SIZE_IN_BYTES + S2N_TLS_GCM_TAG_LEN] = { 0 };
- struct s2n_blob state_blob = {0};
- GUARD(s2n_blob_init(&state_blob, s_data, sizeof(s_data)));
- struct s2n_stuffer state = {0};
-
key = s2n_get_ticket_encrypt_decrypt_key(conn->config);
/* No keys loaded by the user or the keys are either in decrypt-only or expired state */
S2N_ERROR_IF(!key, S2N_ERR_NO_TICKET_ENCRYPT_DECRYPT_KEY);
- GUARD(s2n_stuffer_write_bytes(to, key->key_name, S2N_TICKET_KEY_NAME_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(to, key->key_name, S2N_TICKET_KEY_NAME_LEN));
- GUARD_AS_POSIX(s2n_get_public_random_data(&iv));
- GUARD(s2n_stuffer_write(to, &iv));
+ POSIX_GUARD_RESULT(s2n_get_public_random_data(&iv));
+ POSIX_GUARD(s2n_stuffer_write(to, &iv));
- GUARD(s2n_blob_init(&aes_key_blob, key->aes_key, S2N_AES256_KEY_LEN));
- GUARD(s2n_session_key_alloc(&aes_ticket_key));
- GUARD(s2n_aes256_gcm.init(&aes_ticket_key));
- GUARD(s2n_aes256_gcm.set_encryption_key(&aes_ticket_key, &aes_key_blob));
+ POSIX_GUARD(s2n_blob_init(&aes_key_blob, key->aes_key, S2N_AES256_KEY_LEN));
+ POSIX_GUARD(s2n_session_key_alloc(&aes_ticket_key));
+ POSIX_GUARD(s2n_aes256_gcm.init(&aes_ticket_key));
+ POSIX_GUARD(s2n_aes256_gcm.set_encryption_key(&aes_ticket_key, &aes_key_blob));
- GUARD(s2n_stuffer_init(&aad, &aad_blob));
- GUARD(s2n_stuffer_write_bytes(&aad, key->implicit_aad, S2N_TICKET_AAD_IMPLICIT_LEN));
- GUARD(s2n_stuffer_write_bytes(&aad, key->key_name, S2N_TICKET_KEY_NAME_LEN));
+ POSIX_GUARD(s2n_stuffer_init(&aad, &aad_blob));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&aad, key->implicit_aad, S2N_TICKET_AAD_IMPLICIT_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&aad, key->key_name, S2N_TICKET_KEY_NAME_LEN));
- GUARD(s2n_stuffer_init(&state, &state_blob));
- GUARD(s2n_serialize_resumption_state(conn, &state));
+ uint32_t plaintext_header_size = s2n_stuffer_data_available(to);
+ POSIX_GUARD_RESULT(s2n_serialize_resumption_state(conn, to));
+ POSIX_GUARD(s2n_stuffer_skip_write(to, S2N_TLS_GCM_TAG_LEN));
- GUARD(s2n_aes256_gcm.io.aead.encrypt(&aes_ticket_key, &iv, &aad_blob, &state_blob, &state_blob));
+ struct s2n_blob state_blob = { 0 };
+ struct s2n_stuffer copy_for_encryption = *to;
+ POSIX_GUARD(s2n_stuffer_skip_read(&copy_for_encryption, plaintext_header_size));
+ uint32_t state_blob_size = s2n_stuffer_data_available(&copy_for_encryption);
+ uint8_t *state_blob_data = s2n_stuffer_raw_read(&copy_for_encryption, state_blob_size);
+ POSIX_ENSURE_REF(state_blob_data);
+ POSIX_GUARD(s2n_blob_init(&state_blob, state_blob_data, state_blob_size));
- GUARD(s2n_stuffer_write(to, &state_blob));
+ POSIX_GUARD(s2n_aes256_gcm.io.aead.encrypt(&aes_ticket_key, &iv, &aad_blob, &state_blob, &state_blob));
- GUARD(s2n_aes256_gcm.destroy_key(&aes_ticket_key));
- GUARD(s2n_session_key_free(&aes_ticket_key));
+ POSIX_GUARD(s2n_aes256_gcm.destroy_key(&aes_ticket_key));
+ POSIX_GUARD(s2n_session_key_free(&aes_ticket_key));
return 0;
}
-int s2n_decrypt_session_ticket(struct s2n_connection *conn)
+int s2n_decrypt_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *from)
{
struct s2n_ticket_key *key;
DEFER_CLEANUP(struct s2n_session_key aes_ticket_key = {0}, s2n_session_key_free);
struct s2n_blob aes_key_blob = {0};
- struct s2n_stuffer *from;
uint8_t key_name[S2N_TICKET_KEY_NAME_LEN];
uint8_t iv_data[S2N_TLS_GCM_IV_LEN] = { 0 };
struct s2n_blob iv = { 0 };
- GUARD(s2n_blob_init(&iv, iv_data, sizeof(iv_data)));
+ POSIX_GUARD(s2n_blob_init(&iv, iv_data, sizeof(iv_data)));
uint8_t aad_data[S2N_TICKET_AAD_LEN] = { 0 };
struct s2n_blob aad_blob = {0};
- GUARD(s2n_blob_init(&aad_blob, aad_data, sizeof(aad_data)));
+ POSIX_GUARD(s2n_blob_init(&aad_blob, aad_data, sizeof(aad_data)));
struct s2n_stuffer aad = {0};
- uint8_t s_data[S2N_STATE_SIZE_IN_BYTES] = { 0 };
- struct s2n_blob state_blob = {0};
- GUARD(s2n_blob_init(&state_blob, s_data, sizeof(s_data)));
- struct s2n_stuffer state = {0};
-
- uint8_t en_data[S2N_STATE_SIZE_IN_BYTES + S2N_TLS_GCM_TAG_LEN] = {0};
- struct s2n_blob en_blob = {0};
- GUARD(s2n_blob_init(&en_blob, en_data, sizeof(en_data)));
-
- from = &conn->client_ticket_to_decrypt;
- GUARD(s2n_stuffer_read_bytes(from, key_name, S2N_TICKET_KEY_NAME_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(from, key_name, S2N_TICKET_KEY_NAME_LEN));
key = s2n_find_ticket_key(conn->config, key_name);
/* Key has expired; do full handshake with New Session Ticket (NST) */
S2N_ERROR_IF(!key, S2N_ERR_KEY_USED_IN_SESSION_TICKET_NOT_FOUND);
- GUARD(s2n_stuffer_read(from, &iv));
+ POSIX_GUARD(s2n_stuffer_read(from, &iv));
s2n_blob_init(&aes_key_blob, key->aes_key, S2N_AES256_KEY_LEN);
- GUARD(s2n_session_key_alloc(&aes_ticket_key));
- GUARD(s2n_aes256_gcm.init(&aes_ticket_key));
- GUARD(s2n_aes256_gcm.set_decryption_key(&aes_ticket_key, &aes_key_blob));
-
- GUARD(s2n_stuffer_init(&aad, &aad_blob));
- GUARD(s2n_stuffer_write_bytes(&aad, key->implicit_aad, S2N_TICKET_AAD_IMPLICIT_LEN));
- GUARD(s2n_stuffer_write_bytes(&aad, key->key_name, S2N_TICKET_KEY_NAME_LEN));
-
- GUARD(s2n_stuffer_read(from, &en_blob));
-
- GUARD(s2n_aes256_gcm.io.aead.decrypt(&aes_ticket_key, &iv, &aad_blob, &en_blob, &en_blob));
-
- GUARD(s2n_stuffer_init(&state, &state_blob));
- GUARD(s2n_stuffer_write_bytes(&state, en_data, S2N_STATE_SIZE_IN_BYTES));
-
- GUARD(s2n_deserialize_resumption_state(conn, &state));
+ POSIX_GUARD(s2n_session_key_alloc(&aes_ticket_key));
+ POSIX_GUARD(s2n_aes256_gcm.init(&aes_ticket_key));
+ POSIX_GUARD(s2n_aes256_gcm.set_decryption_key(&aes_ticket_key, &aes_key_blob));
+
+ POSIX_GUARD(s2n_stuffer_init(&aad, &aad_blob));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&aad, key->implicit_aad, S2N_TICKET_AAD_IMPLICIT_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&aad, key->key_name, S2N_TICKET_KEY_NAME_LEN));
+
+ struct s2n_blob en_blob = { 0 };
+ uint32_t en_blob_size = s2n_stuffer_data_available(from);
+ uint8_t *en_blob_data = s2n_stuffer_raw_read(from, en_blob_size);
+ POSIX_ENSURE_REF(en_blob_data);
+ POSIX_GUARD(s2n_blob_init(&en_blob, en_blob_data, en_blob_size));
+ POSIX_GUARD(s2n_aes256_gcm.io.aead.decrypt(&aes_ticket_key, &iv, &aad_blob, &en_blob, &en_blob));
+
+ struct s2n_blob state_blob = { 0 };
+ uint32_t state_blob_size = en_blob_size - S2N_TLS_GCM_TAG_LEN;
+ POSIX_GUARD(s2n_blob_init(&state_blob, en_blob.data, state_blob_size));
+ struct s2n_stuffer state_stuffer = { 0 };
+ POSIX_GUARD(s2n_stuffer_init(&state_stuffer, &state_blob));
+ POSIX_GUARD(s2n_stuffer_skip_write(&state_stuffer, state_blob_size));
+ POSIX_GUARD_RESULT(s2n_deserialize_resumption_state(conn, &from->blob, &state_stuffer));
uint64_t now;
- GUARD(conn->config->wall_clock(conn->config->sys_clock_ctx, &now));
+ POSIX_GUARD(conn->config->wall_clock(conn->config->sys_clock_ctx, &now));
/* If the key is in decrypt-only state, then a new key is assigned
* for the ticket.
@@ -591,13 +833,11 @@ int s2n_decrypt_session_ticket(struct s2n_connection *conn)
/* Check if a key in encrypt-decrypt state is available */
if (s2n_config_is_encrypt_decrypt_key_available(conn->config) == 1) {
conn->session_ticket_status = S2N_NEW_TICKET;
- conn->handshake.handshake_type |= WITH_SESSION_TICKET;
-
- return 0;
+ POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, WITH_SESSION_TICKET));
+ return S2N_SUCCESS;
}
}
-
- return 0;
+ return S2N_SUCCESS;
}
int s2n_encrypt_session_cache(struct s2n_connection *conn, struct s2n_stuffer *to)
@@ -605,7 +845,6 @@ int s2n_encrypt_session_cache(struct s2n_connection *conn, struct s2n_stuffer *t
return s2n_encrypt_session_ticket(conn, to);
}
-
int s2n_decrypt_session_cache(struct s2n_connection *conn, struct s2n_stuffer *from)
{
struct s2n_ticket_key *key;
@@ -616,51 +855,50 @@ int s2n_decrypt_session_cache(struct s2n_connection *conn, struct s2n_stuffer *f
uint8_t iv_data[S2N_TLS_GCM_IV_LEN] = { 0 };
struct s2n_blob iv = {0};
- GUARD(s2n_blob_init(&iv, iv_data, sizeof(iv_data)));
+ POSIX_GUARD(s2n_blob_init(&iv, iv_data, sizeof(iv_data)));
uint8_t aad_data[S2N_TICKET_AAD_LEN] = { 0 };
struct s2n_blob aad_blob = {0};
- GUARD(s2n_blob_init(&aad_blob, aad_data, sizeof(aad_data)));
+ POSIX_GUARD(s2n_blob_init(&aad_blob, aad_data, sizeof(aad_data)));
struct s2n_stuffer aad = {0};
- uint8_t s_data[S2N_STATE_SIZE_IN_BYTES] = { 0 };
+ uint8_t s_data[S2N_TLS12_STATE_SIZE_IN_BYTES] = { 0 };
struct s2n_blob state_blob = {0};
- GUARD(s2n_blob_init(&state_blob, s_data, sizeof(s_data)));
+ POSIX_GUARD(s2n_blob_init(&state_blob, s_data, sizeof(s_data)));
struct s2n_stuffer state = {0};
- uint8_t en_data[S2N_STATE_SIZE_IN_BYTES + S2N_TLS_GCM_TAG_LEN] = {0};
+ uint8_t en_data[S2N_TLS12_STATE_SIZE_IN_BYTES + S2N_TLS_GCM_TAG_LEN] = {0};
struct s2n_blob en_blob = {0};
- GUARD(s2n_blob_init(&en_blob, en_data, sizeof(en_data)));
+ POSIX_GUARD(s2n_blob_init(&en_blob, en_data, sizeof(en_data)));
- GUARD(s2n_stuffer_read_bytes(from, key_name, S2N_TICKET_KEY_NAME_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(from, key_name, S2N_TICKET_KEY_NAME_LEN));
key = s2n_find_ticket_key(conn->config, key_name);
/* Key has expired; do full handshake with New Session Ticket (NST) */
S2N_ERROR_IF(!key, S2N_ERR_KEY_USED_IN_SESSION_TICKET_NOT_FOUND);
- GUARD(s2n_stuffer_read(from, &iv));
+ POSIX_GUARD(s2n_stuffer_read(from, &iv));
s2n_blob_init(&aes_key_blob, key->aes_key, S2N_AES256_KEY_LEN);
- GUARD(s2n_session_key_alloc(&aes_ticket_key));
- GUARD(s2n_aes256_gcm.init(&aes_ticket_key));
- GUARD(s2n_aes256_gcm.set_decryption_key(&aes_ticket_key, &aes_key_blob));
-
- GUARD(s2n_stuffer_init(&aad, &aad_blob));
- GUARD(s2n_stuffer_write_bytes(&aad, key->implicit_aad, S2N_TICKET_AAD_IMPLICIT_LEN));
- GUARD(s2n_stuffer_write_bytes(&aad, key->key_name, S2N_TICKET_KEY_NAME_LEN));
+ POSIX_GUARD(s2n_session_key_alloc(&aes_ticket_key));
+ POSIX_GUARD(s2n_aes256_gcm.init(&aes_ticket_key));
+ POSIX_GUARD(s2n_aes256_gcm.set_decryption_key(&aes_ticket_key, &aes_key_blob));
- GUARD(s2n_stuffer_read(from, &en_blob));
+ POSIX_GUARD(s2n_stuffer_init(&aad, &aad_blob));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&aad, key->implicit_aad, S2N_TICKET_AAD_IMPLICIT_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&aad, key->key_name, S2N_TICKET_KEY_NAME_LEN));
- GUARD(s2n_aes256_gcm.io.aead.decrypt(&aes_ticket_key, &iv, &aad_blob, &en_blob, &en_blob));
+ POSIX_GUARD(s2n_stuffer_read(from, &en_blob));
- GUARD(s2n_stuffer_init(&state, &state_blob));
- GUARD(s2n_stuffer_write_bytes(&state, en_data, S2N_STATE_SIZE_IN_BYTES));
+ POSIX_GUARD(s2n_aes256_gcm.io.aead.decrypt(&aes_ticket_key, &iv, &aad_blob, &en_blob, &en_blob));
+ POSIX_GUARD(s2n_aes256_gcm.destroy_key(&aes_ticket_key));
+ POSIX_GUARD(s2n_session_key_free(&aes_ticket_key));
- GUARD(s2n_deserialize_resumption_state(conn, &state));
+ POSIX_GUARD(s2n_stuffer_init(&state, &state_blob));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&state, en_data, S2N_TLS12_STATE_SIZE_IN_BYTES));
- GUARD(s2n_aes256_gcm.destroy_key(&aes_ticket_key));
- GUARD(s2n_session_key_free(&aes_ticket_key));
+ POSIX_GUARD_RESULT(s2n_deserialize_resumption_state(conn, NULL, &state));
return 0;
}
@@ -680,14 +918,14 @@ int s2n_config_wipe_expired_ticket_crypto_keys(struct s2n_config *config, int8_t
}
uint64_t now;
- GUARD(config->wall_clock(config->sys_clock_ctx, &now));
- notnull_check(config->ticket_keys);
+ POSIX_GUARD(config->wall_clock(config->sys_clock_ctx, &now));
+ POSIX_ENSURE_REF(config->ticket_keys);
uint32_t ticket_keys_len = 0;
- GUARD_AS_POSIX(s2n_set_len(config->ticket_keys, &ticket_keys_len));
+ POSIX_GUARD_RESULT(s2n_set_len(config->ticket_keys, &ticket_keys_len));
for (uint32_t i = 0; i < ticket_keys_len; i++) {
- GUARD_AS_POSIX(s2n_set_get(config->ticket_keys, i, (void **)&ticket_key));
+ POSIX_GUARD_RESULT(s2n_set_get(config->ticket_keys, i, (void **)&ticket_key));
if (now >= ticket_key->intro_timestamp +
config->encrypt_decrypt_key_lifetime_in_nanos + config->decrypt_key_lifetime_in_nanos) {
expired_keys_index[num_of_expired_keys] = i;
@@ -697,7 +935,7 @@ int s2n_config_wipe_expired_ticket_crypto_keys(struct s2n_config *config, int8_t
end:
for (int j = 0; j < num_of_expired_keys; j++) {
- GUARD_AS_POSIX(s2n_set_remove(config->ticket_keys, expired_keys_index[j] - j));
+ POSIX_GUARD_RESULT(s2n_set_remove(config->ticket_keys, expired_keys_index[j] - j));
}
return 0;
@@ -707,6 +945,83 @@ end:
int s2n_config_store_ticket_key(struct s2n_config *config, struct s2n_ticket_key *key)
{
/* Keys are stored from oldest to newest */
- GUARD_AS_POSIX(s2n_set_add(config->ticket_keys, key));
+ POSIX_GUARD_RESULT(s2n_set_add(config->ticket_keys, key));
+ return S2N_SUCCESS;
+}
+
+int s2n_config_set_initial_ticket_count(struct s2n_config *config, uint8_t num)
+{
+ POSIX_ENSURE_REF(config);
+
+ config->initial_tickets_to_send = num;
+ POSIX_GUARD(s2n_config_set_session_tickets_onoff(config, true));
+
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_add_new_tickets_to_send(struct s2n_connection *conn, uint8_t num)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_GUARD_RESULT(s2n_psk_validate_keying_material(conn));
+
+ uint32_t out = conn->tickets_to_send + num;
+ POSIX_ENSURE(out <= UINT16_MAX, S2N_ERR_INTEGER_OVERFLOW);
+ conn->tickets_to_send = out;
+
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_get_tickets_sent(struct s2n_connection *conn, uint16_t *num)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(num);
+ POSIX_ENSURE(conn->mode == S2N_SERVER, S2N_ERR_CLIENT_MODE);
+ *num = conn->tickets_sent;
+ return S2N_SUCCESS;
+}
+
+int s2n_connection_set_server_keying_material_lifetime(struct s2n_connection *conn, uint32_t lifetime_in_secs)
+{
+ POSIX_ENSURE_REF(conn);
+ conn->server_keying_material_lifetime = lifetime_in_secs;
+ return S2N_SUCCESS;
+}
+
+int s2n_config_set_session_ticket_cb(struct s2n_config *config, s2n_session_ticket_fn callback, void *ctx)
+{
+ POSIX_ENSURE_MUT(config);
+
+ config->session_ticket_cb = callback;
+ config->session_ticket_ctx = ctx;
+ return S2N_SUCCESS;
+}
+
+int s2n_session_ticket_get_data_len(struct s2n_session_ticket *ticket, size_t *data_len)
+{
+ POSIX_ENSURE_REF(ticket);
+ POSIX_ENSURE_MUT(data_len);
+
+ *data_len = ticket->ticket_data.size;
+ return S2N_SUCCESS;
+}
+
+int s2n_session_ticket_get_data(struct s2n_session_ticket *ticket, size_t max_data_len, uint8_t *data)
+{
+ POSIX_ENSURE_REF(ticket);
+ POSIX_ENSURE_MUT(data);
+
+ POSIX_ENSURE(ticket->ticket_data.size <= max_data_len, S2N_ERR_SERIALIZED_SESSION_STATE_TOO_LONG);
+ POSIX_CHECKED_MEMCPY(data, ticket->ticket_data.data, ticket->ticket_data.size);
+
+ return S2N_SUCCESS;
+}
+
+int s2n_session_ticket_get_lifetime(struct s2n_session_ticket *ticket, uint32_t *session_lifetime)
+{
+ POSIX_ENSURE_REF(ticket);
+ POSIX_ENSURE_REF(session_lifetime);
+
+ *session_lifetime = ticket->session_lifetime;
+
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_resume.h b/contrib/restricted/aws/s2n/tls/s2n_resume.h
index c58025e41f..2d104d6b4c 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_resume.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_resume.h
@@ -19,16 +19,22 @@
#include "stuffer/s2n_stuffer.h"
-#define S2N_SERIALIZED_FORMAT_VERSION 1
#define S2N_STATE_LIFETIME_IN_NANOS 54000000000000 /* 15 hours */
-#define S2N_STATE_SIZE_IN_BYTES (1 + 8 + 1 + S2N_TLS_CIPHER_SUITE_LEN + S2N_TLS_SECRET_LEN)
+#define S2N_TLS12_STATE_SIZE_IN_BYTES (1 + 8 + 1 + S2N_TLS_CIPHER_SUITE_LEN + S2N_TLS_SECRET_LEN + 1)
+#define S2N_TLS13_FIXED_STATE_SIZE 21
+#define S2N_TLS13_FIXED_EARLY_DATA_STATE_SIZE 3
+
#define S2N_TLS_SESSION_CACHE_TTL (6 * 60 * 60)
#define S2N_TICKET_KEY_NAME_LEN 16
#define S2N_TICKET_AAD_IMPLICIT_LEN 12
#define S2N_TICKET_AAD_LEN (S2N_TICKET_AAD_IMPLICIT_LEN + S2N_TICKET_KEY_NAME_LEN)
#define S2N_AES256_KEY_LEN 32
#define ONE_SEC_IN_NANOS 1000000000
-#define S2N_TICKET_SIZE_IN_BYTES (S2N_TICKET_KEY_NAME_LEN + S2N_TLS_GCM_IV_LEN + S2N_STATE_SIZE_IN_BYTES + S2N_TLS_GCM_TAG_LEN)
+#define ONE_MILLISEC_IN_NANOS 1000000
+#define ONE_WEEK_IN_SEC 604800
+#define S2N_TLS12_TICKET_SIZE_IN_BYTES (S2N_TICKET_KEY_NAME_LEN + S2N_TLS_GCM_IV_LEN + \
+ S2N_TLS12_STATE_SIZE_IN_BYTES + S2N_TLS_GCM_TAG_LEN)
+
#define S2N_TICKET_ENCRYPT_DECRYPT_KEY_LIFETIME_IN_NANOS 7200000000000 /* 2 hours */
#define S2N_TICKET_DECRYPT_KEY_LIFETIME_IN_NANOS 46800000000000 /* 13 hours */
#define S2N_STATE_FORMAT_LEN 1
@@ -37,6 +43,11 @@
#define S2N_GREATER_OR_EQUAL 1
#define S2N_LESS_THAN -1
+#define S2N_TLS12_SESSION_SIZE S2N_STATE_FORMAT_LEN + \
+ S2N_SESSION_TICKET_SIZE_LEN + \
+ S2N_TLS12_TICKET_SIZE_IN_BYTES + \
+ S2N_TLS12_STATE_SIZE_IN_BYTES
+
struct s2n_connection;
struct s2n_config;
@@ -52,9 +63,19 @@ struct s2n_ticket_key_weight {
uint8_t key_index;
};
+struct s2n_ticket_fields {
+ struct s2n_blob session_secret;
+ uint32_t ticket_age_add;
+};
+
+struct s2n_session_ticket {
+ struct s2n_blob ticket_data;
+ uint32_t session_lifetime;
+};
+
extern struct s2n_ticket_key *s2n_find_ticket_key(struct s2n_config *config, const uint8_t *name);
extern int s2n_encrypt_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *to);
-extern int s2n_decrypt_session_ticket(struct s2n_connection *conn);
+extern int s2n_decrypt_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *from);
extern int s2n_encrypt_session_cache(struct s2n_connection *conn, struct s2n_stuffer *to);
extern int s2n_decrypt_session_cache(struct s2n_connection *conn, struct s2n_stuffer *from);
extern int s2n_config_is_encrypt_decrypt_key_available(struct s2n_config *config);
@@ -67,6 +88,14 @@ typedef enum {
S2N_STATE_WITH_SESSION_TICKET
} s2n_client_tls_session_state_format;
+typedef enum {
+ S2N_SERIALIZED_FORMAT_TLS12_V1 = 1,
+ S2N_SERIALIZED_FORMAT_TLS13_V1,
+ S2N_SERIALIZED_FORMAT_TLS12_V2,
+ S2N_SERIALIZED_FORMAT_TLS12_V3,
+} s2n_serial_format_version;
+
extern int s2n_allowed_to_cache_connection(struct s2n_connection *conn);
extern int s2n_resume_from_cache(struct s2n_connection *conn);
-extern int s2n_store_to_cache(struct s2n_connection *conn);
+S2N_RESULT s2n_store_to_cache(struct s2n_connection *conn);
+S2N_RESULT s2n_connection_get_session_state_size(struct s2n_connection *conn, size_t *state_size);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
index 388fb25b56..90c0cb16a3 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-#include <s2n.h>
+#include "api/s2n.h"
#include "tls/s2n_security_policies.h"
#include "tls/s2n_connection.h"
@@ -27,9 +27,9 @@ const struct s2n_security_policy security_policy_20170210 = {
.ecc_preferences = &s2n_ecc_preferences_20140601,
};
-const struct s2n_security_policy security_policy_20201110 = {
+const struct s2n_security_policy security_policy_default_tls13 = {
.minimum_protocol_version = S2N_TLS10,
- .cipher_preferences = &cipher_preferences_20190801,
+ .cipher_preferences = &cipher_preferences_20210831,
.kem_preferences = &kem_preferences_null,
.signature_preferences = &s2n_signature_preferences_20200207,
.certificate_signature_preferences = &s2n_certificate_signature_preferences_20201110,
@@ -70,6 +70,14 @@ const struct s2n_security_policy security_policy_20170405 = {
.ecc_preferences = &s2n_ecc_preferences_20140601,
};
+const struct s2n_security_policy security_policy_20170405_gcm = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_20170405_gcm,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20140601,
+ .ecc_preferences = &s2n_ecc_preferences_20140601,
+};
+
const struct s2n_security_policy security_policy_elb_2015_04 = {
.minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &elb_security_policy_2015_04,
@@ -281,6 +289,46 @@ const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2019_legacy
.ecc_preferences = &s2n_ecc_preferences_20140601,
};
+const struct s2n_security_policy security_policy_aws_crt_sdk_ssl_v3 = {
+ .minimum_protocol_version = S2N_SSLv3,
+ .cipher_preferences = &cipher_preferences_aws_crt_sdk_ssl_v3,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_aws_crt_sdk_tls_10 = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_aws_crt_sdk_default,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_aws_crt_sdk_tls_11 = {
+ .minimum_protocol_version = S2N_TLS11,
+ .cipher_preferences = &cipher_preferences_aws_crt_sdk_default,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_aws_crt_sdk_tls_12 = {
+ .minimum_protocol_version = S2N_TLS12,
+ .cipher_preferences = &cipher_preferences_aws_crt_sdk_default,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_aws_crt_sdk_tls_13 = {
+ .minimum_protocol_version = S2N_TLS13,
+ .cipher_preferences = &cipher_preferences_aws_crt_sdk_tls_13,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
const struct s2n_security_policy security_policy_kms_tls_1_0_2018_10 = {
.minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &cipher_preferences_kms_tls_1_0_2018_10,
@@ -289,6 +337,14 @@ const struct s2n_security_policy security_policy_kms_tls_1_0_2018_10 = {
.ecc_preferences = &s2n_ecc_preferences_20140601,
};
+const struct s2n_security_policy security_policy_kms_tls_1_0_2021_08 = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_kms_tls_1_0_2021_08,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2019_06 = {
.minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &cipher_preferences_kms_pq_tls_1_0_2019_06,
@@ -337,6 +393,88 @@ const struct s2n_security_policy security_policy_pq_tls_1_0_2020_12 = {
.ecc_preferences = &s2n_ecc_preferences_20200310,
};
+const struct s2n_security_policy security_policy_pq_tls_1_1_2021_05_17 = {
+ .minimum_protocol_version = S2N_TLS11,
+ .cipher_preferences = &cipher_preferences_pq_tls_1_1_2021_05_17,
+ .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05,
+ .signature_preferences = &s2n_signature_preferences_20140601,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_18 = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_pq_tls_1_0_2021_05_18,
+ .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05,
+ .signature_preferences = &s2n_signature_preferences_20140601,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_19 = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_pq_tls_1_0_2021_05_19,
+ .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05,
+ .signature_preferences = &s2n_signature_preferences_20140601,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_20 = {
+ .minimum_protocol_version = S2N_TLS10,
+ /* Yes, this is the same cipher_preferences as kms_pq_tls_1_0_2020_07. Both allow Kyber, BIKE, SIKE. The difference
+ * between these policies is the kem_preferences, which have been updated to prefer Round 3 over Round 2. */
+ .cipher_preferences = &cipher_preferences_kms_pq_tls_1_0_2020_07,
+ .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05,
+ .signature_preferences = &s2n_signature_preferences_20140601,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_pq_tls_1_1_2021_05_21 = {
+ .minimum_protocol_version = S2N_TLS11,
+ .cipher_preferences = &cipher_preferences_pq_tls_1_1_2021_05_21,
+ .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_22 = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_pq_tls_1_0_2021_05_22,
+ .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_23 = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_pq_tls_1_0_2021_05_23,
+ .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_24 = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_pq_tls_1_0_2021_05_24,
+ .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_25 = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_pq_tls_1_0_2021_05_25,
+ .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05,
+ .signature_preferences = &s2n_signature_preferences_20140601,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_26 = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_pq_tls_1_0_2021_05_26,
+ .kem_preferences = &kem_preferences_pq_tls_1_0_2021_05,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
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,
@@ -345,6 +483,14 @@ const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10 = {
.ecc_preferences = &s2n_ecc_preferences_20140601,
};
+const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2021_08 = {
+ .minimum_protocol_version = S2N_TLS12,
+ .cipher_preferences = &cipher_preferences_kms_fips_tls_1_2_2021_08,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20140601,
+};
+
const struct s2n_security_policy security_policy_20140601 = {
.minimum_protocol_version = S2N_SSLv3,
.cipher_preferences = &cipher_preferences_20140601,
@@ -441,6 +587,30 @@ const struct s2n_security_policy security_policy_20190214 = {
.ecc_preferences = &s2n_ecc_preferences_20140601,
};
+const struct s2n_security_policy security_policy_20190214_gcm = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_20190214_gcm,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20140601,
+ .ecc_preferences = &s2n_ecc_preferences_20140601,
+};
+
+const struct s2n_security_policy security_policy_20210825 = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_20210825,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
+const struct s2n_security_policy security_policy_20210825_gcm = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_20210825_gcm,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20200207,
+ .ecc_preferences = &s2n_ecc_preferences_20200310,
+};
+
const struct s2n_security_policy security_policy_20170328 = {
.minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &cipher_preferences_20170328,
@@ -449,6 +619,14 @@ const struct s2n_security_policy security_policy_20170328 = {
.ecc_preferences = &s2n_ecc_preferences_20140601,
};
+const struct s2n_security_policy security_policy_20170328_gcm = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_20170328_gcm,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20140601,
+ .ecc_preferences = &s2n_ecc_preferences_20140601,
+};
+
const struct s2n_security_policy security_policy_20170718 = {
.minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &cipher_preferences_20170718,
@@ -457,6 +635,14 @@ const struct s2n_security_policy security_policy_20170718 = {
.ecc_preferences = &s2n_ecc_preferences_20140601,
};
+const struct s2n_security_policy security_policy_20170718_gcm = {
+ .minimum_protocol_version = S2N_TLS10,
+ .cipher_preferences = &cipher_preferences_20170718_gcm,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20140601,
+ .ecc_preferences = &s2n_ecc_preferences_20140601,
+};
+
const struct s2n_security_policy security_policy_20201021 = {
.minimum_protocol_version = S2N_TLS10,
.cipher_preferences = &cipher_preferences_20190122,
@@ -465,6 +651,22 @@ const struct s2n_security_policy security_policy_20201021 = {
.ecc_preferences = &s2n_ecc_preferences_20201021,
};
+const struct s2n_security_policy security_policy_20210816 = {
+ .minimum_protocol_version = S2N_TLS12,
+ .cipher_preferences = &cipher_preferences_20210816,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20210816,
+ .ecc_preferences = &s2n_ecc_preferences_20210816,
+};
+
+const struct s2n_security_policy security_policy_20210816_gcm = {
+ .minimum_protocol_version = S2N_TLS12,
+ .cipher_preferences = &cipher_preferences_20210816_gcm,
+ .kem_preferences = &kem_preferences_null,
+ .signature_preferences = &s2n_signature_preferences_20210816,
+ .ecc_preferences = &s2n_ecc_preferences_20210816,
+};
+
const struct s2n_security_policy security_policy_test_all = {
.minimum_protocol_version = S2N_SSLv3,
.cipher_preferences = &cipher_preferences_test_all,
@@ -531,7 +733,7 @@ const struct s2n_security_policy security_policy_null = {
struct s2n_security_policy_selection security_policy_selection[] = {
{ .version="default", .security_policy=&security_policy_20170210, .ecc_extension_required=0, .pq_kem_extension_required=0 },
- { .version="default_tls13", .security_policy=&security_policy_20201110, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="default_tls13", .security_policy=&security_policy_default_tls13, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="default_fips", .security_policy=&security_policy_20170405, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="ELBSecurityPolicy-TLS-1-0-2015-04", .security_policy=&security_policy_elb_2015_04, .ecc_extension_required=0, .pq_kem_extension_required=0 },
/* Not a mistake. TLS-1-0-2015-05 and 2016-08 are equivalent */
@@ -563,14 +765,32 @@ struct s2n_security_policy_selection security_policy_selection[] = {
{ .version="CloudFront-TLS-1-1-2016-Legacy", .security_policy=&security_policy_cloudfront_tls_1_1_2016_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="CloudFront-TLS-1-2-2018-Legacy", .security_policy=&security_policy_cloudfront_tls_1_2_2018_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="CloudFront-TLS-1-2-2019-Legacy", .security_policy=&security_policy_cloudfront_tls_1_2_2019_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="AWS-CRT-SDK-SSLv3.0", .security_policy=&security_policy_aws_crt_sdk_ssl_v3, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="AWS-CRT-SDK-TLSv1.0", .security_policy=&security_policy_aws_crt_sdk_tls_10, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="AWS-CRT-SDK-TLSv1.1", .security_policy=&security_policy_aws_crt_sdk_tls_11, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="AWS-CRT-SDK-TLSv1.2", .security_policy=&security_policy_aws_crt_sdk_tls_12, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="AWS-CRT-SDK-TLSv1.3", .security_policy=&security_policy_aws_crt_sdk_tls_13, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ /* KMS TLS Policies*/
{ .version="KMS-TLS-1-0-2018-10", .security_policy=&security_policy_kms_tls_1_0_2018_10, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="KMS-TLS-1-0-2021-08", .security_policy=&security_policy_kms_tls_1_0_2021_08, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="KMS-FIPS-TLS-1-2-2018-10", .security_policy=&security_policy_kms_fips_tls_1_2_2018_10, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="KMS-FIPS-TLS-1-2-2021-08", .security_policy=&security_policy_kms_fips_tls_1_2_2021_08, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="KMS-PQ-TLS-1-0-2019-06", .security_policy=&security_policy_kms_pq_tls_1_0_2019_06, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .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 },
- { .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="PQ-TLS-1-1-2021-05-17", .security_policy=&security_policy_pq_tls_1_1_2021_05_17, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="PQ-TLS-1-0-2021-05-18", .security_policy=&security_policy_pq_tls_1_0_2021_05_18, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="PQ-TLS-1-0-2021-05-19", .security_policy=&security_policy_pq_tls_1_0_2021_05_19, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="PQ-TLS-1-0-2021-05-20", .security_policy=&security_policy_pq_tls_1_0_2021_05_20, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="PQ-TLS-1-1-2021-05-21", .security_policy=&security_policy_pq_tls_1_1_2021_05_21, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="PQ-TLS-1-0-2021-05-22", .security_policy=&security_policy_pq_tls_1_0_2021_05_22, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="PQ-TLS-1-0-2021-05-23", .security_policy=&security_policy_pq_tls_1_0_2021_05_23, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="PQ-TLS-1-0-2021-05-24", .security_policy=&security_policy_pq_tls_1_0_2021_05_24, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="PQ-TLS-1-0-2021-05-25", .security_policy=&security_policy_pq_tls_1_0_2021_05_25, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="PQ-TLS-1-0-2021-05-26", .security_policy=&security_policy_pq_tls_1_0_2021_05_26, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20140601", .security_policy=&security_policy_20140601, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20141001", .security_policy=&security_policy_20141001, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20150202", .security_policy=&security_policy_20150202, .ecc_extension_required=0, .pq_kem_extension_required=0 },
@@ -581,9 +801,15 @@ struct s2n_security_policy_selection security_policy_selection[] = {
{ .version="20160824", .security_policy=&security_policy_20160824, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20170210", .security_policy=&security_policy_20170210, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20170328", .security_policy=&security_policy_20170328, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="20170328_gcm", .security_policy=&security_policy_20170328_gcm, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20190214", .security_policy=&security_policy_20190214, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="20190214_gcm", .security_policy=&security_policy_20190214_gcm, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="20210825", .security_policy=&security_policy_20210825, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="20210825_gcm", .security_policy=&security_policy_20210825_gcm, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20170405", .security_policy=&security_policy_20170405, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="20170405_gcm", .security_policy=&security_policy_20170405_gcm, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20170718", .security_policy=&security_policy_20170718, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="20170718_gcm", .security_policy=&security_policy_20170718_gcm, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20190120", .security_policy=&security_policy_20190120, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20190121", .security_policy=&security_policy_20190121, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20190122", .security_policy=&security_policy_20190122, .ecc_extension_required=0, .pq_kem_extension_required=0 },
@@ -591,6 +817,8 @@ struct s2n_security_policy_selection security_policy_selection[] = {
{ .version="20190802", .security_policy=&security_policy_20190802, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20200207", .security_policy=&security_policy_test_all_tls13, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="20201021", .security_policy=&security_policy_20201021, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="20210816", .security_policy=&security_policy_20210816, .ecc_extension_required=0, .pq_kem_extension_required=0 },
+ { .version="20210816_GCM", .security_policy=&security_policy_20210816_gcm, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="test_all", .security_policy=&security_policy_test_all, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="test_all_fips", .security_policy=&security_policy_test_all_fips, .ecc_extension_required=0, .pq_kem_extension_required=0 },
{ .version="test_all_ecdsa", .security_policy=&security_policy_test_all_ecdsa, .ecc_extension_required=0, .pq_kem_extension_required=0 },
@@ -604,8 +832,8 @@ struct s2n_security_policy_selection security_policy_selection[] = {
int s2n_find_security_policy_from_version(const char *version, const struct s2n_security_policy **security_policy)
{
- notnull_check(version);
- notnull_check(security_policy);
+ POSIX_ENSURE_REF(version);
+ POSIX_ENSURE_REF(security_policy);
for (int i = 0; security_policy_selection[i].version != NULL; i++) {
if (!strcasecmp(version, security_policy_selection[i].version)) {
@@ -614,18 +842,21 @@ int s2n_find_security_policy_from_version(const char *version, const struct s2n_
}
}
- S2N_ERROR(S2N_ERR_INVALID_SECURITY_POLICY);
+ POSIX_BAIL(S2N_ERR_INVALID_SECURITY_POLICY);
}
int s2n_config_set_cipher_preferences(struct s2n_config *config, const char *version)
{
const struct s2n_security_policy *security_policy = NULL;
- GUARD(s2n_find_security_policy_from_version(version, &security_policy));
- ENSURE_POSIX_REF(security_policy);
- ENSURE_POSIX_REF(security_policy->cipher_preferences);
- ENSURE_POSIX_REF(security_policy->kem_preferences);
- ENSURE_POSIX_REF(security_policy->signature_preferences);
- ENSURE_POSIX_REF(security_policy->ecc_preferences);
+ POSIX_GUARD(s2n_find_security_policy_from_version(version, &security_policy));
+ POSIX_ENSURE_REF(security_policy);
+ POSIX_ENSURE_REF(security_policy->cipher_preferences);
+ POSIX_ENSURE_REF(security_policy->kem_preferences);
+ POSIX_ENSURE_REF(security_policy->signature_preferences);
+ POSIX_ENSURE_REF(security_policy->ecc_preferences);
+
+ /* If the security policy's minimum version is higher than what libcrypto supports, return an error. */
+ POSIX_ENSURE((security_policy->minimum_protocol_version <= s2n_get_highest_fully_supported_tls_version()), S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
config->security_policy = security_policy;
return 0;
@@ -634,12 +865,15 @@ int s2n_config_set_cipher_preferences(struct s2n_config *config, const char *ver
int s2n_connection_set_cipher_preferences(struct s2n_connection *conn, const char *version)
{
const struct s2n_security_policy *security_policy = NULL;
- GUARD(s2n_find_security_policy_from_version(version, &security_policy));
- ENSURE_POSIX_REF(security_policy);
- ENSURE_POSIX_REF(security_policy->cipher_preferences);
- ENSURE_POSIX_REF(security_policy->kem_preferences);
- ENSURE_POSIX_REF(security_policy->signature_preferences);
- ENSURE_POSIX_REF(security_policy->ecc_preferences);
+ POSIX_GUARD(s2n_find_security_policy_from_version(version, &security_policy));
+ POSIX_ENSURE_REF(security_policy);
+ POSIX_ENSURE_REF(security_policy->cipher_preferences);
+ POSIX_ENSURE_REF(security_policy->kem_preferences);
+ POSIX_ENSURE_REF(security_policy->signature_preferences);
+ POSIX_ENSURE_REF(security_policy->ecc_preferences);
+
+ /* If the security policy's minimum version is higher than what libcrypto supports, return an error. */
+ POSIX_ENSURE((security_policy->minimum_protocol_version <= s2n_get_highest_fully_supported_tls_version()), S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
conn->security_policy_override = security_policy;
return 0;
@@ -649,33 +883,30 @@ int s2n_security_policies_init()
{
for (int i = 0; security_policy_selection[i].version != NULL; i++) {
const struct s2n_security_policy *security_policy = security_policy_selection[i].security_policy;
- notnull_check(security_policy);
+ POSIX_ENSURE_REF(security_policy);
const struct s2n_cipher_preferences *cipher_preference = security_policy->cipher_preferences;
- notnull_check(cipher_preference);
+ POSIX_ENSURE_REF(cipher_preference);
const struct s2n_kem_preferences *kem_preference = security_policy->kem_preferences;
- notnull_check(kem_preference);
+ POSIX_ENSURE_REF(kem_preference);
const struct s2n_ecc_preferences *ecc_preference = security_policy->ecc_preferences;
- notnull_check(ecc_preference);
- GUARD(s2n_check_ecc_preferences_curves_list(ecc_preference));
+ POSIX_ENSURE_REF(ecc_preference);
+ POSIX_GUARD(s2n_check_ecc_preferences_curves_list(ecc_preference));
const struct s2n_signature_preferences *certificate_signature_preference = security_policy->certificate_signature_preferences;
if (certificate_signature_preference != NULL) {
- GUARD_AS_POSIX(s2n_validate_certificate_signature_preferences(certificate_signature_preference));
+ POSIX_GUARD_RESULT(s2n_validate_certificate_signature_preferences(certificate_signature_preference));
}
if (security_policy != &security_policy_null) {
- /* catch any offending security policy that does not support P-256 */
- S2N_ERROR_IF(!s2n_ecc_preferences_includes_curve(ecc_preference, TLS_EC_CURVE_SECP_256_R1), S2N_ERR_INVALID_SECURITY_POLICY);
+ /* All policies must have at least one ecc curve configured. */
+ S2N_ERROR_IF(ecc_preference->count == 0, S2N_ERR_INVALID_SECURITY_POLICY);
}
for (int j = 0; j < cipher_preference->count; j++) {
struct s2n_cipher_suite *cipher = cipher_preference->suites[j];
- notnull_check(cipher);
+ POSIX_ENSURE_REF(cipher);
- /* TLS1.3 does not include key exchange algorithms in its cipher suites,
- * but the elliptic curves extension is always required. */
if (cipher->minimum_required_tls_version >= S2N_TLS13) {
- security_policy_selection[i].ecc_extension_required = 1;
security_policy_selection[i].supports_tls13 = 1;
}
@@ -683,16 +914,16 @@ int s2n_security_policies_init()
S2N_ERROR_IF(s2n_is_valid_tls13_cipher(cipher->iana_value) ^
(cipher->minimum_required_tls_version >= S2N_TLS13), S2N_ERR_INVALID_SECURITY_POLICY);
- if (s2n_kex_includes(cipher->key_exchange_alg, &s2n_ecdhe)) {
+ if (s2n_cipher_suite_requires_ecc_extension(cipher)) {
security_policy_selection[i].ecc_extension_required = 1;
}
- if (s2n_kex_includes(cipher->key_exchange_alg, &s2n_kem)) {
+ if (s2n_cipher_suite_requires_pq_extension(cipher)) {
security_policy_selection[i].pq_kem_extension_required = 1;
}
}
- GUARD(s2n_validate_kem_preferences(kem_preference, security_policy_selection[i].pq_kem_extension_required));
+ POSIX_GUARD(s2n_validate_kem_preferences(kem_preference, security_policy_selection[i].pq_kem_extension_required));
}
return 0;
}
@@ -708,6 +939,18 @@ bool s2n_ecc_is_extension_required(const struct s2n_security_policy *security_po
return 1 == security_policy_selection[i].ecc_extension_required;
}
}
+
+ /* If cipher preference is not in the official list, compute the result */
+ const struct s2n_cipher_preferences *cipher_preferences = security_policy->cipher_preferences;
+ if (cipher_preferences == NULL) {
+ return false;
+ }
+ for (uint8_t i = 0; i < cipher_preferences->count; i++) {
+ if (s2n_cipher_suite_requires_ecc_extension(cipher_preferences->suites[i])) {
+ return true;
+ }
+ }
+
return false;
}
@@ -722,6 +965,17 @@ bool s2n_pq_kem_is_extension_required(const struct s2n_security_policy *security
return 1 == security_policy_selection[i].pq_kem_extension_required;
}
}
+
+ /* If cipher preference is not in the official list, compute the result */
+ const struct s2n_cipher_preferences *cipher_preferences = security_policy->cipher_preferences;
+ if (cipher_preferences == NULL) {
+ return false;
+ }
+ for (uint8_t i = 0; i < cipher_preferences->count; i++) {
+ if (s2n_cipher_suite_requires_pq_extension(cipher_preferences->suites[i])) {
+ return true;
+ }
+ }
return false;
}
@@ -747,7 +1001,7 @@ bool s2n_security_policy_supports_tls13(const struct s2n_security_policy *securi
}
for (uint8_t i = 0; i < cipher_preferences->count; i++) {
- if (s2n_is_valid_tls13_cipher(cipher_preferences->suites[i]->iana_value)) {
+ if (cipher_preferences->suites[i]->minimum_required_tls_version >= S2N_TLS13) {
return true;
}
}
@@ -757,13 +1011,13 @@ bool s2n_security_policy_supports_tls13(const struct s2n_security_policy *securi
int s2n_connection_is_valid_for_cipher_preferences(struct s2n_connection *conn, const char *version)
{
- notnull_check(conn);
- notnull_check(version);
- notnull_check(conn->secure.cipher_suite);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(version);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite);
const struct s2n_security_policy *security_policy = NULL;
- GUARD(s2n_find_security_policy_from_version(version, &security_policy));
- notnull_check(security_policy);
+ POSIX_GUARD(s2n_find_security_policy_from_version(version, &security_policy));
+ POSIX_ENSURE_REF(security_policy);
/* make sure we dont use a tls version lower than that configured by the version */
if (s2n_connection_get_actual_protocol_version(conn) < security_policy->minimum_protocol_version) {
@@ -771,7 +1025,7 @@ int s2n_connection_is_valid_for_cipher_preferences(struct s2n_connection *conn,
}
struct s2n_cipher_suite *cipher = conn->secure.cipher_suite;
- notnull_check(cipher);
+ POSIX_ENSURE_REF(cipher);
for (int i = 0; i < security_policy->cipher_preferences->count; ++i) {
if (0 == memcmp(security_policy->cipher_preferences->suites[i]->iana_value, cipher->iana_value, S2N_TLS_CIPHER_SUITE_LEN)) {
return 1;
@@ -782,21 +1036,22 @@ int s2n_connection_is_valid_for_cipher_preferences(struct s2n_connection *conn,
}
int s2n_validate_kem_preferences(const struct s2n_kem_preferences *kem_preferences, bool pq_kem_extension_required) {
- notnull_check(kem_preferences);
+ POSIX_ENSURE_REF(kem_preferences);
/* Basic sanity checks to assert that the count is 0 if and only if the associated list is NULL */
- ENSURE_POSIX(S2N_IFF(kem_preferences->tls13_kem_group_count == 0, kem_preferences->tls13_kem_groups == NULL),
+ POSIX_ENSURE(S2N_IFF(kem_preferences->tls13_kem_group_count == 0, kem_preferences->tls13_kem_groups == NULL),
S2N_ERR_INVALID_SECURITY_POLICY);
- ENSURE_POSIX(S2N_IFF(kem_preferences->kem_count == 0, kem_preferences->kems == NULL),
+ POSIX_ENSURE(S2N_IFF(kem_preferences->kem_count == 0, kem_preferences->kems == NULL),
S2N_ERR_INVALID_SECURITY_POLICY);
+ POSIX_ENSURE(kem_preferences->tls13_kem_group_count <= S2N_SUPPORTED_KEM_GROUPS_COUNT, S2N_ERR_ARRAY_INDEX_OOB);
/* The PQ KEM extension is applicable only to TLS 1.2 */
if (pq_kem_extension_required) {
- ENSURE_POSIX(kem_preferences->kem_count > 0, S2N_ERR_INVALID_SECURITY_POLICY);
- ENSURE_POSIX(kem_preferences->kems != NULL, S2N_ERR_INVALID_SECURITY_POLICY);
+ POSIX_ENSURE(kem_preferences->kem_count > 0, S2N_ERR_INVALID_SECURITY_POLICY);
+ POSIX_ENSURE(kem_preferences->kems != NULL, S2N_ERR_INVALID_SECURITY_POLICY);
} else {
- ENSURE_POSIX(kem_preferences->kem_count == 0, S2N_ERR_INVALID_SECURITY_POLICY);
- ENSURE_POSIX(kem_preferences->kems == NULL, S2N_ERR_INVALID_SECURITY_POLICY);
+ POSIX_ENSURE(kem_preferences->kem_count == 0, S2N_ERR_INVALID_SECURITY_POLICY);
+ POSIX_ENSURE(kem_preferences->kems == NULL, S2N_ERR_INVALID_SECURITY_POLICY);
}
return S2N_SUCCESS;
@@ -804,7 +1059,7 @@ int s2n_validate_kem_preferences(const struct s2n_kem_preferences *kem_preferenc
S2N_RESULT s2n_validate_certificate_signature_preferences(const struct s2n_signature_preferences *certificate_signature_preferences)
{
- ENSURE_REF(certificate_signature_preferences);
+ RESULT_ENSURE_REF(certificate_signature_preferences);
size_t rsa_pss_scheme_count = 0;
@@ -817,6 +1072,6 @@ S2N_RESULT s2n_validate_certificate_signature_preferences(const struct s2n_signa
/* The Openssl function used to parse signatures off certificates does not differentiate between any rsa pss
* signature schemes. Therefore a security policy with a certificate signatures preference list must include
* all rsa_pss signature schemes. */
- ENSURE(rsa_pss_scheme_count == NUM_RSA_PSS_SCHEMES || rsa_pss_scheme_count == 0, S2N_ERR_INVALID_SECURITY_POLICY);
+ RESULT_ENSURE(rsa_pss_scheme_count == NUM_RSA_PSS_SCHEMES || rsa_pss_scheme_count == 0, S2N_ERR_INVALID_SECURITY_POLICY);
return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
index f724eb1934..be28fb584a 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h
@@ -53,12 +53,16 @@ extern const struct s2n_security_policy security_policy_20160804;
extern const struct s2n_security_policy security_policy_20160824;
extern const struct s2n_security_policy security_policy_20170210;
extern const struct s2n_security_policy security_policy_20170328;
+extern const struct s2n_security_policy security_policy_20170328_gcm;
extern const struct s2n_security_policy security_policy_20170405;
+extern const struct s2n_security_policy security_policy_20170405_gcm;
extern const struct s2n_security_policy security_policy_20170718;
+extern const struct s2n_security_policy security_policy_20170718_gcm;
extern const struct s2n_security_policy security_policy_20190214;
+extern const struct s2n_security_policy security_policy_20190214_gcm;
extern const struct s2n_security_policy security_policy_20190801;
extern const struct s2n_security_policy security_policy_20190802;
-extern const struct s2n_security_policy security_policy_20201110;
+extern const struct s2n_security_policy security_policy_default_tls13;
extern const struct s2n_security_policy security_policy_test_all;
extern const struct s2n_security_policy security_policy_test_all_tls12;
@@ -79,12 +83,28 @@ 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;
+extern const struct s2n_security_policy security_policy_aws_crt_sdk_ssl_v3;
+extern const struct s2n_security_policy security_policy_aws_crt_sdk_tls_10;
+extern const struct s2n_security_policy security_policy_aws_crt_sdk_tls_11;
+extern const struct s2n_security_policy security_policy_aws_crt_sdk_tls_12;
+extern const struct s2n_security_policy security_policy_aws_crt_sdk_tls_13;
+
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;
+extern const struct s2n_security_policy security_policy_pq_tls_1_1_2021_05_17;
+extern const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_18;
+extern const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_19;
+extern const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_20;
+extern const struct s2n_security_policy security_policy_pq_tls_1_1_2021_05_21;
+extern const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_22;
+extern const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_23;
+extern const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_24;
+extern const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_25;
+extern const struct s2n_security_policy security_policy_pq_tls_1_0_2021_05_26;
extern const struct s2n_security_policy security_policy_cloudfront_upstream;
extern const struct s2n_security_policy security_policy_cloudfront_upstream_tls10;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_send.c b/contrib/restricted/aws/s2n/tls/s2n_send.c
index 4f59054845..013fa28b66 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_send.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_send.c
@@ -15,7 +15,7 @@
#include <sys/param.h>
#include <errno.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include "error/s2n_errno.h"
@@ -45,9 +45,9 @@ int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * blocked)
w = s2n_connection_send_stuffer(&conn->out, conn, s2n_stuffer_data_available(&conn->out));
if (w < 0) {
if (errno == EWOULDBLOCK || errno == EAGAIN) {
- S2N_ERROR(S2N_ERR_IO_BLOCKED);
+ POSIX_BAIL(S2N_ERR_IO_BLOCKED);
}
- S2N_ERROR(S2N_ERR_IO);
+ POSIX_BAIL(S2N_ERR_IO);
}
conn->wire_bytes_out += w;
}
@@ -55,15 +55,15 @@ int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * blocked)
if (conn->closing) {
conn->closed = 1;
}
- GUARD(s2n_stuffer_rewrite(&conn->out));
+ POSIX_GUARD(s2n_stuffer_rewrite(&conn->out));
/* If there's an alert pending out, send that */
if (s2n_stuffer_data_available(&conn->reader_alert_out) == 2) {
struct s2n_blob alert = {0};
alert.data = conn->reader_alert_out.blob.data;
alert.size = 2;
- GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
- GUARD(s2n_stuffer_rewrite(&conn->reader_alert_out));
+ POSIX_GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
+ POSIX_GUARD(s2n_stuffer_rewrite(&conn->reader_alert_out));
conn->closing = 1;
/* Actually write it ... */
@@ -75,8 +75,8 @@ int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * blocked)
struct s2n_blob alert = {0};
alert.data = conn->writer_alert_out.blob.data;
alert.size = 2;
- GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
- GUARD(s2n_stuffer_rewrite(&conn->writer_alert_out));
+ POSIX_GUARD(s2n_record_write(conn, TLS_ALERT, &alert));
+ POSIX_GUARD(s2n_stuffer_rewrite(&conn->writer_alert_out));
conn->closing = 1;
/* Actually write it ... */
@@ -92,11 +92,11 @@ ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iov
{
ssize_t user_data_sent, total_size = 0;
- S2N_ERROR_IF(conn->closed, S2N_ERR_CLOSED);
- S2N_ERROR_IF(conn->config->quic_enabled, S2N_ERR_UNSUPPORTED_WITH_QUIC);
+ POSIX_ENSURE(!conn->closed, S2N_ERR_CLOSED);
+ POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_UNSUPPORTED_WITH_QUIC);
/* Flush any pending I/O */
- GUARD(s2n_flush(conn, blocked));
+ POSIX_GUARD(s2n_flush(conn, blocked));
/* Acknowledge consumed and flushed user data as sent */
user_data_sent = conn->current_user_data_consumed;
@@ -104,7 +104,7 @@ ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iov
*blocked = S2N_BLOCKED_ON_WRITE;
uint16_t max_payload_size = 0;
- GUARD_AS_POSIX(s2n_record_max_write_payload_size(conn, &max_payload_size));
+ POSIX_GUARD_RESULT(s2n_record_max_write_payload_size(conn, &max_payload_size));
/* TLS 1.0 and SSLv3 are vulnerable to the so-called Beast attack. Work
* around this by splitting messages into one byte records, and then
@@ -129,15 +129,16 @@ ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iov
bufs = _bufs;
count = _count;
}
- for (int i = 0; i < count; i++) {
+ for (ssize_t i = 0; i < count; i++) {
total_size += bufs[i].iov_len;
}
total_size -= offs;
S2N_ERROR_IF(conn->current_user_data_consumed > total_size, S2N_ERR_SEND_SIZE);
+ POSIX_GUARD_RESULT(s2n_early_data_validate_send(conn, total_size));
if (conn->dynamic_record_timeout_threshold > 0) {
uint64_t elapsed;
- GUARD_AS_POSIX(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed));
+ POSIX_GUARD_RESULT(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed));
/* Reset record size back to a single segment after threshold seconds of inactivity */
if (elapsed - conn->last_write_elapsed > (uint64_t) conn->dynamic_record_timeout_threshold * 1000000000) {
conn->active_application_bytes_consumed = 0;
@@ -154,7 +155,7 @@ ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iov
*/
if (conn->active_application_bytes_consumed < (uint64_t) conn->dynamic_record_resize_threshold) {
uint16_t min_payload_size = 0;
- GUARD_AS_POSIX(s2n_record_min_write_payload_size(conn, &min_payload_size));
+ POSIX_GUARD_RESULT(s2n_record_min_write_payload_size(conn, &min_payload_size));
to_write = MIN(min_payload_size, to_write);
}
@@ -168,12 +169,12 @@ ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iov
}
}
- GUARD(s2n_stuffer_rewrite(&conn->out));
+ POSIX_GUARD(s2n_stuffer_rewrite(&conn->out));
- GUARD(s2n_post_handshake_send(conn, blocked));
+ POSIX_GUARD(s2n_post_handshake_send(conn, blocked));
/* Write and encrypt the record */
- GUARD(s2n_record_writev(conn, TLS_APPLICATION_DATA, bufs, count,
+ POSIX_GUARD(s2n_record_writev(conn, TLS_APPLICATION_DATA, bufs, count,
conn->current_user_data_consumed + offs, to_write));
conn->current_user_data_consumed += to_write;
conn->active_application_bytes_consumed += to_write;
@@ -200,12 +201,13 @@ ssize_t s2n_sendv_with_offset_impl(struct s2n_connection *conn, const struct iov
*blocked = S2N_NOT_BLOCKED;
+ POSIX_GUARD_RESULT(s2n_early_data_record_bytes(conn, total_size));
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);
+ POSIX_ENSURE(!conn->send_in_use, S2N_ERR_REENTRANCY);
conn->send_in_use = true;
ssize_t result = s2n_sendv_with_offset_impl(conn, bufs, count, offs, blocked);
conn->send_in_use = false;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_cert.c b/contrib/restricted/aws/s2n/tls/s2n_server_cert.c
index 0188505ae1..6be1ac6202 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_cert.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_cert.c
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-#include <s2n.h>
+#include "api/s2n.h"
#include "error/s2n_errno.h"
@@ -27,30 +27,30 @@ int s2n_server_cert_recv(struct s2n_connection *conn)
{
if (conn->actual_protocol_version == S2N_TLS13) {
uint8_t certificate_request_context_len;
- GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &certificate_request_context_len));
+ POSIX_GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &certificate_request_context_len));
S2N_ERROR_IF(certificate_request_context_len != 0, S2N_ERR_BAD_MESSAGE);
}
uint32_t size_of_all_certificates;
- GUARD(s2n_stuffer_read_uint24(&conn->handshake.io, &size_of_all_certificates));
+ POSIX_GUARD(s2n_stuffer_read_uint24(&conn->handshake.io, &size_of_all_certificates));
S2N_ERROR_IF(size_of_all_certificates > s2n_stuffer_data_available(&conn->handshake.io) || size_of_all_certificates < 3, S2N_ERR_BAD_MESSAGE);
s2n_cert_public_key public_key;
- GUARD(s2n_pkey_zero_init(&public_key));
+ POSIX_GUARD(s2n_pkey_zero_init(&public_key));
s2n_pkey_type actual_cert_pkey_type;
struct s2n_blob cert_chain = {0};
cert_chain.size = size_of_all_certificates;
cert_chain.data = s2n_stuffer_raw_read(&conn->handshake.io, size_of_all_certificates);
- notnull_check(cert_chain.data);
+ POSIX_ENSURE_REF(cert_chain.data);
- GUARD(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, conn, cert_chain.data,
- cert_chain.size, &actual_cert_pkey_type, &public_key));
+ POSIX_ENSURE(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, conn, cert_chain.data,
+ cert_chain.size, &actual_cert_pkey_type, &public_key) == S2N_CERT_OK, S2N_ERR_CERT_UNTRUSTED);
- GUARD(s2n_is_cert_type_valid_for_auth(conn, actual_cert_pkey_type));
- GUARD(s2n_pkey_setup_for_type(&public_key, actual_cert_pkey_type));
- conn->secure.server_public_key = public_key;
+ POSIX_GUARD(s2n_is_cert_type_valid_for_auth(conn, actual_cert_pkey_type));
+ POSIX_GUARD(s2n_pkey_setup_for_type(&public_key, actual_cert_pkey_type));
+ conn->handshake_params.server_public_key = public_key;
return 0;
}
@@ -62,10 +62,10 @@ int s2n_server_cert_send(struct s2n_connection *conn)
/* server's certificate request context should always be of zero length */
/* https://tools.ietf.org/html/rfc8446#section-4.4.2 */
uint8_t certificate_request_context_len = 0;
- GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, certificate_request_context_len));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, certificate_request_context_len));
}
- GUARD(s2n_send_cert_chain(conn, &conn->handshake.io, conn->handshake_params.our_chain_and_key));
+ POSIX_GUARD(s2n_send_cert_chain(conn, &conn->handshake.io, conn->handshake_params.our_chain_and_key));
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_cert_request.c b/contrib/restricted/aws/s2n/tls/s2n_server_cert_request.c
index 26dcecc56c..45790f0645 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_cert_request.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_cert_request.c
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-#include <s2n.h>
+#include "api/s2n.h"
#include "crypto/s2n_certificate.h"
#include "error/s2n_errno.h"
@@ -60,26 +60,13 @@ static uint8_t s2n_cert_type_preference_list_legacy_dss[] = {
S2N_CERT_TYPE_ECDSA_SIGN
};
-static int s2n_cert_type_to_pkey_type(s2n_cert_type cert_type_in, s2n_pkey_type *pkey_type_out) {
- switch(cert_type_in) {
- case S2N_CERT_TYPE_RSA_SIGN:
- *pkey_type_out = S2N_PKEY_TYPE_RSA;
- return 0;
- case S2N_CERT_TYPE_ECDSA_SIGN:
- *pkey_type_out = S2N_PKEY_TYPE_ECDSA;
- return 0;
- default:
- S2N_ERROR(S2N_CERT_ERR_TYPE_UNSUPPORTED);
- }
-}
-
static int s2n_recv_client_cert_preferences(struct s2n_stuffer *in, s2n_cert_type *chosen_cert_type_out)
{
uint8_t cert_types_len;
- GUARD(s2n_stuffer_read_uint8(in, &cert_types_len));
+ POSIX_GUARD(s2n_stuffer_read_uint8(in, &cert_types_len));
uint8_t *their_cert_type_pref_list = s2n_stuffer_raw_read(in, cert_types_len);
- notnull_check(their_cert_type_pref_list);
+ POSIX_ENSURE_REF(their_cert_type_pref_list);
/* Iterate through our preference list from most to least preferred, and return the first match that we find. */
for (int our_cert_pref_idx = 0; our_cert_pref_idx < sizeof(s2n_cert_type_preference_list); our_cert_pref_idx++) {
@@ -91,18 +78,19 @@ static int s2n_recv_client_cert_preferences(struct s2n_stuffer *in, s2n_cert_typ
}
}
- S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED);
+ POSIX_BAIL(S2N_ERR_CERT_TYPE_UNSUPPORTED);
}
static int s2n_set_cert_chain_as_client(struct s2n_connection *conn)
{
if (s2n_config_get_num_default_certs(conn->config) > 0) {
- GUARD(s2n_choose_sig_scheme_from_peer_preference_list(conn, &conn->handshake_params.server_sig_hash_algs,
- &conn->secure.client_cert_sig_scheme));
+ POSIX_GUARD(s2n_choose_sig_scheme_from_peer_preference_list(conn, &conn->handshake_params.server_sig_hash_algs,
+ &conn->handshake_params.client_cert_sig_scheme));
struct s2n_cert_chain_and_key *cert = s2n_config_get_single_default_cert(conn->config);
- notnull_check(cert);
+ POSIX_ENSURE_REF(cert);
conn->handshake_params.our_chain_and_key = cert;
+ conn->handshake_params.client_cert_pkey_type = s2n_cert_chain_and_key_get_pkey_type(cert);
}
return 0;
@@ -114,13 +102,13 @@ int s2n_tls13_cert_req_recv(struct s2n_connection *conn)
/* read request context length */
uint8_t request_context_length;
- GUARD(s2n_stuffer_read_uint8(in, &request_context_length));
+ POSIX_GUARD(s2n_stuffer_read_uint8(in, &request_context_length));
/* RFC 8446: This field SHALL be zero length unless used for the post-handshake authentication */
S2N_ERROR_IF(request_context_length != 0, S2N_ERR_BAD_MESSAGE);
- GUARD(s2n_extension_list_recv(S2N_EXTENSION_LIST_CERT_REQ, conn, in));
+ POSIX_GUARD(s2n_extension_list_recv(S2N_EXTENSION_LIST_CERT_REQ, conn, in));
- GUARD(s2n_set_cert_chain_as_client(conn));
+ POSIX_GUARD(s2n_set_cert_chain_as_client(conn));
return S2N_SUCCESS;
}
@@ -130,26 +118,25 @@ int s2n_cert_req_recv(struct s2n_connection *conn)
struct s2n_stuffer *in = &conn->handshake.io;
s2n_cert_type cert_type = 0;
- GUARD(s2n_recv_client_cert_preferences(in, &cert_type));
- GUARD(s2n_cert_type_to_pkey_type(cert_type, &conn->secure.client_cert_pkey_type));
+ POSIX_GUARD(s2n_recv_client_cert_preferences(in, &cert_type));
if (conn->actual_protocol_version == S2N_TLS12) {
- GUARD(s2n_recv_supported_sig_scheme_list(in, &conn->handshake_params.server_sig_hash_algs));
+ POSIX_GUARD(s2n_recv_supported_sig_scheme_list(in, &conn->handshake_params.server_sig_hash_algs));
}
uint16_t cert_authorities_len = 0;
- GUARD(s2n_stuffer_read_uint16(in, &cert_authorities_len));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &cert_authorities_len));
/* For now we don't parse X.501 encoded CA Distinguished Names.
* Don't fail just yet as we still may succeed if we provide
* right certificate or if ClientAuth is optional. */
- GUARD(s2n_stuffer_skip_read(in, cert_authorities_len));
+ POSIX_GUARD(s2n_stuffer_skip_read(in, cert_authorities_len));
/* In the future we may have more advanced logic to match a set of configured certificates against
* The cert authorities extension and the signature algorithms advertised.
* For now, this will just set the only certificate configured.
*/
- GUARD(s2n_set_cert_chain_as_client(conn));
+ POSIX_GUARD(s2n_set_cert_chain_as_client(conn));
return 0;
}
@@ -159,9 +146,9 @@ int s2n_tls13_cert_req_send(struct s2n_connection *conn)
struct s2n_stuffer *out = &conn->handshake.io;
/* Write 0 length request context https://tools.ietf.org/html/rfc8446#section-4.3.2 */
- GUARD(s2n_stuffer_write_uint8(out, 0));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, 0));
- GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_CERT_REQ, conn, out));
+ POSIX_GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_CERT_REQ, conn, out));
return S2N_SUCCESS;
}
@@ -174,24 +161,24 @@ int s2n_cert_req_send(struct s2n_connection *conn)
if (conn->config->cert_req_dss_legacy_compat_enabled) {
client_cert_preference_list_size = sizeof(s2n_cert_type_preference_list_legacy_dss);
}
- GUARD(s2n_stuffer_write_uint8(out, client_cert_preference_list_size));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, client_cert_preference_list_size));
for (int i = 0; i < client_cert_preference_list_size; i++) {
if (conn->config->cert_req_dss_legacy_compat_enabled) {
- GUARD(s2n_stuffer_write_uint8(out, s2n_cert_type_preference_list_legacy_dss[i]));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, s2n_cert_type_preference_list_legacy_dss[i]));
} else {
- GUARD(s2n_stuffer_write_uint8(out, s2n_cert_type_preference_list[i]));
+ POSIX_GUARD(s2n_stuffer_write_uint8(out, s2n_cert_type_preference_list[i]));
}
}
if (conn->actual_protocol_version == S2N_TLS12) {
- GUARD(s2n_send_supported_sig_scheme_list(conn, out));
+ POSIX_GUARD(s2n_send_supported_sig_scheme_list(conn, out));
}
/* RFC 5246 7.4.4 - If the certificate_authorities list is empty, then the
* client MAY send any certificate of the appropriate ClientCertificateType */
uint16_t acceptable_cert_authorities_len = 0;
- GUARD(s2n_stuffer_write_uint16(out, acceptable_cert_authorities_len));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, acceptable_cert_authorities_len));
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_extensions.c b/contrib/restricted/aws/s2n/tls/s2n_server_extensions.c
index 0fc8f6bb15..b604556009 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_extensions.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_extensions.c
@@ -29,10 +29,12 @@ int s2n_server_extensions_send(struct s2n_connection *conn, struct s2n_stuffer *
{
uint32_t data_available_before_extensions = s2n_stuffer_data_available(out);
- if (conn->actual_protocol_version >= S2N_TLS13) {
- GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_SERVER_HELLO_TLS13, conn, out));
+ if (s2n_is_hello_retry_message(conn)) {
+ POSIX_GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_HELLO_RETRY_REQUEST, conn, out));
+ } else if (conn->actual_protocol_version >= S2N_TLS13) {
+ POSIX_GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_SERVER_HELLO_TLS13, conn, out));
} else {
- GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_SERVER_HELLO_DEFAULT, conn, out));
+ POSIX_GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_SERVER_HELLO_DEFAULT, conn, out));
}
/* The ServerHello extension list size (uint16_t) is NOT written if the list is empty.
@@ -45,7 +47,7 @@ int s2n_server_extensions_send(struct s2n_connection *conn, struct s2n_stuffer *
* so will never produce an empty list.
*/
if(s2n_stuffer_data_available(out) - data_available_before_extensions == S2N_EMPTY_EXTENSION_LIST_SIZE) {
- GUARD(s2n_stuffer_wipe_n(out, S2N_EMPTY_EXTENSION_LIST_SIZE));
+ POSIX_GUARD(s2n_stuffer_wipe_n(out, S2N_EMPTY_EXTENSION_LIST_SIZE));
}
return S2N_SUCCESS;
@@ -54,18 +56,20 @@ int s2n_server_extensions_send(struct s2n_connection *conn, struct s2n_stuffer *
int s2n_server_extensions_recv(struct s2n_connection *conn, struct s2n_stuffer *in)
{
s2n_parsed_extensions_list parsed_extension_list = { 0 };
- GUARD(s2n_extension_list_parse(in, &parsed_extension_list));
+ POSIX_GUARD(s2n_extension_list_parse(in, &parsed_extension_list));
/* Process supported_versions first so that we know which extensions list to use.
* - If the supported_versions extension exists, then it will set server_protocol_version.
* - If the supported_versions extension does not exist, then the server_protocol_version will remain
* unknown and we will use the default list of allowed extension types. */
- GUARD(s2n_extension_process(&s2n_server_supported_versions_extension, conn, &parsed_extension_list));
+ POSIX_GUARD(s2n_extension_process(&s2n_server_supported_versions_extension, conn, &parsed_extension_list));
- if (conn->server_protocol_version >= S2N_TLS13) {
- GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_SERVER_HELLO_TLS13, conn, &parsed_extension_list));
+ if (s2n_is_hello_retry_message(conn)) {
+ POSIX_GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_HELLO_RETRY_REQUEST, conn, &parsed_extension_list));
+ } else if (conn->server_protocol_version >= S2N_TLS13) {
+ POSIX_GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_SERVER_HELLO_TLS13, conn, &parsed_extension_list));
} else {
- GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_SERVER_HELLO_DEFAULT, conn, &parsed_extension_list));
+ POSIX_GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_SERVER_HELLO_DEFAULT, conn, &parsed_extension_list));
}
return S2N_SUCCESS;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_finished.c b/contrib/restricted/aws/s2n/tls/s2n_server_finished.c
index 156641dd14..d7e57a222b 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_finished.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_finished.c
@@ -37,7 +37,7 @@ int s2n_server_finished_recv(struct s2n_connection *conn)
}
uint8_t *their_version = s2n_stuffer_raw_read(&conn->handshake.io, length);
- notnull_check(their_version);
+ POSIX_ENSURE_REF(their_version);
S2N_ERROR_IF(!s2n_constant_time_equals(our_version, their_version, length), S2N_ERR_BAD_MESSAGE);
@@ -50,7 +50,7 @@ int s2n_server_finished_send(struct s2n_connection *conn)
int length = S2N_TLS_FINISHED_LEN;
/* Compute the finished message */
- GUARD(s2n_prf_server_finished(conn));
+ POSIX_GUARD(s2n_prf_server_finished(conn));
our_version = conn->handshake.server_finished;
@@ -58,17 +58,17 @@ int s2n_server_finished_send(struct s2n_connection *conn)
length = S2N_SSL_FINISHED_LEN;
}
- GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, our_version, length));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, our_version, length));
/* Zero the sequence number */
struct s2n_blob seq = {.data = conn->secure.server_sequence_number,.size = S2N_TLS_SEQUENCE_NUM_LEN };
- GUARD(s2n_blob_zero(&seq));
+ POSIX_GUARD(s2n_blob_zero(&seq));
/* Update the secure state to active, and point the client at the active state */
conn->server = &conn->secure;
- if (IS_RESUMPTION_HANDSHAKE(conn->handshake.handshake_type)) {
- GUARD(s2n_prf_key_expansion(conn));
+ if (s2n_connection_is_session_resumed(conn)) {
+ POSIX_GUARD(s2n_prf_key_expansion(conn));
}
return 0;
@@ -76,7 +76,7 @@ int s2n_server_finished_send(struct s2n_connection *conn)
int s2n_tls13_server_finished_recv(struct s2n_connection *conn) {
- eq_check(conn->actual_protocol_version, S2N_TLS13);
+ POSIX_ENSURE_EQ(conn->actual_protocol_version, S2N_TLS13);
uint8_t length = s2n_stuffer_data_available(&conn->handshake.io);
S2N_ERROR_IF(length == 0, S2N_ERR_BAD_MESSAGE);
@@ -89,43 +89,45 @@ int s2n_tls13_server_finished_recv(struct s2n_connection *conn) {
s2n_tls13_connection_keys(keys, conn);
/* get transcript hash */
- struct s2n_hash_state hash_state = {0};
- GUARD(s2n_handshake_get_hash_state(conn, keys.hash_algorithm, &hash_state));
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+ struct s2n_hash_state *hash_state = &conn->handshake.hashes->hash_workspace;
+ POSIX_GUARD_RESULT(s2n_handshake_copy_hash_state(conn, keys.hash_algorithm, hash_state));
/* look up finished secret key */
struct s2n_blob finished_key = {0};
- GUARD(s2n_blob_init(&finished_key, conn->handshake.server_finished, keys.size));
+ POSIX_GUARD(s2n_blob_init(&finished_key, conn->handshake.server_finished, keys.size));
/* generate the hashed message authenticated code */
s2n_tls13_key_blob(server_finished_mac, keys.size);
- GUARD(s2n_tls13_calculate_finished_mac(&keys, &finished_key, &hash_state, &server_finished_mac));
+ POSIX_GUARD(s2n_tls13_calculate_finished_mac(&keys, &finished_key, hash_state, &server_finished_mac));
/* compare mac with received message */
- GUARD(s2n_tls13_mac_verify(&keys, &server_finished_mac, &wire_finished_mac));
+ POSIX_GUARD(s2n_tls13_mac_verify(&keys, &server_finished_mac, &wire_finished_mac));
return 0;
}
int s2n_tls13_server_finished_send(struct s2n_connection *conn) {
- eq_check(conn->actual_protocol_version, S2N_TLS13);
+ POSIX_ENSURE_EQ(conn->actual_protocol_version, S2N_TLS13);
/* get tls13 keys */
s2n_tls13_connection_keys(keys, conn);
/* get transcript hash */
- struct s2n_hash_state hash_state = {0};
- GUARD(s2n_handshake_get_hash_state(conn, keys.hash_algorithm, &hash_state));
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+ struct s2n_hash_state *hash_state = &conn->handshake.hashes->hash_workspace;
+ POSIX_GUARD_RESULT(s2n_handshake_copy_hash_state(conn, keys.hash_algorithm, hash_state));
/* look up finished secret key */
struct s2n_blob finished_key = {0};
- GUARD(s2n_blob_init(&finished_key, conn->handshake.server_finished, keys.size));
+ POSIX_GUARD(s2n_blob_init(&finished_key, conn->handshake.server_finished, keys.size));
/* generate the hashed message authenticated code */
s2n_tls13_key_blob(server_finished_mac, keys.size);
- GUARD(s2n_tls13_calculate_finished_mac(&keys, &finished_key, &hash_state, &server_finished_mac));
+ POSIX_GUARD(s2n_tls13_calculate_finished_mac(&keys, &finished_key, hash_state, &server_finished_mac));
/* write to handshake io */
- GUARD(s2n_stuffer_write(&conn->handshake.io, &server_finished_mac));
+ POSIX_GUARD(s2n_stuffer_write(&conn->handshake.io, &server_finished_mac));
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_hello.c b/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
index 010c06547a..632f745478 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_hello.c
@@ -15,7 +15,7 @@
#include <sys/param.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include <time.h>
#include "crypto/s2n_fips.h"
@@ -31,6 +31,7 @@
#include "tls/s2n_tls13.h"
#include "tls/s2n_security_policies.h"
#include "tls/s2n_tls13_handshake.h"
+#include "tls/s2n_tls13_key_schedule.h"
#include "stuffer/s2n_stuffer.h"
@@ -51,26 +52,26 @@ const uint8_t tls11_downgrade_protection_bytes[] = {
};
static int s2n_hello_retry_validate(struct s2n_connection *conn) {
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
- ENSURE_POSIX(memcmp(hello_retry_req_random, conn->secure.server_random, S2N_TLS_RANDOM_DATA_LEN) == 0,
+ POSIX_ENSURE(memcmp(hello_retry_req_random, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN) == 0,
S2N_ERR_INVALID_HELLO_RETRY);
return S2N_SUCCESS;
}
static int s2n_client_detect_downgrade_mechanism(struct s2n_connection *conn) {
- notnull_check(conn);
- uint8_t *downgrade_bytes = &conn->secure.server_random[S2N_TLS_RANDOM_DATA_LEN - S2N_DOWNGRADE_PROTECTION_SIZE];
+ POSIX_ENSURE_REF(conn);
+ uint8_t *downgrade_bytes = &conn->handshake_params.server_random[S2N_TLS_RANDOM_DATA_LEN - S2N_DOWNGRADE_PROTECTION_SIZE];
/* Detect downgrade attacks according to RFC 8446 section 4.1.3 */
if (conn->client_protocol_version == S2N_TLS13 && conn->server_protocol_version == S2N_TLS12) {
if (s2n_constant_time_equals(downgrade_bytes, tls12_downgrade_protection_bytes, S2N_DOWNGRADE_PROTECTION_SIZE)) {
- S2N_ERROR(S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
+ POSIX_BAIL(S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
}
} else if (conn->client_protocol_version == S2N_TLS13 && conn->server_protocol_version <= S2N_TLS11) {
if (s2n_constant_time_equals(downgrade_bytes, tls11_downgrade_protection_bytes, S2N_DOWNGRADE_PROTECTION_SIZE)) {
- S2N_ERROR(S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
+ POSIX_BAIL(S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
}
}
@@ -78,16 +79,16 @@ static int s2n_client_detect_downgrade_mechanism(struct s2n_connection *conn) {
}
static int s2n_server_add_downgrade_mechanism(struct s2n_connection *conn) {
- notnull_check(conn);
- uint8_t *downgrade_bytes = &conn->secure.server_random[S2N_TLS_RANDOM_DATA_LEN - S2N_DOWNGRADE_PROTECTION_SIZE];
+ POSIX_ENSURE_REF(conn);
+ uint8_t *downgrade_bytes = &conn->handshake_params.server_random[S2N_TLS_RANDOM_DATA_LEN - S2N_DOWNGRADE_PROTECTION_SIZE];
/* Protect against downgrade attacks according to RFC 8446 section 4.1.3 */
if (conn->server_protocol_version >= S2N_TLS13 && conn->actual_protocol_version == S2N_TLS12) {
/* TLS1.3 servers MUST use a special random value when negotiating TLS1.2 */
- memcpy_check(downgrade_bytes, tls12_downgrade_protection_bytes, S2N_DOWNGRADE_PROTECTION_SIZE);
+ POSIX_CHECKED_MEMCPY(downgrade_bytes, tls12_downgrade_protection_bytes, S2N_DOWNGRADE_PROTECTION_SIZE);
} else if (conn->server_protocol_version >= S2N_TLS13 && conn->actual_protocol_version <= S2N_TLS11) {
/* TLS1.3 servers MUST, use a special random value when negotiating TLS1.1 or below */
- memcpy_check(downgrade_bytes, tls11_downgrade_protection_bytes, S2N_DOWNGRADE_PROTECTION_SIZE);
+ POSIX_CHECKED_MEMCPY(downgrade_bytes, tls11_downgrade_protection_bytes, S2N_DOWNGRADE_PROTECTION_SIZE);
}
return 0;
@@ -95,7 +96,7 @@ static int s2n_server_add_downgrade_mechanism(struct s2n_connection *conn) {
static int s2n_server_hello_parse(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
struct s2n_stuffer *in = &conn->handshake.io;
uint8_t compression_method;
@@ -103,50 +104,70 @@ static int s2n_server_hello_parse(struct s2n_connection *conn)
uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN];
uint8_t session_id[S2N_TLS_SESSION_ID_MAX_LEN];
- GUARD(s2n_stuffer_read_bytes(in, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
- GUARD(s2n_stuffer_read_bytes(in, conn->secure.server_random, S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(in, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
+ POSIX_GUARD(s2n_stuffer_read_bytes(in, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN));
/* If the client receives a second HelloRetryRequest in the same connection, it MUST send an error. */
if (s2n_hello_retry_validate(conn) == S2N_SUCCESS) {
- ENSURE_POSIX(!s2n_is_hello_retry_handshake(conn), S2N_ERR_INVALID_HELLO_RETRY);
- GUARD(s2n_set_hello_retry_required(conn));
+ POSIX_ENSURE(!s2n_is_hello_retry_handshake(conn), S2N_ERR_INVALID_HELLO_RETRY);
+ POSIX_GUARD(s2n_set_hello_retry_required(conn));
}
- GUARD(s2n_stuffer_read_uint8(in, &session_id_len));
+ POSIX_GUARD(s2n_stuffer_read_uint8(in, &session_id_len));
S2N_ERROR_IF(session_id_len > S2N_TLS_SESSION_ID_MAX_LEN, S2N_ERR_BAD_MESSAGE);
- GUARD(s2n_stuffer_read_bytes(in, session_id, session_id_len));
+ POSIX_GUARD(s2n_stuffer_read_bytes(in, session_id, session_id_len));
uint8_t *cipher_suite_wire = s2n_stuffer_raw_read(in, S2N_TLS_CIPHER_SUITE_LEN);
- notnull_check(cipher_suite_wire);
+ POSIX_ENSURE_REF(cipher_suite_wire);
- GUARD(s2n_stuffer_read_uint8(in, &compression_method));
+ POSIX_GUARD(s2n_stuffer_read_uint8(in, &compression_method));
S2N_ERROR_IF(compression_method != S2N_TLS_COMPRESSION_METHOD_NULL, S2N_ERR_BAD_MESSAGE);
- GUARD(s2n_server_extensions_recv(conn, in));
+ bool session_ids_match = session_id_len != 0 && session_id_len == conn->session_id_len
+ && memcmp(session_id, conn->session_id, session_id_len) == 0;
+ if (!session_ids_match) {
+ conn->ems_negotiated = false;
+ }
+
+ POSIX_GUARD(s2n_server_extensions_recv(conn, in));
if (conn->server_protocol_version >= S2N_TLS13) {
- S2N_ERROR_IF(session_id_len != conn->session_id_len || memcmp(session_id, conn->session_id, session_id_len), S2N_ERR_BAD_MESSAGE);
+ POSIX_ENSURE(session_ids_match || (session_id_len == 0 && conn->session_id_len == 0), S2N_ERR_BAD_MESSAGE);
conn->actual_protocol_version = conn->server_protocol_version;
- GUARD(s2n_set_cipher_as_client(conn, cipher_suite_wire));
+ POSIX_GUARD(s2n_set_cipher_as_client(conn, cipher_suite_wire));
} else {
conn->server_protocol_version = (uint8_t)(protocol_version[0] * 10) + protocol_version[1];
- S2N_ERROR_IF(s2n_client_detect_downgrade_mechanism(conn), S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
- ENSURE_POSIX(!conn->config->quic_enabled, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
+ POSIX_ENSURE(!s2n_client_detect_downgrade_mechanism(conn), S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED);
+ POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
+
+ /*
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-D.3
+ *# A client that attempts to send 0-RTT data MUST fail a connection if
+ *# it receives a ServerHello with TLS 1.2 or older.
+ */
+ POSIX_ENSURE(conn->early_data_state != S2N_EARLY_DATA_REQUESTED, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
const struct s2n_security_policy *security_policy;
- GUARD(s2n_connection_get_security_policy(conn, &security_policy));
+ POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
if (conn->server_protocol_version < security_policy->minimum_protocol_version
|| conn->server_protocol_version > conn->client_protocol_version) {
- GUARD(s2n_queue_reader_unsupported_protocol_version_alert(conn));
- S2N_ERROR(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
+ POSIX_GUARD(s2n_queue_reader_unsupported_protocol_version_alert(conn));
+ POSIX_BAIL(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
}
uint8_t actual_protocol_version = MIN(conn->server_protocol_version, conn->client_protocol_version);
- /* Use the session state if server sent same session id as client sent in client hello */
- if (session_id_len != 0 && session_id_len == conn->session_id_len
- && !memcmp(session_id, conn->session_id, session_id_len)) {
+
+ /*
+ *= https://tools.ietf.org/rfc/rfc5077#section-3.4
+ *# If the server accepts the ticket
+ *# and the Session ID is not empty, then it MUST respond with the same
+ *# Session ID present in the ClientHello. This allows the client to
+ *# easily differentiate when the server is resuming a session from when
+ *# it is falling back to a full handshake.
+ */
+ if (session_ids_match) {
/* check if the resumed session state is valid */
S2N_ERROR_IF(conn->actual_protocol_version != actual_protocol_version, S2N_ERR_BAD_MESSAGE);
S2N_ERROR_IF(memcmp(conn->secure.cipher_suite->iana_value, cipher_suite_wire, S2N_TLS_CIPHER_SUITE_LEN) != 0, S2N_ERR_BAD_MESSAGE);
@@ -155,54 +176,64 @@ static int s2n_server_hello_parse(struct s2n_connection *conn)
conn->client_session_resumed = 1;
} else {
conn->session_id_len = session_id_len;
- memcpy_check(conn->session_id, session_id, session_id_len);
+ POSIX_CHECKED_MEMCPY(conn->session_id, session_id, session_id_len);
conn->actual_protocol_version = actual_protocol_version;
- GUARD(s2n_set_cipher_as_client(conn, cipher_suite_wire));
+ POSIX_GUARD(s2n_set_cipher_as_client(conn, cipher_suite_wire));
/* Erase master secret which might have been set for session resumption */
- memset_check((uint8_t *)conn->secure.master_secret, 0, S2N_TLS_SECRET_LEN);
+ POSIX_CHECKED_MEMSET((uint8_t *)conn->secrets.tls12.master_secret, 0, S2N_TLS_SECRET_LEN);
/* Erase client session ticket which might have been set for session resumption */
- GUARD(s2n_free(&conn->client_ticket));
+ POSIX_GUARD(s2n_free(&conn->client_ticket));
}
}
+ /* If it is not possible to accept early data on this connection
+ * (for example, because no PSK was negotiated) we need to reject early data now.
+ * Otherwise, early data logic may make certain invalid assumptions about the
+ * state of the connection (for example, that the prf is the early data prf).
+ */
+ POSIX_GUARD_RESULT(s2n_early_data_accept_or_reject(conn));
+ if (conn->early_data_state == S2N_EARLY_DATA_REJECTED) {
+ POSIX_GUARD_RESULT(s2n_tls13_key_schedule_reset(conn));
+ }
+
return 0;
}
int s2n_server_hello_recv(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
/* Read the message off the wire */
- GUARD(s2n_server_hello_parse(conn));
+ POSIX_GUARD(s2n_server_hello_parse(conn));
conn->actual_protocol_version_established = 1;
- GUARD(s2n_conn_set_handshake_type(conn));
+ POSIX_GUARD(s2n_conn_set_handshake_type(conn));
/* If this is a HelloRetryRequest, we don't process the ServerHello.
* Instead we proceed with retry logic. */
if (s2n_is_hello_retry_message(conn)) {
- GUARD(s2n_server_hello_retry_recv(conn));
+ POSIX_GUARD(s2n_server_hello_retry_recv(conn));
return 0;
}
- if (IS_RESUMPTION_HANDSHAKE(conn->handshake.handshake_type)) {
- GUARD(s2n_prf_key_expansion(conn));
+ if (conn->actual_protocol_version < S2N_TLS13 && s2n_connection_is_session_resumed(conn)) {
+ POSIX_GUARD(s2n_prf_key_expansion(conn));
}
/* Choose a default signature scheme */
- GUARD(s2n_choose_default_sig_scheme(conn, &conn->secure.conn_sig_scheme));
+ POSIX_GUARD(s2n_choose_default_sig_scheme(conn, &conn->handshake_params.conn_sig_scheme, S2N_SERVER));
/* Update the required hashes for this connection */
- GUARD(s2n_conn_update_required_handshake_hashes(conn));
+ POSIX_GUARD(s2n_conn_update_required_handshake_hashes(conn));
return 0;
}
int s2n_server_hello_write_message(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
/* The actual_protocol_version is set while processing the CLIENT_HELLO message, so
* it could be S2N_TLS13. SERVER_HELLO should always respond with the legacy version.
@@ -212,38 +243,38 @@ int s2n_server_hello_write_message(struct s2n_connection *conn)
protocol_version[0] = (uint8_t)(legacy_protocol_version / 10);
protocol_version[1] = (uint8_t)(legacy_protocol_version % 10);
- GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
- GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->secure.server_random, S2N_TLS_RANDOM_DATA_LEN));
- GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, conn->session_id_len));
- GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->session_id, conn->session_id_len));
- GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->secure.cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
- GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, S2N_TLS_COMPRESSION_METHOD_NULL));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, conn->session_id_len));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->session_id, conn->session_id_len));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&conn->handshake.io, conn->secure.cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
+ POSIX_GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, S2N_TLS_COMPRESSION_METHOD_NULL));
return 0;
}
int s2n_server_hello_send(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
struct s2n_stuffer server_random = {0};
struct s2n_blob b = {0};
- GUARD(s2n_blob_init(&b, conn->secure.server_random, S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_GUARD(s2n_blob_init(&b, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN));
/* Create the server random data */
- GUARD(s2n_stuffer_init(&server_random, &b));
+ POSIX_GUARD(s2n_stuffer_init(&server_random, &b));
struct s2n_blob rand_data = {0};
- GUARD(s2n_blob_init(&rand_data, s2n_stuffer_raw_write(&server_random, S2N_TLS_RANDOM_DATA_LEN), S2N_TLS_RANDOM_DATA_LEN));
- notnull_check(rand_data.data);
- GUARD_AS_POSIX(s2n_get_public_random_data(&rand_data));
+ POSIX_GUARD(s2n_blob_init(&rand_data, s2n_stuffer_raw_write(&server_random, S2N_TLS_RANDOM_DATA_LEN), S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_ENSURE_REF(rand_data.data);
+ POSIX_GUARD_RESULT(s2n_get_public_random_data(&rand_data));
/* Add a downgrade detection mechanism if required */
- GUARD(s2n_server_add_downgrade_mechanism(conn));
+ POSIX_GUARD(s2n_server_add_downgrade_mechanism(conn));
- GUARD(s2n_server_hello_write_message(conn));
+ POSIX_GUARD(s2n_server_hello_write_message(conn));
- GUARD(s2n_server_extensions_send(conn, &conn->handshake.io));
+ POSIX_GUARD(s2n_server_extensions_send(conn, &conn->handshake.io));
conn->actual_protocol_version_established = 1;
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 a6dda9edf8..c305289100 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c
@@ -35,50 +35,50 @@ uint8_t hello_retry_req_random[S2N_TLS_RANDOM_DATA_LEN] = {
static int s2n_conn_reset_retry_values(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
/* Reset handshake values */
conn->handshake.client_hello_received = 0;
/* Reset client hello state */
- GUARD(s2n_stuffer_wipe(&conn->client_hello.raw_message));
- GUARD(s2n_stuffer_resize(&conn->client_hello.raw_message, 0));
- GUARD(s2n_client_hello_free(&conn->client_hello));
- GUARD(s2n_stuffer_growable_alloc(&conn->client_hello.raw_message, 0));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->client_hello.raw_message));
+ POSIX_GUARD(s2n_stuffer_resize(&conn->client_hello.raw_message, 0));
+ POSIX_GUARD(s2n_client_hello_free(&conn->client_hello));
+ POSIX_GUARD(s2n_stuffer_growable_alloc(&conn->client_hello.raw_message, 0));
return 0;
}
int s2n_server_hello_retry_send(struct s2n_connection *conn)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
- memcpy_check(conn->secure.server_random, hello_retry_req_random, S2N_TLS_RANDOM_DATA_LEN);
+ POSIX_CHECKED_MEMCPY(conn->handshake_params.server_random, hello_retry_req_random, S2N_TLS_RANDOM_DATA_LEN);
- GUARD(s2n_server_hello_write_message(conn));
+ POSIX_GUARD(s2n_server_hello_write_message(conn));
/* Write the extensions */
- GUARD(s2n_server_extensions_send(conn, &conn->handshake.io));
+ POSIX_GUARD(s2n_server_extensions_send(conn, &conn->handshake.io));
/* Update transcript */
- GUARD(s2n_server_hello_retry_recreate_transcript(conn));
- GUARD(s2n_conn_reset_retry_values(conn));
+ POSIX_GUARD(s2n_server_hello_retry_recreate_transcript(conn));
+ POSIX_GUARD(s2n_conn_reset_retry_values(conn));
return 0;
}
int s2n_server_hello_retry_recv(struct s2n_connection *conn)
{
- notnull_check(conn);
- ENSURE_POSIX(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_INVALID_HELLO_RETRY);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_INVALID_HELLO_RETRY);
const struct s2n_ecc_preferences *ecc_pref = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
- notnull_check(ecc_pref);
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
+ POSIX_ENSURE_REF(ecc_pref);
const struct s2n_kem_preferences *kem_pref = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
- notnull_check(kem_pref);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
+ POSIX_ENSURE_REF(kem_pref);
/* Upon receipt of the HelloRetryRequest, the client MUST verify that:
* (1) the selected_group field corresponds to a group
@@ -88,44 +88,34 @@ int s2n_server_hello_retry_recv(struct s2n_connection *conn)
* in the "key_share" extension in the original ClientHello.
* If either of these checks fails, then the client MUST abort the handshake. */
- bool match_found = false;
-
- const struct s2n_ecc_named_curve *named_curve = conn->secure.server_ecc_evp_params.negotiated_curve;
- const struct s2n_kem_group *kem_group = conn->secure.server_kem_group_params.kem_group;
+ const struct s2n_ecc_named_curve *named_curve = conn->kex_params.server_ecc_evp_params.negotiated_curve;
+ const struct s2n_kem_group *kem_group = conn->kex_params.server_kem_group_params.kem_group;
/* Boolean XOR check: exactly one of {named_curve, kem_group} should be non-null. */
- ENSURE_POSIX( (named_curve != NULL) != (kem_group != NULL), S2N_ERR_INVALID_HELLO_RETRY);
+ POSIX_ENSURE( (named_curve != NULL) != (kem_group != NULL), S2N_ERR_INVALID_HELLO_RETRY);
+ bool new_key_share_requested = false;
if (named_curve != NULL) {
- for (size_t i = 0; i < ecc_pref->count; i++) {
- if (ecc_pref->ecc_curves[i] == named_curve) {
- match_found = true;
- ENSURE_POSIX(conn->secure.client_ecc_evp_params[i].evp_pkey == NULL, S2N_ERR_INVALID_HELLO_RETRY);
- break;
- }
- }
+ new_key_share_requested = (named_curve != conn->kex_params.client_ecc_evp_params.negotiated_curve);
}
-
if (kem_group != NULL) {
/* 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_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) {
- match_found = true;
- ENSURE_POSIX(conn->secure.client_kem_group_params[i].kem_params.private_key.data == NULL,
- S2N_ERR_INVALID_HELLO_RETRY);
- ENSURE_POSIX(conn->secure.client_kem_group_params[i].ecc_params.evp_pkey == NULL,
- S2N_ERR_INVALID_HELLO_RETRY);
- }
- }
+ POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
+ new_key_share_requested = (kem_group != conn->kex_params.client_kem_group_params.kem_group);
}
- ENSURE_POSIX(match_found, S2N_ERR_INVALID_HELLO_RETRY);
+ /*
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.1.4
+ *# Clients MUST abort the handshake with an
+ *# "illegal_parameter" alert if the HelloRetryRequest would not result
+ *# in any change in the ClientHello.
+ */
+ POSIX_ENSURE((conn->early_data_state == S2N_EARLY_DATA_REJECTED) || new_key_share_requested,
+ S2N_ERR_INVALID_HELLO_RETRY);
/* Update transcript hash */
- GUARD(s2n_server_hello_retry_recreate_transcript(conn));
+ POSIX_GUARD(s2n_server_hello_retry_recreate_transcript(conn));
return S2N_SUCCESS;
}
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 9116868110..b10b300e57 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c
@@ -13,12 +13,11 @@
* permissions and limitations under the License.
*/
-#include <s2n.h>
+#include "api/s2n.h"
#include "error/s2n_errno.h"
#include "tls/s2n_async_pkey.h"
-#include "tls/s2n_tls_digest_preferences.h"
#include "tls/s2n_kem.h"
#include "tls/s2n_kex.h"
#include "tls/s2n_cipher_suites.h"
@@ -38,50 +37,50 @@ static int s2n_server_key_send_write_signature(struct s2n_connection *conn, stru
int s2n_server_key_recv(struct s2n_connection *conn)
{
- notnull_check(conn);
- notnull_check(conn->secure.cipher_suite);
- notnull_check(conn->secure.cipher_suite->key_exchange_alg);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite->key_exchange_alg);
+ POSIX_ENSURE_REF(conn->handshake.hashes);
- struct s2n_hash_state *signature_hash = &conn->secure.signature_hash;
+ struct s2n_hash_state *signature_hash = &conn->handshake.hashes->hash_workspace;
const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg;
struct s2n_stuffer *in = &conn->handshake.io;
struct s2n_blob data_to_verify = {0};
/* Read the KEX data */
struct s2n_kex_raw_server_data kex_data = {0};
- GUARD_AS_POSIX(s2n_kex_server_key_recv_read_data(key_exchange, conn, &data_to_verify, &kex_data));
+ POSIX_GUARD_RESULT(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;
+ struct s2n_signature_scheme *active_sig_scheme = &conn->handshake_params.conn_sig_scheme;
if (conn->actual_protocol_version == S2N_TLS12) {
/* Verify the SigScheme picked by the Server was in the preference list we sent (or is the default SigScheme) */
- GUARD(s2n_get_and_validate_negotiated_signature_scheme(conn, in, &active_sig_scheme));
- } else {
- active_sig_scheme = conn->secure.conn_sig_scheme;
+ POSIX_GUARD(s2n_get_and_validate_negotiated_signature_scheme(conn, in, active_sig_scheme));
}
- GUARD(s2n_hash_init(signature_hash, active_sig_scheme.hash_alg));
- GUARD(s2n_hash_update(signature_hash, conn->secure.client_random, S2N_TLS_RANDOM_DATA_LEN));
- GUARD(s2n_hash_update(signature_hash, conn->secure.server_random, S2N_TLS_RANDOM_DATA_LEN));
+
+ POSIX_GUARD(s2n_hash_init(signature_hash, active_sig_scheme->hash_alg));
+ POSIX_GUARD(s2n_hash_update(signature_hash, conn->handshake_params.client_random, S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_GUARD(s2n_hash_update(signature_hash, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN));
/* Add KEX specific data */
- GUARD(s2n_hash_update(signature_hash, data_to_verify.data, data_to_verify.size));
+ POSIX_GUARD(s2n_hash_update(signature_hash, data_to_verify.data, data_to_verify.size));
/* Verify the signature */
uint16_t signature_length;
- GUARD(s2n_stuffer_read_uint16(in, &signature_length));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &signature_length));
struct s2n_blob signature = {.size = signature_length, .data = s2n_stuffer_raw_read(in, signature_length)};
- notnull_check(signature.data);
- gt_check(signature_length, 0);
+ POSIX_ENSURE_REF(signature.data);
+ POSIX_ENSURE_GT(signature_length, 0);
- S2N_ERROR_IF(s2n_pkey_verify(&conn->secure.server_public_key, active_sig_scheme.sig_alg,signature_hash, &signature) < 0,
+ S2N_ERROR_IF(s2n_pkey_verify(&conn->handshake_params.server_public_key, active_sig_scheme->sig_alg, signature_hash, &signature) < 0,
S2N_ERR_BAD_MESSAGE);
/* We don't need the key any more, so free it */
- GUARD(s2n_pkey_free(&conn->secure.server_public_key));
+ POSIX_GUARD(s2n_pkey_free(&conn->handshake_params.server_public_key));
/* Parse the KEX data into whatever form needed and save it to the connection object */
- GUARD_AS_POSIX(s2n_kex_server_key_recv_parse_data(key_exchange, conn, &kex_data));
+ POSIX_GUARD_RESULT(s2n_kex_server_key_recv_parse_data(key_exchange, conn, &kex_data));
return 0;
}
@@ -89,13 +88,13 @@ int s2n_ecdhe_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_
{
struct s2n_stuffer *in = &conn->handshake.io;
- GUARD(s2n_ecc_evp_read_params(in, data_to_verify, &raw_server_data->ecdhe_data));
+ POSIX_GUARD(s2n_ecc_evp_read_params(in, data_to_verify, &raw_server_data->ecdhe_data));
return 0;
}
int s2n_ecdhe_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data)
{
- GUARD(s2n_ecc_evp_parse_params(&raw_server_data->ecdhe_data, &conn->secure.server_ecc_evp_params));
+ POSIX_GUARD(s2n_ecc_evp_parse_params(&raw_server_data->ecdhe_data, &conn->kex_params.server_ecc_evp_params));
return 0;
}
@@ -111,23 +110,23 @@ int s2n_dhe_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_bl
/* Keep a copy to the start of the whole structure for the signature check */
data_to_verify->data = s2n_stuffer_raw_read(in, 0);
- notnull_check(data_to_verify->data);
+ POSIX_ENSURE_REF(data_to_verify->data);
/* Read each of the three elements in */
- GUARD(s2n_stuffer_read_uint16(in, &p_length));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &p_length));
dhe_data->p.size = p_length;
dhe_data->p.data = s2n_stuffer_raw_read(in, p_length);
- notnull_check(dhe_data->p.data);
+ POSIX_ENSURE_REF(dhe_data->p.data);
- GUARD(s2n_stuffer_read_uint16(in, &g_length));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &g_length));
dhe_data->g.size = g_length;
dhe_data->g.data = s2n_stuffer_raw_read(in, g_length);
- notnull_check(dhe_data->g.data);
+ POSIX_ENSURE_REF(dhe_data->g.data);
- GUARD(s2n_stuffer_read_uint16(in, &Ys_length));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &Ys_length));
dhe_data->Ys.size = Ys_length;
dhe_data->Ys.data = s2n_stuffer_raw_read(in, Ys_length);
- notnull_check(dhe_data->Ys.data);
+ POSIX_ENSURE_REF(dhe_data->Ys.data);
/* Now we know the total size of the structure */
data_to_verify->size = 2 + p_length + 2 + g_length + 2 + Ys_length;
@@ -139,7 +138,7 @@ int s2n_dhe_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_k
struct s2n_dhe_raw_server_points dhe_data = raw_server_data->dhe_data;
/* Copy the DH details */
- GUARD(s2n_dh_p_g_Ys_to_dh_params(&conn->secure.server_dh_params, &dhe_data.p, &dhe_data.g, &dhe_data.Ys));
+ POSIX_GUARD(s2n_dh_p_g_Ys_to_dh_params(&conn->kex_params.server_dh_params, &dhe_data.p, &dhe_data.g, &dhe_data.Ys));
return 0;
}
@@ -150,26 +149,26 @@ int s2n_kem_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_bl
/* Keep a copy to the start of the whole structure for the signature check */
data_to_verify->data = s2n_stuffer_raw_read(in, 0);
- notnull_check(data_to_verify->data);
+ POSIX_ENSURE_REF(data_to_verify->data);
/* the server sends the KEM ID */
kem_data->kem_name.data = s2n_stuffer_raw_read(in, 2);
- notnull_check(kem_data->kem_name.data);
+ POSIX_ENSURE_REF(kem_data->kem_name.data);
kem_data->kem_name.size = 2;
struct s2n_stuffer kem_id_stuffer = { 0 };
uint8_t kem_id_arr[2];
kem_extension_size kem_id;
struct s2n_blob kem_id_blob = { .data = kem_id_arr, .size = s2n_array_len(kem_id_arr) };
- GUARD(s2n_stuffer_init(&kem_id_stuffer, &kem_id_blob));
- GUARD(s2n_stuffer_write(&kem_id_stuffer, &(kem_data->kem_name)));
- GUARD(s2n_stuffer_read_uint16(&kem_id_stuffer, &kem_id));
+ POSIX_GUARD(s2n_stuffer_init(&kem_id_stuffer, &kem_id_blob));
+ POSIX_GUARD(s2n_stuffer_write(&kem_id_stuffer, &(kem_data->kem_name)));
+ POSIX_GUARD(s2n_stuffer_read_uint16(&kem_id_stuffer, &kem_id));
- GUARD(s2n_get_kem_from_extension_id(kem_id, &(conn->secure.kem_params.kem)));
- GUARD(s2n_kem_recv_public_key(in, &(conn->secure.kem_params)));
+ POSIX_GUARD(s2n_get_kem_from_extension_id(kem_id, &(conn->kex_params.kem_params.kem)));
+ POSIX_GUARD(s2n_kem_recv_public_key(in, &(conn->kex_params.kem_params)));
- kem_data->raw_public_key.data = conn->secure.kem_params.public_key.data;
- kem_data->raw_public_key.size = conn->secure.kem_params.public_key.size;
+ kem_data->raw_public_key.data = conn->kex_params.kem_params.public_key.data;
+ kem_data->raw_public_key.size = conn->kex_params.kem_params.public_key.size;
data_to_verify->size = sizeof(kem_extension_size) + sizeof(kem_public_key_size) + kem_data->raw_public_key.size;
@@ -182,37 +181,37 @@ int s2n_kem_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_k
/* Check that the server's requested kem is supported by the client */
const struct s2n_kem_preferences *kem_preferences = NULL;
- GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences));
- notnull_check(kem_preferences);
+ POSIX_GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences));
+ POSIX_ENSURE_REF(kem_preferences);
const struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite;
const struct s2n_kem *match = NULL;
S2N_ERROR_IF(s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, &kem_data->kem_name, kem_preferences->kems,
kem_preferences->kem_count, &match) != 0, S2N_ERR_KEM_UNSUPPORTED_PARAMS);
- conn->secure.kem_params.kem = match;
+ conn->kex_params.kem_params.kem = match;
- S2N_ERROR_IF(kem_data->raw_public_key.size != conn->secure.kem_params.kem->public_key_length, S2N_ERR_BAD_MESSAGE);
+ S2N_ERROR_IF(kem_data->raw_public_key.size != conn->kex_params.kem_params.kem->public_key_length, S2N_ERR_BAD_MESSAGE);
return 0;
}
int s2n_hybrid_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *total_data_to_verify, struct s2n_kex_raw_server_data *raw_server_data)
{
- notnull_check(conn);
- notnull_check(conn->secure.cipher_suite);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite);
const struct s2n_kex *kex = conn->secure.cipher_suite->key_exchange_alg;
const struct s2n_kex *hybrid_kex_0 = kex->hybrid[0];
const struct s2n_kex *hybrid_kex_1 = kex->hybrid[1];
/* Keep a copy to the start of the whole structure for the signature check */
total_data_to_verify->data = s2n_stuffer_raw_read(&conn->handshake.io, 0);
- notnull_check(total_data_to_verify->data);
+ POSIX_ENSURE_REF(total_data_to_verify->data);
struct s2n_blob data_to_verify_0 = {0};
- GUARD_AS_POSIX(s2n_kex_server_key_recv_read_data(hybrid_kex_0, conn, &data_to_verify_0, raw_server_data));
+ POSIX_GUARD_RESULT(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_AS_POSIX(s2n_kex_server_key_recv_read_data(hybrid_kex_1, conn, &data_to_verify_1, raw_server_data));
+ POSIX_GUARD_RESULT(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;
@@ -220,43 +219,46 @@ int s2n_hybrid_server_key_recv_read_data(struct s2n_connection *conn, struct s2n
int s2n_hybrid_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data)
{
- notnull_check(conn);
- notnull_check(conn->secure.cipher_suite);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite);
const struct s2n_kex *kex = conn->secure.cipher_suite->key_exchange_alg;
const struct s2n_kex *hybrid_kex_0 = kex->hybrid[0];
const struct s2n_kex *hybrid_kex_1 = kex->hybrid[1];
- 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));
+ POSIX_GUARD_RESULT(s2n_kex_server_key_recv_parse_data(hybrid_kex_0, conn, raw_server_data));
+ POSIX_GUARD_RESULT(s2n_kex_server_key_recv_parse_data(hybrid_kex_1, conn, raw_server_data));
return 0;
}
int s2n_server_key_send(struct s2n_connection *conn)
{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+
S2N_ASYNC_PKEY_GUARD(conn);
- struct s2n_hash_state *signature_hash = &conn->secure.signature_hash;
+ struct s2n_hash_state *signature_hash = &conn->handshake.hashes->hash_workspace;
const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg;
struct s2n_stuffer *out = &conn->handshake.io;
struct s2n_blob data_to_sign = {0};
/* Call the negotiated key exchange method to send it's data */
- GUARD_AS_POSIX(s2n_kex_server_key_send(key_exchange, conn, &data_to_sign));
+ POSIX_GUARD_RESULT(s2n_kex_server_key_send(key_exchange, conn, &data_to_sign));
/* Add common signature data */
if (conn->actual_protocol_version == S2N_TLS12) {
- GUARD(s2n_stuffer_write_uint16(out, conn->secure.conn_sig_scheme.iana_value));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, conn->handshake_params.conn_sig_scheme.iana_value));
}
/* Add the random data to the hash */
- GUARD(s2n_hash_init(signature_hash, conn->secure.conn_sig_scheme.hash_alg));
- GUARD(s2n_hash_update(signature_hash, conn->secure.client_random, S2N_TLS_RANDOM_DATA_LEN));
- GUARD(s2n_hash_update(signature_hash, conn->secure.server_random, S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_GUARD(s2n_hash_init(signature_hash, conn->handshake_params.conn_sig_scheme.hash_alg));
+ POSIX_GUARD(s2n_hash_update(signature_hash, conn->handshake_params.client_random, S2N_TLS_RANDOM_DATA_LEN));
+ POSIX_GUARD(s2n_hash_update(signature_hash, conn->handshake_params.server_random, S2N_TLS_RANDOM_DATA_LEN));
/* Add KEX specific data to the hash */
- GUARD(s2n_hash_update(signature_hash, data_to_sign.data, data_to_sign.size));
+ POSIX_GUARD(s2n_hash_update(signature_hash, data_to_sign.data, data_to_sign.size));
- S2N_ASYNC_PKEY_SIGN(conn, conn->secure.conn_sig_scheme.sig_alg, signature_hash, s2n_server_key_send_write_signature);
+ S2N_ASYNC_PKEY_SIGN(conn, conn->handshake_params.conn_sig_scheme.sig_alg, signature_hash, s2n_server_key_send_write_signature);
}
int s2n_ecdhe_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign)
@@ -264,10 +266,10 @@ int s2n_ecdhe_server_key_send(struct s2n_connection *conn, struct s2n_blob *data
struct s2n_stuffer *out = &conn->handshake.io;
/* Generate an ephemeral key and */
- GUARD(s2n_ecc_evp_generate_ephemeral_key(&conn->secure.server_ecc_evp_params));
+ POSIX_GUARD(s2n_ecc_evp_generate_ephemeral_key(&conn->kex_params.server_ecc_evp_params));
/* Write it out and calculate the data to sign later */
- GUARD(s2n_ecc_evp_write_params(&conn->secure.server_ecc_evp_params, out, data_to_sign));
+ POSIX_GUARD(s2n_ecc_evp_write_params(&conn->kex_params.server_ecc_evp_params, out, data_to_sign));
return 0;
}
@@ -276,26 +278,26 @@ int s2n_dhe_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_t
struct s2n_stuffer *out = &conn->handshake.io;
/* Duplicate the DH key from the config */
- GUARD(s2n_dh_params_copy(conn->config->dhparams, &conn->secure.server_dh_params));
+ POSIX_GUARD(s2n_dh_params_copy(conn->config->dhparams, &conn->kex_params.server_dh_params));
/* Generate an ephemeral key */
- GUARD(s2n_dh_generate_ephemeral_key(&conn->secure.server_dh_params));
+ POSIX_GUARD(s2n_dh_generate_ephemeral_key(&conn->kex_params.server_dh_params));
/* Write it out and calculate the data to sign later */
- GUARD(s2n_dh_params_to_p_g_Ys(&conn->secure.server_dh_params, out, data_to_sign));
+ POSIX_GUARD(s2n_dh_params_to_p_g_Ys(&conn->kex_params.server_dh_params, out, data_to_sign));
return 0;
}
int s2n_kem_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign)
{
struct s2n_stuffer *out = &conn->handshake.io;
- const struct s2n_kem *kem = conn->secure.kem_params.kem;
+ const struct s2n_kem *kem = conn->kex_params.kem_params.kem;
data_to_sign->data = s2n_stuffer_raw_write(out, 0);
- notnull_check(data_to_sign->data);
+ POSIX_ENSURE_REF(data_to_sign->data);
- GUARD(s2n_stuffer_write_uint16(out, kem->kem_extension_id));
- GUARD(s2n_kem_send_public_key(out, &(conn->secure.kem_params)));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, kem->kem_extension_id));
+ POSIX_GUARD(s2n_kem_send_public_key(out, &(conn->kex_params.kem_params)));
data_to_sign->size = sizeof(kem_extension_size) + sizeof(kem_public_key_size) + kem->public_key_length;
@@ -304,21 +306,21 @@ int s2n_kem_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_t
int s2n_hybrid_server_key_send(struct s2n_connection *conn, struct s2n_blob *total_data_to_sign)
{
- notnull_check(conn);
- notnull_check(conn->secure.cipher_suite);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(conn->secure.cipher_suite);
const struct s2n_kex *kex = conn->secure.cipher_suite->key_exchange_alg;
const struct s2n_kex *hybrid_kex_0 = kex->hybrid[0];
const struct s2n_kex *hybrid_kex_1 = kex->hybrid[1];
/* Keep a copy to the start of the whole structure for the signature check */
total_data_to_sign->data = s2n_stuffer_raw_write(&conn->handshake.io, 0);
- notnull_check(total_data_to_sign->data);
+ POSIX_ENSURE_REF(total_data_to_sign->data);
struct s2n_blob data_to_verify_0 = {0};
- GUARD_AS_POSIX(s2n_kex_server_key_send(hybrid_kex_0, conn, &data_to_verify_0));
+ POSIX_GUARD_RESULT(s2n_kex_server_key_send(hybrid_kex_0, conn, &data_to_verify_0));
struct s2n_blob data_to_verify_1 = {0};
- GUARD_AS_POSIX(s2n_kex_server_key_send(hybrid_kex_1, conn, &data_to_verify_1));
+ POSIX_GUARD_RESULT(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;
@@ -328,8 +330,8 @@ int s2n_server_key_send_write_signature(struct s2n_connection *conn, struct s2n_
{
struct s2n_stuffer *out = &conn->handshake.io;
- GUARD(s2n_stuffer_write_uint16(out, signature->size));
- GUARD(s2n_stuffer_write_bytes(out, signature->data, signature->size));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, signature->size));
+ POSIX_GUARD(s2n_stuffer_write_bytes(out, signature->data, signature->size));
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c b/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c
index a42c5029d2..a0af0e56ac 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_server_new_session_ticket.c
@@ -15,7 +15,7 @@
#include <sys/param.h>
-#include <s2n.h>
+#include "api/s2n.h"
#include <time.h>
#include "error/s2n_errno.h"
@@ -24,53 +24,376 @@
#include "tls/s2n_alerts.h"
#include "tls/s2n_tls.h"
#include "tls/s2n_resume.h"
+#include "tls/s2n_tls13_handshake.h"
+#include "tls/s2n_record.h"
#include "stuffer/s2n_stuffer.h"
#include "utils/s2n_safety.h"
#include "utils/s2n_random.h"
+/*
+ * The maximum size of the NewSessionTicket message, not taking into account the
+ * ticket itself.
+ *
+ * To get the actual maximum size required for the NewSessionTicket message, we'll need
+ * to add the size of the ticket, which is much less predictable.
+ *
+ * This constant is enforced via unit tests.
+ */
+#define S2N_TLS13_MAX_FIXED_NEW_SESSION_TICKET_SIZE 79
+
int s2n_server_nst_recv(struct s2n_connection *conn) {
- GUARD(s2n_stuffer_read_uint32(&conn->handshake.io, &conn->ticket_lifetime_hint));
+ POSIX_GUARD(s2n_stuffer_read_uint32(&conn->handshake.io, &conn->ticket_lifetime_hint));
uint16_t session_ticket_len;
- GUARD(s2n_stuffer_read_uint16(&conn->handshake.io, &session_ticket_len));
+ POSIX_GUARD(s2n_stuffer_read_uint16(&conn->handshake.io, &session_ticket_len));
if (session_ticket_len > 0) {
- GUARD(s2n_realloc(&conn->client_ticket, session_ticket_len));
+ POSIX_GUARD(s2n_realloc(&conn->client_ticket, session_ticket_len));
+
+ POSIX_GUARD(s2n_stuffer_read(&conn->handshake.io, &conn->client_ticket));
+
+ if (conn->config->session_ticket_cb != NULL) {
+ size_t session_len = s2n_connection_get_session_length(conn);
+
+ /* Alloc some memory for the serialized session ticket */
+ DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
+ POSIX_GUARD(s2n_alloc(&mem, S2N_STATE_FORMAT_LEN + S2N_SESSION_TICKET_SIZE_LEN + \
+ conn->client_ticket.size + S2N_TLS12_STATE_SIZE_IN_BYTES));
+
+ POSIX_GUARD(s2n_connection_get_session(conn, mem.data, session_len));
+ uint32_t session_lifetime = s2n_connection_get_session_ticket_lifetime_hint(conn);
+
+ struct s2n_session_ticket ticket = { .ticket_data = mem, .session_lifetime = session_lifetime };
- GUARD(s2n_stuffer_read(&conn->handshake.io, &conn->client_ticket));
+ POSIX_GUARD(conn->config->session_ticket_cb(conn, conn->config->session_ticket_ctx, &ticket));
+ }
}
- return 0;
+ return S2N_SUCCESS;
}
int s2n_server_nst_send(struct s2n_connection *conn)
{
- uint16_t session_ticket_len = S2N_TICKET_SIZE_IN_BYTES;
- uint8_t data[S2N_TICKET_SIZE_IN_BYTES];
+ uint16_t session_ticket_len = S2N_TLS12_TICKET_SIZE_IN_BYTES;
+ uint8_t data[S2N_TLS12_TICKET_SIZE_IN_BYTES] = { 0 };
struct s2n_blob entry = { .data = data, .size = sizeof(data) };
struct s2n_stuffer to;
uint32_t lifetime_hint_in_secs = (conn->config->encrypt_decrypt_key_lifetime_in_nanos + conn->config->decrypt_key_lifetime_in_nanos) / ONE_SEC_IN_NANOS;
/* When server changes it's mind mid handshake send lifetime hint and session ticket length as zero */
if (!conn->config->use_tickets) {
- GUARD(s2n_stuffer_write_uint32(&conn->handshake.io, 0));
- GUARD(s2n_stuffer_write_uint16(&conn->handshake.io, 0));
+ POSIX_GUARD(s2n_stuffer_write_uint32(&conn->handshake.io, 0));
+ POSIX_GUARD(s2n_stuffer_write_uint16(&conn->handshake.io, 0));
return 0;
}
if (!s2n_server_sending_nst(conn)) {
- S2N_ERROR(S2N_ERR_SENDING_NST);
+ POSIX_BAIL(S2N_ERR_SENDING_NST);
+ }
+
+ POSIX_GUARD(s2n_stuffer_init(&to, &entry));
+ POSIX_GUARD(s2n_stuffer_write_uint32(&conn->handshake.io, lifetime_hint_in_secs));
+ POSIX_GUARD(s2n_stuffer_write_uint16(&conn->handshake.io, session_ticket_len));
+
+ POSIX_GUARD(s2n_encrypt_session_ticket(conn, &to));
+ POSIX_GUARD(s2n_stuffer_write(&conn->handshake.io, &to.blob));
+
+ /* For parity with TLS1.3, track the single ticket sent.
+ * This simplifies s2n_connection_get_tickets_sent.
+ */
+ conn->tickets_sent++;
+ return S2N_SUCCESS;
+}
+
+S2N_RESULT s2n_tls13_server_nst_send(struct s2n_connection *conn, s2n_blocked_status *blocked)
+{
+ RESULT_ENSURE_REF(conn);
+
+ /* Usually tickets are sent immediately after the handshake.
+ * If possible, reuse the handshake IO stuffer before it's wiped.
+ *
+ * Note: handshake.io isn't explicitly dedicated to only reading or only writing,
+ * so we have to be careful using it outside of s2n_negotiate.
+ * If we use it for writing here, we CAN'T use it for reading any post-handshake messages.
+ */
+ struct s2n_stuffer *nst_stuffer = &conn->handshake.io;
+
+ if (conn->mode != S2N_SERVER || conn->actual_protocol_version < S2N_TLS13 || !conn->config->use_tickets) {
+ return S2N_RESULT_OK;
+ }
+
+ /* No-op if all tickets already sent.
+ * Clean up the stuffer used for the ticket to conserve memory. */
+ if (conn->tickets_to_send == conn->tickets_sent) {
+ RESULT_GUARD_POSIX(s2n_stuffer_resize(nst_stuffer, 0));
+ return S2N_RESULT_OK;
+ }
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ *# Note that in principle it is possible to continue issuing new tickets
+ *# which indefinitely extend the lifetime of the keying material
+ *# originally derived from an initial non-PSK handshake (which was most
+ *# likely tied to the peer's certificate). It is RECOMMENDED that
+ *# implementations place limits on the total lifetime of such keying
+ *# material; these limits should take into account the lifetime of the
+ *# peer's certificate, the likelihood of intervening revocation, and the
+ *# time since the peer's online CertificateVerify signature.
+ */
+ if (s2n_result_is_error(s2n_psk_validate_keying_material(conn))) {
+ conn->tickets_to_send = conn->tickets_sent;
+ return S2N_RESULT_OK;
+ }
+
+ RESULT_ENSURE(conn->tickets_sent <= conn->tickets_to_send, S2N_ERR_INTEGER_OVERFLOW);
+
+ size_t session_state_size = 0;
+ RESULT_GUARD(s2n_connection_get_session_state_size(conn, &session_state_size));
+ const size_t maximum_nst_size = session_state_size + S2N_TLS13_MAX_FIXED_NEW_SESSION_TICKET_SIZE;
+ if (s2n_stuffer_space_remaining(nst_stuffer) < maximum_nst_size) {
+ RESULT_GUARD_POSIX(s2n_stuffer_resize(nst_stuffer, maximum_nst_size));
+ }
+
+ while (conn->tickets_to_send - conn->tickets_sent > 0) {
+ if (s2n_result_is_error(s2n_tls13_server_nst_write(conn, nst_stuffer))) {
+ return S2N_RESULT_OK;
+ }
+
+ struct s2n_blob nst_blob = { 0 };
+ uint16_t nst_size = s2n_stuffer_data_available(nst_stuffer);
+ uint8_t *nst_data = s2n_stuffer_raw_read(nst_stuffer, nst_size);
+ RESULT_ENSURE_REF(nst_data);
+ RESULT_GUARD_POSIX(s2n_blob_init(&nst_blob, nst_data, nst_size));
+
+ RESULT_GUARD_POSIX(s2n_record_write(conn, TLS_HANDSHAKE, &nst_blob));
+ RESULT_GUARD_POSIX(s2n_flush(conn, blocked));
+ RESULT_GUARD_POSIX(s2n_stuffer_wipe(nst_stuffer));
+ }
+
+ RESULT_GUARD_POSIX(s2n_stuffer_resize(nst_stuffer, 0));
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ *# Indicates the lifetime in seconds as a 32-bit
+ *# unsigned integer in network byte order from the time of ticket
+ *# issuance.
+ **/
+static S2N_RESULT s2n_generate_ticket_lifetime(struct s2n_connection *conn, uint32_t *ticket_lifetime)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_MUT(ticket_lifetime);
+
+ uint32_t key_lifetime_in_secs =
+ (conn->config->encrypt_decrypt_key_lifetime_in_nanos + conn->config->decrypt_key_lifetime_in_nanos) / ONE_SEC_IN_NANOS;
+ uint32_t session_lifetime_in_secs = conn->config->session_state_lifetime_in_nanos / ONE_SEC_IN_NANOS;
+ uint32_t key_and_session_min_lifetime = MIN(key_lifetime_in_secs, session_lifetime_in_secs);
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ *# Servers MUST NOT use any value greater than
+ *# 604800 seconds (7 days).
+ **/
+ *ticket_lifetime = MIN(key_and_session_min_lifetime, ONE_WEEK_IN_SEC);
+
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ *# A per-ticket value that is unique across all tickets
+ *# issued on this connection.
+ **/
+static S2N_RESULT s2n_generate_ticket_nonce(uint16_t value, struct s2n_blob *output)
+{
+ RESULT_ENSURE_MUT(output);
+
+ struct s2n_stuffer stuffer = { 0 };
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&stuffer, output));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint16(&stuffer, value));
+
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ *# A securely generated, random 32-bit value that is
+ *# used to obscure the age of the ticket that the client includes in
+ *# the "pre_shared_key" extension.
+ **/
+static S2N_RESULT s2n_generate_ticket_age_add(struct s2n_blob *random_data, uint32_t *ticket_age_add)
+{
+ RESULT_ENSURE_REF(random_data);
+ RESULT_ENSURE_REF(ticket_age_add);
+
+ struct s2n_stuffer stuffer = { 0 };
+ RESULT_GUARD_POSIX(s2n_stuffer_init(&stuffer, random_data));
+ RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&stuffer, random_data->size));
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint32(&stuffer, ticket_age_add));
+
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ *# The PSK associated with the ticket is computed as:
+ *#
+ *# HKDF-Expand-Label(resumption_master_secret,
+ *# "resumption", ticket_nonce, Hash.length)
+ **/
+static int s2n_generate_session_secret(struct s2n_connection *conn, struct s2n_blob *nonce, struct s2n_blob *output)
+{
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(nonce);
+ POSIX_ENSURE_REF(output);
+
+ s2n_tls13_connection_keys(secrets, conn);
+ struct s2n_blob master_secret = { 0 };
+ POSIX_GUARD(s2n_blob_init(&master_secret, conn->secrets.tls13.resumption_master_secret, secrets.size));
+ POSIX_GUARD(s2n_realloc(output, secrets.size));
+ POSIX_GUARD_RESULT(s2n_tls13_derive_session_ticket_secret(&secrets, &master_secret, nonce, output));
+
+ return S2N_SUCCESS;
+}
+
+S2N_RESULT s2n_tls13_server_nst_write(struct s2n_connection *conn, struct s2n_stuffer *output)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(output);
+
+ struct s2n_ticket_fields *ticket_fields = &conn->tls13_ticket_fields;
+
+ /* Write message type because session resumption in TLS13 is a post-handshake message */
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(output, TLS_SERVER_NEW_SESSION_TICKET));
+
+ struct s2n_stuffer_reservation message_size = { 0 };
+ RESULT_GUARD_POSIX(s2n_stuffer_reserve_uint24(output, &message_size));
+
+ uint32_t ticket_lifetime_in_secs = 0;
+ RESULT_GUARD(s2n_generate_ticket_lifetime(conn, &ticket_lifetime_in_secs));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint32(output, ticket_lifetime_in_secs));
+
+ /* Get random data to use as ticket_age_add value */
+ uint8_t data[sizeof(uint32_t)] = { 0 };
+ struct s2n_blob random_data = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&random_data, data, sizeof(data)));
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ *# The server MUST generate a fresh value
+ *# for each ticket it sends.
+ **/
+ RESULT_GUARD(s2n_get_private_random_data(&random_data));
+ RESULT_GUARD(s2n_generate_ticket_age_add(&random_data, &ticket_fields->ticket_age_add));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint32(output, ticket_fields->ticket_age_add));
+
+ /* Write ticket nonce */
+ uint8_t nonce_data[sizeof(uint16_t)] = { 0 };
+ struct s2n_blob nonce = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&nonce, nonce_data, sizeof(nonce_data)));
+ RESULT_GUARD(s2n_generate_ticket_nonce(conn->tickets_sent, &nonce));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(output, nonce.size));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(output, nonce.data, nonce.size));
+
+ /* Derive individual session ticket secret */
+ RESULT_GUARD_POSIX(s2n_generate_session_secret(conn, &nonce, &ticket_fields->session_secret));
+
+ /* Write ticket */
+ struct s2n_stuffer_reservation ticket_size = { 0 };
+ RESULT_GUARD_POSIX(s2n_stuffer_reserve_uint16(output, &ticket_size));
+ RESULT_GUARD_POSIX(s2n_encrypt_session_ticket(conn, output));
+ RESULT_GUARD_POSIX(s2n_stuffer_write_vector_size(&ticket_size));
+
+ RESULT_GUARD_POSIX(s2n_extension_list_send(S2N_EXTENSION_LIST_NST, conn, output));
+
+ RESULT_GUARD_POSIX(s2n_stuffer_write_vector_size(&message_size));
+
+ RESULT_ENSURE(conn->tickets_sent < UINT16_MAX, S2N_ERR_INTEGER_OVERFLOW);
+ conn->tickets_sent++;
+
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ *# struct {
+ *# uint32 ticket_lifetime;
+ *# uint32 ticket_age_add;
+ *# opaque ticket_nonce<0..255>;
+ *# opaque ticket<1..2^16-1>;
+ *# Extension extensions<0..2^16-2>;
+ *# } NewSessionTicket;
+**/
+S2N_RESULT s2n_tls13_server_nst_recv(struct s2n_connection *conn, struct s2n_stuffer *input)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(input);
+ RESULT_ENSURE_REF(conn->config);
+
+ RESULT_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_BAD_MESSAGE);
+ RESULT_ENSURE(conn->mode == S2N_CLIENT, S2N_ERR_BAD_MESSAGE);
+
+ if (!conn->config->use_tickets) {
+ return S2N_RESULT_OK;
+ }
+ struct s2n_ticket_fields *ticket_fields = &conn->tls13_ticket_fields;
+
+ /* Handle `ticket_lifetime` field */
+ uint32_t ticket_lifetime = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint32(input, &ticket_lifetime));
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ *# Servers MUST NOT use any value greater than
+ *# 604800 seconds (7 days).
+ */
+ RESULT_ENSURE(ticket_lifetime <= ONE_WEEK_IN_SEC, S2N_ERR_BAD_MESSAGE);
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
+ *# The value of zero indicates that the
+ *# ticket should be discarded immediately.
+ */
+ if (ticket_lifetime == 0) {
+ return S2N_RESULT_OK;
}
+ conn->ticket_lifetime_hint = ticket_lifetime;
- GUARD(s2n_stuffer_init(&to, &entry));
- GUARD(s2n_stuffer_write_uint32(&conn->handshake.io, lifetime_hint_in_secs));
- GUARD(s2n_stuffer_write_uint16(&conn->handshake.io, session_ticket_len));
+ /* Handle `ticket_age_add` field */
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint32(input, &ticket_fields->ticket_age_add));
- GUARD(s2n_encrypt_session_ticket(conn, &to));
- GUARD(s2n_stuffer_write(&conn->handshake.io, &to.blob));
+ /* Handle `ticket_nonce` field */
+ uint8_t ticket_nonce_len = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(input, &ticket_nonce_len));
+ uint8_t nonce_data[UINT8_MAX] = { 0 };
+ struct s2n_blob nonce = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&nonce, nonce_data, ticket_nonce_len));
+ RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(input, nonce.data, ticket_nonce_len));
+ RESULT_GUARD_POSIX(s2n_generate_session_secret(conn, &nonce, &ticket_fields->session_secret));
+
+ /* Handle `ticket` field */
+ uint16_t session_ticket_len = 0;
+ RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(input, &session_ticket_len));
+ RESULT_ENSURE(session_ticket_len > 0, S2N_ERR_SAFETY);
+ RESULT_GUARD_POSIX(s2n_realloc(&conn->client_ticket, session_ticket_len));
+ RESULT_GUARD_POSIX(s2n_stuffer_read(input, &conn->client_ticket));
+
+ /* Handle `extensions` field */
+ RESULT_GUARD_POSIX(s2n_extension_list_recv(S2N_EXTENSION_LIST_NST, conn, input));
+
+ if (conn->config->session_ticket_cb != NULL) {
+ /* Retrieve serialized session data */
+ const uint16_t session_state_size = s2n_connection_get_session_length(conn);
+ DEFER_CLEANUP(struct s2n_blob session_state = { 0 }, s2n_free);
+ RESULT_GUARD_POSIX(s2n_realloc(&session_state, session_state_size));
+ RESULT_GUARD_POSIX(s2n_connection_get_session(conn, session_state.data, session_state.size));
+
+ struct s2n_session_ticket ticket = {
+ .ticket_data = session_state,
+ .session_lifetime = ticket_lifetime
+ };
+ RESULT_GUARD_POSIX(conn->config->session_ticket_cb(conn, conn->config->session_ticket_ctx, &ticket));
+ }
- return 0;
+ return S2N_RESULT_OK;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_shutdown.c b/contrib/restricted/aws/s2n/tls/s2n_shutdown.c
index 700d94b1d1..383d3026a5 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_shutdown.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_shutdown.c
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-#include <s2n.h>
+#include "api/s2n.h"
#include "tls/s2n_alerts.h"
#include "tls/s2n_connection.h"
@@ -23,8 +23,8 @@
int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status * more)
{
- notnull_check(conn);
- notnull_check(more);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(more);
/* Treat this call as a no-op if already wiped */
if (conn->send == NULL && conn->recv == NULL) {
@@ -32,24 +32,27 @@ int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status * more)
}
uint64_t elapsed;
- GUARD_AS_POSIX(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed));
+ POSIX_GUARD_RESULT(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed));
S2N_ERROR_IF(elapsed < conn->delay, S2N_ERR_SHUTDOWN_PAUSED);
/* Queue our close notify, once. Use warning level so clients don't give up */
- GUARD(s2n_queue_writer_close_alert_warning(conn));
+ POSIX_GUARD(s2n_queue_writer_close_alert_warning(conn));
/* Write it */
- GUARD(s2n_flush(conn, more));
+ POSIX_GUARD(s2n_flush(conn, more));
/* Assume caller isn't interested in pending incoming data */
if (conn->in_status == PLAINTEXT) {
- GUARD(s2n_stuffer_wipe(&conn->header_in));
- GUARD(s2n_stuffer_wipe(&conn->in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->header_in));
+ POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
conn->in_status = ENCRYPTED;
}
- /* Fails with S2N_ERR_SHUTDOWN_RECORD_TYPE or S2N_ERR_ALERT on receipt of anything but a close_notify */
- GUARD(s2n_recv_close_notify(conn, more));
+ /* Dont expect to receive another close notify alert if we have already received it */
+ if (!conn->close_notify_received) {
+ /* Fails with S2N_ERR_SHUTDOWN_RECORD_TYPE or S2N_ERR_ALERT on receipt of anything but a close_notify */
+ POSIX_GUARD(s2n_recv_close_notify(conn, more));
+ }
return 0;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c
index 4645eae5f1..ae367e9670 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c
@@ -21,7 +21,6 @@
#include "tls/s2n_auth_selection.h"
#include "tls/s2n_cipher_suites.h"
#include "tls/s2n_kex.h"
-#include "tls/s2n_tls_digest_preferences.h"
#include "tls/s2n_signature_algorithms.h"
#include "tls/s2n_signature_scheme.h"
#include "tls/s2n_security_policies.h"
@@ -31,14 +30,19 @@
static int s2n_signature_scheme_valid_to_offer(struct s2n_connection *conn, const struct s2n_signature_scheme *scheme)
{
/* We don't know what protocol version we will eventually negotiate, but we know that it won't be any higher. */
- gte_check(conn->actual_protocol_version, scheme->minimum_protocol_version);
+ POSIX_ENSURE_GTE(conn->actual_protocol_version, scheme->minimum_protocol_version);
+
+ /* QUIC only supports TLS1.3 */
+ if (s2n_connection_is_quic_enabled(conn) && scheme->maximum_protocol_version) {
+ POSIX_ENSURE_GTE(scheme->maximum_protocol_version, S2N_TLS13);
+ }
if (!s2n_is_rsa_pss_signing_supported()) {
- ne_check(scheme->sig_alg, S2N_SIGNATURE_RSA_PSS_RSAE);
+ POSIX_ENSURE_NE(scheme->sig_alg, S2N_SIGNATURE_RSA_PSS_RSAE);
}
if (!s2n_is_rsa_pss_certs_supported()) {
- ne_check(scheme->sig_alg, S2N_SIGNATURE_RSA_PSS_PSS);
+ POSIX_ENSURE_NE(scheme->sig_alg, S2N_SIGNATURE_RSA_PSS_PSS);
}
return 0;
@@ -46,23 +50,23 @@ static int s2n_signature_scheme_valid_to_offer(struct s2n_connection *conn, cons
static int s2n_signature_scheme_valid_to_accept(struct s2n_connection *conn, const struct s2n_signature_scheme *scheme)
{
- notnull_check(scheme);
+ POSIX_ENSURE_REF(scheme);
- GUARD(s2n_signature_scheme_valid_to_offer(conn, scheme));
+ POSIX_GUARD(s2n_signature_scheme_valid_to_offer(conn, scheme));
if (scheme->maximum_protocol_version != S2N_UNKNOWN_PROTOCOL_VERSION) {
- lte_check(conn->actual_protocol_version, scheme->maximum_protocol_version);
+ POSIX_ENSURE_LTE(conn->actual_protocol_version, scheme->maximum_protocol_version);
}
return 0;
}
static int s2n_is_signature_scheme_usable(struct s2n_connection *conn, const struct s2n_signature_scheme *candidate) {
- notnull_check(conn);
- notnull_check(candidate);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(candidate);
- GUARD(s2n_signature_scheme_valid_to_accept(conn, candidate));
- GUARD(s2n_is_sig_scheme_valid_for_auth(conn, candidate));
+ POSIX_GUARD(s2n_signature_scheme_valid_to_accept(conn, candidate));
+ POSIX_GUARD(s2n_is_sig_scheme_valid_for_auth(conn, candidate));
return S2N_SUCCESS;
}
@@ -70,13 +74,13 @@ static int s2n_is_signature_scheme_usable(struct s2n_connection *conn, const str
static int s2n_choose_sig_scheme(struct s2n_connection *conn, struct s2n_sig_scheme_list *peer_wire_prefs,
struct s2n_signature_scheme *chosen_scheme_out)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
const struct s2n_signature_preferences *signature_preferences = NULL;
- GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
- notnull_check(signature_preferences);
+ POSIX_GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
+ POSIX_ENSURE_REF(signature_preferences);
struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite;
- notnull_check(cipher_suite);
+ POSIX_ENSURE_REF(cipher_suite);
for (size_t i = 0; i < signature_preferences->count; i++) {
const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i];
@@ -100,15 +104,15 @@ static int s2n_choose_sig_scheme(struct s2n_connection *conn, struct s2n_sig_sch
}
/* similar to s2n_choose_sig_scheme() without matching client's preference */
-static int s2n_tls13_default_sig_scheme(struct s2n_connection *conn, struct s2n_signature_scheme *chosen_scheme_out)
+int s2n_tls13_default_sig_scheme(struct s2n_connection *conn, struct s2n_signature_scheme *chosen_scheme_out)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
const struct s2n_signature_preferences *signature_preferences = NULL;
- GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
- notnull_check(signature_preferences);
+ POSIX_GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
+ POSIX_ENSURE_REF(signature_preferences);
struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite;
- notnull_check(cipher_suite);
+ POSIX_ENSURE_REF(cipher_suite);
for (size_t i = 0; i < signature_preferences->count; i++) {
const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i];
@@ -121,18 +125,18 @@ static int s2n_tls13_default_sig_scheme(struct s2n_connection *conn, struct s2n_
return S2N_SUCCESS;
}
- S2N_ERROR(S2N_ERR_INVALID_SIGNATURE_SCHEME);
+ POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_SCHEME);
}
int s2n_get_and_validate_negotiated_signature_scheme(struct s2n_connection *conn, struct s2n_stuffer *in,
struct s2n_signature_scheme *chosen_sig_scheme)
{
uint16_t actual_iana_val;
- GUARD(s2n_stuffer_read_uint16(in, &actual_iana_val));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &actual_iana_val));
const struct s2n_signature_preferences *signature_preferences = NULL;
- GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
- notnull_check(signature_preferences);
+ POSIX_GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
+ POSIX_ENSURE_REF(signature_preferences);
for (size_t i = 0; i < signature_preferences->count; i++) {
const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i];
@@ -150,8 +154,8 @@ int s2n_get_and_validate_negotiated_signature_scheme(struct s2n_connection *conn
/* We require an exact match in TLS 1.3, but all previous versions can fall back to the default SignatureScheme.
* This means that an s2n client will accept the default SignatureScheme from a TLS server, even if the client did
* not send it in it's ClientHello. This pre-TLS1.3 behavior is an intentional choice to maximize support. */
- struct s2n_signature_scheme default_scheme;
- GUARD(s2n_choose_default_sig_scheme(conn, &default_scheme));
+ struct s2n_signature_scheme default_scheme = { 0 };
+ POSIX_GUARD(s2n_choose_default_sig_scheme(conn, &default_scheme, S2N_PEER_MODE(conn->mode)));
if ((conn->actual_protocol_version <= S2N_TLS12)
&& (s2n_signature_scheme_valid_to_accept(conn, &default_scheme) == S2N_SUCCESS)
@@ -161,16 +165,21 @@ int s2n_get_and_validate_negotiated_signature_scheme(struct s2n_connection *conn
return S2N_SUCCESS;
}
- S2N_ERROR(S2N_ERR_INVALID_SIGNATURE_SCHEME);
+ POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_SCHEME);
}
-int s2n_choose_default_sig_scheme(struct s2n_connection *conn, struct s2n_signature_scheme *sig_scheme_out)
+int s2n_choose_default_sig_scheme(struct s2n_connection *conn, struct s2n_signature_scheme *sig_scheme_out, s2n_mode signer)
{
- notnull_check(conn);
- notnull_check(conn->secure.cipher_suite);
- notnull_check(sig_scheme_out);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(sig_scheme_out);
- s2n_authentication_method cipher_suite_auth_method = conn->secure.cipher_suite->auth_method;
+ s2n_authentication_method auth_method = 0;
+ if (signer == S2N_CLIENT) {
+ POSIX_GUARD(s2n_get_auth_method_for_cert_type(conn->handshake_params.client_cert_pkey_type, &auth_method));
+ } else {
+ POSIX_ENSURE_REF(conn->secure.cipher_suite);
+ auth_method = conn->secure.cipher_suite->auth_method;
+ }
/* Default our signature digest algorithms. For TLS 1.2 this default is different and may be
* overridden by the signature_algorithms extension. If the server chooses an ECDHE_ECDSA
@@ -178,13 +187,11 @@ int s2n_choose_default_sig_scheme(struct s2n_connection *conn, struct s2n_signat
*/
*sig_scheme_out = s2n_rsa_pkcs1_md5_sha1;
- if (cipher_suite_auth_method == S2N_AUTHENTICATION_ECDSA) {
+ if (auth_method == S2N_AUTHENTICATION_ECDSA) {
*sig_scheme_out = s2n_ecdsa_sha1;
- }
-
- /* Default RSA Hash Algorithm is SHA1 (instead of MD5_SHA1) if TLS 1.2 or FIPS mode */
- if ((conn->actual_protocol_version >= S2N_TLS12 || s2n_is_in_fips_mode())
- && (sig_scheme_out->sig_alg == S2N_SIGNATURE_RSA)) {
+ } else if (conn->actual_protocol_version >= S2N_TLS12) {
+ *sig_scheme_out = s2n_rsa_pkcs1_sha1;
+ } else if (s2n_is_in_fips_mode() && signer == S2N_SERVER) {
*sig_scheme_out = s2n_rsa_pkcs1_sha1;
}
@@ -194,41 +201,39 @@ int s2n_choose_default_sig_scheme(struct s2n_connection *conn, struct s2n_signat
int s2n_choose_sig_scheme_from_peer_preference_list(struct s2n_connection *conn, struct s2n_sig_scheme_list *peer_wire_prefs,
struct s2n_signature_scheme *sig_scheme_out)
{
- notnull_check(conn);
- notnull_check(sig_scheme_out);
-
- struct s2n_signature_scheme chosen_scheme;
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(sig_scheme_out);
+ struct s2n_signature_scheme chosen_scheme = { 0 };
if (conn->actual_protocol_version < S2N_TLS13) {
- GUARD(s2n_choose_default_sig_scheme(conn, &chosen_scheme));
+ POSIX_GUARD(s2n_choose_default_sig_scheme(conn, &chosen_scheme, conn->mode));
} else {
/* Pick a default signature algorithm in TLS 1.3 https://tools.ietf.org/html/rfc8446#section-4.4.2.2 */
- GUARD(s2n_tls13_default_sig_scheme(conn, &chosen_scheme));
+ POSIX_GUARD(s2n_tls13_default_sig_scheme(conn, &chosen_scheme));
}
/* SignatureScheme preference list was first added in TLS 1.2. It will be empty in older TLS versions. */
if (peer_wire_prefs != NULL && peer_wire_prefs->len > 0) {
/* Use a best effort approach to selecting a signature scheme matching client's preferences */
- GUARD(s2n_choose_sig_scheme(conn, peer_wire_prefs, &chosen_scheme));
+ POSIX_GUARD(s2n_choose_sig_scheme(conn, peer_wire_prefs, &chosen_scheme));
}
*sig_scheme_out = chosen_scheme;
-
return S2N_SUCCESS;
}
int s2n_send_supported_sig_scheme_list(struct s2n_connection *conn, struct s2n_stuffer *out)
{
const struct s2n_signature_preferences *signature_preferences = NULL;
- GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
- notnull_check(signature_preferences);
+ POSIX_GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
+ POSIX_ENSURE_REF(signature_preferences);
- GUARD(s2n_stuffer_write_uint16(out, s2n_supported_sig_scheme_list_size(conn)));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, s2n_supported_sig_scheme_list_size(conn)));
for (size_t i = 0; i < signature_preferences->count; i++) {
const struct s2n_signature_scheme *const scheme = signature_preferences->signature_schemes[i];
if (0 == s2n_signature_scheme_valid_to_offer(conn, scheme)) {
- GUARD(s2n_stuffer_write_uint16(out, scheme->iana_value));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, scheme->iana_value));
}
}
@@ -243,8 +248,8 @@ int s2n_supported_sig_scheme_list_size(struct s2n_connection *conn)
int s2n_supported_sig_schemes_count(struct s2n_connection *conn)
{
const struct s2n_signature_preferences *signature_preferences = NULL;
- GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
- notnull_check(signature_preferences);
+ POSIX_GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences));
+ POSIX_ENSURE_REF(signature_preferences);
uint8_t count = 0;
for (size_t i = 0; i < signature_preferences->count; i++) {
@@ -258,7 +263,7 @@ int s2n_supported_sig_schemes_count(struct s2n_connection *conn)
int s2n_recv_supported_sig_scheme_list(struct s2n_stuffer *in, struct s2n_sig_scheme_list *sig_hash_algs)
{
uint16_t length_of_all_pairs;
- GUARD(s2n_stuffer_read_uint16(in, &length_of_all_pairs));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &length_of_all_pairs));
if (length_of_all_pairs > s2n_stuffer_data_available(in)) {
/* Malformed length, ignore the extension */
return 0;
@@ -266,21 +271,21 @@ int s2n_recv_supported_sig_scheme_list(struct s2n_stuffer *in, struct s2n_sig_sc
if (length_of_all_pairs % 2) {
/* Pairs occur in two byte lengths. Malformed length, ignore the extension and skip ahead */
- GUARD(s2n_stuffer_skip_read(in, length_of_all_pairs));
+ POSIX_GUARD(s2n_stuffer_skip_read(in, length_of_all_pairs));
return 0;
}
int pairs_available = length_of_all_pairs / 2;
if (pairs_available > TLS_SIGNATURE_SCHEME_LIST_MAX_LEN) {
- S2N_ERROR(S2N_ERR_TOO_MANY_SIGNATURE_SCHEMES);
+ POSIX_BAIL(S2N_ERR_TOO_MANY_SIGNATURE_SCHEMES);
}
sig_hash_algs->len = 0;
for (size_t i = 0; i < pairs_available; i++) {
uint16_t sig_scheme = 0;
- GUARD(s2n_stuffer_read_uint16(in, &sig_scheme));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &sig_scheme));
sig_hash_algs->iana_list[sig_hash_algs->len] = sig_scheme;
sig_hash_algs->len += 1;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.h b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.h
index b400977a16..f1533335ba 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.h
@@ -15,7 +15,7 @@
#pragma once
-#include <s2n.h>
+#include "api/s2n.h"
#include "crypto/s2n_hash.h"
#include "crypto/s2n_signature.h"
@@ -29,7 +29,9 @@ struct s2n_sig_scheme_list {
uint8_t len;
};
-int s2n_choose_default_sig_scheme(struct s2n_connection *conn, struct s2n_signature_scheme *sig_scheme_out);
+int s2n_choose_default_sig_scheme(struct s2n_connection *conn, struct s2n_signature_scheme *sig_scheme_out, s2n_mode signer);
+int s2n_tls13_default_sig_scheme(struct s2n_connection *conn, struct s2n_signature_scheme *sig_scheme_out);
+
int s2n_choose_sig_scheme_from_peer_preference_list(struct s2n_connection *conn, struct s2n_sig_scheme_list *sig_hash_algs,
struct s2n_signature_scheme *sig_scheme_out);
int s2n_get_and_validate_negotiated_signature_scheme(struct s2n_connection *conn, struct s2n_stuffer *in,
diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c
index 911e717127..6ccddacab6 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c
@@ -13,7 +13,7 @@
* permissions and limitations under the License.
*/
-#include <s2n.h>
+#include "api/s2n.h"
#include "crypto/s2n_hash.h"
#include "crypto/s2n_signature.h"
@@ -339,3 +339,19 @@ const struct s2n_signature_preferences s2n_certificate_signature_preferences_202
.count = s2n_array_len(s2n_sig_scheme_pref_list_20201110),
.signature_schemes = s2n_sig_scheme_pref_list_20201110,
};
+
+/* Based on s2n_sig_scheme_pref_list_20140601 but with all hashes < SHA-384 removed */
+const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20210816[] = {
+ /* RSA PKCS1 */
+ &s2n_rsa_pkcs1_sha384,
+ &s2n_rsa_pkcs1_sha512,
+
+ /* ECDSA - TLS 1.2 */
+ &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */
+ &s2n_ecdsa_sha512,
+};
+
+const struct s2n_signature_preferences s2n_signature_preferences_20210816 = {
+ .count = s2n_array_len(s2n_sig_scheme_pref_list_20210816),
+ .signature_schemes = s2n_sig_scheme_pref_list_20210816
+};
diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h
index 416f936a6d..3f78d8a500 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h
@@ -15,7 +15,7 @@
#pragma once
-#include <s2n.h>
+#include "api/s2n.h"
#include <strings.h>
#include "crypto/s2n_hash.h"
@@ -76,6 +76,7 @@ extern const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha512;
extern const struct s2n_signature_preferences s2n_signature_preferences_20140601;
extern const struct s2n_signature_preferences s2n_signature_preferences_20200207;
extern const struct s2n_signature_preferences s2n_signature_preferences_20201021;
+extern const struct s2n_signature_preferences s2n_signature_preferences_20210816;
extern const struct s2n_signature_preferences s2n_signature_preferences_null;
extern const struct s2n_signature_preferences s2n_certificate_signature_preferences_20201110;
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls.h b/contrib/restricted/aws/s2n/tls/s2n_tls.h
index d74822a236..7f17c8bc7c 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls.h
@@ -24,6 +24,7 @@ extern uint8_t s2n_unknown_protocol_version;
extern uint8_t s2n_highest_protocol_version;
extern int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * more);
+int s2n_client_hello_request_recv(struct s2n_connection *conn);
extern int s2n_client_hello_send(struct s2n_connection *conn);
extern int s2n_client_hello_recv(struct s2n_connection *conn);
extern int s2n_establish_session(struct s2n_connection *conn);
@@ -57,6 +58,9 @@ extern int s2n_tls13_cert_verify_recv(struct s2n_connection *conn);
extern int s2n_tls13_cert_verify_send(struct s2n_connection *conn);
extern int s2n_server_nst_send(struct s2n_connection *conn);
extern int s2n_server_nst_recv(struct s2n_connection *conn);
+S2N_RESULT s2n_tls13_server_nst_send(struct s2n_connection *conn, s2n_blocked_status *blocked);
+S2N_RESULT s2n_tls13_server_nst_write(struct s2n_connection *conn, struct s2n_stuffer *output);
+S2N_RESULT s2n_tls13_server_nst_recv(struct s2n_connection *conn, struct s2n_stuffer *input);
extern int s2n_ccs_send(struct s2n_connection *conn);
extern int s2n_basic_ccs_recv(struct s2n_connection *conn);
extern int s2n_server_ccs_recv(struct s2n_connection *conn);
@@ -69,6 +73,8 @@ extern int s2n_tls13_client_finished_send(struct s2n_connection *conn);
extern int s2n_tls13_client_finished_recv(struct s2n_connection *conn);
extern int s2n_tls13_server_finished_send(struct s2n_connection *conn);
extern int s2n_tls13_server_finished_recv(struct s2n_connection *conn);
+extern int s2n_end_of_early_data_send(struct s2n_connection *conn);
+extern int s2n_end_of_early_data_recv(struct s2n_connection *conn);
extern int s2n_process_client_hello(struct s2n_connection *conn);
extern int s2n_handshake_write_header(struct s2n_stuffer *out, uint8_t message_type);
extern int s2n_handshake_finish_header(struct s2n_stuffer *out);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13.c b/contrib/restricted/aws/s2n/tls/s2n_tls13.c
index 52dd99a86a..790ad8cadc 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls13.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13.c
@@ -16,6 +16,7 @@
#include "api/s2n.h"
#include "tls/s2n_tls.h"
#include "tls/s2n_tls13.h"
+#include "crypto/s2n_rsa_pss.h"
#include "crypto/s2n_rsa_signing.h"
bool s2n_use_default_tls13_config_flag = false;
@@ -25,6 +26,17 @@ bool s2n_use_default_tls13_config()
return s2n_use_default_tls13_config_flag;
}
+bool s2n_is_tls13_fully_supported()
+{
+ /* Older versions of Openssl (eg 1.0.2) do not support RSA PSS, which is required for TLS 1.3. */
+ return s2n_is_rsa_pss_signing_supported() && s2n_is_rsa_pss_certs_supported();
+}
+
+int s2n_get_highest_fully_supported_tls_version()
+{
+ return s2n_is_tls13_fully_supported() ? S2N_TLS13 : S2N_TLS12;
+}
+
/* Allow TLS1.3 to be negotiated, and use the default TLS1.3 security policy.
* This is NOT the default behavior, and this method is deprecated.
*
@@ -33,6 +45,17 @@ bool s2n_use_default_tls13_config()
*/
int s2n_enable_tls13()
{
+ return s2n_enable_tls13_in_test();
+}
+
+/* Allow TLS1.3 to be negotiated, and use the default TLS1.3 security policy.
+ * This is NOT the default behavior, and this method is deprecated.
+ *
+ * Please consider using the default behavior and configuring
+ * TLS1.2/TLS1.3 via explicit security policy instead.
+ */
+int s2n_enable_tls13_in_test()
+{
s2n_highest_protocol_version = S2N_TLS13;
s2n_use_default_tls13_config_flag = true;
return S2N_SUCCESS;
@@ -44,9 +67,9 @@ int s2n_enable_tls13()
* Please consider using the default behavior and configuring
* TLS1.2/TLS1.3 via explicit security policy instead.
*/
-int s2n_disable_tls13()
+int s2n_disable_tls13_in_test()
{
- ENSURE_POSIX(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
+ POSIX_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
s2n_highest_protocol_version = S2N_TLS12;
s2n_use_default_tls13_config_flag = false;
return S2N_SUCCESS;
@@ -57,9 +80,9 @@ int s2n_disable_tls13()
* This method is intended for use in existing unit tests when the APIs
* to enable/disable TLS1.3 have already been called.
*/
-int s2n_reset_tls13()
+int s2n_reset_tls13_in_test()
{
- ENSURE_POSIX(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
+ POSIX_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
s2n_highest_protocol_version = S2N_TLS13;
s2n_use_default_tls13_config_flag = false;
return S2N_SUCCESS;
@@ -73,3 +96,53 @@ bool s2n_is_valid_tls13_cipher(const uint8_t version[2]) {
*/
return version[0] == 0x13 && version[1] >= 0x01 && version[1] <= 0x05;
}
+
+/* Use middlebox compatibility mode for TLS1.3 by default.
+ * For now, only disable it when QUIC support is enabled.
+ */
+bool s2n_is_middlebox_compat_enabled(struct s2n_connection *conn)
+{
+ return s2n_connection_get_protocol_version(conn) >= S2N_TLS13
+ && !s2n_connection_is_quic_enabled(conn);
+}
+
+S2N_RESULT s2n_connection_validate_tls13_support(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+
+ /* If the underlying libcrypto supports all features of TLS1.3
+ * (including RSA-PSS, which is unsupported by some libraries),
+ * then we can always support TLS1.3.
+ */
+ if (s2n_is_tls13_fully_supported()) {
+ return S2N_RESULT_OK;
+ }
+
+ /*
+ * If the underlying libcrypto doesn't support all features...
+ */
+
+ /* There are some TLS servers in the wild that will choose options not offered by the client.
+ * So a server might choose to use RSA-PSS even if even if the client does not advertise support for RSA-PSS.
+ * Therefore, only servers can perform TLS1.3 without full feature support.
+ */
+ RESULT_ENSURE(conn->mode == S2N_SERVER, S2N_RSA_PSS_NOT_SUPPORTED);
+
+ /* RSA signatures must use RSA-PSS in TLS1.3.
+ * So RSA-PSS is required for TLS1.3 servers if an RSA certificate is used.
+ */
+ RESULT_ENSURE(!conn->config->is_rsa_cert_configured, S2N_RSA_PSS_NOT_SUPPORTED);
+
+ /* RSA-PSS is also required for TLS1.3 servers if client auth is requested, because the
+ * client might offer an RSA certificate.
+ */
+ s2n_cert_auth_type client_auth_status = S2N_CERT_AUTH_NONE;
+ RESULT_GUARD_POSIX(s2n_connection_get_client_auth_type(conn, &client_auth_status));
+ RESULT_ENSURE(client_auth_status == S2N_CERT_AUTH_NONE, S2N_RSA_PSS_NOT_SUPPORTED);
+
+ return S2N_RESULT_OK;
+}
+
+bool s2n_connection_supports_tls13(struct s2n_connection *conn) {
+ return s2n_result_is_ok(s2n_connection_validate_tls13_support(conn));
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13.h b/contrib/restricted/aws/s2n/tls/s2n_tls13.h
index 53dedaf02e..7ad815bd71 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls13.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13.h
@@ -42,9 +42,16 @@ extern "C" {
extern uint8_t hello_retry_req_random[S2N_TLS_RANDOM_DATA_LEN];
bool s2n_use_default_tls13_config();
-int s2n_disable_tls13();
-int s2n_reset_tls13();
+bool s2n_is_tls13_fully_supported();
+int s2n_get_highest_fully_supported_tls_version();
+int s2n_enable_tls13_in_test();
+int s2n_disable_tls13_in_test();
+int s2n_reset_tls13_in_test();
bool s2n_is_valid_tls13_cipher(const uint8_t version[2]);
+S2N_RESULT s2n_connection_validate_tls13_support(struct s2n_connection *conn);
+bool s2n_connection_supports_tls13(struct s2n_connection *conn);
+
+bool s2n_is_middlebox_compat_enabled(struct s2n_connection *conn);
bool s2n_is_hello_retry_handshake(struct s2n_connection *conn);
bool s2n_is_hello_retry_message(struct s2n_connection *conn);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.c
index 74654f33cf..abc96b8b21 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.c
@@ -60,10 +60,10 @@ int s2n_tls13_cert_verify_send(struct s2n_connection *conn)
if (conn->mode == S2N_SERVER) {
/* Write digital signature */
- GUARD(s2n_tls13_write_cert_verify_signature(conn, &conn->secure.conn_sig_scheme));
+ POSIX_GUARD(s2n_tls13_write_cert_verify_signature(conn, &conn->handshake_params.conn_sig_scheme));
} else {
/* Write digital signature */
- GUARD(s2n_tls13_write_cert_verify_signature(conn, &conn->secure.client_cert_sig_scheme));
+ POSIX_GUARD(s2n_tls13_write_cert_verify_signature(conn, &conn->handshake_params.client_cert_sig_scheme));
}
@@ -72,20 +72,20 @@ int s2n_tls13_cert_verify_send(struct s2n_connection *conn)
int s2n_tls13_write_cert_verify_signature(struct s2n_connection *conn, struct s2n_signature_scheme *chosen_sig_scheme)
{
- notnull_check(conn->handshake_params.our_chain_and_key);
+ POSIX_ENSURE_REF(conn->handshake_params.our_chain_and_key);
/* Write the SignatureScheme out */
struct s2n_stuffer *out = &conn->handshake.io;
- GUARD(s2n_stuffer_write_uint16(out, chosen_sig_scheme->iana_value));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, chosen_sig_scheme->iana_value));
DEFER_CLEANUP(struct s2n_hash_state message_hash = {0}, s2n_hash_free);
- GUARD(s2n_hash_new(&message_hash));
- GUARD(s2n_hash_init(&message_hash, chosen_sig_scheme->hash_alg));
+ POSIX_GUARD(s2n_hash_new(&message_hash));
+ POSIX_GUARD(s2n_hash_init(&message_hash, chosen_sig_scheme->hash_alg));
DEFER_CLEANUP(struct s2n_stuffer unsigned_content = {0}, s2n_stuffer_free);
- GUARD(s2n_tls13_generate_unsigned_cert_verify_content(conn, &unsigned_content, conn->mode));
+ POSIX_GUARD(s2n_tls13_generate_unsigned_cert_verify_content(conn, &unsigned_content, conn->mode));
- GUARD(s2n_hash_update(&message_hash, unsigned_content.blob.data, s2n_stuffer_data_available(&unsigned_content)));
+ POSIX_GUARD(s2n_hash_update(&message_hash, unsigned_content.blob.data, s2n_stuffer_data_available(&unsigned_content)));
S2N_ASYNC_PKEY_SIGN(conn, chosen_sig_scheme->sig_alg, &message_hash, s2n_tls13_write_signature);
}
@@ -94,8 +94,8 @@ int s2n_tls13_write_signature(struct s2n_connection *conn, struct s2n_blob *sign
{
struct s2n_stuffer *out = &conn->handshake.io;
- GUARD(s2n_stuffer_write_uint16(out, signature->size));
- GUARD(s2n_stuffer_write_bytes(out, signature->data, signature->size));
+ POSIX_GUARD(s2n_stuffer_write_uint16(out, signature->size));
+ POSIX_GUARD(s2n_stuffer_write_bytes(out, signature->data, signature->size));
return 0;
}
@@ -104,30 +104,26 @@ int s2n_tls13_generate_unsigned_cert_verify_content(struct s2n_connection *conn,
{
s2n_tls13_connection_keys(tls13_ctx, conn);
- struct s2n_hash_state handshake_hash, hash_copy;
uint8_t hash_digest_length = tls13_ctx.size;
uint8_t digest_out[S2N_MAX_DIGEST_LEN];
/* Get current handshake hash */
- GUARD(s2n_handshake_get_hash_state(conn, tls13_ctx.hash_algorithm, &handshake_hash));
-
- /* Copy current hash content */
- GUARD(s2n_hash_new(&hash_copy));
- GUARD(s2n_hash_copy(&hash_copy, &handshake_hash));
- GUARD(s2n_hash_digest(&hash_copy, digest_out, hash_digest_length));
- GUARD(s2n_hash_free(&hash_copy));
+ POSIX_ENSURE_REF(conn->handshake.hashes);
+ struct s2n_hash_state *hash_state = &conn->handshake.hashes->hash_workspace;
+ POSIX_GUARD_RESULT(s2n_handshake_copy_hash_state(conn, tls13_ctx.hash_algorithm, hash_state));
+ POSIX_GUARD(s2n_hash_digest(hash_state, digest_out, hash_digest_length));
/* Concatenate the content to be signed/verified */
- GUARD(s2n_stuffer_alloc(unsigned_content, hash_digest_length + s2n_tls13_cert_verify_header_length(mode)));
- GUARD(s2n_stuffer_write_bytes(unsigned_content, S2N_CERT_VERIFY_PREFIX, sizeof(S2N_CERT_VERIFY_PREFIX)));
+ POSIX_GUARD(s2n_stuffer_alloc(unsigned_content, hash_digest_length + s2n_tls13_cert_verify_header_length(mode)));
+ POSIX_GUARD(s2n_stuffer_write_bytes(unsigned_content, S2N_CERT_VERIFY_PREFIX, sizeof(S2N_CERT_VERIFY_PREFIX)));
if (mode == S2N_CLIENT) {
- GUARD(s2n_stuffer_write_bytes(unsigned_content, S2N_CLIENT_CERT_VERIFY_CONTEXT, sizeof(S2N_CLIENT_CERT_VERIFY_CONTEXT)));
+ POSIX_GUARD(s2n_stuffer_write_bytes(unsigned_content, S2N_CLIENT_CERT_VERIFY_CONTEXT, sizeof(S2N_CLIENT_CERT_VERIFY_CONTEXT)));
} else {
- GUARD(s2n_stuffer_write_bytes(unsigned_content, S2N_SERVER_CERT_VERIFY_CONTEXT, sizeof(S2N_SERVER_CERT_VERIFY_CONTEXT)));
+ POSIX_GUARD(s2n_stuffer_write_bytes(unsigned_content, S2N_SERVER_CERT_VERIFY_CONTEXT, sizeof(S2N_SERVER_CERT_VERIFY_CONTEXT)));
}
- GUARD(s2n_stuffer_write_bytes(unsigned_content, digest_out, hash_digest_length));
+ POSIX_GUARD(s2n_stuffer_write_bytes(unsigned_content, digest_out, hash_digest_length));
return 0;
}
@@ -144,16 +140,16 @@ int s2n_tls13_cert_verify_recv(struct s2n_connection *conn)
{
if (conn->mode == S2N_SERVER) {
/* Read the algorithm and update sig_scheme */
- GUARD(s2n_get_and_validate_negotiated_signature_scheme(conn, &conn->handshake.io, &conn->secure.client_cert_sig_scheme));
+ POSIX_GUARD(s2n_get_and_validate_negotiated_signature_scheme(conn, &conn->handshake.io, &conn->handshake_params.client_cert_sig_scheme));
/* Read the rest of the signature and verify */
- GUARD(s2n_tls13_cert_read_and_verify_signature(conn, &conn->secure.client_cert_sig_scheme));
+ POSIX_GUARD(s2n_tls13_cert_read_and_verify_signature(conn, &conn->handshake_params.client_cert_sig_scheme));
} else {
/* Read the algorithm and update sig_scheme */
- GUARD(s2n_get_and_validate_negotiated_signature_scheme(conn, &conn->handshake.io, &conn->secure.conn_sig_scheme));
+ POSIX_GUARD(s2n_get_and_validate_negotiated_signature_scheme(conn, &conn->handshake.io, &conn->handshake_params.conn_sig_scheme));
/* Read the rest of the signature and verify */
- GUARD(s2n_tls13_cert_read_and_verify_signature(conn, &conn->secure.conn_sig_scheme));
+ POSIX_GUARD(s2n_tls13_cert_read_and_verify_signature(conn, &conn->handshake_params.conn_sig_scheme));
}
return 0;
@@ -165,32 +161,32 @@ int s2n_tls13_cert_read_and_verify_signature(struct s2n_connection *conn, struct
DEFER_CLEANUP(struct s2n_blob signed_content = {0}, s2n_free);
DEFER_CLEANUP(struct s2n_stuffer unsigned_content = {0}, s2n_stuffer_free);
DEFER_CLEANUP(struct s2n_hash_state message_hash = {0}, s2n_hash_free);
- GUARD(s2n_hash_new(&message_hash));
+ POSIX_GUARD(s2n_hash_new(&message_hash));
/* Get signature size */
uint16_t signature_size;
- GUARD(s2n_stuffer_read_uint16(in, &signature_size));
+ POSIX_GUARD(s2n_stuffer_read_uint16(in, &signature_size));
S2N_ERROR_IF(signature_size > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE);
/* Get wire signature */
- GUARD(s2n_alloc(&signed_content, signature_size));
+ POSIX_GUARD(s2n_alloc(&signed_content, signature_size));
signed_content.size = signature_size;
- GUARD(s2n_stuffer_read_bytes(in, signed_content.data, signature_size));
+ POSIX_GUARD(s2n_stuffer_read_bytes(in, signed_content.data, signature_size));
/* Verify signature. We send the opposite mode as we are trying to verify what was sent to us */
if (conn->mode == S2N_CLIENT) {
- GUARD(s2n_tls13_generate_unsigned_cert_verify_content(conn, &unsigned_content, S2N_SERVER));
+ POSIX_GUARD(s2n_tls13_generate_unsigned_cert_verify_content(conn, &unsigned_content, S2N_SERVER));
} else {
- GUARD(s2n_tls13_generate_unsigned_cert_verify_content(conn, &unsigned_content, S2N_CLIENT));
+ POSIX_GUARD(s2n_tls13_generate_unsigned_cert_verify_content(conn, &unsigned_content, S2N_CLIENT));
}
- GUARD(s2n_hash_init(&message_hash, chosen_sig_scheme->hash_alg));
- GUARD(s2n_hash_update(&message_hash, unsigned_content.blob.data, s2n_stuffer_data_available(&unsigned_content)));
+ POSIX_GUARD(s2n_hash_init(&message_hash, chosen_sig_scheme->hash_alg));
+ POSIX_GUARD(s2n_hash_update(&message_hash, unsigned_content.blob.data, s2n_stuffer_data_available(&unsigned_content)));
if (conn->mode == S2N_CLIENT) {
- GUARD(s2n_pkey_verify(&conn->secure.server_public_key, chosen_sig_scheme->sig_alg, &message_hash, &signed_content));
+ POSIX_GUARD(s2n_pkey_verify(&conn->handshake_params.server_public_key, chosen_sig_scheme->sig_alg, &message_hash, &signed_content));
} else {
- GUARD(s2n_pkey_verify(&conn->secure.client_public_key, chosen_sig_scheme->sig_alg, &message_hash, &signed_content));
+ POSIX_GUARD(s2n_pkey_verify(&conn->handshake_params.client_public_key, chosen_sig_scheme->sig_alg, &message_hash, &signed_content));
}
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 4382c02382..e5b2bd3202 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c
@@ -15,358 +15,143 @@
#include "tls/s2n_tls13_handshake.h"
#include "tls/s2n_cipher_suites.h"
+#include "tls/s2n_key_log.h"
#include "tls/s2n_security_policies.h"
static int s2n_zero_sequence_number(struct s2n_connection *conn, s2n_mode mode)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
struct s2n_blob sequence_number;
if (mode == S2N_CLIENT) {
- GUARD(s2n_blob_init(&sequence_number, conn->secure.client_sequence_number, sizeof(conn->secure.client_sequence_number)));
+ POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure.client_sequence_number, sizeof(conn->secure.client_sequence_number)));
} else {
- GUARD(s2n_blob_init(&sequence_number, conn->secure.server_sequence_number, sizeof(conn->secure.server_sequence_number)));
+ POSIX_GUARD(s2n_blob_init(&sequence_number, conn->secure.server_sequence_number, sizeof(conn->secure.server_sequence_number)));
}
- GUARD(s2n_blob_zero(&sequence_number));
+ POSIX_GUARD(s2n_blob_zero(&sequence_number));
return S2N_SUCCESS;
}
int s2n_tls13_mac_verify(struct s2n_tls13_keys *keys, struct s2n_blob *finished_verify, struct s2n_blob *wire_verify)
{
- notnull_check(wire_verify->data);
- eq_check(wire_verify->size, keys->size);
+ POSIX_ENSURE_REF(wire_verify->data);
+ POSIX_ENSURE_EQ(wire_verify->size, keys->size);
S2N_ERROR_IF(!s2n_constant_time_equals(finished_verify->data, wire_verify->data, keys->size), S2N_ERR_BAD_MESSAGE);
- return 0;
-}
-
-/*
- * Initializes the tls13_keys struct
- */
-static int s2n_tls13_keys_init_with_ref(struct s2n_tls13_keys *handshake, s2n_hmac_algorithm alg, uint8_t * extract, uint8_t * derive)
-{
- notnull_check(handshake);
-
- handshake->hmac_algorithm = alg;
- GUARD(s2n_hmac_hash_alg(alg, &handshake->hash_algorithm));
- GUARD(s2n_hash_digest_size(handshake->hash_algorithm, &handshake->size));
- GUARD(s2n_blob_init(&handshake->extract_secret, extract, handshake->size));
- GUARD(s2n_blob_init(&handshake->derive_secret, derive, handshake->size));
- GUARD(s2n_hmac_new(&handshake->hmac));
-
- return 0;
+ return S2N_SUCCESS;
}
int s2n_tls13_keys_from_conn(struct s2n_tls13_keys *keys, struct s2n_connection *conn)
{
- GUARD(s2n_tls13_keys_init_with_ref(keys, conn->secure.cipher_suite->prf_alg, conn->secure.rsa_premaster_secret, conn->secure.master_secret));
-
- return 0;
+ POSIX_GUARD(s2n_tls13_keys_init(keys, conn->secure.cipher_suite->prf_alg));
+ return S2N_SUCCESS;
}
int s2n_tls13_compute_ecc_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret) {
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
const struct s2n_ecc_preferences *ecc_preferences = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_preferences));
- notnull_check(ecc_preferences);
-
- struct s2n_ecc_evp_params *server_key = &conn->secure.server_ecc_evp_params;
- notnull_check(server_key);
- notnull_check(server_key->negotiated_curve);
- /* for now we do this tedious loop to find the matching client key selection.
- * this can be simplified if we get an index or a pointer to a specific key */
- int selection = -1;
- for (int i = 0; i < ecc_preferences->count; i++) {
- if (server_key->negotiated_curve->iana_id == ecc_preferences->ecc_curves[i]->iana_id) {
- selection = i;
- break;
- }
- }
+ POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_preferences));
+ POSIX_ENSURE_REF(ecc_preferences);
- S2N_ERROR_IF(selection < 0, S2N_ERR_BAD_KEY_SHARE);
- struct s2n_ecc_evp_params *client_key = &conn->secure.client_ecc_evp_params[selection];
- notnull_check(client_key);
+ struct s2n_ecc_evp_params *server_key = &conn->kex_params.server_ecc_evp_params;
+ POSIX_ENSURE_REF(server_key);
+ POSIX_ENSURE_REF(server_key->negotiated_curve);
+
+ struct s2n_ecc_evp_params *client_key = &conn->kex_params.client_ecc_evp_params;
+ POSIX_ENSURE_REF(client_key);
+ POSIX_ENSURE_REF(client_key->negotiated_curve);
+
+ POSIX_ENSURE_EQ(server_key->negotiated_curve, client_key->negotiated_curve);
if (conn->mode == S2N_CLIENT) {
- GUARD(s2n_ecc_evp_compute_shared_secret_from_params(client_key, server_key, shared_secret));
+ POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(client_key, server_key, shared_secret));
} else {
- GUARD(s2n_ecc_evp_compute_shared_secret_from_params(server_key, client_key, shared_secret));
+ POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(server_key, client_key, shared_secret));
}
- return 0;
+ return S2N_SUCCESS;
}
/* Computes the ECDHE+PQKEM hybrid shared secret as defined in
* https://tools.ietf.org/html/draft-stebila-tls-hybrid-design */
int s2n_tls13_compute_pq_hybrid_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret) {
- notnull_check(conn);
- notnull_check(shared_secret);
+ POSIX_ENSURE_REF(conn);
+ POSIX_ENSURE_REF(shared_secret);
- /* conn->secure.server_ecc_evp_params should be set only during a classic/non-hybrid handshake */
- eq_check(NULL, conn->secure.server_ecc_evp_params.negotiated_curve);
- eq_check(NULL, conn->secure.server_ecc_evp_params.evp_pkey);
+ /* conn->kex_params.server_ecc_evp_params should be set only during a classic/non-hybrid handshake */
+ POSIX_ENSURE_EQ(NULL, conn->kex_params.server_ecc_evp_params.negotiated_curve);
+ POSIX_ENSURE_EQ(NULL, conn->kex_params.server_ecc_evp_params.evp_pkey);
- struct s2n_kem_group_params *server_kem_group_params = &conn->secure.server_kem_group_params;
- notnull_check(server_kem_group_params);
+ struct s2n_kem_group_params *server_kem_group_params = &conn->kex_params.server_kem_group_params;
+ POSIX_ENSURE_REF(server_kem_group_params);
struct s2n_ecc_evp_params *server_ecc_params = &server_kem_group_params->ecc_params;
- notnull_check(server_ecc_params);
+ POSIX_ENSURE_REF(server_ecc_params);
- struct s2n_kem_group_params *client_kem_group_params = conn->secure.chosen_client_kem_group_params;
- notnull_check(client_kem_group_params);
+ struct s2n_kem_group_params *client_kem_group_params = &conn->kex_params.client_kem_group_params;
+ POSIX_ENSURE_REF(client_kem_group_params);
struct s2n_ecc_evp_params *client_ecc_params = &client_kem_group_params->ecc_params;
- notnull_check(client_ecc_params);
+ POSIX_ENSURE_REF(client_ecc_params);
DEFER_CLEANUP(struct s2n_blob ecdhe_shared_secret = { 0 }, s2n_blob_zeroize_free);
/* Compute the ECDHE shared secret, and retrieve the PQ shared secret. */
if (conn->mode == S2N_CLIENT) {
- GUARD(s2n_ecc_evp_compute_shared_secret_from_params(client_ecc_params, server_ecc_params, &ecdhe_shared_secret));
+ POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(client_ecc_params, server_ecc_params, &ecdhe_shared_secret));
} else {
- GUARD(s2n_ecc_evp_compute_shared_secret_from_params(server_ecc_params, client_ecc_params, &ecdhe_shared_secret));
+ POSIX_GUARD(s2n_ecc_evp_compute_shared_secret_from_params(server_ecc_params, client_ecc_params, &ecdhe_shared_secret));
}
struct s2n_blob *pq_shared_secret = &client_kem_group_params->kem_params.shared_secret;
- notnull_check(pq_shared_secret);
- notnull_check(pq_shared_secret->data);
+ POSIX_ENSURE_REF(pq_shared_secret);
+ POSIX_ENSURE_REF(pq_shared_secret->data);
- const struct s2n_kem_group *negotiated_kem_group = conn->secure.server_kem_group_params.kem_group;
- notnull_check(negotiated_kem_group);
- notnull_check(negotiated_kem_group->kem);
+ const struct s2n_kem_group *negotiated_kem_group = conn->kex_params.server_kem_group_params.kem_group;
+ POSIX_ENSURE_REF(negotiated_kem_group);
+ POSIX_ENSURE_REF(negotiated_kem_group->kem);
- eq_check(pq_shared_secret->size, negotiated_kem_group->kem->shared_secret_key_length);
+ POSIX_ENSURE_EQ(pq_shared_secret->size, negotiated_kem_group->kem->shared_secret_key_length);
/* Construct the concatenated/hybrid shared secret */
uint32_t hybrid_shared_secret_size = ecdhe_shared_secret.size + negotiated_kem_group->kem->shared_secret_key_length;
- GUARD(s2n_alloc(shared_secret, hybrid_shared_secret_size));
+ POSIX_GUARD(s2n_alloc(shared_secret, hybrid_shared_secret_size));
struct s2n_stuffer stuffer_combiner = { 0 };
- GUARD(s2n_stuffer_init(&stuffer_combiner, shared_secret));
- GUARD(s2n_stuffer_write(&stuffer_combiner, &ecdhe_shared_secret));
- GUARD(s2n_stuffer_write(&stuffer_combiner, pq_shared_secret));
-
- /* No longer need PQ shared secret or ECC keys */
- GUARD(s2n_kem_group_free(server_kem_group_params));
- GUARD(s2n_kem_group_free(client_kem_group_params));
+ POSIX_GUARD(s2n_stuffer_init(&stuffer_combiner, shared_secret));
+ POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, &ecdhe_shared_secret));
+ POSIX_GUARD(s2n_stuffer_write(&stuffer_combiner, pq_shared_secret));
return S2N_SUCCESS;
}
static int s2n_tls13_pq_hybrid_supported(struct s2n_connection *conn) {
- return conn->secure.server_kem_group_params.kem_group != NULL;
+ return conn->kex_params.server_kem_group_params.kem_group != NULL;
}
int s2n_tls13_compute_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
if (s2n_tls13_pq_hybrid_supported(conn)) {
- GUARD(s2n_tls13_compute_pq_hybrid_shared_secret(conn, shared_secret));
+ POSIX_GUARD(s2n_tls13_compute_pq_hybrid_shared_secret(conn, shared_secret));
} else {
- GUARD(s2n_tls13_compute_ecc_shared_secret(conn, shared_secret));
+ POSIX_GUARD(s2n_tls13_compute_ecc_shared_secret(conn, shared_secret));
}
- return S2N_SUCCESS;
-}
+ POSIX_GUARD_RESULT(s2n_connection_wipe_all_keyshares(conn));
-/*
- * This function executes after Server Hello is processed
- * and handshake hashes are computed. It produces and configure
- * the shared secret, handshake secrets, handshake traffic keys,
- * and finished keys.
- */
-int s2n_tls13_handle_handshake_secrets(struct s2n_connection *conn)
-{
- notnull_check(conn);
- const struct s2n_ecc_preferences *ecc_preferences = NULL;
- GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_preferences));
- notnull_check(ecc_preferences);
-
- /* get tls13 key context */
- s2n_tls13_connection_keys(secrets, conn);
-
- /* get shared secret */
- DEFER_CLEANUP(struct s2n_blob shared_secret = { 0 }, s2n_free);
- GUARD(s2n_tls13_compute_shared_secret(conn, &shared_secret));
-
- /* derive early 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);
- s2n_stack_blob(server_hs_secret, secrets.size, S2N_TLS13_SECRET_MAX_LEN);
-
- struct s2n_hash_state hash_state = {0};
- GUARD(s2n_handshake_get_hash_state(conn, secrets.hash_algorithm, &hash_state));
- GUARD(s2n_tls13_derive_handshake_secrets(&secrets, &shared_secret, &hash_state, &client_hs_secret, &server_hs_secret));
-
- /* trigger secret callbacks */
- if (conn->secret_cb && conn->config->quic_enabled) {
- GUARD(conn->secret_cb(conn->secret_cb_context, conn, S2N_CLIENT_HANDSHAKE_TRAFFIC_SECRET,
- client_hs_secret.data, client_hs_secret.size));
- GUARD(conn->secret_cb(conn->secret_cb_context, conn, S2N_SERVER_HANDSHAKE_TRAFFIC_SECRET,
- server_hs_secret.data, server_hs_secret.size));
- }
-
- /* produce handshake traffic keys and configure record algorithm */
- s2n_tls13_key_blob(server_hs_key, conn->secure.cipher_suite->record_alg->cipher->key_material_size);
- struct s2n_blob server_hs_iv = { .data = conn->secure.server_implicit_iv, .size = S2N_TLS13_FIXED_IV_LEN };
- GUARD(s2n_tls13_derive_traffic_keys(&secrets, &server_hs_secret, &server_hs_key, &server_hs_iv));
-
- s2n_tls13_key_blob(client_hs_key, conn->secure.cipher_suite->record_alg->cipher->key_material_size);
- struct s2n_blob client_hs_iv = { .data = conn->secure.client_implicit_iv, .size = S2N_TLS13_FIXED_IV_LEN };
- GUARD(s2n_tls13_derive_traffic_keys(&secrets, &client_hs_secret, &client_hs_key, &client_hs_iv));
-
- GUARD(conn->secure.cipher_suite->record_alg->cipher->init(&conn->secure.server_key));
- GUARD(conn->secure.cipher_suite->record_alg->cipher->init(&conn->secure.client_key));
-
- if (conn->mode == S2N_CLIENT) {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure.server_key, &server_hs_key));
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure.client_key, &client_hs_key));
- } else {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure.server_key, &server_hs_key));
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure.client_key, &client_hs_key));
- }
+ /* It would make more sense to wipe the PSK secrets in s2n_tls13_handle_early_secret,
+ * but at that point we don't know whether or not the server will request a HRR request
+ * and we'll have to use the secrets again.
+ *
+ * Instead, wipe them here when we wipe all the other connection secrets. */
+ POSIX_GUARD_RESULT(s2n_psk_parameters_wipe_secrets(&conn->psk_params));
- /* calculate server + client finished keys and store them in handshake struct */
- struct s2n_blob server_finished_key = { .data = conn->handshake.server_finished, .size = secrets.size };
- struct s2n_blob client_finished_key = { .data = conn->handshake.client_finished, .size = secrets.size };
- GUARD(s2n_tls13_derive_finished_key(&secrets, &server_hs_secret, &server_finished_key));
- GUARD(s2n_tls13_derive_finished_key(&secrets, &client_hs_secret, &client_finished_key));
-
- /* since shared secret has been computed, clean up keys */
- GUARD(s2n_ecc_evp_params_free(&conn->secure.server_ecc_evp_params));
- for (int i = 0; i < ecc_preferences->count; i++) {
- GUARD(s2n_ecc_evp_params_free(&conn->secure.client_ecc_evp_params[i]));
- }
-
- /* According to https://tools.ietf.org/html/rfc8446#section-5.3:
- * Each sequence number is set to zero at the beginning of a connection and
- * whenever the key is changed
- */
- GUARD(s2n_zero_sequence_number(conn, S2N_CLIENT));
- GUARD(s2n_zero_sequence_number(conn, S2N_SERVER));
-
- return 0;
-}
-
-static int s2n_tls13_handle_application_secret(struct s2n_connection *conn, s2n_mode mode)
-{
- /* get tls13 key context */
- s2n_tls13_connection_keys(keys, conn);
- bool is_sending_secret = (mode == conn->mode);
-
- uint8_t *app_secret_data, *implicit_iv_data;
- struct s2n_session_key *session_key;
- s2n_secret_type_t secret_type;
- if (mode == S2N_CLIENT) {
- app_secret_data = conn->secure.client_app_secret;
- implicit_iv_data = conn->secure.client_implicit_iv;
- session_key = &conn->secure.client_key;
- secret_type = S2N_CLIENT_APPLICATION_TRAFFIC_SECRET;
- } else {
- app_secret_data = conn->secure.server_app_secret;
- implicit_iv_data = conn->secure.server_implicit_iv;
- session_key = &conn->secure.server_key;
- secret_type = S2N_SERVER_APPLICATION_TRAFFIC_SECRET;
- }
-
- /* use frozen hashes during the server finished state */
- struct s2n_hash_state *hash_state;
- GUARD_NONNULL(hash_state = &conn->handshake.server_finished_copy);
-
- /* calculate secret */
- struct s2n_blob app_secret = { .data = app_secret_data, .size = keys.size };
- GUARD(s2n_tls13_derive_application_secret(&keys, hash_state, &app_secret, mode));
-
- /* trigger secret callback */
- if (conn->secret_cb && conn->config->quic_enabled) {
- GUARD(conn->secret_cb(conn->secret_cb_context, conn, secret_type,
- app_secret.data, app_secret.size));
- }
-
- /* derive key from secret */
- s2n_tls13_key_blob(app_key, conn->secure.cipher_suite->record_alg->cipher->key_material_size);
- struct s2n_blob app_iv = { .data = implicit_iv_data, .size = S2N_TLS13_FIXED_IV_LEN };
- GUARD(s2n_tls13_derive_traffic_keys(&keys, &app_secret, &app_key, &app_iv));
-
- /* update record algorithm secrets */
- if (is_sending_secret) {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(session_key, &app_key));
- } else {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(session_key, &app_key));
- }
-
- /* According to https://tools.ietf.org/html/rfc8446#section-5.3:
- * Each sequence number is set to zero at the beginning of a connection and
- * whenever the key is changed
- */
- GUARD(s2n_zero_sequence_number(conn, mode));
-
- return S2N_SUCCESS;
-}
-
-/* The application secrets are derived from the master secret, so the
- * master secret must be handled BEFORE the application secrets.
- */
-static int s2n_tls13_handle_master_secret(struct s2n_connection *conn)
-{
- s2n_tls13_connection_keys(keys, conn);
- GUARD(s2n_tls13_extract_master_secret(&keys));
- 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);
- if (conn->actual_protocol_version < S2N_TLS13) {
- return S2N_SUCCESS;
- }
-
- switch(s2n_conn_get_current_message_type(conn)) {
- case SERVER_HELLO:
- GUARD(s2n_tls13_handle_handshake_secrets(conn));
- /* Set negotiated crypto parameters for encryption */
- conn->server = &conn->secure;
- conn->client = &conn->secure;
- break;
- case SERVER_FINISHED:
- if (conn->mode == S2N_SERVER) {
- GUARD(s2n_tls13_handle_master_secret(conn));
- GUARD(s2n_tls13_handle_application_secret(conn, S2N_SERVER));
- }
- break;
- case CLIENT_FINISHED:
- if (conn->mode == S2N_CLIENT) {
- GUARD(s2n_tls13_handle_master_secret(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;
- }
return S2N_SUCCESS;
}
int s2n_update_application_traffic_keys(struct s2n_connection *conn, s2n_mode mode, keyupdate_status status)
{
- notnull_check(conn);
+ POSIX_ENSURE_REF(conn);
/* get tls13 key context */
s2n_tls13_connection_keys(keys, conn);
@@ -377,28 +162,28 @@ int s2n_update_application_traffic_keys(struct s2n_connection *conn, s2n_mode mo
if (mode == S2N_CLIENT) {
old_key = &conn->secure.client_key;
- GUARD(s2n_blob_init(&old_app_secret, conn->secure.client_app_secret, keys.size));
- GUARD(s2n_blob_init(&app_iv, conn->secure.client_implicit_iv, S2N_TLS13_FIXED_IV_LEN));
+ POSIX_GUARD(s2n_blob_init(&old_app_secret, conn->secrets.tls13.client_app_secret, keys.size));
+ POSIX_GUARD(s2n_blob_init(&app_iv, conn->secure.client_implicit_iv, S2N_TLS13_FIXED_IV_LEN));
} else {
old_key = &conn->secure.server_key;
- GUARD(s2n_blob_init(&old_app_secret, conn->secure.server_app_secret, keys.size));
- GUARD(s2n_blob_init(&app_iv, conn->secure.server_implicit_iv, S2N_TLS13_FIXED_IV_LEN));
+ POSIX_GUARD(s2n_blob_init(&old_app_secret, conn->secrets.tls13.server_app_secret, keys.size));
+ POSIX_GUARD(s2n_blob_init(&app_iv, conn->secure.server_implicit_iv, S2N_TLS13_FIXED_IV_LEN));
}
/* Produce new application secret */
s2n_stack_blob(app_secret_update, keys.size, S2N_TLS13_SECRET_MAX_LEN);
/* Derives next generation of traffic secret */
- GUARD(s2n_tls13_update_application_traffic_secret(&keys, &old_app_secret, &app_secret_update));
+ POSIX_GUARD(s2n_tls13_update_application_traffic_secret(&keys, &old_app_secret, &app_secret_update));
s2n_tls13_key_blob(app_key, conn->secure.cipher_suite->record_alg->cipher->key_material_size);
/* Derives next generation of traffic key */
- GUARD(s2n_tls13_derive_traffic_keys(&keys, &app_secret_update, &app_key, &app_iv));
+ POSIX_GUARD(s2n_tls13_derive_traffic_keys(&keys, &app_secret_update, &app_key, &app_iv));
if (status == RECEIVING) {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(old_key, &app_key));
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_decryption_key(old_key, &app_key));
} else {
- GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(old_key, &app_key));
+ POSIX_GUARD(conn->secure.cipher_suite->record_alg->cipher->set_encryption_key(old_key, &app_key));
}
/* According to https://tools.ietf.org/html/rfc8446#section-5.3:
@@ -406,12 +191,12 @@ int s2n_update_application_traffic_keys(struct s2n_connection *conn, s2n_mode mo
* whenever the key is changed; the first record transmitted under a particular traffic key
* MUST use sequence number 0.
*/
- GUARD(s2n_zero_sequence_number(conn, mode));
+ POSIX_GUARD(s2n_zero_sequence_number(conn, mode));
/* Save updated secret */
struct s2n_stuffer old_secret_stuffer = {0};
- GUARD(s2n_stuffer_init(&old_secret_stuffer, &old_app_secret));
- GUARD(s2n_stuffer_write_bytes(&old_secret_stuffer, app_secret_update.data, keys.size));
+ POSIX_GUARD(s2n_stuffer_init(&old_secret_stuffer, &old_app_secret));
+ POSIX_GUARD(s2n_stuffer_write_bytes(&old_secret_stuffer, app_secret_update.data, keys.size));
return S2N_SUCCESS;
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.h b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.h
index f496677a09..e9785de6d0 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.h
@@ -25,16 +25,16 @@ int s2n_tls13_mac_verify(struct s2n_tls13_keys *keys, struct s2n_blob *finished_
#define s2n_get_hash_state(hash_state, alg, conn) \
struct s2n_hash_state hash_state = {0}; \
- GUARD(s2n_handshake_get_hash_state(conn, alg, &hash_state));
+ POSIX_GUARD(s2n_handshake_get_hash_state(conn, alg, &hash_state));
/* Creates a reference to tls13_keys from connection */
#define s2n_tls13_connection_keys(keys, conn) \
DEFER_CLEANUP(struct s2n_tls13_keys keys = {0}, s2n_tls13_keys_free);\
- GUARD(s2n_tls13_keys_from_conn(&keys, conn));
+ POSIX_GUARD(s2n_tls13_keys_from_conn(&keys, conn));
int s2n_tls13_keys_from_conn(struct s2n_tls13_keys *keys, struct s2n_connection *conn);
-int s2n_tls13_handle_secrets(struct s2n_connection *conn);
+int s2n_tls13_compute_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret);
int s2n_update_application_traffic_keys(struct s2n_connection *conn, s2n_mode mode, keyupdate_status status);
int s2n_server_hello_retry_recreate_transcript(struct s2n_connection *conn);
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.c
new file mode 100644
index 0000000000..16fd78c042
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#include "tls/s2n_tls13_handshake.h"
+#include "utils/s2n_result.h"
+
+/* The state machine refers to the "master" secret as the "application" secret.
+ * Let's use that terminology here to match.
+ */
+#define S2N_APPLICATION_SECRET S2N_MASTER_SECRET
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A
+ *# The notation "K_{send,recv} = foo" means "set
+ *# the send/recv key to the given key".
+ */
+#define K_send(conn, secret_type) RESULT_GUARD(s2n_set_key(conn, secret_type, (conn)->mode))
+#define K_recv(conn, secret_type) RESULT_GUARD(s2n_set_key(conn, secret_type, S2N_PEER_MODE((conn)->mode)))
+
+static const struct s2n_blob s2n_zero_length_context = { 0 };
+
+static S2N_RESULT s2n_zero_sequence_number(struct s2n_connection *conn, s2n_mode mode)
+{
+ RESULT_ENSURE_REF(conn);
+ struct s2n_blob sequence_number;
+ if (mode == S2N_CLIENT) {
+ RESULT_GUARD_POSIX(s2n_blob_init(&sequence_number,
+ conn->secure.client_sequence_number, sizeof(conn->secure.client_sequence_number)));
+ } else {
+ RESULT_GUARD_POSIX(s2n_blob_init(&sequence_number,
+ conn->secure.server_sequence_number, sizeof(conn->secure.server_sequence_number)));
+ }
+ RESULT_GUARD_POSIX(s2n_blob_zero(&sequence_number));
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_set_key(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type, s2n_mode mode)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->secure.cipher_suite);
+ const struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite;
+ RESULT_ENSURE_REF(conn->secure.cipher_suite->record_alg);
+ RESULT_ENSURE_REF(conn->secure.cipher_suite->record_alg->cipher);
+ const struct s2n_cipher *cipher = conn->secure.cipher_suite->record_alg->cipher;
+
+ uint8_t *implicit_iv_data = NULL;
+ struct s2n_session_key *session_key = NULL;
+ if (mode == S2N_CLIENT) {
+ implicit_iv_data = conn->secure.client_implicit_iv;
+ session_key = &conn->secure.client_key;
+ conn->client = &conn->secure;
+ } else {
+ implicit_iv_data = conn->secure.server_implicit_iv;
+ session_key = &conn->secure.server_key;
+ conn->server = &conn->secure;
+ }
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.3
+ *# The traffic keying material is generated from the following input
+ *# values:
+ *#
+ *# - A secret value
+ **/
+ struct s2n_blob secret = { 0 };
+ uint8_t secret_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&secret, secret_bytes, S2N_TLS13_SECRET_MAX_LEN));
+ RESULT_GUARD(s2n_tls13_secrets_get(conn, secret_type, mode, &secret));
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.3
+ *#
+ *# - A purpose value indicating the specific value being generated
+ **/
+ const struct s2n_blob *key_purpose = &s2n_tls13_label_traffic_secret_key;
+ const struct s2n_blob *iv_purpose = &s2n_tls13_label_traffic_secret_iv;
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.3
+ *#
+ *# - The length of the key being generated
+ **/
+ const uint32_t key_size = cipher->key_material_size;
+ const uint32_t iv_size = S2N_TLS13_FIXED_IV_LEN;
+
+ /*
+ * TODO: We should be able to reuse the prf_work_space rather
+ * than allocating a new HMAC every time.
+ * https://github.com/aws/s2n-tls/issues/3206
+ */
+ s2n_hmac_algorithm hmac_alg = cipher_suite->prf_alg;
+ DEFER_CLEANUP(struct s2n_hmac_state hmac = { 0 }, s2n_hmac_free);
+ RESULT_GUARD_POSIX(s2n_hmac_new(&hmac));
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.3
+ *#
+ *# The traffic keying material is generated from an input traffic secret
+ *# value using:
+ *#
+ *# [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
+ **/
+ struct s2n_blob key = { 0 };
+ uint8_t key_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&key, key_bytes, key_size));
+ RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac, hmac_alg,
+ &secret, key_purpose, &s2n_zero_length_context, &key));
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.3
+ *# [sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)
+ **/
+ struct s2n_blob iv = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&iv, implicit_iv_data, iv_size));
+ RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac, hmac_alg,
+ &secret, iv_purpose, &s2n_zero_length_context, &iv));
+
+ bool is_sending_secret = (mode == conn->mode);
+ if (is_sending_secret) {
+ RESULT_GUARD_POSIX(cipher->set_encryption_key(session_key, &key));
+ } else {
+ RESULT_GUARD_POSIX(cipher->set_decryption_key(session_key, &key));
+ }
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-5.3
+ *# Each sequence number is
+ *# set to zero at the beginning of a connection and whenever the key is
+ *# changed; the first record transmitted under a particular traffic key
+ *# MUST use sequence number 0.
+ */
+ RESULT_GUARD(s2n_zero_sequence_number(conn, mode));
+
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_client_key_schedule(struct s2n_connection *conn)
+{
+ message_type_t message_type = s2n_conn_get_current_message_type(conn);
+
+ /**
+ * How client keys are set varies depending on early data state.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A
+ *# Actions which are taken only in certain circumstances
+ *# are indicated in [].
+ */
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.1
+ *# START <----+
+ *# Send ClientHello | | Recv HelloRetryRequest
+ *# [K_send = early data] | |
+ */
+ if (message_type == CLIENT_HELLO
+ && conn->early_data_state == S2N_EARLY_DATA_REQUESTED) {
+ K_send(conn, S2N_EARLY_SECRET);
+ }
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.1
+ *# v |
+ *# / WAIT_SH ----+
+ *# | | Recv ServerHello
+ *# | | K_recv = handshake
+ */
+ if (message_type == SERVER_HELLO) {
+ K_recv(conn, S2N_HANDSHAKE_SECRET);
+ }
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.1
+ *# Can | V
+ *# send | WAIT_EE
+ *# early | | Recv EncryptedExtensions
+ *# data | +--------+--------+
+ *# | Using | | Using certificate
+ *# | PSK | v
+ *# | | WAIT_CERT_CR
+ *# | | Recv | | Recv CertificateRequest
+ *# | | Certificate | v
+ *# | | | WAIT_CERT
+ *# | | | | Recv Certificate
+ *# | | v v
+ *# | | WAIT_CV
+ *# | | | Recv CertificateVerify
+ *# | +> WAIT_FINISHED <+
+ *# | | Recv Finished
+ *# \ | [Send EndOfEarlyData]
+ *# | K_send = handshake
+ */
+ if ((message_type == SERVER_FINISHED && !WITH_EARLY_DATA(conn))
+ || (message_type == END_OF_EARLY_DATA)) {
+ K_send(conn, S2N_HANDSHAKE_SECRET);
+ }
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.1
+ *# | [Send Certificate [+ CertificateVerify]]
+ *# Can send | Send Finished
+ *# app data --> | K_send = K_recv = application
+ */
+ if (message_type == CLIENT_FINISHED) {
+ K_send(conn, S2N_APPLICATION_SECRET);
+ K_recv(conn, S2N_APPLICATION_SECRET);
+ }
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.1
+ *# after here v
+ *# CONNECTED
+ */
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_server_key_schedule(struct s2n_connection *conn)
+{
+ message_type_t message_type = s2n_conn_get_current_message_type(conn);
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.2
+ *# START <-----+
+ *# Recv ClientHello | | Send HelloRetryRequest
+ *# v |
+ *# RECVD_CH ----+
+ *# | Select parameters
+ *# v
+ *# NEGOTIATED
+ *# | Send ServerHello
+ *# | K_send = handshake
+ */
+ if (message_type == SERVER_HELLO) {
+ K_send(conn, S2N_HANDSHAKE_SECRET);
+ }
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.2
+ *# | Send EncryptedExtensions
+ *# | [Send CertificateRequest]
+ *# Can send | [Send Certificate + CertificateVerify]
+ *# app data | Send Finished
+ *# after --> | K_send = application
+ */
+ if (message_type == SERVER_FINISHED) {
+ K_send(conn, S2N_APPLICATION_SECRET);
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.2
+ *# here +--------+--------+
+ *# No 0-RTT | | 0-RTT
+ *# | |
+ *# K_recv = handshake | | K_recv = early data
+ */
+ if (WITH_EARLY_DATA(conn)) {
+ K_recv(conn, S2N_EARLY_SECRET);
+ } else {
+ K_recv(conn, S2N_HANDSHAKE_SECRET);
+ }
+ }
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.2
+ *# [Skip decrypt errors] | +------> WAIT_EOED -+
+ *# | | Recv | | Recv EndOfEarlyData
+ *# | | early data | | K_recv = handshake
+ *# | +------------+ |
+ */
+ if (message_type == END_OF_EARLY_DATA) {
+ K_recv(conn, S2N_HANDSHAKE_SECRET);
+ }
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.2
+ *# | |
+ *# +> WAIT_FLIGHT2 <--------+
+ *# |
+ *# +--------+--------+
+ *# No auth | | Client auth
+ *# | |
+ *# | v
+ *# | WAIT_CERT
+ *# | Recv | | Recv Certificate
+ *# | empty | v
+ *# | Certificate | WAIT_CV
+ *# | | | Recv
+ *# | v | CertificateVerify
+ *# +-> WAIT_FINISHED <---+
+ *# | Recv Finished
+ *# | K_recv = application
+ */
+ if (message_type == CLIENT_FINISHED) {
+ K_recv(conn, S2N_APPLICATION_SECRET);
+ }
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#appendix-A.2
+ *# v
+ *# CONNECTED
+ */
+ return S2N_RESULT_OK;
+}
+
+s2n_result (*key_schedules[])(struct s2n_connection*) = {
+ [S2N_CLIENT] = &s2n_client_key_schedule,
+ [S2N_SERVER] = &s2n_server_key_schedule,
+};
+
+S2N_RESULT s2n_tls13_key_schedule_update(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
+ return S2N_RESULT_OK;
+ }
+ RESULT_ENSURE_REF(key_schedules[conn->mode]);
+ RESULT_GUARD(key_schedules[conn->mode](conn));
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_tls13_key_schedule_reset(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ conn->client = &conn->initial;
+ conn->server = &conn->initial;
+ conn->secrets.tls13.extract_secret_type = S2N_NONE_SECRET;
+ return S2N_RESULT_OK;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.h b/contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.h
new file mode 100644
index 0000000000..0991be9c06
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_key_schedule.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 "utils/s2n_result.h"
+
+S2N_RESULT s2n_tls13_key_schedule_update(struct s2n_connection *conn);
+S2N_RESULT s2n_tls13_key_schedule_reset(struct s2n_connection *conn);
+
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
new file mode 100644
index 0000000000..9bbe24ec84
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.c
@@ -0,0 +1,626 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file is distributed
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#include "tls/s2n_tls13_secrets.h"
+
+#include "tls/s2n_connection.h"
+#include "tls/s2n_key_log.h"
+#include "tls/s2n_tls13_handshake.h"
+#include "utils/s2n_bitmap.h"
+
+#define S2N_MAX_HASHLEN SHA384_DIGEST_LENGTH
+
+#define CONN_HMAC_ALG(conn) ((conn)->secure.cipher_suite->prf_alg)
+#define CONN_SECRETS(conn) ((conn)->secrets.tls13)
+#define CONN_HASHES(conn) ((conn)->handshake.hashes)
+
+#define CONN_SECRET(conn, secret) ( \
+ (struct s2n_blob) { .data = CONN_SECRETS(conn).secret, .size = s2n_get_hash_len(CONN_HMAC_ALG(conn))} )
+#define CONN_HASH(conn, hash) ( \
+ (struct s2n_blob) { .data = CONN_HASHES(conn)->hash, .size = s2n_get_hash_len(CONN_HMAC_ALG(conn))} )
+#define CONN_FINISHED(conn, mode) ( \
+ (struct s2n_blob) { .data = (conn)->handshake.mode##_finished, .size = s2n_get_hash_len(CONN_HMAC_ALG(conn))})
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# If a given secret is not available, then the 0-value consisting of a
+ *# string of Hash.length bytes set to zeros is used.
+ */
+static uint8_t zero_value_bytes[S2N_MAX_HASHLEN] = { 0 };
+#define ZERO_VALUE(hmac_alg) ( \
+ (const struct s2n_blob) { .data = zero_value_bytes, .size = s2n_get_hash_len(hmac_alg)})
+
+/**
+ * When an operation doesn't need an actual transcript hash,
+ * it uses an empty transcript hash as an input instead.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# Note that in some cases a zero-
+ *# length Context (indicated by "") is passed to HKDF-Expand-Label
+ */
+#define EMPTY_CONTEXT(hmac_alg) ( \
+ (const struct s2n_blob) { .data = s2n_get_empty_context(hmac_alg), .size = s2n_get_hash_len(hmac_alg)})
+
+static uint8_t s2n_get_hash_len(s2n_hmac_algorithm hmac_alg)
+{
+ uint8_t hash_size = 0;
+ if (s2n_hmac_digest_size(hmac_alg, &hash_size) != S2N_SUCCESS) {
+ return 0;
+ }
+ return hash_size;
+}
+
+static uint8_t *s2n_get_empty_context(s2n_hmac_algorithm hmac_alg)
+{
+ static uint8_t sha256_empty_digest[S2N_MAX_HASHLEN] = { 0 };
+ static uint8_t sha384_empty_digest[S2N_MAX_HASHLEN] = { 0 };
+
+ switch(hmac_alg) {
+ case S2N_HMAC_SHA256:
+ return sha256_empty_digest;
+ case S2N_HMAC_SHA384:
+ return sha384_empty_digest;
+ default:
+ return NULL;
+ }
+}
+
+static s2n_hmac_algorithm supported_hmacs[] = {
+ S2N_HMAC_SHA256,
+ S2N_HMAC_SHA384
+};
+
+S2N_RESULT s2n_tls13_empty_transcripts_init()
+{
+ DEFER_CLEANUP(struct s2n_hash_state hash = { 0 }, s2n_hash_free);
+ RESULT_GUARD_POSIX(s2n_hash_new(&hash));
+
+ s2n_hash_algorithm hash_alg = S2N_HASH_NONE;
+ for (size_t i = 0; i < s2n_array_len(supported_hmacs); i++) {
+ s2n_hmac_algorithm hmac_alg = supported_hmacs[i];
+ struct s2n_blob digest = EMPTY_CONTEXT(hmac_alg);
+
+ RESULT_GUARD_POSIX(s2n_hmac_hash_alg(hmac_alg, &hash_alg));
+ RESULT_GUARD_POSIX(s2n_hash_init(&hash, hash_alg));
+ RESULT_GUARD_POSIX(s2n_hash_digest(&hash, digest.data, digest.size));
+ }
+
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_calculate_transcript_digest(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->handshake.hashes);
+
+ s2n_hash_algorithm hash_algorithm = S2N_HASH_NONE;
+ RESULT_ENSURE_REF(conn->secure.cipher_suite);
+ RESULT_GUARD_POSIX(s2n_hmac_hash_alg(conn->secure.cipher_suite->prf_alg, &hash_algorithm));
+
+ uint8_t digest_size = 0;
+ RESULT_GUARD_POSIX(s2n_hash_digest_size(hash_algorithm, &digest_size));
+
+ struct s2n_blob digest = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&digest, CONN_HASHES(conn)->transcript_hash_digest, digest_size));
+
+ struct s2n_hash_state *hash_state = &conn->handshake.hashes->hash_workspace;
+ RESULT_GUARD(s2n_handshake_copy_hash_state(conn, hash_algorithm, hash_state));
+ RESULT_GUARD_POSIX(s2n_hash_digest(hash_state, digest.data, digest.size));
+
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_extract_secret(s2n_hmac_algorithm hmac_alg,
+ const struct s2n_blob *previous_secret_material, const struct s2n_blob *new_secret_material,
+ struct s2n_blob *output)
+{
+ /*
+ * TODO: We should be able to reuse the prf_work_space rather
+ * than allocating a new HMAC every time.
+ * https://github.com/aws/s2n-tls/issues/3206
+ */
+ DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
+ RESULT_GUARD_POSIX(s2n_hmac_new(&hmac_state));
+
+ RESULT_GUARD_POSIX(s2n_hkdf_extract(&hmac_state, hmac_alg,
+ previous_secret_material, new_secret_material, output));
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# Derive-Secret(Secret, Label, Messages) =
+ *# HKDF-Expand-Label(Secret, Label,
+ *# Transcript-Hash(Messages), Hash.length)
+ */
+static S2N_RESULT s2n_derive_secret(s2n_hmac_algorithm hmac_alg,
+ const struct s2n_blob *previous_secret_material, const struct s2n_blob *label, const struct s2n_blob *context,
+ struct s2n_blob *output)
+{
+ /*
+ * TODO: We should be able to reuse the prf_work_space rather
+ * than allocating a new HMAC every time.
+ * https://github.com/aws/s2n-tls/issues/3206
+ */
+ DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
+ RESULT_GUARD_POSIX(s2n_hmac_new(&hmac_state));
+
+ output->size = s2n_get_hash_len(hmac_alg);
+ RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac_state, hmac_alg,
+ previous_secret_material, label, context, output));
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_derive_secret_with_context(struct s2n_connection *conn,
+ s2n_extract_secret_type_t input_secret_type, const struct s2n_blob *label, message_type_t transcript_end_msg,
+ struct s2n_blob *output)
+{
+ RESULT_ENSURE(CONN_SECRETS(conn).extract_secret_type == input_secret_type, S2N_ERR_SECRET_SCHEDULE_STATE);
+ RESULT_ENSURE(s2n_conn_get_current_message_type(conn) == transcript_end_msg, S2N_ERR_SECRET_SCHEDULE_STATE);
+ RESULT_GUARD(s2n_derive_secret(CONN_HMAC_ALG(conn), &CONN_SECRET(conn, extract_secret),
+ label, &CONN_HASH(conn, transcript_hash_digest), output));
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_derive_secret_without_context(struct s2n_connection *conn,
+ s2n_extract_secret_type_t input_secret_type, struct s2n_blob *output)
+{
+ RESULT_ENSURE(CONN_SECRETS(conn).extract_secret_type == input_secret_type, S2N_ERR_SECRET_SCHEDULE_STATE);
+ RESULT_GUARD(s2n_derive_secret(CONN_HMAC_ALG(conn), &CONN_SECRET(conn, extract_secret),
+ &s2n_tls13_label_derived_secret, &EMPTY_CONTEXT(CONN_HMAC_ALG(conn)), output));
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.4.4
+ *# The key used to compute the Finished message is computed from the
+ *# Base Key defined in Section 4.4 using HKDF (see Section 7.1).
+ *# Specifically:
+ *#
+ *# finished_key =
+ *# HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
+ **/
+S2N_RESULT s2n_tls13_compute_finished_key(s2n_hmac_algorithm hmac_alg,
+ const struct s2n_blob *base_key, struct s2n_blob *output)
+{
+ /*
+ * TODO: We should be able to reuse the prf_work_space rather
+ * than allocating a new HMAC every time.
+ */
+ DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
+ RESULT_GUARD_POSIX(s2n_hmac_new(&hmac_state));
+
+ RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac_state, hmac_alg,
+ base_key, &s2n_tls13_label_finished, &(struct s2n_blob){0}, output));
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_trigger_secret_callbacks(struct s2n_connection *conn,
+ const struct s2n_blob *secret, s2n_extract_secret_type_t secret_type, s2n_mode mode)
+{
+ static const s2n_secret_type_t conversions[][2] = {
+ [S2N_EARLY_SECRET] = { S2N_CLIENT_EARLY_TRAFFIC_SECRET, S2N_CLIENT_EARLY_TRAFFIC_SECRET },
+ [S2N_HANDSHAKE_SECRET] = { S2N_SERVER_HANDSHAKE_TRAFFIC_SECRET, S2N_CLIENT_HANDSHAKE_TRAFFIC_SECRET },
+ [S2N_MASTER_SECRET] = { S2N_SERVER_APPLICATION_TRAFFIC_SECRET, S2N_CLIENT_APPLICATION_TRAFFIC_SECRET },
+ };
+ s2n_secret_type_t callback_secret_type = conversions[secret_type][mode];
+
+ if (conn->secret_cb && (s2n_connection_is_quic_enabled(conn) || s2n_in_unit_test())) {
+ RESULT_GUARD_POSIX(conn->secret_cb(conn->secret_cb_context, conn, callback_secret_type,
+ secret->data, secret->size));
+ }
+ s2n_result_ignore(s2n_key_log_tls13_secret(conn, secret, callback_secret_type));
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# 0
+ *# |
+ *# v
+ *# PSK -> HKDF-Extract = Early Secret
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# There are multiple potential Early Secret values, depending on which
+ *# PSK the server ultimately selects. The client will need to compute
+ *# one for each potential PSK
+ */
+S2N_RESULT s2n_extract_early_secret(struct s2n_psk *psk)
+{
+ RESULT_ENSURE_REF(psk);
+ RESULT_GUARD_POSIX(s2n_realloc(&psk->early_secret, s2n_get_hash_len(psk->hmac_alg)));
+ RESULT_GUARD(s2n_extract_secret(psk->hmac_alg,
+ &ZERO_VALUE(psk->hmac_alg),
+ &psk->secret,
+ &psk->early_secret));
+ return S2N_RESULT_OK;
+}
+
+/*
+ * When we require an early secret to derive other secrets,
+ * either retrieve the early secret stored on the chosen / early data PSK
+ * or calculate one using a "zero" PSK.
+ */
+static S2N_RESULT s2n_extract_early_secret_for_schedule(struct s2n_connection *conn)
+{
+ struct s2n_psk *psk = conn->psk_params.chosen_psk;
+ s2n_hmac_algorithm hmac_alg = CONN_HMAC_ALG(conn);
+
+ /*
+ * If the client is sending early data, then the PSK is always assumed
+ * to be the first PSK offered.
+ */
+ if (conn->mode == S2N_CLIENT && conn->early_data_state == S2N_EARLY_DATA_REQUESTED) {
+ RESULT_GUARD(s2n_array_get(&conn->psk_params.psk_list, 0, (void**) &psk));
+ RESULT_ENSURE_REF(psk);
+ }
+
+ /**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# if no PSK is selected, it will then need
+ *# to compute the Early Secret corresponding to the zero PSK.
+ */
+ if (psk == NULL) {
+ RESULT_GUARD(s2n_extract_secret(hmac_alg,
+ &ZERO_VALUE(hmac_alg),
+ &ZERO_VALUE(hmac_alg),
+ &CONN_SECRET(conn, extract_secret)));
+ return S2N_RESULT_OK;
+ }
+
+ /*
+ * The early secret is required to generate or verify a PSK's binder,
+ * so must have already been calculated if a valid PSK exists.
+ * Use the early secret stored on the PSK.
+ */
+ RESULT_ENSURE_EQ(hmac_alg, psk->hmac_alg);
+ RESULT_CHECKED_MEMCPY(CONN_SECRETS(conn).extract_secret, psk->early_secret.data, psk->early_secret.size);
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# |
+ *# +-----> Derive-Secret(., "ext binder" | "res binder", "")
+ *# | = binder_key
+ */
+S2N_RESULT s2n_derive_binder_key(struct s2n_psk *psk, struct s2n_blob *output)
+{
+ const struct s2n_blob *label = &s2n_tls13_label_resumption_psk_binder_key;
+ if (psk->type == S2N_PSK_TYPE_EXTERNAL) {
+ label = &s2n_tls13_label_external_psk_binder_key;
+ }
+ RESULT_GUARD(s2n_extract_early_secret(psk));
+ RESULT_GUARD(s2n_derive_secret(psk->hmac_alg,
+ &psk->early_secret,
+ label,
+ &EMPTY_CONTEXT(psk->hmac_alg),
+ output));
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# |
+ *# +-----> Derive-Secret(., "c e traffic", ClientHello)
+ *# | = client_early_traffic_secret
+ */
+static S2N_RESULT s2n_derive_client_early_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
+{
+ RESULT_GUARD(s2n_derive_secret_with_context(conn,
+ S2N_EARLY_SECRET,
+ &s2n_tls13_label_client_early_traffic_secret,
+ CLIENT_HELLO,
+ output));
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# |
+ *# v
+ *# Derive-Secret(., "derived", "")
+ *# |
+ *# v
+ *# (EC)DHE -> HKDF-Extract = Handshake Secret
+ */
+static S2N_RESULT s2n_extract_handshake_secret(struct s2n_connection *conn)
+{
+ struct s2n_blob derived_secret = { 0 };
+ uint8_t derived_secret_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&derived_secret, derived_secret_bytes, S2N_TLS13_SECRET_MAX_LEN));
+ RESULT_GUARD(s2n_derive_secret_without_context(conn, S2N_EARLY_SECRET, &derived_secret));
+
+ DEFER_CLEANUP(struct s2n_blob shared_secret = { 0 }, s2n_blob_zeroize_free);
+ RESULT_GUARD_POSIX(s2n_tls13_compute_shared_secret(conn, &shared_secret));
+
+ RESULT_GUARD(s2n_extract_secret(CONN_HMAC_ALG(conn),
+ &derived_secret,
+ &shared_secret,
+ &CONN_SECRET(conn, extract_secret)));
+
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# |
+ *# +-----> Derive-Secret(., "c hs traffic",
+ *# | ClientHello...ServerHello)
+ *# | = client_handshake_traffic_secret
+ */
+static S2N_RESULT s2n_derive_client_handshake_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
+{
+ RESULT_GUARD(s2n_derive_secret_with_context(conn,
+ S2N_HANDSHAKE_SECRET,
+ &s2n_tls13_label_client_handshake_traffic_secret,
+ SERVER_HELLO,
+ output));
+
+ /*
+ * The client finished key needs to be calculated using the
+ * same connection state as the client handshake secret.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.4.4
+ *# The key used to compute the Finished message is computed from the
+ *# Base Key defined in Section 4.4 using HKDF (see Section 7.1).
+ */
+ RESULT_GUARD(s2n_tls13_compute_finished_key(CONN_HMAC_ALG(conn),
+ output, &CONN_FINISHED(conn, client)));
+
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# |
+ *# +-----> Derive-Secret(., "s hs traffic",
+ *# | ClientHello...ServerHello)
+ *# | = server_handshake_traffic_secret
+ */
+static S2N_RESULT s2n_derive_server_handshake_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
+{
+ RESULT_GUARD(s2n_derive_secret_with_context(conn,
+ S2N_HANDSHAKE_SECRET,
+ &s2n_tls13_label_server_handshake_traffic_secret,
+ SERVER_HELLO,
+ output));
+
+ /*
+ * The server finished key needs to be calculated using the
+ * same connection state as the server handshake secret.
+ *
+ *= https://tools.ietf.org/rfc/rfc8446#section-4.4.4
+ *# The key used to compute the Finished message is computed from the
+ *# Base Key defined in Section 4.4 using HKDF (see Section 7.1).
+ */
+ RESULT_GUARD(s2n_tls13_compute_finished_key(CONN_HMAC_ALG(conn),
+ output, &CONN_FINISHED(conn, server)));
+
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# v
+ *# Derive-Secret(., "derived", "")
+ *# |
+ *# v
+ *# 0 -> HKDF-Extract = Master Secret
+ */
+static S2N_RESULT s2n_extract_master_secret(struct s2n_connection *conn)
+{
+ struct s2n_blob derived_secret = { 0 };
+ uint8_t derived_secret_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
+ RESULT_GUARD_POSIX(s2n_blob_init(&derived_secret, derived_secret_bytes, S2N_TLS13_SECRET_MAX_LEN));
+ RESULT_GUARD(s2n_derive_secret_without_context(conn, S2N_HANDSHAKE_SECRET, &derived_secret));
+
+ RESULT_GUARD(s2n_extract_secret(CONN_HMAC_ALG(conn),
+ &derived_secret,
+ &ZERO_VALUE(CONN_HMAC_ALG(conn)),
+ &CONN_SECRET(conn, extract_secret)));
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# |
+ *# +-----> Derive-Secret(., "c ap traffic",
+ *# | ClientHello...server Finished)
+ *# | = client_application_traffic_secret_0
+ */
+static S2N_RESULT s2n_derive_client_application_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
+{
+ RESULT_GUARD(s2n_derive_secret_with_context(conn,
+ S2N_MASTER_SECRET,
+ &s2n_tls13_label_client_application_traffic_secret,
+ SERVER_FINISHED,
+ output));
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# |
+ *# +-----> Derive-Secret(., "s ap traffic",
+ *# | ClientHello...server Finished)
+ *# | = server_application_traffic_secret_0
+ */
+static S2N_RESULT s2n_derive_server_application_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
+{
+ RESULT_GUARD(s2n_derive_secret_with_context(conn,
+ S2N_MASTER_SECRET,
+ &s2n_tls13_label_server_application_traffic_secret,
+ SERVER_FINISHED,
+ output));
+ return S2N_RESULT_OK;
+}
+
+/**
+ *= https://tools.ietf.org/rfc/rfc8446#section-7.1
+ *# |
+ *# +-----> Derive-Secret(., "res master",
+ *# ClientHello...client Finished)
+ *# = resumption_master_secret
+ */
+S2N_RESULT s2n_derive_resumption_master_secret(struct s2n_connection *conn)
+{
+ RESULT_GUARD(s2n_derive_secret_with_context(conn,
+ S2N_MASTER_SECRET,
+ &s2n_tls13_label_resumption_master_secret,
+ CLIENT_FINISHED,
+ &CONN_SECRET(conn, resumption_master_secret)));
+ return S2N_RESULT_OK;
+}
+
+static s2n_result (*extract_methods[])(struct s2n_connection *conn) = {
+ [S2N_EARLY_SECRET] = &s2n_extract_early_secret_for_schedule,
+ [S2N_HANDSHAKE_SECRET] = &s2n_extract_handshake_secret,
+ [S2N_MASTER_SECRET] = &s2n_extract_master_secret,
+};
+
+S2N_RESULT s2n_tls13_extract_secret(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(conn->secure.cipher_suite);
+ RESULT_ENSURE_REF(conn->handshake.hashes);
+ RESULT_ENSURE_NE(secret_type, S2N_NONE_SECRET);
+
+ RESULT_ENSURE_GTE(secret_type, 0);
+ RESULT_ENSURE_LT(secret_type, s2n_array_len(extract_methods));
+
+ s2n_extract_secret_type_t next_secret_type = CONN_SECRETS(conn).extract_secret_type + 1;
+ for (s2n_extract_secret_type_t i = next_secret_type; i <= secret_type; i++) {
+ RESULT_ENSURE_REF(extract_methods[i]);
+ RESULT_GUARD(extract_methods[i](conn));
+ CONN_SECRETS(conn).extract_secret_type = i;
+ }
+
+ return S2N_RESULT_OK;
+}
+
+static s2n_result (*derive_methods[][2])(struct s2n_connection *conn, struct s2n_blob *secret) = {
+ [S2N_EARLY_SECRET] = { &s2n_derive_client_early_traffic_secret, &s2n_derive_client_early_traffic_secret },
+ [S2N_HANDSHAKE_SECRET] = { &s2n_derive_server_handshake_traffic_secret, &s2n_derive_client_handshake_traffic_secret },
+ [S2N_MASTER_SECRET] = { &s2n_derive_server_application_traffic_secret, &s2n_derive_client_application_traffic_secret },
+};
+
+S2N_RESULT s2n_tls13_derive_secret(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
+ s2n_mode mode, struct s2n_blob *secret)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(secret);
+ RESULT_ENSURE_REF(conn->secure.cipher_suite);
+ RESULT_ENSURE_REF(conn->handshake.hashes);
+ RESULT_ENSURE_NE(secret_type, S2N_NONE_SECRET);
+
+ RESULT_GUARD(s2n_tls13_extract_secret(conn, secret_type));
+
+ RESULT_ENSURE_GTE(secret_type, 0);
+ RESULT_ENSURE_LT(secret_type, s2n_array_len(derive_methods));
+ RESULT_ENSURE_REF(derive_methods[secret_type][mode]);
+ RESULT_GUARD(derive_methods[secret_type][mode](conn, secret));
+
+ RESULT_GUARD(s2n_trigger_secret_callbacks(conn, secret, secret_type, mode));
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_tls13_secrets_clean(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ if (conn->actual_protocol_version < S2N_TLS13) {
+ return S2N_RESULT_OK;
+ }
+
+ /*
+ * Wipe base secrets.
+ * Not strictly necessary, but probably safer than leaving them.
+ * A compromised secret additionally compromises all secrets derived from it,
+ * so these are the most sensitive secrets.
+ */
+ RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, extract_secret)));
+ conn->secrets.tls13.extract_secret_type = S2N_NONE_SECRET;
+
+ /* Wipe other secrets no longer needed */
+ RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, client_early_secret)));
+ RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, client_handshake_secret)));
+ RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, server_handshake_secret)));
+
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_tls13_secrets_update(struct s2n_connection *conn)
+{
+ RESULT_ENSURE_REF(conn);
+ if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
+ return S2N_RESULT_OK;
+ }
+ RESULT_ENSURE_REF(conn->secure.cipher_suite);
+
+ message_type_t message_type = s2n_conn_get_current_message_type(conn);
+ switch(message_type) {
+ case CLIENT_HELLO:
+ if (conn->early_data_state == S2N_EARLY_DATA_REQUESTED
+ || conn->early_data_state == S2N_EARLY_DATA_ACCEPTED) {
+ RESULT_GUARD(s2n_calculate_transcript_digest(conn));
+ RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_EARLY_SECRET,
+ S2N_CLIENT, &CONN_SECRET(conn, client_early_secret)));
+ }
+ break;
+ case SERVER_HELLO:
+ RESULT_GUARD(s2n_calculate_transcript_digest(conn));
+ RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_HANDSHAKE_SECRET,
+ S2N_CLIENT, &CONN_SECRET(conn, client_handshake_secret)));
+ RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_HANDSHAKE_SECRET,
+ S2N_SERVER, &CONN_SECRET(conn, server_handshake_secret)));
+ break;
+ case SERVER_FINISHED:
+ RESULT_GUARD(s2n_calculate_transcript_digest(conn));
+ RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_MASTER_SECRET,
+ S2N_CLIENT, &CONN_SECRET(conn, client_app_secret)));
+ RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_MASTER_SECRET,
+ S2N_SERVER, &CONN_SECRET(conn, server_app_secret)));
+ break;
+ case CLIENT_FINISHED:
+ RESULT_GUARD(s2n_calculate_transcript_digest(conn));
+ RESULT_GUARD(s2n_derive_resumption_master_secret(conn));
+ break;
+ default:
+ break;
+ }
+ return S2N_RESULT_OK;
+}
+
+S2N_RESULT s2n_tls13_secrets_get(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
+ s2n_mode mode, struct s2n_blob *secret)
+{
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(secret);
+
+ uint8_t *secrets[][2] = {
+ [S2N_EARLY_SECRET] = { NULL, CONN_SECRETS(conn).client_early_secret },
+ [S2N_HANDSHAKE_SECRET] = { CONN_SECRETS(conn).server_handshake_secret, CONN_SECRETS(conn).client_handshake_secret },
+ [S2N_MASTER_SECRET] = { CONN_SECRETS(conn).server_app_secret, CONN_SECRETS(conn).client_app_secret },
+ };
+ RESULT_ENSURE_GT(secret_type, S2N_NONE_SECRET);
+ RESULT_ENSURE_LT(secret_type, s2n_array_len(secrets));
+ RESULT_ENSURE_LTE(secret_type, CONN_SECRETS(conn).extract_secret_type);
+ RESULT_ENSURE_REF(secrets[secret_type][mode]);
+
+ secret->size = s2n_get_hash_len(CONN_HMAC_ALG(conn));
+ RESULT_CHECKED_MEMCPY(secret->data, secrets[secret_type][mode], secret->size);
+ RESULT_ENSURE_GT(secret->size, 0);
+ return S2N_RESULT_OK;
+}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.h b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.h
new file mode 100644
index 0000000000..37c50a117c
--- /dev/null
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_secrets.h
@@ -0,0 +1,55 @@
+/*
+ * 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/s2n_crypto_constants.h"
+#include "tls/s2n_quic_support.h"
+#include "utils/s2n_blob.h"
+#include "utils/s2n_result.h"
+
+/* tls/s2n_tls13_secrets should eventually replace crypto/s2n_tls13_keys.h */
+#include "crypto/s2n_tls13_keys.h"
+
+typedef enum {
+ S2N_NONE_SECRET = 0,
+ S2N_EARLY_SECRET,
+ S2N_HANDSHAKE_SECRET,
+ S2N_MASTER_SECRET
+} s2n_extract_secret_type_t;
+
+struct s2n_tls13_secrets {
+ uint8_t extract_secret[S2N_TLS13_SECRET_MAX_LEN];
+ s2n_extract_secret_type_t extract_secret_type;
+
+ uint8_t client_early_secret[S2N_TLS13_SECRET_MAX_LEN];
+ uint8_t client_handshake_secret[S2N_TLS13_SECRET_MAX_LEN];
+ uint8_t server_handshake_secret[S2N_TLS13_SECRET_MAX_LEN];
+
+ uint8_t client_app_secret[S2N_TLS13_SECRET_MAX_LEN];
+ uint8_t server_app_secret[S2N_TLS13_SECRET_MAX_LEN];
+ uint8_t resumption_master_secret[S2N_TLS13_SECRET_MAX_LEN];
+};
+
+S2N_RESULT s2n_tls13_empty_transcripts_init();
+
+S2N_RESULT s2n_tls13_secrets_update(struct s2n_connection *conn);
+S2N_RESULT s2n_tls13_secrets_get(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
+ s2n_mode mode, struct s2n_blob *secret);
+S2N_RESULT s2n_tls13_secrets_clean(struct s2n_connection *conn);
+
+S2N_RESULT s2n_derive_binder_key(struct s2n_psk *psk, struct s2n_blob *output);
+S2N_RESULT s2n_derive_resumption_master_secret(struct s2n_connection *conn);
+
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls_digest_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_tls_digest_preferences.h
deleted file mode 100644
index 9b856cf481..0000000000
--- a/contrib/restricted/aws/s2n/tls/s2n_tls_digest_preferences.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * A copy of the License is located at
- *
- * http://aws.amazon.com/apache2.0
- *
- * or in the "license" file accompanying this file. This file is distributed
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-#pragma once
-
-#include "tls/s2n_tls_parameters.h"
-
-#include "crypto/s2n_hash.h"
-
-/* Table to translate TLS numbers to s2n algorithms */
-static const s2n_hash_algorithm s2n_hash_tls_to_alg[] = {
- [TLS_HASH_ALGORITHM_MD5] = S2N_HASH_MD5,
- [TLS_HASH_ALGORITHM_SHA1] = S2N_HASH_SHA1,
- [TLS_HASH_ALGORITHM_SHA224] = S2N_HASH_SHA224,
- [TLS_HASH_ALGORITHM_SHA256] = S2N_HASH_SHA256,
- [TLS_HASH_ALGORITHM_SHA384] = S2N_HASH_SHA384,
- [TLS_HASH_ALGORITHM_SHA512] = S2N_HASH_SHA512 };
-
-/* Table to translate from s2n algorithm numbers to TLS numbers */
-static const uint8_t s2n_hash_alg_to_tls[] = {
- [S2N_HASH_MD5] = TLS_HASH_ALGORITHM_MD5,
- [S2N_HASH_SHA1] = TLS_HASH_ALGORITHM_SHA1,
- [S2N_HASH_SHA224] = TLS_HASH_ALGORITHM_SHA224,
- [S2N_HASH_SHA256] = TLS_HASH_ALGORITHM_SHA256,
- [S2N_HASH_SHA384] = TLS_HASH_ALGORITHM_SHA384,
- [S2N_HASH_SHA512] = TLS_HASH_ALGORITHM_SHA512 };
-
diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h b/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
index 7bce43d0b2..c998d6b1c8 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h
@@ -65,20 +65,27 @@
#define TLS_EXTENSION_PQ_KEM_PARAMETERS 0xFE01
#define TLS_PQ_KEM_EXTENSION_ID_BIKE1_L1_R1 1
#define TLS_PQ_KEM_EXTENSION_ID_BIKE1_L1_R2 13
+#define TLS_PQ_KEM_EXTENSION_ID_BIKE1_L1_R3 25
#define TLS_PQ_KEM_EXTENSION_ID_SIKE_P503_R1 10
-#define TLS_PQ_KEM_EXTENSION_ID_SIKE_P434_R2 19
+#define TLS_PQ_KEM_EXTENSION_ID_SIKE_P434_R3 19
#define TLS_PQ_KEM_EXTENSION_ID_KYBER_512_R2 23
#define TLS_PQ_KEM_EXTENSION_ID_KYBER_512_90S_R2 24
+#define TLS_PQ_KEM_EXTENSION_ID_KYBER_512_R3 28
/* TLS 1.3 hybrid post-quantum definitions are from the proposed reserved range defined
- * in https://tools.ietf.org/html/draft-stebila-tls-hybrid-design. Values for interoperability
- * are defined in https://docs.google.com/spreadsheets/d/12YarzaNv3XQNLnvDsWLlRKwtZFhRrDdWf36YlzwrPeg/edit#gid=0. */
-#define TLS_PQ_KEM_GROUP_ID_X25519_SIKE_P434_R2 0x2F27
-#define TLS_PQ_KEM_GROUP_ID_SECP256R1_SIKE_P434_R2 0x2F1F
-#define TLS_PQ_KEM_GROUP_ID_X25519_BIKE1_L1_R2 0x2F28
-#define TLS_PQ_KEM_GROUP_ID_SECP256R1_BIKE1_L1_R2 0x2F23
-#define TLS_PQ_KEM_GROUP_ID_X25519_KYBER_512_R2 0x2F26
-#define TLS_PQ_KEM_GROUP_ID_SECP256R1_KYBER_512_R2 0x2F0F
+ * in https://tools.ietf.org/html/draft-stebila-tls-hybrid-design. Values for interoperability are defined in
+ * https://github.com/open-quantum-safe/openssl/blob/OQS-OpenSSL_1_1_1-stable/oqs-template/oqs-kem-info.md */
+#define TLS_PQ_KEM_GROUP_ID_X25519_SIKE_P434_R3 0x2F27
+#define TLS_PQ_KEM_GROUP_ID_SECP256R1_SIKE_P434_R3 0x2F1F
+#define TLS_PQ_KEM_GROUP_ID_X25519_BIKE1_L1_R2 0x2F28
+#define TLS_PQ_KEM_GROUP_ID_SECP256R1_BIKE1_L1_R2 0x2F23
+#define TLS_PQ_KEM_GROUP_ID_X25519_KYBER_512_R2 0x2F26
+#define TLS_PQ_KEM_GROUP_ID_SECP256R1_KYBER_512_R2 0x2F0F
+#define TLS_PQ_KEM_GROUP_ID_X25519_BIKE_L1_R3 0x2F37
+#define TLS_PQ_KEM_GROUP_ID_SECP256R1_BIKE_L1_R3 0x2F38
+#define TLS_PQ_KEM_GROUP_ID_X25519_KYBER_512_R3 0x2F39
+#define TLS_PQ_KEM_GROUP_ID_SECP256R1_KYBER_512_R3 0x2F3A
+
/* From https://tools.ietf.org/html/rfc7507 */
#define TLS_FALLBACK_SCSV 0x56, 0x00
@@ -100,12 +107,14 @@
#define TLS_EXTENSION_SIGNATURE_ALGORITHMS 13
#define TLS_EXTENSION_ALPN 16
#define TLS_EXTENSION_SCT_LIST 18
+#define TLS_EXTENSION_EMS 23
#define TLS_EXTENSION_SESSION_TICKET 35
#define TLS_EXTENSION_PRE_SHARED_KEY 41
#define TLS_EXTENSION_CERT_AUTHORITIES 47
#define TLS_EXTENSION_RENEGOTIATION_INFO 65281
/* TLS 1.3 extensions from https://tools.ietf.org/html/rfc8446#section-4.2 */
+#define TLS_EXTENSION_EARLY_DATA 42
#define TLS_EXTENSION_SUPPORTED_VERSIONS 43
#define TLS_EXTENSION_COOKIE 44
#define TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES 45
@@ -116,33 +125,12 @@
#define TLS_PSK_DHE_KE_MODE 1
/**
- *= https://tools.ietf.org/id/draft-ietf-quic-tls-32.txt#8.2
+ *= https://tools.ietf.org/rfc/rfc9001.txt#8.2
*# enum {
- *# quic_transport_parameters(0xffa5), (65535)
+ *# quic_transport_parameters(0x39), (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 */
-#define TLS_SIGNATURE_ALGORITHM_ANONYMOUS 0
-#define TLS_SIGNATURE_ALGORITHM_RSA 1
-#define TLS_SIGNATURE_ALGORITHM_DSA 2
-#define TLS_SIGNATURE_ALGORITHM_ECDSA 3
-#define TLS_SIGNATURE_ALGORITHM_PRIVATE 224
-
-#define TLS_SIGNATURE_ALGORITHM_COUNT 4
-
-/* TLS Hash Algorithm - https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
-/* https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-18 */
-#define TLS_HASH_ALGORITHM_ANONYMOUS 0
-#define TLS_HASH_ALGORITHM_MD5 1
-#define TLS_HASH_ALGORITHM_SHA1 2
-#define TLS_HASH_ALGORITHM_SHA224 3
-#define TLS_HASH_ALGORITHM_SHA256 4
-#define TLS_HASH_ALGORITHM_SHA384 5
-#define TLS_HASH_ALGORITHM_SHA512 6
-#define TLS_HASH_ALGORITHM_COUNT 7
+#define TLS_QUIC_TRANSPORT_PARAMETERS 0x39
/* TLS SignatureScheme (Backwards compatible with SigHash and SigAlg values above) */
/* Defined here: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme */
@@ -201,6 +189,7 @@
#define TLS_EC_CURVE_SECP_384_R1 24
#define TLS_EC_CURVE_SECP_521_R1 25
#define TLS_EC_CURVE_ECDH_X25519 29
+#define TLS_EC_CURVE_ECDH_X448 30
/* Ethernet maximum transmission unit (MTU)
* MTU is usually associated with the Ethernet protocol,
@@ -214,21 +203,8 @@
#define TCP_HEADER_LENGTH 20
#define TCP_OPTIONS_LENGTH 40
-/* The maximum size of a TLS record is 16389 bytes. This is; 1 byte for content
- * type, 2 bytes for the protocol version, 2 bytes for the length field,
- * and then up to 2^14 for the encrypted+compressed payload data.
- */
-#define S2N_TLS_RECORD_HEADER_LENGTH 5
-#define S2N_TLS_MAXIMUM_FRAGMENT_LENGTH 16384
-/* Maximum TLS record length allows for 2048 octets of compression expansion and padding */
-#define S2N_TLS_MAXIMUM_RECORD_LENGTH (S2N_TLS_MAXIMUM_FRAGMENT_LENGTH + S2N_TLS_RECORD_HEADER_LENGTH + 2048)
#define S2N_TLS_MAX_FRAG_LEN_EXT_NONE 0
-/* TLS1.3 has a max fragment length of 2^14 + 1 byte for the content type */
-#define S2N_TLS13_MAXIMUM_FRAGMENT_LENGTH 16385
-/* Max encryption overhead is 255 for AEAD padding */
-#define S2N_TLS13_MAXIMUM_RECORD_LENGTH (S2N_TLS13_MAXIMUM_FRAGMENT_LENGTH + S2N_TLS_RECORD_HEADER_LENGTH + 255)
-
/* The maximum size of an SSL2 message is 2^14 - 1, as neither of the first two
* bits in the length field are usable. Per;
* http://www-archive.mozilla.org/projects/security/pki/nss/ssl/draft02.html
@@ -258,7 +234,6 @@
*/
#define S2N_LARGE_RECORD_LENGTH S2N_TLS_MAXIMUM_RECORD_LENGTH
#define S2N_LARGE_FRAGMENT_LENGTH S2N_TLS_MAXIMUM_FRAGMENT_LENGTH
-#define S2N_TLS13_LARGE_FRAGMENT_LENGTH S2N_TLS13_MAXIMUM_FRAGMENT_LENGTH
/* Cap dynamic record resize threshold to 8M */
#define S2N_TLS_MAX_RESIZE_THRESHOLD (1024 * 1024 * 8)
diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
index da2eea8be6..4506878ced 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
+++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c
@@ -30,7 +30,7 @@
#include <openssl/asn1.h>
#include <openssl/x509.h>
-#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
+#if !defined(OPENSSL_IS_BORINGSSL)
#include <openssl/ocsp.h>
#endif
@@ -42,13 +42,6 @@
/* Time used by default for nextUpdate if none provided in OCSP: 1 hour since thisUpdate. */
#define DEFAULT_OCSP_NEXT_UPDATE_PERIOD 3600000000000
-typedef enum {
- UNINIT,
- INIT,
- VALIDATED,
- OCSP_VALIDATED,
-} validator_state;
-
uint8_t s2n_x509_ocsp_stapling_supported(void) {
return S2N_OCSP_STAPLING_SUPPORTED;
}
@@ -64,13 +57,13 @@ uint8_t s2n_x509_trust_store_has_certs(struct s2n_x509_trust_store *store) {
int s2n_x509_trust_store_from_system_defaults(struct s2n_x509_trust_store *store) {
if (!store->trust_store) {
store->trust_store = X509_STORE_new();
- notnull_check(store->trust_store);
+ POSIX_ENSURE_REF(store->trust_store);
}
int err_code = X509_STORE_set_default_paths(store->trust_store);
if (!err_code) {
s2n_x509_trust_store_wipe(store);
- S2N_ERROR(S2N_ERR_X509_TRUST_STORE);
+ POSIX_BAIL(S2N_ERR_X509_TRUST_STORE);
}
X509_STORE_set_flags(store->trust_store, X509_VP_FLAG_DEFAULT);
@@ -80,8 +73,8 @@ int s2n_x509_trust_store_from_system_defaults(struct s2n_x509_trust_store *store
int s2n_x509_trust_store_add_pem(struct s2n_x509_trust_store *store, const char *pem)
{
- notnull_check(store);
- notnull_check(pem);
+ POSIX_ENSURE_REF(store);
+ POSIX_ENSURE_REF(pem);
if (!store->trust_store) {
store->trust_store = X509_STORE_new();
@@ -90,21 +83,24 @@ int s2n_x509_trust_store_add_pem(struct s2n_x509_trust_store *store, const char
DEFER_CLEANUP(struct s2n_stuffer pem_in_stuffer = {0}, s2n_stuffer_free);
DEFER_CLEANUP(struct s2n_stuffer der_out_stuffer = {0}, s2n_stuffer_free);
- GUARD(s2n_stuffer_alloc_ro_from_string(&pem_in_stuffer, pem));
- GUARD(s2n_stuffer_growable_alloc(&der_out_stuffer, 2048));
+ POSIX_GUARD(s2n_stuffer_alloc_ro_from_string(&pem_in_stuffer, pem));
+ POSIX_GUARD(s2n_stuffer_growable_alloc(&der_out_stuffer, 2048));
do {
DEFER_CLEANUP(struct s2n_blob next_cert = {0}, s2n_free);
- GUARD(s2n_stuffer_certificate_from_pem(&pem_in_stuffer, &der_out_stuffer));
- GUARD(s2n_alloc(&next_cert, s2n_stuffer_data_available(&der_out_stuffer)));
- GUARD(s2n_stuffer_read(&der_out_stuffer, &next_cert));
+ POSIX_GUARD(s2n_stuffer_certificate_from_pem(&pem_in_stuffer, &der_out_stuffer));
+ POSIX_GUARD(s2n_alloc(&next_cert, s2n_stuffer_data_available(&der_out_stuffer)));
+ POSIX_GUARD(s2n_stuffer_read(&der_out_stuffer, &next_cert));
const uint8_t *data = next_cert.data;
DEFER_CLEANUP(X509 *ca_cert = d2i_X509(NULL, &data, next_cert.size), X509_free_pointer);
S2N_ERROR_IF(ca_cert == NULL, S2N_ERR_DECODE_CERTIFICATE);
- GUARD_OSSL(X509_STORE_add_cert(store->trust_store, ca_cert), S2N_ERR_DECODE_CERTIFICATE);
+ if (!X509_STORE_add_cert(store->trust_store, ca_cert)) {
+ unsigned long error = ERR_get_error();
+ POSIX_ENSURE(ERR_GET_REASON(error) == X509_R_CERT_ALREADY_IN_HASH_TABLE, S2N_ERR_DECODE_CERTIFICATE);
+ }
} while (s2n_stuffer_data_available(&pem_in_stuffer));
return 0;
@@ -113,13 +109,13 @@ int s2n_x509_trust_store_add_pem(struct s2n_x509_trust_store *store, const char
int s2n_x509_trust_store_from_ca_file(struct s2n_x509_trust_store *store, const char *ca_pem_filename, const char *ca_dir) {
if (!store->trust_store) {
store->trust_store = X509_STORE_new();
- notnull_check(store->trust_store);
+ POSIX_ENSURE_REF(store->trust_store);
}
int err_code = X509_STORE_load_locations(store->trust_store, ca_pem_filename, ca_dir);
if (!err_code) {
s2n_x509_trust_store_wipe(store);
- S2N_ERROR(S2N_ERR_X509_TRUST_STORE);
+ POSIX_BAIL(S2N_ERR_X509_TRUST_STORE);
}
/* It's a likely scenario if this function is called, a self-signed certificate is used, and that is was generated
@@ -141,7 +137,7 @@ void s2n_x509_trust_store_wipe(struct s2n_x509_trust_store *store) {
}
int s2n_x509_validator_init_no_x509_validation(struct s2n_x509_validator *validator) {
- notnull_check(validator);
+ POSIX_ENSURE_REF(validator);
validator->trust_store = NULL;
validator->store_ctx = NULL;
validator->skip_cert_validation = 1;
@@ -154,7 +150,7 @@ int s2n_x509_validator_init_no_x509_validation(struct s2n_x509_validator *valida
}
int s2n_x509_validator_init(struct s2n_x509_validator *validator, struct s2n_x509_trust_store *trust_store, uint8_t check_ocsp) {
- notnull_check(trust_store);
+ POSIX_ENSURE_REF(trust_store);
validator->trust_store = trust_store;
validator->skip_cert_validation = 0;
validator->check_stapled_ocsp = check_ocsp;
@@ -162,7 +158,7 @@ int s2n_x509_validator_init(struct s2n_x509_validator *validator, struct s2n_x50
validator->store_ctx = NULL;
if (validator->trust_store->trust_store) {
validator->store_ctx = X509_STORE_CTX_new();
- notnull_check(validator->store_ctx);
+ POSIX_ENSURE_REF(validator->store_ctx);
}
validator->cert_chain_from_wire = sk_X509_new_null();
validator->state = INIT;
@@ -190,7 +186,7 @@ void s2n_x509_validator_wipe(struct s2n_x509_validator *validator) {
}
int s2n_x509_validator_set_max_chain_depth(struct s2n_x509_validator *validator, uint16_t max_depth) {
- notnull_check(validator);
+ POSIX_ENSURE_REF(validator);
S2N_ERROR_IF(max_depth == 0, S2N_ERR_INVALID_ARGUMENT);
validator->max_chain_depth = max_depth;
@@ -265,7 +261,7 @@ static uint8_t s2n_verify_host_information(struct s2n_x509_validator *validator,
if (common_name) {
char peer_cn[255];
static size_t peer_cn_size = sizeof(peer_cn);
- memset_check(&peer_cn, 0, peer_cn_size);
+ POSIX_CHECKED_MEMSET(&peer_cn, 0, peer_cn_size);
/* X520CommonName allows the following ANSI string types per RFC 5280 Appendix A.1 */
if (ASN1_STRING_type(common_name) == V_ASN1_TELETEXSTRING ||
@@ -276,8 +272,8 @@ static uint8_t s2n_verify_host_information(struct s2n_x509_validator *validator,
size_t len = (size_t) ASN1_STRING_length(common_name);
- lte_check(len, sizeof(peer_cn) - 1);
- memcpy_check(peer_cn, ASN1_STRING_data(common_name), len);
+ POSIX_ENSURE_LTE(len, sizeof(peer_cn) - 1);
+ POSIX_CHECKED_MEMCPY(peer_cn, ASN1_STRING_data(common_name), len);
verified = conn->verify_host_fn(peer_cn, len, conn->data_for_verify_host);
}
}
@@ -291,7 +287,7 @@ static uint8_t s2n_verify_host_information(struct s2n_x509_validator *validator,
s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_validator *validator, struct s2n_connection *conn,
uint8_t *cert_chain_in, uint32_t cert_chain_len, s2n_pkey_type *pkey_type, struct s2n_pkey *public_key_out) {
S2N_ERROR_IF(!validator->skip_cert_validation && !s2n_x509_trust_store_has_certs(validator->trust_store), S2N_ERR_CERT_UNTRUSTED);
- S2N_ERROR_IF(validator->state != INIT, S2N_ERR_INVALID_STATE);
+ S2N_ERROR_IF(validator->state != INIT, S2N_ERR_INVALID_CERT_STATE);
struct s2n_blob cert_chain_blob = {.data = cert_chain_in, .size = cert_chain_len};
DEFER_CLEANUP(struct s2n_stuffer cert_chain_in_stuffer = {0}, s2n_stuffer_free);
@@ -315,7 +311,7 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_
struct s2n_blob asn1cert = {0};
asn1cert.size = certificate_size;
asn1cert.data = s2n_stuffer_raw_read(&cert_chain_in_stuffer, certificate_size);
- notnull_check(asn1cert.data);
+ POSIX_ENSURE_REF(asn1cert.data);
const uint8_t *data = asn1cert.data;
@@ -326,11 +322,11 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_
/* add the cert to the chain. */
if (!sk_X509_push(validator->cert_chain_from_wire, server_cert)) {
X509_free(server_cert);
- S2N_ERROR(S2N_ERR_CERT_UNTRUSTED);
+ POSIX_BAIL(S2N_ERR_CERT_UNTRUSTED);
}
if (!validator->skip_cert_validation) {
- GUARD_AS_POSIX(s2n_validate_certificate_signature(conn, server_cert));
+ POSIX_GUARD_RESULT(s2n_validate_certificate_signature(conn, server_cert));
}
/* Pull the public key from the first certificate */
@@ -341,7 +337,7 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_
/* certificate extensions is a field in TLS 1.3 - https://tools.ietf.org/html/rfc8446#section-4.4.2 */
if (conn->actual_protocol_version >= S2N_TLS13) {
s2n_parsed_extensions_list parsed_extensions_list = { 0 };
- GUARD(s2n_extension_list_parse(&cert_chain_in_stuffer, &parsed_extensions_list));
+ POSIX_GUARD(s2n_extension_list_parse(&cert_chain_in_stuffer, &parsed_extensions_list));
/* RFC 8446: if an extension applies to the entire chain, it SHOULD be included in the first CertificateEntry */
if (sk_X509_num(validator->cert_chain_from_wire) == 1) {
@@ -379,7 +375,7 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_chain(struct s2n_x509_
}
if (conn->actual_protocol_version >= S2N_TLS13) {
- GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_CERTIFICATE, conn, &first_certificate_extensions));
+ POSIX_GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_CERTIFICATE, conn, &first_certificate_extensions));
}
*public_key_out = public_key;
@@ -398,7 +394,7 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(
return S2N_CERT_OK;
}
- S2N_ERROR_IF(validator->state != VALIDATED, S2N_ERR_INVALID_STATE);
+ S2N_ERROR_IF(validator->state != VALIDATED, S2N_ERR_INVALID_CERT_STATE);
#if !S2N_OCSP_STAPLING_SUPPORTED
/* Default to safety */
@@ -467,13 +463,15 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(
}
/* Important: this checks that the stapled ocsp response CAN be verified, not that it has been verified. */
- const int ocsp_verify_err = OCSP_basic_verify(basic_response, cert_chain, validator->trust_store->trust_store, 0);
- /* do the crypto checks on the response.*/
- if (!ocsp_verify_err) {
- ret_val = S2N_CERT_ERR_UNTRUSTED;
+ const int ocsp_verify_res = OCSP_basic_verify(basic_response, cert_chain, validator->trust_store->trust_store, 0);
+
+ /* OCSP_basic_verify() returns 1 on success, 0 on error, or -1 on fatal error such as malloc failure. */
+ if (ocsp_verify_res != _OSSL_SUCCESS) {
+ ret_val = ocsp_verify_res == 0 ? S2N_CERT_ERR_UNTRUSTED : S2N_CERT_ERR_INTERNAL_ERROR;
goto clean_up;
}
+ /* do the crypto checks on the response.*/
int status = 0;
int reason = 0;
@@ -557,42 +555,42 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(
S2N_RESULT s2n_validate_certificate_signature(struct s2n_connection *conn, X509 *x509_cert)
{
- ENSURE_REF(conn);
- ENSURE_REF(x509_cert);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(x509_cert);
const struct s2n_security_policy *security_policy;
- GUARD_AS_RESULT(s2n_connection_get_security_policy(conn, &security_policy));
+ RESULT_GUARD_POSIX(s2n_connection_get_security_policy(conn, &security_policy));
if (security_policy->certificate_signature_preferences == NULL) {
return S2N_RESULT_OK;
}
X509_NAME *issuer_name = X509_get_issuer_name(x509_cert);
- ENSURE_REF(issuer_name);
+ RESULT_ENSURE_REF(issuer_name);
X509_NAME *subject_name = X509_get_subject_name(x509_cert);
- ENSURE_REF(subject_name);
+ RESULT_ENSURE_REF(subject_name);
/* Do not validate any self-signed certificates */
if (X509_NAME_cmp(issuer_name, subject_name) == 0) {
return S2N_RESULT_OK;
}
- GUARD_RESULT(s2n_validate_sig_scheme_supported(conn, x509_cert, security_policy->certificate_signature_preferences));
+ RESULT_GUARD(s2n_validate_sig_scheme_supported(conn, x509_cert, security_policy->certificate_signature_preferences));
return S2N_RESULT_OK;
}
S2N_RESULT s2n_validate_sig_scheme_supported(struct s2n_connection *conn, X509 *x509_cert, const struct s2n_signature_preferences *cert_sig_preferences)
{
- ENSURE_REF(conn);
- ENSURE_REF(x509_cert);
- ENSURE_REF(cert_sig_preferences);
+ RESULT_ENSURE_REF(conn);
+ RESULT_ENSURE_REF(x509_cert);
+ RESULT_ENSURE_REF(cert_sig_preferences);
int nid = 0;
#if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x02070000f)
- ENSURE_REF(x509_cert->sig_alg);
+ RESULT_ENSURE_REF(x509_cert->sig_alg);
nid = OBJ_obj2nid(x509_cert->sig_alg->algorithm);
#else
nid = X509_get_signature_nid(x509_cert);
@@ -602,12 +600,17 @@ S2N_RESULT s2n_validate_sig_scheme_supported(struct s2n_connection *conn, X509 *
if (cert_sig_preferences->signature_schemes[i]->libcrypto_nid == nid) {
/* SHA-1 algorithms are not supported in certificate signatures in TLS1.3 */
- ENSURE(!(conn->actual_protocol_version >= S2N_TLS13 &&
+ RESULT_ENSURE(!(conn->actual_protocol_version >= S2N_TLS13 &&
cert_sig_preferences->signature_schemes[i]->hash_alg == S2N_HASH_SHA1), S2N_ERR_CERT_UNTRUSTED);
return S2N_RESULT_OK;
}
}
- BAIL(S2N_ERR_CERT_UNTRUSTED);
+ RESULT_BAIL(S2N_ERR_CERT_UNTRUSTED);
+}
+
+bool s2n_x509_validator_is_cert_chain_validated(const struct s2n_x509_validator *validator)
+{
+ return validator && (validator->state == VALIDATED || validator->state == OCSP_VALIDATED);
}
diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
index 9e57bb4d34..b35d535141 100644
--- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
+++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h
@@ -21,13 +21,13 @@
#include <openssl/x509v3.h>
-/* one day, BoringSSL/AWS-LC, may add ocsp stapling support. Let's future proof this a bit by grabbing a definition
+/* one day, BoringSSL may add ocsp stapling support. Let's future proof this a bit by grabbing a definition
* that would have to be there when they add support */
-#if (defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)) && !defined(OCSP_RESPONSE_STATUS_SUCCESSFUL)
+#if defined(OPENSSL_IS_BORINGSSL) && !defined(OCSP_RESPONSE_STATUS_SUCCESSFUL)
#define S2N_OCSP_STAPLING_SUPPORTED 0
#else
#define S2N_OCSP_STAPLING_SUPPORTED 1
-#endif /* (defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)) && !defined(OCSP_RESPONSE_STATUS_SUCCESSFUL) */
+#endif /* defined(OPENSSL_IS_BORINGSSL) && !defined(OCSP_RESPONSE_STATUS_SUCCESSFUL) */
typedef enum {
S2N_CERT_OK = 0,
@@ -36,9 +36,17 @@ typedef enum {
S2N_CERT_ERR_EXPIRED = -3,
S2N_CERT_ERR_TYPE_UNSUPPORTED = -4,
S2N_CERT_ERR_INVALID = -5,
- S2N_CERT_ERR_MAX_CHAIN_DEPTH_EXCEEDED = -6
+ S2N_CERT_ERR_MAX_CHAIN_DEPTH_EXCEEDED = -6,
+ S2N_CERT_ERR_INTERNAL_ERROR = -7
} s2n_cert_validation_code;
+typedef enum {
+ UNINIT,
+ INIT,
+ VALIDATED,
+ OCSP_VALIDATED,
+} validator_state;
+
/** Return TRUE for trusted, FALSE for untrusted **/
typedef uint8_t (*verify_host) (const char *host_name, size_t host_name_len, void *data);
struct s2n_connection;
@@ -125,6 +133,12 @@ s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(
const uint8_t *ocsp_response, uint32_t size);
/**
+ * Checks whether the peer's certificate chain has been received and validated.
+ * Should be verified before any use of the peer's certificate data.
+ */
+bool s2n_x509_validator_is_cert_chain_validated(const struct s2n_x509_validator *validator);
+
+/**
* Validates that each certificate in a peer's cert chain contains only signature algorithms in a security policy's
* certificate_signatures_preference list.
*/