1 /* 2 * Copyright (c) 2015, 2020 Joel Sing <jsing@openbsd.org> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <openssl/ssl.h> 18 19 #include <err.h> 20 #include <stdio.h> 21 #include <string.h> 22 23 int ssl3_num_ciphers(void); 24 const SSL_CIPHER *ssl3_get_cipher(unsigned int u); 25 26 int ssl_parse_ciphersuites(STACK_OF(SSL_CIPHER) **out_ciphers, const char *str); 27 28 static inline int 29 ssl_aes_is_accelerated(void) 30 { 31 #if defined(__i386__) || defined(__x86_64__) 32 return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0); 33 #else 34 return (0); 35 #endif 36 } 37 38 static int 39 check_cipher_order(void) 40 { 41 unsigned long id, prev_id = 0; 42 const SSL_CIPHER *cipher; 43 int num_ciphers; 44 int i; 45 46 num_ciphers = ssl3_num_ciphers(); 47 48 for (i = 1; i <= num_ciphers; i++) { 49 /* 50 * For some reason, ssl3_get_cipher() returns ciphers in 51 * reverse order. 52 */ 53 if ((cipher = ssl3_get_cipher(num_ciphers - i)) == NULL) { 54 fprintf(stderr, "FAIL: ssl3_get_cipher(%d) returned " 55 "NULL\n", i); 56 return 1; 57 } 58 if ((id = SSL_CIPHER_get_id(cipher)) <= prev_id) { 59 fprintf(stderr, "FAIL: ssl3_ciphers is not sorted by " 60 "id - cipher %d (%lx) <= cipher %d (%lx)\n", 61 i, id, i - 1, prev_id); 62 return 1; 63 } 64 prev_id = id; 65 } 66 67 return 0; 68 } 69 70 static int 71 cipher_find_test(void) 72 { 73 STACK_OF(SSL_CIPHER) *ciphers; 74 const SSL_CIPHER *cipher; 75 unsigned char buf[2]; 76 SSL_CTX *ssl_ctx = NULL; 77 SSL *ssl = NULL; 78 int ret = 1; 79 int i; 80 81 if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) { 82 fprintf(stderr, "SSL_CTX_new() returned NULL\n"); 83 goto failure; 84 } 85 if ((ssl = SSL_new(ssl_ctx)) == NULL) { 86 fprintf(stderr, "SSL_new() returned NULL\n"); 87 goto failure; 88 } 89 if (!SSL_set_cipher_list(ssl, "ALL")) { 90 fprintf(stderr, "SSL_set_cipher_list failed\n"); 91 goto failure; 92 } 93 94 if ((ciphers = SSL_get_ciphers(ssl)) == NULL) { 95 fprintf(stderr, "no ciphers\n"); 96 goto failure; 97 } 98 99 for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { 100 uint16_t cipher_value; 101 102 cipher = sk_SSL_CIPHER_value(ciphers, i); 103 cipher_value = SSL_CIPHER_get_value(cipher); 104 105 buf[0] = cipher_value >> 8; 106 buf[1] = cipher_value & 0xff; 107 108 if ((cipher = SSL_CIPHER_find(ssl, buf)) == NULL) { 109 fprintf(stderr, 110 "SSL_CIPHER_find() returned NULL for %s\n", 111 SSL_CIPHER_get_name(cipher)); 112 goto failure; 113 } 114 115 if (SSL_CIPHER_get_value(cipher) != cipher_value) { 116 fprintf(stderr, 117 "got cipher with value 0x%x, want 0x%x\n", 118 SSL_CIPHER_get_value(cipher), cipher_value); 119 goto failure; 120 } 121 } 122 123 ret = 0; 124 125 failure: 126 SSL_CTX_free(ssl_ctx); 127 SSL_free(ssl); 128 129 return (ret); 130 } 131 132 static int 133 cipher_get_by_value_tests(void) 134 { 135 STACK_OF(SSL_CIPHER) *ciphers; 136 const SSL_CIPHER *cipher; 137 SSL_CTX *ssl_ctx = NULL; 138 SSL *ssl = NULL; 139 unsigned long id; 140 uint16_t value; 141 int ret = 1; 142 int i; 143 144 if ((ssl_ctx = SSL_CTX_new(SSLv23_method())) == NULL) { 145 fprintf(stderr, "SSL_CTX_new() returned NULL\n"); 146 goto failure; 147 } 148 if ((ssl = SSL_new(ssl_ctx)) == NULL) { 149 fprintf(stderr, "SSL_new() returned NULL\n"); 150 goto failure; 151 } 152 153 if ((ciphers = SSL_get_ciphers(ssl)) == NULL) { 154 fprintf(stderr, "no ciphers\n"); 155 goto failure; 156 } 157 158 for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { 159 cipher = sk_SSL_CIPHER_value(ciphers, i); 160 161 id = SSL_CIPHER_get_id(cipher); 162 if (SSL_CIPHER_get_by_id(id) == NULL) { 163 fprintf(stderr, "SSL_CIPHER_get_by_id() failed " 164 "for %s (0x%lx)\n", SSL_CIPHER_get_name(cipher), 165 id); 166 goto failure; 167 } 168 169 value = SSL_CIPHER_get_value(cipher); 170 if (SSL_CIPHER_get_by_value(value) == NULL) { 171 fprintf(stderr, "SSL_CIPHER_get_by_value() failed " 172 "for %s (0x%04hx)\n", SSL_CIPHER_get_name(cipher), 173 value); 174 goto failure; 175 } 176 } 177 178 ret = 0; 179 180 failure: 181 SSL_CTX_free(ssl_ctx); 182 SSL_free(ssl); 183 184 return (ret); 185 } 186 187 struct parse_ciphersuites_test { 188 const char *str; 189 const int want; 190 const unsigned long cids[32]; 191 }; 192 193 struct parse_ciphersuites_test parse_ciphersuites_tests[] = { 194 { 195 /* LibreSSL names. */ 196 .str = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256:AEAD-AES128-GCM-SHA256", 197 .want = 1, 198 .cids = { 199 TLS1_3_CK_AES_256_GCM_SHA384, 200 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 201 TLS1_3_CK_AES_128_GCM_SHA256, 202 }, 203 }, 204 { 205 /* OpenSSL names. */ 206 .str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256", 207 .want = 1, 208 .cids = { 209 TLS1_3_CK_AES_256_GCM_SHA384, 210 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 211 TLS1_3_CK_AES_128_GCM_SHA256, 212 }, 213 }, 214 { 215 /* Different priority order. */ 216 .str = "AEAD-AES128-GCM-SHA256:AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 217 .want = 1, 218 .cids = { 219 TLS1_3_CK_AES_128_GCM_SHA256, 220 TLS1_3_CK_AES_256_GCM_SHA384, 221 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 222 }, 223 }, 224 { 225 /* Known but unsupported names. */ 226 .str = "AEAD-AES256-GCM-SHA384:AEAD-AES128-CCM-SHA256:AEAD-AES128-CCM-8-SHA256", 227 .want = 1, 228 .cids = { 229 TLS1_3_CK_AES_256_GCM_SHA384, 230 }, 231 }, 232 { 233 /* Empty string means no TLSv1.3 ciphersuites. */ 234 .str = "", 235 .want = 1, 236 .cids = { 0 }, 237 }, 238 { 239 .str = "TLS_CHACHA20_POLY1305_SHA256:TLS_NOT_A_CIPHERSUITE", 240 .want = 0, 241 }, 242 { 243 .str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256", 244 .want = 0, 245 }, 246 }; 247 248 #define N_PARSE_CIPHERSUITES_TESTS \ 249 (sizeof(parse_ciphersuites_tests) / sizeof(*parse_ciphersuites_tests)) 250 251 static int 252 parse_ciphersuites_test(void) 253 { 254 struct parse_ciphersuites_test *pct; 255 STACK_OF(SSL_CIPHER) *ciphers = NULL; 256 SSL_CIPHER *cipher; 257 int failed = 1; 258 int j, ret; 259 size_t i; 260 261 for (i = 0; i < N_PARSE_CIPHERSUITES_TESTS; i++) { 262 pct = &parse_ciphersuites_tests[i]; 263 264 ret = ssl_parse_ciphersuites(&ciphers, pct->str); 265 if (ret != pct->want) { 266 fprintf(stderr, "FAIL: test %zu - " 267 "ssl_parse_ciphersuites returned %d, want %d\n", 268 i, ret, pct->want); 269 goto failed; 270 } 271 if (ret == 0) 272 continue; 273 274 for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { 275 cipher = sk_SSL_CIPHER_value(ciphers, j); 276 if (SSL_CIPHER_get_id(cipher) == pct->cids[j]) 277 continue; 278 fprintf(stderr, "FAIL: test %zu - got cipher %d with " 279 "id %lx, want %lx\n", i, j, 280 SSL_CIPHER_get_id(cipher), pct->cids[j]); 281 goto failed; 282 } 283 if (pct->cids[j] != 0) { 284 fprintf(stderr, "FAIL: test %zu - got %d ciphers, " 285 "expected more", i, sk_SSL_CIPHER_num(ciphers)); 286 goto failed; 287 } 288 } 289 290 failed = 0; 291 292 failed: 293 sk_SSL_CIPHER_free(ciphers); 294 295 return failed; 296 } 297 298 struct cipher_set_test { 299 int ctx_ciphersuites_first; 300 const char *ctx_ciphersuites; 301 const char *ctx_rulestr; 302 int ssl_ciphersuites_first; 303 const char *ssl_ciphersuites; 304 const char *ssl_rulestr; 305 int cids_aes_accel_fixup; 306 unsigned long cids[32]; 307 }; 308 309 struct cipher_set_test cipher_set_tests[] = { 310 { 311 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 312 .cids_aes_accel_fixup = 1, 313 .cids = { 314 TLS1_3_CK_AES_256_GCM_SHA384, 315 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 316 TLS1_3_CK_AES_128_GCM_SHA256, 317 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 318 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 319 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 320 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 321 }, 322 }, 323 { 324 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 325 .cids_aes_accel_fixup = 1, 326 .cids = { 327 TLS1_3_CK_AES_256_GCM_SHA384, 328 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 329 TLS1_3_CK_AES_128_GCM_SHA256, 330 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 331 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 332 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 333 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 334 }, 335 }, 336 { 337 .ctx_ciphersuites_first = 1, 338 .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 339 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 340 .cids = { 341 TLS1_3_CK_AES_256_GCM_SHA384, 342 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 343 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 344 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 345 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 346 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 347 }, 348 }, 349 { 350 .ssl_ciphersuites_first = 1, 351 .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 352 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 353 .cids = { 354 TLS1_3_CK_AES_256_GCM_SHA384, 355 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 356 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 357 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 358 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 359 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 360 }, 361 }, 362 { 363 .ctx_ciphersuites_first = 0, 364 .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 365 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 366 .cids = { 367 TLS1_3_CK_AES_256_GCM_SHA384, 368 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 369 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 370 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 371 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 372 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 373 }, 374 }, 375 { 376 .ssl_ciphersuites_first = 0, 377 .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 378 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 379 .cids = { 380 TLS1_3_CK_AES_256_GCM_SHA384, 381 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 382 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 383 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 384 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 385 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 386 }, 387 }, 388 { 389 .ssl_ciphersuites_first = 1, 390 .ssl_ciphersuites = "", 391 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 392 .cids = { 393 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 394 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 395 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 396 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 397 }, 398 }, 399 { 400 .ssl_ciphersuites_first = 0, 401 .ssl_ciphersuites = "", 402 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 403 .cids = { 404 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 405 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 406 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 407 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 408 }, 409 }, 410 { 411 .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 412 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 413 .cids = { 414 TLS1_3_CK_AES_256_GCM_SHA384, 415 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 416 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 417 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 418 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 419 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 420 }, 421 }, 422 { 423 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 424 .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 425 .cids = { 426 TLS1_3_CK_AES_256_GCM_SHA384, 427 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 428 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 429 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 430 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 431 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 432 }, 433 }, 434 }; 435 436 #define N_CIPHER_SET_TESTS \ 437 (sizeof(cipher_set_tests) / sizeof(*cipher_set_tests)) 438 439 static int 440 cipher_set_test(void) 441 { 442 struct cipher_set_test *cst; 443 STACK_OF(SSL_CIPHER) *ciphers = NULL; 444 SSL_CIPHER *cipher; 445 SSL_CTX *ctx = NULL; 446 SSL *ssl = NULL; 447 int failed = 0; 448 size_t i; 449 int j; 450 451 for (i = 0; i < N_CIPHER_SET_TESTS; i++) { 452 cst = &cipher_set_tests[i]; 453 454 if (!ssl_aes_is_accelerated() && cst->cids_aes_accel_fixup) { 455 cst->cids[0] = TLS1_3_CK_CHACHA20_POLY1305_SHA256; 456 cst->cids[1] = TLS1_3_CK_AES_256_GCM_SHA384; 457 } 458 459 if ((ctx = SSL_CTX_new(TLS_method())) == NULL) 460 errx(1, "SSL_CTX_new"); 461 462 if (cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) { 463 if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites)) 464 errx(1, "SSL_CTX_set_ciphersuites"); 465 } 466 if (cst->ctx_rulestr != NULL) { 467 if (!SSL_CTX_set_cipher_list(ctx, cst->ctx_rulestr)) 468 errx(1, "SSL_CTX_set_cipher_list"); 469 } 470 if (!cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) { 471 if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites)) 472 errx(1, "SSL_CTX_set_ciphersuites"); 473 } 474 475 /* XXX - check SSL_CTX_get_ciphers(ctx) */ 476 477 if ((ssl = SSL_new(ctx)) == NULL) 478 errx(1, "SSL_new"); 479 480 if (cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) { 481 if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites)) 482 errx(1, "SSL_set_ciphersuites"); 483 } 484 if (cst->ssl_rulestr != NULL) { 485 if (!SSL_set_cipher_list(ssl, cst->ssl_rulestr)) 486 errx(1, "SSL_set_cipher_list"); 487 } 488 if (!cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) { 489 if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites)) 490 errx(1, "SSL_set_ciphersuites"); 491 } 492 493 ciphers = SSL_get_ciphers(ssl); 494 495 for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { 496 cipher = sk_SSL_CIPHER_value(ciphers, j); 497 if (SSL_CIPHER_get_id(cipher) == cst->cids[j]) 498 continue; 499 fprintf(stderr, "FAIL: test %zu - got cipher %d with " 500 "id %lx, want %lx\n", i, j, 501 SSL_CIPHER_get_id(cipher), cst->cids[j]); 502 failed |= 1; 503 } 504 if (cst->cids[j] != 0) { 505 fprintf(stderr, "FAIL: test %zu - got %d ciphers, " 506 "expected more", i, sk_SSL_CIPHER_num(ciphers)); 507 failed |= 1; 508 } 509 510 SSL_CTX_free(ctx); 511 SSL_free(ssl); 512 } 513 514 return failed; 515 } 516 517 int 518 main(int argc, char **argv) 519 { 520 int failed = 0; 521 522 failed |= check_cipher_order(); 523 524 failed |= cipher_find_test(); 525 failed |= cipher_get_by_value_tests(); 526 527 failed |= parse_ciphersuites_test(); 528 failed |= cipher_set_test(); 529 530 return (failed); 531 } 532