diff --git a/tests/unit/s2n_client_hello_get_supported_groups_test.c b/tests/unit/s2n_client_hello_get_supported_groups_test.c new file mode 100644 index 00000000000..c08483c983c --- /dev/null +++ b/tests/unit/s2n_client_hello_get_supported_groups_test.c @@ -0,0 +1,295 @@ +/* +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"). +* You may not use this file except in compliance with the License. +* A copy of the License is located at +* +* http://aws.amazon.com/apache2.0 +* +* or in the "license" file accompanying this file. This file is distributed +* on an "AS IS" BASIS, WITHOUT 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_test.h" +#include "testlib/s2n_testlib.h" +#include "tls/extensions/s2n_client_supported_groups.h" +#include "tls/s2n_client_hello.h" +#include "tls/s2n_tls.h" +#include "utils/s2n_random.h" + +#define TEST_SUPPORTED_GROUPS_LIST_COUNT S2N_RECEIVED_SUPPORTED_GROUPS_MAX + +/* Each supported group is 2 bytes. */ +#define TEST_SUPPORTED_GROUPS_LIST_SIZE (TEST_SUPPORTED_GROUPS_LIST_COUNT * 2) + +/* 2 length bytes + space for the maximum number of supported groups. */ +#define TEST_SUPPORTED_GROUPS_EXTENSION_SIZE (2 + TEST_SUPPORTED_GROUPS_LIST_SIZE) + +int main(int argc, char **argv) +{ + BEGIN_TEST(); + + DEFER_CLEANUP(struct s2n_cert_chain_and_key *chain_and_key = NULL, s2n_cert_chain_and_key_ptr_free); + EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&chain_and_key, + S2N_DEFAULT_TEST_CERT_CHAIN, S2N_DEFAULT_TEST_PRIVATE_KEY)); + + /* Safety */ + { + struct s2n_client_hello client_hello = { 0 }; + uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; + uint16_t supported_groups_count = 0; + + EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(NULL, supported_groups, &supported_groups_count, + S2N_RECEIVED_SUPPORTED_GROUPS_MAX), + S2N_ERR_NULL); + EXPECT_EQUAL(supported_groups_count, 0); + + EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(&client_hello, NULL, &supported_groups_count, + S2N_RECEIVED_SUPPORTED_GROUPS_MAX), + S2N_ERR_NULL); + EXPECT_EQUAL(supported_groups_count, 0); + + EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, NULL, + S2N_RECEIVED_SUPPORTED_GROUPS_MAX), + S2N_ERR_NULL); + EXPECT_EQUAL(supported_groups_count, 0); + } + + /* Ensure that the maximum size of the provided supported groups list is respected. */ + { + struct s2n_client_hello client_hello = { 0 }; + + s2n_extension_type_id supported_groups_id = 0; + EXPECT_SUCCESS(s2n_extension_supported_iana_value_to_id(S2N_EXTENSION_SUPPORTED_GROUPS, &supported_groups_id)); + + uint8_t extension_data[TEST_SUPPORTED_GROUPS_EXTENSION_SIZE] = { 0 }; + struct s2n_blob extension_blob = { 0 }; + EXPECT_SUCCESS(s2n_blob_init(&extension_blob, extension_data, sizeof(extension_data))); + + s2n_parsed_extension *supported_groups_extension = &client_hello.extensions.parsed_extensions[supported_groups_id]; + supported_groups_extension->extension_type = S2N_EXTENSION_SUPPORTED_GROUPS; + supported_groups_extension->extension = extension_blob; + + struct s2n_stuffer extension_stuffer = { 0 }; + EXPECT_SUCCESS(s2n_stuffer_init(&extension_stuffer, &extension_blob)); + + EXPECT_SUCCESS(s2n_stuffer_write_uint16(&extension_stuffer, TEST_SUPPORTED_GROUPS_LIST_SIZE)); + + uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; + uint16_t supported_groups_count = 0; + + /* s2n_client_hello_get_supported_groups should fail if the provided buffer is too + * small. + */ + EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, + &supported_groups_count, TEST_SUPPORTED_GROUPS_LIST_COUNT - 1), + S2N_ERR_SAFETY); + EXPECT_EQUAL(supported_groups_count, 0); + + EXPECT_SUCCESS(s2n_stuffer_reread(&extension_stuffer)); + + /* s2n_client_hello_get_supported_groups should succeed with a correctly sized buffer. */ + EXPECT_SUCCESS(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, &supported_groups_count, + S2N_RECEIVED_SUPPORTED_GROUPS_MAX)); + EXPECT_EQUAL(supported_groups_count, s2n_array_len(supported_groups)); + } + + /* Ensure that s2n_client_hello_get_supported_groups fails before the client hello is parsed. */ + { + + } + + /* Ensure that s2n_client_hello_get_supported_groups fails if a supported groups extension + * wasn't received. + */ + for (int disable_ecc = 0; disable_ecc <= 1; disable_ecc++) { + DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free); + EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(config, chain_and_key)); + if (disable_ecc) { + /* The 20150202 security policy doesn't contain any ECDHE cipher suites, so the + * supported groups extension won't be sent. + */ + EXPECT_SUCCESS(s2n_config_set_cipher_preferences(config, "20150202")); + } else { + /* The 20170210 security policy contains ECDHE cipher suites, so the supported + * groups extension will be sent. + */ + EXPECT_SUCCESS(s2n_config_set_cipher_preferences(config, "20170210")); + } + + 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)); + + EXPECT_SUCCESS(s2n_client_hello_send(client)); + EXPECT_SUCCESS(s2n_stuffer_copy(&client->handshake.io, &server->handshake.io, + s2n_stuffer_data_available(&client->handshake.io))); + EXPECT_SUCCESS(s2n_client_hello_recv(server)); + + struct s2n_client_hello *client_hello = s2n_connection_get_client_hello(server); + EXPECT_NOT_NULL(client_hello); + + bool supported_groups_extension_exists = false; + EXPECT_SUCCESS(s2n_client_hello_has_extension(client_hello, S2N_EXTENSION_SUPPORTED_GROUPS, + &supported_groups_extension_exists)); + EXPECT_EQUAL(supported_groups_extension_exists, !disable_ecc); + + uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; + uint16_t supported_groups_count = 0; + int ret = s2n_client_hello_get_supported_groups(client_hello, supported_groups, &supported_groups_count, + s2n_array_len(supported_groups)); + + if (disable_ecc) { + EXPECT_FAILURE_WITH_ERRNO(ret, S2N_ERR_NULL); + EXPECT_EQUAL(supported_groups_count, 0); + } else { + EXPECT_SUCCESS(ret); + + /* The 20170210 security policy contains 2 ECC curves. */ + EXPECT_EQUAL(supported_groups_count, 2); + } + } + + /* Test parsing a supported groups extension with a malformed groups list length. */ + { + struct s2n_client_hello client_hello = { 0 }; + + s2n_extension_type_id supported_groups_id = 0; + EXPECT_SUCCESS(s2n_extension_supported_iana_value_to_id(S2N_EXTENSION_SUPPORTED_GROUPS, &supported_groups_id)); + + s2n_parsed_extension *supported_groups_extension = &client_hello.extensions.parsed_extensions[supported_groups_id]; + supported_groups_extension->extension_type = S2N_EXTENSION_SUPPORTED_GROUPS; + + /* Test parsing a correct groups list length */ + { + uint8_t extension_data[TEST_SUPPORTED_GROUPS_EXTENSION_SIZE] = { 0 }; + struct s2n_blob extension_blob = { 0 }; + EXPECT_SUCCESS(s2n_blob_init(&extension_blob, extension_data, sizeof(extension_data))); + supported_groups_extension->extension = extension_blob; + + struct s2n_stuffer extension_stuffer = { 0 }; + EXPECT_SUCCESS(s2n_stuffer_init(&extension_stuffer, &extension_blob)); + + EXPECT_SUCCESS(s2n_stuffer_write_uint16(&extension_stuffer, TEST_SUPPORTED_GROUPS_LIST_SIZE)); + + uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; + uint16_t supported_groups_count = 0; + EXPECT_SUCCESS(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, + &supported_groups_count, s2n_array_len(supported_groups))); + + EXPECT_EQUAL(supported_groups_count, TEST_SUPPORTED_GROUPS_LIST_COUNT); + } + + /* Test parsing a groups list length that is larger than the extension length */ + { + uint8_t extension_data[TEST_SUPPORTED_GROUPS_EXTENSION_SIZE] = { 0 }; + struct s2n_blob extension_blob = { 0 }; + EXPECT_SUCCESS(s2n_blob_init(&extension_blob, extension_data, sizeof(extension_data))); + supported_groups_extension->extension = extension_blob; + + struct s2n_stuffer extension_stuffer = { 0 }; + EXPECT_SUCCESS(s2n_stuffer_init(&extension_stuffer, &extension_blob)); + + uint16_t too_many_groups_size = TEST_SUPPORTED_GROUPS_LIST_SIZE + 2; + EXPECT_SUCCESS(s2n_stuffer_write_uint16(&extension_stuffer, too_many_groups_size)); + + uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; + uint16_t supported_groups_count = 0; + EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, + &supported_groups_count, s2n_array_len(supported_groups)), + S2N_ERR_SAFETY); + + EXPECT_EQUAL(supported_groups_count, 0); + } + + /* Test parsing a groups list that contains a partial supported group */ + { + uint8_t extension_data[TEST_SUPPORTED_GROUPS_EXTENSION_SIZE] = { 0 }; + struct s2n_blob extension_blob = { 0 }; + EXPECT_SUCCESS(s2n_blob_init(&extension_blob, extension_data, sizeof(extension_data))); + supported_groups_extension->extension = extension_blob; + + struct s2n_stuffer extension_stuffer = { 0 }; + EXPECT_SUCCESS(s2n_stuffer_init(&extension_stuffer, &extension_blob)); + + uint16_t one_and_a_half_groups_size = 3; + EXPECT_SUCCESS(s2n_stuffer_write_uint16(&extension_stuffer, one_and_a_half_groups_size)); + + uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; + uint16_t supported_groups_count = 0; + EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, + &supported_groups_count, s2n_array_len(supported_groups)), + S2N_ERR_SAFETY); + + EXPECT_EQUAL(supported_groups_count, 0); + } + } + + /* Ensure that s2n_client_hello_get_supported_groups writes what is contained in the parsed + * supported groups extension in the client hello. + */ + { + struct s2n_client_hello client_hello = { 0 }; + + s2n_extension_type_id supported_groups_id = 0; + EXPECT_SUCCESS(s2n_extension_supported_iana_value_to_id(S2N_EXTENSION_SUPPORTED_GROUPS, &supported_groups_id)); + + s2n_parsed_extension *supported_groups_extension = &client_hello.extensions.parsed_extensions[supported_groups_id]; + supported_groups_extension->extension_type = S2N_EXTENSION_SUPPORTED_GROUPS; + + for (uint16_t test_groups_count = 0; test_groups_count < S2N_RECEIVED_SUPPORTED_GROUPS_MAX; test_groups_count++) { + uint16_t test_groups_list_size = test_groups_count * 2; + + uint8_t test_groups_list_data[TEST_SUPPORTED_GROUPS_LIST_SIZE] = { 0 }; + struct s2n_blob test_groups_list_blob = { 0 }; + EXPECT_SUCCESS(s2n_blob_init(&test_groups_list_blob, test_groups_list_data, test_groups_list_size)); + EXPECT_OK(s2n_get_public_random_data(&test_groups_list_blob)); + + uint8_t extension_data[TEST_SUPPORTED_GROUPS_EXTENSION_SIZE] = { 0 }; + struct s2n_blob extension_blob = { 0 }; + EXPECT_SUCCESS(s2n_blob_init(&extension_blob, extension_data, sizeof(extension_data))); + supported_groups_extension->extension = extension_blob; + + struct s2n_stuffer extension_stuffer = { 0 }; + EXPECT_SUCCESS(s2n_stuffer_init(&extension_stuffer, &extension_blob)); + EXPECT_SUCCESS(s2n_stuffer_write_uint16(&extension_stuffer, test_groups_list_size)); + EXPECT_SUCCESS(s2n_stuffer_write(&extension_stuffer, &test_groups_list_blob)); + + uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; + uint16_t supported_groups_count = 0; + EXPECT_SUCCESS(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, + &supported_groups_count, s2n_array_len(supported_groups))); + EXPECT_EQUAL(supported_groups_count, test_groups_count); + + struct s2n_stuffer test_groups_list_stuffer = { 0 }; + EXPECT_SUCCESS(s2n_stuffer_init_written(&test_groups_list_stuffer, &test_groups_list_blob)); + + for (size_t i = 0; i < supported_groups_count; i++) { + uint16_t test_group = 0; + EXPECT_SUCCESS(s2n_stuffer_read_uint16(&test_groups_list_stuffer, &test_group)); + + uint16_t written_group = supported_groups[i]; + + EXPECT_EQUAL(test_group, written_group); + } + } + } + + /* Self-talk: Ensure that the retrieved supported groups match what was sent by the client. + * + * This test also ensures that s2n_client_hello_get_supported_groups is usable from within + * the client hello callback. + */ + { + + } + + END_TEST(); +} \ No newline at end of file diff --git a/tests/unit/s2n_client_hello_test.c b/tests/unit/s2n_client_hello_test.c index da160f5023d..4d150223e81 100644 --- a/tests/unit/s2n_client_hello_test.c +++ b/tests/unit/s2n_client_hello_test.c @@ -1632,265 +1632,6 @@ int main(int argc, char **argv) }; }; - /* s2n_client_hello_get_supported_groups tests */ - { -#define TEST_SUPPORTED_GROUPS_LIST_COUNT S2N_RECEIVED_SUPPORTED_GROUPS_MAX - - /* Each supported group is 2 bytes. */ -#define TEST_SUPPORTED_GROUPS_LIST_SIZE (TEST_SUPPORTED_GROUPS_LIST_COUNT * 2) - - /* 2 length bytes + space for the maximum number of supported groups. */ -#define TEST_SUPPORTED_GROUPS_EXTENSION_SIZE (2 + TEST_SUPPORTED_GROUPS_LIST_SIZE) - - /* Safety */ - { - struct s2n_client_hello client_hello = { 0 }; - uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; - uint16_t supported_groups_count = 0; - - EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(NULL, supported_groups, &supported_groups_count, - S2N_RECEIVED_SUPPORTED_GROUPS_MAX), - S2N_ERR_NULL); - EXPECT_EQUAL(supported_groups_count, 0); - - EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(&client_hello, NULL, &supported_groups_count, - S2N_RECEIVED_SUPPORTED_GROUPS_MAX), - S2N_ERR_NULL); - EXPECT_EQUAL(supported_groups_count, 0); - - EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, NULL, - S2N_RECEIVED_SUPPORTED_GROUPS_MAX), - S2N_ERR_NULL); - EXPECT_EQUAL(supported_groups_count, 0); - } - - /* Ensure that the maximum size of the provided supported groups list is respected. */ - { - struct s2n_client_hello client_hello = { 0 }; - - s2n_extension_type_id supported_groups_id = 0; - EXPECT_SUCCESS(s2n_extension_supported_iana_value_to_id(S2N_EXTENSION_SUPPORTED_GROUPS, &supported_groups_id)); - - uint8_t extension_data[TEST_SUPPORTED_GROUPS_EXTENSION_SIZE] = { 0 }; - struct s2n_blob extension_blob = { 0 }; - EXPECT_SUCCESS(s2n_blob_init(&extension_blob, extension_data, sizeof(extension_data))); - - s2n_parsed_extension *supported_groups_extension = &client_hello.extensions.parsed_extensions[supported_groups_id]; - supported_groups_extension->extension_type = S2N_EXTENSION_SUPPORTED_GROUPS; - supported_groups_extension->extension = extension_blob; - - struct s2n_stuffer extension_stuffer = { 0 }; - EXPECT_SUCCESS(s2n_stuffer_init(&extension_stuffer, &extension_blob)); - - EXPECT_SUCCESS(s2n_stuffer_write_uint16(&extension_stuffer, TEST_SUPPORTED_GROUPS_LIST_SIZE)); - - uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; - uint16_t supported_groups_count = 0; - - /* s2n_client_hello_get_supported_groups should fail if the provided buffer is too - * small. - */ - EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, - &supported_groups_count, TEST_SUPPORTED_GROUPS_LIST_COUNT - 1), - S2N_ERR_SAFETY); - EXPECT_EQUAL(supported_groups_count, 0); - - EXPECT_SUCCESS(s2n_stuffer_reread(&extension_stuffer)); - - /* s2n_client_hello_get_supported_groups should succeed with a correctly sized buffer. */ - EXPECT_SUCCESS(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, &supported_groups_count, - S2N_RECEIVED_SUPPORTED_GROUPS_MAX)); - EXPECT_EQUAL(supported_groups_count, s2n_array_len(supported_groups)); - } - - /* Ensure s2n_client_hello_get_supported_groups fails if a supported groups extension - * wasn't received. - */ - for (int disable_ecc = 0; disable_ecc <= 1; disable_ecc++) { - DEFER_CLEANUP(struct s2n_connection *client = s2n_connection_new(S2N_CLIENT), - s2n_connection_ptr_free); - - if (disable_ecc) { - /* The 20150202 security policy doesn't contain any ECDHE cipher suites, so the - * supported groups extension won't be sent. - */ - EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(client, "20150202")); - } else { - /* The 20170210 security policy contains ECDHE cipher suites, so the supported - * groups extension will be sent. - */ - EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(client, "20170210")); - } - - EXPECT_SUCCESS(s2n_handshake_write_header(&client->handshake.io, TLS_CLIENT_HELLO)); - EXPECT_SUCCESS(s2n_client_hello_send(client)); - EXPECT_SUCCESS(s2n_handshake_finish_header(&client->handshake.io)); - - uint32_t raw_size = s2n_stuffer_data_available(&client->handshake.io); - EXPECT_NOT_EQUAL(raw_size, 0); - uint8_t *raw = s2n_stuffer_raw_read(&client->handshake.io, raw_size); - EXPECT_NOT_NULL(raw); - - struct s2n_client_hello *client_hello = s2n_client_hello_parse_message( - raw, raw_size); - EXPECT_NOT_NULL(client_hello); - - bool supported_groups_extension_exists = false; - EXPECT_SUCCESS(s2n_client_hello_has_extension(client_hello, S2N_EXTENSION_SUPPORTED_GROUPS, - &supported_groups_extension_exists)); - EXPECT_EQUAL(supported_groups_extension_exists, !disable_ecc); - - uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; - uint16_t supported_groups_count = 0; - int ret = s2n_client_hello_get_supported_groups(client_hello, supported_groups, &supported_groups_count, - s2n_array_len(supported_groups)); - - if (disable_ecc) { - EXPECT_FAILURE_WITH_ERRNO(ret, S2N_ERR_NULL); - EXPECT_EQUAL(supported_groups_count, 0); - } else { - EXPECT_SUCCESS(ret); - - /* The 20170210 security policy contains 2 ECC curves. */ - EXPECT_EQUAL(supported_groups_count, 2); - } - } - - /* Test parsing a supported groups extension with a malformed groups list length. */ - { - struct s2n_client_hello client_hello = { 0 }; - - s2n_extension_type_id supported_groups_id = 0; - EXPECT_SUCCESS(s2n_extension_supported_iana_value_to_id(S2N_EXTENSION_SUPPORTED_GROUPS, &supported_groups_id)); - - s2n_parsed_extension *supported_groups_extension = &client_hello.extensions.parsed_extensions[supported_groups_id]; - supported_groups_extension->extension_type = S2N_EXTENSION_SUPPORTED_GROUPS; - - /* Test parsing a correct groups list length */ - { - uint8_t extension_data[TEST_SUPPORTED_GROUPS_EXTENSION_SIZE] = { 0 }; - struct s2n_blob extension_blob = { 0 }; - EXPECT_SUCCESS(s2n_blob_init(&extension_blob, extension_data, sizeof(extension_data))); - supported_groups_extension->extension = extension_blob; - - struct s2n_stuffer extension_stuffer = { 0 }; - EXPECT_SUCCESS(s2n_stuffer_init(&extension_stuffer, &extension_blob)); - - EXPECT_SUCCESS(s2n_stuffer_write_uint16(&extension_stuffer, TEST_SUPPORTED_GROUPS_LIST_SIZE)); - - uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; - uint16_t supported_groups_count = 0; - EXPECT_SUCCESS(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, - &supported_groups_count, s2n_array_len(supported_groups))); - - EXPECT_EQUAL(supported_groups_count, TEST_SUPPORTED_GROUPS_LIST_COUNT); - } - - /* Test parsing a groups list length that is larger than the extension length */ - { - uint8_t extension_data[TEST_SUPPORTED_GROUPS_EXTENSION_SIZE] = { 0 }; - struct s2n_blob extension_blob = { 0 }; - EXPECT_SUCCESS(s2n_blob_init(&extension_blob, extension_data, sizeof(extension_data))); - supported_groups_extension->extension = extension_blob; - - struct s2n_stuffer extension_stuffer = { 0 }; - EXPECT_SUCCESS(s2n_stuffer_init(&extension_stuffer, &extension_blob)); - - uint16_t too_many_groups_size = TEST_SUPPORTED_GROUPS_LIST_SIZE + 2; - EXPECT_SUCCESS(s2n_stuffer_write_uint16(&extension_stuffer, too_many_groups_size)); - - uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; - uint16_t supported_groups_count = 0; - EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, - &supported_groups_count, s2n_array_len(supported_groups)), - S2N_ERR_SAFETY); - - EXPECT_EQUAL(supported_groups_count, 0); - } - - /* Test parsing a groups list that contains a partial supported group */ - { - uint8_t extension_data[TEST_SUPPORTED_GROUPS_EXTENSION_SIZE] = { 0 }; - struct s2n_blob extension_blob = { 0 }; - EXPECT_SUCCESS(s2n_blob_init(&extension_blob, extension_data, sizeof(extension_data))); - supported_groups_extension->extension = extension_blob; - - struct s2n_stuffer extension_stuffer = { 0 }; - EXPECT_SUCCESS(s2n_stuffer_init(&extension_stuffer, &extension_blob)); - - uint16_t one_and_a_half_groups_size = 3; - EXPECT_SUCCESS(s2n_stuffer_write_uint16(&extension_stuffer, one_and_a_half_groups_size)); - - uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; - uint16_t supported_groups_count = 0; - EXPECT_FAILURE_WITH_ERRNO(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, - &supported_groups_count, s2n_array_len(supported_groups)), - S2N_ERR_SAFETY); - - EXPECT_EQUAL(supported_groups_count, 0); - } - } - - /* Ensure that s2n_client_hello_get_supported_groups writes what is contained in the parsed - * supported groups extension in the client hello. - */ - { - struct s2n_client_hello client_hello = { 0 }; - - s2n_extension_type_id supported_groups_id = 0; - EXPECT_SUCCESS(s2n_extension_supported_iana_value_to_id(S2N_EXTENSION_SUPPORTED_GROUPS, &supported_groups_id)); - - s2n_parsed_extension *supported_groups_extension = &client_hello.extensions.parsed_extensions[supported_groups_id]; - supported_groups_extension->extension_type = S2N_EXTENSION_SUPPORTED_GROUPS; - - for (uint16_t test_groups_count = 0; test_groups_count < S2N_RECEIVED_SUPPORTED_GROUPS_MAX; test_groups_count++) { - uint16_t test_groups_list_size = test_groups_count * 2; - - uint8_t test_groups_list_data[TEST_SUPPORTED_GROUPS_LIST_SIZE] = { 0 }; - struct s2n_blob test_groups_list_blob = { 0 }; - EXPECT_SUCCESS(s2n_blob_init(&test_groups_list_blob, test_groups_list_data, test_groups_list_size)); - EXPECT_OK(s2n_get_public_random_data(&test_groups_list_blob)); - - uint8_t extension_data[TEST_SUPPORTED_GROUPS_EXTENSION_SIZE] = { 0 }; - struct s2n_blob extension_blob = { 0 }; - EXPECT_SUCCESS(s2n_blob_init(&extension_blob, extension_data, sizeof(extension_data))); - supported_groups_extension->extension = extension_blob; - - struct s2n_stuffer extension_stuffer = { 0 }; - EXPECT_SUCCESS(s2n_stuffer_init(&extension_stuffer, &extension_blob)); - EXPECT_SUCCESS(s2n_stuffer_write_uint16(&extension_stuffer, test_groups_list_size)); - EXPECT_SUCCESS(s2n_stuffer_write(&extension_stuffer, &test_groups_list_blob)); - - uint16_t supported_groups[TEST_SUPPORTED_GROUPS_LIST_COUNT] = { 0 }; - uint16_t supported_groups_count = 0; - EXPECT_SUCCESS(s2n_client_hello_get_supported_groups(&client_hello, supported_groups, - &supported_groups_count, s2n_array_len(supported_groups))); - EXPECT_EQUAL(supported_groups_count, test_groups_count); - - struct s2n_stuffer test_groups_list_stuffer = { 0 }; - EXPECT_SUCCESS(s2n_stuffer_init_written(&test_groups_list_stuffer, &test_groups_list_blob)); - - for (size_t i = 0; i < supported_groups_count; i++) { - uint16_t test_group = 0; - EXPECT_SUCCESS(s2n_stuffer_read_uint16(&test_groups_list_stuffer, &test_group)); - - uint16_t written_group = supported_groups[i]; - - EXPECT_EQUAL(test_group, written_group); - } - } - } - - /* Self-talk: Ensure that the retrieved supported groups match what was sent by the client. - * - * This test also ensures that s2n_client_hello_get_supported_groups is usable from within - * the client hello callback. - */ - { - - } - } - EXPECT_SUCCESS(s2n_cert_chain_and_key_free(chain_and_key)); EXPECT_SUCCESS(s2n_cert_chain_and_key_free(ecdsa_chain_and_key)); END_TEST();