1 /*
2 * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include "testutil.h"
11 #include "helpers/ssltestlib.h"
12 #include <openssl/objects.h>
13
14 #define TEST_true_or_end(a) if (!TEST_true(a)) \
15 goto end;
16
17 #define TEST_false_or_end(a) if (!TEST_false(a)) \
18 goto end;
19
20 #define SERVER_PREFERENCE 1
21 #define CLIENT_PREFERENCE 0
22
23 #define WORK_ON_SSL_OBJECT 1
24 #define WORK_ON_CONTEXT 0
25
26 #define SYNTAX_FAILURE "SYNTAX_FAILURE"
27 #define NEGOTIATION_FAILURE "NEGOTIATION_FAILURE"
28
29 typedef enum TEST_TYPE {
30 TEST_NEGOTIATION_FAILURE = 0,
31 TEST_NEGOTIATION_SUCCESS = 1,
32 TEST_SYNTAX_FAILURE = 2
33 } TEST_TYPE;
34
35 typedef enum SERVER_RESPONSE {
36 HRR = 0,
37 INIT = 1,
38 SH = 2
39 } SERVER_RESPONSE;
40
41 static char *cert = NULL;
42 static char *privkey = NULL;
43
44 struct tls13groupselection_test_st {
45 const char *client_groups;
46 const char *server_groups;
47 const int preference;
48 const char *expected_group;
49 const enum SERVER_RESPONSE expected_server_response;
50 };
51
52 static const struct tls13groupselection_test_st tls13groupselection_tests[] =
53 {
54
55 /*
56 * (A) Test with no explicit key share (backward compatibility)
57 * Key share is implicitly sent for first client group
58 * Test (implicitly) that the key share group is used
59 */
60 { "secp384r1:secp521r1:X25519:prime256v1:X448", /* test 0 */
61 "X25519:secp521r1:secp384r1:prime256v1:X448",
62 CLIENT_PREFERENCE,
63 "secp384r1", SH
64 },
65 { "secp521r1:secp384r1:X25519:prime256v1:X448", /* test 1 */
66 "X25519:secp521r1:secp384r1:prime256v1:X448",
67 SERVER_PREFERENCE,
68 "secp521r1", SH
69 },
70
71 /*
72 * (B) No explicit key share test (backward compatibility)
73 * Key share is implicitly sent for first client group
74 * Check HRR if server does not support key share group
75 */
76 { "secp521r1:secp384r1:X25519:prime256v1:X448", /* test 2 */
77 "X25519:secp384r1:prime256v1",
78 CLIENT_PREFERENCE,
79 "secp384r1", HRR
80 },
81 { "secp521r1:secp384r1:X25519:prime256v1:X448", /* test 3 */
82 "X25519:secp384r1:prime256v1",
83 SERVER_PREFERENCE,
84 "x25519", HRR
85 },
86
87 /*
88 * (C) Explicit key shares, SH tests
89 * Test key share selection as function of client-/server-preference
90 * Test (implicitly) that multiple key shares are generated
91 * Test (implicitly) that multiple tuples don't influence the client
92 * Test (implicitly) that key share prefix doesn't influence the server
93 */
94 { "secp521r1:secp384r1:*X25519/*prime256v1:X448", /* test 4 */
95 "secp521r1:*prime256v1:X25519:X448",
96 CLIENT_PREFERENCE,
97 "x25519", SH
98 },
99 { "secp521r1:secp384r1:*X25519/*prime256v1:X448", /* test 5 */
100 "secp521r1:*prime256v1:X25519:X448",
101 SERVER_PREFERENCE,
102 "secp256r1", SH
103 },
104
105 /*
106 * (D) Explicit key shares, HRR tests
107 * Check that HRR is issued if group in first tuple
108 * is supported but no key share is available for the tuple
109 */
110 { "secp521r1:secp384r1:*X25519:prime256v1:*X448", /* test 6 */
111 "secp384r1:secp521r1:prime256v1/X25519:X448",
112 CLIENT_PREFERENCE,
113 "secp521r1", HRR
114 },
115 { "secp521r1:secp384r1:*X25519:prime256v1:*X448", /* test 7 */
116 "secp384r1:secp521r1:prime256v1/X25519:X448",
117 SERVER_PREFERENCE,
118 "secp384r1", HRR
119 },
120
121 /*
122 * (E) Multiple tuples tests, client without tuple delimiters
123 * Check that second tuple is evaluated if there isn't any match
124 * first tuple
125 */
126 { "*X25519:prime256v1:*X448", /* test 8 */
127 "secp521r1:secp384r1/X448:X25519",
128 CLIENT_PREFERENCE,
129 "x25519", SH
130 },
131 { "*X25519:prime256v1:*X448", /* test 9 */
132 "secp521r1:secp384r1/X448:X25519",
133 SERVER_PREFERENCE,
134 "x448", SH
135 },
136
137 /* (F) Check that '?' will ignore unknown group but use known group */
138 { "*X25519:?unknown_group_123:prime256v1:*X448", /* test 10 */
139 "secp521r1:secp384r1/X448:?unknown_group_456:?X25519",
140 CLIENT_PREFERENCE,
141 "x25519", SH
142 },
143 { "*X25519:prime256v1:*X448:?*unknown_group_789", /* test 11 */
144 "secp521r1:secp384r1/?X448:?unknown_group_456:X25519",
145 SERVER_PREFERENCE,
146 "x448", SH
147 },
148
149 /*
150 * (G) Check full backward compatibility (= don't explicitly set any groups)
151 */
152 { NULL, /* test 12 */
153 NULL,
154 CLIENT_PREFERENCE,
155 #ifndef OPENSSL_NO_ML_KEM
156 "X25519MLKEM768", SH
157 #else
158 "x25519", SH
159 #endif
160 },
161 { NULL, /* test 13 */
162 NULL,
163 SERVER_PREFERENCE,
164 #ifndef OPENSSL_NO_ML_KEM
165 "X25519MLKEM768", SH
166 #else
167 "x25519", SH
168 #endif
169 },
170
171 /*
172 * (H) Check that removal of group is 'active'
173 */
174 { "*X25519:*X448", /* test 14 */
175 "secp521r1:X25519:prime256v1:-X25519:secp384r1/X448",
176 CLIENT_PREFERENCE,
177 "x448", SH
178 },
179 { "*X25519:*X448", /* test 15 */
180 "secp521r1:X25519:prime256v1:-X25519:secp384r1/X448",
181 SERVER_PREFERENCE,
182 "x448", SH
183 },
184 { "*X25519:prime256v1:*X448", /* test 16 */
185 "X25519:prime256v1/X448:-X25519",
186 CLIENT_PREFERENCE,
187 "secp256r1", HRR
188 },
189 { "*X25519:prime256v1:*X448", /* test 17 */
190 "X25519:prime256v1/X448:-X25519",
191 SERVER_PREFERENCE,
192 "secp256r1", HRR
193 },
194 /*
195 * (I) Check handling of the "DEFAULT" 'pseudo group name'
196 */
197 { "*X25519:DEFAULT:-prime256v1:-X448", /* test 18 */
198 "DEFAULT:-X25519:-?X25519MLKEM768",
199 CLIENT_PREFERENCE,
200 "secp384r1", HRR
201 },
202 { "*X25519:DEFAULT:-prime256v1:-X448", /* test 19 */
203 "DEFAULT:-X25519:-?X25519MLKEM768",
204 SERVER_PREFERENCE,
205 "secp384r1", HRR
206 },
207 /*
208 * (J) Deduplication check
209 */
210 { "secp521r1:X25519:prime256v1/X25519:prime256v1/X448", /* test 20 */
211 "secp521r1:X25519:prime256v1/X25519:prime256v1/X448",
212 CLIENT_PREFERENCE,
213 "secp521r1", SH
214 },
215 { "secp521r1:X25519:prime256v1/X25519:prime256v1/X448", /* test 21 */
216 "secp521r1:X25519:prime256v1/X25519:prime256v1/X448",
217 SERVER_PREFERENCE,
218 "secp521r1", SH
219 },
220 /*
221 * (K) Check group removal when first entry requested a keyshare
222 */
223 { "*X25519:*prime256v1:-X25519", /* test 22 */
224 "X25519:prime256v1",
225 CLIENT_PREFERENCE,
226 "secp256r1", SH
227 },
228 /*
229 * (L) Syntax errors
230 */
231 { "*X25519:*prime256v1:NOTVALID", /* test 23 */
232 "",
233 CLIENT_PREFERENCE,
234 SYNTAX_FAILURE
235 },
236 { "X25519//prime256v1", /* test 24 */
237 "",
238 CLIENT_PREFERENCE,
239 SYNTAX_FAILURE
240 },
241 { "**X25519:*prime256v1", /* test 25 */
242 "",
243 CLIENT_PREFERENCE,
244 SYNTAX_FAILURE
245 },
246 { "*X25519:*secp256r1:*X448:*secp521r1:*secp384r1", /* test 26 */
247 "",
248 CLIENT_PREFERENCE,
249 SYNTAX_FAILURE
250 },
251 { "*X25519:*secp256r1:?:*secp521r1", /* test 27 */
252 "",
253 CLIENT_PREFERENCE,
254 SYNTAX_FAILURE
255 },
256 { "*X25519:*secp256r1::secp521r1", /* test 28 */
257 "",
258 CLIENT_PREFERENCE,
259 SYNTAX_FAILURE
260 },
261 { ":*secp256r1:secp521r1", /* test 29 */
262 "",
263 CLIENT_PREFERENCE,
264 SYNTAX_FAILURE
265 },
266 { "*secp256r1:secp521r1:", /* test 30 */
267 "",
268 CLIENT_PREFERENCE,
269 SYNTAX_FAILURE
270 },
271 { "/secp256r1/secp521r1", /* test 31 */
272 "",
273 CLIENT_PREFERENCE,
274 SYNTAX_FAILURE
275 },
276 { "secp256r1/secp521r1/", /* test 32 */
277 "",
278 CLIENT_PREFERENCE,
279 SYNTAX_FAILURE
280 },
281 { "X25519:??secp256r1:X448", /* test 33 */
282 "",
283 CLIENT_PREFERENCE,
284 SYNTAX_FAILURE
285 },
286 { "X25519:secp256r1:**X448", /* test 34 */
287 "",
288 CLIENT_PREFERENCE,
289 SYNTAX_FAILURE
290 },
291 { "--X25519:secp256r1:X448", /* test 35 */
292 "",
293 CLIENT_PREFERENCE,
294 SYNTAX_FAILURE
295 },
296 { "-DEFAULT", /* test 36 */
297 "",
298 CLIENT_PREFERENCE,
299 SYNTAX_FAILURE
300 },
301 { "?DEFAULT", /* test 37 */
302 "",
303 CLIENT_PREFERENCE,
304 SYNTAX_FAILURE
305 },
306 /*
307 * Negotiation Failures
308 * No overlapping groups between client and server
309 */
310 /* test 38 remove all groups */
311 { "X25519:secp256r1:X448:secp521r1:-X448:-secp256r1:-X25519:-secp521r1",
312 "",
313 CLIENT_PREFERENCE,
314 NEGOTIATION_FAILURE, INIT
315 },
316 { "secp384r1:secp521r1:X25519", /* test 39 */
317 "prime256v1:X448",
318 CLIENT_PREFERENCE,
319 NEGOTIATION_FAILURE, INIT
320 },
321 { "secp521r1:secp384r1:X25519", /* test 40 */
322 "prime256v1:X448",
323 SERVER_PREFERENCE,
324 NEGOTIATION_FAILURE, INIT
325 },
326 /*
327 * These are allowed
328 * "X25519/prime256v1:-X448", "X25519:-*X25519:*prime256v1, "*DEFAULT"
329 */
330 /*
331 * Tests to show that spaces between tuples are allowed
332 */
333 { "secp521r1:X25519 / prime256v1/X25519 / prime256v1/X448", /* test 41 */
334 "secp521r1:X25519 / prime256v1/X25519 / prime256v1/X448",
335 CLIENT_PREFERENCE,
336 "secp521r1", SH
337 },
338 { "secp521r1 / prime256v1:X25519 / prime256v1/X448", /* test 42 */
339 "secp521r1 / prime256v1:X25519 / prime256v1/X448",
340 SERVER_PREFERENCE,
341 "secp521r1", SH
342 },
343 /*
344 * Not a syntax error, but invalid because brainpoolP256r1 is the only
345 * key share and is not valid in TLSv1.3
346 */
347 { "*brainpoolP256r1:X25519", /* test 43 */
348 "X25519",
349 SERVER_PREFERENCE,
350 NEGOTIATION_FAILURE, INIT
351 }
352 };
353
server_response_check_cb(int write_p,int version,int content_type,const void * buf,size_t len,SSL * ssl,void * arg)354 static void server_response_check_cb(int write_p, int version,
355 int content_type, const void *buf,
356 size_t len, SSL *ssl, void *arg)
357 {
358 /* Cast arg to SERVER_RESPONSE */
359 enum SERVER_RESPONSE *server_response = (enum SERVER_RESPONSE *)arg;
360 /* Prepare check for HRR */
361 const uint8_t *incoming_random = (uint8_t *)buf + 6;
362 const uint8_t magic_HRR_random[32] = { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
363 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
364 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
365 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C };
366
367 /* Did a server hello arrive? */
368 if (write_p == 0 && /* Incoming data... */
369 content_type == SSL3_RT_HANDSHAKE && /* carrying a handshake record type ... */
370 version == TLS1_3_VERSION && /* for TLSv1.3 ... */
371 ((uint8_t *)buf)[0] == SSL3_MT_SERVER_HELLO) { /* with message type "ServerHello" */
372 /* Check what it is: SH or HRR (compare the 'random' data field with HRR magic number) */
373 if (memcmp((void *)incoming_random, (void *)magic_HRR_random, 32) == 0)
374 *server_response *= HRR;
375 else
376 *server_response *= SH;
377 }
378 }
379
test_invalidsyntax(const struct tls13groupselection_test_st * current_test_vector,int ssl_or_ctx)380 static int test_invalidsyntax(const struct tls13groupselection_test_st *current_test_vector,
381 int ssl_or_ctx)
382 {
383 int ok = 0;
384 SSL_CTX *client_ctx = NULL, *server_ctx = NULL;
385 SSL *clientssl = NULL, *serverssl = NULL;
386
387 if (!TEST_ptr(current_test_vector->client_groups)
388 || !TEST_size_t_ne(strlen(current_test_vector->client_groups), 0))
389 goto end;
390
391 /* Creation of the contexts */
392 TEST_true_or_end(create_ssl_ctx_pair(NULL, TLS_server_method(),
393 TLS_client_method(),
394 TLS1_VERSION, 0,
395 &server_ctx, &client_ctx,
396 cert, privkey));
397
398 /* Customization of the contexts */
399 if (ssl_or_ctx == WORK_ON_CONTEXT)
400 TEST_false_or_end(SSL_CTX_set1_groups_list(client_ctx,
401 current_test_vector->client_groups));
402 /* Creation of the SSL objects */
403 TEST_true_or_end(create_ssl_objects(server_ctx, client_ctx,
404 &serverssl, &clientssl,
405 NULL, NULL));
406
407 /* Customization of the SSL objects */
408 if (ssl_or_ctx == WORK_ON_SSL_OBJECT)
409 TEST_false_or_end(SSL_set1_groups_list(clientssl, current_test_vector->client_groups));
410
411 ok = 1;
412
413 end:
414 SSL_free(serverssl);
415 SSL_free(clientssl);
416 SSL_CTX_free(server_ctx);
417 SSL_CTX_free(client_ctx);
418 return ok;
419
420 }
421
test_groupnegotiation(const struct tls13groupselection_test_st * current_test_vector,int ssl_or_ctx,TEST_TYPE test_type)422 static int test_groupnegotiation(const struct tls13groupselection_test_st *current_test_vector,
423 int ssl_or_ctx, TEST_TYPE test_type)
424 {
425 int ok = 0;
426 int negotiated_group_client = 0;
427 int negotiated_group_server = 0;
428 const char *group_name_client;
429 SSL_CTX *client_ctx = NULL, *server_ctx = NULL;
430 SSL *clientssl = NULL, *serverssl = NULL;
431 enum SERVER_RESPONSE server_response;
432
433 /* Creation of the contexts */
434 TEST_true_or_end(create_ssl_ctx_pair(NULL, TLS_server_method(),
435 TLS_client_method(),
436 TLS1_VERSION, 0,
437 &server_ctx, &client_ctx,
438 cert, privkey));
439
440 /* Customization of the contexts */
441 if (ssl_or_ctx == WORK_ON_CONTEXT) {
442 if (current_test_vector->client_groups != NULL) {
443 TEST_true_or_end(SSL_CTX_set1_groups_list(client_ctx,
444 current_test_vector->client_groups));
445 }
446 if (current_test_vector->server_groups != NULL) {
447 TEST_true_or_end(SSL_CTX_set1_groups_list(server_ctx,
448 current_test_vector->server_groups));
449 }
450 TEST_true_or_end(SSL_CTX_set_min_proto_version(client_ctx, TLS1_3_VERSION));
451 TEST_true_or_end(SSL_CTX_set_min_proto_version(server_ctx, TLS1_3_VERSION));
452 if (current_test_vector->preference == SERVER_PREFERENCE)
453 SSL_CTX_set_options(server_ctx, SSL_OP_SERVER_PREFERENCE);
454 }
455 /* Creation of the SSL objects */
456 if (!TEST_true(create_ssl_objects(server_ctx, client_ctx,
457 &serverssl, &clientssl,
458 NULL, NULL)))
459 goto end;
460
461 /* Customization of the SSL objects */
462 if (ssl_or_ctx == WORK_ON_SSL_OBJECT) {
463 if (current_test_vector->client_groups != NULL)
464 TEST_true_or_end(SSL_set1_groups_list(clientssl, current_test_vector->client_groups));
465
466 if (current_test_vector->server_groups != NULL)
467 TEST_true_or_end(SSL_set1_groups_list(serverssl, current_test_vector->server_groups));
468
469 TEST_true_or_end(SSL_set_min_proto_version(clientssl, TLS1_3_VERSION));
470 TEST_true_or_end(SSL_set_min_proto_version(serverssl, TLS1_3_VERSION));
471
472 if (current_test_vector->preference == SERVER_PREFERENCE)
473 SSL_set_options(serverssl, SSL_OP_SERVER_PREFERENCE);
474 }
475
476 /* We set the message callback on the client side (which checks SH/HRR) */
477 server_response = INIT; /* Variable to hold server response info */
478 SSL_set_msg_callback_arg(clientssl, &server_response); /* add it to the callback */
479 SSL_set_msg_callback(clientssl, server_response_check_cb); /* and activate callback */
480
481 /* Creating a test connection */
482 if (test_type == TEST_NEGOTIATION_SUCCESS) {
483 TEST_true_or_end(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE));
484
485 /*
486 * Checking that the negotiated group matches our expectation
487 * and must be identical on server and client
488 * and must be expected SH or HRR
489 */
490 negotiated_group_client = SSL_get_negotiated_group(clientssl);
491 negotiated_group_server = SSL_get_negotiated_group(serverssl);
492 group_name_client = SSL_group_to_name(clientssl, negotiated_group_client);
493 if (!TEST_int_eq(negotiated_group_client, negotiated_group_server))
494 goto end;
495 if (!TEST_int_eq((int)current_test_vector->expected_server_response, (int)server_response))
496 goto end;
497 if (TEST_str_eq(group_name_client, current_test_vector->expected_group))
498 ok = 1;
499 } else {
500 TEST_false_or_end(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE));
501 if (test_type == TEST_NEGOTIATION_FAILURE &&
502 !TEST_int_eq((int)current_test_vector->expected_server_response,
503 (int)server_response))
504 goto end;
505 ok = 1;
506 }
507
508 end:
509 SSL_free(serverssl);
510 SSL_free(clientssl);
511 SSL_CTX_free(server_ctx);
512 SSL_CTX_free(client_ctx);
513 return ok;
514 }
515
tls13groupselection_test(int i)516 static int tls13groupselection_test(int i)
517 {
518 int testresult = 1; /* Assume the test will succeed */
519 int res = 0;
520 TEST_TYPE test_type = TEST_NEGOTIATION_SUCCESS;
521
522 /*
523 * Call the code under test, once such that the ssl object is used and
524 * once such that the ctx is used. If any of the tests fail (= return 0),
525 * the end result will be 0 thanks to multiplication
526 */
527 TEST_info("==> Running TLSv1.3 test %d", i);
528
529 if (strncmp(tls13groupselection_tests[i].expected_group,
530 SYNTAX_FAILURE, sizeof(SYNTAX_FAILURE)) == 0)
531 test_type = TEST_SYNTAX_FAILURE;
532 else if (strncmp(tls13groupselection_tests[i].expected_group,
533 NEGOTIATION_FAILURE, sizeof(NEGOTIATION_FAILURE)) == 0)
534 test_type = TEST_NEGOTIATION_FAILURE;
535
536 if (test_type == TEST_SYNTAX_FAILURE)
537 res = test_invalidsyntax(&tls13groupselection_tests[i],
538 WORK_ON_SSL_OBJECT);
539 else
540 res = test_groupnegotiation(&tls13groupselection_tests[i],
541 WORK_ON_SSL_OBJECT, test_type);
542
543 if (!res)
544 TEST_error("====> [ERROR] TLSv1.3 test %d with WORK_ON_SSL_OBJECT failed", i);
545 testresult *= res;
546
547 if (test_type == TEST_SYNTAX_FAILURE)
548 res = test_invalidsyntax(&tls13groupselection_tests[i],
549 WORK_ON_CONTEXT);
550 else
551 res = test_groupnegotiation(&tls13groupselection_tests[i],
552 WORK_ON_CONTEXT, test_type);
553
554 if (!res)
555 TEST_error("====> [ERROR] TLSv1.3 test %d with WORK_ON_CONTEXT failed", i);
556 testresult *= res;
557
558 return testresult;
559 }
560
setup_tests(void)561 int setup_tests(void)
562 {
563 if (!TEST_ptr(cert = test_get_argument(0))
564 || !TEST_ptr(privkey = test_get_argument(1)))
565 return 0;
566
567 ADD_ALL_TESTS(tls13groupselection_test, OSSL_NELEM(tls13groupselection_tests));
568 return 1;
569 }
570