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 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 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 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_CIPHER_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_CIPHER_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 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 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