Skip to content

Commit 97799be

Browse files
authored
Add client-side support for PQ HRR (#2260)
* Add client-side support for PQ HRR * Add function to wipe all client keyshares * Fix whitespace
1 parent 4ba1831 commit 97799be

File tree

6 files changed

+575
-131
lines changed

6 files changed

+575
-131
lines changed

tests/unit/s2n_client_hello_retry_test.c

Lines changed: 159 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "tls/s2n_tls13.h"
2626
#include "tls/s2n_tls13_handshake.h"
2727
#include "tls/s2n_connection.h"
28+
#include "crypto/s2n_fips.h"
2829

2930
/* This include is required to access static function s2n_server_hello_parse */
3031
#include "tls/s2n_server_hello.c"
@@ -106,7 +107,7 @@ int main(int argc, char **argv)
106107
EXPECT_SUCCESS(s2n_connection_free(conn));
107108
}
108109

109-
/* Test success case for s2n_server_hello_retry_recv */
110+
/* Test ECC success case for s2n_server_hello_retry_recv */
110111
{
111112
struct s2n_config *server_config;
112113
struct s2n_config *client_config;
@@ -168,8 +169,164 @@ int main(int argc, char **argv)
168169
EXPECT_SUCCESS(s2n_connection_free(server_conn));
169170
EXPECT_SUCCESS(s2n_connection_free(client_conn));
170171
EXPECT_SUCCESS(s2n_cert_chain_and_key_free(tls13_chain_and_key));
171-
172172
}
173+
#if !defined(S2N_NO_PQ)
174+
{
175+
const struct s2n_kem_group *test_kem_groups[] = {
176+
&s2n_secp256r1_sike_p434_r2,
177+
&s2n_secp256r1_bike1_l1_r2,
178+
};
179+
180+
const struct s2n_kem_preferences test_kem_prefs = {
181+
.kem_count = 0,
182+
.kems = NULL,
183+
.tls13_kem_group_count = s2n_array_len(test_kem_groups),
184+
.tls13_kem_groups = test_kem_groups,
185+
};
186+
187+
const struct s2n_security_policy test_security_policy = {
188+
.minimum_protocol_version = S2N_SSLv3,
189+
.cipher_preferences = &cipher_preferences_test_all_tls13,
190+
.kem_preferences = &test_kem_prefs,
191+
.signature_preferences = &s2n_signature_preferences_20200207,
192+
.ecc_preferences = &s2n_ecc_preferences_20200310,
193+
};
194+
195+
if (s2n_is_in_fips_mode()) {
196+
struct s2n_connection *conn;
197+
EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_CLIENT));
198+
conn->actual_protocol_version = S2N_TLS13;
199+
conn->security_policy_override = &test_security_policy;
200+
201+
const struct s2n_kem_preferences *kem_pref = NULL;
202+
GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
203+
EXPECT_NOT_NULL(kem_pref);
204+
205+
conn->secure.server_kem_group_params.kem_group = kem_pref->tls13_kem_groups[0];
206+
EXPECT_NULL(conn->secure.server_ecc_evp_params.negotiated_curve);
207+
208+
EXPECT_FAILURE_WITH_ERRNO(s2n_server_hello_retry_recv(conn), S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
209+
210+
EXPECT_SUCCESS(s2n_connection_free(conn));
211+
} else {
212+
/* s2n_server_hello_retry_recv must fail when a keyshare for a matching PQ KEM was already present */
213+
{
214+
struct s2n_connection *conn;
215+
EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_CLIENT));
216+
conn->actual_protocol_version = S2N_TLS13;
217+
conn->security_policy_override = &test_security_policy;
218+
219+
const struct s2n_kem_preferences *kem_pref = NULL;
220+
GUARD(s2n_connection_get_kem_preferences(conn, &kem_pref));
221+
EXPECT_NOT_NULL(kem_pref);
222+
223+
conn->secure.server_kem_group_params.kem_group = kem_pref->tls13_kem_groups[0];
224+
EXPECT_NULL(conn->secure.server_ecc_evp_params.negotiated_curve);
225+
226+
struct s2n_kem_group_params *client_params = &conn->secure.client_kem_group_params[0];
227+
client_params->kem_group = kem_pref->tls13_kem_groups[0];
228+
client_params->kem_params.kem = kem_pref->tls13_kem_groups[0]->kem;
229+
client_params->ecc_params.negotiated_curve = kem_pref->tls13_kem_groups[0]->curve;
230+
231+
EXPECT_NULL(client_params->ecc_params.evp_pkey);
232+
EXPECT_NULL(client_params->kem_params.private_key.data);
233+
234+
kem_public_key_size public_key_size = kem_pref->tls13_kem_groups[0]->kem->public_key_length;
235+
EXPECT_SUCCESS(s2n_alloc(&client_params->kem_params.public_key, public_key_size));
236+
237+
EXPECT_SUCCESS(s2n_kem_generate_keypair(&client_params->kem_params));
238+
EXPECT_NOT_NULL(client_params->kem_params.private_key.data);
239+
EXPECT_SUCCESS(s2n_ecc_evp_generate_ephemeral_key(&client_params->ecc_params));
240+
EXPECT_NOT_NULL(client_params->ecc_params.evp_pkey);
241+
242+
EXPECT_FAILURE_WITH_ERRNO(s2n_server_hello_retry_recv(conn), S2N_ERR_INVALID_HELLO_RETRY);
243+
244+
EXPECT_SUCCESS(s2n_free(&client_params->kem_params.public_key));
245+
EXPECT_SUCCESS(s2n_connection_free(conn));
246+
}
247+
/* s2n_server_hello_retry_recv must fail if the server chose a PQ KEM
248+
* that wasn't in the client's supported_groups */
249+
{
250+
struct s2n_connection *conn;
251+
EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_CLIENT));
252+
conn->actual_protocol_version = S2N_TLS13;
253+
conn->security_policy_override = &test_security_policy;
254+
255+
/* test_security_policy does not include kyber */
256+
conn->secure.server_kem_group_params.kem_group = &s2n_secp256r1_kyber_512_r2;
257+
EXPECT_NULL(conn->secure.server_ecc_evp_params.negotiated_curve);
258+
259+
EXPECT_FAILURE_WITH_ERRNO(s2n_server_hello_retry_recv(conn), S2N_ERR_INVALID_HELLO_RETRY);
260+
261+
EXPECT_SUCCESS(s2n_connection_free(conn));
262+
}
263+
/* Test failure if exactly one of {named_curve, kem_group} isn't non-null */
264+
{
265+
struct s2n_connection *conn;
266+
EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_CLIENT));
267+
conn->actual_protocol_version = S2N_TLS13;
268+
conn->security_policy_override = &test_security_policy;
269+
270+
conn->secure.server_kem_group_params.kem_group = &s2n_secp256r1_sike_p434_r2;
271+
conn->secure.server_ecc_evp_params.negotiated_curve = &s2n_ecc_curve_secp256r1;
272+
273+
EXPECT_FAILURE_WITH_ERRNO(s2n_server_hello_retry_recv(conn), S2N_ERR_INVALID_HELLO_RETRY);
274+
275+
conn->secure.server_kem_group_params.kem_group = NULL;
276+
conn->secure.server_ecc_evp_params.negotiated_curve = NULL;
277+
278+
EXPECT_FAILURE_WITH_ERRNO(s2n_server_hello_retry_recv(conn), S2N_ERR_INVALID_HELLO_RETRY);
279+
280+
EXPECT_SUCCESS(s2n_connection_free(conn));
281+
}
282+
/* Test PQ KEM success case for s2n_server_hello_retry_recv. */
283+
{
284+
struct s2n_config *config;
285+
struct s2n_connection *conn;
286+
287+
struct s2n_cert_chain_and_key *tls13_chain_and_key;
288+
char tls13_cert_chain[S2N_MAX_TEST_PEM_SIZE] = {0};
289+
char tls13_private_key[S2N_MAX_TEST_PEM_SIZE] = {0};
290+
291+
EXPECT_NOT_NULL(config = s2n_config_new());
292+
EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_CLIENT));
293+
conn->security_policy_override = &test_security_policy;
294+
295+
EXPECT_NOT_NULL(tls13_chain_and_key = s2n_cert_chain_and_key_new());
296+
EXPECT_SUCCESS(s2n_read_test_pem(S2N_ECDSA_P384_PKCS1_CERT_CHAIN, tls13_cert_chain, S2N_MAX_TEST_PEM_SIZE));
297+
EXPECT_SUCCESS(s2n_read_test_pem(S2N_ECDSA_P384_PKCS1_KEY, tls13_private_key, S2N_MAX_TEST_PEM_SIZE));
298+
EXPECT_SUCCESS(s2n_cert_chain_and_key_load_pem(tls13_chain_and_key, tls13_cert_chain, tls13_private_key));
299+
EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(config, tls13_chain_and_key));
300+
301+
/* Client sends ClientHello containing key share for p256+SIKE
302+
* (but indicates support for p256+BIKE in supported_groups) */
303+
EXPECT_SUCCESS(s2n_client_hello_send(conn));
304+
305+
EXPECT_SUCCESS(s2n_stuffer_wipe(&conn->handshake.io));
306+
307+
/* Server responds with HRR indicating p256+BIKE as choice for negotiation;
308+
* the last 6 bytes (0033 0002 2F23) are the key share extension with p256+BIKE */
309+
DEFER_CLEANUP(struct s2n_stuffer hrr = {0}, s2n_stuffer_free);
310+
EXPECT_SUCCESS(s2n_stuffer_alloc_ro_from_hex_string(&hrr,
311+
"0303CF21AD74E59A6111BE1D8C021E65B891C2A211167ABB8C5E079E09E2C8A8339C00130200000C002B00020304003300022F23"));
312+
313+
EXPECT_SUCCESS(s2n_stuffer_copy(&hrr, &conn->handshake.io, s2n_stuffer_data_available(&hrr)));
314+
conn->handshake.message_number = HELLO_RETRY_MSG_NO;
315+
/* Read the message off the wire */
316+
EXPECT_SUCCESS(s2n_server_hello_parse(conn));
317+
conn->actual_protocol_version_established = 1;
318+
319+
EXPECT_SUCCESS(s2n_conn_set_handshake_type(conn));
320+
/* Client receives the HelloRetryRequest message */
321+
EXPECT_SUCCESS(s2n_server_hello_retry_recv(conn));
322+
323+
EXPECT_SUCCESS(s2n_config_free(config));
324+
EXPECT_SUCCESS(s2n_connection_free(conn));
325+
EXPECT_SUCCESS(s2n_cert_chain_and_key_free(tls13_chain_and_key));
326+
}
327+
}
328+
}
329+
#endif
173330
}
174331

175332
/* Verify that the hash transcript recreation function is called correctly,

0 commit comments

Comments
 (0)