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