Skip to content

Commit 86bafa1

Browse files
authored
Make HRRs work with early data (#2611)
Previously, the only valid HRR was in response to a missing key share. Now, we need to also allow HRRs that reject early data but do not alter the key shares.
1 parent 3973821 commit 86bafa1

14 files changed

+452
-103
lines changed

tests/unit/s2n_client_early_data_indication_test.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,5 +297,118 @@ int main(int argc, char **argv)
297297
}
298298
}
299299

300+
/* Test state transitions with a HelloRetryRequest.
301+
*
302+
*= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
303+
*= type=test
304+
*# A server which receives an "early_data" extension MUST behave in one
305+
*# of three ways:
306+
*
307+
*= https://tools.ietf.org/rfc/rfc8446#section-4.2.10
308+
*= type=test
309+
*# - Request that the client send another ClientHello by responding
310+
*# with a HelloRetryRequest.
311+
*/
312+
{
313+
/* Hello Retry Request because of rejected early data.
314+
*
315+
* The S2N server does not reject early data via a HelloRetryRequest, but other implementations might.
316+
* The S2N client should handle retries triggered by early data gracefully.
317+
*/
318+
{
319+
struct s2n_connection *client_conn = s2n_connection_new(S2N_CLIENT);
320+
EXPECT_NOT_NULL(client_conn);
321+
EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(client_conn, "default_tls13"));
322+
EXPECT_OK(s2n_append_test_psk(client_conn, 1, &s2n_tls13_aes_256_gcm_sha384));
323+
EXPECT_EQUAL(client_conn->early_data_state, S2N_UNKNOWN_EARLY_DATA_STATE);
324+
325+
struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER);
326+
EXPECT_NOT_NULL(server_conn);
327+
EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(server_conn, "default_tls13"));
328+
EXPECT_OK(s2n_append_test_psk(server_conn, 0, &s2n_tls13_aes_256_gcm_sha384));
329+
EXPECT_EQUAL(server_conn->early_data_state, S2N_UNKNOWN_EARLY_DATA_STATE);
330+
331+
EXPECT_SUCCESS(s2n_client_hello_send(client_conn));
332+
EXPECT_SUCCESS(s2n_stuffer_copy(&client_conn->handshake.io, &server_conn->handshake.io,
333+
s2n_stuffer_data_available(&client_conn->handshake.io)));
334+
EXPECT_SUCCESS(s2n_client_hello_recv(server_conn));
335+
EXPECT_EQUAL(client_conn->early_data_state, S2N_EARLY_DATA_REQUESTED);
336+
337+
/* Force a retry */
338+
EXPECT_SUCCESS(s2n_set_hello_retry_required(server_conn));
339+
/* There is retry handling logic that checks that the current message
340+
* is a hello retry message, which requires that we be at a specific message number. */
341+
server_conn->handshake.message_number = 1;
342+
client_conn->handshake.message_number = 1;
343+
344+
EXPECT_SUCCESS(s2n_server_hello_retry_send(server_conn));
345+
EXPECT_SUCCESS(s2n_stuffer_copy(&server_conn->handshake.io, &client_conn->handshake.io,
346+
s2n_stuffer_data_available(&server_conn->handshake.io)));
347+
EXPECT_SUCCESS(s2n_server_hello_recv(client_conn));
348+
EXPECT_EQUAL(client_conn->early_data_state, S2N_EARLY_DATA_REJECTED);
349+
350+
EXPECT_SUCCESS(s2n_client_hello_send(client_conn));
351+
EXPECT_EQUAL(client_conn->early_data_state, S2N_EARLY_DATA_REJECTED);
352+
353+
EXPECT_SUCCESS(s2n_connection_free(client_conn));
354+
EXPECT_SUCCESS(s2n_connection_free(server_conn));
355+
}
356+
357+
/* Hello Retry Request because of missing key share: still rejects early data */
358+
{
359+
const struct s2n_ecc_named_curve *const curves_reversed_order[] = {
360+
&s2n_ecc_curve_secp384r1,
361+
&s2n_ecc_curve_secp256r1,
362+
};
363+
const struct s2n_ecc_preferences ecc_prefs_reversed_order = {
364+
.count = s2n_array_len(curves_reversed_order),
365+
.ecc_curves = curves_reversed_order,
366+
};
367+
struct s2n_security_policy sec_policy_reversed_order = security_policy_test_all_tls13;
368+
sec_policy_reversed_order.ecc_preferences = &ecc_prefs_reversed_order;
369+
const struct s2n_security_policy retry_policy = sec_policy_reversed_order;
370+
371+
struct s2n_connection *client_conn = s2n_connection_new(S2N_CLIENT);
372+
EXPECT_NOT_NULL(client_conn);
373+
client_conn->security_policy_override = &retry_policy;
374+
EXPECT_OK(s2n_append_test_psk(client_conn, 1, &s2n_tls13_aes_256_gcm_sha384));
375+
EXPECT_EQUAL(client_conn->early_data_state, S2N_UNKNOWN_EARLY_DATA_STATE);
376+
377+
struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER);
378+
EXPECT_NOT_NULL(server_conn);
379+
server_conn->security_policy_override = &security_policy_test_all_tls13;
380+
EXPECT_OK(s2n_append_test_psk(server_conn, 1, &s2n_tls13_aes_256_gcm_sha384));
381+
EXPECT_EQUAL(server_conn->early_data_state, S2N_UNKNOWN_EARLY_DATA_STATE);
382+
383+
EXPECT_SUCCESS(s2n_client_hello_send(client_conn));
384+
EXPECT_SUCCESS(s2n_stuffer_copy(&client_conn->handshake.io, &server_conn->handshake.io,
385+
s2n_stuffer_data_available(&client_conn->handshake.io)));
386+
EXPECT_SUCCESS(s2n_client_hello_recv(server_conn));
387+
EXPECT_EQUAL(client_conn->early_data_state, S2N_EARLY_DATA_REQUESTED);
388+
EXPECT_EQUAL(server_conn->early_data_state, S2N_EARLY_DATA_REJECTED);
389+
390+
EXPECT_TRUE(s2n_is_hello_retry_handshake(server_conn));
391+
/* There is retry handling logic that checks that the current message
392+
* is a hello retry message, which requires that we be at a specific message number. */
393+
server_conn->handshake.message_number = 1;
394+
client_conn->handshake.message_number = 1;
395+
396+
EXPECT_SUCCESS(s2n_server_hello_retry_send(server_conn));
397+
EXPECT_SUCCESS(s2n_stuffer_copy(&server_conn->handshake.io, &client_conn->handshake.io,
398+
s2n_stuffer_data_available(&server_conn->handshake.io)));
399+
EXPECT_SUCCESS(s2n_server_hello_recv(client_conn));
400+
EXPECT_TRUE(s2n_is_hello_retry_handshake(client_conn));
401+
EXPECT_EQUAL(client_conn->early_data_state, S2N_EARLY_DATA_REJECTED);
402+
EXPECT_EQUAL(server_conn->early_data_state, S2N_EARLY_DATA_REJECTED);
403+
404+
EXPECT_SUCCESS(s2n_client_hello_send(client_conn));
405+
EXPECT_EQUAL(client_conn->early_data_state, S2N_EARLY_DATA_REJECTED);
406+
EXPECT_EQUAL(server_conn->early_data_state, S2N_EARLY_DATA_REJECTED);
407+
408+
EXPECT_SUCCESS(s2n_connection_free(client_conn));
409+
EXPECT_SUCCESS(s2n_connection_free(server_conn));
410+
}
411+
}
412+
300413
END_TEST();
301414
}

