Skip to content

Commit

Permalink
move tests to separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
goatgoose committed Sep 20, 2023
1 parent 7421bd8 commit 9a74e1c
Show file tree
Hide file tree
Showing 2 changed files with 295 additions and 259 deletions.
295 changes: 295 additions & 0 deletions tests/unit/s2n_client_hello_get_supported_groups_test.c
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();
}
Loading

0 comments on commit 9a74e1c

Please sign in to comment.