From 86b6730fe9f25de991587a8a67ebc3367cd4ad6b Mon Sep 17 00:00:00 2001 From: Lindsay Stewart Date: Wed, 17 Apr 2024 13:20:05 -0700 Subject: [PATCH] feat: add basic support for certificate_authorities (#4506) --- tests/unit/s2n_cert_authorities_test.c | 215 ++++++++++++++++++++++ tests/unit/s2n_server_cert_request_test.c | 78 +++++++- tls/extensions/s2n_cert_authorities.c | 54 ++++++ tls/extensions/s2n_cert_authorities.h | 24 +++ tls/extensions/s2n_extension_list.h | 2 +- tls/extensions/s2n_extension_type.h | 1 + tls/extensions/s2n_extension_type_lists.c | 12 ++ tls/s2n_config.c | 1 + tls/s2n_config.h | 3 + tls/s2n_server_cert_request.c | 9 +- 10 files changed, 390 insertions(+), 9 deletions(-) create mode 100644 tests/unit/s2n_cert_authorities_test.c create mode 100644 tls/extensions/s2n_cert_authorities.c create mode 100644 tls/extensions/s2n_cert_authorities.h diff --git a/tests/unit/s2n_cert_authorities_test.c b/tests/unit/s2n_cert_authorities_test.c new file mode 100644 index 00000000000..a2a553c44fb --- /dev/null +++ b/tests/unit/s2n_cert_authorities_test.c @@ -0,0 +1,215 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT 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_cert_authorities.h" + +#include "crypto/s2n_rsa_pss.h" +#include "s2n_test.h" +#include "testlib/s2n_testlib.h" +#include "tls/s2n_tls.h" +#include "utils/s2n_bitmap.h" + +int s2n_parse_client_hello(struct s2n_connection *conn); + +int main(int argc, char **argv) +{ + BEGIN_TEST(); + + DEFER_CLEANUP(struct s2n_cert_chain_and_key *cert_chain = NULL, + s2n_cert_chain_and_key_ptr_free); + EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&cert_chain, + S2N_DEFAULT_ECDSA_TEST_CERT_CHAIN, S2N_DEFAULT_ECDSA_TEST_PRIVATE_KEY)); + + s2n_extension_type_id temp_id = s2n_unsupported_extension; + EXPECT_SUCCESS(s2n_extension_supported_iana_value_to_id( + s2n_cert_authorities_extension.iana_value, &temp_id)); + const s2n_extension_type_id ca_ext_id = temp_id; + + /* Test: s2n_certificate_authorities_extension.send */ + { + /* Test: writes whatever CA data is available */ + { + const uint8_t ca_data[] = "these are my CAs"; + + DEFER_CLEANUP(struct s2n_config *config = s2n_config_new_minimal(), s2n_config_ptr_free); + EXPECT_SUCCESS(s2n_alloc(&config->cert_authorities, sizeof(ca_data))); + EXPECT_MEMCPY_SUCCESS(config->cert_authorities.data, ca_data, sizeof(ca_data)); + + DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER), + s2n_connection_ptr_free); + EXPECT_SUCCESS(s2n_connection_set_config(conn, config)); + conn->actual_protocol_version = S2N_TLS13; + + DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free); + EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0)); + + EXPECT_SUCCESS(s2n_cert_authorities_extension.send(conn, &output)); + + uint16_t size = 0; + EXPECT_SUCCESS(s2n_stuffer_read_uint16(&output, &size)); + EXPECT_EQUAL(size, sizeof(ca_data)); + EXPECT_EQUAL(size, s2n_stuffer_data_available(&output)); + + uint8_t *data = s2n_stuffer_raw_read(&output, size); + EXPECT_NOT_NULL(data); + EXPECT_BYTEARRAY_EQUAL(data, ca_data, sizeof(ca_data)); + }; + }; + + /* Test: s2n_certificate_authorities_extension.should_send */ + { + /* Test: do not send for TLS1.2 */ + { + DEFER_CLEANUP(struct s2n_config *config = s2n_config_new_minimal(), s2n_config_ptr_free); + EXPECT_SUCCESS(s2n_alloc(&config->cert_authorities, 10)); + + DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER), + s2n_connection_ptr_free); + EXPECT_SUCCESS(s2n_connection_set_config(conn, config)); + + DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free); + EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0)); + + conn->actual_protocol_version = S2N_TLS12; + EXPECT_SUCCESS(s2n_extension_send(&s2n_cert_authorities_extension, + conn, &output)); + EXPECT_EQUAL(s2n_stuffer_data_available(&output), 0); + + conn->actual_protocol_version = S2N_TLS13; + EXPECT_SUCCESS(s2n_extension_send(&s2n_cert_authorities_extension, + conn, &output)); + EXPECT_NOT_EQUAL(s2n_stuffer_data_available(&output), 0); + }; + + /* Test: do not send if no CA data set */ + { + DEFER_CLEANUP(struct s2n_config *config = s2n_config_new_minimal(), s2n_config_ptr_free); + + DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER), + s2n_connection_ptr_free); + EXPECT_SUCCESS(s2n_connection_set_config(conn, config)); + + EXPECT_FALSE(s2n_cert_authorities_extension.should_send(conn)); + + EXPECT_SUCCESS(s2n_alloc(&config->cert_authorities, 10)); + EXPECT_TRUE(s2n_cert_authorities_extension.should_send(conn)); + + EXPECT_SUCCESS(s2n_free(&config->cert_authorities)); + EXPECT_FALSE(s2n_cert_authorities_extension.should_send(conn)); + }; + }; + + /* Test: ClientHello extension ignored + * + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.4 + *= type=test + *# The client MAY send the "certificate_authorities" extension in the + *# ClientHello message. + */ + if (s2n_is_tls13_fully_supported()) { + DEFER_CLEANUP(struct s2n_config *config = s2n_config_new_minimal(), s2n_config_ptr_free); + EXPECT_SUCCESS(s2n_config_set_unsafe_for_testing(config)); + EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(config, cert_chain)); + EXPECT_SUCCESS(s2n_config_set_cipher_preferences(config, "default_tls13")); + EXPECT_SUCCESS(s2n_alloc(&config->cert_authorities, 10)); + + DEFER_CLEANUP(struct s2n_connection *client = s2n_connection_new(S2N_CLIENT), + s2n_connection_ptr_free); + EXPECT_SUCCESS(s2n_connection_set_config(client, config)); + EXPECT_SUCCESS(s2n_client_hello_send(client)); + EXPECT_SUCCESS(s2n_parse_client_hello(client)); + struct s2n_client_hello *client_hello = &client->client_hello; + + DEFER_CLEANUP(struct s2n_connection *server = s2n_connection_new(S2N_SERVER), + s2n_connection_ptr_free); + EXPECT_SUCCESS(s2n_connection_set_config(server, config)); + struct s2n_stuffer *input = &server->handshake.io; + + /* Copy ClientHello, except extensions */ + size_t size_without_extensions = client_hello->raw_message.size + - client_hello->extensions.raw.size + - sizeof(uint16_t) /* Extensions size */; + EXPECT_SUCCESS(s2n_stuffer_write_bytes(input, + client_hello->raw_message.data, size_without_extensions)); + + /* Save space for new extensions size */ + struct s2n_stuffer_reservation extensions_size = { 0 }; + EXPECT_SUCCESS(s2n_stuffer_reserve_uint16(input, &extensions_size)); + + /* Write the certificate_authorities extension. + * The client isn't allowed to write it, so use the server. + */ + server->actual_protocol_version = S2N_TLS13; + EXPECT_SUCCESS(s2n_extension_send(&s2n_cert_authorities_extension, + server, input)); + + /* Write the rest of the extensions */ + EXPECT_SUCCESS(s2n_stuffer_write(input, &client_hello->extensions.raw)); + + /* Update the extensions size */ + EXPECT_SUCCESS(s2n_stuffer_write_vector_size(&extensions_size)); + + /* Server should be able to successfully receive the modified ClientHello */ + EXPECT_SUCCESS(s2n_client_hello_recv(server)); + EXPECT_TRUE(server->client_hello.parsed); + EXPECT_EQUAL(server->actual_protocol_version, S2N_TLS13); + + s2n_parsed_extension *extension = &server->client_hello.extensions.parsed_extensions[ca_ext_id]; + EXPECT_TRUE(extension->extension.size > 0); + EXPECT_FALSE(extension->processed); + EXPECT_EQUAL(extension->extension_type, s2n_cert_authorities_extension.iana_value); + }; + + /* Self-talk test: CertificateRequest extension parsed + * + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.4 + *= type=test + *# The server MAY send it in the CertificateRequest message. + **/ + if (s2n_is_tls13_fully_supported()) { + DEFER_CLEANUP(struct s2n_config *config = s2n_config_new_minimal(), s2n_config_ptr_free); + EXPECT_SUCCESS(s2n_config_set_unsafe_for_testing(config)); + EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(config, cert_chain)); + EXPECT_SUCCESS(s2n_config_set_cipher_preferences(config, "default_tls13")); + EXPECT_SUCCESS(s2n_config_set_client_auth_type(config, S2N_CERT_AUTH_OPTIONAL)); + EXPECT_SUCCESS(s2n_alloc(&config->cert_authorities, 10)); + + DEFER_CLEANUP(struct s2n_connection *client = s2n_connection_new(S2N_CLIENT), + s2n_connection_ptr_free); + EXPECT_SUCCESS(s2n_connection_set_config(client, config)); + + DEFER_CLEANUP(struct s2n_connection *server = s2n_connection_new(S2N_SERVER), + s2n_connection_ptr_free); + EXPECT_SUCCESS(s2n_connection_set_config(server, config)); + + DEFER_CLEANUP(struct s2n_test_io_pair io_pair = { 0 }, s2n_io_pair_close); + EXPECT_SUCCESS(s2n_io_pair_init_non_blocking(&io_pair)); + EXPECT_SUCCESS(s2n_connections_set_io_pair(client, server, &io_pair)); + + EXPECT_SUCCESS(s2n_negotiate_test_server_and_client(server, client)); + EXPECT_EQUAL(server->actual_protocol_version, S2N_TLS13); + EXPECT_TRUE(IS_CLIENT_AUTH_HANDSHAKE(server)); + + /* Server sent extension */ + EXPECT_TRUE(S2N_CBIT_TEST(server->extension_requests_sent, ca_ext_id)); + EXPECT_FALSE(S2N_CBIT_TEST(server->extension_requests_received, ca_ext_id)); + + /* Client received extension */ + EXPECT_FALSE(S2N_CBIT_TEST(client->extension_requests_sent, ca_ext_id)); + EXPECT_TRUE(S2N_CBIT_TEST(client->extension_requests_received, ca_ext_id)); + }; + + END_TEST(); +} diff --git a/tests/unit/s2n_server_cert_request_test.c b/tests/unit/s2n_server_cert_request_test.c index 828eddfceb5..fbdd6392c92 100644 --- a/tests/unit/s2n_server_cert_request_test.c +++ b/tests/unit/s2n_server_cert_request_test.c @@ -60,7 +60,7 @@ int main(int argc, char **argv) EXPECT_NOT_NULL(server_conn = s2n_connection_new(S2N_SERVER)); EXPECT_SUCCESS(s2n_connection_set_config(server_conn, server_config)); - s2n_cert_req_send(server_conn); + EXPECT_SUCCESS(s2n_cert_req_send(server_conn)); struct s2n_stuffer *in = &server_conn->handshake.io; uint8_t cert_types_len = 0; @@ -88,7 +88,7 @@ int main(int argc, char **argv) EXPECT_SUCCESS(s2n_connection_set_config(server_conn, server_config)); EXPECT_SUCCESS(s2n_config_enable_cert_req_dss_legacy_compat(server_config)); - s2n_cert_req_send(server_conn); + EXPECT_SUCCESS(s2n_cert_req_send(server_conn)); struct s2n_stuffer *in = &server_conn->handshake.io; uint8_t cert_types_len = 0; @@ -105,6 +105,78 @@ int main(int argc, char **argv) EXPECT_SUCCESS(s2n_connection_free(server_conn)); }; + /* Test: certificate_authorities supported */ + { + /* Test: no cert_authorities sent by default */ + { + DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER), + s2n_connection_ptr_free); + EXPECT_NOT_NULL(conn); + conn->actual_protocol_version = S2N_TLS12; + + DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), + s2n_config_ptr_free); + EXPECT_NOT_NULL(config); + EXPECT_SUCCESS(s2n_connection_set_config(conn, config)); + + EXPECT_SUCCESS(s2n_cert_req_send(conn)); + struct s2n_stuffer *output = &conn->handshake.io; + + uint8_t cert_types_len = 0; + EXPECT_SUCCESS(s2n_stuffer_read_uint8(output, &cert_types_len)); + EXPECT_TRUE(cert_types_len > 0); + EXPECT_SUCCESS(s2n_stuffer_skip_read(output, cert_types_len)); + + uint16_t sig_algs_len = 0; + EXPECT_SUCCESS(s2n_stuffer_read_uint16(output, &sig_algs_len)); + EXPECT_TRUE(sig_algs_len > 0); + EXPECT_SUCCESS(s2n_stuffer_skip_read(output, sig_algs_len)); + + uint16_t cert_authorities_len = 0; + EXPECT_SUCCESS(s2n_stuffer_read_uint16(output, &cert_authorities_len)); + EXPECT_EQUAL(cert_authorities_len, 0); + + EXPECT_EQUAL(s2n_stuffer_data_available(output), 0); + }; + + /* Test: cert_authorities sent if configured */ + { + DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER), + s2n_connection_ptr_free); + EXPECT_NOT_NULL(conn); + + DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), + s2n_config_ptr_free); + EXPECT_NOT_NULL(config); + EXPECT_SUCCESS(s2n_connection_set_config(conn, config)); + + /* If we use TLS1.1 instead of TLS1.2, we don't need to worry about + * skipping the signature algorithms. + */ + conn->actual_protocol_version = S2N_TLS11; + + const uint8_t ca_data[] = "these are my CAs"; + EXPECT_SUCCESS(s2n_alloc(&config->cert_authorities, sizeof(ca_data))); + EXPECT_MEMCPY_SUCCESS(config->cert_authorities.data, ca_data, sizeof(ca_data)); + + EXPECT_SUCCESS(s2n_cert_req_send(conn)); + struct s2n_stuffer *output = &conn->handshake.io; + + uint8_t cert_types_len = 0; + EXPECT_SUCCESS(s2n_stuffer_read_uint8(output, &cert_types_len)); + EXPECT_SUCCESS(s2n_stuffer_skip_read(output, cert_types_len)); + + uint16_t cert_authorities_len = 0; + EXPECT_SUCCESS(s2n_stuffer_read_uint16(output, &cert_authorities_len)); + EXPECT_EQUAL(cert_authorities_len, sizeof(ca_data)); + + uint8_t *cert_authorities_data = s2n_stuffer_raw_read(output, cert_authorities_len); + EXPECT_NOT_NULL(cert_authorities_data); + EXPECT_BYTEARRAY_EQUAL(cert_authorities_data, ca_data, sizeof(ca_data)); + + EXPECT_EQUAL(s2n_stuffer_data_available(output), 0); + }; + }; + END_TEST(); - return 0; } diff --git a/tls/extensions/s2n_cert_authorities.c b/tls/extensions/s2n_cert_authorities.c new file mode 100644 index 00000000000..1043dfe89ee --- /dev/null +++ b/tls/extensions/s2n_cert_authorities.c @@ -0,0 +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. + */ +#include "tls/extensions/s2n_cert_authorities.h" + +#include "utils/s2n_safety.h" + +int s2n_cert_authorities_send(struct s2n_connection *conn, struct s2n_stuffer *out) +{ + POSIX_ENSURE_REF(conn); + POSIX_ENSURE_REF(conn->config); + POSIX_ENSURE_EQ(conn->mode, S2N_SERVER); + struct s2n_blob *cert_authorities = &conn->config->cert_authorities; + POSIX_GUARD(s2n_stuffer_write_uint16(out, cert_authorities->size)); + POSIX_GUARD(s2n_stuffer_write(out, cert_authorities)); + return S2N_SUCCESS; +} + +static bool s2n_cert_authorities_should_send(struct s2n_connection *conn) +{ + return conn && conn->config && conn->config->cert_authorities.size > 0; +} + +const s2n_extension_type s2n_cert_authorities_extension = { + .iana_value = TLS_EXTENSION_CERT_AUTHORITIES, + .minimum_version = S2N_TLS13, + .is_response = false, + .send = s2n_cert_authorities_send, + .should_send = s2n_cert_authorities_should_send, + /* s2n-tls supports sending the extension, but does not support parsing it. + * If received, the extension is ignored. + * + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.4 + *= type=exception + *= reason=Extension ignored when received - No customer use case + *# The "certificate_authorities" extension is used to indicate the + *# certificate authorities (CAs) which an endpoint supports and which + *# SHOULD be used by the receiving endpoint to guide certificate + *# selection. + */ + .recv = s2n_extension_recv_noop, + .if_missing = s2n_extension_noop_if_missing, +}; diff --git a/tls/extensions/s2n_cert_authorities.h b/tls/extensions/s2n_cert_authorities.h new file mode 100644 index 00000000000..6821b1ad99a --- /dev/null +++ b/tls/extensions/s2n_cert_authorities.h @@ -0,0 +1,24 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT 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" +#include "tls/s2n_connection.h" + +extern const s2n_extension_type s2n_cert_authorities_extension; + +int s2n_cert_authorities_send(struct s2n_connection *conn, struct s2n_stuffer *out); diff --git a/tls/extensions/s2n_extension_list.h b/tls/extensions/s2n_extension_list.h index 411c7e4d7cc..ddc1a6be430 100644 --- a/tls/extensions/s2n_extension_list.h +++ b/tls/extensions/s2n_extension_list.h @@ -21,8 +21,8 @@ #define S2N_PARSED_EXTENSIONS_COUNT S2N_SUPPORTED_EXTENSIONS_COUNT typedef struct { - uint16_t extension_type; struct s2n_blob extension; + uint16_t extension_type; uint16_t wire_index; unsigned processed : 1; } s2n_parsed_extension; diff --git a/tls/extensions/s2n_extension_type.h b/tls/extensions/s2n_extension_type.h index a4fd08db501..b1c1ef9f940 100644 --- a/tls/extensions/s2n_extension_type.h +++ b/tls/extensions/s2n_extension_type.h @@ -68,6 +68,7 @@ static const uint16_t s2n_supported_extensions[] = { TLS_EXTENSION_EARLY_DATA, TLS_EXTENSION_EMS, TLS_EXTENSION_NPN, + TLS_EXTENSION_CERT_AUTHORITIES, }; typedef char s2n_extension_bitfield[S2N_SUPPORTED_EXTENSIONS_BITFIELD_LEN]; diff --git a/tls/extensions/s2n_extension_type_lists.c b/tls/extensions/s2n_extension_type_lists.c index 3e2a607fd35..849d626acee 100644 --- a/tls/extensions/s2n_extension_type_lists.c +++ b/tls/extensions/s2n_extension_type_lists.c @@ -16,6 +16,7 @@ #include "tls/extensions/s2n_extension_type_lists.h" #include "api/s2n.h" +#include "tls/extensions/s2n_cert_authorities.h" #include "tls/extensions/s2n_cert_status.h" #include "tls/extensions/s2n_cert_status_response.h" #include "tls/extensions/s2n_client_alpn.h" @@ -131,6 +132,17 @@ static const s2n_extension_type *const encrypted_extensions[] = { static const s2n_extension_type *const cert_req_extensions[] = { &s2n_server_signature_algorithms_extension, &s2n_server_cert_status_request_extension, + /** + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.4 + *= type=exception + *= reason=Currently only supported for servers -- no client use case + *# The client MAY send the "certificate_authorities" extension in the + *# ClientHello message. + * + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.4 + *# The server MAY send it in the CertificateRequest message. + */ + &s2n_cert_authorities_extension, }; static const s2n_extension_type *const certificate_extensions[] = { diff --git a/tls/s2n_config.c b/tls/s2n_config.c index f3674c23310..b595a52c3e3 100644 --- a/tls/s2n_config.c +++ b/tls/s2n_config.c @@ -124,6 +124,7 @@ static int s2n_config_cleanup(struct s2n_config *config) POSIX_GUARD(s2n_config_free_cert_chain_and_key(config)); POSIX_GUARD(s2n_config_free_dhparams(config)); POSIX_GUARD(s2n_free(&config->application_protocols)); + POSIX_GUARD(s2n_free(&config->cert_authorities)); POSIX_GUARD_RESULT(s2n_map_free(config->domain_name_to_cert_map)); POSIX_CHECKED_MEMSET(config, 0, sizeof(struct s2n_config)); diff --git a/tls/s2n_config.h b/tls/s2n_config.h index b2dc2c0ea17..714c8a2328b 100644 --- a/tls/s2n_config.h +++ b/tls/s2n_config.h @@ -225,6 +225,9 @@ struct s2n_config { * the new feature to their entire fleet.) */ s2n_serialization_version serialized_connection_version; + + /* List of certificate authorities supported */ + struct s2n_blob cert_authorities; }; S2N_CLEANUP_RESULT s2n_config_ptr_free(struct s2n_config **config); diff --git a/tls/s2n_server_cert_request.c b/tls/s2n_server_cert_request.c index 79929a32cda..ad36af6dd54 100644 --- a/tls/s2n_server_cert_request.c +++ b/tls/s2n_server_cert_request.c @@ -16,6 +16,7 @@ #include "api/s2n.h" #include "crypto/s2n_certificate.h" #include "error/s2n_errno.h" +#include "extensions/s2n_cert_authorities.h" #include "extensions/s2n_extension_list.h" #include "stuffer/s2n_stuffer.h" #include "tls/s2n_cipher_suites.h" @@ -174,10 +175,8 @@ int s2n_cert_req_send(struct s2n_connection *conn) POSIX_GUARD_RESULT(s2n_signature_algorithms_supported_list_send(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; - POSIX_GUARD(s2n_stuffer_write_uint16(out, acceptable_cert_authorities_len)); + /* Before TLS1.3, certificate_authorities is part of the message instead of an extension */ + POSIX_GUARD(s2n_cert_authorities_send(conn, out)); - return 0; + return S2N_SUCCESS; }