forked from aws/s2n-tls
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
295 additions
and
259 deletions.
There are no files selected for viewing
295 changes: 295 additions & 0 deletions
295
tests/unit/s2n_client_hello_get_supported_groups_test.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} |
Oops, something went wrong.