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 ssl_parse_ciphersuites(STACK_OF(SSL_CIPHER) **out_ciphers, const char *str); 24 25 static inline int 26 ssl_aes_is_accelerated(void) 27 { 28 #if defined(__i386__) || defined(__x86_64__) 29 return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0); 30 #else 31 return (0); 32 #endif 33 } 34 35 static int 36 get_put_test(const char *name, const SSL_METHOD *method) 37 { 38 STACK_OF(SSL_CIPHER) *ciphers; 39 const SSL_CIPHER *cipher; 40 unsigned char buf[2]; 41 SSL_CTX *ssl_ctx = NULL; 42 SSL *ssl = NULL; 43 int ret = 1; 44 int i, len; 45 46 if ((len = method->put_cipher_by_char(NULL, NULL)) != 2) { 47 fprintf(stderr, 48 "%s: put_cipher_by_char() returned len %i (want 2)\n", 49 name, len); 50 return (1); 51 } 52 53 if ((ssl_ctx = SSL_CTX_new(method)) == NULL) { 54 fprintf(stderr, "%s: SSL_CTX_new() returned NULL\n", name); 55 goto failure; 56 } 57 if ((ssl = SSL_new(ssl_ctx)) == NULL) { 58 fprintf(stderr, "%s: SSL_new() returned NULL\n", name); 59 goto failure; 60 } 61 62 if ((ciphers = SSL_get_ciphers(ssl)) == NULL) { 63 fprintf(stderr, "%s: no ciphers\n", name); 64 goto failure; 65 } 66 67 for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { 68 cipher = sk_SSL_CIPHER_value(ciphers, i); 69 if ((len = method->put_cipher_by_char(cipher, buf)) != 2) { 70 fprintf(stderr, 71 "%s: put_cipher_by_char() returned len %i for %s " 72 "(want 2)\n", 73 name, len, SSL_CIPHER_get_name(cipher)); 74 goto failure; 75 } 76 if ((cipher = method->get_cipher_by_char(buf)) == NULL) { 77 fprintf(stderr, 78 "%s: get_cipher_by_char() returned NULL for %s\n", 79 name, SSL_CIPHER_get_name(cipher)); 80 goto failure; 81 } 82 } 83 84 ret = 0; 85 86 failure: 87 SSL_CTX_free(ssl_ctx); 88 SSL_free(ssl); 89 90 return (ret); 91 } 92 93 static int 94 cipher_get_put_tests(void) 95 { 96 int failed = 0; 97 98 failed |= get_put_test("SSLv23", SSLv23_method()); 99 failed |= get_put_test("SSLv23_client", SSLv23_client_method()); 100 failed |= get_put_test("SSLv23_server", SSLv23_server_method()); 101 102 failed |= get_put_test("TLSv1", TLSv1_method()); 103 failed |= get_put_test("TLSv1_client", TLSv1_client_method()); 104 failed |= get_put_test("TLSv1_server", TLSv1_server_method()); 105 106 failed |= get_put_test("TLSv1_1", TLSv1_1_method()); 107 failed |= get_put_test("TLSv1_1_client", TLSv1_1_client_method()); 108 failed |= get_put_test("TLSv1_1_server", TLSv1_1_server_method()); 109 110 failed |= get_put_test("TLSv1_2", TLSv1_2_method()); 111 failed |= get_put_test("TLSv1_2_client", TLSv1_2_client_method()); 112 failed |= get_put_test("TLSv1_2_server", TLSv1_2_server_method()); 113 114 failed |= get_put_test("DTLSv1", DTLSv1_method()); 115 failed |= get_put_test("DTLSv1_client", DTLSv1_client_method()); 116 failed |= get_put_test("DTLSv1_server", DTLSv1_server_method()); 117 118 return failed; 119 } 120 121 static int 122 cipher_get_by_value_tests(void) 123 { 124 STACK_OF(SSL_CIPHER) *ciphers; 125 const SSL_CIPHER *cipher; 126 SSL_CTX *ssl_ctx = NULL; 127 SSL *ssl = NULL; 128 unsigned long id; 129 uint16_t value; 130 int ret = 1; 131 int i; 132 133 if ((ssl_ctx = SSL_CTX_new(SSLv23_method())) == NULL) { 134 fprintf(stderr, "SSL_CTX_new() returned NULL\n"); 135 goto failure; 136 } 137 if ((ssl = SSL_new(ssl_ctx)) == NULL) { 138 fprintf(stderr, "SSL_new() returned NULL\n"); 139 goto failure; 140 } 141 142 if ((ciphers = SSL_get_ciphers(ssl)) == NULL) { 143 fprintf(stderr, "no ciphers\n"); 144 goto failure; 145 } 146 147 for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { 148 cipher = sk_SSL_CIPHER_value(ciphers, i); 149 150 id = SSL_CIPHER_get_id(cipher); 151 if (SSL_CIPHER_get_by_id(id) == NULL) { 152 fprintf(stderr, "SSL_CIPHER_get_by_id() failed " 153 "for %s (0x%lx)\n", SSL_CIPHER_get_name(cipher), 154 id); 155 goto failure; 156 } 157 158 value = SSL_CIPHER_get_value(cipher); 159 if (SSL_CIPHER_get_by_value(value) == NULL) { 160 fprintf(stderr, "SSL_CIPHER_get_by_value() failed " 161 "for %s (0x%04hx)\n", SSL_CIPHER_get_name(cipher), 162 value); 163 goto failure; 164 } 165 } 166 167 ret = 0; 168 169 failure: 170 SSL_CTX_free(ssl_ctx); 171 SSL_free(ssl); 172 173 return (ret); 174 } 175 176 struct parse_ciphersuites_test { 177 const char *str; 178 const int want; 179 const unsigned long cids[32]; 180 }; 181 182 struct parse_ciphersuites_test parse_ciphersuites_tests[] = { 183 { 184 /* LibreSSL names. */ 185 .str = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256:AEAD-AES128-GCM-SHA256", 186 .want = 1, 187 .cids = { 188 TLS1_3_CK_AES_256_GCM_SHA384, 189 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 190 TLS1_3_CK_AES_128_GCM_SHA256, 191 }, 192 }, 193 { 194 /* OpenSSL names. */ 195 .str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256", 196 .want = 1, 197 .cids = { 198 TLS1_3_CK_AES_256_GCM_SHA384, 199 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 200 TLS1_3_CK_AES_128_GCM_SHA256, 201 }, 202 }, 203 { 204 /* Different priority order. */ 205 .str = "AEAD-AES128-GCM-SHA256:AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 206 .want = 1, 207 .cids = { 208 TLS1_3_CK_AES_128_GCM_SHA256, 209 TLS1_3_CK_AES_256_GCM_SHA384, 210 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 211 }, 212 }, 213 { 214 /* Known but unsupported names. */ 215 .str = "AEAD-AES256-GCM-SHA384:AEAD-AES128-CCM-SHA256:AEAD-AES128-CCM-8-SHA256", 216 .want = 1, 217 .cids = { 218 TLS1_3_CK_AES_256_GCM_SHA384, 219 }, 220 }, 221 { 222 /* Empty string means no TLSv1.3 ciphersuites. */ 223 .str = "", 224 .want = 1, 225 .cids = { 0 }, 226 }, 227 { 228 .str = "TLS_CHACHA20_POLY1305_SHA256:TLS_NOT_A_CIPHERSUITE", 229 .want = 0, 230 }, 231 { 232 .str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256", 233 .want = 0, 234 }, 235 }; 236 237 #define N_PARSE_CIPHERSUITES_TESTS \ 238 (sizeof(parse_ciphersuites_tests) / sizeof(*parse_ciphersuites_tests)) 239 240 static int 241 parse_ciphersuites_test(void) 242 { 243 struct parse_ciphersuites_test *pct; 244 STACK_OF(SSL_CIPHER) *ciphers = NULL; 245 SSL_CIPHER *cipher; 246 int failed = 1; 247 int j, ret; 248 size_t i; 249 250 for (i = 0; i < N_PARSE_CIPHERSUITES_TESTS; i++) { 251 pct = &parse_ciphersuites_tests[i]; 252 253 ret = ssl_parse_ciphersuites(&ciphers, pct->str); 254 if (ret != pct->want) { 255 fprintf(stderr, "FAIL: test %zu - " 256 "ssl_parse_ciphersuites returned %d, want %d\n", 257 i, ret, pct->want); 258 goto failed; 259 } 260 if (ret == 0) 261 continue; 262 263 for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { 264 cipher = sk_SSL_CIPHER_value(ciphers, j); 265 if (SSL_CIPHER_get_id(cipher) == pct->cids[j]) 266 continue; 267 fprintf(stderr, "FAIL: test %zu - got cipher %d with " 268 "id %lx, want %lx\n", i, j, 269 SSL_CIPHER_get_id(cipher), pct->cids[j]); 270 goto failed; 271 } 272 if (pct->cids[j] != 0) { 273 fprintf(stderr, "FAIL: test %zu - got %d ciphers, " 274 "expected more", i, sk_SSL_CIPHER_num(ciphers)); 275 goto failed; 276 } 277 } 278 279 failed = 0; 280 281 failed: 282 sk_SSL_CIPHER_free(ciphers); 283 284 return failed; 285 } 286 287 struct cipher_set_test { 288 int ctx_ciphersuites_first; 289 const char *ctx_ciphersuites; 290 const char *ctx_rulestr; 291 int ssl_ciphersuites_first; 292 const char *ssl_ciphersuites; 293 const char *ssl_rulestr; 294 int cids_aes_accel_fixup; 295 unsigned long cids[32]; 296 }; 297 298 struct cipher_set_test cipher_set_tests[] = { 299 { 300 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 301 .cids_aes_accel_fixup = 1, 302 .cids = { 303 TLS1_3_CK_AES_256_GCM_SHA384, 304 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 305 TLS1_3_CK_AES_128_GCM_SHA256, 306 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 307 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 308 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 309 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 310 }, 311 }, 312 { 313 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 314 .cids_aes_accel_fixup = 1, 315 .cids = { 316 TLS1_3_CK_AES_256_GCM_SHA384, 317 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 318 TLS1_3_CK_AES_128_GCM_SHA256, 319 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 320 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 321 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 322 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 323 }, 324 }, 325 { 326 .ctx_ciphersuites_first = 1, 327 .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 328 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 329 .cids = { 330 TLS1_3_CK_AES_256_GCM_SHA384, 331 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 332 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 333 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 334 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 335 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 336 }, 337 }, 338 { 339 .ssl_ciphersuites_first = 1, 340 .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 341 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 342 .cids = { 343 TLS1_3_CK_AES_256_GCM_SHA384, 344 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 345 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 346 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 347 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 348 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 349 }, 350 }, 351 { 352 .ctx_ciphersuites_first = 0, 353 .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 354 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 355 .cids = { 356 TLS1_3_CK_AES_256_GCM_SHA384, 357 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 358 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 359 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 360 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 361 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 362 }, 363 }, 364 { 365 .ssl_ciphersuites_first = 0, 366 .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 367 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 368 .cids = { 369 TLS1_3_CK_AES_256_GCM_SHA384, 370 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 371 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 372 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 373 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 374 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 375 }, 376 }, 377 { 378 .ssl_ciphersuites_first = 1, 379 .ssl_ciphersuites = "", 380 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 381 .cids = { 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 = 0, 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 .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 401 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 402 .cids = { 403 TLS1_3_CK_AES_256_GCM_SHA384, 404 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 405 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 406 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 407 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 408 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 409 }, 410 }, 411 { 412 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 413 .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 414 .cids = { 415 TLS1_3_CK_AES_256_GCM_SHA384, 416 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 417 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 418 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 419 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 420 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 421 }, 422 }, 423 }; 424 425 #define N_CIPHER_SET_TESTS \ 426 (sizeof(cipher_set_tests) / sizeof(*cipher_set_tests)) 427 428 static int 429 cipher_set_test(void) 430 { 431 struct cipher_set_test *cst; 432 STACK_OF(SSL_CIPHER) *ciphers = NULL; 433 SSL_CIPHER *cipher; 434 SSL_CTX *ctx = NULL; 435 SSL *ssl = NULL; 436 int failed = 0; 437 size_t i; 438 int j; 439 440 for (i = 0; i < N_CIPHER_SET_TESTS; i++) { 441 cst = &cipher_set_tests[i]; 442 443 if (!ssl_aes_is_accelerated() && cst->cids_aes_accel_fixup) { 444 cst->cids[0] = TLS1_3_CK_CHACHA20_POLY1305_SHA256; 445 cst->cids[1] = TLS1_3_CK_AES_256_GCM_SHA384; 446 } 447 448 if ((ctx = SSL_CTX_new(TLS_method())) == NULL) 449 errx(1, "SSL_CTX_new"); 450 451 if (cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) { 452 if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites)) 453 errx(1, "SSL_CTX_set_ciphersuites"); 454 } 455 if (cst->ctx_rulestr != NULL) { 456 if (!SSL_CTX_set_cipher_list(ctx, cst->ctx_rulestr)) 457 errx(1, "SSL_CTX_set_cipher_list"); 458 } 459 if (!cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) { 460 if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites)) 461 errx(1, "SSL_CTX_set_ciphersuites"); 462 } 463 464 /* XXX - check SSL_CTX_get_ciphers(ctx) */ 465 466 if ((ssl = SSL_new(ctx)) == NULL) 467 errx(1, "SSL_new"); 468 469 if (cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) { 470 if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites)) 471 errx(1, "SSL_set_ciphersuites"); 472 } 473 if (cst->ssl_rulestr != NULL) { 474 if (!SSL_set_cipher_list(ssl, cst->ssl_rulestr)) 475 errx(1, "SSL_set_cipher_list"); 476 } 477 if (!cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) { 478 if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites)) 479 errx(1, "SSL_set_ciphersuites"); 480 } 481 482 ciphers = SSL_get_ciphers(ssl); 483 484 for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { 485 cipher = sk_SSL_CIPHER_value(ciphers, j); 486 if (SSL_CIPHER_get_id(cipher) == cst->cids[j]) 487 continue; 488 fprintf(stderr, "FAIL: test %zu - got cipher %d with " 489 "id %lx, want %lx\n", i, j, 490 SSL_CIPHER_get_id(cipher), cst->cids[j]); 491 failed |= 1; 492 } 493 if (cst->cids[j] != 0) { 494 fprintf(stderr, "FAIL: test %zu - got %d ciphers, " 495 "expected more", i, sk_SSL_CIPHER_num(ciphers)); 496 failed |= 1; 497 } 498 499 SSL_CTX_free(ctx); 500 SSL_free(ssl); 501 } 502 503 return failed; 504 } 505 506 int 507 main(int argc, char **argv) 508 { 509 int failed = 0; 510 511 failed |= cipher_get_put_tests(); 512 failed |= cipher_get_by_value_tests(); 513 514 failed |= parse_ciphersuites_test(); 515 failed |= cipher_set_test(); 516 517 return (failed); 518 } 519