tests/unit/s2n_client_key_share_extension_pq_test.c

Lines changed: 97 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "pq-crypto/s2n_pq.h"
3131

3232
#define HELLO_RETRY_MSG_NO 1
33+
#define MEM_FOR_EXTENSION 4096
3334

3435
static int s2n_generate_pq_hybrid_key_share_for_test(struct s2n_stuffer *out, struct s2n_kem_group_params *kem_group_params);
3536
static int s2n_copy_pq_share(struct s2n_stuffer *from, struct s2n_blob *to, const struct s2n_kem_group *kem_group);
@@ -172,7 +173,7 @@ int main() {
172173
const struct s2n_kem_group *test_kem_group = kem_pref->tls13_kem_groups[0];
173174

174175
DEFER_CLEANUP(struct s2n_stuffer key_share_extension = {0}, s2n_stuffer_free);
175-
EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&key_share_extension, 4096));
176+
EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&key_share_extension, MEM_FOR_EXTENSION));
176177
EXPECT_SUCCESS(s2n_client_key_share_extension.send(conn, &key_share_extension));
177178

178179
/* First, assert that the client saved its private keys correctly in the connection state
@@ -264,10 +265,9 @@ int main() {
264265
EXPECT_SUCCESS(s2n_connection_get_kem_preferences(conn, &kem_pref));
265266
EXPECT_NOT_NULL(kem_pref);
266267

267-
/* This is for pre-HRR set up; force the client to generate it's default hybrid key share
268-
* so that we can confirm that s2n_send_hrr_pq_hybrid_keyshare wipes it correctly. */
268+
/* This is for pre-HRR set up: force the client to generate its default hybrid key share. */
269269
DEFER_CLEANUP(struct s2n_stuffer key_share_extension = {0}, s2n_stuffer_free);
270-
EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&key_share_extension, 4096));
270+
EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&key_share_extension, MEM_FOR_EXTENSION));
271271
EXPECT_SUCCESS(s2n_client_key_share_extension.send(conn, &key_share_extension));
272272
EXPECT_SUCCESS(s2n_stuffer_wipe(&key_share_extension));
273273
/* Quick sanity check */
@@ -296,19 +296,18 @@ int main() {
296296
EXPECT_NOT_NULL(kem_group_params->ecc_params.evp_pkey);
297297

298298
/* Assert that the client didn't generate/save any key shares that it wasn't supposed to */
299-
for (size_t kem_group_index = 0;
300-
kem_group_index < kem_pref->tls13_kem_group_count; kem_group_index++) {
301-
if (kem_group_index == chosen_index) {
299+
for (size_t kem_group_i = 0; kem_group_i < kem_pref->tls13_kem_group_count; kem_group_i++) {
300+
if (kem_group_i == chosen_index || kem_group_i == 0) {
302301
continue;
303302
}
304-
EXPECT_NULL(conn->secure.client_kem_group_params[kem_group_index].kem_group);
305-
EXPECT_NULL(conn->secure.client_kem_group_params[kem_group_index].kem_params.kem);
306-
EXPECT_NULL(conn->secure.client_kem_group_params[kem_group_index].kem_params.private_key.data);
307-
EXPECT_EQUAL(conn->secure.client_kem_group_params[kem_group_index].kem_params.private_key.size,0);
308-
EXPECT_NULL(conn->secure.client_kem_group_params[kem_group_index].ecc_params.negotiated_curve);
309-
EXPECT_NULL(conn->secure.client_kem_group_params[kem_group_index].ecc_params.evp_pkey);
303+
EXPECT_NULL(conn->secure.client_kem_group_params[kem_group_i].kem_group);
304+
EXPECT_NULL(conn->secure.client_kem_group_params[kem_group_i].kem_params.kem);
305+
EXPECT_NULL(conn->secure.client_kem_group_params[kem_group_i].kem_params.private_key.data);
306+
EXPECT_EQUAL(conn->secure.client_kem_group_params[kem_group_i].kem_params.private_key.size,0);
307+
EXPECT_NULL(conn->secure.client_kem_group_params[kem_group_i].ecc_params.negotiated_curve);
308+
EXPECT_NULL(conn->secure.client_kem_group_params[kem_group_i].ecc_params.evp_pkey);
310309
}
311-
for (size_t ecc_index = 0; ecc_index < S2N_ECC_EVP_SUPPORTED_CURVES_COUNT; ecc_index++) {
310+
for (size_t ecc_index = 1; ecc_index < S2N_ECC_EVP_SUPPORTED_CURVES_COUNT; ecc_index++) {
312311
EXPECT_NULL(conn->secure.client_ecc_evp_params[ecc_index].negotiated_curve);
313312
EXPECT_NULL(conn->secure.client_ecc_evp_params[ecc_index].evp_pkey);
314313
}
@@ -349,6 +348,89 @@ int main() {
349348

350349
EXPECT_SUCCESS(s2n_connection_free(conn));
351350
}
351+
352+
/* Test sending in response to HRR for early data */
353+
{
354+
struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
355+
conn->security_policy_override = &test_security_policy;
356+
EXPECT_NOT_NULL(conn);
357+
358+
const struct s2n_ecc_preferences *ecc_preferences = NULL;
359+
EXPECT_SUCCESS(s2n_connection_get_ecc_preferences(conn, &ecc_preferences));
360+
EXPECT_NOT_NULL(ecc_preferences);
361+
362+
const struct s2n_kem_preferences *kem_pref = NULL;
363+
EXPECT_SUCCESS(s2n_connection_get_kem_preferences(conn, &kem_pref));
364+
EXPECT_NOT_NULL(kem_pref);
365+
366+
struct s2n_stuffer first_extension = { 0 }, second_extension = { 0 };
367+
EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&first_extension, MEM_FOR_EXTENSION));
368+
EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&second_extension, MEM_FOR_EXTENSION));
369+
370+
EXPECT_SUCCESS(s2n_client_key_share_extension.send(conn, &first_extension));
371+
372+
conn->secure.server_kem_group_params.kem_group = conn->secure.client_kem_group_params[0].kem_group;
373+
conn->secure.server_kem_group_params.ecc_params.negotiated_curve =
374+
conn->secure.client_kem_group_params[0].ecc_params.negotiated_curve;
375+
376+
/* Setup the client to have received a HelloRetryRequest */
377+
EXPECT_MEMCPY_SUCCESS(conn->secure.server_random, hello_retry_req_random, S2N_TLS_RANDOM_DATA_LEN);
378+
EXPECT_SUCCESS(s2n_connection_set_all_protocol_versions(conn, S2N_TLS13));
379+
EXPECT_SUCCESS(s2n_set_connection_hello_retry_flags(conn));
380+
conn->early_data_state = S2N_EARLY_DATA_REJECTED;
381+
382+
EXPECT_SUCCESS(s2n_client_key_share_extension.send(conn, &second_extension));
383+
384+
/* Read the total length of both extensions.
385+
* The first keys extension contains multiple shares, so should be longer than the second. */
386+
uint16_t first_sent_key_shares_size = 0, second_sent_key_shares_size = 0;
387+
EXPECT_SUCCESS(s2n_stuffer_read_uint16(&first_extension, &first_sent_key_shares_size));
388+
EXPECT_SUCCESS(s2n_stuffer_read_uint16(&second_extension, &second_sent_key_shares_size));
389+
EXPECT_EQUAL(first_sent_key_shares_size, s2n_stuffer_data_available(&first_extension));
390+
EXPECT_EQUAL(second_sent_key_shares_size, s2n_stuffer_data_available(&second_extension));
391+
EXPECT_TRUE(second_sent_key_shares_size < first_sent_key_shares_size);
392+
393+
/* Read the iana of the first share.
394+
* Both shares should contain the same iana, and it should be equal to the server's chosen kem group. */
395+
uint16_t first_sent_hybrid_iana_id = 0, second_sent_hybrid_iana_id = 0;
396+
EXPECT_SUCCESS(s2n_stuffer_read_uint16(&first_extension, &first_sent_hybrid_iana_id));
397+
EXPECT_SUCCESS(s2n_stuffer_read_uint16(&second_extension, &second_sent_hybrid_iana_id));
398+
EXPECT_EQUAL(first_sent_hybrid_iana_id, conn->secure.server_kem_group_params.kem_group->iana_id);
399+
EXPECT_EQUAL(first_sent_hybrid_iana_id, second_sent_hybrid_iana_id);
400+
401+
/* Read the total share size, including both ecc and kem.
402+
* The first extension contains multiple shares, so should contain more data than the share size.
403+
* The second extension only contains one share, so should contain only the share size. */
404+
uint16_t first_total_hybrid_share_size = 0, second_total_hybrid_share_size = 0;
405+
EXPECT_SUCCESS(s2n_stuffer_read_uint16(&first_extension, &first_total_hybrid_share_size));
406+
EXPECT_SUCCESS(s2n_stuffer_read_uint16(&second_extension, &second_total_hybrid_share_size));
407+
EXPECT_TRUE(first_total_hybrid_share_size < s2n_stuffer_data_available(&first_extension));
408+
EXPECT_EQUAL(second_total_hybrid_share_size, s2n_stuffer_data_available(&second_extension));
409+
410+
/* Read the ecc share size.
411+
* The ecc share should be identical for both, so the size should be the same. */
412+
uint16_t first_ecc_share_size = 0, second_ecc_share_size = 0;
413+
EXPECT_SUCCESS(s2n_stuffer_read_uint16(&first_extension, &first_ecc_share_size));
414+
EXPECT_SUCCESS(s2n_stuffer_read_uint16(&second_extension, &second_ecc_share_size));
415+
EXPECT_EQUAL(first_ecc_share_size, second_ecc_share_size);
416+
417+
/* Read the ecc share.
418+
* The ecc share should be identical for both. */
419+
uint8_t *first_ecc_share_data = NULL, *second_ecc_share_data = NULL;
420+
EXPECT_NOT_NULL(first_ecc_share_data = s2n_stuffer_raw_read(&first_extension, first_ecc_share_size));
421+
EXPECT_NOT_NULL(second_ecc_share_data = s2n_stuffer_raw_read(&second_extension, second_ecc_share_size));
422+
EXPECT_BYTEARRAY_EQUAL(first_ecc_share_data, second_ecc_share_data, first_ecc_share_size);
423+
424+
/* The pq share should take up the rest of the key share.
425+
* For now the pq share is different between extensions, so we can't assert anything else. */
426+
uint16_t second_pq_share_size = 0;
427+
EXPECT_SUCCESS(s2n_stuffer_read_uint16(&second_extension, &second_pq_share_size));
428+
EXPECT_EQUAL(second_pq_share_size, s2n_stuffer_data_available(&second_extension));
429+
430+
EXPECT_SUCCESS(s2n_stuffer_free(&first_extension));
431+
EXPECT_SUCCESS(s2n_stuffer_free(&second_extension));
432+
EXPECT_SUCCESS(s2n_connection_free(conn));
433+
}
352434
}
353435

354436
/* Test failure when server chooses a KEM group that is not in the client's preferences */
@@ -364,7 +446,7 @@ int main() {
364446
conn->secure.server_kem_group_params.kem_group = &s2n_secp256r1_bike1_l1_r2;
365447

366448
DEFER_CLEANUP(struct s2n_stuffer key_share_extension = {0}, s2n_stuffer_free);
367-
EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&key_share_extension, 4096));
449+
EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&key_share_extension, MEM_FOR_EXTENSION));
368450
EXPECT_FAILURE_WITH_ERRNO(s2n_client_key_share_extension.send(conn, &key_share_extension), S2N_ERR_INVALID_HELLO_RETRY);
369451

370452
EXPECT_SUCCESS(s2n_connection_free(conn));

0 commit comments

Comments
 (0)