1 /* 2 * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <stdint.h> 29 #include <errno.h> 30 31 #ifdef _WIN32 32 #include <windows.h> 33 #else 34 #include <signal.h> 35 #include <sys/types.h> 36 #include <unistd.h> 37 #endif 38 39 #include "brssl.h" 40 41 static int verbose = 0; 42 43 static void 44 usage_twrch(void) 45 { 46 fprintf(stderr, 47 "usage: brssl twrch [ options ]\n"); 48 fprintf(stderr, 49 "options:\n"); 50 fprintf(stderr, 51 " -trace dump all packets on stderr\n"); 52 fprintf(stderr, 53 " -v verbose error messages on stderr\n"); 54 fprintf(stderr, 55 " -server act as an SSL server\n"); 56 fprintf(stderr, 57 " -client act as an SSL client\n"); 58 fprintf(stderr, 59 " -sni name use specified name for SNI\n"); 60 fprintf(stderr, 61 " -mono use monodirectional buffering\n"); 62 fprintf(stderr, 63 " -buf length set the I/O buffer length (in bytes)\n"); 64 fprintf(stderr, 65 " -cache length set the session cache storage length (in bytes)\n"); 66 fprintf(stderr, 67 " -cert fname read certificate chain from file 'fname'\n"); 68 fprintf(stderr, 69 " -key fname read private key from file 'fname'\n"); 70 fprintf(stderr, 71 " -CA file add trust anchors from 'file' (for peer auth)\n"); 72 fprintf(stderr, 73 " -anon_ok request but do not require a client certificate\n"); 74 fprintf(stderr, 75 " -nostaticecdh prohibit full-static ECDH (client only)\n"); 76 fprintf(stderr, 77 " -list list supported names (protocols, algorithms...)\n"); 78 fprintf(stderr, 79 " -vmin name set minimum supported version (default: TLS-1.0)\n"); 80 fprintf(stderr, 81 " -vmax name set maximum supported version (default: TLS-1.2)\n"); 82 fprintf(stderr, 83 " -cs names set list of supported cipher suites (comma-separated)\n"); 84 fprintf(stderr, 85 " -hf names add support for some hash functions (comma-separated)\n"); 86 fprintf(stderr, 87 " -minhello len set minimum ClientHello length (in bytes)\n"); 88 fprintf(stderr, 89 " -serverpref enforce server's preferences for cipher suites\n"); 90 fprintf(stderr, 91 " -noreneg prohibit renegotiations\n"); 92 fprintf(stderr, 93 " -alpn name add protocol name to list of protocols (ALPN extension)\n"); 94 fprintf(stderr, 95 " -strictalpn fail on ALPN mismatch\n"); 96 } 97 98 static void 99 free_alpn(void *alpn) 100 { 101 xfree(*(char **)alpn); 102 } 103 104 static void 105 dump_blob(const char *name, const void *data, size_t len) 106 { 107 const unsigned char *buf; 108 size_t u; 109 110 buf = data; 111 fprintf(stderr, "%s (len = %lu)", name, (unsigned long)len); 112 for (u = 0; u < len; u ++) { 113 if ((u & 15) == 0) { 114 fprintf(stderr, "\n%08lX ", (unsigned long)u); 115 } else if ((u & 7) == 0) { 116 fprintf(stderr, " "); 117 } 118 fprintf(stderr, " %02x", buf[u]); 119 } 120 fprintf(stderr, "\n"); 121 } 122 123 /* 124 * Callback for reading bytes from standard input. 125 */ 126 static int 127 stdin_read(void *ctx, unsigned char *buf, size_t len) 128 { 129 for (;;) { 130 #ifdef _WIN32 131 DWORD rlen; 132 #else 133 ssize_t rlen; 134 #endif 135 int eof; 136 137 #ifdef _WIN32 138 eof = !ReadFile(GetStdHandle(STD_INPUT_HANDLE), 139 buf, len, &rlen, NULL) || rlen == 0; 140 #else 141 rlen = read(0, buf, len); 142 if (rlen <= 0) { 143 if (rlen < 0 && errno == EINTR) { 144 continue; 145 } 146 eof = 1; 147 } else { 148 eof = 0; 149 } 150 #endif 151 if (eof) { 152 if (*(int *)ctx) { 153 if (verbose) { 154 fprintf(stderr, "recv: EOF\n"); 155 } 156 } 157 return -1; 158 } 159 if (*(int *)ctx) { 160 dump_blob("recv", buf, (size_t)rlen); 161 } 162 return (int)rlen; 163 } 164 } 165 166 /* 167 * Callback for writing bytes on standard output. 168 */ 169 static int 170 stdout_write(void *ctx, const unsigned char *buf, size_t len) 171 { 172 for (;;) { 173 #ifdef _WIN32 174 DWORD wlen; 175 #else 176 ssize_t wlen; 177 #endif 178 int eof; 179 180 #ifdef _WIN32 181 eof = !WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), 182 buf, len, &wlen, NULL); 183 #else 184 wlen = write(1, buf, len); 185 if (wlen <= 0) { 186 if (wlen < 0 && errno == EINTR) { 187 continue; 188 } 189 eof = 1; 190 } else { 191 eof = 0; 192 } 193 #endif 194 if (eof) { 195 if (*(int *)ctx) { 196 if (verbose) { 197 fprintf(stderr, "send: EOF\n"); 198 } 199 } 200 return -1; 201 } 202 if (*(int *)ctx) { 203 dump_blob("send", buf, (size_t)wlen); 204 } 205 return (int)wlen; 206 } 207 } 208 209 static void 210 print_error(int err) 211 { 212 const char *name, *comment; 213 214 name = find_error_name(err, &comment); 215 if (name != NULL) { 216 fprintf(stderr, "ERR %d: %s\n %s\n", err, name, comment); 217 return; 218 } 219 if (err >= BR_ERR_RECV_FATAL_ALERT 220 && err < BR_ERR_RECV_FATAL_ALERT + 256) 221 { 222 fprintf(stderr, "ERR %d: received fatal alert %d\n", 223 err, err - BR_ERR_RECV_FATAL_ALERT); 224 return; 225 } 226 if (err >= BR_ERR_SEND_FATAL_ALERT 227 && err < BR_ERR_SEND_FATAL_ALERT + 256) 228 { 229 fprintf(stderr, "ERR %d: sent fatal alert %d\n", 230 err, err - BR_ERR_SEND_FATAL_ALERT); 231 return; 232 } 233 fprintf(stderr, "ERR %d: UNKNOWN\n", err); 234 } 235 236 /* see brssl.h */ 237 int 238 do_twrch(int argc, char *argv[]) 239 { 240 int retcode; 241 int trace; 242 int is_client; 243 int is_server; 244 const char *sni; 245 int i, bidi; 246 unsigned vmin, vmax; 247 cipher_suite *suites; 248 size_t num_suites; 249 uint16_t *suite_ids; 250 unsigned hfuns; 251 br_x509_certificate *chain; 252 size_t chain_len; 253 int cert_signer_algo; 254 private_key *sk; 255 int nostaticecdh; 256 anchor_list anchors = VEC_INIT; 257 VECTOR(char *) alpn_names = VEC_INIT; 258 br_x509_minimal_context xc; 259 x509_noanchor_context xwc; 260 const br_hash_class *dnhash; 261 size_t u; 262 union { 263 br_ssl_engine_context eng; 264 br_ssl_server_context srv; 265 br_ssl_client_context cnt; 266 } cc; 267 br_ssl_session_cache_lru lru; 268 unsigned char *iobuf, *cache; 269 size_t iobuf_len, cache_len, minhello_len; 270 br_sslio_context ioc; 271 uint32_t flags; 272 int reconnect; 273 274 retcode = 0; 275 trace = 0; 276 is_client = 0; 277 is_server = 0; 278 sni = NULL; 279 bidi = 1; 280 vmin = 0; 281 vmax = 0; 282 suites = NULL; 283 num_suites = 0; 284 suite_ids = NULL; 285 hfuns = 0; 286 chain = NULL; 287 chain_len = 0; 288 cert_signer_algo = 0; 289 sk = NULL; 290 nostaticecdh = 0; 291 iobuf = NULL; 292 iobuf_len = 0; 293 cache = NULL; 294 cache_len = (size_t)-1; 295 minhello_len = (size_t)-1; 296 flags = 0; 297 reconnect = 0; 298 for (i = 0; i < argc; i ++) { 299 const char *arg; 300 301 arg = argv[i]; 302 if (arg[0] != '-') { 303 usage_twrch(); 304 goto twrch_exit_error; 305 } 306 if (eqstr(arg, "-trace")) { 307 trace = 1; 308 } else if (eqstr(arg, "-v")) { 309 verbose = 1; 310 } else if (eqstr(arg, "-server")) { 311 is_server = 1; 312 } else if (eqstr(arg, "-client")) { 313 is_client = 1; 314 } else if (eqstr(arg, "-sni")) { 315 if (++ i >= argc) { 316 fprintf(stderr, 317 "ERROR: no argument for '-sni'\n"); 318 usage_twrch(); 319 goto twrch_exit_error; 320 } 321 arg = argv[i]; 322 if (sni != NULL) { 323 fprintf(stderr, "ERROR: duplicate SNI\n"); 324 usage_twrch(); 325 goto twrch_exit_error; 326 } 327 sni = arg; 328 } else if (eqstr(arg, "-mono")) { 329 bidi = 0; 330 } else if (eqstr(arg, "-buf")) { 331 if (++ i >= argc) { 332 fprintf(stderr, 333 "ERROR: no argument for '-buf'\n"); 334 usage_twrch(); 335 goto twrch_exit_error; 336 } 337 arg = argv[i]; 338 if (iobuf_len != 0) { 339 fprintf(stderr, 340 "ERROR: duplicate I/O buffer length\n"); 341 usage_twrch(); 342 goto twrch_exit_error; 343 } 344 iobuf_len = parse_size(arg); 345 if (iobuf_len == (size_t)-1) { 346 usage_twrch(); 347 goto twrch_exit_error; 348 } 349 } else if (eqstr(arg, "-cache")) { 350 if (++ i >= argc) { 351 fprintf(stderr, 352 "ERROR: no argument for '-cache'\n"); 353 usage_twrch(); 354 goto twrch_exit_error; 355 } 356 arg = argv[i]; 357 if (cache_len != (size_t)-1) { 358 fprintf(stderr, "ERROR: duplicate session" 359 " cache length\n"); 360 usage_twrch(); 361 goto twrch_exit_error; 362 } 363 cache_len = parse_size(arg); 364 if (cache_len == (size_t)-1) { 365 usage_twrch(); 366 goto twrch_exit_error; 367 } 368 } else if (eqstr(arg, "-cert")) { 369 if (++ i >= argc) { 370 fprintf(stderr, 371 "ERROR: no argument for '-cert'\n"); 372 usage_twrch(); 373 goto twrch_exit_error; 374 } 375 if (chain != NULL) { 376 fprintf(stderr, 377 "ERROR: duplicate certificate chain\n"); 378 usage_twrch(); 379 goto twrch_exit_error; 380 } 381 arg = argv[i]; 382 chain = read_certificates(arg, &chain_len); 383 if (chain == NULL || chain_len == 0) { 384 goto twrch_exit_error; 385 } 386 } else if (eqstr(arg, "-key")) { 387 if (++ i >= argc) { 388 fprintf(stderr, 389 "ERROR: no argument for '-key'\n"); 390 usage_twrch(); 391 goto twrch_exit_error; 392 } 393 if (sk != NULL) { 394 fprintf(stderr, 395 "ERROR: duplicate private key\n"); 396 usage_twrch(); 397 goto twrch_exit_error; 398 } 399 arg = argv[i]; 400 sk = read_private_key(arg); 401 if (sk == NULL) { 402 goto twrch_exit_error; 403 } 404 } else if (eqstr(arg, "-CA")) { 405 if (++ i >= argc) { 406 fprintf(stderr, 407 "ERROR: no argument for '-CA'\n"); 408 usage_twrch(); 409 goto twrch_exit_error; 410 } 411 arg = argv[i]; 412 if (read_trust_anchors(&anchors, arg) == 0) { 413 usage_twrch(); 414 goto twrch_exit_error; 415 } 416 } else if (eqstr(arg, "-anon_ok")) { 417 flags |= BR_OPT_TOLERATE_NO_CLIENT_AUTH; 418 } else if (eqstr(arg, "-nostaticecdh")) { 419 nostaticecdh = 1; 420 } else if (eqstr(arg, "-list")) { 421 list_names(); 422 goto twrch_exit; 423 } else if (eqstr(arg, "-vmin")) { 424 if (++ i >= argc) { 425 fprintf(stderr, 426 "ERROR: no argument for '-vmin'\n"); 427 usage_twrch(); 428 goto twrch_exit_error; 429 } 430 arg = argv[i]; 431 if (vmin != 0) { 432 fprintf(stderr, 433 "ERROR: duplicate minimum version\n"); 434 usage_twrch(); 435 goto twrch_exit_error; 436 } 437 vmin = parse_version(arg, strlen(arg)); 438 if (vmin == 0) { 439 fprintf(stderr, 440 "ERROR: unrecognised version '%s'\n", 441 arg); 442 usage_twrch(); 443 goto twrch_exit_error; 444 } 445 } else if (eqstr(arg, "-vmax")) { 446 if (++ i >= argc) { 447 fprintf(stderr, 448 "ERROR: no argument for '-vmax'\n"); 449 usage_twrch(); 450 goto twrch_exit_error; 451 } 452 arg = argv[i]; 453 if (vmax != 0) { 454 fprintf(stderr, 455 "ERROR: duplicate maximum version\n"); 456 usage_twrch(); 457 goto twrch_exit_error; 458 } 459 vmax = parse_version(arg, strlen(arg)); 460 if (vmax == 0) { 461 fprintf(stderr, 462 "ERROR: unrecognised version '%s'\n", 463 arg); 464 usage_twrch(); 465 goto twrch_exit_error; 466 } 467 } else if (eqstr(arg, "-cs")) { 468 if (++ i >= argc) { 469 fprintf(stderr, 470 "ERROR: no argument for '-cs'\n"); 471 usage_twrch(); 472 goto twrch_exit_error; 473 } 474 arg = argv[i]; 475 if (suites != NULL) { 476 fprintf(stderr, "ERROR: duplicate list" 477 " of cipher suites\n"); 478 usage_twrch(); 479 goto twrch_exit_error; 480 } 481 suites = parse_suites(arg, &num_suites); 482 if (suites == NULL) { 483 usage_twrch(); 484 goto twrch_exit_error; 485 } 486 } else if (eqstr(arg, "-hf")) { 487 unsigned x; 488 489 if (++ i >= argc) { 490 fprintf(stderr, 491 "ERROR: no argument for '-hf'\n"); 492 usage_twrch(); 493 goto twrch_exit_error; 494 } 495 arg = argv[i]; 496 x = parse_hash_functions(arg); 497 if (x == 0) { 498 usage_twrch(); 499 goto twrch_exit_error; 500 } 501 hfuns |= x; 502 } else if (eqstr(arg, "-minhello")) { 503 if (++ i >= argc) { 504 fprintf(stderr, 505 "ERROR: no argument for '-minhello'\n"); 506 usage_twrch(); 507 goto twrch_exit_error; 508 } 509 arg = argv[i]; 510 if (minhello_len != (size_t)-1) { 511 fprintf(stderr, "ERROR: duplicate minimum" 512 " ClientHello length\n"); 513 usage_twrch(); 514 goto twrch_exit_error; 515 } 516 minhello_len = parse_size(arg); 517 /* 518 * Minimum ClientHello length must fit on 16 bits. 519 */ 520 if (minhello_len == (size_t)-1 521 || (((minhello_len >> 12) >> 4) != 0)) 522 { 523 usage_twrch(); 524 goto twrch_exit_error; 525 } 526 } else if (eqstr(arg, "-serverpref")) { 527 flags |= BR_OPT_ENFORCE_SERVER_PREFERENCES; 528 } else if (eqstr(arg, "-noreneg")) { 529 flags |= BR_OPT_NO_RENEGOTIATION; 530 } else if (eqstr(arg, "-alpn")) { 531 if (++ i >= argc) { 532 fprintf(stderr, 533 "ERROR: no argument for '-alpn'\n"); 534 usage_twrch(); 535 goto twrch_exit_error; 536 } 537 VEC_ADD(alpn_names, xstrdup(argv[i])); 538 } else if (eqstr(arg, "-strictalpn")) { 539 flags |= BR_OPT_FAIL_ON_ALPN_MISMATCH; 540 } else { 541 fprintf(stderr, "ERROR: unknown option: '%s'\n", arg); 542 usage_twrch(); 543 goto twrch_exit_error; 544 } 545 } 546 547 /* 548 * Verify consistency of options. 549 */ 550 if (!is_client && !is_server) { 551 fprintf(stderr, "ERROR:" 552 " one of -server and -client must be specified\n"); 553 usage_twrch(); 554 goto twrch_exit_error; 555 } 556 if (is_client && is_server) { 557 fprintf(stderr, "ERROR:" 558 " -server and -client may not be both specified\n"); 559 usage_twrch(); 560 goto twrch_exit_error; 561 } 562 563 if (vmin == 0) { 564 vmin = BR_TLS10; 565 } 566 if (vmax == 0) { 567 vmax = BR_TLS12; 568 } 569 if (vmax < vmin) { 570 fprintf(stderr, "ERROR: impossible minimum/maximum protocol" 571 " version combination\n"); 572 usage_twrch(); 573 goto twrch_exit_error; 574 } 575 if (is_server) { 576 if (chain == NULL) { 577 fprintf(stderr, "ERROR: no certificate specified" 578 " for server (-cert)\n"); 579 usage_twrch(); 580 goto twrch_exit_error; 581 } 582 if (sk == NULL) { 583 fprintf(stderr, "ERROR: no private key specified" 584 " for server (-key)\n"); 585 usage_twrch(); 586 goto twrch_exit_error; 587 } 588 } else { 589 if (chain == NULL && sk != NULL) { 590 fprintf(stderr, "ERROR: private key (-key)" 591 " but no certificate (-cert)"); 592 usage_twrch(); 593 goto twrch_exit_error; 594 } 595 if (chain != NULL && sk == NULL) { 596 fprintf(stderr, "ERROR: certificate (-cert)" 597 " but no private key (-key)"); 598 usage_twrch(); 599 goto twrch_exit_error; 600 } 601 } 602 if (suites == NULL) { 603 num_suites = 0; 604 605 for (u = 0; cipher_suites[u].name; u ++) { 606 if ((cipher_suites[u].req & REQ_TLS12) == 0 607 || vmax >= BR_TLS12) 608 { 609 num_suites ++; 610 } 611 } 612 suites = xmalloc(num_suites * sizeof *suites); 613 num_suites = 0; 614 for (u = 0; cipher_suites[u].name; u ++) { 615 if ((cipher_suites[u].req & REQ_TLS12) == 0 616 || vmax >= BR_TLS12) 617 { 618 suites[num_suites ++] = cipher_suites[u]; 619 } 620 } 621 } 622 if (hfuns == 0) { 623 hfuns = (unsigned)-1; 624 } 625 if (sk != NULL) { 626 switch (sk->key_type) { 627 int curve; 628 uint32_t supp; 629 630 case BR_KEYTYPE_RSA: 631 break; 632 case BR_KEYTYPE_EC: 633 curve = sk->key.ec.curve; 634 supp = br_ec_get_default()->supported_curves; 635 if (curve > 31 || !((supp >> curve) & 1)) { 636 fprintf(stderr, "ERROR: private key curve (%d)" 637 " is not supported\n", curve); 638 goto twrch_exit_error; 639 } 640 break; 641 default: 642 fprintf(stderr, "ERROR: unsupported" 643 " private key type (%d)\n", sk->key_type); 644 goto twrch_exit_error; 645 } 646 } 647 if (chain != NULL) { 648 cert_signer_algo = get_cert_signer_algo(chain); 649 if (cert_signer_algo == 0) { 650 goto twrch_exit_error; 651 } 652 } 653 if (iobuf_len == 0) { 654 if (bidi) { 655 iobuf_len = BR_SSL_BUFSIZE_BIDI; 656 } else { 657 iobuf_len = BR_SSL_BUFSIZE_MONO; 658 } 659 } 660 iobuf = xmalloc(iobuf_len); 661 if (is_server) { 662 if (cache_len == (size_t)-1) { 663 cache_len = 5000; 664 } 665 cache = xmalloc(cache_len); 666 } 667 668 /* 669 * Initialise the relevant context. 670 */ 671 if (is_client) { 672 br_ssl_client_zero(&cc.cnt); 673 } else { 674 br_ssl_server_zero(&cc.srv); 675 } 676 677 /* 678 * Compute implementation requirements and inject implementations. 679 */ 680 suite_ids = xmalloc(num_suites * sizeof *suite_ids); 681 br_ssl_engine_set_versions(&cc.eng, vmin, vmax); 682 br_ssl_engine_set_all_flags(&cc.eng, flags); 683 if (vmin <= BR_TLS11) { 684 if (!(hfuns & (1 << br_md5_ID))) { 685 fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need MD5\n"); 686 goto twrch_exit_error; 687 } 688 if (!(hfuns & (1 << br_sha1_ID))) { 689 fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need SHA-1\n"); 690 goto twrch_exit_error; 691 } 692 } 693 for (u = 0; u < num_suites; u ++) { 694 unsigned req; 695 696 req = suites[u].req; 697 suite_ids[u] = suites[u].suite; 698 if ((req & REQ_TLS12) != 0 && vmax < BR_TLS12) { 699 fprintf(stderr, 700 "ERROR: cipher suite %s requires TLS 1.2\n", 701 suites[u].name); 702 goto twrch_exit_error; 703 } 704 if ((req & REQ_SHA1) != 0 && !(hfuns & (1 << br_sha1_ID))) { 705 fprintf(stderr, 706 "ERROR: cipher suite %s requires SHA-1\n", 707 suites[u].name); 708 goto twrch_exit_error; 709 } 710 if ((req & REQ_SHA256) != 0 && !(hfuns & (1 << br_sha256_ID))) { 711 fprintf(stderr, 712 "ERROR: cipher suite %s requires SHA-256\n", 713 suites[u].name); 714 goto twrch_exit_error; 715 } 716 if ((req & REQ_SHA384) != 0 && !(hfuns & (1 << br_sha384_ID))) { 717 fprintf(stderr, 718 "ERROR: cipher suite %s requires SHA-384\n", 719 suites[u].name); 720 goto twrch_exit_error; 721 } 722 /* TODO: algorithm implementation selection */ 723 if ((req & REQ_AESCBC) != 0) { 724 br_ssl_engine_set_default_aes_cbc(&cc.eng); 725 } 726 if ((req & REQ_AESCCM) != 0) { 727 br_ssl_engine_set_default_aes_ccm(&cc.eng); 728 } 729 if ((req & REQ_AESGCM) != 0) { 730 br_ssl_engine_set_default_aes_gcm(&cc.eng); 731 } 732 if ((req & REQ_CHAPOL) != 0) { 733 br_ssl_engine_set_default_chapol(&cc.eng); 734 } 735 if ((req & REQ_3DESCBC) != 0) { 736 br_ssl_engine_set_default_des_cbc(&cc.eng); 737 } 738 if (is_client && (req & REQ_RSAKEYX) != 0) { 739 br_ssl_client_set_default_rsapub(&cc.cnt); 740 } 741 if (is_client && (req & REQ_ECDHE_RSA) != 0) { 742 br_ssl_engine_set_default_rsavrfy(&cc.eng); 743 } 744 if (is_client && (req & REQ_ECDH) != 0) { 745 br_ssl_engine_set_default_ec(&cc.eng); 746 } 747 if ((req & (REQ_ECDHE_RSA | REQ_ECDHE_ECDSA)) != 0) { 748 br_ssl_engine_set_default_ec(&cc.eng); 749 } 750 } 751 br_ssl_engine_set_suites(&cc.eng, suite_ids, num_suites); 752 753 dnhash = NULL; 754 for (u = 0; hash_functions[u].name; u ++) { 755 const br_hash_class *hc; 756 int id; 757 758 hc = hash_functions[u].hclass; 759 id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK; 760 if ((hfuns & ((unsigned)1 << id)) != 0) { 761 dnhash = hc; 762 br_ssl_engine_set_hash(&cc.eng, id, hc); 763 } 764 } 765 if (vmin <= BR_TLS11) { 766 br_ssl_engine_set_prf10(&cc.eng, &br_tls10_prf); 767 } 768 if (vmax >= BR_TLS12) { 769 if ((hfuns & ((unsigned)1 << br_sha256_ID)) != 0) { 770 br_ssl_engine_set_prf_sha256(&cc.eng, 771 &br_tls12_sha256_prf); 772 } 773 if ((hfuns & ((unsigned)1 << br_sha384_ID)) != 0) { 774 br_ssl_engine_set_prf_sha384(&cc.eng, 775 &br_tls12_sha384_prf); 776 } 777 } 778 if (VEC_LEN(alpn_names) != 0) { 779 br_ssl_engine_set_protocol_names(&cc.eng, 780 (const char **)&VEC_ELT(alpn_names, 0), 781 VEC_LEN(alpn_names)); 782 } 783 784 /* 785 * In server role, we use a session cache (size can be 786 * specified; if size is zero, then no cache is set). 787 */ 788 if (is_server && cache != NULL) { 789 br_ssl_session_cache_lru_init(&lru, cache, cache_len); 790 br_ssl_server_set_cache(&cc.srv, &lru.vtable); 791 } 792 793 /* 794 * For a server, set the policy handler. 795 */ 796 if (is_server) { 797 switch (sk->key_type) { 798 case BR_KEYTYPE_RSA: 799 br_ssl_server_set_single_rsa(&cc.srv, 800 chain, chain_len, &sk->key.rsa, 801 BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, 802 br_rsa_private_get_default(), 803 br_rsa_pkcs1_sign_get_default()); 804 break; 805 case BR_KEYTYPE_EC: 806 br_ssl_server_set_single_ec(&cc.srv, 807 chain, chain_len, &sk->key.ec, 808 BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, 809 cert_signer_algo, 810 br_ec_get_default(), 811 br_ecdsa_sign_asn1_get_default()); 812 break; 813 default: 814 fprintf(stderr, "ERROR: unsupported" 815 " private key type (%d)\n", sk->key_type); 816 goto twrch_exit_error; 817 } 818 } 819 820 /* 821 * For a client, if a certificate was specified, use it. 822 */ 823 if (is_client && chain != NULL) { 824 switch (sk->key_type) { 825 unsigned usages; 826 827 case BR_KEYTYPE_RSA: 828 br_ssl_client_set_single_rsa(&cc.cnt, 829 chain, chain_len, &sk->key.rsa, 830 br_rsa_pkcs1_sign_get_default()); 831 break; 832 case BR_KEYTYPE_EC: 833 if (nostaticecdh) { 834 cert_signer_algo = 0; 835 usages = BR_KEYTYPE_SIGN; 836 } else { 837 usages = BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN; 838 } 839 br_ssl_client_set_single_ec(&cc.cnt, 840 chain, chain_len, &sk->key.ec, 841 usages, cert_signer_algo, 842 br_ec_get_default(), 843 br_ecdsa_sign_asn1_get_default()); 844 break; 845 default: 846 fprintf(stderr, "ERROR: unsupported" 847 " private key type (%d)\n", sk->key_type); 848 goto twrch_exit_error; 849 } 850 } 851 852 /* 853 * On a client, or if trust anchors have been configured, then 854 * set an X.509 validation engine. If there are no trust anchors 855 * (client only), then a "no anchor" wrapper will be applied. 856 */ 857 if (is_client || VEC_LEN(anchors) != 0) { 858 br_x509_minimal_init(&xc, dnhash, 859 &VEC_ELT(anchors, 0), VEC_LEN(anchors)); 860 for (u = 0; hash_functions[u].name; u ++) { 861 const br_hash_class *hc; 862 int id; 863 864 hc = hash_functions[u].hclass; 865 id = (hc->desc >> BR_HASHDESC_ID_OFF) 866 & BR_HASHDESC_ID_MASK; 867 if ((hfuns & ((unsigned)1 << id)) != 0) { 868 br_x509_minimal_set_hash(&xc, id, hc); 869 } 870 } 871 br_ssl_engine_set_default_rsavrfy(&cc.eng); 872 br_ssl_engine_set_default_ecdsa(&cc.eng); 873 br_x509_minimal_set_rsa(&xc, br_rsa_pkcs1_vrfy_get_default()); 874 br_x509_minimal_set_ecdsa(&xc, 875 br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default()); 876 br_ssl_engine_set_x509(&cc.eng, &xc.vtable); 877 878 if (VEC_LEN(anchors) == 0) { 879 x509_noanchor_init(&xwc, &xc.vtable); 880 br_ssl_engine_set_x509(&cc.eng, &xwc.vtable); 881 } else { 882 br_ssl_engine_set_x509(&cc.eng, &xc.vtable); 883 } 884 if (is_server) { 885 br_ssl_server_set_trust_anchor_names_alt(&cc.srv, 886 &VEC_ELT(anchors, 0), VEC_LEN(anchors)); 887 } 888 } 889 890 /* 891 * Set I/O buffer. 892 */ 893 br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi); 894 895 /* 896 * Start the engine. 897 */ 898 if (is_client) { 899 br_ssl_client_reset(&cc.cnt, sni, 0); 900 } 901 if (is_server) { 902 br_ssl_server_reset(&cc.srv); 903 } 904 905 /* 906 * On Unix systems, we want to ignore SIGPIPE: if the peer 907 * closes the connection abruptly, then we want to report it 908 * as a "normal" error (exit code = 1). 909 */ 910 #ifndef _WIN32 911 signal(SIGPIPE, SIG_IGN); 912 #endif 913 914 /* 915 * Initialize the callbacks for exchanging data over stdin and 916 * stdout. 917 */ 918 br_sslio_init(&ioc, &cc.eng, stdin_read, &trace, stdout_write, &trace); 919 920 /* 921 * Run the Twrch protocol. 922 */ 923 for (;;) { 924 br_sha1_context sc; 925 unsigned char hv[20], tmp[41]; 926 uint64_t count; 927 int fb, i; 928 929 /* 930 * Read line, byte by byte, hashing it on the fly. 931 */ 932 br_sha1_init(&sc); 933 count = 0; 934 fb = 0; 935 for (;;) { 936 unsigned char x; 937 938 if (br_sslio_read(&ioc, &x, 1) < 0) { 939 if (count == 0 && reconnect) { 940 reconnect = 0; 941 if (br_sslio_close(&ioc) < 0) { 942 goto twrch_loop_finished; 943 } 944 if (is_client) { 945 br_ssl_client_reset( 946 &cc.cnt, sni, 1); 947 } 948 if (is_server) { 949 br_ssl_server_reset(&cc.srv); 950 } 951 br_sslio_init(&ioc, &cc.eng, 952 stdin_read, &trace, 953 stdout_write, &trace); 954 continue; 955 } 956 goto twrch_loop_finished; 957 } 958 if (count == 0) { 959 fb = x; 960 } 961 if (x == 0x0A) { 962 break; 963 } 964 br_sha1_update(&sc, &x, 1); 965 count ++; 966 } 967 if (count == 1) { 968 switch (fb) { 969 case 'C': 970 br_sslio_close(&ioc); 971 goto twrch_loop_finished; 972 case 'T': 973 if (br_sslio_close(&ioc) < 0) { 974 goto twrch_loop_finished; 975 } 976 if (is_client) { 977 br_ssl_client_reset(&cc.cnt, sni, 1); 978 } 979 if (is_server) { 980 br_ssl_server_reset(&cc.srv); 981 } 982 br_sslio_init(&ioc, &cc.eng, 983 stdin_read, &trace, 984 stdout_write, &trace); 985 continue; 986 case 'G': 987 if (!br_ssl_engine_renegotiate(&cc.eng)) { 988 br_sslio_write_all(&ioc, "DENIED\n", 7); 989 br_sslio_flush(&ioc); 990 } else { 991 br_sslio_write_all(&ioc, "OK\n", 3); 992 br_sslio_flush(&ioc); 993 } 994 continue; 995 case 'R': 996 reconnect = 1; 997 br_sslio_write_all(&ioc, "OK\n", 3); 998 br_sslio_flush(&ioc); 999 continue; 1000 case 'U': 1001 if (is_client) { 1002 br_ssl_client_forget_session(&cc.cnt); 1003 } 1004 if (is_server && cache != NULL) { 1005 br_ssl_session_parameters pp; 1006 1007 br_ssl_engine_get_session_parameters( 1008 &cc.eng, &pp); 1009 if (pp.session_id_len == 32) { 1010 br_ssl_session_cache_lru_forget( 1011 &lru, pp.session_id); 1012 } 1013 } 1014 br_sslio_write_all(&ioc, "DONE\n", 5); 1015 br_sslio_flush(&ioc); 1016 continue; 1017 } 1018 } 1019 br_sha1_out(&sc, hv); 1020 for (i = 0; i < 20; i ++) { 1021 int x; 1022 1023 x = hv[i]; 1024 tmp[(i << 1) + 0] = "0123456789abcdef"[x >> 4]; 1025 tmp[(i << 1) + 1] = "0123456789abcdef"[x & 15]; 1026 } 1027 tmp[40] = 0x0A; 1028 br_sslio_write_all(&ioc, tmp, 41); 1029 br_sslio_flush(&ioc); 1030 } 1031 1032 twrch_loop_finished: 1033 if (br_ssl_engine_current_state(&cc.eng) == BR_SSL_CLOSED) { 1034 int err; 1035 1036 err = br_ssl_engine_last_error(&cc.eng); 1037 if (err == 0) { 1038 retcode = 0; 1039 } else { 1040 if (verbose) { 1041 print_error(err); 1042 } 1043 retcode = 1; 1044 } 1045 } else { 1046 if (verbose) { 1047 fprintf(stderr, "Engine not closed!\n"); 1048 } 1049 retcode = 1; 1050 } 1051 1052 /* 1053 * Release allocated structures. 1054 */ 1055 twrch_exit: 1056 xfree(suites); 1057 xfree(suite_ids); 1058 free_certificates(chain, chain_len); 1059 free_private_key(sk); 1060 VEC_CLEAREXT(anchors, &free_ta_contents); 1061 VEC_CLEAREXT(alpn_names, &free_alpn); 1062 xfree(iobuf); 1063 xfree(cache); 1064 return retcode; 1065 1066 twrch_exit_error: 1067 retcode = -1; 1068 goto twrch_exit; 1069 } 1070