xref: /freebsd/contrib/bearssl/tools/twrch.c (revision 2aaf9152a852aba9eb2036b95f4948ee77988826)
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
usage_twrch(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
free_alpn(void * alpn)99 free_alpn(void *alpn)
100 {
101 	xfree(*(char **)alpn);
102 }
103 
104 static void
dump_blob(const char * name,const void * data,size_t len)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
stdin_read(void * ctx,unsigned char * buf,size_t len)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
stdout_write(void * ctx,const unsigned char * buf,size_t len)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
print_error(int err)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
do_twrch(int argc,char * argv[])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