Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions tests/unit/s2n_client_hello_recv_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "tls/s2n_connection.h"
#include "tls/s2n_client_hello.h"

#include "utils/s2n_blob.h"
#include "utils/s2n_safety.h"

int main(int argc, char **argv)
Expand Down Expand Up @@ -375,6 +376,48 @@ int main(int argc, char **argv)
s2n_connection_free(server_conn);
}

/* Test that curve selection will be NIST P-256 when tls12 client does not sending curve extension. */
{
S2N_BLOB_FROM_HEX(tls12_client_hello_no_curves,
"030307de81928fe1" "7cba77904c2798da" "2521a76b013a16e4" "21ade32208f658d4" "327d000048000400"
"05000a0016002f00" "3300350039003c00" "3d0067006b009c00" "9d009e009fc009c0" "0ac011c012c013c0"
"14c023c024c027c0" "28c02bc02cc02fc0" "30cca8cca9ccaaff" "04ff0800ff010000" "30000d0016001404"
"0105010601030104" "0305030603030302" "010203000b000201" "00fe01000c000a00" "17000d0013000100"
"0a");

/* The above code is generated the following code,
disabling s2n_client_supported_groups_extension
from client_hello_extensions (s2n_extension_type_lists.c)
and exporting the resulting client_conn->handshake.io.blob

EXPECT_NOT_NULL(client_conn = s2n_connection_new(S2N_CLIENT));
EXPECT_SUCCESS(s2n_connection_set_config(client_conn, tls12_config));
EXPECT_SUCCESS(s2n_client_hello_send(client_conn));
EXPECT_EQUAL(client_conn->client_protocol_version, S2N_TLS12);
EXPECT_EQUAL(client_conn->client_hello_version, S2N_TLS12);
Comment on lines +393 to +397
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why store this as a blob instead of just executing it as part of the test? What's the benefit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not possible to execute the current test with code unless we can expose not sending supported_groups extension

s2n_connection_free(client_conn);
*/

EXPECT_SUCCESS(s2n_enable_tls13());

EXPECT_NOT_NULL(server_conn = s2n_connection_new(S2N_SERVER));
EXPECT_SUCCESS(s2n_connection_set_config(server_conn, tls13_config));

EXPECT_SUCCESS(s2n_stuffer_write(&server_conn->handshake.io, &tls12_client_hello_no_curves));
EXPECT_SUCCESS(s2n_client_hello_recv(server_conn));

/* ensure negotiated_curve == secp256r1 for maximum client compatability */
EXPECT_EQUAL(server_conn->secure.server_ecc_evp_params.negotiated_curve, &s2n_ecc_curve_secp256r1);

EXPECT_EQUAL(server_conn->server_protocol_version, S2N_TLS13);
EXPECT_EQUAL(server_conn->actual_protocol_version, S2N_TLS12);
EXPECT_EQUAL(server_conn->client_protocol_version, S2N_TLS12);
EXPECT_EQUAL(server_conn->client_hello_version, S2N_TLS12);

s2n_connection_free(server_conn);
EXPECT_SUCCESS(s2n_disable_tls13());
}

s2n_config_free(tls12_config);
s2n_config_free(tls13_config);
s2n_cert_chain_and_key_free(chain_and_key);
Expand Down
7 changes: 5 additions & 2 deletions tls/s2n_client_hello.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,11 @@ static int s2n_parse_client_hello(struct s2n_connection *conn)
GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
notnull_check(ecc_pref);

/* This is going to be our default if the client has no preference. */
conn->secure.server_ecc_evp_params.negotiated_curve = ecc_pref->ecc_curves[0];
/* 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));

Expand Down
9 changes: 9 additions & 0 deletions tls/s2n_ecc_preferences.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,12 @@ bool s2n_ecc_preferences_includes_curve(const struct s2n_ecc_preferences *ecc_pr

return false;
}

/* Check that ecc preferences include P-256 */
S2N_RESULT s2n_ecc_preferences_includes_p256(const struct s2n_ecc_preferences *ecc_preferences) {
if (!s2n_ecc_preferences_includes_curve(ecc_preferences, TLS_EC_CURVE_SECP_256_R1)) {
return S2N_RESULT_ERROR;
}

return S2N_RESULT_OK;
}
1 change: 1 addition & 0 deletions tls/s2n_ecc_preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ 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);
S2N_RESULT s2n_ecc_preferences_includes_p256(const struct s2n_ecc_preferences *ecc_preferences);
5 changes: 5 additions & 0 deletions tls/s2n_security_policies.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,11 @@ int s2n_security_policies_init()
const struct s2n_ecc_preferences *ecc_preference = security_policy->ecc_preferences;
notnull_check(ecc_preference);
GUARD(s2n_check_ecc_preferences_curves_list(ecc_preference));
if (security_policy != &security_policy_null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Might want a newline between line 638 and line 639

/* catch any offending security policy that does not support P-256 */
GUARD_AS_POSIX(s2n_ecc_preferences_includes_p256(ecc_preference));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this require a separate method? Why not just use s2n_ecc_preferences_includes_curve directly?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And why do this is production code instead of in a unit test that iterates over all security policies?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this require a separate method? Why not just use s2n_ecc_preferences_includes_curve directly?

I can use s2n_ecc_preferences_includes_curve() if that's preferred

And why do this is production code instead of in a unit test that iterates over all security policies?

  1. this is where all security policies is in scope
  2. this is inline with checks done in this security_policies block. even though it has a one time initialization cost during runtime, but a violation of this rule will also be caught during unit tests in this function

}

for (int j = 0; j < cipher_preference->count; j++) {
struct s2n_cipher_suite *cipher = cipher_preference->suites[j];
notnull_check(cipher);
Expand Down