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 struct parse_ciphersuites_test { 133 const char *str; 134 const int want; 135 const unsigned long cids[32]; 136 }; 137 138 struct parse_ciphersuites_test parse_ciphersuites_tests[] = { 139 { 140 /* LibreSSL names. */ 141 .str = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256:AEAD-AES128-GCM-SHA256", 142 .want = 1, 143 .cids = { 144 TLS1_3_CK_AES_256_GCM_SHA384, 145 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 146 TLS1_3_CK_AES_128_GCM_SHA256, 147 }, 148 }, 149 { 150 /* OpenSSL names. */ 151 .str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256", 152 .want = 1, 153 .cids = { 154 TLS1_3_CK_AES_256_GCM_SHA384, 155 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 156 TLS1_3_CK_AES_128_GCM_SHA256, 157 }, 158 }, 159 { 160 /* Different priority order. */ 161 .str = "AEAD-AES128-GCM-SHA256:AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 162 .want = 1, 163 .cids = { 164 TLS1_3_CK_AES_128_GCM_SHA256, 165 TLS1_3_CK_AES_256_GCM_SHA384, 166 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 167 }, 168 }, 169 { 170 /* Known but unsupported names. */ 171 .str = "AEAD-AES256-GCM-SHA384:AEAD-AES128-CCM-SHA256:AEAD-AES128-CCM-8-SHA256", 172 .want = 1, 173 .cids = { 174 TLS1_3_CK_AES_256_GCM_SHA384, 175 }, 176 }, 177 { 178 /* Empty string means no TLSv1.3 ciphersuites. */ 179 .str = "", 180 .want = 1, 181 .cids = { 0 }, 182 }, 183 { 184 .str = "TLS_CHACHA20_POLY1305_SHA256:TLS_NOT_A_CIPHERSUITE", 185 .want = 0, 186 }, 187 { 188 .str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256", 189 .want = 0, 190 }, 191 }; 192 193 #define N_PARSE_CIPHERSUITES_TESTS \ 194 (sizeof(parse_ciphersuites_tests) / sizeof(*parse_ciphersuites_tests)) 195 196 static int 197 parse_ciphersuites_test(void) 198 { 199 struct parse_ciphersuites_test *pct; 200 STACK_OF(SSL_CIPHER) *ciphers = NULL; 201 SSL_CIPHER *cipher; 202 int failed = 1; 203 int j, ret; 204 size_t i; 205 206 for (i = 0; i < N_PARSE_CIPHERSUITES_TESTS; i++) { 207 pct = &parse_ciphersuites_tests[i]; 208 209 ret = ssl_parse_ciphersuites(&ciphers, pct->str); 210 if (ret != pct->want) { 211 fprintf(stderr, "FAIL: test %zu - " 212 "ssl_parse_ciphersuites returned %d, want %d\n", 213 i, ret, pct->want); 214 goto failed; 215 } 216 if (ret == 0) 217 continue; 218 219 for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { 220 cipher = sk_SSL_CIPHER_value(ciphers, j); 221 if (SSL_CIPHER_get_id(cipher) == pct->cids[j]) 222 continue; 223 fprintf(stderr, "FAIL: test %zu - got cipher %d with " 224 "id %lx, want %lx\n", i, j, 225 SSL_CIPHER_get_id(cipher), pct->cids[j]); 226 goto failed; 227 } 228 if (pct->cids[j] != 0) { 229 fprintf(stderr, "FAIL: test %zu - got %d ciphers, " 230 "expected more", i, sk_SSL_CIPHER_num(ciphers)); 231 goto failed; 232 } 233 } 234 235 failed = 0; 236 237 failed: 238 sk_SSL_CIPHER_free(ciphers); 239 240 return failed; 241 } 242 243 struct cipher_set_test { 244 int ctx_ciphersuites_first; 245 const char *ctx_ciphersuites; 246 const char *ctx_rulestr; 247 int ssl_ciphersuites_first; 248 const char *ssl_ciphersuites; 249 const char *ssl_rulestr; 250 int cids_aes_accel_fixup; 251 unsigned long cids[32]; 252 }; 253 254 struct cipher_set_test cipher_set_tests[] = { 255 { 256 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 257 .cids_aes_accel_fixup = 1, 258 .cids = { 259 TLS1_3_CK_AES_256_GCM_SHA384, 260 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 261 TLS1_3_CK_AES_128_GCM_SHA256, 262 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 263 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 264 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 265 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 266 }, 267 }, 268 { 269 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 270 .cids_aes_accel_fixup = 1, 271 .cids = { 272 TLS1_3_CK_AES_256_GCM_SHA384, 273 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 274 TLS1_3_CK_AES_128_GCM_SHA256, 275 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 276 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 277 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 278 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 279 }, 280 }, 281 { 282 .ctx_ciphersuites_first = 1, 283 .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 284 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 285 .cids = { 286 TLS1_3_CK_AES_256_GCM_SHA384, 287 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 288 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 289 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 290 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 291 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 292 }, 293 }, 294 { 295 .ssl_ciphersuites_first = 1, 296 .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 297 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 298 .cids = { 299 TLS1_3_CK_AES_256_GCM_SHA384, 300 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 301 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 302 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 303 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 304 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 305 }, 306 }, 307 { 308 .ctx_ciphersuites_first = 0, 309 .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 310 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 311 .cids = { 312 TLS1_3_CK_AES_256_GCM_SHA384, 313 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 314 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 315 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 316 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 317 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 318 }, 319 }, 320 { 321 .ssl_ciphersuites_first = 0, 322 .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 323 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 324 .cids = { 325 TLS1_3_CK_AES_256_GCM_SHA384, 326 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 327 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 328 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 329 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 330 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 331 }, 332 }, 333 { 334 .ssl_ciphersuites_first = 1, 335 .ssl_ciphersuites = "", 336 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 337 .cids = { 338 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 339 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 340 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 341 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 342 }, 343 }, 344 { 345 .ssl_ciphersuites_first = 0, 346 .ssl_ciphersuites = "", 347 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 348 .cids = { 349 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 350 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 351 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 352 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 353 }, 354 }, 355 { 356 .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 357 .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 358 .cids = { 359 TLS1_3_CK_AES_256_GCM_SHA384, 360 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 361 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 362 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 363 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 364 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 365 }, 366 }, 367 { 368 .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", 369 .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", 370 .cids = { 371 TLS1_3_CK_AES_256_GCM_SHA384, 372 TLS1_3_CK_CHACHA20_POLY1305_SHA256, 373 TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 374 TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 375 TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 376 TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 377 }, 378 }, 379 }; 380 381 #define N_CIPHER_SET_TESTS \ 382 (sizeof(cipher_set_tests) / sizeof(*cipher_set_tests)) 383 384 static int 385 cipher_set_test(void) 386 { 387 struct cipher_set_test *cst; 388 STACK_OF(SSL_CIPHER) *ciphers = NULL; 389 SSL_CIPHER *cipher; 390 SSL_CTX *ctx = NULL; 391 SSL *ssl = NULL; 392 int failed = 0; 393 size_t i; 394 int j; 395 396 for (i = 0; i < N_CIPHER_SET_TESTS; i++) { 397 cst = &cipher_set_tests[i]; 398 399 if (!ssl_aes_is_accelerated() && cst->cids_aes_accel_fixup) { 400 cst->cids[0] = TLS1_3_CK_CHACHA20_POLY1305_SHA256; 401 cst->cids[1] = TLS1_3_CK_AES_256_GCM_SHA384; 402 } 403 404 if ((ctx = SSL_CTX_new(TLS_method())) == NULL) 405 errx(1, "SSL_CTX_new"); 406 407 if (cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) { 408 if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites)) 409 errx(1, "SSL_CTX_set_ciphersuites"); 410 } 411 if (cst->ctx_rulestr != NULL) { 412 if (!SSL_CTX_set_cipher_list(ctx, cst->ctx_rulestr)) 413 errx(1, "SSL_CTX_set_cipher_list"); 414 } 415 if (!cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) { 416 if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites)) 417 errx(1, "SSL_CTX_set_ciphersuites"); 418 } 419 420 /* XXX - check SSL_CTX_get_ciphers(ctx) */ 421 422 if ((ssl = SSL_new(ctx)) == NULL) 423 errx(1, "SSL_new"); 424 425 if (cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) { 426 if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites)) 427 errx(1, "SSL_set_ciphersuites"); 428 } 429 if (cst->ssl_rulestr != NULL) { 430 if (!SSL_set_cipher_list(ssl, cst->ssl_rulestr)) 431 errx(1, "SSL_set_cipher_list"); 432 } 433 if (!cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) { 434 if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites)) 435 errx(1, "SSL_set_ciphersuites"); 436 } 437 438 ciphers = SSL_get_ciphers(ssl); 439 440 for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { 441 cipher = sk_SSL_CIPHER_value(ciphers, j); 442 if (SSL_CIPHER_get_id(cipher) == cst->cids[j]) 443 continue; 444 fprintf(stderr, "FAIL: test %zu - got cipher %d with " 445 "id %lx, want %lx\n", i, j, 446 SSL_CIPHER_get_id(cipher), cst->cids[j]); 447 failed |= 1; 448 } 449 if (cst->cids[j] != 0) { 450 fprintf(stderr, "FAIL: test %zu - got %d ciphers, " 451 "expected more", i, sk_SSL_CIPHER_num(ciphers)); 452 failed |= 1; 453 } 454 455 SSL_CTX_free(ctx); 456 SSL_free(ssl); 457 } 458 459 return failed; 460 } 461 462 int 463 main(int argc, char **argv) 464 { 465 int failed = 0; 466 467 failed |= check_cipher_order(); 468 469 failed |= cipher_find_test(); 470 471 failed |= parse_ciphersuites_test(); 472 failed |= cipher_set_test(); 473 474 return (failed); 475 } 476