diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:45:01 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:01 +0300 |
commit | 2d37894b1b037cf24231090eda8589bbb44fb6fc (patch) | |
tree | be835aa92c6248212e705f25388ebafcf84bc7a1 /contrib/restricted/aws/s2n/tls | |
parent | 718c552901d703c502ccbefdfc3c9028d608b947 (diff) | |
download | ydb-2d37894b1b037cf24231090eda8589bbb44fb6fc.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/restricted/aws/s2n/tls')
161 files changed, 25479 insertions, 25479 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 7ad2946880..e66b7c0478 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.c @@ -1,129 +1,129 @@ -/* - * 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/extensions/s2n_client_alpn.h" - -#include "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" - -#include "utils/s2n_safety.h" - -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); -static int s2n_client_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_alpn_extension = { - .iana_value = TLS_EXTENSION_ALPN, - .is_response = false, - .send = s2n_client_alpn_send, - .recv = s2n_client_alpn_recv, - .should_send = s2n_client_alpn_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_client_alpn_should_send(struct s2n_connection *conn) -{ - struct s2n_blob *client_app_protocols; - - return s2n_connection_get_protocol_preferences(conn, &client_app_protocols) == S2N_SUCCESS - && client_app_protocols->size != 0 && client_app_protocols->data != NULL; -} - -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); - - GUARD(s2n_stuffer_write_uint16(out, client_app_protocols->size)); - GUARD(s2n_stuffer_write(out, client_app_protocols)); - - return S2N_SUCCESS; -} - -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)); - - if (!server_app_protocols->size) { - /* No protocols configured, nothing to do */ - return S2N_SUCCESS; - } - - 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; - } - - 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); - - /* 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; - } - } - } - - GUARD(s2n_stuffer_reread(&client_protos)); - } - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_extensions_client_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_client_alpn_extension, conn, out); -} - -int s2n_recv_client_alpn(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_alpn_extension, conn, extension); -} +/* + * 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/extensions/s2n_client_alpn.h" + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" + +#include "utils/s2n_safety.h" + +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); +static int s2n_client_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_alpn_extension = { + .iana_value = TLS_EXTENSION_ALPN, + .is_response = false, + .send = s2n_client_alpn_send, + .recv = s2n_client_alpn_recv, + .should_send = s2n_client_alpn_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_client_alpn_should_send(struct s2n_connection *conn) +{ + struct s2n_blob *client_app_protocols; + + return s2n_connection_get_protocol_preferences(conn, &client_app_protocols) == S2N_SUCCESS + && client_app_protocols->size != 0 && client_app_protocols->data != NULL; +} + +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); + + GUARD(s2n_stuffer_write_uint16(out, client_app_protocols->size)); + GUARD(s2n_stuffer_write(out, client_app_protocols)); + + return S2N_SUCCESS; +} + +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)); + + if (!server_app_protocols->size) { + /* No protocols configured, nothing to do */ + return S2N_SUCCESS; + } + + 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; + } + + 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); + + /* 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; + } + } + } + + GUARD(s2n_stuffer_reread(&client_protos)); + } + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_extensions_client_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_client_alpn_extension, conn, out); +} + +int s2n_recv_client_alpn(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_alpn_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.h index d25bbb027b..177ca5daea 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_alpn.h @@ -1,27 +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 "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_alpn_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -extern int s2n_extensions_client_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out); -extern int s2n_recv_client_alpn(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_alpn_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +extern int s2n_extensions_client_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out); +extern int s2n_recv_client_alpn(struct s2n_connection *conn, struct s2n_stuffer *extension); 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 1e3ea069f2..97797cc054 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 @@ -1,521 +1,521 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "tls/extensions/s2n_client_key_share.h" -#include "tls/extensions/s2n_key_share.h" -#include "tls/s2n_security_policies.h" -#include "tls/s2n_kem_preferences.h" - -#include "error/s2n_errno.h" -#include "stuffer/s2n_stuffer.h" -#include "utils/s2n_safety.h" -#include "tls/s2n_tls13.h" -#include "crypto/s2n_fips.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." - * - * Structure: - * Extension type (2 bytes) - * Extension data size (2 bytes) - * Client shares size (2 bytes) - * Client shares: - * Named group (2 bytes) - * Key share size (2 bytes) - * Key share (variable size) - * - * This extension only modifies the connection's client ecc_evp_params. It does - * not make any decisions about which set of params to use. - * - * The server will NOT alert when processing a client extension that violates the RFC. - * So the server will accept: - * - Multiple key shares for the same named group. The server will accept the first - * key share for the group and ignore any duplicates. - * - Key shares for named groups not in the client's supported_groups extension. - **/ - -static int s2n_client_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_client_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_key_share_extension = { - .iana_value = TLS_EXTENSION_KEY_SHARE, - .is_response = false, - .send = s2n_client_key_share_send, - .recv = s2n_client_key_share_recv, - .should_send = s2n_extension_send_if_tls13_connection, - .if_missing = s2n_extension_noop_if_missing, -}; - -static int s2n_generate_preferred_ecc_key_shares(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; - - const struct s2n_ecc_preferences *ecc_pref = NULL; - GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); - notnull_check(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; - } - - 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)); - } - } - - 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); - - 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)); - - 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); - - /* This function should never be called when in FIPS mode */ - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); - - const struct s2n_kem_group *kem_group = kem_group_params->kem_group; - notnull_check(kem_group); - - /* The structure of the PQ share is: - * IANA ID (2 bytes) - * || total share size (2 bytes) - * || size of ECC key share (2 bytes) - * || 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)); - - struct s2n_stuffer_reservation total_share_size = {0}; - 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)); - - 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)); - - 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); - - /* Client should skip sending PQ groups/key shares if in FIPS mode */ - if (s2n_is_in_fips_mode()) { - return S2N_SUCCESS; - } - - const struct s2n_kem_preferences *kem_pref = NULL; - GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); - notnull_check(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); - - 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); - } - } - - /* 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 in FIPS mode, the client should not have sent any PQ IDs - * in the supported_groups list of the initial ClientHello */ - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); - - 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); - } - } - - /* 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)); - } else { - GUARD(s2n_send_hrr_ecc_keyshare(conn, out)); - } - - 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)); - - 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)); - - 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_blob point_blob = { 0 }; - 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)); - } - - 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); - - const struct s2n_ecc_preferences *ecc_pref = NULL; - GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); - notnull_check(ecc_pref); - - 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]; - break; - } - } - - /* Ignore unsupported curves */ - if (!curve || !client_ecc_params) { - return S2N_SUCCESS; - } - - /* Ignore curves that we've already received material for */ - if (client_ecc_params->negotiated_curve) { - return S2N_SUCCESS; - } - - /* Ignore curves with unexpected share sizes */ - if (key_share->blob.size != curve->share_size) { - 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; - } - - 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); - - const struct s2n_kem_preferences *kem_pref = NULL; - GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); - notnull_check(kem_pref); - - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); - - 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]; - break; - } - } - - /* Ignore unsupported KEM groups */ - if (!kem_group || !client_kem_group_params) { - return S2N_SUCCESS; - } - - /* Ignore KEM groups that we've already received material for */ - if (client_kem_group_params->kem_group) { - return S2N_SUCCESS; - } - - /* Ignore KEM groups with unexpected overall total share sizes */ - if (key_share->blob.size != kem_group->client_share_size) { - 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 */ - 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)); - /* 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) { - 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)); - return S2N_SUCCESS; - } - - client_kem_group_params->kem_group = kem_group; - *match = true; - 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); - - 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; - - while (bytes_processed < key_shares_size) { - GUARD(s2n_stuffer_read_uint16(extension, &named_group)); - GUARD(s2n_stuffer_read_uint16(extension, &share_size)); - - 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; - - 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)); - - /* Try to parse the share as ECC, then as PQ/hybrid; will ignore - * shares for unrecognized groups. */ - GUARD(s2n_client_key_share_recv_ecc(conn, &key_share, named_group, &match_found)); - if (!s2n_is_in_fips_mode()) { - GUARD(s2n_client_key_share_recv_pq_hybrid(conn, &key_share, named_group, &match_found)); - } - } - - /* 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)); - } - - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -uint32_t s2n_extensions_client_key_share_size(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); - - uint32_t s2n_client_key_share_extension_size = S2N_SIZE_OF_EXTENSION_TYPE - + S2N_SIZE_OF_EXTENSION_DATA_SIZE - + S2N_SIZE_OF_CLIENT_SHARES_SIZE; - - s2n_client_key_share_extension_size += S2N_SIZE_OF_KEY_SHARE_SIZE + S2N_SIZE_OF_NAMED_GROUP; - s2n_client_key_share_extension_size += ecc_pref->ecc_curves[0]->share_size; - - return s2n_client_key_share_extension_size; -} - -int s2n_extensions_client_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_client_key_share_extension, conn, out); -} - -int s2n_extensions_client_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_key_share_extension, conn, extension); -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "tls/extensions/s2n_client_key_share.h" +#include "tls/extensions/s2n_key_share.h" +#include "tls/s2n_security_policies.h" +#include "tls/s2n_kem_preferences.h" + +#include "error/s2n_errno.h" +#include "stuffer/s2n_stuffer.h" +#include "utils/s2n_safety.h" +#include "tls/s2n_tls13.h" +#include "crypto/s2n_fips.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." + * + * Structure: + * Extension type (2 bytes) + * Extension data size (2 bytes) + * Client shares size (2 bytes) + * Client shares: + * Named group (2 bytes) + * Key share size (2 bytes) + * Key share (variable size) + * + * This extension only modifies the connection's client ecc_evp_params. It does + * not make any decisions about which set of params to use. + * + * The server will NOT alert when processing a client extension that violates the RFC. + * So the server will accept: + * - Multiple key shares for the same named group. The server will accept the first + * key share for the group and ignore any duplicates. + * - Key shares for named groups not in the client's supported_groups extension. + **/ + +static int s2n_client_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_client_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_key_share_extension = { + .iana_value = TLS_EXTENSION_KEY_SHARE, + .is_response = false, + .send = s2n_client_key_share_send, + .recv = s2n_client_key_share_recv, + .should_send = s2n_extension_send_if_tls13_connection, + .if_missing = s2n_extension_noop_if_missing, +}; + +static int s2n_generate_preferred_ecc_key_shares(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; + + const struct s2n_ecc_preferences *ecc_pref = NULL; + GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); + notnull_check(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; + } + + 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)); + } + } + + 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); + + 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)); + + 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); + + /* This function should never be called when in FIPS mode */ + ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + + const struct s2n_kem_group *kem_group = kem_group_params->kem_group; + notnull_check(kem_group); + + /* The structure of the PQ share is: + * IANA ID (2 bytes) + * || total share size (2 bytes) + * || size of ECC key share (2 bytes) + * || 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)); + + struct s2n_stuffer_reservation total_share_size = {0}; + 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)); + + 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)); + + 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); + + /* Client should skip sending PQ groups/key shares if in FIPS mode */ + if (s2n_is_in_fips_mode()) { + return S2N_SUCCESS; + } + + const struct s2n_kem_preferences *kem_pref = NULL; + GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); + notnull_check(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); + + 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); + } + } + + /* 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 in FIPS mode, the client should not have sent any PQ IDs + * in the supported_groups list of the initial ClientHello */ + ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + + 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); + } + } + + /* 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)); + } else { + GUARD(s2n_send_hrr_ecc_keyshare(conn, out)); + } + + 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)); + + 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)); + + 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_blob point_blob = { 0 }; + 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)); + } + + 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); + + const struct s2n_ecc_preferences *ecc_pref = NULL; + GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); + notnull_check(ecc_pref); + + 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]; + break; + } + } + + /* Ignore unsupported curves */ + if (!curve || !client_ecc_params) { + return S2N_SUCCESS; + } + + /* Ignore curves that we've already received material for */ + if (client_ecc_params->negotiated_curve) { + return S2N_SUCCESS; + } + + /* Ignore curves with unexpected share sizes */ + if (key_share->blob.size != curve->share_size) { + 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; + } + + 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); + + const struct s2n_kem_preferences *kem_pref = NULL; + GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); + notnull_check(kem_pref); + + ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + + 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]; + break; + } + } + + /* Ignore unsupported KEM groups */ + if (!kem_group || !client_kem_group_params) { + return S2N_SUCCESS; + } + + /* Ignore KEM groups that we've already received material for */ + if (client_kem_group_params->kem_group) { + return S2N_SUCCESS; + } + + /* Ignore KEM groups with unexpected overall total share sizes */ + if (key_share->blob.size != kem_group->client_share_size) { + 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 */ + 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)); + /* 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) { + 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)); + return S2N_SUCCESS; + } + + client_kem_group_params->kem_group = kem_group; + *match = true; + 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); + + 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; + + while (bytes_processed < key_shares_size) { + GUARD(s2n_stuffer_read_uint16(extension, &named_group)); + GUARD(s2n_stuffer_read_uint16(extension, &share_size)); + + 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; + + 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)); + + /* Try to parse the share as ECC, then as PQ/hybrid; will ignore + * shares for unrecognized groups. */ + GUARD(s2n_client_key_share_recv_ecc(conn, &key_share, named_group, &match_found)); + if (!s2n_is_in_fips_mode()) { + GUARD(s2n_client_key_share_recv_pq_hybrid(conn, &key_share, named_group, &match_found)); + } + } + + /* 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)); + } + + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +uint32_t s2n_extensions_client_key_share_size(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); + + uint32_t s2n_client_key_share_extension_size = S2N_SIZE_OF_EXTENSION_TYPE + + S2N_SIZE_OF_EXTENSION_DATA_SIZE + + S2N_SIZE_OF_CLIENT_SHARES_SIZE; + + s2n_client_key_share_extension_size += S2N_SIZE_OF_KEY_SHARE_SIZE + S2N_SIZE_OF_NAMED_GROUP; + s2n_client_key_share_extension_size += ecc_pref->ecc_curves[0]->share_size; + + return s2n_client_key_share_extension_size; +} + +int s2n_extensions_client_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_client_key_share_extension, conn, out); +} + +int s2n_extensions_client_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_key_share_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.h index 365bc2ecf1..9977625680 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_key_share.h @@ -1,27 +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 "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_key_share_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -extern int s2n_extensions_client_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); -extern uint32_t s2n_extensions_client_key_share_size(struct s2n_connection *conn); -extern int s2n_extensions_client_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out); - +/* + * 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_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_key_share_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +extern int s2n_extensions_client_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); +extern uint32_t s2n_extensions_client_key_share_size(struct s2n_connection *conn); +extern int s2n_extensions_client_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out); + 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 6f419250db..880193a1a1 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 @@ -1,75 +1,75 @@ -/* - * 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/extensions/s2n_client_max_frag_len.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" - -#include "utils/s2n_safety.h" - -static bool s2n_client_max_frag_len_should_send(struct s2n_connection *conn); -static int s2n_client_max_frag_len_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_client_max_frag_len_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_max_frag_len_extension = { - .iana_value = TLS_EXTENSION_MAX_FRAG_LEN, - .is_response = false, - .send = s2n_client_max_frag_len_send, - .recv = s2n_client_max_frag_len_recv, - .should_send = s2n_client_max_frag_len_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_client_max_frag_len_should_send(struct s2n_connection *conn) -{ - return conn->config->mfl_code != S2N_TLS_MAX_FRAG_LEN_EXT_NONE; -} - -static int s2n_client_max_frag_len_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_stuffer_write_uint8(out, conn->config->mfl_code); -} - -static int s2n_client_max_frag_len_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - if (!conn->config->accept_mfl) { - return S2N_SUCCESS; - } - - 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) { - return S2N_SUCCESS; - } - - conn->mfl_code = mfl_code; - conn->max_outgoing_fragment_length = mfl_code_to_length[mfl_code]; - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_extensions_client_max_frag_len_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_client_max_frag_len_extension, conn, out); -} - -int s2n_recv_client_max_frag_len(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_max_frag_len_extension, conn, extension); -} +/* + * 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/extensions/s2n_client_max_frag_len.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" + +#include "utils/s2n_safety.h" + +static bool s2n_client_max_frag_len_should_send(struct s2n_connection *conn); +static int s2n_client_max_frag_len_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_client_max_frag_len_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_max_frag_len_extension = { + .iana_value = TLS_EXTENSION_MAX_FRAG_LEN, + .is_response = false, + .send = s2n_client_max_frag_len_send, + .recv = s2n_client_max_frag_len_recv, + .should_send = s2n_client_max_frag_len_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_client_max_frag_len_should_send(struct s2n_connection *conn) +{ + return conn->config->mfl_code != S2N_TLS_MAX_FRAG_LEN_EXT_NONE; +} + +static int s2n_client_max_frag_len_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_stuffer_write_uint8(out, conn->config->mfl_code); +} + +static int s2n_client_max_frag_len_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + if (!conn->config->accept_mfl) { + return S2N_SUCCESS; + } + + 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) { + return S2N_SUCCESS; + } + + conn->mfl_code = mfl_code; + conn->max_outgoing_fragment_length = mfl_code_to_length[mfl_code]; + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_extensions_client_max_frag_len_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_client_max_frag_len_extension, conn, out); +} + +int s2n_recv_client_max_frag_len(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_max_frag_len_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_max_frag_len.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_max_frag_len.h index cb822a5410..49bb3be845 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_max_frag_len.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_max_frag_len.h @@ -1,26 +1,26 @@ -/* - * 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_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_max_frag_len_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -extern int s2n_extensions_client_max_frag_len_send(struct s2n_connection *conn, struct s2n_stuffer *out); -extern int s2n_recv_client_max_frag_len(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * 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_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_max_frag_len_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +extern int s2n_extensions_client_max_frag_len_send(struct s2n_connection *conn, struct s2n_stuffer *out); +extern int s2n_recv_client_max_frag_len(struct s2n_connection *conn, struct s2n_stuffer *extension); diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.c index b553cdf6ca..450e293299 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 @@ -1,89 +1,89 @@ -/* - * 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 <stdint.h> -#include <sys/param.h> - -#include "tls/extensions/s2n_client_pq_kem.h" -#include "tls/s2n_kem.h" -#include "tls/s2n_security_policies.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" - -#include "utils/s2n_safety.h" - -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); -static int s2n_client_pq_kem_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_pq_kem_extension = { - .iana_value = TLS_EXTENSION_PQ_KEM_PARAMETERS, - .is_response = false, - .send = s2n_client_pq_kem_send, - .recv = s2n_client_pq_kem_recv, - .should_send = s2n_client_pq_kem_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_client_pq_kem_should_send(struct s2n_connection *conn) -{ - const struct s2n_security_policy *security_policy; - return s2n_connection_get_security_policy(conn, &security_policy) == S2N_SUCCESS - && s2n_pq_kem_is_extension_required(security_policy); -} - -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); - - 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)); - } - - return S2N_SUCCESS; -} - -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; - - 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; - } - - proposed_kems->size = size_of_all; - proposed_kems->data = s2n_stuffer_raw_read(extension, proposed_kems->size); - notnull_check(proposed_kems->data); - - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_extensions_client_pq_kem_send(struct s2n_connection *conn, struct s2n_stuffer *out, uint16_t pq_kem_list_size) -{ - return s2n_extension_send(&s2n_client_pq_kem_extension, conn, out); -} - -int s2n_recv_pq_kem_extension(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_pq_kem_extension, conn, extension); -} +/* + * 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 <stdint.h> +#include <sys/param.h> + +#include "tls/extensions/s2n_client_pq_kem.h" +#include "tls/s2n_kem.h" +#include "tls/s2n_security_policies.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" + +#include "utils/s2n_safety.h" + +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); +static int s2n_client_pq_kem_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_pq_kem_extension = { + .iana_value = TLS_EXTENSION_PQ_KEM_PARAMETERS, + .is_response = false, + .send = s2n_client_pq_kem_send, + .recv = s2n_client_pq_kem_recv, + .should_send = s2n_client_pq_kem_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_client_pq_kem_should_send(struct s2n_connection *conn) +{ + const struct s2n_security_policy *security_policy; + return s2n_connection_get_security_policy(conn, &security_policy) == S2N_SUCCESS + && s2n_pq_kem_is_extension_required(security_policy); +} + +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); + + 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)); + } + + return S2N_SUCCESS; +} + +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; + + 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; + } + + proposed_kems->size = size_of_all; + proposed_kems->data = s2n_stuffer_raw_read(extension, proposed_kems->size); + notnull_check(proposed_kems->data); + + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_extensions_client_pq_kem_send(struct s2n_connection *conn, struct s2n_stuffer *out, uint16_t pq_kem_list_size) +{ + return s2n_extension_send(&s2n_client_pq_kem_extension, conn, out); +} + +int s2n_recv_pq_kem_extension(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_pq_kem_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.h index bc7dd6868e..91934773f3 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_pq_kem.h @@ -1,27 +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 "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_pq_kem_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -extern int s2n_extensions_client_pq_kem_send(struct s2n_connection *conn, struct s2n_stuffer *out, uint16_t pq_kem_list_size); -extern int s2n_recv_pq_kem_extension(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_pq_kem_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +extern int s2n_extensions_client_pq_kem_send(struct s2n_connection *conn, struct s2n_stuffer *out, uint16_t pq_kem_list_size); +extern int s2n_recv_pq_kem_extension(struct s2n_connection *conn, struct s2n_stuffer *extension); diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c index 0d8cecefab..6e058d4392 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.c @@ -1,271 +1,271 @@ -/* - * 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 "crypto/s2n_hash.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" - -#include "utils/s2n_safety.h" - -#define SIZE_OF_BINDER_SIZE sizeof(uint8_t) -#define SIZE_OF_BINDER_LIST_SIZE sizeof(uint16_t) - -static bool s2n_client_psk_should_send(struct s2n_connection *conn); -static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_client_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_psk_extension = { - .iana_value = TLS_EXTENSION_PRE_SHARED_KEY, - .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, -}; - -static bool s2n_client_psk_should_send(struct s2n_connection *conn) -{ - return conn && s2n_connection_get_protocol_version(conn) >= S2N_TLS13 - && conn->psk_params.psk_list.len; -} - -static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - notnull_check(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)); - - 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); - - /* 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)); - - /* Calculate binder size */ - uint8_t hash_size = 0; - GUARD(s2n_hash_digest_size(psk->hash_alg, &hash_size)); - binder_list_size += hash_size + SIZE_OF_BINDER_SIZE; - } - - 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. - * - * 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)); - - return S2N_SUCCESS; -} - -/* Match a PSK identity received from the client against the server's known PSK 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) -{ - ENSURE_REF(match); - ENSURE_REF(wire_identity); - ENSURE_REF(known_psks); - - *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); - - 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; -} - -static S2N_RESULT s2n_client_psk_recv_identity_list(struct s2n_connection *conn, struct s2n_stuffer *wire_identities_in) -{ - ENSURE_REF(conn); - ENSURE_REF(wire_identities_in); - - uint8_t wire_index = 0; - 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)); - - uint8_t *identity_data; - ENSURE_REF(identity_data = s2n_stuffer_raw_read(wire_identities_in, identity_size)); - - struct s2n_blob identity = { 0 }; - GUARD_AS_RESULT(s2n_blob_init(&identity, identity_data, identity_size)); - - /* TODO: Validate obfuscated_ticket_age when using session tickets: - * https://github.com/awslabs/s2n/issues/2417 - * - * "For identities established externally, an obfuscated_ticket_age of 0 SHOULD be - * used, and servers MUST ignore the value." - */ - uint32_t obfuscated_ticket_age = 0; - GUARD_AS_RESULT(s2n_stuffer_read_uint32(wire_identities_in, &obfuscated_ticket_age)); - - /* TODO: Implement the callback to choose a PSK: https://github.com/awslabs/s2n/issues/2397 - * - * When we don't have a callback configured to choose a PSK, we should fall back to accepting - * the first PSK identity that also exists in our list of supported PSKs. */ - GUARD_RESULT(s2n_match_psk_identity(&conn->psk_params.psk_list, &identity, &conn->psk_params.chosen_psk)); - - if (conn->psk_params.chosen_psk) { - conn->psk_params.chosen_psk_wire_index = wire_index; - return S2N_RESULT_OK; - } - - wire_index++; - } - 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); - - uint8_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)); - - uint8_t *wire_binder_data; - 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)); - - if (wire_index == conn->psk_params.chosen_psk_wire_index) { - GUARD_AS_RESULT(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); -} - -static S2N_RESULT s2n_client_psk_recv_identities(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - ENSURE_REF(conn); - - uint16_t identity_list_size = 0; - GUARD_AS_RESULT(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)); - - struct s2n_blob identity_list_blob = { 0 }; - GUARD_AS_RESULT(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)); - - 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); - - uint16_t binder_list_size = 0; - GUARD_AS_RESULT(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)); - - struct s2n_blob binder_list_blob = { 0 }; - GUARD_AS_RESULT(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)); - - /* 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); - 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)); - - 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; - } - - if (s2n_result_is_error(s2n_client_psk_recv_identities(conn, extension))) { - /* https://tools.ietf.org/html/rfc8446#section-4.2.11: - * "If no acceptable PSKs are found, the server SHOULD perform a non-PSK - * handshake if possible." - */ - conn->psk_params.chosen_psk = NULL; - } - - if (conn->psk_params.chosen_psk) { - /* https://tools.ietf.org/html/rfc8446#section-4.2.11: - * "Prior to accepting PSK key establishment, the server MUST validate - * the corresponding binder value. If this value is not present or does - * not validate, the server MUST abort the handshake." - */ - GUARD_AS_POSIX(s2n_client_psk_recv_binders(conn, extension)); - } - - /* At this point, we have either chosen a PSK or fallen back to a full handshake. - * Wipe any PSKs not chosen. */ - GUARD_AS_POSIX(s2n_psk_parameters_free_unused_psks(&conn->psk_params)); - - return S2N_SUCCESS; -} +/* + * 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 "crypto/s2n_hash.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" + +#include "utils/s2n_safety.h" + +#define SIZE_OF_BINDER_SIZE sizeof(uint8_t) +#define SIZE_OF_BINDER_LIST_SIZE sizeof(uint16_t) + +static bool s2n_client_psk_should_send(struct s2n_connection *conn); +static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_client_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_psk_extension = { + .iana_value = TLS_EXTENSION_PRE_SHARED_KEY, + .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, +}; + +static bool s2n_client_psk_should_send(struct s2n_connection *conn) +{ + return conn && s2n_connection_get_protocol_version(conn) >= S2N_TLS13 + && conn->psk_params.psk_list.len; +} + +static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + notnull_check(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)); + + 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); + + /* 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)); + + /* Calculate binder size */ + uint8_t hash_size = 0; + GUARD(s2n_hash_digest_size(psk->hash_alg, &hash_size)); + binder_list_size += hash_size + SIZE_OF_BINDER_SIZE; + } + + 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. + * + * 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)); + + return S2N_SUCCESS; +} + +/* Match a PSK identity received from the client against the server's known PSK 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) +{ + ENSURE_REF(match); + ENSURE_REF(wire_identity); + ENSURE_REF(known_psks); + + *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); + + 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; +} + +static S2N_RESULT s2n_client_psk_recv_identity_list(struct s2n_connection *conn, struct s2n_stuffer *wire_identities_in) +{ + ENSURE_REF(conn); + ENSURE_REF(wire_identities_in); + + uint8_t wire_index = 0; + 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)); + + uint8_t *identity_data; + ENSURE_REF(identity_data = s2n_stuffer_raw_read(wire_identities_in, identity_size)); + + struct s2n_blob identity = { 0 }; + GUARD_AS_RESULT(s2n_blob_init(&identity, identity_data, identity_size)); + + /* TODO: Validate obfuscated_ticket_age when using session tickets: + * https://github.com/awslabs/s2n/issues/2417 + * + * "For identities established externally, an obfuscated_ticket_age of 0 SHOULD be + * used, and servers MUST ignore the value." + */ + uint32_t obfuscated_ticket_age = 0; + GUARD_AS_RESULT(s2n_stuffer_read_uint32(wire_identities_in, &obfuscated_ticket_age)); + + /* TODO: Implement the callback to choose a PSK: https://github.com/awslabs/s2n/issues/2397 + * + * When we don't have a callback configured to choose a PSK, we should fall back to accepting + * the first PSK identity that also exists in our list of supported PSKs. */ + GUARD_RESULT(s2n_match_psk_identity(&conn->psk_params.psk_list, &identity, &conn->psk_params.chosen_psk)); + + if (conn->psk_params.chosen_psk) { + conn->psk_params.chosen_psk_wire_index = wire_index; + return S2N_RESULT_OK; + } + + wire_index++; + } + 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); + + uint8_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)); + + uint8_t *wire_binder_data; + 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)); + + if (wire_index == conn->psk_params.chosen_psk_wire_index) { + GUARD_AS_RESULT(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); +} + +static S2N_RESULT s2n_client_psk_recv_identities(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + ENSURE_REF(conn); + + uint16_t identity_list_size = 0; + GUARD_AS_RESULT(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)); + + struct s2n_blob identity_list_blob = { 0 }; + GUARD_AS_RESULT(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)); + + 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); + + uint16_t binder_list_size = 0; + GUARD_AS_RESULT(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)); + + struct s2n_blob binder_list_blob = { 0 }; + GUARD_AS_RESULT(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)); + + /* 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); + 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)); + + 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; + } + + if (s2n_result_is_error(s2n_client_psk_recv_identities(conn, extension))) { + /* https://tools.ietf.org/html/rfc8446#section-4.2.11: + * "If no acceptable PSKs are found, the server SHOULD perform a non-PSK + * handshake if possible." + */ + conn->psk_params.chosen_psk = NULL; + } + + if (conn->psk_params.chosen_psk) { + /* https://tools.ietf.org/html/rfc8446#section-4.2.11: + * "Prior to accepting PSK key establishment, the server MUST validate + * the corresponding binder value. If this value is not present or does + * not validate, the server MUST abort the handshake." + */ + GUARD_AS_POSIX(s2n_client_psk_recv_binders(conn, extension)); + } + + /* At this point, we have either chosen a PSK or fallen back to a full handshake. + * Wipe any PSKs not chosen. */ + GUARD_AS_POSIX(s2n_psk_parameters_free_unused_psks(&conn->psk_params)); + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h index 0e12137676..a317ace2bc 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_psk.h @@ -1,22 +1,22 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_psk_extension; +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_psk_extension; 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 502b84b624..3a012f47d1 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 @@ -1,51 +1,51 @@ -/* - * 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/extensions/s2n_client_renegotiation_info.h" -#include "tls/s2n_tls.h" - -#include "utils/s2n_safety.h" - -static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_renegotiation_info_extension = { - .iana_value = TLS_EXTENSION_RENEGOTIATION_INFO, - .is_response = false, - .send = s2n_extension_send_unimplemented, - .recv = s2n_client_renegotiation_recv, - .should_send = s2n_extension_never_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - /* RFC5746 Section 3.2: The renegotiated_connection field is of zero length for the initial handshake. */ - uint8_t renegotiated_connection_len; - 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; - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_recv_client_renegotiation_info(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_renegotiation_info_extension, conn, extension); -} +/* + * 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/extensions/s2n_client_renegotiation_info.h" +#include "tls/s2n_tls.h" + +#include "utils/s2n_safety.h" + +static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_renegotiation_info_extension = { + .iana_value = TLS_EXTENSION_RENEGOTIATION_INFO, + .is_response = false, + .send = s2n_extension_send_unimplemented, + .recv = s2n_client_renegotiation_recv, + .should_send = s2n_extension_never_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static int s2n_client_renegotiation_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + /* RFC5746 Section 3.2: The renegotiated_connection field is of zero length for the initial handshake. */ + uint8_t renegotiated_connection_len; + 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; + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_recv_client_renegotiation_info(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_renegotiation_info_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.h index d1e37e9677..dbc98ddf80 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_renegotiation_info.h @@ -1,25 +1,25 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_renegotiation_info_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_recv_client_renegotiation_info(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * 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_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_renegotiation_info_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_recv_client_renegotiation_info(struct s2n_connection *conn, struct s2n_stuffer *extension); diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_sct_list.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_sct_list.c index ecf86b2647..d3f699c8c3 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_sct_list.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_sct_list.c @@ -1,59 +1,59 @@ -/* - * 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/extensions/s2n_client_sct_list.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" - -#include "utils/s2n_safety.h" - -static bool s2n_client_sct_list_should_send(struct s2n_connection *conn); -static int s2n_client_sct_list_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_sct_list_extension = { - .iana_value = TLS_EXTENSION_SCT_LIST, - .is_response = false, - .send = s2n_extension_send_noop, - .recv = s2n_client_sct_list_recv, - .should_send = s2n_client_sct_list_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_client_sct_list_should_send(struct s2n_connection *conn) -{ - return conn->config->ct_type != S2N_CT_SUPPORT_NONE; -} - -static int s2n_client_sct_list_recv(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - conn->ct_level_requested = S2N_CT_SUPPORT_REQUEST; - /* Skip reading the extension, per RFC6962 (3.1.1) it SHOULD be empty anyway */ - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_extensions_client_sct_list_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_client_sct_list_extension, conn, out); -} - -int s2n_recv_client_sct_list(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_sct_list_extension, conn, extension); -} +/* + * 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/extensions/s2n_client_sct_list.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" + +#include "utils/s2n_safety.h" + +static bool s2n_client_sct_list_should_send(struct s2n_connection *conn); +static int s2n_client_sct_list_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_sct_list_extension = { + .iana_value = TLS_EXTENSION_SCT_LIST, + .is_response = false, + .send = s2n_extension_send_noop, + .recv = s2n_client_sct_list_recv, + .should_send = s2n_client_sct_list_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_client_sct_list_should_send(struct s2n_connection *conn) +{ + return conn->config->ct_type != S2N_CT_SUPPORT_NONE; +} + +static int s2n_client_sct_list_recv(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + conn->ct_level_requested = S2N_CT_SUPPORT_REQUEST; + /* Skip reading the extension, per RFC6962 (3.1.1) it SHOULD be empty anyway */ + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_extensions_client_sct_list_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_client_sct_list_extension, conn, out); +} + +int s2n_recv_client_sct_list(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_sct_list_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_sct_list.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_sct_list.h index 9d7a75e7cb..2f03d9baff 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_sct_list.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_sct_list.h @@ -1,26 +1,26 @@ -/* - * 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_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_sct_list_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -extern int s2n_extensions_client_sct_list_send(struct s2n_connection *conn, struct s2n_stuffer *out); -extern int s2n_recv_client_sct_list(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * 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_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_sct_list_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +extern int s2n_extensions_client_sct_list_send(struct s2n_connection *conn, struct s2n_stuffer *out); +extern int s2n_recv_client_sct_list(struct s2n_connection *conn, struct s2n_stuffer *extension); 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 c9eaca23a9..904976e4cc 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 @@ -1,110 +1,110 @@ -/* - * 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/extensions/s2n_client_server_name.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" - -#include "utils/s2n_safety.h" - -#define S2N_NAME_TYPE_HOST_NAME 0 - -static bool s2n_client_server_name_should_send(struct s2n_connection *conn); -static int s2n_client_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_client_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_server_name_extension = { - .iana_value = TLS_EXTENSION_SERVER_NAME, - .is_response = false, - .send = s2n_client_server_name_send, - .recv = s2n_client_server_name_recv, - .should_send = s2n_client_server_name_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_client_server_name_should_send(struct s2n_connection *conn) -{ - return conn && strlen(conn->server_name) > 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)); - - /* 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)); - - 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))); - - GUARD(s2n_stuffer_write_vector_size(&server_name_list_size)); - return S2N_SUCCESS; -} - -static int s2n_client_server_name_check(struct s2n_connection *conn, struct s2n_stuffer *extension, uint16_t *server_name_len) -{ - notnull_check(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)); - - uint8_t server_name_type; - GUARD(s2n_stuffer_read_uint8(extension, &server_name_type)); - eq_check(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)); - - return S2N_SUCCESS; -} - -static int s2n_client_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - notnull_check(conn); - - /* Exit early if we've already parsed the server name */ - if (conn->server_name[0]) { - return S2N_SUCCESS; - } - - /* Ignore if malformed. We just won't use the server name. */ - uint16_t server_name_len; - if (s2n_client_server_name_check(conn, extension, &server_name_len) != S2N_SUCCESS) { - return S2N_SUCCESS; - } - - 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); - - return S2N_SUCCESS; -} - -int s2n_extensions_client_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_client_server_name_extension, conn, out); -} - -int s2n_parse_client_hello_server_name(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_server_name_extension, conn, extension); -} +/* + * 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/extensions/s2n_client_server_name.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" + +#include "utils/s2n_safety.h" + +#define S2N_NAME_TYPE_HOST_NAME 0 + +static bool s2n_client_server_name_should_send(struct s2n_connection *conn); +static int s2n_client_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_client_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_server_name_extension = { + .iana_value = TLS_EXTENSION_SERVER_NAME, + .is_response = false, + .send = s2n_client_server_name_send, + .recv = s2n_client_server_name_recv, + .should_send = s2n_client_server_name_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_client_server_name_should_send(struct s2n_connection *conn) +{ + return conn && strlen(conn->server_name) > 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)); + + /* 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)); + + 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))); + + GUARD(s2n_stuffer_write_vector_size(&server_name_list_size)); + return S2N_SUCCESS; +} + +static int s2n_client_server_name_check(struct s2n_connection *conn, struct s2n_stuffer *extension, uint16_t *server_name_len) +{ + notnull_check(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)); + + uint8_t server_name_type; + GUARD(s2n_stuffer_read_uint8(extension, &server_name_type)); + eq_check(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)); + + return S2N_SUCCESS; +} + +static int s2n_client_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + notnull_check(conn); + + /* Exit early if we've already parsed the server name */ + if (conn->server_name[0]) { + return S2N_SUCCESS; + } + + /* Ignore if malformed. We just won't use the server name. */ + uint16_t server_name_len; + if (s2n_client_server_name_check(conn, extension, &server_name_len) != S2N_SUCCESS) { + return S2N_SUCCESS; + } + + 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); + + return S2N_SUCCESS; +} + +int s2n_extensions_client_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_client_server_name_extension, conn, out); +} + +int s2n_parse_client_hello_server_name(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_server_name_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_server_name.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_server_name.h index a6c2f2250a..a6dde369dc 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_server_name.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_server_name.h @@ -1,26 +1,26 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_server_name_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -extern int s2n_extensions_client_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out); -extern int s2n_parse_client_hello_server_name(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_server_name_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +extern int s2n_extensions_client_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out); +extern int s2n_parse_client_hello_server_name(struct s2n_connection *conn, struct s2n_stuffer *extension); 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 3628f7be9a..96ef1b7308 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 @@ -1,82 +1,82 @@ -/* - * 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/extensions/s2n_client_session_ticket.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" -#include "tls/s2n_resume.h" - -#include "utils/s2n_safety.h" - -static bool s2n_client_session_ticket_should_send(struct s2n_connection *conn); -static int s2n_client_session_ticket_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_client_session_ticket_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_session_ticket_extension = { - .iana_value = TLS_EXTENSION_SESSION_TICKET, - .is_response = false, - .send = s2n_client_session_ticket_send, - .recv = s2n_client_session_ticket_recv, - .should_send = s2n_client_session_ticket_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_client_session_ticket_should_send(struct s2n_connection *conn) -{ - return conn->config->use_tickets; -} - -static int s2n_client_session_ticket_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - 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) { - /* Ignore the extension. */ - return S2N_SUCCESS; - } - - /* s2n server does not support session ticket with CLIENT_AUTH enabled */ - if (s2n_connection_is_client_auth_enabled(conn) > 0) { - return S2N_SUCCESS; - } - - if (s2n_stuffer_data_available(extension) == S2N_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)); - } else if (s2n_config_is_encrypt_decrypt_key_available(conn->config) == 1) { - conn->session_ticket_status = S2N_NEW_TICKET; - } - - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_extensions_client_session_ticket_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_client_session_ticket_extension, conn, out); -} - -int s2n_recv_client_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_session_ticket_extension, conn, extension); -} +/* + * 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/extensions/s2n_client_session_ticket.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" +#include "tls/s2n_resume.h" + +#include "utils/s2n_safety.h" + +static bool s2n_client_session_ticket_should_send(struct s2n_connection *conn); +static int s2n_client_session_ticket_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_client_session_ticket_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_session_ticket_extension = { + .iana_value = TLS_EXTENSION_SESSION_TICKET, + .is_response = false, + .send = s2n_client_session_ticket_send, + .recv = s2n_client_session_ticket_recv, + .should_send = s2n_client_session_ticket_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_client_session_ticket_should_send(struct s2n_connection *conn) +{ + return conn->config->use_tickets; +} + +static int s2n_client_session_ticket_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + 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) { + /* Ignore the extension. */ + return S2N_SUCCESS; + } + + /* s2n server does not support session ticket with CLIENT_AUTH enabled */ + if (s2n_connection_is_client_auth_enabled(conn) > 0) { + return S2N_SUCCESS; + } + + if (s2n_stuffer_data_available(extension) == S2N_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)); + } else if (s2n_config_is_encrypt_decrypt_key_available(conn->config) == 1) { + conn->session_ticket_status = S2N_NEW_TICKET; + } + + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_extensions_client_session_ticket_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_client_session_ticket_extension, conn, out); +} + +int s2n_recv_client_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_session_ticket_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_session_ticket.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_session_ticket.h index e0cdd7225c..4b3b045dcd 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_session_ticket.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_session_ticket.h @@ -1,25 +1,25 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_session_ticket_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -extern int s2n_extensions_client_session_ticket_send(struct s2n_connection *conn, struct s2n_stuffer *out); -extern int s2n_recv_client_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * 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_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_session_ticket_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +extern int s2n_extensions_client_session_ticket_send(struct s2n_connection *conn, struct s2n_stuffer *out); +extern int s2n_recv_client_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *extension); diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_signature_algorithms.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_signature_algorithms.c index 6d6124a261..9986a2cad1 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_signature_algorithms.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_signature_algorithms.c @@ -1,64 +1,64 @@ -/* - * 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/extensions/s2n_client_signature_algorithms.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" -#include "tls/s2n_signature_algorithms.h" - -#include "utils/s2n_safety.h" - -static bool s2n_client_signature_algorithms_should_send(struct s2n_connection *conn); -static int s2n_client_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_signature_algorithms_extension = { - .iana_value = TLS_EXTENSION_SIGNATURE_ALGORITHMS, - .is_response = false, - .send = s2n_send_supported_sig_scheme_list, - .recv = s2n_client_signature_algorithms_recv, - .should_send = s2n_client_signature_algorithms_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_client_signature_algorithms_should_send(struct s2n_connection *conn) -{ - return s2n_connection_get_protocol_version(conn) >= S2N_TLS12; -} - -static int s2n_client_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_recv_supported_sig_scheme_list(extension, &conn->handshake_params.client_sig_hash_algs); -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_extensions_client_signature_algorithms_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_client_signature_algorithms_extension, conn, out); -} - -int s2n_extensions_client_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_signature_algorithms_extension, conn, extension); -} - -int s2n_extensions_client_signature_algorithms_size(struct s2n_connection *conn) -{ - /* extra 6 = 2 from extension type, 2 from extension size, 2 from list length */ - return s2n_supported_sig_scheme_list_size(conn) + 6; -} +/* + * 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/extensions/s2n_client_signature_algorithms.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" +#include "tls/s2n_signature_algorithms.h" + +#include "utils/s2n_safety.h" + +static bool s2n_client_signature_algorithms_should_send(struct s2n_connection *conn); +static int s2n_client_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_signature_algorithms_extension = { + .iana_value = TLS_EXTENSION_SIGNATURE_ALGORITHMS, + .is_response = false, + .send = s2n_send_supported_sig_scheme_list, + .recv = s2n_client_signature_algorithms_recv, + .should_send = s2n_client_signature_algorithms_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_client_signature_algorithms_should_send(struct s2n_connection *conn) +{ + return s2n_connection_get_protocol_version(conn) >= S2N_TLS12; +} + +static int s2n_client_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_recv_supported_sig_scheme_list(extension, &conn->handshake_params.client_sig_hash_algs); +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_extensions_client_signature_algorithms_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_client_signature_algorithms_extension, conn, out); +} + +int s2n_extensions_client_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_signature_algorithms_extension, conn, extension); +} + +int s2n_extensions_client_signature_algorithms_size(struct s2n_connection *conn) +{ + /* extra 6 = 2 from extension type, 2 from extension size, 2 from list length */ + return s2n_supported_sig_scheme_list_size(conn) + 6; +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_signature_algorithms.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_signature_algorithms.h index 817594f6f7..0832d40460 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_signature_algorithms.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_signature_algorithms.h @@ -1,27 +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 "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_signature_algorithms_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -int s2n_extensions_client_signature_algorithms_send(struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_extensions_client_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); -int s2n_extensions_client_signature_algorithms_size(struct s2n_connection *conn); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_signature_algorithms_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +int s2n_extensions_client_signature_algorithms_send(struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_extensions_client_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); +int s2n_extensions_client_signature_algorithms_size(struct s2n_connection *conn); 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 62e3df4aa8..e5144fba8b 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 @@ -1,91 +1,91 @@ -/* - * 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/extensions/s2n_client_status_request.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" - -#include "utils/s2n_safety.h" - -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); -static int s2n_client_status_request_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_status_request_extension = { - .iana_value = TLS_EXTENSION_STATUS_REQUEST, - .is_response = false, - .send = s2n_client_status_request_send, - .recv = s2n_client_status_request_recv, - .should_send = s2n_client_status_request_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_client_status_request_should_send(struct s2n_connection *conn) -{ - return conn->config->status_request_type != S2N_STATUS_REQUEST_NONE; -} - -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)); - - /* 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)); - - /* 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)); - - return S2N_SUCCESS; -} - -static int s2n_client_status_request_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - if (s2n_stuffer_data_available(extension) < 5) { - /* Malformed length, ignore the extension */ - return S2N_SUCCESS; - } - - uint8_t type; - 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; - } - - conn->status_type = (s2n_status_request_type) type; - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_extensions_client_status_request_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_client_status_request_extension, conn, out); -} - -int s2n_recv_client_status_request(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_status_request_extension, conn, extension); -} +/* + * 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/extensions/s2n_client_status_request.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" + +#include "utils/s2n_safety.h" + +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); +static int s2n_client_status_request_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_status_request_extension = { + .iana_value = TLS_EXTENSION_STATUS_REQUEST, + .is_response = false, + .send = s2n_client_status_request_send, + .recv = s2n_client_status_request_recv, + .should_send = s2n_client_status_request_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_client_status_request_should_send(struct s2n_connection *conn) +{ + return conn->config->status_request_type != S2N_STATUS_REQUEST_NONE; +} + +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)); + + /* 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)); + + /* 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)); + + return S2N_SUCCESS; +} + +static int s2n_client_status_request_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + if (s2n_stuffer_data_available(extension) < 5) { + /* Malformed length, ignore the extension */ + return S2N_SUCCESS; + } + + uint8_t type; + 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; + } + + conn->status_type = (s2n_status_request_type) type; + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_extensions_client_status_request_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_client_status_request_extension, conn, out); +} + +int s2n_recv_client_status_request(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_status_request_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_status_request.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_status_request.h index f1274143da..b3862755fc 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_status_request.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_status_request.h @@ -1,26 +1,26 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_status_request_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -extern int s2n_extensions_client_status_request_send(struct s2n_connection *conn, struct s2n_stuffer *out); -extern int s2n_recv_client_status_request(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_status_request_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +extern int s2n_extensions_client_status_request_send(struct s2n_connection *conn, struct s2n_stuffer *out); +extern int s2n_recv_client_status_request(struct s2n_connection *conn, struct s2n_stuffer *extension); 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 d01017e244..9c1bf71092 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 @@ -1,201 +1,201 @@ -/* - * 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/extensions/s2n_client_supported_groups.h" -#include "tls/extensions/s2n_ec_point_format.h" - -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" -#include "tls/s2n_security_policies.h" - -#include "utils/s2n_safety.h" -#include "crypto/s2n_fips.h" -#include "tls/s2n_tls13.h" - -static int s2n_client_supported_groups_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_client_supported_groups_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_supported_groups_extension = { - .iana_value = TLS_EXTENSION_SUPPORTED_GROUPS, - .is_response = false, - .send = s2n_client_supported_groups_send, - .recv = s2n_client_supported_groups_recv, - .should_send = s2n_extension_should_send_if_ecc_enabled, - .if_missing = s2n_extension_noop_if_missing, -}; - -bool s2n_extension_should_send_if_ecc_enabled(struct s2n_connection *conn) -{ - const struct s2n_security_policy *security_policy; - return s2n_connection_get_security_policy(conn, &security_policy) == S2N_SUCCESS - && s2n_ecc_is_extension_required(security_policy); -} - -static int s2n_client_supported_groups_send(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); - - const struct s2n_kem_preferences *kem_pref = NULL; - GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); - notnull_check(kem_pref); - - /* Group list len */ - struct s2n_stuffer_reservation group_list_len = { 0 }; - GUARD(s2n_stuffer_reserve_uint16(out, &group_list_len)); - - /* Send KEM groups list first */ - if (s2n_connection_get_protocol_version(conn) >= S2N_TLS13 && !s2n_is_in_fips_mode()) { - 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)); - } - } - - /* 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)); - } - - GUARD(s2n_stuffer_write_vector_size(&group_list_len)); - - return S2N_SUCCESS; -} - -/* Populates the appropriate index of either the mutually_supported_curves or - * mutually_supported_kem_groups array based on the received IANA ID. Will - * ignore unrecognized IANA IDs (and return success). */ -static int s2n_client_supported_groups_recv_iana_id(struct s2n_connection *conn, uint16_t iana_id) { - notnull_check(conn); - - const struct s2n_ecc_preferences *ecc_pref = NULL; - GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); - notnull_check(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; - return S2N_SUCCESS; - } - } - - /* Return early if in FIPS mode, or if TLS 1.3 is disabled, so as to ignore PQ IDs */ - if (s2n_is_in_fips_mode() || s2n_connection_get_protocol_version(conn) < S2N_TLS13) { - return S2N_SUCCESS; - } - - 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 < 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; - return S2N_SUCCESS; - } - } - - return S2N_SUCCESS; -} - -static int s2n_choose_supported_group(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); - - /* 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; - - /* Prefer to negotiate hybrid PQ over ECC. If in FIPS mode, 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]; - 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; - 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]; - if (candidate_curve != NULL) { - conn->secure.server_ecc_evp_params.negotiated_curve = candidate_curve; - return S2N_SUCCESS; - } - } - - return S2N_SUCCESS; -} - -static int s2n_client_supported_groups_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) { - notnull_check(conn); - notnull_check(extension); - - uint16_t size_of_all; - 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; - } - - 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)); - } - - GUARD(s2n_choose_supported_group(conn)); - - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -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)); - - /* 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)); - - return S2N_SUCCESS; -} - -int s2n_recv_client_supported_groups(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_supported_groups_extension, conn, extension); -} +/* + * 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/extensions/s2n_client_supported_groups.h" +#include "tls/extensions/s2n_ec_point_format.h" + +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" +#include "tls/s2n_security_policies.h" + +#include "utils/s2n_safety.h" +#include "crypto/s2n_fips.h" +#include "tls/s2n_tls13.h" + +static int s2n_client_supported_groups_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_client_supported_groups_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_supported_groups_extension = { + .iana_value = TLS_EXTENSION_SUPPORTED_GROUPS, + .is_response = false, + .send = s2n_client_supported_groups_send, + .recv = s2n_client_supported_groups_recv, + .should_send = s2n_extension_should_send_if_ecc_enabled, + .if_missing = s2n_extension_noop_if_missing, +}; + +bool s2n_extension_should_send_if_ecc_enabled(struct s2n_connection *conn) +{ + const struct s2n_security_policy *security_policy; + return s2n_connection_get_security_policy(conn, &security_policy) == S2N_SUCCESS + && s2n_ecc_is_extension_required(security_policy); +} + +static int s2n_client_supported_groups_send(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); + + const struct s2n_kem_preferences *kem_pref = NULL; + GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); + notnull_check(kem_pref); + + /* Group list len */ + struct s2n_stuffer_reservation group_list_len = { 0 }; + GUARD(s2n_stuffer_reserve_uint16(out, &group_list_len)); + + /* Send KEM groups list first */ + if (s2n_connection_get_protocol_version(conn) >= S2N_TLS13 && !s2n_is_in_fips_mode()) { + 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)); + } + } + + /* 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)); + } + + GUARD(s2n_stuffer_write_vector_size(&group_list_len)); + + return S2N_SUCCESS; +} + +/* Populates the appropriate index of either the mutually_supported_curves or + * mutually_supported_kem_groups array based on the received IANA ID. Will + * ignore unrecognized IANA IDs (and return success). */ +static int s2n_client_supported_groups_recv_iana_id(struct s2n_connection *conn, uint16_t iana_id) { + notnull_check(conn); + + const struct s2n_ecc_preferences *ecc_pref = NULL; + GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); + notnull_check(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; + return S2N_SUCCESS; + } + } + + /* Return early if in FIPS mode, or if TLS 1.3 is disabled, so as to ignore PQ IDs */ + if (s2n_is_in_fips_mode() || s2n_connection_get_protocol_version(conn) < S2N_TLS13) { + return S2N_SUCCESS; + } + + 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 < 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; + return S2N_SUCCESS; + } + } + + return S2N_SUCCESS; +} + +static int s2n_choose_supported_group(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); + + /* 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; + + /* Prefer to negotiate hybrid PQ over ECC. If in FIPS mode, 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]; + 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; + 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]; + if (candidate_curve != NULL) { + conn->secure.server_ecc_evp_params.negotiated_curve = candidate_curve; + return S2N_SUCCESS; + } + } + + return S2N_SUCCESS; +} + +static int s2n_client_supported_groups_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) { + notnull_check(conn); + notnull_check(extension); + + uint16_t size_of_all; + 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; + } + + 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)); + } + + GUARD(s2n_choose_supported_group(conn)); + + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +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)); + + /* 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)); + + return S2N_SUCCESS; +} + +int s2n_recv_client_supported_groups(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_supported_groups_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.h index d1590938b8..e5b798543e 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_groups.h @@ -1,27 +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 "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_supported_groups_extension; -bool s2n_extension_should_send_if_ecc_enabled(struct s2n_connection *conn); - -/* Old-style extension functions -- remove after extensions refactor is complete */ -int s2n_extensions_client_supported_groups_send(struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_recv_client_supported_groups(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_supported_groups_extension; +bool s2n_extension_should_send_if_ecc_enabled(struct s2n_connection *conn); + +/* Old-style extension functions -- remove after extensions refactor is complete */ +int s2n_extensions_client_supported_groups_send(struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_recv_client_supported_groups(struct s2n_connection *conn, struct s2n_stuffer *extension); 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 3b686e12f6..d0ec8cb329 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 @@ -1,153 +1,153 @@ -/* - * 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/extensions/s2n_client_supported_versions.h" -#include "tls/extensions/s2n_supported_versions.h" -#include "tls/s2n_alerts.h" -#include "tls/s2n_cipher_preferences.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" - -#include "utils/s2n_safety.h" - -/** - * Specified in https://tools.ietf.org/html/rfc8446#section-4.2.1 - * - * "The "supported_versions" extension is used by the client to indicate - * which versions of TLS it supports and by the server to indicate which - * version it is using. The extension contains a list of supported - * versions in preference order, with the most preferred version first." - * - * Structure: - * Extension type (2 bytes) - * Extension size (2 bytes) - * Version list length (1 byte) - * Version list (number of versions * 2 bytes) - * - * Note: We assume in these functions that the supported version numbers - * are consecutive. This is true because S2N does not support SSLv2, and - * is already an assumption made in the old client hello version handling. - **/ - -static int s2n_client_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_client_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *in); - -const s2n_extension_type s2n_client_supported_versions_extension = { - .iana_value = TLS_EXTENSION_SUPPORTED_VERSIONS, - .is_response = false, - .send = s2n_client_supported_versions_send, - .recv = s2n_client_supported_versions_recv, - .should_send = s2n_extension_send_if_tls13_connection, - .if_missing = s2n_extension_noop_if_missing, -}; - -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 version_list_length = highest_supported_version - minimum_supported_version + 1; - 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)); - } - - return S2N_SUCCESS; -} - -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 size_of_version_list; - 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); - - conn->client_protocol_version = s2n_unknown_protocol_version; - conn->actual_protocol_version = s2n_unknown_protocol_version; - - 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)); - - /* 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 - * a TLS1.3 extension, we will skip any SSLv2 values. */ - if (client_version_parts[0] != 3 || client_version_parts[1] > 4) { - continue; - } - - uint16_t client_version = (client_version_parts[0] * 10) + client_version_parts[1]; - - conn->client_protocol_version = MAX(client_version, conn->client_protocol_version); - - if (client_version > highest_supported_version) { - continue; - } - - if (client_version < minimum_supported_version) { - continue; - } - - /* We ignore the client's preferred order and instead choose - * the highest version that both client and server support. */ - conn->actual_protocol_version = MAX(client_version, conn->actual_protocol_version); - } - - S2N_ERROR_IF(conn->actual_protocol_version == s2n_unknown_protocol_version, S2N_ERR_UNKNOWN_PROTOCOL_VERSION); - - return S2N_SUCCESS; -} - -static int s2n_client_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *in) -{ - if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { - return S2N_SUCCESS; - } - - if (s2n_extensions_client_supported_versions_process(conn, in) < 0) { - s2n_queue_reader_unsupported_protocol_version_alert(conn); - S2N_ERROR(S2N_ERR_BAD_MESSAGE); - } - return S2N_SUCCESS; -} - -/* 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 highest_supported_version = conn->client_protocol_version; - - uint8_t version_list_length = highest_supported_version - minimum_supported_version + 1; - - return version_list_length * S2N_TLS_PROTOCOL_VERSION_LEN + 5; -} - -int s2n_extensions_client_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) { - return s2n_extension_recv(&s2n_client_supported_versions_extension, conn, extension); -} - -int s2n_extensions_client_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out) { - return s2n_extension_send(&s2n_client_supported_versions_extension, conn, out); -} +/* + * 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/extensions/s2n_client_supported_versions.h" +#include "tls/extensions/s2n_supported_versions.h" +#include "tls/s2n_alerts.h" +#include "tls/s2n_cipher_preferences.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" + +#include "utils/s2n_safety.h" + +/** + * Specified in https://tools.ietf.org/html/rfc8446#section-4.2.1 + * + * "The "supported_versions" extension is used by the client to indicate + * which versions of TLS it supports and by the server to indicate which + * version it is using. The extension contains a list of supported + * versions in preference order, with the most preferred version first." + * + * Structure: + * Extension type (2 bytes) + * Extension size (2 bytes) + * Version list length (1 byte) + * Version list (number of versions * 2 bytes) + * + * Note: We assume in these functions that the supported version numbers + * are consecutive. This is true because S2N does not support SSLv2, and + * is already an assumption made in the old client hello version handling. + **/ + +static int s2n_client_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_client_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *in); + +const s2n_extension_type s2n_client_supported_versions_extension = { + .iana_value = TLS_EXTENSION_SUPPORTED_VERSIONS, + .is_response = false, + .send = s2n_client_supported_versions_send, + .recv = s2n_client_supported_versions_recv, + .should_send = s2n_extension_send_if_tls13_connection, + .if_missing = s2n_extension_noop_if_missing, +}; + +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 version_list_length = highest_supported_version - minimum_supported_version + 1; + 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)); + } + + return S2N_SUCCESS; +} + +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 size_of_version_list; + 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); + + conn->client_protocol_version = s2n_unknown_protocol_version; + conn->actual_protocol_version = s2n_unknown_protocol_version; + + 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)); + + /* 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 + * a TLS1.3 extension, we will skip any SSLv2 values. */ + if (client_version_parts[0] != 3 || client_version_parts[1] > 4) { + continue; + } + + uint16_t client_version = (client_version_parts[0] * 10) + client_version_parts[1]; + + conn->client_protocol_version = MAX(client_version, conn->client_protocol_version); + + if (client_version > highest_supported_version) { + continue; + } + + if (client_version < minimum_supported_version) { + continue; + } + + /* We ignore the client's preferred order and instead choose + * the highest version that both client and server support. */ + conn->actual_protocol_version = MAX(client_version, conn->actual_protocol_version); + } + + S2N_ERROR_IF(conn->actual_protocol_version == s2n_unknown_protocol_version, S2N_ERR_UNKNOWN_PROTOCOL_VERSION); + + return S2N_SUCCESS; +} + +static int s2n_client_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *in) +{ + if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { + return S2N_SUCCESS; + } + + if (s2n_extensions_client_supported_versions_process(conn, in) < 0) { + s2n_queue_reader_unsupported_protocol_version_alert(conn); + S2N_ERROR(S2N_ERR_BAD_MESSAGE); + } + return S2N_SUCCESS; +} + +/* 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 highest_supported_version = conn->client_protocol_version; + + uint8_t version_list_length = highest_supported_version - minimum_supported_version + 1; + + return version_list_length * S2N_TLS_PROTOCOL_VERSION_LEN + 5; +} + +int s2n_extensions_client_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) { + return s2n_extension_recv(&s2n_client_supported_versions_extension, conn, extension); +} + +int s2n_extensions_client_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out) { + return s2n_extension_send(&s2n_client_supported_versions_extension, conn, out); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.h index c3657953c9..b9deabe628 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_client_supported_versions.h @@ -1,26 +1,26 @@ -/* - * 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_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_supported_versions_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -extern int s2n_extensions_client_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); -extern int s2n_extensions_client_supported_versions_size(struct s2n_connection *conn); -extern int s2n_extensions_client_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out); +/* + * 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_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_supported_versions_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +extern int s2n_extensions_client_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); +extern int s2n_extensions_client_supported_versions_size(struct s2n_connection *conn); +extern int s2n_extensions_client_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out); diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.c index add1f64269..7e8885bc0b 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.c @@ -1,103 +1,103 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "tls/extensions/s2n_cookie.h" -#include "tls/s2n_tls.h" - -#define S2N_SIZE_OF_EXTENSION_TYPE 2 -#define S2N_SIZE_OF_EXTENSION_DATA_SIZE 2 -#define S2N_SIZE_OF_COOKIE_DATA_SIZE 2 - -const s2n_extension_type s2n_client_cookie_extension = { - .iana_value = TLS_EXTENSION_COOKIE, - .is_response = true, - .send = s2n_extension_send_noop, - .recv = s2n_extension_recv_noop, - .should_send = s2n_extension_never_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_cookie_should_send(struct s2n_connection *conn); -static int s2n_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_server_cookie_extension = { - .iana_value = TLS_EXTENSION_COOKIE, - .is_response = false, - .send = s2n_cookie_send, - .recv = s2n_cookie_recv, - .should_send = s2n_cookie_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -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; -} - -static int s2n_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - notnull_check(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)); - 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; - } - - 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); - - 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)); - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_extensions_cookie_size(struct s2n_connection *conn) -{ - GUARD(s2n_stuffer_reread(&conn->cookie_stuffer)); - - if (s2n_stuffer_data_available(&conn->cookie_stuffer) == 0) { - return 0; - } - - const int cookie_extension_size = S2N_SIZE_OF_EXTENSION_TYPE - + S2N_SIZE_OF_EXTENSION_DATA_SIZE - + S2N_SIZE_OF_COOKIE_DATA_SIZE - + s2n_stuffer_data_available(&conn->cookie_stuffer); - - return cookie_extension_size; -} - -int s2n_extensions_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_send(&s2n_server_cookie_extension, conn, extension); -} - -int s2n_extensions_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_server_cookie_extension, conn, out); -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "tls/extensions/s2n_cookie.h" +#include "tls/s2n_tls.h" + +#define S2N_SIZE_OF_EXTENSION_TYPE 2 +#define S2N_SIZE_OF_EXTENSION_DATA_SIZE 2 +#define S2N_SIZE_OF_COOKIE_DATA_SIZE 2 + +const s2n_extension_type s2n_client_cookie_extension = { + .iana_value = TLS_EXTENSION_COOKIE, + .is_response = true, + .send = s2n_extension_send_noop, + .recv = s2n_extension_recv_noop, + .should_send = s2n_extension_never_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_cookie_should_send(struct s2n_connection *conn); +static int s2n_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_server_cookie_extension = { + .iana_value = TLS_EXTENSION_COOKIE, + .is_response = false, + .send = s2n_cookie_send, + .recv = s2n_cookie_recv, + .should_send = s2n_cookie_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +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; +} + +static int s2n_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + notnull_check(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)); + 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; + } + + 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); + + 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)); + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_extensions_cookie_size(struct s2n_connection *conn) +{ + GUARD(s2n_stuffer_reread(&conn->cookie_stuffer)); + + if (s2n_stuffer_data_available(&conn->cookie_stuffer) == 0) { + return 0; + } + + const int cookie_extension_size = S2N_SIZE_OF_EXTENSION_TYPE + + S2N_SIZE_OF_EXTENSION_DATA_SIZE + + S2N_SIZE_OF_COOKIE_DATA_SIZE + + s2n_stuffer_data_available(&conn->cookie_stuffer); + + return cookie_extension_size; +} + +int s2n_extensions_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_send(&s2n_server_cookie_extension, conn, extension); +} + +int s2n_extensions_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_server_cookie_extension, conn, out); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.h index 115226d9d4..4a77ba323e 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_cookie.h @@ -1,29 +1,29 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_client_cookie_extension; -extern const s2n_extension_type s2n_server_cookie_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -int s2n_extensions_cookie_size(struct s2n_connection *conn); -int s2n_extensions_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_extensions_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_client_cookie_extension; +extern const s2n_extension_type s2n_server_cookie_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +int s2n_extensions_cookie_size(struct s2n_connection *conn); +int s2n_extensions_cookie_send(struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_extensions_cookie_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.c index ac6a162efb..cb720581a6 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 @@ -1,91 +1,91 @@ -/* - * 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/extensions/s2n_client_supported_groups.h" -#include "tls/extensions/s2n_ec_point_format.h" -#include "tls/s2n_tls.h" - -#include "utils/s2n_safety.h" - -static int s2n_ec_point_format_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_ec_point_format_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_client_ec_point_format_extension = { - .iana_value = TLS_EXTENSION_EC_POINT_FORMATS, - .is_response = false, - .send = s2n_ec_point_format_send, - .recv = s2n_ec_point_format_recv, - .should_send = s2n_extension_should_send_if_ecc_enabled, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_server_ec_point_format_should_send(struct s2n_connection *conn); - -const s2n_extension_type s2n_server_ec_point_format_extension = { - .iana_value = TLS_EXTENSION_EC_POINT_FORMATS, - .is_response = true, - .send = s2n_ec_point_format_send, - .recv = s2n_extension_recv_noop, - .should_send = s2n_server_ec_point_format_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_server_ec_point_format_should_send(struct s2n_connection *conn) -{ - return conn && conn->secure.cipher_suite - && s2n_kex_includes(conn->secure.cipher_suite->key_exchange_alg, &s2n_ecdhe); -} - -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)); - - /* Only allow uncompressed format */ - GUARD(s2n_stuffer_write_uint8(out, TLS_EC_POINT_FORMAT_UNCOMPRESSED)); - - return S2N_SUCCESS; -} - -static int s2n_ec_point_format_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - /** - * Only uncompressed points are supported by the server and the client must include it in - * the extension. Just skip the extension. - */ - conn->ec_point_formats = 1; - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_server_ecc_point_format_extension_size(struct s2n_connection *conn) -{ - if (s2n_server_ec_point_format_extension.should_send(conn) && s2n_server_can_send_ec_point_formats(conn)) { - return sizeof(uint16_t) /* extension type */ - + sizeof(uint16_t) /* extension size */ - + sizeof(uint8_t) /* point list size */ - + sizeof(uint8_t); /* point */ - } - return 0; -} - -int s2n_recv_client_ec_point_formats(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_client_ec_point_format_extension, conn, extension); -} +/* + * 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/extensions/s2n_client_supported_groups.h" +#include "tls/extensions/s2n_ec_point_format.h" +#include "tls/s2n_tls.h" + +#include "utils/s2n_safety.h" + +static int s2n_ec_point_format_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_ec_point_format_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_client_ec_point_format_extension = { + .iana_value = TLS_EXTENSION_EC_POINT_FORMATS, + .is_response = false, + .send = s2n_ec_point_format_send, + .recv = s2n_ec_point_format_recv, + .should_send = s2n_extension_should_send_if_ecc_enabled, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_server_ec_point_format_should_send(struct s2n_connection *conn); + +const s2n_extension_type s2n_server_ec_point_format_extension = { + .iana_value = TLS_EXTENSION_EC_POINT_FORMATS, + .is_response = true, + .send = s2n_ec_point_format_send, + .recv = s2n_extension_recv_noop, + .should_send = s2n_server_ec_point_format_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_server_ec_point_format_should_send(struct s2n_connection *conn) +{ + return conn && conn->secure.cipher_suite + && s2n_kex_includes(conn->secure.cipher_suite->key_exchange_alg, &s2n_ecdhe); +} + +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)); + + /* Only allow uncompressed format */ + GUARD(s2n_stuffer_write_uint8(out, TLS_EC_POINT_FORMAT_UNCOMPRESSED)); + + return S2N_SUCCESS; +} + +static int s2n_ec_point_format_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + /** + * Only uncompressed points are supported by the server and the client must include it in + * the extension. Just skip the extension. + */ + conn->ec_point_formats = 1; + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_server_ecc_point_format_extension_size(struct s2n_connection *conn) +{ + if (s2n_server_ec_point_format_extension.should_send(conn) && s2n_server_can_send_ec_point_formats(conn)) { + return sizeof(uint16_t) /* extension type */ + + sizeof(uint16_t) /* extension size */ + + sizeof(uint8_t) /* point list size */ + + sizeof(uint8_t); /* point */ + } + return 0; +} + +int s2n_recv_client_ec_point_formats(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_client_ec_point_format_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.h index ac01ad7672..4e7cf3065d 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_ec_point_format.h @@ -1,29 +1,29 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -#define TLS_EC_POINT_FORMAT_UNCOMPRESSED 0 - -extern const s2n_extension_type s2n_client_ec_point_format_extension; -extern const s2n_extension_type s2n_server_ec_point_format_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -int s2n_server_ecc_point_format_extension_size(struct s2n_connection *conn); -int s2n_recv_client_ec_point_formats(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +#define TLS_EC_POINT_FORMAT_UNCOMPRESSED 0 + +extern const s2n_extension_type s2n_client_ec_point_format_extension; +extern const s2n_extension_type s2n_server_ec_point_format_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +int s2n_server_ecc_point_format_extension_size(struct s2n_connection *conn); +int s2n_recv_client_ec_point_formats(struct s2n_connection *conn, struct s2n_stuffer *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 11c840d66a..81c9e9bf5a 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.c @@ -1,184 +1,184 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "s2n_extension_list.h" -#include "s2n_extension_type.h" -#include "s2n_extension_type_lists.h" - -#include <s2n.h> - -#include "error/s2n_errno.h" -#include "utils/s2n_safety.h" - -#define s2n_parsed_extension_is_empty(parsed_extension) ((parsed_extension)->extension.data == NULL) - -static const s2n_parsed_extension empty_parsed_extensions[S2N_PARSED_EXTENSIONS_COUNT] = { 0 }; - -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)); - - struct s2n_stuffer_reservation total_extensions_size = {0}; - 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)); - } - - 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)); - 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); - - if (s2n_parsed_extension_is_empty(&parsed_extensions[extension_id])) { - GUARD(s2n_extension_is_missing(extension_type, conn)); - return S2N_SUCCESS; - } - - ENSURE_POSIX(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)); - - GUARD(s2n_extension_recv(extension_type, conn, &extension_stuffer)); - - return S2N_SUCCESS; -} - -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); - - s2n_extension_type_id extension_id; - 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); - - /* Wipe parsed_extension. - * We can check for unprocessed extensions later by checking for non-blank parsed_extensions. */ - parsed_extension_list->parsed_extensions[extension_id] = empty_parsed_extensions[0]; - - return result; -} - -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); - - s2n_extension_type_list *extension_type_list; - 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], - conn, parsed_extension_list)); - } - - /* If parsed_extension_list.parsed_extensions is not completely wiped at this point, - * then we have received an extension not allowed on this message type. - * - * According to the RFC, we should alert and close the connection. - * From https://tools.ietf.org/html/rfc8446#section-4.2: - * If an implementation receives an extension which it recognizes and which is not - * specified for the message in which it appears, it MUST abort the handshake with an - * "illegal_parameter" alert. - * - * However, to be more tolerant of non-compliant peers, we will just ignore and not - * process the illegal extensions, treating them as if they are unsupported. - */ - - return S2N_SUCCESS; -} - -static int s2n_extension_parse(struct s2n_stuffer *in, s2n_parsed_extension *parsed_extensions) -{ - notnull_check(parsed_extensions); - - uint16_t extension_type; - ENSURE_POSIX(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, - S2N_ERR_BAD_MESSAGE); - - uint8_t *extension_data = s2n_stuffer_raw_read(in, extension_size); - ENSURE_POSIX(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) { - /* Ignore unknown extensions */ - return S2N_SUCCESS; - } - - s2n_parsed_extension *parsed_extension = &parsed_extensions[extension_id]; - - /* Error if extension is a duplicate */ - ENSURE_POSIX(s2n_parsed_extension_is_empty(parsed_extension), - S2N_ERR_DUPLICATE_EXTENSION); - - /* Fill in parsed extension */ - parsed_extension->extension_type = extension_type; - GUARD(s2n_blob_init(&parsed_extension->extension, extension_data, extension_size)); - - return S2N_SUCCESS; -} - -int s2n_extension_list_parse(struct s2n_stuffer *in, s2n_parsed_extensions_list *parsed_extension_list) -{ - notnull_check(in); - notnull_check(parsed_extension_list); - - memset_check((s2n_parsed_extension*) parsed_extension_list->parsed_extensions, - 0, sizeof(parsed_extension_list->parsed_extensions)); - - uint16_t total_extensions_size; - if (s2n_stuffer_read_uint16(in, &total_extensions_size) != S2N_SUCCESS) { - total_extensions_size = 0; - } - - uint8_t *extensions_data = s2n_stuffer_raw_read(in, total_extensions_size); - ENSURE_POSIX(extensions_data != NULL, S2N_ERR_BAD_MESSAGE); - - 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)); - - while (s2n_stuffer_data_available(&extensions_stuffer)) { - GUARD(s2n_extension_parse(&extensions_stuffer, parsed_extension_list->parsed_extensions)); - } - - return S2N_SUCCESS; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "s2n_extension_list.h" +#include "s2n_extension_type.h" +#include "s2n_extension_type_lists.h" + +#include <s2n.h> + +#include "error/s2n_errno.h" +#include "utils/s2n_safety.h" + +#define s2n_parsed_extension_is_empty(parsed_extension) ((parsed_extension)->extension.data == NULL) + +static const s2n_parsed_extension empty_parsed_extensions[S2N_PARSED_EXTENSIONS_COUNT] = { 0 }; + +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)); + + struct s2n_stuffer_reservation total_extensions_size = {0}; + 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)); + } + + 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)); + 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); + + if (s2n_parsed_extension_is_empty(&parsed_extensions[extension_id])) { + GUARD(s2n_extension_is_missing(extension_type, conn)); + return S2N_SUCCESS; + } + + ENSURE_POSIX(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)); + + GUARD(s2n_extension_recv(extension_type, conn, &extension_stuffer)); + + return S2N_SUCCESS; +} + +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); + + s2n_extension_type_id extension_id; + 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); + + /* Wipe parsed_extension. + * We can check for unprocessed extensions later by checking for non-blank parsed_extensions. */ + parsed_extension_list->parsed_extensions[extension_id] = empty_parsed_extensions[0]; + + return result; +} + +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); + + s2n_extension_type_list *extension_type_list; + 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], + conn, parsed_extension_list)); + } + + /* If parsed_extension_list.parsed_extensions is not completely wiped at this point, + * then we have received an extension not allowed on this message type. + * + * According to the RFC, we should alert and close the connection. + * From https://tools.ietf.org/html/rfc8446#section-4.2: + * If an implementation receives an extension which it recognizes and which is not + * specified for the message in which it appears, it MUST abort the handshake with an + * "illegal_parameter" alert. + * + * However, to be more tolerant of non-compliant peers, we will just ignore and not + * process the illegal extensions, treating them as if they are unsupported. + */ + + return S2N_SUCCESS; +} + +static int s2n_extension_parse(struct s2n_stuffer *in, s2n_parsed_extension *parsed_extensions) +{ + notnull_check(parsed_extensions); + + uint16_t extension_type; + ENSURE_POSIX(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, + S2N_ERR_BAD_MESSAGE); + + uint8_t *extension_data = s2n_stuffer_raw_read(in, extension_size); + ENSURE_POSIX(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) { + /* Ignore unknown extensions */ + return S2N_SUCCESS; + } + + s2n_parsed_extension *parsed_extension = &parsed_extensions[extension_id]; + + /* Error if extension is a duplicate */ + ENSURE_POSIX(s2n_parsed_extension_is_empty(parsed_extension), + S2N_ERR_DUPLICATE_EXTENSION); + + /* Fill in parsed extension */ + parsed_extension->extension_type = extension_type; + GUARD(s2n_blob_init(&parsed_extension->extension, extension_data, extension_size)); + + return S2N_SUCCESS; +} + +int s2n_extension_list_parse(struct s2n_stuffer *in, s2n_parsed_extensions_list *parsed_extension_list) +{ + notnull_check(in); + notnull_check(parsed_extension_list); + + memset_check((s2n_parsed_extension*) parsed_extension_list->parsed_extensions, + 0, sizeof(parsed_extension_list->parsed_extensions)); + + uint16_t total_extensions_size; + if (s2n_stuffer_read_uint16(in, &total_extensions_size) != S2N_SUCCESS) { + total_extensions_size = 0; + } + + uint8_t *extensions_data = s2n_stuffer_raw_read(in, total_extensions_size); + ENSURE_POSIX(extensions_data != NULL, S2N_ERR_BAD_MESSAGE); + + 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)); + + while (s2n_stuffer_data_available(&extensions_stuffer)) { + GUARD(s2n_extension_parse(&extensions_stuffer, parsed_extension_list->parsed_extensions)); + } + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h index 3609587ac4..35582e5638 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_list.h @@ -1,51 +1,51 @@ -/* - * 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 "stuffer/s2n_stuffer.h" -#include "tls/extensions/s2n_extension_type.h" - -#define S2N_PARSED_EXTENSIONS_COUNT S2N_SUPPORTED_EXTENSIONS_COUNT - -typedef struct { - uint16_t extension_type; - struct s2n_blob extension; -} s2n_parsed_extension; - -typedef struct { - s2n_parsed_extension parsed_extensions[S2N_PARSED_EXTENSIONS_COUNT]; - struct s2n_blob raw; /* Needed by some ClientHello APIs */ -} s2n_parsed_extensions_list; - -typedef enum { - S2N_EXTENSION_LIST_CLIENT_HELLO = 0, - 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_EMPTY, - S2N_EXTENSION_LIST_IDS_COUNT, -} s2n_extension_list_id; - -int s2n_extension_list_send(s2n_extension_list_id list_type, struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_extension_list_recv(s2n_extension_list_id list_type, struct s2n_connection *conn, struct s2n_stuffer *in); - -int s2n_extension_process(const s2n_extension_type *extension_type, struct s2n_connection *conn, - s2n_parsed_extensions_list *parsed_extension_list); -int s2n_extension_list_process(s2n_extension_list_id list_type, struct s2n_connection *conn, - s2n_parsed_extensions_list *parsed_extension_list); -int s2n_extension_list_parse(struct s2n_stuffer *in, s2n_parsed_extensions_list *parsed_extension_list); +/* + * 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 "stuffer/s2n_stuffer.h" +#include "tls/extensions/s2n_extension_type.h" + +#define S2N_PARSED_EXTENSIONS_COUNT S2N_SUPPORTED_EXTENSIONS_COUNT + +typedef struct { + uint16_t extension_type; + struct s2n_blob extension; +} s2n_parsed_extension; + +typedef struct { + s2n_parsed_extension parsed_extensions[S2N_PARSED_EXTENSIONS_COUNT]; + struct s2n_blob raw; /* Needed by some ClientHello APIs */ +} s2n_parsed_extensions_list; + +typedef enum { + S2N_EXTENSION_LIST_CLIENT_HELLO = 0, + 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_EMPTY, + S2N_EXTENSION_LIST_IDS_COUNT, +} s2n_extension_list_id; + +int s2n_extension_list_send(s2n_extension_list_id list_type, struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_extension_list_recv(s2n_extension_list_id list_type, struct s2n_connection *conn, struct s2n_stuffer *in); + +int s2n_extension_process(const s2n_extension_type *extension_type, struct s2n_connection *conn, + s2n_parsed_extensions_list *parsed_extension_list); +int s2n_extension_list_process(s2n_extension_list_id list_type, struct s2n_connection *conn, + s2n_parsed_extensions_list *parsed_extension_list); +int s2n_extension_list_parse(struct s2n_stuffer *in, s2n_parsed_extensions_list *parsed_extension_list); 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 a961692f92..040c57a16c 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.c @@ -1,212 +1,212 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <s2n.h> - -#include "error/s2n_errno.h" -#include "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_tls13.h" -#include "utils/s2n_bitmap.h" -#include "utils/s2n_safety.h" - -#define TLS_EXTENSION_DATA_LENGTH_BYTES 2 - -/* Because there are 65536 possible extension IANAs, we will only - * put the lowest (and most common) in a lookup table to conserve space. */ -#define S2N_MAX_INDEXED_EXTENSION_IANA 60 - -const s2n_extension_type_id s2n_unsupported_extension = S2N_SUPPORTED_EXTENSIONS_COUNT; -s2n_extension_type_id s2n_extension_ianas_to_ids[S2N_MAX_INDEXED_EXTENSION_IANA]; - -int s2n_extension_type_init() -{ - /* Initialize to s2n_unsupported_extension */ - for (int i = 0; i < S2N_MAX_INDEXED_EXTENSION_IANA; i++) { - s2n_extension_ianas_to_ids[i] = s2n_unsupported_extension; - } - - /* Reverse the mapping */ - for (int i = 0; i < S2N_SUPPORTED_EXTENSIONS_COUNT; i++) { - uint16_t iana_value = s2n_supported_extensions[i]; - if (iana_value < S2N_MAX_INDEXED_EXTENSION_IANA) { - s2n_extension_ianas_to_ids[iana_value] = i; - } - } - - return S2N_SUCCESS; -} - -/* Convert the IANA value (which ranges from 0->65535) to an id with a more - * constrained range. That id can be used for bitfields, array indexes, etc. - * to avoid allocating too much memory. */ -s2n_extension_type_id s2n_extension_iana_value_to_id(const uint16_t iana_value) -{ - /* Check the lookup table */ - if (iana_value < S2N_MAX_INDEXED_EXTENSION_IANA) { - return s2n_extension_ianas_to_ids[iana_value]; - } - - /* Fall back to the full list. We can handle this more - * efficiently later if our extension list gets long. */ - for (int i = 0; i < S2N_SUPPORTED_EXTENSIONS_COUNT; i++) { - if (s2n_supported_extensions[i] == iana_value) { - return i; - } - } - - return s2n_unsupported_extension; -} - -int s2n_extension_supported_iana_value_to_id(const uint16_t iana_value, s2n_extension_type_id *internal_id) -{ - notnull_check(internal_id); - - *internal_id = s2n_extension_iana_value_to_id(iana_value); - S2N_ERROR_IF(*internal_id == s2n_unsupported_extension, S2N_ERR_UNRECOGNIZED_EXTENSION); - return S2N_SUCCESS; -} - -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); - - s2n_extension_type_id extension_id; - 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 && - !S2N_CBIT_TEST(conn->extension_requests_received, extension_id)) { - 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)); - - /* Reserve space for extension size */ - struct s2n_stuffer_reservation extension_size_bytes = {0}; - GUARD(s2n_stuffer_reserve_uint16(out, &extension_size_bytes)); - - /* Write extension data */ - GUARD(extension_type->send(conn, out)); - - /* Record extension size */ - GUARD(s2n_stuffer_write_vector_size(&extension_size_bytes)); - - /* Set request bit flag */ - if (!extension_type->is_response) { - S2N_CBIT_SET(conn->extension_requests_sent, extension_id); - } - - return S2N_SUCCESS; -} - -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); - - 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 && - !S2N_CBIT_TEST(conn->extension_requests_sent, extension_id)) { - S2N_ERROR(S2N_ERR_UNSUPPORTED_EXTENSION); - } - - GUARD(extension_type->recv(conn, in)); - - /* Set request bit flag */ - if (!extension_type->is_response) { - S2N_CBIT_SET(conn->extension_requests_received, extension_id); - } - - return S2N_SUCCESS; -} - -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); - - s2n_extension_type_id extension_id; - 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 && - !S2N_CBIT_TEST(conn->extension_requests_sent, extension_id)) { - return S2N_SUCCESS; - } - - 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); -} - -int s2n_extension_recv_unimplemented(struct s2n_connection *conn, struct s2n_stuffer *in) -{ - S2N_ERROR(S2N_ERR_UNIMPLEMENTED); -} - -int s2n_extension_send_noop(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return S2N_SUCCESS; -} - -int s2n_extension_recv_noop(struct s2n_connection *conn, struct s2n_stuffer *in) -{ - return S2N_SUCCESS; -} - -bool s2n_extension_always_send(struct s2n_connection *conn) -{ - return true; -} - -bool s2n_extension_never_send(struct s2n_connection *conn) -{ - return false; -} - -bool s2n_extension_send_if_tls13_connection(struct s2n_connection *conn) -{ - return s2n_connection_get_protocol_version(conn) >= S2N_TLS13; -} - -int s2n_extension_error_if_missing(struct s2n_connection *conn) -{ - S2N_ERROR(S2N_ERR_MISSING_EXTENSION); -} - -int s2n_extension_noop_if_missing(struct s2n_connection *conn) -{ - return S2N_SUCCESS; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <s2n.h> + +#include "error/s2n_errno.h" +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_tls13.h" +#include "utils/s2n_bitmap.h" +#include "utils/s2n_safety.h" + +#define TLS_EXTENSION_DATA_LENGTH_BYTES 2 + +/* Because there are 65536 possible extension IANAs, we will only + * put the lowest (and most common) in a lookup table to conserve space. */ +#define S2N_MAX_INDEXED_EXTENSION_IANA 60 + +const s2n_extension_type_id s2n_unsupported_extension = S2N_SUPPORTED_EXTENSIONS_COUNT; +s2n_extension_type_id s2n_extension_ianas_to_ids[S2N_MAX_INDEXED_EXTENSION_IANA]; + +int s2n_extension_type_init() +{ + /* Initialize to s2n_unsupported_extension */ + for (int i = 0; i < S2N_MAX_INDEXED_EXTENSION_IANA; i++) { + s2n_extension_ianas_to_ids[i] = s2n_unsupported_extension; + } + + /* Reverse the mapping */ + for (int i = 0; i < S2N_SUPPORTED_EXTENSIONS_COUNT; i++) { + uint16_t iana_value = s2n_supported_extensions[i]; + if (iana_value < S2N_MAX_INDEXED_EXTENSION_IANA) { + s2n_extension_ianas_to_ids[iana_value] = i; + } + } + + return S2N_SUCCESS; +} + +/* Convert the IANA value (which ranges from 0->65535) to an id with a more + * constrained range. That id can be used for bitfields, array indexes, etc. + * to avoid allocating too much memory. */ +s2n_extension_type_id s2n_extension_iana_value_to_id(const uint16_t iana_value) +{ + /* Check the lookup table */ + if (iana_value < S2N_MAX_INDEXED_EXTENSION_IANA) { + return s2n_extension_ianas_to_ids[iana_value]; + } + + /* Fall back to the full list. We can handle this more + * efficiently later if our extension list gets long. */ + for (int i = 0; i < S2N_SUPPORTED_EXTENSIONS_COUNT; i++) { + if (s2n_supported_extensions[i] == iana_value) { + return i; + } + } + + return s2n_unsupported_extension; +} + +int s2n_extension_supported_iana_value_to_id(const uint16_t iana_value, s2n_extension_type_id *internal_id) +{ + notnull_check(internal_id); + + *internal_id = s2n_extension_iana_value_to_id(iana_value); + S2N_ERROR_IF(*internal_id == s2n_unsupported_extension, S2N_ERR_UNRECOGNIZED_EXTENSION); + return S2N_SUCCESS; +} + +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); + + s2n_extension_type_id extension_id; + 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 && + !S2N_CBIT_TEST(conn->extension_requests_received, extension_id)) { + 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)); + + /* Reserve space for extension size */ + struct s2n_stuffer_reservation extension_size_bytes = {0}; + GUARD(s2n_stuffer_reserve_uint16(out, &extension_size_bytes)); + + /* Write extension data */ + GUARD(extension_type->send(conn, out)); + + /* Record extension size */ + GUARD(s2n_stuffer_write_vector_size(&extension_size_bytes)); + + /* Set request bit flag */ + if (!extension_type->is_response) { + S2N_CBIT_SET(conn->extension_requests_sent, extension_id); + } + + return S2N_SUCCESS; +} + +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); + + 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 && + !S2N_CBIT_TEST(conn->extension_requests_sent, extension_id)) { + S2N_ERROR(S2N_ERR_UNSUPPORTED_EXTENSION); + } + + GUARD(extension_type->recv(conn, in)); + + /* Set request bit flag */ + if (!extension_type->is_response) { + S2N_CBIT_SET(conn->extension_requests_received, extension_id); + } + + return S2N_SUCCESS; +} + +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); + + s2n_extension_type_id extension_id; + 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 && + !S2N_CBIT_TEST(conn->extension_requests_sent, extension_id)) { + return S2N_SUCCESS; + } + + 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); +} + +int s2n_extension_recv_unimplemented(struct s2n_connection *conn, struct s2n_stuffer *in) +{ + S2N_ERROR(S2N_ERR_UNIMPLEMENTED); +} + +int s2n_extension_send_noop(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return S2N_SUCCESS; +} + +int s2n_extension_recv_noop(struct s2n_connection *conn, struct s2n_stuffer *in) +{ + return S2N_SUCCESS; +} + +bool s2n_extension_always_send(struct s2n_connection *conn) +{ + return true; +} + +bool s2n_extension_never_send(struct s2n_connection *conn) +{ + return false; +} + +bool s2n_extension_send_if_tls13_connection(struct s2n_connection *conn) +{ + return s2n_connection_get_protocol_version(conn) >= S2N_TLS13; +} + +int s2n_extension_error_if_missing(struct s2n_connection *conn) +{ + S2N_ERROR(S2N_ERR_MISSING_EXTENSION); +} + +int s2n_extension_noop_if_missing(struct s2n_connection *conn) +{ + return S2N_SUCCESS; +} 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 22e01b2005..674c8e63dd 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type.h @@ -1,99 +1,99 @@ -/* - * 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 <stdbool.h> - -#include "stuffer/s2n_stuffer.h" -#include "tls/s2n_tls_parameters.h" - -#define S2N_EXTENSION_TYPE_FIELD_LENGTH 2 -#define S2N_EXTENSION_LENGTH_FIELD_LENGTH 2 - -/* The number of extensions supported by S2N */ -#define S2N_SUPPORTED_EXTENSIONS_COUNT (sizeof(s2n_supported_extensions) / sizeof(s2n_supported_extensions[0])) - -/* The number of bytes needed to assign 1 bit to every supported extension. - * The +1 is necessary to handle any remainder left over when dividing. */ -#define S2N_SUPPORTED_EXTENSIONS_BITFIELD_LEN ((S2N_SUPPORTED_EXTENSIONS_COUNT / sizeof(char)) + 1) - -struct s2n_connection; -typedef struct { - uint16_t iana_value; - unsigned is_response:1; - - int (*send) (struct s2n_connection *conn, struct s2n_stuffer *out); - int (*recv) (struct s2n_connection *conn, struct s2n_stuffer *in); - - /* Returns true or false to indicate whether the extension should be sent */ - bool (*should_send) (struct s2n_connection *conn); - - /* Handler called if an extension is not received */ - int (*if_missing) (struct s2n_connection *conn); -} s2n_extension_type; - -static const uint16_t s2n_supported_extensions[] = { - TLS_EXTENSION_RENEGOTIATION_INFO, - TLS_EXTENSION_PQ_KEM_PARAMETERS, - TLS_EXTENSION_SERVER_NAME, - TLS_EXTENSION_MAX_FRAG_LEN, - TLS_EXTENSION_STATUS_REQUEST, - TLS_EXTENSION_SUPPORTED_GROUPS, - TLS_EXTENSION_EC_POINT_FORMATS, - TLS_EXTENSION_SIGNATURE_ALGORITHMS, - TLS_EXTENSION_ALPN, - TLS_EXTENSION_SCT_LIST, - TLS_EXTENSION_SESSION_TICKET, - TLS_EXTENSION_SUPPORTED_VERSIONS, - TLS_EXTENSION_KEY_SHARE, - TLS_EXTENSION_COOKIE, - TLS_QUIC_TRANSPORT_PARAMETERS, - TLS_EXTENSION_PRE_SHARED_KEY, -}; - -typedef char s2n_extension_bitfield[S2N_SUPPORTED_EXTENSIONS_BITFIELD_LEN]; - -typedef uint8_t s2n_extension_type_id; -extern const s2n_extension_type_id s2n_unsupported_extension; - -int s2n_extension_send(const s2n_extension_type *extension_type, struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_extension_recv(const s2n_extension_type *extension_type, struct s2n_connection *conn, struct s2n_stuffer *in); -int s2n_extension_is_missing(const s2n_extension_type *extension_type, struct s2n_connection *conn); - -/* Map from TLS IANA value to internal s2n id. - * All possible IANA values is a large space, so using an internal id gives us more - * flexibility when using arrays / bitfields / etc. */ -int s2n_extension_supported_iana_value_to_id(const uint16_t iana_value, s2n_extension_type_id *internal_id); - -/* Initializer */ -int s2n_extension_type_init(); - -/* Common implementations for send */ -int s2n_extension_send_unimplemented(struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_extension_send_noop(struct s2n_connection *conn, struct s2n_stuffer *out); - -/* Common implementations for recv */ -int s2n_extension_recv_unimplemented(struct s2n_connection *conn, struct s2n_stuffer *in); -int s2n_extension_recv_noop(struct s2n_connection *conn, struct s2n_stuffer *out); - -/* Common implementations for should_send */ -bool s2n_extension_always_send(struct s2n_connection *conn); -bool s2n_extension_never_send(struct s2n_connection *conn); -bool s2n_extension_send_if_tls13_connection(struct s2n_connection *conn); - -/* Common implementations for if_missing */ -int s2n_extension_error_if_missing(struct s2n_connection *conn); -int s2n_extension_noop_if_missing(struct s2n_connection *conn); +/* + * 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 <stdbool.h> + +#include "stuffer/s2n_stuffer.h" +#include "tls/s2n_tls_parameters.h" + +#define S2N_EXTENSION_TYPE_FIELD_LENGTH 2 +#define S2N_EXTENSION_LENGTH_FIELD_LENGTH 2 + +/* The number of extensions supported by S2N */ +#define S2N_SUPPORTED_EXTENSIONS_COUNT (sizeof(s2n_supported_extensions) / sizeof(s2n_supported_extensions[0])) + +/* The number of bytes needed to assign 1 bit to every supported extension. + * The +1 is necessary to handle any remainder left over when dividing. */ +#define S2N_SUPPORTED_EXTENSIONS_BITFIELD_LEN ((S2N_SUPPORTED_EXTENSIONS_COUNT / sizeof(char)) + 1) + +struct s2n_connection; +typedef struct { + uint16_t iana_value; + unsigned is_response:1; + + int (*send) (struct s2n_connection *conn, struct s2n_stuffer *out); + int (*recv) (struct s2n_connection *conn, struct s2n_stuffer *in); + + /* Returns true or false to indicate whether the extension should be sent */ + bool (*should_send) (struct s2n_connection *conn); + + /* Handler called if an extension is not received */ + int (*if_missing) (struct s2n_connection *conn); +} s2n_extension_type; + +static const uint16_t s2n_supported_extensions[] = { + TLS_EXTENSION_RENEGOTIATION_INFO, + TLS_EXTENSION_PQ_KEM_PARAMETERS, + TLS_EXTENSION_SERVER_NAME, + TLS_EXTENSION_MAX_FRAG_LEN, + TLS_EXTENSION_STATUS_REQUEST, + TLS_EXTENSION_SUPPORTED_GROUPS, + TLS_EXTENSION_EC_POINT_FORMATS, + TLS_EXTENSION_SIGNATURE_ALGORITHMS, + TLS_EXTENSION_ALPN, + TLS_EXTENSION_SCT_LIST, + TLS_EXTENSION_SESSION_TICKET, + TLS_EXTENSION_SUPPORTED_VERSIONS, + TLS_EXTENSION_KEY_SHARE, + TLS_EXTENSION_COOKIE, + TLS_QUIC_TRANSPORT_PARAMETERS, + TLS_EXTENSION_PRE_SHARED_KEY, +}; + +typedef char s2n_extension_bitfield[S2N_SUPPORTED_EXTENSIONS_BITFIELD_LEN]; + +typedef uint8_t s2n_extension_type_id; +extern const s2n_extension_type_id s2n_unsupported_extension; + +int s2n_extension_send(const s2n_extension_type *extension_type, struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_extension_recv(const s2n_extension_type *extension_type, struct s2n_connection *conn, struct s2n_stuffer *in); +int s2n_extension_is_missing(const s2n_extension_type *extension_type, struct s2n_connection *conn); + +/* Map from TLS IANA value to internal s2n id. + * All possible IANA values is a large space, so using an internal id gives us more + * flexibility when using arrays / bitfields / etc. */ +int s2n_extension_supported_iana_value_to_id(const uint16_t iana_value, s2n_extension_type_id *internal_id); + +/* Initializer */ +int s2n_extension_type_init(); + +/* Common implementations for send */ +int s2n_extension_send_unimplemented(struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_extension_send_noop(struct s2n_connection *conn, struct s2n_stuffer *out); + +/* Common implementations for recv */ +int s2n_extension_recv_unimplemented(struct s2n_connection *conn, struct s2n_stuffer *in); +int s2n_extension_recv_noop(struct s2n_connection *conn, struct s2n_stuffer *out); + +/* Common implementations for should_send */ +bool s2n_extension_always_send(struct s2n_connection *conn); +bool s2n_extension_never_send(struct s2n_connection *conn); +bool s2n_extension_send_if_tls13_connection(struct s2n_connection *conn); + +/* Common implementations for if_missing */ +int s2n_extension_error_if_missing(struct s2n_connection *conn); +int s2n_extension_noop_if_missing(struct s2n_connection *conn); 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 86e55bbd8a..ed4c196f59 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 @@ -1,121 +1,121 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <s2n.h> - -#include "tls/extensions/s2n_extension_type_lists.h" -#include "tls/s2n_connection.h" - -#include "tls/extensions/s2n_cookie.h" -#include "tls/extensions/s2n_client_supported_versions.h" -#include "tls/extensions/s2n_client_signature_algorithms.h" -#include "tls/extensions/s2n_client_max_frag_len.h" -#include "tls/extensions/s2n_client_session_ticket.h" -#include "tls/extensions/s2n_client_server_name.h" -#include "tls/extensions/s2n_client_alpn.h" -#include "tls/extensions/s2n_client_status_request.h" -#include "tls/extensions/s2n_client_key_share.h" -#include "tls/extensions/s2n_client_sct_list.h" -#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_client_renegotiation_info.h" -#include "tls/extensions/s2n_ec_point_format.h" -#include "tls/extensions/s2n_quic_transport_params.h" -#include "tls/extensions/s2n_server_certificate_status.h" -#include "tls/extensions/s2n_server_renegotiation_info.h" -#include "tls/extensions/s2n_server_alpn.h" -#include "tls/extensions/s2n_server_status_request.h" -#include "tls/extensions/s2n_server_sct_list.h" -#include "tls/extensions/s2n_server_max_fragment_length.h" -#include "tls/extensions/s2n_server_session_ticket.h" -#include "tls/extensions/s2n_server_server_name.h" -#include "tls/extensions/s2n_server_signature_algorithms.h" -#include "tls/extensions/s2n_server_supported_versions.h" -#include "tls/extensions/s2n_server_key_share.h" - -static const s2n_extension_type *const client_hello_extensions[] = { - &s2n_client_supported_versions_extension, - &s2n_client_key_share_extension, - &s2n_client_signature_algorithms_extension, - &s2n_client_server_name_extension, - &s2n_client_alpn_extension, - &s2n_client_status_request_extension, - &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_client_psk_extension /* MUST be last */ -}; - -static const s2n_extension_type *const tls12_server_hello_extensions[] = { - &s2n_server_supported_versions_extension, - &s2n_server_server_name_extension, - &s2n_server_ec_point_format_extension, - &s2n_server_renegotiation_info_extension, - &s2n_server_alpn_extension, - &s2n_server_status_request_extension, - &s2n_server_sct_list_extension, - &s2n_server_max_fragment_length_extension, - &s2n_server_session_ticket_extension, -}; - -static const s2n_extension_type *const tls13_server_hello_extensions[] = { - &s2n_server_supported_versions_extension, - &s2n_server_key_share_extension, - &s2n_server_cookie_extension, -}; - -static const s2n_extension_type *const encrypted_extensions[] = { - &s2n_server_server_name_extension, - &s2n_server_max_fragment_length_extension, - &s2n_server_alpn_extension, - &s2n_quic_transport_parameters_extension, -}; - -static const s2n_extension_type *const cert_req_extensions[] = { - &s2n_server_signature_algorithms_extension, -}; - -static const s2n_extension_type *const certificate_extensions[] = { - &s2n_tls13_server_status_request_extension, - &s2n_server_sct_list_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_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_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)); - - *extension_list = &extension_lists[list_type]; - return S2N_SUCCESS; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <s2n.h> + +#include "tls/extensions/s2n_extension_type_lists.h" +#include "tls/s2n_connection.h" + +#include "tls/extensions/s2n_cookie.h" +#include "tls/extensions/s2n_client_supported_versions.h" +#include "tls/extensions/s2n_client_signature_algorithms.h" +#include "tls/extensions/s2n_client_max_frag_len.h" +#include "tls/extensions/s2n_client_session_ticket.h" +#include "tls/extensions/s2n_client_server_name.h" +#include "tls/extensions/s2n_client_alpn.h" +#include "tls/extensions/s2n_client_status_request.h" +#include "tls/extensions/s2n_client_key_share.h" +#include "tls/extensions/s2n_client_sct_list.h" +#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_client_renegotiation_info.h" +#include "tls/extensions/s2n_ec_point_format.h" +#include "tls/extensions/s2n_quic_transport_params.h" +#include "tls/extensions/s2n_server_certificate_status.h" +#include "tls/extensions/s2n_server_renegotiation_info.h" +#include "tls/extensions/s2n_server_alpn.h" +#include "tls/extensions/s2n_server_status_request.h" +#include "tls/extensions/s2n_server_sct_list.h" +#include "tls/extensions/s2n_server_max_fragment_length.h" +#include "tls/extensions/s2n_server_session_ticket.h" +#include "tls/extensions/s2n_server_server_name.h" +#include "tls/extensions/s2n_server_signature_algorithms.h" +#include "tls/extensions/s2n_server_supported_versions.h" +#include "tls/extensions/s2n_server_key_share.h" + +static const s2n_extension_type *const client_hello_extensions[] = { + &s2n_client_supported_versions_extension, + &s2n_client_key_share_extension, + &s2n_client_signature_algorithms_extension, + &s2n_client_server_name_extension, + &s2n_client_alpn_extension, + &s2n_client_status_request_extension, + &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_client_psk_extension /* MUST be last */ +}; + +static const s2n_extension_type *const tls12_server_hello_extensions[] = { + &s2n_server_supported_versions_extension, + &s2n_server_server_name_extension, + &s2n_server_ec_point_format_extension, + &s2n_server_renegotiation_info_extension, + &s2n_server_alpn_extension, + &s2n_server_status_request_extension, + &s2n_server_sct_list_extension, + &s2n_server_max_fragment_length_extension, + &s2n_server_session_ticket_extension, +}; + +static const s2n_extension_type *const tls13_server_hello_extensions[] = { + &s2n_server_supported_versions_extension, + &s2n_server_key_share_extension, + &s2n_server_cookie_extension, +}; + +static const s2n_extension_type *const encrypted_extensions[] = { + &s2n_server_server_name_extension, + &s2n_server_max_fragment_length_extension, + &s2n_server_alpn_extension, + &s2n_quic_transport_parameters_extension, +}; + +static const s2n_extension_type *const cert_req_extensions[] = { + &s2n_server_signature_algorithms_extension, +}; + +static const s2n_extension_type *const certificate_extensions[] = { + &s2n_tls13_server_status_request_extension, + &s2n_server_sct_list_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_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_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)); + + *extension_list = &extension_lists[list_type]; + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.h index d57cfa2988..114f6ae75e 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_extension_type_lists.h @@ -1,26 +1,26 @@ -/* - * 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_list.h" -#include "tls/extensions/s2n_extension_type.h" - -typedef struct { - const s2n_extension_type *const *extension_types; - const uint8_t count; -} s2n_extension_type_list; - -int s2n_extension_type_list_get(s2n_extension_list_id list_type, s2n_extension_type_list **extension_type_list); +/* + * 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_list.h" +#include "tls/extensions/s2n_extension_type.h" + +typedef struct { + const s2n_extension_type *const *extension_types; + const uint8_t count; +} s2n_extension_type_list; + +int s2n_extension_type_list_get(s2n_extension_list_id list_type, s2n_extension_type_list **extension_type_list); 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 0b64096b2f..a91dbfd30b 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.c @@ -1,33 +1,33 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "tls/extensions/s2n_key_share.h" -#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) -{ - notnull_check(out); - notnull_check(ecc_evp_params); - notnull_check(ecc_evp_params->negotiated_curve); - - 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)); - - GUARD(s2n_ecc_evp_generate_ephemeral_key(ecc_evp_params)); - GUARD(s2n_ecc_evp_write_params_point(ecc_evp_params, out)); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "tls/extensions/s2n_key_share.h" +#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) +{ + notnull_check(out); + notnull_check(ecc_evp_params); + notnull_check(ecc_evp_params->negotiated_curve); + + 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)); + + GUARD(s2n_ecc_evp_generate_ephemeral_key(ecc_evp_params)); + GUARD(s2n_ecc_evp_write_params_point(ecc_evp_params, out)); + + return 0; +} 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 a29fdd3806..f621d76b52 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_key_share.h @@ -1,28 +1,28 @@ -/* - * 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 "crypto/s2n_ecc_evp.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -#define S2N_SIZE_OF_EXTENSION_TYPE 2 -#define S2N_SIZE_OF_EXTENSION_DATA_SIZE 2 -#define S2N_SIZE_OF_CLIENT_SHARES_SIZE 2 -#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); +/* + * 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 "crypto/s2n_ecc_evp.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +#define S2N_SIZE_OF_EXTENSION_TYPE 2 +#define S2N_SIZE_OF_EXTENSION_DATA_SIZE 2 +#define S2N_SIZE_OF_CLIENT_SHARES_SIZE 2 +#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); 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 9b6fa1bee3..56f17abc3b 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 @@ -1,77 +1,77 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "tls/extensions/s2n_quic_transport_params.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" - -#include "stuffer/s2n_stuffer.h" -#include "utils/s2n_safety.h" - -/* - * The quic_transport_params extension is required by the QUIC protocol to - * negotiate additional connection parameters when using S2N. - * - * This extension should not be sent or received unless using S2N with QUIC. - * S2N treats the extension data as opaque bytes and performs no validation. - */ - -static bool s2n_quic_transport_params_should_send(struct s2n_connection *conn) -{ - return conn && conn->config && conn->config->quic_enabled; -} - -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); - return S2N_SUCCESS; -} - -static int s2n_quic_transport_params_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - notnull_check(conn); - notnull_check(out); - - if (conn->our_quic_transport_parameters.size) { - 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); - - 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)); - } - return S2N_SUCCESS; -} - -const s2n_extension_type s2n_quic_transport_parameters_extension = { - .iana_value = TLS_QUIC_TRANSPORT_PARAMETERS, - .is_response = false, - .send = s2n_quic_transport_params_send, - .recv = s2n_quic_transport_params_recv, - .should_send = s2n_quic_transport_params_should_send, - .if_missing = s2n_quic_transport_params_if_missing, -}; +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "tls/extensions/s2n_quic_transport_params.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" + +#include "stuffer/s2n_stuffer.h" +#include "utils/s2n_safety.h" + +/* + * The quic_transport_params extension is required by the QUIC protocol to + * negotiate additional connection parameters when using S2N. + * + * This extension should not be sent or received unless using S2N with QUIC. + * S2N treats the extension data as opaque bytes and performs no validation. + */ + +static bool s2n_quic_transport_params_should_send(struct s2n_connection *conn) +{ + return conn && conn->config && conn->config->quic_enabled; +} + +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); + return S2N_SUCCESS; +} + +static int s2n_quic_transport_params_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + notnull_check(conn); + notnull_check(out); + + if (conn->our_quic_transport_parameters.size) { + 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); + + 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)); + } + return S2N_SUCCESS; +} + +const s2n_extension_type s2n_quic_transport_parameters_extension = { + .iana_value = TLS_QUIC_TRANSPORT_PARAMETERS, + .is_response = false, + .send = s2n_quic_transport_params_send, + .recv = s2n_quic_transport_params_recv, + .should_send = s2n_quic_transport_params_should_send, + .if_missing = s2n_quic_transport_params_if_missing, +}; diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.h index ed0a73d140..93369b5478 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_quic_transport_params.h @@ -1,20 +1,20 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" - -extern const s2n_extension_type s2n_quic_transport_parameters_extension; +/* + * 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_quic_transport_parameters_extension; diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c index 50dbcf11f9..a1f5ac17cf 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.c @@ -1,81 +1,81 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_safety.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" - -#include "tls/extensions/s2n_server_alpn.h" - -static bool s2n_alpn_should_send(struct s2n_connection *conn); -static int s2n_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_server_alpn_extension = { - .iana_value = TLS_EXTENSION_ALPN, - .is_response = true, - .send = s2n_alpn_send, - .recv = s2n_alpn_recv, - .should_send = s2n_alpn_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_alpn_should_send(struct s2n_connection *conn) -{ - return conn && strlen(conn->application_protocol) > 0; -} - -static int s2n_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - notnull_check(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))); - - /* 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)); - - return S2N_SUCCESS; -} - -static int s2n_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - notnull_check(conn); - - uint16_t size_of_all; - 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)); - - uint8_t *protocol = s2n_stuffer_raw_read(extension, protocol_len); - notnull_check(protocol); - - /* copy the first protocol name */ - memcpy_check(conn->application_protocol, protocol, protocol_len); - conn->application_protocol[protocol_len] = '\0'; - - return S2N_SUCCESS; -} +/* + * 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 "stuffer/s2n_stuffer.h" + +#include "utils/s2n_safety.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" + +#include "tls/extensions/s2n_server_alpn.h" + +static bool s2n_alpn_should_send(struct s2n_connection *conn); +static int s2n_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_server_alpn_extension = { + .iana_value = TLS_EXTENSION_ALPN, + .is_response = true, + .send = s2n_alpn_send, + .recv = s2n_alpn_recv, + .should_send = s2n_alpn_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_alpn_should_send(struct s2n_connection *conn) +{ + return conn && strlen(conn->application_protocol) > 0; +} + +static int s2n_alpn_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + notnull_check(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))); + + /* 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)); + + return S2N_SUCCESS; +} + +static int s2n_alpn_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + notnull_check(conn); + + uint16_t size_of_all; + 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)); + + uint8_t *protocol = s2n_stuffer_raw_read(extension, protocol_len); + notnull_check(protocol); + + /* copy the first protocol name */ + memcpy_check(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_alpn.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.h index 5e5564dd54..ccdf3fce9c 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_alpn.h @@ -1,20 +1,20 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" - -extern const s2n_extension_type s2n_server_alpn_extension; +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" + +extern const s2n_extension_type s2n_server_alpn_extension; 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 a362b446af..486835689c 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 @@ -1,80 +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 "tls/s2n_config.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_x509_validator.h" -#include "tls/extensions/s2n_server_certificate_status.h" -#include "utils/s2n_safety.h" - -#define U24_SIZE 3 - -/* In TLS 1.3, a response to a Status Request extension is sent as an extension with - * status request as well as the OCSP response. This contrasts to TLS 1.2 where - * the OCSP response is sent in the Certificate Status handshake message */ - -static bool s2n_tls13_server_status_request_should_send(struct s2n_connection *conn); - -const s2n_extension_type s2n_tls13_server_status_request_extension = { - .iana_value = TLS_EXTENSION_STATUS_REQUEST, - .is_response = true, - .send = s2n_server_certificate_status_send, - .recv = s2n_server_certificate_status_recv, - .should_send = s2n_tls13_server_status_request_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_tls13_server_status_request_should_send(struct s2n_connection *conn) -{ - return s2n_server_can_send_ocsp(conn); -} - -int s2n_server_certificate_status_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - notnull_check(conn); - struct s2n_blob *ocsp_status = &conn->handshake_params.our_chain_and_key->ocsp_status; - notnull_check(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)); - - return S2N_SUCCESS; -} - -int s2n_server_certificate_status_recv(struct s2n_connection *conn, struct s2n_stuffer *in) -{ - notnull_check(conn); - - uint8_t type; - GUARD(s2n_stuffer_read_uint8(in, &type)); - if (type != S2N_STATUS_REQUEST_OCSP) { - /* We only support OCSP */ - return S2N_SUCCESS; - } - - uint32_t status_size; - GUARD(s2n_stuffer_read_uint24(in, &status_size)); - lte_check(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)); - - GUARD(s2n_x509_validator_validate_cert_stapled_ocsp_response( - &conn->x509_validator, conn, conn->status_response.data, conn->status_response.size)); - - return S2N_SUCCESS; -} +/* + * 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_config.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_x509_validator.h" +#include "tls/extensions/s2n_server_certificate_status.h" +#include "utils/s2n_safety.h" + +#define U24_SIZE 3 + +/* In TLS 1.3, a response to a Status Request extension is sent as an extension with + * status request as well as the OCSP response. This contrasts to TLS 1.2 where + * the OCSP response is sent in the Certificate Status handshake message */ + +static bool s2n_tls13_server_status_request_should_send(struct s2n_connection *conn); + +const s2n_extension_type s2n_tls13_server_status_request_extension = { + .iana_value = TLS_EXTENSION_STATUS_REQUEST, + .is_response = true, + .send = s2n_server_certificate_status_send, + .recv = s2n_server_certificate_status_recv, + .should_send = s2n_tls13_server_status_request_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_tls13_server_status_request_should_send(struct s2n_connection *conn) +{ + return s2n_server_can_send_ocsp(conn); +} + +int s2n_server_certificate_status_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + notnull_check(conn); + struct s2n_blob *ocsp_status = &conn->handshake_params.our_chain_and_key->ocsp_status; + notnull_check(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)); + + return S2N_SUCCESS; +} + +int s2n_server_certificate_status_recv(struct s2n_connection *conn, struct s2n_stuffer *in) +{ + notnull_check(conn); + + uint8_t type; + GUARD(s2n_stuffer_read_uint8(in, &type)); + if (type != S2N_STATUS_REQUEST_OCSP) { + /* We only support OCSP */ + return S2N_SUCCESS; + } + + uint32_t status_size; + GUARD(s2n_stuffer_read_uint24(in, &status_size)); + lte_check(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)); + + GUARD(s2n_x509_validator_validate_cert_stapled_ocsp_response( + &conn->x509_validator, conn, conn->status_response.data, conn->status_response.size)); + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.h index ad5d1f380f..0f5ef18742 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_certificate_status.h @@ -1,25 +1,25 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_tls13_server_status_request_extension; - -int s2n_server_certificate_status_send(struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_server_certificate_status_recv(struct s2n_connection *conn, struct s2n_stuffer *in); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_tls13_server_status_request_extension; + +int s2n_server_certificate_status_send(struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_server_certificate_status_recv(struct s2n_connection *conn, struct s2n_stuffer *in); 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 5203e7db57..af112de0f4 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 @@ -1,430 +1,430 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "tls/extensions/s2n_server_key_share.h" -#include "tls/s2n_security_policies.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls13.h" - -#include "utils/s2n_safety.h" - -#include "crypto/s2n_fips.h" - -static int s2n_server_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_server_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_server_key_share_extension = { - .iana_value = TLS_EXTENSION_KEY_SHARE, - .is_response = false, - .send = s2n_server_key_share_send, - .recv = s2n_server_key_share_recv, - .should_send = s2n_extension_send_if_tls13_connection, - .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); - - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); - - struct s2n_kem_group_params *server_kem_group_params = &conn->secure.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)); - - struct s2n_stuffer_reservation total_share_size = { 0 }; - 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); - /* 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)); - - 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); - - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); - - 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); - - const struct s2n_kem_group *server_kem_group = conn->secure.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); - - ENSURE_POSIX(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); - - 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); - - 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); - - 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); - - const struct s2n_ecc_preferences *ecc_pref = NULL; - GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); - notnull_check(ecc_pref); - - const struct s2n_ecc_named_curve *server_curve = conn->secure.server_ecc_evp_params.negotiated_curve; - notnull_check(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); - - return S2N_SUCCESS; -} - -static int s2n_server_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out) { - notnull_check(conn); - notnull_check(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; - - /* 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); - - /* Retry requests only require the selected named group, not an actual share. - * https://tools.ietf.org/html/rfc8446#section-4.2.8 */ - if (s2n_is_hello_retry_message(conn)) { - uint16_t named_group_id; - if (curve != NULL) { - named_group_id = curve->iana_id; - } else { - named_group_id = kem_group->iana_id; - } - - 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)); - } else { - GUARD(s2n_server_key_share_send_check_pq_hybrid(conn)); - GUARD(s2n_server_key_share_generate_pq_hybrid(conn, out)); - } - - return S2N_SUCCESS; -} - -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); - - /* If in FIPS mode, the client should not have sent any PQ IDs - * in the supported_groups list of the initial ClientHello */ - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); - - const struct s2n_kem_preferences *kem_pref = NULL; - GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); - notnull_check(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); - - size_t kem_group_index = 0; - for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) { - if (named_group_iana == kem_pref->tls13_kem_groups[i]->iana_id) { - kem_group_index = i; - break; - } - } - - struct s2n_kem_group_params *server_kem_group_params = &conn->secure.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; - - /* If this a HRR, the server will only have sent the named group ID. We assign the - * appropriate KEM group params above, then exit early so that the client can - * generate the correct key share. */ - if (s2n_is_hello_retry_message(conn)) { - return S2N_SUCCESS; - } - - /* 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]; - - 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); - - /* 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); - - /* Parse the PQ KEM key share */ - ENSURE_POSIX(s2n_kem_recv_ciphertext(extension, &conn->secure.chosen_client_kem_group_params->kem_params) == S2N_SUCCESS, - S2N_ERR_BAD_KEY_SHARE); - - return S2N_SUCCESS; -} - -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); - - const struct s2n_ecc_preferences *ecc_pref = NULL; - GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); - notnull_check(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), - S2N_ERR_ECDHE_UNSUPPORTED_CURVE); - - size_t supported_curve_index = 0; - - for (size_t i = 0; i < ecc_pref->count; i++) { - if (named_group_iana == ecc_pref->ecc_curves[i]->iana_id) { - supported_curve_index = i; - break; - } - } - - struct s2n_ecc_evp_params *server_ecc_evp_params = &conn->secure.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. - * Set the server negotiated curve and exit early so a proper keyshare can be generated. */ - if (s2n_is_hello_retry_message(conn)) { - 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); - - 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)); - S2N_ERROR_IF(s2n_stuffer_data_available(extension) < share_size, S2N_ERR_BAD_KEY_SHARE); - - /* Proceed to parse share */ - struct s2n_blob point_blob; - S2N_ERROR_IF(s2n_ecc_evp_read_params_point(extension, share_size, &point_blob) < 0, S2N_ERR_BAD_KEY_SHARE); - S2N_ERROR_IF(s2n_ecc_evp_parse_params_point(&point_blob, server_ecc_evp_params) < 0, S2N_ERR_BAD_KEY_SHARE); - S2N_ERROR_IF(server_ecc_evp_params->evp_pkey == NULL, S2N_ERR_BAD_KEY_SHARE); - - return S2N_SUCCESS; -} - -/* - * From https://tools.ietf.org/html/rfc8446#section-4.2.8 - * - * If using (EC)DHE key establishment, servers offer exactly one - * KeyShareEntry in the ServerHello. This value MUST be in the same - * group as the KeyShareEntry value offered by the client that the - * server has selected for the negotiated key exchange. - */ -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); - - 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)); - - const struct s2n_kem_preferences *kem_pref = NULL; - GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); - notnull_check(kem_pref); - - const struct s2n_ecc_preferences *ecc_pref = NULL; - GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); - notnull_check(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)); - } 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)); - } else { - S2N_ERROR(S2N_ERR_ECDHE_UNSUPPORTED_CURVE); - } - - return S2N_SUCCESS; -} - -/* 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); - - 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); - - /* Boolean XOR check. When receiving the supported_groups extension, s2n server - * should (exclusively) set either server_curve or server_kem_group based on the - * set of mutually supported groups. If both server_curve and server_kem_group - * are NULL, it is because client and server do not share any mutually supported - * 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); - - /* 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); - - 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->secure.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; - } - } - - /* 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)); - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -/* - * Calculate the data length for Server Key Share extension - * based on negotiated_curve selected in server_ecc_evp_params. - * - * Retry requests have a different key share format, - * https://tools.ietf.org/html/rfc8446#section-4.2.8 - * - * This functions does not error, but s2n_extensions_server_key_share_send() would - */ -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; - int key_share_size = S2N_SIZE_OF_EXTENSION_TYPE - + S2N_SIZE_OF_EXTENSION_DATA_SIZE - + S2N_SIZE_OF_NAMED_GROUP; - - /* If this is a KeyShareHelloRetryRequest we don't include the share size */ - if (s2n_is_hello_retry_message(conn)) { - return key_share_size; - } - - if (curve == NULL) { - return 0; - } - - /* If this is a full KeyShareEntry, include the share size */ - key_share_size += (S2N_SIZE_OF_KEY_SHARE_SIZE + curve->share_size); - - return key_share_size; -} - -/* - * Sends Key Share extension in Server Hello. - * - * Expects negotiated_curve to be set and generates a ephemeral key for key sharing - */ -int s2n_extensions_server_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_server_key_share_extension, conn, out); -} - -/* - * Client receives a Server Hello key share. - * - * If the curve is supported, conn->secure.server_ecc_evp_params will be set. - */ -int s2n_extensions_server_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_server_key_share_extension, conn, extension); -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "tls/extensions/s2n_server_key_share.h" +#include "tls/s2n_security_policies.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls13.h" + +#include "utils/s2n_safety.h" + +#include "crypto/s2n_fips.h" + +static int s2n_server_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_server_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_server_key_share_extension = { + .iana_value = TLS_EXTENSION_KEY_SHARE, + .is_response = false, + .send = s2n_server_key_share_send, + .recv = s2n_server_key_share_recv, + .should_send = s2n_extension_send_if_tls13_connection, + .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); + + ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + + struct s2n_kem_group_params *server_kem_group_params = &conn->secure.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)); + + struct s2n_stuffer_reservation total_share_size = { 0 }; + 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); + /* 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)); + + 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); + + ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + + 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); + + const struct s2n_kem_group *server_kem_group = conn->secure.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); + + ENSURE_POSIX(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); + + 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); + + 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); + + 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); + + const struct s2n_ecc_preferences *ecc_pref = NULL; + GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); + notnull_check(ecc_pref); + + const struct s2n_ecc_named_curve *server_curve = conn->secure.server_ecc_evp_params.negotiated_curve; + notnull_check(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); + + return S2N_SUCCESS; +} + +static int s2n_server_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out) { + notnull_check(conn); + notnull_check(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; + + /* 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); + + /* Retry requests only require the selected named group, not an actual share. + * https://tools.ietf.org/html/rfc8446#section-4.2.8 */ + if (s2n_is_hello_retry_message(conn)) { + uint16_t named_group_id; + if (curve != NULL) { + named_group_id = curve->iana_id; + } else { + named_group_id = kem_group->iana_id; + } + + 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)); + } else { + GUARD(s2n_server_key_share_send_check_pq_hybrid(conn)); + GUARD(s2n_server_key_share_generate_pq_hybrid(conn, out)); + } + + return S2N_SUCCESS; +} + +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); + + /* If in FIPS mode, the client should not have sent any PQ IDs + * in the supported_groups list of the initial ClientHello */ + ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + + const struct s2n_kem_preferences *kem_pref = NULL; + GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); + notnull_check(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); + + size_t kem_group_index = 0; + for (size_t i = 0; i < kem_pref->tls13_kem_group_count; i++) { + if (named_group_iana == kem_pref->tls13_kem_groups[i]->iana_id) { + kem_group_index = i; + break; + } + } + + struct s2n_kem_group_params *server_kem_group_params = &conn->secure.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; + + /* If this a HRR, the server will only have sent the named group ID. We assign the + * appropriate KEM group params above, then exit early so that the client can + * generate the correct key share. */ + if (s2n_is_hello_retry_message(conn)) { + return S2N_SUCCESS; + } + + /* 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]; + + 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); + + /* 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); + + /* Parse the PQ KEM key share */ + ENSURE_POSIX(s2n_kem_recv_ciphertext(extension, &conn->secure.chosen_client_kem_group_params->kem_params) == S2N_SUCCESS, + S2N_ERR_BAD_KEY_SHARE); + + return S2N_SUCCESS; +} + +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); + + const struct s2n_ecc_preferences *ecc_pref = NULL; + GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); + notnull_check(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), + S2N_ERR_ECDHE_UNSUPPORTED_CURVE); + + size_t supported_curve_index = 0; + + for (size_t i = 0; i < ecc_pref->count; i++) { + if (named_group_iana == ecc_pref->ecc_curves[i]->iana_id) { + supported_curve_index = i; + break; + } + } + + struct s2n_ecc_evp_params *server_ecc_evp_params = &conn->secure.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. + * Set the server negotiated curve and exit early so a proper keyshare can be generated. */ + if (s2n_is_hello_retry_message(conn)) { + 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); + + 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)); + S2N_ERROR_IF(s2n_stuffer_data_available(extension) < share_size, S2N_ERR_BAD_KEY_SHARE); + + /* Proceed to parse share */ + struct s2n_blob point_blob; + S2N_ERROR_IF(s2n_ecc_evp_read_params_point(extension, share_size, &point_blob) < 0, S2N_ERR_BAD_KEY_SHARE); + S2N_ERROR_IF(s2n_ecc_evp_parse_params_point(&point_blob, server_ecc_evp_params) < 0, S2N_ERR_BAD_KEY_SHARE); + S2N_ERROR_IF(server_ecc_evp_params->evp_pkey == NULL, S2N_ERR_BAD_KEY_SHARE); + + return S2N_SUCCESS; +} + +/* + * From https://tools.ietf.org/html/rfc8446#section-4.2.8 + * + * If using (EC)DHE key establishment, servers offer exactly one + * KeyShareEntry in the ServerHello. This value MUST be in the same + * group as the KeyShareEntry value offered by the client that the + * server has selected for the negotiated key exchange. + */ +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); + + 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)); + + const struct s2n_kem_preferences *kem_pref = NULL; + GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref)); + notnull_check(kem_pref); + + const struct s2n_ecc_preferences *ecc_pref = NULL; + GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); + notnull_check(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)); + } 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)); + } else { + S2N_ERROR(S2N_ERR_ECDHE_UNSUPPORTED_CURVE); + } + + return S2N_SUCCESS; +} + +/* 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); + + 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); + + /* Boolean XOR check. When receiving the supported_groups extension, s2n server + * should (exclusively) set either server_curve or server_kem_group based on the + * set of mutually supported groups. If both server_curve and server_kem_group + * are NULL, it is because client and server do not share any mutually supported + * 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); + + /* 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); + + 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->secure.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; + } + } + + /* 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)); + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +/* + * Calculate the data length for Server Key Share extension + * based on negotiated_curve selected in server_ecc_evp_params. + * + * Retry requests have a different key share format, + * https://tools.ietf.org/html/rfc8446#section-4.2.8 + * + * This functions does not error, but s2n_extensions_server_key_share_send() would + */ +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; + int key_share_size = S2N_SIZE_OF_EXTENSION_TYPE + + S2N_SIZE_OF_EXTENSION_DATA_SIZE + + S2N_SIZE_OF_NAMED_GROUP; + + /* If this is a KeyShareHelloRetryRequest we don't include the share size */ + if (s2n_is_hello_retry_message(conn)) { + return key_share_size; + } + + if (curve == NULL) { + return 0; + } + + /* If this is a full KeyShareEntry, include the share size */ + key_share_size += (S2N_SIZE_OF_KEY_SHARE_SIZE + curve->share_size); + + return key_share_size; +} + +/* + * Sends Key Share extension in Server Hello. + * + * Expects negotiated_curve to be set and generates a ephemeral key for key sharing + */ +int s2n_extensions_server_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_server_key_share_extension, conn, out); +} + +/* + * Client receives a Server Hello key share. + * + * If the curve is supported, conn->secure.server_ecc_evp_params will be set. + */ +int s2n_extensions_server_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_server_key_share_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.h index afc1589a18..11a289d1de 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_key_share.h @@ -1,30 +1,30 @@ -/* - * 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_connection.h" -#include "stuffer/s2n_stuffer.h" - -#include "tls/extensions/s2n_key_share.h" - -extern const s2n_extension_type s2n_server_key_share_extension; - -extern int s2n_extensions_server_key_share_select(struct s2n_connection *conn); - -/* Old-style extension functions -- remove after extensions refactor is complete */ -extern int s2n_extensions_server_key_share_send_size(struct s2n_connection *conn); -extern int s2n_extensions_server_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out); -extern int s2n_extensions_server_key_share_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * 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_connection.h" +#include "stuffer/s2n_stuffer.h" + +#include "tls/extensions/s2n_key_share.h" + +extern const s2n_extension_type s2n_server_key_share_extension; + +extern int s2n_extensions_server_key_share_select(struct s2n_connection *conn); + +/* Old-style extension functions -- remove after extensions refactor is complete */ +extern int s2n_extensions_server_key_share_send_size(struct s2n_connection *conn); +extern int s2n_extensions_server_key_share_send(struct s2n_connection *conn, struct s2n_stuffer *out); +extern 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 65a0c611dc..69b1530e54 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 @@ -1,61 +1,61 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "error/s2n_errno.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_safety.h" - -#include "tls/s2n_tls_parameters.h" -#include "tls/s2n_connection.h" - -#include "tls/extensions/s2n_server_max_fragment_length.h" - -static bool s2n_max_fragment_length_should_send(struct s2n_connection *conn); -static int s2n_max_fragment_length_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_max_fragment_length_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_server_max_fragment_length_extension = { - .iana_value = TLS_EXTENSION_MAX_FRAG_LEN, - .is_response = true, - .send = s2n_max_fragment_length_send, - .recv = s2n_max_fragment_length_recv, - .should_send = s2n_max_fragment_length_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_max_fragment_length_should_send(struct s2n_connection *conn) -{ - return conn && conn->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)); - 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); - - uint8_t mfl_code; - GUARD(s2n_stuffer_read_uint8(extension, &mfl_code)); - S2N_ERROR_IF(mfl_code != conn->config->mfl_code, S2N_ERR_MAX_FRAG_LEN_MISMATCH); - return S2N_SUCCESS; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "error/s2n_errno.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_safety.h" + +#include "tls/s2n_tls_parameters.h" +#include "tls/s2n_connection.h" + +#include "tls/extensions/s2n_server_max_fragment_length.h" + +static bool s2n_max_fragment_length_should_send(struct s2n_connection *conn); +static int s2n_max_fragment_length_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_max_fragment_length_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_server_max_fragment_length_extension = { + .iana_value = TLS_EXTENSION_MAX_FRAG_LEN, + .is_response = true, + .send = s2n_max_fragment_length_send, + .recv = s2n_max_fragment_length_recv, + .should_send = s2n_max_fragment_length_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_max_fragment_length_should_send(struct s2n_connection *conn) +{ + return conn && conn->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)); + 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); + + uint8_t mfl_code; + GUARD(s2n_stuffer_read_uint8(extension, &mfl_code)); + S2N_ERROR_IF(mfl_code != conn->config->mfl_code, S2N_ERR_MAX_FRAG_LEN_MISMATCH); + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_max_fragment_length.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_max_fragment_length.h index 57211c20b8..8a8ae81ad1 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_max_fragment_length.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_max_fragment_length.h @@ -1,20 +1,20 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" - -extern const s2n_extension_type s2n_server_max_fragment_length_extension; +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" + +extern const s2n_extension_type s2n_server_max_fragment_length_extension; diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.c index f7d4ee7c97..aac791c43c 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 @@ -1,87 +1,87 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "error/s2n_errno.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_safety.h" - -#include "tls/s2n_tls_parameters.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" -#include "tls/extensions/s2n_server_renegotiation_info.h" - -static bool s2n_renegotiation_info_should_send(struct s2n_connection *conn); -static int s2n_renegotiation_info_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_renegotiation_info_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_server_renegotiation_info_extension = { - .iana_value = TLS_EXTENSION_RENEGOTIATION_INFO, - .is_response = false, - .send = s2n_renegotiation_info_send, - .recv = s2n_renegotiation_info_recv, - .should_send = s2n_renegotiation_info_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_renegotiation_info_should_send(struct s2n_connection *conn) -{ - return conn && conn->secure_renegotiation && s2n_connection_get_protocol_version(conn) < S2N_TLS13; -} - -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)); - return S2N_SUCCESS; -} - -static int s2n_renegotiation_info_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - /* RFC5746 Section 3.4: The client MUST then verify that the length of - * the "renegotiated_connection" field is zero, and if it is not, MUST - * abort the handshake. */ - uint8_t renegotiated_connection_len; - 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); - conn->secure_renegotiation = 1; - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_recv_server_renegotiation_info_ext(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_server_renegotiation_info_extension, conn, extension); -} - -int s2n_send_server_renegotiation_info_ext(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_server_renegotiation_info_extension, conn, out); -} - -int s2n_server_renegotiation_info_ext_size(struct s2n_connection *conn) -{ - if (s2n_renegotiation_info_should_send(conn)) { - /* 2 for ext type, 2 for extension length, 1 for value of 0 */ - return 5; - } - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "error/s2n_errno.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_safety.h" + +#include "tls/s2n_tls_parameters.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" +#include "tls/extensions/s2n_server_renegotiation_info.h" + +static bool s2n_renegotiation_info_should_send(struct s2n_connection *conn); +static int s2n_renegotiation_info_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_renegotiation_info_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_server_renegotiation_info_extension = { + .iana_value = TLS_EXTENSION_RENEGOTIATION_INFO, + .is_response = false, + .send = s2n_renegotiation_info_send, + .recv = s2n_renegotiation_info_recv, + .should_send = s2n_renegotiation_info_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_renegotiation_info_should_send(struct s2n_connection *conn) +{ + return conn && conn->secure_renegotiation && s2n_connection_get_protocol_version(conn) < S2N_TLS13; +} + +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)); + return S2N_SUCCESS; +} + +static int s2n_renegotiation_info_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + /* RFC5746 Section 3.4: The client MUST then verify that the length of + * the "renegotiated_connection" field is zero, and if it is not, MUST + * abort the handshake. */ + uint8_t renegotiated_connection_len; + 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); + conn->secure_renegotiation = 1; + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_recv_server_renegotiation_info_ext(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_server_renegotiation_info_extension, conn, extension); +} + +int s2n_send_server_renegotiation_info_ext(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_server_renegotiation_info_extension, conn, out); +} + +int s2n_server_renegotiation_info_ext_size(struct s2n_connection *conn) +{ + if (s2n_renegotiation_info_should_send(conn)) { + /* 2 for ext type, 2 for extension length, 1 for value of 0 */ + return 5; + } + + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.h index 3fd0f128e9..b037b2182a 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_renegotiation_info.h @@ -1,27 +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 "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_server_renegotiation_info_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -int s2n_recv_server_renegotiation_info_ext(struct s2n_connection *conn, struct s2n_stuffer *extension); -int s2n_send_server_renegotiation_info_ext(struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_server_renegotiation_info_ext_size(struct s2n_connection *conn); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_server_renegotiation_info_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +int s2n_recv_server_renegotiation_info_ext(struct s2n_connection *conn, struct s2n_stuffer *extension); +int s2n_send_server_renegotiation_info_ext(struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_server_renegotiation_info_ext_size(struct s2n_connection *conn); 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 88b2cf7837..8a8158aecf 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 @@ -1,67 +1,67 @@ -/* - * 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 "stuffer/s2n_stuffer.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" -#include "tls/extensions/s2n_server_sct_list.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_blob.h" - -static bool s2n_server_sct_list_should_send(struct s2n_connection *conn); -static int s2n_server_sct_list_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_server_sct_list_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_server_sct_list_extension = { - .iana_value = TLS_EXTENSION_SCT_LIST, - .is_response = true, - .send = s2n_server_sct_list_send, - .recv = s2n_server_sct_list_recv, - .should_send = s2n_server_sct_list_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_server_sct_list_should_send(struct s2n_connection *conn) -{ - return s2n_server_can_send_sct_list(conn); -} - -int s2n_server_sct_list_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - notnull_check(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)); - - return S2N_SUCCESS; -} - -int s2n_server_sct_list_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - notnull_check(conn); - - struct s2n_blob sct_list; - size_t data_available = s2n_stuffer_data_available(extension); - GUARD(s2n_blob_init(&sct_list, - s2n_stuffer_raw_read(extension, data_available), - data_available)); - notnull_check(sct_list.data); - - GUARD(s2n_dup(&sct_list, &conn->ct_response)); - - return S2N_SUCCESS; -} +/* + * 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 "stuffer/s2n_stuffer.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" +#include "tls/extensions/s2n_server_sct_list.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_blob.h" + +static bool s2n_server_sct_list_should_send(struct s2n_connection *conn); +static int s2n_server_sct_list_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_server_sct_list_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_server_sct_list_extension = { + .iana_value = TLS_EXTENSION_SCT_LIST, + .is_response = true, + .send = s2n_server_sct_list_send, + .recv = s2n_server_sct_list_recv, + .should_send = s2n_server_sct_list_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_server_sct_list_should_send(struct s2n_connection *conn) +{ + return s2n_server_can_send_sct_list(conn); +} + +int s2n_server_sct_list_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + notnull_check(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)); + + return S2N_SUCCESS; +} + +int s2n_server_sct_list_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + notnull_check(conn); + + struct s2n_blob sct_list; + size_t data_available = s2n_stuffer_data_available(extension); + GUARD(s2n_blob_init(&sct_list, + s2n_stuffer_raw_read(extension, data_available), + data_available)); + notnull_check(sct_list.data); + + GUARD(s2n_dup(&sct_list, &conn->ct_response)); + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_sct_list.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_sct_list.h index 08dd86fdb8..2632c76238 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_sct_list.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_sct_list.h @@ -1,20 +1,20 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" - -extern const s2n_extension_type s2n_server_sct_list_extension; +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" + +extern const s2n_extension_type s2n_server_sct_list_extension; 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 22e0b03cd7..158a9eae6c 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 @@ -1,51 +1,51 @@ -/* - * 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 "stuffer/s2n_stuffer.h" - -#include "tls/s2n_connection.h" -#include "tls/extensions/s2n_server_server_name.h" - -static bool s2n_server_name_should_send(struct s2n_connection *conn); -static int s2n_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_server_server_name_extension = { - .iana_value = TLS_EXTENSION_SERVER_NAME, - .is_response = true, - .send = s2n_server_name_send, - .recv = s2n_server_name_recv, - .should_send = s2n_server_name_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_server_name_should_send(struct s2n_connection *conn) -{ - return conn && conn->server_name_used && !s2n_connection_is_session_resumed(conn); -} - -static int s2n_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - /* Write nothing. The extension just needs to exist. */ - return S2N_SUCCESS; -} - -static int s2n_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - notnull_check(conn); - /* Read nothing. The extension just needs to exist. */ - conn->server_name_used = 1; - return S2N_SUCCESS; -} +/* + * 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 "stuffer/s2n_stuffer.h" + +#include "tls/s2n_connection.h" +#include "tls/extensions/s2n_server_server_name.h" + +static bool s2n_server_name_should_send(struct s2n_connection *conn); +static int s2n_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_server_server_name_extension = { + .iana_value = TLS_EXTENSION_SERVER_NAME, + .is_response = true, + .send = s2n_server_name_send, + .recv = s2n_server_name_recv, + .should_send = s2n_server_name_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_server_name_should_send(struct s2n_connection *conn) +{ + return conn && conn->server_name_used && !s2n_connection_is_session_resumed(conn); +} + +static int s2n_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + /* Write nothing. The extension just needs to exist. */ + return S2N_SUCCESS; +} + +static int s2n_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + notnull_check(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_server_name.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_server_name.h index 2519dfcd18..8ed13d3084 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_server_name.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_server_name.h @@ -1,20 +1,20 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" - -extern const s2n_extension_type s2n_server_server_name_extension; +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" + +extern const s2n_extension_type s2n_server_server_name_extension; 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 02a52c6cf7..74875f05a6 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 @@ -1,68 +1,68 @@ -/* - * 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 "stuffer/s2n_stuffer.h" - -#include "tls/s2n_tls_parameters.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" -#include "tls/extensions/s2n_server_session_ticket.h" - -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); - -const s2n_extension_type s2n_server_session_ticket_extension = { - .iana_value = TLS_EXTENSION_SESSION_TICKET, - .is_response = true, - .send = s2n_extension_send_noop, - .recv = s2n_session_ticket_recv, - .should_send = s2n_session_ticket_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_session_ticket_should_send(struct s2n_connection *conn) -{ - return s2n_server_sending_nst(conn) && s2n_connection_get_protocol_version(conn) < S2N_TLS13; -} - -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); - conn->session_ticket_status = S2N_NEW_TICKET; - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_recv_server_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_server_session_ticket_extension, conn, extension); -} - -int s2n_send_server_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_server_session_ticket_extension, conn, out); -} - -int s2n_server_session_ticket_ext_size(struct s2n_connection *conn) -{ - if (s2n_session_ticket_should_send(conn)) { - /* 2 for extension type. 2 for extension length of 0 */ - return 4; - } - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "stuffer/s2n_stuffer.h" + +#include "tls/s2n_tls_parameters.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" +#include "tls/extensions/s2n_server_session_ticket.h" + +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); + +const s2n_extension_type s2n_server_session_ticket_extension = { + .iana_value = TLS_EXTENSION_SESSION_TICKET, + .is_response = true, + .send = s2n_extension_send_noop, + .recv = s2n_session_ticket_recv, + .should_send = s2n_session_ticket_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_session_ticket_should_send(struct s2n_connection *conn) +{ + return s2n_server_sending_nst(conn) && s2n_connection_get_protocol_version(conn) < S2N_TLS13; +} + +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); + conn->session_ticket_status = S2N_NEW_TICKET; + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_recv_server_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_server_session_ticket_extension, conn, extension); +} + +int s2n_send_server_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_server_session_ticket_extension, conn, out); +} + +int s2n_server_session_ticket_ext_size(struct s2n_connection *conn) +{ + if (s2n_session_ticket_should_send(conn)) { + /* 2 for extension type. 2 for extension length of 0 */ + return 4; + } + + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_session_ticket.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_session_ticket.h index 0733c02380..2e9ba959cb 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_session_ticket.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_session_ticket.h @@ -1,27 +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 "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_server_session_ticket_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -int s2n_recv_server_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *extension); -int s2n_send_server_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_server_session_ticket_ext_size(struct s2n_connection *conn); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_server_session_ticket_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +int s2n_recv_server_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *extension); +int s2n_send_server_session_ticket_ext(struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_server_session_ticket_ext_size(struct s2n_connection *conn); diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_signature_algorithms.c b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_signature_algorithms.c index a864012dd5..e7bd8a32cc 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_signature_algorithms.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_signature_algorithms.c @@ -1,42 +1,42 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <sys/param.h> -#include <stdint.h> - -#include "tls/extensions/s2n_client_signature_algorithms.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" -#include "tls/s2n_signature_algorithms.h" - -#include "stuffer/s2n_stuffer.h" -#include "utils/s2n_safety.h" - -static int s2n_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_server_signature_algorithms_extension = { - .iana_value = TLS_EXTENSION_SIGNATURE_ALGORITHMS, - .is_response = false, - .send = s2n_send_supported_sig_scheme_list, - .recv = s2n_signature_algorithms_recv, - .should_send = s2n_extension_always_send, - .if_missing = s2n_extension_error_if_missing, -}; - -static int s2n_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_recv_supported_sig_scheme_list(extension, &conn->handshake_params.server_sig_hash_algs); -} +/* + * 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/extensions/s2n_client_signature_algorithms.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" +#include "tls/s2n_signature_algorithms.h" + +#include "stuffer/s2n_stuffer.h" +#include "utils/s2n_safety.h" + +static int s2n_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_server_signature_algorithms_extension = { + .iana_value = TLS_EXTENSION_SIGNATURE_ALGORITHMS, + .is_response = false, + .send = s2n_send_supported_sig_scheme_list, + .recv = s2n_signature_algorithms_recv, + .should_send = s2n_extension_always_send, + .if_missing = s2n_extension_error_if_missing, +}; + +static int s2n_signature_algorithms_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_recv_supported_sig_scheme_list(extension, &conn->handshake_params.server_sig_hash_algs); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_signature_algorithms.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_signature_algorithms.h index 05a6cc2d9d..644d71770e 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_signature_algorithms.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_signature_algorithms.h @@ -1,20 +1,20 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "tls/extensions/s2n_extension_type.h" - -extern const s2n_extension_type s2n_server_signature_algorithms_extension; +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" + +extern const s2n_extension_type s2n_server_signature_algorithms_extension; 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 463f0898cd..7003bf46ba 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 @@ -1,66 +1,66 @@ -/* - * 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 "stuffer/s2n_stuffer.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" -#include "tls/extensions/s2n_server_status_request.h" - -static bool s2n_server_status_request_should_send(struct s2n_connection *conn); -static int s2n_server_status_request_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); - -const s2n_extension_type s2n_server_status_request_extension = { - .iana_value = TLS_EXTENSION_STATUS_REQUEST, - .is_response = true, - .send = s2n_extension_send_noop, - .recv = s2n_server_status_request_recv, - .should_send = s2n_server_status_request_should_send, - .if_missing = s2n_extension_noop_if_missing, -}; - -static bool s2n_server_status_request_should_send(struct s2n_connection *conn) -{ - return s2n_server_can_send_ocsp(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); - conn->status_type = S2N_STATUS_REQUEST_OCSP; - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_server_extensions_status_request_send_size(struct s2n_connection *conn) -{ - if (s2n_server_can_send_ocsp(conn)) { - return 2 * sizeof(uint16_t); - } - - return 0; -} - -int s2n_server_extensions_status_request_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_server_status_request_extension, conn, out); -} - -int s2n_recv_server_status_request(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_server_status_request_extension, conn, extension); -} +/* + * 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 "stuffer/s2n_stuffer.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" +#include "tls/extensions/s2n_server_status_request.h" + +static bool s2n_server_status_request_should_send(struct s2n_connection *conn); +static int s2n_server_status_request_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); + +const s2n_extension_type s2n_server_status_request_extension = { + .iana_value = TLS_EXTENSION_STATUS_REQUEST, + .is_response = true, + .send = s2n_extension_send_noop, + .recv = s2n_server_status_request_recv, + .should_send = s2n_server_status_request_should_send, + .if_missing = s2n_extension_noop_if_missing, +}; + +static bool s2n_server_status_request_should_send(struct s2n_connection *conn) +{ + return s2n_server_can_send_ocsp(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); + conn->status_type = S2N_STATUS_REQUEST_OCSP; + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_server_extensions_status_request_send_size(struct s2n_connection *conn) +{ + if (s2n_server_can_send_ocsp(conn)) { + return 2 * sizeof(uint16_t); + } + + return 0; +} + +int s2n_server_extensions_status_request_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_server_status_request_extension, conn, out); +} + +int s2n_recv_server_status_request(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_server_status_request_extension, conn, extension); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_status_request.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_status_request.h index cbe695f9b4..b43ff10ca8 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_status_request.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_status_request.h @@ -1,27 +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 "tls/extensions/s2n_extension_type.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_server_status_request_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -int s2n_server_extensions_status_request_send_size(struct s2n_connection *conn); -int s2n_server_extensions_status_request_send(struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_recv_server_status_request(struct s2n_connection *conn, struct s2n_stuffer *extension); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "tls/extensions/s2n_extension_type.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_server_status_request_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +int s2n_server_extensions_status_request_send_size(struct s2n_connection *conn); +int s2n_server_extensions_status_request_send(struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_recv_server_status_request(struct s2n_connection *conn, struct s2n_stuffer *extension); 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 026cec9c21..cd0fb015dc 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 @@ -1,106 +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 <sys/param.h> -#include <stdint.h> - -#include "tls/extensions/s2n_server_supported_versions.h" -#include "tls/extensions/s2n_supported_versions.h" -#include "tls/s2n_alerts.h" -#include "tls/s2n_cipher_preferences.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" - -#include "utils/s2n_safety.h" - -/** - * Specified in https://tools.ietf.org/html/rfc8446#section-4.2.1 - * - * "A server which negotiates TLS 1.3 MUST respond by sending a - * "supported_versions" extension containing the selected version value - * (0x0304)." - * - * Structure: - * Extension type (2 bytes) - * Extension size (2 bytes) - * Selected Version (2 byte) - **/ - -static int s2n_server_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out); -static int s2n_server_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *in); - -const s2n_extension_type s2n_server_supported_versions_extension = { - .iana_value = TLS_EXTENSION_SUPPORTED_VERSIONS, - .is_response = true, - .send = s2n_server_supported_versions_send, - .recv = s2n_server_supported_versions_recv, - .should_send = s2n_extension_send_if_tls13_connection, - .if_missing = s2n_extension_noop_if_missing, -}; - -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)); - - return S2N_SUCCESS; -} - -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 server_version_parts[S2N_TLS_PROTOCOL_VERSION_LEN]; - 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); - - conn->server_protocol_version = server_version; - - return S2N_SUCCESS; -} - -static int s2n_server_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *in) -{ - if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { - return S2N_SUCCESS; - } - - S2N_ERROR_IF(s2n_extensions_server_supported_versions_process(conn, in) < 0, S2N_ERR_BAD_MESSAGE); - return S2N_SUCCESS; -} - -/* Old-style extension functions -- remove after extensions refactor is complete */ - -int s2n_extensions_server_supported_versions_size(struct s2n_connection *conn) -{ - return 6; -} - -int s2n_extensions_server_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) -{ - return s2n_extension_recv(&s2n_server_supported_versions_extension, conn, extension); -} - -int s2n_extensions_server_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - return s2n_extension_send(&s2n_server_supported_versions_extension, conn, out); -} +/* + * 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/extensions/s2n_server_supported_versions.h" +#include "tls/extensions/s2n_supported_versions.h" +#include "tls/s2n_alerts.h" +#include "tls/s2n_cipher_preferences.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" + +#include "utils/s2n_safety.h" + +/** + * Specified in https://tools.ietf.org/html/rfc8446#section-4.2.1 + * + * "A server which negotiates TLS 1.3 MUST respond by sending a + * "supported_versions" extension containing the selected version value + * (0x0304)." + * + * Structure: + * Extension type (2 bytes) + * Extension size (2 bytes) + * Selected Version (2 byte) + **/ + +static int s2n_server_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out); +static int s2n_server_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *in); + +const s2n_extension_type s2n_server_supported_versions_extension = { + .iana_value = TLS_EXTENSION_SUPPORTED_VERSIONS, + .is_response = true, + .send = s2n_server_supported_versions_send, + .recv = s2n_server_supported_versions_recv, + .should_send = s2n_extension_send_if_tls13_connection, + .if_missing = s2n_extension_noop_if_missing, +}; + +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)); + + return S2N_SUCCESS; +} + +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 server_version_parts[S2N_TLS_PROTOCOL_VERSION_LEN]; + 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); + + conn->server_protocol_version = server_version; + + return S2N_SUCCESS; +} + +static int s2n_server_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *in) +{ + if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { + return S2N_SUCCESS; + } + + S2N_ERROR_IF(s2n_extensions_server_supported_versions_process(conn, in) < 0, S2N_ERR_BAD_MESSAGE); + return S2N_SUCCESS; +} + +/* Old-style extension functions -- remove after extensions refactor is complete */ + +int s2n_extensions_server_supported_versions_size(struct s2n_connection *conn) +{ + return 6; +} + +int s2n_extensions_server_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) +{ + return s2n_extension_recv(&s2n_server_supported_versions_extension, conn, extension); +} + +int s2n_extensions_server_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + return s2n_extension_send(&s2n_server_supported_versions_extension, conn, out); +} diff --git a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.h b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.h index 4d49a61dea..c7312be137 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_server_supported_versions.h @@ -1,27 +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 "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern const s2n_extension_type s2n_server_supported_versions_extension; - -/* Old-style extension functions -- remove after extensions refactor is complete */ -int s2n_extensions_server_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); -int s2n_extensions_server_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_extensions_server_supported_versions_size(struct s2n_connection *conn); +/* + * 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_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern const s2n_extension_type s2n_server_supported_versions_extension; + +/* Old-style extension functions -- remove after extensions refactor is complete */ +int s2n_extensions_server_supported_versions_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); +int s2n_extensions_server_supported_versions_send(struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_extensions_server_supported_versions_size(struct s2n_connection *conn); 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 018fff5b26..d02b3f920d 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.c +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.c @@ -1,31 +1,31 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <stdint.h> -#include <sys/param.h> - -#include "tls/extensions/s2n_supported_versions.h" -#include "tls/s2n_security_policies.h" - -#include "utils/s2n_safety.h" - -int 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)); - *min_version = security_policy->minimum_protocol_version; - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <stdint.h> +#include <sys/param.h> + +#include "tls/extensions/s2n_supported_versions.h" +#include "tls/s2n_security_policies.h" + +#include "utils/s2n_safety.h" + +int 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)); + *min_version = security_policy->minimum_protocol_version; + + return 0; +} 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 44e2d17957..613830c347 100644 --- a/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.h +++ b/contrib/restricted/aws/s2n/tls/extensions/s2n_supported_versions.h @@ -1,21 +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/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -extern int s2n_connection_get_minimum_supported_version(struct s2n_connection *conn, uint8_t *min_version); +/* + * 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_connection.h" +#include "stuffer/s2n_stuffer.h" + +extern int 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 d22e782952..b7a0b23160 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_aead.c +++ b/contrib/restricted/aws/s2n/tls/s2n_aead.c @@ -1,78 +1,78 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "error/s2n_errno.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_mem.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) -{ - /* 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)); - - 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) -{ - 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. - */ - - 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)); - - return S2N_RESULT_OK; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "error/s2n_errno.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_mem.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) +{ + /* 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)); + + 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) +{ + 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. + */ + + 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)); + + 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 4aafb59900..79f14f3214 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_alerts.c +++ b/contrib/restricted/aws/s2n/tls/s2n_alerts.c @@ -1,185 +1,185 @@ -/* - * 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 <stdint.h> -#include <sys/param.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_tls_parameters.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_record.h" -#include "tls/s2n_resume.h" -#include "tls/s2n_alerts.h" - -#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 - -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; -} - -static bool s2n_handle_as_warning(struct s2n_connection *conn, uint8_t level, uint8_t type) -{ - /* Only TLS1.2 considers the alert level. The alert level field is - * considered deprecated in TLS1.3. */ - if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { - return level == S2N_TLS_ALERT_LEVEL_WARNING - && conn->config->alert_behavior == S2N_ALERT_IGNORE_WARNINGS; - } - - /* user_canceled is the only alert currently treated as a warning in TLS1.3. - * We need to treat it as a warning regardless of alert_behavior to avoid marking - * correctly-closed connections as failed. */ - return type == S2N_TLS_ALERT_USER_CANCELED; -} - -int s2n_process_alert_fragment(struct s2n_connection *conn) -{ - notnull_check(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); - - while (s2n_stuffer_data_available(&conn->in)) { - uint8_t bytes_required = 2; - - /* Alerts are two bytes long, but can still be fragmented or coalesced */ - if (s2n_stuffer_data_available(&conn->alert_in) == 1) { - bytes_required = 1; - } - - 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)); - - 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; - 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)); - return 0; - } - - /* RFC 5077 5.1 - Expire any cached session on an error alert */ - if (s2n_allowed_to_cache_connection(conn) && conn->session_id_len) { - conn->config->cache_delete(conn, conn->config->cache_delete_data, conn->session_id, conn->session_id_len); - } - - /* All other alerts are treated as fatal errors */ - conn->closed = 1; - S2N_ERROR(S2N_ERR_ALERT); - } - } - - return 0; -} - -int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn) -{ - notnull_check(conn); - - uint8_t alert[2]; - alert[0] = S2N_TLS_ALERT_LEVEL_WARNING; - alert[1] = S2N_TLS_ALERT_CLOSE_NOTIFY; - - struct s2n_blob out = {.data = alert,.size = sizeof(alert) }; - - /* If there is an alert pending or we've already sent a close_notify, do nothing */ - if (s2n_stuffer_data_available(&conn->writer_alert_out) || conn->close_notify_queued) { - return S2N_SUCCESS; - } - - if (!s2n_alerts_supported(conn)) { - return S2N_SUCCESS; - } - - GUARD(s2n_stuffer_write(&conn->writer_alert_out, &out)); - conn->close_notify_queued = 1; - - return S2N_SUCCESS; -} - -static int s2n_queue_reader_alert(struct s2n_connection *conn, uint8_t level, uint8_t error_code) -{ - notnull_check(conn); - - uint8_t alert[2]; - alert[0] = level; - alert[1] = error_code; - - struct s2n_blob out = {.data = alert,.size = sizeof(alert) }; - - /* If there is an alert pending, do nothing */ - if (s2n_stuffer_data_available(&conn->reader_alert_out)) { - return S2N_SUCCESS; - } - - if (!s2n_alerts_supported(conn)) { - return S2N_SUCCESS; - } - - GUARD(s2n_stuffer_write(&conn->reader_alert_out, &out)); - - return S2N_SUCCESS; -} - -int s2n_queue_reader_unsupported_protocol_version_alert(struct s2n_connection *conn) -{ - return s2n_queue_reader_alert(conn, S2N_TLS_ALERT_LEVEL_FATAL, S2N_TLS_ALERT_PROTOCOL_VERSION); -} - -int s2n_queue_reader_handshake_failure_alert(struct s2n_connection *conn) -{ - return s2n_queue_reader_alert(conn, S2N_TLS_ALERT_LEVEL_FATAL, S2N_TLS_ALERT_HANDSHAKE_FAILURE); -} +/* + * 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 <stdint.h> +#include <sys/param.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_tls_parameters.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_record.h" +#include "tls/s2n_resume.h" +#include "tls/s2n_alerts.h" + +#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 + +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; +} + +static bool s2n_handle_as_warning(struct s2n_connection *conn, uint8_t level, uint8_t type) +{ + /* Only TLS1.2 considers the alert level. The alert level field is + * considered deprecated in TLS1.3. */ + if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) { + return level == S2N_TLS_ALERT_LEVEL_WARNING + && conn->config->alert_behavior == S2N_ALERT_IGNORE_WARNINGS; + } + + /* user_canceled is the only alert currently treated as a warning in TLS1.3. + * We need to treat it as a warning regardless of alert_behavior to avoid marking + * correctly-closed connections as failed. */ + return type == S2N_TLS_ALERT_USER_CANCELED; +} + +int s2n_process_alert_fragment(struct s2n_connection *conn) +{ + notnull_check(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); + + while (s2n_stuffer_data_available(&conn->in)) { + uint8_t bytes_required = 2; + + /* Alerts are two bytes long, but can still be fragmented or coalesced */ + if (s2n_stuffer_data_available(&conn->alert_in) == 1) { + bytes_required = 1; + } + + 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)); + + 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; + 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)); + return 0; + } + + /* RFC 5077 5.1 - Expire any cached session on an error alert */ + if (s2n_allowed_to_cache_connection(conn) && conn->session_id_len) { + conn->config->cache_delete(conn, conn->config->cache_delete_data, conn->session_id, conn->session_id_len); + } + + /* All other alerts are treated as fatal errors */ + conn->closed = 1; + S2N_ERROR(S2N_ERR_ALERT); + } + } + + return 0; +} + +int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn) +{ + notnull_check(conn); + + uint8_t alert[2]; + alert[0] = S2N_TLS_ALERT_LEVEL_WARNING; + alert[1] = S2N_TLS_ALERT_CLOSE_NOTIFY; + + struct s2n_blob out = {.data = alert,.size = sizeof(alert) }; + + /* If there is an alert pending or we've already sent a close_notify, do nothing */ + if (s2n_stuffer_data_available(&conn->writer_alert_out) || conn->close_notify_queued) { + return S2N_SUCCESS; + } + + if (!s2n_alerts_supported(conn)) { + return S2N_SUCCESS; + } + + GUARD(s2n_stuffer_write(&conn->writer_alert_out, &out)); + conn->close_notify_queued = 1; + + return S2N_SUCCESS; +} + +static int s2n_queue_reader_alert(struct s2n_connection *conn, uint8_t level, uint8_t error_code) +{ + notnull_check(conn); + + uint8_t alert[2]; + alert[0] = level; + alert[1] = error_code; + + struct s2n_blob out = {.data = alert,.size = sizeof(alert) }; + + /* If there is an alert pending, do nothing */ + if (s2n_stuffer_data_available(&conn->reader_alert_out)) { + return S2N_SUCCESS; + } + + if (!s2n_alerts_supported(conn)) { + return S2N_SUCCESS; + } + + GUARD(s2n_stuffer_write(&conn->reader_alert_out, &out)); + + return S2N_SUCCESS; +} + +int s2n_queue_reader_unsupported_protocol_version_alert(struct s2n_connection *conn) +{ + return s2n_queue_reader_alert(conn, S2N_TLS_ALERT_LEVEL_FATAL, S2N_TLS_ALERT_PROTOCOL_VERSION); +} + +int s2n_queue_reader_handshake_failure_alert(struct s2n_connection *conn) +{ + return s2n_queue_reader_alert(conn, S2N_TLS_ALERT_LEVEL_FATAL, S2N_TLS_ALERT_HANDSHAKE_FAILURE); +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_alerts.h b/contrib/restricted/aws/s2n/tls/s2n_alerts.h index 74194022cc..694c64068c 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_alerts.h +++ b/contrib/restricted/aws/s2n/tls/s2n_alerts.h @@ -1,25 +1,25 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include <stdint.h> - -#include "tls/s2n_connection.h" - -extern int s2n_process_alert_fragment(struct s2n_connection *conn); -extern int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn); -extern int s2n_queue_reader_unsupported_protocol_version_alert(struct s2n_connection *conn); -extern int s2n_queue_reader_handshake_failure_alert(struct s2n_connection *conn); +/* + * 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 <stdint.h> + +#include "tls/s2n_connection.h" + +extern int s2n_process_alert_fragment(struct s2n_connection *conn); +extern int s2n_queue_writer_close_alert_warning(struct s2n_connection *conn); +extern int s2n_queue_reader_unsupported_protocol_version_alert(struct s2n_connection *conn); +extern int s2n_queue_reader_handshake_failure_alert(struct s2n_connection *conn); diff --git a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c index 722b38dd98..15c539da6b 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c +++ b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.c @@ -1,411 +1,411 @@ -/* - * 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_async_pkey.h" - -#include "crypto/s2n_hash.h" -#include "crypto/s2n_signature.h" -#include "error/s2n_errno.h" -#include "s2n.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_handshake.h" -#include "utils/s2n_blob.h" -#include "utils/s2n_mem.h" -#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; - struct s2n_blob decrypted; - unsigned rsa_failed : 1; -}; - -struct s2n_async_pkey_sign_data { - s2n_async_pkey_sign_complete on_complete; - struct s2n_hash_state digest; - s2n_signature_algorithm sig_alg; - struct s2n_blob signature; -}; - -struct s2n_async_pkey_op { - s2n_async_pkey_op_type type; - struct s2n_connection *conn; - unsigned complete : 1; - unsigned applied : 1; - union { - struct s2n_async_pkey_decrypt_data decrypt; - struct s2n_async_pkey_sign_data sign; - } 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 (*free)(struct s2n_async_pkey_op *op); -}; - -static S2N_RESULT s2n_async_get_actions(s2n_async_pkey_op_type type, const struct s2n_async_pkey_op_actions **actions); - -static S2N_RESULT s2n_async_pkey_op_allocate(struct s2n_async_pkey_op **op); - -static 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); -static 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); - -static 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); -static 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); - -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_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_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, - .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, - .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); - - switch (type) { - case S2N_ASYNC_DECRYPT: - *actions = &s2n_async_pkey_decrypt_op; - return S2N_RESULT_OK; - case S2N_ASYNC_SIGN: - *actions = &s2n_async_pkey_sign_op; - return S2N_RESULT_OK; - /* No default for compiler warnings */ - } - - return S2N_RESULT_ERROR; -} - -static S2N_RESULT s2n_async_pkey_op_allocate(struct s2n_async_pkey_op **op) -{ - ENSURE_REF(op); - 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)); - - *op = (void *) mem.data; - if (s2n_blob_init(&mem, NULL, 0) != S2N_SUCCESS) { - *op = NULL; - return S2N_RESULT_ERROR; - } - return S2N_RESULT_OK; -} - -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); - - if (conn->config->async_pkey_cb) { - GUARD_RESULT(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)); - } - - return S2N_RESULT_OK; -} - -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); - - DEFER_CLEANUP(struct s2n_async_pkey_op *op = NULL, s2n_async_pkey_op_free_pointer); - GUARD_RESULT(s2n_async_pkey_op_allocate(&op)); - - op->type = S2N_ASYNC_DECRYPT; - op->conn = conn; - - 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); - - /* 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); -} - -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); - - 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)); - - return S2N_RESULT_OK; -} - -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); - - if (conn->config->async_pkey_cb) { - GUARD_RESULT(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)); - } - - return S2N_RESULT_OK; -} - -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); - - DEFER_CLEANUP(struct s2n_async_pkey_op *op = NULL, s2n_async_pkey_op_free_pointer); - GUARD_RESULT(s2n_async_pkey_op_allocate(&op)); - - op->type = S2N_ASYNC_SIGN; - op->conn = conn; - - 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; - - 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); -} - -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); - - const struct s2n_pkey *pkey = conn->handshake_params.our_chain_and_key->private_key; - DEFER_CLEANUP(struct s2n_blob signed_content = { 0 }, s2n_free); - - uint32_t maximum_signature_length = s2n_pkey_size(pkey); - GUARD_AS_RESULT(s2n_alloc(&signed_content, maximum_signature_length)); - - GUARD_AS_RESULT(s2n_pkey_sign(pkey, sig_alg, digest, &signed_content)); - - GUARD_AS_RESULT(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); - - const struct s2n_async_pkey_op_actions *actions = NULL; - GUARD_AS_POSIX(s2n_async_get_actions(op->type, &actions)); - notnull_check(actions); - - GUARD_AS_POSIX(actions->perform(op, key)); - - op->complete = true; - - return S2N_SUCCESS; -} - -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); - /* 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); - - const struct s2n_async_pkey_op_actions *actions = NULL; - GUARD_AS_POSIX(s2n_async_get_actions(op->type, &actions)); - notnull_check(actions); - - GUARD_AS_POSIX(actions->apply(op, conn)); - - op->applied = true; - conn->handshake.async_state = S2N_ASYNC_INVOKED_COMPLETE; - - /* Free up the decrypt/sign structs to avoid storing secrets for too long */ - GUARD_AS_POSIX(actions->free(op)); - - return S2N_SUCCESS; -} - -int s2n_async_pkey_op_free(struct s2n_async_pkey_op *op) -{ - ENSURE_POSIX_REF(op); - const struct s2n_async_pkey_op_actions *actions = NULL; - GUARD_AS_POSIX(s2n_async_get_actions(op->type, &actions)); - notnull_check(actions); - - /* If applied the decrypt/sign structs were released in apply call */ - if (!op->applied) { GUARD_AS_POSIX(actions->free(op)); } - - GUARD_POSIX(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); - - struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt; - - decrypt->rsa_failed = s2n_pkey_decrypt(pkey, &decrypt->encrypted, &decrypt->decrypted) != S2N_SUCCESS; - - return S2N_RESULT_OK; -} - -S2N_RESULT s2n_async_pkey_decrypt_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn) -{ - ENSURE_REF(op); - 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)); - - return S2N_RESULT_OK; -} - -S2N_RESULT s2n_async_pkey_decrypt_free(struct s2n_async_pkey_op *op) -{ - 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)); - - 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); - - struct s2n_async_pkey_sign_data *sign = &op->op.sign; - - uint32_t maximum_signature_length = s2n_pkey_size(pkey); - GUARD_AS_RESULT(s2n_alloc(&sign->signature, maximum_signature_length)); - - GUARD_AS_RESULT(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); - - struct s2n_async_pkey_sign_data *sign = &op->op.sign; - - GUARD_AS_RESULT(sign->on_complete(conn, &sign->signature)); - - return S2N_RESULT_OK; -} - -S2N_RESULT s2n_async_pkey_sign_free(struct s2n_async_pkey_op *op) -{ - ENSURE_REF(op); - - struct s2n_async_pkey_sign_data *sign = &op->op.sign; - - GUARD_AS_RESULT(s2n_hash_free(&sign->digest)); - GUARD_AS_RESULT(s2n_free(&sign->signature)); - - return S2N_RESULT_OK; -} +/* + * 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_async_pkey.h" + +#include "crypto/s2n_hash.h" +#include "crypto/s2n_signature.h" +#include "error/s2n_errno.h" +#include "s2n.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_handshake.h" +#include "utils/s2n_blob.h" +#include "utils/s2n_mem.h" +#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; + struct s2n_blob decrypted; + unsigned rsa_failed : 1; +}; + +struct s2n_async_pkey_sign_data { + s2n_async_pkey_sign_complete on_complete; + struct s2n_hash_state digest; + s2n_signature_algorithm sig_alg; + struct s2n_blob signature; +}; + +struct s2n_async_pkey_op { + s2n_async_pkey_op_type type; + struct s2n_connection *conn; + unsigned complete : 1; + unsigned applied : 1; + union { + struct s2n_async_pkey_decrypt_data decrypt; + struct s2n_async_pkey_sign_data sign; + } 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 (*free)(struct s2n_async_pkey_op *op); +}; + +static S2N_RESULT s2n_async_get_actions(s2n_async_pkey_op_type type, const struct s2n_async_pkey_op_actions **actions); + +static S2N_RESULT s2n_async_pkey_op_allocate(struct s2n_async_pkey_op **op); + +static 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); +static 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); + +static 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); +static 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); + +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_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_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, + .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, + .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); + + switch (type) { + case S2N_ASYNC_DECRYPT: + *actions = &s2n_async_pkey_decrypt_op; + return S2N_RESULT_OK; + case S2N_ASYNC_SIGN: + *actions = &s2n_async_pkey_sign_op; + return S2N_RESULT_OK; + /* No default for compiler warnings */ + } + + return S2N_RESULT_ERROR; +} + +static S2N_RESULT s2n_async_pkey_op_allocate(struct s2n_async_pkey_op **op) +{ + ENSURE_REF(op); + 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)); + + *op = (void *) mem.data; + if (s2n_blob_init(&mem, NULL, 0) != S2N_SUCCESS) { + *op = NULL; + return S2N_RESULT_ERROR; + } + return S2N_RESULT_OK; +} + +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); + + if (conn->config->async_pkey_cb) { + GUARD_RESULT(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)); + } + + return S2N_RESULT_OK; +} + +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); + + DEFER_CLEANUP(struct s2n_async_pkey_op *op = NULL, s2n_async_pkey_op_free_pointer); + GUARD_RESULT(s2n_async_pkey_op_allocate(&op)); + + op->type = S2N_ASYNC_DECRYPT; + op->conn = conn; + + 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); + + /* 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); +} + +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); + + 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)); + + return S2N_RESULT_OK; +} + +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); + + if (conn->config->async_pkey_cb) { + GUARD_RESULT(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)); + } + + return S2N_RESULT_OK; +} + +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); + + DEFER_CLEANUP(struct s2n_async_pkey_op *op = NULL, s2n_async_pkey_op_free_pointer); + GUARD_RESULT(s2n_async_pkey_op_allocate(&op)); + + op->type = S2N_ASYNC_SIGN; + op->conn = conn; + + 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; + + 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); +} + +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); + + const struct s2n_pkey *pkey = conn->handshake_params.our_chain_and_key->private_key; + DEFER_CLEANUP(struct s2n_blob signed_content = { 0 }, s2n_free); + + uint32_t maximum_signature_length = s2n_pkey_size(pkey); + GUARD_AS_RESULT(s2n_alloc(&signed_content, maximum_signature_length)); + + GUARD_AS_RESULT(s2n_pkey_sign(pkey, sig_alg, digest, &signed_content)); + + GUARD_AS_RESULT(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); + + const struct s2n_async_pkey_op_actions *actions = NULL; + GUARD_AS_POSIX(s2n_async_get_actions(op->type, &actions)); + notnull_check(actions); + + GUARD_AS_POSIX(actions->perform(op, key)); + + op->complete = true; + + return S2N_SUCCESS; +} + +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); + /* 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); + + const struct s2n_async_pkey_op_actions *actions = NULL; + GUARD_AS_POSIX(s2n_async_get_actions(op->type, &actions)); + notnull_check(actions); + + GUARD_AS_POSIX(actions->apply(op, conn)); + + op->applied = true; + conn->handshake.async_state = S2N_ASYNC_INVOKED_COMPLETE; + + /* Free up the decrypt/sign structs to avoid storing secrets for too long */ + GUARD_AS_POSIX(actions->free(op)); + + return S2N_SUCCESS; +} + +int s2n_async_pkey_op_free(struct s2n_async_pkey_op *op) +{ + ENSURE_POSIX_REF(op); + const struct s2n_async_pkey_op_actions *actions = NULL; + GUARD_AS_POSIX(s2n_async_get_actions(op->type, &actions)); + notnull_check(actions); + + /* If applied the decrypt/sign structs were released in apply call */ + if (!op->applied) { GUARD_AS_POSIX(actions->free(op)); } + + GUARD_POSIX(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); + + struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt; + + decrypt->rsa_failed = s2n_pkey_decrypt(pkey, &decrypt->encrypted, &decrypt->decrypted) != S2N_SUCCESS; + + return S2N_RESULT_OK; +} + +S2N_RESULT s2n_async_pkey_decrypt_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn) +{ + ENSURE_REF(op); + 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)); + + return S2N_RESULT_OK; +} + +S2N_RESULT s2n_async_pkey_decrypt_free(struct s2n_async_pkey_op *op) +{ + 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)); + + 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); + + struct s2n_async_pkey_sign_data *sign = &op->op.sign; + + uint32_t maximum_signature_length = s2n_pkey_size(pkey); + GUARD_AS_RESULT(s2n_alloc(&sign->signature, maximum_signature_length)); + + GUARD_AS_RESULT(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); + + struct s2n_async_pkey_sign_data *sign = &op->op.sign; + + GUARD_AS_RESULT(sign->on_complete(conn, &sign->signature)); + + return S2N_RESULT_OK; +} + +S2N_RESULT s2n_async_pkey_sign_free(struct s2n_async_pkey_op *op) +{ + ENSURE_REF(op); + + struct s2n_async_pkey_sign_data *sign = &op->op.sign; + + GUARD_AS_RESULT(s2n_hash_free(&sign->digest)); + GUARD_AS_RESULT(s2n_free(&sign->signature)); + + 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 d829d75a7e..2ef8386d2f 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_async_pkey.h +++ b/contrib/restricted/aws/s2n/tls/s2n_async_pkey.h @@ -1,71 +1,71 @@ -/* - * 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_connection.h" -#include "utils/s2n_blob.h" -#include "utils/s2n_result.h" - -typedef int (*s2n_async_pkey_sign_complete)(struct s2n_connection *conn, struct s2n_blob *signature); -typedef int (*s2n_async_pkey_decrypt_complete)(struct s2n_connection *conn, bool rsa_failed, struct s2n_blob *decrypted); - -struct s2n_async_pkey_op; - -/* Guard to handle async states inside handler which uses async pkey operations. If async operation was not invoked - * it means that we enter this handler for the first time and handler may or may not use async operation, so we let it - * continue. If async operation is invoking or was invoked, but yet to be complete, we error out of the handler to let - * s2n_handle_retry_state try again. If async operation was complete we clear the state and let s2n_handle_retry_state - * proceed to the next handler */ -#define S2N_ASYNC_PKEY_GUARD(conn) \ - do { \ - __typeof(conn) __tmp_conn = (conn); \ - GUARD_NONNULL(__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_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) - -/* Macros for safe exection of async sign/decrypt. - * - * When operation is done asynchronously, we drop to s2n_negotiate loop with S2N_ERR_ASYNC_BLOCKED error and do not - * perform any of the operations to follow after s2n_async* call. To enforce that there are no operations after the - * 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)); - -#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)); - -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); - -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, - s2n_async_pkey_sign_complete on_complete); +/* + * 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_connection.h" +#include "utils/s2n_blob.h" +#include "utils/s2n_result.h" + +typedef int (*s2n_async_pkey_sign_complete)(struct s2n_connection *conn, struct s2n_blob *signature); +typedef int (*s2n_async_pkey_decrypt_complete)(struct s2n_connection *conn, bool rsa_failed, struct s2n_blob *decrypted); + +struct s2n_async_pkey_op; + +/* Guard to handle async states inside handler which uses async pkey operations. If async operation was not invoked + * it means that we enter this handler for the first time and handler may or may not use async operation, so we let it + * continue. If async operation is invoking or was invoked, but yet to be complete, we error out of the handler to let + * s2n_handle_retry_state try again. If async operation was complete we clear the state and let s2n_handle_retry_state + * proceed to the next handler */ +#define S2N_ASYNC_PKEY_GUARD(conn) \ + do { \ + __typeof(conn) __tmp_conn = (conn); \ + GUARD_NONNULL(__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_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) + +/* Macros for safe exection of async sign/decrypt. + * + * When operation is done asynchronously, we drop to s2n_negotiate loop with S2N_ERR_ASYNC_BLOCKED error and do not + * perform any of the operations to follow after s2n_async* call. To enforce that there are no operations after the + * 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)); + +#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)); + +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); + +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, + s2n_async_pkey_sign_complete on_complete); diff --git a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c index 87c6b69277..2d5070e32e 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c +++ b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.c @@ -1,228 +1,228 @@ -/* - * 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 "crypto/s2n_certificate.h" -#include "crypto/s2n_ecdsa.h" -#include "crypto/s2n_signature.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_kex.h" -#include "tls/s2n_auth_selection.h" - -#include "utils/s2n_safety.h" - -/* This module should contain any logic related to choosing a valid combination of - * signature algorithm, authentication method, and certificate to use for authentication. - * - * We choose our auth methods by: - * 1. Finding a cipher suite with an auth method that we have valid certs for. In TLS1.3, - * this is a no-op -- cipher suites do not specify an auth method. - * 2. Choosing a signature algorithm that matches both the auth method (if set) and the - * available certs. - * 3. Selecting the cert that matches the chosen signature algorithm. - * - * This is a break from the original s2n pre-TLS1.3 flow, when we could choose certs and - * ciphers at the same time. Our cipher suites differentiate between "RSA" and "ECDSA", - * but not between "RSA" and "RSA-PSS". To make that decision, we need to wait until - * we've chosen a signature algorithm. This allows us to use RSA-PSS with existing - * TLS1.2 cipher suites. - */ - -static 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: - case S2N_PKEY_TYPE_RSA_PSS: - *auth_method = S2N_AUTHENTICATION_RSA; - return S2N_SUCCESS; - case S2N_PKEY_TYPE_ECDSA: - *auth_method = S2N_AUTHENTICATION_ECDSA; - return S2N_SUCCESS; - case S2N_PKEY_TYPE_UNKNOWN: - case S2N_PKEY_TYPE_SENTINEL: - S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED); - } - S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED); -} - -static int s2n_get_cert_type_for_sig_alg(s2n_signature_algorithm sig_alg, s2n_pkey_type *cert_type) -{ - switch(sig_alg) { - case S2N_SIGNATURE_RSA_PSS_RSAE: - case S2N_SIGNATURE_RSA: - *cert_type = S2N_PKEY_TYPE_RSA; - return S2N_SUCCESS; - case S2N_SIGNATURE_ECDSA: - *cert_type = S2N_PKEY_TYPE_ECDSA; - return S2N_SUCCESS; - case S2N_SIGNATURE_RSA_PSS_PSS: - *cert_type = S2N_PKEY_TYPE_RSA_PSS; - return S2N_SUCCESS; - case S2N_SIGNATURE_ANONYMOUS: - S2N_ERROR(S2N_ERR_INVALID_SIGNATURE_ALGORITHM); - } - S2N_ERROR(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); - - s2n_pkey_type cert_type_for_sig_alg; - 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. - * - * Therefore, if a cipher suite uses a non-ephemeral kex, then any signature - * 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); - } - - /* If a cipher suite includes an auth method, then the signature algorithm - * must match that auth method. - */ - 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); - } - - return S2N_SUCCESS; -} - -static int s2n_certs_exist_for_sig_scheme(struct s2n_connection *conn, const struct s2n_signature_scheme *sig_scheme) -{ - notnull_check(sig_scheme); - - s2n_pkey_type cert_type; - 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); - - /* 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)); - } - - return S2N_SUCCESS; -} - -static int s2n_certs_exist_for_auth_method(struct s2n_connection *conn, s2n_authentication_method auth_method) -{ - s2n_authentication_method auth_method_for_cert_type; - for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { - GUARD(s2n_get_auth_method_for_cert_type(i, &auth_method_for_cert_type)); - - if (auth_method != S2N_AUTHENTICATION_METHOD_SENTINEL && auth_method != auth_method_for_cert_type) { - continue; - } - - if (s2n_get_compatible_cert_chain_and_key(conn, i) != NULL) { - return S2N_SUCCESS; - } - } - S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED); -} - -/* A cipher suite is valid if: - * - At least one compatible cert is configured - * - * TLS1.3 ciphers are valid if ANY certs are configured, as authentication - * method is not tied to cipher suites in TLS1.3. - * - * This method is called by the server when choosing a cipher suite. - */ -int s2n_is_cipher_suite_valid_for_auth(struct s2n_connection *conn, struct s2n_cipher_suite *cipher_suite) -{ - notnull_check(cipher_suite); - - GUARD(s2n_certs_exist_for_auth_method(conn, cipher_suite->auth_method)); - - return S2N_SUCCESS; -} - -/* A signature algorithm is valid if: - * - At least one compatible cert is configured. - * - The signature algorithm is allowed by the cipher suite's auth method - * (if running as a pre-TLS1.3 server). - * - * This method is called by the both server and client when choosing a signature algorithm. - */ -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); - - struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite; - notnull_check(cipher_suite); - - 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)); - } - return S2N_SUCCESS; -} - -/* A cert is valid if: - * - The configured cipher suite's auth method (if present) supports the cert. - * - * We could also verify that at least one of our supported sig algs - * supports the cert, but that seems unnecessary. If we don't have a valid - * sig alg, we'll fail on CertVerify. - * - * This method is called by the client when receiving the server's cert. - */ -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); - - s2n_authentication_method auth_method; - 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); - } - - return S2N_SUCCESS; -} - -/* Choose the cert associated with our configured signature algorithm. - * - * This method is called by the server after configuring its cipher suite and sig algs. - */ -int s2n_select_certs_for_server_auth(struct s2n_connection *conn, struct s2n_cert_chain_and_key **chosen_certs) -{ - notnull_check(conn); - - s2n_pkey_type cert_type; - GUARD(s2n_get_cert_type_for_sig_alg(conn->secure.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); - - return S2N_SUCCESS; -} +/* + * 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 "crypto/s2n_certificate.h" +#include "crypto/s2n_ecdsa.h" +#include "crypto/s2n_signature.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_kex.h" +#include "tls/s2n_auth_selection.h" + +#include "utils/s2n_safety.h" + +/* This module should contain any logic related to choosing a valid combination of + * signature algorithm, authentication method, and certificate to use for authentication. + * + * We choose our auth methods by: + * 1. Finding a cipher suite with an auth method that we have valid certs for. In TLS1.3, + * this is a no-op -- cipher suites do not specify an auth method. + * 2. Choosing a signature algorithm that matches both the auth method (if set) and the + * available certs. + * 3. Selecting the cert that matches the chosen signature algorithm. + * + * This is a break from the original s2n pre-TLS1.3 flow, when we could choose certs and + * ciphers at the same time. Our cipher suites differentiate between "RSA" and "ECDSA", + * but not between "RSA" and "RSA-PSS". To make that decision, we need to wait until + * we've chosen a signature algorithm. This allows us to use RSA-PSS with existing + * TLS1.2 cipher suites. + */ + +static 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: + case S2N_PKEY_TYPE_RSA_PSS: + *auth_method = S2N_AUTHENTICATION_RSA; + return S2N_SUCCESS; + case S2N_PKEY_TYPE_ECDSA: + *auth_method = S2N_AUTHENTICATION_ECDSA; + return S2N_SUCCESS; + case S2N_PKEY_TYPE_UNKNOWN: + case S2N_PKEY_TYPE_SENTINEL: + S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED); + } + S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED); +} + +static int s2n_get_cert_type_for_sig_alg(s2n_signature_algorithm sig_alg, s2n_pkey_type *cert_type) +{ + switch(sig_alg) { + case S2N_SIGNATURE_RSA_PSS_RSAE: + case S2N_SIGNATURE_RSA: + *cert_type = S2N_PKEY_TYPE_RSA; + return S2N_SUCCESS; + case S2N_SIGNATURE_ECDSA: + *cert_type = S2N_PKEY_TYPE_ECDSA; + return S2N_SUCCESS; + case S2N_SIGNATURE_RSA_PSS_PSS: + *cert_type = S2N_PKEY_TYPE_RSA_PSS; + return S2N_SUCCESS; + case S2N_SIGNATURE_ANONYMOUS: + S2N_ERROR(S2N_ERR_INVALID_SIGNATURE_ALGORITHM); + } + S2N_ERROR(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); + + s2n_pkey_type cert_type_for_sig_alg; + 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. + * + * Therefore, if a cipher suite uses a non-ephemeral kex, then any signature + * 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); + } + + /* If a cipher suite includes an auth method, then the signature algorithm + * must match that auth method. + */ + 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); + } + + return S2N_SUCCESS; +} + +static int s2n_certs_exist_for_sig_scheme(struct s2n_connection *conn, const struct s2n_signature_scheme *sig_scheme) +{ + notnull_check(sig_scheme); + + s2n_pkey_type cert_type; + 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); + + /* 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)); + } + + return S2N_SUCCESS; +} + +static int s2n_certs_exist_for_auth_method(struct s2n_connection *conn, s2n_authentication_method auth_method) +{ + s2n_authentication_method auth_method_for_cert_type; + for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { + GUARD(s2n_get_auth_method_for_cert_type(i, &auth_method_for_cert_type)); + + if (auth_method != S2N_AUTHENTICATION_METHOD_SENTINEL && auth_method != auth_method_for_cert_type) { + continue; + } + + if (s2n_get_compatible_cert_chain_and_key(conn, i) != NULL) { + return S2N_SUCCESS; + } + } + S2N_ERROR(S2N_ERR_CERT_TYPE_UNSUPPORTED); +} + +/* A cipher suite is valid if: + * - At least one compatible cert is configured + * + * TLS1.3 ciphers are valid if ANY certs are configured, as authentication + * method is not tied to cipher suites in TLS1.3. + * + * This method is called by the server when choosing a cipher suite. + */ +int s2n_is_cipher_suite_valid_for_auth(struct s2n_connection *conn, struct s2n_cipher_suite *cipher_suite) +{ + notnull_check(cipher_suite); + + GUARD(s2n_certs_exist_for_auth_method(conn, cipher_suite->auth_method)); + + return S2N_SUCCESS; +} + +/* A signature algorithm is valid if: + * - At least one compatible cert is configured. + * - The signature algorithm is allowed by the cipher suite's auth method + * (if running as a pre-TLS1.3 server). + * + * This method is called by the both server and client when choosing a signature algorithm. + */ +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); + + struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite; + notnull_check(cipher_suite); + + 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)); + } + return S2N_SUCCESS; +} + +/* A cert is valid if: + * - The configured cipher suite's auth method (if present) supports the cert. + * + * We could also verify that at least one of our supported sig algs + * supports the cert, but that seems unnecessary. If we don't have a valid + * sig alg, we'll fail on CertVerify. + * + * This method is called by the client when receiving the server's cert. + */ +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); + + s2n_authentication_method auth_method; + 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); + } + + return S2N_SUCCESS; +} + +/* Choose the cert associated with our configured signature algorithm. + * + * This method is called by the server after configuring its cipher suite and sig algs. + */ +int s2n_select_certs_for_server_auth(struct s2n_connection *conn, struct s2n_cert_chain_and_key **chosen_certs) +{ + notnull_check(conn); + + s2n_pkey_type cert_type; + GUARD(s2n_get_cert_type_for_sig_alg(conn->secure.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); + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.h b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.h index 2c709e99fb..370f00c4f8 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_auth_selection.h +++ b/contrib/restricted/aws/s2n/tls/s2n_auth_selection.h @@ -1,27 +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 "tls/s2n_cipher_suites.h" - -#include "crypto/s2n_certificate.h" -#include "crypto/s2n_signature.h" - -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); -int s2n_select_certs_for_server_auth(struct s2n_connection *conn, struct s2n_cert_chain_and_key **chosen_certs); - +/* + * 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_cipher_suites.h" + +#include "crypto/s2n_certificate.h" +#include "crypto/s2n_signature.h" + +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); +int s2n_select_certs_for_server_auth(struct s2n_connection *conn, struct s2n_cert_chain_and_key **chosen_certs); + diff --git a/contrib/restricted/aws/s2n/tls/s2n_cbc.c b/contrib/restricted/aws/s2n/tls/s2n_cbc.c index 5c9a8fa5b1..b2ae713e8e 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cbc.c +++ b/contrib/restricted/aws/s2n/tls/s2n_cbc.c @@ -1,103 +1,103 @@ -/* - * 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 "error/s2n_errno.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_mem.h" - -#include "crypto/s2n_hmac.h" - -#include "tls/s2n_record.h" - -/* A TLS CBC record looks like .. - * - * [ Payload data ] [ HMAC ] [ Padding ] [ Padding length byte ] - * - * Each byte in the padding is expected to be set to the same value - * as the padding length byte. So if the padding length byte is '2' - * then the padding will be [ '2', '2' ] (there'll be three bytes - * set to that value if you include the padding length byte). - * - * The goal of s2n_verify_cbc() is to verify that the padding and hmac - * are correct, without leaking (via timing) how much padding there - * actually is: as this is considered secret. - * - * In addition to our efforts here though, s2n also wraps any CBC - * verification error (or record parsing error in general) with - * a randomized delay of between 1ms and 10 seconds. See s2n_connection.c. - * This amount of delay randomization is sufficient to increase the - * complexity of attack for even a 1 microsecond timing leak (which - * is quite large) by a factor of around 83 trillion. - */ -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)); - - /* 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); - - int payload_and_padding_size = decrypted->size - mac_digest_size; - - /* Determine what the padding length is */ - uint8_t padding_length = decrypted->data[decrypted->size - 1]; - - 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)); - - /* 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)); - - 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)); - - /* SSLv3 doesn't specify what the padding should actually be */ - if (conn->actual_protocol_version == S2N_SSLv3) { - return 0 - mismatches; - } - - /* Check the maximum amount that could theoretically be padding */ - 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++) { - 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; -} +/* + * 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 "error/s2n_errno.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_mem.h" + +#include "crypto/s2n_hmac.h" + +#include "tls/s2n_record.h" + +/* A TLS CBC record looks like .. + * + * [ Payload data ] [ HMAC ] [ Padding ] [ Padding length byte ] + * + * Each byte in the padding is expected to be set to the same value + * as the padding length byte. So if the padding length byte is '2' + * then the padding will be [ '2', '2' ] (there'll be three bytes + * set to that value if you include the padding length byte). + * + * The goal of s2n_verify_cbc() is to verify that the padding and hmac + * are correct, without leaking (via timing) how much padding there + * actually is: as this is considered secret. + * + * In addition to our efforts here though, s2n also wraps any CBC + * verification error (or record parsing error in general) with + * a randomized delay of between 1ms and 10 seconds. See s2n_connection.c. + * This amount of delay randomization is sufficient to increase the + * complexity of attack for even a 1 microsecond timing leak (which + * is quite large) by a factor of around 83 trillion. + */ +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)); + + /* 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); + + int payload_and_padding_size = decrypted->size - mac_digest_size; + + /* Determine what the padding length is */ + uint8_t padding_length = decrypted->data[decrypted->size - 1]; + + 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)); + + /* 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)); + + 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)); + + /* SSLv3 doesn't specify what the padding should actually be */ + if (conn->actual_protocol_version == S2N_SSLv3) { + return 0 - mismatches; + } + + /* Check the maximum amount that could theoretically be padding */ + 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++) { + 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 652d0f6230..19caaa96a1 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_change_cipher_spec.c +++ b/contrib/restricted/aws/s2n/tls/s2n_change_cipher_spec.c @@ -1,90 +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. - */ - -#include <stdint.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_safety.h" - -/* From RFC5246 7.1: https://tools.ietf.org/html/rfc5246#section-7.1 */ -#define CHANGE_CIPHER_SPEC_TYPE 1 - -int s2n_basic_ccs_recv(struct s2n_connection *conn) -{ - uint8_t type; - - GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &type)); - S2N_ERROR_IF(type != CHANGE_CIPHER_SPEC_TYPE, S2N_ERR_BAD_MESSAGE); - - return 0; -} - -int s2n_client_ccs_recv(struct s2n_connection *conn) -{ - 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)); - - /* Compute the finished message */ - GUARD(s2n_prf_client_finished(conn)); - - /* Update the client to use the cipher-suite */ - conn->client = &conn->secure; - - /* 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)); - - return 0; -} - -int s2n_server_ccs_recv(struct s2n_connection *conn) -{ - 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)); - - /* Compute the finished message */ - GUARD(s2n_prf_server_finished(conn)); - - /* Update the secure state to active, and point the client at the active state */ - conn->server = &conn->secure; - - /* 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)); - - return 0; -} - -int s2n_ccs_send(struct s2n_connection *conn) -{ - GUARD(s2n_stuffer_write_uint8(&conn->handshake.io, CHANGE_CIPHER_SPEC_TYPE)); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <stdint.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_safety.h" + +/* From RFC5246 7.1: https://tools.ietf.org/html/rfc5246#section-7.1 */ +#define CHANGE_CIPHER_SPEC_TYPE 1 + +int s2n_basic_ccs_recv(struct s2n_connection *conn) +{ + uint8_t type; + + GUARD(s2n_stuffer_read_uint8(&conn->handshake.io, &type)); + S2N_ERROR_IF(type != CHANGE_CIPHER_SPEC_TYPE, S2N_ERR_BAD_MESSAGE); + + return 0; +} + +int s2n_client_ccs_recv(struct s2n_connection *conn) +{ + 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)); + + /* Compute the finished message */ + GUARD(s2n_prf_client_finished(conn)); + + /* Update the client to use the cipher-suite */ + conn->client = &conn->secure; + + /* 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)); + + return 0; +} + +int s2n_server_ccs_recv(struct s2n_connection *conn) +{ + 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)); + + /* Compute the finished message */ + GUARD(s2n_prf_server_finished(conn)); + + /* Update the secure state to active, and point the client at the active state */ + conn->server = &conn->secure; + + /* 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)); + + return 0; +} + +int s2n_ccs_send(struct s2n_connection *conn) +{ + 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 585a1d4b3d..4343b88f00 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.c @@ -1,1127 +1,1127 @@ -/* - * 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_cipher_preferences.h" -#include <s2n.h> -#include <stdint.h> -#include <strings.h> -#include "tls/s2n_config.h" -#include "tls/s2n_kem.h" -#include "tls/s2n_kex.h" - -#include "error/s2n_errno.h" -#include "utils/s2n_safety.h" - -/* clang-format off */ -/* TLS 1.3 cipher suites, in order of preference. - * Can be added to other ciphers suite lists to enable - * TLS1.3 compatibility. */ -#define S2N_TLS13_CIPHER_SUITES_20190801 \ - &s2n_tls13_aes_256_gcm_sha384, \ - &s2n_tls13_aes_128_gcm_sha256, \ - &s2n_tls13_chacha20_poly1305_sha256 - -#define S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716 \ - &s2n_tls13_aes_128_gcm_sha256, \ - &s2n_tls13_aes_256_gcm_sha384, \ - &s2n_tls13_chacha20_poly1305_sha256 - -/* s2n's list of cipher suites, in order of preferences, as of 2019-08-01 */ -struct s2n_cipher_suite *cipher_suites_20190801[] = { - S2N_TLS13_CIPHER_SUITES_20190801, - &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, - &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, - &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_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_20190801 = { - .count = s2n_array_len(cipher_suites_20190801), - .suites = cipher_suites_20190801, -}; - -/* 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, - &s2n_dhe_rsa_with_aes_128_cbc_sha, - &s2n_dhe_rsa_with_3des_ede_cbc_sha, - &s2n_rsa_with_aes_128_cbc_sha256, - &s2n_rsa_with_aes_128_cbc_sha, - &s2n_rsa_with_3des_ede_cbc_sha, - &s2n_rsa_with_rc4_128_sha, - &s2n_rsa_with_rc4_128_md5 -}; - -const struct s2n_cipher_preferences cipher_preferences_20140601 = { - .count = s2n_array_len(cipher_suites_20140601), - .suites = cipher_suites_20140601, -}; - -/* Disable SSLv3 due to POODLE */ -const struct s2n_cipher_preferences cipher_preferences_20141001 = { - .count = s2n_array_len(cipher_suites_20140601), - .suites = cipher_suites_20140601, -}; - -/* Disable RC4 */ -struct s2n_cipher_suite *cipher_suites_20150202[] = { - &s2n_dhe_rsa_with_aes_128_cbc_sha256, - &s2n_dhe_rsa_with_aes_128_cbc_sha, - &s2n_dhe_rsa_with_3des_ede_cbc_sha, - &s2n_rsa_with_aes_128_cbc_sha256, - &s2n_rsa_with_aes_128_cbc_sha, - &s2n_rsa_with_3des_ede_cbc_sha -}; - -const struct s2n_cipher_preferences cipher_preferences_20150202 = { - .count = s2n_array_len(cipher_suites_20150202), - .suites = cipher_suites_20150202, -}; - -/* Support AES-GCM modes */ -struct s2n_cipher_suite *cipher_suites_20150214[] = { - &s2n_dhe_rsa_with_aes_128_gcm_sha256, - &s2n_dhe_rsa_with_aes_128_cbc_sha256, - &s2n_dhe_rsa_with_aes_128_cbc_sha, - &s2n_dhe_rsa_with_3des_ede_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_3des_ede_cbc_sha -}; - -const struct s2n_cipher_preferences cipher_preferences_20150214 = { - .count = s2n_array_len(cipher_suites_20150214), - .suites = cipher_suites_20150214, -}; - -/* Make a CBC cipher #1 to avoid negotiating GCM with buggy Java clients */ -struct s2n_cipher_suite *cipher_suites_20160411[] = { - &s2n_ecdhe_rsa_with_aes_128_cbc_sha, - &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_sha, - &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, -}; - -const struct s2n_cipher_preferences cipher_preferences_20160411 = { - .count = s2n_array_len(cipher_suites_20160411), - .suites = cipher_suites_20160411, -}; - -/* Use ECDHE instead of plain DHE. Prioritize ECDHE in favour of non ECDHE; GCM in favour of CBC; AES128 in favour of AES256. */ -struct s2n_cipher_suite *cipher_suites_20150306[] = { - &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_3des_ede_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, - &s2n_rsa_with_3des_ede_cbc_sha -}; - -const struct s2n_cipher_preferences cipher_preferences_20150306 = { - .count = s2n_array_len(cipher_suites_20150306), - .suites = cipher_suites_20150306, -}; - -struct s2n_cipher_suite *cipher_suites_20160804[] = { - &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 -}; - -const struct s2n_cipher_preferences cipher_preferences_20160804 = { - .count = s2n_array_len(cipher_suites_20160804), - .suites = cipher_suites_20160804, -}; - -struct s2n_cipher_suite *cipher_suites_20160824[] = { - &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_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_20160824 = { - .count = s2n_array_len(cipher_suites_20160824), - .suites = cipher_suites_20160824, -}; - -/* Add ChaCha20 suite */ -struct s2n_cipher_suite *cipher_suites_20170210[] = { - &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, - &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, - &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_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_20170210 = { - .count = s2n_array_len(cipher_suites_20170210), - .suites = cipher_suites_20170210, -}; - -/* Same as 20160411, but with ChaCha20 added as 1st in Preference List */ -struct s2n_cipher_suite *cipher_suites_20190122[] = { - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, - &s2n_ecdhe_rsa_with_aes_128_cbc_sha, - &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_sha, - &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, -}; - -const struct s2n_cipher_preferences cipher_preferences_20190122 = { - .count = s2n_array_len(cipher_suites_20190122), - .suites = cipher_suites_20190122, -}; - -/* Same as 20160804, but with ChaCha20 added as 2nd in Preference List */ -struct s2n_cipher_suite *cipher_suites_20190121[] = { - &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, - &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, - &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 -}; - -const struct s2n_cipher_preferences cipher_preferences_20190121 = { - .count = s2n_array_len(cipher_suites_20190121), - .suites = cipher_suites_20190121, -}; - -/* Same as 20160411, but with ChaCha20 in 3rd Place after CBC and GCM */ -struct s2n_cipher_suite *cipher_suites_20190120[] = { - &s2n_ecdhe_rsa_with_aes_128_cbc_sha, - &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, - &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, - &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_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, -}; - -const struct s2n_cipher_preferences cipher_preferences_20190120 = { - .count = s2n_array_len(cipher_suites_20190120), - .suites = cipher_suites_20190120, -}; - -/* Preferences optimized for interop, includes ECDSA priortitized. DHE and 3DES are added(at the lowest preference). */ -struct s2n_cipher_suite *cipher_suites_20190214[] = { - &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_20190214 = { - .count = s2n_array_len(cipher_suites_20190214), - .suites = cipher_suites_20190214, -}; - -struct s2n_cipher_suite *cipher_suites_null[] = { - &s2n_null_cipher_suite -}; - -const struct s2n_cipher_preferences cipher_preferences_null = { - .count = s2n_array_len(cipher_suites_null), - .suites = cipher_suites_null, -}; - -/* Preferences optimized for interop. DHE and 3DES are added(at the lowest preference). */ -struct s2n_cipher_suite *cipher_suites_20170328[] = { - &s2n_ecdhe_rsa_with_aes_128_cbc_sha, - &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_sha, - &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_20170328 = { - .count = s2n_array_len(cipher_suites_20170328), - .suites = cipher_suites_20170328, -}; - -/* Preferences optimized for FIPS compatibility. */ -struct s2n_cipher_suite *cipher_suites_20170405[] = { - &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, - &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, - &s2n_ecdhe_rsa_with_aes_256_gcm_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, -}; - -const struct s2n_cipher_preferences cipher_preferences_20170405 = { - .count = s2n_array_len(cipher_suites_20170405), - .suites = cipher_suites_20170405, -}; - -/* 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[] = { - &s2n_ecdhe_rsa_with_aes_128_cbc_sha, - &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_sha, - &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, -}; - -const struct s2n_cipher_preferences cipher_preferences_20170718 = { - .count = s2n_array_len(cipher_suites_20170718), - .suites = cipher_suites_20170718, -}; - -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, - &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, - &s2n_rsa_with_3des_ede_cbc_sha, -}; - -const struct s2n_cipher_preferences elb_security_policy_2015_04 = { - .count = s2n_array_len(cipher_suites_elb_security_policy_2015_04), - .suites = cipher_suites_elb_security_policy_2015_04, -}; - -struct s2n_cipher_suite *cipher_suites_elb_security_policy_2016_08[] = { - &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 elb_security_policy_2016_08 = { - .count = s2n_array_len(cipher_suites_elb_security_policy_2016_08), - .suites = cipher_suites_elb_security_policy_2016_08, -}; - -struct s2n_cipher_suite *cipher_suites_elb_security_policy_tls_1_2_2017_01[] = { - &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_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_rsa_with_aes_128_gcm_sha256, - &s2n_rsa_with_aes_128_cbc_sha256, - &s2n_rsa_with_aes_256_gcm_sha384, - &s2n_rsa_with_aes_256_cbc_sha256, -}; - -const struct s2n_cipher_preferences elb_security_policy_tls_1_2_2017_01 = { - .count = s2n_array_len(cipher_suites_elb_security_policy_tls_1_2_2017_01), - .suites = cipher_suites_elb_security_policy_tls_1_2_2017_01, -}; - -struct s2n_cipher_suite *cipher_suites_elb_security_policy_tls_1_1_2017_01[] = { - &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 elb_security_policy_tls_1_1_2017_01 = { - .count = s2n_array_len(cipher_suites_elb_security_policy_tls_1_1_2017_01), - .suites = cipher_suites_elb_security_policy_tls_1_1_2017_01, -}; - -struct s2n_cipher_suite *cipher_suites_elb_security_policy_tls_1_2_ext_2018_06[] = { - &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 elb_security_policy_tls_1_2_ext_2018_06 = { - .count = s2n_array_len(cipher_suites_elb_security_policy_tls_1_2_ext_2018_06), - .suites = cipher_suites_elb_security_policy_tls_1_2_ext_2018_06, -}; - -struct s2n_cipher_suite *cipher_suites_elb_security_policy_fs_2018_06[] = { - &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, -}; - -const struct s2n_cipher_preferences elb_security_policy_fs_2018_06 = { - .count = s2n_array_len(cipher_suites_elb_security_policy_fs_2018_06), - .suites = cipher_suites_elb_security_policy_fs_2018_06, -}; - -struct s2n_cipher_suite *cipher_suites_elb_security_policy_fs_1_2_2019_08[] = { - &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, -}; - -const struct s2n_cipher_preferences elb_security_policy_fs_1_2_2019_08 = { - .count = s2n_array_len(cipher_suites_elb_security_policy_fs_1_2_2019_08), - .suites = cipher_suites_elb_security_policy_fs_1_2_2019_08, -}; - -struct s2n_cipher_suite *cipher_suites_elb_security_policy_fs_1_1_2019_08[] = { - &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, -}; - -const struct s2n_cipher_preferences elb_security_policy_fs_1_1_2019_08 = { - .count = s2n_array_len(cipher_suites_elb_security_policy_fs_1_1_2019_08), - .suites = cipher_suites_elb_security_policy_fs_1_1_2019_08, -}; - -struct s2n_cipher_suite *cipher_suites_elb_security_policy_fs_1_2_Res_2019_08[] = { - &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_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 elb_security_policy_fs_1_2_Res_2019_08 = { - .count = s2n_array_len(cipher_suites_elb_security_policy_fs_1_2_Res_2019_08), - .suites = cipher_suites_elb_security_policy_fs_1_2_Res_2019_08, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_upstream[] = { - &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, - &s2n_ecdhe_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_cbc_sha384, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha, - &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_rsa_with_aes_256_gcm_sha384, - &s2n_rsa_with_aes_128_gcm_sha256, - &s2n_rsa_with_aes_256_cbc_sha, - &s2n_rsa_with_aes_128_cbc_sha256, - &s2n_rsa_with_aes_128_cbc_sha, - &s2n_rsa_with_3des_ede_cbc_sha, - &s2n_rsa_with_rc4_128_md5 -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream = { - .count = s2n_array_len(cipher_suites_cloudfront_upstream), - .suites = cipher_suites_cloudfront_upstream, -}; - -/* CloudFront viewer facing (with TLS 1.3) */ -struct s2n_cipher_suite *cipher_suites_cloudfront_ssl_v_3[] = { - S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716, - &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, - &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, - &s2n_ecdhe_rsa_with_aes_128_cbc_sha, - &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, - &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_sha, - &s2n_rsa_with_aes_128_cbc_sha, - &s2n_rsa_with_3des_ede_cbc_sha, - &s2n_rsa_with_rc4_128_md5 -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_ssl_v_3 = { - .count = s2n_array_len(cipher_suites_cloudfront_ssl_v_3), - .suites = cipher_suites_cloudfront_ssl_v_3, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_0_2014[] = { - 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_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_chacha20_poly1305_sha256, - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, - &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_sha, - &s2n_rsa_with_aes_128_cbc_sha, - &s2n_rsa_with_3des_ede_cbc_sha, -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2014 = { - .count = s2n_array_len(cipher_suites_cloudfront_tls_1_0_2014), - .suites = cipher_suites_cloudfront_tls_1_0_2014, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_0_2016[] = { - 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_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_chacha20_poly1305_sha256, - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, - &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_sha, - &s2n_rsa_with_aes_128_cbc_sha -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2016 = { - .count = s2n_array_len(cipher_suites_cloudfront_tls_1_0_2016), - .suites = cipher_suites_cloudfront_tls_1_0_2016, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_1_2016[] = { - 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_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_chacha20_poly1305_sha256, - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, - &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_sha, - &s2n_rsa_with_aes_128_cbc_sha -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_1_2016 = { - .count = s2n_array_len(cipher_suites_cloudfront_tls_1_1_2016), - .suites = cipher_suites_cloudfront_tls_1_1_2016, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_2_2018[] = { - 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_128_cbc_sha256, - &s2n_ecdhe_rsa_with_aes_128_cbc_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_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_sha256 -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2018 = { - .count = s2n_array_len(cipher_suites_cloudfront_tls_1_2_2018), - .suites = cipher_suites_cloudfront_tls_1_2_2018, -}; - -/* CloudFront viewer facing legacy TLS 1.2 policies */ -struct s2n_cipher_suite *cipher_suites_cloudfront_ssl_v_3_legacy[] = { - &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_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_sha, - &s2n_rsa_with_aes_128_cbc_sha, - &s2n_rsa_with_3des_ede_cbc_sha, - &s2n_rsa_with_rc4_128_md5 -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_ssl_v_3_legacy = { - .count = s2n_array_len(cipher_suites_cloudfront_ssl_v_3_legacy), - .suites = cipher_suites_cloudfront_ssl_v_3_legacy, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_0_2014_legacy[] = { - &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_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_sha, - &s2n_rsa_with_aes_128_cbc_sha, - &s2n_rsa_with_3des_ede_cbc_sha, -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2014_legacy = { - .count = s2n_array_len(cipher_suites_cloudfront_tls_1_0_2014_legacy), - .suites = cipher_suites_cloudfront_tls_1_0_2014_legacy, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_0_2016_legacy[] = { - &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_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_sha, - &s2n_rsa_with_aes_128_cbc_sha -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2016_legacy = { - .count = s2n_array_len(cipher_suites_cloudfront_tls_1_0_2016_legacy), - .suites = cipher_suites_cloudfront_tls_1_0_2016_legacy, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_1_2016_legacy[] = { - &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_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_sha, - &s2n_rsa_with_aes_128_cbc_sha -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_1_2016_legacy = { - .count = s2n_array_len(cipher_suites_cloudfront_tls_1_1_2016_legacy), - .suites = cipher_suites_cloudfront_tls_1_1_2016_legacy, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_2_2018_legacy[] = { - &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_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_rsa_with_aes_128_gcm_sha256, - &s2n_rsa_with_aes_256_gcm_sha384, - &s2n_rsa_with_aes_128_cbc_sha256 -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2018_legacy = { - .count = s2n_array_len(cipher_suites_cloudfront_tls_1_2_2018_legacy), - .suites = cipher_suites_cloudfront_tls_1_2_2018_legacy, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_2_2019_legacy[] = { - &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_256_cbc_sha384, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, - &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, - &s2n_ecdhe_rsa_with_aes_128_cbc_sha256 -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2019_legacy = { - .count = s2n_array_len(cipher_suites_cloudfront_tls_1_2_2019_legacy), - .suites = cipher_suites_cloudfront_tls_1_2_2019_legacy, -}; - -/* CloudFront upstream */ -struct s2n_cipher_suite *cipher_suites_cloudfront_upstream_tls10[] = { - &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, - &s2n_ecdhe_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_cbc_sha384, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha, - &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_rsa_with_aes_256_gcm_sha384, - &s2n_rsa_with_aes_128_gcm_sha256, - &s2n_rsa_with_aes_256_cbc_sha, - &s2n_rsa_with_aes_128_cbc_sha256, - &s2n_rsa_with_aes_128_cbc_sha, - &s2n_rsa_with_3des_ede_cbc_sha, - &s2n_rsa_with_rc4_128_md5 -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls10 = { - .count = s2n_array_len(cipher_suites_cloudfront_upstream_tls10), - .suites = cipher_suites_cloudfront_upstream_tls10, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_upstream_tls11[] = { - &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, - &s2n_ecdhe_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_cbc_sha384, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha, - &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_rsa_with_aes_256_gcm_sha384, - &s2n_rsa_with_aes_128_gcm_sha256, - &s2n_rsa_with_aes_256_cbc_sha, - &s2n_rsa_with_aes_128_cbc_sha256, - &s2n_rsa_with_aes_128_cbc_sha, - &s2n_rsa_with_3des_ede_cbc_sha, - &s2n_rsa_with_rc4_128_md5 -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls11 = { - .count = s2n_array_len(cipher_suites_cloudfront_upstream_tls11), - .suites = cipher_suites_cloudfront_upstream_tls11, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_upstream_tls12[] = { - &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, - &s2n_ecdhe_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_cbc_sha384, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha, - &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_rsa_with_aes_256_gcm_sha384, - &s2n_rsa_with_aes_128_gcm_sha256, - &s2n_rsa_with_aes_256_cbc_sha, - &s2n_rsa_with_aes_128_cbc_sha256, - &s2n_rsa_with_aes_128_cbc_sha, - &s2n_rsa_with_3des_ede_cbc_sha, - &s2n_rsa_with_rc4_128_md5 -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls12 = { - .count = s2n_array_len(cipher_suites_cloudfront_upstream_tls12), - .suites = cipher_suites_cloudfront_upstream_tls12, -}; - -struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_2_2019[] = { - 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_256_cbc_sha384, - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, - &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, - &s2n_ecdhe_rsa_with_aes_128_cbc_sha256 -}; - -const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2019 = { - .count = s2n_array_len(cipher_suites_cloudfront_tls_1_2_2019), - .suites = cipher_suites_cloudfront_tls_1_2_2019, -}; - -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, - &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_2018_10 = { - .count = s2n_array_len(cipher_suites_kms_tls_1_0_2018_10), - .suites = cipher_suites_kms_tls_1_0_2018_10, -}; - -#if !defined(S2N_NO_PQ) - -struct s2n_cipher_suite *cipher_suites_kms_pq_tls_1_0_2019_06[] = { - &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384, - &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384, - &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, -}; - -/* Includes only round 1 PQ KEM params */ -const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2019_06 = { - .count = s2n_array_len(cipher_suites_kms_pq_tls_1_0_2019_06), - .suites = cipher_suites_kms_pq_tls_1_0_2019_06, -}; - -/* Includes round 1 and round 2 PQ KEM params. The cipher suite list is the same - * as in cipher_preferences_kms_pq_tls_1_0_2019_06.*/ -const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2020_02 = { - .count = s2n_array_len(cipher_suites_kms_pq_tls_1_0_2019_06), - .suites = cipher_suites_kms_pq_tls_1_0_2019_06, -}; - -struct s2n_cipher_suite *cipher_suites_pq_sike_test_tls_1_0_2019_11[] = { - &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, -}; - -/* Includes only SIKE round 1 (for integration tests) */ -const struct s2n_cipher_preferences cipher_preferences_pq_sike_test_tls_1_0_2019_11 = { - .count = s2n_array_len(cipher_suites_pq_sike_test_tls_1_0_2019_11), - .suites = cipher_suites_pq_sike_test_tls_1_0_2019_11, -}; - -/* Includes only SIKE round 1 and round 2 (for integration tests). The cipher suite list - * is the same as in cipher_preferences_pq_sike_test_tls_1_0_2019_11. */ -const struct s2n_cipher_preferences cipher_preferences_pq_sike_test_tls_1_0_2020_02 = { - .count = s2n_array_len(cipher_suites_pq_sike_test_tls_1_0_2019_11), - .suites = cipher_suites_pq_sike_test_tls_1_0_2019_11, -}; - -/* Includes Both Round 2 and Round 1 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, - &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_kms_pq_tls_1_0_2020_07 = { - .count = s2n_array_len(cipher_suites_kms_pq_tls_1_0_2020_07), - .suites = cipher_suites_kms_pq_tls_1_0_2020_07, -}; - -struct s2n_cipher_suite *cipher_suites_pq_tls_1_0_2020_12[] = { - 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_2020_12 = { - .count = s2n_array_len(cipher_suites_pq_tls_1_0_2020_12), - .suites = cipher_suites_pq_tls_1_0_2020_12, -}; - -#endif - -struct s2n_cipher_suite *cipher_suites_kms_fips_tls_1_2_2018_10[] = { - &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, - &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, - &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_2018_10 = { - .count = s2n_array_len(cipher_suites_kms_fips_tls_1_2_2018_10), - .suites = cipher_suites_kms_fips_tls_1_2_2018_10, -}; - -/* clang-format on */ +/* + * 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_cipher_preferences.h" +#include <s2n.h> +#include <stdint.h> +#include <strings.h> +#include "tls/s2n_config.h" +#include "tls/s2n_kem.h" +#include "tls/s2n_kex.h" + +#include "error/s2n_errno.h" +#include "utils/s2n_safety.h" + +/* clang-format off */ +/* TLS 1.3 cipher suites, in order of preference. + * Can be added to other ciphers suite lists to enable + * TLS1.3 compatibility. */ +#define S2N_TLS13_CIPHER_SUITES_20190801 \ + &s2n_tls13_aes_256_gcm_sha384, \ + &s2n_tls13_aes_128_gcm_sha256, \ + &s2n_tls13_chacha20_poly1305_sha256 + +#define S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716 \ + &s2n_tls13_aes_128_gcm_sha256, \ + &s2n_tls13_aes_256_gcm_sha384, \ + &s2n_tls13_chacha20_poly1305_sha256 + +/* s2n's list of cipher suites, in order of preferences, as of 2019-08-01 */ +struct s2n_cipher_suite *cipher_suites_20190801[] = { + S2N_TLS13_CIPHER_SUITES_20190801, + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, + &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_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_20190801 = { + .count = s2n_array_len(cipher_suites_20190801), + .suites = cipher_suites_20190801, +}; + +/* 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, + &s2n_dhe_rsa_with_aes_128_cbc_sha, + &s2n_dhe_rsa_with_3des_ede_cbc_sha, + &s2n_rsa_with_aes_128_cbc_sha256, + &s2n_rsa_with_aes_128_cbc_sha, + &s2n_rsa_with_3des_ede_cbc_sha, + &s2n_rsa_with_rc4_128_sha, + &s2n_rsa_with_rc4_128_md5 +}; + +const struct s2n_cipher_preferences cipher_preferences_20140601 = { + .count = s2n_array_len(cipher_suites_20140601), + .suites = cipher_suites_20140601, +}; + +/* Disable SSLv3 due to POODLE */ +const struct s2n_cipher_preferences cipher_preferences_20141001 = { + .count = s2n_array_len(cipher_suites_20140601), + .suites = cipher_suites_20140601, +}; + +/* Disable RC4 */ +struct s2n_cipher_suite *cipher_suites_20150202[] = { + &s2n_dhe_rsa_with_aes_128_cbc_sha256, + &s2n_dhe_rsa_with_aes_128_cbc_sha, + &s2n_dhe_rsa_with_3des_ede_cbc_sha, + &s2n_rsa_with_aes_128_cbc_sha256, + &s2n_rsa_with_aes_128_cbc_sha, + &s2n_rsa_with_3des_ede_cbc_sha +}; + +const struct s2n_cipher_preferences cipher_preferences_20150202 = { + .count = s2n_array_len(cipher_suites_20150202), + .suites = cipher_suites_20150202, +}; + +/* Support AES-GCM modes */ +struct s2n_cipher_suite *cipher_suites_20150214[] = { + &s2n_dhe_rsa_with_aes_128_gcm_sha256, + &s2n_dhe_rsa_with_aes_128_cbc_sha256, + &s2n_dhe_rsa_with_aes_128_cbc_sha, + &s2n_dhe_rsa_with_3des_ede_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_3des_ede_cbc_sha +}; + +const struct s2n_cipher_preferences cipher_preferences_20150214 = { + .count = s2n_array_len(cipher_suites_20150214), + .suites = cipher_suites_20150214, +}; + +/* Make a CBC cipher #1 to avoid negotiating GCM with buggy Java clients */ +struct s2n_cipher_suite *cipher_suites_20160411[] = { + &s2n_ecdhe_rsa_with_aes_128_cbc_sha, + &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_sha, + &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, +}; + +const struct s2n_cipher_preferences cipher_preferences_20160411 = { + .count = s2n_array_len(cipher_suites_20160411), + .suites = cipher_suites_20160411, +}; + +/* Use ECDHE instead of plain DHE. Prioritize ECDHE in favour of non ECDHE; GCM in favour of CBC; AES128 in favour of AES256. */ +struct s2n_cipher_suite *cipher_suites_20150306[] = { + &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_3des_ede_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, + &s2n_rsa_with_3des_ede_cbc_sha +}; + +const struct s2n_cipher_preferences cipher_preferences_20150306 = { + .count = s2n_array_len(cipher_suites_20150306), + .suites = cipher_suites_20150306, +}; + +struct s2n_cipher_suite *cipher_suites_20160804[] = { + &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 +}; + +const struct s2n_cipher_preferences cipher_preferences_20160804 = { + .count = s2n_array_len(cipher_suites_20160804), + .suites = cipher_suites_20160804, +}; + +struct s2n_cipher_suite *cipher_suites_20160824[] = { + &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_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_20160824 = { + .count = s2n_array_len(cipher_suites_20160824), + .suites = cipher_suites_20160824, +}; + +/* Add ChaCha20 suite */ +struct s2n_cipher_suite *cipher_suites_20170210[] = { + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, + &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_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_20170210 = { + .count = s2n_array_len(cipher_suites_20170210), + .suites = cipher_suites_20170210, +}; + +/* Same as 20160411, but with ChaCha20 added as 1st in Preference List */ +struct s2n_cipher_suite *cipher_suites_20190122[] = { + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, + &s2n_ecdhe_rsa_with_aes_128_cbc_sha, + &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_sha, + &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, +}; + +const struct s2n_cipher_preferences cipher_preferences_20190122 = { + .count = s2n_array_len(cipher_suites_20190122), + .suites = cipher_suites_20190122, +}; + +/* Same as 20160804, but with ChaCha20 added as 2nd in Preference List */ +struct s2n_cipher_suite *cipher_suites_20190121[] = { + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, + &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 +}; + +const struct s2n_cipher_preferences cipher_preferences_20190121 = { + .count = s2n_array_len(cipher_suites_20190121), + .suites = cipher_suites_20190121, +}; + +/* Same as 20160411, but with ChaCha20 in 3rd Place after CBC and GCM */ +struct s2n_cipher_suite *cipher_suites_20190120[] = { + &s2n_ecdhe_rsa_with_aes_128_cbc_sha, + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, + &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_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, +}; + +const struct s2n_cipher_preferences cipher_preferences_20190120 = { + .count = s2n_array_len(cipher_suites_20190120), + .suites = cipher_suites_20190120, +}; + +/* Preferences optimized for interop, includes ECDSA priortitized. DHE and 3DES are added(at the lowest preference). */ +struct s2n_cipher_suite *cipher_suites_20190214[] = { + &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_20190214 = { + .count = s2n_array_len(cipher_suites_20190214), + .suites = cipher_suites_20190214, +}; + +struct s2n_cipher_suite *cipher_suites_null[] = { + &s2n_null_cipher_suite +}; + +const struct s2n_cipher_preferences cipher_preferences_null = { + .count = s2n_array_len(cipher_suites_null), + .suites = cipher_suites_null, +}; + +/* Preferences optimized for interop. DHE and 3DES are added(at the lowest preference). */ +struct s2n_cipher_suite *cipher_suites_20170328[] = { + &s2n_ecdhe_rsa_with_aes_128_cbc_sha, + &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_sha, + &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_20170328 = { + .count = s2n_array_len(cipher_suites_20170328), + .suites = cipher_suites_20170328, +}; + +/* Preferences optimized for FIPS compatibility. */ +struct s2n_cipher_suite *cipher_suites_20170405[] = { + &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, + &s2n_ecdhe_rsa_with_aes_256_gcm_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, +}; + +const struct s2n_cipher_preferences cipher_preferences_20170405 = { + .count = s2n_array_len(cipher_suites_20170405), + .suites = cipher_suites_20170405, +}; + +/* 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[] = { + &s2n_ecdhe_rsa_with_aes_128_cbc_sha, + &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_sha, + &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, +}; + +const struct s2n_cipher_preferences cipher_preferences_20170718 = { + .count = s2n_array_len(cipher_suites_20170718), + .suites = cipher_suites_20170718, +}; + +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, + &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, + &s2n_rsa_with_3des_ede_cbc_sha, +}; + +const struct s2n_cipher_preferences elb_security_policy_2015_04 = { + .count = s2n_array_len(cipher_suites_elb_security_policy_2015_04), + .suites = cipher_suites_elb_security_policy_2015_04, +}; + +struct s2n_cipher_suite *cipher_suites_elb_security_policy_2016_08[] = { + &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 elb_security_policy_2016_08 = { + .count = s2n_array_len(cipher_suites_elb_security_policy_2016_08), + .suites = cipher_suites_elb_security_policy_2016_08, +}; + +struct s2n_cipher_suite *cipher_suites_elb_security_policy_tls_1_2_2017_01[] = { + &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_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_rsa_with_aes_128_gcm_sha256, + &s2n_rsa_with_aes_128_cbc_sha256, + &s2n_rsa_with_aes_256_gcm_sha384, + &s2n_rsa_with_aes_256_cbc_sha256, +}; + +const struct s2n_cipher_preferences elb_security_policy_tls_1_2_2017_01 = { + .count = s2n_array_len(cipher_suites_elb_security_policy_tls_1_2_2017_01), + .suites = cipher_suites_elb_security_policy_tls_1_2_2017_01, +}; + +struct s2n_cipher_suite *cipher_suites_elb_security_policy_tls_1_1_2017_01[] = { + &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 elb_security_policy_tls_1_1_2017_01 = { + .count = s2n_array_len(cipher_suites_elb_security_policy_tls_1_1_2017_01), + .suites = cipher_suites_elb_security_policy_tls_1_1_2017_01, +}; + +struct s2n_cipher_suite *cipher_suites_elb_security_policy_tls_1_2_ext_2018_06[] = { + &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 elb_security_policy_tls_1_2_ext_2018_06 = { + .count = s2n_array_len(cipher_suites_elb_security_policy_tls_1_2_ext_2018_06), + .suites = cipher_suites_elb_security_policy_tls_1_2_ext_2018_06, +}; + +struct s2n_cipher_suite *cipher_suites_elb_security_policy_fs_2018_06[] = { + &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, +}; + +const struct s2n_cipher_preferences elb_security_policy_fs_2018_06 = { + .count = s2n_array_len(cipher_suites_elb_security_policy_fs_2018_06), + .suites = cipher_suites_elb_security_policy_fs_2018_06, +}; + +struct s2n_cipher_suite *cipher_suites_elb_security_policy_fs_1_2_2019_08[] = { + &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, +}; + +const struct s2n_cipher_preferences elb_security_policy_fs_1_2_2019_08 = { + .count = s2n_array_len(cipher_suites_elb_security_policy_fs_1_2_2019_08), + .suites = cipher_suites_elb_security_policy_fs_1_2_2019_08, +}; + +struct s2n_cipher_suite *cipher_suites_elb_security_policy_fs_1_1_2019_08[] = { + &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, +}; + +const struct s2n_cipher_preferences elb_security_policy_fs_1_1_2019_08 = { + .count = s2n_array_len(cipher_suites_elb_security_policy_fs_1_1_2019_08), + .suites = cipher_suites_elb_security_policy_fs_1_1_2019_08, +}; + +struct s2n_cipher_suite *cipher_suites_elb_security_policy_fs_1_2_Res_2019_08[] = { + &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_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 elb_security_policy_fs_1_2_Res_2019_08 = { + .count = s2n_array_len(cipher_suites_elb_security_policy_fs_1_2_Res_2019_08), + .suites = cipher_suites_elb_security_policy_fs_1_2_Res_2019_08, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_upstream[] = { + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_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_cbc_sha384, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha, + &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_rsa_with_aes_256_gcm_sha384, + &s2n_rsa_with_aes_128_gcm_sha256, + &s2n_rsa_with_aes_256_cbc_sha, + &s2n_rsa_with_aes_128_cbc_sha256, + &s2n_rsa_with_aes_128_cbc_sha, + &s2n_rsa_with_3des_ede_cbc_sha, + &s2n_rsa_with_rc4_128_md5 +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream = { + .count = s2n_array_len(cipher_suites_cloudfront_upstream), + .suites = cipher_suites_cloudfront_upstream, +}; + +/* CloudFront viewer facing (with TLS 1.3) */ +struct s2n_cipher_suite *cipher_suites_cloudfront_ssl_v_3[] = { + S2N_TLS13_CLOUDFRONT_CIPHER_SUITES_20200716, + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, + &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, + &s2n_ecdhe_rsa_with_aes_128_cbc_sha, + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + &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_sha, + &s2n_rsa_with_aes_128_cbc_sha, + &s2n_rsa_with_3des_ede_cbc_sha, + &s2n_rsa_with_rc4_128_md5 +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_ssl_v_3 = { + .count = s2n_array_len(cipher_suites_cloudfront_ssl_v_3), + .suites = cipher_suites_cloudfront_ssl_v_3, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_0_2014[] = { + 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_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_chacha20_poly1305_sha256, + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + &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_sha, + &s2n_rsa_with_aes_128_cbc_sha, + &s2n_rsa_with_3des_ede_cbc_sha, +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2014 = { + .count = s2n_array_len(cipher_suites_cloudfront_tls_1_0_2014), + .suites = cipher_suites_cloudfront_tls_1_0_2014, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_0_2016[] = { + 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_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_chacha20_poly1305_sha256, + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + &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_sha, + &s2n_rsa_with_aes_128_cbc_sha +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2016 = { + .count = s2n_array_len(cipher_suites_cloudfront_tls_1_0_2016), + .suites = cipher_suites_cloudfront_tls_1_0_2016, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_1_2016[] = { + 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_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_chacha20_poly1305_sha256, + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + &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_sha, + &s2n_rsa_with_aes_128_cbc_sha +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_1_2016 = { + .count = s2n_array_len(cipher_suites_cloudfront_tls_1_1_2016), + .suites = cipher_suites_cloudfront_tls_1_1_2016, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_2_2018[] = { + 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_128_cbc_sha256, + &s2n_ecdhe_rsa_with_aes_128_cbc_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_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_sha256 +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2018 = { + .count = s2n_array_len(cipher_suites_cloudfront_tls_1_2_2018), + .suites = cipher_suites_cloudfront_tls_1_2_2018, +}; + +/* CloudFront viewer facing legacy TLS 1.2 policies */ +struct s2n_cipher_suite *cipher_suites_cloudfront_ssl_v_3_legacy[] = { + &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_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_sha, + &s2n_rsa_with_aes_128_cbc_sha, + &s2n_rsa_with_3des_ede_cbc_sha, + &s2n_rsa_with_rc4_128_md5 +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_ssl_v_3_legacy = { + .count = s2n_array_len(cipher_suites_cloudfront_ssl_v_3_legacy), + .suites = cipher_suites_cloudfront_ssl_v_3_legacy, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_0_2014_legacy[] = { + &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_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_sha, + &s2n_rsa_with_aes_128_cbc_sha, + &s2n_rsa_with_3des_ede_cbc_sha, +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2014_legacy = { + .count = s2n_array_len(cipher_suites_cloudfront_tls_1_0_2014_legacy), + .suites = cipher_suites_cloudfront_tls_1_0_2014_legacy, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_0_2016_legacy[] = { + &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_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_sha, + &s2n_rsa_with_aes_128_cbc_sha +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2016_legacy = { + .count = s2n_array_len(cipher_suites_cloudfront_tls_1_0_2016_legacy), + .suites = cipher_suites_cloudfront_tls_1_0_2016_legacy, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_1_2016_legacy[] = { + &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_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_sha, + &s2n_rsa_with_aes_128_cbc_sha +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_1_2016_legacy = { + .count = s2n_array_len(cipher_suites_cloudfront_tls_1_1_2016_legacy), + .suites = cipher_suites_cloudfront_tls_1_1_2016_legacy, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_2_2018_legacy[] = { + &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_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_rsa_with_aes_128_gcm_sha256, + &s2n_rsa_with_aes_256_gcm_sha384, + &s2n_rsa_with_aes_128_cbc_sha256 +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2018_legacy = { + .count = s2n_array_len(cipher_suites_cloudfront_tls_1_2_2018_legacy), + .suites = cipher_suites_cloudfront_tls_1_2_2018_legacy, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_2_2019_legacy[] = { + &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_256_cbc_sha384, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, + &s2n_ecdhe_rsa_with_aes_128_cbc_sha256 +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2019_legacy = { + .count = s2n_array_len(cipher_suites_cloudfront_tls_1_2_2019_legacy), + .suites = cipher_suites_cloudfront_tls_1_2_2019_legacy, +}; + +/* CloudFront upstream */ +struct s2n_cipher_suite *cipher_suites_cloudfront_upstream_tls10[] = { + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_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_cbc_sha384, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha, + &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_rsa_with_aes_256_gcm_sha384, + &s2n_rsa_with_aes_128_gcm_sha256, + &s2n_rsa_with_aes_256_cbc_sha, + &s2n_rsa_with_aes_128_cbc_sha256, + &s2n_rsa_with_aes_128_cbc_sha, + &s2n_rsa_with_3des_ede_cbc_sha, + &s2n_rsa_with_rc4_128_md5 +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls10 = { + .count = s2n_array_len(cipher_suites_cloudfront_upstream_tls10), + .suites = cipher_suites_cloudfront_upstream_tls10, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_upstream_tls11[] = { + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_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_cbc_sha384, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha, + &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_rsa_with_aes_256_gcm_sha384, + &s2n_rsa_with_aes_128_gcm_sha256, + &s2n_rsa_with_aes_256_cbc_sha, + &s2n_rsa_with_aes_128_cbc_sha256, + &s2n_rsa_with_aes_128_cbc_sha, + &s2n_rsa_with_3des_ede_cbc_sha, + &s2n_rsa_with_rc4_128_md5 +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls11 = { + .count = s2n_array_len(cipher_suites_cloudfront_upstream_tls11), + .suites = cipher_suites_cloudfront_upstream_tls11, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_upstream_tls12[] = { + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_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_cbc_sha384, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha, + &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_rsa_with_aes_256_gcm_sha384, + &s2n_rsa_with_aes_128_gcm_sha256, + &s2n_rsa_with_aes_256_cbc_sha, + &s2n_rsa_with_aes_128_cbc_sha256, + &s2n_rsa_with_aes_128_cbc_sha, + &s2n_rsa_with_3des_ede_cbc_sha, + &s2n_rsa_with_rc4_128_md5 +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls12 = { + .count = s2n_array_len(cipher_suites_cloudfront_upstream_tls12), + .suites = cipher_suites_cloudfront_upstream_tls12, +}; + +struct s2n_cipher_suite *cipher_suites_cloudfront_tls_1_2_2019[] = { + 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_256_cbc_sha384, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, + &s2n_ecdhe_rsa_with_aes_128_cbc_sha256 +}; + +const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2019 = { + .count = s2n_array_len(cipher_suites_cloudfront_tls_1_2_2019), + .suites = cipher_suites_cloudfront_tls_1_2_2019, +}; + +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, + &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_2018_10 = { + .count = s2n_array_len(cipher_suites_kms_tls_1_0_2018_10), + .suites = cipher_suites_kms_tls_1_0_2018_10, +}; + +#if !defined(S2N_NO_PQ) + +struct s2n_cipher_suite *cipher_suites_kms_pq_tls_1_0_2019_06[] = { + &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384, + &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, +}; + +/* Includes only round 1 PQ KEM params */ +const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2019_06 = { + .count = s2n_array_len(cipher_suites_kms_pq_tls_1_0_2019_06), + .suites = cipher_suites_kms_pq_tls_1_0_2019_06, +}; + +/* Includes round 1 and round 2 PQ KEM params. The cipher suite list is the same + * as in cipher_preferences_kms_pq_tls_1_0_2019_06.*/ +const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2020_02 = { + .count = s2n_array_len(cipher_suites_kms_pq_tls_1_0_2019_06), + .suites = cipher_suites_kms_pq_tls_1_0_2019_06, +}; + +struct s2n_cipher_suite *cipher_suites_pq_sike_test_tls_1_0_2019_11[] = { + &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, +}; + +/* Includes only SIKE round 1 (for integration tests) */ +const struct s2n_cipher_preferences cipher_preferences_pq_sike_test_tls_1_0_2019_11 = { + .count = s2n_array_len(cipher_suites_pq_sike_test_tls_1_0_2019_11), + .suites = cipher_suites_pq_sike_test_tls_1_0_2019_11, +}; + +/* Includes only SIKE round 1 and round 2 (for integration tests). The cipher suite list + * is the same as in cipher_preferences_pq_sike_test_tls_1_0_2019_11. */ +const struct s2n_cipher_preferences cipher_preferences_pq_sike_test_tls_1_0_2020_02 = { + .count = s2n_array_len(cipher_suites_pq_sike_test_tls_1_0_2019_11), + .suites = cipher_suites_pq_sike_test_tls_1_0_2019_11, +}; + +/* Includes Both Round 2 and Round 1 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, + &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_kms_pq_tls_1_0_2020_07 = { + .count = s2n_array_len(cipher_suites_kms_pq_tls_1_0_2020_07), + .suites = cipher_suites_kms_pq_tls_1_0_2020_07, +}; + +struct s2n_cipher_suite *cipher_suites_pq_tls_1_0_2020_12[] = { + 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_2020_12 = { + .count = s2n_array_len(cipher_suites_pq_tls_1_0_2020_12), + .suites = cipher_suites_pq_tls_1_0_2020_12, +}; + +#endif + +struct s2n_cipher_suite *cipher_suites_kms_fips_tls_1_2_2018_10[] = { + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, + &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_2018_10 = { + .count = s2n_array_len(cipher_suites_kms_fips_tls_1_2_2018_10), + .suites = cipher_suites_kms_fips_tls_1_2_2018_10, +}; + +/* 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 d48935608b..b70fa55922 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_preferences.h @@ -1,103 +1,103 @@ -/* - * 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 <stdint.h> -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_kem.h" -#include "tls/s2n_tls13.h" - -struct s2n_cipher_preferences { - uint8_t count; - struct s2n_cipher_suite **suites; -}; - -extern const struct s2n_cipher_preferences cipher_preferences_20140601; -extern const struct s2n_cipher_preferences cipher_preferences_20141001; -extern const struct s2n_cipher_preferences cipher_preferences_20150202; -extern const struct s2n_cipher_preferences cipher_preferences_20150214; -extern const struct s2n_cipher_preferences cipher_preferences_20150306; -extern const struct s2n_cipher_preferences cipher_preferences_20160411; -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_20170405; -extern const struct s2n_cipher_preferences cipher_preferences_20170718; -extern const struct s2n_cipher_preferences cipher_preferences_20190214; -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_test_all; - -extern const struct s2n_cipher_preferences cipher_preferences_test_all_tls12; -extern const struct s2n_cipher_preferences cipher_preferences_test_all_fips; -extern const struct s2n_cipher_preferences cipher_preferences_test_all_ecdsa; -extern const struct s2n_cipher_preferences cipher_preferences_test_ecdsa_priority; -extern const struct s2n_cipher_preferences cipher_preferences_test_all_rsa_kex; -extern const struct s2n_cipher_preferences cipher_preferences_test_all_tls13; - -/* See https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html */ -extern const struct s2n_cipher_preferences elb_security_policy_2015_04; -extern const struct s2n_cipher_preferences elb_security_policy_2016_08; - -extern const struct s2n_cipher_preferences elb_security_policy_tls_1_1_2017_01; -extern const struct s2n_cipher_preferences elb_security_policy_tls_1_2_2017_01; -extern const struct s2n_cipher_preferences elb_security_policy_tls_1_2_ext_2018_06; - -extern const struct s2n_cipher_preferences elb_security_policy_fs_2018_06; -extern const struct s2n_cipher_preferences elb_security_policy_fs_1_2_2019_08; -extern const struct s2n_cipher_preferences elb_security_policy_fs_1_1_2019_08; -extern const struct s2n_cipher_preferences elb_security_policy_fs_1_2_Res_2019_08; - -/* CloudFront upstream */ -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream; -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls10; -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls11; -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls12; -/* CloudFront viewer facing */ -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_ssl_v_3; -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2014; -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2016; -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_1_2016; -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2018; -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2019; - -/* CloudFront viewer facing legacy TLS 1.2 policies */ -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_ssl_v_3_legacy; -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2014_legacy; -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2016_legacy; -extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_1_2016_legacy; -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; - -#if !defined(S2N_NO_PQ) - -extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2019_06; -extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2020_02; -extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2020_07; -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; - -#endif - -extern const struct s2n_cipher_preferences cipher_preferences_kms_fips_tls_1_2_2018_10; -extern const struct s2n_cipher_preferences cipher_preferences_null; - +/* + * 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 <stdint.h> +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_kem.h" +#include "tls/s2n_tls13.h" + +struct s2n_cipher_preferences { + uint8_t count; + struct s2n_cipher_suite **suites; +}; + +extern const struct s2n_cipher_preferences cipher_preferences_20140601; +extern const struct s2n_cipher_preferences cipher_preferences_20141001; +extern const struct s2n_cipher_preferences cipher_preferences_20150202; +extern const struct s2n_cipher_preferences cipher_preferences_20150214; +extern const struct s2n_cipher_preferences cipher_preferences_20150306; +extern const struct s2n_cipher_preferences cipher_preferences_20160411; +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_20170405; +extern const struct s2n_cipher_preferences cipher_preferences_20170718; +extern const struct s2n_cipher_preferences cipher_preferences_20190214; +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_test_all; + +extern const struct s2n_cipher_preferences cipher_preferences_test_all_tls12; +extern const struct s2n_cipher_preferences cipher_preferences_test_all_fips; +extern const struct s2n_cipher_preferences cipher_preferences_test_all_ecdsa; +extern const struct s2n_cipher_preferences cipher_preferences_test_ecdsa_priority; +extern const struct s2n_cipher_preferences cipher_preferences_test_all_rsa_kex; +extern const struct s2n_cipher_preferences cipher_preferences_test_all_tls13; + +/* See https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html */ +extern const struct s2n_cipher_preferences elb_security_policy_2015_04; +extern const struct s2n_cipher_preferences elb_security_policy_2016_08; + +extern const struct s2n_cipher_preferences elb_security_policy_tls_1_1_2017_01; +extern const struct s2n_cipher_preferences elb_security_policy_tls_1_2_2017_01; +extern const struct s2n_cipher_preferences elb_security_policy_tls_1_2_ext_2018_06; + +extern const struct s2n_cipher_preferences elb_security_policy_fs_2018_06; +extern const struct s2n_cipher_preferences elb_security_policy_fs_1_2_2019_08; +extern const struct s2n_cipher_preferences elb_security_policy_fs_1_1_2019_08; +extern const struct s2n_cipher_preferences elb_security_policy_fs_1_2_Res_2019_08; + +/* CloudFront upstream */ +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls10; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls11; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_upstream_tls12; +/* CloudFront viewer facing */ +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_ssl_v_3; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2014; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2016; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_1_2016; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2018; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_2_2019; + +/* CloudFront viewer facing legacy TLS 1.2 policies */ +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_ssl_v_3_legacy; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2014_legacy; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_0_2016_legacy; +extern const struct s2n_cipher_preferences cipher_preferences_cloudfront_tls_1_1_2016_legacy; +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; + +#if !defined(S2N_NO_PQ) + +extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2019_06; +extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2020_02; +extern const struct s2n_cipher_preferences cipher_preferences_kms_pq_tls_1_0_2020_07; +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; + +#endif + +extern const struct s2n_cipher_preferences cipher_preferences_kms_fips_tls_1_2_2018_10; +extern const struct s2n_cipher_preferences cipher_preferences_null; + diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c index 0c2fdaeab2..f3597ee3c2 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.c @@ -1,1265 +1,1265 @@ -/* - * 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 <string.h> - -#include <openssl/crypto.h> - -#include "error/s2n_errno.h" - -#include "crypto/s2n_cipher.h" -#include "crypto/s2n_openssl.h" - -#include "tls/s2n_auth_selection.h" -#include "tls/s2n_kex.h" -#include "tls/s2n_security_policies.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls13.h" -#include "utils/s2n_safety.h" -#include "tls/s2n_psk.h" - -/************************* - * S2n Record Algorithms * - *************************/ -const struct s2n_record_algorithm s2n_record_alg_null = { - .cipher = &s2n_null_cipher, - .hmac_alg = S2N_HMAC_NONE, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_rc4_md5 = { - .cipher = &s2n_rc4, - .hmac_alg = S2N_HMAC_MD5, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_rc4_sslv3_md5 = { - .cipher = &s2n_rc4, - .hmac_alg = S2N_HMAC_SSLv3_MD5, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_rc4_sha = { - .cipher = &s2n_rc4, - .hmac_alg = S2N_HMAC_SHA1, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_rc4_sslv3_sha = { - .cipher = &s2n_rc4, - .hmac_alg = S2N_HMAC_SSLv3_SHA1, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_3des_sha = { - .cipher = &s2n_3des, - .hmac_alg = S2N_HMAC_SHA1, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_3des_sslv3_sha = { - .cipher = &s2n_3des, - .hmac_alg = S2N_HMAC_SSLv3_SHA1, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes128_sha = { - .cipher = &s2n_aes128, - .hmac_alg = S2N_HMAC_SHA1, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes128_sslv3_sha = { - .cipher = &s2n_aes128, - .hmac_alg = S2N_HMAC_SSLv3_SHA1, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes128_sha_composite = { - .cipher = &s2n_aes128_sha, - .hmac_alg = S2N_HMAC_NONE, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes128_sha256 = { - .cipher = &s2n_aes128, - .hmac_alg = S2N_HMAC_SHA256, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes128_sha256_composite = { - .cipher = &s2n_aes128_sha256, - .hmac_alg = S2N_HMAC_NONE, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes256_sha = { - .cipher = &s2n_aes256, - .hmac_alg = S2N_HMAC_SHA1, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes256_sslv3_sha = { - .cipher = &s2n_aes256, - .hmac_alg = S2N_HMAC_SSLv3_SHA1, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes256_sha_composite = { - .cipher = &s2n_aes256_sha, - .hmac_alg = S2N_HMAC_NONE, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes256_sha256 = { - .cipher = &s2n_aes256, - .hmac_alg = S2N_HMAC_SHA256, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes256_sha256_composite = { - .cipher = &s2n_aes256_sha256, - .hmac_alg = S2N_HMAC_NONE, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes256_sha384 = { - .cipher = &s2n_aes256, - .hmac_alg = S2N_HMAC_SHA384, - .flags = 0, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes128_gcm = { - .cipher = &s2n_aes128_gcm, - .hmac_alg = S2N_HMAC_NONE, - .flags = S2N_TLS12_AES_GCM_AEAD_NONCE, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_aes256_gcm = { - .cipher = &s2n_aes256_gcm, - .hmac_alg = S2N_HMAC_NONE, - .flags = S2N_TLS12_AES_GCM_AEAD_NONCE, - .encryption_limit = UINT64_MAX, -}; - -const struct s2n_record_algorithm s2n_record_alg_chacha20_poly1305 = { - .cipher = &s2n_chacha20_poly1305, - .hmac_alg = S2N_HMAC_NONE, - /* Per RFC 7905, ChaCha20-Poly1305 will use a nonce construction expected to be used in TLS1.3. - * Give it a distinct 1.2 nonce value in case this changes. - */ - .flags = S2N_TLS12_CHACHA_POLY_AEAD_NONCE, - .encryption_limit = UINT64_MAX, -}; - -/* TLS 1.3 Record Algorithms */ -const struct s2n_record_algorithm s2n_tls13_record_alg_aes128_gcm = { - .cipher = &s2n_tls13_aes128_gcm, - .hmac_alg = S2N_HMAC_NONE, /* previously used in 1.2 prf, we do not need this */ - .flags = S2N_TLS13_RECORD_AEAD_NONCE, - .encryption_limit = S2N_TLS13_AES_GCM_MAXIMUM_RECORD_NUMBER, -}; - -const struct s2n_record_algorithm s2n_tls13_record_alg_aes256_gcm = { - .cipher = &s2n_tls13_aes256_gcm, - .hmac_alg = S2N_HMAC_NONE, - .flags = S2N_TLS13_RECORD_AEAD_NONCE, - .encryption_limit = S2N_TLS13_AES_GCM_MAXIMUM_RECORD_NUMBER, -}; - -const struct s2n_record_algorithm s2n_tls13_record_alg_chacha20_poly1305 = { - .cipher = &s2n_chacha20_poly1305, - .hmac_alg = S2N_HMAC_NONE, - /* this mirrors s2n_record_alg_chacha20_poly1305 with the exception of TLS 1.3 nonce flag */ - .flags = S2N_TLS13_RECORD_AEAD_NONCE, - .encryption_limit = UINT64_MAX, -}; - -/********************* - * S2n Cipher Suites * - *********************/ - -/* This is the initial cipher suite, but is never negotiated */ -struct s2n_cipher_suite s2n_null_cipher_suite = { - .available = 1, - .name = "TLS_NULL_WITH_NULL_NULL", - .iana_value = { TLS_NULL_WITH_NULL_NULL }, - .key_exchange_alg = &s2n_rsa, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = &s2n_record_alg_null, -}; - -struct s2n_cipher_suite s2n_rsa_with_rc4_128_md5 = /* 0x00,0x04 */ { - .available = 0, - .name = "RC4-MD5", - .iana_value = { TLS_RSA_WITH_RC4_128_MD5 }, - .key_exchange_alg = &s2n_rsa, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_rc4_md5 }, - .num_record_algs = 1, - .sslv3_record_alg = &s2n_record_alg_rc4_sslv3_md5, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_rsa_with_rc4_128_sha = /* 0x00,0x05 */ { - .available = 0, - .name = "RC4-SHA", - .iana_value = { TLS_RSA_WITH_RC4_128_SHA }, - .key_exchange_alg = &s2n_rsa, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_rc4_sha }, - .num_record_algs = 1, - .sslv3_record_alg = &s2n_record_alg_rc4_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_rsa_with_3des_ede_cbc_sha = /* 0x00,0x0A */ { - .available = 0, - .name = "DES-CBC3-SHA", - .iana_value = { TLS_RSA_WITH_3DES_EDE_CBC_SHA }, - .key_exchange_alg = &s2n_rsa, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_3des_sha }, - .num_record_algs = 1, - .sslv3_record_alg = &s2n_record_alg_3des_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_dhe_rsa_with_3des_ede_cbc_sha = /* 0x00,0x16 */ { - .available = 0, - .name = "EDH-RSA-DES-CBC3-SHA", - .iana_value = { TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA }, - .key_exchange_alg = &s2n_dhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_3des_sha }, - .num_record_algs = 1, - .sslv3_record_alg = &s2n_record_alg_3des_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_rsa_with_aes_128_cbc_sha = /* 0x00,0x2F */ { - .available = 0, - .name = "AES128-SHA", - .iana_value = { TLS_RSA_WITH_AES_128_CBC_SHA }, - .key_exchange_alg = &s2n_rsa, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_sha_composite, &s2n_record_alg_aes128_sha }, - .num_record_algs = 2, - .sslv3_record_alg = &s2n_record_alg_aes128_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_cbc_sha = /* 0x00,0x33 */ { - .available = 0, - .name = "DHE-RSA-AES128-SHA", - .iana_value = { TLS_DHE_RSA_WITH_AES_128_CBC_SHA }, - .key_exchange_alg = &s2n_dhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_sha_composite, &s2n_record_alg_aes128_sha }, - .num_record_algs = 2, - .sslv3_record_alg = &s2n_record_alg_aes128_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_rsa_with_aes_256_cbc_sha = /* 0x00,0x35 */ { - .available = 0, - .name = "AES256-SHA", - .iana_value = { TLS_RSA_WITH_AES_256_CBC_SHA }, - .key_exchange_alg = &s2n_rsa, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_sha_composite, &s2n_record_alg_aes256_sha }, - .num_record_algs = 2, - .sslv3_record_alg = &s2n_record_alg_aes256_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_cbc_sha = /* 0x00,0x39 */ { - .available = 0, - .name = "DHE-RSA-AES256-SHA", - .iana_value = { TLS_DHE_RSA_WITH_AES_256_CBC_SHA }, - .key_exchange_alg = &s2n_dhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_sha_composite, &s2n_record_alg_aes256_sha }, - .num_record_algs = 2, - .sslv3_record_alg = &s2n_record_alg_aes256_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_rsa_with_aes_128_cbc_sha256 = /* 0x00,0x3C */ { - .available = 0, - .name = "AES128-SHA256", - .iana_value = { TLS_RSA_WITH_AES_128_CBC_SHA256 }, - .key_exchange_alg = &s2n_rsa, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_sha256_composite, &s2n_record_alg_aes128_sha256 }, - .num_record_algs = 2, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_rsa_with_aes_256_cbc_sha256 = /* 0x00,0x3D */ { - .available = 0, - .name = "AES256-SHA256", - .iana_value = { TLS_RSA_WITH_AES_256_CBC_SHA256 }, - .key_exchange_alg = &s2n_rsa, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_sha256_composite, &s2n_record_alg_aes256_sha256 }, - .num_record_algs = 2, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_cbc_sha256 = /* 0x00,0x67 */ { - .available = 0, - .name = "DHE-RSA-AES128-SHA256", - .iana_value = { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 }, - .key_exchange_alg = &s2n_dhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_sha256_composite, &s2n_record_alg_aes128_sha256 }, - .num_record_algs = 2, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_cbc_sha256 = /* 0x00,0x6B */ { - .available = 0, - .name = "DHE-RSA-AES256-SHA256", - .iana_value = { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 }, - .key_exchange_alg = &s2n_dhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_sha256_composite, &s2n_record_alg_aes256_sha256 }, - .num_record_algs = 2, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_rsa_with_aes_128_gcm_sha256 = /* 0x00,0x9C */ { - .available = 0, - .name = "AES128-GCM-SHA256", - .iana_value = { TLS_RSA_WITH_AES_128_GCM_SHA256 }, - .key_exchange_alg = &s2n_rsa, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_rsa_with_aes_256_gcm_sha384 = /* 0x00,0x9D */ { - .available = 0, - .name = "AES256-GCM-SHA384", - .iana_value = { TLS_RSA_WITH_AES_256_GCM_SHA384 }, - .key_exchange_alg = &s2n_rsa, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA384, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_gcm_sha256 = /* 0x00,0x9E */ { - .available = 0, - .name = "DHE-RSA-AES128-GCM-SHA256", - .iana_value = { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 }, - .key_exchange_alg = &s2n_dhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_gcm_sha384 = /* 0x00,0x9F */ { - .available = 0, - .name = "DHE-RSA-AES256-GCM-SHA384", - .iana_value = { TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 }, - .key_exchange_alg = &s2n_dhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA384, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_cbc_sha = /* 0xC0,0x09 */ { - .available = 0, - .name = "ECDHE-ECDSA-AES128-SHA", - .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_ECDSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_sha_composite, &s2n_record_alg_aes128_sha }, - .num_record_algs = 2, - .sslv3_record_alg = &s2n_record_alg_aes128_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_cbc_sha = /* 0xC0,0x0A */ { - .available = 0, - .name = "ECDHE-ECDSA-AES256-SHA", - .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_ECDSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_sha_composite, &s2n_record_alg_aes256_sha }, - .num_record_algs = 2, - .sslv3_record_alg = &s2n_record_alg_aes256_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_ecdhe_rsa_with_rc4_128_sha = /* 0xC0,0x11 */ { - .available = 0, - .name = "ECDHE-RSA-RC4-SHA", - .iana_value = { TLS_ECDHE_RSA_WITH_RC4_128_SHA }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_rc4_sha }, - .num_record_algs = 1, - .sslv3_record_alg = &s2n_record_alg_rc4_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_ecdhe_rsa_with_3des_ede_cbc_sha = /* 0xC0,0x12 */ { - .available = 0, - .name = "ECDHE-RSA-DES-CBC3-SHA", - .iana_value = { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_3des_sha }, - .num_record_algs = 1, - .sslv3_record_alg = &s2n_record_alg_3des_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_cbc_sha = /* 0xC0,0x13 */ { - .available = 0, - .name = "ECDHE-RSA-AES128-SHA", - .iana_value = { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_sha_composite, &s2n_record_alg_aes128_sha }, - .num_record_algs = 2, - .sslv3_record_alg = &s2n_record_alg_aes128_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_cbc_sha = /* 0xC0,0x14 */ { - .available = 0, - .name = "ECDHE-RSA-AES256-SHA", - .iana_value = { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_sha_composite, &s2n_record_alg_aes256_sha }, - .num_record_algs = 2, - .sslv3_record_alg = &s2n_record_alg_aes256_sslv3_sha, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_SSLv3, -}; - -struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256 = /* 0xC0,0x23 */ { - .available = 0, - .name = "ECDHE-ECDSA-AES128-SHA256", - .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_ECDSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_sha256_composite, &s2n_record_alg_aes128_sha256 }, - .num_record_algs = 2, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384 = /* 0xC0,0x24 */ { - .available = 0, - .name = "ECDHE-ECDSA-AES256-SHA384", - .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_ECDSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_sha384 }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA384, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_cbc_sha256 = /* 0xC0,0x27 */ { - .available = 0, - .name = "ECDHE-RSA-AES128-SHA256", - .iana_value = { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_sha256_composite, &s2n_record_alg_aes128_sha256 }, - .num_record_algs = 2, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_cbc_sha384 = /* 0xC0,0x28 */ { - .available = 0, - .name = "ECDHE-RSA-AES256-SHA384", - .iana_value = { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_sha384 }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA384, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256 = /* 0xC0,0x2B */ { - .available = 0, - .name = "ECDHE-ECDSA-AES128-GCM-SHA256", - .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_ECDSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384 = /* 0xC0,0x2C */ { - .available = 0, - .name = "ECDHE-ECDSA-AES256-GCM-SHA384", - .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_ECDSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA384, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_gcm_sha256 = /* 0xC0,0x2F */ { - .available = 0, - .name = "ECDHE-RSA-AES128-GCM-SHA256", - .iana_value = { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes128_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_gcm_sha384 = /* 0xC0,0x30 */ { - .available = 0, - .name = "ECDHE-RSA-AES256-GCM-SHA384", - .iana_value = { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA384, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_rsa_with_chacha20_poly1305_sha256 = /* 0xCC,0xA8 */ { - .available = 0, - .name = "ECDHE-RSA-CHACHA20-POLY1305", - .iana_value = { TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_chacha20_poly1305 }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256 = /* 0xCC,0xA9 */ { - .available = 0, - .name = "ECDHE-ECDSA-CHACHA20-POLY1305", - .iana_value = { TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 }, - .key_exchange_alg = &s2n_ecdhe, - .auth_method = S2N_AUTHENTICATION_ECDSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_chacha20_poly1305 }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_dhe_rsa_with_chacha20_poly1305_sha256 = /* 0xCC,0xAA */ { - .available = 0, - .name = "DHE-RSA-CHACHA20-POLY1305", - .iana_value = { TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 }, - .key_exchange_alg = &s2n_dhe, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_chacha20_poly1305 }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS12, -}; - -/* From https://tools.ietf.org/html/draft-campagna-tls-bike-sike-hybrid */ - -struct s2n_cipher_suite s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384 = /* 0xFF, 0x0C */ { - .available = 0, - .name = "ECDHE-KYBER-RSA-AES256-GCM-SHA384", - .iana_value = { TLS_ECDHE_KYBER_RSA_WITH_AES_256_GCM_SHA384 }, - .key_exchange_alg = &s2n_hybrid_ecdhe_kem, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA384, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384 = /* 0xFF, 0x04 */ { - .available = 0, - .name = "ECDHE-BIKE-RSA-AES256-GCM-SHA384", - .iana_value = { TLS_ECDHE_BIKE_RSA_WITH_AES_256_GCM_SHA384 }, - .key_exchange_alg = &s2n_hybrid_ecdhe_kem, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA384, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384 = /* 0xFF, 0x08 */ { - .available = 0, - .name = "ECDHE-SIKE-RSA-AES256-GCM-SHA384", - .iana_value = { TLS_ECDHE_SIKE_RSA_WITH_AES_256_GCM_SHA384 }, - .key_exchange_alg = &s2n_hybrid_ecdhe_kem, - .auth_method = S2N_AUTHENTICATION_RSA, - .record_alg = NULL, - .all_record_algs = { &s2n_record_alg_aes256_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA384, - .minimum_required_tls_version = S2N_TLS12, -}; - -struct s2n_cipher_suite s2n_tls13_aes_128_gcm_sha256 = { - .available = 0, - .name = "TLS_AES_128_GCM_SHA256", - .iana_value = { TLS_AES_128_GCM_SHA256 }, - .key_exchange_alg = NULL, - .auth_method = S2N_AUTHENTICATION_METHOD_TLS13, - .record_alg = NULL, - .all_record_algs = { &s2n_tls13_record_alg_aes128_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS13, -}; - -struct s2n_cipher_suite s2n_tls13_aes_256_gcm_sha384 = { - .available = 0, - .name = "TLS_AES_256_GCM_SHA384", - .iana_value = { TLS_AES_256_GCM_SHA384 }, - .key_exchange_alg = NULL, - .auth_method = S2N_AUTHENTICATION_METHOD_TLS13, - .record_alg = NULL, - .all_record_algs = { &s2n_tls13_record_alg_aes256_gcm }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA384, - .minimum_required_tls_version = S2N_TLS13, -}; - -struct s2n_cipher_suite s2n_tls13_chacha20_poly1305_sha256 = { - .available = 0, - .name = "TLS_CHACHA20_POLY1305_SHA256", - .iana_value = { TLS_CHACHA20_POLY1305_SHA256 }, - .key_exchange_alg = NULL, - .auth_method = S2N_AUTHENTICATION_METHOD_TLS13, - .record_alg = NULL, - .all_record_algs = { &s2n_tls13_record_alg_chacha20_poly1305 }, - .num_record_algs = 1, - .sslv3_record_alg = NULL, - .prf_alg = S2N_HMAC_SHA256, - .minimum_required_tls_version = S2N_TLS13, -}; - -/* All of the cipher suites that s2n negotiates in order of IANA value. - * New cipher suites MUST be added here, IN ORDER, or they will not be - * properly initialized. - */ -static struct s2n_cipher_suite *s2n_all_cipher_suites[] = { - &s2n_rsa_with_rc4_128_md5, /* 0x00,0x04 */ - &s2n_rsa_with_rc4_128_sha, /* 0x00,0x05 */ - &s2n_rsa_with_3des_ede_cbc_sha, /* 0x00,0x0A */ - &s2n_dhe_rsa_with_3des_ede_cbc_sha, /* 0x00,0x16 */ - &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ - &s2n_dhe_rsa_with_aes_128_cbc_sha, /* 0x00,0x33 */ - &s2n_rsa_with_aes_256_cbc_sha, /* 0x00,0x35 */ - &s2n_dhe_rsa_with_aes_256_cbc_sha, /* 0x00,0x39 */ - &s2n_rsa_with_aes_128_cbc_sha256, /* 0x00,0x3C */ - &s2n_rsa_with_aes_256_cbc_sha256, /* 0x00,0x3D */ - &s2n_dhe_rsa_with_aes_128_cbc_sha256, /* 0x00,0x67 */ - &s2n_dhe_rsa_with_aes_256_cbc_sha256, /* 0x00,0x6B */ - &s2n_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9C */ - &s2n_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9D */ - &s2n_dhe_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9E */ - &s2n_dhe_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9F */ - - &s2n_tls13_aes_128_gcm_sha256, /* 0x13,0x01 */ - &s2n_tls13_aes_256_gcm_sha384, /* 0x13,0x02 */ - &s2n_tls13_chacha20_poly1305_sha256, /* 0x13,0x03 */ - - &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha, /* 0xC0,0x09 */ - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, /* 0xC0,0x0A */ - &s2n_ecdhe_rsa_with_rc4_128_sha, /* 0xC0,0x11 */ - &s2n_ecdhe_rsa_with_3des_ede_cbc_sha, /* 0xC0,0x12 */ - &s2n_ecdhe_rsa_with_aes_128_cbc_sha, /* 0xC0,0x13 */ - &s2n_ecdhe_rsa_with_aes_256_cbc_sha, /* 0xC0,0x14 */ - &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, /* 0xC0,0x23 */ - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, /* 0xC0,0x24 */ - &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, /* 0xC0,0x27 */ - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, /* 0xC0,0x28 */ - &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, /* 0xC0,0x2B */ - &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, /* 0xC0,0x2C */ - &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, /* 0xC0,0x2F */ - &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, /* 0xC0,0x30 */ - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA8 */ - &s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */ - &s2n_dhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xAA */ -#if !defined(S2N_NO_PQ) - &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x04 */ - &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x08 */ - &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x0C */ -#endif -}; - -/* All supported ciphers. Exposed for integration testing. */ -const struct s2n_cipher_preferences cipher_preferences_test_all = { - .count = s2n_array_len(s2n_all_cipher_suites), - .suites = s2n_all_cipher_suites, -}; - -/* All TLS12 Cipher Suites */ - -static struct s2n_cipher_suite *s2n_all_tls12_cipher_suites[] = { - &s2n_rsa_with_rc4_128_md5, /* 0x00,0x04 */ - &s2n_rsa_with_rc4_128_sha, /* 0x00,0x05 */ - &s2n_rsa_with_3des_ede_cbc_sha, /* 0x00,0x0A */ - &s2n_dhe_rsa_with_3des_ede_cbc_sha, /* 0x00,0x16 */ - &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ - &s2n_dhe_rsa_with_aes_128_cbc_sha, /* 0x00,0x33 */ - &s2n_rsa_with_aes_256_cbc_sha, /* 0x00,0x35 */ - &s2n_dhe_rsa_with_aes_256_cbc_sha, /* 0x00,0x39 */ - &s2n_rsa_with_aes_128_cbc_sha256, /* 0x00,0x3C */ - &s2n_rsa_with_aes_256_cbc_sha256, /* 0x00,0x3D */ - &s2n_dhe_rsa_with_aes_128_cbc_sha256, /* 0x00,0x67 */ - &s2n_dhe_rsa_with_aes_256_cbc_sha256, /* 0x00,0x6B */ - &s2n_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9C */ - &s2n_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9D */ - &s2n_dhe_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9E */ - &s2n_dhe_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9F */ - - &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha, /* 0xC0,0x09 */ - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, /* 0xC0,0x0A */ - &s2n_ecdhe_rsa_with_rc4_128_sha, /* 0xC0,0x11 */ - &s2n_ecdhe_rsa_with_3des_ede_cbc_sha, /* 0xC0,0x12 */ - &s2n_ecdhe_rsa_with_aes_128_cbc_sha, /* 0xC0,0x13 */ - &s2n_ecdhe_rsa_with_aes_256_cbc_sha, /* 0xC0,0x14 */ - &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, /* 0xC0,0x23 */ - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, /* 0xC0,0x24 */ - &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, /* 0xC0,0x27 */ - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, /* 0xC0,0x28 */ - &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, /* 0xC0,0x2B */ - &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, /* 0xC0,0x2C */ - &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, /* 0xC0,0x2F */ - &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, /* 0xC0,0x30 */ - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA8 */ - &s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */ - &s2n_dhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xAA */ -#if !defined(S2N_NO_PQ) - &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x04 */ - &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x08 */ - &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x0C */ -#endif -}; - -const struct s2n_cipher_preferences cipher_preferences_test_all_tls12 = { - .count = s2n_array_len(s2n_all_tls12_cipher_suites), - .suites = s2n_all_tls12_cipher_suites, -}; - -/* All of the cipher suites that s2n can negotiate when in FIPS mode, - * in order of IANA value. Exposed for the "test_all_fips" cipher preference list. - */ -static struct s2n_cipher_suite *s2n_all_fips_cipher_suites[] = { - &s2n_rsa_with_3des_ede_cbc_sha, /* 0x00,0x0A */ - &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ - &s2n_rsa_with_aes_256_cbc_sha, /* 0x00,0x35 */ - &s2n_rsa_with_aes_128_cbc_sha256, /* 0x00,0x3C */ - &s2n_rsa_with_aes_256_cbc_sha256, /* 0x00,0x3D */ - &s2n_dhe_rsa_with_aes_128_cbc_sha256, /* 0x00,0x67 */ - &s2n_dhe_rsa_with_aes_256_cbc_sha256, /* 0x00,0x6B */ - &s2n_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9C */ - &s2n_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9D */ - &s2n_dhe_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9E */ - &s2n_dhe_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9F */ - &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, /* 0xC0,0x23 */ - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, /* 0xC0,0x24 */ - &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, /* 0xC0,0x27 */ - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, /* 0xC0,0x28 */ - &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, /* 0xC0,0x2B */ - &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, /* 0xC0,0x2C */ - &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, /* 0xC0,0x2F */ - &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, /* 0xC0,0x30 */ -}; - -/* All supported FIPS ciphers. Exposed for integration testing. */ -const struct s2n_cipher_preferences cipher_preferences_test_all_fips = { - .count = s2n_array_len(s2n_all_fips_cipher_suites), - .suites = s2n_all_fips_cipher_suites, -}; - -/* All of the ECDSA cipher suites that s2n can negotiate, in order of IANA - * value. Exposed for the "test_all_ecdsa" cipher preference list. - */ -static struct s2n_cipher_suite *s2n_all_ecdsa_cipher_suites[] = { - &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha, /* 0xC0,0x09 */ - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, /* 0xC0,0x0A */ - &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, /* 0xC0,0x23 */ - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, /* 0xC0,0x24 */ - &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, /* 0xC0,0x2B */ - &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, /* 0xC0,0x2C */ - &s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */ -}; - -/* All supported ECDSA cipher suites. Exposed for integration testing. */ -const struct s2n_cipher_preferences cipher_preferences_test_all_ecdsa = { - .count = s2n_array_len(s2n_all_ecdsa_cipher_suites), - .suites = s2n_all_ecdsa_cipher_suites, -}; - -/* All cipher suites that uses RSA key exchange. Exposed for unit or integration tests. */ -static struct s2n_cipher_suite *s2n_all_rsa_kex_cipher_suites[] = { - &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ - &s2n_rsa_with_rc4_128_md5, /* 0x00,0x04 */ - &s2n_rsa_with_rc4_128_sha, /* 0x00,0x05 */ - &s2n_rsa_with_3des_ede_cbc_sha, /* 0x00,0x0A */ - &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ - &s2n_rsa_with_aes_256_cbc_sha, /* 0x00,0x35 */ - &s2n_rsa_with_aes_128_cbc_sha256, /* 0x00,0x3C */ - &s2n_rsa_with_aes_256_cbc_sha256, /* 0x00,0x3D */ - &s2n_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9C */ - &s2n_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9D */ -}; - -/* Cipher preferences with rsa key exchange. Exposed for unit and integration tests. */ -const struct s2n_cipher_preferences cipher_preferences_test_all_rsa_kex = { - .count = s2n_array_len(s2n_all_rsa_kex_cipher_suites), - .suites = s2n_all_rsa_kex_cipher_suites, -}; - -/* All ECDSA cipher suites first, then the rest of the supported ciphers that s2n can negotiate. - * Exposed for the "test_ecdsa_priority" cipher preference list. - */ -static struct s2n_cipher_suite *s2n_ecdsa_priority_cipher_suites[] = { - &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha, /* 0xC0,0x09 */ - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, /* 0xC0,0x0A */ - &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, /* 0xC0,0x23 */ - &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, /* 0xC0,0x24 */ - &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, /* 0xC0,0x2B */ - &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, /* 0xC0,0x2C */ - &s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */ - &s2n_rsa_with_rc4_128_md5, /* 0x00,0x04 */ - &s2n_rsa_with_rc4_128_sha, /* 0x00,0x05 */ - &s2n_rsa_with_3des_ede_cbc_sha, /* 0x00,0x0A */ - &s2n_dhe_rsa_with_3des_ede_cbc_sha, /* 0x00,0x16 */ - &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ - &s2n_dhe_rsa_with_aes_128_cbc_sha, /* 0x00,0x33 */ - &s2n_rsa_with_aes_256_cbc_sha, /* 0x00,0x35 */ - &s2n_dhe_rsa_with_aes_256_cbc_sha, /* 0x00,0x39 */ - &s2n_rsa_with_aes_128_cbc_sha256, /* 0x00,0x3C */ - &s2n_rsa_with_aes_256_cbc_sha256, /* 0x00,0x3D */ - &s2n_dhe_rsa_with_aes_128_cbc_sha256, /* 0x00,0x67 */ - &s2n_dhe_rsa_with_aes_256_cbc_sha256, /* 0x00,0x6B */ - &s2n_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9C */ - &s2n_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9D */ - &s2n_dhe_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9E */ - &s2n_dhe_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9F */ - &s2n_ecdhe_rsa_with_rc4_128_sha, /* 0xC0,0x11 */ - &s2n_ecdhe_rsa_with_3des_ede_cbc_sha, /* 0xC0,0x12 */ - &s2n_ecdhe_rsa_with_aes_128_cbc_sha, /* 0xC0,0x13 */ - &s2n_ecdhe_rsa_with_aes_256_cbc_sha, /* 0xC0,0x14 */ - &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, /* 0xC0,0x27 */ - &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, /* 0xC0,0x28 */ - &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, /* 0xC0,0x2F */ - &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, /* 0xC0,0x30 */ - &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA8 */ - &s2n_dhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xAA */ -}; - -/* All cipher suites, but with ECDSA priority. Exposed for integration testing. */ -const struct s2n_cipher_preferences cipher_preferences_test_ecdsa_priority = { - .count = s2n_array_len(s2n_ecdsa_priority_cipher_suites), - .suites = s2n_ecdsa_priority_cipher_suites, -}; - -static struct s2n_cipher_suite *s2n_all_tls13_cipher_suites[] = { - &s2n_tls13_aes_128_gcm_sha256, /* 0x13,0x01 */ - &s2n_tls13_aes_256_gcm_sha384, /* 0x13,0x02 */ - &s2n_tls13_chacha20_poly1305_sha256, /* 0x13,0x03 */ -}; - -const struct s2n_cipher_preferences cipher_preferences_test_all_tls13 = { - .count = s2n_array_len(s2n_all_tls13_cipher_suites), - .suites = s2n_all_tls13_cipher_suites, -}; - -/* Determines cipher suite availability and selects record algorithms */ -int s2n_cipher_suites_init(void) -{ - const int num_cipher_suites = s2n_array_len(s2n_all_cipher_suites); - for (int i = 0; i < num_cipher_suites; i++) { - struct s2n_cipher_suite *cur_suite = s2n_all_cipher_suites[i]; - cur_suite->available = 0; - cur_suite->record_alg = NULL; - - /* Find the highest priority supported record algorithm */ - for (int j = 0; j < cur_suite->num_record_algs; j++) { - /* Can we use the record algorithm's cipher? Won't be available if the system CPU architecture - * doesn't support it or if the libcrypto lacks the feature. All hmac_algs are supported. - */ - if (cur_suite->all_record_algs[j]->cipher->is_available()) { - /* Found a supported record algorithm. Use it. */ - cur_suite->available = 1; - cur_suite->record_alg = cur_suite->all_record_algs[j]; - break; - } - } - - /* Initialize SSLv3 cipher suite if SSLv3 utilizes a different record algorithm */ - if (cur_suite->sslv3_record_alg && cur_suite->sslv3_record_alg->cipher->is_available()) { - struct s2n_blob cur_suite_mem = { .data = (uint8_t *) cur_suite, .size = sizeof(struct s2n_cipher_suite) }; - struct s2n_blob new_suite_mem = { 0 }; - 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; - new_suite->record_alg = cur_suite->sslv3_record_alg; - cur_suite->sslv3_cipher_suite = new_suite; - } else { - cur_suite->sslv3_cipher_suite = cur_suite; - } - } - -#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(); -#else - OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); -#endif - - return 0; -} - -/* Reset any selected record algorithms */ -int s2n_cipher_suites_cleanup(void) -{ - const int num_cipher_suites = sizeof(s2n_all_cipher_suites) / sizeof(struct s2n_cipher_suite *); - for (int i = 0; i < num_cipher_suites; i++) { - struct s2n_cipher_suite *cur_suite = s2n_all_cipher_suites[i]; - cur_suite->available = 0; - cur_suite->record_alg = NULL; - - /* 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))); - } - cur_suite->sslv3_cipher_suite = NULL; - } - -#if !S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0) - /*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 */ -#endif - - return 0; -} - -struct s2n_cipher_suite *s2n_cipher_suite_from_wire(const uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN]) -{ - int low = 0; - int top = (sizeof(s2n_all_cipher_suites) / sizeof(struct s2n_cipher_suite *)) - 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); - - if (m == 0) { - return s2n_all_cipher_suites[mid]; - } else if (m > 0) { - top = mid - 1; - } else if (m < 0) { - low = mid + 1; - } - } - - return NULL; -} - -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); - - /* 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); - 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); - - /* 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); - } - - return 0; -} - -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++) { - 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)) { - return 1; - } - } - - return 0; -} - -static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire, uint32_t count, uint32_t cipher_suite_len) -{ - uint8_t renegotiation_info_scsv[S2N_TLS_CIPHER_SUITE_LEN] = { TLS_EMPTY_RENEGOTIATION_INFO_SCSV }; - struct s2n_cipher_suite *higher_vers_match = NULL; - - /* RFC 7507 - If client is attempting to negotiate a TLS Version that is lower than the highest supported server - * version, and the client cipher list contains TLS_FALLBACK_SCSV, then the server must abort the connection since - * TLS_FALLBACK_SCSV should only be present when the client previously failed to negotiate a higher TLS version. - */ - if (conn->client_protocol_version < conn->server_protocol_version) { - 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); - } - } - - /* RFC5746 Section 3.6: A server must check if TLS_EMPTY_RENEGOTIATION_INFO_SCSV is included */ - if (s2n_wire_ciphers_contain(renegotiation_info_scsv, wire, count, cipher_suite_len)) { - conn->secure_renegotiation = 1; - } - - const struct s2n_security_policy *security_policy; - 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++) { - const uint8_t *ours = security_policy->cipher_preferences->suites[i]->iana_value; - - 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); - - /* 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)) { - continue; - } - - /* If connection is for SSLv3, use SSLv3 version of suites */ - if (conn->client_protocol_version == S2N_SSLv3) { - match = match->sslv3_cipher_suite; - } - - /* Skip the suite if we don't have an available implementation */ - if (!match->available) { - continue; - } - - /* Make sure the cipher is valid for available certs */ - if (s2n_is_cipher_suite_valid_for_auth(conn, match) != S2N_SUCCESS) { - continue; - } - - /* TLS 1.3 does not include key exchange in cipher suites */ - if (match->minimum_required_tls_version < S2N_TLS13) { - /* If the kex is not supported continue to the next candidate */ - if (!s2n_kex_supported(match, conn)) { - continue; - } - - /* If the kex is not configured correctly continue to the next candidate */ - if (s2n_configure_kex(match, conn)) { - continue; - } - } - - /* For TLS1.3 when PSKs are present, the server must consider the hash algorithm associated with the chosen PSK - * when choosing a cipher suite. Server MUST reject any cipher suite without a matching hash algorithm and - * continue to the next candidate. - * */ - if (conn->actual_protocol_version >= S2N_TLS13 && conn->psk_params.chosen_psk != NULL) { - s2n_hmac_algorithm chosen_psk_hmac_alg = { 0 }; - GUARD(s2n_hash_hmac_alg(conn->psk_params.chosen_psk->hash_alg, &chosen_psk_hmac_alg)); - if (match->prf_alg != chosen_psk_hmac_alg) { - continue; - } - } - - /* Don't immediately choose a cipher the connection shouldn't be able to support */ - if (conn->actual_protocol_version < match->minimum_required_tls_version) { - if (!higher_vers_match) { - higher_vers_match = match; - } - continue; - } - - conn->secure.cipher_suite = match; - return S2N_SUCCESS; - } - } - - /* Settle for a cipher with a higher required proto version, if it was set */ - if (higher_vers_match) { - conn->secure.cipher_suite = higher_vers_match; - return S2N_SUCCESS; - } - - S2N_ERROR(S2N_ERR_CIPHER_NOT_SUPPORTED); -} - -int s2n_set_cipher_as_sslv2_server(struct s2n_connection *conn, uint8_t *wire, uint16_t count) -{ - return s2n_set_cipher_as_server(conn, wire, count, S2N_SSLv2_CIPHER_SUITE_LEN); -} - -int s2n_set_cipher_as_tls_server(struct s2n_connection *conn, uint8_t *wire, uint16_t count) -{ - return s2n_set_cipher_as_server(conn, wire, count, S2N_TLS_CIPHER_SUITE_LEN); -} +/* + * 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 <string.h> + +#include <openssl/crypto.h> + +#include "error/s2n_errno.h" + +#include "crypto/s2n_cipher.h" +#include "crypto/s2n_openssl.h" + +#include "tls/s2n_auth_selection.h" +#include "tls/s2n_kex.h" +#include "tls/s2n_security_policies.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls13.h" +#include "utils/s2n_safety.h" +#include "tls/s2n_psk.h" + +/************************* + * S2n Record Algorithms * + *************************/ +const struct s2n_record_algorithm s2n_record_alg_null = { + .cipher = &s2n_null_cipher, + .hmac_alg = S2N_HMAC_NONE, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_rc4_md5 = { + .cipher = &s2n_rc4, + .hmac_alg = S2N_HMAC_MD5, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_rc4_sslv3_md5 = { + .cipher = &s2n_rc4, + .hmac_alg = S2N_HMAC_SSLv3_MD5, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_rc4_sha = { + .cipher = &s2n_rc4, + .hmac_alg = S2N_HMAC_SHA1, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_rc4_sslv3_sha = { + .cipher = &s2n_rc4, + .hmac_alg = S2N_HMAC_SSLv3_SHA1, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_3des_sha = { + .cipher = &s2n_3des, + .hmac_alg = S2N_HMAC_SHA1, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_3des_sslv3_sha = { + .cipher = &s2n_3des, + .hmac_alg = S2N_HMAC_SSLv3_SHA1, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes128_sha = { + .cipher = &s2n_aes128, + .hmac_alg = S2N_HMAC_SHA1, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes128_sslv3_sha = { + .cipher = &s2n_aes128, + .hmac_alg = S2N_HMAC_SSLv3_SHA1, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes128_sha_composite = { + .cipher = &s2n_aes128_sha, + .hmac_alg = S2N_HMAC_NONE, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes128_sha256 = { + .cipher = &s2n_aes128, + .hmac_alg = S2N_HMAC_SHA256, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes128_sha256_composite = { + .cipher = &s2n_aes128_sha256, + .hmac_alg = S2N_HMAC_NONE, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes256_sha = { + .cipher = &s2n_aes256, + .hmac_alg = S2N_HMAC_SHA1, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes256_sslv3_sha = { + .cipher = &s2n_aes256, + .hmac_alg = S2N_HMAC_SSLv3_SHA1, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes256_sha_composite = { + .cipher = &s2n_aes256_sha, + .hmac_alg = S2N_HMAC_NONE, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes256_sha256 = { + .cipher = &s2n_aes256, + .hmac_alg = S2N_HMAC_SHA256, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes256_sha256_composite = { + .cipher = &s2n_aes256_sha256, + .hmac_alg = S2N_HMAC_NONE, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes256_sha384 = { + .cipher = &s2n_aes256, + .hmac_alg = S2N_HMAC_SHA384, + .flags = 0, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes128_gcm = { + .cipher = &s2n_aes128_gcm, + .hmac_alg = S2N_HMAC_NONE, + .flags = S2N_TLS12_AES_GCM_AEAD_NONCE, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_aes256_gcm = { + .cipher = &s2n_aes256_gcm, + .hmac_alg = S2N_HMAC_NONE, + .flags = S2N_TLS12_AES_GCM_AEAD_NONCE, + .encryption_limit = UINT64_MAX, +}; + +const struct s2n_record_algorithm s2n_record_alg_chacha20_poly1305 = { + .cipher = &s2n_chacha20_poly1305, + .hmac_alg = S2N_HMAC_NONE, + /* Per RFC 7905, ChaCha20-Poly1305 will use a nonce construction expected to be used in TLS1.3. + * Give it a distinct 1.2 nonce value in case this changes. + */ + .flags = S2N_TLS12_CHACHA_POLY_AEAD_NONCE, + .encryption_limit = UINT64_MAX, +}; + +/* TLS 1.3 Record Algorithms */ +const struct s2n_record_algorithm s2n_tls13_record_alg_aes128_gcm = { + .cipher = &s2n_tls13_aes128_gcm, + .hmac_alg = S2N_HMAC_NONE, /* previously used in 1.2 prf, we do not need this */ + .flags = S2N_TLS13_RECORD_AEAD_NONCE, + .encryption_limit = S2N_TLS13_AES_GCM_MAXIMUM_RECORD_NUMBER, +}; + +const struct s2n_record_algorithm s2n_tls13_record_alg_aes256_gcm = { + .cipher = &s2n_tls13_aes256_gcm, + .hmac_alg = S2N_HMAC_NONE, + .flags = S2N_TLS13_RECORD_AEAD_NONCE, + .encryption_limit = S2N_TLS13_AES_GCM_MAXIMUM_RECORD_NUMBER, +}; + +const struct s2n_record_algorithm s2n_tls13_record_alg_chacha20_poly1305 = { + .cipher = &s2n_chacha20_poly1305, + .hmac_alg = S2N_HMAC_NONE, + /* this mirrors s2n_record_alg_chacha20_poly1305 with the exception of TLS 1.3 nonce flag */ + .flags = S2N_TLS13_RECORD_AEAD_NONCE, + .encryption_limit = UINT64_MAX, +}; + +/********************* + * S2n Cipher Suites * + *********************/ + +/* This is the initial cipher suite, but is never negotiated */ +struct s2n_cipher_suite s2n_null_cipher_suite = { + .available = 1, + .name = "TLS_NULL_WITH_NULL_NULL", + .iana_value = { TLS_NULL_WITH_NULL_NULL }, + .key_exchange_alg = &s2n_rsa, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = &s2n_record_alg_null, +}; + +struct s2n_cipher_suite s2n_rsa_with_rc4_128_md5 = /* 0x00,0x04 */ { + .available = 0, + .name = "RC4-MD5", + .iana_value = { TLS_RSA_WITH_RC4_128_MD5 }, + .key_exchange_alg = &s2n_rsa, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_rc4_md5 }, + .num_record_algs = 1, + .sslv3_record_alg = &s2n_record_alg_rc4_sslv3_md5, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_rsa_with_rc4_128_sha = /* 0x00,0x05 */ { + .available = 0, + .name = "RC4-SHA", + .iana_value = { TLS_RSA_WITH_RC4_128_SHA }, + .key_exchange_alg = &s2n_rsa, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_rc4_sha }, + .num_record_algs = 1, + .sslv3_record_alg = &s2n_record_alg_rc4_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_rsa_with_3des_ede_cbc_sha = /* 0x00,0x0A */ { + .available = 0, + .name = "DES-CBC3-SHA", + .iana_value = { TLS_RSA_WITH_3DES_EDE_CBC_SHA }, + .key_exchange_alg = &s2n_rsa, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_3des_sha }, + .num_record_algs = 1, + .sslv3_record_alg = &s2n_record_alg_3des_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_dhe_rsa_with_3des_ede_cbc_sha = /* 0x00,0x16 */ { + .available = 0, + .name = "EDH-RSA-DES-CBC3-SHA", + .iana_value = { TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA }, + .key_exchange_alg = &s2n_dhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_3des_sha }, + .num_record_algs = 1, + .sslv3_record_alg = &s2n_record_alg_3des_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_rsa_with_aes_128_cbc_sha = /* 0x00,0x2F */ { + .available = 0, + .name = "AES128-SHA", + .iana_value = { TLS_RSA_WITH_AES_128_CBC_SHA }, + .key_exchange_alg = &s2n_rsa, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_sha_composite, &s2n_record_alg_aes128_sha }, + .num_record_algs = 2, + .sslv3_record_alg = &s2n_record_alg_aes128_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_cbc_sha = /* 0x00,0x33 */ { + .available = 0, + .name = "DHE-RSA-AES128-SHA", + .iana_value = { TLS_DHE_RSA_WITH_AES_128_CBC_SHA }, + .key_exchange_alg = &s2n_dhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_sha_composite, &s2n_record_alg_aes128_sha }, + .num_record_algs = 2, + .sslv3_record_alg = &s2n_record_alg_aes128_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_rsa_with_aes_256_cbc_sha = /* 0x00,0x35 */ { + .available = 0, + .name = "AES256-SHA", + .iana_value = { TLS_RSA_WITH_AES_256_CBC_SHA }, + .key_exchange_alg = &s2n_rsa, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_sha_composite, &s2n_record_alg_aes256_sha }, + .num_record_algs = 2, + .sslv3_record_alg = &s2n_record_alg_aes256_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_cbc_sha = /* 0x00,0x39 */ { + .available = 0, + .name = "DHE-RSA-AES256-SHA", + .iana_value = { TLS_DHE_RSA_WITH_AES_256_CBC_SHA }, + .key_exchange_alg = &s2n_dhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_sha_composite, &s2n_record_alg_aes256_sha }, + .num_record_algs = 2, + .sslv3_record_alg = &s2n_record_alg_aes256_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_rsa_with_aes_128_cbc_sha256 = /* 0x00,0x3C */ { + .available = 0, + .name = "AES128-SHA256", + .iana_value = { TLS_RSA_WITH_AES_128_CBC_SHA256 }, + .key_exchange_alg = &s2n_rsa, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_sha256_composite, &s2n_record_alg_aes128_sha256 }, + .num_record_algs = 2, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_rsa_with_aes_256_cbc_sha256 = /* 0x00,0x3D */ { + .available = 0, + .name = "AES256-SHA256", + .iana_value = { TLS_RSA_WITH_AES_256_CBC_SHA256 }, + .key_exchange_alg = &s2n_rsa, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_sha256_composite, &s2n_record_alg_aes256_sha256 }, + .num_record_algs = 2, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_cbc_sha256 = /* 0x00,0x67 */ { + .available = 0, + .name = "DHE-RSA-AES128-SHA256", + .iana_value = { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 }, + .key_exchange_alg = &s2n_dhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_sha256_composite, &s2n_record_alg_aes128_sha256 }, + .num_record_algs = 2, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_cbc_sha256 = /* 0x00,0x6B */ { + .available = 0, + .name = "DHE-RSA-AES256-SHA256", + .iana_value = { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 }, + .key_exchange_alg = &s2n_dhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_sha256_composite, &s2n_record_alg_aes256_sha256 }, + .num_record_algs = 2, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_rsa_with_aes_128_gcm_sha256 = /* 0x00,0x9C */ { + .available = 0, + .name = "AES128-GCM-SHA256", + .iana_value = { TLS_RSA_WITH_AES_128_GCM_SHA256 }, + .key_exchange_alg = &s2n_rsa, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_rsa_with_aes_256_gcm_sha384 = /* 0x00,0x9D */ { + .available = 0, + .name = "AES256-GCM-SHA384", + .iana_value = { TLS_RSA_WITH_AES_256_GCM_SHA384 }, + .key_exchange_alg = &s2n_rsa, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA384, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_gcm_sha256 = /* 0x00,0x9E */ { + .available = 0, + .name = "DHE-RSA-AES128-GCM-SHA256", + .iana_value = { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 }, + .key_exchange_alg = &s2n_dhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_gcm_sha384 = /* 0x00,0x9F */ { + .available = 0, + .name = "DHE-RSA-AES256-GCM-SHA384", + .iana_value = { TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 }, + .key_exchange_alg = &s2n_dhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA384, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_cbc_sha = /* 0xC0,0x09 */ { + .available = 0, + .name = "ECDHE-ECDSA-AES128-SHA", + .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_ECDSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_sha_composite, &s2n_record_alg_aes128_sha }, + .num_record_algs = 2, + .sslv3_record_alg = &s2n_record_alg_aes128_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_cbc_sha = /* 0xC0,0x0A */ { + .available = 0, + .name = "ECDHE-ECDSA-AES256-SHA", + .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_ECDSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_sha_composite, &s2n_record_alg_aes256_sha }, + .num_record_algs = 2, + .sslv3_record_alg = &s2n_record_alg_aes256_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_ecdhe_rsa_with_rc4_128_sha = /* 0xC0,0x11 */ { + .available = 0, + .name = "ECDHE-RSA-RC4-SHA", + .iana_value = { TLS_ECDHE_RSA_WITH_RC4_128_SHA }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_rc4_sha }, + .num_record_algs = 1, + .sslv3_record_alg = &s2n_record_alg_rc4_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_ecdhe_rsa_with_3des_ede_cbc_sha = /* 0xC0,0x12 */ { + .available = 0, + .name = "ECDHE-RSA-DES-CBC3-SHA", + .iana_value = { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_3des_sha }, + .num_record_algs = 1, + .sslv3_record_alg = &s2n_record_alg_3des_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_cbc_sha = /* 0xC0,0x13 */ { + .available = 0, + .name = "ECDHE-RSA-AES128-SHA", + .iana_value = { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_sha_composite, &s2n_record_alg_aes128_sha }, + .num_record_algs = 2, + .sslv3_record_alg = &s2n_record_alg_aes128_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_cbc_sha = /* 0xC0,0x14 */ { + .available = 0, + .name = "ECDHE-RSA-AES256-SHA", + .iana_value = { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_sha_composite, &s2n_record_alg_aes256_sha }, + .num_record_algs = 2, + .sslv3_record_alg = &s2n_record_alg_aes256_sslv3_sha, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_SSLv3, +}; + +struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256 = /* 0xC0,0x23 */ { + .available = 0, + .name = "ECDHE-ECDSA-AES128-SHA256", + .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_ECDSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_sha256_composite, &s2n_record_alg_aes128_sha256 }, + .num_record_algs = 2, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384 = /* 0xC0,0x24 */ { + .available = 0, + .name = "ECDHE-ECDSA-AES256-SHA384", + .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_ECDSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_sha384 }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA384, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_cbc_sha256 = /* 0xC0,0x27 */ { + .available = 0, + .name = "ECDHE-RSA-AES128-SHA256", + .iana_value = { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_sha256_composite, &s2n_record_alg_aes128_sha256 }, + .num_record_algs = 2, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_cbc_sha384 = /* 0xC0,0x28 */ { + .available = 0, + .name = "ECDHE-RSA-AES256-SHA384", + .iana_value = { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_sha384 }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA384, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256 = /* 0xC0,0x2B */ { + .available = 0, + .name = "ECDHE-ECDSA-AES128-GCM-SHA256", + .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_ECDSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384 = /* 0xC0,0x2C */ { + .available = 0, + .name = "ECDHE-ECDSA-AES256-GCM-SHA384", + .iana_value = { TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_ECDSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA384, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_gcm_sha256 = /* 0xC0,0x2F */ { + .available = 0, + .name = "ECDHE-RSA-AES128-GCM-SHA256", + .iana_value = { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes128_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_gcm_sha384 = /* 0xC0,0x30 */ { + .available = 0, + .name = "ECDHE-RSA-AES256-GCM-SHA384", + .iana_value = { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA384, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_rsa_with_chacha20_poly1305_sha256 = /* 0xCC,0xA8 */ { + .available = 0, + .name = "ECDHE-RSA-CHACHA20-POLY1305", + .iana_value = { TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_chacha20_poly1305 }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256 = /* 0xCC,0xA9 */ { + .available = 0, + .name = "ECDHE-ECDSA-CHACHA20-POLY1305", + .iana_value = { TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 }, + .key_exchange_alg = &s2n_ecdhe, + .auth_method = S2N_AUTHENTICATION_ECDSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_chacha20_poly1305 }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_dhe_rsa_with_chacha20_poly1305_sha256 = /* 0xCC,0xAA */ { + .available = 0, + .name = "DHE-RSA-CHACHA20-POLY1305", + .iana_value = { TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 }, + .key_exchange_alg = &s2n_dhe, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_chacha20_poly1305 }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS12, +}; + +/* From https://tools.ietf.org/html/draft-campagna-tls-bike-sike-hybrid */ + +struct s2n_cipher_suite s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384 = /* 0xFF, 0x0C */ { + .available = 0, + .name = "ECDHE-KYBER-RSA-AES256-GCM-SHA384", + .iana_value = { TLS_ECDHE_KYBER_RSA_WITH_AES_256_GCM_SHA384 }, + .key_exchange_alg = &s2n_hybrid_ecdhe_kem, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA384, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384 = /* 0xFF, 0x04 */ { + .available = 0, + .name = "ECDHE-BIKE-RSA-AES256-GCM-SHA384", + .iana_value = { TLS_ECDHE_BIKE_RSA_WITH_AES_256_GCM_SHA384 }, + .key_exchange_alg = &s2n_hybrid_ecdhe_kem, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA384, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384 = /* 0xFF, 0x08 */ { + .available = 0, + .name = "ECDHE-SIKE-RSA-AES256-GCM-SHA384", + .iana_value = { TLS_ECDHE_SIKE_RSA_WITH_AES_256_GCM_SHA384 }, + .key_exchange_alg = &s2n_hybrid_ecdhe_kem, + .auth_method = S2N_AUTHENTICATION_RSA, + .record_alg = NULL, + .all_record_algs = { &s2n_record_alg_aes256_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA384, + .minimum_required_tls_version = S2N_TLS12, +}; + +struct s2n_cipher_suite s2n_tls13_aes_128_gcm_sha256 = { + .available = 0, + .name = "TLS_AES_128_GCM_SHA256", + .iana_value = { TLS_AES_128_GCM_SHA256 }, + .key_exchange_alg = NULL, + .auth_method = S2N_AUTHENTICATION_METHOD_TLS13, + .record_alg = NULL, + .all_record_algs = { &s2n_tls13_record_alg_aes128_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS13, +}; + +struct s2n_cipher_suite s2n_tls13_aes_256_gcm_sha384 = { + .available = 0, + .name = "TLS_AES_256_GCM_SHA384", + .iana_value = { TLS_AES_256_GCM_SHA384 }, + .key_exchange_alg = NULL, + .auth_method = S2N_AUTHENTICATION_METHOD_TLS13, + .record_alg = NULL, + .all_record_algs = { &s2n_tls13_record_alg_aes256_gcm }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA384, + .minimum_required_tls_version = S2N_TLS13, +}; + +struct s2n_cipher_suite s2n_tls13_chacha20_poly1305_sha256 = { + .available = 0, + .name = "TLS_CHACHA20_POLY1305_SHA256", + .iana_value = { TLS_CHACHA20_POLY1305_SHA256 }, + .key_exchange_alg = NULL, + .auth_method = S2N_AUTHENTICATION_METHOD_TLS13, + .record_alg = NULL, + .all_record_algs = { &s2n_tls13_record_alg_chacha20_poly1305 }, + .num_record_algs = 1, + .sslv3_record_alg = NULL, + .prf_alg = S2N_HMAC_SHA256, + .minimum_required_tls_version = S2N_TLS13, +}; + +/* All of the cipher suites that s2n negotiates in order of IANA value. + * New cipher suites MUST be added here, IN ORDER, or they will not be + * properly initialized. + */ +static struct s2n_cipher_suite *s2n_all_cipher_suites[] = { + &s2n_rsa_with_rc4_128_md5, /* 0x00,0x04 */ + &s2n_rsa_with_rc4_128_sha, /* 0x00,0x05 */ + &s2n_rsa_with_3des_ede_cbc_sha, /* 0x00,0x0A */ + &s2n_dhe_rsa_with_3des_ede_cbc_sha, /* 0x00,0x16 */ + &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ + &s2n_dhe_rsa_with_aes_128_cbc_sha, /* 0x00,0x33 */ + &s2n_rsa_with_aes_256_cbc_sha, /* 0x00,0x35 */ + &s2n_dhe_rsa_with_aes_256_cbc_sha, /* 0x00,0x39 */ + &s2n_rsa_with_aes_128_cbc_sha256, /* 0x00,0x3C */ + &s2n_rsa_with_aes_256_cbc_sha256, /* 0x00,0x3D */ + &s2n_dhe_rsa_with_aes_128_cbc_sha256, /* 0x00,0x67 */ + &s2n_dhe_rsa_with_aes_256_cbc_sha256, /* 0x00,0x6B */ + &s2n_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9C */ + &s2n_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9D */ + &s2n_dhe_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9E */ + &s2n_dhe_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9F */ + + &s2n_tls13_aes_128_gcm_sha256, /* 0x13,0x01 */ + &s2n_tls13_aes_256_gcm_sha384, /* 0x13,0x02 */ + &s2n_tls13_chacha20_poly1305_sha256, /* 0x13,0x03 */ + + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha, /* 0xC0,0x09 */ + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, /* 0xC0,0x0A */ + &s2n_ecdhe_rsa_with_rc4_128_sha, /* 0xC0,0x11 */ + &s2n_ecdhe_rsa_with_3des_ede_cbc_sha, /* 0xC0,0x12 */ + &s2n_ecdhe_rsa_with_aes_128_cbc_sha, /* 0xC0,0x13 */ + &s2n_ecdhe_rsa_with_aes_256_cbc_sha, /* 0xC0,0x14 */ + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, /* 0xC0,0x23 */ + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, /* 0xC0,0x24 */ + &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, /* 0xC0,0x27 */ + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, /* 0xC0,0x28 */ + &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, /* 0xC0,0x2B */ + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, /* 0xC0,0x2C */ + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, /* 0xC0,0x2F */ + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, /* 0xC0,0x30 */ + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA8 */ + &s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */ + &s2n_dhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xAA */ +#if !defined(S2N_NO_PQ) + &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x04 */ + &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x08 */ + &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x0C */ +#endif +}; + +/* All supported ciphers. Exposed for integration testing. */ +const struct s2n_cipher_preferences cipher_preferences_test_all = { + .count = s2n_array_len(s2n_all_cipher_suites), + .suites = s2n_all_cipher_suites, +}; + +/* All TLS12 Cipher Suites */ + +static struct s2n_cipher_suite *s2n_all_tls12_cipher_suites[] = { + &s2n_rsa_with_rc4_128_md5, /* 0x00,0x04 */ + &s2n_rsa_with_rc4_128_sha, /* 0x00,0x05 */ + &s2n_rsa_with_3des_ede_cbc_sha, /* 0x00,0x0A */ + &s2n_dhe_rsa_with_3des_ede_cbc_sha, /* 0x00,0x16 */ + &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ + &s2n_dhe_rsa_with_aes_128_cbc_sha, /* 0x00,0x33 */ + &s2n_rsa_with_aes_256_cbc_sha, /* 0x00,0x35 */ + &s2n_dhe_rsa_with_aes_256_cbc_sha, /* 0x00,0x39 */ + &s2n_rsa_with_aes_128_cbc_sha256, /* 0x00,0x3C */ + &s2n_rsa_with_aes_256_cbc_sha256, /* 0x00,0x3D */ + &s2n_dhe_rsa_with_aes_128_cbc_sha256, /* 0x00,0x67 */ + &s2n_dhe_rsa_with_aes_256_cbc_sha256, /* 0x00,0x6B */ + &s2n_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9C */ + &s2n_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9D */ + &s2n_dhe_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9E */ + &s2n_dhe_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9F */ + + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha, /* 0xC0,0x09 */ + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, /* 0xC0,0x0A */ + &s2n_ecdhe_rsa_with_rc4_128_sha, /* 0xC0,0x11 */ + &s2n_ecdhe_rsa_with_3des_ede_cbc_sha, /* 0xC0,0x12 */ + &s2n_ecdhe_rsa_with_aes_128_cbc_sha, /* 0xC0,0x13 */ + &s2n_ecdhe_rsa_with_aes_256_cbc_sha, /* 0xC0,0x14 */ + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, /* 0xC0,0x23 */ + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, /* 0xC0,0x24 */ + &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, /* 0xC0,0x27 */ + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, /* 0xC0,0x28 */ + &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, /* 0xC0,0x2B */ + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, /* 0xC0,0x2C */ + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, /* 0xC0,0x2F */ + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, /* 0xC0,0x30 */ + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA8 */ + &s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */ + &s2n_dhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xAA */ +#if !defined(S2N_NO_PQ) + &s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x04 */ + &s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x08 */ + &s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384, /* 0xFF,0x0C */ +#endif +}; + +const struct s2n_cipher_preferences cipher_preferences_test_all_tls12 = { + .count = s2n_array_len(s2n_all_tls12_cipher_suites), + .suites = s2n_all_tls12_cipher_suites, +}; + +/* All of the cipher suites that s2n can negotiate when in FIPS mode, + * in order of IANA value. Exposed for the "test_all_fips" cipher preference list. + */ +static struct s2n_cipher_suite *s2n_all_fips_cipher_suites[] = { + &s2n_rsa_with_3des_ede_cbc_sha, /* 0x00,0x0A */ + &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ + &s2n_rsa_with_aes_256_cbc_sha, /* 0x00,0x35 */ + &s2n_rsa_with_aes_128_cbc_sha256, /* 0x00,0x3C */ + &s2n_rsa_with_aes_256_cbc_sha256, /* 0x00,0x3D */ + &s2n_dhe_rsa_with_aes_128_cbc_sha256, /* 0x00,0x67 */ + &s2n_dhe_rsa_with_aes_256_cbc_sha256, /* 0x00,0x6B */ + &s2n_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9C */ + &s2n_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9D */ + &s2n_dhe_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9E */ + &s2n_dhe_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9F */ + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, /* 0xC0,0x23 */ + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, /* 0xC0,0x24 */ + &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, /* 0xC0,0x27 */ + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, /* 0xC0,0x28 */ + &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, /* 0xC0,0x2B */ + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, /* 0xC0,0x2C */ + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, /* 0xC0,0x2F */ + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, /* 0xC0,0x30 */ +}; + +/* All supported FIPS ciphers. Exposed for integration testing. */ +const struct s2n_cipher_preferences cipher_preferences_test_all_fips = { + .count = s2n_array_len(s2n_all_fips_cipher_suites), + .suites = s2n_all_fips_cipher_suites, +}; + +/* All of the ECDSA cipher suites that s2n can negotiate, in order of IANA + * value. Exposed for the "test_all_ecdsa" cipher preference list. + */ +static struct s2n_cipher_suite *s2n_all_ecdsa_cipher_suites[] = { + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha, /* 0xC0,0x09 */ + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, /* 0xC0,0x0A */ + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, /* 0xC0,0x23 */ + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, /* 0xC0,0x24 */ + &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, /* 0xC0,0x2B */ + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, /* 0xC0,0x2C */ + &s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */ +}; + +/* All supported ECDSA cipher suites. Exposed for integration testing. */ +const struct s2n_cipher_preferences cipher_preferences_test_all_ecdsa = { + .count = s2n_array_len(s2n_all_ecdsa_cipher_suites), + .suites = s2n_all_ecdsa_cipher_suites, +}; + +/* All cipher suites that uses RSA key exchange. Exposed for unit or integration tests. */ +static struct s2n_cipher_suite *s2n_all_rsa_kex_cipher_suites[] = { + &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ + &s2n_rsa_with_rc4_128_md5, /* 0x00,0x04 */ + &s2n_rsa_with_rc4_128_sha, /* 0x00,0x05 */ + &s2n_rsa_with_3des_ede_cbc_sha, /* 0x00,0x0A */ + &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ + &s2n_rsa_with_aes_256_cbc_sha, /* 0x00,0x35 */ + &s2n_rsa_with_aes_128_cbc_sha256, /* 0x00,0x3C */ + &s2n_rsa_with_aes_256_cbc_sha256, /* 0x00,0x3D */ + &s2n_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9C */ + &s2n_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9D */ +}; + +/* Cipher preferences with rsa key exchange. Exposed for unit and integration tests. */ +const struct s2n_cipher_preferences cipher_preferences_test_all_rsa_kex = { + .count = s2n_array_len(s2n_all_rsa_kex_cipher_suites), + .suites = s2n_all_rsa_kex_cipher_suites, +}; + +/* All ECDSA cipher suites first, then the rest of the supported ciphers that s2n can negotiate. + * Exposed for the "test_ecdsa_priority" cipher preference list. + */ +static struct s2n_cipher_suite *s2n_ecdsa_priority_cipher_suites[] = { + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha, /* 0xC0,0x09 */ + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha, /* 0xC0,0x0A */ + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, /* 0xC0,0x23 */ + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, /* 0xC0,0x24 */ + &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, /* 0xC0,0x2B */ + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, /* 0xC0,0x2C */ + &s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA9 */ + &s2n_rsa_with_rc4_128_md5, /* 0x00,0x04 */ + &s2n_rsa_with_rc4_128_sha, /* 0x00,0x05 */ + &s2n_rsa_with_3des_ede_cbc_sha, /* 0x00,0x0A */ + &s2n_dhe_rsa_with_3des_ede_cbc_sha, /* 0x00,0x16 */ + &s2n_rsa_with_aes_128_cbc_sha, /* 0x00,0x2F */ + &s2n_dhe_rsa_with_aes_128_cbc_sha, /* 0x00,0x33 */ + &s2n_rsa_with_aes_256_cbc_sha, /* 0x00,0x35 */ + &s2n_dhe_rsa_with_aes_256_cbc_sha, /* 0x00,0x39 */ + &s2n_rsa_with_aes_128_cbc_sha256, /* 0x00,0x3C */ + &s2n_rsa_with_aes_256_cbc_sha256, /* 0x00,0x3D */ + &s2n_dhe_rsa_with_aes_128_cbc_sha256, /* 0x00,0x67 */ + &s2n_dhe_rsa_with_aes_256_cbc_sha256, /* 0x00,0x6B */ + &s2n_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9C */ + &s2n_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9D */ + &s2n_dhe_rsa_with_aes_128_gcm_sha256, /* 0x00,0x9E */ + &s2n_dhe_rsa_with_aes_256_gcm_sha384, /* 0x00,0x9F */ + &s2n_ecdhe_rsa_with_rc4_128_sha, /* 0xC0,0x11 */ + &s2n_ecdhe_rsa_with_3des_ede_cbc_sha, /* 0xC0,0x12 */ + &s2n_ecdhe_rsa_with_aes_128_cbc_sha, /* 0xC0,0x13 */ + &s2n_ecdhe_rsa_with_aes_256_cbc_sha, /* 0xC0,0x14 */ + &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, /* 0xC0,0x27 */ + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, /* 0xC0,0x28 */ + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, /* 0xC0,0x2F */ + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, /* 0xC0,0x30 */ + &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xA8 */ + &s2n_dhe_rsa_with_chacha20_poly1305_sha256, /* 0xCC,0xAA */ +}; + +/* All cipher suites, but with ECDSA priority. Exposed for integration testing. */ +const struct s2n_cipher_preferences cipher_preferences_test_ecdsa_priority = { + .count = s2n_array_len(s2n_ecdsa_priority_cipher_suites), + .suites = s2n_ecdsa_priority_cipher_suites, +}; + +static struct s2n_cipher_suite *s2n_all_tls13_cipher_suites[] = { + &s2n_tls13_aes_128_gcm_sha256, /* 0x13,0x01 */ + &s2n_tls13_aes_256_gcm_sha384, /* 0x13,0x02 */ + &s2n_tls13_chacha20_poly1305_sha256, /* 0x13,0x03 */ +}; + +const struct s2n_cipher_preferences cipher_preferences_test_all_tls13 = { + .count = s2n_array_len(s2n_all_tls13_cipher_suites), + .suites = s2n_all_tls13_cipher_suites, +}; + +/* Determines cipher suite availability and selects record algorithms */ +int s2n_cipher_suites_init(void) +{ + const int num_cipher_suites = s2n_array_len(s2n_all_cipher_suites); + for (int i = 0; i < num_cipher_suites; i++) { + struct s2n_cipher_suite *cur_suite = s2n_all_cipher_suites[i]; + cur_suite->available = 0; + cur_suite->record_alg = NULL; + + /* Find the highest priority supported record algorithm */ + for (int j = 0; j < cur_suite->num_record_algs; j++) { + /* Can we use the record algorithm's cipher? Won't be available if the system CPU architecture + * doesn't support it or if the libcrypto lacks the feature. All hmac_algs are supported. + */ + if (cur_suite->all_record_algs[j]->cipher->is_available()) { + /* Found a supported record algorithm. Use it. */ + cur_suite->available = 1; + cur_suite->record_alg = cur_suite->all_record_algs[j]; + break; + } + } + + /* Initialize SSLv3 cipher suite if SSLv3 utilizes a different record algorithm */ + if (cur_suite->sslv3_record_alg && cur_suite->sslv3_record_alg->cipher->is_available()) { + struct s2n_blob cur_suite_mem = { .data = (uint8_t *) cur_suite, .size = sizeof(struct s2n_cipher_suite) }; + struct s2n_blob new_suite_mem = { 0 }; + 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; + new_suite->record_alg = cur_suite->sslv3_record_alg; + cur_suite->sslv3_cipher_suite = new_suite; + } else { + cur_suite->sslv3_cipher_suite = cur_suite; + } + } + +#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(); +#else + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); +#endif + + return 0; +} + +/* Reset any selected record algorithms */ +int s2n_cipher_suites_cleanup(void) +{ + const int num_cipher_suites = sizeof(s2n_all_cipher_suites) / sizeof(struct s2n_cipher_suite *); + for (int i = 0; i < num_cipher_suites; i++) { + struct s2n_cipher_suite *cur_suite = s2n_all_cipher_suites[i]; + cur_suite->available = 0; + cur_suite->record_alg = NULL; + + /* 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))); + } + cur_suite->sslv3_cipher_suite = NULL; + } + +#if !S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0) + /*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 */ +#endif + + return 0; +} + +struct s2n_cipher_suite *s2n_cipher_suite_from_wire(const uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN]) +{ + int low = 0; + int top = (sizeof(s2n_all_cipher_suites) / sizeof(struct s2n_cipher_suite *)) - 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); + + if (m == 0) { + return s2n_all_cipher_suites[mid]; + } else if (m > 0) { + top = mid - 1; + } else if (m < 0) { + low = mid + 1; + } + } + + return NULL; +} + +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); + + /* 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); + 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); + + /* 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); + } + + return 0; +} + +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++) { + 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)) { + return 1; + } + } + + return 0; +} + +static int s2n_set_cipher_as_server(struct s2n_connection *conn, uint8_t *wire, uint32_t count, uint32_t cipher_suite_len) +{ + uint8_t renegotiation_info_scsv[S2N_TLS_CIPHER_SUITE_LEN] = { TLS_EMPTY_RENEGOTIATION_INFO_SCSV }; + struct s2n_cipher_suite *higher_vers_match = NULL; + + /* RFC 7507 - If client is attempting to negotiate a TLS Version that is lower than the highest supported server + * version, and the client cipher list contains TLS_FALLBACK_SCSV, then the server must abort the connection since + * TLS_FALLBACK_SCSV should only be present when the client previously failed to negotiate a higher TLS version. + */ + if (conn->client_protocol_version < conn->server_protocol_version) { + 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); + } + } + + /* RFC5746 Section 3.6: A server must check if TLS_EMPTY_RENEGOTIATION_INFO_SCSV is included */ + if (s2n_wire_ciphers_contain(renegotiation_info_scsv, wire, count, cipher_suite_len)) { + conn->secure_renegotiation = 1; + } + + const struct s2n_security_policy *security_policy; + 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++) { + const uint8_t *ours = security_policy->cipher_preferences->suites[i]->iana_value; + + 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); + + /* 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)) { + continue; + } + + /* If connection is for SSLv3, use SSLv3 version of suites */ + if (conn->client_protocol_version == S2N_SSLv3) { + match = match->sslv3_cipher_suite; + } + + /* Skip the suite if we don't have an available implementation */ + if (!match->available) { + continue; + } + + /* Make sure the cipher is valid for available certs */ + if (s2n_is_cipher_suite_valid_for_auth(conn, match) != S2N_SUCCESS) { + continue; + } + + /* TLS 1.3 does not include key exchange in cipher suites */ + if (match->minimum_required_tls_version < S2N_TLS13) { + /* If the kex is not supported continue to the next candidate */ + if (!s2n_kex_supported(match, conn)) { + continue; + } + + /* If the kex is not configured correctly continue to the next candidate */ + if (s2n_configure_kex(match, conn)) { + continue; + } + } + + /* For TLS1.3 when PSKs are present, the server must consider the hash algorithm associated with the chosen PSK + * when choosing a cipher suite. Server MUST reject any cipher suite without a matching hash algorithm and + * continue to the next candidate. + * */ + if (conn->actual_protocol_version >= S2N_TLS13 && conn->psk_params.chosen_psk != NULL) { + s2n_hmac_algorithm chosen_psk_hmac_alg = { 0 }; + GUARD(s2n_hash_hmac_alg(conn->psk_params.chosen_psk->hash_alg, &chosen_psk_hmac_alg)); + if (match->prf_alg != chosen_psk_hmac_alg) { + continue; + } + } + + /* Don't immediately choose a cipher the connection shouldn't be able to support */ + if (conn->actual_protocol_version < match->minimum_required_tls_version) { + if (!higher_vers_match) { + higher_vers_match = match; + } + continue; + } + + conn->secure.cipher_suite = match; + return S2N_SUCCESS; + } + } + + /* Settle for a cipher with a higher required proto version, if it was set */ + if (higher_vers_match) { + conn->secure.cipher_suite = higher_vers_match; + return S2N_SUCCESS; + } + + S2N_ERROR(S2N_ERR_CIPHER_NOT_SUPPORTED); +} + +int s2n_set_cipher_as_sslv2_server(struct s2n_connection *conn, uint8_t *wire, uint16_t count) +{ + return s2n_set_cipher_as_server(conn, wire, count, S2N_SSLv2_CIPHER_SUITE_LEN); +} + +int s2n_set_cipher_as_tls_server(struct s2n_connection *conn, uint8_t *wire, uint16_t count) +{ + return s2n_set_cipher_as_server(conn, wire, count, S2N_TLS_CIPHER_SUITE_LEN); +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h index 2bd9bf0358..009f13471b 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h +++ b/contrib/restricted/aws/s2n/tls/s2n_cipher_suites.h @@ -1,172 +1,172 @@ -/* - * 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 "tls/s2n_connection.h" -#include "tls/s2n_crypto.h" - -#include "crypto/s2n_certificate.h" -#include "crypto/s2n_cipher.h" -#include "crypto/s2n_hmac.h" - -#include <stdint.h> - -/* Key exchange flags that can be OR'ed */ -#define S2N_KEY_EXCHANGE_DH 0x01 /* Diffie-Hellman key exchange, including ephemeral */ -#define S2N_KEY_EXCHANGE_EPH 0x02 /* Ephemeral key exchange */ -#define S2N_KEY_EXCHANGE_ECC 0x04 /* Elliptic curve cryptography */ - -#define S2N_MAX_POSSIBLE_RECORD_ALGS 2 -#if !defined(S2N_NO_PQ) -#define S2N_PQ_CIPHER_SUITE_COUNT 3 -#else -#define S2N_PQ_CIPHER_SUITE_COUNT 0 -#endif - -/* Kept up-to-date by s2n_cipher_suite_match_test */ -#define S2N_CIPHER_SUITE_COUNT (36 + S2N_PQ_CIPHER_SUITE_COUNT) - - -/* Record algorithm flags that can be OR'ed */ -#define S2N_TLS12_AES_GCM_AEAD_NONCE 0x01 -#define S2N_TLS12_CHACHA_POLY_AEAD_NONCE 0x02 -#define S2N_TLS13_RECORD_AEAD_NONCE 0x04 - -/* From RFC: https://tools.ietf.org/html/rfc8446#section-5.5 - * For AES-GCM, up to 2^24.5 full-size records (about 24 million) may be - * encrypted on a given connection while keeping a safety margin of - * approximately 2^-57 for Authenticated Encryption (AE) security. - * S2N_TLS13_MAXIMUM_RECORD_NUMBER is 2^24.5 rounded down to the nearest whole number - * minus 1 for the key update message. - */ -#define S2N_TLS13_AES_GCM_MAXIMUM_RECORD_NUMBER ((uint64_t) 23726565) - -typedef enum { - S2N_AUTHENTICATION_RSA = 0, - S2N_AUTHENTICATION_ECDSA, - S2N_AUTHENTICATION_METHOD_SENTINEL -} s2n_authentication_method; - -/* Used by TLS 1.3 CipherSuites (Eg TLS_AES_128_GCM_SHA256 "0x1301") where the Auth method will be specified by the - * SignatureScheme Extension, not the CipherSuite. */ -#define S2N_AUTHENTICATION_METHOD_TLS13 S2N_AUTHENTICATION_METHOD_SENTINEL - -struct s2n_record_algorithm { - const struct s2n_cipher *cipher; - s2n_hmac_algorithm hmac_alg; - uint32_t flags; - uint64_t encryption_limit; -}; - -/* Verbose names to avoid confusion with s2n_cipher. Exposed for unit tests */ -extern const struct s2n_record_algorithm s2n_record_alg_null; -extern const struct s2n_record_algorithm s2n_record_alg_rc4_md5; -extern const struct s2n_record_algorithm s2n_record_alg_rc4_sha; -extern const struct s2n_record_algorithm s2n_record_alg_3des_sha; -extern const struct s2n_record_algorithm s2n_record_alg_aes128_sha; -extern const struct s2n_record_algorithm s2n_record_alg_aes128_sha_composite; -extern const struct s2n_record_algorithm s2n_record_alg_aes128_sha256; -extern const struct s2n_record_algorithm s2n_record_alg_aes128_sha256_composite; -extern const struct s2n_record_algorithm s2n_record_alg_aes256_sha; -extern const struct s2n_record_algorithm s2n_record_alg_aes256_sha_composite; -extern const struct s2n_record_algorithm s2n_record_alg_aes256_sha256; -extern const struct s2n_record_algorithm s2n_record_alg_aes256_sha256_composite; -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; - -struct s2n_cipher_suite { - /* Is there an implementation available? Set in s2n_cipher_suites_init() */ - unsigned int available:1; - - /* Cipher name in Openssl format */ - const char *name; - const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN]; - - const struct s2n_kex *key_exchange_alg; - - const s2n_authentication_method auth_method; - - /* Algorithms used for per-record security. Set in s2n_cipher_suites_init() */ - const struct s2n_record_algorithm *record_alg; - - /* List of all possible record alg implementations in descending priority */ - const struct s2n_record_algorithm *all_record_algs[S2N_MAX_POSSIBLE_RECORD_ALGS]; - const uint8_t num_record_algs; - - /* SSLv3 utilizes HMAC differently from TLS */ - const struct s2n_record_algorithm *sslv3_record_alg; - struct s2n_cipher_suite *sslv3_cipher_suite; - - /* RFC 5426(TLS1.2) allows cipher suite defined PRFs. Cipher suites defined in and before TLS1.2 will use - * P_hash with SHA256 when TLS1.2 is negotiated. - */ - const s2n_hmac_algorithm prf_alg; - - const uint8_t minimum_required_tls_version; -}; - -/* Never negotiated */ -extern struct s2n_cipher_suite s2n_null_cipher_suite; - -extern struct s2n_cipher_suite s2n_rsa_with_rc4_128_md5; -extern struct s2n_cipher_suite s2n_rsa_with_rc4_128_sha; -extern struct s2n_cipher_suite s2n_rsa_with_3des_ede_cbc_sha; -extern struct s2n_cipher_suite s2n_dhe_rsa_with_3des_ede_cbc_sha; -extern struct s2n_cipher_suite s2n_rsa_with_aes_128_cbc_sha; -extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_cbc_sha; -extern struct s2n_cipher_suite s2n_rsa_with_aes_256_cbc_sha; -extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_cbc_sha; -extern struct s2n_cipher_suite s2n_rsa_with_aes_128_cbc_sha256; -extern struct s2n_cipher_suite s2n_rsa_with_aes_256_cbc_sha256; -extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_cbc_sha256; -extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_cbc_sha256; -extern struct s2n_cipher_suite s2n_rsa_with_aes_128_gcm_sha256; -extern struct s2n_cipher_suite s2n_rsa_with_aes_256_gcm_sha384; -extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_gcm_sha256; -extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_gcm_sha384; -extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_cbc_sha; -extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_cbc_sha; -extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_3des_ede_cbc_sha; -extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_cbc_sha; -extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_cbc_sha; -extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256; -extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384; -extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_cbc_sha256; -extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_cbc_sha384; -extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256; -extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384; -extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_gcm_sha256; -extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_gcm_sha384; -extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_chacha20_poly1305_sha256; -extern struct s2n_cipher_suite s2n_dhe_rsa_with_chacha20_poly1305_sha256; -extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256; -extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_rc4_128_sha; -extern struct s2n_cipher_suite s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384; -extern struct s2n_cipher_suite s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384; -extern struct s2n_cipher_suite s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384; -extern struct s2n_cipher_suite s2n_tls13_aes_256_gcm_sha384; -extern struct s2n_cipher_suite s2n_tls13_aes_128_gcm_sha256; -extern struct s2n_cipher_suite s2n_tls13_chacha20_poly1305_sha256; - -extern int s2n_cipher_suites_init(void); -extern int s2n_cipher_suites_cleanup(void); -extern struct s2n_cipher_suite *s2n_cipher_suite_from_wire(const uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN]); -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); +/* + * 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 "tls/s2n_connection.h" +#include "tls/s2n_crypto.h" + +#include "crypto/s2n_certificate.h" +#include "crypto/s2n_cipher.h" +#include "crypto/s2n_hmac.h" + +#include <stdint.h> + +/* Key exchange flags that can be OR'ed */ +#define S2N_KEY_EXCHANGE_DH 0x01 /* Diffie-Hellman key exchange, including ephemeral */ +#define S2N_KEY_EXCHANGE_EPH 0x02 /* Ephemeral key exchange */ +#define S2N_KEY_EXCHANGE_ECC 0x04 /* Elliptic curve cryptography */ + +#define S2N_MAX_POSSIBLE_RECORD_ALGS 2 +#if !defined(S2N_NO_PQ) +#define S2N_PQ_CIPHER_SUITE_COUNT 3 +#else +#define S2N_PQ_CIPHER_SUITE_COUNT 0 +#endif + +/* Kept up-to-date by s2n_cipher_suite_match_test */ +#define S2N_CIPHER_SUITE_COUNT (36 + S2N_PQ_CIPHER_SUITE_COUNT) + + +/* Record algorithm flags that can be OR'ed */ +#define S2N_TLS12_AES_GCM_AEAD_NONCE 0x01 +#define S2N_TLS12_CHACHA_POLY_AEAD_NONCE 0x02 +#define S2N_TLS13_RECORD_AEAD_NONCE 0x04 + +/* From RFC: https://tools.ietf.org/html/rfc8446#section-5.5 + * For AES-GCM, up to 2^24.5 full-size records (about 24 million) may be + * encrypted on a given connection while keeping a safety margin of + * approximately 2^-57 for Authenticated Encryption (AE) security. + * S2N_TLS13_MAXIMUM_RECORD_NUMBER is 2^24.5 rounded down to the nearest whole number + * minus 1 for the key update message. + */ +#define S2N_TLS13_AES_GCM_MAXIMUM_RECORD_NUMBER ((uint64_t) 23726565) + +typedef enum { + S2N_AUTHENTICATION_RSA = 0, + S2N_AUTHENTICATION_ECDSA, + S2N_AUTHENTICATION_METHOD_SENTINEL +} s2n_authentication_method; + +/* Used by TLS 1.3 CipherSuites (Eg TLS_AES_128_GCM_SHA256 "0x1301") where the Auth method will be specified by the + * SignatureScheme Extension, not the CipherSuite. */ +#define S2N_AUTHENTICATION_METHOD_TLS13 S2N_AUTHENTICATION_METHOD_SENTINEL + +struct s2n_record_algorithm { + const struct s2n_cipher *cipher; + s2n_hmac_algorithm hmac_alg; + uint32_t flags; + uint64_t encryption_limit; +}; + +/* Verbose names to avoid confusion with s2n_cipher. Exposed for unit tests */ +extern const struct s2n_record_algorithm s2n_record_alg_null; +extern const struct s2n_record_algorithm s2n_record_alg_rc4_md5; +extern const struct s2n_record_algorithm s2n_record_alg_rc4_sha; +extern const struct s2n_record_algorithm s2n_record_alg_3des_sha; +extern const struct s2n_record_algorithm s2n_record_alg_aes128_sha; +extern const struct s2n_record_algorithm s2n_record_alg_aes128_sha_composite; +extern const struct s2n_record_algorithm s2n_record_alg_aes128_sha256; +extern const struct s2n_record_algorithm s2n_record_alg_aes128_sha256_composite; +extern const struct s2n_record_algorithm s2n_record_alg_aes256_sha; +extern const struct s2n_record_algorithm s2n_record_alg_aes256_sha_composite; +extern const struct s2n_record_algorithm s2n_record_alg_aes256_sha256; +extern const struct s2n_record_algorithm s2n_record_alg_aes256_sha256_composite; +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; + +struct s2n_cipher_suite { + /* Is there an implementation available? Set in s2n_cipher_suites_init() */ + unsigned int available:1; + + /* Cipher name in Openssl format */ + const char *name; + const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN]; + + const struct s2n_kex *key_exchange_alg; + + const s2n_authentication_method auth_method; + + /* Algorithms used for per-record security. Set in s2n_cipher_suites_init() */ + const struct s2n_record_algorithm *record_alg; + + /* List of all possible record alg implementations in descending priority */ + const struct s2n_record_algorithm *all_record_algs[S2N_MAX_POSSIBLE_RECORD_ALGS]; + const uint8_t num_record_algs; + + /* SSLv3 utilizes HMAC differently from TLS */ + const struct s2n_record_algorithm *sslv3_record_alg; + struct s2n_cipher_suite *sslv3_cipher_suite; + + /* RFC 5426(TLS1.2) allows cipher suite defined PRFs. Cipher suites defined in and before TLS1.2 will use + * P_hash with SHA256 when TLS1.2 is negotiated. + */ + const s2n_hmac_algorithm prf_alg; + + const uint8_t minimum_required_tls_version; +}; + +/* Never negotiated */ +extern struct s2n_cipher_suite s2n_null_cipher_suite; + +extern struct s2n_cipher_suite s2n_rsa_with_rc4_128_md5; +extern struct s2n_cipher_suite s2n_rsa_with_rc4_128_sha; +extern struct s2n_cipher_suite s2n_rsa_with_3des_ede_cbc_sha; +extern struct s2n_cipher_suite s2n_dhe_rsa_with_3des_ede_cbc_sha; +extern struct s2n_cipher_suite s2n_rsa_with_aes_128_cbc_sha; +extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_cbc_sha; +extern struct s2n_cipher_suite s2n_rsa_with_aes_256_cbc_sha; +extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_cbc_sha; +extern struct s2n_cipher_suite s2n_rsa_with_aes_128_cbc_sha256; +extern struct s2n_cipher_suite s2n_rsa_with_aes_256_cbc_sha256; +extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_cbc_sha256; +extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_cbc_sha256; +extern struct s2n_cipher_suite s2n_rsa_with_aes_128_gcm_sha256; +extern struct s2n_cipher_suite s2n_rsa_with_aes_256_gcm_sha384; +extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_128_gcm_sha256; +extern struct s2n_cipher_suite s2n_dhe_rsa_with_aes_256_gcm_sha384; +extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_cbc_sha; +extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_cbc_sha; +extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_3des_ede_cbc_sha; +extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_cbc_sha; +extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_cbc_sha; +extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256; +extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384; +extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_cbc_sha256; +extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_cbc_sha384; +extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256; +extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384; +extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_128_gcm_sha256; +extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_aes_256_gcm_sha384; +extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_chacha20_poly1305_sha256; +extern struct s2n_cipher_suite s2n_dhe_rsa_with_chacha20_poly1305_sha256; +extern struct s2n_cipher_suite s2n_ecdhe_ecdsa_with_chacha20_poly1305_sha256; +extern struct s2n_cipher_suite s2n_ecdhe_rsa_with_rc4_128_sha; +extern struct s2n_cipher_suite s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384; +extern struct s2n_cipher_suite s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384; +extern struct s2n_cipher_suite s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384; +extern struct s2n_cipher_suite s2n_tls13_aes_256_gcm_sha384; +extern struct s2n_cipher_suite s2n_tls13_aes_128_gcm_sha256; +extern struct s2n_cipher_suite s2n_tls13_chacha20_poly1305_sha256; + +extern int s2n_cipher_suites_init(void); +extern int s2n_cipher_suites_cleanup(void); +extern struct s2n_cipher_suite *s2n_cipher_suite_from_wire(const uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN]); +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); diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_cert.c b/contrib/restricted/aws/s2n/tls/s2n_client_cert.c index edec36255f..7dde226788 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_cert.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_cert.c @@ -1,99 +1,99 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <s2n.h> - -#include "crypto/s2n_certificate.h" -#include "error/s2n_errno.h" -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_config.h" -#include "tls/s2n_tls.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_blob.h" -#include "utils/s2n_safety.h" - - -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)); - 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)); - - 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)); - return 0; - } - - client_cert_chain.data = s2n_stuffer_raw_read(in, client_cert_chain.size); - notnull_check(client_cert_chain.data); - - s2n_cert_public_key public_key; - GUARD(s2n_pkey_zero_init(&public_key)); - - s2n_pkey_type pkey_type; - - /* Determine the Cert Type, Verify the Cert, and extract the Public Key */ - S2N_ERROR_IF(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, 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; - - return 0; -} - - -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 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 - * - * This field SHALL be zero length unless used for the post-handshake authentication - * 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)); - } - - if (chain_and_key == NULL) { - GUARD(s2n_conn_set_handshake_no_client_cert(conn)); - 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; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <s2n.h> + +#include "crypto/s2n_certificate.h" +#include "error/s2n_errno.h" +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_config.h" +#include "tls/s2n_tls.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_blob.h" +#include "utils/s2n_safety.h" + + +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)); + 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)); + + 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)); + return 0; + } + + client_cert_chain.data = s2n_stuffer_raw_read(in, client_cert_chain.size); + notnull_check(client_cert_chain.data); + + s2n_cert_public_key public_key; + GUARD(s2n_pkey_zero_init(&public_key)); + + s2n_pkey_type pkey_type; + + /* Determine the Cert Type, Verify the Cert, and extract the Public Key */ + S2N_ERROR_IF(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, 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; + + return 0; +} + + +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 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 + * + * This field SHALL be zero length unless used for the post-handshake authentication + * 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)); + } + + if (chain_and_key == NULL) { + GUARD(s2n_conn_set_handshake_no_client_cert(conn)); + 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; +} 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 5296762282..a218c13c18 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_cert_verify.c @@ -1,91 +1,91 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <s2n.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_config.h" -#include "tls/s2n_signature_algorithms.h" -#include "tls/s2n_tls.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_safety.h" - - -int s2n_client_cert_verify_recv(struct s2n_connection *conn) -{ - struct s2n_stuffer *in = &conn->handshake.io; - struct s2n_signature_scheme chosen_sig_scheme = s2n_rsa_pkcs1_md5_sha1; - - if(conn->actual_protocol_version >= S2N_TLS12){ - /* 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)); - } - uint16_t signature_size; - struct s2n_blob signature = {0}; - 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); - - /* 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)); - - /* Verify the signature */ - GUARD(s2n_pkey_verify(&conn->secure.client_public_key, chosen_sig_scheme.sig_alg, &conn->handshake.ccv_hash_copy, &signature)); - - /* Client certificate has been verified. Minimize required handshake hash algs */ - GUARD(s2n_conn_update_required_handshake_hashes(conn)); - - return 0; -} - -int s2n_client_cert_verify_send(struct s2n_connection *conn) -{ - struct s2n_stuffer *out = &conn->handshake.io; - - struct s2n_signature_scheme chosen_sig_scheme = s2n_rsa_pkcs1_md5_sha1; - - 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)); - } - - /* 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_cert_chain_and_key *cert_chain_and_key = conn->handshake_params.our_chain_and_key; - - DEFER_CLEANUP(struct s2n_blob signature = {0}, s2n_free); - uint32_t max_signature_size = s2n_pkey_size(cert_chain_and_key->private_key); - GUARD(s2n_alloc(&signature, max_signature_size)); - - GUARD(s2n_pkey_sign(cert_chain_and_key->private_key, chosen_sig_scheme.sig_alg, &conn->handshake.ccv_hash_copy, &signature)); - - GUARD(s2n_stuffer_write_uint16(out, signature.size)); - GUARD(s2n_stuffer_write(out, &signature)); - - /* Client certificate has been verified. Minimize required handshake hash algs */ - GUARD(s2n_conn_update_required_handshake_hashes(conn)); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <s2n.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_config.h" +#include "tls/s2n_signature_algorithms.h" +#include "tls/s2n_tls.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_safety.h" + + +int s2n_client_cert_verify_recv(struct s2n_connection *conn) +{ + struct s2n_stuffer *in = &conn->handshake.io; + struct s2n_signature_scheme chosen_sig_scheme = s2n_rsa_pkcs1_md5_sha1; + + if(conn->actual_protocol_version >= S2N_TLS12){ + /* 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)); + } + uint16_t signature_size; + struct s2n_blob signature = {0}; + 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); + + /* 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)); + + /* Verify the signature */ + GUARD(s2n_pkey_verify(&conn->secure.client_public_key, chosen_sig_scheme.sig_alg, &conn->handshake.ccv_hash_copy, &signature)); + + /* Client certificate has been verified. Minimize required handshake hash algs */ + GUARD(s2n_conn_update_required_handshake_hashes(conn)); + + return 0; +} + +int s2n_client_cert_verify_send(struct s2n_connection *conn) +{ + struct s2n_stuffer *out = &conn->handshake.io; + + struct s2n_signature_scheme chosen_sig_scheme = s2n_rsa_pkcs1_md5_sha1; + + 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)); + } + + /* 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_cert_chain_and_key *cert_chain_and_key = conn->handshake_params.our_chain_and_key; + + DEFER_CLEANUP(struct s2n_blob signature = {0}, s2n_free); + uint32_t max_signature_size = s2n_pkey_size(cert_chain_and_key->private_key); + GUARD(s2n_alloc(&signature, max_signature_size)); + + GUARD(s2n_pkey_sign(cert_chain_and_key->private_key, chosen_sig_scheme.sig_alg, &conn->handshake.ccv_hash_copy, &signature)); + + GUARD(s2n_stuffer_write_uint16(out, signature.size)); + GUARD(s2n_stuffer_write(out, &signature)); + + /* Client certificate has been verified. Minimize required handshake hash algs */ + GUARD(s2n_conn_update_required_handshake_hashes(conn)); + + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_finished.c b/contrib/restricted/aws/s2n/tls/s2n_client_finished.c index d98da3452c..cc85970145 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_finished.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_finished.c @@ -1,110 +1,110 @@ -/* - * 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 <stdint.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls13_handshake.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_safety.h" - -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); - - S2N_ERROR_IF(!s2n_constant_time_equals(our_version, their_version, S2N_TLS_FINISHED_LEN) || conn->handshake.rsa_failed, S2N_ERR_BAD_MESSAGE); - - return 0; -} - -int s2n_client_finished_send(struct s2n_connection *conn) -{ - uint8_t *our_version; - 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)); - 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)); - } else { - 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); - - uint8_t length = s2n_stuffer_data_available(&conn->handshake.io); - S2N_ERROR_IF(length == 0, S2N_ERR_BAD_MESSAGE); - - /* read finished mac from handshake */ - struct s2n_blob wire_finished_mac = {0}; - s2n_blob_init(&wire_finished_mac, s2n_stuffer_raw_read(&conn->handshake.io, length), length); - - /* 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)); - - struct s2n_blob finished_key = {0}; - 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)); - - 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); - - /* 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)); - - /* look up finished secret key */ - struct s2n_blob finished_key = {0}; - 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)); - - /* write to handshake io */ - GUARD(s2n_stuffer_write(&conn->handshake.io, &client_finished_mac)); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <stdint.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls13_handshake.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_safety.h" + +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); + + S2N_ERROR_IF(!s2n_constant_time_equals(our_version, their_version, S2N_TLS_FINISHED_LEN) || conn->handshake.rsa_failed, S2N_ERR_BAD_MESSAGE); + + return 0; +} + +int s2n_client_finished_send(struct s2n_connection *conn) +{ + uint8_t *our_version; + 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)); + 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)); + } else { + 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); + + uint8_t length = s2n_stuffer_data_available(&conn->handshake.io); + S2N_ERROR_IF(length == 0, S2N_ERR_BAD_MESSAGE); + + /* read finished mac from handshake */ + struct s2n_blob wire_finished_mac = {0}; + s2n_blob_init(&wire_finished_mac, s2n_stuffer_raw_read(&conn->handshake.io, length), length); + + /* 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)); + + struct s2n_blob finished_key = {0}; + 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)); + + 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); + + /* 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)); + + /* look up finished secret key */ + struct s2n_blob finished_key = {0}; + 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)); + + /* write to handshake io */ + 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 95b1277e96..15bf12c525 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_hello.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello.c @@ -1,510 +1,510 @@ -/* - * 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 <time.h> -#include <stdint.h> -#include <stdlib.h> - -#include "crypto/s2n_fips.h" - -#include "error/s2n_errno.h" - -#include "crypto/s2n_hash.h" - -#include "tls/extensions/s2n_extension_list.h" -#include "tls/extensions/s2n_server_key_share.h" -#include "tls/s2n_auth_selection.h" -#include "tls/s2n_cipher_preferences.h" -#include "tls/s2n_security_policies.h" -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_client_hello.h" -#include "tls/s2n_alerts.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" - -#include "utils/s2n_bitmap.h" -#include "utils/s2n_random.h" -#include "utils/s2n_safety.h" - -struct s2n_client_hello *s2n_connection_get_client_hello(struct s2n_connection *conn) { - if (conn->client_hello.parsed != 1) { - return NULL; - } - - return &conn->client_hello; -} - -static uint32_t min_size(struct s2n_blob *blob, uint32_t max_length) { - return blob->size < max_length ? blob->size : max_length; -} - -static S2N_RESULT s2n_generate_client_session_id(struct s2n_connection *conn) -{ - ENSURE_REF(conn); - ENSURE_REF(conn->config); - - /* Session id already generated - no-op */ - if (conn->session_id_len) { - return S2N_RESULT_OK; - } - - /* Only generate the session id for pre-TLS1.3 if using tickets */ - if (conn->client_protocol_version < S2N_TLS13 && !conn->config->use_tickets) { - 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) { - 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)); - 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); - - 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); - - 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)); - - return len; -} - -ssize_t s2n_client_hello_get_cipher_suites_length(struct s2n_client_hello *ch) { - notnull_check(ch); - - return ch->cipher_suites.size; -} - -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); - - uint32_t len = min_size(&ch->cipher_suites, max_length); - - memcpy_check(out, &ch->cipher_suites.data, len); - - return len; -} - -ssize_t s2n_client_hello_get_extensions_length(struct s2n_client_hello *ch) { - notnull_check(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); - - uint32_t len = min_size(&ch->extensions.raw, max_length); - - memcpy_check(out, &ch->extensions.raw.data, len); - - return len; -} - -int s2n_client_hello_free(struct s2n_client_hello *client_hello) -{ - notnull_check(client_hello); - - 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; - - return 0; -} - -int s2n_collect_client_hello(struct s2n_connection *conn, struct s2n_stuffer *source) -{ - notnull_check(conn); - notnull_check(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)); - - return 0; -} - -static int s2n_parse_client_hello(struct s2n_connection *conn) -{ - notnull_check(conn); - GUARD(s2n_collect_client_hello(conn, &conn->handshake.io)); - - if (conn->client_hello_version == S2N_SSLv2) { - GUARD(s2n_sslv2_client_hello_recv(conn)); - return S2N_SUCCESS; - } - - /* Going forward, we parse the collected client hello */ - struct s2n_client_hello *client_hello = &conn->client_hello; - struct s2n_stuffer *in = &client_hello->raw_message; - - 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)); - - /* 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 - * an unexpected value above 0x0303. - */ - 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)); - 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)); - - 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); - - 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); - - /* 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)); - - 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; - - GUARD(s2n_extension_list_parse(in, &conn->client_hello.extensions)); - - return S2N_SUCCESS; -} - -int s2n_process_client_hello(struct s2n_connection *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)); - - /* Ensure that highest supported version is set correctly */ - if (!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); - } - - /* s2n_extension_list_process clears the parsed extensions as it processes them. - * 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, ©_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)); - } - - /* for pre TLS 1.3 connections, protocol selection is not done in supported_versions extensions, so do it here */ - if (conn->actual_protocol_version < S2N_TLS13) { - conn->actual_protocol_version = MIN(conn->server_protocol_version, conn->client_protocol_version); - } - - 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); - } - - 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); - } - - /* Find potential certificate matches before we choose the cipher. */ - 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)); - - /* And set the signature and hash algorithm used for key exchange signatures */ - GUARD(s2n_choose_sig_scheme_from_peer_preference_list(conn, - &conn->handshake_params.client_sig_hash_algs, - &conn->secure.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)); - - return 0; -} - -int s2n_client_hello_recv(struct s2n_connection *conn) -{ - /* Parse client hello */ - GUARD(s2n_parse_client_hello(conn)); - - /* 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 */ - conn->client_hello.parsed = 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; - } - } - } - - if (conn->client_hello_version != S2N_SSLv2) { - GUARD(s2n_process_client_hello(conn)); - } - - return 0; -} - -int s2n_client_hello_send(struct s2n_connection *conn) -{ - const struct s2n_security_policy *security_policy; - GUARD(s2n_connection_get_security_policy(conn, &security_policy)); - - const struct s2n_cipher_preferences *cipher_preferences = security_policy->cipher_preferences; - notnull_check(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)) { - conn->client_protocol_version = MIN(conn->client_protocol_version, S2N_TLS12); - conn->actual_protocol_version = MIN(conn->actual_protocol_version, S2N_TLS12); - } - - struct s2n_stuffer *out = &conn->handshake.io; - struct s2n_stuffer client_random = {0}; - 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)); - /* Create the client random data */ - 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)); - - 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)); - - GUARD_AS_POSIX(s2n_generate_client_session_id(conn)); - 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)); - } - - /* 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)); - - /* Now, write the IANA values of every available cipher suite in our list */ - 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)); - } - } - - /* 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)); - - /* Write size of the list of available ciphers */ - 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)); - - /* Write the extensions */ - 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)); - - return S2N_SUCCESS; -} - -/* See http://www-archive.mozilla.org/projects/security/pki/nss/ssl/draft02.html 2.5 */ -int s2n_sslv2_client_hello_recv(struct s2n_connection *conn) -{ - struct s2n_client_hello *client_hello = &conn->client_hello; - struct s2n_stuffer *in = &client_hello->raw_message; - - const struct s2n_security_policy *security_policy; - 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); - } - 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); - - uint16_t session_id_length; - GUARD(s2n_stuffer_read_uint16(in, &session_id_length)); - - uint16_t challenge_length; - 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); - - /* Find potential certificate matches before we choose the cipher. */ - 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)); - - S2N_ERROR_IF(session_id_length > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE); - 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)); - 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)); - - b.data += S2N_TLS_RANDOM_DATA_LEN - challenge_length; - b.size -= S2N_TLS_RANDOM_DATA_LEN - challenge_length; - - GUARD(s2n_stuffer_read(in, &b)); - - return 0; -} - -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); - - s2n_extension_type_id extension_type_id; - 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); - - *parsed_extension = found_parsed_extension; - return S2N_SUCCESS; -} - -ssize_t s2n_client_hello_get_extension_length(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type) -{ - notnull_check(ch); - - s2n_parsed_extension *parsed_extension = NULL; - if (s2n_client_hello_get_parsed_extension(extension_type, &ch->extensions, &parsed_extension) != S2N_SUCCESS) { - return 0; - } - - return parsed_extension->extension.size; -} - -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); - - s2n_parsed_extension *parsed_extension = NULL; - if (s2n_client_hello_get_parsed_extension(extension_type, &ch->extensions, &parsed_extension) != S2N_SUCCESS) { - return 0; - } - - uint32_t len = min_size(&parsed_extension->extension, max_length); - memcpy_check(out, parsed_extension->extension.data, len); - return len; -} +/* + * 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 <time.h> +#include <stdint.h> +#include <stdlib.h> + +#include "crypto/s2n_fips.h" + +#include "error/s2n_errno.h" + +#include "crypto/s2n_hash.h" + +#include "tls/extensions/s2n_extension_list.h" +#include "tls/extensions/s2n_server_key_share.h" +#include "tls/s2n_auth_selection.h" +#include "tls/s2n_cipher_preferences.h" +#include "tls/s2n_security_policies.h" +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_client_hello.h" +#include "tls/s2n_alerts.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" + +#include "utils/s2n_bitmap.h" +#include "utils/s2n_random.h" +#include "utils/s2n_safety.h" + +struct s2n_client_hello *s2n_connection_get_client_hello(struct s2n_connection *conn) { + if (conn->client_hello.parsed != 1) { + return NULL; + } + + return &conn->client_hello; +} + +static uint32_t min_size(struct s2n_blob *blob, uint32_t max_length) { + return blob->size < max_length ? blob->size : max_length; +} + +static S2N_RESULT s2n_generate_client_session_id(struct s2n_connection *conn) +{ + ENSURE_REF(conn); + ENSURE_REF(conn->config); + + /* Session id already generated - no-op */ + if (conn->session_id_len) { + return S2N_RESULT_OK; + } + + /* Only generate the session id for pre-TLS1.3 if using tickets */ + if (conn->client_protocol_version < S2N_TLS13 && !conn->config->use_tickets) { + 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) { + 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)); + 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); + + 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); + + 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)); + + return len; +} + +ssize_t s2n_client_hello_get_cipher_suites_length(struct s2n_client_hello *ch) { + notnull_check(ch); + + return ch->cipher_suites.size; +} + +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); + + uint32_t len = min_size(&ch->cipher_suites, max_length); + + memcpy_check(out, &ch->cipher_suites.data, len); + + return len; +} + +ssize_t s2n_client_hello_get_extensions_length(struct s2n_client_hello *ch) { + notnull_check(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); + + uint32_t len = min_size(&ch->extensions.raw, max_length); + + memcpy_check(out, &ch->extensions.raw.data, len); + + return len; +} + +int s2n_client_hello_free(struct s2n_client_hello *client_hello) +{ + notnull_check(client_hello); + + 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; + + return 0; +} + +int s2n_collect_client_hello(struct s2n_connection *conn, struct s2n_stuffer *source) +{ + notnull_check(conn); + notnull_check(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)); + + return 0; +} + +static int s2n_parse_client_hello(struct s2n_connection *conn) +{ + notnull_check(conn); + GUARD(s2n_collect_client_hello(conn, &conn->handshake.io)); + + if (conn->client_hello_version == S2N_SSLv2) { + GUARD(s2n_sslv2_client_hello_recv(conn)); + return S2N_SUCCESS; + } + + /* Going forward, we parse the collected client hello */ + struct s2n_client_hello *client_hello = &conn->client_hello; + struct s2n_stuffer *in = &client_hello->raw_message; + + 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)); + + /* 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 + * an unexpected value above 0x0303. + */ + 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)); + 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)); + + 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); + + 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); + + /* 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)); + + 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; + + GUARD(s2n_extension_list_parse(in, &conn->client_hello.extensions)); + + return S2N_SUCCESS; +} + +int s2n_process_client_hello(struct s2n_connection *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)); + + /* Ensure that highest supported version is set correctly */ + if (!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); + } + + /* s2n_extension_list_process clears the parsed extensions as it processes them. + * 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, ©_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)); + } + + /* for pre TLS 1.3 connections, protocol selection is not done in supported_versions extensions, so do it here */ + if (conn->actual_protocol_version < S2N_TLS13) { + conn->actual_protocol_version = MIN(conn->server_protocol_version, conn->client_protocol_version); + } + + 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); + } + + 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); + } + + /* Find potential certificate matches before we choose the cipher. */ + 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)); + + /* And set the signature and hash algorithm used for key exchange signatures */ + GUARD(s2n_choose_sig_scheme_from_peer_preference_list(conn, + &conn->handshake_params.client_sig_hash_algs, + &conn->secure.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)); + + return 0; +} + +int s2n_client_hello_recv(struct s2n_connection *conn) +{ + /* Parse client hello */ + GUARD(s2n_parse_client_hello(conn)); + + /* 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 */ + conn->client_hello.parsed = 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; + } + } + } + + if (conn->client_hello_version != S2N_SSLv2) { + GUARD(s2n_process_client_hello(conn)); + } + + return 0; +} + +int s2n_client_hello_send(struct s2n_connection *conn) +{ + const struct s2n_security_policy *security_policy; + GUARD(s2n_connection_get_security_policy(conn, &security_policy)); + + const struct s2n_cipher_preferences *cipher_preferences = security_policy->cipher_preferences; + notnull_check(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)) { + conn->client_protocol_version = MIN(conn->client_protocol_version, S2N_TLS12); + conn->actual_protocol_version = MIN(conn->actual_protocol_version, S2N_TLS12); + } + + struct s2n_stuffer *out = &conn->handshake.io; + struct s2n_stuffer client_random = {0}; + 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)); + /* Create the client random data */ + 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)); + + 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)); + + GUARD_AS_POSIX(s2n_generate_client_session_id(conn)); + 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)); + } + + /* 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)); + + /* Now, write the IANA values of every available cipher suite in our list */ + 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)); + } + } + + /* 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)); + + /* Write size of the list of available ciphers */ + 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)); + + /* Write the extensions */ + 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)); + + return S2N_SUCCESS; +} + +/* See http://www-archive.mozilla.org/projects/security/pki/nss/ssl/draft02.html 2.5 */ +int s2n_sslv2_client_hello_recv(struct s2n_connection *conn) +{ + struct s2n_client_hello *client_hello = &conn->client_hello; + struct s2n_stuffer *in = &client_hello->raw_message; + + const struct s2n_security_policy *security_policy; + 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); + } + 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); + + uint16_t session_id_length; + GUARD(s2n_stuffer_read_uint16(in, &session_id_length)); + + uint16_t challenge_length; + 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); + + /* Find potential certificate matches before we choose the cipher. */ + 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)); + + S2N_ERROR_IF(session_id_length > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE); + 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)); + 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)); + + b.data += S2N_TLS_RANDOM_DATA_LEN - challenge_length; + b.size -= S2N_TLS_RANDOM_DATA_LEN - challenge_length; + + GUARD(s2n_stuffer_read(in, &b)); + + return 0; +} + +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); + + s2n_extension_type_id extension_type_id; + 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); + + *parsed_extension = found_parsed_extension; + return S2N_SUCCESS; +} + +ssize_t s2n_client_hello_get_extension_length(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type) +{ + notnull_check(ch); + + s2n_parsed_extension *parsed_extension = NULL; + if (s2n_client_hello_get_parsed_extension(extension_type, &ch->extensions, &parsed_extension) != S2N_SUCCESS) { + return 0; + } + + return parsed_extension->extension.size; +} + +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); + + s2n_parsed_extension *parsed_extension = NULL; + if (s2n_client_hello_get_parsed_extension(extension_type, &ch->extensions, &parsed_extension) != S2N_SUCCESS) { + return 0; + } + + uint32_t len = min_size(&parsed_extension->extension, max_length); + memcpy_check(out, parsed_extension->extension.data, len); + return len; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_hello.h b/contrib/restricted/aws/s2n/tls/s2n_client_hello.h index f8e8c8c999..59eb0b12c7 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_hello.h +++ b/contrib/restricted/aws/s2n/tls/s2n_client_hello.h @@ -1,49 +1,49 @@ -/* - * 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 <stdint.h> -#include <s2n.h> - -#include "stuffer/s2n_stuffer.h" -#include "tls/extensions/s2n_extension_list.h" - -#include "utils/s2n_array.h" -/* - * the 'data' pointers in the below blobs - * point to data in the raw_message stuffer - */ -struct s2n_client_hello { - struct s2n_stuffer raw_message; - - s2n_parsed_extensions_list extensions; - struct s2n_blob cipher_suites; - - unsigned int parsed:1; -}; - -int s2n_client_hello_free(struct s2n_client_hello *client_hello); - -extern struct s2n_client_hello *s2n_connection_get_client_hello(struct s2n_connection *conn); - -extern ssize_t s2n_client_hello_get_raw_message_length(struct s2n_client_hello *ch); -extern ssize_t s2n_client_hello_get_raw_message(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length); - -extern ssize_t s2n_client_hello_get_cipher_suites_length(struct s2n_client_hello *ch); -extern ssize_t s2n_client_hello_get_cipher_suites(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length); - -extern ssize_t s2n_client_hello_get_extensions_length(struct s2n_client_hello *ch); -extern ssize_t s2n_client_hello_get_extensions(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length); +/* + * 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 <stdint.h> +#include <s2n.h> + +#include "stuffer/s2n_stuffer.h" +#include "tls/extensions/s2n_extension_list.h" + +#include "utils/s2n_array.h" +/* + * the 'data' pointers in the below blobs + * point to data in the raw_message stuffer + */ +struct s2n_client_hello { + struct s2n_stuffer raw_message; + + s2n_parsed_extensions_list extensions; + struct s2n_blob cipher_suites; + + unsigned int parsed:1; +}; + +int s2n_client_hello_free(struct s2n_client_hello *client_hello); + +extern struct s2n_client_hello *s2n_connection_get_client_hello(struct s2n_connection *conn); + +extern ssize_t s2n_client_hello_get_raw_message_length(struct s2n_client_hello *ch); +extern ssize_t s2n_client_hello_get_raw_message(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length); + +extern ssize_t s2n_client_hello_get_cipher_suites_length(struct s2n_client_hello *ch); +extern ssize_t s2n_client_hello_get_cipher_suites(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length); + +extern ssize_t s2n_client_hello_get_extensions_length(struct s2n_client_hello *ch); +extern ssize_t s2n_client_hello_get_extensions(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length); 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 7e07867d31..99510d8628 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c +++ b/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.c @@ -1,318 +1,318 @@ -/* - * 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 <s2n.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_async_pkey.h" -#include "tls/s2n_handshake.h" -#include "tls/s2n_kem.h" -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_kex.h" -#include "tls/s2n_resume.h" - -#include "stuffer/s2n_stuffer.h" - -#include "crypto/s2n_dhe.h" -#include "crypto/s2n_rsa.h" -#include "crypto/s2n_pkey.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_random.h" - -#define get_client_hello_protocol_version(conn) (conn->client_hello_version == S2N_SSLv2 ? conn->client_protocol_version : conn->client_hello_version) - -typedef int s2n_kex_client_key_method(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); -typedef void *s2n_stuffer_action(struct s2n_stuffer *stuffer, uint32_t data_len); - -static int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rsa_failed, struct s2n_blob *shared_key); - -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); - 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; - client_key_exchange_message->data = stuffer_action(io, 0); - notnull_check(client_key_exchange_message->data); - const uint32_t start_cursor = *cursor; - - DEFER_CLEANUP(struct s2n_blob shared_key_0 = {0}, s2n_free); - GUARD(kex_method(hybrid_kex_0, conn, &shared_key_0)); - - struct s2n_blob *shared_key_1 = &(conn->secure.kem_params.shared_secret); - GUARD(kex_method(hybrid_kex_1, conn, shared_key_1)); - - const uint32_t end_cursor = *cursor; - gte_check(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)); - 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)); - - GUARD(s2n_kem_free(&conn->secure.kem_params)); - - return 0; -} - -static int s2n_calculate_keys(struct s2n_connection *conn, struct s2n_blob *shared_key) -{ - /* Turn the pre-master secret into a master secret */ - GUARD(s2n_kex_tls_prf(conn->secure.cipher_suite->key_exchange_alg, conn, shared_key)); - /* Erase the pre-master secret */ - GUARD(s2n_blob_zero(shared_key)); - if (shared_key->allocated) { - GUARD(s2n_free(shared_key)); - } - /* Expand the keys */ - GUARD(s2n_prf_key_expansion(conn)); - /* Save the master secret in the cache */ - if (s2n_allowed_to_cache_connection(conn)) { - GUARD(s2n_store_to_cache(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; - shared_key->size = S2N_TLS_SECRET_LEN; - - S2N_ASYNC_PKEY_GUARD(conn); - - struct s2n_stuffer *in = &conn->handshake.io; - uint8_t client_hello_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; - uint16_t length; - - if (conn->actual_protocol_version == S2N_SSLv3) { - length = s2n_stuffer_data_available(in); - } else { - GUARD(s2n_stuffer_read_uint16(in, &length)); - } - - S2N_ERROR_IF(length > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE); - - /* Keep a copy of the client hello version in wire format, which should be - * either the protocol version supported by client if the supported version is <= TLS1.2, - * or TLS1.2 (the legacy version) if client supported version is TLS1.3 - */ - uint8_t legacy_client_hello_protocol_version = get_client_hello_protocol_version(conn); - client_hello_protocol_version[0] = legacy_client_hello_protocol_version / 10; - client_hello_protocol_version[1] = legacy_client_hello_protocol_version % 10; - - /* 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); - - /* 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]; - - S2N_ASYNC_PKEY_DECRYPT(conn, &encrypted, shared_key, s2n_rsa_client_key_recv_complete); -} - -int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rsa_failed, struct s2n_blob *decrypted) -{ - 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) { - /* Copy (maybe) decrypted data into shared key */ - memcpy_check(conn->secure.rsa_premaster_secret, decrypted->data, S2N_TLS_SECRET_LEN); - } - - /* Get client hello protocol version for comparison with decrypted data */ - uint8_t legacy_client_hello_protocol_version = get_client_hello_protocol_version(conn); - uint8_t client_hello_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; - client_hello_protocol_version[0] = legacy_client_hello_protocol_version / 10; - client_hello_protocol_version[1] = legacy_client_hello_protocol_version % 10; - - conn->handshake.rsa_failed = rsa_failed; - - /* 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); - - return 0; -} - -int s2n_dhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key) -{ - 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)); - /* We don't need the server params any more */ - GUARD(s2n_dh_params_free(&conn->secure.server_dh_params)); - return 0; -} - -int s2n_ecdhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key) -{ - 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)); - /* We don't need the server params any more */ - GUARD(s2n_ecc_evp_params_free(&conn->secure.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 - * 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 - * as the argument, but we can't (easily) change the function signature - * because it has to be consistent with what is defined in s2n_kex. - * - * 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); - - GUARD(s2n_kem_recv_ciphertext(&(conn->handshake.io), &(conn->secure.kem_params))); - - return 0; -} - -int s2n_hybrid_client_key_recv(struct s2n_connection *conn, struct s2n_blob *combined_shared_key) -{ - return s2n_hybrid_client_action(conn, combined_shared_key, &s2n_kex_client_key_recv, &conn->handshake.io.read_cursor, - &s2n_stuffer_raw_read); -} - -int s2n_client_key_recv(struct s2n_connection *conn) -{ - const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg; - struct s2n_blob shared_key = {0}; - - GUARD(s2n_kex_client_key_recv(key_exchange, conn, &shared_key)); - - GUARD(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)); - - /* We don't need the server params any more */ - GUARD(s2n_dh_params_free(&conn->secure.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)); - - /* We don't need the server params any more */ - GUARD(s2n_ecc_evp_params_free(&conn->secure.server_ecc_evp_params)); - return 0; -} - -int s2n_rsa_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key) -{ - uint8_t client_hello_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; - uint8_t legacy_client_hello_protocol_version = get_client_hello_protocol_version(conn); - 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->size = S2N_TLS_SECRET_LEN; - - GUARD_AS_POSIX(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); - - int encrypted_size = s2n_pkey_size(&conn->secure.server_public_key); - S2N_ERROR_IF(encrypted_size < 0 || encrypted_size > 0xffff, S2N_ERR_SIZE_MISMATCH); - - if (conn->actual_protocol_version > S2N_SSLv3) { - 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); - - /* Encrypt the secret and send it on */ - GUARD(s2n_pkey_encrypt(&conn->secure.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)); - 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 +/* + * 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 <s2n.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_async_pkey.h" +#include "tls/s2n_handshake.h" +#include "tls/s2n_kem.h" +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_kex.h" +#include "tls/s2n_resume.h" + +#include "stuffer/s2n_stuffer.h" + +#include "crypto/s2n_dhe.h" +#include "crypto/s2n_rsa.h" +#include "crypto/s2n_pkey.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_random.h" + +#define get_client_hello_protocol_version(conn) (conn->client_hello_version == S2N_SSLv2 ? conn->client_protocol_version : conn->client_hello_version) + +typedef int s2n_kex_client_key_method(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); +typedef void *s2n_stuffer_action(struct s2n_stuffer *stuffer, uint32_t data_len); + +static int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rsa_failed, struct s2n_blob *shared_key); + +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); + 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; + client_key_exchange_message->data = stuffer_action(io, 0); + notnull_check(client_key_exchange_message->data); + const uint32_t start_cursor = *cursor; + + DEFER_CLEANUP(struct s2n_blob shared_key_0 = {0}, s2n_free); + GUARD(kex_method(hybrid_kex_0, conn, &shared_key_0)); + + struct s2n_blob *shared_key_1 = &(conn->secure.kem_params.shared_secret); + GUARD(kex_method(hybrid_kex_1, conn, shared_key_1)); + + const uint32_t end_cursor = *cursor; + gte_check(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)); + 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)); + + GUARD(s2n_kem_free(&conn->secure.kem_params)); + + return 0; +} + +static int s2n_calculate_keys(struct s2n_connection *conn, struct s2n_blob *shared_key) +{ + /* Turn the pre-master secret into a master secret */ + GUARD(s2n_kex_tls_prf(conn->secure.cipher_suite->key_exchange_alg, conn, shared_key)); + /* Erase the pre-master secret */ + GUARD(s2n_blob_zero(shared_key)); + if (shared_key->allocated) { + GUARD(s2n_free(shared_key)); + } + /* Expand the keys */ + GUARD(s2n_prf_key_expansion(conn)); + /* Save the master secret in the cache */ + if (s2n_allowed_to_cache_connection(conn)) { + GUARD(s2n_store_to_cache(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; + shared_key->size = S2N_TLS_SECRET_LEN; + + S2N_ASYNC_PKEY_GUARD(conn); + + struct s2n_stuffer *in = &conn->handshake.io; + uint8_t client_hello_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; + uint16_t length; + + if (conn->actual_protocol_version == S2N_SSLv3) { + length = s2n_stuffer_data_available(in); + } else { + GUARD(s2n_stuffer_read_uint16(in, &length)); + } + + S2N_ERROR_IF(length > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE); + + /* Keep a copy of the client hello version in wire format, which should be + * either the protocol version supported by client if the supported version is <= TLS1.2, + * or TLS1.2 (the legacy version) if client supported version is TLS1.3 + */ + uint8_t legacy_client_hello_protocol_version = get_client_hello_protocol_version(conn); + client_hello_protocol_version[0] = legacy_client_hello_protocol_version / 10; + client_hello_protocol_version[1] = legacy_client_hello_protocol_version % 10; + + /* 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); + + /* 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]; + + S2N_ASYNC_PKEY_DECRYPT(conn, &encrypted, shared_key, s2n_rsa_client_key_recv_complete); +} + +int s2n_rsa_client_key_recv_complete(struct s2n_connection *conn, bool rsa_failed, struct s2n_blob *decrypted) +{ + 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) { + /* Copy (maybe) decrypted data into shared key */ + memcpy_check(conn->secure.rsa_premaster_secret, decrypted->data, S2N_TLS_SECRET_LEN); + } + + /* Get client hello protocol version for comparison with decrypted data */ + uint8_t legacy_client_hello_protocol_version = get_client_hello_protocol_version(conn); + uint8_t client_hello_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; + client_hello_protocol_version[0] = legacy_client_hello_protocol_version / 10; + client_hello_protocol_version[1] = legacy_client_hello_protocol_version % 10; + + conn->handshake.rsa_failed = rsa_failed; + + /* 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); + + return 0; +} + +int s2n_dhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key) +{ + 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)); + /* We don't need the server params any more */ + GUARD(s2n_dh_params_free(&conn->secure.server_dh_params)); + return 0; +} + +int s2n_ecdhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key) +{ + 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)); + /* We don't need the server params any more */ + GUARD(s2n_ecc_evp_params_free(&conn->secure.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 * 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 - * as the argument, but we can't (easily) change the function signature - * because it has to be consistent with what is defined in s2n_kex. - * - * 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); - - GUARD(s2n_kem_send_ciphertext(&(conn->handshake.io), &(conn->secure.kem_params))); - - return 0; -} - -int s2n_hybrid_client_key_send(struct s2n_connection *conn, struct s2n_blob *combined_shared_key) -{ - return s2n_hybrid_client_action(conn, combined_shared_key, &s2n_kex_client_key_send, &conn->handshake.io.write_cursor, - s2n_stuffer_raw_write); -} - -int s2n_client_key_send(struct s2n_connection *conn) -{ - const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg; - struct s2n_blob shared_key = {0}; - - GUARD(s2n_kex_client_key_send(key_exchange, conn, &shared_key)); - - GUARD(s2n_calculate_keys(conn, &shared_key)); - return 0; -} + * can't reassign *shared_key to point to kem_params.shared_secret, + * because that would require us to take struct s2n_blob **shared_key + * as the argument, but we can't (easily) change the function signature + * because it has to be consistent with what is defined in s2n_kex. + * + * 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); + + GUARD(s2n_kem_recv_ciphertext(&(conn->handshake.io), &(conn->secure.kem_params))); + + return 0; +} + +int s2n_hybrid_client_key_recv(struct s2n_connection *conn, struct s2n_blob *combined_shared_key) +{ + return s2n_hybrid_client_action(conn, combined_shared_key, &s2n_kex_client_key_recv, &conn->handshake.io.read_cursor, + &s2n_stuffer_raw_read); +} + +int s2n_client_key_recv(struct s2n_connection *conn) +{ + const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg; + struct s2n_blob shared_key = {0}; + + GUARD(s2n_kex_client_key_recv(key_exchange, conn, &shared_key)); + + GUARD(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)); + + /* We don't need the server params any more */ + GUARD(s2n_dh_params_free(&conn->secure.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)); + + /* We don't need the server params any more */ + GUARD(s2n_ecc_evp_params_free(&conn->secure.server_ecc_evp_params)); + return 0; +} + +int s2n_rsa_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key) +{ + uint8_t client_hello_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; + uint8_t legacy_client_hello_protocol_version = get_client_hello_protocol_version(conn); + 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->size = S2N_TLS_SECRET_LEN; + + GUARD_AS_POSIX(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); + + int encrypted_size = s2n_pkey_size(&conn->secure.server_public_key); + S2N_ERROR_IF(encrypted_size < 0 || encrypted_size > 0xffff, S2N_ERR_SIZE_MISMATCH); + + if (conn->actual_protocol_version > S2N_SSLv3) { + 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); + + /* Encrypt the secret and send it on */ + GUARD(s2n_pkey_encrypt(&conn->secure.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)); + 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 + * 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 + * as the argument, but we can't (easily) change the function signature + * because it has to be consistent with what is defined in s2n_kex. + * + * 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); + + GUARD(s2n_kem_send_ciphertext(&(conn->handshake.io), &(conn->secure.kem_params))); + + return 0; +} + +int s2n_hybrid_client_key_send(struct s2n_connection *conn, struct s2n_blob *combined_shared_key) +{ + return s2n_hybrid_client_action(conn, combined_shared_key, &s2n_kex_client_key_send, &conn->handshake.io.write_cursor, + s2n_stuffer_raw_write); +} + +int s2n_client_key_send(struct s2n_connection *conn) +{ + const struct s2n_kex *key_exchange = conn->secure.cipher_suite->key_exchange_alg; + struct s2n_blob shared_key = {0}; + + GUARD(s2n_kex_client_key_send(key_exchange, conn, &shared_key)); + + GUARD(s2n_calculate_keys(conn, &shared_key)); + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.h b/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.h index ee37cb4a8f..5389988dcc 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.h +++ b/contrib/restricted/aws/s2n/tls/s2n_client_key_exchange.h @@ -1,35 +1,35 @@ -/* - * 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_connection.h" -#include "utils/s2n_blob.h" - -int s2n_dhe_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key); -int s2n_ecdhe_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key); -int s2n_rsa_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key); -int s2n_kem_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key); -int s2n_hybrid_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key); - -int s2n_dhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key); -int s2n_ecdhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key); -int s2n_rsa_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key); -int s2n_kem_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key); -int s2n_hybrid_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key); - -int s2n_dhe_client_key_external(struct s2n_connection * conn, struct s2n_blob* shared_key); -int s2n_ecdhe_client_key_external(struct s2n_connection * conn, struct s2n_blob* shared_key); -int s2n_rsa_client_key_external(struct s2n_connection *conn, struct s2n_blob *shared_key); +/* + * 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_connection.h" +#include "utils/s2n_blob.h" + +int s2n_dhe_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key); +int s2n_ecdhe_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key); +int s2n_rsa_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key); +int s2n_kem_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key); +int s2n_hybrid_client_key_send(struct s2n_connection *conn, struct s2n_blob *shared_key); + +int s2n_dhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key); +int s2n_ecdhe_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key); +int s2n_rsa_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key); +int s2n_kem_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key); +int s2n_hybrid_client_key_recv(struct s2n_connection *conn, struct s2n_blob *shared_key); + +int s2n_dhe_client_key_external(struct s2n_connection * conn, struct s2n_blob* shared_key); +int s2n_ecdhe_client_key_external(struct s2n_connection * conn, struct s2n_blob* shared_key); +int s2n_rsa_client_key_external(struct s2n_connection *conn, struct s2n_blob *shared_key); diff --git a/contrib/restricted/aws/s2n/tls/s2n_config.c b/contrib/restricted/aws/s2n/tls/s2n_config.c index dc674d2803..51a974f8c7 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_config.c +++ b/contrib/restricted/aws/s2n/tls/s2n_config.c @@ -1,860 +1,860 @@ -/* - * 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 <strings.h> -#include <time.h> - -#include "error/s2n_errno.h" - -#include "crypto/s2n_certificate.h" -#include "crypto/s2n_fips.h" - -#include "tls/s2n_cipher_preferences.h" -#include "tls/s2n_security_policies.h" -#include "tls/s2n_tls13.h" -#include "utils/s2n_safety.h" -#include "crypto/s2n_hkdf.h" -#include "utils/s2n_map.h" -#include "utils/s2n_blob.h" - -#if defined(CLOCK_MONOTONIC_RAW) -#define S2N_CLOCK_HW CLOCK_MONOTONIC_RAW -#else -#define S2N_CLOCK_HW CLOCK_MONOTONIC -#endif - -#define S2N_CLOCK_SYS CLOCK_REALTIME - -static int monotonic_clock(void *data, uint64_t *nanoseconds) -{ - struct timespec current_time = {0}; - - GUARD(clock_gettime(S2N_CLOCK_HW, ¤t_time)); - - *nanoseconds = (uint64_t)current_time.tv_sec * 1000000000ull; - *nanoseconds += current_time.tv_nsec; - - return 0; -} - -static int wall_clock(void *data, uint64_t *nanoseconds) -{ - struct timespec current_time = {0}; - - GUARD(clock_gettime(S2N_CLOCK_SYS, ¤t_time)); - - *nanoseconds = (uint64_t)current_time.tv_sec * 1000000000ull; - *nanoseconds += current_time.tv_nsec; - - return 0; -} - -static struct s2n_config s2n_default_config = {0}; -static struct s2n_config s2n_default_fips_config = {0}; -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")); - return S2N_SUCCESS; -} - -static int s2n_config_setup_tls13(struct s2n_config *config) -{ - 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")); - 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; - - /* 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->cert_req_dss_legacy_compat_enabled = 0; - - GUARD(s2n_config_setup_default(config)); - if (s2n_use_default_tls13_config()) { - GUARD(s2n_config_setup_tls13(config)); - } else if (s2n_is_in_fips_mode()) { - 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; - - s2n_x509_trust_store_init_empty(&config->trust_store); - s2n_x509_trust_store_from_system_defaults(&config->trust_store); - - return 0; -} - -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)); - - return 0; -} - -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); - - struct s2n_map *domain_name_to_cert_map = config->domain_name_to_cert_map; - /* s2n_map does not allow zero-size key */ - if (name->size == 0) { - return 0; - } - 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)); - 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)); - } else { - struct certs_by_type *value = (void *) s2n_map_value.data;; - if (value->certs[cert_type] == NULL) { - value->certs[cert_type] = cert_key_pair; - } else if (config->cert_tiebreak_cb) { - /* There's an existing certificate for this (domain_name, auth_method). - * Run the application's tiebreaking callback to decide which cert should be used. - * An application may have some context specific logic to resolve ties that are based - * on factors like trust, expiry, etc. - */ - struct s2n_cert_chain_and_key *winner = config->cert_tiebreak_cb( - value->certs[cert_type], - cert_key_pair, - name->data, - name->size); - if (winner) { - value->certs[cert_type] = winner; - } - } - } - - return 0; -} - -static int s2n_config_build_domain_name_to_cert_map(struct s2n_config *config, struct s2n_cert_chain_and_key *cert_key_pair) -{ - - uint32_t cn_len = 0; - GUARD_AS_POSIX(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)); - - 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)); - } - } 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)); - } - } - - return 0; -} - -struct s2n_config *s2n_fetch_default_config(void) -{ - if (s2n_use_default_tls13_config()) { - return &s2n_default_tls13_config; - } - if (s2n_is_in_fips_mode()) { - return &s2n_default_fips_config; - } - return &s2n_default_config; -} - -int s2n_config_set_unsafe_for_testing(struct s2n_config *config) -{ - S2N_ERROR_IF(!S2N_IN_TEST, S2N_ERR_NOT_IN_UNIT_TEST); - config->client_cert_auth_type = S2N_CERT_AUTH_NONE; - config->check_ocsp = 0; - config->disable_x509_validation = 1; - - return S2N_SUCCESS; -} - -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)); - - /* Set up TLS 1.3 defaults */ - GUARD(s2n_config_init(&s2n_default_tls13_config)); - 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_tls13_config); -} - -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))); - - new_config = (struct s2n_config *)(void *)allocator.data; - if (s2n_config_init(new_config) != S2N_SUCCESS) { - s2n_free(&allocator); - return NULL; - } - - return new_config; -} - -static int s2n_config_store_ticket_key_comparator(const void *a, const void *b) -{ - if (((const struct s2n_ticket_key *) a)->intro_timestamp >= ((const struct s2n_ticket_key *) b)->intro_timestamp) { - return S2N_GREATER_OR_EQUAL; - } else { - return S2N_LESS_THAN; - } -} - -static int s2n_verify_unique_ticket_key_comparator(const void *a, const void *b) -{ - return memcmp(a, b, SHA_DIGEST_LENGTH); -} - -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)); - } - - if (config->ticket_key_hashes == NULL) { - notnull_check(config->ticket_key_hashes = s2n_set_new(SHA_DIGEST_LENGTH, s2n_verify_unique_ticket_key_comparator)); - } - - return 0; -} - -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)); - } - - if (config->ticket_key_hashes != NULL) { - GUARD_AS_POSIX(s2n_set_free_p(&config->ticket_key_hashes)); - } - - return 0; -} - -int s2n_config_free_cert_chain_and_key(struct s2n_config *config) -{ - /* Free the cert_chain_and_key since the application has no reference - * to it. This is necessary until s2n_config_add_cert_chain_and_key is deprecated. */ - if (config->cert_allocated) { - for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { - s2n_cert_chain_and_key_free(config->default_certs_by_type.certs[i]); - } - } - - return 0; -} - -int s2n_config_free_dhparams(struct s2n_config *config) -{ - if (config->dhparams) { - GUARD(s2n_dh_params_free(config->dhparams)); - } - - GUARD(s2n_free_object((uint8_t **)&config->dhparams, sizeof(struct s2n_dh_params))); - return 0; -} - -int s2n_config_free(struct s2n_config *config) -{ - s2n_config_cleanup(config); - - 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); - *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); - 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); - config->ct_type = type; - - return 0; -} - -int s2n_config_set_alert_behavior(struct s2n_config *config, s2n_alert_behavior alert_behavior) -{ - notnull_check(config); - - switch (alert_behavior) { - case S2N_ALERT_FAIL_ON_WARNINGS: - case S2N_ALERT_IGNORE_WARNINGS: - config->alert_behavior = alert_behavior; - break; - default: - S2N_ERROR(S2N_ERR_INVALID_ARGUMENT); - } - - return 0; -} - -int s2n_config_set_verify_host_callback(struct s2n_config *config, s2n_verify_host_fn verify_host_fn, void *data) -{ - notnull_check(config); - config->verify_host = verify_host_fn; - config->data_for_verify_host = data; - return 0; -} - -int s2n_config_set_check_stapled_ocsp_response(struct s2n_config *config, uint8_t check_ocsp) -{ - notnull_check(config); - S2N_ERROR_IF(check_ocsp && !s2n_x509_ocsp_stapling_supported(), S2N_ERR_OCSP_NOT_SUPPORTED); - config->check_ocsp = check_ocsp; - return 0; -} - -int s2n_config_disable_x509_verification(struct s2n_config *config) -{ - notnull_check(config); - s2n_x509_trust_store_wipe(&config->trust_store); - config->disable_x509_validation = 1; - return 0; -} - -int s2n_config_set_max_cert_chain_depth(struct s2n_config *config, uint16_t max_depth) -{ - notnull_check(config); - S2N_ERROR_IF(max_depth == 0, S2N_ERR_INVALID_ARGUMENT); - - config->max_verify_cert_chain_depth = max_depth; - config->max_verify_cert_chain_depth_set = 1; - return 0; -} - - -int s2n_config_set_status_request_type(struct s2n_config *config, s2n_status_request_type type) -{ - S2N_ERROR_IF(type == S2N_STATUS_REQUEST_OCSP && !s2n_x509_ocsp_stapling_supported(), S2N_ERR_OCSP_NOT_SUPPORTED); - - notnull_check(config); - config->status_request_type = type; - - return 0; -} - -int s2n_config_add_pem_to_trust_store(struct s2n_config *config, const char *pem) -{ - notnull_check(config); - notnull_check(pem); - - 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); - int err_code = s2n_x509_trust_store_from_ca_file(&config->trust_store, ca_pem_filename, ca_dir); - - if (!err_code) { - config->status_request_type = s2n_x509_ocsp_stapling_supported() ? S2N_STATUS_REQUEST_OCSP : S2N_STATUS_REQUEST_NONE; - } - - return err_code; -} - -/* Deprecated. Superseded by s2n_config_add_cert_chain_and_key_to_store */ -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)); - config->cert_allocated = 1; - - return 0; -} - -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)); - - 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; -} - -int s2n_config_set_async_pkey_callback(struct s2n_config *config, s2n_async_pkey_fn fn) -{ - notnull_check(config); - - config->async_pkey_cb = fn; - - return S2N_SUCCESS; -} - -int s2n_config_clear_default_certificates(struct s2n_config *config) -{ - notnull_check(config); - for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { - config->default_certs_by_type.certs[i] = NULL; - } - return 0; -} - -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); - 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]); - 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++) { - s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pairs[i]); - config->default_certs_by_type.certs[cert_type] = cert_key_pairs[i]; - } - - config->default_certs_are_explicit = 1; - return 0; -} - -int s2n_config_add_dhparams(struct s2n_config *config, const char *dhparams_pem) -{ - DEFER_CLEANUP(struct s2n_stuffer dhparams_in_stuffer = {0}, s2n_stuffer_free); - DEFER_CLEANUP(struct s2n_stuffer dhparams_out_stuffer = {0}, s2n_stuffer_free); - struct s2n_blob dhparams_blob = {0}; - struct s2n_blob mem = {0}; - - /* Allocate the memory for the chain and key struct */ - 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) { - s2n_free(&mem); - S2N_ERROR_PRESERVE_ERRNO(); - } - if (s2n_stuffer_growable_alloc(&dhparams_out_stuffer, strlen(dhparams_pem)) != S2N_SUCCESS) { - s2n_free(&mem); - S2N_ERROR_PRESERVE_ERRNO(); - } - - /* Convert pem to asn1 and asn1 to the private key */ - 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); - - 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); - - config->wall_clock = clock_fn; - config->sys_clock_ctx = ctx; - - return 0; -} - -extern int s2n_config_set_monotonic_clock(struct s2n_config *config, s2n_clock_time_nanoseconds clock_fn, void *ctx) -{ - notnull_check(clock_fn); - - config->monotonic_clock = clock_fn; - config->monotonic_clock_ctx = ctx; - - return 0; -} - -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); - - config->cache_store = cache_store_callback; - config->cache_store_data = data; - - return 0; -} - -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); - - config->cache_retrieve = cache_retrieve_callback; - config->cache_retrieve_data = data; - - return 0; -} - -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); - - config->cache_delete = cache_delete_callback; - config->cache_delete_data = data; - - return 0; -} - -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); - - if (s2n_config_get_num_default_certs(config) == 0) { - S2N_ERROR(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); - - switch (type) { - case S2N_EXTENSION_CERTIFICATE_TRANSPARENCY: - { - 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)); - } break; - default: - S2N_ERROR(S2N_ERR_UNRECOGNIZED_EXTENSION); - } - - return 0; -} - -int s2n_config_set_client_hello_cb(struct s2n_config *config, s2n_client_hello_fn client_hello_cb, void *ctx) -{ - config->client_hello_cb = client_hello_cb; - config->client_hello_cb_ctx = ctx; - - return 0; -} - -int s2n_config_send_max_fragment_length(struct s2n_config *config, s2n_max_frag_len mfl_code) -{ - notnull_check(config); - - S2N_ERROR_IF(mfl_code > S2N_TLS_MAX_FRAG_LEN_4096, S2N_ERR_INVALID_MAX_FRAG_LEN); - - config->mfl_code = mfl_code; - - return 0; -} - -int s2n_config_accept_max_fragment_length(struct s2n_config *config) -{ - notnull_check(config); - - config->accept_mfl = 1; - - return 0; -} - -int s2n_config_set_session_state_lifetime(struct s2n_config *config, - uint64_t lifetime_in_secs) -{ - notnull_check(config); - - config->session_state_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS); - return 0; -} - -int s2n_config_set_session_tickets_onoff(struct s2n_config *config, uint8_t enabled) -{ - notnull_check(config); - - if (config->use_tickets == enabled) { - return 0; - } - - config->use_tickets = enabled; - - /* session ticket || session id is enabled */ - if (enabled) { - GUARD(s2n_config_init_session_ticket_keys(config)); - } else if (!config->use_session_cache) { - GUARD(s2n_config_free_session_ticket_keys(config)); - } - - return 0; -} - -int s2n_config_set_session_cache_onoff(struct s2n_config *config, uint8_t enabled) -{ - notnull_check(config); - if (enabled && config->cache_store && config->cache_retrieve && config->cache_delete) { - 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)); - } - config->use_session_cache = 0; - } - return 0; -} - -int s2n_config_set_ticket_encrypt_decrypt_key_lifetime(struct s2n_config *config, - uint64_t lifetime_in_secs) -{ - notnull_check(config); - - config->encrypt_decrypt_key_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS); - return 0; -} - -int s2n_config_set_ticket_decrypt_key_lifetime(struct s2n_config *config, - uint64_t lifetime_in_secs) -{ - notnull_check(config); - - config->decrypt_key_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS); - return 0; -} - -int s2n_config_add_ticket_crypto_key(struct s2n_config *config, - const uint8_t *name, uint32_t name_len, - uint8_t *key, uint32_t key_len, - uint64_t intro_time_in_seconds_from_epoch) -{ - notnull_check(config); - notnull_check(name); - notnull_check(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)); - - 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)); - 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); - - uint8_t output_pad[S2N_AES256_KEY_LEN + S2N_TICKET_AAD_IMPLICIT_LEN]; - struct s2n_blob out_key = { .data = output_pad, .size = sizeof(output_pad) }; - struct s2n_blob in_key = { .data = key, .size = key_len }; - struct s2n_blob salt = { .size = 0 }; - struct s2n_blob info = { .size = 0 }; - - struct s2n_ticket_key *session_ticket_key; - DEFER_CLEANUP(struct s2n_blob allocator = {0}, s2n_free); - 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)); - - 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)); - - GUARD_AS_POSIX(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)); - } - - /* Insert hash key into a sorted array at known index */ - GUARD_AS_POSIX(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); - out_key.data = output_pad + S2N_AES256_KEY_LEN; - memcpy_check(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)); - 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)); - - return 0; -} - -int s2n_config_set_cert_tiebreak_callback(struct s2n_config *config, s2n_cert_tiebreak_callback cert_tiebreak_cb) -{ - config->cert_tiebreak_cb = cert_tiebreak_cb; - return 0; -} - -struct s2n_cert_chain_and_key *s2n_config_get_single_default_cert(struct s2n_config *config) -{ - notnull_check_ptr(config); - struct s2n_cert_chain_and_key *cert = NULL; - - for (int i = S2N_CERT_TYPE_COUNT - 1; i >= 0; i--) { - if (config->default_certs_by_type.certs[i] != NULL) { - cert = config->default_certs_by_type.certs[i]; - } - } - return cert; -} - -int s2n_config_get_num_default_certs(struct s2n_config *config) -{ - notnull_check(config); - int num_certs = 0; - for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { - if (config->default_certs_by_type.certs[i] != NULL) { - num_certs++; - } - } - - return num_certs; -} - -int s2n_config_enable_cert_req_dss_legacy_compat(struct s2n_config *config) -{ - notnull_check(config); - config->cert_req_dss_legacy_compat_enabled = 1; - return S2N_SUCCESS; -} +/* + * 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 <strings.h> +#include <time.h> + +#include "error/s2n_errno.h" + +#include "crypto/s2n_certificate.h" +#include "crypto/s2n_fips.h" + +#include "tls/s2n_cipher_preferences.h" +#include "tls/s2n_security_policies.h" +#include "tls/s2n_tls13.h" +#include "utils/s2n_safety.h" +#include "crypto/s2n_hkdf.h" +#include "utils/s2n_map.h" +#include "utils/s2n_blob.h" + +#if defined(CLOCK_MONOTONIC_RAW) +#define S2N_CLOCK_HW CLOCK_MONOTONIC_RAW +#else +#define S2N_CLOCK_HW CLOCK_MONOTONIC +#endif + +#define S2N_CLOCK_SYS CLOCK_REALTIME + +static int monotonic_clock(void *data, uint64_t *nanoseconds) +{ + struct timespec current_time = {0}; + + GUARD(clock_gettime(S2N_CLOCK_HW, ¤t_time)); + + *nanoseconds = (uint64_t)current_time.tv_sec * 1000000000ull; + *nanoseconds += current_time.tv_nsec; + + return 0; +} + +static int wall_clock(void *data, uint64_t *nanoseconds) +{ + struct timespec current_time = {0}; + + GUARD(clock_gettime(S2N_CLOCK_SYS, ¤t_time)); + + *nanoseconds = (uint64_t)current_time.tv_sec * 1000000000ull; + *nanoseconds += current_time.tv_nsec; + + return 0; +} + +static struct s2n_config s2n_default_config = {0}; +static struct s2n_config s2n_default_fips_config = {0}; +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")); + return S2N_SUCCESS; +} + +static int s2n_config_setup_tls13(struct s2n_config *config) +{ + 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")); + 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; + + /* 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->cert_req_dss_legacy_compat_enabled = 0; + + GUARD(s2n_config_setup_default(config)); + if (s2n_use_default_tls13_config()) { + GUARD(s2n_config_setup_tls13(config)); + } else if (s2n_is_in_fips_mode()) { + 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; + + s2n_x509_trust_store_init_empty(&config->trust_store); + s2n_x509_trust_store_from_system_defaults(&config->trust_store); + + return 0; +} + +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)); + + return 0; +} + +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); + + struct s2n_map *domain_name_to_cert_map = config->domain_name_to_cert_map; + /* s2n_map does not allow zero-size key */ + if (name->size == 0) { + return 0; + } + 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)); + 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)); + } else { + struct certs_by_type *value = (void *) s2n_map_value.data;; + if (value->certs[cert_type] == NULL) { + value->certs[cert_type] = cert_key_pair; + } else if (config->cert_tiebreak_cb) { + /* There's an existing certificate for this (domain_name, auth_method). + * Run the application's tiebreaking callback to decide which cert should be used. + * An application may have some context specific logic to resolve ties that are based + * on factors like trust, expiry, etc. + */ + struct s2n_cert_chain_and_key *winner = config->cert_tiebreak_cb( + value->certs[cert_type], + cert_key_pair, + name->data, + name->size); + if (winner) { + value->certs[cert_type] = winner; + } + } + } + + return 0; +} + +static int s2n_config_build_domain_name_to_cert_map(struct s2n_config *config, struct s2n_cert_chain_and_key *cert_key_pair) +{ + + uint32_t cn_len = 0; + GUARD_AS_POSIX(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)); + + 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)); + } + } 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)); + } + } + + return 0; +} + +struct s2n_config *s2n_fetch_default_config(void) +{ + if (s2n_use_default_tls13_config()) { + return &s2n_default_tls13_config; + } + if (s2n_is_in_fips_mode()) { + return &s2n_default_fips_config; + } + return &s2n_default_config; +} + +int s2n_config_set_unsafe_for_testing(struct s2n_config *config) +{ + S2N_ERROR_IF(!S2N_IN_TEST, S2N_ERR_NOT_IN_UNIT_TEST); + config->client_cert_auth_type = S2N_CERT_AUTH_NONE; + config->check_ocsp = 0; + config->disable_x509_validation = 1; + + return S2N_SUCCESS; +} + +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)); + + /* Set up TLS 1.3 defaults */ + GUARD(s2n_config_init(&s2n_default_tls13_config)); + 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_tls13_config); +} + +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))); + + new_config = (struct s2n_config *)(void *)allocator.data; + if (s2n_config_init(new_config) != S2N_SUCCESS) { + s2n_free(&allocator); + return NULL; + } + + return new_config; +} + +static int s2n_config_store_ticket_key_comparator(const void *a, const void *b) +{ + if (((const struct s2n_ticket_key *) a)->intro_timestamp >= ((const struct s2n_ticket_key *) b)->intro_timestamp) { + return S2N_GREATER_OR_EQUAL; + } else { + return S2N_LESS_THAN; + } +} + +static int s2n_verify_unique_ticket_key_comparator(const void *a, const void *b) +{ + return memcmp(a, b, SHA_DIGEST_LENGTH); +} + +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)); + } + + if (config->ticket_key_hashes == NULL) { + notnull_check(config->ticket_key_hashes = s2n_set_new(SHA_DIGEST_LENGTH, s2n_verify_unique_ticket_key_comparator)); + } + + return 0; +} + +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)); + } + + if (config->ticket_key_hashes != NULL) { + GUARD_AS_POSIX(s2n_set_free_p(&config->ticket_key_hashes)); + } + + return 0; +} + +int s2n_config_free_cert_chain_and_key(struct s2n_config *config) +{ + /* Free the cert_chain_and_key since the application has no reference + * to it. This is necessary until s2n_config_add_cert_chain_and_key is deprecated. */ + if (config->cert_allocated) { + for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { + s2n_cert_chain_and_key_free(config->default_certs_by_type.certs[i]); + } + } + + return 0; +} + +int s2n_config_free_dhparams(struct s2n_config *config) +{ + if (config->dhparams) { + GUARD(s2n_dh_params_free(config->dhparams)); + } + + GUARD(s2n_free_object((uint8_t **)&config->dhparams, sizeof(struct s2n_dh_params))); + return 0; +} + +int s2n_config_free(struct s2n_config *config) +{ + s2n_config_cleanup(config); + + 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); + *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); + 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); + config->ct_type = type; + + return 0; +} + +int s2n_config_set_alert_behavior(struct s2n_config *config, s2n_alert_behavior alert_behavior) +{ + notnull_check(config); + + switch (alert_behavior) { + case S2N_ALERT_FAIL_ON_WARNINGS: + case S2N_ALERT_IGNORE_WARNINGS: + config->alert_behavior = alert_behavior; + break; + default: + S2N_ERROR(S2N_ERR_INVALID_ARGUMENT); + } + + return 0; +} + +int s2n_config_set_verify_host_callback(struct s2n_config *config, s2n_verify_host_fn verify_host_fn, void *data) +{ + notnull_check(config); + config->verify_host = verify_host_fn; + config->data_for_verify_host = data; + return 0; +} + +int s2n_config_set_check_stapled_ocsp_response(struct s2n_config *config, uint8_t check_ocsp) +{ + notnull_check(config); + S2N_ERROR_IF(check_ocsp && !s2n_x509_ocsp_stapling_supported(), S2N_ERR_OCSP_NOT_SUPPORTED); + config->check_ocsp = check_ocsp; + return 0; +} + +int s2n_config_disable_x509_verification(struct s2n_config *config) +{ + notnull_check(config); + s2n_x509_trust_store_wipe(&config->trust_store); + config->disable_x509_validation = 1; + return 0; +} + +int s2n_config_set_max_cert_chain_depth(struct s2n_config *config, uint16_t max_depth) +{ + notnull_check(config); + S2N_ERROR_IF(max_depth == 0, S2N_ERR_INVALID_ARGUMENT); + + config->max_verify_cert_chain_depth = max_depth; + config->max_verify_cert_chain_depth_set = 1; + return 0; +} + + +int s2n_config_set_status_request_type(struct s2n_config *config, s2n_status_request_type type) +{ + S2N_ERROR_IF(type == S2N_STATUS_REQUEST_OCSP && !s2n_x509_ocsp_stapling_supported(), S2N_ERR_OCSP_NOT_SUPPORTED); + + notnull_check(config); + config->status_request_type = type; + + return 0; +} + +int s2n_config_add_pem_to_trust_store(struct s2n_config *config, const char *pem) +{ + notnull_check(config); + notnull_check(pem); + + 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); + int err_code = s2n_x509_trust_store_from_ca_file(&config->trust_store, ca_pem_filename, ca_dir); + + if (!err_code) { + config->status_request_type = s2n_x509_ocsp_stapling_supported() ? S2N_STATUS_REQUEST_OCSP : S2N_STATUS_REQUEST_NONE; + } + + return err_code; +} + +/* Deprecated. Superseded by s2n_config_add_cert_chain_and_key_to_store */ +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)); + config->cert_allocated = 1; + + return 0; +} + +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)); + + 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; +} + +int s2n_config_set_async_pkey_callback(struct s2n_config *config, s2n_async_pkey_fn fn) +{ + notnull_check(config); + + config->async_pkey_cb = fn; + + return S2N_SUCCESS; +} + +int s2n_config_clear_default_certificates(struct s2n_config *config) +{ + notnull_check(config); + for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { + config->default_certs_by_type.certs[i] = NULL; + } + return 0; +} + +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); + 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]); + 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++) { + s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pairs[i]); + config->default_certs_by_type.certs[cert_type] = cert_key_pairs[i]; + } + + config->default_certs_are_explicit = 1; + return 0; +} + +int s2n_config_add_dhparams(struct s2n_config *config, const char *dhparams_pem) +{ + DEFER_CLEANUP(struct s2n_stuffer dhparams_in_stuffer = {0}, s2n_stuffer_free); + DEFER_CLEANUP(struct s2n_stuffer dhparams_out_stuffer = {0}, s2n_stuffer_free); + struct s2n_blob dhparams_blob = {0}; + struct s2n_blob mem = {0}; + + /* Allocate the memory for the chain and key struct */ + 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) { + s2n_free(&mem); + S2N_ERROR_PRESERVE_ERRNO(); + } + if (s2n_stuffer_growable_alloc(&dhparams_out_stuffer, strlen(dhparams_pem)) != S2N_SUCCESS) { + s2n_free(&mem); + S2N_ERROR_PRESERVE_ERRNO(); + } + + /* Convert pem to asn1 and asn1 to the private key */ + 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); + + 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); + + config->wall_clock = clock_fn; + config->sys_clock_ctx = ctx; + + return 0; +} + +extern int s2n_config_set_monotonic_clock(struct s2n_config *config, s2n_clock_time_nanoseconds clock_fn, void *ctx) +{ + notnull_check(clock_fn); + + config->monotonic_clock = clock_fn; + config->monotonic_clock_ctx = ctx; + + return 0; +} + +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); + + config->cache_store = cache_store_callback; + config->cache_store_data = data; + + return 0; +} + +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); + + config->cache_retrieve = cache_retrieve_callback; + config->cache_retrieve_data = data; + + return 0; +} + +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); + + config->cache_delete = cache_delete_callback; + config->cache_delete_data = data; + + return 0; +} + +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); + + if (s2n_config_get_num_default_certs(config) == 0) { + S2N_ERROR(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); + + switch (type) { + case S2N_EXTENSION_CERTIFICATE_TRANSPARENCY: + { + 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)); + } break; + default: + S2N_ERROR(S2N_ERR_UNRECOGNIZED_EXTENSION); + } + + return 0; +} + +int s2n_config_set_client_hello_cb(struct s2n_config *config, s2n_client_hello_fn client_hello_cb, void *ctx) +{ + config->client_hello_cb = client_hello_cb; + config->client_hello_cb_ctx = ctx; + + return 0; +} + +int s2n_config_send_max_fragment_length(struct s2n_config *config, s2n_max_frag_len mfl_code) +{ + notnull_check(config); + + S2N_ERROR_IF(mfl_code > S2N_TLS_MAX_FRAG_LEN_4096, S2N_ERR_INVALID_MAX_FRAG_LEN); + + config->mfl_code = mfl_code; + + return 0; +} + +int s2n_config_accept_max_fragment_length(struct s2n_config *config) +{ + notnull_check(config); + + config->accept_mfl = 1; + + return 0; +} + +int s2n_config_set_session_state_lifetime(struct s2n_config *config, + uint64_t lifetime_in_secs) +{ + notnull_check(config); + + config->session_state_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS); + return 0; +} + +int s2n_config_set_session_tickets_onoff(struct s2n_config *config, uint8_t enabled) +{ + notnull_check(config); + + if (config->use_tickets == enabled) { + return 0; + } + + config->use_tickets = enabled; + + /* session ticket || session id is enabled */ + if (enabled) { + GUARD(s2n_config_init_session_ticket_keys(config)); + } else if (!config->use_session_cache) { + GUARD(s2n_config_free_session_ticket_keys(config)); + } + + return 0; +} + +int s2n_config_set_session_cache_onoff(struct s2n_config *config, uint8_t enabled) +{ + notnull_check(config); + if (enabled && config->cache_store && config->cache_retrieve && config->cache_delete) { + 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)); + } + config->use_session_cache = 0; + } + return 0; +} + +int s2n_config_set_ticket_encrypt_decrypt_key_lifetime(struct s2n_config *config, + uint64_t lifetime_in_secs) +{ + notnull_check(config); + + config->encrypt_decrypt_key_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS); + return 0; +} + +int s2n_config_set_ticket_decrypt_key_lifetime(struct s2n_config *config, + uint64_t lifetime_in_secs) +{ + notnull_check(config); + + config->decrypt_key_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS); + return 0; +} + +int s2n_config_add_ticket_crypto_key(struct s2n_config *config, + const uint8_t *name, uint32_t name_len, + uint8_t *key, uint32_t key_len, + uint64_t intro_time_in_seconds_from_epoch) +{ + notnull_check(config); + notnull_check(name); + notnull_check(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)); + + 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)); + 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); + + uint8_t output_pad[S2N_AES256_KEY_LEN + S2N_TICKET_AAD_IMPLICIT_LEN]; + struct s2n_blob out_key = { .data = output_pad, .size = sizeof(output_pad) }; + struct s2n_blob in_key = { .data = key, .size = key_len }; + struct s2n_blob salt = { .size = 0 }; + struct s2n_blob info = { .size = 0 }; + + struct s2n_ticket_key *session_ticket_key; + DEFER_CLEANUP(struct s2n_blob allocator = {0}, s2n_free); + 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)); + + 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)); + + GUARD_AS_POSIX(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)); + } + + /* Insert hash key into a sorted array at known index */ + GUARD_AS_POSIX(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); + out_key.data = output_pad + S2N_AES256_KEY_LEN; + memcpy_check(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)); + 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)); + + return 0; +} + +int s2n_config_set_cert_tiebreak_callback(struct s2n_config *config, s2n_cert_tiebreak_callback cert_tiebreak_cb) +{ + config->cert_tiebreak_cb = cert_tiebreak_cb; + return 0; +} + +struct s2n_cert_chain_and_key *s2n_config_get_single_default_cert(struct s2n_config *config) +{ + notnull_check_ptr(config); + struct s2n_cert_chain_and_key *cert = NULL; + + for (int i = S2N_CERT_TYPE_COUNT - 1; i >= 0; i--) { + if (config->default_certs_by_type.certs[i] != NULL) { + cert = config->default_certs_by_type.certs[i]; + } + } + return cert; +} + +int s2n_config_get_num_default_certs(struct s2n_config *config) +{ + notnull_check(config); + int num_certs = 0; + for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { + if (config->default_certs_by_type.certs[i] != NULL) { + num_certs++; + } + } + + return num_certs; +} + +int s2n_config_enable_cert_req_dss_legacy_compat(struct s2n_config *config) +{ + notnull_check(config); + config->cert_req_dss_legacy_compat_enabled = 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 83985dc7e8..be8baf1da1 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_config.h +++ b/contrib/restricted/aws/s2n/tls/s2n_config.h @@ -1,115 +1,115 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "api/s2n.h" -#include "crypto/s2n_certificate.h" -#include "crypto/s2n_dhe.h" -#include "tls/s2n_resume.h" -#include "tls/s2n_x509_validator.h" -#include "utils/s2n_blob.h" -#include "utils/s2n_set.h" - -#define S2N_MAX_TICKET_KEYS 48 -#define S2N_MAX_TICKET_KEY_HASHES 500 /* 10KB */ - -struct s2n_cipher_preferences; - -struct s2n_config { - 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 */ - unsigned cert_req_dss_legacy_compat_enabled:1; - - struct s2n_dh_params *dhparams; - /* Needed until we can deprecate s2n_config_add_cert_chain_and_key. This is - * used to release memory allocated only in the deprecated API that the application - * does not have a reference to. */ - struct s2n_map *domain_name_to_cert_map; - struct certs_by_type default_certs_by_type; - struct s2n_blob application_protocols; - s2n_status_request_type status_request_type; - s2n_clock_time_nanoseconds wall_clock; - s2n_clock_time_nanoseconds monotonic_clock; - - const struct s2n_security_policy *security_policy; - - void *sys_clock_ctx; - void *monotonic_clock_ctx; - - s2n_client_hello_fn *client_hello_cb; - void *client_hello_cb_ctx; - - uint64_t session_state_lifetime_in_nanos; - - struct s2n_set *ticket_keys; - struct s2n_set *ticket_key_hashes; - uint64_t encrypt_decrypt_key_lifetime_in_nanos; - uint64_t decrypt_key_lifetime_in_nanos; - - /* If session cache is being used, these must all be set */ - s2n_cache_store_callback cache_store; - void *cache_store_data; - - s2n_cache_retrieve_callback cache_retrieve; - void *cache_retrieve_data; - - s2n_cache_delete_callback cache_delete; - void *cache_delete_data; - - s2n_ct_support_level ct_type; - - s2n_cert_auth_type client_cert_auth_type; - - s2n_alert_behavior alert_behavior; - - /* Return TRUE if the host should be trusted, If FALSE this will likely be called again for every host/alternative name - * in the certificate. If any respond TRUE. If none return TRUE, the cert will be considered untrusted. */ - uint8_t (*verify_host)(const char *host_name, size_t host_name_len, void *data); - void *data_for_verify_host; - - /* Application supplied callback to resolve domain name conflicts when loading certs. */ - s2n_cert_tiebreak_callback cert_tiebreak_cb; - - uint8_t mfl_code; - - struct s2n_x509_trust_store trust_store; - uint16_t max_verify_cert_chain_depth; - - s2n_async_pkey_fn async_pkey_cb; -}; - -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); - -int s2n_config_init_session_ticket_keys(struct s2n_config *config); -int s2n_config_free_session_ticket_keys(struct s2n_config *config); - -void s2n_wipe_static_configs(void); -extern struct s2n_cert_chain_and_key *s2n_config_get_single_default_cert(struct s2n_config *config); -int s2n_config_get_num_default_certs(struct s2n_config *config); +/* + * 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_certificate.h" +#include "crypto/s2n_dhe.h" +#include "tls/s2n_resume.h" +#include "tls/s2n_x509_validator.h" +#include "utils/s2n_blob.h" +#include "utils/s2n_set.h" + +#define S2N_MAX_TICKET_KEYS 48 +#define S2N_MAX_TICKET_KEY_HASHES 500 /* 10KB */ + +struct s2n_cipher_preferences; + +struct s2n_config { + 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 */ + unsigned cert_req_dss_legacy_compat_enabled:1; + + struct s2n_dh_params *dhparams; + /* Needed until we can deprecate s2n_config_add_cert_chain_and_key. This is + * used to release memory allocated only in the deprecated API that the application + * does not have a reference to. */ + struct s2n_map *domain_name_to_cert_map; + struct certs_by_type default_certs_by_type; + struct s2n_blob application_protocols; + s2n_status_request_type status_request_type; + s2n_clock_time_nanoseconds wall_clock; + s2n_clock_time_nanoseconds monotonic_clock; + + const struct s2n_security_policy *security_policy; + + void *sys_clock_ctx; + void *monotonic_clock_ctx; + + s2n_client_hello_fn *client_hello_cb; + void *client_hello_cb_ctx; + + uint64_t session_state_lifetime_in_nanos; + + struct s2n_set *ticket_keys; + struct s2n_set *ticket_key_hashes; + uint64_t encrypt_decrypt_key_lifetime_in_nanos; + uint64_t decrypt_key_lifetime_in_nanos; + + /* If session cache is being used, these must all be set */ + s2n_cache_store_callback cache_store; + void *cache_store_data; + + s2n_cache_retrieve_callback cache_retrieve; + void *cache_retrieve_data; + + s2n_cache_delete_callback cache_delete; + void *cache_delete_data; + + s2n_ct_support_level ct_type; + + s2n_cert_auth_type client_cert_auth_type; + + s2n_alert_behavior alert_behavior; + + /* Return TRUE if the host should be trusted, If FALSE this will likely be called again for every host/alternative name + * in the certificate. If any respond TRUE. If none return TRUE, the cert will be considered untrusted. */ + uint8_t (*verify_host)(const char *host_name, size_t host_name_len, void *data); + void *data_for_verify_host; + + /* Application supplied callback to resolve domain name conflicts when loading certs. */ + s2n_cert_tiebreak_callback cert_tiebreak_cb; + + uint8_t mfl_code; + + struct s2n_x509_trust_store trust_store; + uint16_t max_verify_cert_chain_depth; + + s2n_async_pkey_fn async_pkey_cb; +}; + +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); + +int s2n_config_init_session_ticket_keys(struct s2n_config *config); +int s2n_config_free_session_ticket_keys(struct s2n_config *config); + +void s2n_wipe_static_configs(void); +extern struct s2n_cert_chain_and_key *s2n_config_get_single_default_cert(struct s2n_config *config); +int s2n_config_get_num_default_certs(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 89aa144750..ae23da2439 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_connection.c +++ b/contrib/restricted/aws/s2n/tls/s2n_connection.c @@ -1,1354 +1,1354 @@ -/* - * 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 <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include <time.h> -#include <unistd.h> - -#include <s2n.h> -#include <stdbool.h> - -#include "crypto/s2n_fips.h" - -#include "error/s2n_errno.h" - -#include "tls/extensions/s2n_client_server_name.h" -#include "tls/s2n_alerts.h" -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_connection_evp_digests.h" -#include "tls/s2n_handshake.h" -#include "tls/s2n_kem.h" -#include "tls/s2n_prf.h" -#include "tls/s2n_record.h" -#include "tls/s2n_resume.h" -#include "tls/s2n_security_policies.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" - -#include "crypto/s2n_certificate.h" -#include "crypto/s2n_cipher.h" - -#include "utils/s2n_blob.h" -#include "utils/s2n_compiler.h" -#include "utils/s2n_mem.h" -#include "utils/s2n_random.h" -#include "utils/s2n_safety.h" -#include "utils/s2n_socket.h" -#include "utils/s2n_timer.h" - -#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)); - - return 0; -} - -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)); - - return 0; -} - -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)); - - /* 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())); - - 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)); - - 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)); - - 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)); - - 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)); - - /* 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)); - - /* 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)); - - GUARD_PTR(s2n_connection_new_hmacs(conn)); - GUARD_PTR(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)); - - 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)); - - return 0; -} - -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)); - - 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; - s2n_connection_set_config(conn, config); - - return 0; -} - -static int s2n_connection_wipe_keys(struct s2n_connection *conn) -{ - /* Destroy any keys - we call destroy on the object as that is where - * keys are allocated. */ - if (conn->secure.cipher_suite - && 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)); - } - - /* 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)); - 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)); - - return 0; -} - -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)); - - return 0; -} - -static int s2n_connection_free_io_contexts(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; - } - - 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))); - - return 0; -} - -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)); - } - if (s2n_connection_is_managed_corked(conn) && conn->send){ - 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)); - - return 0; -} - -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)); - - return 0; -} - -static uint8_t s2n_default_verify_host(const char *host_name, size_t len, void *data) -{ - /* if present, match server_name of the connection using rules - * outlined in RFC6125 6.4. */ - - struct s2n_connection *conn = data; - - if (conn->server_name[0] == '\0') { - return 0; - } - - /* complete match */ - if (strlen(conn->server_name) == len && - strncasecmp(conn->server_name, host_name, len) == 0) { - return 1; - } - - /* match 1 level of wildcard */ - if (len > 2 && host_name[0] == '*' && host_name[1] == '.') { - const char *suffix = strchr(conn->server_name, '.'); - - if (suffix == NULL) { - return 0; - } - - if (strlen(suffix) == len - 1 && - strncasecmp(suffix, host_name + 1, len - 1) == 0) { - return 1; - } - } - - return 0; -} - -int s2n_connection_free(struct s2n_connection *conn) -{ - GUARD(s2n_connection_wipe_keys(conn)); - GUARD(s2n_connection_free_keys(conn)); - GUARD(s2n_psk_parameters_free(&conn->psk_params)); - - GUARD(s2n_prf_free(conn)); - - GUARD(s2n_connection_reset_hashes(conn)); - GUARD(s2n_connection_free_hashes(conn)); - - GUARD(s2n_connection_reset_hmacs(conn)); - GUARD(s2n_connection_free_hmacs(conn)); - - GUARD(s2n_connection_free_io_contexts(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)); - 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))); - - return 0; -} - -int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *config) -{ - notnull_check(conn); - notnull_check(config); - - if (conn->config == config) { - return 0; - } - - /* 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); - } - - s2n_x509_validator_wipe(&conn->x509_validator); - - s2n_cert_auth_type auth_type = config->client_cert_auth_type; - - if (conn->client_cert_auth_type_overridden) { - auth_type = conn->client_cert_auth_type; - } - - 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)); - } - else { - 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; - conn->data_for_verify_host = config->data_for_verify_host; - } else { - conn->verify_host_fn = s2n_default_verify_host; - conn->data_for_verify_host = conn; - } - } - - 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)); - } - } - - conn->config = config; - return 0; -} - -int s2n_connection_set_ctx(struct s2n_connection *conn, void *ctx) -{ - conn->context = ctx; - return 0; -} - -void *s2n_connection_get_ctx(struct s2n_connection *conn) -{ - return conn->context; -} - -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)); - - ENSURE_POSIX(s2n_stuffer_is_consumed(&conn->out), S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA); - 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)); - - POSTCONDITION_POSIX(s2n_stuffer_validate(&conn->out)); - POSTCONDITION_POSIX(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)); - - /* Wipe the buffers we are going to free */ - GUARD(s2n_stuffer_wipe(&conn->handshake.io)); - 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)); - - /* 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)); - - return 0; -} - -int s2n_connection_wipe(struct s2n_connection *conn) -{ - /* First make a copy of everything we'd like to save, which isn't very much. */ - int mode = conn->mode; - struct s2n_config *config = conn->config; - struct s2n_stuffer alert_in = {0}; - struct s2n_stuffer reader_alert_out = {0}; - struct s2n_stuffer writer_alert_out = {0}; - struct s2n_stuffer client_ticket_to_decrypt = {0}; - struct s2n_stuffer handshake_io = {0}; - struct s2n_stuffer client_hello_raw_message = {0}; - struct s2n_stuffer header_in = {0}; - struct s2n_stuffer in = {0}; - struct s2n_stuffer out = {0}; - /* Session keys will be wiped. Preserve structs to avoid reallocation */ - struct s2n_session_key initial_client_key = {0}; - 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}; - struct s2n_connection_hmac_handles hmac_handles = {0}; - - /* 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)); - - /* 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)); - - /* Allocate memory for handling handshakes */ - 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)); - - /* Remove context associated with connection */ - conn->context = NULL; - conn->verify_host_fn_overridden = 0; - conn->verify_host_fn = NULL; - conn->data_for_verify_host = NULL; - - /* Clone the stuffers */ - /* ignore gcc 4.7 address warnings because dest is allocated on the stack */ - /* pragma gcc diagnostic was added in gcc 4.6 */ -#if S2N_GCC_VERSION_AT_LEAST(4,6,0) -#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)); -#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)); - - /* Re-initialize hash and hmac states */ - GUARD(s2n_connection_init_hashes(conn)); - GUARD(s2n_connection_init_hmacs(conn)); - - GUARD_AS_POSIX(s2n_psk_parameters_init(&conn->psk_params)); - - /* Require all handshakes hashes. This set can be reduced as the handshake progresses. */ - 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 */ - /* during handshake. */ - conn->server_protocol_version = s2n_highest_protocol_version; - conn->client_protocol_version = s2n_unknown_protocol_version; - conn->actual_protocol_version = s2n_unknown_protocol_version; - } - else { - /* For clients, also set actual_protocol_version. Record generation uses that value for the initial */ - /* ClientHello record version. Not all servers ignore the record version in ClientHello. */ - conn->server_protocol_version = s2n_unknown_protocol_version; - conn->client_protocol_version = s2n_highest_protocol_version; - conn->actual_protocol_version = s2n_highest_protocol_version; - } - - return 0; -} - -int s2n_connection_set_recv_ctx(struct s2n_connection *conn, void *ctx) -{ - conn->recv_io_context = ctx; - return 0; -} - -int s2n_connection_set_send_ctx(struct s2n_connection *conn, void *ctx) -{ - conn->send_io_context = ctx; - return 0; -} - -int s2n_connection_set_recv_cb(struct s2n_connection *conn, s2n_recv_fn recv) -{ - conn->recv = recv; - return 0; -} - -int s2n_connection_set_send_cb(struct s2n_connection *conn, s2n_send_fn send) -{ - conn->send = send; - return 0; -} - -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); - - *der_cert_chain_out = conn->secure.client_cert_chain.data; - *cert_chain_len = conn->secure.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); - - 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); - } - - notnull_check(*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); - - 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); - } - - notnull_check(*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); - - 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); - } - - notnull_check(*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); - - 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); - } - - notnull_check(*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); - - 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); - } - - notnull_check(*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); - - *protocol_preferences = NULL; - if (conn->application_protocols_overridden.size > 0) { - *protocol_preferences = &conn->application_protocols_overridden; - } else { - *protocol_preferences = &conn->config->application_protocols; - } - - notnull_check(*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); - - if (conn->client_cert_auth_type_overridden) { - *client_cert_auth_type = conn->client_cert_auth_type; - } else { - *client_cert_auth_type = conn->config->client_cert_auth_type; - } - - return 0; -} - -int s2n_connection_set_client_auth_type(struct s2n_connection *conn, s2n_cert_auth_type client_cert_auth_type) -{ - conn->client_cert_auth_type_overridden = 1; - conn->client_cert_auth_type = client_cert_auth_type; - return 0; -} - -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)); - - 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; - - /* 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)); - - return 0; -} - -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))); - - 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; - - /* 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)); - - uint8_t ipv6; - if (0 == s2n_socket_is_ipv6(wfd, &ipv6)) { - conn->ipv6 = (ipv6 ? 1 : 0); - } - - conn->write_fd_broken = 0; - - return 0; -} - -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)); - 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); - } - conn->corked_io = 1; - - return 0; -} - -uint64_t s2n_connection_get_wire_bytes_in(struct s2n_connection *conn) -{ - return conn->wire_bytes_in; -} - -uint64_t s2n_connection_get_wire_bytes_out(struct s2n_connection *conn) -{ - return conn->wire_bytes_out; -} - -const char *s2n_connection_get_cipher(struct s2n_connection *conn) -{ - notnull_check_ptr(conn); - notnull_check_ptr(conn->secure.cipher_suite); - - return conn->secure.cipher_suite->name; -} - -const char *s2n_connection_get_curve(struct s2n_connection *conn) -{ - notnull_check_ptr(conn); - - if (!conn->secure.server_ecc_evp_params.negotiated_curve) { - return "NONE"; - } - - return conn->secure.server_ecc_evp_params.negotiated_curve->name; -} - -const char *s2n_connection_get_kem_name(struct s2n_connection *conn) -{ - notnull_check_ptr(conn); - - if (!conn->secure.kem_params.kem) { - return "NONE"; - } - - return conn->secure.kem_params.kem->name; -} - -const char *s2n_connection_get_kem_group_name(struct s2n_connection *conn) -{ - notnull_check_ptr(conn); - - if (!conn->secure.chosen_client_kem_group_params || !conn->secure.chosen_client_kem_group_params->kem_group) { - return "NONE"; - } - - return conn->secure.chosen_client_kem_group_params->kem_group->name; -} - -int s2n_connection_get_client_protocol_version(struct s2n_connection *conn) -{ - notnull_check(conn); - - return conn->client_protocol_version; -} - -int s2n_connection_get_server_protocol_version(struct s2n_connection *conn) -{ - notnull_check(conn); - - return conn->server_protocol_version; -} - -int s2n_connection_get_actual_protocol_version(struct s2n_connection *conn) -{ - notnull_check(conn); - - return conn->actual_protocol_version; -} - -int s2n_connection_get_client_hello_version(struct s2n_connection *conn) -{ - notnull_check(conn); - - return conn->client_hello_version; -} - -int s2n_connection_client_cert_used(struct s2n_connection *conn) -{ - notnull_check(conn); - - if ((conn->handshake.handshake_type & CLIENT_AUTH) && is_handshake_complete(conn)) { - if (conn->handshake.handshake_type & NO_CLIENT_CERT) { - return 0; - } - return 1; - } - return 0; -} - -int s2n_connection_get_alert(struct s2n_connection *conn) -{ - notnull_check(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)); - - return alert_code; -} - -int s2n_set_server_name(struct s2n_connection *conn, const char *server_name) -{ - notnull_check(conn); - notnull_check(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); - - return 0; -} - -const char *s2n_get_server_name(struct s2n_connection *conn) -{ - notnull_check_ptr(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)); - - if (!conn->server_name[0]) { - return NULL; - } - - return conn->server_name; -} - -const char *s2n_get_application_protocol(struct s2n_connection *conn) -{ - notnull_check_ptr(conn); - - if (strlen(conn->application_protocol) == 0) { - return NULL; - } - - return conn->application_protocol; -} - -int s2n_connection_get_session_id_length(struct s2n_connection *conn) -{ - notnull_check(conn); - 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); - - 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); - - return session_id_len; -} - -int s2n_connection_set_blinding(struct s2n_connection *conn, s2n_blinding blinding) -{ - notnull_check(conn); - conn->blinding = blinding; - - return 0; -} - -#define ONE_S INT64_C(1000000000) -#define TEN_S INT64_C(10000000000) - -uint64_t s2n_connection_get_delay(struct s2n_connection *conn) -{ - if (!conn->delay) { - return 0; - } - - uint64_t elapsed; - /* This will cast -1 to max uint64_t */ - GUARD_AS_POSIX(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed)); - - if (elapsed > conn->delay) { - return 0; - } - - return conn->delay - elapsed; -} - -int s2n_connection_kill(struct s2n_connection *conn) -{ - notnull_check(conn); - - conn->closed = 1; - - /* Delay between 10 and 30 seconds in nanoseconds */ - int64_t min = TEN_S, max = 3 * TEN_S; - - /* 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)); - - conn->delay = min + rand_delay; - - /* Restart the write timer */ - GUARD_AS_POSIX(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 }; - int r; - - do { - r = nanosleep(&sleep_time, &sleep_time); - } - while (r != 0); - } - - return 0; -} - -const uint8_t *s2n_connection_get_ocsp_response(struct s2n_connection *conn, uint32_t * length) -{ - notnull_check_ptr(conn); - notnull_check_ptr(length); - - *length = conn->status_response.size; - return conn->status_response.data; -} - -int s2n_connection_prefer_throughput(struct s2n_connection *conn) -{ - notnull_check(conn); - - if (!conn->mfl_code) { - conn->max_outgoing_fragment_length = S2N_LARGE_FRAGMENT_LENGTH; - } - - return 0; -} - -int s2n_connection_prefer_low_latency(struct s2n_connection *conn) -{ - notnull_check(conn); - - if (!conn->mfl_code) { - conn->max_outgoing_fragment_length = S2N_SMALL_FRAGMENT_LENGTH; - } - - return 0; -} - -int s2n_connection_set_dynamic_record_threshold(struct s2n_connection *conn, uint32_t resize_threshold, uint16_t timeout_threshold) -{ - notnull_check(conn); - S2N_ERROR_IF(resize_threshold > S2N_TLS_MAX_RESIZE_THRESHOLD, S2N_ERR_INVALID_DYNAMIC_THRESHOLD); - - conn->dynamic_record_resize_threshold = resize_threshold; - conn->dynamic_record_timeout_threshold = timeout_threshold; - return 0; -} - -int s2n_connection_set_verify_host_callback(struct s2n_connection *conn, s2n_verify_host_fn verify_host_fn, void *data) { - notnull_check(conn); - - conn->verify_host_fn = verify_host_fn; - conn->data_for_verify_host = data; - conn->verify_host_fn_overridden = 1; - - return 0; -} - -int s2n_connection_recv_stuffer(struct s2n_stuffer *stuffer, struct s2n_connection *conn, uint32_t len) -{ - notnull_check(conn->recv); - /* Make sure we have enough space to write */ - GUARD(s2n_stuffer_reserve_space(stuffer, len)); - - int r = 0; - do { - errno = 0; - r = conn->recv(conn->recv_io_context, stuffer->blob.data + stuffer->write_cursor, len); - S2N_ERROR_IF(r < 0 && errno != EINTR, S2N_ERR_RECV_STUFFER_FROM_CONN); - } while (r < 0); - - /* Record just how many bytes we have written */ - 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); - if (conn->write_fd_broken) { - S2N_ERROR(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); - - int w = 0; - do { - errno = 0; - w = conn->send(conn->send_io_context, stuffer->blob.data + stuffer->read_cursor, len); - if (w < 0 && errno == EPIPE) { - conn->write_fd_broken = 1; - } - S2N_ERROR_IF(w < 0 && errno != EINTR, S2N_ERR_SEND_STUFFER_TO_CONN); - } while (w < 0); - - 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); - - return (s2n_connection->managed_io && s2n_connection->corked_io); -} - -const uint8_t *s2n_connection_get_sct_list(struct s2n_connection *conn, uint32_t *length) -{ - if (!length) { - return NULL; - } - - *length = conn->ct_response.size; - return conn->ct_response.data; -} - -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)); - - 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); - return conn->handshake_params.our_chain_and_key; -} - -uint8_t s2n_connection_get_protocol_version(const struct s2n_connection *conn) -{ - if (conn == NULL) { - return S2N_UNKNOWN_PROTOCOL_VERSION; - } - - if (conn->actual_protocol_version != S2N_UNKNOWN_PROTOCOL_VERSION) { - return conn->actual_protocol_version; - } - - if (conn->mode == S2N_CLIENT) { - return conn->client_protocol_version; - } - return conn->server_protocol_version; -} - -int s2n_connection_set_keyshare_by_name_for_testing(struct s2n_connection *conn, const char* curve_name) -{ - ENSURE_POSIX(S2N_IN_TEST, S2N_ERR_NOT_IN_TEST); - notnull_check(conn); - - if (!strcmp(curve_name, "none")) { - S2N_SET_KEY_SHARE_LIST_EMPTY(conn->preferred_key_shares); - return S2N_SUCCESS; - } - - const struct s2n_ecc_preferences *ecc_pref = NULL; - GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); - notnull_check(ecc_pref); - - 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; - } - } - - S2N_ERROR(S2N_ERR_ECDHE_UNSUPPORTED_CURVE); -} +/* + * 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 <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <time.h> +#include <unistd.h> + +#include <s2n.h> +#include <stdbool.h> + +#include "crypto/s2n_fips.h" + +#include "error/s2n_errno.h" + +#include "tls/extensions/s2n_client_server_name.h" +#include "tls/s2n_alerts.h" +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_connection_evp_digests.h" +#include "tls/s2n_handshake.h" +#include "tls/s2n_kem.h" +#include "tls/s2n_prf.h" +#include "tls/s2n_record.h" +#include "tls/s2n_resume.h" +#include "tls/s2n_security_policies.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" + +#include "crypto/s2n_certificate.h" +#include "crypto/s2n_cipher.h" + +#include "utils/s2n_blob.h" +#include "utils/s2n_compiler.h" +#include "utils/s2n_mem.h" +#include "utils/s2n_random.h" +#include "utils/s2n_safety.h" +#include "utils/s2n_socket.h" +#include "utils/s2n_timer.h" + +#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)); + + return 0; +} + +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)); + + return 0; +} + +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)); + + /* 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())); + + 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)); + + 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)); + + 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)); + + 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)); + + /* 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)); + + /* 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)); + + GUARD_PTR(s2n_connection_new_hmacs(conn)); + GUARD_PTR(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)); + + 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)); + + return 0; +} + +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)); + + 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; + s2n_connection_set_config(conn, config); + + return 0; +} + +static int s2n_connection_wipe_keys(struct s2n_connection *conn) +{ + /* Destroy any keys - we call destroy on the object as that is where + * keys are allocated. */ + if (conn->secure.cipher_suite + && 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)); + } + + /* 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)); + 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)); + + return 0; +} + +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)); + + return 0; +} + +static int s2n_connection_free_io_contexts(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; + } + + 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))); + + return 0; +} + +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)); + } + if (s2n_connection_is_managed_corked(conn) && conn->send){ + 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)); + + return 0; +} + +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)); + + return 0; +} + +static uint8_t s2n_default_verify_host(const char *host_name, size_t len, void *data) +{ + /* if present, match server_name of the connection using rules + * outlined in RFC6125 6.4. */ + + struct s2n_connection *conn = data; + + if (conn->server_name[0] == '\0') { + return 0; + } + + /* complete match */ + if (strlen(conn->server_name) == len && + strncasecmp(conn->server_name, host_name, len) == 0) { + return 1; + } + + /* match 1 level of wildcard */ + if (len > 2 && host_name[0] == '*' && host_name[1] == '.') { + const char *suffix = strchr(conn->server_name, '.'); + + if (suffix == NULL) { + return 0; + } + + if (strlen(suffix) == len - 1 && + strncasecmp(suffix, host_name + 1, len - 1) == 0) { + return 1; + } + } + + return 0; +} + +int s2n_connection_free(struct s2n_connection *conn) +{ + GUARD(s2n_connection_wipe_keys(conn)); + GUARD(s2n_connection_free_keys(conn)); + GUARD(s2n_psk_parameters_free(&conn->psk_params)); + + GUARD(s2n_prf_free(conn)); + + GUARD(s2n_connection_reset_hashes(conn)); + GUARD(s2n_connection_free_hashes(conn)); + + GUARD(s2n_connection_reset_hmacs(conn)); + GUARD(s2n_connection_free_hmacs(conn)); + + GUARD(s2n_connection_free_io_contexts(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)); + 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))); + + return 0; +} + +int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *config) +{ + notnull_check(conn); + notnull_check(config); + + if (conn->config == config) { + return 0; + } + + /* 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); + } + + s2n_x509_validator_wipe(&conn->x509_validator); + + s2n_cert_auth_type auth_type = config->client_cert_auth_type; + + if (conn->client_cert_auth_type_overridden) { + auth_type = conn->client_cert_auth_type; + } + + 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)); + } + else { + 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; + conn->data_for_verify_host = config->data_for_verify_host; + } else { + conn->verify_host_fn = s2n_default_verify_host; + conn->data_for_verify_host = conn; + } + } + + 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)); + } + } + + conn->config = config; + return 0; +} + +int s2n_connection_set_ctx(struct s2n_connection *conn, void *ctx) +{ + conn->context = ctx; + return 0; +} + +void *s2n_connection_get_ctx(struct s2n_connection *conn) +{ + return conn->context; +} + +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)); + + ENSURE_POSIX(s2n_stuffer_is_consumed(&conn->out), S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA); + 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)); + + POSTCONDITION_POSIX(s2n_stuffer_validate(&conn->out)); + POSTCONDITION_POSIX(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)); + + /* Wipe the buffers we are going to free */ + GUARD(s2n_stuffer_wipe(&conn->handshake.io)); + 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)); + + /* 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)); + + return 0; +} + +int s2n_connection_wipe(struct s2n_connection *conn) +{ + /* First make a copy of everything we'd like to save, which isn't very much. */ + int mode = conn->mode; + struct s2n_config *config = conn->config; + struct s2n_stuffer alert_in = {0}; + struct s2n_stuffer reader_alert_out = {0}; + struct s2n_stuffer writer_alert_out = {0}; + struct s2n_stuffer client_ticket_to_decrypt = {0}; + struct s2n_stuffer handshake_io = {0}; + struct s2n_stuffer client_hello_raw_message = {0}; + struct s2n_stuffer header_in = {0}; + struct s2n_stuffer in = {0}; + struct s2n_stuffer out = {0}; + /* Session keys will be wiped. Preserve structs to avoid reallocation */ + struct s2n_session_key initial_client_key = {0}; + 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}; + struct s2n_connection_hmac_handles hmac_handles = {0}; + + /* 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)); + + /* 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)); + + /* Allocate memory for handling handshakes */ + 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)); + + /* Remove context associated with connection */ + conn->context = NULL; + conn->verify_host_fn_overridden = 0; + conn->verify_host_fn = NULL; + conn->data_for_verify_host = NULL; + + /* Clone the stuffers */ + /* ignore gcc 4.7 address warnings because dest is allocated on the stack */ + /* pragma gcc diagnostic was added in gcc 4.6 */ +#if S2N_GCC_VERSION_AT_LEAST(4,6,0) +#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)); +#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)); + + /* Re-initialize hash and hmac states */ + GUARD(s2n_connection_init_hashes(conn)); + GUARD(s2n_connection_init_hmacs(conn)); + + GUARD_AS_POSIX(s2n_psk_parameters_init(&conn->psk_params)); + + /* Require all handshakes hashes. This set can be reduced as the handshake progresses. */ + 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 */ + /* during handshake. */ + conn->server_protocol_version = s2n_highest_protocol_version; + conn->client_protocol_version = s2n_unknown_protocol_version; + conn->actual_protocol_version = s2n_unknown_protocol_version; + } + else { + /* For clients, also set actual_protocol_version. Record generation uses that value for the initial */ + /* ClientHello record version. Not all servers ignore the record version in ClientHello. */ + conn->server_protocol_version = s2n_unknown_protocol_version; + conn->client_protocol_version = s2n_highest_protocol_version; + conn->actual_protocol_version = s2n_highest_protocol_version; + } + + return 0; +} + +int s2n_connection_set_recv_ctx(struct s2n_connection *conn, void *ctx) +{ + conn->recv_io_context = ctx; + return 0; +} + +int s2n_connection_set_send_ctx(struct s2n_connection *conn, void *ctx) +{ + conn->send_io_context = ctx; + return 0; +} + +int s2n_connection_set_recv_cb(struct s2n_connection *conn, s2n_recv_fn recv) +{ + conn->recv = recv; + return 0; +} + +int s2n_connection_set_send_cb(struct s2n_connection *conn, s2n_send_fn send) +{ + conn->send = send; + return 0; +} + +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); + + *der_cert_chain_out = conn->secure.client_cert_chain.data; + *cert_chain_len = conn->secure.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); + + 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); + } + + notnull_check(*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); + + 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); + } + + notnull_check(*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); + + 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); + } + + notnull_check(*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); + + 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); + } + + notnull_check(*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); + + 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); + } + + notnull_check(*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); + + *protocol_preferences = NULL; + if (conn->application_protocols_overridden.size > 0) { + *protocol_preferences = &conn->application_protocols_overridden; + } else { + *protocol_preferences = &conn->config->application_protocols; + } + + notnull_check(*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); + + if (conn->client_cert_auth_type_overridden) { + *client_cert_auth_type = conn->client_cert_auth_type; + } else { + *client_cert_auth_type = conn->config->client_cert_auth_type; + } + + return 0; +} + +int s2n_connection_set_client_auth_type(struct s2n_connection *conn, s2n_cert_auth_type client_cert_auth_type) +{ + conn->client_cert_auth_type_overridden = 1; + conn->client_cert_auth_type = client_cert_auth_type; + return 0; +} + +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)); + + 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; + + /* 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)); + + return 0; +} + +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))); + + 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; + + /* 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)); + + uint8_t ipv6; + if (0 == s2n_socket_is_ipv6(wfd, &ipv6)) { + conn->ipv6 = (ipv6 ? 1 : 0); + } + + conn->write_fd_broken = 0; + + return 0; +} + +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)); + 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); + } + conn->corked_io = 1; + + return 0; +} + +uint64_t s2n_connection_get_wire_bytes_in(struct s2n_connection *conn) +{ + return conn->wire_bytes_in; +} + +uint64_t s2n_connection_get_wire_bytes_out(struct s2n_connection *conn) +{ + return conn->wire_bytes_out; +} + +const char *s2n_connection_get_cipher(struct s2n_connection *conn) +{ + notnull_check_ptr(conn); + notnull_check_ptr(conn->secure.cipher_suite); + + return conn->secure.cipher_suite->name; +} + +const char *s2n_connection_get_curve(struct s2n_connection *conn) +{ + notnull_check_ptr(conn); + + if (!conn->secure.server_ecc_evp_params.negotiated_curve) { + return "NONE"; + } + + return conn->secure.server_ecc_evp_params.negotiated_curve->name; +} + +const char *s2n_connection_get_kem_name(struct s2n_connection *conn) +{ + notnull_check_ptr(conn); + + if (!conn->secure.kem_params.kem) { + return "NONE"; + } + + return conn->secure.kem_params.kem->name; +} + +const char *s2n_connection_get_kem_group_name(struct s2n_connection *conn) +{ + notnull_check_ptr(conn); + + if (!conn->secure.chosen_client_kem_group_params || !conn->secure.chosen_client_kem_group_params->kem_group) { + return "NONE"; + } + + return conn->secure.chosen_client_kem_group_params->kem_group->name; +} + +int s2n_connection_get_client_protocol_version(struct s2n_connection *conn) +{ + notnull_check(conn); + + return conn->client_protocol_version; +} + +int s2n_connection_get_server_protocol_version(struct s2n_connection *conn) +{ + notnull_check(conn); + + return conn->server_protocol_version; +} + +int s2n_connection_get_actual_protocol_version(struct s2n_connection *conn) +{ + notnull_check(conn); + + return conn->actual_protocol_version; +} + +int s2n_connection_get_client_hello_version(struct s2n_connection *conn) +{ + notnull_check(conn); + + return conn->client_hello_version; +} + +int s2n_connection_client_cert_used(struct s2n_connection *conn) +{ + notnull_check(conn); + + if ((conn->handshake.handshake_type & CLIENT_AUTH) && is_handshake_complete(conn)) { + if (conn->handshake.handshake_type & NO_CLIENT_CERT) { + return 0; + } + return 1; + } + return 0; +} + +int s2n_connection_get_alert(struct s2n_connection *conn) +{ + notnull_check(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)); + + return alert_code; +} + +int s2n_set_server_name(struct s2n_connection *conn, const char *server_name) +{ + notnull_check(conn); + notnull_check(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); + + return 0; +} + +const char *s2n_get_server_name(struct s2n_connection *conn) +{ + notnull_check_ptr(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)); + + if (!conn->server_name[0]) { + return NULL; + } + + return conn->server_name; +} + +const char *s2n_get_application_protocol(struct s2n_connection *conn) +{ + notnull_check_ptr(conn); + + if (strlen(conn->application_protocol) == 0) { + return NULL; + } + + return conn->application_protocol; +} + +int s2n_connection_get_session_id_length(struct s2n_connection *conn) +{ + notnull_check(conn); + 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); + + 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); + + return session_id_len; +} + +int s2n_connection_set_blinding(struct s2n_connection *conn, s2n_blinding blinding) +{ + notnull_check(conn); + conn->blinding = blinding; + + return 0; +} + +#define ONE_S INT64_C(1000000000) +#define TEN_S INT64_C(10000000000) + +uint64_t s2n_connection_get_delay(struct s2n_connection *conn) +{ + if (!conn->delay) { + return 0; + } + + uint64_t elapsed; + /* This will cast -1 to max uint64_t */ + GUARD_AS_POSIX(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed)); + + if (elapsed > conn->delay) { + return 0; + } + + return conn->delay - elapsed; +} + +int s2n_connection_kill(struct s2n_connection *conn) +{ + notnull_check(conn); + + conn->closed = 1; + + /* Delay between 10 and 30 seconds in nanoseconds */ + int64_t min = TEN_S, max = 3 * TEN_S; + + /* 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)); + + conn->delay = min + rand_delay; + + /* Restart the write timer */ + GUARD_AS_POSIX(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 }; + int r; + + do { + r = nanosleep(&sleep_time, &sleep_time); + } + while (r != 0); + } + + return 0; +} + +const uint8_t *s2n_connection_get_ocsp_response(struct s2n_connection *conn, uint32_t * length) +{ + notnull_check_ptr(conn); + notnull_check_ptr(length); + + *length = conn->status_response.size; + return conn->status_response.data; +} + +int s2n_connection_prefer_throughput(struct s2n_connection *conn) +{ + notnull_check(conn); + + if (!conn->mfl_code) { + conn->max_outgoing_fragment_length = S2N_LARGE_FRAGMENT_LENGTH; + } + + return 0; +} + +int s2n_connection_prefer_low_latency(struct s2n_connection *conn) +{ + notnull_check(conn); + + if (!conn->mfl_code) { + conn->max_outgoing_fragment_length = S2N_SMALL_FRAGMENT_LENGTH; + } + + return 0; +} + +int s2n_connection_set_dynamic_record_threshold(struct s2n_connection *conn, uint32_t resize_threshold, uint16_t timeout_threshold) +{ + notnull_check(conn); + S2N_ERROR_IF(resize_threshold > S2N_TLS_MAX_RESIZE_THRESHOLD, S2N_ERR_INVALID_DYNAMIC_THRESHOLD); + + conn->dynamic_record_resize_threshold = resize_threshold; + conn->dynamic_record_timeout_threshold = timeout_threshold; + return 0; +} + +int s2n_connection_set_verify_host_callback(struct s2n_connection *conn, s2n_verify_host_fn verify_host_fn, void *data) { + notnull_check(conn); + + conn->verify_host_fn = verify_host_fn; + conn->data_for_verify_host = data; + conn->verify_host_fn_overridden = 1; + + return 0; +} + +int s2n_connection_recv_stuffer(struct s2n_stuffer *stuffer, struct s2n_connection *conn, uint32_t len) +{ + notnull_check(conn->recv); + /* Make sure we have enough space to write */ + GUARD(s2n_stuffer_reserve_space(stuffer, len)); + + int r = 0; + do { + errno = 0; + r = conn->recv(conn->recv_io_context, stuffer->blob.data + stuffer->write_cursor, len); + S2N_ERROR_IF(r < 0 && errno != EINTR, S2N_ERR_RECV_STUFFER_FROM_CONN); + } while (r < 0); + + /* Record just how many bytes we have written */ + 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); + if (conn->write_fd_broken) { + S2N_ERROR(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); + + int w = 0; + do { + errno = 0; + w = conn->send(conn->send_io_context, stuffer->blob.data + stuffer->read_cursor, len); + if (w < 0 && errno == EPIPE) { + conn->write_fd_broken = 1; + } + S2N_ERROR_IF(w < 0 && errno != EINTR, S2N_ERR_SEND_STUFFER_TO_CONN); + } while (w < 0); + + 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); + + return (s2n_connection->managed_io && s2n_connection->corked_io); +} + +const uint8_t *s2n_connection_get_sct_list(struct s2n_connection *conn, uint32_t *length) +{ + if (!length) { + return NULL; + } + + *length = conn->ct_response.size; + return conn->ct_response.data; +} + +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)); + + 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); + return conn->handshake_params.our_chain_and_key; +} + +uint8_t s2n_connection_get_protocol_version(const struct s2n_connection *conn) +{ + if (conn == NULL) { + return S2N_UNKNOWN_PROTOCOL_VERSION; + } + + if (conn->actual_protocol_version != S2N_UNKNOWN_PROTOCOL_VERSION) { + return conn->actual_protocol_version; + } + + if (conn->mode == S2N_CLIENT) { + return conn->client_protocol_version; + } + return conn->server_protocol_version; +} + +int s2n_connection_set_keyshare_by_name_for_testing(struct s2n_connection *conn, const char* curve_name) +{ + ENSURE_POSIX(S2N_IN_TEST, S2N_ERR_NOT_IN_TEST); + notnull_check(conn); + + if (!strcmp(curve_name, "none")) { + S2N_SET_KEY_SHARE_LIST_EMPTY(conn->preferred_key_shares); + return S2N_SUCCESS; + } + + const struct s2n_ecc_preferences *ecc_pref = NULL; + GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref)); + notnull_check(ecc_pref); + + 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; + } + } + + S2N_ERROR(S2N_ERR_ECDHE_UNSUPPORTED_CURVE); +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_connection.h b/contrib/restricted/aws/s2n/tls/s2n_connection.h index 9dac38db8a..5ba5667fc2 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_connection.h +++ b/contrib/restricted/aws/s2n/tls/s2n_connection.h @@ -1,349 +1,349 @@ -/* - * 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 <errno.h> -#include <s2n.h> -#include <signal.h> -#include <stdint.h> - -#include "stuffer/s2n_stuffer.h" - -#include "tls/s2n_client_hello.h" -#include "tls/s2n_config.h" -#include "tls/s2n_crypto.h" -#include "tls/s2n_handshake.h" -#include "tls/s2n_prf.h" -#include "tls/s2n_quic_support.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" - -#include "utils/s2n_mem.h" -#include "utils/s2n_timer.h" - -#define S2N_TLS_PROTOCOL_VERSION_LEN 2 - -#define is_handshake_complete(conn) (APPLICATION_DATA == s2n_conn_get_current_message_type(conn)) - -typedef enum { - S2N_NO_TICKET = 0, - S2N_DECRYPT_TICKET, - S2N_NEW_TICKET -} 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 - */ - unsigned corked_io:1; - - /* Session resumption indicator on client side */ - unsigned client_session_resumed:1; - - /* Determines if we're currently sending or receiving in s2n_shutdown */ - unsigned close_notify_queued:1; - - /* s2n does not support renegotiation. - * RFC5746 Section 4.3 suggests servers implement a minimal version of the - * renegotiation_info extension even if renegotiation is not supported. - * Some clients may fail the handshake if a corresponding renegotiation_info - * extension is not sent back by the server. - */ - unsigned secure_renegotiation:1; - /* Was the EC point formats sent by the client */ - unsigned ec_point_formats:1; - - /* whether the connection address is ipv6 or not */ - unsigned ipv6:1; - - /* Whether server_name extension was used to make a decision on cert selection. - * RFC6066 Section 3 states that server which used server_name to make a decision - * on certificate or security settings has to send an empty server_name. - */ - unsigned server_name_used:1; - - /* If write fd is broken */ - unsigned write_fd_broken:1; - - /* Track request extensions to ensure correct response extension behavior. - * - * We need to track client and server extensions separately because some - * extensions (like request_status and other Certificate extensions) can - * be requested by the client, the server, or both. - */ - s2n_extension_bitfield extension_requests_sent; - s2n_extension_bitfield extension_requests_received; - - /* Is this connection a client or a server connection */ - s2n_mode mode; - - /* Does s2n handle the blinding, or does the application */ - s2n_blinding blinding; - - /* A timer to measure the time between record writes */ - struct s2n_timer write_timer; - - /* last written time */ - uint64_t last_write_elapsed; - - /* When fatal errors occurs, s2n imposes a pause before - * the connection is closed. If non-zero, this value tracks - * how many nanoseconds to pause - which will be relative to - * the write_timer value. */ - uint64_t delay; - - /* The session id */ - uint8_t session_id[S2N_TLS_SESSION_ID_MAX_LEN]; - uint8_t session_id_len; - - /* The version advertised by the client, by the - * server, and the actual version we are currently - * speaking. */ - uint8_t client_hello_version; - uint8_t client_protocol_version; - uint8_t server_protocol_version; - uint8_t actual_protocol_version; - - /* Flag indicating whether a protocol version has been - * negotiated yet. */ - uint8_t actual_protocol_version_established; - - /* Our crypto parameters */ - struct s2n_crypto_parameters initial; - struct s2n_crypto_parameters secure; - - /* Which set is the client/server actually using? */ - struct s2n_crypto_parameters *client; - struct s2n_crypto_parameters *server; - - /* Contains parameters needed during the handshake phase */ - struct s2n_handshake_parameters handshake_params; - - /* Our PSK parameters */ - struct s2n_psk_parameters psk_params; - - /* The PRF needs some storage elements to work with */ - struct s2n_prf_working_space prf_space; - - /* Whether to use client_cert_auth_type stored in s2n_config or in this s2n_connection. - * - * By default the s2n_connection will defer to s2n_config->client_cert_auth_type on whether or not to use Client Auth. - * But users can override Client Auth at the connection level using s2n_connection_set_client_auth_type() without mutating - * s2n_config since s2n_config can be shared between multiple s2n_connections. */ - uint8_t client_cert_auth_type_overridden; - - /* Whether or not the s2n_connection should require the Client to authenticate itself to the server. Only used if - * client_cert_auth_type_overridden is non-zero. */ - s2n_cert_auth_type client_cert_auth_type; - - /* Our workhorse stuffers, used for buffering the plaintext - * and encrypted data in both directions. - */ - uint8_t header_in_data[S2N_TLS_RECORD_HEADER_LENGTH]; - struct s2n_stuffer header_in; - struct s2n_stuffer in; - struct s2n_stuffer out; - enum { ENCRYPTED, PLAINTEXT } in_status; - - /* How much of the current user buffer have we already - * encrypted and sent or have pending for the wire but have - * not acknowledged to the user. - */ - ssize_t current_user_data_consumed; - - /* An alert may be fragmented across multiple records, - * this stuffer is used to re-assemble. - */ - uint8_t alert_in_data[S2N_ALERT_LENGTH]; - struct s2n_stuffer alert_in; - - /* An alert may be partially written in the outbound - * direction, so we keep this as a small 2 byte queue. - * - * We keep separate queues for alerts generated by - * readers (a response to an alert from a peer) and writers (an - * intentional shutdown) so that the s2n reader and writer - * can be separate duplex I/O threads. - */ - uint8_t reader_alert_out_data[S2N_ALERT_LENGTH]; - uint8_t writer_alert_out_data[S2N_ALERT_LENGTH]; - struct s2n_stuffer reader_alert_out; - struct s2n_stuffer writer_alert_out; - - /* Our handshake state machine */ - struct s2n_handshake handshake; - - /* Maximum outgoing fragment size for this connection. Does not limit - * incoming record size. - * - * This value is updated when: - * 1. s2n_connection_prefer_low_latency is set - * 2. s2n_connection_prefer_throughput is set - * 3. TLS Maximum Fragment Length extension is negotiated - * - * Default value: S2N_DEFAULT_FRAGMENT_LENGTH - */ - uint16_t max_outgoing_fragment_length; - - /* The number of bytes to send before changing the record size. - * If this value > 0 then dynamic TLS record size is enabled. Otherwise, the feature is disabled (default). - */ - uint32_t dynamic_record_resize_threshold; - - /* Reset record size back to a single segment after threshold seconds of inactivity */ - uint16_t dynamic_record_timeout_threshold; - - /* number of bytes consumed during application activity */ - uint64_t active_application_bytes_consumed; - - /* Negotiated TLS extension Maximum Fragment Length code */ - uint8_t mfl_code; - - /* Keep some accounting on each connection */ - uint64_t wire_bytes_in; - uint64_t wire_bytes_out; - - /* Is the connection open or closed ? We use C's only - * atomic type as both the reader and the writer threads - * may declare a connection closed. - * - * A connection can be gracefully closed or hard-closed. - * When gracefully closed the reader or the writer mark - * the connection as closing, and then the writer will - * send an alert message before closing the connection - * and marking it as closed. - * - * A hard-close goes straight to closed with no alert - * message being sent. - */ - sig_atomic_t closing; - sig_atomic_t closed; - - /* TLS extension data */ - char server_name[S2N_MAX_SERVER_NAME + 1]; - - /* The application protocol decided upon during the client hello. - * If ALPN is being used, then: - * In server mode, this will be set by the time client_hello_cb is invoked. - * In client mode, this will be set after is_handshake_complete(connection) is true. - */ - char application_protocol[256]; - - /* OCSP stapling response data */ - s2n_status_request_type status_type; - struct s2n_blob status_response; - - /* Certificate Transparency response data */ - s2n_ct_support_level ct_level_requested; - struct s2n_blob ct_response; - - /* QUIC transport parameters data: https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-8.2 */ - struct s2n_blob our_quic_transport_parameters; - struct s2n_blob peer_quic_transport_parameters; - - struct s2n_client_hello client_hello; - - struct s2n_x509_validator x509_validator; - - /* After a connection is created this is the verification function that should always be used. At init time, - * the config should be checked for a verify callback and each connection should default to that. However, - * from the user's perspective, it's sometimes simpler to manage state by attaching each validation function/data - * to the connection, instead of globally to a single config.*/ - s2n_verify_host_fn verify_host_fn; - void *data_for_verify_host; - uint8_t verify_host_fn_overridden; - - /* Session ticket data */ - s2n_session_ticket_status session_ticket_status; - struct s2n_blob client_ticket; - uint32_t ticket_lifetime_hint; - - /* Session ticket extension from client to attempt to decrypt as the server. */ - uint8_t ticket_ext_data[S2N_TICKET_SIZE_IN_BYTES]; - struct s2n_stuffer client_ticket_to_decrypt; - - /* 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; -}; - -int s2n_connection_is_managed_corked(const struct s2n_connection *s2n_connection); -int s2n_connection_is_client_auth_enabled(struct s2n_connection *s2n_connection); - -/* Kill a bad connection */ -int s2n_connection_kill(struct s2n_connection *conn); - -/* Send/recv a stuffer to/from a connection */ -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); - -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); -int s2n_connection_get_signature_preferences(struct s2n_connection *conn, const struct s2n_signature_preferences **signature_preferences); -int s2n_connection_get_ecc_preferences(struct s2n_connection *conn, const struct s2n_ecc_preferences **ecc_preferences); -int s2n_connection_get_protocol_preferences(struct s2n_connection *conn, struct s2n_blob **protocol_preferences); -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); -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); +/* + * 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 <errno.h> +#include <s2n.h> +#include <signal.h> +#include <stdint.h> + +#include "stuffer/s2n_stuffer.h" + +#include "tls/s2n_client_hello.h" +#include "tls/s2n_config.h" +#include "tls/s2n_crypto.h" +#include "tls/s2n_handshake.h" +#include "tls/s2n_prf.h" +#include "tls/s2n_quic_support.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" + +#include "utils/s2n_mem.h" +#include "utils/s2n_timer.h" + +#define S2N_TLS_PROTOCOL_VERSION_LEN 2 + +#define is_handshake_complete(conn) (APPLICATION_DATA == s2n_conn_get_current_message_type(conn)) + +typedef enum { + S2N_NO_TICKET = 0, + S2N_DECRYPT_TICKET, + S2N_NEW_TICKET +} 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 + */ + unsigned corked_io:1; + + /* Session resumption indicator on client side */ + unsigned client_session_resumed:1; + + /* Determines if we're currently sending or receiving in s2n_shutdown */ + unsigned close_notify_queued:1; + + /* s2n does not support renegotiation. + * RFC5746 Section 4.3 suggests servers implement a minimal version of the + * renegotiation_info extension even if renegotiation is not supported. + * Some clients may fail the handshake if a corresponding renegotiation_info + * extension is not sent back by the server. + */ + unsigned secure_renegotiation:1; + /* Was the EC point formats sent by the client */ + unsigned ec_point_formats:1; + + /* whether the connection address is ipv6 or not */ + unsigned ipv6:1; + + /* Whether server_name extension was used to make a decision on cert selection. + * RFC6066 Section 3 states that server which used server_name to make a decision + * on certificate or security settings has to send an empty server_name. + */ + unsigned server_name_used:1; + + /* If write fd is broken */ + unsigned write_fd_broken:1; + + /* Track request extensions to ensure correct response extension behavior. + * + * We need to track client and server extensions separately because some + * extensions (like request_status and other Certificate extensions) can + * be requested by the client, the server, or both. + */ + s2n_extension_bitfield extension_requests_sent; + s2n_extension_bitfield extension_requests_received; + + /* Is this connection a client or a server connection */ + s2n_mode mode; + + /* Does s2n handle the blinding, or does the application */ + s2n_blinding blinding; + + /* A timer to measure the time between record writes */ + struct s2n_timer write_timer; + + /* last written time */ + uint64_t last_write_elapsed; + + /* When fatal errors occurs, s2n imposes a pause before + * the connection is closed. If non-zero, this value tracks + * how many nanoseconds to pause - which will be relative to + * the write_timer value. */ + uint64_t delay; + + /* The session id */ + uint8_t session_id[S2N_TLS_SESSION_ID_MAX_LEN]; + uint8_t session_id_len; + + /* The version advertised by the client, by the + * server, and the actual version we are currently + * speaking. */ + uint8_t client_hello_version; + uint8_t client_protocol_version; + uint8_t server_protocol_version; + uint8_t actual_protocol_version; + + /* Flag indicating whether a protocol version has been + * negotiated yet. */ + uint8_t actual_protocol_version_established; + + /* Our crypto parameters */ + struct s2n_crypto_parameters initial; + struct s2n_crypto_parameters secure; + + /* Which set is the client/server actually using? */ + struct s2n_crypto_parameters *client; + struct s2n_crypto_parameters *server; + + /* Contains parameters needed during the handshake phase */ + struct s2n_handshake_parameters handshake_params; + + /* Our PSK parameters */ + struct s2n_psk_parameters psk_params; + + /* The PRF needs some storage elements to work with */ + struct s2n_prf_working_space prf_space; + + /* Whether to use client_cert_auth_type stored in s2n_config or in this s2n_connection. + * + * By default the s2n_connection will defer to s2n_config->client_cert_auth_type on whether or not to use Client Auth. + * But users can override Client Auth at the connection level using s2n_connection_set_client_auth_type() without mutating + * s2n_config since s2n_config can be shared between multiple s2n_connections. */ + uint8_t client_cert_auth_type_overridden; + + /* Whether or not the s2n_connection should require the Client to authenticate itself to the server. Only used if + * client_cert_auth_type_overridden is non-zero. */ + s2n_cert_auth_type client_cert_auth_type; + + /* Our workhorse stuffers, used for buffering the plaintext + * and encrypted data in both directions. + */ + uint8_t header_in_data[S2N_TLS_RECORD_HEADER_LENGTH]; + struct s2n_stuffer header_in; + struct s2n_stuffer in; + struct s2n_stuffer out; + enum { ENCRYPTED, PLAINTEXT } in_status; + + /* How much of the current user buffer have we already + * encrypted and sent or have pending for the wire but have + * not acknowledged to the user. + */ + ssize_t current_user_data_consumed; + + /* An alert may be fragmented across multiple records, + * this stuffer is used to re-assemble. + */ + uint8_t alert_in_data[S2N_ALERT_LENGTH]; + struct s2n_stuffer alert_in; + + /* An alert may be partially written in the outbound + * direction, so we keep this as a small 2 byte queue. + * + * We keep separate queues for alerts generated by + * readers (a response to an alert from a peer) and writers (an + * intentional shutdown) so that the s2n reader and writer + * can be separate duplex I/O threads. + */ + uint8_t reader_alert_out_data[S2N_ALERT_LENGTH]; + uint8_t writer_alert_out_data[S2N_ALERT_LENGTH]; + struct s2n_stuffer reader_alert_out; + struct s2n_stuffer writer_alert_out; + + /* Our handshake state machine */ + struct s2n_handshake handshake; + + /* Maximum outgoing fragment size for this connection. Does not limit + * incoming record size. + * + * This value is updated when: + * 1. s2n_connection_prefer_low_latency is set + * 2. s2n_connection_prefer_throughput is set + * 3. TLS Maximum Fragment Length extension is negotiated + * + * Default value: S2N_DEFAULT_FRAGMENT_LENGTH + */ + uint16_t max_outgoing_fragment_length; + + /* The number of bytes to send before changing the record size. + * If this value > 0 then dynamic TLS record size is enabled. Otherwise, the feature is disabled (default). + */ + uint32_t dynamic_record_resize_threshold; + + /* Reset record size back to a single segment after threshold seconds of inactivity */ + uint16_t dynamic_record_timeout_threshold; + + /* number of bytes consumed during application activity */ + uint64_t active_application_bytes_consumed; + + /* Negotiated TLS extension Maximum Fragment Length code */ + uint8_t mfl_code; + + /* Keep some accounting on each connection */ + uint64_t wire_bytes_in; + uint64_t wire_bytes_out; + + /* Is the connection open or closed ? We use C's only + * atomic type as both the reader and the writer threads + * may declare a connection closed. + * + * A connection can be gracefully closed or hard-closed. + * When gracefully closed the reader or the writer mark + * the connection as closing, and then the writer will + * send an alert message before closing the connection + * and marking it as closed. + * + * A hard-close goes straight to closed with no alert + * message being sent. + */ + sig_atomic_t closing; + sig_atomic_t closed; + + /* TLS extension data */ + char server_name[S2N_MAX_SERVER_NAME + 1]; + + /* The application protocol decided upon during the client hello. + * If ALPN is being used, then: + * In server mode, this will be set by the time client_hello_cb is invoked. + * In client mode, this will be set after is_handshake_complete(connection) is true. + */ + char application_protocol[256]; + + /* OCSP stapling response data */ + s2n_status_request_type status_type; + struct s2n_blob status_response; + + /* Certificate Transparency response data */ + s2n_ct_support_level ct_level_requested; + struct s2n_blob ct_response; + + /* QUIC transport parameters data: https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-8.2 */ + struct s2n_blob our_quic_transport_parameters; + struct s2n_blob peer_quic_transport_parameters; + + struct s2n_client_hello client_hello; + + struct s2n_x509_validator x509_validator; + + /* After a connection is created this is the verification function that should always be used. At init time, + * the config should be checked for a verify callback and each connection should default to that. However, + * from the user's perspective, it's sometimes simpler to manage state by attaching each validation function/data + * to the connection, instead of globally to a single config.*/ + s2n_verify_host_fn verify_host_fn; + void *data_for_verify_host; + uint8_t verify_host_fn_overridden; + + /* Session ticket data */ + s2n_session_ticket_status session_ticket_status; + struct s2n_blob client_ticket; + uint32_t ticket_lifetime_hint; + + /* Session ticket extension from client to attempt to decrypt as the server. */ + uint8_t ticket_ext_data[S2N_TICKET_SIZE_IN_BYTES]; + struct s2n_stuffer client_ticket_to_decrypt; + + /* 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; +}; + +int s2n_connection_is_managed_corked(const struct s2n_connection *s2n_connection); +int s2n_connection_is_client_auth_enabled(struct s2n_connection *s2n_connection); + +/* Kill a bad connection */ +int s2n_connection_kill(struct s2n_connection *conn); + +/* Send/recv a stuffer to/from a connection */ +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); + +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); +int s2n_connection_get_signature_preferences(struct s2n_connection *conn, const struct s2n_signature_preferences **signature_preferences); +int s2n_connection_get_ecc_preferences(struct s2n_connection *conn, const struct s2n_ecc_preferences **ecc_preferences); +int s2n_connection_get_protocol_preferences(struct s2n_connection *conn, struct s2n_blob **protocol_preferences); +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); +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); 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 895dc39dc4..f7c08dc594 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c +++ b/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.c @@ -1,140 +1,140 @@ -/* - * 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_evp_digests.h" - -#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; - - 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 HMAC state as it is unnecessary and excessive copying - * would impact performance. - */ -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)); - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS = WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND = either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "tls/s2n_connection_evp_digests.h" + +#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; + + 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 HMAC state as it is unnecessary and excessive copying + * would impact performance. + */ +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)); + 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 135b8d9b3c..80e16823ba 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.h +++ b/contrib/restricted/aws/s2n/tls/s2n_connection_evp_digests.h @@ -1,70 +1,70 @@ -/* - * 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_connection.h" -#include "tls/s2n_prf.h" - -#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; - struct s2n_hmac_evp_backup initial_client_copy; - struct s2n_hmac_evp_backup initial_server; - struct s2n_hmac_evp_backup secure_client; - struct s2n_hmac_evp_backup secure_client_copy; - 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); +/* + * 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_connection.h" +#include "tls/s2n_prf.h" + +#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; + struct s2n_hmac_evp_backup initial_client_copy; + struct s2n_hmac_evp_backup initial_server; + struct s2n_hmac_evp_backup secure_client; + struct s2n_hmac_evp_backup secure_client_copy; + 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 8b1289d8db..515165c09d 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_crypto.h +++ b/contrib/restricted/aws/s2n/tls/s2n_crypto.h @@ -1,73 +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. - */ - -#pragma once - -#include "tls/s2n_config.h" -#include "tls/s2n_signature_scheme.h" -#include "tls/s2n_crypto_constants.h" -#include "tls/s2n_kem.h" - -#include "crypto/s2n_certificate.h" -#include "crypto/s2n_cipher.h" -#include "crypto/s2n_hmac.h" -#include "crypto/s2n_hash.h" -#include "crypto/s2n_pkey.h" -#include "crypto/s2n_signature.h" -#include "crypto/s2n_tls13_keys.h" -#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_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_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]; - 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_signature_scheme client_cert_sig_scheme; - - 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_sequence_number[S2N_TLS_SEQUENCE_NUM_LEN]; - uint8_t server_sequence_number[S2N_TLS_SEQUENCE_NUM_LEN]; -}; +/* + * 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_config.h" +#include "tls/s2n_signature_scheme.h" +#include "tls/s2n_crypto_constants.h" +#include "tls/s2n_kem.h" + +#include "crypto/s2n_certificate.h" +#include "crypto/s2n_cipher.h" +#include "crypto/s2n_hmac.h" +#include "crypto/s2n_hash.h" +#include "crypto/s2n_pkey.h" +#include "crypto/s2n_signature.h" +#include "crypto/s2n_tls13_keys.h" +#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_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_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]; + 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_signature_scheme client_cert_sig_scheme; + + 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_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_crypto_constants.h b/contrib/restricted/aws/s2n/tls/s2n_crypto_constants.h index 9b3753ec92..52316e256e 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_crypto_constants.h +++ b/contrib/restricted/aws/s2n/tls/s2n_crypto_constants.h @@ -1,50 +1,50 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#define S2N_TLS_SECRET_LEN 48 -#define S2N_TLS_RANDOM_DATA_LEN 32 -#define S2N_TLS_SEQUENCE_NUM_LEN 8 -#define S2N_TLS_CIPHER_SUITE_LEN 2 -#define S2N_SSLv2_CIPHER_SUITE_LEN 3 -#define S2N_TLS_FINISHED_LEN 12 -#define S2N_SSL_FINISHED_LEN 36 -#define S2N_TLS_MAX_IV_LEN 16 - -/* From RFC 5246 6.2.3.3 */ -#define S2N_TLS12_AAD_LEN 13 -#define S2N_TLS_MAX_AAD_LEN S2N_TLS12_AAD_LEN -#define S2N_TLS_GCM_FIXED_IV_LEN 4 -#define S2N_TLS_GCM_EXPLICIT_IV_LEN 8 -#define S2N_TLS_GCM_IV_LEN (S2N_TLS_GCM_FIXED_IV_LEN + S2N_TLS_GCM_EXPLICIT_IV_LEN) -#define S2N_TLS_GCM_TAG_LEN 16 -#define S2N_TLS_AES_128_GCM_KEY_LEN 16 -#define S2N_TLS_AES_256_GCM_KEY_LEN 32 - -/* TLS 1.3 uses only implicit IVs - RFC 8446 5.3 */ -#define S2N_TLS13_AAD_LEN 5 -#define S2N_TLS13_RECORD_IV_LEN 0 -#define S2N_TLS13_FIXED_IV_LEN 12 - -/* From RFC 7905 */ -#define S2N_TLS_CHACHA20_POLY1305_FIXED_IV_LEN 12 -#define S2N_TLS_CHACHA20_POLY1305_EXPLICIT_IV_LEN 0 -#define S2N_TLS_CHACHA20_POLY1305_IV_LEN 12 -#define S2N_TLS_CHACHA20_POLY1305_KEY_LEN 32 -#define S2N_TLS_CHACHA20_POLY1305_TAG_LEN 16 - -/* RFC 5246 7.4.1.2 */ -#define S2N_TLS_SESSION_ID_MAX_LEN 32 +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#define S2N_TLS_SECRET_LEN 48 +#define S2N_TLS_RANDOM_DATA_LEN 32 +#define S2N_TLS_SEQUENCE_NUM_LEN 8 +#define S2N_TLS_CIPHER_SUITE_LEN 2 +#define S2N_SSLv2_CIPHER_SUITE_LEN 3 +#define S2N_TLS_FINISHED_LEN 12 +#define S2N_SSL_FINISHED_LEN 36 +#define S2N_TLS_MAX_IV_LEN 16 + +/* From RFC 5246 6.2.3.3 */ +#define S2N_TLS12_AAD_LEN 13 +#define S2N_TLS_MAX_AAD_LEN S2N_TLS12_AAD_LEN +#define S2N_TLS_GCM_FIXED_IV_LEN 4 +#define S2N_TLS_GCM_EXPLICIT_IV_LEN 8 +#define S2N_TLS_GCM_IV_LEN (S2N_TLS_GCM_FIXED_IV_LEN + S2N_TLS_GCM_EXPLICIT_IV_LEN) +#define S2N_TLS_GCM_TAG_LEN 16 +#define S2N_TLS_AES_128_GCM_KEY_LEN 16 +#define S2N_TLS_AES_256_GCM_KEY_LEN 32 + +/* TLS 1.3 uses only implicit IVs - RFC 8446 5.3 */ +#define S2N_TLS13_AAD_LEN 5 +#define S2N_TLS13_RECORD_IV_LEN 0 +#define S2N_TLS13_FIXED_IV_LEN 12 + +/* From RFC 7905 */ +#define S2N_TLS_CHACHA20_POLY1305_FIXED_IV_LEN 12 +#define S2N_TLS_CHACHA20_POLY1305_EXPLICIT_IV_LEN 0 +#define S2N_TLS_CHACHA20_POLY1305_IV_LEN 12 +#define S2N_TLS_CHACHA20_POLY1305_KEY_LEN 32 +#define S2N_TLS_CHACHA20_POLY1305_TAG_LEN 16 + +/* RFC 5246 7.4.1.2 */ +#define S2N_TLS_SESSION_ID_MAX_LEN 32 diff --git a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c index 0568c39589..12db371abb 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c +++ b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.c @@ -1,111 +1,111 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <s2n.h> - -#include "tls/s2n_ecc_preferences.h" -#include "tls/s2n_connection.h" -#include "crypto/s2n_ecc_evp.h" -#include "utils/s2n_safety.h" - -const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20140601[] = { - &s2n_ecc_curve_secp256r1, - &s2n_ecc_curve_secp384r1, -}; - -const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20200310[] = { -#if EVP_APIS_SUPPORTED - &s2n_ecc_curve_x25519, -#endif - &s2n_ecc_curve_secp256r1, - &s2n_ecc_curve_secp384r1, -}; - -const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20201021[] = { - &s2n_ecc_curve_secp256r1, - &s2n_ecc_curve_secp384r1, - &s2n_ecc_curve_secp521r1, -}; - -const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_test_all[] = { -#if EVP_APIS_SUPPORTED - &s2n_ecc_curve_x25519, -#endif - &s2n_ecc_curve_secp256r1, - &s2n_ecc_curve_secp384r1, - &s2n_ecc_curve_secp521r1, -}; - -const struct s2n_ecc_preferences s2n_ecc_preferences_20140601 = { - .count = s2n_array_len(s2n_ecc_pref_list_20140601), - .ecc_curves = s2n_ecc_pref_list_20140601, -}; - -const struct s2n_ecc_preferences s2n_ecc_preferences_20200310 = { - .count = s2n_array_len(s2n_ecc_pref_list_20200310), - .ecc_curves = s2n_ecc_pref_list_20200310, -}; - -const struct s2n_ecc_preferences s2n_ecc_preferences_20201021 = { - .count = s2n_array_len(s2n_ecc_pref_list_20201021), - .ecc_curves = s2n_ecc_pref_list_20201021, -}; - -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, -}; - -const struct s2n_ecc_preferences s2n_ecc_preferences_null = { - .count = 0, - .ecc_curves = NULL, -}; - -/* Checks if the ecc_curves present in s2n_ecc_preferences list is a subset of s2n_all_supported_curves_list - * maintained in s2n_ecc_evp.c */ -int s2n_check_ecc_preferences_curves_list(const struct s2n_ecc_preferences *ecc_preferences) { - int check = 1; - 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++) { - if (named_curve->iana_id == s2n_all_supported_curves_list[j]->iana_id) { - curve_found = 1; - break; - } - } - check *= curve_found; - if (check == 0) { - S2N_ERROR(S2N_ERR_ECDHE_UNSUPPORTED_CURVE); - } - } - return S2N_SUCCESS; -} - -/* Determines if query_iana_id corresponds to a curve for these ECC preferences. */ -bool s2n_ecc_preferences_includes_curve(const struct s2n_ecc_preferences *ecc_preferences, uint16_t query_iana_id) { - if (ecc_preferences == NULL) { - return false; - } - - for (size_t i = 0; i < ecc_preferences->count; i++) { - if (query_iana_id == ecc_preferences->ecc_curves[i]->iana_id) { - return true; - } - } - - return false; -} - +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <s2n.h> + +#include "tls/s2n_ecc_preferences.h" +#include "tls/s2n_connection.h" +#include "crypto/s2n_ecc_evp.h" +#include "utils/s2n_safety.h" + +const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20140601[] = { + &s2n_ecc_curve_secp256r1, + &s2n_ecc_curve_secp384r1, +}; + +const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20200310[] = { +#if EVP_APIS_SUPPORTED + &s2n_ecc_curve_x25519, +#endif + &s2n_ecc_curve_secp256r1, + &s2n_ecc_curve_secp384r1, +}; + +const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_20201021[] = { + &s2n_ecc_curve_secp256r1, + &s2n_ecc_curve_secp384r1, + &s2n_ecc_curve_secp521r1, +}; + +const struct s2n_ecc_named_curve *const s2n_ecc_pref_list_test_all[] = { +#if EVP_APIS_SUPPORTED + &s2n_ecc_curve_x25519, +#endif + &s2n_ecc_curve_secp256r1, + &s2n_ecc_curve_secp384r1, + &s2n_ecc_curve_secp521r1, +}; + +const struct s2n_ecc_preferences s2n_ecc_preferences_20140601 = { + .count = s2n_array_len(s2n_ecc_pref_list_20140601), + .ecc_curves = s2n_ecc_pref_list_20140601, +}; + +const struct s2n_ecc_preferences s2n_ecc_preferences_20200310 = { + .count = s2n_array_len(s2n_ecc_pref_list_20200310), + .ecc_curves = s2n_ecc_pref_list_20200310, +}; + +const struct s2n_ecc_preferences s2n_ecc_preferences_20201021 = { + .count = s2n_array_len(s2n_ecc_pref_list_20201021), + .ecc_curves = s2n_ecc_pref_list_20201021, +}; + +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, +}; + +const struct s2n_ecc_preferences s2n_ecc_preferences_null = { + .count = 0, + .ecc_curves = NULL, +}; + +/* Checks if the ecc_curves present in s2n_ecc_preferences list is a subset of s2n_all_supported_curves_list + * maintained in s2n_ecc_evp.c */ +int s2n_check_ecc_preferences_curves_list(const struct s2n_ecc_preferences *ecc_preferences) { + int check = 1; + 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++) { + if (named_curve->iana_id == s2n_all_supported_curves_list[j]->iana_id) { + curve_found = 1; + break; + } + } + check *= curve_found; + if (check == 0) { + S2N_ERROR(S2N_ERR_ECDHE_UNSUPPORTED_CURVE); + } + } + return S2N_SUCCESS; +} + +/* Determines if query_iana_id corresponds to a curve for these ECC preferences. */ +bool s2n_ecc_preferences_includes_curve(const struct s2n_ecc_preferences *ecc_preferences, uint16_t query_iana_id) { + if (ecc_preferences == NULL) { + return false; + } + + for (size_t i = 0; i < ecc_preferences->count; i++) { + if (query_iana_id == ecc_preferences->ecc_curves[i]->iana_id) { + return true; + } + } + + return false; +} + diff --git a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h index 8a78398b85..96afa8051a 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h +++ b/contrib/restricted/aws/s2n/tls/s2n_ecc_preferences.h @@ -1,35 +1,35 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include <s2n.h> -#include <strings.h> -#include <stdbool.h> - -#include "crypto/s2n_ecc_evp.h" - -struct s2n_ecc_preferences { - uint8_t count; - const struct s2n_ecc_named_curve *const *ecc_curves; -}; -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_test_all; -extern const struct s2n_ecc_preferences s2n_ecc_preferences_null; - -int s2n_check_ecc_preferences_curves_list(const struct s2n_ecc_preferences *ecc_preferences); -bool s2n_ecc_preferences_includes_curve(const struct s2n_ecc_preferences *ecc_preferences, uint16_t query_iana_id); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include <s2n.h> +#include <strings.h> +#include <stdbool.h> + +#include "crypto/s2n_ecc_evp.h" + +struct s2n_ecc_preferences { + uint8_t count; + const struct s2n_ecc_named_curve *const *ecc_curves; +}; +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_test_all; +extern const struct s2n_ecc_preferences s2n_ecc_preferences_null; + +int s2n_check_ecc_preferences_curves_list(const struct s2n_ecc_preferences *ecc_preferences); +bool s2n_ecc_preferences_includes_curve(const struct s2n_ecc_preferences *ecc_preferences, uint16_t query_iana_id); diff --git a/contrib/restricted/aws/s2n/tls/s2n_encrypted_extensions.c b/contrib/restricted/aws/s2n/tls/s2n_encrypted_extensions.c index f0d2b94dd8..d61d7c1b2d 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_encrypted_extensions.c +++ b/contrib/restricted/aws/s2n/tls/s2n_encrypted_extensions.c @@ -1,55 +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. - */ - -#include "error/s2n_errno.h" -#include "utils/s2n_safety.h" -#include "stuffer/s2n_stuffer.h" - -#include "tls/s2n_tls.h" -#include "tls/s2n_tls13.h" - -#include "tls/extensions/s2n_extension_list.h" - -/** - * Specified in https://tools.ietf.org/html/rfc8446#section-4.3.1 - * - * In all handshakes, the server MUST send the EncryptedExtensions - * message immediately after the ServerHello message. - * - * The EncryptedExtensions message contains extensions that can be - * protected, i.e., any which are not needed to establish the - * cryptographic context but which are not associated with individual - * certificates. - **/ - -int s2n_encrypted_extensions_send(struct s2n_connection *conn) -{ - notnull_check(conn); - ENSURE_POSIX(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)); - 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); - - struct s2n_stuffer *in = &conn->handshake.io; - GUARD(s2n_extension_list_recv(S2N_EXTENSION_LIST_ENCRYPTED_EXTENSIONS, conn, in)); - return S2N_SUCCESS; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "error/s2n_errno.h" +#include "utils/s2n_safety.h" +#include "stuffer/s2n_stuffer.h" + +#include "tls/s2n_tls.h" +#include "tls/s2n_tls13.h" + +#include "tls/extensions/s2n_extension_list.h" + +/** + * Specified in https://tools.ietf.org/html/rfc8446#section-4.3.1 + * + * In all handshakes, the server MUST send the EncryptedExtensions + * message immediately after the ServerHello message. + * + * The EncryptedExtensions message contains extensions that can be + * protected, i.e., any which are not needed to establish the + * cryptographic context but which are not associated with individual + * certificates. + **/ + +int s2n_encrypted_extensions_send(struct s2n_connection *conn) +{ + notnull_check(conn); + ENSURE_POSIX(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)); + 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); + + struct s2n_stuffer *in = &conn->handshake.io; + 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 95c0df5283..e61b9f2850 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_establish_session.c +++ b/contrib/restricted/aws/s2n/tls/s2n_establish_session.c @@ -1,55 +1,55 @@ -/* - * Copyright 2020 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 <stdint.h> -#include <s2n.h> - -#include "error/s2n_errno.h" - -#include "stuffer/s2n_stuffer.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" - -#include "utils/s2n_array.h" - - -/* Establishing a session requires reading the CLIENT_HELLO message and then generating security parameters. - * - * S2N supports resuming sessions under TLS1.2 if the client sends a session ID. The server can lookup a - * 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)); - conn->handshake.client_hello_received = 1; - } - - 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)); - } - - GUARD(s2n_conn_clear_handshake_read_block(conn)); - - return 0; -} - +/* + * Copyright 2020 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 <stdint.h> +#include <s2n.h> + +#include "error/s2n_errno.h" + +#include "stuffer/s2n_stuffer.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" + +#include "utils/s2n_array.h" + + +/* Establishing a session requires reading the CLIENT_HELLO message and then generating security parameters. + * + * S2N supports resuming sessions under TLS1.2 if the client sends a session ID. The server can lookup a + * 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)); + conn->handshake.client_hello_received = 1; + } + + 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)); + } + + 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 9e667acaa3..922cd67c2b 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_handshake.c +++ b/contrib/restricted/aws/s2n/tls/s2n_handshake.c @@ -1,331 +1,331 @@ -/* - * 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 <stdint.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_record.h" -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_tls.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_map.h" - -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)); - - /* Leave the length blank for now */ - uint16_t length = 0; - GUARD(s2n_stuffer_write_uint24(out, length)); - - return 0; -} - -int s2n_handshake_finish_header(struct s2n_stuffer *out) -{ - uint16_t length = s2n_stuffer_data_available(out); - S2N_ERROR_IF(length < TLS_HANDSHAKE_HEADER_LENGTH, S2N_ERR_SIZE_MISMATCH); - - 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)); - - return 0; -} - -int s2n_handshake_parse_header(struct s2n_connection *conn, uint8_t * message_type, uint32_t * length) -{ - 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)); - - return 0; -} - -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); - - switch (hash_alg) { - case S2N_HASH_MD5: - *hash_state = &conn->handshake.md5; - break; - case S2N_HASH_SHA1: - *hash_state = &conn->handshake.sha1; - break; - case S2N_HASH_SHA224: - *hash_state = &conn->handshake.sha224; - break; - case S2N_HASH_SHA256: - *hash_state = &conn->handshake.sha256; - break; - case S2N_HASH_SHA384: - *hash_state = &conn->handshake.sha384; - break; - case S2N_HASH_SHA512: - *hash_state = &conn->handshake.sha512; - break; - case S2N_HASH_MD5_SHA1: - *hash_state = &conn->handshake.md5_sha1; - break; - default: - S2N_ERROR(S2N_ERR_HASH_INVALID_ALGORITHM); - break; - } - - return 0; -} - -int 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; -} - -/* 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) -{ - 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; -} - -int s2n_handshake_require_all_hashes(struct s2n_handshake *handshake) -{ - memset(handshake->required_hash_algs, 1, sizeof(handshake->required_hash_algs)); - return 0; -} - -static int s2n_handshake_require_hash(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg) -{ - handshake->required_hash_algs[hash_alg] = 1; - return 0; -} - -uint8_t s2n_handshake_is_hash_required(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg) -{ - return handshake->required_hash_algs[hash_alg]; -} - -/* Update the required handshake hash algs depending on current handshake session state. - * This function must called at the end of a handshake message handler. Additionally it must be called after the - * ClientHello or ServerHello is processed in client and server mode respectively. The relevant handshake parameters - * are not available until those messages are processed. - */ -int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn) -{ - /* Clear all of the required hashes */ - memset(conn->handshake.required_hash_algs, 0, sizeof(conn->handshake.required_hash_algs)); - - 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)); - - /* 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; - } - - /* We don't need all of the hashes. Set the hash alg(s) required for the PRF */ - switch (conn->actual_protocol_version) { - 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)); - break; - case S2N_TLS12: - /* fall through */ - case S2N_TLS13: - { - /* 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)); - break; - } - } - - return 0; -} - -/* - * Take a hostname and return a single "simple" wildcard domain name that matches it. - * The output wildcard representation is meant to be compared directly against a wildcard domain in a certificate. - * We take a restrictive definition of wildcard here to achieve a single unique wildcard representation - * given any input hostname. - * No embedded or trailing wildcards are supported. Additionally, we only support one level of wildcard matching. - * Thus the output should be a single wildcard character in the first(left-most) DNS label. - * - * Example: - * - my.domain.name -> *.domain.name - * - * Not supported: - * - my.domain.name -> m*.domain.name - * - my.domain.name -> my.*.name - * etc. - * - * The motivation for using a constrained definition of wildcard: - * - Support for issuing non-simple wildcard certificates is insignificant. - * - Certificate selection can be implemented with a constant number of lookups(two). - */ -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, '.')); - - /* No first label found */ - if (s2n_stuffer_data_available(hostname_stuffer) == 0) { - return 0; - } - - /* Slap a single wildcard character to be the first label in output */ - 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))); - - return 0; -} - -static int s2n_find_cert_matches(struct s2n_map *domain_name_to_cert_map, - struct s2n_blob *dns_name, - struct s2n_cert_chain_and_key *matches[S2N_CERT_TYPE_COUNT], - uint8_t *match_exists) -{ - 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)); - if (key_found) { - struct certs_by_type *value = (void *) map_value.data; - for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { - matches[i] = value->certs[i]; - } - *match_exists = 1; - } - - return 0; -} - -/* Find certificates that match the ServerName TLS extension sent by the client. - * For a given ServerName there can be multiple matching certificates based on the - * type of key in the certificate. - * - * A match is determined using s2n_map lookup by DNS name. - * Wildcards that have a single * in the left most label are supported. - */ -int s2n_conn_find_name_matching_certs(struct s2n_connection *conn) -{ - if (!s2n_server_received_server_name(conn)) { - return 0; - } - 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); - char normalized_hostname[S2N_MAX_SERVER_NAME + 1] = { 0 }; - memcpy_check(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)); - 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)); - - /* Find the exact matches for the ServerName */ - 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))); - - if (!conn->handshake_params.exact_sni_match_exists) { - /* We have not yet found an exact domain match. Try to find wildcard matches. */ - 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)); - 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; - } - - /* 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, - &wildcard_blob, - conn->handshake_params.wc_sni_matches, - &(conn->handshake_params.wc_sni_match_exists))); - } - - /* If we found a suitable cert, we should send back the ServerName extension. - * Note that this may have already been set by the client hello callback, so we won't override its value - */ - conn->server_name_used = conn->server_name_used - || conn->handshake_params.exact_sni_match_exists - || conn->handshake_params.wc_sni_match_exists; - - return 0; -} - -/* Find the optimal certificate of a specific type. - * The priority of set of certificates to choose from: - * 1. Certificates that match the client's ServerName extension. - * 2. Default certificates - */ -struct s2n_cert_chain_and_key *s2n_get_compatible_cert_chain_and_key(struct s2n_connection *conn, const s2n_pkey_type cert_type) -{ - if (conn->handshake_params.exact_sni_match_exists) { - /* This may return NULL if there was an SNI match, but not a match the cipher_suite's authentication type. */ - return conn->handshake_params.exact_sni_matches[cert_type]; - } if (conn->handshake_params.wc_sni_match_exists) { - return conn->handshake_params.wc_sni_matches[cert_type]; - } else { - /* We don't have any name matches. Use the default certificate that works with the key type. */ - return conn->config->default_certs_by_type.certs[cert_type]; - } -} +/* + * 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 <stdint.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_record.h" +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_tls.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_map.h" + +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)); + + /* Leave the length blank for now */ + uint16_t length = 0; + GUARD(s2n_stuffer_write_uint24(out, length)); + + return 0; +} + +int s2n_handshake_finish_header(struct s2n_stuffer *out) +{ + uint16_t length = s2n_stuffer_data_available(out); + S2N_ERROR_IF(length < TLS_HANDSHAKE_HEADER_LENGTH, S2N_ERR_SIZE_MISMATCH); + + 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)); + + return 0; +} + +int s2n_handshake_parse_header(struct s2n_connection *conn, uint8_t * message_type, uint32_t * length) +{ + 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)); + + return 0; +} + +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); + + switch (hash_alg) { + case S2N_HASH_MD5: + *hash_state = &conn->handshake.md5; + break; + case S2N_HASH_SHA1: + *hash_state = &conn->handshake.sha1; + break; + case S2N_HASH_SHA224: + *hash_state = &conn->handshake.sha224; + break; + case S2N_HASH_SHA256: + *hash_state = &conn->handshake.sha256; + break; + case S2N_HASH_SHA384: + *hash_state = &conn->handshake.sha384; + break; + case S2N_HASH_SHA512: + *hash_state = &conn->handshake.sha512; + break; + case S2N_HASH_MD5_SHA1: + *hash_state = &conn->handshake.md5_sha1; + break; + default: + S2N_ERROR(S2N_ERR_HASH_INVALID_ALGORITHM); + break; + } + + return 0; +} + +int 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; +} + +/* 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) +{ + 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; +} + +int s2n_handshake_require_all_hashes(struct s2n_handshake *handshake) +{ + memset(handshake->required_hash_algs, 1, sizeof(handshake->required_hash_algs)); + return 0; +} + +static int s2n_handshake_require_hash(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg) +{ + handshake->required_hash_algs[hash_alg] = 1; + return 0; +} + +uint8_t s2n_handshake_is_hash_required(struct s2n_handshake *handshake, s2n_hash_algorithm hash_alg) +{ + return handshake->required_hash_algs[hash_alg]; +} + +/* Update the required handshake hash algs depending on current handshake session state. + * This function must called at the end of a handshake message handler. Additionally it must be called after the + * ClientHello or ServerHello is processed in client and server mode respectively. The relevant handshake parameters + * are not available until those messages are processed. + */ +int s2n_conn_update_required_handshake_hashes(struct s2n_connection *conn) +{ + /* Clear all of the required hashes */ + memset(conn->handshake.required_hash_algs, 0, sizeof(conn->handshake.required_hash_algs)); + + 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)); + + /* 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; + } + + /* We don't need all of the hashes. Set the hash alg(s) required for the PRF */ + switch (conn->actual_protocol_version) { + 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)); + break; + case S2N_TLS12: + /* fall through */ + case S2N_TLS13: + { + /* 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)); + break; + } + } + + return 0; +} + +/* + * Take a hostname and return a single "simple" wildcard domain name that matches it. + * The output wildcard representation is meant to be compared directly against a wildcard domain in a certificate. + * We take a restrictive definition of wildcard here to achieve a single unique wildcard representation + * given any input hostname. + * No embedded or trailing wildcards are supported. Additionally, we only support one level of wildcard matching. + * Thus the output should be a single wildcard character in the first(left-most) DNS label. + * + * Example: + * - my.domain.name -> *.domain.name + * + * Not supported: + * - my.domain.name -> m*.domain.name + * - my.domain.name -> my.*.name + * etc. + * + * The motivation for using a constrained definition of wildcard: + * - Support for issuing non-simple wildcard certificates is insignificant. + * - Certificate selection can be implemented with a constant number of lookups(two). + */ +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, '.')); + + /* No first label found */ + if (s2n_stuffer_data_available(hostname_stuffer) == 0) { + return 0; + } + + /* Slap a single wildcard character to be the first label in output */ + 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))); + + return 0; +} + +static int s2n_find_cert_matches(struct s2n_map *domain_name_to_cert_map, + struct s2n_blob *dns_name, + struct s2n_cert_chain_and_key *matches[S2N_CERT_TYPE_COUNT], + uint8_t *match_exists) +{ + 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)); + if (key_found) { + struct certs_by_type *value = (void *) map_value.data; + for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) { + matches[i] = value->certs[i]; + } + *match_exists = 1; + } + + return 0; +} + +/* Find certificates that match the ServerName TLS extension sent by the client. + * For a given ServerName there can be multiple matching certificates based on the + * type of key in the certificate. + * + * A match is determined using s2n_map lookup by DNS name. + * Wildcards that have a single * in the left most label are supported. + */ +int s2n_conn_find_name_matching_certs(struct s2n_connection *conn) +{ + if (!s2n_server_received_server_name(conn)) { + return 0; + } + 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); + char normalized_hostname[S2N_MAX_SERVER_NAME + 1] = { 0 }; + memcpy_check(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)); + 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)); + + /* Find the exact matches for the ServerName */ + 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))); + + if (!conn->handshake_params.exact_sni_match_exists) { + /* We have not yet found an exact domain match. Try to find wildcard matches. */ + 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)); + 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; + } + + /* 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, + &wildcard_blob, + conn->handshake_params.wc_sni_matches, + &(conn->handshake_params.wc_sni_match_exists))); + } + + /* If we found a suitable cert, we should send back the ServerName extension. + * Note that this may have already been set by the client hello callback, so we won't override its value + */ + conn->server_name_used = conn->server_name_used + || conn->handshake_params.exact_sni_match_exists + || conn->handshake_params.wc_sni_match_exists; + + return 0; +} + +/* Find the optimal certificate of a specific type. + * The priority of set of certificates to choose from: + * 1. Certificates that match the client's ServerName extension. + * 2. Default certificates + */ +struct s2n_cert_chain_and_key *s2n_get_compatible_cert_chain_and_key(struct s2n_connection *conn, const s2n_pkey_type cert_type) +{ + if (conn->handshake_params.exact_sni_match_exists) { + /* This may return NULL if there was an SNI match, but not a match the cipher_suite's authentication type. */ + return conn->handshake_params.exact_sni_matches[cert_type]; + } if (conn->handshake_params.wc_sni_match_exists) { + return conn->handshake_params.wc_sni_matches[cert_type]; + } else { + /* We don't have any name matches. Use the default certificate that works with the key type. */ + return conn->config->default_certs_by_type.certs[cert_type]; + } +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake.h b/contrib/restricted/aws/s2n/tls/s2n_handshake.h index a0fde5f3af..cb871889e4 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_handshake.h +++ b/contrib/restricted/aws/s2n/tls/s2n_handshake.h @@ -1,220 +1,220 @@ -/* - * 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 <stdint.h> -#include <s2n.h> - -#include "tls/s2n_crypto.h" -#include "tls/s2n_signature_algorithms.h" -#include "tls/s2n_tls_parameters.h" - -#include "stuffer/s2n_stuffer.h" - -#include "crypto/s2n_certificate.h" -#include "crypto/s2n_hash.h" - -/* From RFC 8446: https://tools.ietf.org/html/rfc8446#appendix-B.3 */ -#define TLS_HELLO_REQUEST 0 -#define TLS_CLIENT_HELLO 1 -#define TLS_SERVER_HELLO 2 -#define TLS_SERVER_NEW_SESSION_TICKET 4 -#define TLS_ENCRYPTED_EXTENSIONS 8 -#define TLS_CERTIFICATE 11 -#define TLS_SERVER_KEY 12 -#define TLS_CERT_REQ 13 -#define TLS_SERVER_HELLO_DONE 14 -#define TLS_CERT_VERIFY 15 -#define TLS_CLIENT_KEY 16 -#define TLS_FINISHED 20 -#define TLS_SERVER_CERT_STATUS 22 -#define TLS_SERVER_SESSION_LOOKUP 23 -#define TLS_KEY_UPDATE 24 -#define TLS_MESSAGE_HASH 254 - -/* This is the list of message types that we support */ -typedef enum { - CLIENT_HELLO=0, - SERVER_HELLO, - SERVER_CERT, - SERVER_NEW_SESSION_TICKET, - SERVER_CERT_STATUS, - SERVER_KEY, - SERVER_CERT_REQ, - SERVER_HELLO_DONE, - CLIENT_CERT, - CLIENT_KEY, - CLIENT_CERT_VERIFY, - CLIENT_CHANGE_CIPHER_SPEC, - CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, - SERVER_FINISHED, - - /* TLS1.3 message types. Defined: https://tools.ietf.org/html/rfc8446#appendix-B.3 */ - ENCRYPTED_EXTENSIONS, - SERVER_CERT_VERIFY, - HELLO_RETRY_MSG, - - 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_state; - -struct s2n_handshake_parameters { - /* Signature/hash algorithm pairs offered by the client in the signature_algorithms extension */ - struct s2n_sig_scheme_list client_sig_hash_algs; - - /* Signature/hash algorithm pairs offered by the server in the certificate request */ - struct s2n_sig_scheme_list server_sig_hash_algs; - - /* The cert chain we will send the peer. */ - struct s2n_cert_chain_and_key *our_chain_and_key; - - /* The subset of certificates that match the server_name presented in the ClientHello. - * In the case of multiple certificates matching a server_name, s2n will prefer certificates - * in FIFO order based on calls to s2n_config_add_cert_chain_and_key_to_store - * - * Note that in addition to domain matching, the key type for the certificate must also be - * suitable for a negotiation in order to be selected. The set of matching certs here are indexed - * by s2n_authentication_method. - * - * Example: - * - Assume certA is added to s2n_config via s2n_config_add_cert_chain_and_key_to_store - * - Next certB is added. - * - if certA matches www.foo.com and certB matches www.foo.com, s2n will prefer certA - * - * Note that in addition to domain matching, the key type for the certificate must also be - * suitable for a negotiation in order to be selected. - * - * Example: - * - Assume certA and certB match server_name www.foo.com - * - certA is ECDSA and certB is RSA. - * - Client only supports RSA ciphers - * - certB will be selected. - */ - struct s2n_cert_chain_and_key *exact_sni_matches[S2N_CERT_TYPE_COUNT]; - 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; -}; - -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; - - /* 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. - */ - uint8_t required_hash_algs[S2N_HASH_SENTINEL]; - - 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 */ - 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; - - /* State of the async pkey operation during handshake */ - s2n_async_state async_state; - - /* Indicates the CLIENT_HELLO message has been completely received */ - unsigned client_hello_received:1; - - /* Indicates the handshake blocked while trying to read or write data, and has been paused */ - unsigned paused:1; - - /* Set to 1 if the RSA verification failed */ - 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); -struct s2n_cert_chain_and_key *s2n_get_compatible_cert_chain_and_key(struct s2n_connection *conn, const s2n_pkey_type cert_type); -int s2n_conn_update_handshake_hashes(struct s2n_connection *conn, struct s2n_blob *data); -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); +/* + * 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 <stdint.h> +#include <s2n.h> + +#include "tls/s2n_crypto.h" +#include "tls/s2n_signature_algorithms.h" +#include "tls/s2n_tls_parameters.h" + +#include "stuffer/s2n_stuffer.h" + +#include "crypto/s2n_certificate.h" +#include "crypto/s2n_hash.h" + +/* From RFC 8446: https://tools.ietf.org/html/rfc8446#appendix-B.3 */ +#define TLS_HELLO_REQUEST 0 +#define TLS_CLIENT_HELLO 1 +#define TLS_SERVER_HELLO 2 +#define TLS_SERVER_NEW_SESSION_TICKET 4 +#define TLS_ENCRYPTED_EXTENSIONS 8 +#define TLS_CERTIFICATE 11 +#define TLS_SERVER_KEY 12 +#define TLS_CERT_REQ 13 +#define TLS_SERVER_HELLO_DONE 14 +#define TLS_CERT_VERIFY 15 +#define TLS_CLIENT_KEY 16 +#define TLS_FINISHED 20 +#define TLS_SERVER_CERT_STATUS 22 +#define TLS_SERVER_SESSION_LOOKUP 23 +#define TLS_KEY_UPDATE 24 +#define TLS_MESSAGE_HASH 254 + +/* This is the list of message types that we support */ +typedef enum { + CLIENT_HELLO=0, + SERVER_HELLO, + SERVER_CERT, + SERVER_NEW_SESSION_TICKET, + SERVER_CERT_STATUS, + SERVER_KEY, + SERVER_CERT_REQ, + SERVER_HELLO_DONE, + CLIENT_CERT, + CLIENT_KEY, + CLIENT_CERT_VERIFY, + CLIENT_CHANGE_CIPHER_SPEC, + CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, + SERVER_FINISHED, + + /* TLS1.3 message types. Defined: https://tools.ietf.org/html/rfc8446#appendix-B.3 */ + ENCRYPTED_EXTENSIONS, + SERVER_CERT_VERIFY, + HELLO_RETRY_MSG, + + 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_state; + +struct s2n_handshake_parameters { + /* Signature/hash algorithm pairs offered by the client in the signature_algorithms extension */ + struct s2n_sig_scheme_list client_sig_hash_algs; + + /* Signature/hash algorithm pairs offered by the server in the certificate request */ + struct s2n_sig_scheme_list server_sig_hash_algs; + + /* The cert chain we will send the peer. */ + struct s2n_cert_chain_and_key *our_chain_and_key; + + /* The subset of certificates that match the server_name presented in the ClientHello. + * In the case of multiple certificates matching a server_name, s2n will prefer certificates + * in FIFO order based on calls to s2n_config_add_cert_chain_and_key_to_store + * + * Note that in addition to domain matching, the key type for the certificate must also be + * suitable for a negotiation in order to be selected. The set of matching certs here are indexed + * by s2n_authentication_method. + * + * Example: + * - Assume certA is added to s2n_config via s2n_config_add_cert_chain_and_key_to_store + * - Next certB is added. + * - if certA matches www.foo.com and certB matches www.foo.com, s2n will prefer certA + * + * Note that in addition to domain matching, the key type for the certificate must also be + * suitable for a negotiation in order to be selected. + * + * Example: + * - Assume certA and certB match server_name www.foo.com + * - certA is ECDSA and certB is RSA. + * - Client only supports RSA ciphers + * - certB will be selected. + */ + struct s2n_cert_chain_and_key *exact_sni_matches[S2N_CERT_TYPE_COUNT]; + 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; +}; + +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; + + /* 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. + */ + uint8_t required_hash_algs[S2N_HASH_SENTINEL]; + + 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 */ + 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; + + /* State of the async pkey operation during handshake */ + s2n_async_state async_state; + + /* Indicates the CLIENT_HELLO message has been completely received */ + unsigned client_hello_received:1; + + /* Indicates the handshake blocked while trying to read or write data, and has been paused */ + unsigned paused:1; + + /* Set to 1 if the RSA verification failed */ + 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); +struct s2n_cert_chain_and_key *s2n_get_compatible_cert_chain_and_key(struct s2n_connection *conn, const s2n_pkey_type cert_type); +int s2n_conn_update_handshake_hashes(struct s2n_connection *conn, struct s2n_blob *data); +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_io.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c index 356bfa2201..ad53a33938 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c +++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_io.c @@ -1,1215 +1,1215 @@ -/* - * 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 <errno.h> -#include <s2n.h> - -#include "error/s2n_errno.h" - -#include "crypto/s2n_fips.h" - -#include "tls/s2n_async_pkey.h" -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_record.h" -#include "tls/s2n_resume.h" -#include "tls/s2n_alerts.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls13.h" -#include "tls/s2n_tls13_handshake.h" -#include "tls/s2n_kex.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" - -/* clang-format off */ -struct s2n_handshake_action { - uint8_t record_type; - uint8_t message_type; - char writer; /* 'S' or 'C' for server or client, 'B' for both */ - int (*handler[2]) (struct s2n_connection * conn); -}; - -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); -} - -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); -} - -/* Client and Server handlers for each message type we support. - * See http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-7 for the list of handshake message types - */ -static struct s2n_handshake_action state_machine[] = { - /* message_type_t = {Record type Message type Writer S2N_SERVER S2N_CLIENT } */ - [CLIENT_HELLO] = {TLS_HANDSHAKE, TLS_CLIENT_HELLO, 'C', {s2n_establish_session, s2n_client_hello_send}}, - [SERVER_HELLO] = {TLS_HANDSHAKE, TLS_SERVER_HELLO, 'S', {s2n_server_hello_send, s2n_server_hello_recv}}, - [SERVER_NEW_SESSION_TICKET] = {TLS_HANDSHAKE, TLS_SERVER_NEW_SESSION_TICKET,'S', {s2n_server_nst_send, s2n_server_nst_recv}}, - [SERVER_CERT] = {TLS_HANDSHAKE, TLS_CERTIFICATE, 'S', {s2n_server_cert_send, s2n_server_cert_recv}}, - [SERVER_CERT_STATUS] = {TLS_HANDSHAKE, TLS_SERVER_CERT_STATUS, 'S', {s2n_server_status_send, s2n_server_status_recv}}, - [SERVER_KEY] = {TLS_HANDSHAKE, TLS_SERVER_KEY, 'S', {s2n_server_key_send, s2n_server_key_recv}}, - [SERVER_CERT_REQ] = {TLS_HANDSHAKE, TLS_CERT_REQ, 'S', {s2n_cert_req_send, s2n_cert_req_recv}}, - [SERVER_HELLO_DONE] = {TLS_HANDSHAKE, TLS_SERVER_HELLO_DONE, 'S', {s2n_server_done_send, s2n_server_done_recv}}, - [CLIENT_CERT] = {TLS_HANDSHAKE, TLS_CERTIFICATE, 'C', {s2n_client_cert_recv, s2n_client_cert_send}}, - [CLIENT_KEY] = {TLS_HANDSHAKE, TLS_CLIENT_KEY, 'C', {s2n_client_key_recv, s2n_client_key_send}}, - [CLIENT_CERT_VERIFY] = {TLS_HANDSHAKE, TLS_CERT_VERIFY, 'C', {s2n_client_cert_verify_recv, s2n_client_cert_verify_send}}, - [CLIENT_CHANGE_CIPHER_SPEC] = {TLS_CHANGE_CIPHER_SPEC, 0, 'C', {s2n_client_ccs_recv, s2n_ccs_send}}, - [CLIENT_FINISHED] = {TLS_HANDSHAKE, TLS_FINISHED, 'C', {s2n_client_finished_recv, s2n_client_finished_send}}, - [SERVER_CHANGE_CIPHER_SPEC] = {TLS_CHANGE_CIPHER_SPEC, 0, 'S', {s2n_ccs_send, s2n_server_ccs_recv}}, - [SERVER_FINISHED] = {TLS_HANDSHAKE, TLS_FINISHED, 'S', {s2n_server_finished_send, s2n_server_finished_recv}}, - [APPLICATION_DATA] = {TLS_APPLICATION_DATA, 0, 'B', {s2n_always_fail_send, s2n_always_fail_recv}} -}; - -/* - * Client and Server handlers for TLS1.3. - */ -static struct s2n_handshake_action tls13_state_machine[] = { - /* message_type_t = {Record type, Message type, Writer, {Server handler, client handler} } */ - [CLIENT_HELLO] = {TLS_HANDSHAKE, TLS_CLIENT_HELLO, 'C', {s2n_establish_session, s2n_client_hello_send}}, - [SERVER_HELLO] = {TLS_HANDSHAKE, TLS_SERVER_HELLO, 'S', {s2n_server_hello_send, s2n_server_hello_recv}}, - [HELLO_RETRY_MSG] = {TLS_HANDSHAKE, TLS_SERVER_HELLO, 'S', {s2n_server_hello_retry_send, s2n_server_hello_retry_recv}}, - [ENCRYPTED_EXTENSIONS] = {TLS_HANDSHAKE, TLS_ENCRYPTED_EXTENSIONS, 'S', {s2n_encrypted_extensions_send, s2n_encrypted_extensions_recv}}, - [SERVER_CERT_REQ] = {TLS_HANDSHAKE, TLS_CERT_REQ, 'S', {s2n_tls13_cert_req_send, s2n_tls13_cert_req_recv}}, - [SERVER_CERT] = {TLS_HANDSHAKE, TLS_CERTIFICATE, 'S', {s2n_server_cert_send, s2n_server_cert_recv}}, - [SERVER_CERT_VERIFY] = {TLS_HANDSHAKE, TLS_CERT_VERIFY, 'S', {s2n_tls13_cert_verify_send, s2n_tls13_cert_verify_recv}}, - [SERVER_FINISHED] = {TLS_HANDSHAKE, TLS_FINISHED, 'S', {s2n_tls13_server_finished_send, s2n_tls13_server_finished_recv}}, - - [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}}, - - /* 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}}, - [SERVER_CHANGE_CIPHER_SPEC] = {TLS_CHANGE_CIPHER_SPEC, 0, 'S', {s2n_ccs_send, s2n_basic_ccs_recv}}, - - [APPLICATION_DATA] = {TLS_APPLICATION_DATA, 0, 'B', {s2n_always_fail_send, s2n_always_fail_recv}}, -}; - -#define MESSAGE_NAME_ENTRY(msg) [msg] = #msg - -static const char *message_names[] = { - MESSAGE_NAME_ENTRY(CLIENT_HELLO), - MESSAGE_NAME_ENTRY(SERVER_HELLO), - MESSAGE_NAME_ENTRY(ENCRYPTED_EXTENSIONS), - MESSAGE_NAME_ENTRY(SERVER_NEW_SESSION_TICKET), - MESSAGE_NAME_ENTRY(SERVER_CERT), - MESSAGE_NAME_ENTRY(SERVER_CERT_STATUS), - MESSAGE_NAME_ENTRY(SERVER_CERT_VERIFY), - MESSAGE_NAME_ENTRY(SERVER_KEY), - MESSAGE_NAME_ENTRY(SERVER_CERT_REQ), - MESSAGE_NAME_ENTRY(SERVER_HELLO_DONE), - MESSAGE_NAME_ENTRY(CLIENT_CERT), - MESSAGE_NAME_ENTRY(CLIENT_KEY), - MESSAGE_NAME_ENTRY(CLIENT_CERT_VERIFY), - MESSAGE_NAME_ENTRY(CLIENT_CHANGE_CIPHER_SPEC), - MESSAGE_NAME_ENTRY(CLIENT_FINISHED), - MESSAGE_NAME_ENTRY(SERVER_CHANGE_CIPHER_SPEC), - MESSAGE_NAME_ENTRY(SERVER_FINISHED), - MESSAGE_NAME_ENTRY(HELLO_RETRY_MSG), - 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 - -/* We support different ordering of TLS Handshake messages, depending on what is being negotiated. There's also a dummy "INITIAL" handshake - * that everything starts out as until we know better. - */ - -static message_type_t handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_LENGTH] = { - [INITIAL] = { - CLIENT_HELLO, - SERVER_HELLO - }, - - [NEGOTIATED] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | WITH_SESSION_TICKET ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - APPLICATION_DATA}, - - [NEGOTIATED | FULL_HANDSHAKE ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_HELLO_DONE, - CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | WITH_SESSION_TICKET ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_HELLO_DONE, - CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_HELLO_DONE, - CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | WITH_SESSION_TICKET ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_HELLO_DONE, - CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS ] ={ - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_HELLO_DONE, - CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | WITH_SESSION_TICKET ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_HELLO_DONE, - CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_HELLO_DONE, - CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | WITH_SESSION_TICKET ] ={ - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_HELLO_DONE, - CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | WITH_SESSION_TICKET] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | NO_CLIENT_CERT ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | WITH_SESSION_TICKET] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | WITH_SESSION_TICKET] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | WITH_SESSION_TICKET ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, - CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - APPLICATION_DATA - }, -}; - -/* - * This selection of handshakes resembles the standard set, but with changes made to support tls1.3. - * - * These are just the basic handshakes. At the moment hello retries, session resumption, and early data are not supported. - * - * The CHANGE_CIPHER_SPEC messages are included only for middlebox compatibility. - * See https://tools.ietf.org/html/rfc8446#appendix-D.4 - */ -static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_LENGTH] = { - [INITIAL] = { - CLIENT_HELLO, - SERVER_HELLO - }, - - [INITIAL | HELLO_RETRY_REQUEST] = { - CLIENT_HELLO, - HELLO_RETRY_MSG - }, - - [NEGOTIATED | FULL_HANDSHAKE] = { - CLIENT_HELLO, - SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, - CLIENT_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | MIDDLEBOX_COMPAT] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, - CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST] = { - CLIENT_HELLO, - HELLO_RETRY_MSG, - CLIENT_HELLO, - SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, - CLIENT_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT] = { - CLIENT_HELLO, - HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC, - CLIENT_CHANGE_CIPHER_SPEC, CLIENT_HELLO, - SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, - CLIENT_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH] = { - CLIENT_HELLO, - HELLO_RETRY_MSG, - 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 | MIDDLEBOX_COMPAT] = { - CLIENT_HELLO, - HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC, - CLIENT_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, - 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 | HELLO_RETRY_REQUEST | CLIENT_AUTH | NO_CLIENT_CERT | MIDDLEBOX_COMPAT] = { - CLIENT_HELLO, - HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC, - CLIENT_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, - CLIENT_CERT, CLIENT_CERT_VERIFY, CLIENT_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | MIDDLEBOX_COMPAT] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, - CLIENT_CHANGE_CIPHER_SPEC, 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, - CLIENT_CERT, CLIENT_FINISHED, - APPLICATION_DATA - }, - - [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT | MIDDLEBOX_COMPAT] = { - CLIENT_HELLO, - SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, - CLIENT_CHANGE_CIPHER_SPEC, CLIENT_CERT, CLIENT_FINISHED, - APPLICATION_DATA - }, -}; -/* clang-format on */ - -#define MAX_HANDSHAKE_TYPE_LEN 152 -static char handshake_type_str[S2N_HANDSHAKES_COUNT][MAX_HANDSHAKE_TYPE_LEN] = {0}; - -static const char* handshake_type_names[] = { - "NEGOTIATED|", - "FULL_HANDSHAKE|", - "TLS12_PERFECT_FORWARD_SECRECY|", - "OCSP_STATUS|", - "CLIENT_AUTH|", - "WITH_SESSION_TICKET|", - "NO_CLIENT_CERT|", - "HELLO_RETRY_REQUEST|", - "MIDDLEBOX_COMPAT|", -}; - -#define IS_TLS13_HANDSHAKE( conn ) ((conn)->actual_protocol_version == S2N_TLS13) - -#define ACTIVE_STATE_MACHINE( conn ) (IS_TLS13_HANDSHAKE(conn) ? tls13_state_machine : state_machine) -#define ACTIVE_HANDSHAKES( conn ) (IS_TLS13_HANDSHAKE(conn) ? tls13_handshakes : handshakes) - -#define ACTIVE_MESSAGE( conn ) ACTIVE_HANDSHAKES(conn)[ (conn)->handshake.handshake_type ][ (conn)->handshake.message_number ] - -#define ACTIVE_STATE( conn ) ACTIVE_STATE_MACHINE(conn)[ ACTIVE_MESSAGE( (conn) ) ] -#define CCS_STATE( conn ) (((conn)->mode == S2N_CLIENT) ? ACTIVE_STATE_MACHINE(conn)[SERVER_CHANGE_CIPHER_SPEC] \ - : ACTIVE_STATE_MACHINE(conn)[CLIENT_CHANGE_CIPHER_SPEC] ) - -#define EXPECTED_RECORD_TYPE( conn ) ACTIVE_STATE( conn ).record_type -#define EXPECTED_MESSAGE_TYPE( conn ) ACTIVE_STATE( conn ).message_type - -#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 */ -message_type_t s2n_conn_get_current_message_type(struct s2n_connection *conn) -{ - return ACTIVE_MESSAGE(conn); -} - -static int s2n_advance_message(struct s2n_connection *conn) -{ - /* Get the mode: 'C'lient or 'S'erver */ - char previous_writer = ACTIVE_STATE(conn).writer; - char this_mode = CONNECTION_WRITER(conn); - - /* Actually advance the message number */ - conn->handshake.message_number++; - - /* When reading and using TLS1.3, skip optional change_cipher_spec states. */ - if (ACTIVE_STATE(conn).writer != this_mode && - EXPECTED_RECORD_TYPE(conn) == TLS_CHANGE_CIPHER_SPEC && - IS_TLS13_HANDSHAKE(conn)) { - conn->handshake.message_number++; - } - - /* Set TCP_QUICKACK to avoid artificial delay during the handshake */ - 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; - } - - /* Are we changing I/O directions */ - if (ACTIVE_STATE(conn).writer == previous_writer || ACTIVE_STATE(conn).writer == 'A') { - return 0; - } - - /* 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)); - } - - return 0; - } - - /* 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)); - } - - return 0; -} - -int s2n_generate_new_client_session_id(struct s2n_connection *conn) -{ - if (conn->mode == S2N_SERVER) { - 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)); - conn->session_id_len = S2N_TLS_SESSION_ID_MAX_LEN; - } - - return 0; -} - -/* 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; - - return S2N_SUCCESS; -} - -bool s2n_is_hello_retry_message(struct s2n_connection *conn) -{ - return (ACTIVE_MESSAGE(conn) == HELLO_RETRY_MSG); -} - -bool s2n_is_hello_retry_handshake(struct s2n_connection *conn) -{ - return conn->handshake.handshake_type & HELLO_RETRY_REQUEST; -} - -int s2n_conn_set_handshake_type(struct s2n_connection *conn) -{ - if (conn->handshake.handshake_type & HELLO_RETRY_REQUEST) { - ENSURE_POSIX(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_INVALID_HELLO_RETRY); - conn->handshake.handshake_type = HELLO_RETRY_REQUEST; - } else { - conn->handshake.handshake_type = INITIAL; - } - - /* A handshake type has been negotiated */ - conn->handshake.handshake_type |= NEGOTIATED; - - s2n_cert_auth_type client_cert_auth_type; - GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type)); - - if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED) { - /* If we're a client, and Client Auth is REQUIRED, then the Client must expect the CLIENT_CERT_REQ Message */ - conn->handshake.handshake_type |= CLIENT_AUTH; - } else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE) { - /* If we're a server, and Client Auth is REQUIRED or OPTIONAL, then the server must send the CLIENT_CERT_REQ Message*/ - conn->handshake.handshake_type |= CLIENT_AUTH; - } - - if (IS_TLS13_HANDSHAKE(conn)) { - /* Use middlebox compatibility mode for TLS1.3 by default. - * For now, only disable it when QUIC support is enabled. */ - if (!conn->config->quic_enabled) { - conn->handshake.handshake_type |= MIDDLEBOX_COMPAT; - } - conn->handshake.handshake_type |= FULL_HANDSHAKE; - - return 0; - } - - if (conn->config->use_tickets) { - if (conn->session_ticket_status == S2N_DECRYPT_TICKET) { - if (!s2n_decrypt_session_ticket(conn)) { - return 0; - } - - 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; - } - - /* If a session ticket is presented by the client, then skip lookup in Session ID server cache */ - goto skip_cache_lookup; - } - - if (conn->session_ticket_status == S2N_NEW_TICKET) { - conn->handshake.handshake_type |= WITH_SESSION_TICKET; - } - } - - /* If a TLS session is resumed, the Server should respond in its ServerHello with the same SessionId the - * 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))) { - return r; - } - } - -skip_cache_lookup: - if (conn->mode == S2N_CLIENT && conn->client_session_resumed == 1) { - return 0; - } - - /* If we're doing full handshake, generate a new session id. */ - GUARD(s2n_generate_new_client_session_id(conn)); - - /* If we get this far, it's a full handshake */ - conn->handshake.handshake_type |= FULL_HANDSHAKE; - - if (s2n_kex_is_ephemeral(conn->secure.cipher_suite->key_exchange_alg)) { - conn->handshake.handshake_type |= TLS12_PERFECT_FORWARD_SECRECY; - } - - if (s2n_server_can_send_ocsp(conn) || s2n_server_sent_ocsp(conn)) { - conn->handshake.handshake_type |= OCSP_STATUS; - } - - return 0; -} - -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)); - 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; - - return 0; -} - -const char *s2n_connection_get_last_message_name(struct s2n_connection *conn) -{ - notnull_check_ptr(conn); - - return message_names[ACTIVE_MESSAGE(conn)]; -} - -const char *s2n_connection_get_handshake_type_name(struct s2n_connection *conn) -{ - notnull_check_ptr(conn); - - int handshake_type = conn->handshake.handshake_type; - - if (handshake_type == INITIAL) { - return "INITIAL"; - } - - if (handshake_type_str[handshake_type][0] != '\0') { - return handshake_type_str[handshake_type]; - } - - /* Compute handshake_type_str[handshake_type] */ - 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) { - if (handshake_type & (1 << i)) { - p = s2n_strcpy(p, end, handshake_type_names[i]); - } - } - - if (p != handshake_type_str[handshake_type] && '|' == *(p - 1)) { - *(p - 1) = '\0'; - } - - return handshake_type_str[handshake_type]; -} - -/* Writing is relatively straight forward, simply write each message out as a record, - * we may fragment a message across multiple records, but we never coalesce multiple - * messages into single records. - * Precondition: secure outbound I/O has already been flushed - */ -static int s2n_handshake_write_io(struct s2n_connection *conn) -{ - uint8_t record_type = EXPECTED_RECORD_TYPE(conn); - s2n_blocked_status blocked = S2N_NOT_BLOCKED; - - /* Populate handshake.io with header/payload for the current state, once. - * Check wiped instead of s2n_stuffer_data_available to differentiate between the initial call - * to s2n_handshake_write_io and a repeated call after an EWOULDBLOCK. - */ - 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)); - } - GUARD(ACTIVE_STATE(conn).handler[conn->mode] (conn)); - if (record_type == TLS_HANDSHAKE) { - GUARD(s2n_handshake_finish_header(&conn->handshake.io)); - } - } - - /* Write the handshake data to records in fragment sized chunks */ - 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)); - 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); - - if (conn->config->quic_enabled) { - GUARD_AS_POSIX(s2n_quic_write_handshake_message(conn, &out)); - } else { - 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)); - } - - /* Actually send the record. We could block here. Assume the caller will call flush before coming back. */ - 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)); - - /* Update the secrets, if necessary */ - GUARD(s2n_tls13_handle_secrets(conn)); - - /* Advance the state machine */ - GUARD(s2n_advance_message(conn)); - - return 0; -} - -/* - * Returns: - * 1 - more data is needed to complete the handshake message. - * 0 - we read the whole handshake message. - * -1 - error processing the handshake message. - */ -static int s2n_read_full_handshake_message(struct s2n_connection *conn, uint8_t *message_type) -{ - uint32_t current_handshake_data = s2n_stuffer_data_available(&conn->handshake.io); - if (current_handshake_data < TLS_HANDSHAKE_HEADER_LENGTH) { - /* The message may be so badly fragmented that we don't even read the full header, take - * 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))); - return 1; - } - - /* Get the remainder of the header */ - 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)); - - S2N_ERROR_IF(handshake_message_length > S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH, S2N_ERR_BAD_MESSAGE); - - uint32_t bytes_to_take = handshake_message_length - s2n_stuffer_data_available(&conn->handshake.io); - 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)); - - /* If we have the whole handshake message, then success */ - if (s2n_stuffer_data_available(&conn->handshake.io) == handshake_message_length) { - return 0; - } - - /* We don't have the whole message, so we'll need to go again */ - GUARD(s2n_stuffer_reread(&conn->handshake.io)); - - return 1; -} - -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)); - - 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); - - /* MD5 and SHA sum the handshake data too */ - GUARD(s2n_conn_update_handshake_hashes(conn, &handshake_record)); - - return 0; -} - -static int s2n_handshake_handle_sslv2(struct s2n_connection *conn) -{ - S2N_ERROR_IF(ACTIVE_MESSAGE(conn) != CLIENT_HELLO, S2N_ERR_BAD_MESSAGE); - - /* 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)); - - hashed.data = conn->in.blob.data; - hashed.size = s2n_stuffer_data_available(&conn->in); - 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))); - /* 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)); - - /* 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)); - } - - return r; - } - - conn->in_status = ENCRYPTED; - - /* Advance the state machine */ - GUARD(s2n_advance_message(conn)); - - return 0; -} - -static int s2n_try_delete_session_cache(struct s2n_connection *conn) -{ - notnull_check(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; -} - -/* Reading is a little more complicated than writing as the TLS RFCs allow content - * types to be interleaved at the record layer. We may get an alert message - * during the handshake phase, or messages of types that we don't support (e.g. - * HEARTBEAT messages), or during renegotiations we may even get application - * data messages that need to be handled by the application. The latter is punted - * for now (s2n does not support renegotiations). - */ -static int s2n_handshake_read_io(struct s2n_connection *conn) -{ - uint8_t record_type; - uint8_t message_type; - int isSSLv2 = 0; - - /* 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) { - record_type = TLS_HANDSHAKE; - GUARD_AS_POSIX(s2n_quic_read_handshake_message(conn, &message_type)); - } else { - GUARD(s2n_read_full_record(conn, &record_type, &isSSLv2)); - } - - if (isSSLv2) { - S2N_ERROR_IF(record_type != SSLv2_CLIENT_HELLO, S2N_ERR_BAD_MESSAGE); - 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) { - /* 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); - } - - 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)); - - /* 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; - - /* 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)); - } - - return 0; - } else if (record_type != TLS_HANDSHAKE) { - if (record_type == TLS_ALERT) { - 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; - } - - /* Record is a handshake message */ - S2N_ERROR_IF(s2n_stuffer_data_available(&conn->in) == 0, S2N_ERR_BAD_MESSAGE); - - while (s2n_stuffer_data_available(&conn->in)) { - /* 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))); - - /* 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; - } - - s2n_cert_auth_type client_cert_auth_type; - 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) { - conn->handshake.handshake_type |= CLIENT_AUTH; - } - - /* According to rfc6066 section 8, server may choose not to send "CertificateStatus" message even if it has - * sent "status_request" extension in the ServerHello message. */ - 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; - } - - 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; - } - - /* Update the secrets, if necessary */ - GUARD(s2n_tls13_handle_secrets(conn)); - - /* Advance the state machine */ - GUARD(s2n_advance_message(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; -} - -static int s2n_handle_retry_state(struct s2n_connection *conn) -{ - /* If we were blocked reading or writing a record, then the handler is waiting on - * external data. The handler will know how to continue, so we should call the - * handler right away. We aren't going to read more handshake data yet or proceed - * to the next handler because the current message has not finished processing. */ - 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 the handler is still waiting for data, return control to the caller. */ - S2N_ERROR_PRESERVE_ERRNO(); - } - - 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)); - 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)) { - /* 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)); - } - } else { - /* The read handler processed the record successfully, we are done with this - * record. Advance the state machine. */ - GUARD(s2n_advance_message(conn)); - } - - return 0; -} - -int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked) -{ - notnull_check(conn); - notnull_check(blocked); - - while (ACTIVE_STATE(conn).writer != 'B') { - errno = 0; - s2n_errno = S2N_ERR_OK; - - /* Flush any pending I/O or alert messages */ - 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)); - } - - if (CONNECTION_IS_WRITER(conn)) { - *blocked = S2N_BLOCKED_ON_WRITE; - const int write_result = s2n_handshake_write_io(conn); - - if (write_result < 0) { - 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; - const int write_s2n_errno = s2n_errno; - const char *write_s2n_debug_str = s2n_debug_str; - - if (s2n_handshake_read_io(conn) < 0 && s2n_errno == S2N_ERR_ALERT) { - /* s2n_handshake_read_io has set s2n_errno */ - S2N_ERROR_PRESERVE_ERRNO(); - } else { - /* Let the write error take precedence if we didn't read an alert. */ - errno = write_errno; - s2n_errno = write_s2n_errno; - s2n_debug_str = write_s2n_debug_str; - S2N_ERROR_PRESERVE_ERRNO(); - } - } - - if (s2n_errno == S2N_ERR_ASYNC_BLOCKED) { - *blocked = S2N_BLOCKED_ON_APPLICATION_INPUT; - } - - S2N_ERROR_PRESERVE_ERRNO(); - } - } else { - *blocked = S2N_BLOCKED_ON_READ; - const int read_result = s2n_handshake_read_io(conn); - - if (read_result < 0) { - /* 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) { - s2n_try_delete_session_cache(conn); - } - - if (s2n_errno == S2N_ERR_ASYNC_BLOCKED) { - *blocked = S2N_BLOCKED_ON_APPLICATION_INPUT; - } - - 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)); - } - } - - *blocked = S2N_NOT_BLOCKED; - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <sys/param.h> + +#include <errno.h> +#include <s2n.h> + +#include "error/s2n_errno.h" + +#include "crypto/s2n_fips.h" + +#include "tls/s2n_async_pkey.h" +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_record.h" +#include "tls/s2n_resume.h" +#include "tls/s2n_alerts.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls13.h" +#include "tls/s2n_tls13_handshake.h" +#include "tls/s2n_kex.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" + +/* clang-format off */ +struct s2n_handshake_action { + uint8_t record_type; + uint8_t message_type; + char writer; /* 'S' or 'C' for server or client, 'B' for both */ + int (*handler[2]) (struct s2n_connection * conn); +}; + +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); +} + +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); +} + +/* Client and Server handlers for each message type we support. + * See http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-7 for the list of handshake message types + */ +static struct s2n_handshake_action state_machine[] = { + /* message_type_t = {Record type Message type Writer S2N_SERVER S2N_CLIENT } */ + [CLIENT_HELLO] = {TLS_HANDSHAKE, TLS_CLIENT_HELLO, 'C', {s2n_establish_session, s2n_client_hello_send}}, + [SERVER_HELLO] = {TLS_HANDSHAKE, TLS_SERVER_HELLO, 'S', {s2n_server_hello_send, s2n_server_hello_recv}}, + [SERVER_NEW_SESSION_TICKET] = {TLS_HANDSHAKE, TLS_SERVER_NEW_SESSION_TICKET,'S', {s2n_server_nst_send, s2n_server_nst_recv}}, + [SERVER_CERT] = {TLS_HANDSHAKE, TLS_CERTIFICATE, 'S', {s2n_server_cert_send, s2n_server_cert_recv}}, + [SERVER_CERT_STATUS] = {TLS_HANDSHAKE, TLS_SERVER_CERT_STATUS, 'S', {s2n_server_status_send, s2n_server_status_recv}}, + [SERVER_KEY] = {TLS_HANDSHAKE, TLS_SERVER_KEY, 'S', {s2n_server_key_send, s2n_server_key_recv}}, + [SERVER_CERT_REQ] = {TLS_HANDSHAKE, TLS_CERT_REQ, 'S', {s2n_cert_req_send, s2n_cert_req_recv}}, + [SERVER_HELLO_DONE] = {TLS_HANDSHAKE, TLS_SERVER_HELLO_DONE, 'S', {s2n_server_done_send, s2n_server_done_recv}}, + [CLIENT_CERT] = {TLS_HANDSHAKE, TLS_CERTIFICATE, 'C', {s2n_client_cert_recv, s2n_client_cert_send}}, + [CLIENT_KEY] = {TLS_HANDSHAKE, TLS_CLIENT_KEY, 'C', {s2n_client_key_recv, s2n_client_key_send}}, + [CLIENT_CERT_VERIFY] = {TLS_HANDSHAKE, TLS_CERT_VERIFY, 'C', {s2n_client_cert_verify_recv, s2n_client_cert_verify_send}}, + [CLIENT_CHANGE_CIPHER_SPEC] = {TLS_CHANGE_CIPHER_SPEC, 0, 'C', {s2n_client_ccs_recv, s2n_ccs_send}}, + [CLIENT_FINISHED] = {TLS_HANDSHAKE, TLS_FINISHED, 'C', {s2n_client_finished_recv, s2n_client_finished_send}}, + [SERVER_CHANGE_CIPHER_SPEC] = {TLS_CHANGE_CIPHER_SPEC, 0, 'S', {s2n_ccs_send, s2n_server_ccs_recv}}, + [SERVER_FINISHED] = {TLS_HANDSHAKE, TLS_FINISHED, 'S', {s2n_server_finished_send, s2n_server_finished_recv}}, + [APPLICATION_DATA] = {TLS_APPLICATION_DATA, 0, 'B', {s2n_always_fail_send, s2n_always_fail_recv}} +}; + +/* + * Client and Server handlers for TLS1.3. + */ +static struct s2n_handshake_action tls13_state_machine[] = { + /* message_type_t = {Record type, Message type, Writer, {Server handler, client handler} } */ + [CLIENT_HELLO] = {TLS_HANDSHAKE, TLS_CLIENT_HELLO, 'C', {s2n_establish_session, s2n_client_hello_send}}, + [SERVER_HELLO] = {TLS_HANDSHAKE, TLS_SERVER_HELLO, 'S', {s2n_server_hello_send, s2n_server_hello_recv}}, + [HELLO_RETRY_MSG] = {TLS_HANDSHAKE, TLS_SERVER_HELLO, 'S', {s2n_server_hello_retry_send, s2n_server_hello_retry_recv}}, + [ENCRYPTED_EXTENSIONS] = {TLS_HANDSHAKE, TLS_ENCRYPTED_EXTENSIONS, 'S', {s2n_encrypted_extensions_send, s2n_encrypted_extensions_recv}}, + [SERVER_CERT_REQ] = {TLS_HANDSHAKE, TLS_CERT_REQ, 'S', {s2n_tls13_cert_req_send, s2n_tls13_cert_req_recv}}, + [SERVER_CERT] = {TLS_HANDSHAKE, TLS_CERTIFICATE, 'S', {s2n_server_cert_send, s2n_server_cert_recv}}, + [SERVER_CERT_VERIFY] = {TLS_HANDSHAKE, TLS_CERT_VERIFY, 'S', {s2n_tls13_cert_verify_send, s2n_tls13_cert_verify_recv}}, + [SERVER_FINISHED] = {TLS_HANDSHAKE, TLS_FINISHED, 'S', {s2n_tls13_server_finished_send, s2n_tls13_server_finished_recv}}, + + [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}}, + + /* 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}}, + [SERVER_CHANGE_CIPHER_SPEC] = {TLS_CHANGE_CIPHER_SPEC, 0, 'S', {s2n_ccs_send, s2n_basic_ccs_recv}}, + + [APPLICATION_DATA] = {TLS_APPLICATION_DATA, 0, 'B', {s2n_always_fail_send, s2n_always_fail_recv}}, +}; + +#define MESSAGE_NAME_ENTRY(msg) [msg] = #msg + +static const char *message_names[] = { + MESSAGE_NAME_ENTRY(CLIENT_HELLO), + MESSAGE_NAME_ENTRY(SERVER_HELLO), + MESSAGE_NAME_ENTRY(ENCRYPTED_EXTENSIONS), + MESSAGE_NAME_ENTRY(SERVER_NEW_SESSION_TICKET), + MESSAGE_NAME_ENTRY(SERVER_CERT), + MESSAGE_NAME_ENTRY(SERVER_CERT_STATUS), + MESSAGE_NAME_ENTRY(SERVER_CERT_VERIFY), + MESSAGE_NAME_ENTRY(SERVER_KEY), + MESSAGE_NAME_ENTRY(SERVER_CERT_REQ), + MESSAGE_NAME_ENTRY(SERVER_HELLO_DONE), + MESSAGE_NAME_ENTRY(CLIENT_CERT), + MESSAGE_NAME_ENTRY(CLIENT_KEY), + MESSAGE_NAME_ENTRY(CLIENT_CERT_VERIFY), + MESSAGE_NAME_ENTRY(CLIENT_CHANGE_CIPHER_SPEC), + MESSAGE_NAME_ENTRY(CLIENT_FINISHED), + MESSAGE_NAME_ENTRY(SERVER_CHANGE_CIPHER_SPEC), + MESSAGE_NAME_ENTRY(SERVER_FINISHED), + MESSAGE_NAME_ENTRY(HELLO_RETRY_MSG), + 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 + +/* We support different ordering of TLS Handshake messages, depending on what is being negotiated. There's also a dummy "INITIAL" handshake + * that everything starts out as until we know better. + */ + +static message_type_t handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_LENGTH] = { + [INITIAL] = { + CLIENT_HELLO, + SERVER_HELLO + }, + + [NEGOTIATED] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | WITH_SESSION_TICKET ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + APPLICATION_DATA}, + + [NEGOTIATED | FULL_HANDSHAKE ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_HELLO_DONE, + CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | WITH_SESSION_TICKET ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_HELLO_DONE, + CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_HELLO_DONE, + CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | WITH_SESSION_TICKET ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_HELLO_DONE, + CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS ] ={ + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_HELLO_DONE, + CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | WITH_SESSION_TICKET ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_HELLO_DONE, + CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_HELLO_DONE, + CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | WITH_SESSION_TICKET ] ={ + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_HELLO_DONE, + CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | WITH_SESSION_TICKET] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | NO_CLIENT_CERT ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | WITH_SESSION_TICKET] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | WITH_SESSION_TICKET] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | WITH_SESSION_TICKET ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CERT_VERIFY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | TLS12_PERFECT_FORWARD_SECRECY | OCSP_STATUS | CLIENT_AUTH | NO_CLIENT_CERT | WITH_SESSION_TICKET ] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CERT, SERVER_CERT_STATUS, SERVER_KEY, SERVER_CERT_REQ, SERVER_HELLO_DONE, + CLIENT_CERT, CLIENT_KEY, CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + SERVER_NEW_SESSION_TICKET, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, + APPLICATION_DATA + }, +}; + +/* + * This selection of handshakes resembles the standard set, but with changes made to support tls1.3. + * + * These are just the basic handshakes. At the moment hello retries, session resumption, and early data are not supported. + * + * The CHANGE_CIPHER_SPEC messages are included only for middlebox compatibility. + * See https://tools.ietf.org/html/rfc8446#appendix-D.4 + */ +static message_type_t tls13_handshakes[S2N_HANDSHAKES_COUNT][S2N_MAX_HANDSHAKE_LENGTH] = { + [INITIAL] = { + CLIENT_HELLO, + SERVER_HELLO + }, + + [INITIAL | HELLO_RETRY_REQUEST] = { + CLIENT_HELLO, + HELLO_RETRY_MSG + }, + + [NEGOTIATED | FULL_HANDSHAKE] = { + CLIENT_HELLO, + SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, + CLIENT_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | MIDDLEBOX_COMPAT] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, + CLIENT_CHANGE_CIPHER_SPEC, CLIENT_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST] = { + CLIENT_HELLO, + HELLO_RETRY_MSG, + CLIENT_HELLO, + SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, + CLIENT_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | MIDDLEBOX_COMPAT] = { + CLIENT_HELLO, + HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC, + CLIENT_CHANGE_CIPHER_SPEC, CLIENT_HELLO, + SERVER_HELLO, ENCRYPTED_EXTENSIONS, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, + CLIENT_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | HELLO_RETRY_REQUEST | CLIENT_AUTH] = { + CLIENT_HELLO, + HELLO_RETRY_MSG, + 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 | MIDDLEBOX_COMPAT] = { + CLIENT_HELLO, + HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC, + CLIENT_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, + 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 | HELLO_RETRY_REQUEST | CLIENT_AUTH | NO_CLIENT_CERT | MIDDLEBOX_COMPAT] = { + CLIENT_HELLO, + HELLO_RETRY_MSG, SERVER_CHANGE_CIPHER_SPEC, + CLIENT_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, + CLIENT_CERT, CLIENT_CERT_VERIFY, CLIENT_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | MIDDLEBOX_COMPAT] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, + CLIENT_CHANGE_CIPHER_SPEC, 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, + CLIENT_CERT, CLIENT_FINISHED, + APPLICATION_DATA + }, + + [NEGOTIATED | FULL_HANDSHAKE | CLIENT_AUTH | NO_CLIENT_CERT | MIDDLEBOX_COMPAT] = { + CLIENT_HELLO, + SERVER_HELLO, SERVER_CHANGE_CIPHER_SPEC, ENCRYPTED_EXTENSIONS, SERVER_CERT_REQ, SERVER_CERT, SERVER_CERT_VERIFY, SERVER_FINISHED, + CLIENT_CHANGE_CIPHER_SPEC, CLIENT_CERT, CLIENT_FINISHED, + APPLICATION_DATA + }, +}; +/* clang-format on */ + +#define MAX_HANDSHAKE_TYPE_LEN 152 +static char handshake_type_str[S2N_HANDSHAKES_COUNT][MAX_HANDSHAKE_TYPE_LEN] = {0}; + +static const char* handshake_type_names[] = { + "NEGOTIATED|", + "FULL_HANDSHAKE|", + "TLS12_PERFECT_FORWARD_SECRECY|", + "OCSP_STATUS|", + "CLIENT_AUTH|", + "WITH_SESSION_TICKET|", + "NO_CLIENT_CERT|", + "HELLO_RETRY_REQUEST|", + "MIDDLEBOX_COMPAT|", +}; + +#define IS_TLS13_HANDSHAKE( conn ) ((conn)->actual_protocol_version == S2N_TLS13) + +#define ACTIVE_STATE_MACHINE( conn ) (IS_TLS13_HANDSHAKE(conn) ? tls13_state_machine : state_machine) +#define ACTIVE_HANDSHAKES( conn ) (IS_TLS13_HANDSHAKE(conn) ? tls13_handshakes : handshakes) + +#define ACTIVE_MESSAGE( conn ) ACTIVE_HANDSHAKES(conn)[ (conn)->handshake.handshake_type ][ (conn)->handshake.message_number ] + +#define ACTIVE_STATE( conn ) ACTIVE_STATE_MACHINE(conn)[ ACTIVE_MESSAGE( (conn) ) ] +#define CCS_STATE( conn ) (((conn)->mode == S2N_CLIENT) ? ACTIVE_STATE_MACHINE(conn)[SERVER_CHANGE_CIPHER_SPEC] \ + : ACTIVE_STATE_MACHINE(conn)[CLIENT_CHANGE_CIPHER_SPEC] ) + +#define EXPECTED_RECORD_TYPE( conn ) ACTIVE_STATE( conn ).record_type +#define EXPECTED_MESSAGE_TYPE( conn ) ACTIVE_STATE( conn ).message_type + +#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 */ +message_type_t s2n_conn_get_current_message_type(struct s2n_connection *conn) +{ + return ACTIVE_MESSAGE(conn); +} + +static int s2n_advance_message(struct s2n_connection *conn) +{ + /* Get the mode: 'C'lient or 'S'erver */ + char previous_writer = ACTIVE_STATE(conn).writer; + char this_mode = CONNECTION_WRITER(conn); + + /* Actually advance the message number */ + conn->handshake.message_number++; + + /* When reading and using TLS1.3, skip optional change_cipher_spec states. */ + if (ACTIVE_STATE(conn).writer != this_mode && + EXPECTED_RECORD_TYPE(conn) == TLS_CHANGE_CIPHER_SPEC && + IS_TLS13_HANDSHAKE(conn)) { + conn->handshake.message_number++; + } + + /* Set TCP_QUICKACK to avoid artificial delay during the handshake */ + 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; + } + + /* Are we changing I/O directions */ + if (ACTIVE_STATE(conn).writer == previous_writer || ACTIVE_STATE(conn).writer == 'A') { + return 0; + } + + /* 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)); + } + + return 0; + } + + /* 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)); + } + + return 0; +} + +int s2n_generate_new_client_session_id(struct s2n_connection *conn) +{ + if (conn->mode == S2N_SERVER) { + 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)); + conn->session_id_len = S2N_TLS_SESSION_ID_MAX_LEN; + } + + return 0; +} + +/* 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; + + return S2N_SUCCESS; +} + +bool s2n_is_hello_retry_message(struct s2n_connection *conn) +{ + return (ACTIVE_MESSAGE(conn) == HELLO_RETRY_MSG); +} + +bool s2n_is_hello_retry_handshake(struct s2n_connection *conn) +{ + return conn->handshake.handshake_type & HELLO_RETRY_REQUEST; +} + +int s2n_conn_set_handshake_type(struct s2n_connection *conn) +{ + if (conn->handshake.handshake_type & HELLO_RETRY_REQUEST) { + ENSURE_POSIX(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_INVALID_HELLO_RETRY); + conn->handshake.handshake_type = HELLO_RETRY_REQUEST; + } else { + conn->handshake.handshake_type = INITIAL; + } + + /* A handshake type has been negotiated */ + conn->handshake.handshake_type |= NEGOTIATED; + + s2n_cert_auth_type client_cert_auth_type; + GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type)); + + if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED) { + /* If we're a client, and Client Auth is REQUIRED, then the Client must expect the CLIENT_CERT_REQ Message */ + conn->handshake.handshake_type |= CLIENT_AUTH; + } else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE) { + /* If we're a server, and Client Auth is REQUIRED or OPTIONAL, then the server must send the CLIENT_CERT_REQ Message*/ + conn->handshake.handshake_type |= CLIENT_AUTH; + } + + if (IS_TLS13_HANDSHAKE(conn)) { + /* Use middlebox compatibility mode for TLS1.3 by default. + * For now, only disable it when QUIC support is enabled. */ + if (!conn->config->quic_enabled) { + conn->handshake.handshake_type |= MIDDLEBOX_COMPAT; + } + conn->handshake.handshake_type |= FULL_HANDSHAKE; + + return 0; + } + + if (conn->config->use_tickets) { + if (conn->session_ticket_status == S2N_DECRYPT_TICKET) { + if (!s2n_decrypt_session_ticket(conn)) { + return 0; + } + + 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; + } + + /* If a session ticket is presented by the client, then skip lookup in Session ID server cache */ + goto skip_cache_lookup; + } + + if (conn->session_ticket_status == S2N_NEW_TICKET) { + conn->handshake.handshake_type |= WITH_SESSION_TICKET; + } + } + + /* If a TLS session is resumed, the Server should respond in its ServerHello with the same SessionId the + * 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))) { + return r; + } + } + +skip_cache_lookup: + if (conn->mode == S2N_CLIENT && conn->client_session_resumed == 1) { + return 0; + } + + /* If we're doing full handshake, generate a new session id. */ + GUARD(s2n_generate_new_client_session_id(conn)); + + /* If we get this far, it's a full handshake */ + conn->handshake.handshake_type |= FULL_HANDSHAKE; + + if (s2n_kex_is_ephemeral(conn->secure.cipher_suite->key_exchange_alg)) { + conn->handshake.handshake_type |= TLS12_PERFECT_FORWARD_SECRECY; + } + + if (s2n_server_can_send_ocsp(conn) || s2n_server_sent_ocsp(conn)) { + conn->handshake.handshake_type |= OCSP_STATUS; + } + + return 0; +} + +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)); + 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; + + return 0; +} + +const char *s2n_connection_get_last_message_name(struct s2n_connection *conn) +{ + notnull_check_ptr(conn); + + return message_names[ACTIVE_MESSAGE(conn)]; +} + +const char *s2n_connection_get_handshake_type_name(struct s2n_connection *conn) +{ + notnull_check_ptr(conn); + + int handshake_type = conn->handshake.handshake_type; + + if (handshake_type == INITIAL) { + return "INITIAL"; + } + + if (handshake_type_str[handshake_type][0] != '\0') { + return handshake_type_str[handshake_type]; + } + + /* Compute handshake_type_str[handshake_type] */ + 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) { + if (handshake_type & (1 << i)) { + p = s2n_strcpy(p, end, handshake_type_names[i]); + } + } + + if (p != handshake_type_str[handshake_type] && '|' == *(p - 1)) { + *(p - 1) = '\0'; + } + + return handshake_type_str[handshake_type]; +} + +/* Writing is relatively straight forward, simply write each message out as a record, + * we may fragment a message across multiple records, but we never coalesce multiple + * messages into single records. + * Precondition: secure outbound I/O has already been flushed + */ +static int s2n_handshake_write_io(struct s2n_connection *conn) +{ + uint8_t record_type = EXPECTED_RECORD_TYPE(conn); + s2n_blocked_status blocked = S2N_NOT_BLOCKED; + + /* Populate handshake.io with header/payload for the current state, once. + * Check wiped instead of s2n_stuffer_data_available to differentiate between the initial call + * to s2n_handshake_write_io and a repeated call after an EWOULDBLOCK. + */ + 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)); + } + GUARD(ACTIVE_STATE(conn).handler[conn->mode] (conn)); + if (record_type == TLS_HANDSHAKE) { + GUARD(s2n_handshake_finish_header(&conn->handshake.io)); + } + } + + /* Write the handshake data to records in fragment sized chunks */ + 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)); + 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); + + if (conn->config->quic_enabled) { + GUARD_AS_POSIX(s2n_quic_write_handshake_message(conn, &out)); + } else { + 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)); + } + + /* Actually send the record. We could block here. Assume the caller will call flush before coming back. */ + 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)); + + /* Update the secrets, if necessary */ + GUARD(s2n_tls13_handle_secrets(conn)); + + /* Advance the state machine */ + GUARD(s2n_advance_message(conn)); + + return 0; +} + +/* + * Returns: + * 1 - more data is needed to complete the handshake message. + * 0 - we read the whole handshake message. + * -1 - error processing the handshake message. + */ +static int s2n_read_full_handshake_message(struct s2n_connection *conn, uint8_t *message_type) +{ + uint32_t current_handshake_data = s2n_stuffer_data_available(&conn->handshake.io); + if (current_handshake_data < TLS_HANDSHAKE_HEADER_LENGTH) { + /* The message may be so badly fragmented that we don't even read the full header, take + * 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))); + return 1; + } + + /* Get the remainder of the header */ + 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)); + + S2N_ERROR_IF(handshake_message_length > S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH, S2N_ERR_BAD_MESSAGE); + + uint32_t bytes_to_take = handshake_message_length - s2n_stuffer_data_available(&conn->handshake.io); + 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)); + + /* If we have the whole handshake message, then success */ + if (s2n_stuffer_data_available(&conn->handshake.io) == handshake_message_length) { + return 0; + } + + /* We don't have the whole message, so we'll need to go again */ + GUARD(s2n_stuffer_reread(&conn->handshake.io)); + + return 1; +} + +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)); + + 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); + + /* MD5 and SHA sum the handshake data too */ + GUARD(s2n_conn_update_handshake_hashes(conn, &handshake_record)); + + return 0; +} + +static int s2n_handshake_handle_sslv2(struct s2n_connection *conn) +{ + S2N_ERROR_IF(ACTIVE_MESSAGE(conn) != CLIENT_HELLO, S2N_ERR_BAD_MESSAGE); + + /* 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)); + + hashed.data = conn->in.blob.data; + hashed.size = s2n_stuffer_data_available(&conn->in); + 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))); + /* 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)); + + /* 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)); + } + + return r; + } + + conn->in_status = ENCRYPTED; + + /* Advance the state machine */ + GUARD(s2n_advance_message(conn)); + + return 0; +} + +static int s2n_try_delete_session_cache(struct s2n_connection *conn) +{ + notnull_check(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; +} + +/* Reading is a little more complicated than writing as the TLS RFCs allow content + * types to be interleaved at the record layer. We may get an alert message + * during the handshake phase, or messages of types that we don't support (e.g. + * HEARTBEAT messages), or during renegotiations we may even get application + * data messages that need to be handled by the application. The latter is punted + * for now (s2n does not support renegotiations). + */ +static int s2n_handshake_read_io(struct s2n_connection *conn) +{ + uint8_t record_type; + uint8_t message_type; + int isSSLv2 = 0; + + /* 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) { + record_type = TLS_HANDSHAKE; + GUARD_AS_POSIX(s2n_quic_read_handshake_message(conn, &message_type)); + } else { + GUARD(s2n_read_full_record(conn, &record_type, &isSSLv2)); + } + + if (isSSLv2) { + S2N_ERROR_IF(record_type != SSLv2_CLIENT_HELLO, S2N_ERR_BAD_MESSAGE); + 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) { + /* 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); + } + + 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)); + + /* 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; + + /* 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)); + } + + return 0; + } else if (record_type != TLS_HANDSHAKE) { + if (record_type == TLS_ALERT) { + 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; + } + + /* Record is a handshake message */ + S2N_ERROR_IF(s2n_stuffer_data_available(&conn->in) == 0, S2N_ERR_BAD_MESSAGE); + + while (s2n_stuffer_data_available(&conn->in)) { + /* 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))); + + /* 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; + } + + s2n_cert_auth_type client_cert_auth_type; + 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) { + conn->handshake.handshake_type |= CLIENT_AUTH; + } + + /* According to rfc6066 section 8, server may choose not to send "CertificateStatus" message even if it has + * sent "status_request" extension in the ServerHello message. */ + 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; + } + + 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; + } + + /* Update the secrets, if necessary */ + GUARD(s2n_tls13_handle_secrets(conn)); + + /* Advance the state machine */ + GUARD(s2n_advance_message(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; +} + +static int s2n_handle_retry_state(struct s2n_connection *conn) +{ + /* If we were blocked reading or writing a record, then the handler is waiting on + * external data. The handler will know how to continue, so we should call the + * handler right away. We aren't going to read more handshake data yet or proceed + * to the next handler because the current message has not finished processing. */ + 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 the handler is still waiting for data, return control to the caller. */ + S2N_ERROR_PRESERVE_ERRNO(); + } + + 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)); + 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)) { + /* 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)); + } + } else { + /* The read handler processed the record successfully, we are done with this + * record. Advance the state machine. */ + GUARD(s2n_advance_message(conn)); + } + + return 0; +} + +int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked) +{ + notnull_check(conn); + notnull_check(blocked); + + while (ACTIVE_STATE(conn).writer != 'B') { + errno = 0; + s2n_errno = S2N_ERR_OK; + + /* Flush any pending I/O or alert messages */ + 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)); + } + + if (CONNECTION_IS_WRITER(conn)) { + *blocked = S2N_BLOCKED_ON_WRITE; + const int write_result = s2n_handshake_write_io(conn); + + if (write_result < 0) { + 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; + const int write_s2n_errno = s2n_errno; + const char *write_s2n_debug_str = s2n_debug_str; + + if (s2n_handshake_read_io(conn) < 0 && s2n_errno == S2N_ERR_ALERT) { + /* s2n_handshake_read_io has set s2n_errno */ + S2N_ERROR_PRESERVE_ERRNO(); + } else { + /* Let the write error take precedence if we didn't read an alert. */ + errno = write_errno; + s2n_errno = write_s2n_errno; + s2n_debug_str = write_s2n_debug_str; + S2N_ERROR_PRESERVE_ERRNO(); + } + } + + if (s2n_errno == S2N_ERR_ASYNC_BLOCKED) { + *blocked = S2N_BLOCKED_ON_APPLICATION_INPUT; + } + + S2N_ERROR_PRESERVE_ERRNO(); + } + } else { + *blocked = S2N_BLOCKED_ON_READ; + const int read_result = s2n_handshake_read_io(conn); + + if (read_result < 0) { + /* 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) { + s2n_try_delete_session_cache(conn); + } + + if (s2n_errno == S2N_ERR_ASYNC_BLOCKED) { + *blocked = S2N_BLOCKED_ON_APPLICATION_INPUT; + } + + 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)); + } + } + + *blocked = S2N_NOT_BLOCKED; + + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_handshake_transcript.c b/contrib/restricted/aws/s2n/tls/s2n_handshake_transcript.c index 7023d78e59..7c6c3dffb6 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_handshake_transcript.c +++ b/contrib/restricted/aws/s2n/tls/s2n_handshake_transcript.c @@ -1,136 +1,136 @@ -/* - * 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_tls.h" -#include "tls/s2n_tls13_handshake.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_blob.h" - -/* 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); - - if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_MD5)) { - /* The handshake MD5 hash state will fail the s2n_hash_is_available() check - * since MD5 is not permitted in FIPS mode. This check will not be used as - * the handshake MD5 hash state is specifically used by the TLS 1.0 and TLS 1.1 - * 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)); - } - - if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA1)) { - GUARD(s2n_hash_update(&conn->handshake.sha1, data->data, data->size)); - } - - const uint8_t md5_sha1_required = (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_MD5) && - s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA1)); - - if (md5_sha1_required) { - /* The MD5_SHA1 hash can still be used for TLS 1.0 and 1.1 in FIPS mode for - * the handshake hashes. This will only be used for the signature check in the - * 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)); - } - - if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA224)) { - GUARD(s2n_hash_update(&conn->handshake.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)); - } - - if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA384)) { - GUARD(s2n_hash_update(&conn->handshake.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)); - } - - /* 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; -} - -/* When a HelloRetryRequest message is used, the hash transcript needs to be recreated. - * This is done with a synthetic message header, and the hash of ClientHello1. - * - * https://tools.ietf.org/html/rfc8446#section-4.4.1 - */ -int s2n_server_hello_retry_recreate_transcript(struct s2n_connection *conn) -{ - notnull_check(conn); - - s2n_tls13_connection_keys(keys, conn); - uint8_t hash_digest_length = keys.size; - - /* Create the MessageHash (our synthetic message) */ - uint8_t msghdr[MESSAGE_HASH_HEADER_LENGTH] = {0}; - msghdr[0] = TLS_MESSAGE_HASH; - 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)); - - /* Step 1: Reset the hash state */ - GUARD(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)); - - /* 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)); - - return 0; -} - +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls13_handshake.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_blob.h" + +/* 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); + + if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_MD5)) { + /* The handshake MD5 hash state will fail the s2n_hash_is_available() check + * since MD5 is not permitted in FIPS mode. This check will not be used as + * the handshake MD5 hash state is specifically used by the TLS 1.0 and TLS 1.1 + * 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)); + } + + if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA1)) { + GUARD(s2n_hash_update(&conn->handshake.sha1, data->data, data->size)); + } + + const uint8_t md5_sha1_required = (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_MD5) && + s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA1)); + + if (md5_sha1_required) { + /* The MD5_SHA1 hash can still be used for TLS 1.0 and 1.1 in FIPS mode for + * the handshake hashes. This will only be used for the signature check in the + * 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)); + } + + if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA224)) { + GUARD(s2n_hash_update(&conn->handshake.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)); + } + + if (s2n_handshake_is_hash_required(&conn->handshake, S2N_HASH_SHA384)) { + GUARD(s2n_hash_update(&conn->handshake.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)); + } + + /* 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; +} + +/* When a HelloRetryRequest message is used, the hash transcript needs to be recreated. + * This is done with a synthetic message header, and the hash of ClientHello1. + * + * https://tools.ietf.org/html/rfc8446#section-4.4.1 + */ +int s2n_server_hello_retry_recreate_transcript(struct s2n_connection *conn) +{ + notnull_check(conn); + + s2n_tls13_connection_keys(keys, conn); + uint8_t hash_digest_length = keys.size; + + /* Create the MessageHash (our synthetic message) */ + uint8_t msghdr[MESSAGE_HASH_HEADER_LENGTH] = {0}; + msghdr[0] = TLS_MESSAGE_HASH; + 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)); + + /* Step 1: Reset the hash state */ + GUARD(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)); + + /* 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)); + + return 0; +} + diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem.c b/contrib/restricted/aws/s2n/tls/s2n_kem.c index e1b413cfe2..4ddbbc8683 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kem.c +++ b/contrib/restricted/aws/s2n/tls/s2n_kem.c @@ -1,509 +1,509 @@ -/* - * 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 "stuffer/s2n_stuffer.h" -#include "tls/s2n_tls_parameters.h" -#include "tls/s2n_kem.h" -#include "tls/extensions/s2n_key_share.h" -#include "utils/s2n_mem.h" -#include "utils/s2n_safety.h" -#include "pq-crypto/s2n_pq.h" - -/* The KEM IDs and names come from https://tools.ietf.org/html/draft-campagna-tls-bike-sike-hybrid */ -const struct s2n_kem s2n_bike1_l1_r1 = { - .name = "BIKE1r1-Level1", - .kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_BIKE1_L1_R1, - .public_key_length = BIKE1_L1_R1_PUBLIC_KEY_BYTES, - .private_key_length = BIKE1_L1_R1_SECRET_KEY_BYTES, - .shared_secret_key_length = BIKE1_L1_R1_SHARED_SECRET_BYTES, - .ciphertext_length = BIKE1_L1_R1_CIPHERTEXT_BYTES, - .generate_keypair = &BIKE1_L1_R1_crypto_kem_keypair, - .encapsulate = &BIKE1_L1_R1_crypto_kem_enc, - .decapsulate = &BIKE1_L1_R1_crypto_kem_dec, -}; - -const struct s2n_kem s2n_bike1_l1_r2 = { - .name = "BIKE1r2-Level1", - .kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_BIKE1_L1_R2, - .public_key_length = BIKE1_L1_R2_PUBLIC_KEY_BYTES, - .private_key_length = BIKE1_L1_R2_SECRET_KEY_BYTES, - .shared_secret_key_length = BIKE1_L1_R2_SHARED_SECRET_BYTES, - .ciphertext_length = BIKE1_L1_R2_CIPHERTEXT_BYTES, - .generate_keypair = &BIKE1_L1_R2_crypto_kem_keypair, - .encapsulate = &BIKE1_L1_R2_crypto_kem_enc, - .decapsulate = &BIKE1_L1_R2_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, - .public_key_length = SIKE_P503_R1_PUBLIC_KEY_BYTES, - .private_key_length = SIKE_P503_R1_SECRET_KEY_BYTES, - .shared_secret_key_length = SIKE_P503_R1_SHARED_SECRET_BYTES, - .ciphertext_length = SIKE_P503_R1_CIPHERTEXT_BYTES, - .generate_keypair = &SIKE_P503_r1_crypto_kem_keypair, - .encapsulate = &SIKE_P503_r1_crypto_kem_enc, - .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, - .public_key_length = KYBER_512_R2_PUBLIC_KEY_BYTES, - .private_key_length = KYBER_512_R2_SECRET_KEY_BYTES, - .shared_secret_key_length = KYBER_512_R2_SHARED_SECRET_BYTES, - .ciphertext_length = KYBER_512_R2_CIPHERTEXT_BYTES, - .generate_keypair = &kyber_512_r2_crypto_kem_keypair, - .encapsulate = &kyber_512_r2_crypto_kem_enc, - .decapsulate = &kyber_512_r2_crypto_kem_dec, -}; - -const struct s2n_kem s2n_kyber_512_90s_r2 = { - .name = "kyber51290sr2", - .kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_KYBER_512_90S_R2, - .public_key_length = KYBER_512_R2_PUBLIC_KEY_BYTES, - .private_key_length = KYBER_512_R2_SECRET_KEY_BYTES, - .shared_secret_key_length = KYBER_512_R2_SHARED_SECRET_BYTES, - .ciphertext_length = KYBER_512_R2_CIPHERTEXT_BYTES, - .generate_keypair = &kyber_512_90s_r2_crypto_kem_keypair, - .encapsulate = &kyber_512_90s_r2_crypto_kem_enc, - .decapsulate = &kyber_512_90s_r2_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 -}; - -const struct s2n_kem *sike_kems[] = { - &s2n_sike_p503_r1, - &s2n_sike_p434_r2, -}; - -const struct s2n_kem *kyber_kems[] = { - &s2n_kyber_512_r2, - &s2n_kyber_512_90s_r2, -}; - -const struct s2n_iana_to_kem kem_mapping[3] = { - { - .iana_value = { TLS_ECDHE_BIKE_RSA_WITH_AES_256_GCM_SHA384 }, - .kems = bike_kems, - .kem_count = s2n_array_len(bike_kems), - }, - { - .iana_value = { TLS_ECDHE_SIKE_RSA_WITH_AES_256_GCM_SHA384 }, - .kems = sike_kems, - .kem_count = s2n_array_len(sike_kems), - }, - { - .iana_value = { TLS_ECDHE_KYBER_RSA_WITH_AES_256_GCM_SHA384 }, - .kems = kyber_kems, - .kem_count = s2n_array_len(kyber_kems), - } -}; - -/* Specific assignments of KEM group IDs and names have not yet been - * published in an RFC (or draft). There is consensus in the - * 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. - * - * 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, - .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) + - (S2N_SIZE_OF_KEY_SHARE_SIZE + SIKE_P434_R2_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), - .curve = &s2n_ecc_curve_secp256r1, - .kem = &s2n_sike_p434_r2, -}; - -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) + - (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE1_L1_R2_PUBLIC_KEY_BYTES), - .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) + - (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE1_L1_R2_CIPHERTEXT_BYTES), - .curve = &s2n_ecc_curve_secp256r1, - .kem = &s2n_bike1_l1_r2, -}; - -const struct s2n_kem_group s2n_secp256r1_kyber_512_r2 = { - .name = "secp256r1_kyber-512-r2", - .iana_id = TLS_PQ_KEM_GROUP_ID_SECP256R1_KYBER_512_R2, - .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) + - (S2N_SIZE_OF_KEY_SHARE_SIZE + KYBER_512_R2_PUBLIC_KEY_BYTES), - .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) + - (S2N_SIZE_OF_KEY_SHARE_SIZE + KYBER_512_R2_CIPHERTEXT_BYTES), - .curve = &s2n_ecc_curve_secp256r1, - .kem = &s2n_kyber_512_r2, -}; - -#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, - .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) + - (S2N_SIZE_OF_KEY_SHARE_SIZE + SIKE_P434_R2_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), - .curve = &s2n_ecc_curve_x25519, - .kem = &s2n_sike_p434_r2, -}; - -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) + - (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE1_L1_R2_PUBLIC_KEY_BYTES), - .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) + - (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE1_L1_R2_CIPHERTEXT_BYTES), - .curve = &s2n_ecc_curve_x25519, - .kem = &s2n_bike1_l1_r2, -}; - -const struct s2n_kem_group s2n_x25519_kyber_512_r2 = { - .name = "x25519_kyber-512-r2", - .iana_id = TLS_PQ_KEM_GROUP_ID_X25519_KYBER_512_R2, - .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) + - (S2N_SIZE_OF_KEY_SHARE_SIZE + KYBER_512_R2_PUBLIC_KEY_BYTES), - .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) + - (S2N_SIZE_OF_KEY_SHARE_SIZE + KYBER_512_R2_CIPHERTEXT_BYTES), - .curve = &s2n_ecc_curve_x25519, - .kem = &s2n_kyber_512_r2, -}; -#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 }; -#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) - -S2N_RESULT s2n_kem_generate_keypair(struct s2n_kem_params *kem_params) -{ - ENSURE_REF(kem_params); - ENSURE_REF(kem_params->kem); - const struct s2n_kem *kem = kem_params->kem; - 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); - - /* Need to save the private key for decapsulation */ - GUARD_AS_RESULT(s2n_alloc(&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; -} - -S2N_RESULT s2n_kem_encapsulate(struct s2n_kem_params *kem_params, struct s2n_blob *ciphertext) -{ - ENSURE_REF(kem_params); - ENSURE_REF(kem_params->kem); - const struct s2n_kem *kem = kem_params->kem; - ENSURE_REF(kem->encapsulate); - - ENSURE(kem_params->public_key.size == kem->public_key_length, S2N_ERR_SAFETY); - ENSURE_REF(kem_params->public_key.data); - - ENSURE_REF(ciphertext); - ENSURE_REF(ciphertext->data); - 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)); - - GUARD_PQ_AS_RESULT(kem->encapsulate(ciphertext->data, kem_params->shared_secret.data, kem_params->public_key.data)); - return S2N_RESULT_OK; -} - -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); - const struct s2n_kem *kem = kem_params->kem; - ENSURE_REF(kem->decapsulate); - - ENSURE(kem_params->private_key.size == kem->private_key_length, S2N_ERR_SAFETY); - ENSURE_REF(kem_params->private_key.data); - - ENSURE_REF(ciphertext); - ENSURE_REF(ciphertext->data); - 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)); - - GUARD_PQ_AS_RESULT(kem->decapsulate(kem_params->shared_secret.data, ciphertext->data, kem_params->private_key.data)); - return S2N_RESULT_OK; -} - -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)); - - for (uint8_t i = 0; i < compatible_kems->kem_count; i++) { - if (candidate_kem->kem_extension_id == compatible_kems->kems[i]->kem_extension_id) { - *kem_is_compatible = 1; - return S2N_SUCCESS; - } - } - - *kem_is_compatible = 0; - return S2N_SUCCESS; -} - -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)); - - /* Each KEM ID is 2 bytes */ - uint8_t num_client_candidate_kems = client_kem_ids->size / 2; - - for (uint8_t i = 0; i < num_server_supported_kems; i++) { - 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)); - - if (!server_kem_is_compatible) { - continue; - } - - 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)); - - 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)); - } - - /* Client and server did not propose any mutually supported KEMs compatible with the ciphersuite */ - S2N_ERROR(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)); - if (kem_is_compatible) { - *chosen_kem = server_kem_pref_list[i]; - return S2N_SUCCESS; - } - } - - /* The server preference list did not contain any KEM extensions compatible with the ciphersuite */ - S2N_ERROR(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)); - } - 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)); - } - return S2N_SUCCESS; -} - -int s2n_cipher_suite_to_kem(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN], const struct s2n_iana_to_kem **compatible_params) { - for (int i = 0; i < s2n_array_len(kem_mapping); i++) { - const struct s2n_iana_to_kem *candidate = &kem_mapping[i]; - if (memcmp(iana_value, candidate->iana_value, S2N_TLS_CIPHER_SUITE_LEN) == 0) { - *compatible_params = candidate; - return S2N_SUCCESS; - } - } - S2N_ERROR(S2N_ERR_KEM_UNSUPPORTED_PARAMS); -} - -int s2n_get_kem_from_extension_id(kem_extension_size kem_id, const struct s2n_kem **kem) { - for (int i = 0; i < s2n_array_len(kem_mapping); i++) { - const struct s2n_iana_to_kem *iana_to_kem = &kem_mapping[i]; - - for (int j = 0; j < iana_to_kem->kem_count; j++) { - const struct s2n_kem *candidate_kem = iana_to_kem->kems[j]; - if (candidate_kem->kem_extension_id == kem_id) { - *kem = candidate_kem; - return S2N_SUCCESS; - } - } - } - - S2N_ERROR(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); - - const struct s2n_kem *kem = kem_params->kem; - - 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); - 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)); - - /* 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 - * does not continue to point at *out, else we may unexpectedly - * overwrite part of the stuffer when s2n_kem_free() is called. */ - kem_params->public_key.data = NULL; - kem_params->public_key.size = 0; - - return S2N_SUCCESS; -} - -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); - - const struct s2n_kem *kem = kem_params->kem; - kem_public_key_size public_key_length; - - 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)); - - 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); - - const struct s2n_kem *kem = kem_params->kem; - - 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); - - /* Saves the shared secret in kem_params */ - GUARD_AS_POSIX(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); - - const struct s2n_kem *kem = kem_params->kem; - kem_ciphertext_key_size ciphertext_length; - - 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); - - /* Saves the shared secret in kem_params */ - GUARD_AS_POSIX(s2n_kem_decapsulate(kem_params, &ciphertext)); - - return S2N_SUCCESS; -} - -#if defined(S2N_NO_PQ) -/* IF S2N_NO_PQ was defined at compile time, the PQ KEM code will have been entirely excluded - * from compilation. We define stubs of these functions here to error if they are called. */ -/* 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); } -/* 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); } -/* 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); } -/* 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); } -/* 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); } -#endif +/* + * 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 "stuffer/s2n_stuffer.h" +#include "tls/s2n_tls_parameters.h" +#include "tls/s2n_kem.h" +#include "tls/extensions/s2n_key_share.h" +#include "utils/s2n_mem.h" +#include "utils/s2n_safety.h" +#include "pq-crypto/s2n_pq.h" + +/* The KEM IDs and names come from https://tools.ietf.org/html/draft-campagna-tls-bike-sike-hybrid */ +const struct s2n_kem s2n_bike1_l1_r1 = { + .name = "BIKE1r1-Level1", + .kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_BIKE1_L1_R1, + .public_key_length = BIKE1_L1_R1_PUBLIC_KEY_BYTES, + .private_key_length = BIKE1_L1_R1_SECRET_KEY_BYTES, + .shared_secret_key_length = BIKE1_L1_R1_SHARED_SECRET_BYTES, + .ciphertext_length = BIKE1_L1_R1_CIPHERTEXT_BYTES, + .generate_keypair = &BIKE1_L1_R1_crypto_kem_keypair, + .encapsulate = &BIKE1_L1_R1_crypto_kem_enc, + .decapsulate = &BIKE1_L1_R1_crypto_kem_dec, +}; + +const struct s2n_kem s2n_bike1_l1_r2 = { + .name = "BIKE1r2-Level1", + .kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_BIKE1_L1_R2, + .public_key_length = BIKE1_L1_R2_PUBLIC_KEY_BYTES, + .private_key_length = BIKE1_L1_R2_SECRET_KEY_BYTES, + .shared_secret_key_length = BIKE1_L1_R2_SHARED_SECRET_BYTES, + .ciphertext_length = BIKE1_L1_R2_CIPHERTEXT_BYTES, + .generate_keypair = &BIKE1_L1_R2_crypto_kem_keypair, + .encapsulate = &BIKE1_L1_R2_crypto_kem_enc, + .decapsulate = &BIKE1_L1_R2_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, + .public_key_length = SIKE_P503_R1_PUBLIC_KEY_BYTES, + .private_key_length = SIKE_P503_R1_SECRET_KEY_BYTES, + .shared_secret_key_length = SIKE_P503_R1_SHARED_SECRET_BYTES, + .ciphertext_length = SIKE_P503_R1_CIPHERTEXT_BYTES, + .generate_keypair = &SIKE_P503_r1_crypto_kem_keypair, + .encapsulate = &SIKE_P503_r1_crypto_kem_enc, + .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, + .public_key_length = KYBER_512_R2_PUBLIC_KEY_BYTES, + .private_key_length = KYBER_512_R2_SECRET_KEY_BYTES, + .shared_secret_key_length = KYBER_512_R2_SHARED_SECRET_BYTES, + .ciphertext_length = KYBER_512_R2_CIPHERTEXT_BYTES, + .generate_keypair = &kyber_512_r2_crypto_kem_keypair, + .encapsulate = &kyber_512_r2_crypto_kem_enc, + .decapsulate = &kyber_512_r2_crypto_kem_dec, +}; + +const struct s2n_kem s2n_kyber_512_90s_r2 = { + .name = "kyber51290sr2", + .kem_extension_id = TLS_PQ_KEM_EXTENSION_ID_KYBER_512_90S_R2, + .public_key_length = KYBER_512_R2_PUBLIC_KEY_BYTES, + .private_key_length = KYBER_512_R2_SECRET_KEY_BYTES, + .shared_secret_key_length = KYBER_512_R2_SHARED_SECRET_BYTES, + .ciphertext_length = KYBER_512_R2_CIPHERTEXT_BYTES, + .generate_keypair = &kyber_512_90s_r2_crypto_kem_keypair, + .encapsulate = &kyber_512_90s_r2_crypto_kem_enc, + .decapsulate = &kyber_512_90s_r2_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 +}; + +const struct s2n_kem *sike_kems[] = { + &s2n_sike_p503_r1, + &s2n_sike_p434_r2, +}; + +const struct s2n_kem *kyber_kems[] = { + &s2n_kyber_512_r2, + &s2n_kyber_512_90s_r2, +}; + +const struct s2n_iana_to_kem kem_mapping[3] = { + { + .iana_value = { TLS_ECDHE_BIKE_RSA_WITH_AES_256_GCM_SHA384 }, + .kems = bike_kems, + .kem_count = s2n_array_len(bike_kems), + }, + { + .iana_value = { TLS_ECDHE_SIKE_RSA_WITH_AES_256_GCM_SHA384 }, + .kems = sike_kems, + .kem_count = s2n_array_len(sike_kems), + }, + { + .iana_value = { TLS_ECDHE_KYBER_RSA_WITH_AES_256_GCM_SHA384 }, + .kems = kyber_kems, + .kem_count = s2n_array_len(kyber_kems), + } +}; + +/* Specific assignments of KEM group IDs and names have not yet been + * published in an RFC (or draft). There is consensus in the + * 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. + * + * 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, + .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) + + (S2N_SIZE_OF_KEY_SHARE_SIZE + SIKE_P434_R2_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), + .curve = &s2n_ecc_curve_secp256r1, + .kem = &s2n_sike_p434_r2, +}; + +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) + + (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE1_L1_R2_PUBLIC_KEY_BYTES), + .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) + + (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE1_L1_R2_CIPHERTEXT_BYTES), + .curve = &s2n_ecc_curve_secp256r1, + .kem = &s2n_bike1_l1_r2, +}; + +const struct s2n_kem_group s2n_secp256r1_kyber_512_r2 = { + .name = "secp256r1_kyber-512-r2", + .iana_id = TLS_PQ_KEM_GROUP_ID_SECP256R1_KYBER_512_R2, + .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) + + (S2N_SIZE_OF_KEY_SHARE_SIZE + KYBER_512_R2_PUBLIC_KEY_BYTES), + .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + SECP256R1_SHARE_SIZE) + + (S2N_SIZE_OF_KEY_SHARE_SIZE + KYBER_512_R2_CIPHERTEXT_BYTES), + .curve = &s2n_ecc_curve_secp256r1, + .kem = &s2n_kyber_512_r2, +}; + +#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, + .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) + + (S2N_SIZE_OF_KEY_SHARE_SIZE + SIKE_P434_R2_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), + .curve = &s2n_ecc_curve_x25519, + .kem = &s2n_sike_p434_r2, +}; + +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) + + (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE1_L1_R2_PUBLIC_KEY_BYTES), + .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) + + (S2N_SIZE_OF_KEY_SHARE_SIZE + BIKE1_L1_R2_CIPHERTEXT_BYTES), + .curve = &s2n_ecc_curve_x25519, + .kem = &s2n_bike1_l1_r2, +}; + +const struct s2n_kem_group s2n_x25519_kyber_512_r2 = { + .name = "x25519_kyber-512-r2", + .iana_id = TLS_PQ_KEM_GROUP_ID_X25519_KYBER_512_R2, + .client_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) + + (S2N_SIZE_OF_KEY_SHARE_SIZE + KYBER_512_R2_PUBLIC_KEY_BYTES), + .server_share_size = (S2N_SIZE_OF_KEY_SHARE_SIZE + X25519_SHARE_SIZE) + + (S2N_SIZE_OF_KEY_SHARE_SIZE + KYBER_512_R2_CIPHERTEXT_BYTES), + .curve = &s2n_ecc_curve_x25519, + .kem = &s2n_kyber_512_r2, +}; +#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 }; +#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) + +S2N_RESULT s2n_kem_generate_keypair(struct s2n_kem_params *kem_params) +{ + ENSURE_REF(kem_params); + ENSURE_REF(kem_params->kem); + const struct s2n_kem *kem = kem_params->kem; + 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); + + /* Need to save the private key for decapsulation */ + GUARD_AS_RESULT(s2n_alloc(&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; +} + +S2N_RESULT s2n_kem_encapsulate(struct s2n_kem_params *kem_params, struct s2n_blob *ciphertext) +{ + ENSURE_REF(kem_params); + ENSURE_REF(kem_params->kem); + const struct s2n_kem *kem = kem_params->kem; + ENSURE_REF(kem->encapsulate); + + ENSURE(kem_params->public_key.size == kem->public_key_length, S2N_ERR_SAFETY); + ENSURE_REF(kem_params->public_key.data); + + ENSURE_REF(ciphertext); + ENSURE_REF(ciphertext->data); + 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)); + + GUARD_PQ_AS_RESULT(kem->encapsulate(ciphertext->data, kem_params->shared_secret.data, kem_params->public_key.data)); + return S2N_RESULT_OK; +} + +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); + const struct s2n_kem *kem = kem_params->kem; + ENSURE_REF(kem->decapsulate); + + ENSURE(kem_params->private_key.size == kem->private_key_length, S2N_ERR_SAFETY); + ENSURE_REF(kem_params->private_key.data); + + ENSURE_REF(ciphertext); + ENSURE_REF(ciphertext->data); + 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)); + + GUARD_PQ_AS_RESULT(kem->decapsulate(kem_params->shared_secret.data, ciphertext->data, kem_params->private_key.data)); + return S2N_RESULT_OK; +} + +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)); + + for (uint8_t i = 0; i < compatible_kems->kem_count; i++) { + if (candidate_kem->kem_extension_id == compatible_kems->kems[i]->kem_extension_id) { + *kem_is_compatible = 1; + return S2N_SUCCESS; + } + } + + *kem_is_compatible = 0; + return S2N_SUCCESS; +} + +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)); + + /* Each KEM ID is 2 bytes */ + uint8_t num_client_candidate_kems = client_kem_ids->size / 2; + + for (uint8_t i = 0; i < num_server_supported_kems; i++) { + 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)); + + if (!server_kem_is_compatible) { + continue; + } + + 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)); + + 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)); + } + + /* Client and server did not propose any mutually supported KEMs compatible with the ciphersuite */ + S2N_ERROR(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)); + if (kem_is_compatible) { + *chosen_kem = server_kem_pref_list[i]; + return S2N_SUCCESS; + } + } + + /* The server preference list did not contain any KEM extensions compatible with the ciphersuite */ + S2N_ERROR(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)); + } + 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)); + } + return S2N_SUCCESS; +} + +int s2n_cipher_suite_to_kem(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN], const struct s2n_iana_to_kem **compatible_params) { + for (int i = 0; i < s2n_array_len(kem_mapping); i++) { + const struct s2n_iana_to_kem *candidate = &kem_mapping[i]; + if (memcmp(iana_value, candidate->iana_value, S2N_TLS_CIPHER_SUITE_LEN) == 0) { + *compatible_params = candidate; + return S2N_SUCCESS; + } + } + S2N_ERROR(S2N_ERR_KEM_UNSUPPORTED_PARAMS); +} + +int s2n_get_kem_from_extension_id(kem_extension_size kem_id, const struct s2n_kem **kem) { + for (int i = 0; i < s2n_array_len(kem_mapping); i++) { + const struct s2n_iana_to_kem *iana_to_kem = &kem_mapping[i]; + + for (int j = 0; j < iana_to_kem->kem_count; j++) { + const struct s2n_kem *candidate_kem = iana_to_kem->kems[j]; + if (candidate_kem->kem_extension_id == kem_id) { + *kem = candidate_kem; + return S2N_SUCCESS; + } + } + } + + S2N_ERROR(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); + + const struct s2n_kem *kem = kem_params->kem; + + 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); + 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)); + + /* 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 + * does not continue to point at *out, else we may unexpectedly + * overwrite part of the stuffer when s2n_kem_free() is called. */ + kem_params->public_key.data = NULL; + kem_params->public_key.size = 0; + + return S2N_SUCCESS; +} + +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); + + const struct s2n_kem *kem = kem_params->kem; + kem_public_key_size public_key_length; + + 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)); + + 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); + + const struct s2n_kem *kem = kem_params->kem; + + 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); + + /* Saves the shared secret in kem_params */ + GUARD_AS_POSIX(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); + + const struct s2n_kem *kem = kem_params->kem; + kem_ciphertext_key_size ciphertext_length; + + 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); + + /* Saves the shared secret in kem_params */ + GUARD_AS_POSIX(s2n_kem_decapsulate(kem_params, &ciphertext)); + + return S2N_SUCCESS; +} + +#if defined(S2N_NO_PQ) +/* IF S2N_NO_PQ was defined at compile time, the PQ KEM code will have been entirely excluded + * from compilation. We define stubs of these functions here to error if they are called. */ +/* 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); } +/* 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); } +/* 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); } +/* 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); } +/* 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); } +#endif diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem.h b/contrib/restricted/aws/s2n/tls/s2n_kem.h index 76908aa968..ddea9d09ca 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kem.h +++ b/contrib/restricted/aws/s2n/tls/s2n_kem.h @@ -1,181 +1,181 @@ -/* - * 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 <stdint.h> -#include "tls/s2n_crypto_constants.h" -#include "utils/s2n_blob.h" -#include "stuffer/s2n_stuffer.h" -#include "crypto/s2n_ecc_evp.h" - -typedef uint16_t kem_extension_size; -typedef uint16_t kem_public_key_size; -typedef uint16_t kem_private_key_size; -typedef uint16_t kem_shared_secret_size; -typedef uint16_t kem_ciphertext_key_size; - -#define IN /* Indicates a necessary function input */ -#define OUT /* Indicates a function output */ - -struct s2n_kem { - const char *name; - const kem_extension_size kem_extension_id; - const kem_public_key_size public_key_length; - const kem_private_key_size private_key_length; - const kem_shared_secret_size shared_secret_key_length; - const kem_ciphertext_key_size ciphertext_length; - /* NIST Post Quantum KEM submissions require the following API for compatibility */ - int (*generate_keypair)(OUT unsigned char *public_key, OUT unsigned char *private_key); - int (*encapsulate)(OUT unsigned char *ciphertext, OUT unsigned char *shared_secret, IN const unsigned char *public_key); - int (*decapsulate)(OUT unsigned char *shared_secret, IN const unsigned char *ciphertext, IN const unsigned char *private_key); -}; - -struct s2n_kem_params { - const struct s2n_kem *kem; - struct s2n_blob public_key; - struct s2n_blob private_key; - struct s2n_blob shared_secret; -}; - -struct s2n_iana_to_kem { - const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN]; - const struct s2n_kem **kems; - uint8_t kem_count; -}; - -struct s2n_kem_group { - const char *name; - uint16_t iana_id; - uint16_t client_share_size; - uint16_t server_share_size; - const struct s2n_ecc_named_curve *curve; - const struct s2n_kem *kem; -}; - -struct s2n_kem_group_params { - const struct s2n_kem_group *kem_group; - struct s2n_kem_params kem_params; - struct s2n_ecc_evp_params ecc_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_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; - -/* x25519 based tls13_kem_groups require EVP_APIS_SUPPORTED */ -#if EVP_APIS_SUPPORTED -#define S2N_SUPPORTED_KEM_GROUPS_COUNT 6 -#else -#define S2N_SUPPORTED_KEM_GROUPS_COUNT 3 -#endif - -extern const struct s2n_kem_group s2n_secp256r1_sike_p434_r2; -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; -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); -extern 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); -extern 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); -extern int s2n_kem_free(struct s2n_kem_params *kem_params); -extern int s2n_kem_group_free(struct s2n_kem_group_params *kem_group_params); -extern int s2n_cipher_suite_to_kem(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN], - const struct s2n_iana_to_kem **supported_params); -extern int s2n_get_kem_from_extension_id(kem_extension_size kem_id, const struct s2n_kem **kem); -extern int s2n_kem_send_public_key(struct s2n_stuffer *out, struct s2n_kem_params *kem_params); -extern int s2n_kem_recv_public_key(struct s2n_stuffer *in, struct s2n_kem_params *kem_params); -extern int s2n_kem_send_ciphertext(struct s2n_stuffer *out, struct s2n_kem_params *kem_params); -extern int s2n_kem_recv_ciphertext(struct s2n_stuffer *in, struct s2n_kem_params *kem_params); - -/* The following are API signatures for PQ KEMs as defined by NIST. All functions return 0 - * on success, and !0 on failure. Avoid calling these functions directly within s2n. Instead, - * use s2n_kem_{generate_keypair, encapsulate, decapsulate}, or - * s2n_kem_{send_public_key, recv_public_key, send_ciphertext, recv_ciphertext}. - * - * int *_keypair(OUT pk, OUT sk) - Generate public/private keypair - * pk - generated public key - * sk - generated secret key - * - * int *_enc(OUT ct, OUT ss, IN pk) - Generate a shared secret and encapsulate it - * ct - key encapsulation message (ciphertext) - * ss - plaintext shared secret - * pk - public key to use for encapsulation - * - * int *_dec(OUT ss, IN ct, IN sk) - Decapsulate a key encapsulation message and recover the shared secret - * ss - plaintext shared secret - * ct - key encapsulation message (ciphertext) - * sk - secret key to use for decapsulation */ - -/* If s2n is compiled with support for PQ crypto, these functions will be defined in the respective KEM directories. - * If s2n is compiled without support for PQ, stubs of these functions are defined in s2n_kem.c. */ -/* sikep503r1 */ -#define SIKE_P503_R1_SECRET_KEY_BYTES 434 -#define SIKE_P503_R1_PUBLIC_KEY_BYTES 378 -#define SIKE_P503_R1_CIPHERTEXT_BYTES 402 -#define SIKE_P503_R1_SHARED_SECRET_BYTES 16 -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 */ -#define BIKE1_L1_R1_SECRET_KEY_BYTES 3110 -#define BIKE1_L1_R1_PUBLIC_KEY_BYTES 2542 -#define BIKE1_L1_R1_CIPHERTEXT_BYTES 2542 -#define BIKE1_L1_R1_SHARED_SECRET_BYTES 32 -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 */ -#define BIKE1_L1_R2_SECRET_KEY_BYTES 6460 -#define BIKE1_L1_R2_PUBLIC_KEY_BYTES 2946 -#define BIKE1_L1_R2_CIPHERTEXT_BYTES 2946 -#define BIKE1_L1_R2_SHARED_SECRET_BYTES 32 -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); - -/* 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 -#define KYBER_512_R2_CIPHERTEXT_BYTES 736 -#define KYBER_512_R2_SHARED_SECRET_BYTES 32 -int kyber_512_r2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk); -int kyber_512_r2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk); -int kyber_512_r2_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk); -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); +/* + * 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 <stdint.h> +#include "tls/s2n_crypto_constants.h" +#include "utils/s2n_blob.h" +#include "stuffer/s2n_stuffer.h" +#include "crypto/s2n_ecc_evp.h" + +typedef uint16_t kem_extension_size; +typedef uint16_t kem_public_key_size; +typedef uint16_t kem_private_key_size; +typedef uint16_t kem_shared_secret_size; +typedef uint16_t kem_ciphertext_key_size; + +#define IN /* Indicates a necessary function input */ +#define OUT /* Indicates a function output */ + +struct s2n_kem { + const char *name; + const kem_extension_size kem_extension_id; + const kem_public_key_size public_key_length; + const kem_private_key_size private_key_length; + const kem_shared_secret_size shared_secret_key_length; + const kem_ciphertext_key_size ciphertext_length; + /* NIST Post Quantum KEM submissions require the following API for compatibility */ + int (*generate_keypair)(OUT unsigned char *public_key, OUT unsigned char *private_key); + int (*encapsulate)(OUT unsigned char *ciphertext, OUT unsigned char *shared_secret, IN const unsigned char *public_key); + int (*decapsulate)(OUT unsigned char *shared_secret, IN const unsigned char *ciphertext, IN const unsigned char *private_key); +}; + +struct s2n_kem_params { + const struct s2n_kem *kem; + struct s2n_blob public_key; + struct s2n_blob private_key; + struct s2n_blob shared_secret; +}; + +struct s2n_iana_to_kem { + const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN]; + const struct s2n_kem **kems; + uint8_t kem_count; +}; + +struct s2n_kem_group { + const char *name; + uint16_t iana_id; + uint16_t client_share_size; + uint16_t server_share_size; + const struct s2n_ecc_named_curve *curve; + const struct s2n_kem *kem; +}; + +struct s2n_kem_group_params { + const struct s2n_kem_group *kem_group; + struct s2n_kem_params kem_params; + struct s2n_ecc_evp_params ecc_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_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; + +/* x25519 based tls13_kem_groups require EVP_APIS_SUPPORTED */ +#if EVP_APIS_SUPPORTED +#define S2N_SUPPORTED_KEM_GROUPS_COUNT 6 +#else +#define S2N_SUPPORTED_KEM_GROUPS_COUNT 3 +#endif + +extern const struct s2n_kem_group s2n_secp256r1_sike_p434_r2; +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; +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); +extern 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); +extern 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); +extern int s2n_kem_free(struct s2n_kem_params *kem_params); +extern int s2n_kem_group_free(struct s2n_kem_group_params *kem_group_params); +extern int s2n_cipher_suite_to_kem(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN], + const struct s2n_iana_to_kem **supported_params); +extern int s2n_get_kem_from_extension_id(kem_extension_size kem_id, const struct s2n_kem **kem); +extern int s2n_kem_send_public_key(struct s2n_stuffer *out, struct s2n_kem_params *kem_params); +extern int s2n_kem_recv_public_key(struct s2n_stuffer *in, struct s2n_kem_params *kem_params); +extern int s2n_kem_send_ciphertext(struct s2n_stuffer *out, struct s2n_kem_params *kem_params); +extern int s2n_kem_recv_ciphertext(struct s2n_stuffer *in, struct s2n_kem_params *kem_params); + +/* The following are API signatures for PQ KEMs as defined by NIST. All functions return 0 + * on success, and !0 on failure. Avoid calling these functions directly within s2n. Instead, + * use s2n_kem_{generate_keypair, encapsulate, decapsulate}, or + * s2n_kem_{send_public_key, recv_public_key, send_ciphertext, recv_ciphertext}. + * + * int *_keypair(OUT pk, OUT sk) - Generate public/private keypair + * pk - generated public key + * sk - generated secret key + * + * int *_enc(OUT ct, OUT ss, IN pk) - Generate a shared secret and encapsulate it + * ct - key encapsulation message (ciphertext) + * ss - plaintext shared secret + * pk - public key to use for encapsulation + * + * int *_dec(OUT ss, IN ct, IN sk) - Decapsulate a key encapsulation message and recover the shared secret + * ss - plaintext shared secret + * ct - key encapsulation message (ciphertext) + * sk - secret key to use for decapsulation */ + +/* If s2n is compiled with support for PQ crypto, these functions will be defined in the respective KEM directories. + * If s2n is compiled without support for PQ, stubs of these functions are defined in s2n_kem.c. */ +/* sikep503r1 */ +#define SIKE_P503_R1_SECRET_KEY_BYTES 434 +#define SIKE_P503_R1_PUBLIC_KEY_BYTES 378 +#define SIKE_P503_R1_CIPHERTEXT_BYTES 402 +#define SIKE_P503_R1_SHARED_SECRET_BYTES 16 +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 */ +#define BIKE1_L1_R1_SECRET_KEY_BYTES 3110 +#define BIKE1_L1_R1_PUBLIC_KEY_BYTES 2542 +#define BIKE1_L1_R1_CIPHERTEXT_BYTES 2542 +#define BIKE1_L1_R1_SHARED_SECRET_BYTES 32 +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 */ +#define BIKE1_L1_R2_SECRET_KEY_BYTES 6460 +#define BIKE1_L1_R2_PUBLIC_KEY_BYTES 2946 +#define BIKE1_L1_R2_CIPHERTEXT_BYTES 2946 +#define BIKE1_L1_R2_SHARED_SECRET_BYTES 32 +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); + +/* 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 +#define KYBER_512_R2_CIPHERTEXT_BYTES 736 +#define KYBER_512_R2_SHARED_SECRET_BYTES 32 +int kyber_512_r2_crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk); +int kyber_512_r2_crypto_kem_enc(OUT unsigned char *ct, OUT unsigned char *ss, IN const unsigned char *pk); +int kyber_512_r2_crypto_kem_dec(OUT unsigned char *ss, IN const unsigned char *ct, IN const unsigned char *sk); +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); diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c index c725c242fe..4b9290c418 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c +++ b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.c @@ -1,138 +1,138 @@ -/* - * 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_kem_preferences.h" - -#if !defined(S2N_NO_PQ) - -/* Extension list for round 1 PQ KEMs, in order of preference */ -const struct s2n_kem *pq_kems_r1[2] = { - &s2n_bike1_l1_r1, - &s2n_sike_p503_r1, -}; - -/* Extension list for round 2 and round 1 PQ KEMs, in order of preference */ -const struct s2n_kem *pq_kems_r2r1[4] = { - &s2n_bike1_l1_r2, - &s2n_sike_p434_r2, - &s2n_bike1_l1_r1, - &s2n_sike_p503_r1, -}; - -const struct s2n_kem *pq_kems_r2r1_2020_07[5] = { - &s2n_kyber_512_r2, - &s2n_bike1_l1_r2, - &s2n_sike_p434_r2, - &s2n_bike1_l1_r1, - &s2n_sike_p503_r1, -}; - -/* Extension list for SIKE P503 Round 1 only (for testing) */ -const struct s2n_kem *pq_kems_sike_r1[1] = { - &s2n_sike_p503_r1, -}; - -/* Extension list for SIKE P434 Round 2 and SIKE P503 Round 1 only (for testing), - * in order of preference */ -const struct s2n_kem *pq_kems_sike_r2r1[2] = { - &s2n_sike_p434_r2, - &s2n_sike_p503_r1, -}; - -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, -#else - &s2n_secp256r1_kyber_512_r2, - &s2n_secp256r1_bike1_l1_r2, - &s2n_secp256r1_sike_p434_r2, -#endif -}; - -/* Includes only round 1 PQ KEM params */ -const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2019_06 = { - .kem_count = s2n_array_len(pq_kems_r1), - .kems = pq_kems_r1, - .tls13_kem_group_count = 0, - .tls13_kem_groups = NULL, -}; - -/* Includes round 1 and round 2 PQ KEM params. */ -const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2020_02 = { - .kem_count = s2n_array_len(pq_kems_r2r1), - .kems = pq_kems_r2r1, - .tls13_kem_group_count = 0, - .tls13_kem_groups = NULL, -}; - -const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2020_07 = { - .kem_count = s2n_array_len(pq_kems_r2r1_2020_07), - .kems = pq_kems_r2r1_2020_07, - .tls13_kem_group_count = 0, - .tls13_kem_groups = NULL, -}; - -/* Includes only SIKE round 1 (for integration tests) */ -const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2019_11 = { - .kem_count = s2n_array_len(pq_kems_sike_r1), - .kems = pq_kems_sike_r1, - .tls13_kem_group_count = 0, - .tls13_kem_groups = NULL, -}; - -/* Includes only SIKE round 1 and round 2 (for integration tests). */ -const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2020_02 = { - .kem_count = s2n_array_len(pq_kems_sike_r2r1), - .kems = pq_kems_sike_r2r1, - .tls13_kem_group_count = 0, - .tls13_kem_groups = NULL, -}; - -const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2020_12 = { - .kem_count = s2n_array_len(pq_kems_r2r1_2020_07), - .kems = pq_kems_r2r1_2020_07, - .tls13_kem_group_count = s2n_array_len(pq_kem_groups_r2), - .tls13_kem_groups = pq_kem_groups_r2, -}; - -#endif - -const struct s2n_kem_preferences kem_preferences_null = { - .kem_count = 0, - .kems = NULL, - .tls13_kem_group_count = 0, - .tls13_kem_groups = NULL, -}; - -/* Determines if query_iana_id corresponds to a tls13_kem_group for these KEM preferences. */ -bool s2n_kem_preferences_includes_tls13_kem_group(const struct s2n_kem_preferences *kem_preferences, - uint16_t query_iana_id) { - if (kem_preferences == NULL) { - return false; - } - - for (size_t i = 0; i < kem_preferences->tls13_kem_group_count; i++) { - if (query_iana_id == kem_preferences->tls13_kem_groups[i]->iana_id) { - return true; - } - } - - return false; -} +/* + * 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_kem_preferences.h" + +#if !defined(S2N_NO_PQ) + +/* Extension list for round 1 PQ KEMs, in order of preference */ +const struct s2n_kem *pq_kems_r1[2] = { + &s2n_bike1_l1_r1, + &s2n_sike_p503_r1, +}; + +/* Extension list for round 2 and round 1 PQ KEMs, in order of preference */ +const struct s2n_kem *pq_kems_r2r1[4] = { + &s2n_bike1_l1_r2, + &s2n_sike_p434_r2, + &s2n_bike1_l1_r1, + &s2n_sike_p503_r1, +}; + +const struct s2n_kem *pq_kems_r2r1_2020_07[5] = { + &s2n_kyber_512_r2, + &s2n_bike1_l1_r2, + &s2n_sike_p434_r2, + &s2n_bike1_l1_r1, + &s2n_sike_p503_r1, +}; + +/* Extension list for SIKE P503 Round 1 only (for testing) */ +const struct s2n_kem *pq_kems_sike_r1[1] = { + &s2n_sike_p503_r1, +}; + +/* Extension list for SIKE P434 Round 2 and SIKE P503 Round 1 only (for testing), + * in order of preference */ +const struct s2n_kem *pq_kems_sike_r2r1[2] = { + &s2n_sike_p434_r2, + &s2n_sike_p503_r1, +}; + +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, +#else + &s2n_secp256r1_kyber_512_r2, + &s2n_secp256r1_bike1_l1_r2, + &s2n_secp256r1_sike_p434_r2, +#endif +}; + +/* Includes only round 1 PQ KEM params */ +const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2019_06 = { + .kem_count = s2n_array_len(pq_kems_r1), + .kems = pq_kems_r1, + .tls13_kem_group_count = 0, + .tls13_kem_groups = NULL, +}; + +/* Includes round 1 and round 2 PQ KEM params. */ +const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2020_02 = { + .kem_count = s2n_array_len(pq_kems_r2r1), + .kems = pq_kems_r2r1, + .tls13_kem_group_count = 0, + .tls13_kem_groups = NULL, +}; + +const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2020_07 = { + .kem_count = s2n_array_len(pq_kems_r2r1_2020_07), + .kems = pq_kems_r2r1_2020_07, + .tls13_kem_group_count = 0, + .tls13_kem_groups = NULL, +}; + +/* Includes only SIKE round 1 (for integration tests) */ +const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2019_11 = { + .kem_count = s2n_array_len(pq_kems_sike_r1), + .kems = pq_kems_sike_r1, + .tls13_kem_group_count = 0, + .tls13_kem_groups = NULL, +}; + +/* Includes only SIKE round 1 and round 2 (for integration tests). */ +const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2020_02 = { + .kem_count = s2n_array_len(pq_kems_sike_r2r1), + .kems = pq_kems_sike_r2r1, + .tls13_kem_group_count = 0, + .tls13_kem_groups = NULL, +}; + +const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2020_12 = { + .kem_count = s2n_array_len(pq_kems_r2r1_2020_07), + .kems = pq_kems_r2r1_2020_07, + .tls13_kem_group_count = s2n_array_len(pq_kem_groups_r2), + .tls13_kem_groups = pq_kem_groups_r2, +}; + +#endif + +const struct s2n_kem_preferences kem_preferences_null = { + .kem_count = 0, + .kems = NULL, + .tls13_kem_group_count = 0, + .tls13_kem_groups = NULL, +}; + +/* Determines if query_iana_id corresponds to a tls13_kem_group for these KEM preferences. */ +bool s2n_kem_preferences_includes_tls13_kem_group(const struct s2n_kem_preferences *kem_preferences, + uint16_t query_iana_id) { + if (kem_preferences == NULL) { + return false; + } + + for (size_t i = 0; i < kem_preferences->tls13_kem_group_count; i++) { + if (query_iana_id == kem_preferences->tls13_kem_groups[i]->iana_id) { + return true; + } + } + + return false; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h index e62c60ec8a..e6226bb8f3 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h +++ b/contrib/restricted/aws/s2n/tls/s2n_kem_preferences.h @@ -1,54 +1,54 @@ -/* - * 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 <stdbool.h> -#include "tls/s2n_kem.h" -#include "tls/s2n_kex.h" - -struct s2n_kem_preferences { - /* kems used for hybrid TLS 1.2 */ - uint8_t kem_count; - const struct s2n_kem **kems; - - /* tls13_kem_groups used for hybrid TLS 1.3 */ - uint8_t tls13_kem_group_count; - const struct s2n_kem_group **tls13_kem_groups; -}; - -#if !defined(S2N_NO_PQ) - -extern const struct s2n_kem *pq_kems_r1[2]; -extern const struct s2n_kem *pq_kems_r2r1[4]; -extern const struct s2n_kem *pq_kems_r2r1_2020_07[5]; -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_group *pq_kem_groups_r2[]; - -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; -extern const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2020_07; -extern const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2019_11; -extern const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2020_02; -extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2020_12; - -#endif - -extern const struct s2n_kem_preferences kem_preferences_null; - -bool s2n_kem_preferences_includes_tls13_kem_group(const struct s2n_kem_preferences *kem_preferences, - uint16_t query_iana_id); +/* + * 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 <stdbool.h> +#include "tls/s2n_kem.h" +#include "tls/s2n_kex.h" + +struct s2n_kem_preferences { + /* kems used for hybrid TLS 1.2 */ + uint8_t kem_count; + const struct s2n_kem **kems; + + /* tls13_kem_groups used for hybrid TLS 1.3 */ + uint8_t tls13_kem_group_count; + const struct s2n_kem_group **tls13_kem_groups; +}; + +#if !defined(S2N_NO_PQ) + +extern const struct s2n_kem *pq_kems_r1[2]; +extern const struct s2n_kem *pq_kems_r2r1[4]; +extern const struct s2n_kem *pq_kems_r2r1_2020_07[5]; +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_group *pq_kem_groups_r2[]; + +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; +extern const struct s2n_kem_preferences kem_preferences_kms_pq_tls_1_0_2020_07; +extern const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2019_11; +extern const struct s2n_kem_preferences kem_preferences_pq_sike_test_tls_1_0_2020_02; +extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2020_12; + +#endif + +extern const struct s2n_kem_preferences kem_preferences_null; + +bool s2n_kem_preferences_includes_tls13_kem_group(const struct s2n_kem_preferences *kem_preferences, + uint16_t query_iana_id); diff --git a/contrib/restricted/aws/s2n/tls/s2n_kex.c b/contrib/restricted/aws/s2n/tls/s2n_kex.c index 4b6f9e9435..d01a25faef 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kex.c +++ b/contrib/restricted/aws/s2n/tls/s2n_kex.c @@ -1,257 +1,257 @@ -/* - * 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_kex.h" -#include "crypto/s2n_fips.h" -#include "tls/s2n_cipher_preferences.h" -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_client_key_exchange.h" -#include "tls/s2n_kem.h" -#include "tls/s2n_security_policies.h" -#include "tls/s2n_server_key_exchange.h" -#include "tls/s2n_tls.h" -#include "utils/s2n_safety.h" - -static int s2n_check_rsa_key(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) -{ - return s2n_get_compatible_cert_chain_and_key(conn, S2N_PKEY_TYPE_RSA) != NULL; -} - -static int s2n_check_dhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) -{ - return conn->config->dhparams != NULL; -} - -static int s2n_check_ecdhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) -{ - return conn->secure.server_ecc_evp_params.negotiated_curve != NULL; -} - -static int s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) -{ - notnull_check(conn); - /* There is no support for PQ KEMs while in FIPS mode */ - if (s2n_is_in_fips_mode()) { - return 0; - } - - const struct s2n_kem_preferences *kem_preferences = NULL; - GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences)); - notnull_check(kem_preferences); - - if (kem_preferences->kem_count == 0) { - return 0; - } - - const struct s2n_iana_to_kem *supported_params = NULL; - /* If the cipher suite has no supported KEMs return false */ - if (s2n_cipher_suite_to_kem(cipher_suite->iana_value, &supported_params) != 0) { - return 0; - } - if (supported_params->kem_count == 0) { - return 0; - } - - struct s2n_blob *client_kem_pref_list = &(conn->secure.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 */ - if (s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems, - kem_preferences->kem_count, &chosen_kem) - != 0) { - return 0; - } - } else { - /* If the client did send a PQ KEM extension, then the server must find a mutually supported parameter. */ - if (s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, client_kem_pref_list, kem_preferences->kems, - kem_preferences->kem_count, &chosen_kem) - != 0) { - return 0; - } - } - - return chosen_kem != NULL; -} - -static int s2n_configure_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) -{ - notnull_check(conn); - /* There is no support for PQ KEMs while in FIPS mode */ - S2N_ERROR_IF(s2n_is_in_fips_mode(), S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); - - const struct s2n_kem_preferences *kem_preferences = NULL; - GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences)); - notnull_check(kem_preferences); - - struct s2n_blob *proposed_kems = &(conn->secure.client_pq_kem_extension); - const struct s2n_kem *chosen_kem = NULL; - if (proposed_kems == NULL || proposed_kems->data == NULL) { - /* If the client did not send a PQ KEM extension, then the server can pick its preferred parameter */ - GUARD(s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems, - kem_preferences->kem_count, &chosen_kem)); - } else { - /* If the client did send a PQ KEM extension, then the server must find a mutually supported parameter. */ - GUARD(s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, proposed_kems, kem_preferences->kems, - kem_preferences->kem_count, &chosen_kem)); - } - - conn->secure.kem_params.kem = chosen_kem; - return 0; -} - -static int s2n_no_op_configure(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) -{ - return 0; -} - -static int s2n_check_hybrid_ecdhe_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) -{ - return s2n_check_ecdhe(cipher_suite, conn) && s2n_check_kem(cipher_suite, conn); -} - -const struct s2n_kex s2n_kem = { - .is_ephemeral = 1, - .connection_supported = &s2n_check_kem, - .configure_connection = &s2n_configure_kem, - .server_key_recv_read_data = &s2n_kem_server_key_recv_read_data, - .server_key_recv_parse_data = &s2n_kem_server_key_recv_parse_data, - .server_key_send = &s2n_kem_server_key_send, - .client_key_recv = &s2n_kem_client_key_recv, - .client_key_send = &s2n_kem_client_key_send, -}; - -const struct s2n_kex s2n_rsa = { - .is_ephemeral = 0, - .connection_supported = &s2n_check_rsa_key, - .configure_connection = &s2n_no_op_configure, - .server_key_recv_read_data = NULL, - .server_key_recv_parse_data = NULL, - .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, -}; - -const struct s2n_kex s2n_dhe = { - .is_ephemeral = 1, - .connection_supported = &s2n_check_dhe, - .configure_connection = &s2n_no_op_configure, - .server_key_recv_read_data = &s2n_dhe_server_key_recv_read_data, - .server_key_recv_parse_data = &s2n_dhe_server_key_recv_parse_data, - .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, -}; - -const struct s2n_kex s2n_ecdhe = { - .is_ephemeral = 1, - .connection_supported = &s2n_check_ecdhe, - .configure_connection = &s2n_no_op_configure, - .server_key_recv_read_data = &s2n_ecdhe_server_key_recv_read_data, - .server_key_recv_parse_data = &s2n_ecdhe_server_key_recv_parse_data, - .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, -}; - -const struct s2n_kex s2n_hybrid_ecdhe_kem = { - .is_ephemeral = 1, - .hybrid = { &s2n_ecdhe, &s2n_kem }, - .connection_supported = &s2n_check_hybrid_ecdhe_kem, - .configure_connection = &s2n_configure_kem, - .server_key_recv_read_data = &s2n_hybrid_server_key_recv_read_data, - .server_key_recv_parse_data = &s2n_hybrid_server_key_recv_parse_data, - .server_key_send = &s2n_hybrid_server_key_send, - .client_key_recv = &s2n_hybrid_client_key_recv, - .client_key_send = &s2n_hybrid_client_key_send, - .prf = &s2n_hybrid_prf_master_secret, -}; - -int s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) -{ - /* Don't return -1 from notnull_check because that might allow a improperly configured kex to be marked as "supported" */ - return cipher_suite->key_exchange_alg->connection_supported != NULL && cipher_suite->key_exchange_alg->connection_supported(cipher_suite, conn); -} - -int s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) -{ - notnull_check(cipher_suite); - notnull_check(cipher_suite->key_exchange_alg); - notnull_check(cipher_suite->key_exchange_alg->configure_connection); - return cipher_suite->key_exchange_alg->configure_connection(cipher_suite, conn); -} - -int s2n_kex_is_ephemeral(const struct s2n_kex *kex) -{ - notnull_check(kex); - return kex->is_ephemeral; -} - -int s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data) -{ - notnull_check(kex); - notnull_check(kex->server_key_recv_parse_data); - return kex->server_key_recv_parse_data(conn, raw_server_data); -} - -int s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data) -{ - notnull_check(kex); - notnull_check(kex->server_key_recv_read_data); - return kex->server_key_recv_read_data(conn, data_to_verify, raw_server_data); -} - -int s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign) -{ - notnull_check(kex); - notnull_check(kex->server_key_send); - return kex->server_key_send(conn, data_to_sign); -} - -int s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key) -{ - notnull_check(kex); - notnull_check(kex->client_key_recv); - return kex->client_key_recv(conn, shared_key); -} - -int s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key) -{ - notnull_check(kex); - notnull_check(kex->client_key_send); - return kex->client_key_send(conn, shared_key); -} - -int s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret) -{ - notnull_check(kex); - notnull_check(kex->prf); - return kex->prf(conn, premaster_secret); -} - -bool s2n_kex_includes(const struct s2n_kex *kex, const struct s2n_kex *query) -{ - if (kex == query) { - return true; - } - - if (kex == NULL || query == NULL) { - return false; - } - - return query == kex->hybrid[0] || query == kex->hybrid[1]; -} +/* + * 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_kex.h" +#include "crypto/s2n_fips.h" +#include "tls/s2n_cipher_preferences.h" +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_client_key_exchange.h" +#include "tls/s2n_kem.h" +#include "tls/s2n_security_policies.h" +#include "tls/s2n_server_key_exchange.h" +#include "tls/s2n_tls.h" +#include "utils/s2n_safety.h" + +static int s2n_check_rsa_key(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +{ + return s2n_get_compatible_cert_chain_and_key(conn, S2N_PKEY_TYPE_RSA) != NULL; +} + +static int s2n_check_dhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +{ + return conn->config->dhparams != NULL; +} + +static int s2n_check_ecdhe(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +{ + return conn->secure.server_ecc_evp_params.negotiated_curve != NULL; +} + +static int s2n_check_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +{ + notnull_check(conn); + /* There is no support for PQ KEMs while in FIPS mode */ + if (s2n_is_in_fips_mode()) { + return 0; + } + + const struct s2n_kem_preferences *kem_preferences = NULL; + GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences)); + notnull_check(kem_preferences); + + if (kem_preferences->kem_count == 0) { + return 0; + } + + const struct s2n_iana_to_kem *supported_params = NULL; + /* If the cipher suite has no supported KEMs return false */ + if (s2n_cipher_suite_to_kem(cipher_suite->iana_value, &supported_params) != 0) { + return 0; + } + if (supported_params->kem_count == 0) { + return 0; + } + + struct s2n_blob *client_kem_pref_list = &(conn->secure.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 */ + if (s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems, + kem_preferences->kem_count, &chosen_kem) + != 0) { + return 0; + } + } else { + /* If the client did send a PQ KEM extension, then the server must find a mutually supported parameter. */ + if (s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, client_kem_pref_list, kem_preferences->kems, + kem_preferences->kem_count, &chosen_kem) + != 0) { + return 0; + } + } + + return chosen_kem != NULL; +} + +static int s2n_configure_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +{ + notnull_check(conn); + /* There is no support for PQ KEMs while in FIPS mode */ + S2N_ERROR_IF(s2n_is_in_fips_mode(), S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + + const struct s2n_kem_preferences *kem_preferences = NULL; + GUARD(s2n_connection_get_kem_preferences(conn, &kem_preferences)); + notnull_check(kem_preferences); + + struct s2n_blob *proposed_kems = &(conn->secure.client_pq_kem_extension); + const struct s2n_kem *chosen_kem = NULL; + if (proposed_kems == NULL || proposed_kems->data == NULL) { + /* If the client did not send a PQ KEM extension, then the server can pick its preferred parameter */ + GUARD(s2n_choose_kem_without_peer_pref_list(cipher_suite->iana_value, kem_preferences->kems, + kem_preferences->kem_count, &chosen_kem)); + } else { + /* If the client did send a PQ KEM extension, then the server must find a mutually supported parameter. */ + GUARD(s2n_choose_kem_with_peer_pref_list(cipher_suite->iana_value, proposed_kems, kem_preferences->kems, + kem_preferences->kem_count, &chosen_kem)); + } + + conn->secure.kem_params.kem = chosen_kem; + return 0; +} + +static int s2n_no_op_configure(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +{ + return 0; +} + +static int s2n_check_hybrid_ecdhe_kem(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +{ + return s2n_check_ecdhe(cipher_suite, conn) && s2n_check_kem(cipher_suite, conn); +} + +const struct s2n_kex s2n_kem = { + .is_ephemeral = 1, + .connection_supported = &s2n_check_kem, + .configure_connection = &s2n_configure_kem, + .server_key_recv_read_data = &s2n_kem_server_key_recv_read_data, + .server_key_recv_parse_data = &s2n_kem_server_key_recv_parse_data, + .server_key_send = &s2n_kem_server_key_send, + .client_key_recv = &s2n_kem_client_key_recv, + .client_key_send = &s2n_kem_client_key_send, +}; + +const struct s2n_kex s2n_rsa = { + .is_ephemeral = 0, + .connection_supported = &s2n_check_rsa_key, + .configure_connection = &s2n_no_op_configure, + .server_key_recv_read_data = NULL, + .server_key_recv_parse_data = NULL, + .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, +}; + +const struct s2n_kex s2n_dhe = { + .is_ephemeral = 1, + .connection_supported = &s2n_check_dhe, + .configure_connection = &s2n_no_op_configure, + .server_key_recv_read_data = &s2n_dhe_server_key_recv_read_data, + .server_key_recv_parse_data = &s2n_dhe_server_key_recv_parse_data, + .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, +}; + +const struct s2n_kex s2n_ecdhe = { + .is_ephemeral = 1, + .connection_supported = &s2n_check_ecdhe, + .configure_connection = &s2n_no_op_configure, + .server_key_recv_read_data = &s2n_ecdhe_server_key_recv_read_data, + .server_key_recv_parse_data = &s2n_ecdhe_server_key_recv_parse_data, + .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, +}; + +const struct s2n_kex s2n_hybrid_ecdhe_kem = { + .is_ephemeral = 1, + .hybrid = { &s2n_ecdhe, &s2n_kem }, + .connection_supported = &s2n_check_hybrid_ecdhe_kem, + .configure_connection = &s2n_configure_kem, + .server_key_recv_read_data = &s2n_hybrid_server_key_recv_read_data, + .server_key_recv_parse_data = &s2n_hybrid_server_key_recv_parse_data, + .server_key_send = &s2n_hybrid_server_key_send, + .client_key_recv = &s2n_hybrid_client_key_recv, + .client_key_send = &s2n_hybrid_client_key_send, + .prf = &s2n_hybrid_prf_master_secret, +}; + +int s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +{ + /* Don't return -1 from notnull_check because that might allow a improperly configured kex to be marked as "supported" */ + return cipher_suite->key_exchange_alg->connection_supported != NULL && cipher_suite->key_exchange_alg->connection_supported(cipher_suite, conn); +} + +int s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn) +{ + notnull_check(cipher_suite); + notnull_check(cipher_suite->key_exchange_alg); + notnull_check(cipher_suite->key_exchange_alg->configure_connection); + return cipher_suite->key_exchange_alg->configure_connection(cipher_suite, conn); +} + +int s2n_kex_is_ephemeral(const struct s2n_kex *kex) +{ + notnull_check(kex); + return kex->is_ephemeral; +} + +int s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data) +{ + notnull_check(kex); + notnull_check(kex->server_key_recv_parse_data); + return kex->server_key_recv_parse_data(conn, raw_server_data); +} + +int s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data) +{ + notnull_check(kex); + notnull_check(kex->server_key_recv_read_data); + return kex->server_key_recv_read_data(conn, data_to_verify, raw_server_data); +} + +int s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign) +{ + notnull_check(kex); + notnull_check(kex->server_key_send); + return kex->server_key_send(conn, data_to_sign); +} + +int s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key) +{ + notnull_check(kex); + notnull_check(kex->client_key_recv); + return kex->client_key_recv(conn, shared_key); +} + +int s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key) +{ + notnull_check(kex); + notnull_check(kex->client_key_send); + return kex->client_key_send(conn, shared_key); +} + +int s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret) +{ + notnull_check(kex); + notnull_check(kex->prf); + return kex->prf(conn, premaster_secret); +} + +bool s2n_kex_includes(const struct s2n_kex *kex, const struct s2n_kex *query) +{ + if (kex == query) { + return true; + } + + if (kex == NULL || query == NULL) { + return false; + } + + return query == kex->hybrid[0] || query == kex->hybrid[1]; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_kex.h b/contrib/restricted/aws/s2n/tls/s2n_kex.h index f168df5384..587cde5d63 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kex.h +++ b/contrib/restricted/aws/s2n/tls/s2n_kex.h @@ -1,55 +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 <stdint.h> -#include "tls/s2n_connection.h" -#include "tls/s2n_kex_data.h" - -struct s2n_kex { - uint8_t is_ephemeral; - const struct s2n_kex *hybrid[2]; - - int (*connection_supported)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); - int (*configure_connection)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); - int (*server_key_recv_read_data)(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *kex_data); - int (*server_key_recv_parse_data)(struct s2n_connection *conn, struct s2n_kex_raw_server_data *kex_data); - int (*server_key_send)(struct s2n_connection *conn, struct s2n_blob *data_to_sign); - int (*client_key_recv)(struct s2n_connection *conn, struct s2n_blob *shared_key); - int (*client_key_send)(struct s2n_connection *conn, struct s2n_blob *shared_key); - int (*prf)(struct s2n_connection *conn, struct s2n_blob *premaster_secret); -}; - -extern const struct s2n_kex s2n_kem; -extern const struct s2n_kex s2n_rsa; -extern const struct s2n_kex s2n_dhe; -extern const struct s2n_kex s2n_ecdhe; -extern const struct s2n_kex s2n_hybrid_ecdhe_kem; - -extern int s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); -extern int s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); -extern int s2n_kex_is_ephemeral(const struct s2n_kex *kex); - -extern int s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify, - struct s2n_kex_raw_server_data *raw_server_data); -extern int s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); -extern int s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign); -extern int s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); -extern int s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); - -extern int s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret); - -extern bool s2n_kex_includes(const struct s2n_kex *kex, const struct s2n_kex *query); +/* + * 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 <stdint.h> +#include "tls/s2n_connection.h" +#include "tls/s2n_kex_data.h" + +struct s2n_kex { + uint8_t is_ephemeral; + const struct s2n_kex *hybrid[2]; + + int (*connection_supported)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); + int (*configure_connection)(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); + int (*server_key_recv_read_data)(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *kex_data); + int (*server_key_recv_parse_data)(struct s2n_connection *conn, struct s2n_kex_raw_server_data *kex_data); + int (*server_key_send)(struct s2n_connection *conn, struct s2n_blob *data_to_sign); + int (*client_key_recv)(struct s2n_connection *conn, struct s2n_blob *shared_key); + int (*client_key_send)(struct s2n_connection *conn, struct s2n_blob *shared_key); + int (*prf)(struct s2n_connection *conn, struct s2n_blob *premaster_secret); +}; + +extern const struct s2n_kex s2n_kem; +extern const struct s2n_kex s2n_rsa; +extern const struct s2n_kex s2n_dhe; +extern const struct s2n_kex s2n_ecdhe; +extern const struct s2n_kex s2n_hybrid_ecdhe_kem; + +extern int s2n_kex_supported(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); +extern int s2n_configure_kex(const struct s2n_cipher_suite *cipher_suite, struct s2n_connection *conn); +extern int s2n_kex_is_ephemeral(const struct s2n_kex *kex); + +extern int s2n_kex_server_key_recv_read_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_verify, + struct s2n_kex_raw_server_data *raw_server_data); +extern int s2n_kex_server_key_recv_parse_data(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); +extern int s2n_kex_server_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *data_to_sign); +extern int s2n_kex_client_key_recv(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); +extern int s2n_kex_client_key_send(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *shared_key); + +extern int s2n_kex_tls_prf(const struct s2n_kex *kex, struct s2n_connection *conn, struct s2n_blob *premaster_secret); + +extern bool s2n_kex_includes(const struct s2n_kex *kex, const struct s2n_kex *query); diff --git a/contrib/restricted/aws/s2n/tls/s2n_kex_data.h b/contrib/restricted/aws/s2n/tls/s2n_kex_data.h index 9a202d3da6..425f427a27 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_kex_data.h +++ b/contrib/restricted/aws/s2n/tls/s2n_kex_data.h @@ -1,40 +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. - */ - -#pragma once - -#include "utils/s2n_blob.h" - -struct s2n_ecdhe_raw_server_params { - struct s2n_blob point_blob; - struct s2n_blob curve_blob; -}; - -struct s2n_dhe_raw_server_points { - struct s2n_blob p; - struct s2n_blob g; - struct s2n_blob Ys; -}; - -struct s2n_kem_raw_server_params { - struct s2n_blob kem_name; - struct s2n_blob raw_public_key; -}; - -struct s2n_kex_raw_server_data { - struct s2n_ecdhe_raw_server_params ecdhe_data; - struct s2n_dhe_raw_server_points dhe_data; - struct s2n_kem_raw_server_params kem_data; -}; +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "utils/s2n_blob.h" + +struct s2n_ecdhe_raw_server_params { + struct s2n_blob point_blob; + struct s2n_blob curve_blob; +}; + +struct s2n_dhe_raw_server_points { + struct s2n_blob p; + struct s2n_blob g; + struct s2n_blob Ys; +}; + +struct s2n_kem_raw_server_params { + struct s2n_blob kem_name; + struct s2n_blob raw_public_key; +}; + +struct s2n_kex_raw_server_data { + struct s2n_ecdhe_raw_server_params ecdhe_data; + struct s2n_dhe_raw_server_points dhe_data; + struct s2n_kem_raw_server_params kem_data; +}; diff --git a/contrib/restricted/aws/s2n/tls/s2n_key_update.c b/contrib/restricted/aws/s2n/tls/s2n_key_update.c index 02e5cf9978..6f63e02b38 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_key_update.c +++ b/contrib/restricted/aws/s2n/tls/s2n_key_update.c @@ -1,115 +1,115 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "error/s2n_errno.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_key_update.h" -#include "tls/s2n_tls13_handshake.h" -#include "tls/s2n_record.h" - -#include "crypto/s2n_sequence.h" - -#include "utils/s2n_safety.h" - -int s2n_key_update_write(struct s2n_blob *out); -int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequence_number); - - -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); - - uint8_t key_update_request; - 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)); - } else { - GUARD(s2n_update_application_traffic_keys(conn, S2N_CLIENT, RECEIVING)); - } - - return S2N_SUCCESS; -} - -int s2n_key_update_send(struct s2n_connection *conn) -{ - notnull_check(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)); - } else { - GUARD(s2n_blob_init(&sequence_number, conn->secure.server_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN)); - } - - 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))); - - /* Write key update message */ - GUARD(s2n_key_update_write(&key_update_blob)); - - /* Encrypt the message */ - GUARD(s2n_record_write(conn, TLS_HANDSHAKE, &key_update_blob)); - - /* Update encryption key */ - GUARD(s2n_update_application_traffic_keys(conn, conn->mode, SENDING)); - conn->key_update_pending = false; - } - - return S2N_SUCCESS; -} - -int s2n_key_update_write(struct s2n_blob *out) -{ - notnull_check(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)); - - /* s2n currently does not require peers to update their encryption keys. */ - 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); - - uint64_t output = 0; - 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; - } - - return S2N_SUCCESS; -} - +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "error/s2n_errno.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_key_update.h" +#include "tls/s2n_tls13_handshake.h" +#include "tls/s2n_record.h" + +#include "crypto/s2n_sequence.h" + +#include "utils/s2n_safety.h" + +int s2n_key_update_write(struct s2n_blob *out); +int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequence_number); + + +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); + + uint8_t key_update_request; + 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)); + } else { + GUARD(s2n_update_application_traffic_keys(conn, S2N_CLIENT, RECEIVING)); + } + + return S2N_SUCCESS; +} + +int s2n_key_update_send(struct s2n_connection *conn) +{ + notnull_check(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)); + } else { + GUARD(s2n_blob_init(&sequence_number, conn->secure.server_sequence_number, S2N_TLS_SEQUENCE_NUM_LEN)); + } + + 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))); + + /* Write key update message */ + GUARD(s2n_key_update_write(&key_update_blob)); + + /* Encrypt the message */ + GUARD(s2n_record_write(conn, TLS_HANDSHAKE, &key_update_blob)); + + /* Update encryption key */ + GUARD(s2n_update_application_traffic_keys(conn, conn->mode, SENDING)); + conn->key_update_pending = false; + } + + return S2N_SUCCESS; +} + +int s2n_key_update_write(struct s2n_blob *out) +{ + notnull_check(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)); + + /* s2n currently does not require peers to update their encryption keys. */ + 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); + + uint64_t output = 0; + 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; + } + + return S2N_SUCCESS; +} + diff --git a/contrib/restricted/aws/s2n/tls/s2n_key_update.h b/contrib/restricted/aws/s2n/tls/s2n_key_update.h index 2eaa69a5f8..20ac48411c 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_key_update.h +++ b/contrib/restricted/aws/s2n/tls/s2n_key_update.h @@ -1,34 +1,34 @@ -/* - * 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_connection.h" - -#define S2N_KEY_UPDATE_MESSAGE_SIZE 5 -#define S2N_KEY_UPDATE_LENGTH 1 - -typedef enum { - SENDING=0, - RECEIVING -} keyupdate_status; - -typedef enum { - S2N_KEY_UPDATE_NOT_REQUESTED=0, - S2N_KEY_UPDATE_REQUESTED -} keyupdate_request; - -int s2n_key_update_recv(struct s2n_connection *conn, struct s2n_stuffer *request); -int s2n_key_update_send(struct s2n_connection *conn); +/* + * 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_connection.h" + +#define S2N_KEY_UPDATE_MESSAGE_SIZE 5 +#define S2N_KEY_UPDATE_LENGTH 1 + +typedef enum { + SENDING=0, + RECEIVING +} keyupdate_status; + +typedef enum { + S2N_KEY_UPDATE_NOT_REQUESTED=0, + S2N_KEY_UPDATE_REQUESTED +} keyupdate_request; + +int s2n_key_update_recv(struct s2n_connection *conn, struct s2n_stuffer *request); +int s2n_key_update_send(struct s2n_connection *conn); diff --git a/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c b/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c index f04b7b40e4..7ad96a4d31 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c +++ b/contrib/restricted/aws/s2n/tls/s2n_ocsp_stapling.c @@ -1,40 +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 <strings.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_config.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_x509_validator.h" -#include "tls/extensions/s2n_server_certificate_status.h" -#include "utils/s2n_safety.h" - -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)); - } - - return 0; -} - -int s2n_server_status_recv(struct s2n_connection *conn) -{ - return s2n_server_certificate_status_recv(conn, &conn->handshake.io); -} +/* + * 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 <strings.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_config.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_x509_validator.h" +#include "tls/extensions/s2n_server_certificate_status.h" +#include "utils/s2n_safety.h" + +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)); + } + + return 0; +} + +int s2n_server_status_recv(struct s2n_connection *conn) +{ + return s2n_server_certificate_status_recv(conn, &conn->handshake.io); +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c index d5ba4ab672..34594576db 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c +++ b/contrib/restricted/aws/s2n/tls/s2n_post_handshake.c @@ -1,69 +1,69 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "error/s2n_errno.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_key_update.h" -#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); - - 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)); - - 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_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)); - - switch (post_handshake_id) - { - case TLS_KEY_UPDATE: - GUARD(s2n_key_update_recv(conn, &post_handshake_stuffer)); - break; - default: - /* Ignore all other messages */ - break; - } - - return S2N_SUCCESS; -} - -int s2n_post_handshake_send(struct s2n_connection *conn, s2n_blocked_status *blocked) -{ - notnull_check(conn); - - GUARD(s2n_key_update_send(conn)); - GUARD(s2n_flush(conn, blocked)); - GUARD(s2n_stuffer_rewrite(&conn->out)); - - return S2N_SUCCESS; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "error/s2n_errno.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_key_update.h" +#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); + + 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)); + + 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_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)); + + switch (post_handshake_id) + { + case TLS_KEY_UPDATE: + GUARD(s2n_key_update_recv(conn, &post_handshake_stuffer)); + break; + default: + /* Ignore all other messages */ + break; + } + + return S2N_SUCCESS; +} + +int s2n_post_handshake_send(struct s2n_connection *conn, s2n_blocked_status *blocked) +{ + notnull_check(conn); + + GUARD(s2n_key_update_send(conn)); + GUARD(s2n_flush(conn, blocked)); + GUARD(s2n_stuffer_rewrite(&conn->out)); + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_post_handshake.h b/contrib/restricted/aws/s2n/tls/s2n_post_handshake.h index b2c646c367..f021f7afb5 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_post_handshake.h +++ b/contrib/restricted/aws/s2n/tls/s2n_post_handshake.h @@ -1,21 +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/s2n_connection.h" - -int s2n_post_handshake_recv(struct s2n_connection *conn); -int s2n_post_handshake_send(struct s2n_connection *conn, s2n_blocked_status *blocked); +/* + * 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_connection.h" + +int s2n_post_handshake_recv(struct s2n_connection *conn); +int s2n_post_handshake_send(struct s2n_connection *conn, s2n_blocked_status *blocked); diff --git a/contrib/restricted/aws/s2n/tls/s2n_prf.c b/contrib/restricted/aws/s2n/tls/s2n_prf.c index ebf6273880..fbfffb5fad 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_prf.c +++ b/contrib/restricted/aws/s2n/tls/s2n_prf.c @@ -1,692 +1,692 @@ -/* - * 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 <openssl/md5.h> -#include <openssl/sha.h> -#include <string.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_prf.h" - -#include "stuffer/s2n_stuffer.h" - -#include "crypto/s2n_hmac.h" -#include "crypto/s2n_hash.h" -#include "crypto/s2n_openssl.h" -#include "crypto/s2n_fips.h" - -#include "utils/s2n_safety.h" -#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, - 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; - - uint32_t outputlen = out->size; - uint8_t *output = out->data; - uint8_t iteration = 1; - - uint8_t A = 'A'; - while (outputlen) { - GUARD(s2n_hash_reset(sha1)); - - for (int i = 0; i < iteration; i++) { - 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)); - - if (seed_b) { - 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)); - } - } - - GUARD(s2n_hash_digest(sha1, ws->ssl3.sha1_digest, sizeof(ws->ssl3.sha1_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))); - - uint32_t bytes_to_copy = MIN(outputlen, sizeof(ws->ssl3.md5_digest)); - - memcpy_check(output, ws->ssl3.md5_digest, bytes_to_copy); - - outputlen -= bytes_to_copy; - output += bytes_to_copy; - - /* Increment the letter */ - A++; - iteration++; - } - - GUARD(s2n_hash_reset(md5)); - GUARD(s2n_hash_reset(sha1)); - - return 0; -} - -#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC) -static int s2n_evp_hmac_p_hash_new(struct s2n_prf_working_space *ws) -{ - notnull_check(ws->tls.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) -{ - 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); - - /* 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)); - } - - 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), - 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) -{ - /* 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); - } - - /* 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)); - - /* Initialize the message digest context with the above message digest and mac key */ - return s2n_evp_hmac_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) -{ - GUARD_OSSL(EVP_DigestSignUpdate(ws->tls.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) -{ - /* 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); - - return 0; -} - -static int s2n_evp_hmac_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); - - return 0; -} - -static int s2n_evp_hmac_p_hash_reset(struct s2n_prf_working_space *ws) -{ - GUARD(s2n_evp_hmac_p_hash_wipe(ws)); - - return s2n_evp_hmac_p_hash_digest_init(ws); -} - -static int s2n_evp_hmac_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)); - - /* 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; - - return 0; -} - -static int s2n_evp_hmac_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; - - return 0; -} - -static const struct s2n_p_hash_hmac s2n_evp_hmac = { - .alloc = &s2n_evp_hmac_p_hash_new, - .init = &s2n_evp_hmac_p_hash_init, - .update = &s2n_evp_hmac_p_hash_update, - .final = &s2n_evp_hmac_p_hash_digest, - .reset = &s2n_evp_hmac_p_hash_reset, - .cleanup = &s2n_evp_hmac_p_hash_cleanup, - .free = &s2n_evp_hmac_p_hash_free, -}; -#endif /* !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC) */ - -static int s2n_hmac_p_hash_new(struct s2n_prf_working_space *ws) -{ - GUARD(s2n_hmac_new(&ws->tls.p_hash.s2n_hmac)); - - return s2n_hmac_init(&ws->tls.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); -} - -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); -} - -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); -} - -static int s2n_hmac_p_hash_reset(struct s2n_prf_working_space *ws) -{ - return s2n_hmac_reset(&ws->tls.p_hash.s2n_hmac); -} - -static int s2n_hmac_p_hash_cleanup(struct s2n_prf_working_space *ws) -{ - return s2n_hmac_p_hash_reset(ws); -} - -static int s2n_hmac_p_hash_free(struct s2n_prf_working_space *ws) -{ - return s2n_hmac_free(&ws->tls.p_hash.s2n_hmac); -} - -static const struct s2n_p_hash_hmac s2n_hmac = { - .alloc = &s2n_hmac_p_hash_new, - .init = &s2n_hmac_p_hash_init, - .update = &s2n_hmac_p_hash_update, - .final = &s2n_hmac_p_hash_digest, - .reset = &s2n_hmac_p_hash_reset, - .cleanup = &s2n_hmac_p_hash_cleanup, - .free = &s2n_hmac_p_hash_free, -}; - -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)); - - const struct s2n_p_hash_hmac *hmac = ws->tls.p_hash_hmac_impl; - - /* 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)); - - if (seed_b) { - GUARD(hmac->update(ws, seed_b->data, seed_b->size)); - if (seed_c) { - GUARD(hmac->update(ws, seed_c->data, seed_c->size)); - } - } - GUARD(hmac->final(ws, ws->tls.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)); - - /* 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)); - if (seed_b) { - GUARD(hmac->update(ws, seed_b->data, seed_b->size)); - if (seed_c) { - GUARD(hmac->update(ws, seed_c->data, seed_c->size)); - } - } - - GUARD(hmac->final(ws, ws->tls.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]; - 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)); - } - - 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 -} - -int s2n_prf_new(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(); - - return conn->prf_space.tls.p_hash_hmac_impl->alloc(&conn->prf_space); -} - -int 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(); - - return conn->prf_space.tls.p_hash_hmac_impl->free(&conn->prf_space); -} - -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) -{ - /* 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); - } - - /* We zero the out blob because p_hash works by XOR'ing with the existing - * buffer. This is a little convoluted but means we can avoid dynamic memory - * allocation. When we call p_hash once (in the TLS1.2 case) it will produce - * the right values. When we call it twice in the regular case, the two - * outputs will be XORd just ass the TLS 1.0 and 1.1 RFCs require. - */ - 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(); - - if (conn->actual_protocol_version == S2N_TLS12) { - return s2n_p_hash(&conn->prf_space, conn->secure.cipher_suite->prf_alg, secret, label, seed_a, seed_b, - seed_c, out); - } - - 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)); - 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)); - - 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}; - - uint8_t master_secret_label[] = "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, NULL, &master_secret); -} - -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}; - - 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); -} - -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) -{ - 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 - }; - uint8_t xorpad2[48] = - { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c - }; - 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)); - - return 0; -} - -static int s2n_sslv3_client_finished(struct s2n_connection *conn) -{ - 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); -} - -static int s2n_sslv3_server_finished(struct s2n_connection *conn) -{ - 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); -} - -int s2n_prf_client_finished(struct s2n_connection *conn) -{ - struct s2n_blob master_secret, md5, sha; - uint8_t md5_digest[MD5_DIGEST_LENGTH]; - uint8_t sha_digest[SHA384_DIGEST_LENGTH]; - uint8_t client_finished_label[] = "client finished"; - struct s2n_blob client_finished = {0}; - struct s2n_blob label = {0}; - - if (conn->actual_protocol_version == S2N_SSLv3) { - return s2n_sslv3_client_finished(conn); - } - - client_finished.data = conn->handshake.client_finished; - client_finished.size = S2N_TLS_FINISHED_LEN; - 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); - 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)); - 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)); - sha.size = SHA384_DIGEST_LENGTH; - break; - default: - S2N_ERROR(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)); - md5.data = md5_digest; - md5.size = MD5_DIGEST_LENGTH; - sha.data = sha_digest; - sha.size = SHA_DIGEST_LENGTH; - - return s2n_prf(conn, &master_secret, &label, &md5, &sha, NULL, &client_finished); -} - -int s2n_prf_server_finished(struct s2n_connection *conn) -{ - struct s2n_blob master_secret, md5, sha; - uint8_t md5_digest[MD5_DIGEST_LENGTH]; - uint8_t sha_digest[SHA384_DIGEST_LENGTH]; - uint8_t server_finished_label[] = "server finished"; - struct s2n_blob server_finished = {0}; - struct s2n_blob label = {0}; - - if (conn->actual_protocol_version == S2N_SSLv3) { - return s2n_sslv3_server_finished(conn); - } - - server_finished.data = conn->handshake.server_finished; - server_finished.size = S2N_TLS_FINISHED_LEN; - 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); - 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)); - 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)); - sha.size = SHA384_DIGEST_LENGTH; - break; - default: - S2N_ERROR(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)); - md5.data = md5_digest; - md5.size = MD5_DIGEST_LENGTH; - sha.data = sha_digest; - sha.size = SHA_DIGEST_LENGTH; - - return s2n_prf(conn, &master_secret, &label, &md5, &sha, NULL, &server_finished); -} - -static int s2n_prf_make_client_key(struct s2n_connection *conn, struct s2n_stuffer *key_material) -{ - 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); - - if (conn->mode == S2N_CLIENT) { - 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)); - } - - return 0; -} - -static int s2n_prf_make_server_key(struct s2n_connection *conn, struct s2n_stuffer *key_material) -{ - 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); - - if (conn->mode == S2N_SERVER) { - 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)); - } - - return 0; -} - -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 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))); - - 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)); - - 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)); - - /* 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)); - } - - /* 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)); - - /* 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)); - - /* Make the client key */ - GUARD(s2n_prf_make_client_key(conn, &key_material)); - - /* Make the server key */ - 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)); - } - - /* TLS >= 1.1 has no implicit IVs for non AEAD ciphers */ - if (conn->actual_protocol_version > S2N_TLS10 && conn->secure.cipher_suite->record_alg->cipher->type != S2N_AEAD) { - return 0; - } - - uint32_t implicit_iv_size = 0; - switch (conn->secure.cipher_suite->record_alg->cipher->type) { - case S2N_AEAD: - implicit_iv_size = conn->secure.cipher_suite->record_alg->cipher->io.aead.fixed_iv_size; - break; - case S2N_CBC: - implicit_iv_size = conn->secure.cipher_suite->record_alg->cipher->io.cbc.block_size; - break; - case S2N_COMPOSITE: - implicit_iv_size = conn->secure.cipher_suite->record_alg->cipher->io.comp.block_size; - break; - /* No-op for stream ciphers */ - default: - break; - } - - 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)); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <sys/param.h> +#include <openssl/md5.h> +#include <openssl/sha.h> +#include <string.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_prf.h" + +#include "stuffer/s2n_stuffer.h" + +#include "crypto/s2n_hmac.h" +#include "crypto/s2n_hash.h" +#include "crypto/s2n_openssl.h" +#include "crypto/s2n_fips.h" + +#include "utils/s2n_safety.h" +#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, + 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; + + uint32_t outputlen = out->size; + uint8_t *output = out->data; + uint8_t iteration = 1; + + uint8_t A = 'A'; + while (outputlen) { + GUARD(s2n_hash_reset(sha1)); + + for (int i = 0; i < iteration; i++) { + 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)); + + if (seed_b) { + 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)); + } + } + + GUARD(s2n_hash_digest(sha1, ws->ssl3.sha1_digest, sizeof(ws->ssl3.sha1_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))); + + uint32_t bytes_to_copy = MIN(outputlen, sizeof(ws->ssl3.md5_digest)); + + memcpy_check(output, ws->ssl3.md5_digest, bytes_to_copy); + + outputlen -= bytes_to_copy; + output += bytes_to_copy; + + /* Increment the letter */ + A++; + iteration++; + } + + GUARD(s2n_hash_reset(md5)); + GUARD(s2n_hash_reset(sha1)); + + return 0; +} + +#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC) +static int s2n_evp_hmac_p_hash_new(struct s2n_prf_working_space *ws) +{ + notnull_check(ws->tls.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) +{ + 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); + + /* 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)); + } + + 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), + 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) +{ + /* 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); + } + + /* 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)); + + /* Initialize the message digest context with the above message digest and mac key */ + return s2n_evp_hmac_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) +{ + GUARD_OSSL(EVP_DigestSignUpdate(ws->tls.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) +{ + /* 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); + + return 0; +} + +static int s2n_evp_hmac_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); + + return 0; +} + +static int s2n_evp_hmac_p_hash_reset(struct s2n_prf_working_space *ws) +{ + GUARD(s2n_evp_hmac_p_hash_wipe(ws)); + + return s2n_evp_hmac_p_hash_digest_init(ws); +} + +static int s2n_evp_hmac_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)); + + /* 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; + + return 0; +} + +static int s2n_evp_hmac_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; + + return 0; +} + +static const struct s2n_p_hash_hmac s2n_evp_hmac = { + .alloc = &s2n_evp_hmac_p_hash_new, + .init = &s2n_evp_hmac_p_hash_init, + .update = &s2n_evp_hmac_p_hash_update, + .final = &s2n_evp_hmac_p_hash_digest, + .reset = &s2n_evp_hmac_p_hash_reset, + .cleanup = &s2n_evp_hmac_p_hash_cleanup, + .free = &s2n_evp_hmac_p_hash_free, +}; +#endif /* !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC) */ + +static int s2n_hmac_p_hash_new(struct s2n_prf_working_space *ws) +{ + GUARD(s2n_hmac_new(&ws->tls.p_hash.s2n_hmac)); + + return s2n_hmac_init(&ws->tls.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); +} + +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); +} + +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); +} + +static int s2n_hmac_p_hash_reset(struct s2n_prf_working_space *ws) +{ + return s2n_hmac_reset(&ws->tls.p_hash.s2n_hmac); +} + +static int s2n_hmac_p_hash_cleanup(struct s2n_prf_working_space *ws) +{ + return s2n_hmac_p_hash_reset(ws); +} + +static int s2n_hmac_p_hash_free(struct s2n_prf_working_space *ws) +{ + return s2n_hmac_free(&ws->tls.p_hash.s2n_hmac); +} + +static const struct s2n_p_hash_hmac s2n_hmac = { + .alloc = &s2n_hmac_p_hash_new, + .init = &s2n_hmac_p_hash_init, + .update = &s2n_hmac_p_hash_update, + .final = &s2n_hmac_p_hash_digest, + .reset = &s2n_hmac_p_hash_reset, + .cleanup = &s2n_hmac_p_hash_cleanup, + .free = &s2n_hmac_p_hash_free, +}; + +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)); + + const struct s2n_p_hash_hmac *hmac = ws->tls.p_hash_hmac_impl; + + /* 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)); + + if (seed_b) { + GUARD(hmac->update(ws, seed_b->data, seed_b->size)); + if (seed_c) { + GUARD(hmac->update(ws, seed_c->data, seed_c->size)); + } + } + GUARD(hmac->final(ws, ws->tls.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)); + + /* 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)); + if (seed_b) { + GUARD(hmac->update(ws, seed_b->data, seed_b->size)); + if (seed_c) { + GUARD(hmac->update(ws, seed_c->data, seed_c->size)); + } + } + + GUARD(hmac->final(ws, ws->tls.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]; + 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)); + } + + 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 +} + +int s2n_prf_new(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(); + + return conn->prf_space.tls.p_hash_hmac_impl->alloc(&conn->prf_space); +} + +int 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(); + + return conn->prf_space.tls.p_hash_hmac_impl->free(&conn->prf_space); +} + +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) +{ + /* 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); + } + + /* We zero the out blob because p_hash works by XOR'ing with the existing + * buffer. This is a little convoluted but means we can avoid dynamic memory + * allocation. When we call p_hash once (in the TLS1.2 case) it will produce + * the right values. When we call it twice in the regular case, the two + * outputs will be XORd just ass the TLS 1.0 and 1.1 RFCs require. + */ + 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(); + + if (conn->actual_protocol_version == S2N_TLS12) { + return s2n_p_hash(&conn->prf_space, conn->secure.cipher_suite->prf_alg, secret, label, seed_a, seed_b, + seed_c, out); + } + + 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)); + 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)); + + 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}; + + uint8_t master_secret_label[] = "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, NULL, &master_secret); +} + +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}; + + 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); +} + +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) +{ + 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 + }; + uint8_t xorpad2[48] = + { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c + }; + 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)); + + return 0; +} + +static int s2n_sslv3_client_finished(struct s2n_connection *conn) +{ + 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); +} + +static int s2n_sslv3_server_finished(struct s2n_connection *conn) +{ + 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); +} + +int s2n_prf_client_finished(struct s2n_connection *conn) +{ + struct s2n_blob master_secret, md5, sha; + uint8_t md5_digest[MD5_DIGEST_LENGTH]; + uint8_t sha_digest[SHA384_DIGEST_LENGTH]; + uint8_t client_finished_label[] = "client finished"; + struct s2n_blob client_finished = {0}; + struct s2n_blob label = {0}; + + if (conn->actual_protocol_version == S2N_SSLv3) { + return s2n_sslv3_client_finished(conn); + } + + client_finished.data = conn->handshake.client_finished; + client_finished.size = S2N_TLS_FINISHED_LEN; + 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); + 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)); + 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)); + sha.size = SHA384_DIGEST_LENGTH; + break; + default: + S2N_ERROR(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)); + md5.data = md5_digest; + md5.size = MD5_DIGEST_LENGTH; + sha.data = sha_digest; + sha.size = SHA_DIGEST_LENGTH; + + return s2n_prf(conn, &master_secret, &label, &md5, &sha, NULL, &client_finished); +} + +int s2n_prf_server_finished(struct s2n_connection *conn) +{ + struct s2n_blob master_secret, md5, sha; + uint8_t md5_digest[MD5_DIGEST_LENGTH]; + uint8_t sha_digest[SHA384_DIGEST_LENGTH]; + uint8_t server_finished_label[] = "server finished"; + struct s2n_blob server_finished = {0}; + struct s2n_blob label = {0}; + + if (conn->actual_protocol_version == S2N_SSLv3) { + return s2n_sslv3_server_finished(conn); + } + + server_finished.data = conn->handshake.server_finished; + server_finished.size = S2N_TLS_FINISHED_LEN; + 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); + 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)); + 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)); + sha.size = SHA384_DIGEST_LENGTH; + break; + default: + S2N_ERROR(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)); + md5.data = md5_digest; + md5.size = MD5_DIGEST_LENGTH; + sha.data = sha_digest; + sha.size = SHA_DIGEST_LENGTH; + + return s2n_prf(conn, &master_secret, &label, &md5, &sha, NULL, &server_finished); +} + +static int s2n_prf_make_client_key(struct s2n_connection *conn, struct s2n_stuffer *key_material) +{ + 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); + + if (conn->mode == S2N_CLIENT) { + 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)); + } + + return 0; +} + +static int s2n_prf_make_server_key(struct s2n_connection *conn, struct s2n_stuffer *key_material) +{ + 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); + + if (conn->mode == S2N_SERVER) { + 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)); + } + + return 0; +} + +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 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))); + + 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)); + + 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)); + + /* 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)); + } + + /* 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)); + + /* 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)); + + /* Make the client key */ + GUARD(s2n_prf_make_client_key(conn, &key_material)); + + /* Make the server key */ + 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)); + } + + /* TLS >= 1.1 has no implicit IVs for non AEAD ciphers */ + if (conn->actual_protocol_version > S2N_TLS10 && conn->secure.cipher_suite->record_alg->cipher->type != S2N_AEAD) { + return 0; + } + + uint32_t implicit_iv_size = 0; + switch (conn->secure.cipher_suite->record_alg->cipher->type) { + case S2N_AEAD: + implicit_iv_size = conn->secure.cipher_suite->record_alg->cipher->io.aead.fixed_iv_size; + break; + case S2N_CBC: + implicit_iv_size = conn->secure.cipher_suite->record_alg->cipher->io.cbc.block_size; + break; + case S2N_COMPOSITE: + implicit_iv_size = conn->secure.cipher_suite->record_alg->cipher->io.comp.block_size; + break; + /* No-op for stream ciphers */ + default: + break; + } + + 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)); + + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_prf.h b/contrib/restricted/aws/s2n/tls/s2n_prf.h index 3f1bcde090..a3679436b2 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_prf.h +++ b/contrib/restricted/aws/s2n/tls/s2n_prf.h @@ -1,70 +1,70 @@ -/* - * 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 <stdint.h> - -#include "crypto/s2n_hash.h" -#include "crypto/s2n_hmac.h" -#include "crypto/s2n_openssl.h" - -#include "utils/s2n_blob.h" - -/* 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 { - 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; -}; - -/* The s2n p_hash implementation is abstracted to allow for separate implementations, using - * either s2n's formally verified HMAC or OpenSSL's EVP HMAC, for use by the TLS PRF. */ -struct s2n_p_hash_hmac { - int (*alloc) (struct s2n_prf_working_space *ws); - int (*init) (struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg, struct s2n_blob *secret); - int (*update) (struct s2n_prf_working_space *ws, const void *data, uint32_t size); - int (*final) (struct s2n_prf_working_space *ws, void *digest, uint32_t size); - int (*reset) (struct s2n_prf_working_space *ws); - int (*cleanup) (struct s2n_prf_working_space *ws); - int (*free) (struct s2n_prf_working_space *ws); -}; - -#include "tls/s2n_connection.h" - -extern int s2n_prf_new(struct s2n_connection *conn); -extern int s2n_prf_free(struct s2n_connection *conn); -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); -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); +/* + * 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 <stdint.h> + +#include "crypto/s2n_hash.h" +#include "crypto/s2n_hmac.h" +#include "crypto/s2n_openssl.h" + +#include "utils/s2n_blob.h" + +/* 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 { + 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; +}; + +/* The s2n p_hash implementation is abstracted to allow for separate implementations, using + * either s2n's formally verified HMAC or OpenSSL's EVP HMAC, for use by the TLS PRF. */ +struct s2n_p_hash_hmac { + int (*alloc) (struct s2n_prf_working_space *ws); + int (*init) (struct s2n_prf_working_space *ws, s2n_hmac_algorithm alg, struct s2n_blob *secret); + int (*update) (struct s2n_prf_working_space *ws, const void *data, uint32_t size); + int (*final) (struct s2n_prf_working_space *ws, void *digest, uint32_t size); + int (*reset) (struct s2n_prf_working_space *ws); + int (*cleanup) (struct s2n_prf_working_space *ws); + int (*free) (struct s2n_prf_working_space *ws); +}; + +#include "tls/s2n_connection.h" + +extern int s2n_prf_new(struct s2n_connection *conn); +extern int s2n_prf_free(struct s2n_connection *conn); +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); +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 1137b67277..e0157f4ae4 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c +++ b/contrib/restricted/aws/s2n/tls/s2n_protocol_preferences.c @@ -1,55 +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. - */ - -#include "tls/s2n_connection.h" -#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) -{ - struct s2n_stuffer protocol_stuffer = {0}; - - GUARD(s2n_free(application_protocols)); - - if (protocols == NULL || protocol_count == 0) { - /* NULL value indicates no preference, so nothing to do */ - return 0; - } - - GUARD(s2n_stuffer_growable_alloc(&protocol_stuffer, 256)); - for (int i = 0; i < protocol_count; 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)); - } - - GUARD(s2n_stuffer_extract_blob(&protocol_stuffer, application_protocols)); - GUARD(s2n_stuffer_free(&protocol_stuffer)); - return 0; -} - -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); -} - -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); -} +/* + * 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 "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) +{ + struct s2n_stuffer protocol_stuffer = {0}; + + GUARD(s2n_free(application_protocols)); + + if (protocols == NULL || protocol_count == 0) { + /* NULL value indicates no preference, so nothing to do */ + return 0; + } + + GUARD(s2n_stuffer_growable_alloc(&protocol_stuffer, 256)); + for (int i = 0; i < protocol_count; 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)); + } + + GUARD(s2n_stuffer_extract_blob(&protocol_stuffer, application_protocols)); + GUARD(s2n_stuffer_free(&protocol_stuffer)); + return 0; +} + +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); +} + +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); +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_psk.c b/contrib/restricted/aws/s2n/tls/s2n_psk.c index 0ce4e1a140..2d764a00ed 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_psk.c +++ b/contrib/restricted/aws/s2n/tls/s2n_psk.c @@ -1,302 +1,302 @@ -/* - * 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 "crypto/s2n_tls13_keys.h" - -#include "tls/s2n_handshake.h" -#include "tls/s2n_psk.h" -#include "tls/s2n_tls13_handshake.h" -#include "tls/s2n_tls.h" - -#include "utils/s2n_array.h" -#include "utils/s2n_mem.h" -#include "utils/s2n_safety.h" - -#define S2N_HASH_ALG_COUNT S2N_HASH_SENTINEL - -int s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type) -{ - notnull_check(psk); - - memset_check(psk, 0, sizeof(struct s2n_psk)); - psk->hash_alg = S2N_HASH_SHA256; - psk->type = type; - - return S2N_SUCCESS; -} - -int s2n_psk_new_identity(struct s2n_psk *psk, const uint8_t *identity, size_t identity_size) -{ - notnull_check(psk); - - GUARD(s2n_realloc(&psk->identity, identity_size)); - memcpy_check(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) -{ - notnull_check(psk); - - GUARD(s2n_realloc(&psk->secret, secret_size)); - memcpy_check(psk->secret.data, secret, secret_size); - - return S2N_SUCCESS; -} - -int s2n_psk_free(struct s2n_psk *psk) -{ - if (psk == NULL) { - return S2N_SUCCESS; - } - - GUARD(s2n_free(&psk->early_secret)); - GUARD(s2n_free(&psk->identity)); - GUARD(s2n_free(&psk->secret)); - - return S2N_SUCCESS; -} - -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(¶ms->psk_list, sizeof(struct s2n_psk))); - return S2N_RESULT_OK; -} - -S2N_RESULT s2n_psk_parameters_free_unused_psks(struct s2n_psk_parameters *params) -{ - ENSURE_REF(params); - for (size_t i = 0; i < params->psk_list.len; i++) { - struct s2n_psk *psk; - GUARD_RESULT(s2n_array_get(¶ms->psk_list, i, (void**)&psk)); - - if(psk == params->chosen_psk) { - continue; - } - GUARD_AS_RESULT(s2n_psk_free(psk)); - } - return S2N_RESULT_OK; -} - -S2N_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params) -{ - ENSURE_REF(params); - - /* Free all PSKs */ - GUARD_RESULT(s2n_psk_parameters_free_unused_psks(params)); - GUARD_AS_RESULT(s2n_psk_free(params->chosen_psk)); - - struct s2n_blob psk_list_mem = params->psk_list.mem; - s2n_result result = s2n_psk_parameters_init(params); - params->psk_list.mem = psk_list_mem; - - return result; -} - -int s2n_psk_parameters_free(struct s2n_psk_parameters *params) -{ - notnull_check(params); - GUARD_AS_POSIX(s2n_psk_parameters_wipe(params)); - GUARD(s2n_free(¶ms->psk_list.mem)); - 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_hash_algorithm hash_alg, - const struct s2n_blob *partial_client_hello, struct s2n_blob *output_binder_hash) -{ - notnull_check(partial_client_hello); - notnull_check(output_binder_hash); - - /* Retrieve the current transcript. - * The current transcript will be empty unless this handshake included a HelloRetryRequest. */ - struct s2n_hash_state current_hash_state = {0}; - GUARD(s2n_handshake_get_hash_state(conn, hash_alg, ¤t_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, ¤t_hash_state)); - - /* Add the partial client hello to the transcript. */ - GUARD(s2n_hash_update(&hash_copy, 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)); - - return S2N_SUCCESS; -} - -static int s2n_tls13_keys_init_with_psk(struct s2n_tls13_keys *keys, struct s2n_psk *psk) -{ - notnull_check(keys); - - keys->hash_algorithm = psk->hash_alg; - GUARD(s2n_hash_hmac_alg(keys->hash_algorithm, &keys->hmac_algorithm)); - GUARD(s2n_hash_digest_size(keys->hash_algorithm, &keys->size)); - GUARD(s2n_blob_init(&keys->extract_secret, keys->extract_secret_bytes, keys->size)); - GUARD(s2n_blob_init(&keys->derive_secret, keys->derive_secret_bytes, keys->size)); - GUARD(s2n_hmac_new(&keys->hmac)); - - return S2N_SUCCESS; -} - -/* The binder is computed in the same way as the Finished message - * (https://tools.ietf.org/html/rfc8446#section-4.4.4) but with the BaseKey being the binder_key - * derived via the key schedule from the corresponding PSK which is being offered - * (https://tools.ietf.org/html/rfc8446#section-7.1) - */ -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); - - DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free); - GUARD(s2n_tls13_keys_init_with_psk(&psk_keys, psk)); - 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)); - - /* Derive the binder key */ - GUARD(s2n_tls13_derive_binder_key(&psk_keys, psk)); - 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)); - - /* 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)); - - return S2N_SUCCESS; -} - -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); - - DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free); - GUARD(s2n_tls13_keys_init_with_psk(&psk_keys, psk)); - eq_check(binder_to_verify->size, psk_keys.size); - - /* Calculate the binder hash from the transcript */ - s2n_tls13_key_blob(binder_hash, psk_keys.size); - GUARD(s2n_psk_calculate_binder_hash(conn, psk->hash_alg, partial_client_hello, &binder_hash)); - - /* 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)); - - /* 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)); - - return S2N_SUCCESS; -} - -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); - - 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)); - - 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)); - - return S2N_RESULT_OK; -} - -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); - - struct s2n_psk_parameters *psk_params = &conn->psk_params; - struct s2n_array *psk_list = &psk_params->psk_list; - - /* Setup memory to hold the binder hashes. We potentially need one for - * every hash algorithm. */ - uint8_t binder_hashes_data[S2N_HASH_ALG_COUNT][S2N_TLS13_SECRET_MAX_LEN] = { 0 }; - 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)); - - /* 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); - - /* Retrieve or calculate the binder hash. */ - struct s2n_blob *binder_hash = &binder_hashes[psk->hash_alg]; - if (binder_hash->size == 0) { - uint8_t hash_size = 0; - GUARD_AS_RESULT(s2n_hash_digest_size(psk->hash_alg, &hash_size)); - GUARD_AS_RESULT(s2n_blob_init(binder_hash, binder_hashes_data[psk->hash_alg], hash_size)); - GUARD_AS_RESULT(s2n_psk_calculate_binder_hash(conn, psk->hash_alg, partial_client_hello, binder_hash)); - } - - GUARD_RESULT(s2n_psk_write_binder(conn, psk, binder_hash, out)); - } - GUARD_AS_RESULT(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); - - if (!conn->psk_params.binder_list_size) { - return S2N_RESULT_OK; - } - - struct s2n_stuffer *client_hello = &conn->handshake.io; - struct s2n_psk_parameters *psk_params = &conn->psk_params; - - /* Fill in the correct message size. */ - GUARD_AS_RESULT(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)); - - /* 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, - s2n_stuffer_data_available(client_hello))); - - GUARD_RESULT(s2n_psk_write_binder_list(conn, &partial_client_hello, client_hello)); - return S2N_RESULT_OK; -} +/* + * 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 "crypto/s2n_tls13_keys.h" + +#include "tls/s2n_handshake.h" +#include "tls/s2n_psk.h" +#include "tls/s2n_tls13_handshake.h" +#include "tls/s2n_tls.h" + +#include "utils/s2n_array.h" +#include "utils/s2n_mem.h" +#include "utils/s2n_safety.h" + +#define S2N_HASH_ALG_COUNT S2N_HASH_SENTINEL + +int s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type) +{ + notnull_check(psk); + + memset_check(psk, 0, sizeof(struct s2n_psk)); + psk->hash_alg = S2N_HASH_SHA256; + psk->type = type; + + return S2N_SUCCESS; +} + +int s2n_psk_new_identity(struct s2n_psk *psk, const uint8_t *identity, size_t identity_size) +{ + notnull_check(psk); + + GUARD(s2n_realloc(&psk->identity, identity_size)); + memcpy_check(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) +{ + notnull_check(psk); + + GUARD(s2n_realloc(&psk->secret, secret_size)); + memcpy_check(psk->secret.data, secret, secret_size); + + return S2N_SUCCESS; +} + +int s2n_psk_free(struct s2n_psk *psk) +{ + if (psk == NULL) { + return S2N_SUCCESS; + } + + GUARD(s2n_free(&psk->early_secret)); + GUARD(s2n_free(&psk->identity)); + GUARD(s2n_free(&psk->secret)); + + return S2N_SUCCESS; +} + +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(¶ms->psk_list, sizeof(struct s2n_psk))); + return S2N_RESULT_OK; +} + +S2N_RESULT s2n_psk_parameters_free_unused_psks(struct s2n_psk_parameters *params) +{ + ENSURE_REF(params); + for (size_t i = 0; i < params->psk_list.len; i++) { + struct s2n_psk *psk; + GUARD_RESULT(s2n_array_get(¶ms->psk_list, i, (void**)&psk)); + + if(psk == params->chosen_psk) { + continue; + } + GUARD_AS_RESULT(s2n_psk_free(psk)); + } + return S2N_RESULT_OK; +} + +S2N_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params) +{ + ENSURE_REF(params); + + /* Free all PSKs */ + GUARD_RESULT(s2n_psk_parameters_free_unused_psks(params)); + GUARD_AS_RESULT(s2n_psk_free(params->chosen_psk)); + + struct s2n_blob psk_list_mem = params->psk_list.mem; + s2n_result result = s2n_psk_parameters_init(params); + params->psk_list.mem = psk_list_mem; + + return result; +} + +int s2n_psk_parameters_free(struct s2n_psk_parameters *params) +{ + notnull_check(params); + GUARD_AS_POSIX(s2n_psk_parameters_wipe(params)); + GUARD(s2n_free(¶ms->psk_list.mem)); + 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_hash_algorithm hash_alg, + const struct s2n_blob *partial_client_hello, struct s2n_blob *output_binder_hash) +{ + notnull_check(partial_client_hello); + notnull_check(output_binder_hash); + + /* Retrieve the current transcript. + * The current transcript will be empty unless this handshake included a HelloRetryRequest. */ + struct s2n_hash_state current_hash_state = {0}; + GUARD(s2n_handshake_get_hash_state(conn, hash_alg, ¤t_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, ¤t_hash_state)); + + /* Add the partial client hello to the transcript. */ + GUARD(s2n_hash_update(&hash_copy, 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)); + + return S2N_SUCCESS; +} + +static int s2n_tls13_keys_init_with_psk(struct s2n_tls13_keys *keys, struct s2n_psk *psk) +{ + notnull_check(keys); + + keys->hash_algorithm = psk->hash_alg; + GUARD(s2n_hash_hmac_alg(keys->hash_algorithm, &keys->hmac_algorithm)); + GUARD(s2n_hash_digest_size(keys->hash_algorithm, &keys->size)); + GUARD(s2n_blob_init(&keys->extract_secret, keys->extract_secret_bytes, keys->size)); + GUARD(s2n_blob_init(&keys->derive_secret, keys->derive_secret_bytes, keys->size)); + GUARD(s2n_hmac_new(&keys->hmac)); + + return S2N_SUCCESS; +} + +/* The binder is computed in the same way as the Finished message + * (https://tools.ietf.org/html/rfc8446#section-4.4.4) but with the BaseKey being the binder_key + * derived via the key schedule from the corresponding PSK which is being offered + * (https://tools.ietf.org/html/rfc8446#section-7.1) + */ +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); + + DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free); + GUARD(s2n_tls13_keys_init_with_psk(&psk_keys, psk)); + 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)); + + /* Derive the binder key */ + GUARD(s2n_tls13_derive_binder_key(&psk_keys, psk)); + 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)); + + /* 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)); + + return S2N_SUCCESS; +} + +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); + + DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free); + GUARD(s2n_tls13_keys_init_with_psk(&psk_keys, psk)); + eq_check(binder_to_verify->size, psk_keys.size); + + /* Calculate the binder hash from the transcript */ + s2n_tls13_key_blob(binder_hash, psk_keys.size); + GUARD(s2n_psk_calculate_binder_hash(conn, psk->hash_alg, partial_client_hello, &binder_hash)); + + /* 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)); + + /* 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)); + + return S2N_SUCCESS; +} + +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); + + 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)); + + 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)); + + return S2N_RESULT_OK; +} + +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); + + struct s2n_psk_parameters *psk_params = &conn->psk_params; + struct s2n_array *psk_list = &psk_params->psk_list; + + /* Setup memory to hold the binder hashes. We potentially need one for + * every hash algorithm. */ + uint8_t binder_hashes_data[S2N_HASH_ALG_COUNT][S2N_TLS13_SECRET_MAX_LEN] = { 0 }; + 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)); + + /* 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); + + /* Retrieve or calculate the binder hash. */ + struct s2n_blob *binder_hash = &binder_hashes[psk->hash_alg]; + if (binder_hash->size == 0) { + uint8_t hash_size = 0; + GUARD_AS_RESULT(s2n_hash_digest_size(psk->hash_alg, &hash_size)); + GUARD_AS_RESULT(s2n_blob_init(binder_hash, binder_hashes_data[psk->hash_alg], hash_size)); + GUARD_AS_RESULT(s2n_psk_calculate_binder_hash(conn, psk->hash_alg, partial_client_hello, binder_hash)); + } + + GUARD_RESULT(s2n_psk_write_binder(conn, psk, binder_hash, out)); + } + GUARD_AS_RESULT(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); + + if (!conn->psk_params.binder_list_size) { + return S2N_RESULT_OK; + } + + struct s2n_stuffer *client_hello = &conn->handshake.io; + struct s2n_psk_parameters *psk_params = &conn->psk_params; + + /* Fill in the correct message size. */ + GUARD_AS_RESULT(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)); + + /* 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, + s2n_stuffer_data_available(client_hello))); + + GUARD_RESULT(s2n_psk_write_binder_list(conn, &partial_client_hello, client_hello)); + 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 5568bf0ca5..a805eaddfa 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_psk.h +++ b/contrib/restricted/aws/s2n/tls/s2n_psk.h @@ -1,63 +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 <s2n.h> - -#include "crypto/s2n_hash.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_EXTERNAL, -} s2n_psk_type; - -struct s2n_psk { - s2n_psk_type type; - struct s2n_blob identity; - struct s2n_blob secret; - s2n_hash_algorithm hash_alg; - uint32_t obfuscated_ticket_age; - struct s2n_blob early_secret; -}; - -struct s2n_psk_parameters { - struct s2n_array psk_list; - uint16_t binder_list_size; - uint8_t chosen_psk_wire_index; - struct s2n_psk *chosen_psk; -}; - -int s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type); -int s2n_psk_new_identity(struct s2n_psk *psk, const uint8_t *identity, size_t identity_size); -int s2n_psk_new_secret(struct s2n_psk *psk, const uint8_t *secret, size_t secret_size); -int s2n_psk_free(struct s2n_psk *psk); - -S2N_RESULT s2n_psk_parameters_init(struct s2n_psk_parameters *params); -S2N_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params); -S2N_RESULT s2n_psk_parameters_free_unused_psks(struct s2n_psk_parameters *params); -int s2n_psk_parameters_free(struct s2n_psk_parameters *params); - -S2N_RESULT s2n_finish_psk_extension(struct s2n_connection *conn); - -int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, - const struct s2n_blob *partial_client_hello, struct s2n_blob *output_binder_hash); -int s2n_psk_calculate_binder(struct s2n_psk *psk, const struct s2n_blob *binder_hash, - struct s2n_blob *output_binder); -int s2n_psk_verify_binder(struct s2n_connection *conn, struct s2n_psk *psk, - const struct s2n_blob *partial_client_hello, struct s2n_blob *binder_to_verify); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include <s2n.h> + +#include "crypto/s2n_hash.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_EXTERNAL, +} s2n_psk_type; + +struct s2n_psk { + s2n_psk_type type; + struct s2n_blob identity; + struct s2n_blob secret; + s2n_hash_algorithm hash_alg; + uint32_t obfuscated_ticket_age; + struct s2n_blob early_secret; +}; + +struct s2n_psk_parameters { + struct s2n_array psk_list; + uint16_t binder_list_size; + uint8_t chosen_psk_wire_index; + struct s2n_psk *chosen_psk; +}; + +int s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type); +int s2n_psk_new_identity(struct s2n_psk *psk, const uint8_t *identity, size_t identity_size); +int s2n_psk_new_secret(struct s2n_psk *psk, const uint8_t *secret, size_t secret_size); +int s2n_psk_free(struct s2n_psk *psk); + +S2N_RESULT s2n_psk_parameters_init(struct s2n_psk_parameters *params); +S2N_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params); +S2N_RESULT s2n_psk_parameters_free_unused_psks(struct s2n_psk_parameters *params); +int s2n_psk_parameters_free(struct s2n_psk_parameters *params); + +S2N_RESULT s2n_finish_psk_extension(struct s2n_connection *conn); + +int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hash_algorithm hash_alg, + const struct s2n_blob *partial_client_hello, struct s2n_blob *output_binder_hash); +int s2n_psk_calculate_binder(struct s2n_psk *psk, const struct s2n_blob *binder_hash, + struct s2n_blob *output_binder); +int s2n_psk_verify_binder(struct s2n_connection *conn, struct s2n_psk *psk, + const struct s2n_blob *partial_client_hello, struct s2n_blob *binder_to_verify); diff --git a/contrib/restricted/aws/s2n/tls/s2n_quic_support.c b/contrib/restricted/aws/s2n/tls/s2n_quic_support.c index 33ee5e6ad8..226b87ee9a 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_quic_support.c +++ b/contrib/restricted/aws/s2n/tls/s2n_quic_support.c @@ -1,115 +1,115 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include "tls/s2n_quic_support.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_tls13.h" -#include "tls/s2n_tls.h" - -#include "utils/s2n_mem.h" -#include "utils/s2n_safety.h" - -/* When reading and writing records with TCP, S2N sets its input and output buffers - * to the maximum record fragment size to prevent resizing those buffers later. - * - * However, because S2N with QUIC reads and writes messages instead of records, - * the "maximum size" for the input and output buffers would be the maximum message size: 64k. - * Since most messages are MUCH smaller than that (<3k), setting the buffer that large is wasteful. - * - * Instead, we intentionally choose a smaller size and accept that an abnormally large message - * could cause the buffer to resize. */ -#define S2N_EXPECTED_QUIC_MESSAGE_SIZE S2N_DEFAULT_FRAGMENT_LENGTH - -S2N_RESULT s2n_read_in_bytes(struct s2n_connection *conn, struct s2n_stuffer *output, uint32_t length); - -int s2n_config_enable_quic(struct s2n_config *config) -{ - notnull_check(config); - config->quic_enabled = true; - return S2N_SUCCESS; -} - -int s2n_connection_set_quic_transport_parameters(struct s2n_connection *conn, - const uint8_t *data_buffer, uint16_t data_len) -{ - notnull_check(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); - - return S2N_SUCCESS; -} - -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); - - *data_buffer = conn->peer_quic_transport_parameters.data; - *data_len = conn->peer_quic_transport_parameters.size; - - return S2N_SUCCESS; -} - -int s2n_connection_set_secret_callback(struct s2n_connection *conn, s2n_secret_cb cb_func, void *ctx) -{ - notnull_check(conn); - notnull_check(cb_func); - - conn->secret_cb = cb_func; - conn->secret_cb_context = ctx; - - return S2N_SUCCESS; -} - -/* When using QUIC, S2N reads unencrypted handshake messages instead of encrypted records. - * This method sets up the S2N input buffers to match the results of using s2n_read_full_record. - */ -S2N_RESULT s2n_quic_read_handshake_message(struct s2n_connection *conn, uint8_t *message_type) -{ - 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)); - - GUARD_RESULT(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)); - - ENSURE(message_len < S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH, S2N_ERR_BAD_MESSAGE); - GUARD_RESULT(s2n_read_in_bytes(conn, &conn->in, message_len)); - - return S2N_RESULT_OK; -} - -/* When using QUIC, S2N writes unencrypted handshake messages instead of encrypted records. - * This method sets up the S2N output buffer to match the result of using s2n_record_write. - */ -S2N_RESULT s2n_quic_write_handshake_message(struct s2n_connection *conn, struct s2n_blob *in) -{ - 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)); - - GUARD_AS_RESULT(s2n_stuffer_write(&conn->out, in)); - return S2N_RESULT_OK; -} +/* + * 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_quic_support.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_tls13.h" +#include "tls/s2n_tls.h" + +#include "utils/s2n_mem.h" +#include "utils/s2n_safety.h" + +/* When reading and writing records with TCP, S2N sets its input and output buffers + * to the maximum record fragment size to prevent resizing those buffers later. + * + * However, because S2N with QUIC reads and writes messages instead of records, + * the "maximum size" for the input and output buffers would be the maximum message size: 64k. + * Since most messages are MUCH smaller than that (<3k), setting the buffer that large is wasteful. + * + * Instead, we intentionally choose a smaller size and accept that an abnormally large message + * could cause the buffer to resize. */ +#define S2N_EXPECTED_QUIC_MESSAGE_SIZE S2N_DEFAULT_FRAGMENT_LENGTH + +S2N_RESULT s2n_read_in_bytes(struct s2n_connection *conn, struct s2n_stuffer *output, uint32_t length); + +int s2n_config_enable_quic(struct s2n_config *config) +{ + notnull_check(config); + config->quic_enabled = true; + return S2N_SUCCESS; +} + +int s2n_connection_set_quic_transport_parameters(struct s2n_connection *conn, + const uint8_t *data_buffer, uint16_t data_len) +{ + notnull_check(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); + + return S2N_SUCCESS; +} + +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); + + *data_buffer = conn->peer_quic_transport_parameters.data; + *data_len = conn->peer_quic_transport_parameters.size; + + return S2N_SUCCESS; +} + +int s2n_connection_set_secret_callback(struct s2n_connection *conn, s2n_secret_cb cb_func, void *ctx) +{ + notnull_check(conn); + notnull_check(cb_func); + + conn->secret_cb = cb_func; + conn->secret_cb_context = ctx; + + return S2N_SUCCESS; +} + +/* When using QUIC, S2N reads unencrypted handshake messages instead of encrypted records. + * This method sets up the S2N input buffers to match the results of using s2n_read_full_record. + */ +S2N_RESULT s2n_quic_read_handshake_message(struct s2n_connection *conn, uint8_t *message_type) +{ + 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)); + + GUARD_RESULT(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)); + + ENSURE(message_len < S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH, S2N_ERR_BAD_MESSAGE); + GUARD_RESULT(s2n_read_in_bytes(conn, &conn->in, message_len)); + + return S2N_RESULT_OK; +} + +/* When using QUIC, S2N writes unencrypted handshake messages instead of encrypted records. + * This method sets up the S2N output buffer to match the result of using s2n_record_write. + */ +S2N_RESULT s2n_quic_write_handshake_message(struct s2n_connection *conn, struct s2n_blob *in) +{ + 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)); + + GUARD_AS_RESULT(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 621c4dcd0f..459e03a2fd 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_quic_support.h +++ b/contrib/restricted/aws/s2n/tls/s2n_quic_support.h @@ -1,76 +1,76 @@ -/* - * 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" - -/* - * APIs intended to support an external implementation of the QUIC protocol: - * https://datatracker.ietf.org/wg/quic/about/ - * - * QUIC requires access to parts of S2N not usually surfaced to customers. These APIs change - * 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. - */ - -S2N_API int s2n_config_enable_quic(struct s2n_config *config); - -/* - * Set the data to be sent in the quic_transport_parameters extension. - * The data provided will be copied into a buffer owned by S2N. - */ -S2N_API int s2n_connection_set_quic_transport_parameters(struct s2n_connection *conn, - const uint8_t *data_buffer, uint16_t data_len); - -/* - * Retrieve the data from the peer's quic_transport_parameters extension. - * data_buffer will be set to a buffer owned by S2N which will be freed when the connection is freed. - * data_len will be set to the length of the data returned. - * - * S2N treats the extension data as opaque bytes and performs no validation. - */ -S2N_API int s2n_connection_get_quic_transport_parameters(struct s2n_connection *conn, - const uint8_t **data_buffer, uint16_t *data_len); - -typedef enum { - S2N_CLIENT_EARLY_TRAFFIC_SECRET = 0, - S2N_CLIENT_HANDSHAKE_TRAFFIC_SECRET, - S2N_SERVER_HANDSHAKE_TRAFFIC_SECRET, - S2N_CLIENT_APPLICATION_TRAFFIC_SECRET, - S2N_SERVER_APPLICATION_TRAFFIC_SECRET, -} s2n_secret_type_t; - -/* - * Called when S2N begins using a new key. - * - * The memory pointed to by "secret" will be wiped after this method returns and should be copied by - * the application if necessary. The application should also be very careful managing the memory and - * lifespan of the secret: if the secret is compromised, TLS is compromised. - */ -typedef int (*s2n_secret_cb) (void* context, struct s2n_connection *conn, - s2n_secret_type_t secret_type, - uint8_t *secret, uint8_t secret_size); - -/* - * Set the function to be called when S2N begins using a new key. - * - * 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); +/* + * 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" + +/* + * APIs intended to support an external implementation of the QUIC protocol: + * https://datatracker.ietf.org/wg/quic/about/ + * + * QUIC requires access to parts of S2N not usually surfaced to customers. These APIs change + * 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. + */ + +S2N_API int s2n_config_enable_quic(struct s2n_config *config); + +/* + * Set the data to be sent in the quic_transport_parameters extension. + * The data provided will be copied into a buffer owned by S2N. + */ +S2N_API int s2n_connection_set_quic_transport_parameters(struct s2n_connection *conn, + const uint8_t *data_buffer, uint16_t data_len); + +/* + * Retrieve the data from the peer's quic_transport_parameters extension. + * data_buffer will be set to a buffer owned by S2N which will be freed when the connection is freed. + * data_len will be set to the length of the data returned. + * + * S2N treats the extension data as opaque bytes and performs no validation. + */ +S2N_API int s2n_connection_get_quic_transport_parameters(struct s2n_connection *conn, + const uint8_t **data_buffer, uint16_t *data_len); + +typedef enum { + S2N_CLIENT_EARLY_TRAFFIC_SECRET = 0, + S2N_CLIENT_HANDSHAKE_TRAFFIC_SECRET, + S2N_SERVER_HANDSHAKE_TRAFFIC_SECRET, + S2N_CLIENT_APPLICATION_TRAFFIC_SECRET, + S2N_SERVER_APPLICATION_TRAFFIC_SECRET, +} s2n_secret_type_t; + +/* + * Called when S2N begins using a new key. + * + * The memory pointed to by "secret" will be wiped after this method returns and should be copied by + * the application if necessary. The application should also be very careful managing the memory and + * lifespan of the secret: if the secret is compromised, TLS is compromised. + */ +typedef int (*s2n_secret_cb) (void* context, struct s2n_connection *conn, + s2n_secret_type_t secret_type, + uint8_t *secret, uint8_t secret_size); + +/* + * Set the function to be called when S2N begins using a new key. + * + * 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); diff --git a/contrib/restricted/aws/s2n/tls/s2n_record.h b/contrib/restricted/aws/s2n/tls/s2n_record.h index 2e081c2876..f5b6f27502 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_record.h +++ b/contrib/restricted/aws/s2n/tls/s2n_record.h @@ -1,34 +1,34 @@ -/* - * 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 <stdint.h> - -#include "s2n_connection.h" - -#define TLS13_CONTENT_TYPE_LENGTH 1 - -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); -extern int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const struct iovec *in, int in_count, size_t offs, size_t to_write); -extern int s2n_record_parse(struct s2n_connection *conn); -extern int s2n_record_header_parse(struct s2n_connection *conn, uint8_t * content_type, uint16_t * fragment_length); -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); +/* + * 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 <stdint.h> + +#include "s2n_connection.h" + +#define TLS13_CONTENT_TYPE_LENGTH 1 + +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); +extern int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const struct iovec *in, int in_count, size_t offs, size_t to_write); +extern int s2n_record_parse(struct s2n_connection *conn); +extern int s2n_record_header_parse(struct s2n_connection *conn, uint8_t * content_type, uint16_t * fragment_length); +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); diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_read.c b/contrib/restricted/aws/s2n/tls/s2n_record_read.c index 28fe7681f5..7b8536818e 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_record_read.c +++ b/contrib/restricted/aws/s2n/tls/s2n_record_read.c @@ -1,210 +1,210 @@ -/* - * 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 "crypto/s2n_sequence.h" -#include "crypto/s2n_cipher.h" -#include "crypto/s2n_hmac.h" - -#include "error/s2n_errno.h" - -#include "stuffer/s2n_stuffer.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_crypto.h" -#include "tls/s2n_record_read.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_blob.h" - -int s2n_sslv2_record_header_parse( - struct s2n_connection *conn, - uint8_t * record_type, - uint8_t * client_protocol_version, - uint16_t * fragment_length) -{ - struct s2n_stuffer *in = &conn->header_in; - - 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)); - - /* Adjust to account for the 3 bytes of payload data we consumed in the header */ - *fragment_length -= 3; - - 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)); - - *client_protocol_version = (protocol_version[0] * 10) + protocol_version[1]; - - return 0; -} - -int s2n_record_header_parse( - struct s2n_connection *conn, - uint8_t *content_type, - uint16_t *fragment_length) -{ - struct s2n_stuffer *in = &conn->header_in; - - 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)); - - uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; - 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 - * layer version number for the first TLS record. There is some ambiguity here because the client does not know - * what version to use in the record header prior to receiving the ServerHello. Some client implementations may use - * a garbage value(not {03,XX}) in the ClientHello. - * Choose to be lenient to these clients. After protocol negotiation, we will enforce that all record versions - * match the negotiated version. - */ - - 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)); - - /* 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)); - - return 0; -} - -/* In TLS 1.3, handle CCS message as unprotected records all the time. - * https://tools.ietf.org/html/rfc8446#section-5 - * - * In TLS 1.2 and TLS 1.3 Alert messages are plaintext or encrypted - * depending on the context of the connection. If we receive an encrypted - * alert, the record type is TLS_APPLICATION_DATA at this point. It will - * be decrypted and processed in s2n_handshake_io. We may receive a - * plaintext alert if we hit an error before the handshake completed - * (like a certificate failed to validate). - * https://tools.ietf.org/html/rfc8446#section-6 - * - * This function is specific to TLS 1.3 to avoid changing the behavior - * of existing interpretation of TLS 1.2 alerts. */ -static bool s2n_is_tls13_plaintext_content(struct s2n_connection *conn, uint8_t content_type) -{ - return conn->actual_protocol_version == S2N_TLS13 && (content_type == TLS_ALERT || content_type == TLS_CHANGE_CIPHER_SPEC); -} - -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)); - - struct s2n_crypto_parameters *current_client_crypto = conn->client; - struct s2n_crypto_parameters *current_server_crypto = conn->server; - if (s2n_is_tls13_plaintext_content(conn, content_type)) { - conn->client = &conn->initial; - conn->server = &conn->initial; - } - - const struct s2n_cipher_suite *cipher_suite = conn->client->cipher_suite; - uint8_t *implicit_iv = conn->client->client_implicit_iv; - struct s2n_hmac_state *mac = &conn->client->client_record_mac; - uint8_t *sequence_number = conn->client->client_sequence_number; - struct s2n_session_key *session_key = &conn->client->client_key; - - if (conn->mode == S2N_CLIENT) { - cipher_suite = conn->server->cipher_suite; - implicit_iv = conn->server->server_implicit_iv; - mac = &conn->server->server_record_mac; - sequence_number = conn->server->server_sequence_number; - session_key = &conn->server->server_key; - } - - if (s2n_is_tls13_plaintext_content(conn, content_type)) { - conn->client = current_client_crypto; - conn->server = current_server_crypto; - } - - 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)); - break; - case S2N_CBC: - 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)); - break; - case S2N_STREAM: - 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); - break; - } - - return 0; -} - -int s2n_tls13_parse_record_type(struct s2n_stuffer *stuffer, uint8_t *record_type) -{ - uint32_t bytes_left = s2n_stuffer_data_available(stuffer); - - /* From rfc8446 Section 5.4 - * The presence of padding does not change the overall record size - * limitations: the full encoded TLSInnerPlaintext MUST NOT exceed 2^14 - * + 1 octets - * - * Certain versions of Java can generate inner plaintexts with lengths up to - * S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH + 16 (See JDK-8221253) - * However, after the padding is stripped, the result will always be no more than - * S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH - 1 - */ - 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)); - - /* Record type should have values greater than zero. - * If zero, treat as padding, keep reading and wiping from the back - * until a non-zero value is found - */ - *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)); - - /* set the record type */ - 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)); - } - - /* only the original plaintext should remain */ - /* now reset the read cursor at where it should be */ - 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); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <sys/param.h> + +#include "crypto/s2n_sequence.h" +#include "crypto/s2n_cipher.h" +#include "crypto/s2n_hmac.h" + +#include "error/s2n_errno.h" + +#include "stuffer/s2n_stuffer.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_crypto.h" +#include "tls/s2n_record_read.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_blob.h" + +int s2n_sslv2_record_header_parse( + struct s2n_connection *conn, + uint8_t * record_type, + uint8_t * client_protocol_version, + uint16_t * fragment_length) +{ + struct s2n_stuffer *in = &conn->header_in; + + 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)); + + /* Adjust to account for the 3 bytes of payload data we consumed in the header */ + *fragment_length -= 3; + + 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)); + + *client_protocol_version = (protocol_version[0] * 10) + protocol_version[1]; + + return 0; +} + +int s2n_record_header_parse( + struct s2n_connection *conn, + uint8_t *content_type, + uint16_t *fragment_length) +{ + struct s2n_stuffer *in = &conn->header_in; + + 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)); + + uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; + 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 + * layer version number for the first TLS record. There is some ambiguity here because the client does not know + * what version to use in the record header prior to receiving the ServerHello. Some client implementations may use + * a garbage value(not {03,XX}) in the ClientHello. + * Choose to be lenient to these clients. After protocol negotiation, we will enforce that all record versions + * match the negotiated version. + */ + + 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)); + + /* 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)); + + return 0; +} + +/* In TLS 1.3, handle CCS message as unprotected records all the time. + * https://tools.ietf.org/html/rfc8446#section-5 + * + * In TLS 1.2 and TLS 1.3 Alert messages are plaintext or encrypted + * depending on the context of the connection. If we receive an encrypted + * alert, the record type is TLS_APPLICATION_DATA at this point. It will + * be decrypted and processed in s2n_handshake_io. We may receive a + * plaintext alert if we hit an error before the handshake completed + * (like a certificate failed to validate). + * https://tools.ietf.org/html/rfc8446#section-6 + * + * This function is specific to TLS 1.3 to avoid changing the behavior + * of existing interpretation of TLS 1.2 alerts. */ +static bool s2n_is_tls13_plaintext_content(struct s2n_connection *conn, uint8_t content_type) +{ + return conn->actual_protocol_version == S2N_TLS13 && (content_type == TLS_ALERT || content_type == TLS_CHANGE_CIPHER_SPEC); +} + +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)); + + struct s2n_crypto_parameters *current_client_crypto = conn->client; + struct s2n_crypto_parameters *current_server_crypto = conn->server; + if (s2n_is_tls13_plaintext_content(conn, content_type)) { + conn->client = &conn->initial; + conn->server = &conn->initial; + } + + const struct s2n_cipher_suite *cipher_suite = conn->client->cipher_suite; + uint8_t *implicit_iv = conn->client->client_implicit_iv; + struct s2n_hmac_state *mac = &conn->client->client_record_mac; + uint8_t *sequence_number = conn->client->client_sequence_number; + struct s2n_session_key *session_key = &conn->client->client_key; + + if (conn->mode == S2N_CLIENT) { + cipher_suite = conn->server->cipher_suite; + implicit_iv = conn->server->server_implicit_iv; + mac = &conn->server->server_record_mac; + sequence_number = conn->server->server_sequence_number; + session_key = &conn->server->server_key; + } + + if (s2n_is_tls13_plaintext_content(conn, content_type)) { + conn->client = current_client_crypto; + conn->server = current_server_crypto; + } + + 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)); + break; + case S2N_CBC: + 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)); + break; + case S2N_STREAM: + 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); + break; + } + + return 0; +} + +int s2n_tls13_parse_record_type(struct s2n_stuffer *stuffer, uint8_t *record_type) +{ + uint32_t bytes_left = s2n_stuffer_data_available(stuffer); + + /* From rfc8446 Section 5.4 + * The presence of padding does not change the overall record size + * limitations: the full encoded TLSInnerPlaintext MUST NOT exceed 2^14 + * + 1 octets + * + * Certain versions of Java can generate inner plaintexts with lengths up to + * S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH + 16 (See JDK-8221253) + * However, after the padding is stripped, the result will always be no more than + * S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH - 1 + */ + 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)); + + /* Record type should have values greater than zero. + * If zero, treat as padding, keep reading and wiping from the back + * until a non-zero value is found + */ + *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)); + + /* set the record type */ + 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)); + } + + /* only the original plaintext should remain */ + /* now reset the read cursor at where it should be */ + 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); + + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_record_read.h b/contrib/restricted/aws/s2n/tls/s2n_record_read.h index 1c79e42f73..dd54f3d1fe 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_record_read.h +++ b/contrib/restricted/aws/s2n/tls/s2n_record_read.h @@ -1,55 +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_connection.h" - -int s2n_record_parse_aead( - const struct s2n_cipher_suite *cipher_suite, - struct s2n_connection *conn, - uint8_t content_type, - uint16_t encrypted_length, - uint8_t * implicit_iv, - struct s2n_hmac_state *mac, - uint8_t * sequence_number, - struct s2n_session_key *session_key); -int s2n_record_parse_cbc( - const struct s2n_cipher_suite *cipher_suite, - struct s2n_connection *conn, - uint8_t content_type, - uint16_t encrypted_length, - uint8_t * implicit_iv, - struct s2n_hmac_state *mac, - uint8_t * sequence_number, - struct s2n_session_key *session_key); -int s2n_record_parse_composite( - const struct s2n_cipher_suite *cipher_suite, - struct s2n_connection *conn, - uint8_t content_type, - uint16_t encrypted_length, - uint8_t * implicit_iv, - struct s2n_hmac_state *mac, - uint8_t * sequence_number, - struct s2n_session_key *session_key); -int s2n_record_parse_stream( - const struct s2n_cipher_suite *cipher_suite, - struct s2n_connection *conn, - uint8_t content_type, - uint16_t encrypted_length, - uint8_t * implicit_iv, - struct s2n_hmac_state *mac, - uint8_t * sequence_number, - struct s2n_session_key *session_key); +/* + * 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_connection.h" + +int s2n_record_parse_aead( + const struct s2n_cipher_suite *cipher_suite, + struct s2n_connection *conn, + uint8_t content_type, + uint16_t encrypted_length, + uint8_t * implicit_iv, + struct s2n_hmac_state *mac, + uint8_t * sequence_number, + struct s2n_session_key *session_key); +int s2n_record_parse_cbc( + const struct s2n_cipher_suite *cipher_suite, + struct s2n_connection *conn, + uint8_t content_type, + uint16_t encrypted_length, + uint8_t * implicit_iv, + struct s2n_hmac_state *mac, + uint8_t * sequence_number, + struct s2n_session_key *session_key); +int s2n_record_parse_composite( + const struct s2n_cipher_suite *cipher_suite, + struct s2n_connection *conn, + uint8_t content_type, + uint16_t encrypted_length, + uint8_t * implicit_iv, + struct s2n_hmac_state *mac, + uint8_t * sequence_number, + struct s2n_session_key *session_key); +int s2n_record_parse_stream( + const struct s2n_cipher_suite *cipher_suite, + struct s2n_connection *conn, + uint8_t content_type, + uint16_t encrypted_length, + uint8_t * implicit_iv, + struct s2n_hmac_state *mac, + uint8_t * sequence_number, + struct s2n_session_key *session_key); 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 b613ca6235..2c2c8df1f1 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c +++ b/contrib/restricted/aws/s2n/tls/s2n_record_read_aead.c @@ -1,127 +1,127 @@ -/* - * 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 "crypto/s2n_sequence.h" -#include "crypto/s2n_cipher.h" -#include "crypto/s2n_hmac.h" - -#include "error/s2n_errno.h" - -#include "stuffer/s2n_stuffer.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_crypto.h" -#include "tls/s2n_record.h" -#include "tls/s2n_record_read.h" - -#include "utils/s2n_annotations.h" -#include "utils/s2n_blob.h" -#include "utils/s2n_safety.h" - -int s2n_record_parse_aead( - const struct s2n_cipher_suite *cipher_suite, - struct s2n_connection *conn, - uint8_t content_type, - uint16_t encrypted_length, - uint8_t * implicit_iv, - struct s2n_hmac_state *mac, - uint8_t * sequence_number, - struct s2n_session_key *session_key) -{ - const int is_tls13_record = cipher_suite->record_alg->flags & S2N_TLS13_RECORD_AEAD_NONCE; - /* TLS 1.3 record protection uses a different 5 byte associated data than TLS 1.2's */ - 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); - /* In AEAD mode, the explicit IV is in the record */ - gte_check(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)); - - 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)); - } 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 - * and also used for TLS 1.3 record protection (RFC 8446 Section 5.2). - * - * In these cipher modes, the sequence number (64 bits) is left padded by 4 bytes - * 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)); - for (int i = 0; i < cipher_suite->record_alg->cipher->io.aead.fixed_iv_size; i++) { - S2N_INVARIENT(i <= cipher_suite->record_alg->cipher->io.aead.fixed_iv_size); - aad_iv[i] = aad_iv[i] ^ implicit_iv[i]; - } - } else { - S2N_ERROR(S2N_ERR_INVALID_NONCE_TYPE); - } - - /* Set the IV size to the amount of data written */ - iv.size = s2n_stuffer_data_available(&iv_stuffer); - - 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); - 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)); - } else { - GUARD_AS_POSIX(s2n_aead_aad_init(conn, sequence_number, content_type, payload_length, &ad_stuffer)); - } - - /* Decrypt stuff! */ - /* Skip explicit IV for decryption */ - en.size -= cipher_suite->record_alg->cipher->io.aead.record_iv_size; - 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); - - 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)); - - /* 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)); - - /* 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)); - } - - /* Truncate and wipe the MAC and any padding */ - GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length)); - conn->in_status = PLAINTEXT; - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "crypto/s2n_sequence.h" +#include "crypto/s2n_cipher.h" +#include "crypto/s2n_hmac.h" + +#include "error/s2n_errno.h" + +#include "stuffer/s2n_stuffer.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_crypto.h" +#include "tls/s2n_record.h" +#include "tls/s2n_record_read.h" + +#include "utils/s2n_annotations.h" +#include "utils/s2n_blob.h" +#include "utils/s2n_safety.h" + +int s2n_record_parse_aead( + const struct s2n_cipher_suite *cipher_suite, + struct s2n_connection *conn, + uint8_t content_type, + uint16_t encrypted_length, + uint8_t * implicit_iv, + struct s2n_hmac_state *mac, + uint8_t * sequence_number, + struct s2n_session_key *session_key) +{ + const int is_tls13_record = cipher_suite->record_alg->flags & S2N_TLS13_RECORD_AEAD_NONCE; + /* TLS 1.3 record protection uses a different 5 byte associated data than TLS 1.2's */ + 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); + /* In AEAD mode, the explicit IV is in the record */ + gte_check(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)); + + 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)); + } 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 + * and also used for TLS 1.3 record protection (RFC 8446 Section 5.2). + * + * In these cipher modes, the sequence number (64 bits) is left padded by 4 bytes + * 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)); + for (int i = 0; i < cipher_suite->record_alg->cipher->io.aead.fixed_iv_size; i++) { + S2N_INVARIENT(i <= cipher_suite->record_alg->cipher->io.aead.fixed_iv_size); + aad_iv[i] = aad_iv[i] ^ implicit_iv[i]; + } + } else { + S2N_ERROR(S2N_ERR_INVALID_NONCE_TYPE); + } + + /* Set the IV size to the amount of data written */ + iv.size = s2n_stuffer_data_available(&iv_stuffer); + + 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); + 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)); + } else { + GUARD_AS_POSIX(s2n_aead_aad_init(conn, sequence_number, content_type, payload_length, &ad_stuffer)); + } + + /* Decrypt stuff! */ + /* Skip explicit IV for decryption */ + en.size -= cipher_suite->record_alg->cipher->io.aead.record_iv_size; + 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); + + 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)); + + /* 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)); + + /* 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)); + } + + /* Truncate and wipe the MAC and any padding */ + 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 21d96e8370..9948469593 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_record_read_cbc.c +++ b/contrib/restricted/aws/s2n/tls/s2n_record_read_cbc.c @@ -1,130 +1,130 @@ -/* - * 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 "crypto/s2n_sequence.h" -#include "crypto/s2n_cipher.h" -#include "crypto/s2n_hmac.h" - -#include "error/s2n_errno.h" - -#include "stuffer/s2n_stuffer.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_crypto.h" -#include "tls/s2n_record.h" -#include "tls/s2n_record_read.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_blob.h" - -int s2n_record_parse_cbc( - const struct s2n_cipher_suite *cipher_suite, - struct s2n_connection *conn, - uint8_t content_type, - uint16_t encrypted_length, - uint8_t * implicit_iv, - struct s2n_hmac_state *mac, - uint8_t * sequence_number, - struct s2n_session_key *session_key) -{ - struct s2n_blob iv = {.data = implicit_iv,.size = cipher_suite->record_alg->cipher->io.cbc.record_iv_size }; - uint8_t ivpad[S2N_TLS_MAX_IV_LEN]; - - /* Add the header to the HMAC */ - uint8_t *header = s2n_stuffer_raw_read(&conn->header_in, S2N_TLS_RECORD_HEADER_LENGTH); - notnull_check(header); - - lte_check(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); - encrypted_length -= iv.size; - } - - struct s2n_blob en = {.size = encrypted_length,.data = s2n_stuffer_raw_read(&conn->in, encrypted_length) }; - notnull_check(en.data); - - uint16_t payload_length = encrypted_length; - uint8_t mac_digest_size; - GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size)); - - gte_check(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); - - /* ... and that we have a multiple of the block size */ - eq_check(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); - } - - 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); - } - - /* Subtract the padding length */ - gt_check(en.size, 0); - uint32_t out = 0; - 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)); - - if (conn->actual_protocol_version == S2N_SSLv3) { - GUARD(s2n_hmac_update(mac, header, 1)); - GUARD(s2n_hmac_update(mac, header + 3, 2)); - } else { - 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)); - - /* Padding */ - if (s2n_verify_cbc(conn, mac, &en) < 0) { - GUARD(s2n_stuffer_wipe(&conn->in)); - S2N_ERROR(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)); - - /* 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)); - } - - /* Truncate and wipe the MAC and any padding */ - GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length)); - conn->in_status = PLAINTEXT; - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "crypto/s2n_sequence.h" +#include "crypto/s2n_cipher.h" +#include "crypto/s2n_hmac.h" + +#include "error/s2n_errno.h" + +#include "stuffer/s2n_stuffer.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_crypto.h" +#include "tls/s2n_record.h" +#include "tls/s2n_record_read.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_blob.h" + +int s2n_record_parse_cbc( + const struct s2n_cipher_suite *cipher_suite, + struct s2n_connection *conn, + uint8_t content_type, + uint16_t encrypted_length, + uint8_t * implicit_iv, + struct s2n_hmac_state *mac, + uint8_t * sequence_number, + struct s2n_session_key *session_key) +{ + struct s2n_blob iv = {.data = implicit_iv,.size = cipher_suite->record_alg->cipher->io.cbc.record_iv_size }; + uint8_t ivpad[S2N_TLS_MAX_IV_LEN]; + + /* Add the header to the HMAC */ + uint8_t *header = s2n_stuffer_raw_read(&conn->header_in, S2N_TLS_RECORD_HEADER_LENGTH); + notnull_check(header); + + lte_check(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); + encrypted_length -= iv.size; + } + + struct s2n_blob en = {.size = encrypted_length,.data = s2n_stuffer_raw_read(&conn->in, encrypted_length) }; + notnull_check(en.data); + + uint16_t payload_length = encrypted_length; + uint8_t mac_digest_size; + GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size)); + + gte_check(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); + + /* ... and that we have a multiple of the block size */ + eq_check(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); + } + + 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); + } + + /* Subtract the padding length */ + gt_check(en.size, 0); + uint32_t out = 0; + 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)); + + if (conn->actual_protocol_version == S2N_SSLv3) { + GUARD(s2n_hmac_update(mac, header, 1)); + GUARD(s2n_hmac_update(mac, header + 3, 2)); + } else { + 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)); + + /* Padding */ + if (s2n_verify_cbc(conn, mac, &en) < 0) { + GUARD(s2n_stuffer_wipe(&conn->in)); + S2N_ERROR(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)); + + /* 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)); + } + + /* Truncate and wipe the MAC and any padding */ + 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 a35cc8bf11..3d39bdd8c7 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_record_read_composite.c +++ b/contrib/restricted/aws/s2n/tls/s2n_record_read_composite.c @@ -1,114 +1,114 @@ -/* - * 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 "crypto/s2n_sequence.h" -#include "crypto/s2n_cipher.h" -#include "crypto/s2n_hmac.h" - -#include "error/s2n_errno.h" - -#include "stuffer/s2n_stuffer.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_crypto.h" -#include "tls/s2n_record_read.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_blob.h" - -int s2n_record_parse_composite( - const struct s2n_cipher_suite *cipher_suite, - struct s2n_connection *conn, - uint8_t content_type, - uint16_t encrypted_length, - uint8_t * implicit_iv, - struct s2n_hmac_state *mac, - uint8_t * sequence_number, - struct s2n_session_key *session_key) -{ - /* Don't reduce encrypted length for explicit IV, composite decrypt expects it */ - struct s2n_blob iv = {.data = implicit_iv,.size = cipher_suite->record_alg->cipher->io.comp.record_iv_size }; - uint8_t ivpad[S2N_TLS_MAX_IV_LEN]; - - /* Add the header to the HMAC */ - uint8_t *header = s2n_stuffer_raw_read(&conn->header_in, S2N_TLS_RECORD_HEADER_LENGTH); - notnull_check(header); - - struct s2n_blob en = {.size = encrypted_length,.data = s2n_stuffer_raw_read(&conn->in, encrypted_length) }; - notnull_check(en.data); - - uint16_t payload_length = encrypted_length; - uint8_t mac_digest_size; - GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size)); - - gte_check(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. - * Composite "decrypt" will MAC the actual payload data. - */ - /* 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)); - - gte_check(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)); - payload_length = out; - } - - /* Decrypt stuff! */ - ne_check(en.size, 0); - eq_check(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); - - /* 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))); - - memcpy_check(implicit_iv, ivpad, iv.size); - - /* Subtract the padding length */ - gt_check(en.size, 0); - uint32_t out = 0; - 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)); - - /* 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)); - - /* 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)); - } - - /* Truncate and wipe the MAC and any padding */ - GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length)); - conn->in_status = PLAINTEXT; - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "crypto/s2n_sequence.h" +#include "crypto/s2n_cipher.h" +#include "crypto/s2n_hmac.h" + +#include "error/s2n_errno.h" + +#include "stuffer/s2n_stuffer.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_crypto.h" +#include "tls/s2n_record_read.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_blob.h" + +int s2n_record_parse_composite( + const struct s2n_cipher_suite *cipher_suite, + struct s2n_connection *conn, + uint8_t content_type, + uint16_t encrypted_length, + uint8_t * implicit_iv, + struct s2n_hmac_state *mac, + uint8_t * sequence_number, + struct s2n_session_key *session_key) +{ + /* Don't reduce encrypted length for explicit IV, composite decrypt expects it */ + struct s2n_blob iv = {.data = implicit_iv,.size = cipher_suite->record_alg->cipher->io.comp.record_iv_size }; + uint8_t ivpad[S2N_TLS_MAX_IV_LEN]; + + /* Add the header to the HMAC */ + uint8_t *header = s2n_stuffer_raw_read(&conn->header_in, S2N_TLS_RECORD_HEADER_LENGTH); + notnull_check(header); + + struct s2n_blob en = {.size = encrypted_length,.data = s2n_stuffer_raw_read(&conn->in, encrypted_length) }; + notnull_check(en.data); + + uint16_t payload_length = encrypted_length; + uint8_t mac_digest_size; + GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size)); + + gte_check(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. + * Composite "decrypt" will MAC the actual payload data. + */ + /* 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)); + + gte_check(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)); + payload_length = out; + } + + /* Decrypt stuff! */ + ne_check(en.size, 0); + eq_check(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); + + /* 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))); + + memcpy_check(implicit_iv, ivpad, iv.size); + + /* Subtract the padding length */ + gt_check(en.size, 0); + uint32_t out = 0; + 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)); + + /* 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)); + + /* 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)); + } + + /* Truncate and wipe the MAC and any padding */ + 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 718fb3e8aa..dc6d6cb93e 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_record_read_stream.c +++ b/contrib/restricted/aws/s2n/tls/s2n_record_read_stream.c @@ -1,98 +1,98 @@ -/* - * 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 "crypto/s2n_sequence.h" -#include "crypto/s2n_cipher.h" -#include "crypto/s2n_hmac.h" - -#include "error/s2n_errno.h" - -#include "stuffer/s2n_stuffer.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_crypto.h" -#include "tls/s2n_record_read.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_blob.h" - -int s2n_record_parse_stream( - const struct s2n_cipher_suite *cipher_suite, - struct s2n_connection *conn, - uint8_t content_type, - uint16_t encrypted_length, - uint8_t * implicit_iv, - struct s2n_hmac_state *mac, - uint8_t * sequence_number, - struct s2n_session_key *session_key) -{ - /* Add the header to the HMAC */ - uint8_t *header = s2n_stuffer_raw_read(&conn->header_in, S2N_TLS_RECORD_HEADER_LENGTH); - notnull_check(header); - - struct s2n_blob en = {.size = encrypted_length,.data = s2n_stuffer_raw_read(&conn->in, encrypted_length) }; - notnull_check(en.data); - - uint16_t payload_length = encrypted_length; - uint8_t mac_digest_size; - GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size)); - - gte_check(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)); - - /* 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)); - - if (conn->actual_protocol_version == S2N_SSLv3) { - GUARD(s2n_hmac_update(mac, header, 1)); - GUARD(s2n_hmac_update(mac, header + 3, 2)); - } else { - 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)); - - /* MAC check for streaming ciphers - no padding */ - 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)); - - 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); - } - - /* 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)); - - /* Truncate and wipe the MAC and any padding */ - GUARD(s2n_stuffer_wipe_n(&conn->in, s2n_stuffer_data_available(&conn->in) - payload_length)); - conn->in_status = PLAINTEXT; - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "crypto/s2n_sequence.h" +#include "crypto/s2n_cipher.h" +#include "crypto/s2n_hmac.h" + +#include "error/s2n_errno.h" + +#include "stuffer/s2n_stuffer.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_crypto.h" +#include "tls/s2n_record_read.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_blob.h" + +int s2n_record_parse_stream( + const struct s2n_cipher_suite *cipher_suite, + struct s2n_connection *conn, + uint8_t content_type, + uint16_t encrypted_length, + uint8_t * implicit_iv, + struct s2n_hmac_state *mac, + uint8_t * sequence_number, + struct s2n_session_key *session_key) +{ + /* Add the header to the HMAC */ + uint8_t *header = s2n_stuffer_raw_read(&conn->header_in, S2N_TLS_RECORD_HEADER_LENGTH); + notnull_check(header); + + struct s2n_blob en = {.size = encrypted_length,.data = s2n_stuffer_raw_read(&conn->in, encrypted_length) }; + notnull_check(en.data); + + uint16_t payload_length = encrypted_length; + uint8_t mac_digest_size; + GUARD(s2n_hmac_digest_size(mac->alg, &mac_digest_size)); + + gte_check(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)); + + /* 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)); + + if (conn->actual_protocol_version == S2N_SSLv3) { + GUARD(s2n_hmac_update(mac, header, 1)); + GUARD(s2n_hmac_update(mac, header + 3, 2)); + } else { + 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)); + + /* MAC check for streaming ciphers - no padding */ + 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)); + + 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); + } + + /* 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)); + + /* Truncate and wipe the MAC and any padding */ + 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 4cb2648ffd..df28a9d58e 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_record_write.c +++ b/contrib/restricted/aws/s2n/tls/s2n_record_write.c @@ -1,455 +1,455 @@ -/* - * 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 <stdint.h> -#include <sys/param.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_record.h" -#include "tls/s2n_crypto.h" - -#include "stuffer/s2n_stuffer.h" - -#include "crypto/s2n_sequence.h" -#include "crypto/s2n_cipher.h" -#include "crypto/s2n_hmac.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_random.h" -#include "utils/s2n_blob.h" - -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); - struct s2n_crypto_parameters *active = conn->server; - - if (conn->mode == S2N_CLIENT) { - active = conn->client; - } - - uint8_t extra; - GUARD_AS_RESULT(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 */ - extra += 1; - - if (conn->actual_protocol_version > S2N_TLS10) { - extra += active->cipher_suite->record_alg->cipher->io.cbc.record_iv_size; - } - } else if (active->cipher_suite->record_alg->cipher->type == S2N_AEAD) { - extra += active->cipher_suite->record_alg->cipher->io.aead.tag_size; - extra += active->cipher_suite->record_alg->cipher->io.aead.record_iv_size; - } else if (active->cipher_suite->record_alg->cipher->type == S2N_COMPOSITE && conn->actual_protocol_version > S2N_TLS10) { - extra += active->cipher_suite->record_alg->cipher->io.comp.record_iv_size; - } - - *out = extra; - - return S2N_RESULT_OK; -} - -/* This function returns maximum size of plaintext data to write for the payload. - * Record overheads are not included here. - */ -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); - - *max_fragment_size = MIN(conn->max_outgoing_fragment_length, S2N_TLS_MAXIMUM_FRAGMENT_LENGTH); - - 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); - /* 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); - uint16_t size = min_outgoing_fragment_length; - - const struct s2n_crypto_parameters *active = conn->mode == S2N_CLIENT ? conn->client : conn->server; - - /* Round the fragment size down to be block aligned */ - if (active->cipher_suite->record_alg->cipher->type == S2N_CBC) { - size -= size % active->cipher_suite->record_alg->cipher->io.cbc.block_size; - } else if (active->cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) { - size -= size % active->cipher_suite->record_alg->cipher->io.comp.block_size; - /* Composite digest length */ - size -= active->cipher_suite->record_alg->cipher->io.comp.mac_key_size; - /* Padding length byte */ - size -= 1; - } - - /* 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); - size -= overhead; - - ENSURE(size > 0, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL); - ENSURE(size <= ETH_MTU, S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE); - - *payload_size = size; - - return S2N_RESULT_OK; -} - -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) { - /* 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 - * protocol version in ClientHello, so we're still able to negotiate protocol versions above TLS1.0 */ - record_protocol_version = MIN(record_protocol_version, S2N_TLS10); - } - - /* In accordance to TLS 1.3 spec, https://tools.ietf.org/html/rfc8446#section-5.1 - * tls record version should never be greater than 33 (legacy TLS 1.2 version). - */ - record_protocol_version = MIN(record_protocol_version, S2N_TLS12); - - uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; - 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)); - - return 0; -} - -static inline int s2n_record_encrypt( - struct s2n_connection *conn, - const struct s2n_cipher_suite *cipher_suite, - struct s2n_session_key *session_key, - struct s2n_blob *iv, - struct s2n_blob *aad, - struct s2n_blob *en, - uint8_t *implicit_iv, uint16_t block_size) -{ - notnull_check(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)); - break; - case S2N_CBC: - 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); - } - break; - case S2N_AEAD: - 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)); - - /* 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); - break; - default: - S2N_ERROR(S2N_ERR_CIPHER_TYPE); - break; - } - - return 0; -} - -int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const struct iovec *in, int in_count, size_t offs, size_t to_write) -{ - struct s2n_blob iv = { 0 }; - uint8_t padding = 0; - uint16_t block_size = 0; - uint8_t aad_iv[S2N_TLS_MAX_IV_LEN] = { 0 }; - - /* In TLS 1.3, handle CCS message as unprotected records */ - struct s2n_crypto_parameters *current_client_crypto = conn->client; - struct s2n_crypto_parameters *current_server_crypto = conn->server; - if (conn->actual_protocol_version == S2N_TLS13 && content_type == TLS_CHANGE_CIPHER_SPEC) { - conn->client = &conn->initial; - conn->server = &conn->initial; - } - - uint8_t *sequence_number = conn->server->server_sequence_number; - struct s2n_hmac_state *mac = &conn->server->server_record_mac; - struct s2n_session_key *session_key = &conn->server->server_key; - const struct s2n_cipher_suite *cipher_suite = conn->server->cipher_suite; - uint8_t *implicit_iv = conn->server->server_implicit_iv; - - if (conn->mode == S2N_CLIENT) { - sequence_number = conn->client->client_sequence_number; - mac = &conn->client->client_record_mac; - session_key = &conn->client->client_key; - cipher_suite = conn->client->cipher_suite; - implicit_iv = conn->client->client_implicit_iv; - } - - 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)); - - /* 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)); - 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)); - - /* If we have padding to worry about, figure that out too */ - if (cipher_suite->record_alg->cipher->type == S2N_CBC) { - block_size = cipher_suite->record_alg->cipher->io.cbc.block_size; - if (((data_bytes_to_take + extra) % block_size)) { - padding = block_size - ((data_bytes_to_take + extra) % block_size); - } - } else if (cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) { - block_size = cipher_suite->record_alg->cipher->io.comp.block_size; - } - - /* 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)); - - /* Now that we know the length, start writing the record */ - 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)); - - /* 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)); - - if (conn->actual_protocol_version > S2N_SSLv3) { - 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)); - } - - /* Compute non-payload parts of the MAC(seq num, type, proto vers, fragment length) for composite ciphers. - * Composite "encrypt" will MAC the payload data and fill in padding. - */ - if (cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) { - /* Only fragment length is needed for MAC, but the EVP ctrl function needs fragment length + eiv len. */ - uint16_t payload_and_eiv_len = data_bytes_to_take; - if (conn->actual_protocol_version > S2N_TLS10) { - payload_and_eiv_len += block_size; - } - - /* 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, - 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; - } - - /* Rewrite the length to be the actual fragment length */ - const uint16_t actual_fragment_length = data_bytes_to_take + padding + extra; - /* 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)); - - /* 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)); - - 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)); - } 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)); - 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); - } - - /* 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)); - } else { - GUARD_AS_POSIX(s2n_aead_aad_init(conn, sequence_number, content_type, data_bytes_to_take, &ad_stuffer)); - } - } 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)); - 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. - * - * How? Openssl's AES-CBC stitched encrypt populates the first block of application data with: - * AES(Key, XOR(iv, initial_block)) - * - * If we make initial_block a random block unrelated to random_iv, explicit IV for this record - * is random value based on the two random blobs we just generated: - * AES(Key, XOR(random_iv, explicit_iv_placeholder) == AES(Key, XOR(random_iv, random_iv2)) - * - * NOTE: We can't use the same random IV blob as both the initial block and IV since it will result in: - * AES(Key, XOR(random_iv, random_iv)) == AES(Key, 0), which will be shared by all records in this session. - */ - 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)); - } 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)); - } - } - } - - /* 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)); - - /* Write the plaintext data */ - 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)); - - /* Write the digest */ - uint8_t *digest = s2n_stuffer_raw_write(&conn->out, mac_digest_size); - notnull_check(digest); - - GUARD(s2n_hmac_digest(mac, digest, mac_digest_size)); - 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)); - } - - if (cipher_suite->record_alg->cipher->type == S2N_CBC) { - /* Include padding bytes, each with the value 'p', and - * 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)); - } - } - - /* Rewind to rewrite/encrypt the packet */ - GUARD(s2n_stuffer_rewrite(&conn->out)); - - /* Skip the header */ - 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)); - 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; - } - 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)); - } - /* Encrypt the padding and the padding length byte too */ - encrypted_length += padding + 1; - break; - case S2N_COMPOSITE: - /* Composite CBC expects a pointer starting at explicit IV: [Explicit IV | fragment | MAC | padding | padding len ] - * extra will account for the explicit IV len(if applicable), MAC digest len, padding len + padding byte. - */ - encrypted_length += extra; - break; - default: - break; - } - - /* Check that stuffer have enough space to write encrypted record, because raw_write cannot expand tainted stuffer */ - S2N_ERROR_IF(s2n_stuffer_space_remaining(&conn->out) < encrypted_length, S2N_ERR_RECORD_STUFFER_SIZE); - - /* 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)); - - if (conn->actual_protocol_version == S2N_TLS13 && content_type == TLS_CHANGE_CIPHER_SPEC) { - conn->client = current_client_crypto; - conn->server = current_server_crypto; - } - - conn->wire_bytes_out += actual_fragment_length + S2N_TLS_RECORD_HEADER_LENGTH; - - return data_bytes_to_take; -} - -int s2n_record_write(struct s2n_connection *conn, uint8_t content_type, struct s2n_blob *in) -{ - struct iovec iov; - iov.iov_base = in->data; - iov.iov_len = in->size; - return s2n_record_writev(conn, content_type, &iov, 1, 0, in->size); -} +/* + * 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 <stdint.h> +#include <sys/param.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_record.h" +#include "tls/s2n_crypto.h" + +#include "stuffer/s2n_stuffer.h" + +#include "crypto/s2n_sequence.h" +#include "crypto/s2n_cipher.h" +#include "crypto/s2n_hmac.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_random.h" +#include "utils/s2n_blob.h" + +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); + struct s2n_crypto_parameters *active = conn->server; + + if (conn->mode == S2N_CLIENT) { + active = conn->client; + } + + uint8_t extra; + GUARD_AS_RESULT(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 */ + extra += 1; + + if (conn->actual_protocol_version > S2N_TLS10) { + extra += active->cipher_suite->record_alg->cipher->io.cbc.record_iv_size; + } + } else if (active->cipher_suite->record_alg->cipher->type == S2N_AEAD) { + extra += active->cipher_suite->record_alg->cipher->io.aead.tag_size; + extra += active->cipher_suite->record_alg->cipher->io.aead.record_iv_size; + } else if (active->cipher_suite->record_alg->cipher->type == S2N_COMPOSITE && conn->actual_protocol_version > S2N_TLS10) { + extra += active->cipher_suite->record_alg->cipher->io.comp.record_iv_size; + } + + *out = extra; + + return S2N_RESULT_OK; +} + +/* This function returns maximum size of plaintext data to write for the payload. + * Record overheads are not included here. + */ +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); + + *max_fragment_size = MIN(conn->max_outgoing_fragment_length, S2N_TLS_MAXIMUM_FRAGMENT_LENGTH); + + 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); + /* 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); + uint16_t size = min_outgoing_fragment_length; + + const struct s2n_crypto_parameters *active = conn->mode == S2N_CLIENT ? conn->client : conn->server; + + /* Round the fragment size down to be block aligned */ + if (active->cipher_suite->record_alg->cipher->type == S2N_CBC) { + size -= size % active->cipher_suite->record_alg->cipher->io.cbc.block_size; + } else if (active->cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) { + size -= size % active->cipher_suite->record_alg->cipher->io.comp.block_size; + /* Composite digest length */ + size -= active->cipher_suite->record_alg->cipher->io.comp.mac_key_size; + /* Padding length byte */ + size -= 1; + } + + /* 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); + size -= overhead; + + ENSURE(size > 0, S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL); + ENSURE(size <= ETH_MTU, S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE); + + *payload_size = size; + + return S2N_RESULT_OK; +} + +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) { + /* 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 + * protocol version in ClientHello, so we're still able to negotiate protocol versions above TLS1.0 */ + record_protocol_version = MIN(record_protocol_version, S2N_TLS10); + } + + /* In accordance to TLS 1.3 spec, https://tools.ietf.org/html/rfc8446#section-5.1 + * tls record version should never be greater than 33 (legacy TLS 1.2 version). + */ + record_protocol_version = MIN(record_protocol_version, S2N_TLS12); + + uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; + 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)); + + return 0; +} + +static inline int s2n_record_encrypt( + struct s2n_connection *conn, + const struct s2n_cipher_suite *cipher_suite, + struct s2n_session_key *session_key, + struct s2n_blob *iv, + struct s2n_blob *aad, + struct s2n_blob *en, + uint8_t *implicit_iv, uint16_t block_size) +{ + notnull_check(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)); + break; + case S2N_CBC: + 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); + } + break; + case S2N_AEAD: + 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)); + + /* 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); + break; + default: + S2N_ERROR(S2N_ERR_CIPHER_TYPE); + break; + } + + return 0; +} + +int s2n_record_writev(struct s2n_connection *conn, uint8_t content_type, const struct iovec *in, int in_count, size_t offs, size_t to_write) +{ + struct s2n_blob iv = { 0 }; + uint8_t padding = 0; + uint16_t block_size = 0; + uint8_t aad_iv[S2N_TLS_MAX_IV_LEN] = { 0 }; + + /* In TLS 1.3, handle CCS message as unprotected records */ + struct s2n_crypto_parameters *current_client_crypto = conn->client; + struct s2n_crypto_parameters *current_server_crypto = conn->server; + if (conn->actual_protocol_version == S2N_TLS13 && content_type == TLS_CHANGE_CIPHER_SPEC) { + conn->client = &conn->initial; + conn->server = &conn->initial; + } + + uint8_t *sequence_number = conn->server->server_sequence_number; + struct s2n_hmac_state *mac = &conn->server->server_record_mac; + struct s2n_session_key *session_key = &conn->server->server_key; + const struct s2n_cipher_suite *cipher_suite = conn->server->cipher_suite; + uint8_t *implicit_iv = conn->server->server_implicit_iv; + + if (conn->mode == S2N_CLIENT) { + sequence_number = conn->client->client_sequence_number; + mac = &conn->client->client_record_mac; + session_key = &conn->client->client_key; + cipher_suite = conn->client->cipher_suite; + implicit_iv = conn->client->client_implicit_iv; + } + + 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)); + + /* 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)); + 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)); + + /* If we have padding to worry about, figure that out too */ + if (cipher_suite->record_alg->cipher->type == S2N_CBC) { + block_size = cipher_suite->record_alg->cipher->io.cbc.block_size; + if (((data_bytes_to_take + extra) % block_size)) { + padding = block_size - ((data_bytes_to_take + extra) % block_size); + } + } else if (cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) { + block_size = cipher_suite->record_alg->cipher->io.comp.block_size; + } + + /* 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)); + + /* Now that we know the length, start writing the record */ + 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)); + + /* 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)); + + if (conn->actual_protocol_version > S2N_SSLv3) { + 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)); + } + + /* Compute non-payload parts of the MAC(seq num, type, proto vers, fragment length) for composite ciphers. + * Composite "encrypt" will MAC the payload data and fill in padding. + */ + if (cipher_suite->record_alg->cipher->type == S2N_COMPOSITE) { + /* Only fragment length is needed for MAC, but the EVP ctrl function needs fragment length + eiv len. */ + uint16_t payload_and_eiv_len = data_bytes_to_take; + if (conn->actual_protocol_version > S2N_TLS10) { + payload_and_eiv_len += block_size; + } + + /* 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, + 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; + } + + /* Rewrite the length to be the actual fragment length */ + const uint16_t actual_fragment_length = data_bytes_to_take + padding + extra; + /* 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)); + + /* 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)); + + 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)); + } 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)); + 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); + } + + /* 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)); + } else { + GUARD_AS_POSIX(s2n_aead_aad_init(conn, sequence_number, content_type, data_bytes_to_take, &ad_stuffer)); + } + } 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)); + 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. + * + * How? Openssl's AES-CBC stitched encrypt populates the first block of application data with: + * AES(Key, XOR(iv, initial_block)) + * + * If we make initial_block a random block unrelated to random_iv, explicit IV for this record + * is random value based on the two random blobs we just generated: + * AES(Key, XOR(random_iv, explicit_iv_placeholder) == AES(Key, XOR(random_iv, random_iv2)) + * + * NOTE: We can't use the same random IV blob as both the initial block and IV since it will result in: + * AES(Key, XOR(random_iv, random_iv)) == AES(Key, 0), which will be shared by all records in this session. + */ + 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)); + } 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)); + } + } + } + + /* 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)); + + /* Write the plaintext data */ + 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)); + + /* Write the digest */ + uint8_t *digest = s2n_stuffer_raw_write(&conn->out, mac_digest_size); + notnull_check(digest); + + GUARD(s2n_hmac_digest(mac, digest, mac_digest_size)); + 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)); + } + + if (cipher_suite->record_alg->cipher->type == S2N_CBC) { + /* Include padding bytes, each with the value 'p', and + * 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)); + } + } + + /* Rewind to rewrite/encrypt the packet */ + GUARD(s2n_stuffer_rewrite(&conn->out)); + + /* Skip the header */ + 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)); + 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; + } + 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)); + } + /* Encrypt the padding and the padding length byte too */ + encrypted_length += padding + 1; + break; + case S2N_COMPOSITE: + /* Composite CBC expects a pointer starting at explicit IV: [Explicit IV | fragment | MAC | padding | padding len ] + * extra will account for the explicit IV len(if applicable), MAC digest len, padding len + padding byte. + */ + encrypted_length += extra; + break; + default: + break; + } + + /* Check that stuffer have enough space to write encrypted record, because raw_write cannot expand tainted stuffer */ + S2N_ERROR_IF(s2n_stuffer_space_remaining(&conn->out) < encrypted_length, S2N_ERR_RECORD_STUFFER_SIZE); + + /* 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)); + + if (conn->actual_protocol_version == S2N_TLS13 && content_type == TLS_CHANGE_CIPHER_SPEC) { + conn->client = current_client_crypto; + conn->server = current_server_crypto; + } + + conn->wire_bytes_out += actual_fragment_length + S2N_TLS_RECORD_HEADER_LENGTH; + + return data_bytes_to_take; +} + +int s2n_record_write(struct s2n_connection *conn, uint8_t content_type, struct s2n_blob *in) +{ + struct iovec iov; + iov.iov_base = in->data; + iov.iov_len = in->size; + return s2n_record_writev(conn, content_type, &iov, 1, 0, in->size); +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_recv.c b/contrib/restricted/aws/s2n/tls/s2n_recv.c index e04b752fe8..8d0d04d4f0 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_recv.c +++ b/contrib/restricted/aws/s2n/tls/s2n_recv.c @@ -1,229 +1,229 @@ -/* - * 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> - -/* Use usleep */ -#define _XOPEN_SOURCE 500 -#include <unistd.h> - -#include <errno.h> -#include <s2n.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_handshake.h" -#include "tls/s2n_record.h" -#include "tls/s2n_resume.h" -#include "tls/s2n_alerts.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_post_handshake.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_socket.h" -#include "utils/s2n_safety.h" -#include "utils/s2n_blob.h" - -S2N_RESULT s2n_read_in_bytes(struct s2n_connection *conn, struct s2n_stuffer *output, uint32_t length) -{ - while (s2n_stuffer_data_available(output) < length) { - uint32_t remaining = length - s2n_stuffer_data_available(output); - - errno = 0; - int r = s2n_connection_recv_stuffer(output, conn, remaining); - if (r == 0) { - conn->closed = 1; - BAIL(S2N_ERR_CLOSED); - } else if (r < 0) { - if (errno == EWOULDBLOCK || errno == EAGAIN) { - BAIL(S2N_ERR_IO_BLOCKED); - } - BAIL(S2N_ERR_IO); - } - conn->wire_bytes_in += r; - } - - return S2N_RESULT_OK; -} - -int s2n_read_full_record(struct s2n_connection *conn, uint8_t * record_type, int *isSSLv2) -{ - *isSSLv2 = 0; - - /* If the record has already been decrypted, then leave it alone */ - if (conn->in_status == PLAINTEXT) { - /* Only application data packets count as plaintext */ - *record_type = TLS_APPLICATION_DATA; - return S2N_SUCCESS; - } - 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)); - - uint16_t fragment_length; - - /* If the first bit is set then this is an SSLv2 record */ - if (conn->header_in.blob.data[0] & 0x80) { - 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(); - } - } else { - if (s2n_record_header_parse(conn, record_type, &fragment_length) < 0) { - GUARD(s2n_connection_kill(conn)); - S2N_ERROR_PRESERVE_ERRNO(); - } - } - - /* Read enough to have the whole record */ - GUARD_AS_POSIX(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(); - } - - /* In TLS 1.3, encrypted handshake records would appear to be of record type - * TLS_APPLICATION_DATA. The actual record content type is found after the encrypted - * is decrypted. - */ - if (conn->actual_protocol_version == S2N_TLS13 && *record_type == TLS_APPLICATION_DATA) { - GUARD(s2n_tls13_parse_record_type(&conn->in, record_type)); - } - - return 0; -} - -ssize_t s2n_recv(struct s2n_connection * conn, void *buf, ssize_t size, s2n_blocked_status * blocked) -{ - ssize_t bytes_read = 0; - struct s2n_blob out = {.data = (uint8_t *) buf }; - - if (conn->closed) { - return 0; - } - *blocked = S2N_BLOCKED_ON_READ; - - S2N_ERROR_IF(conn->config->quic_enabled, S2N_ERR_UNSUPPORTED_WITH_QUIC); - - while (size && !conn->closed) { - int isSSLv2 = 0; - uint8_t record_type; - int r = s2n_read_full_record(conn, &record_type, &isSSLv2); - if (r < 0) { - if (s2n_errno == S2N_ERR_CLOSED) { - *blocked = S2N_NOT_BLOCKED; - if (!bytes_read) { - return 0; - } else { - return bytes_read; - } - } - - /* Don't propagate the error if we already read some bytes */ - if (s2n_errno == S2N_ERR_IO_BLOCKED && bytes_read) { - s2n_errno = S2N_ERR_OK; - return bytes_read; - } - - /* If we get here, it's an error condition */ - if (s2n_errno != S2N_ERR_IO_BLOCKED && s2n_allowed_to_cache_connection(conn) && conn->session_id_len) { - conn->config->cache_delete(conn, conn->config->cache_delete_data, conn->session_id, conn->session_id_len); - } - - S2N_ERROR_PRESERVE_ERRNO(); - } - - S2N_ERROR_IF(isSSLv2, S2N_ERR_BAD_MESSAGE); - - if (record_type != TLS_APPLICATION_DATA) { - switch (record_type) - { - case TLS_ALERT: - GUARD(s2n_process_alert_fragment(conn)); - GUARD(s2n_flush(conn, blocked)); - break; - case TLS_HANDSHAKE: - GUARD(s2n_post_handshake_recv(conn)); - break; - } - GUARD(s2n_stuffer_wipe(&conn->header_in)); - 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)); - bytes_read += out.size; - - out.data += out.size; - size -= out.size; - - /* 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)); - conn->in_status = ENCRYPTED; - } - - /* If we've read some data, return it */ - if (bytes_read) { - break; - } - } - - if (s2n_stuffer_data_available(&conn->in) == 0) { - *blocked = S2N_NOT_BLOCKED; - } - - return bytes_read; -} - -uint32_t s2n_peek(struct s2n_connection *conn) { - return s2n_stuffer_data_available(&conn->in); -} - -int s2n_recv_close_notify(struct s2n_connection *conn, s2n_blocked_status * blocked) -{ - uint8_t record_type; - int isSSLv2; - *blocked = S2N_BLOCKED_ON_READ; - - 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)); - - *blocked = S2N_NOT_BLOCKED; - return 0; -} - +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <sys/param.h> + +/* Use usleep */ +#define _XOPEN_SOURCE 500 +#include <unistd.h> + +#include <errno.h> +#include <s2n.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_handshake.h" +#include "tls/s2n_record.h" +#include "tls/s2n_resume.h" +#include "tls/s2n_alerts.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_post_handshake.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_socket.h" +#include "utils/s2n_safety.h" +#include "utils/s2n_blob.h" + +S2N_RESULT s2n_read_in_bytes(struct s2n_connection *conn, struct s2n_stuffer *output, uint32_t length) +{ + while (s2n_stuffer_data_available(output) < length) { + uint32_t remaining = length - s2n_stuffer_data_available(output); + + errno = 0; + int r = s2n_connection_recv_stuffer(output, conn, remaining); + if (r == 0) { + conn->closed = 1; + BAIL(S2N_ERR_CLOSED); + } else if (r < 0) { + if (errno == EWOULDBLOCK || errno == EAGAIN) { + BAIL(S2N_ERR_IO_BLOCKED); + } + BAIL(S2N_ERR_IO); + } + conn->wire_bytes_in += r; + } + + return S2N_RESULT_OK; +} + +int s2n_read_full_record(struct s2n_connection *conn, uint8_t * record_type, int *isSSLv2) +{ + *isSSLv2 = 0; + + /* If the record has already been decrypted, then leave it alone */ + if (conn->in_status == PLAINTEXT) { + /* Only application data packets count as plaintext */ + *record_type = TLS_APPLICATION_DATA; + return S2N_SUCCESS; + } + 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)); + + uint16_t fragment_length; + + /* If the first bit is set then this is an SSLv2 record */ + if (conn->header_in.blob.data[0] & 0x80) { + 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(); + } + } else { + if (s2n_record_header_parse(conn, record_type, &fragment_length) < 0) { + GUARD(s2n_connection_kill(conn)); + S2N_ERROR_PRESERVE_ERRNO(); + } + } + + /* Read enough to have the whole record */ + GUARD_AS_POSIX(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(); + } + + /* In TLS 1.3, encrypted handshake records would appear to be of record type + * TLS_APPLICATION_DATA. The actual record content type is found after the encrypted + * is decrypted. + */ + if (conn->actual_protocol_version == S2N_TLS13 && *record_type == TLS_APPLICATION_DATA) { + GUARD(s2n_tls13_parse_record_type(&conn->in, record_type)); + } + + return 0; +} + +ssize_t s2n_recv(struct s2n_connection * conn, void *buf, ssize_t size, s2n_blocked_status * blocked) +{ + ssize_t bytes_read = 0; + struct s2n_blob out = {.data = (uint8_t *) buf }; + + if (conn->closed) { + return 0; + } + *blocked = S2N_BLOCKED_ON_READ; + + S2N_ERROR_IF(conn->config->quic_enabled, S2N_ERR_UNSUPPORTED_WITH_QUIC); + + while (size && !conn->closed) { + int isSSLv2 = 0; + uint8_t record_type; + int r = s2n_read_full_record(conn, &record_type, &isSSLv2); + if (r < 0) { + if (s2n_errno == S2N_ERR_CLOSED) { + *blocked = S2N_NOT_BLOCKED; + if (!bytes_read) { + return 0; + } else { + return bytes_read; + } + } + + /* Don't propagate the error if we already read some bytes */ + if (s2n_errno == S2N_ERR_IO_BLOCKED && bytes_read) { + s2n_errno = S2N_ERR_OK; + return bytes_read; + } + + /* If we get here, it's an error condition */ + if (s2n_errno != S2N_ERR_IO_BLOCKED && s2n_allowed_to_cache_connection(conn) && conn->session_id_len) { + conn->config->cache_delete(conn, conn->config->cache_delete_data, conn->session_id, conn->session_id_len); + } + + S2N_ERROR_PRESERVE_ERRNO(); + } + + S2N_ERROR_IF(isSSLv2, S2N_ERR_BAD_MESSAGE); + + if (record_type != TLS_APPLICATION_DATA) { + switch (record_type) + { + case TLS_ALERT: + GUARD(s2n_process_alert_fragment(conn)); + GUARD(s2n_flush(conn, blocked)); + break; + case TLS_HANDSHAKE: + GUARD(s2n_post_handshake_recv(conn)); + break; + } + GUARD(s2n_stuffer_wipe(&conn->header_in)); + 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)); + bytes_read += out.size; + + out.data += out.size; + size -= out.size; + + /* 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)); + conn->in_status = ENCRYPTED; + } + + /* If we've read some data, return it */ + if (bytes_read) { + break; + } + } + + if (s2n_stuffer_data_available(&conn->in) == 0) { + *blocked = S2N_NOT_BLOCKED; + } + + return bytes_read; +} + +uint32_t s2n_peek(struct s2n_connection *conn) { + return s2n_stuffer_data_available(&conn->in); +} + +int s2n_recv_close_notify(struct s2n_connection *conn, s2n_blocked_status * blocked) +{ + uint8_t record_type; + int isSSLv2; + *blocked = S2N_BLOCKED_ON_READ; + + 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)); + + *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 20dc850a9f..f4571bf042 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_resume.c +++ b/contrib/restricted/aws/s2n/tls/s2n_resume.c @@ -1,712 +1,712 @@ -/* - * 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 <math.h> - -#include <s2n.h> - -#include "error/s2n_errno.h" -#include "stuffer/s2n_stuffer.h" -#include "utils/s2n_safety.h" -#include "utils/s2n_blob.h" -#include "utils/s2n_random.h" -#include "utils/s2n_set.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_resume.h" -#include "tls/s2n_crypto.h" -#include "tls/s2n_tls.h" - -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) { - return 0; - } - - struct s2n_config *config = conn->config; - - notnull_check(config); - return config->use_session_cache; -} - -static int s2n_serialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *to) -{ - uint64_t now; - - S2N_ERROR_IF(s2n_stuffer_space_remaining(to) < S2N_STATE_SIZE_IN_BYTES, S2N_ERR_STUFFER_IS_FULL); - - /* Get the time */ - 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)); - - return 0; -} - -static int s2n_deserialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *from) -{ - uint8_t format; - uint8_t protocol_version; - uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN]; - - S2N_ERROR_IF(s2n_stuffer_data_available(from) < S2N_STATE_SIZE_IN_BYTES, S2N_ERR_STUFFER_OUT_OF_DATA); - - GUARD(s2n_stuffer_read_uint8(from, &format)); - S2N_ERROR_IF(format != S2N_SERIALIZED_FORMAT_VERSION, S2N_ERR_INVALID_SERIALIZED_SESSION_STATE); - - 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)); - 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)); - - uint64_t then; - 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)); - - return 0; -} - -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)); - } 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)); - } - - /* Serialize session state */ - GUARD(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); - } - - uint8_t format; - uint64_t then; - - GUARD(s2n_stuffer_read_uint8(from, &format)); - if (format != S2N_SERIALIZED_FORMAT_VERSION) { - S2N_ERROR(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE); - } - - GUARD(s2n_stuffer_read_uint8(from, &conn->actual_protocol_version)); - - 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)); - - GUARD(s2n_stuffer_read_uint64(from, &then)); - - /* Last but not least, put the master secret in place */ - GUARD(s2n_stuffer_read_bytes(from, conn->secure.master_secret, S2N_TLS_SECRET_LEN)); - - return 0; -} - -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)); - - 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); - } - - conn->session_id_len = session_id_len; - GUARD(s2n_stuffer_read_bytes(from, conn->session_id, session_id_len)); - - GUARD(s2n_client_deserialize_session_state(conn, from)); - - return 0; -} - -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)); - - if (session_ticket_len == 0 || session_ticket_len > s2n_stuffer_data_available(from)) { - S2N_ERROR(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE); - } - - GUARD(s2n_realloc(&conn->client_ticket, session_ticket_len)); - GUARD(s2n_stuffer_read(from, &conn->client_ticket)); - - GUARD(s2n_client_deserialize_session_state(conn, from)); - - return 0; -} - -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)); - - switch (format) { - case S2N_STATE_WITH_SESSION_ID: - 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)); - break; - default: - S2N_ERROR(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE); - } - - return 0; -} - -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 }; - struct s2n_blob entry = {0}; - GUARD(s2n_blob_init(&entry, data, S2N_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); - } - 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)); - - return 0; -} - -int s2n_store_to_cache(struct s2n_connection *conn) -{ - uint8_t data[S2N_TICKET_SIZE_IN_BYTES] = { 0 }; - struct s2n_blob entry = {0}; - GUARD(s2n_blob_init(&entry, data, S2N_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); - - GUARD(s2n_stuffer_init(&to, &entry)); - GUARD(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; -} - -int s2n_connection_set_session(struct s2n_connection *conn, const uint8_t *session, size_t length) -{ - notnull_check(conn); - notnull_check(session); - - DEFER_CLEANUP(struct s2n_blob session_data = {0}, s2n_free); - GUARD(s2n_alloc(&session_data, length)); - 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)); - return 0; -} - -int s2n_connection_get_session(struct s2n_connection *conn, uint8_t *session, size_t max_length) -{ - notnull_check(conn); - notnull_check(session); - - int len = s2n_connection_get_session_length(conn); - - if (len == 0) { - return 0; - } - - 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)); - - struct s2n_stuffer to = {0}; - GUARD(s2n_stuffer_init(&to, &serialized_data)); - 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); - 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) -{ - /* Session resumption using session ticket "format (1) + session_ticket_len + session_ticket + session state" */ - 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; - } -} - -int s2n_connection_is_session_resumed(struct s2n_connection *conn) -{ - notnull_check(conn); - return IS_RESUMPTION_HANDSHAKE(conn->handshake.handshake_type) ? 1 : 0; -} - -int s2n_connection_is_ocsp_stapled(struct s2n_connection *conn) -{ - notnull_check(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); - } -} - -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); - - uint32_t ticket_keys_len = 0; - GUARD_AS_POSIX(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)); - uint64_t key_intro_time = ticket_key->intro_timestamp; - - if (key_intro_time < now - && now < key_intro_time + config->encrypt_decrypt_key_lifetime_in_nanos) { - return 1; - } - } - - return 0; -} - -/* This function is used in s2n_get_ticket_encrypt_decrypt_key to compute the weight - * of the keys and to choose a single key from all of the encrypt-decrypt keys. - * Higher the weight of the key, higher the probability of being picked. - */ -int s2n_compute_weight_of_encrypt_decrypt_keys(struct s2n_config *config, - uint8_t *encrypt_decrypt_keys_index, - uint8_t num_encrypt_decrypt_keys, - uint64_t now) -{ - double total_weight = 0; - struct s2n_ticket_key_weight ticket_keys_weight[S2N_MAX_TICKET_KEYS]; - struct s2n_ticket_key *ticket_key = NULL; - - /* 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)); - - 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); - - /* The % of encryption using this key is linearly increasing */ - if (now < key_encryption_peak_time) { - ticket_keys_weight[i].key_weight = now - key_intro_time; - } else { - /* The % of encryption using this key is linearly decreasing */ - ticket_keys_weight[i].key_weight = (config->encrypt_decrypt_key_lifetime_in_nanos / 2) - (now - key_encryption_peak_time); - } - - ticket_keys_weight[i].key_index = encrypt_decrypt_keys_index[i]; - total_weight += ticket_keys_weight[i].key_weight; - } - - /* 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)); - double random = (double)random_int / (double)pow(2, 53); - - /* Compute cumulative weight of encrypt-decrypt keys */ - for (int i = 0; i < num_encrypt_decrypt_keys; i++) { - ticket_keys_weight[i].key_weight = ticket_keys_weight[i].key_weight / total_weight; - - if (i > 0) { - ticket_keys_weight[i].key_weight += ticket_keys_weight[i - 1].key_weight; - } - - if (ticket_keys_weight[i].key_weight > random) { - return ticket_keys_weight[i].key_index; - } - } - - S2N_ERROR(S2N_ERR_ENCRYPT_DECRYPT_KEY_SELECTION_FAILED); -} - -/* This function is used in s2n_encrypt_session_ticket in order for s2n to - * choose a key in encrypt-decrypt state from all of the keys added to config - */ -struct s2n_ticket_key *s2n_get_ticket_encrypt_decrypt_key(struct s2n_config *config) -{ - uint8_t num_encrypt_decrypt_keys = 0; - uint8_t encrypt_decrypt_keys_index[S2N_MAX_TICKET_KEYS] = { 0 }; - 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); - - uint32_t ticket_keys_len = 0; - GUARD_RESULT_PTR(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)); - uint64_t key_intro_time = ticket_key->intro_timestamp; - - if (key_intro_time < now - && now < key_intro_time + config->encrypt_decrypt_key_lifetime_in_nanos) { - encrypt_decrypt_keys_index[num_encrypt_decrypt_keys] = idx; - num_encrypt_decrypt_keys++; - } - } - - if (num_encrypt_decrypt_keys == 0) { - S2N_ERROR_PTR(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)); - 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)); - - GUARD_RESULT_PTR(s2n_set_get(config->ticket_keys, idx, (void **)&ticket_key)); - return ticket_key; -} - -/* This function is used in s2n_decrypt_session_ticket in order for s2n to - * find the matching key that was used for encryption. - */ -struct s2n_ticket_key *s2n_find_ticket_key(struct s2n_config *config, const uint8_t *name) -{ - 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); - - uint32_t ticket_keys_len = 0; - GUARD_RESULT_PTR(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)); - - if (memcmp(ticket_key->key_name, name, S2N_TICKET_KEY_NAME_LEN) == 0) { - - /* Check to see if the key has expired */ - if (now >= ticket_key->intro_timestamp + - config->encrypt_decrypt_key_lifetime_in_nanos + config->decrypt_key_lifetime_in_nanos) { - s2n_config_wipe_expired_ticket_crypto_keys(config, i); - - return NULL; - } - - return ticket_key; - } - } - - return NULL; -} - -int s2n_encrypt_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *to) -{ - struct s2n_ticket_key *key; - struct s2n_session_key aes_ticket_key = {0}; - struct s2n_blob aes_key_blob = {0}; - - 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))); - - 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))); - 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)); - - GUARD_AS_POSIX(s2n_get_public_random_data(&iv)); - 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)); - - 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_init(&state, &state_blob)); - GUARD(s2n_serialize_resumption_state(conn, &state)); - - GUARD(s2n_aes256_gcm.io.aead.encrypt(&aes_ticket_key, &iv, &aad_blob, &state_blob, &state_blob)); - - GUARD(s2n_stuffer_write(to, &state_blob)); - - GUARD(s2n_aes256_gcm.destroy_key(&aes_ticket_key)); - GUARD(s2n_session_key_free(&aes_ticket_key)); - - return 0; -} - -int s2n_decrypt_session_ticket(struct s2n_connection *conn) -{ - 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))); - - 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))); - 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)); - - 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)); - - 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)); - - uint64_t now; - 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. - */ - if (now >= key->intro_timestamp + conn->config->encrypt_decrypt_key_lifetime_in_nanos) { - /* 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; - } - } - - return 0; -} - -int s2n_encrypt_session_cache(struct s2n_connection *conn, struct s2n_stuffer *to) -{ - 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; - struct s2n_session_key aes_ticket_key = {0}; - struct s2n_blob aes_key_blob = {0}; - - uint8_t key_name[S2N_TICKET_KEY_NAME_LEN] = {0}; - - uint8_t iv_data[S2N_TLS_GCM_IV_LEN] = { 0 }; - struct s2n_blob iv = {0}; - 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))); - 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))); - - 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)); - - 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)); - - GUARD(s2n_aes256_gcm.destroy_key(&aes_ticket_key)); - GUARD(s2n_session_key_free(&aes_ticket_key)); - - return 0; -} - -/* This function is used to remove all or just one expired key from server config */ -int s2n_config_wipe_expired_ticket_crypto_keys(struct s2n_config *config, int8_t expired_key_index) -{ - int num_of_expired_keys = 0; - int expired_keys_index[S2N_MAX_TICKET_KEYS]; - struct s2n_ticket_key *ticket_key = NULL; - - if (expired_key_index != -1) { - expired_keys_index[num_of_expired_keys] = expired_key_index; - num_of_expired_keys++; - - goto end; - } - - uint64_t now; - GUARD(config->wall_clock(config->sys_clock_ctx, &now)); - notnull_check(config->ticket_keys); - - uint32_t ticket_keys_len = 0; - GUARD_AS_POSIX(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)); - 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; - num_of_expired_keys++; - } - } - -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)); - } - - return 0; -} - - -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)); - return S2N_SUCCESS; -} +/* + * 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 <math.h> + +#include <s2n.h> + +#include "error/s2n_errno.h" +#include "stuffer/s2n_stuffer.h" +#include "utils/s2n_safety.h" +#include "utils/s2n_blob.h" +#include "utils/s2n_random.h" +#include "utils/s2n_set.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_resume.h" +#include "tls/s2n_crypto.h" +#include "tls/s2n_tls.h" + +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) { + return 0; + } + + struct s2n_config *config = conn->config; + + notnull_check(config); + return config->use_session_cache; +} + +static int s2n_serialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *to) +{ + uint64_t now; + + S2N_ERROR_IF(s2n_stuffer_space_remaining(to) < S2N_STATE_SIZE_IN_BYTES, S2N_ERR_STUFFER_IS_FULL); + + /* Get the time */ + 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)); + + return 0; +} + +static int s2n_deserialize_resumption_state(struct s2n_connection *conn, struct s2n_stuffer *from) +{ + uint8_t format; + uint8_t protocol_version; + uint8_t cipher_suite[S2N_TLS_CIPHER_SUITE_LEN]; + + S2N_ERROR_IF(s2n_stuffer_data_available(from) < S2N_STATE_SIZE_IN_BYTES, S2N_ERR_STUFFER_OUT_OF_DATA); + + GUARD(s2n_stuffer_read_uint8(from, &format)); + S2N_ERROR_IF(format != S2N_SERIALIZED_FORMAT_VERSION, S2N_ERR_INVALID_SERIALIZED_SESSION_STATE); + + 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)); + 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)); + + uint64_t then; + 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)); + + return 0; +} + +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)); + } 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)); + } + + /* Serialize session state */ + GUARD(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); + } + + uint8_t format; + uint64_t then; + + GUARD(s2n_stuffer_read_uint8(from, &format)); + if (format != S2N_SERIALIZED_FORMAT_VERSION) { + S2N_ERROR(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE); + } + + GUARD(s2n_stuffer_read_uint8(from, &conn->actual_protocol_version)); + + 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)); + + GUARD(s2n_stuffer_read_uint64(from, &then)); + + /* Last but not least, put the master secret in place */ + GUARD(s2n_stuffer_read_bytes(from, conn->secure.master_secret, S2N_TLS_SECRET_LEN)); + + return 0; +} + +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)); + + 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); + } + + conn->session_id_len = session_id_len; + GUARD(s2n_stuffer_read_bytes(from, conn->session_id, session_id_len)); + + GUARD(s2n_client_deserialize_session_state(conn, from)); + + return 0; +} + +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)); + + if (session_ticket_len == 0 || session_ticket_len > s2n_stuffer_data_available(from)) { + S2N_ERROR(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE); + } + + GUARD(s2n_realloc(&conn->client_ticket, session_ticket_len)); + GUARD(s2n_stuffer_read(from, &conn->client_ticket)); + + GUARD(s2n_client_deserialize_session_state(conn, from)); + + return 0; +} + +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)); + + switch (format) { + case S2N_STATE_WITH_SESSION_ID: + 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)); + break; + default: + S2N_ERROR(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE); + } + + return 0; +} + +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 }; + struct s2n_blob entry = {0}; + GUARD(s2n_blob_init(&entry, data, S2N_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); + } + 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)); + + return 0; +} + +int s2n_store_to_cache(struct s2n_connection *conn) +{ + uint8_t data[S2N_TICKET_SIZE_IN_BYTES] = { 0 }; + struct s2n_blob entry = {0}; + GUARD(s2n_blob_init(&entry, data, S2N_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); + + GUARD(s2n_stuffer_init(&to, &entry)); + GUARD(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; +} + +int s2n_connection_set_session(struct s2n_connection *conn, const uint8_t *session, size_t length) +{ + notnull_check(conn); + notnull_check(session); + + DEFER_CLEANUP(struct s2n_blob session_data = {0}, s2n_free); + GUARD(s2n_alloc(&session_data, length)); + 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)); + return 0; +} + +int s2n_connection_get_session(struct s2n_connection *conn, uint8_t *session, size_t max_length) +{ + notnull_check(conn); + notnull_check(session); + + int len = s2n_connection_get_session_length(conn); + + if (len == 0) { + return 0; + } + + 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)); + + struct s2n_stuffer to = {0}; + GUARD(s2n_stuffer_init(&to, &serialized_data)); + 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); + 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) +{ + /* Session resumption using session ticket "format (1) + session_ticket_len + session_ticket + session state" */ + 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; + } +} + +int s2n_connection_is_session_resumed(struct s2n_connection *conn) +{ + notnull_check(conn); + return IS_RESUMPTION_HANDSHAKE(conn->handshake.handshake_type) ? 1 : 0; +} + +int s2n_connection_is_ocsp_stapled(struct s2n_connection *conn) +{ + notnull_check(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); + } +} + +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); + + uint32_t ticket_keys_len = 0; + GUARD_AS_POSIX(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)); + uint64_t key_intro_time = ticket_key->intro_timestamp; + + if (key_intro_time < now + && now < key_intro_time + config->encrypt_decrypt_key_lifetime_in_nanos) { + return 1; + } + } + + return 0; +} + +/* This function is used in s2n_get_ticket_encrypt_decrypt_key to compute the weight + * of the keys and to choose a single key from all of the encrypt-decrypt keys. + * Higher the weight of the key, higher the probability of being picked. + */ +int s2n_compute_weight_of_encrypt_decrypt_keys(struct s2n_config *config, + uint8_t *encrypt_decrypt_keys_index, + uint8_t num_encrypt_decrypt_keys, + uint64_t now) +{ + double total_weight = 0; + struct s2n_ticket_key_weight ticket_keys_weight[S2N_MAX_TICKET_KEYS]; + struct s2n_ticket_key *ticket_key = NULL; + + /* 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)); + + 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); + + /* The % of encryption using this key is linearly increasing */ + if (now < key_encryption_peak_time) { + ticket_keys_weight[i].key_weight = now - key_intro_time; + } else { + /* The % of encryption using this key is linearly decreasing */ + ticket_keys_weight[i].key_weight = (config->encrypt_decrypt_key_lifetime_in_nanos / 2) - (now - key_encryption_peak_time); + } + + ticket_keys_weight[i].key_index = encrypt_decrypt_keys_index[i]; + total_weight += ticket_keys_weight[i].key_weight; + } + + /* 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)); + double random = (double)random_int / (double)pow(2, 53); + + /* Compute cumulative weight of encrypt-decrypt keys */ + for (int i = 0; i < num_encrypt_decrypt_keys; i++) { + ticket_keys_weight[i].key_weight = ticket_keys_weight[i].key_weight / total_weight; + + if (i > 0) { + ticket_keys_weight[i].key_weight += ticket_keys_weight[i - 1].key_weight; + } + + if (ticket_keys_weight[i].key_weight > random) { + return ticket_keys_weight[i].key_index; + } + } + + S2N_ERROR(S2N_ERR_ENCRYPT_DECRYPT_KEY_SELECTION_FAILED); +} + +/* This function is used in s2n_encrypt_session_ticket in order for s2n to + * choose a key in encrypt-decrypt state from all of the keys added to config + */ +struct s2n_ticket_key *s2n_get_ticket_encrypt_decrypt_key(struct s2n_config *config) +{ + uint8_t num_encrypt_decrypt_keys = 0; + uint8_t encrypt_decrypt_keys_index[S2N_MAX_TICKET_KEYS] = { 0 }; + 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); + + uint32_t ticket_keys_len = 0; + GUARD_RESULT_PTR(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)); + uint64_t key_intro_time = ticket_key->intro_timestamp; + + if (key_intro_time < now + && now < key_intro_time + config->encrypt_decrypt_key_lifetime_in_nanos) { + encrypt_decrypt_keys_index[num_encrypt_decrypt_keys] = idx; + num_encrypt_decrypt_keys++; + } + } + + if (num_encrypt_decrypt_keys == 0) { + S2N_ERROR_PTR(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)); + 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)); + + GUARD_RESULT_PTR(s2n_set_get(config->ticket_keys, idx, (void **)&ticket_key)); + return ticket_key; +} + +/* This function is used in s2n_decrypt_session_ticket in order for s2n to + * find the matching key that was used for encryption. + */ +struct s2n_ticket_key *s2n_find_ticket_key(struct s2n_config *config, const uint8_t *name) +{ + 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); + + uint32_t ticket_keys_len = 0; + GUARD_RESULT_PTR(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)); + + if (memcmp(ticket_key->key_name, name, S2N_TICKET_KEY_NAME_LEN) == 0) { + + /* Check to see if the key has expired */ + if (now >= ticket_key->intro_timestamp + + config->encrypt_decrypt_key_lifetime_in_nanos + config->decrypt_key_lifetime_in_nanos) { + s2n_config_wipe_expired_ticket_crypto_keys(config, i); + + return NULL; + } + + return ticket_key; + } + } + + return NULL; +} + +int s2n_encrypt_session_ticket(struct s2n_connection *conn, struct s2n_stuffer *to) +{ + struct s2n_ticket_key *key; + struct s2n_session_key aes_ticket_key = {0}; + struct s2n_blob aes_key_blob = {0}; + + 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))); + + 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))); + 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)); + + GUARD_AS_POSIX(s2n_get_public_random_data(&iv)); + 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)); + + 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_init(&state, &state_blob)); + GUARD(s2n_serialize_resumption_state(conn, &state)); + + GUARD(s2n_aes256_gcm.io.aead.encrypt(&aes_ticket_key, &iv, &aad_blob, &state_blob, &state_blob)); + + GUARD(s2n_stuffer_write(to, &state_blob)); + + GUARD(s2n_aes256_gcm.destroy_key(&aes_ticket_key)); + GUARD(s2n_session_key_free(&aes_ticket_key)); + + return 0; +} + +int s2n_decrypt_session_ticket(struct s2n_connection *conn) +{ + 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))); + + 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))); + 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)); + + 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)); + + 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)); + + uint64_t now; + 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. + */ + if (now >= key->intro_timestamp + conn->config->encrypt_decrypt_key_lifetime_in_nanos) { + /* 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; + } + } + + return 0; +} + +int s2n_encrypt_session_cache(struct s2n_connection *conn, struct s2n_stuffer *to) +{ + 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; + struct s2n_session_key aes_ticket_key = {0}; + struct s2n_blob aes_key_blob = {0}; + + uint8_t key_name[S2N_TICKET_KEY_NAME_LEN] = {0}; + + uint8_t iv_data[S2N_TLS_GCM_IV_LEN] = { 0 }; + struct s2n_blob iv = {0}; + 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))); + 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))); + + 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)); + + 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)); + + GUARD(s2n_aes256_gcm.destroy_key(&aes_ticket_key)); + GUARD(s2n_session_key_free(&aes_ticket_key)); + + return 0; +} + +/* This function is used to remove all or just one expired key from server config */ +int s2n_config_wipe_expired_ticket_crypto_keys(struct s2n_config *config, int8_t expired_key_index) +{ + int num_of_expired_keys = 0; + int expired_keys_index[S2N_MAX_TICKET_KEYS]; + struct s2n_ticket_key *ticket_key = NULL; + + if (expired_key_index != -1) { + expired_keys_index[num_of_expired_keys] = expired_key_index; + num_of_expired_keys++; + + goto end; + } + + uint64_t now; + GUARD(config->wall_clock(config->sys_clock_ctx, &now)); + notnull_check(config->ticket_keys); + + uint32_t ticket_keys_len = 0; + GUARD_AS_POSIX(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)); + 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; + num_of_expired_keys++; + } + } + +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)); + } + + return 0; +} + + +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)); + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_resume.h b/contrib/restricted/aws/s2n/tls/s2n_resume.h index 2ce6a8559c..c58025e41f 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_resume.h +++ b/contrib/restricted/aws/s2n/tls/s2n_resume.h @@ -1,72 +1,72 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include "utils/s2n_blob.h" - -#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_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 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 -#define S2N_TICKET_LIFETIME_HINT_LEN 4 -#define S2N_SESSION_TICKET_SIZE_LEN 2 -#define S2N_GREATER_OR_EQUAL 1 -#define S2N_LESS_THAN -1 - -struct s2n_connection; -struct s2n_config; - -struct s2n_ticket_key { - unsigned char key_name[S2N_TICKET_KEY_NAME_LEN]; - uint8_t aes_key[S2N_AES256_KEY_LEN]; - uint8_t implicit_aad[S2N_TICKET_AAD_IMPLICIT_LEN]; - uint64_t intro_timestamp; -}; - -struct s2n_ticket_key_weight { - double key_weight; - uint8_t key_index; -}; - -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_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); -extern int s2n_verify_unique_ticket_key(struct s2n_config *config, uint8_t *hash, uint16_t *insert_index); -extern int s2n_config_wipe_expired_ticket_crypto_keys(struct s2n_config *config, int8_t expired_key_index); -extern int s2n_config_store_ticket_key(struct s2n_config *config, struct s2n_ticket_key *key); - -typedef enum { - S2N_STATE_WITH_SESSION_ID = 0, - S2N_STATE_WITH_SESSION_TICKET -} s2n_client_tls_session_state_format; - -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); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include "utils/s2n_blob.h" + +#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_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 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 +#define S2N_TICKET_LIFETIME_HINT_LEN 4 +#define S2N_SESSION_TICKET_SIZE_LEN 2 +#define S2N_GREATER_OR_EQUAL 1 +#define S2N_LESS_THAN -1 + +struct s2n_connection; +struct s2n_config; + +struct s2n_ticket_key { + unsigned char key_name[S2N_TICKET_KEY_NAME_LEN]; + uint8_t aes_key[S2N_AES256_KEY_LEN]; + uint8_t implicit_aad[S2N_TICKET_AAD_IMPLICIT_LEN]; + uint64_t intro_timestamp; +}; + +struct s2n_ticket_key_weight { + double key_weight; + uint8_t key_index; +}; + +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_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); +extern int s2n_verify_unique_ticket_key(struct s2n_config *config, uint8_t *hash, uint16_t *insert_index); +extern int s2n_config_wipe_expired_ticket_crypto_keys(struct s2n_config *config, int8_t expired_key_index); +extern int s2n_config_store_ticket_key(struct s2n_config *config, struct s2n_ticket_key *key); + +typedef enum { + S2N_STATE_WITH_SESSION_ID = 0, + S2N_STATE_WITH_SESSION_TICKET +} s2n_client_tls_session_state_format; + +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); diff --git a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c index 47edfd32c7..2daa495369 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.c +++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.c @@ -1,826 +1,826 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <s2n.h> - -#include "tls/s2n_security_policies.h" -#include "tls/s2n_connection.h" -#include "utils/s2n_safety.h" - -const struct s2n_security_policy security_policy_20170210 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20170210, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20201110 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20190801, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20200207, - .certificate_signature_preferences = &s2n_certificate_signature_preferences_20201110, - .ecc_preferences = &s2n_ecc_preferences_20200310, -}; - -const struct s2n_security_policy security_policy_20190801 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20190801, - .kem_preferences = &kem_preferences_null, - /* The discrepancy in the date exists because the signature preferences - * were named when cipher preferences and signature preferences were - * tracked separately, and we chose to keep the cipher preference - * name because customers use it. - */ - .signature_preferences = &s2n_signature_preferences_20200207, - .ecc_preferences = &s2n_ecc_preferences_20200310, -}; - -const struct s2n_security_policy security_policy_20190802 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20190801, - .kem_preferences = &kem_preferences_null, - /* The discrepancy in the date exists because the signature preferences - * were named when cipher preferences and signature preferences were - * tracked separately, and we chose to keep the cipher preference - * name because customers use it. - */ - .signature_preferences = &s2n_signature_preferences_20200207, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20170405 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20170405, - .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, - .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_2016_08 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &elb_security_policy_2016_08, - .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_tls_1_1_2017_01 = { - .minimum_protocol_version = S2N_TLS11, - .cipher_preferences = &elb_security_policy_tls_1_1_2017_01, - .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_tls_1_2_2017_01 = { - .minimum_protocol_version = S2N_TLS12, - .cipher_preferences = &elb_security_policy_tls_1_2_2017_01, - .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_tls_1_2_ext_2018_06 = { - .minimum_protocol_version = S2N_TLS12, - .cipher_preferences = &elb_security_policy_tls_1_2_ext_2018_06, - .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_fs_2018_06 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &elb_security_policy_fs_2018_06, - .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_fs_1_2_2019_08 = { - .minimum_protocol_version = S2N_TLS12, - .cipher_preferences = &elb_security_policy_fs_1_2_2019_08, - .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_fs_1_1_2019_08 = { - .minimum_protocol_version = S2N_TLS11, - .cipher_preferences = &elb_security_policy_fs_1_1_2019_08, - .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_fs_1_2_Res_2019_08 = { - .minimum_protocol_version = S2N_TLS12, - .cipher_preferences = &elb_security_policy_fs_1_2_Res_2019_08, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -/* CloudFront upstream */ -const struct s2n_security_policy security_policy_cloudfront_upstream = { - .minimum_protocol_version = S2N_SSLv3, - .cipher_preferences = &cipher_preferences_cloudfront_upstream, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_cloudfront_upstream_tls10 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_cloudfront_upstream_tls10, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_cloudfront_upstream_tls11 = { - .minimum_protocol_version = S2N_TLS11, - .cipher_preferences = &cipher_preferences_cloudfront_upstream_tls11, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_cloudfront_upstream_tls12 = { - .minimum_protocol_version = S2N_TLS12, - .cipher_preferences = &cipher_preferences_cloudfront_upstream_tls12, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -/* CloudFront viewer facing */ -const struct s2n_security_policy security_policy_cloudfront_ssl_v_3 = { - .minimum_protocol_version = S2N_SSLv3, - .cipher_preferences = &cipher_preferences_cloudfront_ssl_v_3, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20200207, - .ecc_preferences = &s2n_ecc_preferences_20200310, -}; - -const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2014 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_cloudfront_tls_1_0_2014, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20200207, - .ecc_preferences = &s2n_ecc_preferences_20200310, -}; - -const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2016 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_cloudfront_tls_1_0_2016, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20200207, - .ecc_preferences = &s2n_ecc_preferences_20200310, -}; - -const struct s2n_security_policy security_policy_cloudfront_tls_1_1_2016 = { - .minimum_protocol_version = S2N_TLS11, - .cipher_preferences = &cipher_preferences_cloudfront_tls_1_1_2016, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20200207, - .ecc_preferences = &s2n_ecc_preferences_20200310, -}; - -const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2018 = { - .minimum_protocol_version = S2N_TLS12, - .cipher_preferences = &cipher_preferences_cloudfront_tls_1_2_2018, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20200207, - .ecc_preferences = &s2n_ecc_preferences_20200310, -}; - -const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2019 = { - .minimum_protocol_version = S2N_TLS12, - .cipher_preferences = &cipher_preferences_cloudfront_tls_1_2_2019, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20200207, - .ecc_preferences = &s2n_ecc_preferences_20200310, -}; - -/* CloudFront viewer facing legacy TLS 1.2 policies */ -const struct s2n_security_policy security_policy_cloudfront_ssl_v_3_legacy = { - .minimum_protocol_version = S2N_SSLv3, - .cipher_preferences = &cipher_preferences_cloudfront_ssl_v_3_legacy, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2014_legacy = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_cloudfront_tls_1_0_2014_legacy, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2016_legacy = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_cloudfront_tls_1_0_2016_legacy, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_cloudfront_tls_1_1_2016_legacy = { - .minimum_protocol_version = S2N_TLS11, - .cipher_preferences = &cipher_preferences_cloudfront_tls_1_1_2016_legacy, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2018_legacy = { - .minimum_protocol_version = S2N_TLS12, - .cipher_preferences = &cipher_preferences_cloudfront_tls_1_2_2018_legacy, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2019_legacy = { - .minimum_protocol_version = S2N_TLS12, - .cipher_preferences = &cipher_preferences_cloudfront_tls_1_2_2019_legacy, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -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, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -#if !defined(S2N_NO_PQ) - -const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2019_06 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_kms_pq_tls_1_0_2019_06, - .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2019_06, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_02 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_kms_pq_tls_1_0_2020_02, - .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_02, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2019_11 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_pq_sike_test_tls_1_0_2019_11, - .kem_preferences = &kem_preferences_pq_sike_test_tls_1_0_2019_11, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2020_02 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_pq_sike_test_tls_1_0_2020_02, - .kem_preferences = &kem_preferences_pq_sike_test_tls_1_0_2020_02, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_07 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_kms_pq_tls_1_0_2020_07, - .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_07, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_pq_tls_1_0_2020_12 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_pq_tls_1_0_2020_12, - .kem_preferences = &kem_preferences_pq_tls_1_0_2020_12, - .signature_preferences = &s2n_signature_preferences_20200207, - .ecc_preferences = &s2n_ecc_preferences_20200310, -}; - -#endif -const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10 = { - .minimum_protocol_version = S2N_TLS12, - .cipher_preferences = &cipher_preferences_kms_fips_tls_1_2_2018_10, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20140601 = { - .minimum_protocol_version = S2N_SSLv3, - .cipher_preferences = &cipher_preferences_20140601, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20141001 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20141001, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20150202 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20150202, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20150214 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20150214, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20160411 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20160411, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20150306 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20150306, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20160804 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20160804, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20160824 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20160824, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20190122 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20190122, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20190121 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20190121, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20190120 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20190120, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20190214 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20190214, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_20170328 = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_20170328, - .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, - .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, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20201021, - .ecc_preferences = &s2n_ecc_preferences_20201021, -}; - -const struct s2n_security_policy security_policy_test_all = { - .minimum_protocol_version = S2N_SSLv3, - .cipher_preferences = &cipher_preferences_test_all, -#if !defined(S2N_NO_PQ) - .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_07, -#else - .kem_preferences = &kem_preferences_null, -#endif - .signature_preferences = &s2n_signature_preferences_20201021, - .ecc_preferences = &s2n_ecc_preferences_test_all, -}; - -const struct s2n_security_policy security_policy_test_all_tls12 = { - .minimum_protocol_version = S2N_SSLv3, - .cipher_preferences = &cipher_preferences_test_all_tls12, -#if !defined(S2N_NO_PQ) - .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_07, -#else - .kem_preferences = &kem_preferences_null, -#endif - .signature_preferences = &s2n_signature_preferences_20201021, - .ecc_preferences = &s2n_ecc_preferences_20201021, -}; - -const struct s2n_security_policy security_policy_test_all_fips = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_test_all_fips, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_test_all_ecdsa = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_test_all_ecdsa, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20201021, - .ecc_preferences = &s2n_ecc_preferences_test_all, -}; - -const struct s2n_security_policy security_policy_test_all_rsa_kex = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_test_all_rsa_kex, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20140601, - .ecc_preferences = &s2n_ecc_preferences_20140601, -}; - -const struct s2n_security_policy security_policy_test_all_tls13 = { - .minimum_protocol_version = S2N_SSLv3, - .cipher_preferences = &cipher_preferences_test_all_tls13, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20201021, - .ecc_preferences = &s2n_ecc_preferences_test_all, -}; - -const struct s2n_security_policy security_policy_test_ecdsa_priority = { - .minimum_protocol_version = S2N_SSLv3, - .cipher_preferences = &cipher_preferences_test_ecdsa_priority, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_20201021, - .ecc_preferences = &s2n_ecc_preferences_test_all, -}; - -const struct s2n_security_policy security_policy_null = { - .minimum_protocol_version = S2N_TLS10, - .cipher_preferences = &cipher_preferences_null, - .kem_preferences = &kem_preferences_null, - .signature_preferences = &s2n_signature_preferences_null, - .ecc_preferences = &s2n_ecc_preferences_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_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 */ - { .version="ELBSecurityPolicy-TLS-1-0-2015-05", .security_policy=&security_policy_elb_2016_08, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="ELBSecurityPolicy-2016-08", .security_policy=&security_policy_elb_2016_08, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="ELBSecurityPolicy-TLS-1-1-2017-01", .security_policy=&security_policy_elb_tls_1_1_2017_01, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="ELBSecurityPolicy-TLS-1-2-2017-01", .security_policy=&security_policy_elb_tls_1_2_2017_01, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="ELBSecurityPolicy-TLS-1-2-Ext-2018-06", .security_policy=&security_policy_elb_tls_1_2_ext_2018_06, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="ELBSecurityPolicy-FS-2018-06", .security_policy=&security_policy_elb_fs_2018_06, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="ELBSecurityPolicy-FS-1-2-2019-08", .security_policy=&security_policy_elb_fs_1_2_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="ELBSecurityPolicy-FS-1-1-2019-08", .security_policy=&security_policy_elb_fs_1_1_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="ELBSecurityPolicy-FS-1-2-Res-2019-08", .security_policy=&security_policy_elb_fs_1_2_Res_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="CloudFront-Upstream", .security_policy=&security_policy_cloudfront_upstream, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="CloudFront-Upstream-TLS-1-0", .security_policy=&security_policy_cloudfront_upstream_tls10, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="CloudFront-Upstream-TLS-1-1", .security_policy=&security_policy_cloudfront_upstream_tls11, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="CloudFront-Upstream-TLS-1-2", .security_policy=&security_policy_cloudfront_upstream_tls12, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - /* CloudFront Viewer Facing */ - { .version="CloudFront-SSL-v-3", .security_policy=&security_policy_cloudfront_ssl_v_3, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="CloudFront-TLS-1-0-2014", .security_policy=&security_policy_cloudfront_tls_1_0_2014, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="CloudFront-TLS-1-0-2016", .security_policy=&security_policy_cloudfront_tls_1_0_2016, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="CloudFront-TLS-1-1-2016", .security_policy=&security_policy_cloudfront_tls_1_1_2016, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="CloudFront-TLS-1-2-2018", .security_policy=&security_policy_cloudfront_tls_1_2_2018, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="CloudFront-TLS-1-2-2019", .security_policy=&security_policy_cloudfront_tls_1_2_2019, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - /* CloudFront Legacy (TLS 1.2) policies */ - { .version="CloudFront-SSL-v-3-Legacy", .security_policy=&security_policy_cloudfront_ssl_v_3_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="CloudFront-TLS-1-0-2014-Legacy", .security_policy=&security_policy_cloudfront_tls_1_0_2014_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="CloudFront-TLS-1-0-2016-Legacy", .security_policy=&security_policy_cloudfront_tls_1_0_2016_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .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="KMS-TLS-1-0-2018-10", .security_policy=&security_policy_kms_tls_1_0_2018_10, .ecc_extension_required=0, .pq_kem_extension_required=0 }, -#if !defined(S2N_NO_PQ) - { .version="KMS-PQ-TLS-1-0-2019-06", .security_policy=&security_policy_kms_pq_tls_1_0_2019_06, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="KMS-PQ-TLS-1-0-2020-02", .security_policy=&security_policy_kms_pq_tls_1_0_2020_02, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="KMS-PQ-TLS-1-0-2020-07", .security_policy=&security_policy_kms_pq_tls_1_0_2020_07, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="PQ-SIKE-TEST-TLS-1-0-2019-11", .security_policy=&security_policy_pq_sike_test_tls_1_0_2019_11, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="PQ-SIKE-TEST-TLS-1-0-2020-02", .security_policy=&security_policy_pq_sike_test_tls_1_0_2020_02, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="PQ-TLS-1-0-2020-12", .security_policy=&security_policy_pq_tls_1_0_2020_12, .ecc_extension_required=0, .pq_kem_extension_required=0 }, -#endif - { .version="KMS-FIPS-TLS-1-2-2018-10", .security_policy=&security_policy_kms_fips_tls_1_2_2018_10, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="20140601", .security_policy=&security_policy_20140601, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="20141001", .security_policy=&security_policy_20141001, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="20150202", .security_policy=&security_policy_20150202, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="20150214", .security_policy=&security_policy_20150214, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="20150306", .security_policy=&security_policy_20150306, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="20160411", .security_policy=&security_policy_20160411, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="20160804", .security_policy=&security_policy_20160804, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .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="20190214", .security_policy=&security_policy_20190214, .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="20170718", .security_policy=&security_policy_20170718, .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 }, - { .version="20190801", .security_policy=&security_policy_20190801, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .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="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 }, - { .version="test_all_rsa_kex", .security_policy=&security_policy_test_all_rsa_kex, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="test_ecdsa_priority", .security_policy=&security_policy_test_ecdsa_priority, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="test_all_tls12", .security_policy=&security_policy_test_all_tls12, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="test_all_tls13", .security_policy=&security_policy_test_all_tls13, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version="null", .security_policy=&security_policy_null, .ecc_extension_required=0, .pq_kem_extension_required=0 }, - { .version=NULL, .security_policy=NULL, .ecc_extension_required=0, .pq_kem_extension_required=0 } -}; - -int s2n_find_security_policy_from_version(const char *version, const struct s2n_security_policy **security_policy) -{ - notnull_check(version); - notnull_check(security_policy); - - for (int i = 0; security_policy_selection[i].version != NULL; i++) { - if (!strcasecmp(version, security_policy_selection[i].version)) { - *security_policy = security_policy_selection[i].security_policy; - return 0; - } - } - - S2N_ERROR(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); - - config->security_policy = security_policy; - return 0; -} - -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); - - conn->security_policy_override = security_policy; - return 0; -} - -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); - const struct s2n_cipher_preferences *cipher_preference = security_policy->cipher_preferences; - notnull_check(cipher_preference); - const struct s2n_kem_preferences *kem_preference = security_policy->kem_preferences; - notnull_check(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)); - - 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)); - } - - 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); - } - - for (int j = 0; j < cipher_preference->count; j++) { - struct s2n_cipher_suite *cipher = cipher_preference->suites[j]; - notnull_check(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; - } - - /* Sanity check that valid tls13 has minimum tls version set correctly */ - 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)) { - security_policy_selection[i].ecc_extension_required = 1; - } - - if (s2n_kex_includes(cipher->key_exchange_alg, &s2n_kem)) { - security_policy_selection[i].pq_kem_extension_required = 1; - } - } - - GUARD(s2n_validate_kem_preferences(kem_preference, security_policy_selection[i].pq_kem_extension_required)); - } - return 0; -} - -bool s2n_ecc_is_extension_required(const struct s2n_security_policy *security_policy) -{ - if (security_policy == NULL) { - return false; - } - - for (int i = 0; security_policy_selection[i].version != NULL; i++) { - if (security_policy_selection[i].security_policy == security_policy) { - return 1 == security_policy_selection[i].ecc_extension_required; - } - } - return false; -} - -bool s2n_pq_kem_is_extension_required(const struct s2n_security_policy *security_policy) -{ - if (security_policy == NULL) { - return false; - } - - for (int i = 0; security_policy_selection[i].version != NULL; i++) { - if (security_policy_selection[i].security_policy == security_policy) { - return 1 == security_policy_selection[i].pq_kem_extension_required; - } - } - return false; -} - -/* Checks whether cipher preference supports TLS 1.3 based on whether it is configured - * with TLS 1.3 ciphers. Returns true or false. - */ -bool s2n_security_policy_supports_tls13(const struct s2n_security_policy *security_policy) -{ - if (security_policy == NULL) { - return false; - } - - for (uint8_t i = 0; security_policy_selection[i].version != NULL; i++) { - if (security_policy_selection[i].security_policy == security_policy) { - return security_policy_selection[i].supports_tls13 == 1; - } - } - - /* 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_is_valid_tls13_cipher(cipher_preferences->suites[i]->iana_value)) { - return true; - } - } - - return false; -} - -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); - - const struct s2n_security_policy *security_policy = NULL; - GUARD(s2n_find_security_policy_from_version(version, &security_policy)); - notnull_check(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) { - return 0; - } - - struct s2n_cipher_suite *cipher = conn->secure.cipher_suite; - notnull_check(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; - } - } - - return 0; -} - -int s2n_validate_kem_preferences(const struct s2n_kem_preferences *kem_preferences, bool pq_kem_extension_required) { - notnull_check(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), - S2N_ERR_INVALID_SECURITY_POLICY); - ENSURE_POSIX(S2N_IFF(kem_preferences->kem_count == 0, kem_preferences->kems == NULL), - S2N_ERR_INVALID_SECURITY_POLICY); - - /* 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); - } else { - ENSURE_POSIX(kem_preferences->kem_count == 0, S2N_ERR_INVALID_SECURITY_POLICY); - ENSURE_POSIX(kem_preferences->kems == NULL, S2N_ERR_INVALID_SECURITY_POLICY); - } - - return S2N_SUCCESS; -} - -S2N_RESULT s2n_validate_certificate_signature_preferences(const struct s2n_signature_preferences *certificate_signature_preferences) -{ - ENSURE_REF(certificate_signature_preferences); - - size_t rsa_pss_scheme_count = 0; - - for (size_t i = 0; i < certificate_signature_preferences->count; i++) { - if (certificate_signature_preferences->signature_schemes[i]->libcrypto_nid == NID_rsassaPss) { - rsa_pss_scheme_count++; - } - } - - /* 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); - return S2N_RESULT_OK; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <s2n.h> + +#include "tls/s2n_security_policies.h" +#include "tls/s2n_connection.h" +#include "utils/s2n_safety.h" + +const struct s2n_security_policy security_policy_20170210 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20170210, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20201110 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20190801, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20200207, + .certificate_signature_preferences = &s2n_certificate_signature_preferences_20201110, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +const struct s2n_security_policy security_policy_20190801 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20190801, + .kem_preferences = &kem_preferences_null, + /* The discrepancy in the date exists because the signature preferences + * were named when cipher preferences and signature preferences were + * tracked separately, and we chose to keep the cipher preference + * name because customers use it. + */ + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +const struct s2n_security_policy security_policy_20190802 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20190801, + .kem_preferences = &kem_preferences_null, + /* The discrepancy in the date exists because the signature preferences + * were named when cipher preferences and signature preferences were + * tracked separately, and we chose to keep the cipher preference + * name because customers use it. + */ + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20170405 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20170405, + .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, + .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_2016_08 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &elb_security_policy_2016_08, + .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_tls_1_1_2017_01 = { + .minimum_protocol_version = S2N_TLS11, + .cipher_preferences = &elb_security_policy_tls_1_1_2017_01, + .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_tls_1_2_2017_01 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &elb_security_policy_tls_1_2_2017_01, + .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_tls_1_2_ext_2018_06 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &elb_security_policy_tls_1_2_ext_2018_06, + .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_fs_2018_06 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &elb_security_policy_fs_2018_06, + .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_fs_1_2_2019_08 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &elb_security_policy_fs_1_2_2019_08, + .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_fs_1_1_2019_08 = { + .minimum_protocol_version = S2N_TLS11, + .cipher_preferences = &elb_security_policy_fs_1_1_2019_08, + .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_fs_1_2_Res_2019_08 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &elb_security_policy_fs_1_2_Res_2019_08, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +/* CloudFront upstream */ +const struct s2n_security_policy security_policy_cloudfront_upstream = { + .minimum_protocol_version = S2N_SSLv3, + .cipher_preferences = &cipher_preferences_cloudfront_upstream, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_cloudfront_upstream_tls10 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_cloudfront_upstream_tls10, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_cloudfront_upstream_tls11 = { + .minimum_protocol_version = S2N_TLS11, + .cipher_preferences = &cipher_preferences_cloudfront_upstream_tls11, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_cloudfront_upstream_tls12 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_cloudfront_upstream_tls12, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +/* CloudFront viewer facing */ +const struct s2n_security_policy security_policy_cloudfront_ssl_v_3 = { + .minimum_protocol_version = S2N_SSLv3, + .cipher_preferences = &cipher_preferences_cloudfront_ssl_v_3, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2014 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_cloudfront_tls_1_0_2014, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2016 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_cloudfront_tls_1_0_2016, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +const struct s2n_security_policy security_policy_cloudfront_tls_1_1_2016 = { + .minimum_protocol_version = S2N_TLS11, + .cipher_preferences = &cipher_preferences_cloudfront_tls_1_1_2016, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2018 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_cloudfront_tls_1_2_2018, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2019 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_cloudfront_tls_1_2_2019, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +/* CloudFront viewer facing legacy TLS 1.2 policies */ +const struct s2n_security_policy security_policy_cloudfront_ssl_v_3_legacy = { + .minimum_protocol_version = S2N_SSLv3, + .cipher_preferences = &cipher_preferences_cloudfront_ssl_v_3_legacy, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2014_legacy = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_cloudfront_tls_1_0_2014_legacy, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2016_legacy = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_cloudfront_tls_1_0_2016_legacy, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_cloudfront_tls_1_1_2016_legacy = { + .minimum_protocol_version = S2N_TLS11, + .cipher_preferences = &cipher_preferences_cloudfront_tls_1_1_2016_legacy, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2018_legacy = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_cloudfront_tls_1_2_2018_legacy, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2019_legacy = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_cloudfront_tls_1_2_2019_legacy, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +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, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +#if !defined(S2N_NO_PQ) + +const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2019_06 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_kms_pq_tls_1_0_2019_06, + .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2019_06, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_02 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_kms_pq_tls_1_0_2020_02, + .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_02, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2019_11 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_pq_sike_test_tls_1_0_2019_11, + .kem_preferences = &kem_preferences_pq_sike_test_tls_1_0_2019_11, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2020_02 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_pq_sike_test_tls_1_0_2020_02, + .kem_preferences = &kem_preferences_pq_sike_test_tls_1_0_2020_02, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_07 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_kms_pq_tls_1_0_2020_07, + .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_07, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_pq_tls_1_0_2020_12 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_pq_tls_1_0_2020_12, + .kem_preferences = &kem_preferences_pq_tls_1_0_2020_12, + .signature_preferences = &s2n_signature_preferences_20200207, + .ecc_preferences = &s2n_ecc_preferences_20200310, +}; + +#endif +const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_kms_fips_tls_1_2_2018_10, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20140601 = { + .minimum_protocol_version = S2N_SSLv3, + .cipher_preferences = &cipher_preferences_20140601, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20141001 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20141001, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20150202 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20150202, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20150214 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20150214, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20160411 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20160411, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20150306 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20150306, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20160804 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20160804, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20160824 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20160824, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20190122 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20190122, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20190121 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20190121, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20190120 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20190120, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20190214 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20190214, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_20170328 = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_20170328, + .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, + .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, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20201021, + .ecc_preferences = &s2n_ecc_preferences_20201021, +}; + +const struct s2n_security_policy security_policy_test_all = { + .minimum_protocol_version = S2N_SSLv3, + .cipher_preferences = &cipher_preferences_test_all, +#if !defined(S2N_NO_PQ) + .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_07, +#else + .kem_preferences = &kem_preferences_null, +#endif + .signature_preferences = &s2n_signature_preferences_20201021, + .ecc_preferences = &s2n_ecc_preferences_test_all, +}; + +const struct s2n_security_policy security_policy_test_all_tls12 = { + .minimum_protocol_version = S2N_SSLv3, + .cipher_preferences = &cipher_preferences_test_all_tls12, +#if !defined(S2N_NO_PQ) + .kem_preferences = &kem_preferences_kms_pq_tls_1_0_2020_07, +#else + .kem_preferences = &kem_preferences_null, +#endif + .signature_preferences = &s2n_signature_preferences_20201021, + .ecc_preferences = &s2n_ecc_preferences_20201021, +}; + +const struct s2n_security_policy security_policy_test_all_fips = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_test_all_fips, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_test_all_ecdsa = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_test_all_ecdsa, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20201021, + .ecc_preferences = &s2n_ecc_preferences_test_all, +}; + +const struct s2n_security_policy security_policy_test_all_rsa_kex = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_test_all_rsa_kex, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20140601, + .ecc_preferences = &s2n_ecc_preferences_20140601, +}; + +const struct s2n_security_policy security_policy_test_all_tls13 = { + .minimum_protocol_version = S2N_SSLv3, + .cipher_preferences = &cipher_preferences_test_all_tls13, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20201021, + .ecc_preferences = &s2n_ecc_preferences_test_all, +}; + +const struct s2n_security_policy security_policy_test_ecdsa_priority = { + .minimum_protocol_version = S2N_SSLv3, + .cipher_preferences = &cipher_preferences_test_ecdsa_priority, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20201021, + .ecc_preferences = &s2n_ecc_preferences_test_all, +}; + +const struct s2n_security_policy security_policy_null = { + .minimum_protocol_version = S2N_TLS10, + .cipher_preferences = &cipher_preferences_null, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_null, + .ecc_preferences = &s2n_ecc_preferences_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_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 */ + { .version="ELBSecurityPolicy-TLS-1-0-2015-05", .security_policy=&security_policy_elb_2016_08, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="ELBSecurityPolicy-2016-08", .security_policy=&security_policy_elb_2016_08, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="ELBSecurityPolicy-TLS-1-1-2017-01", .security_policy=&security_policy_elb_tls_1_1_2017_01, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="ELBSecurityPolicy-TLS-1-2-2017-01", .security_policy=&security_policy_elb_tls_1_2_2017_01, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="ELBSecurityPolicy-TLS-1-2-Ext-2018-06", .security_policy=&security_policy_elb_tls_1_2_ext_2018_06, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="ELBSecurityPolicy-FS-2018-06", .security_policy=&security_policy_elb_fs_2018_06, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="ELBSecurityPolicy-FS-1-2-2019-08", .security_policy=&security_policy_elb_fs_1_2_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="ELBSecurityPolicy-FS-1-1-2019-08", .security_policy=&security_policy_elb_fs_1_1_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="ELBSecurityPolicy-FS-1-2-Res-2019-08", .security_policy=&security_policy_elb_fs_1_2_Res_2019_08, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-Upstream", .security_policy=&security_policy_cloudfront_upstream, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-Upstream-TLS-1-0", .security_policy=&security_policy_cloudfront_upstream_tls10, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-Upstream-TLS-1-1", .security_policy=&security_policy_cloudfront_upstream_tls11, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-Upstream-TLS-1-2", .security_policy=&security_policy_cloudfront_upstream_tls12, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + /* CloudFront Viewer Facing */ + { .version="CloudFront-SSL-v-3", .security_policy=&security_policy_cloudfront_ssl_v_3, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-TLS-1-0-2014", .security_policy=&security_policy_cloudfront_tls_1_0_2014, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-TLS-1-0-2016", .security_policy=&security_policy_cloudfront_tls_1_0_2016, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-TLS-1-1-2016", .security_policy=&security_policy_cloudfront_tls_1_1_2016, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-TLS-1-2-2018", .security_policy=&security_policy_cloudfront_tls_1_2_2018, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-TLS-1-2-2019", .security_policy=&security_policy_cloudfront_tls_1_2_2019, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + /* CloudFront Legacy (TLS 1.2) policies */ + { .version="CloudFront-SSL-v-3-Legacy", .security_policy=&security_policy_cloudfront_ssl_v_3_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-TLS-1-0-2014-Legacy", .security_policy=&security_policy_cloudfront_tls_1_0_2014_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="CloudFront-TLS-1-0-2016-Legacy", .security_policy=&security_policy_cloudfront_tls_1_0_2016_legacy, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .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="KMS-TLS-1-0-2018-10", .security_policy=&security_policy_kms_tls_1_0_2018_10, .ecc_extension_required=0, .pq_kem_extension_required=0 }, +#if !defined(S2N_NO_PQ) + { .version="KMS-PQ-TLS-1-0-2019-06", .security_policy=&security_policy_kms_pq_tls_1_0_2019_06, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="KMS-PQ-TLS-1-0-2020-02", .security_policy=&security_policy_kms_pq_tls_1_0_2020_02, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="KMS-PQ-TLS-1-0-2020-07", .security_policy=&security_policy_kms_pq_tls_1_0_2020_07, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="PQ-SIKE-TEST-TLS-1-0-2019-11", .security_policy=&security_policy_pq_sike_test_tls_1_0_2019_11, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="PQ-SIKE-TEST-TLS-1-0-2020-02", .security_policy=&security_policy_pq_sike_test_tls_1_0_2020_02, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="PQ-TLS-1-0-2020-12", .security_policy=&security_policy_pq_tls_1_0_2020_12, .ecc_extension_required=0, .pq_kem_extension_required=0 }, +#endif + { .version="KMS-FIPS-TLS-1-2-2018-10", .security_policy=&security_policy_kms_fips_tls_1_2_2018_10, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="20140601", .security_policy=&security_policy_20140601, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="20141001", .security_policy=&security_policy_20141001, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="20150202", .security_policy=&security_policy_20150202, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="20150214", .security_policy=&security_policy_20150214, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="20150306", .security_policy=&security_policy_20150306, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="20160411", .security_policy=&security_policy_20160411, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="20160804", .security_policy=&security_policy_20160804, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .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="20190214", .security_policy=&security_policy_20190214, .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="20170718", .security_policy=&security_policy_20170718, .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 }, + { .version="20190801", .security_policy=&security_policy_20190801, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .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="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 }, + { .version="test_all_rsa_kex", .security_policy=&security_policy_test_all_rsa_kex, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="test_ecdsa_priority", .security_policy=&security_policy_test_ecdsa_priority, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="test_all_tls12", .security_policy=&security_policy_test_all_tls12, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="test_all_tls13", .security_policy=&security_policy_test_all_tls13, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version="null", .security_policy=&security_policy_null, .ecc_extension_required=0, .pq_kem_extension_required=0 }, + { .version=NULL, .security_policy=NULL, .ecc_extension_required=0, .pq_kem_extension_required=0 } +}; + +int s2n_find_security_policy_from_version(const char *version, const struct s2n_security_policy **security_policy) +{ + notnull_check(version); + notnull_check(security_policy); + + for (int i = 0; security_policy_selection[i].version != NULL; i++) { + if (!strcasecmp(version, security_policy_selection[i].version)) { + *security_policy = security_policy_selection[i].security_policy; + return 0; + } + } + + S2N_ERROR(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); + + config->security_policy = security_policy; + return 0; +} + +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); + + conn->security_policy_override = security_policy; + return 0; +} + +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); + const struct s2n_cipher_preferences *cipher_preference = security_policy->cipher_preferences; + notnull_check(cipher_preference); + const struct s2n_kem_preferences *kem_preference = security_policy->kem_preferences; + notnull_check(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)); + + 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)); + } + + 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); + } + + for (int j = 0; j < cipher_preference->count; j++) { + struct s2n_cipher_suite *cipher = cipher_preference->suites[j]; + notnull_check(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; + } + + /* Sanity check that valid tls13 has minimum tls version set correctly */ + 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)) { + security_policy_selection[i].ecc_extension_required = 1; + } + + if (s2n_kex_includes(cipher->key_exchange_alg, &s2n_kem)) { + security_policy_selection[i].pq_kem_extension_required = 1; + } + } + + GUARD(s2n_validate_kem_preferences(kem_preference, security_policy_selection[i].pq_kem_extension_required)); + } + return 0; +} + +bool s2n_ecc_is_extension_required(const struct s2n_security_policy *security_policy) +{ + if (security_policy == NULL) { + return false; + } + + for (int i = 0; security_policy_selection[i].version != NULL; i++) { + if (security_policy_selection[i].security_policy == security_policy) { + return 1 == security_policy_selection[i].ecc_extension_required; + } + } + return false; +} + +bool s2n_pq_kem_is_extension_required(const struct s2n_security_policy *security_policy) +{ + if (security_policy == NULL) { + return false; + } + + for (int i = 0; security_policy_selection[i].version != NULL; i++) { + if (security_policy_selection[i].security_policy == security_policy) { + return 1 == security_policy_selection[i].pq_kem_extension_required; + } + } + return false; +} + +/* Checks whether cipher preference supports TLS 1.3 based on whether it is configured + * with TLS 1.3 ciphers. Returns true or false. + */ +bool s2n_security_policy_supports_tls13(const struct s2n_security_policy *security_policy) +{ + if (security_policy == NULL) { + return false; + } + + for (uint8_t i = 0; security_policy_selection[i].version != NULL; i++) { + if (security_policy_selection[i].security_policy == security_policy) { + return security_policy_selection[i].supports_tls13 == 1; + } + } + + /* 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_is_valid_tls13_cipher(cipher_preferences->suites[i]->iana_value)) { + return true; + } + } + + return false; +} + +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); + + const struct s2n_security_policy *security_policy = NULL; + GUARD(s2n_find_security_policy_from_version(version, &security_policy)); + notnull_check(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) { + return 0; + } + + struct s2n_cipher_suite *cipher = conn->secure.cipher_suite; + notnull_check(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; + } + } + + return 0; +} + +int s2n_validate_kem_preferences(const struct s2n_kem_preferences *kem_preferences, bool pq_kem_extension_required) { + notnull_check(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), + S2N_ERR_INVALID_SECURITY_POLICY); + ENSURE_POSIX(S2N_IFF(kem_preferences->kem_count == 0, kem_preferences->kems == NULL), + S2N_ERR_INVALID_SECURITY_POLICY); + + /* 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); + } else { + ENSURE_POSIX(kem_preferences->kem_count == 0, S2N_ERR_INVALID_SECURITY_POLICY); + ENSURE_POSIX(kem_preferences->kems == NULL, S2N_ERR_INVALID_SECURITY_POLICY); + } + + return S2N_SUCCESS; +} + +S2N_RESULT s2n_validate_certificate_signature_preferences(const struct s2n_signature_preferences *certificate_signature_preferences) +{ + ENSURE_REF(certificate_signature_preferences); + + size_t rsa_pss_scheme_count = 0; + + for (size_t i = 0; i < certificate_signature_preferences->count; i++) { + if (certificate_signature_preferences->signature_schemes[i]->libcrypto_nid == NID_rsassaPss) { + rsa_pss_scheme_count++; + } + } + + /* 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); + 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 d4ca93a220..ab71889ad7 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_security_policies.h +++ b/contrib/restricted/aws/s2n/tls/s2n_security_policies.h @@ -1,118 +1,118 @@ -/* - * 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 <stdint.h> -#include "tls/s2n_cipher_preferences.h" -#include "tls/s2n_kem_preferences.h" -#include "tls/s2n_signature_scheme.h" -#include "tls/s2n_ecc_preferences.h" - -/* Kept up-to-date by s2n_security_policies_test */ -#define NUM_RSA_PSS_SCHEMES 6 - -struct s2n_security_policy { - uint8_t minimum_protocol_version; - const struct s2n_cipher_preferences *cipher_preferences; - const struct s2n_kem_preferences *kem_preferences; - const struct s2n_signature_preferences *signature_preferences; - const struct s2n_signature_preferences *certificate_signature_preferences; - const struct s2n_ecc_preferences *ecc_preferences; -}; - -struct s2n_security_policy_selection { - const char *version; - const struct s2n_security_policy *security_policy; - unsigned ecc_extension_required:1; - unsigned pq_kem_extension_required:1; - unsigned supports_tls13:1; -}; - -extern struct s2n_security_policy_selection security_policy_selection[]; - -extern const struct s2n_security_policy security_policy_20140601; -extern const struct s2n_security_policy security_policy_20141001; -extern const struct s2n_security_policy security_policy_20150202; -extern const struct s2n_security_policy security_policy_20150214; -extern const struct s2n_security_policy security_policy_20150306; -extern const struct s2n_security_policy security_policy_20160411; -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_20170405; -extern const struct s2n_security_policy security_policy_20170718; -extern const struct s2n_security_policy security_policy_20190214; -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_test_all; - -extern const struct s2n_security_policy security_policy_test_all_tls12; -extern const struct s2n_security_policy security_policy_test_all_fips; -extern const struct s2n_security_policy security_policy_test_all_ecdsa; -extern const struct s2n_security_policy security_policy_test_ecdsa_priority; -extern const struct s2n_security_policy security_policy_test_all_rsa_kex; -extern const struct s2n_security_policy security_policy_test_all_tls13; - -/* See https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html */ -extern const struct s2n_security_policy security_policy_elb_2015_04; -extern const struct s2n_security_policy security_policy_elb_2016_08; -extern const struct s2n_security_policy security_policy_elb_tls_1_2_2017_01; -extern const struct s2n_security_policy security_policy_elb_tls_1_1_2017_01; -extern const struct s2n_security_policy security_policy_elb_tls_1_2_ext_2018_06; -extern const struct s2n_security_policy security_policy_elb_fs_2018_06; -extern const struct s2n_security_policy security_policy_elb_fs_1_2_2019_08; -extern const struct s2n_security_policy security_policy_elb_fs_1_1_2019_08; -extern const struct s2n_security_policy security_policy_elb_fs_1_2_res_2019_08; - -#if !defined(S2N_NO_PQ) -extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2019_06; -extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_02; -extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_07; -extern const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2019_11; -extern const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2020_02; -extern const struct s2n_security_policy security_policy_pq_tls_1_0_2020_12; -#endif - -extern const struct s2n_security_policy security_policy_cloudfront_upstream; -extern const struct s2n_security_policy security_policy_cloudfront_upstream_tls10; -extern const struct s2n_security_policy security_policy_cloudfront_upstream_tls12; -extern const struct s2n_security_policy security_policy_cloudfront_ssl_v_3; -extern const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2014; -extern const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2016; -extern const struct s2n_security_policy security_policy_cloudfront_tls_1_1_2016; -extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2018; -extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2019; - -extern const struct s2n_security_policy security_policy_kms_tls_1_0_2018_10; -extern const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10; - -extern const struct s2n_security_policy security_policy_20190120; -extern const struct s2n_security_policy security_policy_20190121; -extern const struct s2n_security_policy security_policy_20190122; - -extern const struct s2n_security_policy security_policy_null; - -int s2n_security_policies_init(); -int s2n_config_set_cipher_preferences(struct s2n_config *config, const char *version); -int s2n_connection_set_cipher_preferences(struct s2n_connection *conn, const char *version); -bool s2n_ecc_is_extension_required(const struct s2n_security_policy *security_policy); -bool s2n_pq_kem_is_extension_required(const struct s2n_security_policy *security_policy); -bool s2n_security_policy_supports_tls13(const struct s2n_security_policy *security_policy); -int s2n_find_security_policy_from_version(const char *version, const struct s2n_security_policy **security_policy); -int s2n_validate_kem_preferences(const struct s2n_kem_preferences *kem_preferences, bool pq_kem_extension_required); -S2N_RESULT s2n_validate_certificate_signature_preferences(const struct s2n_signature_preferences *s2n_certificate_signature_preferences); +/* + * 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 <stdint.h> +#include "tls/s2n_cipher_preferences.h" +#include "tls/s2n_kem_preferences.h" +#include "tls/s2n_signature_scheme.h" +#include "tls/s2n_ecc_preferences.h" + +/* Kept up-to-date by s2n_security_policies_test */ +#define NUM_RSA_PSS_SCHEMES 6 + +struct s2n_security_policy { + uint8_t minimum_protocol_version; + const struct s2n_cipher_preferences *cipher_preferences; + const struct s2n_kem_preferences *kem_preferences; + const struct s2n_signature_preferences *signature_preferences; + const struct s2n_signature_preferences *certificate_signature_preferences; + const struct s2n_ecc_preferences *ecc_preferences; +}; + +struct s2n_security_policy_selection { + const char *version; + const struct s2n_security_policy *security_policy; + unsigned ecc_extension_required:1; + unsigned pq_kem_extension_required:1; + unsigned supports_tls13:1; +}; + +extern struct s2n_security_policy_selection security_policy_selection[]; + +extern const struct s2n_security_policy security_policy_20140601; +extern const struct s2n_security_policy security_policy_20141001; +extern const struct s2n_security_policy security_policy_20150202; +extern const struct s2n_security_policy security_policy_20150214; +extern const struct s2n_security_policy security_policy_20150306; +extern const struct s2n_security_policy security_policy_20160411; +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_20170405; +extern const struct s2n_security_policy security_policy_20170718; +extern const struct s2n_security_policy security_policy_20190214; +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_test_all; + +extern const struct s2n_security_policy security_policy_test_all_tls12; +extern const struct s2n_security_policy security_policy_test_all_fips; +extern const struct s2n_security_policy security_policy_test_all_ecdsa; +extern const struct s2n_security_policy security_policy_test_ecdsa_priority; +extern const struct s2n_security_policy security_policy_test_all_rsa_kex; +extern const struct s2n_security_policy security_policy_test_all_tls13; + +/* See https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html */ +extern const struct s2n_security_policy security_policy_elb_2015_04; +extern const struct s2n_security_policy security_policy_elb_2016_08; +extern const struct s2n_security_policy security_policy_elb_tls_1_2_2017_01; +extern const struct s2n_security_policy security_policy_elb_tls_1_1_2017_01; +extern const struct s2n_security_policy security_policy_elb_tls_1_2_ext_2018_06; +extern const struct s2n_security_policy security_policy_elb_fs_2018_06; +extern const struct s2n_security_policy security_policy_elb_fs_1_2_2019_08; +extern const struct s2n_security_policy security_policy_elb_fs_1_1_2019_08; +extern const struct s2n_security_policy security_policy_elb_fs_1_2_res_2019_08; + +#if !defined(S2N_NO_PQ) +extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2019_06; +extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_02; +extern const struct s2n_security_policy security_policy_kms_pq_tls_1_0_2020_07; +extern const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2019_11; +extern const struct s2n_security_policy security_policy_pq_sike_test_tls_1_0_2020_02; +extern const struct s2n_security_policy security_policy_pq_tls_1_0_2020_12; +#endif + +extern const struct s2n_security_policy security_policy_cloudfront_upstream; +extern const struct s2n_security_policy security_policy_cloudfront_upstream_tls10; +extern const struct s2n_security_policy security_policy_cloudfront_upstream_tls12; +extern const struct s2n_security_policy security_policy_cloudfront_ssl_v_3; +extern const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2014; +extern const struct s2n_security_policy security_policy_cloudfront_tls_1_0_2016; +extern const struct s2n_security_policy security_policy_cloudfront_tls_1_1_2016; +extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2018; +extern const struct s2n_security_policy security_policy_cloudfront_tls_1_2_2019; + +extern const struct s2n_security_policy security_policy_kms_tls_1_0_2018_10; +extern const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10; + +extern const struct s2n_security_policy security_policy_20190120; +extern const struct s2n_security_policy security_policy_20190121; +extern const struct s2n_security_policy security_policy_20190122; + +extern const struct s2n_security_policy security_policy_null; + +int s2n_security_policies_init(); +int s2n_config_set_cipher_preferences(struct s2n_config *config, const char *version); +int s2n_connection_set_cipher_preferences(struct s2n_connection *conn, const char *version); +bool s2n_ecc_is_extension_required(const struct s2n_security_policy *security_policy); +bool s2n_pq_kem_is_extension_required(const struct s2n_security_policy *security_policy); +bool s2n_security_policy_supports_tls13(const struct s2n_security_policy *security_policy); +int s2n_find_security_policy_from_version(const char *version, const struct s2n_security_policy **security_policy); +int s2n_validate_kem_preferences(const struct s2n_kem_preferences *kem_preferences, bool pq_kem_extension_required); +S2N_RESULT s2n_validate_certificate_signature_preferences(const struct s2n_signature_preferences *s2n_certificate_signature_preferences); diff --git a/contrib/restricted/aws/s2n/tls/s2n_send.c b/contrib/restricted/aws/s2n/tls/s2n_send.c index 47551d7af6..c9f9cf89d6 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_send.c +++ b/contrib/restricted/aws/s2n/tls/s2n_send.c @@ -1,217 +1,217 @@ -/* - * 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 <errno.h> -#include <s2n.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_handshake.h" -#include "tls/s2n_post_handshake.h" -#include "tls/s2n_record.h" - -#include "stuffer/s2n_stuffer.h" - -#include "crypto/s2n_cipher.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_blob.h" - -int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * blocked) -{ - int w; - - *blocked = S2N_BLOCKED_ON_WRITE; - - /* Write any data that's already pending */ - WRITE: - while (s2n_stuffer_data_available(&conn->out)) { - errno = 0; - w = s2n_connection_send_stuffer(&conn->out, conn, s2n_stuffer_data_available(&conn->out)); - if (w < 0) { - if (errno == EWOULDBLOCK || errno == EAGAIN) { - S2N_ERROR(S2N_ERR_IO_BLOCKED); - } - S2N_ERROR(S2N_ERR_IO); - } - conn->wire_bytes_out += w; - } - - if (conn->closing) { - conn->closed = 1; - } - 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)); - conn->closing = 1; - - /* Actually write it ... */ - goto WRITE; - } - - /* Do the same for writer driven alerts */ - if (s2n_stuffer_data_available(&conn->writer_alert_out) == 2) { - struct s2n_blob alert = {0}; - alert.data = conn->writer_alert_out.blob.data; - alert.size = 2; - GUARD(s2n_record_write(conn, TLS_ALERT, &alert)); - GUARD(s2n_stuffer_rewrite(&conn->writer_alert_out)); - conn->closing = 1; - - /* Actually write it ... */ - goto WRITE; - } - - *blocked = S2N_NOT_BLOCKED; - - return 0; -} - -ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, ssize_t offs, s2n_blocked_status *blocked) -{ - ssize_t 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); - - /* Flush any pending I/O */ - GUARD(s2n_flush(conn, blocked)); - - /* Acknowledge consumed and flushed user data as sent */ - user_data_sent = conn->current_user_data_consumed; - - *blocked = S2N_BLOCKED_ON_WRITE; - - uint16_t max_payload_size = 0; - GUARD_AS_POSIX(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 - * the remainder can follow as usual. - */ - int cbcHackUsed = 0; - - struct s2n_crypto_parameters *writer = conn->server; - if (conn->mode == S2N_CLIENT) { - writer = conn->client; - } - - /* Defensive check against an invalid retry */ - if (offs) { - const struct iovec* _bufs = bufs; - ssize_t _count = count; - while (offs >= _bufs->iov_len && _count > 0) { - offs -= _bufs->iov_len; - _bufs++; - _count--; - } - bufs = _bufs; - count = _count; - } - for (int 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); - - if (conn->dynamic_record_timeout_threshold > 0) { - uint64_t elapsed; - GUARD_AS_POSIX(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; - } - conn->last_write_elapsed = elapsed; - } - - /* Now write the data we were asked to send this round */ - while (total_size - conn->current_user_data_consumed) { - ssize_t to_write = MIN(total_size - conn->current_user_data_consumed, max_payload_size); - - /* If dynamic record size is enabled, - * use small TLS records that fit into a single TCP segment for the threshold bytes of data - */ - 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)); - to_write = MIN(min_payload_size, to_write); - } - - /* Don't split messages in server mode for interoperability with naive clients. - * Some clients may have expectations based on the amount of content in the first record. - */ - if (conn->actual_protocol_version < S2N_TLS11 && writer->cipher_suite->record_alg->cipher->type == S2N_CBC && conn->mode != S2N_SERVER) { - if (to_write > 1 && cbcHackUsed == 0) { - to_write = 1; - cbcHackUsed = 1; - } - } - - GUARD(s2n_stuffer_rewrite(&conn->out)); - - GUARD(s2n_post_handshake_send(conn, blocked)); - - /* Write and encrypt the record */ - 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; - - /* Send it */ - if (s2n_flush(conn, blocked) < 0) { - if (s2n_errno == S2N_ERR_IO_BLOCKED && user_data_sent > 0) { - /* We successfully sent >0 user bytes on the wire, but not the full requested payload - * because we became blocked on I/O. Acknowledge the data sent. */ - - conn->current_user_data_consumed -= user_data_sent; - return user_data_sent; - } else { - S2N_ERROR_PRESERVE_ERRNO(); - } - } - - /* Acknowledge consumed and flushed user data as sent */ - user_data_sent = conn->current_user_data_consumed; - } - - /* If everything has been written, then there's no user data pending */ - conn->current_user_data_consumed = 0; - - *blocked = S2N_NOT_BLOCKED; - - return total_size; -} - -ssize_t s2n_sendv(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, s2n_blocked_status *blocked) -{ - return s2n_sendv_with_offset(conn, bufs, count, 0, blocked); -} - -ssize_t s2n_send(struct s2n_connection *conn, const void *buf, ssize_t size, s2n_blocked_status *blocked) -{ - struct iovec iov; - iov.iov_base = (void*)(uintptr_t)buf; - iov.iov_len = size; - return s2n_sendv_with_offset(conn, &iov, 1, 0, blocked); -} +/* + * 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 <errno.h> +#include <s2n.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_handshake.h" +#include "tls/s2n_post_handshake.h" +#include "tls/s2n_record.h" + +#include "stuffer/s2n_stuffer.h" + +#include "crypto/s2n_cipher.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_blob.h" + +int s2n_flush(struct s2n_connection *conn, s2n_blocked_status * blocked) +{ + int w; + + *blocked = S2N_BLOCKED_ON_WRITE; + + /* Write any data that's already pending */ + WRITE: + while (s2n_stuffer_data_available(&conn->out)) { + errno = 0; + w = s2n_connection_send_stuffer(&conn->out, conn, s2n_stuffer_data_available(&conn->out)); + if (w < 0) { + if (errno == EWOULDBLOCK || errno == EAGAIN) { + S2N_ERROR(S2N_ERR_IO_BLOCKED); + } + S2N_ERROR(S2N_ERR_IO); + } + conn->wire_bytes_out += w; + } + + if (conn->closing) { + conn->closed = 1; + } + 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)); + conn->closing = 1; + + /* Actually write it ... */ + goto WRITE; + } + + /* Do the same for writer driven alerts */ + if (s2n_stuffer_data_available(&conn->writer_alert_out) == 2) { + struct s2n_blob alert = {0}; + alert.data = conn->writer_alert_out.blob.data; + alert.size = 2; + GUARD(s2n_record_write(conn, TLS_ALERT, &alert)); + GUARD(s2n_stuffer_rewrite(&conn->writer_alert_out)); + conn->closing = 1; + + /* Actually write it ... */ + goto WRITE; + } + + *blocked = S2N_NOT_BLOCKED; + + return 0; +} + +ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, ssize_t offs, s2n_blocked_status *blocked) +{ + ssize_t 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); + + /* Flush any pending I/O */ + GUARD(s2n_flush(conn, blocked)); + + /* Acknowledge consumed and flushed user data as sent */ + user_data_sent = conn->current_user_data_consumed; + + *blocked = S2N_BLOCKED_ON_WRITE; + + uint16_t max_payload_size = 0; + GUARD_AS_POSIX(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 + * the remainder can follow as usual. + */ + int cbcHackUsed = 0; + + struct s2n_crypto_parameters *writer = conn->server; + if (conn->mode == S2N_CLIENT) { + writer = conn->client; + } + + /* Defensive check against an invalid retry */ + if (offs) { + const struct iovec* _bufs = bufs; + ssize_t _count = count; + while (offs >= _bufs->iov_len && _count > 0) { + offs -= _bufs->iov_len; + _bufs++; + _count--; + } + bufs = _bufs; + count = _count; + } + for (int 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); + + if (conn->dynamic_record_timeout_threshold > 0) { + uint64_t elapsed; + GUARD_AS_POSIX(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; + } + conn->last_write_elapsed = elapsed; + } + + /* Now write the data we were asked to send this round */ + while (total_size - conn->current_user_data_consumed) { + ssize_t to_write = MIN(total_size - conn->current_user_data_consumed, max_payload_size); + + /* If dynamic record size is enabled, + * use small TLS records that fit into a single TCP segment for the threshold bytes of data + */ + 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)); + to_write = MIN(min_payload_size, to_write); + } + + /* Don't split messages in server mode for interoperability with naive clients. + * Some clients may have expectations based on the amount of content in the first record. + */ + if (conn->actual_protocol_version < S2N_TLS11 && writer->cipher_suite->record_alg->cipher->type == S2N_CBC && conn->mode != S2N_SERVER) { + if (to_write > 1 && cbcHackUsed == 0) { + to_write = 1; + cbcHackUsed = 1; + } + } + + GUARD(s2n_stuffer_rewrite(&conn->out)); + + GUARD(s2n_post_handshake_send(conn, blocked)); + + /* Write and encrypt the record */ + 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; + + /* Send it */ + if (s2n_flush(conn, blocked) < 0) { + if (s2n_errno == S2N_ERR_IO_BLOCKED && user_data_sent > 0) { + /* We successfully sent >0 user bytes on the wire, but not the full requested payload + * because we became blocked on I/O. Acknowledge the data sent. */ + + conn->current_user_data_consumed -= user_data_sent; + return user_data_sent; + } else { + S2N_ERROR_PRESERVE_ERRNO(); + } + } + + /* Acknowledge consumed and flushed user data as sent */ + user_data_sent = conn->current_user_data_consumed; + } + + /* If everything has been written, then there's no user data pending */ + conn->current_user_data_consumed = 0; + + *blocked = S2N_NOT_BLOCKED; + + return total_size; +} + +ssize_t s2n_sendv(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, s2n_blocked_status *blocked) +{ + return s2n_sendv_with_offset(conn, bufs, count, 0, blocked); +} + +ssize_t s2n_send(struct s2n_connection *conn, const void *buf, ssize_t size, s2n_blocked_status *blocked) +{ + struct iovec iov; + iov.iov_base = (void*)(uintptr_t)buf; + iov.iov_len = size; + return s2n_sendv_with_offset(conn, &iov, 1, 0, blocked); +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_cert.c b/contrib/restricted/aws/s2n/tls/s2n_server_cert.c index cd50e5acd6..0188505ae1 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_cert.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_cert.c @@ -1,71 +1,71 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <s2n.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_auth_selection.h" -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_tls.h" - -#include "utils/s2n_safety.h" - -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)); - 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)); - - 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)); - - 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); - - GUARD(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, conn, cert_chain.data, - cert_chain.size, &actual_cert_pkey_type, &public_key)); - - 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; - - return 0; -} - -int s2n_server_cert_send(struct s2n_connection *conn) -{ - S2N_ERROR_IF(conn->handshake_params.our_chain_and_key == NULL, S2N_ERR_CERT_TYPE_UNSUPPORTED); - if (conn->actual_protocol_version == S2N_TLS13) { - /* 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)); - } - - GUARD(s2n_send_cert_chain(conn, &conn->handshake.io, conn->handshake_params.our_chain_and_key)); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <s2n.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_auth_selection.h" +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_tls.h" + +#include "utils/s2n_safety.h" + +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)); + 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)); + + 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)); + + 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); + + GUARD(s2n_x509_validator_validate_cert_chain(&conn->x509_validator, conn, cert_chain.data, + cert_chain.size, &actual_cert_pkey_type, &public_key)); + + 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; + + return 0; +} + +int s2n_server_cert_send(struct s2n_connection *conn) +{ + S2N_ERROR_IF(conn->handshake_params.our_chain_and_key == NULL, S2N_ERR_CERT_TYPE_UNSUPPORTED); + if (conn->actual_protocol_version == S2N_TLS13) { + /* 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)); + } + + 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 92b591890d..26dcecc56c 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_cert_request.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_cert_request.c @@ -1,197 +1,197 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <s2n.h> - -#include "crypto/s2n_certificate.h" -#include "error/s2n_errno.h" -#include "extensions/s2n_extension_list.h" -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_config.h" -#include "tls/s2n_signature_algorithms.h" -#include "tls/s2n_signature_scheme.h" -#include "tls/s2n_tls.h" -#include "stuffer/s2n_stuffer.h" -#include "utils/s2n_safety.h" -#include "utils/s2n_array.h" - -/* RFC's that define below values: - * - https://tools.ietf.org/html/rfc5246#section-7.4.4 - * - https://tools.ietf.org/search/rfc4492#section-5.5 - */ -typedef enum { - S2N_CERT_TYPE_RSA_SIGN = 1, - S2N_CERT_TYPE_DSS_SIGN = 2, - S2N_CERT_TYPE_RSA_FIXED_DH = 3, - S2N_CERT_TYPE_DSS_FIXED_DH = 4, - S2N_CERT_TYPE_RSA_EPHEMERAL_DH_RESERVED = 5, - S2N_CERT_TYPE_DSS_EPHEMERAL_DH_RESERVED = 6, - S2N_CERT_TYPE_FORTEZZA_DMS_RESERVED = 20, - S2N_CERT_TYPE_ECDSA_SIGN = 64, - S2N_CERT_TYPE_RSA_FIXED_ECDH = 65, - S2N_CERT_TYPE_ECDSA_FIXED_ECDH = 66, -} s2n_cert_type; - -static uint8_t s2n_cert_type_preference_list[] = { - S2N_CERT_TYPE_RSA_SIGN, - S2N_CERT_TYPE_ECDSA_SIGN -}; - -/* - * Include DSS sign certificate type in server certificate request. - * Only will be used if cert_req_dss_legacy_compat_enabled is set by calling s2n_config_enable_cert_req_dss_legacy_compat. - */ -static uint8_t s2n_cert_type_preference_list_legacy_dss[] = { - S2N_CERT_TYPE_RSA_SIGN, - S2N_CERT_TYPE_DSS_SIGN, - 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)); - - uint8_t *their_cert_type_pref_list = s2n_stuffer_raw_read(in, cert_types_len); - notnull_check(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++) { - for (int their_cert_idx = 0; their_cert_idx < cert_types_len; their_cert_idx++) { - if (their_cert_type_pref_list[their_cert_idx] == s2n_cert_type_preference_list[our_cert_pref_idx]) { - *chosen_cert_type_out = s2n_cert_type_preference_list[our_cert_pref_idx]; - return 0; - } - } - } - - S2N_ERROR(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)); - - struct s2n_cert_chain_and_key *cert = s2n_config_get_single_default_cert(conn->config); - notnull_check(cert); - conn->handshake_params.our_chain_and_key = cert; - } - - return 0; -} - -int s2n_tls13_cert_req_recv(struct s2n_connection *conn) -{ - struct s2n_stuffer *in = &conn->handshake.io; - - /* read request context length */ - uint8_t request_context_length; - 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)); - - GUARD(s2n_set_cert_chain_as_client(conn)); - - return S2N_SUCCESS; -} - -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)); - - if (conn->actual_protocol_version == S2N_TLS12) { - 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)); - - /* 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)); - - /* 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)); - - return 0; -} - -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)); - - GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_CERT_REQ, conn, out)); - - return S2N_SUCCESS; -} - -int s2n_cert_req_send(struct s2n_connection *conn) -{ - struct s2n_stuffer *out = &conn->handshake.io; - - uint8_t client_cert_preference_list_size = sizeof(s2n_cert_type_preference_list); - 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)); - - 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])); - } else { - 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)); - } - - /* 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)); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <s2n.h> + +#include "crypto/s2n_certificate.h" +#include "error/s2n_errno.h" +#include "extensions/s2n_extension_list.h" +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_config.h" +#include "tls/s2n_signature_algorithms.h" +#include "tls/s2n_signature_scheme.h" +#include "tls/s2n_tls.h" +#include "stuffer/s2n_stuffer.h" +#include "utils/s2n_safety.h" +#include "utils/s2n_array.h" + +/* RFC's that define below values: + * - https://tools.ietf.org/html/rfc5246#section-7.4.4 + * - https://tools.ietf.org/search/rfc4492#section-5.5 + */ +typedef enum { + S2N_CERT_TYPE_RSA_SIGN = 1, + S2N_CERT_TYPE_DSS_SIGN = 2, + S2N_CERT_TYPE_RSA_FIXED_DH = 3, + S2N_CERT_TYPE_DSS_FIXED_DH = 4, + S2N_CERT_TYPE_RSA_EPHEMERAL_DH_RESERVED = 5, + S2N_CERT_TYPE_DSS_EPHEMERAL_DH_RESERVED = 6, + S2N_CERT_TYPE_FORTEZZA_DMS_RESERVED = 20, + S2N_CERT_TYPE_ECDSA_SIGN = 64, + S2N_CERT_TYPE_RSA_FIXED_ECDH = 65, + S2N_CERT_TYPE_ECDSA_FIXED_ECDH = 66, +} s2n_cert_type; + +static uint8_t s2n_cert_type_preference_list[] = { + S2N_CERT_TYPE_RSA_SIGN, + S2N_CERT_TYPE_ECDSA_SIGN +}; + +/* + * Include DSS sign certificate type in server certificate request. + * Only will be used if cert_req_dss_legacy_compat_enabled is set by calling s2n_config_enable_cert_req_dss_legacy_compat. + */ +static uint8_t s2n_cert_type_preference_list_legacy_dss[] = { + S2N_CERT_TYPE_RSA_SIGN, + S2N_CERT_TYPE_DSS_SIGN, + 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)); + + uint8_t *their_cert_type_pref_list = s2n_stuffer_raw_read(in, cert_types_len); + notnull_check(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++) { + for (int their_cert_idx = 0; their_cert_idx < cert_types_len; their_cert_idx++) { + if (their_cert_type_pref_list[their_cert_idx] == s2n_cert_type_preference_list[our_cert_pref_idx]) { + *chosen_cert_type_out = s2n_cert_type_preference_list[our_cert_pref_idx]; + return 0; + } + } + } + + S2N_ERROR(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)); + + struct s2n_cert_chain_and_key *cert = s2n_config_get_single_default_cert(conn->config); + notnull_check(cert); + conn->handshake_params.our_chain_and_key = cert; + } + + return 0; +} + +int s2n_tls13_cert_req_recv(struct s2n_connection *conn) +{ + struct s2n_stuffer *in = &conn->handshake.io; + + /* read request context length */ + uint8_t request_context_length; + 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)); + + GUARD(s2n_set_cert_chain_as_client(conn)); + + return S2N_SUCCESS; +} + +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)); + + if (conn->actual_protocol_version == S2N_TLS12) { + 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)); + + /* 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)); + + /* 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)); + + return 0; +} + +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)); + + GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_CERT_REQ, conn, out)); + + return S2N_SUCCESS; +} + +int s2n_cert_req_send(struct s2n_connection *conn) +{ + struct s2n_stuffer *out = &conn->handshake.io; + + uint8_t client_cert_preference_list_size = sizeof(s2n_cert_type_preference_list); + 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)); + + 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])); + } else { + 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)); + } + + /* 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)); + + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_done.c b/contrib/restricted/aws/s2n/tls/s2n_server_done.c index ebd2bc9e7b..6ddc123140 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_done.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_done.c @@ -1,35 +1,35 @@ -/* - * 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 <stdint.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" - -#include "stuffer/s2n_stuffer.h" - -int s2n_server_done_recv(struct s2n_connection *conn) -{ - S2N_ERROR_IF(s2n_stuffer_data_available(&conn->handshake.io), S2N_ERR_BAD_MESSAGE); - - return 0; -} - -int s2n_server_done_send(struct s2n_connection *conn) -{ - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <stdint.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" + +#include "stuffer/s2n_stuffer.h" + +int s2n_server_done_recv(struct s2n_connection *conn) +{ + S2N_ERROR_IF(s2n_stuffer_data_available(&conn->handshake.io), S2N_ERR_BAD_MESSAGE); + + return 0; +} + +int s2n_server_done_send(struct s2n_connection *conn) +{ + 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 6a022b14e2..0fc8f6bb15 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_extensions.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_extensions.c @@ -1,72 +1,72 @@ -/* - * 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_server_extensions.h" - -#include "tls/extensions/s2n_extension_list.h" -#include "tls/extensions/s2n_server_supported_versions.h" -#include "tls/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" -#include "utils/s2n_safety.h" - - -/* An empty list will just contain the uint16_t list size */ -#define S2N_EMPTY_EXTENSION_LIST_SIZE sizeof(uint16_t) - -int s2n_server_extensions_send(struct s2n_connection *conn, struct s2n_stuffer *out) -{ - 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)); - } else { - 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. - * This is to support older clients written before extensions existed that might fail - * on any unexpected bytes at the end of the ServerHello. - * - * This behavior is outlined in the TLS1.2 RFC: https://tools.ietf.org/html/rfc5246#appendix-A.4.1 - * - * This behavior does not affect TLS1.3, which always requires at least the supported_version extension - * 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)); - } - - return S2N_SUCCESS; -} - -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)); - - /* 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)); - - if (conn->server_protocol_version >= S2N_TLS13) { - 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)); - } - - return S2N_SUCCESS; -} +/* + * 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_server_extensions.h" + +#include "tls/extensions/s2n_extension_list.h" +#include "tls/extensions/s2n_server_supported_versions.h" +#include "tls/s2n_connection.h" +#include "stuffer/s2n_stuffer.h" +#include "utils/s2n_safety.h" + + +/* An empty list will just contain the uint16_t list size */ +#define S2N_EMPTY_EXTENSION_LIST_SIZE sizeof(uint16_t) + +int s2n_server_extensions_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + 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)); + } else { + 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. + * This is to support older clients written before extensions existed that might fail + * on any unexpected bytes at the end of the ServerHello. + * + * This behavior is outlined in the TLS1.2 RFC: https://tools.ietf.org/html/rfc5246#appendix-A.4.1 + * + * This behavior does not affect TLS1.3, which always requires at least the supported_version extension + * 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)); + } + + return S2N_SUCCESS; +} + +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)); + + /* 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)); + + if (conn->server_protocol_version >= S2N_TLS13) { + 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)); + } + + return S2N_SUCCESS; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_extensions.h b/contrib/restricted/aws/s2n/tls/s2n_server_extensions.h index f196a2396a..57b720395c 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_extensions.h +++ b/contrib/restricted/aws/s2n/tls/s2n_server_extensions.h @@ -1,22 +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/s2n_connection.h" -#include "stuffer/s2n_stuffer.h" - -int s2n_server_extensions_send(struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_server_extensions_recv(struct s2n_connection *conn, struct s2n_stuffer *in); +/* + * 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_connection.h" +#include "stuffer/s2n_stuffer.h" + +int s2n_server_extensions_send(struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_server_extensions_recv(struct s2n_connection *conn, struct s2n_stuffer *in); diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_finished.c b/contrib/restricted/aws/s2n/tls/s2n_server_finished.c index 1df8bfc8fe..156641dd14 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_finished.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_finished.c @@ -1,131 +1,131 @@ -/* - * 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 <stdint.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_resume.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls13_handshake.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_safety.h" - -int s2n_server_finished_recv(struct s2n_connection *conn) -{ - uint8_t *our_version; - int length = S2N_TLS_FINISHED_LEN; - our_version = conn->handshake.server_finished; - - if (conn->actual_protocol_version == S2N_SSLv3) { - length = S2N_SSL_FINISHED_LEN; - } - - uint8_t *their_version = s2n_stuffer_raw_read(&conn->handshake.io, length); - notnull_check(their_version); - - S2N_ERROR_IF(!s2n_constant_time_equals(our_version, their_version, length), S2N_ERR_BAD_MESSAGE); - - return 0; -} - -int s2n_server_finished_send(struct s2n_connection *conn) -{ - uint8_t *our_version; - int length = S2N_TLS_FINISHED_LEN; - - /* Compute the finished message */ - GUARD(s2n_prf_server_finished(conn)); - - our_version = conn->handshake.server_finished; - - if (conn->actual_protocol_version == S2N_SSLv3) { - length = S2N_SSL_FINISHED_LEN; - } - - 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)); - - /* 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)); - } - - return 0; -} - - -int s2n_tls13_server_finished_recv(struct s2n_connection *conn) { - eq_check(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); - - /* read finished mac from handshake */ - struct s2n_blob wire_finished_mac = {0}; - s2n_blob_init(&wire_finished_mac, s2n_stuffer_raw_read(&conn->handshake.io, length), length); - - /* 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)); - - /* look up finished secret key */ - struct s2n_blob finished_key = {0}; - 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)); - - /* compare mac with received message */ - 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); - - /* 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)); - - /* look up finished secret key */ - struct s2n_blob finished_key = {0}; - 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)); - - /* write to handshake io */ - GUARD(s2n_stuffer_write(&conn->handshake.io, &server_finished_mac)); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <stdint.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_resume.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls13_handshake.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_safety.h" + +int s2n_server_finished_recv(struct s2n_connection *conn) +{ + uint8_t *our_version; + int length = S2N_TLS_FINISHED_LEN; + our_version = conn->handshake.server_finished; + + if (conn->actual_protocol_version == S2N_SSLv3) { + length = S2N_SSL_FINISHED_LEN; + } + + uint8_t *their_version = s2n_stuffer_raw_read(&conn->handshake.io, length); + notnull_check(their_version); + + S2N_ERROR_IF(!s2n_constant_time_equals(our_version, their_version, length), S2N_ERR_BAD_MESSAGE); + + return 0; +} + +int s2n_server_finished_send(struct s2n_connection *conn) +{ + uint8_t *our_version; + int length = S2N_TLS_FINISHED_LEN; + + /* Compute the finished message */ + GUARD(s2n_prf_server_finished(conn)); + + our_version = conn->handshake.server_finished; + + if (conn->actual_protocol_version == S2N_SSLv3) { + length = S2N_SSL_FINISHED_LEN; + } + + 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)); + + /* 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)); + } + + return 0; +} + + +int s2n_tls13_server_finished_recv(struct s2n_connection *conn) { + eq_check(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); + + /* read finished mac from handshake */ + struct s2n_blob wire_finished_mac = {0}; + s2n_blob_init(&wire_finished_mac, s2n_stuffer_raw_read(&conn->handshake.io, length), length); + + /* 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)); + + /* look up finished secret key */ + struct s2n_blob finished_key = {0}; + 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)); + + /* compare mac with received message */ + 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); + + /* 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)); + + /* look up finished secret key */ + struct s2n_blob finished_key = {0}; + 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)); + + /* write to handshake io */ + 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 11259dad7b..010c06547a 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_hello.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_hello.c @@ -1,251 +1,251 @@ -/* - * 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 <s2n.h> -#include <time.h> - -#include "crypto/s2n_fips.h" - -#include "error/s2n_errno.h" - -#include "tls/s2n_cipher_preferences.h" -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_alerts.h" -#include "tls/s2n_server_extensions.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls13.h" -#include "tls/s2n_security_policies.h" -#include "tls/s2n_tls13_handshake.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_random.h" - -/* From RFC5246 7.4.1.2. */ -#define S2N_TLS_COMPRESSION_METHOD_NULL 0 - -/* From RFC8446 4.1.3. */ -#define S2N_DOWNGRADE_PROTECTION_SIZE 8 -const uint8_t tls12_downgrade_protection_bytes[] = { - 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x01 -}; - -const uint8_t tls11_downgrade_protection_bytes[] = { - 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x00 -}; - -static int s2n_hello_retry_validate(struct s2n_connection *conn) { - notnull_check(conn); - - ENSURE_POSIX(memcmp(hello_retry_req_random, conn->secure.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]; - - /* 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); - } - } 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); - } - } - - return 0; -} - -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]; - - /* 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); - } 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); - } - - return 0; -} - -static int s2n_server_hello_parse(struct s2n_connection *conn) -{ - notnull_check(conn); - - struct s2n_stuffer *in = &conn->handshake.io; - uint8_t compression_method; - uint8_t session_id_len; - 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)); - - /* 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)); - } - - 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)); - - uint8_t *cipher_suite_wire = s2n_stuffer_raw_read(in, S2N_TLS_CIPHER_SUITE_LEN); - notnull_check(cipher_suite_wire); - - 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)); - - 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); - conn->actual_protocol_version = conn->server_protocol_version; - 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); - - const struct s2n_security_policy *security_policy; - 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); - } - - 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)) { - /* 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); - - /* Session is resumed */ - conn->client_session_resumed = 1; - } else { - conn->session_id_len = session_id_len; - memcpy_check(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)); - /* Erase master secret which might have been set for session resumption */ - memset_check((uint8_t *)conn->secure.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)); - } - } - - return 0; -} - -int s2n_server_hello_recv(struct s2n_connection *conn) -{ - notnull_check(conn); - - /* Read the message off the wire */ - GUARD(s2n_server_hello_parse(conn)); - - conn->actual_protocol_version_established = 1; - - 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)); - return 0; - } - - if (IS_RESUMPTION_HANDSHAKE(conn->handshake.handshake_type)) { - GUARD(s2n_prf_key_expansion(conn)); - } - - /* Choose a default signature scheme */ - GUARD(s2n_choose_default_sig_scheme(conn, &conn->secure.conn_sig_scheme)); - - /* Update the required hashes for this connection */ - GUARD(s2n_conn_update_required_handshake_hashes(conn)); - - return 0; -} - -int s2n_server_hello_write_message(struct s2n_connection *conn) -{ - notnull_check(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. - * https://tools.ietf.org/html/rfc8446#section-4.1.3 */ - const uint16_t legacy_protocol_version = MIN(conn->actual_protocol_version, S2N_TLS12); - uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; - 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)); - - return 0; -} - -int s2n_server_hello_send(struct s2n_connection *conn) -{ - notnull_check(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)); - - /* Create the server random data */ - 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)); - - /* Add a downgrade detection mechanism if required */ - GUARD(s2n_server_add_downgrade_mechanism(conn)); - - GUARD(s2n_server_hello_write_message(conn)); - - GUARD(s2n_server_extensions_send(conn, &conn->handshake.io)); - - conn->actual_protocol_version_established = 1; - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <sys/param.h> + +#include <s2n.h> +#include <time.h> + +#include "crypto/s2n_fips.h" + +#include "error/s2n_errno.h" + +#include "tls/s2n_cipher_preferences.h" +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_alerts.h" +#include "tls/s2n_server_extensions.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls13.h" +#include "tls/s2n_security_policies.h" +#include "tls/s2n_tls13_handshake.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_random.h" + +/* From RFC5246 7.4.1.2. */ +#define S2N_TLS_COMPRESSION_METHOD_NULL 0 + +/* From RFC8446 4.1.3. */ +#define S2N_DOWNGRADE_PROTECTION_SIZE 8 +const uint8_t tls12_downgrade_protection_bytes[] = { + 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x01 +}; + +const uint8_t tls11_downgrade_protection_bytes[] = { + 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x00 +}; + +static int s2n_hello_retry_validate(struct s2n_connection *conn) { + notnull_check(conn); + + ENSURE_POSIX(memcmp(hello_retry_req_random, conn->secure.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]; + + /* 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); + } + } 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); + } + } + + return 0; +} + +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]; + + /* 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); + } 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); + } + + return 0; +} + +static int s2n_server_hello_parse(struct s2n_connection *conn) +{ + notnull_check(conn); + + struct s2n_stuffer *in = &conn->handshake.io; + uint8_t compression_method; + uint8_t session_id_len; + 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)); + + /* 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)); + } + + 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)); + + uint8_t *cipher_suite_wire = s2n_stuffer_raw_read(in, S2N_TLS_CIPHER_SUITE_LEN); + notnull_check(cipher_suite_wire); + + 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)); + + 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); + conn->actual_protocol_version = conn->server_protocol_version; + 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); + + const struct s2n_security_policy *security_policy; + 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); + } + + 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)) { + /* 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); + + /* Session is resumed */ + conn->client_session_resumed = 1; + } else { + conn->session_id_len = session_id_len; + memcpy_check(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)); + /* Erase master secret which might have been set for session resumption */ + memset_check((uint8_t *)conn->secure.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)); + } + } + + return 0; +} + +int s2n_server_hello_recv(struct s2n_connection *conn) +{ + notnull_check(conn); + + /* Read the message off the wire */ + GUARD(s2n_server_hello_parse(conn)); + + conn->actual_protocol_version_established = 1; + + 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)); + return 0; + } + + if (IS_RESUMPTION_HANDSHAKE(conn->handshake.handshake_type)) { + GUARD(s2n_prf_key_expansion(conn)); + } + + /* Choose a default signature scheme */ + GUARD(s2n_choose_default_sig_scheme(conn, &conn->secure.conn_sig_scheme)); + + /* Update the required hashes for this connection */ + GUARD(s2n_conn_update_required_handshake_hashes(conn)); + + return 0; +} + +int s2n_server_hello_write_message(struct s2n_connection *conn) +{ + notnull_check(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. + * https://tools.ietf.org/html/rfc8446#section-4.1.3 */ + const uint16_t legacy_protocol_version = MIN(conn->actual_protocol_version, S2N_TLS12); + uint8_t protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN]; + 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)); + + return 0; +} + +int s2n_server_hello_send(struct s2n_connection *conn) +{ + notnull_check(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)); + + /* Create the server random data */ + 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)); + + /* Add a downgrade detection mechanism if required */ + GUARD(s2n_server_add_downgrade_mechanism(conn)); + + GUARD(s2n_server_hello_write_message(conn)); + + GUARD(s2n_server_extensions_send(conn, &conn->handshake.io)); + + conn->actual_protocol_version_established = 1; + + return 0; +} 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 6bff554dee..f35c5a0016 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_hello_retry.c @@ -1,131 +1,131 @@ -/* - * 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 <stdbool.h> - -#include "error/s2n_errno.h" -#include "utils/s2n_blob.h" -#include "tls/s2n_cipher_suites.h" -#include "tls/s2n_server_extensions.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_tls13.h" -#include "tls/s2n_tls13_handshake.h" -#include "utils/s2n_safety.h" -#include "crypto/s2n_fips.h" - -/* From RFC5246 7.4.1.2. */ -#define S2N_TLS_COMPRESSION_METHOD_NULL 0 - -/* from RFC: https://tools.ietf.org/html/rfc8446#section-4.1.3*/ -uint8_t hello_retry_req_random[S2N_TLS_RANDOM_DATA_LEN] = { - 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, - 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C -}; - -static int s2n_conn_reset_retry_values(struct s2n_connection *conn) -{ - notnull_check(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)); - - return 0; -} - -int s2n_server_hello_retry_send(struct s2n_connection *conn) -{ - notnull_check(conn); - - memcpy_check(conn->secure.server_random, hello_retry_req_random, S2N_TLS_RANDOM_DATA_LEN); - - GUARD(s2n_server_hello_write_message(conn)); - - /* Write the extensions */ - 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)); - - 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); - - 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); - - /* Upon receipt of the HelloRetryRequest, the client MUST verify that: - * (1) the selected_group field corresponds to a group - * which was provided in the "supported_groups" extension in the - * original ClientHello and - * (2) the selected_group field does not correspond to a group which was provided - * 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; - - /* 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); - - 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; - } - } - } - - if (kem_group != NULL) { - /* If in FIPS mode, the client should not have sent any PQ IDs - * in the supported_groups list of the initial ClientHello */ - ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); - - 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); - } - } - } - - ENSURE_POSIX(match_found, S2N_ERR_INVALID_HELLO_RETRY); - - /* Update transcript hash */ - GUARD(s2n_server_hello_retry_recreate_transcript(conn)); - - return S2N_SUCCESS; -} +/* + * 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 <stdbool.h> + +#include "error/s2n_errno.h" +#include "utils/s2n_blob.h" +#include "tls/s2n_cipher_suites.h" +#include "tls/s2n_server_extensions.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_tls13.h" +#include "tls/s2n_tls13_handshake.h" +#include "utils/s2n_safety.h" +#include "crypto/s2n_fips.h" + +/* From RFC5246 7.4.1.2. */ +#define S2N_TLS_COMPRESSION_METHOD_NULL 0 + +/* from RFC: https://tools.ietf.org/html/rfc8446#section-4.1.3*/ +uint8_t hello_retry_req_random[S2N_TLS_RANDOM_DATA_LEN] = { + 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, + 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C +}; + +static int s2n_conn_reset_retry_values(struct s2n_connection *conn) +{ + notnull_check(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)); + + return 0; +} + +int s2n_server_hello_retry_send(struct s2n_connection *conn) +{ + notnull_check(conn); + + memcpy_check(conn->secure.server_random, hello_retry_req_random, S2N_TLS_RANDOM_DATA_LEN); + + GUARD(s2n_server_hello_write_message(conn)); + + /* Write the extensions */ + 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)); + + 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); + + 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); + + /* Upon receipt of the HelloRetryRequest, the client MUST verify that: + * (1) the selected_group field corresponds to a group + * which was provided in the "supported_groups" extension in the + * original ClientHello and + * (2) the selected_group field does not correspond to a group which was provided + * 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; + + /* 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); + + 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; + } + } + } + + if (kem_group != NULL) { + /* If in FIPS mode, the client should not have sent any PQ IDs + * in the supported_groups list of the initial ClientHello */ + ENSURE_POSIX(s2n_is_in_fips_mode() == false, S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS); + + 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); + } + } + } + + ENSURE_POSIX(match_found, S2N_ERR_INVALID_HELLO_RETRY); + + /* Update transcript hash */ + 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 855d2373b1..2169f7c5e2 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c +++ b/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.c @@ -1,335 +1,335 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <s2n.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" -#include "tls/s2n_connection.h" -#include "tls/s2n_signature_algorithms.h" -#include "tls/s2n_cipher_preferences.h" -#include "tls/s2n_security_policies.h" - -#include "stuffer/s2n_stuffer.h" - -#include "crypto/s2n_dhe.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_random.h" - -static int s2n_server_key_send_write_signature(struct s2n_connection *conn, struct s2n_blob *signature); - -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); - - struct s2n_hash_state *signature_hash = &conn->secure.signature_hash; - 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(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; - 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; - } - 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)); - - /* Add KEX specific data */ - 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)); - - struct s2n_blob signature = {.size = signature_length, .data = s2n_stuffer_raw_read(in, signature_length)}; - notnull_check(signature.data); - gt_check(signature_length, 0); - - S2N_ERROR_IF(s2n_pkey_verify(&conn->secure.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)); - - /* Parse the KEX data into whatever form needed and save it to the connection object */ - GUARD(s2n_kex_server_key_recv_parse_data(key_exchange, conn, &kex_data)); - return 0; -} - -int s2n_ecdhe_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data) -{ - struct s2n_stuffer *in = &conn->handshake.io; - - 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)); - - return 0; -} - -int s2n_dhe_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data) -{ - struct s2n_stuffer *in = &conn->handshake.io; - struct s2n_dhe_raw_server_points *dhe_data = &raw_server_data->dhe_data; - - uint16_t p_length; - uint16_t g_length; - uint16_t Ys_length; - - /* 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); - - /* Read each of the three elements in */ - 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); - - 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); - - 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); - - /* Now we know the total size of the structure */ - data_to_verify->size = 2 + p_length + 2 + g_length + 2 + Ys_length; - return 0; -} - -int s2n_dhe_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data) -{ - 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)); - return 0; -} - -int s2n_kem_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data) -{ - struct s2n_kem_raw_server_params *kem_data = &raw_server_data->kem_data; - struct s2n_stuffer *in = &conn->handshake.io; - - /* 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); - - /* the server sends the KEM ID */ - kem_data->kem_name.data = s2n_stuffer_raw_read(in, 2); - notnull_check(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)); - - 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))); - - 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; - - data_to_verify->size = sizeof(kem_extension_size) + sizeof(kem_public_key_size) + kem_data->raw_public_key.size; - - return 0; -} - -int s2n_kem_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data) -{ - struct s2n_kem_raw_server_params *kem_data = &raw_server_data->kem_data; - - /* 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); - - 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; - - S2N_ERROR_IF(kem_data->raw_public_key.size != conn->secure.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); - 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); - - struct s2n_blob data_to_verify_0 = {0}; - GUARD(s2n_kex_server_key_recv_read_data(hybrid_kex_0, conn, &data_to_verify_0, raw_server_data)); - - struct s2n_blob data_to_verify_1 = {0}; - GUARD(s2n_kex_server_key_recv_read_data(hybrid_kex_1, conn, &data_to_verify_1, raw_server_data)); - - total_data_to_verify->size = data_to_verify_0.size + data_to_verify_1.size; - return 0; -} - -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); - 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(s2n_kex_server_key_recv_parse_data(hybrid_kex_0, conn, raw_server_data)); - GUARD(s2n_kex_server_key_recv_parse_data(hybrid_kex_1, conn, raw_server_data)); - return 0; -} - -int s2n_server_key_send(struct s2n_connection *conn) -{ - S2N_ASYNC_PKEY_GUARD(conn); - - struct s2n_hash_state *signature_hash = &conn->secure.signature_hash; - 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(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)); - } - - /* 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)); - - /* Add KEX specific data to the hash */ - 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); -} - -int s2n_ecdhe_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign) -{ - 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)); - - /* 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)); - return 0; -} - -int s2n_dhe_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign) -{ - 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)); - - /* Generate an ephemeral key */ - GUARD(s2n_dh_generate_ephemeral_key(&conn->secure.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)); - 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; - - data_to_sign->data = s2n_stuffer_raw_write(out, 0); - notnull_check(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))); - - data_to_sign->size = sizeof(kem_extension_size) + sizeof(kem_public_key_size) + kem->public_key_length; - - return 0; -} - -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); - 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); - - struct s2n_blob data_to_verify_0 = {0}; - GUARD(s2n_kex_server_key_send(hybrid_kex_0, conn, &data_to_verify_0)); - - struct s2n_blob data_to_verify_1 = {0}; - GUARD(s2n_kex_server_key_send(hybrid_kex_1, conn, &data_to_verify_1)); - - total_data_to_sign->size = data_to_verify_0.size + data_to_verify_1.size; - return 0; -} - -int s2n_server_key_send_write_signature(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_bytes(out, signature->data, signature->size)); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <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" +#include "tls/s2n_connection.h" +#include "tls/s2n_signature_algorithms.h" +#include "tls/s2n_cipher_preferences.h" +#include "tls/s2n_security_policies.h" + +#include "stuffer/s2n_stuffer.h" + +#include "crypto/s2n_dhe.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_random.h" + +static int s2n_server_key_send_write_signature(struct s2n_connection *conn, struct s2n_blob *signature); + +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); + + struct s2n_hash_state *signature_hash = &conn->secure.signature_hash; + 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(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; + 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; + } + 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)); + + /* Add KEX specific data */ + 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)); + + struct s2n_blob signature = {.size = signature_length, .data = s2n_stuffer_raw_read(in, signature_length)}; + notnull_check(signature.data); + gt_check(signature_length, 0); + + S2N_ERROR_IF(s2n_pkey_verify(&conn->secure.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)); + + /* Parse the KEX data into whatever form needed and save it to the connection object */ + GUARD(s2n_kex_server_key_recv_parse_data(key_exchange, conn, &kex_data)); + return 0; +} + +int s2n_ecdhe_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data) +{ + struct s2n_stuffer *in = &conn->handshake.io; + + 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)); + + return 0; +} + +int s2n_dhe_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data) +{ + struct s2n_stuffer *in = &conn->handshake.io; + struct s2n_dhe_raw_server_points *dhe_data = &raw_server_data->dhe_data; + + uint16_t p_length; + uint16_t g_length; + uint16_t Ys_length; + + /* 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); + + /* Read each of the three elements in */ + 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); + + 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); + + 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); + + /* Now we know the total size of the structure */ + data_to_verify->size = 2 + p_length + 2 + g_length + 2 + Ys_length; + return 0; +} + +int s2n_dhe_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data) +{ + 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)); + return 0; +} + +int s2n_kem_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data) +{ + struct s2n_kem_raw_server_params *kem_data = &raw_server_data->kem_data; + struct s2n_stuffer *in = &conn->handshake.io; + + /* 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); + + /* the server sends the KEM ID */ + kem_data->kem_name.data = s2n_stuffer_raw_read(in, 2); + notnull_check(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)); + + 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))); + + 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; + + data_to_verify->size = sizeof(kem_extension_size) + sizeof(kem_public_key_size) + kem_data->raw_public_key.size; + + return 0; +} + +int s2n_kem_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data) +{ + struct s2n_kem_raw_server_params *kem_data = &raw_server_data->kem_data; + + /* 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); + + 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; + + S2N_ERROR_IF(kem_data->raw_public_key.size != conn->secure.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); + 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); + + struct s2n_blob data_to_verify_0 = {0}; + GUARD(s2n_kex_server_key_recv_read_data(hybrid_kex_0, conn, &data_to_verify_0, raw_server_data)); + + struct s2n_blob data_to_verify_1 = {0}; + GUARD(s2n_kex_server_key_recv_read_data(hybrid_kex_1, conn, &data_to_verify_1, raw_server_data)); + + total_data_to_verify->size = data_to_verify_0.size + data_to_verify_1.size; + return 0; +} + +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); + 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(s2n_kex_server_key_recv_parse_data(hybrid_kex_0, conn, raw_server_data)); + GUARD(s2n_kex_server_key_recv_parse_data(hybrid_kex_1, conn, raw_server_data)); + return 0; +} + +int s2n_server_key_send(struct s2n_connection *conn) +{ + S2N_ASYNC_PKEY_GUARD(conn); + + struct s2n_hash_state *signature_hash = &conn->secure.signature_hash; + 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(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)); + } + + /* 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)); + + /* Add KEX specific data to the hash */ + 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); +} + +int s2n_ecdhe_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign) +{ + 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)); + + /* 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)); + return 0; +} + +int s2n_dhe_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign) +{ + 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)); + + /* Generate an ephemeral key */ + GUARD(s2n_dh_generate_ephemeral_key(&conn->secure.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)); + 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; + + data_to_sign->data = s2n_stuffer_raw_write(out, 0); + notnull_check(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))); + + data_to_sign->size = sizeof(kem_extension_size) + sizeof(kem_public_key_size) + kem->public_key_length; + + return 0; +} + +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); + 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); + + struct s2n_blob data_to_verify_0 = {0}; + GUARD(s2n_kex_server_key_send(hybrid_kex_0, conn, &data_to_verify_0)); + + struct s2n_blob data_to_verify_1 = {0}; + GUARD(s2n_kex_server_key_send(hybrid_kex_1, conn, &data_to_verify_1)); + + total_data_to_sign->size = data_to_verify_0.size + data_to_verify_1.size; + return 0; +} + +int s2n_server_key_send_write_signature(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_bytes(out, signature->data, signature->size)); + + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.h b/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.h index 2c1deb9eba..2402bd3281 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.h +++ b/contrib/restricted/aws/s2n/tls/s2n_server_key_exchange.h @@ -1,35 +1,35 @@ -/* - * 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_connection.h" -#include "tls/s2n_kex.h" -#include "utils/s2n_blob.h" - -int s2n_dhe_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data); -int s2n_ecdhe_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data); -int s2n_kem_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data); -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); - -int s2n_dhe_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); -int s2n_ecdhe_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); -int s2n_kem_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); -int s2n_hybrid_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); - -int s2n_dhe_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign); -int s2n_ecdhe_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign); -int s2n_kem_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign); -int s2n_hybrid_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign); +/* + * 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_connection.h" +#include "tls/s2n_kex.h" +#include "utils/s2n_blob.h" + +int s2n_dhe_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data); +int s2n_ecdhe_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data); +int s2n_kem_server_key_recv_read_data(struct s2n_connection *conn, struct s2n_blob *data_to_verify, struct s2n_kex_raw_server_data *raw_server_data); +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); + +int s2n_dhe_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); +int s2n_ecdhe_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); +int s2n_kem_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); +int s2n_hybrid_server_key_recv_parse_data(struct s2n_connection *conn, struct s2n_kex_raw_server_data *raw_server_data); + +int s2n_dhe_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign); +int s2n_ecdhe_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign); +int s2n_kem_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign); +int s2n_hybrid_server_key_send(struct s2n_connection *conn, struct s2n_blob *data_to_sign); 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 593a1efdba..a42c5029d2 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 @@ -1,76 +1,76 @@ -/* - * 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 <s2n.h> -#include <time.h> - -#include "error/s2n_errno.h" - -#include "tls/s2n_connection.h" -#include "tls/s2n_alerts.h" -#include "tls/s2n_tls.h" -#include "tls/s2n_resume.h" - -#include "stuffer/s2n_stuffer.h" - -#include "utils/s2n_safety.h" -#include "utils/s2n_random.h" - -int s2n_server_nst_recv(struct s2n_connection *conn) { - 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)); - - if (session_ticket_len > 0) { - GUARD(s2n_realloc(&conn->client_ticket, session_ticket_len)); - - GUARD(s2n_stuffer_read(&conn->handshake.io, &conn->client_ticket)); - } - - return 0; -} - -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]; - 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)); - - return 0; - } - - if (!s2n_server_sending_nst(conn)) { - S2N_ERROR(S2N_ERR_SENDING_NST); - } - - 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)); - - GUARD(s2n_encrypt_session_ticket(conn, &to)); - GUARD(s2n_stuffer_write(&conn->handshake.io, &to.blob)); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <sys/param.h> + +#include <s2n.h> +#include <time.h> + +#include "error/s2n_errno.h" + +#include "tls/s2n_connection.h" +#include "tls/s2n_alerts.h" +#include "tls/s2n_tls.h" +#include "tls/s2n_resume.h" + +#include "stuffer/s2n_stuffer.h" + +#include "utils/s2n_safety.h" +#include "utils/s2n_random.h" + +int s2n_server_nst_recv(struct s2n_connection *conn) { + 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)); + + if (session_ticket_len > 0) { + GUARD(s2n_realloc(&conn->client_ticket, session_ticket_len)); + + GUARD(s2n_stuffer_read(&conn->handshake.io, &conn->client_ticket)); + } + + return 0; +} + +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]; + 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)); + + return 0; + } + + if (!s2n_server_sending_nst(conn)) { + S2N_ERROR(S2N_ERR_SENDING_NST); + } + + 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)); + + GUARD(s2n_encrypt_session_ticket(conn, &to)); + GUARD(s2n_stuffer_write(&conn->handshake.io, &to.blob)); + + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_shutdown.c b/contrib/restricted/aws/s2n/tls/s2n_shutdown.c index 4963e0e25d..700d94b1d1 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_shutdown.c +++ b/contrib/restricted/aws/s2n/tls/s2n_shutdown.c @@ -1,55 +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. - */ - -#include <s2n.h> - -#include "tls/s2n_alerts.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_tls.h" - -#include "utils/s2n_safety.h" - -int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status * more) -{ - notnull_check(conn); - notnull_check(more); - - /* Treat this call as a no-op if already wiped */ - if (conn->send == NULL && conn->recv == NULL) { - return 0; - } - - uint64_t elapsed; - GUARD_AS_POSIX(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)); - - /* Write it */ - 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)); - 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)); - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <s2n.h> + +#include "tls/s2n_alerts.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_tls.h" + +#include "utils/s2n_safety.h" + +int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status * more) +{ + notnull_check(conn); + notnull_check(more); + + /* Treat this call as a no-op if already wiped */ + if (conn->send == NULL && conn->recv == NULL) { + return 0; + } + + uint64_t elapsed; + GUARD_AS_POSIX(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)); + + /* Write it */ + 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)); + 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)); + + 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 310b48aeb0..4645eae5f1 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c +++ b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.c @@ -1,290 +1,290 @@ -/* - * 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 "crypto/s2n_fips.h" -#include "crypto/s2n_rsa_signing.h" -#include "crypto/s2n_rsa_pss.h" -#include "error/s2n_errno.h" - -#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" - -#include "utils/s2n_safety.h" - -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); - - if (!s2n_is_rsa_pss_signing_supported()) { - ne_check(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); - } - - return 0; -} - -static int s2n_signature_scheme_valid_to_accept(struct s2n_connection *conn, const struct s2n_signature_scheme *scheme) -{ - notnull_check(scheme); - - 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); - } - - 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); - - GUARD(s2n_signature_scheme_valid_to_accept(conn, candidate)); - GUARD(s2n_is_sig_scheme_valid_for_auth(conn, candidate)); - - return S2N_SUCCESS; -} - -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); - const struct s2n_signature_preferences *signature_preferences = NULL; - GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences)); - notnull_check(signature_preferences); - - struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite; - notnull_check(cipher_suite); - - for (size_t i = 0; i < signature_preferences->count; i++) { - const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i]; - - if (s2n_is_signature_scheme_usable(conn, candidate) != S2N_SUCCESS) { - continue; - } - - for (size_t j = 0; j < peer_wire_prefs->len; j++) { - uint16_t their_iana_val = peer_wire_prefs->iana_list[j]; - - if (candidate->iana_value == their_iana_val) { - *chosen_scheme_out = *candidate; - return S2N_SUCCESS; - } - } - } - - /* do not error even if there's no match */ - return S2N_SUCCESS; -} - -/* 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) -{ - notnull_check(conn); - const struct s2n_signature_preferences *signature_preferences = NULL; - GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences)); - notnull_check(signature_preferences); - - struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite; - notnull_check(cipher_suite); - - for (size_t i = 0; i < signature_preferences->count; i++) { - const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i]; - - if (s2n_is_signature_scheme_usable(conn, candidate) != S2N_SUCCESS) { - continue; - } - - *chosen_scheme_out = *candidate; - return S2N_SUCCESS; - } - - S2N_ERROR(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)); - - const struct s2n_signature_preferences *signature_preferences = NULL; - GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences)); - notnull_check(signature_preferences); - - for (size_t i = 0; i < signature_preferences->count; i++) { - const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i]; - - if (0 != s2n_signature_scheme_valid_to_accept(conn, candidate)) { - continue; - } - - if (candidate->iana_value == actual_iana_val) { - *chosen_sig_scheme = *candidate; - return S2N_SUCCESS; - } - } - - /* 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)); - - if ((conn->actual_protocol_version <= S2N_TLS12) - && (s2n_signature_scheme_valid_to_accept(conn, &default_scheme) == S2N_SUCCESS) - && (actual_iana_val == default_scheme.iana_value)) { - - *chosen_sig_scheme = default_scheme; - return S2N_SUCCESS; - } - - S2N_ERROR(S2N_ERR_INVALID_SIGNATURE_SCHEME); -} - -int s2n_choose_default_sig_scheme(struct s2n_connection *conn, struct s2n_signature_scheme *sig_scheme_out) -{ - notnull_check(conn); - notnull_check(conn->secure.cipher_suite); - notnull_check(sig_scheme_out); - - s2n_authentication_method 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 - * cipher suite, this will be overridden to SHA1. - */ - *sig_scheme_out = s2n_rsa_pkcs1_md5_sha1; - - if (cipher_suite_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)) { - *sig_scheme_out = s2n_rsa_pkcs1_sha1; - } - - return S2N_SUCCESS; -} - -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; - - if (conn->actual_protocol_version < S2N_TLS13) { - GUARD(s2n_choose_default_sig_scheme(conn, &chosen_scheme)); - } 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)); - } - - /* 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)); - } - - *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); - - 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)); - } - } - - return 0; -} - -int s2n_supported_sig_scheme_list_size(struct s2n_connection *conn) -{ - return s2n_supported_sig_schemes_count(conn) * TLS_SIGNATURE_SCHEME_LEN; -} - -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); - - uint8_t count = 0; - for (size_t i = 0; i < signature_preferences->count; i++) { - if (0 == s2n_signature_scheme_valid_to_offer(conn, signature_preferences->signature_schemes[i])) { - count ++; - } - } - return count; -} - -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)); - if (length_of_all_pairs > s2n_stuffer_data_available(in)) { - /* Malformed length, ignore the extension */ - return 0; - } - - 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)); - 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); - } - - 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)); - - sig_hash_algs->iana_list[sig_hash_algs->len] = sig_scheme; - sig_hash_algs->len += 1; - } - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "crypto/s2n_fips.h" +#include "crypto/s2n_rsa_signing.h" +#include "crypto/s2n_rsa_pss.h" +#include "error/s2n_errno.h" + +#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" + +#include "utils/s2n_safety.h" + +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); + + if (!s2n_is_rsa_pss_signing_supported()) { + ne_check(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); + } + + return 0; +} + +static int s2n_signature_scheme_valid_to_accept(struct s2n_connection *conn, const struct s2n_signature_scheme *scheme) +{ + notnull_check(scheme); + + 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); + } + + 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); + + GUARD(s2n_signature_scheme_valid_to_accept(conn, candidate)); + GUARD(s2n_is_sig_scheme_valid_for_auth(conn, candidate)); + + return S2N_SUCCESS; +} + +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); + const struct s2n_signature_preferences *signature_preferences = NULL; + GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences)); + notnull_check(signature_preferences); + + struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite; + notnull_check(cipher_suite); + + for (size_t i = 0; i < signature_preferences->count; i++) { + const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i]; + + if (s2n_is_signature_scheme_usable(conn, candidate) != S2N_SUCCESS) { + continue; + } + + for (size_t j = 0; j < peer_wire_prefs->len; j++) { + uint16_t their_iana_val = peer_wire_prefs->iana_list[j]; + + if (candidate->iana_value == their_iana_val) { + *chosen_scheme_out = *candidate; + return S2N_SUCCESS; + } + } + } + + /* do not error even if there's no match */ + return S2N_SUCCESS; +} + +/* 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) +{ + notnull_check(conn); + const struct s2n_signature_preferences *signature_preferences = NULL; + GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences)); + notnull_check(signature_preferences); + + struct s2n_cipher_suite *cipher_suite = conn->secure.cipher_suite; + notnull_check(cipher_suite); + + for (size_t i = 0; i < signature_preferences->count; i++) { + const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i]; + + if (s2n_is_signature_scheme_usable(conn, candidate) != S2N_SUCCESS) { + continue; + } + + *chosen_scheme_out = *candidate; + return S2N_SUCCESS; + } + + S2N_ERROR(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)); + + const struct s2n_signature_preferences *signature_preferences = NULL; + GUARD(s2n_connection_get_signature_preferences(conn, &signature_preferences)); + notnull_check(signature_preferences); + + for (size_t i = 0; i < signature_preferences->count; i++) { + const struct s2n_signature_scheme *candidate = signature_preferences->signature_schemes[i]; + + if (0 != s2n_signature_scheme_valid_to_accept(conn, candidate)) { + continue; + } + + if (candidate->iana_value == actual_iana_val) { + *chosen_sig_scheme = *candidate; + return S2N_SUCCESS; + } + } + + /* 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)); + + if ((conn->actual_protocol_version <= S2N_TLS12) + && (s2n_signature_scheme_valid_to_accept(conn, &default_scheme) == S2N_SUCCESS) + && (actual_iana_val == default_scheme.iana_value)) { + + *chosen_sig_scheme = default_scheme; + return S2N_SUCCESS; + } + + S2N_ERROR(S2N_ERR_INVALID_SIGNATURE_SCHEME); +} + +int s2n_choose_default_sig_scheme(struct s2n_connection *conn, struct s2n_signature_scheme *sig_scheme_out) +{ + notnull_check(conn); + notnull_check(conn->secure.cipher_suite); + notnull_check(sig_scheme_out); + + s2n_authentication_method 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 + * cipher suite, this will be overridden to SHA1. + */ + *sig_scheme_out = s2n_rsa_pkcs1_md5_sha1; + + if (cipher_suite_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)) { + *sig_scheme_out = s2n_rsa_pkcs1_sha1; + } + + return S2N_SUCCESS; +} + +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; + + if (conn->actual_protocol_version < S2N_TLS13) { + GUARD(s2n_choose_default_sig_scheme(conn, &chosen_scheme)); + } 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)); + } + + /* 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)); + } + + *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); + + 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)); + } + } + + return 0; +} + +int s2n_supported_sig_scheme_list_size(struct s2n_connection *conn) +{ + return s2n_supported_sig_schemes_count(conn) * TLS_SIGNATURE_SCHEME_LEN; +} + +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); + + uint8_t count = 0; + for (size_t i = 0; i < signature_preferences->count; i++) { + if (0 == s2n_signature_scheme_valid_to_offer(conn, signature_preferences->signature_schemes[i])) { + count ++; + } + } + return count; +} + +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)); + if (length_of_all_pairs > s2n_stuffer_data_available(in)) { + /* Malformed length, ignore the extension */ + return 0; + } + + 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)); + 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); + } + + 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)); + + sig_hash_algs->iana_list[sig_hash_algs->len] = sig_scheme; + sig_hash_algs->len += 1; + } + + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.h b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.h index 123c4266d9..b400977a16 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.h +++ b/contrib/restricted/aws/s2n/tls/s2n_signature_algorithms.h @@ -1,41 +1,41 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include <s2n.h> - -#include "crypto/s2n_hash.h" -#include "crypto/s2n_signature.h" - -#include "stuffer/s2n_stuffer.h" - -struct s2n_connection; - -struct s2n_sig_scheme_list { - uint16_t iana_list[TLS_SIGNATURE_SCHEME_LIST_MAX_LEN]; - uint8_t len; -}; - -int s2n_choose_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, - struct s2n_signature_scheme *chosen_sig_scheme); - -int s2n_recv_supported_sig_scheme_list(struct s2n_stuffer *in, struct s2n_sig_scheme_list *sig_hash_algs); -int s2n_send_supported_sig_scheme_list(struct s2n_connection *conn, struct s2n_stuffer *out); -int s2n_supported_sig_schemes_count(struct s2n_connection *conn); -int s2n_supported_sig_scheme_list_size(struct s2n_connection *conn); +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include <s2n.h> + +#include "crypto/s2n_hash.h" +#include "crypto/s2n_signature.h" + +#include "stuffer/s2n_stuffer.h" + +struct s2n_connection; + +struct s2n_sig_scheme_list { + uint16_t iana_list[TLS_SIGNATURE_SCHEME_LIST_MAX_LEN]; + uint8_t len; +}; + +int s2n_choose_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, + struct s2n_signature_scheme *chosen_sig_scheme); + +int s2n_recv_supported_sig_scheme_list(struct s2n_stuffer *in, struct s2n_sig_scheme_list *sig_hash_algs); +int s2n_send_supported_sig_scheme_list(struct s2n_connection *conn, struct s2n_stuffer *out); +int s2n_supported_sig_schemes_count(struct s2n_connection *conn); +int s2n_supported_sig_scheme_list_size(struct s2n_connection *conn); diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c index 3f3ad6dfd4..911e717127 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c +++ b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.c @@ -1,341 +1,341 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#include <s2n.h> - -#include "crypto/s2n_hash.h" -#include "crypto/s2n_signature.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_signature_scheme.h" -#include "crypto/s2n_ecc_evp.h" -#include "utils/s2n_safety.h" - -/* RSA PKCS1 */ -const struct s2n_signature_scheme s2n_rsa_pkcs1_md5_sha1 = { - .iana_value = TLS_SIGNATURE_SCHEME_PRIVATE_INTERNAL_RSA_PKCS1_MD5_SHA1, - .hash_alg = S2N_HASH_MD5_SHA1, - .sig_alg = S2N_SIGNATURE_RSA, - .libcrypto_nid = NID_md5_sha1, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ - .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 or sha1 */ -}; - -const struct s2n_signature_scheme s2n_rsa_pkcs1_sha1 = { - .iana_value = TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA1, - .hash_alg = S2N_HASH_SHA1, - .sig_alg = S2N_SIGNATURE_RSA, - .libcrypto_nid = NID_sha1WithRSAEncryption, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ - .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 or sha1 */ -}; - -const struct s2n_signature_scheme s2n_rsa_pkcs1_sha224 = { - .iana_value = TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA224, - .hash_alg = S2N_HASH_SHA224, - .sig_alg = S2N_SIGNATURE_RSA, - .libcrypto_nid = NID_sha224WithRSAEncryption, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ - .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 */ -}; - -const struct s2n_signature_scheme s2n_rsa_pkcs1_sha256 = { - .iana_value = TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA256, - .hash_alg = S2N_HASH_SHA256, - .sig_alg = S2N_SIGNATURE_RSA, - .libcrypto_nid = NID_sha256WithRSAEncryption, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ - .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 */ -}; - -const struct s2n_signature_scheme s2n_rsa_pkcs1_sha384 = { - .iana_value = TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA384, - .hash_alg = S2N_HASH_SHA384, - .sig_alg = S2N_SIGNATURE_RSA, - .libcrypto_nid = NID_sha384WithRSAEncryption, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ - .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 */ -}; - -const struct s2n_signature_scheme s2n_rsa_pkcs1_sha512 = { - .iana_value = TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA512, - .hash_alg = S2N_HASH_SHA512, - .sig_alg = S2N_SIGNATURE_RSA, - .libcrypto_nid = NID_sha512WithRSAEncryption, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ - .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 */ -}; - -/* TLS 1.2 Compatible ECDSA Signature Schemes */ -const struct s2n_signature_scheme s2n_ecdsa_sha1 = { - .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SHA1, - .hash_alg = S2N_HASH_SHA1, - .sig_alg = S2N_SIGNATURE_ECDSA, - .libcrypto_nid = NID_ecdsa_with_SHA1, - .signature_curve = NULL, /* Decided by supported_groups Extension in TLS 1.2 and before */ - .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support sha1 and requires a signature curve */ -}; - -const struct s2n_signature_scheme s2n_ecdsa_sha224 = { - .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SHA224, - .hash_alg = S2N_HASH_SHA224, - .sig_alg = S2N_SIGNATURE_ECDSA, - .libcrypto_nid = NID_ecdsa_with_SHA224, - .signature_curve = NULL, /* Decided by supported_groups Extension in TLS 1.2 and before */ - .maximum_protocol_version = S2N_TLS12, /* TLS1.3 requires a signature curve */ -}; - -const struct s2n_signature_scheme s2n_ecdsa_sha256 = { - .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SHA256, - .hash_alg = S2N_HASH_SHA256, - .sig_alg = S2N_SIGNATURE_ECDSA, - .libcrypto_nid = NID_ecdsa_with_SHA256, - .signature_curve = NULL, /* Decided by supported_groups Extension in TLS 1.2 and before */ - .maximum_protocol_version = S2N_TLS12, /* TLS1.3 requires a signature curve */ -}; - -const struct s2n_signature_scheme s2n_ecdsa_sha384 = { - .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SHA384, - .hash_alg = S2N_HASH_SHA384, - .sig_alg = S2N_SIGNATURE_ECDSA, - .libcrypto_nid = NID_ecdsa_with_SHA384, - .signature_curve = NULL, /* Decided by supported_groups Extension in TLS 1.2 and before */ - .maximum_protocol_version = S2N_TLS12, /* TLS1.3 requires a signature curve */ -}; - -const struct s2n_signature_scheme s2n_ecdsa_sha512 = { - .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SHA512, - .hash_alg = S2N_HASH_SHA512, - .sig_alg = S2N_SIGNATURE_ECDSA, - .libcrypto_nid = NID_ecdsa_with_SHA512, - .signature_curve = NULL, /* Decided by supported_groups Extension in TLS 1.2 and before */ - .maximum_protocol_version = S2N_TLS12, /* TLS1.3 requires a signature curve */ -}; - -/* TLS 1.3 Compatible ECDSA Schemes */ -/* In TLS 1.3 the two byte IANA value also defines the Curve to use for signing */ - -const struct s2n_signature_scheme s2n_ecdsa_secp256r1_sha256 = { - .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SECP256R1_SHA256, - .hash_alg = S2N_HASH_SHA256, - .sig_alg = S2N_SIGNATURE_ECDSA, - .libcrypto_nid = NID_ecdsa_with_SHA256, - .signature_curve = &s2n_ecc_curve_secp256r1, /* Hardcoded as of TLS 1.3 */ - .minimum_protocol_version = S2N_TLS13, -}; - -const struct s2n_signature_scheme s2n_ecdsa_secp384r1_sha384 = { - .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SECP384R1_SHA384, - .hash_alg = S2N_HASH_SHA384, - .sig_alg = S2N_SIGNATURE_ECDSA, - .libcrypto_nid = NID_ecdsa_with_SHA384, - .signature_curve = &s2n_ecc_curve_secp384r1, /* Hardcoded as of TLS 1.3 */ - .minimum_protocol_version = S2N_TLS13, -}; - -const struct s2n_signature_scheme s2n_ecdsa_secp521r1_sha512 = { - .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SECP521R1_SHA512, - .hash_alg = S2N_HASH_SHA512, - .sig_alg = S2N_SIGNATURE_ECDSA, - .signature_curve = &s2n_ecc_curve_secp521r1, /* Hardcoded as of TLS 1.3 */ - .minimum_protocol_version = S2N_TLS13, -}; - -/** - * RSA-PSS-RSAE - */ -const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha256 = { - .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA256, - .hash_alg = S2N_HASH_SHA256, - .sig_alg = S2N_SIGNATURE_RSA_PSS_RSAE, - .libcrypto_nid = NID_rsassaPss, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ -}; - -const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha384 = { - .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA384, - .hash_alg = S2N_HASH_SHA384, - .sig_alg = S2N_SIGNATURE_RSA_PSS_RSAE, - .libcrypto_nid = NID_rsassaPss, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ -}; - -const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha512 = { - .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA512, - .hash_alg = S2N_HASH_SHA512, - .sig_alg = S2N_SIGNATURE_RSA_PSS_RSAE, - .libcrypto_nid = NID_rsassaPss, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ -}; - -/** - * RSA-PSS-PSS - */ -const struct s2n_signature_scheme s2n_rsa_pss_pss_sha256 = { - .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA256, - .hash_alg = S2N_HASH_SHA256, - .sig_alg = S2N_SIGNATURE_RSA_PSS_PSS, - .libcrypto_nid = NID_rsassaPss, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ - .minimum_protocol_version = S2N_TLS13, -}; - -const struct s2n_signature_scheme s2n_rsa_pss_pss_sha384 = { - .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA384, - .hash_alg = S2N_HASH_SHA384, - .sig_alg = S2N_SIGNATURE_RSA_PSS_PSS, - .libcrypto_nid = NID_rsassaPss, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ - .minimum_protocol_version = S2N_TLS13, -}; - -const struct s2n_signature_scheme s2n_rsa_pss_pss_sha512 = { - .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA512, - .hash_alg = S2N_HASH_SHA512, - .sig_alg = S2N_SIGNATURE_RSA_PSS_PSS, - .libcrypto_nid = NID_rsassaPss, - .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ - .minimum_protocol_version = S2N_TLS13, -}; - -/* All Supported SignatureSchemes. */ -/* No MD5 to avoid SLOTH Vulnerability */ -const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20140601[] = { - /* RSA PKCS1 */ - &s2n_rsa_pkcs1_sha256, - &s2n_rsa_pkcs1_sha384, - &s2n_rsa_pkcs1_sha512, - &s2n_rsa_pkcs1_sha224, - - /* ECDSA - TLS 1.2 */ - &s2n_ecdsa_sha256, /* same iana value as TLS 1.3 s2n_ecdsa_secp256r1_sha256 */ - &s2n_ecdsa_secp256r1_sha256, - &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */ - &s2n_ecdsa_secp384r1_sha384, - &s2n_ecdsa_sha512, - &s2n_ecdsa_sha224, - - /* SHA-1 Legacy */ - &s2n_rsa_pkcs1_sha1, - &s2n_ecdsa_sha1, -}; - -/* The original preference list, but with rsa_pss supported. */ -const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20200207[] = { - /* RSA PSS */ - &s2n_rsa_pss_pss_sha256, - &s2n_rsa_pss_pss_sha384, - &s2n_rsa_pss_pss_sha512, - &s2n_rsa_pss_rsae_sha256, - &s2n_rsa_pss_rsae_sha384, - &s2n_rsa_pss_rsae_sha512, - - /* RSA PKCS1 */ - &s2n_rsa_pkcs1_sha256, - &s2n_rsa_pkcs1_sha384, - &s2n_rsa_pkcs1_sha512, - &s2n_rsa_pkcs1_sha224, - - /* ECDSA - TLS 1.2 */ - &s2n_ecdsa_sha256, /* same iana value as TLS 1.3 s2n_ecdsa_secp256r1_sha256 */ - &s2n_ecdsa_secp256r1_sha256, - &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */ - &s2n_ecdsa_secp384r1_sha384, - &s2n_ecdsa_sha512, - &s2n_ecdsa_sha224, - - /* SHA-1 Legacy */ - &s2n_rsa_pkcs1_sha1, - &s2n_ecdsa_sha1, -}; - -/* Add s2n_ecdsa_secp521r1_sha512 */ -const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20201021[] = { - /* RSA PSS */ - &s2n_rsa_pss_pss_sha256, - &s2n_rsa_pss_pss_sha384, - &s2n_rsa_pss_pss_sha512, - &s2n_rsa_pss_rsae_sha256, - &s2n_rsa_pss_rsae_sha384, - &s2n_rsa_pss_rsae_sha512, - - /* RSA PKCS1 */ - &s2n_rsa_pkcs1_sha256, - &s2n_rsa_pkcs1_sha384, - &s2n_rsa_pkcs1_sha512, - &s2n_rsa_pkcs1_sha224, - - /* ECDSA - TLS 1.2 */ - &s2n_ecdsa_sha256, /* same iana value as TLS 1.3 s2n_ecdsa_secp256r1_sha256 */ - &s2n_ecdsa_secp256r1_sha256, - &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */ - &s2n_ecdsa_secp384r1_sha384, - &s2n_ecdsa_sha512, /* same iana value as TLS 1.3 s2n_ecdsa_secp521r1_sha512 */ - &s2n_ecdsa_secp521r1_sha512, - &s2n_ecdsa_sha224, - - /* SHA-1 Legacy */ - &s2n_rsa_pkcs1_sha1, - &s2n_ecdsa_sha1, -}; - -const struct s2n_signature_preferences s2n_signature_preferences_20140601 = { - .count = s2n_array_len(s2n_sig_scheme_pref_list_20140601), - .signature_schemes = s2n_sig_scheme_pref_list_20140601, -}; - -const struct s2n_signature_preferences s2n_signature_preferences_20200207 = { - .count = s2n_array_len(s2n_sig_scheme_pref_list_20200207), - .signature_schemes = s2n_sig_scheme_pref_list_20200207, -}; - -const struct s2n_signature_preferences s2n_signature_preferences_20201021 = { - .count = s2n_array_len(s2n_sig_scheme_pref_list_20201021), - .signature_schemes = s2n_sig_scheme_pref_list_20201021, -}; - -const struct s2n_signature_preferences s2n_signature_preferences_null = { - .count = 0, - .signature_schemes = NULL, -}; - -/* TLS1.3 supported signature schemes, without SHA-1 legacy algorithms */ -const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20201110[] = { - /* RSA PSS */ - &s2n_rsa_pss_pss_sha256, - &s2n_rsa_pss_pss_sha384, - &s2n_rsa_pss_pss_sha512, - &s2n_rsa_pss_rsae_sha256, - &s2n_rsa_pss_rsae_sha384, - &s2n_rsa_pss_rsae_sha512, - - /* RSA PKCS1 */ - &s2n_rsa_pkcs1_sha256, - &s2n_rsa_pkcs1_sha384, - &s2n_rsa_pkcs1_sha512, - &s2n_rsa_pkcs1_sha224, - - /* ECDSA - TLS 1.2 */ - &s2n_ecdsa_sha256, /* same iana value as TLS 1.3 s2n_ecdsa_secp256r1_sha256 */ - &s2n_ecdsa_secp256r1_sha256, - &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */ - &s2n_ecdsa_secp384r1_sha384, - &s2n_ecdsa_sha512, - &s2n_ecdsa_sha224, -}; - -const struct s2n_signature_preferences s2n_certificate_signature_preferences_20201110 = { - .count = s2n_array_len(s2n_sig_scheme_pref_list_20201110), - .signature_schemes = s2n_sig_scheme_pref_list_20201110, -}; +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include <s2n.h> + +#include "crypto/s2n_hash.h" +#include "crypto/s2n_signature.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_signature_scheme.h" +#include "crypto/s2n_ecc_evp.h" +#include "utils/s2n_safety.h" + +/* RSA PKCS1 */ +const struct s2n_signature_scheme s2n_rsa_pkcs1_md5_sha1 = { + .iana_value = TLS_SIGNATURE_SCHEME_PRIVATE_INTERNAL_RSA_PKCS1_MD5_SHA1, + .hash_alg = S2N_HASH_MD5_SHA1, + .sig_alg = S2N_SIGNATURE_RSA, + .libcrypto_nid = NID_md5_sha1, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ + .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 or sha1 */ +}; + +const struct s2n_signature_scheme s2n_rsa_pkcs1_sha1 = { + .iana_value = TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA1, + .hash_alg = S2N_HASH_SHA1, + .sig_alg = S2N_SIGNATURE_RSA, + .libcrypto_nid = NID_sha1WithRSAEncryption, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ + .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 or sha1 */ +}; + +const struct s2n_signature_scheme s2n_rsa_pkcs1_sha224 = { + .iana_value = TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA224, + .hash_alg = S2N_HASH_SHA224, + .sig_alg = S2N_SIGNATURE_RSA, + .libcrypto_nid = NID_sha224WithRSAEncryption, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ + .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 */ +}; + +const struct s2n_signature_scheme s2n_rsa_pkcs1_sha256 = { + .iana_value = TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA256, + .hash_alg = S2N_HASH_SHA256, + .sig_alg = S2N_SIGNATURE_RSA, + .libcrypto_nid = NID_sha256WithRSAEncryption, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ + .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 */ +}; + +const struct s2n_signature_scheme s2n_rsa_pkcs1_sha384 = { + .iana_value = TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA384, + .hash_alg = S2N_HASH_SHA384, + .sig_alg = S2N_SIGNATURE_RSA, + .libcrypto_nid = NID_sha384WithRSAEncryption, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ + .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 */ +}; + +const struct s2n_signature_scheme s2n_rsa_pkcs1_sha512 = { + .iana_value = TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA512, + .hash_alg = S2N_HASH_SHA512, + .sig_alg = S2N_SIGNATURE_RSA, + .libcrypto_nid = NID_sha512WithRSAEncryption, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ + .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support pkcs1 */ +}; + +/* TLS 1.2 Compatible ECDSA Signature Schemes */ +const struct s2n_signature_scheme s2n_ecdsa_sha1 = { + .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SHA1, + .hash_alg = S2N_HASH_SHA1, + .sig_alg = S2N_SIGNATURE_ECDSA, + .libcrypto_nid = NID_ecdsa_with_SHA1, + .signature_curve = NULL, /* Decided by supported_groups Extension in TLS 1.2 and before */ + .maximum_protocol_version = S2N_TLS12, /* TLS1.3 does not support sha1 and requires a signature curve */ +}; + +const struct s2n_signature_scheme s2n_ecdsa_sha224 = { + .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SHA224, + .hash_alg = S2N_HASH_SHA224, + .sig_alg = S2N_SIGNATURE_ECDSA, + .libcrypto_nid = NID_ecdsa_with_SHA224, + .signature_curve = NULL, /* Decided by supported_groups Extension in TLS 1.2 and before */ + .maximum_protocol_version = S2N_TLS12, /* TLS1.3 requires a signature curve */ +}; + +const struct s2n_signature_scheme s2n_ecdsa_sha256 = { + .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SHA256, + .hash_alg = S2N_HASH_SHA256, + .sig_alg = S2N_SIGNATURE_ECDSA, + .libcrypto_nid = NID_ecdsa_with_SHA256, + .signature_curve = NULL, /* Decided by supported_groups Extension in TLS 1.2 and before */ + .maximum_protocol_version = S2N_TLS12, /* TLS1.3 requires a signature curve */ +}; + +const struct s2n_signature_scheme s2n_ecdsa_sha384 = { + .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SHA384, + .hash_alg = S2N_HASH_SHA384, + .sig_alg = S2N_SIGNATURE_ECDSA, + .libcrypto_nid = NID_ecdsa_with_SHA384, + .signature_curve = NULL, /* Decided by supported_groups Extension in TLS 1.2 and before */ + .maximum_protocol_version = S2N_TLS12, /* TLS1.3 requires a signature curve */ +}; + +const struct s2n_signature_scheme s2n_ecdsa_sha512 = { + .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SHA512, + .hash_alg = S2N_HASH_SHA512, + .sig_alg = S2N_SIGNATURE_ECDSA, + .libcrypto_nid = NID_ecdsa_with_SHA512, + .signature_curve = NULL, /* Decided by supported_groups Extension in TLS 1.2 and before */ + .maximum_protocol_version = S2N_TLS12, /* TLS1.3 requires a signature curve */ +}; + +/* TLS 1.3 Compatible ECDSA Schemes */ +/* In TLS 1.3 the two byte IANA value also defines the Curve to use for signing */ + +const struct s2n_signature_scheme s2n_ecdsa_secp256r1_sha256 = { + .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SECP256R1_SHA256, + .hash_alg = S2N_HASH_SHA256, + .sig_alg = S2N_SIGNATURE_ECDSA, + .libcrypto_nid = NID_ecdsa_with_SHA256, + .signature_curve = &s2n_ecc_curve_secp256r1, /* Hardcoded as of TLS 1.3 */ + .minimum_protocol_version = S2N_TLS13, +}; + +const struct s2n_signature_scheme s2n_ecdsa_secp384r1_sha384 = { + .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SECP384R1_SHA384, + .hash_alg = S2N_HASH_SHA384, + .sig_alg = S2N_SIGNATURE_ECDSA, + .libcrypto_nid = NID_ecdsa_with_SHA384, + .signature_curve = &s2n_ecc_curve_secp384r1, /* Hardcoded as of TLS 1.3 */ + .minimum_protocol_version = S2N_TLS13, +}; + +const struct s2n_signature_scheme s2n_ecdsa_secp521r1_sha512 = { + .iana_value = TLS_SIGNATURE_SCHEME_ECDSA_SECP521R1_SHA512, + .hash_alg = S2N_HASH_SHA512, + .sig_alg = S2N_SIGNATURE_ECDSA, + .signature_curve = &s2n_ecc_curve_secp521r1, /* Hardcoded as of TLS 1.3 */ + .minimum_protocol_version = S2N_TLS13, +}; + +/** + * RSA-PSS-RSAE + */ +const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha256 = { + .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA256, + .hash_alg = S2N_HASH_SHA256, + .sig_alg = S2N_SIGNATURE_RSA_PSS_RSAE, + .libcrypto_nid = NID_rsassaPss, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ +}; + +const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha384 = { + .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA384, + .hash_alg = S2N_HASH_SHA384, + .sig_alg = S2N_SIGNATURE_RSA_PSS_RSAE, + .libcrypto_nid = NID_rsassaPss, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ +}; + +const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha512 = { + .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA512, + .hash_alg = S2N_HASH_SHA512, + .sig_alg = S2N_SIGNATURE_RSA_PSS_RSAE, + .libcrypto_nid = NID_rsassaPss, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ +}; + +/** + * RSA-PSS-PSS + */ +const struct s2n_signature_scheme s2n_rsa_pss_pss_sha256 = { + .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA256, + .hash_alg = S2N_HASH_SHA256, + .sig_alg = S2N_SIGNATURE_RSA_PSS_PSS, + .libcrypto_nid = NID_rsassaPss, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ + .minimum_protocol_version = S2N_TLS13, +}; + +const struct s2n_signature_scheme s2n_rsa_pss_pss_sha384 = { + .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA384, + .hash_alg = S2N_HASH_SHA384, + .sig_alg = S2N_SIGNATURE_RSA_PSS_PSS, + .libcrypto_nid = NID_rsassaPss, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ + .minimum_protocol_version = S2N_TLS13, +}; + +const struct s2n_signature_scheme s2n_rsa_pss_pss_sha512 = { + .iana_value = TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA512, + .hash_alg = S2N_HASH_SHA512, + .sig_alg = S2N_SIGNATURE_RSA_PSS_PSS, + .libcrypto_nid = NID_rsassaPss, + .signature_curve = NULL, /* Elliptic Curve not needed for RSA */ + .minimum_protocol_version = S2N_TLS13, +}; + +/* All Supported SignatureSchemes. */ +/* No MD5 to avoid SLOTH Vulnerability */ +const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20140601[] = { + /* RSA PKCS1 */ + &s2n_rsa_pkcs1_sha256, + &s2n_rsa_pkcs1_sha384, + &s2n_rsa_pkcs1_sha512, + &s2n_rsa_pkcs1_sha224, + + /* ECDSA - TLS 1.2 */ + &s2n_ecdsa_sha256, /* same iana value as TLS 1.3 s2n_ecdsa_secp256r1_sha256 */ + &s2n_ecdsa_secp256r1_sha256, + &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */ + &s2n_ecdsa_secp384r1_sha384, + &s2n_ecdsa_sha512, + &s2n_ecdsa_sha224, + + /* SHA-1 Legacy */ + &s2n_rsa_pkcs1_sha1, + &s2n_ecdsa_sha1, +}; + +/* The original preference list, but with rsa_pss supported. */ +const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20200207[] = { + /* RSA PSS */ + &s2n_rsa_pss_pss_sha256, + &s2n_rsa_pss_pss_sha384, + &s2n_rsa_pss_pss_sha512, + &s2n_rsa_pss_rsae_sha256, + &s2n_rsa_pss_rsae_sha384, + &s2n_rsa_pss_rsae_sha512, + + /* RSA PKCS1 */ + &s2n_rsa_pkcs1_sha256, + &s2n_rsa_pkcs1_sha384, + &s2n_rsa_pkcs1_sha512, + &s2n_rsa_pkcs1_sha224, + + /* ECDSA - TLS 1.2 */ + &s2n_ecdsa_sha256, /* same iana value as TLS 1.3 s2n_ecdsa_secp256r1_sha256 */ + &s2n_ecdsa_secp256r1_sha256, + &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */ + &s2n_ecdsa_secp384r1_sha384, + &s2n_ecdsa_sha512, + &s2n_ecdsa_sha224, + + /* SHA-1 Legacy */ + &s2n_rsa_pkcs1_sha1, + &s2n_ecdsa_sha1, +}; + +/* Add s2n_ecdsa_secp521r1_sha512 */ +const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20201021[] = { + /* RSA PSS */ + &s2n_rsa_pss_pss_sha256, + &s2n_rsa_pss_pss_sha384, + &s2n_rsa_pss_pss_sha512, + &s2n_rsa_pss_rsae_sha256, + &s2n_rsa_pss_rsae_sha384, + &s2n_rsa_pss_rsae_sha512, + + /* RSA PKCS1 */ + &s2n_rsa_pkcs1_sha256, + &s2n_rsa_pkcs1_sha384, + &s2n_rsa_pkcs1_sha512, + &s2n_rsa_pkcs1_sha224, + + /* ECDSA - TLS 1.2 */ + &s2n_ecdsa_sha256, /* same iana value as TLS 1.3 s2n_ecdsa_secp256r1_sha256 */ + &s2n_ecdsa_secp256r1_sha256, + &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */ + &s2n_ecdsa_secp384r1_sha384, + &s2n_ecdsa_sha512, /* same iana value as TLS 1.3 s2n_ecdsa_secp521r1_sha512 */ + &s2n_ecdsa_secp521r1_sha512, + &s2n_ecdsa_sha224, + + /* SHA-1 Legacy */ + &s2n_rsa_pkcs1_sha1, + &s2n_ecdsa_sha1, +}; + +const struct s2n_signature_preferences s2n_signature_preferences_20140601 = { + .count = s2n_array_len(s2n_sig_scheme_pref_list_20140601), + .signature_schemes = s2n_sig_scheme_pref_list_20140601, +}; + +const struct s2n_signature_preferences s2n_signature_preferences_20200207 = { + .count = s2n_array_len(s2n_sig_scheme_pref_list_20200207), + .signature_schemes = s2n_sig_scheme_pref_list_20200207, +}; + +const struct s2n_signature_preferences s2n_signature_preferences_20201021 = { + .count = s2n_array_len(s2n_sig_scheme_pref_list_20201021), + .signature_schemes = s2n_sig_scheme_pref_list_20201021, +}; + +const struct s2n_signature_preferences s2n_signature_preferences_null = { + .count = 0, + .signature_schemes = NULL, +}; + +/* TLS1.3 supported signature schemes, without SHA-1 legacy algorithms */ +const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20201110[] = { + /* RSA PSS */ + &s2n_rsa_pss_pss_sha256, + &s2n_rsa_pss_pss_sha384, + &s2n_rsa_pss_pss_sha512, + &s2n_rsa_pss_rsae_sha256, + &s2n_rsa_pss_rsae_sha384, + &s2n_rsa_pss_rsae_sha512, + + /* RSA PKCS1 */ + &s2n_rsa_pkcs1_sha256, + &s2n_rsa_pkcs1_sha384, + &s2n_rsa_pkcs1_sha512, + &s2n_rsa_pkcs1_sha224, + + /* ECDSA - TLS 1.2 */ + &s2n_ecdsa_sha256, /* same iana value as TLS 1.3 s2n_ecdsa_secp256r1_sha256 */ + &s2n_ecdsa_secp256r1_sha256, + &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */ + &s2n_ecdsa_secp384r1_sha384, + &s2n_ecdsa_sha512, + &s2n_ecdsa_sha224, +}; + +const struct s2n_signature_preferences s2n_certificate_signature_preferences_20201110 = { + .count = s2n_array_len(s2n_sig_scheme_pref_list_20201110), + .signature_schemes = s2n_sig_scheme_pref_list_20201110, +}; diff --git a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h index 1f16a61276..416f936a6d 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h +++ b/contrib/restricted/aws/s2n/tls/s2n_signature_scheme.h @@ -1,81 +1,81 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -#pragma once - -#include <s2n.h> -#include <strings.h> - -#include "crypto/s2n_hash.h" -#include "crypto/s2n_signature.h" -#include "crypto/s2n_ecc_evp.h" - -struct s2n_signature_scheme { - uint16_t iana_value; - s2n_hash_algorithm hash_alg; - s2n_signature_algorithm sig_alg; - uint8_t minimum_protocol_version; - uint8_t maximum_protocol_version; - uint16_t libcrypto_nid; - - /* Curve is only specified for ECDSA Signatures */ - struct s2n_ecc_named_curve const *signature_curve; -}; - -struct s2n_signature_preferences{ - uint8_t count; - const struct s2n_signature_scheme *const *signature_schemes; -}; - -/* RSA PKCS1 */ -/* s2n_rsa_pkcs1_md5_sha1 is not in any preference list, but it is needed since it's the default for TLS 1.0 and 1.1 if - * no SignatureScheme is sent. */ -extern const struct s2n_signature_scheme s2n_rsa_pkcs1_md5_sha1; -extern const struct s2n_signature_scheme s2n_rsa_pkcs1_sha1; -extern const struct s2n_signature_scheme s2n_rsa_pkcs1_sha224; -extern const struct s2n_signature_scheme s2n_rsa_pkcs1_sha256; -extern const struct s2n_signature_scheme s2n_rsa_pkcs1_sha384; -extern const struct s2n_signature_scheme s2n_rsa_pkcs1_sha512; - -/* TLS 1.2 Compatible ECDSA Schemes */ -extern const struct s2n_signature_scheme s2n_ecdsa_sha1; -extern const struct s2n_signature_scheme s2n_ecdsa_sha224; -extern const struct s2n_signature_scheme s2n_ecdsa_sha256; -extern const struct s2n_signature_scheme s2n_ecdsa_sha384; -extern const struct s2n_signature_scheme s2n_ecdsa_sha512; - -/* TLS 1.3 Compatible ECDSA Schemes */ -extern const struct s2n_signature_scheme s2n_ecdsa_secp256r1_sha256; -extern const struct s2n_signature_scheme s2n_ecdsa_secp384r1_sha384; -extern const struct s2n_signature_scheme s2n_ecdsa_secp521r1_sha512; - -/* RSA PSS */ -/* - * Use RSA-PSS-RSAE instead of RSA-PSS-PSS in order to work with older certificates. - * For more info see: https://crypto.stackexchange.com/a/58708 - */ -extern const struct s2n_signature_scheme s2n_rsa_pss_pss_sha256; -extern const struct s2n_signature_scheme s2n_rsa_pss_pss_sha384; -extern const struct s2n_signature_scheme s2n_rsa_pss_pss_sha512; -extern const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha256; -extern const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha384; -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_null; - -extern const struct s2n_signature_preferences s2n_certificate_signature_preferences_20201110; +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#pragma once + +#include <s2n.h> +#include <strings.h> + +#include "crypto/s2n_hash.h" +#include "crypto/s2n_signature.h" +#include "crypto/s2n_ecc_evp.h" + +struct s2n_signature_scheme { + uint16_t iana_value; + s2n_hash_algorithm hash_alg; + s2n_signature_algorithm sig_alg; + uint8_t minimum_protocol_version; + uint8_t maximum_protocol_version; + uint16_t libcrypto_nid; + + /* Curve is only specified for ECDSA Signatures */ + struct s2n_ecc_named_curve const *signature_curve; +}; + +struct s2n_signature_preferences{ + uint8_t count; + const struct s2n_signature_scheme *const *signature_schemes; +}; + +/* RSA PKCS1 */ +/* s2n_rsa_pkcs1_md5_sha1 is not in any preference list, but it is needed since it's the default for TLS 1.0 and 1.1 if + * no SignatureScheme is sent. */ +extern const struct s2n_signature_scheme s2n_rsa_pkcs1_md5_sha1; +extern const struct s2n_signature_scheme s2n_rsa_pkcs1_sha1; +extern const struct s2n_signature_scheme s2n_rsa_pkcs1_sha224; +extern const struct s2n_signature_scheme s2n_rsa_pkcs1_sha256; +extern const struct s2n_signature_scheme s2n_rsa_pkcs1_sha384; +extern const struct s2n_signature_scheme s2n_rsa_pkcs1_sha512; + +/* TLS 1.2 Compatible ECDSA Schemes */ +extern const struct s2n_signature_scheme s2n_ecdsa_sha1; +extern const struct s2n_signature_scheme s2n_ecdsa_sha224; +extern const struct s2n_signature_scheme s2n_ecdsa_sha256; +extern const struct s2n_signature_scheme s2n_ecdsa_sha384; +extern const struct s2n_signature_scheme s2n_ecdsa_sha512; + +/* TLS 1.3 Compatible ECDSA Schemes */ +extern const struct s2n_signature_scheme s2n_ecdsa_secp256r1_sha256; +extern const struct s2n_signature_scheme s2n_ecdsa_secp384r1_sha384; +extern const struct s2n_signature_scheme s2n_ecdsa_secp521r1_sha512; + +/* RSA PSS */ +/* + * Use RSA-PSS-RSAE instead of RSA-PSS-PSS in order to work with older certificates. + * For more info see: https://crypto.stackexchange.com/a/58708 + */ +extern const struct s2n_signature_scheme s2n_rsa_pss_pss_sha256; +extern const struct s2n_signature_scheme s2n_rsa_pss_pss_sha384; +extern const struct s2n_signature_scheme s2n_rsa_pss_pss_sha512; +extern const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha256; +extern const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha384; +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_null; + +extern const struct s2n_signature_preferences s2n_certificate_signature_preferences_20201110; diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls.c b/contrib/restricted/aws/s2n/tls/s2n_tls.c index b8507d1124..07ef4ff382 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls.c +++ b/contrib/restricted/aws/s2n/tls/s2n_tls.c @@ -1,39 +1,39 @@ -/* - * 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 <stdint.h> - -#include "tls/s2n_tls.h" -#include "tls/s2n_tls_parameters.h" - -uint8_t s2n_highest_protocol_version = S2N_TLS13; -uint8_t s2n_unknown_protocol_version = S2N_UNKNOWN_PROTOCOL_VERSION; - -/* - * Convert max_fragment_length codes to length. - * RFC 6066 says: - * enum{ - * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) - * } MaxFragmentLength; - * and we add 0 -> extension unused - */ -uint16_t mfl_code_to_length[5] = -{ - S2N_DEFAULT_FRAGMENT_LENGTH, /* S2N_TLS_MAX_FRAG_LEN_EXT_NONE */ - 512, /* S2N_TLS_MAX_FRAG_LEN_512 */ - 1024, /* S2N_TLS_MAX_FRAG_LEN_1024 */ - 2048, /* S2N_TLS_MAX_FRAG_LEN_2048 */ - 4096, /* S2N_TLS_MAX_FRAG_LEN_4096 */ -}; +/* + * 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 <stdint.h> + +#include "tls/s2n_tls.h" +#include "tls/s2n_tls_parameters.h" + +uint8_t s2n_highest_protocol_version = S2N_TLS13; +uint8_t s2n_unknown_protocol_version = S2N_UNKNOWN_PROTOCOL_VERSION; + +/* + * Convert max_fragment_length codes to length. + * RFC 6066 says: + * enum{ + * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) + * } MaxFragmentLength; + * and we add 0 -> extension unused + */ +uint16_t mfl_code_to_length[5] = +{ + S2N_DEFAULT_FRAGMENT_LENGTH, /* S2N_TLS_MAX_FRAG_LEN_EXT_NONE */ + 512, /* S2N_TLS_MAX_FRAG_LEN_512 */ + 1024, /* S2N_TLS_MAX_FRAG_LEN_1024 */ + 2048, /* S2N_TLS_MAX_FRAG_LEN_2048 */ + 4096, /* S2N_TLS_MAX_FRAG_LEN_4096 */ +}; diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls.h b/contrib/restricted/aws/s2n/tls/s2n_tls.h index 3ab543942a..d74822a236 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls.h +++ b/contrib/restricted/aws/s2n/tls/s2n_tls.h @@ -1,100 +1,100 @@ -/* - * 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 <stdint.h> -#include <stdbool.h> - -#include "tls/s2n_connection.h" - -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); -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); -extern int s2n_sslv2_client_hello_recv(struct s2n_connection *conn); -extern int s2n_server_hello_retry_send(struct s2n_connection *conn); -extern int s2n_server_hello_retry_recv(struct s2n_connection *conn); -extern int s2n_server_hello_write_message(struct s2n_connection *conn); -extern int s2n_server_hello_send(struct s2n_connection *conn); -extern int s2n_server_hello_recv(struct s2n_connection *conn); -extern int s2n_encrypted_extensions_send(struct s2n_connection *conn); -extern int s2n_encrypted_extensions_recv(struct s2n_connection *conn); -extern int s2n_server_cert_send(struct s2n_connection *conn); -extern int s2n_server_cert_recv(struct s2n_connection *conn); -extern int s2n_server_status_send(struct s2n_connection *conn); -extern int s2n_server_status_recv(struct s2n_connection *conn); -extern int s2n_server_key_send(struct s2n_connection *conn); -extern int s2n_server_key_recv(struct s2n_connection *conn); -extern int s2n_cert_req_recv(struct s2n_connection *conn); -extern int s2n_cert_req_send(struct s2n_connection *conn); -extern int s2n_tls13_cert_req_send(struct s2n_connection *conn); -extern int s2n_tls13_cert_req_recv(struct s2n_connection *conn); -extern int s2n_server_done_send(struct s2n_connection *conn); -extern int s2n_server_done_recv(struct s2n_connection *conn); -extern int s2n_client_cert_recv(struct s2n_connection *conn); -extern int s2n_client_cert_send(struct s2n_connection *conn); -extern int s2n_client_key_send(struct s2n_connection *conn); -extern int s2n_client_key_recv(struct s2n_connection *conn); -extern int s2n_client_cert_verify_recv(struct s2n_connection *conn); -extern int s2n_client_cert_verify_send(struct s2n_connection *conn); -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); -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); -extern int s2n_client_ccs_recv(struct s2n_connection *conn); -extern int s2n_client_finished_send(struct s2n_connection *conn); -extern int s2n_client_finished_recv(struct s2n_connection *conn); -extern int s2n_server_finished_send(struct s2n_connection *conn); -extern int s2n_server_finished_recv(struct s2n_connection *conn); -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_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); -extern int s2n_handshake_parse_header(struct s2n_connection *conn, uint8_t * message_type, uint32_t * length); -extern int s2n_read_full_record(struct s2n_connection *conn, uint8_t * record_type, int *isSSLv2); -extern int s2n_recv_close_notify(struct s2n_connection *conn, s2n_blocked_status * blocked); - -extern uint16_t mfl_code_to_length[5]; - -#define s2n_server_received_server_name(conn) ((conn)->server_name[0] != 0) - -#define s2n_server_can_send_ec_point_formats(conn) \ - ((conn)->ec_point_formats) - -#define s2n_server_can_send_ocsp(conn) ((conn)->mode == S2N_SERVER && \ - (conn)->status_type == S2N_STATUS_REQUEST_OCSP && \ - (conn)->handshake_params.our_chain_and_key && \ - (conn)->handshake_params.our_chain_and_key->ocsp_status.size > 0) - -#define s2n_server_sent_ocsp(conn) ((conn)->mode == S2N_CLIENT && \ - (conn)->status_type == S2N_STATUS_REQUEST_OCSP) - -#define s2n_server_can_send_sct_list(conn) ((conn)->mode == S2N_SERVER && \ - (conn)->ct_level_requested == S2N_CT_SUPPORT_REQUEST && \ - (conn)->handshake_params.our_chain_and_key && \ - (conn)->handshake_params.our_chain_and_key->sct_list.size > 0) - -#define s2n_server_sending_nst(conn) ((conn)->config->use_tickets && \ - (conn)->session_ticket_status == S2N_NEW_TICKET) +/* + * 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 <stdint.h> +#include <stdbool.h> + +#include "tls/s2n_connection.h" + +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); +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); +extern int s2n_sslv2_client_hello_recv(struct s2n_connection *conn); +extern int s2n_server_hello_retry_send(struct s2n_connection *conn); +extern int s2n_server_hello_retry_recv(struct s2n_connection *conn); +extern int s2n_server_hello_write_message(struct s2n_connection *conn); +extern int s2n_server_hello_send(struct s2n_connection *conn); +extern int s2n_server_hello_recv(struct s2n_connection *conn); +extern int s2n_encrypted_extensions_send(struct s2n_connection *conn); +extern int s2n_encrypted_extensions_recv(struct s2n_connection *conn); +extern int s2n_server_cert_send(struct s2n_connection *conn); +extern int s2n_server_cert_recv(struct s2n_connection *conn); +extern int s2n_server_status_send(struct s2n_connection *conn); +extern int s2n_server_status_recv(struct s2n_connection *conn); +extern int s2n_server_key_send(struct s2n_connection *conn); +extern int s2n_server_key_recv(struct s2n_connection *conn); +extern int s2n_cert_req_recv(struct s2n_connection *conn); +extern int s2n_cert_req_send(struct s2n_connection *conn); +extern int s2n_tls13_cert_req_send(struct s2n_connection *conn); +extern int s2n_tls13_cert_req_recv(struct s2n_connection *conn); +extern int s2n_server_done_send(struct s2n_connection *conn); +extern int s2n_server_done_recv(struct s2n_connection *conn); +extern int s2n_client_cert_recv(struct s2n_connection *conn); +extern int s2n_client_cert_send(struct s2n_connection *conn); +extern int s2n_client_key_send(struct s2n_connection *conn); +extern int s2n_client_key_recv(struct s2n_connection *conn); +extern int s2n_client_cert_verify_recv(struct s2n_connection *conn); +extern int s2n_client_cert_verify_send(struct s2n_connection *conn); +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); +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); +extern int s2n_client_ccs_recv(struct s2n_connection *conn); +extern int s2n_client_finished_send(struct s2n_connection *conn); +extern int s2n_client_finished_recv(struct s2n_connection *conn); +extern int s2n_server_finished_send(struct s2n_connection *conn); +extern int s2n_server_finished_recv(struct s2n_connection *conn); +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_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); +extern int s2n_handshake_parse_header(struct s2n_connection *conn, uint8_t * message_type, uint32_t * length); +extern int s2n_read_full_record(struct s2n_connection *conn, uint8_t * record_type, int *isSSLv2); +extern int s2n_recv_close_notify(struct s2n_connection *conn, s2n_blocked_status * blocked); + +extern uint16_t mfl_code_to_length[5]; + +#define s2n_server_received_server_name(conn) ((conn)->server_name[0] != 0) + +#define s2n_server_can_send_ec_point_formats(conn) \ + ((conn)->ec_point_formats) + +#define s2n_server_can_send_ocsp(conn) ((conn)->mode == S2N_SERVER && \ + (conn)->status_type == S2N_STATUS_REQUEST_OCSP && \ + (conn)->handshake_params.our_chain_and_key && \ + (conn)->handshake_params.our_chain_and_key->ocsp_status.size > 0) + +#define s2n_server_sent_ocsp(conn) ((conn)->mode == S2N_CLIENT && \ + (conn)->status_type == S2N_STATUS_REQUEST_OCSP) + +#define s2n_server_can_send_sct_list(conn) ((conn)->mode == S2N_SERVER && \ + (conn)->ct_level_requested == S2N_CT_SUPPORT_REQUEST && \ + (conn)->handshake_params.our_chain_and_key && \ + (conn)->handshake_params.our_chain_and_key->sct_list.size > 0) + +#define s2n_server_sending_nst(conn) ((conn)->config->use_tickets && \ + (conn)->session_ticket_status == S2N_NEW_TICKET) diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13.c b/contrib/restricted/aws/s2n/tls/s2n_tls13.c index 038ca9db3f..52dd99a86a 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls13.c +++ b/contrib/restricted/aws/s2n/tls/s2n_tls13.c @@ -1,75 +1,75 @@ -/* - * 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_tls.h" -#include "tls/s2n_tls13.h" -#include "crypto/s2n_rsa_signing.h" - -bool s2n_use_default_tls13_config_flag = false; - -bool s2n_use_default_tls13_config() -{ - return s2n_use_default_tls13_config_flag; -} - -/* 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() -{ - s2n_highest_protocol_version = S2N_TLS13; - s2n_use_default_tls13_config_flag = true; - return S2N_SUCCESS; -} - -/* Do NOT allow TLS1.3 to be negotiated, regardless of 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_disable_tls13() -{ - ENSURE_POSIX(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; -} - -/* Reset S2N to the default protocol version behavior. - * - * 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() -{ - ENSURE_POSIX(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; -} - -/* Returns whether a uint16 iana value is a valid TLS 1.3 cipher suite */ -bool s2n_is_valid_tls13_cipher(const uint8_t version[2]) { - /* Valid TLS 1.3 Ciphers are - * 0x1301, 0x1302, 0x1303, 0x1304, 0x1305. - * (https://tools.ietf.org/html/rfc8446#appendix-B.4) - */ - return version[0] == 0x13 && version[1] >= 0x01 && version[1] <= 0x05; -} +/* + * 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_tls.h" +#include "tls/s2n_tls13.h" +#include "crypto/s2n_rsa_signing.h" + +bool s2n_use_default_tls13_config_flag = false; + +bool s2n_use_default_tls13_config() +{ + return s2n_use_default_tls13_config_flag; +} + +/* 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() +{ + s2n_highest_protocol_version = S2N_TLS13; + s2n_use_default_tls13_config_flag = true; + return S2N_SUCCESS; +} + +/* Do NOT allow TLS1.3 to be negotiated, regardless of 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_disable_tls13() +{ + ENSURE_POSIX(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; +} + +/* Reset S2N to the default protocol version behavior. + * + * 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() +{ + ENSURE_POSIX(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; +} + +/* Returns whether a uint16 iana value is a valid TLS 1.3 cipher suite */ +bool s2n_is_valid_tls13_cipher(const uint8_t version[2]) { + /* Valid TLS 1.3 Ciphers are + * 0x1301, 0x1302, 0x1303, 0x1304, 0x1305. + * (https://tools.ietf.org/html/rfc8446#appendix-B.4) + */ + return version[0] == 0x13 && version[1] >= 0x01 && version[1] <= 0x05; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13.h b/contrib/restricted/aws/s2n/tls/s2n_tls13.h index 1a48bd5ecd..53dedaf02e 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls13.h +++ b/contrib/restricted/aws/s2n/tls/s2n_tls13.h @@ -1,51 +1,51 @@ -/* - * 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.h" -#include "utils/s2n_compiler.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if S2N_GCC_VERSION_AT_LEAST(4, 5, 0) - S2N_API - __attribute__((deprecated("The use of TLS1.3 is configured through security policies"))) - extern int s2n_enable_tls13(); -#else - S2N_API - __attribute__((deprecated)) - extern int s2n_enable_tls13(); -#endif - -#ifdef __cplusplus -} -#endif - - -/* from RFC: https://tools.ietf.org/html/rfc8446#section-4.1.3*/ -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_valid_tls13_cipher(const uint8_t version[2]); - -bool s2n_is_hello_retry_handshake(struct s2n_connection *conn); -bool s2n_is_hello_retry_message(struct s2n_connection *conn); -int s2n_set_hello_retry_required(struct s2n_connection *conn); +/* + * 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.h" +#include "utils/s2n_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if S2N_GCC_VERSION_AT_LEAST(4, 5, 0) + S2N_API + __attribute__((deprecated("The use of TLS1.3 is configured through security policies"))) + extern int s2n_enable_tls13(); +#else + S2N_API + __attribute__((deprecated)) + extern int s2n_enable_tls13(); +#endif + +#ifdef __cplusplus +} +#endif + + +/* from RFC: https://tools.ietf.org/html/rfc8446#section-4.1.3*/ +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_valid_tls13_cipher(const uint8_t version[2]); + +bool s2n_is_hello_retry_handshake(struct s2n_connection *conn); +bool s2n_is_hello_retry_message(struct s2n_connection *conn); +int s2n_set_hello_retry_required(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 fbaf926a4b..74654f33cf 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.c +++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.c @@ -1,197 +1,197 @@ -/* - * 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 "crypto/s2n_hash.h" -#include "error/s2n_errno.h" -#include "stuffer/s2n_stuffer.h" -#include "tls/s2n_async_pkey.h" -#include "tls/s2n_tls13_handshake.h" -#include "tls/s2n_tls13_certificate_verify.h" -#include "tls/s2n_connection.h" -#include "utils/s2n_safety.h" - -#include <stdint.h> - -/** - * Specified in https://tools.ietf.org/html/rfc8446#section-4.4.3 - * - * Servers MUST send this message when authenticating via a certificate. - * Clients MUST send this message whenever authenticating via a certificate. - * When sent, this message MUST appear immediately after the Certificate - * message and immediately prior to the Finished message. - **/ - -/* 64 'space' characters (0x20) */ -const uint8_t S2N_CERT_VERIFY_PREFIX[] = {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; -/* 'TLS 1.3, server CertificateVerify' with 0x00 separator */ -const uint8_t S2N_SERVER_CERT_VERIFY_CONTEXT[] = {0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e, 0x33, - 0x2c, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x00}; -/* 'TLS 1.3, client CertificateVerify' with 0x00 separator */ -const uint8_t S2N_CLIENT_CERT_VERIFY_CONTEXT[] = {0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e, 0x33, - 0x2c, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x00}; - - -static int s2n_tls13_write_cert_verify_signature(struct s2n_connection *conn, struct s2n_signature_scheme *chosen_sig_scheme); -static int s2n_tls13_write_signature(struct s2n_connection *conn, struct s2n_blob *signature); -static int s2n_tls13_generate_unsigned_cert_verify_content(struct s2n_connection *conn, struct s2n_stuffer *unsigned_content, s2n_mode mode); -static int s2n_tls13_cert_read_and_verify_signature(struct s2n_connection *conn, struct s2n_signature_scheme *chosen_sig_scheme); -static uint8_t s2n_tls13_cert_verify_header_length(s2n_mode mode); - -int s2n_tls13_cert_verify_send(struct s2n_connection *conn) -{ - S2N_ASYNC_PKEY_GUARD(conn); - - if (conn->mode == S2N_SERVER) { - /* Write digital signature */ - GUARD(s2n_tls13_write_cert_verify_signature(conn, &conn->secure.conn_sig_scheme)); - } else { - /* Write digital signature */ - GUARD(s2n_tls13_write_cert_verify_signature(conn, &conn->secure.client_cert_sig_scheme)); - } - - - return 0; -} - -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); - - /* Write the SignatureScheme out */ - struct s2n_stuffer *out = &conn->handshake.io; - 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)); - - DEFER_CLEANUP(struct s2n_stuffer unsigned_content = {0}, s2n_stuffer_free); - 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))); - - S2N_ASYNC_PKEY_SIGN(conn, chosen_sig_scheme->sig_alg, &message_hash, s2n_tls13_write_signature); -} - -int s2n_tls13_write_signature(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_bytes(out, signature->data, signature->size)); - - return 0; -} - -int s2n_tls13_generate_unsigned_cert_verify_content(struct s2n_connection *conn, struct s2n_stuffer *unsigned_content, s2n_mode mode) -{ - 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)); - - /* 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))); - - if (mode == S2N_CLIENT) { - 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))); - } - - GUARD(s2n_stuffer_write_bytes(unsigned_content, digest_out, hash_digest_length)); - - return 0; -} - -uint8_t s2n_tls13_cert_verify_header_length(s2n_mode mode) -{ - if (mode == S2N_CLIENT) { - return sizeof(S2N_CERT_VERIFY_PREFIX) + sizeof(S2N_CLIENT_CERT_VERIFY_CONTEXT); - } - return sizeof(S2N_CERT_VERIFY_PREFIX) + sizeof(S2N_SERVER_CERT_VERIFY_CONTEXT); -} - -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)); - - /* Read the rest of the signature and verify */ - GUARD(s2n_tls13_cert_read_and_verify_signature(conn, &conn->secure.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)); - - /* Read the rest of the signature and verify */ - GUARD(s2n_tls13_cert_read_and_verify_signature(conn, &conn->secure.conn_sig_scheme)); - } - - return 0; -} - -int s2n_tls13_cert_read_and_verify_signature(struct s2n_connection *conn, struct s2n_signature_scheme *chosen_sig_scheme) -{ - struct s2n_stuffer *in = &conn->handshake.io; - 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)); - - /* Get signature size */ - uint16_t signature_size; - 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)); - signed_content.size = signature_size; - 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)); - } else { - 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))); - - if (conn->mode == S2N_CLIENT) { - GUARD(s2n_pkey_verify(&conn->secure.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)); - } - - return 0; -} +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +#include "crypto/s2n_hash.h" +#include "error/s2n_errno.h" +#include "stuffer/s2n_stuffer.h" +#include "tls/s2n_async_pkey.h" +#include "tls/s2n_tls13_handshake.h" +#include "tls/s2n_tls13_certificate_verify.h" +#include "tls/s2n_connection.h" +#include "utils/s2n_safety.h" + +#include <stdint.h> + +/** + * Specified in https://tools.ietf.org/html/rfc8446#section-4.4.3 + * + * Servers MUST send this message when authenticating via a certificate. + * Clients MUST send this message whenever authenticating via a certificate. + * When sent, this message MUST appear immediately after the Certificate + * message and immediately prior to the Finished message. + **/ + +/* 64 'space' characters (0x20) */ +const uint8_t S2N_CERT_VERIFY_PREFIX[] = {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; +/* 'TLS 1.3, server CertificateVerify' with 0x00 separator */ +const uint8_t S2N_SERVER_CERT_VERIFY_CONTEXT[] = {0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e, 0x33, + 0x2c, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x00}; +/* 'TLS 1.3, client CertificateVerify' with 0x00 separator */ +const uint8_t S2N_CLIENT_CERT_VERIFY_CONTEXT[] = {0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e, 0x33, + 0x2c, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x00}; + + +static int s2n_tls13_write_cert_verify_signature(struct s2n_connection *conn, struct s2n_signature_scheme *chosen_sig_scheme); +static int s2n_tls13_write_signature(struct s2n_connection *conn, struct s2n_blob *signature); +static int s2n_tls13_generate_unsigned_cert_verify_content(struct s2n_connection *conn, struct s2n_stuffer *unsigned_content, s2n_mode mode); +static int s2n_tls13_cert_read_and_verify_signature(struct s2n_connection *conn, struct s2n_signature_scheme *chosen_sig_scheme); +static uint8_t s2n_tls13_cert_verify_header_length(s2n_mode mode); + +int s2n_tls13_cert_verify_send(struct s2n_connection *conn) +{ + S2N_ASYNC_PKEY_GUARD(conn); + + if (conn->mode == S2N_SERVER) { + /* Write digital signature */ + GUARD(s2n_tls13_write_cert_verify_signature(conn, &conn->secure.conn_sig_scheme)); + } else { + /* Write digital signature */ + GUARD(s2n_tls13_write_cert_verify_signature(conn, &conn->secure.client_cert_sig_scheme)); + } + + + return 0; +} + +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); + + /* Write the SignatureScheme out */ + struct s2n_stuffer *out = &conn->handshake.io; + 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)); + + DEFER_CLEANUP(struct s2n_stuffer unsigned_content = {0}, s2n_stuffer_free); + 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))); + + S2N_ASYNC_PKEY_SIGN(conn, chosen_sig_scheme->sig_alg, &message_hash, s2n_tls13_write_signature); +} + +int s2n_tls13_write_signature(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_bytes(out, signature->data, signature->size)); + + return 0; +} + +int s2n_tls13_generate_unsigned_cert_verify_content(struct s2n_connection *conn, struct s2n_stuffer *unsigned_content, s2n_mode mode) +{ + 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)); + + /* 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))); + + if (mode == S2N_CLIENT) { + 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))); + } + + GUARD(s2n_stuffer_write_bytes(unsigned_content, digest_out, hash_digest_length)); + + return 0; +} + +uint8_t s2n_tls13_cert_verify_header_length(s2n_mode mode) +{ + if (mode == S2N_CLIENT) { + return sizeof(S2N_CERT_VERIFY_PREFIX) + sizeof(S2N_CLIENT_CERT_VERIFY_CONTEXT); + } + return sizeof(S2N_CERT_VERIFY_PREFIX) + sizeof(S2N_SERVER_CERT_VERIFY_CONTEXT); +} + +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)); + + /* Read the rest of the signature and verify */ + GUARD(s2n_tls13_cert_read_and_verify_signature(conn, &conn->secure.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)); + + /* Read the rest of the signature and verify */ + GUARD(s2n_tls13_cert_read_and_verify_signature(conn, &conn->secure.conn_sig_scheme)); + } + + return 0; +} + +int s2n_tls13_cert_read_and_verify_signature(struct s2n_connection *conn, struct s2n_signature_scheme *chosen_sig_scheme) +{ + struct s2n_stuffer *in = &conn->handshake.io; + 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)); + + /* Get signature size */ + uint16_t signature_size; + 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)); + signed_content.size = signature_size; + 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)); + } else { + 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))); + + if (conn->mode == S2N_CLIENT) { + GUARD(s2n_pkey_verify(&conn->secure.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)); + } + + return 0; +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.h b/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.h index a64204a18a..e70bb46298 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.h +++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_certificate_verify.h @@ -1,21 +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/s2n_connection.h" - -int s2n_tls13_cert_verify_recv(struct s2n_connection *conn); -int s2n_tls13_cert_verify_send(struct s2n_connection *conn); +/* + * 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_connection.h" + +int s2n_tls13_cert_verify_recv(struct s2n_connection *conn); +int s2n_tls13_cert_verify_send(struct s2n_connection *conn); diff --git a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c index b89c6f04fb..fe000814e7 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c +++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.c @@ -1,401 +1,401 @@ -/* - * 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 "tls/s2n_cipher_suites.h" -#include "tls/s2n_security_policies.h" - -static int s2n_zero_sequence_number(struct s2n_connection *conn, s2n_mode mode) -{ - notnull_check(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))); - } else { - GUARD(s2n_blob_init(&sequence_number, conn->secure.server_sequence_number, sizeof(conn->secure.server_sequence_number))); - } - 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); - - 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; -} - -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; -} - -int s2n_tls13_compute_ecc_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret) { - notnull_check(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; - } - } - - 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); - - if (conn->mode == S2N_CLIENT) { - 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)); - } - - return 0; -} - -/* 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); - - /* 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); - - struct s2n_kem_group_params *server_kem_group_params = &conn->secure.server_kem_group_params; - notnull_check(server_kem_group_params); - struct s2n_ecc_evp_params *server_ecc_params = &server_kem_group_params->ecc_params; - notnull_check(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_ecc_evp_params *client_ecc_params = &client_kem_group_params->ecc_params; - notnull_check(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)); - } else { - 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); - - 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); - - eq_check(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)); - 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)); - - return S2N_SUCCESS; -} - -static int s2n_tls13_pq_hybrid_supported(struct s2n_connection *conn) { - return conn->secure.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); - - if (s2n_tls13_pq_hybrid_supported(conn)) { - GUARD(s2n_tls13_compute_pq_hybrid_shared_secret(conn, shared_secret)); - } else { - GUARD(s2n_tls13_compute_ecc_shared_secret(conn, shared_secret)); - } - - return S2N_SUCCESS; -} - -/* - * 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)); - - /* 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)); - } - - /* 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; -} - -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)); - 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); - - /* get tls13 key context */ - s2n_tls13_connection_keys(keys, conn); - - struct s2n_session_key *old_key; - struct s2n_blob old_app_secret; - struct s2n_blob app_iv; - - 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)); - } 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)); - } - - /* 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)); - - 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)); - if (status == RECEIVING) { - 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)); - } - - /* 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; the first record transmitted under a particular traffic key - * MUST use sequence number 0. - */ - 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)); - - return S2N_SUCCESS; -} +/* + * 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 "tls/s2n_cipher_suites.h" +#include "tls/s2n_security_policies.h" + +static int s2n_zero_sequence_number(struct s2n_connection *conn, s2n_mode mode) +{ + notnull_check(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))); + } else { + GUARD(s2n_blob_init(&sequence_number, conn->secure.server_sequence_number, sizeof(conn->secure.server_sequence_number))); + } + 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); + + 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; +} + +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; +} + +int s2n_tls13_compute_ecc_shared_secret(struct s2n_connection *conn, struct s2n_blob *shared_secret) { + notnull_check(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; + } + } + + 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); + + if (conn->mode == S2N_CLIENT) { + 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)); + } + + return 0; +} + +/* 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); + + /* 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); + + struct s2n_kem_group_params *server_kem_group_params = &conn->secure.server_kem_group_params; + notnull_check(server_kem_group_params); + struct s2n_ecc_evp_params *server_ecc_params = &server_kem_group_params->ecc_params; + notnull_check(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_ecc_evp_params *client_ecc_params = &client_kem_group_params->ecc_params; + notnull_check(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)); + } else { + 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); + + 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); + + eq_check(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)); + 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)); + + return S2N_SUCCESS; +} + +static int s2n_tls13_pq_hybrid_supported(struct s2n_connection *conn) { + return conn->secure.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); + + if (s2n_tls13_pq_hybrid_supported(conn)) { + GUARD(s2n_tls13_compute_pq_hybrid_shared_secret(conn, shared_secret)); + } else { + GUARD(s2n_tls13_compute_ecc_shared_secret(conn, shared_secret)); + } + + return S2N_SUCCESS; +} + +/* + * 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)); + + /* 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)); + } + + /* 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; +} + +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)); + 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); + + /* get tls13 key context */ + s2n_tls13_connection_keys(keys, conn); + + struct s2n_session_key *old_key; + struct s2n_blob old_app_secret; + struct s2n_blob app_iv; + + 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)); + } 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)); + } + + /* 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)); + + 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)); + if (status == RECEIVING) { + 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)); + } + + /* 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; the first record transmitted under a particular traffic key + * MUST use sequence number 0. + */ + 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)); + + 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 68253fa3cb..f496677a09 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.h +++ b/contrib/restricted/aws/s2n/tls/s2n_tls13_handshake.h @@ -1,40 +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. - */ - -#pragma once - -#include "crypto/s2n_tls13_keys.h" -#include "utils/s2n_blob.h" -#include "utils/s2n_safety.h" -#include "tls/s2n_connection.h" -#include "tls/s2n_key_update.h" - -int s2n_tls13_mac_verify(struct s2n_tls13_keys *keys, struct s2n_blob *finished_verify, struct s2n_blob *wire_verify); - -#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)); - -/* 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)); - -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_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); +/* + * 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 "crypto/s2n_tls13_keys.h" +#include "utils/s2n_blob.h" +#include "utils/s2n_safety.h" +#include "tls/s2n_connection.h" +#include "tls/s2n_key_update.h" + +int s2n_tls13_mac_verify(struct s2n_tls13_keys *keys, struct s2n_blob *finished_verify, struct s2n_blob *wire_verify); + +#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)); + +/* 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)); + +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_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_tls_digest_preferences.h b/contrib/restricted/aws/s2n/tls/s2n_tls_digest_preferences.h index e49258d768..9b856cf481 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls_digest_preferences.h +++ b/contrib/restricted/aws/s2n/tls/s2n_tls_digest_preferences.h @@ -1,38 +1,38 @@ -/* - * 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 }; - +/* + * 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 e42a56ba49..1980a69138 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h +++ b/contrib/restricted/aws/s2n/tls/s2n_tls_parameters.h @@ -1,268 +1,268 @@ -/* - * 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 "crypto/s2n_hash.h" - -/* Codes from http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-5 */ -#define TLS_NULL_WITH_NULL_NULL 0x00, 0x00 -#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x00, 0x3D -#define TLS_RSA_WITH_AES_256_CBC_SHA 0x00, 0x35 -#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x00, 0x3C -#define TLS_RSA_WITH_AES_128_CBC_SHA 0x00, 0x2F -#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x00, 0x0A -#define TLS_RSA_WITH_RC4_128_MD5 0x00, 0x04 -#define TLS_RSA_WITH_RC4_128_SHA 0x00, 0x05 - -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x00, 0x33 -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x00, 0x67 -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x00, 0x39 -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x00, 0x6B -#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x00, 0x16 - -#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC0, 0x09 -#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC0, 0x23 -#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC0, 0x0A -#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC0, 0x24 - -#define TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC0, 0x11 -#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC0, 0x13 -#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC0, 0x27 -#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC0, 0x14 -#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC0, 0x28 -#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC0, 0x12 - -#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x00, 0x9C -#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x00, 0x9D -#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x00, 0x9E -#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x00, 0x9F -#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC0, 0x2B -#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC0, 0x2C -#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC0, 0x2F -#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC0, 0x30 - -#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCC, 0xA8 -#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCC, 0xA9 -#define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCC, 0xAA - -/* TLS 1.2 hybrid post-quantum definitions from https://tools.ietf.org/html/draft-campagna-tls-bike-sike-hybrid */ -#define TLS_ECDHE_BIKE_RSA_WITH_AES_256_GCM_SHA384 0xFF, 0x04 -#define TLS_ECDHE_SIKE_RSA_WITH_AES_256_GCM_SHA384 0xFF, 0x08 -#define TLS_ECDHE_KYBER_RSA_WITH_AES_256_GCM_SHA384 0xFF, 0x0C -#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_SIKE_P503_R1 10 -#define TLS_PQ_KEM_EXTENSION_ID_SIKE_P434_R2 19 -#define TLS_PQ_KEM_EXTENSION_ID_KYBER_512_R2 23 -#define TLS_PQ_KEM_EXTENSION_ID_KYBER_512_90S_R2 24 - -/* 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 - -/* From https://tools.ietf.org/html/rfc7507 */ -#define TLS_FALLBACK_SCSV 0x56, 0x00 -#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00, 0xff - -/* TLS 1.3 cipher suites from https://tools.ietf.org/html/rfc8446#appendix-B.4 */ -#define TLS_AES_128_GCM_SHA256 0x13, 0x01 -#define TLS_AES_256_GCM_SHA384 0x13, 0x02 -#define TLS_CHACHA20_POLY1305_SHA256 0x13, 0x03 -#define TLS_AES_128_CCM_SHA256 0x13, 0x04 -#define TLS_AES_128_CCM_8_SHA256 0x13, 0x05 - -/* TLS extensions from https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml */ -#define TLS_EXTENSION_SERVER_NAME 0 -#define TLS_EXTENSION_MAX_FRAG_LEN 1 -#define TLS_EXTENSION_STATUS_REQUEST 5 -#define TLS_EXTENSION_SUPPORTED_GROUPS 10 -#define TLS_EXTENSION_EC_POINT_FORMATS 11 -#define TLS_EXTENSION_SIGNATURE_ALGORITHMS 13 -#define TLS_EXTENSION_ALPN 16 -#define TLS_EXTENSION_SCT_LIST 18 -#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_SUPPORTED_VERSIONS 43 -#define TLS_EXTENSION_COOKIE 44 -#define TLS_EXTENSION_KEY_SHARE 51 - -/* QUIC-TLS extension from https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-8.2 */ -#define TLS_QUIC_TRANSPORT_PARAMETERS 65535 - -/* 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 - -/* TLS SignatureScheme (Backwards compatible with SigHash and SigAlg values above) */ -/* Defined here: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme */ -#define TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA1 0x0201 -#define TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA224 0x0301 -#define TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA256 0x0401 -#define TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA384 0x0501 -#define TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA512 0x0601 - -/* In TLS 1.0 and 1.1 the hard-coded default scheme was RSA_PKCS1_MD5_SHA1, but there's no IANA defined backwards - * compatible value for that Scheme for TLS 1.2 and 1.3. So we define an internal value in the private range that won't - * match anything in the valid range so that all TLS Versions can use the same SignatureScheme negotiation abstraction - * layer. This scheme isn't in any preference list, so it can't be negotiated even if a client sent it in its pref list. */ -#define TLS_SIGNATURE_SCHEME_PRIVATE_INTERNAL_RSA_PKCS1_MD5_SHA1 0xFFFF - -/* TLS 1.2 Backwards Compatible ECDSA Schemes */ -#define TLS_SIGNATURE_SCHEME_ECDSA_SHA1 0x0203 -#define TLS_SIGNATURE_SCHEME_ECDSA_SHA224 0x0303 -#define TLS_SIGNATURE_SCHEME_ECDSA_SHA256 0x0403 -#define TLS_SIGNATURE_SCHEME_ECDSA_SHA384 0x0503 -#define TLS_SIGNATURE_SCHEME_ECDSA_SHA512 0x0603 - -/* TLS 1.3 ECDSA Signature Schemes */ -#define TLS_SIGNATURE_SCHEME_ECDSA_SECP256R1_SHA256 0x0403 -#define TLS_SIGNATURE_SCHEME_ECDSA_SECP384R1_SHA384 0x0503 -#define TLS_SIGNATURE_SCHEME_ECDSA_SECP521R1_SHA512 0x0603 -#define TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA256 0x0804 -#define TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA384 0x0805 -#define TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA512 0x0806 -#define TLS_SIGNATURE_SCHEME_ED25519 0x0807 -#define TLS_SIGNATURE_SCHEME_ED448 0x0808 -#define TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA256 0x0809 -#define TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA384 0x080A -#define TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA512 0x080B - - -#define TLS_SIGNATURE_SCHEME_LEN 2 -#define TLS_SIGNATURE_SCHEME_LIST_MAX_LEN 64 - -/* The TLS record types we support */ -#define SSLv2_CLIENT_HELLO 1 -#define TLS_CHANGE_CIPHER_SPEC 20 -#define TLS_ALERT 21 -#define TLS_HANDSHAKE 22 -#define TLS_APPLICATION_DATA 23 - -/* Elliptic curve formats from http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-9 - * Only uncompressed is supported. - */ -#define TLS_EC_FORMAT_UNCOMPRESSED 0 -#define TLS_EC_FORMAT_ANSIX962_COMPRESSED_PRIME 1 -#define TLS_EC_FORMAT_ANSIX962_COMPRESSED_CHAR2 2 - -/* Elliptic curves from https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 */ -#define TLS_EC_CURVE_SECP_256_R1 23 -#define TLS_EC_CURVE_SECP_384_R1 24 -#define TLS_EC_CURVE_SECP_521_R1 25 -#define TLS_EC_CURVE_ECDH_X25519 29 - -/* Ethernet maximum transmission unit (MTU) - * MTU is usually associated with the Ethernet protocol, - * where a 1500-byte packet is the largest allowed in it - */ -#define ETH_MTU 1500 - -#define IP_V4_HEADER_LENGTH 20 -#define IP_V6_HEADER_LENGTH 40 - -#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 - * section 1.1 - */ -#define S2N_SSL2_RECORD_HEADER_LENGTH 2 -#define S2N_SSL2_MAXIMUM_MESSAGE_LENGTH 16383 -#define S2N_SSL2_MAXIMUM_RECORD_LENGTH (S2N_SSL2_MAXIMUM_MESSAGE_LENGTH + S2N_SSL2_RECORD_HEADER_LENGTH) - -/* s2n can use a "small" record length that is aligned to the dominant internet MTU; - * 1500 bytes, minus 20 bytes for an IP header, minus 20 bytes for a tcp - * header and 20 bytes for tcp/ip options (timestamp, sack etc) and a "large" record - * length that is designed to maximize throughput (fewer MACs per byte transferred - * and better efficiency of crypto engines). - */ -#define S2N_SMALL_RECORD_LENGTH (1500 - 20 - 20 - 20) -#define S2N_SMALL_FRAGMENT_LENGTH (S2N_SMALL_RECORD_LENGTH - S2N_TLS_RECORD_HEADER_LENGTH) - -/* Testing in the wild has found 8k max record sizes give a good balance of low latency - * and throughput. - */ -#define S2N_DEFAULT_RECORD_LENGTH 8092 -#define S2N_DEFAULT_FRAGMENT_LENGTH (S2N_DEFAULT_RECORD_LENGTH - S2N_TLS_RECORD_HEADER_LENGTH) - -/* S2N_LARGE_RECORD_LENGTH is used for initializing output buffers, we use the largest - * possible value of all supported protocols to avoid branching at runtime - */ -#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) - -/* Put a 64k cap on the size of any handshake message */ -#define S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH (64 * 1024) - -/* Maximum size for full encoded TLSInnerPlaintext (https://tools.ietf.org/html/rfc8446#section-5.4) */ -#define S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH ((1 << 14) + 1) - -/* Alert messages are always 2 bytes long */ -#define S2N_ALERT_LENGTH 2 - -/* Handshake messages have their own header too */ -#define TLS_HANDSHAKE_HEADER_LENGTH 4 - -#define S2N_MAX_SERVER_NAME 255 +/* + * 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 "crypto/s2n_hash.h" + +/* Codes from http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-5 */ +#define TLS_NULL_WITH_NULL_NULL 0x00, 0x00 +#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x00, 0x3D +#define TLS_RSA_WITH_AES_256_CBC_SHA 0x00, 0x35 +#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x00, 0x3C +#define TLS_RSA_WITH_AES_128_CBC_SHA 0x00, 0x2F +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x00, 0x0A +#define TLS_RSA_WITH_RC4_128_MD5 0x00, 0x04 +#define TLS_RSA_WITH_RC4_128_SHA 0x00, 0x05 + +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x00, 0x33 +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x00, 0x67 +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x00, 0x39 +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x00, 0x6B +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x00, 0x16 + +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC0, 0x09 +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC0, 0x23 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC0, 0x0A +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC0, 0x24 + +#define TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC0, 0x11 +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC0, 0x13 +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC0, 0x27 +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC0, 0x14 +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC0, 0x28 +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC0, 0x12 + +#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x00, 0x9C +#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x00, 0x9D +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x00, 0x9E +#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x00, 0x9F +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC0, 0x2B +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC0, 0x2C +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC0, 0x2F +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC0, 0x30 + +#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCC, 0xA8 +#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCC, 0xA9 +#define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCC, 0xAA + +/* TLS 1.2 hybrid post-quantum definitions from https://tools.ietf.org/html/draft-campagna-tls-bike-sike-hybrid */ +#define TLS_ECDHE_BIKE_RSA_WITH_AES_256_GCM_SHA384 0xFF, 0x04 +#define TLS_ECDHE_SIKE_RSA_WITH_AES_256_GCM_SHA384 0xFF, 0x08 +#define TLS_ECDHE_KYBER_RSA_WITH_AES_256_GCM_SHA384 0xFF, 0x0C +#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_SIKE_P503_R1 10 +#define TLS_PQ_KEM_EXTENSION_ID_SIKE_P434_R2 19 +#define TLS_PQ_KEM_EXTENSION_ID_KYBER_512_R2 23 +#define TLS_PQ_KEM_EXTENSION_ID_KYBER_512_90S_R2 24 + +/* 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 + +/* From https://tools.ietf.org/html/rfc7507 */ +#define TLS_FALLBACK_SCSV 0x56, 0x00 +#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00, 0xff + +/* TLS 1.3 cipher suites from https://tools.ietf.org/html/rfc8446#appendix-B.4 */ +#define TLS_AES_128_GCM_SHA256 0x13, 0x01 +#define TLS_AES_256_GCM_SHA384 0x13, 0x02 +#define TLS_CHACHA20_POLY1305_SHA256 0x13, 0x03 +#define TLS_AES_128_CCM_SHA256 0x13, 0x04 +#define TLS_AES_128_CCM_8_SHA256 0x13, 0x05 + +/* TLS extensions from https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml */ +#define TLS_EXTENSION_SERVER_NAME 0 +#define TLS_EXTENSION_MAX_FRAG_LEN 1 +#define TLS_EXTENSION_STATUS_REQUEST 5 +#define TLS_EXTENSION_SUPPORTED_GROUPS 10 +#define TLS_EXTENSION_EC_POINT_FORMATS 11 +#define TLS_EXTENSION_SIGNATURE_ALGORITHMS 13 +#define TLS_EXTENSION_ALPN 16 +#define TLS_EXTENSION_SCT_LIST 18 +#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_SUPPORTED_VERSIONS 43 +#define TLS_EXTENSION_COOKIE 44 +#define TLS_EXTENSION_KEY_SHARE 51 + +/* QUIC-TLS extension from https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-8.2 */ +#define TLS_QUIC_TRANSPORT_PARAMETERS 65535 + +/* 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 + +/* TLS SignatureScheme (Backwards compatible with SigHash and SigAlg values above) */ +/* Defined here: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme */ +#define TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA1 0x0201 +#define TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA224 0x0301 +#define TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA256 0x0401 +#define TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA384 0x0501 +#define TLS_SIGNATURE_SCHEME_RSA_PKCS1_SHA512 0x0601 + +/* In TLS 1.0 and 1.1 the hard-coded default scheme was RSA_PKCS1_MD5_SHA1, but there's no IANA defined backwards + * compatible value for that Scheme for TLS 1.2 and 1.3. So we define an internal value in the private range that won't + * match anything in the valid range so that all TLS Versions can use the same SignatureScheme negotiation abstraction + * layer. This scheme isn't in any preference list, so it can't be negotiated even if a client sent it in its pref list. */ +#define TLS_SIGNATURE_SCHEME_PRIVATE_INTERNAL_RSA_PKCS1_MD5_SHA1 0xFFFF + +/* TLS 1.2 Backwards Compatible ECDSA Schemes */ +#define TLS_SIGNATURE_SCHEME_ECDSA_SHA1 0x0203 +#define TLS_SIGNATURE_SCHEME_ECDSA_SHA224 0x0303 +#define TLS_SIGNATURE_SCHEME_ECDSA_SHA256 0x0403 +#define TLS_SIGNATURE_SCHEME_ECDSA_SHA384 0x0503 +#define TLS_SIGNATURE_SCHEME_ECDSA_SHA512 0x0603 + +/* TLS 1.3 ECDSA Signature Schemes */ +#define TLS_SIGNATURE_SCHEME_ECDSA_SECP256R1_SHA256 0x0403 +#define TLS_SIGNATURE_SCHEME_ECDSA_SECP384R1_SHA384 0x0503 +#define TLS_SIGNATURE_SCHEME_ECDSA_SECP521R1_SHA512 0x0603 +#define TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA256 0x0804 +#define TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA384 0x0805 +#define TLS_SIGNATURE_SCHEME_RSA_PSS_RSAE_SHA512 0x0806 +#define TLS_SIGNATURE_SCHEME_ED25519 0x0807 +#define TLS_SIGNATURE_SCHEME_ED448 0x0808 +#define TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA256 0x0809 +#define TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA384 0x080A +#define TLS_SIGNATURE_SCHEME_RSA_PSS_PSS_SHA512 0x080B + + +#define TLS_SIGNATURE_SCHEME_LEN 2 +#define TLS_SIGNATURE_SCHEME_LIST_MAX_LEN 64 + +/* The TLS record types we support */ +#define SSLv2_CLIENT_HELLO 1 +#define TLS_CHANGE_CIPHER_SPEC 20 +#define TLS_ALERT 21 +#define TLS_HANDSHAKE 22 +#define TLS_APPLICATION_DATA 23 + +/* Elliptic curve formats from http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-9 + * Only uncompressed is supported. + */ +#define TLS_EC_FORMAT_UNCOMPRESSED 0 +#define TLS_EC_FORMAT_ANSIX962_COMPRESSED_PRIME 1 +#define TLS_EC_FORMAT_ANSIX962_COMPRESSED_CHAR2 2 + +/* Elliptic curves from https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 */ +#define TLS_EC_CURVE_SECP_256_R1 23 +#define TLS_EC_CURVE_SECP_384_R1 24 +#define TLS_EC_CURVE_SECP_521_R1 25 +#define TLS_EC_CURVE_ECDH_X25519 29 + +/* Ethernet maximum transmission unit (MTU) + * MTU is usually associated with the Ethernet protocol, + * where a 1500-byte packet is the largest allowed in it + */ +#define ETH_MTU 1500 + +#define IP_V4_HEADER_LENGTH 20 +#define IP_V6_HEADER_LENGTH 40 + +#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 + * section 1.1 + */ +#define S2N_SSL2_RECORD_HEADER_LENGTH 2 +#define S2N_SSL2_MAXIMUM_MESSAGE_LENGTH 16383 +#define S2N_SSL2_MAXIMUM_RECORD_LENGTH (S2N_SSL2_MAXIMUM_MESSAGE_LENGTH + S2N_SSL2_RECORD_HEADER_LENGTH) + +/* s2n can use a "small" record length that is aligned to the dominant internet MTU; + * 1500 bytes, minus 20 bytes for an IP header, minus 20 bytes for a tcp + * header and 20 bytes for tcp/ip options (timestamp, sack etc) and a "large" record + * length that is designed to maximize throughput (fewer MACs per byte transferred + * and better efficiency of crypto engines). + */ +#define S2N_SMALL_RECORD_LENGTH (1500 - 20 - 20 - 20) +#define S2N_SMALL_FRAGMENT_LENGTH (S2N_SMALL_RECORD_LENGTH - S2N_TLS_RECORD_HEADER_LENGTH) + +/* Testing in the wild has found 8k max record sizes give a good balance of low latency + * and throughput. + */ +#define S2N_DEFAULT_RECORD_LENGTH 8092 +#define S2N_DEFAULT_FRAGMENT_LENGTH (S2N_DEFAULT_RECORD_LENGTH - S2N_TLS_RECORD_HEADER_LENGTH) + +/* S2N_LARGE_RECORD_LENGTH is used for initializing output buffers, we use the largest + * possible value of all supported protocols to avoid branching at runtime + */ +#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) + +/* Put a 64k cap on the size of any handshake message */ +#define S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH (64 * 1024) + +/* Maximum size for full encoded TLSInnerPlaintext (https://tools.ietf.org/html/rfc8446#section-5.4) */ +#define S2N_MAXIMUM_INNER_PLAINTEXT_LENGTH ((1 << 14) + 1) + +/* Alert messages are always 2 bytes long */ +#define S2N_ALERT_LENGTH 2 + +/* Handshake messages have their own header too */ +#define TLS_HANDSHAKE_HEADER_LENGTH 4 + +#define S2N_MAX_SERVER_NAME 255 diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c index be03383648..da2eea8be6 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c +++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.c @@ -1,613 +1,613 @@ -/* - * 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 "crypto/s2n_openssl.h" -#include "crypto/s2n_openssl_x509.h" -#include "utils/s2n_asn1_time.h" -#include "utils/s2n_result.h" -#include "utils/s2n_safety.h" -#include "utils/s2n_rfc5952.h" -#include "tls/extensions/s2n_extension_list.h" -#include "tls/s2n_config.h" -#include "tls/s2n_connection.h" - -#include <arpa/inet.h> -#include <sys/socket.h> - -#include <openssl/err.h> -#include <openssl/asn1.h> -#include <openssl/x509.h> - -#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC) -#include <openssl/ocsp.h> -#endif - -#ifndef X509_V_FLAG_PARTIAL_CHAIN -#define X509_V_FLAG_PARTIAL_CHAIN 0x80000 -#endif - -#define DEFAULT_MAX_CHAIN_DEPTH 7 -/* Time used by default for nextUpdate if none provided in OCSP: 1 hour since thisUpdate. */ -#define DEFAULT_OCSP_NEXT_UPDATE_PERIOD 3600000000000 - -typedef enum { - UNINIT, - INIT, - VALIDATED, - OCSP_VALIDATED, -} validator_state; - -uint8_t s2n_x509_ocsp_stapling_supported(void) { - return S2N_OCSP_STAPLING_SUPPORTED; -} - -void s2n_x509_trust_store_init_empty(struct s2n_x509_trust_store *store) { - store->trust_store = NULL; -} - -uint8_t s2n_x509_trust_store_has_certs(struct s2n_x509_trust_store *store) { - return store->trust_store ? (uint8_t) 1 : (uint8_t) 0; -} - -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); - } - - 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); - } - - X509_STORE_set_flags(store->trust_store, X509_VP_FLAG_DEFAULT); - - return 0; -} - -int s2n_x509_trust_store_add_pem(struct s2n_x509_trust_store *store, const char *pem) -{ - notnull_check(store); - notnull_check(pem); - - if (!store->trust_store) { - store->trust_store = X509_STORE_new(); - } - - 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)); - - 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)); - - 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); - } while (s2n_stuffer_data_available(&pem_in_stuffer)); - - return 0; -} - -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); - } - - 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); - } - - /* It's a likely scenario if this function is called, a self-signed certificate is used, and that is was generated - * without a trust anchor. However if you call this function, the assumption is you trust ca_file or path and if a certificate - * is encountered that's in that path, it should be trusted. The following flag tells libcrypto to not care that the cert - * is missing a root anchor. */ - unsigned long flags = X509_VP_FLAG_DEFAULT; - flags |= X509_V_FLAG_PARTIAL_CHAIN; - X509_STORE_set_flags(store->trust_store, flags); - - return 0; -} - -void s2n_x509_trust_store_wipe(struct s2n_x509_trust_store *store) { - if (store->trust_store) { - X509_STORE_free(store->trust_store); - store->trust_store = NULL; - } -} - -int s2n_x509_validator_init_no_x509_validation(struct s2n_x509_validator *validator) { - notnull_check(validator); - validator->trust_store = NULL; - validator->store_ctx = NULL; - validator->skip_cert_validation = 1; - validator->check_stapled_ocsp = 0; - validator->max_chain_depth = DEFAULT_MAX_CHAIN_DEPTH; - validator->state = INIT; - validator->cert_chain_from_wire = sk_X509_new_null(); - - return 0; -} - -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); - validator->trust_store = trust_store; - validator->skip_cert_validation = 0; - validator->check_stapled_ocsp = check_ocsp; - validator->max_chain_depth = DEFAULT_MAX_CHAIN_DEPTH; - validator->store_ctx = NULL; - if (validator->trust_store->trust_store) { - validator->store_ctx = X509_STORE_CTX_new(); - notnull_check(validator->store_ctx); - } - validator->cert_chain_from_wire = sk_X509_new_null(); - validator->state = INIT; - - return 0; -} - -static inline void wipe_cert_chain(STACK_OF(X509) *cert_chain) { - if (cert_chain) { - sk_X509_pop_free(cert_chain, X509_free); - } -} - -void s2n_x509_validator_wipe(struct s2n_x509_validator *validator) { - if (validator->store_ctx) { - X509_STORE_CTX_free(validator->store_ctx); - validator->store_ctx = NULL; - } - wipe_cert_chain(validator->cert_chain_from_wire); - validator->cert_chain_from_wire = NULL; - validator->trust_store = NULL; - validator->skip_cert_validation = 0; - validator->state = UNINIT; - validator->max_chain_depth = 0; -} - -int s2n_x509_validator_set_max_chain_depth(struct s2n_x509_validator *validator, uint16_t max_depth) { - notnull_check(validator); - S2N_ERROR_IF(max_depth == 0, S2N_ERR_INVALID_ARGUMENT); - - validator->max_chain_depth = max_depth; - return 0; -} - -/* - * For each name in the cert. Iterate them. Call the callback. If one returns true, then consider it validated, - * if none of them return true, the cert is considered invalid. - */ -static uint8_t s2n_verify_host_information(struct s2n_x509_validator *validator, struct s2n_connection *conn, X509 *public_cert) { - (void)validator; - uint8_t verified = 0; - uint8_t san_found = 0; - - /* Check SubjectAltNames before CommonName as per RFC 6125 6.4.4 */ - STACK_OF(GENERAL_NAME) *names_list = X509_get_ext_d2i(public_cert, NID_subject_alt_name, NULL, NULL); - int n = sk_GENERAL_NAME_num(names_list); - for (int i = 0; i < n && !verified; i++) { - GENERAL_NAME *current_name = sk_GENERAL_NAME_value(names_list, i); - if (current_name->type == GEN_DNS) { - san_found = 1; - - const char *name = (const char *) ASN1_STRING_data(current_name->d.ia5); - size_t name_len = (size_t) ASN1_STRING_length(current_name->d.ia5); - - verified = conn->verify_host_fn(name, name_len, conn->data_for_verify_host); - } else if (current_name->type == GEN_URI) { - const char *name = (const char *) ASN1_STRING_data(current_name->d.ia5); - size_t name_len = (size_t) ASN1_STRING_length(current_name->d.ia5); - - verified = conn->verify_host_fn(name, name_len, conn->data_for_verify_host); - } else if (current_name->type == GEN_IPADD) { - san_found = 1; - /* try to validate an IP address if it's in the subject alt name. */ - const unsigned char *ip_addr = current_name->d.iPAddress->data; - size_t ip_addr_len = (size_t)current_name->d.iPAddress->length; - - s2n_result parse_result = S2N_RESULT_ERROR; - s2n_stack_blob(address, INET6_ADDRSTRLEN + 1, INET6_ADDRSTRLEN + 1); - if (ip_addr_len == 4) { - parse_result = s2n_inet_ntop(AF_INET, ip_addr, &address); - } else if (ip_addr_len == 16) { - parse_result = s2n_inet_ntop(AF_INET6, ip_addr, &address); - } - - /* strlen should be safe here since we made sure we were null terminated AND that inet_ntop succeeded */ - if (s2n_result_is_ok(parse_result)) { - verified = conn->verify_host_fn( - (const char *)address.data, - strlen((const char *)address.data), - conn->data_for_verify_host); - } - } - } - - GENERAL_NAMES_free(names_list); - - /* if no SubjectAltNames of type DNS found, go to the common name. */ - if (!verified && !san_found) { - X509_NAME *subject_name = X509_get_subject_name(public_cert); - if (subject_name) { - int next_idx = 0, curr_idx = -1; - while ((next_idx = X509_NAME_get_index_by_NID(subject_name, NID_commonName, curr_idx)) >= 0) { - curr_idx = next_idx; - } - - if (curr_idx >= 0) { - ASN1_STRING *common_name = - X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, curr_idx)); - - if (common_name) { - char peer_cn[255]; - static size_t peer_cn_size = sizeof(peer_cn); - memset_check(&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 || - ASN1_STRING_type(common_name) == V_ASN1_PRINTABLESTRING || - ASN1_STRING_type(common_name) == V_ASN1_UNIVERSALSTRING || - ASN1_STRING_type(common_name) == V_ASN1_UTF8STRING || - ASN1_STRING_type(common_name) == V_ASN1_BMPSTRING ) { - - 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); - verified = conn->verify_host_fn(peer_cn, len, conn->data_for_verify_host); - } - } - } - } - } - - return verified; -} - -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); - - 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); - - S2N_ERROR_IF(s2n_stuffer_init(&cert_chain_in_stuffer, &cert_chain_blob) < 0, S2N_ERR_CERT_UNTRUSTED); - S2N_ERROR_IF(s2n_stuffer_write(&cert_chain_in_stuffer, &cert_chain_blob) < 0, S2N_ERR_CERT_UNTRUSTED); - - s2n_parsed_extensions_list first_certificate_extensions = {0}; - - X509 *server_cert = NULL; - - DEFER_CLEANUP(struct s2n_pkey public_key = {0}, s2n_pkey_free); - s2n_pkey_zero_init(&public_key); - - while (s2n_stuffer_data_available(&cert_chain_in_stuffer) && sk_X509_num(validator->cert_chain_from_wire) < validator->max_chain_depth) { - uint32_t certificate_size = 0; - - S2N_ERROR_IF(s2n_stuffer_read_uint24(&cert_chain_in_stuffer, &certificate_size) < 0, S2N_ERR_CERT_UNTRUSTED); - S2N_ERROR_IF(certificate_size == 0 || certificate_size > s2n_stuffer_data_available(&cert_chain_in_stuffer), S2N_ERR_CERT_UNTRUSTED); - - 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); - - const uint8_t *data = asn1cert.data; - - /* the cert is der encoded, just convert it. */ - server_cert = d2i_X509(NULL, &data, asn1cert.size); - S2N_ERROR_IF(!server_cert, S2N_ERR_CERT_UNTRUSTED); - - /* 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); - } - - if (!validator->skip_cert_validation) { - GUARD_AS_POSIX(s2n_validate_certificate_signature(conn, server_cert)); - } - - /* Pull the public key from the first certificate */ - if (sk_X509_num(validator->cert_chain_from_wire) == 1) { - S2N_ERROR_IF(s2n_asn1der_to_public_key_and_type(&public_key, pkey_type, &asn1cert) < 0, S2N_ERR_CERT_UNTRUSTED); - } - - /* certificate extensions is a field in TLS 1.3 - https://tools.ietf.org/html/rfc8446#section-4.4.2 */ - if (conn->actual_protocol_version >= S2N_TLS13) { - s2n_parsed_extensions_list parsed_extensions_list = { 0 }; - 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) { - first_certificate_extensions = parsed_extensions_list; - } - } - } - - /* if this occurred we exceeded validator->max_chain_depth */ - S2N_ERROR_IF(!validator->skip_cert_validation && s2n_stuffer_data_available(&cert_chain_in_stuffer), S2N_ERR_CERT_UNTRUSTED); - S2N_ERROR_IF(sk_X509_num(validator->cert_chain_from_wire) < 1, S2N_ERR_CERT_UNTRUSTED); - - if (!validator->skip_cert_validation) { - X509 *leaf = sk_X509_value(validator->cert_chain_from_wire, 0); - S2N_ERROR_IF(!leaf, S2N_ERR_CERT_UNTRUSTED); - S2N_ERROR_IF(conn->verify_host_fn && !s2n_verify_host_information(validator, conn, leaf), S2N_ERR_CERT_UNTRUSTED); - - int op_code = X509_STORE_CTX_init(validator->store_ctx, validator->trust_store->trust_store, leaf, validator->cert_chain_from_wire); - S2N_ERROR_IF(op_code <= 0, S2N_ERR_CERT_UNTRUSTED); - - X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(validator->store_ctx); - X509_VERIFY_PARAM_set_depth(param, validator->max_chain_depth); - - uint64_t current_sys_time = 0; - conn->config->wall_clock(conn->config->sys_clock_ctx, ¤t_sys_time); - - /* this wants seconds not nanoseconds */ - time_t current_time = (time_t)(current_sys_time / 1000000000); - X509_STORE_CTX_set_time(validator->store_ctx, 0, current_time); - - op_code = X509_verify_cert(validator->store_ctx); - - S2N_ERROR_IF(op_code <= 0, S2N_ERR_CERT_UNTRUSTED); - validator->state = VALIDATED; - } - - if (conn->actual_protocol_version >= S2N_TLS13) { - GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_CERTIFICATE, conn, &first_certificate_extensions)); - } - - *public_key_out = public_key; - - /* Reset the old struct, so we don't clean up public_key_out */ - s2n_pkey_zero_init(&public_key); - - return S2N_CERT_OK; -} - -s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(struct s2n_x509_validator *validator, - struct s2n_connection *conn, const uint8_t *ocsp_response_raw, uint32_t ocsp_response_length) { - - if (validator->skip_cert_validation || !validator->check_stapled_ocsp) { - validator->state = OCSP_VALIDATED; - return S2N_CERT_OK; - } - - S2N_ERROR_IF(validator->state != VALIDATED, S2N_ERR_INVALID_STATE); - -#if !S2N_OCSP_STAPLING_SUPPORTED - /* Default to safety */ - return S2N_CERT_ERR_UNTRUSTED; -#else - - OCSP_RESPONSE *ocsp_response = NULL; - OCSP_BASICRESP *basic_response = NULL; - STACK_OF(X509) *cert_chain = NULL; - - s2n_cert_validation_code ret_val = S2N_CERT_ERR_INVALID; - - if (!ocsp_response_raw) { - return ret_val; - } - - ocsp_response = d2i_OCSP_RESPONSE(NULL, &ocsp_response_raw, ocsp_response_length); - - if (!ocsp_response) { - goto clean_up; - } - - int ocsp_status = OCSP_response_status(ocsp_response); - - if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { - goto clean_up; - } - - basic_response = OCSP_response_get1_basic(ocsp_response); - if (!basic_response) { - goto clean_up; - } - - /* X509_STORE_CTX_get0_chain() is better because it doesn't return a copy. But it's not available for Openssl 1.0.2. - * Therefore, we call this variant and clean it up at the end of the function. - * See the comments here: - * https://www.openssl.org/docs/man1.0.2/man3/X509_STORE_CTX_get1_chain.html - */ - cert_chain = X509_STORE_CTX_get1_chain(validator->store_ctx); - if (!cert_chain) { - goto clean_up; - } - - const int certs_in_chain = sk_X509_num(cert_chain); - - if (!certs_in_chain) { - goto clean_up; - } - - /* leaf is the top: not the bottom. */ - X509 *subject = sk_X509_value(cert_chain, 0); - X509 *issuer = NULL; - /* find the issuer in the chain. If it's not there. Fail everything. */ - for (int i = 0; i < certs_in_chain; ++i) { - X509 *issuer_candidate = sk_X509_value(cert_chain, i); - const int issuer_value = X509_check_issued(issuer_candidate, subject); - - if (issuer_value == X509_V_OK) { - issuer = issuer_candidate; - break; - } - } - - if (!issuer) { - goto clean_up; - } - - /* 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; - goto clean_up; - } - - int status = 0; - int reason = 0; - - /* sha1 is the only supported OCSP digest */ - OCSP_CERTID *cert_id = OCSP_cert_to_id(EVP_sha1(), subject, issuer); - - if (!cert_id) { - goto clean_up; - } - - ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd; - /* Actual verification of the response */ - const int ocsp_resp_find_status_res = OCSP_resp_find_status(basic_response, cert_id, &status, &reason, &revtime, &thisupd, &nextupd); - OCSP_CERTID_free(cert_id); - - if (!ocsp_resp_find_status_res) { - ret_val = S2N_CERT_ERR_UNTRUSTED; - goto clean_up; - } - - uint64_t this_update = 0; - s2n_result thisupd_result = s2n_asn1_time_to_nano_since_epoch_ticks((const char *) thisupd->data, - (uint32_t) thisupd->length, &this_update); - - uint64_t next_update = 0; - s2n_result nextupd_result = S2N_RESULT_OK; - if (nextupd) { - nextupd_result = s2n_asn1_time_to_nano_since_epoch_ticks((const char *) nextupd->data, - (uint32_t) nextupd->length, &next_update); - } else { - next_update = this_update + DEFAULT_OCSP_NEXT_UPDATE_PERIOD; - } - - uint64_t current_time = 0; - const int current_time_err = conn->config->wall_clock(conn->config->sys_clock_ctx, ¤t_time); - - if (current_time_err) { - goto clean_up; - } - - if (s2n_result_is_error(thisupd_result) || s2n_result_is_error(nextupd_result) || current_time_err) { - ret_val = S2N_CERT_ERR_UNTRUSTED; - goto clean_up; - } - - if (current_time < this_update || current_time > next_update) { - ret_val = S2N_CERT_ERR_EXPIRED; - goto clean_up; - } - - switch (status) { - case V_OCSP_CERTSTATUS_GOOD: - validator->state = OCSP_VALIDATED; - ret_val = S2N_CERT_OK; - break; - case V_OCSP_CERTSTATUS_REVOKED: - ret_val = S2N_CERT_ERR_REVOKED; - goto clean_up; - case V_OCSP_CERTSTATUS_UNKNOWN: - goto clean_up; - default: - goto clean_up; - } - - clean_up: - if (basic_response) { - OCSP_BASICRESP_free(basic_response); - } - - if (ocsp_response) { - OCSP_RESPONSE_free(ocsp_response); - } - - if (cert_chain) { - wipe_cert_chain(cert_chain); - } - - return ret_val; -#endif /* S2N_OCSP_STAPLING_SUPPORTED */ -} - -S2N_RESULT s2n_validate_certificate_signature(struct s2n_connection *conn, X509 *x509_cert) -{ - ENSURE_REF(conn); - ENSURE_REF(x509_cert); - - const struct s2n_security_policy *security_policy; - GUARD_AS_RESULT(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); - - X509_NAME *subject_name = X509_get_subject_name(x509_cert); - 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)); - - 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); - - int nid = 0; - - #if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x02070000f) - ENSURE_REF(x509_cert->sig_alg); - nid = OBJ_obj2nid(x509_cert->sig_alg->algorithm); - #else - nid = X509_get_signature_nid(x509_cert); - #endif - - for (size_t i = 0; i < cert_sig_preferences->count; i++) { - - 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 && - cert_sig_preferences->signature_schemes[i]->hash_alg == S2N_HASH_SHA1), S2N_ERR_CERT_UNTRUSTED); - - return S2N_RESULT_OK; - } - } - - BAIL(S2N_ERR_CERT_UNTRUSTED); -} +/* + * 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 "crypto/s2n_openssl.h" +#include "crypto/s2n_openssl_x509.h" +#include "utils/s2n_asn1_time.h" +#include "utils/s2n_result.h" +#include "utils/s2n_safety.h" +#include "utils/s2n_rfc5952.h" +#include "tls/extensions/s2n_extension_list.h" +#include "tls/s2n_config.h" +#include "tls/s2n_connection.h" + +#include <arpa/inet.h> +#include <sys/socket.h> + +#include <openssl/err.h> +#include <openssl/asn1.h> +#include <openssl/x509.h> + +#if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC) +#include <openssl/ocsp.h> +#endif + +#ifndef X509_V_FLAG_PARTIAL_CHAIN +#define X509_V_FLAG_PARTIAL_CHAIN 0x80000 +#endif + +#define DEFAULT_MAX_CHAIN_DEPTH 7 +/* Time used by default for nextUpdate if none provided in OCSP: 1 hour since thisUpdate. */ +#define DEFAULT_OCSP_NEXT_UPDATE_PERIOD 3600000000000 + +typedef enum { + UNINIT, + INIT, + VALIDATED, + OCSP_VALIDATED, +} validator_state; + +uint8_t s2n_x509_ocsp_stapling_supported(void) { + return S2N_OCSP_STAPLING_SUPPORTED; +} + +void s2n_x509_trust_store_init_empty(struct s2n_x509_trust_store *store) { + store->trust_store = NULL; +} + +uint8_t s2n_x509_trust_store_has_certs(struct s2n_x509_trust_store *store) { + return store->trust_store ? (uint8_t) 1 : (uint8_t) 0; +} + +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); + } + + 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); + } + + X509_STORE_set_flags(store->trust_store, X509_VP_FLAG_DEFAULT); + + return 0; +} + +int s2n_x509_trust_store_add_pem(struct s2n_x509_trust_store *store, const char *pem) +{ + notnull_check(store); + notnull_check(pem); + + if (!store->trust_store) { + store->trust_store = X509_STORE_new(); + } + + 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)); + + 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)); + + 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); + } while (s2n_stuffer_data_available(&pem_in_stuffer)); + + return 0; +} + +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); + } + + 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); + } + + /* It's a likely scenario if this function is called, a self-signed certificate is used, and that is was generated + * without a trust anchor. However if you call this function, the assumption is you trust ca_file or path and if a certificate + * is encountered that's in that path, it should be trusted. The following flag tells libcrypto to not care that the cert + * is missing a root anchor. */ + unsigned long flags = X509_VP_FLAG_DEFAULT; + flags |= X509_V_FLAG_PARTIAL_CHAIN; + X509_STORE_set_flags(store->trust_store, flags); + + return 0; +} + +void s2n_x509_trust_store_wipe(struct s2n_x509_trust_store *store) { + if (store->trust_store) { + X509_STORE_free(store->trust_store); + store->trust_store = NULL; + } +} + +int s2n_x509_validator_init_no_x509_validation(struct s2n_x509_validator *validator) { + notnull_check(validator); + validator->trust_store = NULL; + validator->store_ctx = NULL; + validator->skip_cert_validation = 1; + validator->check_stapled_ocsp = 0; + validator->max_chain_depth = DEFAULT_MAX_CHAIN_DEPTH; + validator->state = INIT; + validator->cert_chain_from_wire = sk_X509_new_null(); + + return 0; +} + +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); + validator->trust_store = trust_store; + validator->skip_cert_validation = 0; + validator->check_stapled_ocsp = check_ocsp; + validator->max_chain_depth = DEFAULT_MAX_CHAIN_DEPTH; + validator->store_ctx = NULL; + if (validator->trust_store->trust_store) { + validator->store_ctx = X509_STORE_CTX_new(); + notnull_check(validator->store_ctx); + } + validator->cert_chain_from_wire = sk_X509_new_null(); + validator->state = INIT; + + return 0; +} + +static inline void wipe_cert_chain(STACK_OF(X509) *cert_chain) { + if (cert_chain) { + sk_X509_pop_free(cert_chain, X509_free); + } +} + +void s2n_x509_validator_wipe(struct s2n_x509_validator *validator) { + if (validator->store_ctx) { + X509_STORE_CTX_free(validator->store_ctx); + validator->store_ctx = NULL; + } + wipe_cert_chain(validator->cert_chain_from_wire); + validator->cert_chain_from_wire = NULL; + validator->trust_store = NULL; + validator->skip_cert_validation = 0; + validator->state = UNINIT; + validator->max_chain_depth = 0; +} + +int s2n_x509_validator_set_max_chain_depth(struct s2n_x509_validator *validator, uint16_t max_depth) { + notnull_check(validator); + S2N_ERROR_IF(max_depth == 0, S2N_ERR_INVALID_ARGUMENT); + + validator->max_chain_depth = max_depth; + return 0; +} + +/* + * For each name in the cert. Iterate them. Call the callback. If one returns true, then consider it validated, + * if none of them return true, the cert is considered invalid. + */ +static uint8_t s2n_verify_host_information(struct s2n_x509_validator *validator, struct s2n_connection *conn, X509 *public_cert) { + (void)validator; + uint8_t verified = 0; + uint8_t san_found = 0; + + /* Check SubjectAltNames before CommonName as per RFC 6125 6.4.4 */ + STACK_OF(GENERAL_NAME) *names_list = X509_get_ext_d2i(public_cert, NID_subject_alt_name, NULL, NULL); + int n = sk_GENERAL_NAME_num(names_list); + for (int i = 0; i < n && !verified; i++) { + GENERAL_NAME *current_name = sk_GENERAL_NAME_value(names_list, i); + if (current_name->type == GEN_DNS) { + san_found = 1; + + const char *name = (const char *) ASN1_STRING_data(current_name->d.ia5); + size_t name_len = (size_t) ASN1_STRING_length(current_name->d.ia5); + + verified = conn->verify_host_fn(name, name_len, conn->data_for_verify_host); + } else if (current_name->type == GEN_URI) { + const char *name = (const char *) ASN1_STRING_data(current_name->d.ia5); + size_t name_len = (size_t) ASN1_STRING_length(current_name->d.ia5); + + verified = conn->verify_host_fn(name, name_len, conn->data_for_verify_host); + } else if (current_name->type == GEN_IPADD) { + san_found = 1; + /* try to validate an IP address if it's in the subject alt name. */ + const unsigned char *ip_addr = current_name->d.iPAddress->data; + size_t ip_addr_len = (size_t)current_name->d.iPAddress->length; + + s2n_result parse_result = S2N_RESULT_ERROR; + s2n_stack_blob(address, INET6_ADDRSTRLEN + 1, INET6_ADDRSTRLEN + 1); + if (ip_addr_len == 4) { + parse_result = s2n_inet_ntop(AF_INET, ip_addr, &address); + } else if (ip_addr_len == 16) { + parse_result = s2n_inet_ntop(AF_INET6, ip_addr, &address); + } + + /* strlen should be safe here since we made sure we were null terminated AND that inet_ntop succeeded */ + if (s2n_result_is_ok(parse_result)) { + verified = conn->verify_host_fn( + (const char *)address.data, + strlen((const char *)address.data), + conn->data_for_verify_host); + } + } + } + + GENERAL_NAMES_free(names_list); + + /* if no SubjectAltNames of type DNS found, go to the common name. */ + if (!verified && !san_found) { + X509_NAME *subject_name = X509_get_subject_name(public_cert); + if (subject_name) { + int next_idx = 0, curr_idx = -1; + while ((next_idx = X509_NAME_get_index_by_NID(subject_name, NID_commonName, curr_idx)) >= 0) { + curr_idx = next_idx; + } + + if (curr_idx >= 0) { + ASN1_STRING *common_name = + X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, curr_idx)); + + if (common_name) { + char peer_cn[255]; + static size_t peer_cn_size = sizeof(peer_cn); + memset_check(&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 || + ASN1_STRING_type(common_name) == V_ASN1_PRINTABLESTRING || + ASN1_STRING_type(common_name) == V_ASN1_UNIVERSALSTRING || + ASN1_STRING_type(common_name) == V_ASN1_UTF8STRING || + ASN1_STRING_type(common_name) == V_ASN1_BMPSTRING ) { + + 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); + verified = conn->verify_host_fn(peer_cn, len, conn->data_for_verify_host); + } + } + } + } + } + + return verified; +} + +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); + + 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); + + S2N_ERROR_IF(s2n_stuffer_init(&cert_chain_in_stuffer, &cert_chain_blob) < 0, S2N_ERR_CERT_UNTRUSTED); + S2N_ERROR_IF(s2n_stuffer_write(&cert_chain_in_stuffer, &cert_chain_blob) < 0, S2N_ERR_CERT_UNTRUSTED); + + s2n_parsed_extensions_list first_certificate_extensions = {0}; + + X509 *server_cert = NULL; + + DEFER_CLEANUP(struct s2n_pkey public_key = {0}, s2n_pkey_free); + s2n_pkey_zero_init(&public_key); + + while (s2n_stuffer_data_available(&cert_chain_in_stuffer) && sk_X509_num(validator->cert_chain_from_wire) < validator->max_chain_depth) { + uint32_t certificate_size = 0; + + S2N_ERROR_IF(s2n_stuffer_read_uint24(&cert_chain_in_stuffer, &certificate_size) < 0, S2N_ERR_CERT_UNTRUSTED); + S2N_ERROR_IF(certificate_size == 0 || certificate_size > s2n_stuffer_data_available(&cert_chain_in_stuffer), S2N_ERR_CERT_UNTRUSTED); + + 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); + + const uint8_t *data = asn1cert.data; + + /* the cert is der encoded, just convert it. */ + server_cert = d2i_X509(NULL, &data, asn1cert.size); + S2N_ERROR_IF(!server_cert, S2N_ERR_CERT_UNTRUSTED); + + /* 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); + } + + if (!validator->skip_cert_validation) { + GUARD_AS_POSIX(s2n_validate_certificate_signature(conn, server_cert)); + } + + /* Pull the public key from the first certificate */ + if (sk_X509_num(validator->cert_chain_from_wire) == 1) { + S2N_ERROR_IF(s2n_asn1der_to_public_key_and_type(&public_key, pkey_type, &asn1cert) < 0, S2N_ERR_CERT_UNTRUSTED); + } + + /* certificate extensions is a field in TLS 1.3 - https://tools.ietf.org/html/rfc8446#section-4.4.2 */ + if (conn->actual_protocol_version >= S2N_TLS13) { + s2n_parsed_extensions_list parsed_extensions_list = { 0 }; + 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) { + first_certificate_extensions = parsed_extensions_list; + } + } + } + + /* if this occurred we exceeded validator->max_chain_depth */ + S2N_ERROR_IF(!validator->skip_cert_validation && s2n_stuffer_data_available(&cert_chain_in_stuffer), S2N_ERR_CERT_UNTRUSTED); + S2N_ERROR_IF(sk_X509_num(validator->cert_chain_from_wire) < 1, S2N_ERR_CERT_UNTRUSTED); + + if (!validator->skip_cert_validation) { + X509 *leaf = sk_X509_value(validator->cert_chain_from_wire, 0); + S2N_ERROR_IF(!leaf, S2N_ERR_CERT_UNTRUSTED); + S2N_ERROR_IF(conn->verify_host_fn && !s2n_verify_host_information(validator, conn, leaf), S2N_ERR_CERT_UNTRUSTED); + + int op_code = X509_STORE_CTX_init(validator->store_ctx, validator->trust_store->trust_store, leaf, validator->cert_chain_from_wire); + S2N_ERROR_IF(op_code <= 0, S2N_ERR_CERT_UNTRUSTED); + + X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(validator->store_ctx); + X509_VERIFY_PARAM_set_depth(param, validator->max_chain_depth); + + uint64_t current_sys_time = 0; + conn->config->wall_clock(conn->config->sys_clock_ctx, ¤t_sys_time); + + /* this wants seconds not nanoseconds */ + time_t current_time = (time_t)(current_sys_time / 1000000000); + X509_STORE_CTX_set_time(validator->store_ctx, 0, current_time); + + op_code = X509_verify_cert(validator->store_ctx); + + S2N_ERROR_IF(op_code <= 0, S2N_ERR_CERT_UNTRUSTED); + validator->state = VALIDATED; + } + + if (conn->actual_protocol_version >= S2N_TLS13) { + GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_CERTIFICATE, conn, &first_certificate_extensions)); + } + + *public_key_out = public_key; + + /* Reset the old struct, so we don't clean up public_key_out */ + s2n_pkey_zero_init(&public_key); + + return S2N_CERT_OK; +} + +s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(struct s2n_x509_validator *validator, + struct s2n_connection *conn, const uint8_t *ocsp_response_raw, uint32_t ocsp_response_length) { + + if (validator->skip_cert_validation || !validator->check_stapled_ocsp) { + validator->state = OCSP_VALIDATED; + return S2N_CERT_OK; + } + + S2N_ERROR_IF(validator->state != VALIDATED, S2N_ERR_INVALID_STATE); + +#if !S2N_OCSP_STAPLING_SUPPORTED + /* Default to safety */ + return S2N_CERT_ERR_UNTRUSTED; +#else + + OCSP_RESPONSE *ocsp_response = NULL; + OCSP_BASICRESP *basic_response = NULL; + STACK_OF(X509) *cert_chain = NULL; + + s2n_cert_validation_code ret_val = S2N_CERT_ERR_INVALID; + + if (!ocsp_response_raw) { + return ret_val; + } + + ocsp_response = d2i_OCSP_RESPONSE(NULL, &ocsp_response_raw, ocsp_response_length); + + if (!ocsp_response) { + goto clean_up; + } + + int ocsp_status = OCSP_response_status(ocsp_response); + + if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + goto clean_up; + } + + basic_response = OCSP_response_get1_basic(ocsp_response); + if (!basic_response) { + goto clean_up; + } + + /* X509_STORE_CTX_get0_chain() is better because it doesn't return a copy. But it's not available for Openssl 1.0.2. + * Therefore, we call this variant and clean it up at the end of the function. + * See the comments here: + * https://www.openssl.org/docs/man1.0.2/man3/X509_STORE_CTX_get1_chain.html + */ + cert_chain = X509_STORE_CTX_get1_chain(validator->store_ctx); + if (!cert_chain) { + goto clean_up; + } + + const int certs_in_chain = sk_X509_num(cert_chain); + + if (!certs_in_chain) { + goto clean_up; + } + + /* leaf is the top: not the bottom. */ + X509 *subject = sk_X509_value(cert_chain, 0); + X509 *issuer = NULL; + /* find the issuer in the chain. If it's not there. Fail everything. */ + for (int i = 0; i < certs_in_chain; ++i) { + X509 *issuer_candidate = sk_X509_value(cert_chain, i); + const int issuer_value = X509_check_issued(issuer_candidate, subject); + + if (issuer_value == X509_V_OK) { + issuer = issuer_candidate; + break; + } + } + + if (!issuer) { + goto clean_up; + } + + /* 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; + goto clean_up; + } + + int status = 0; + int reason = 0; + + /* sha1 is the only supported OCSP digest */ + OCSP_CERTID *cert_id = OCSP_cert_to_id(EVP_sha1(), subject, issuer); + + if (!cert_id) { + goto clean_up; + } + + ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd; + /* Actual verification of the response */ + const int ocsp_resp_find_status_res = OCSP_resp_find_status(basic_response, cert_id, &status, &reason, &revtime, &thisupd, &nextupd); + OCSP_CERTID_free(cert_id); + + if (!ocsp_resp_find_status_res) { + ret_val = S2N_CERT_ERR_UNTRUSTED; + goto clean_up; + } + + uint64_t this_update = 0; + s2n_result thisupd_result = s2n_asn1_time_to_nano_since_epoch_ticks((const char *) thisupd->data, + (uint32_t) thisupd->length, &this_update); + + uint64_t next_update = 0; + s2n_result nextupd_result = S2N_RESULT_OK; + if (nextupd) { + nextupd_result = s2n_asn1_time_to_nano_since_epoch_ticks((const char *) nextupd->data, + (uint32_t) nextupd->length, &next_update); + } else { + next_update = this_update + DEFAULT_OCSP_NEXT_UPDATE_PERIOD; + } + + uint64_t current_time = 0; + const int current_time_err = conn->config->wall_clock(conn->config->sys_clock_ctx, ¤t_time); + + if (current_time_err) { + goto clean_up; + } + + if (s2n_result_is_error(thisupd_result) || s2n_result_is_error(nextupd_result) || current_time_err) { + ret_val = S2N_CERT_ERR_UNTRUSTED; + goto clean_up; + } + + if (current_time < this_update || current_time > next_update) { + ret_val = S2N_CERT_ERR_EXPIRED; + goto clean_up; + } + + switch (status) { + case V_OCSP_CERTSTATUS_GOOD: + validator->state = OCSP_VALIDATED; + ret_val = S2N_CERT_OK; + break; + case V_OCSP_CERTSTATUS_REVOKED: + ret_val = S2N_CERT_ERR_REVOKED; + goto clean_up; + case V_OCSP_CERTSTATUS_UNKNOWN: + goto clean_up; + default: + goto clean_up; + } + + clean_up: + if (basic_response) { + OCSP_BASICRESP_free(basic_response); + } + + if (ocsp_response) { + OCSP_RESPONSE_free(ocsp_response); + } + + if (cert_chain) { + wipe_cert_chain(cert_chain); + } + + return ret_val; +#endif /* S2N_OCSP_STAPLING_SUPPORTED */ +} + +S2N_RESULT s2n_validate_certificate_signature(struct s2n_connection *conn, X509 *x509_cert) +{ + ENSURE_REF(conn); + ENSURE_REF(x509_cert); + + const struct s2n_security_policy *security_policy; + GUARD_AS_RESULT(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); + + X509_NAME *subject_name = X509_get_subject_name(x509_cert); + 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)); + + 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); + + int nid = 0; + + #if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x02070000f) + ENSURE_REF(x509_cert->sig_alg); + nid = OBJ_obj2nid(x509_cert->sig_alg->algorithm); + #else + nid = X509_get_signature_nid(x509_cert); + #endif + + for (size_t i = 0; i < cert_sig_preferences->count; i++) { + + 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 && + cert_sig_preferences->signature_schemes[i]->hash_alg == S2N_HASH_SHA1), S2N_ERR_CERT_UNTRUSTED); + + return S2N_RESULT_OK; + } + } + + BAIL(S2N_ERR_CERT_UNTRUSTED); +} diff --git a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h index 5c51858979..9e57bb4d34 100644 --- a/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h +++ b/contrib/restricted/aws/s2n/tls/s2n_x509_validator.h @@ -1,134 +1,134 @@ -/* - * 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_signature_scheme.h" - -#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 - * that would have to be there when they add support */ -#if (defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)) && !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) */ - -typedef enum { - S2N_CERT_OK = 0, - S2N_CERT_ERR_UNTRUSTED = -1, - S2N_CERT_ERR_REVOKED = -2, - 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_validation_code; - -/** 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; - -/** - * Trust store simply contains the trust store each connection should validate certs against. - * For most use cases, you only need one of these per application. - */ -struct s2n_x509_trust_store { - X509_STORE *trust_store; -}; - -/** - * You should have one instance of this per connection. - */ -struct s2n_x509_validator { - struct s2n_x509_trust_store *trust_store; - X509_STORE_CTX *store_ctx; - uint8_t skip_cert_validation; - uint8_t check_stapled_ocsp; - uint16_t max_chain_depth; - STACK_OF(X509) *cert_chain_from_wire; - int state; -}; - -/** Some libcrypto implementations do not support OCSP validation. Returns 1 if supported, 0 otherwise. */ -uint8_t s2n_x509_ocsp_stapling_supported(void); - -/** Initialize the trust store to empty defaults (no allocations happen here) */ -void s2n_x509_trust_store_init_empty(struct s2n_x509_trust_store *store); - -/** Returns TRUE if the trust store has certificates installed, FALSE otherwise */ -uint8_t s2n_x509_trust_store_has_certs(struct s2n_x509_trust_store *store); - -/** Initializes the trust store to default system paths **/ -int s2n_x509_trust_store_from_system_defaults(struct s2n_x509_trust_store *store); - -/** Initialize trust store from a PEM. This will allocate memory, and load PEM into the Trust Store **/ -int s2n_x509_trust_store_add_pem(struct s2n_x509_trust_store *store, const char *pem); - -/** Initialize trust store from a CA file. This will allocate memory, and load each cert in the file into the trust store - * Returns 0 on success, or S2N error codes on failure. */ -int s2n_x509_trust_store_from_ca_file(struct s2n_x509_trust_store *store, const char *ca_pem_filename, const char *ca_dir); - -/** Cleans up, and frees any underlying memory in the trust store. */ -void s2n_x509_trust_store_wipe(struct s2n_x509_trust_store *store); - -/** Initialize the validator in unsafe mode. No validity checks for OCSP, host checks, or X.509 will be performed. */ -int s2n_x509_validator_init_no_x509_validation(struct s2n_x509_validator *validator); - -/** Initialize the validator in safe mode. Will use trust store to validate x.509 certificates, ocsp responses, and will call - * the verify host callback to determine if a subject name or alternative name from the cert should be trusted. - * Returns 0 on success, and an S2N_ERR_* on failure. - */ -int s2n_x509_validator_init(struct s2n_x509_validator *validator, struct s2n_x509_trust_store *trust_store, uint8_t check_ocsp); - -/** - * Sets the maximum depth for a cert chain that can be used at validation. - */ -int s2n_x509_validator_set_max_chain_depth(struct s2n_x509_validator *validator, uint16_t max_depth); - -/** Cleans up underlying memory and data members. Struct can be reused afterwards. */ -void s2n_x509_validator_wipe(struct s2n_x509_validator *validator); - -/** - * Validates a certificate chain against the configured trust store in safe mode. In unsafe mode, it will find the public key - * and return it but not validate the certificates. Alternative Names and Subject Name will be passed to the host verification callback. - * The verification callback will be possibly called multiple times depending on how many names are found. - * If any of those calls return TRUE, that stage of the validation will continue, otherwise once all names are tried and none matched as - * trusted, the chain will be considered UNTRUSTED. - * - * This function can only be called once per instance of an s2n_x509_validator. If must be called prior to calling - * s2n_x509_validator_validate_cert_stapled_ocsp_response(). - */ -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); - -/** - * Validates an ocsp response against the most recent certificate chain. Also verifies the timestamps on the response. This function can only be - * called once per instance of an s2n_x509_validator and only after a successful call to s2n_x509_validator_validate_cert_chain(). - */ -s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(struct s2n_x509_validator *validator, struct s2n_connection *conn, - const uint8_t *ocsp_response, uint32_t size); - -/** - * Validates that each certificate in a peer's cert chain contains only signature algorithms in a security policy's - * certificate_signatures_preference list. - */ -S2N_RESULT s2n_validate_certificate_signature(struct s2n_connection *conn, X509 *x509_cert); - -/* Checks to see if a certificate has a signature algorithm that's in our certificate_signature_preferences list */ -S2N_RESULT s2n_validate_sig_scheme_supported(struct s2n_connection *conn, X509 *x509_cert, const struct s2n_signature_preferences *cert_sig_preferences); +/* + * 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_signature_scheme.h" + +#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 + * that would have to be there when they add support */ +#if (defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)) && !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) */ + +typedef enum { + S2N_CERT_OK = 0, + S2N_CERT_ERR_UNTRUSTED = -1, + S2N_CERT_ERR_REVOKED = -2, + 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_validation_code; + +/** 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; + +/** + * Trust store simply contains the trust store each connection should validate certs against. + * For most use cases, you only need one of these per application. + */ +struct s2n_x509_trust_store { + X509_STORE *trust_store; +}; + +/** + * You should have one instance of this per connection. + */ +struct s2n_x509_validator { + struct s2n_x509_trust_store *trust_store; + X509_STORE_CTX *store_ctx; + uint8_t skip_cert_validation; + uint8_t check_stapled_ocsp; + uint16_t max_chain_depth; + STACK_OF(X509) *cert_chain_from_wire; + int state; +}; + +/** Some libcrypto implementations do not support OCSP validation. Returns 1 if supported, 0 otherwise. */ +uint8_t s2n_x509_ocsp_stapling_supported(void); + +/** Initialize the trust store to empty defaults (no allocations happen here) */ +void s2n_x509_trust_store_init_empty(struct s2n_x509_trust_store *store); + +/** Returns TRUE if the trust store has certificates installed, FALSE otherwise */ +uint8_t s2n_x509_trust_store_has_certs(struct s2n_x509_trust_store *store); + +/** Initializes the trust store to default system paths **/ +int s2n_x509_trust_store_from_system_defaults(struct s2n_x509_trust_store *store); + +/** Initialize trust store from a PEM. This will allocate memory, and load PEM into the Trust Store **/ +int s2n_x509_trust_store_add_pem(struct s2n_x509_trust_store *store, const char *pem); + +/** Initialize trust store from a CA file. This will allocate memory, and load each cert in the file into the trust store + * Returns 0 on success, or S2N error codes on failure. */ +int s2n_x509_trust_store_from_ca_file(struct s2n_x509_trust_store *store, const char *ca_pem_filename, const char *ca_dir); + +/** Cleans up, and frees any underlying memory in the trust store. */ +void s2n_x509_trust_store_wipe(struct s2n_x509_trust_store *store); + +/** Initialize the validator in unsafe mode. No validity checks for OCSP, host checks, or X.509 will be performed. */ +int s2n_x509_validator_init_no_x509_validation(struct s2n_x509_validator *validator); + +/** Initialize the validator in safe mode. Will use trust store to validate x.509 certificates, ocsp responses, and will call + * the verify host callback to determine if a subject name or alternative name from the cert should be trusted. + * Returns 0 on success, and an S2N_ERR_* on failure. + */ +int s2n_x509_validator_init(struct s2n_x509_validator *validator, struct s2n_x509_trust_store *trust_store, uint8_t check_ocsp); + +/** + * Sets the maximum depth for a cert chain that can be used at validation. + */ +int s2n_x509_validator_set_max_chain_depth(struct s2n_x509_validator *validator, uint16_t max_depth); + +/** Cleans up underlying memory and data members. Struct can be reused afterwards. */ +void s2n_x509_validator_wipe(struct s2n_x509_validator *validator); + +/** + * Validates a certificate chain against the configured trust store in safe mode. In unsafe mode, it will find the public key + * and return it but not validate the certificates. Alternative Names and Subject Name will be passed to the host verification callback. + * The verification callback will be possibly called multiple times depending on how many names are found. + * If any of those calls return TRUE, that stage of the validation will continue, otherwise once all names are tried and none matched as + * trusted, the chain will be considered UNTRUSTED. + * + * This function can only be called once per instance of an s2n_x509_validator. If must be called prior to calling + * s2n_x509_validator_validate_cert_stapled_ocsp_response(). + */ +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); + +/** + * Validates an ocsp response against the most recent certificate chain. Also verifies the timestamps on the response. This function can only be + * called once per instance of an s2n_x509_validator and only after a successful call to s2n_x509_validator_validate_cert_chain(). + */ +s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(struct s2n_x509_validator *validator, struct s2n_connection *conn, + const uint8_t *ocsp_response, uint32_t size); + +/** + * Validates that each certificate in a peer's cert chain contains only signature algorithms in a security policy's + * certificate_signatures_preference list. + */ +S2N_RESULT s2n_validate_certificate_signature(struct s2n_connection *conn, X509 *x509_cert); + +/* Checks to see if a certificate has a signature algorithm that's in our certificate_signature_preferences list */ +S2N_RESULT s2n_validate_sig_scheme_supported(struct s2n_connection *conn, X509 *x509_cert, const struct s2n_signature_preferences *cert_sig_preferences); |