]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bearssl/tools/client.c
Merge ^/vendor/llvm-project/release-10.x up to its last change (upstream
[FreeBSD/FreeBSD.git] / contrib / bearssl / tools / client.c
1 /*
2  * Copyright (c) 2016 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 #include <signal.h>
31
32 #ifdef _WIN32
33 #include <winsock2.h>
34 #include <ws2tcpip.h>
35 #else
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <netdb.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <unistd.h>
42 #include <fcntl.h>
43
44 #define SOCKET             int
45 #define INVALID_SOCKET     (-1)
46 #endif
47
48 #include "brssl.h"
49
50 static int
51 host_connect(const char *host, const char *port, int verbose)
52 {
53         struct addrinfo hints, *si, *p;
54         SOCKET fd;
55         int err;
56
57         memset(&hints, 0, sizeof hints);
58         hints.ai_family = PF_UNSPEC;
59         hints.ai_socktype = SOCK_STREAM;
60         err = getaddrinfo(host, port, &hints, &si);
61         if (err != 0) {
62                 fprintf(stderr, "ERROR: getaddrinfo(): %s\n",
63                         gai_strerror(err));
64                 return INVALID_SOCKET;
65         }
66         fd = INVALID_SOCKET;
67         for (p = si; p != NULL; p = p->ai_next) {
68                 if (verbose) {
69                         struct sockaddr *sa;
70                         void *addr;
71                         char tmp[INET6_ADDRSTRLEN + 50];
72
73                         sa = (struct sockaddr *)p->ai_addr;
74                         if (sa->sa_family == AF_INET) {
75                                 addr = &((struct sockaddr_in *)
76                                         (void *)sa)->sin_addr;
77                         } else if (sa->sa_family == AF_INET6) {
78                                 addr = &((struct sockaddr_in6 *)
79                                         (void *)sa)->sin6_addr;
80                         } else {
81                                 addr = NULL;
82                         }
83                         if (addr != NULL) {
84                                 if (!inet_ntop(p->ai_family, addr,
85                                         tmp, sizeof tmp))
86                                 {
87                                         strcpy(tmp, "<invalid>");
88                                 }
89                         } else {
90                                 sprintf(tmp, "<unknown family: %d>",
91                                         (int)sa->sa_family);
92                         }
93                         fprintf(stderr, "connecting to: %s\n", tmp);
94                 }
95                 fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
96                 if (fd == INVALID_SOCKET) {
97                         if (verbose) {
98                                 perror("socket()");
99                         }
100                         continue;
101                 }
102                 if (connect(fd, p->ai_addr, p->ai_addrlen) == INVALID_SOCKET) {
103                         if (verbose) {
104                                 perror("connect()");
105                         }
106 #ifdef _WIN32
107                         closesocket(fd);
108 #else
109                         close(fd);
110 #endif
111                         continue;
112                 }
113                 break;
114         }
115         if (p == NULL) {
116                 freeaddrinfo(si);
117                 fprintf(stderr, "ERROR: failed to connect\n");
118                 return INVALID_SOCKET;
119         }
120         freeaddrinfo(si);
121         if (verbose) {
122                 fprintf(stderr, "connected.\n");
123         }
124
125         /*
126          * We make the socket non-blocking, since we are going to use
127          * poll() or select() to organise I/O.
128          */
129 #ifdef _WIN32
130         {
131                 u_long arg;
132
133                 arg = 1;
134                 ioctlsocket(fd, FIONBIO, &arg);
135         }
136 #else
137         fcntl(fd, F_SETFL, O_NONBLOCK);
138 #endif
139         return fd;
140 }
141
142 typedef struct {
143         const br_ssl_client_certificate_class *vtable;
144         int verbose;
145         br_x509_certificate *chain;
146         size_t chain_len;
147         private_key *sk;
148         int issuer_key_type;
149 } ccert_context;
150
151 static void
152 cc_start_name_list(const br_ssl_client_certificate_class **pctx)
153 {
154         ccert_context *zc;
155
156         zc = (ccert_context *)pctx;
157         if (zc->verbose) {
158                 fprintf(stderr, "Server requests a client certificate.\n");
159                 fprintf(stderr, "--- anchor DN list start ---\n");
160         }
161 }
162
163 static void
164 cc_start_name(const br_ssl_client_certificate_class **pctx, size_t len)
165 {
166         ccert_context *zc;
167
168         zc = (ccert_context *)pctx;
169         if (zc->verbose) {
170                 fprintf(stderr, "new anchor name, length = %u\n",
171                         (unsigned)len);
172         }
173 }
174
175 static void
176 cc_append_name(const br_ssl_client_certificate_class **pctx,
177         const unsigned char *data, size_t len)
178 {
179         ccert_context *zc;
180
181         zc = (ccert_context *)pctx;
182         if (zc->verbose) {
183                 size_t u;
184
185                 for (u = 0; u < len; u ++) {
186                         if (u == 0) {
187                                 fprintf(stderr, "  ");
188                         } else if (u > 0 && u % 16 == 0) {
189                                 fprintf(stderr, "\n  ");
190                         }
191                         fprintf(stderr, " %02x", data[u]);
192                 }
193                 if (len > 0) {
194                         fprintf(stderr, "\n");
195                 }
196         }
197 }
198
199 static void
200 cc_end_name(const br_ssl_client_certificate_class **pctx)
201 {
202         (void)pctx;
203 }
204
205 static void
206 cc_end_name_list(const br_ssl_client_certificate_class **pctx)
207 {
208         ccert_context *zc;
209
210         zc = (ccert_context *)pctx;
211         if (zc->verbose) {
212                 fprintf(stderr, "--- anchor DN list end ---\n");
213         }
214 }
215
216 static void
217 print_hashes(unsigned hh, unsigned hh2)
218 {
219         int i;
220
221         for (i = 0; i < 8; i ++) {
222                 const char *name;
223
224                 name = hash_function_name(i);
225                 if (((hh >> i) & 1) != 0) {
226                         fprintf(stderr, " %s", name);
227                 } else if (((hh2 >> i) & 1) != 0) {
228                         fprintf(stderr, " (%s)", name);
229                 }
230         }
231 }
232
233 static int
234 choose_hash(unsigned hh)
235 {
236         static const int f[] = {
237                 br_sha256_ID, br_sha224_ID, br_sha384_ID, br_sha512_ID,
238                 br_sha1_ID, br_md5sha1_ID, -1
239         };
240
241         size_t u;
242
243         for (u = 0; f[u] >= 0; u ++) {
244                 if (((hh >> f[u]) & 1) != 0) {
245                         return f[u];
246                 }
247         }
248         return -1;
249 }
250
251 static void
252 cc_choose(const br_ssl_client_certificate_class **pctx,
253         const br_ssl_client_context *cc, uint32_t auth_types,
254         br_ssl_client_certificate *choices)
255 {
256         ccert_context *zc;
257         int scurve;
258
259         zc = (ccert_context *)pctx;
260         scurve = br_ssl_client_get_server_curve(cc);
261         if (zc->verbose) {
262                 unsigned hashes;
263
264                 hashes = br_ssl_client_get_server_hashes(cc);
265                 if ((auth_types & 0x00FF) != 0) {
266                         fprintf(stderr, "supported: RSA signatures:");
267                         print_hashes(auth_types, hashes);
268                         fprintf(stderr, "\n");
269                 }
270                 if ((auth_types & 0xFF00) != 0) {
271                         fprintf(stderr, "supported: ECDSA signatures:");
272                         print_hashes(auth_types >> 8, hashes >> 8);
273                         fprintf(stderr, "\n");
274                 }
275                 if ((auth_types & 0x010000) != 0) {
276                         fprintf(stderr, "supported:"
277                                 " fixed ECDH (cert signed with RSA)\n");
278                 }
279                 if ((auth_types & 0x020000) != 0) {
280                         fprintf(stderr, "supported:"
281                                 " fixed ECDH (cert signed with ECDSA)\n");
282                 }
283                 if (scurve) {
284                         fprintf(stderr, "server key curve: %s (%d)\n",
285                                 ec_curve_name(scurve), scurve);
286                 } else {
287                         fprintf(stderr, "server key is not EC\n");
288                 }
289         }
290         switch (zc->sk->key_type) {
291         case BR_KEYTYPE_RSA:
292                 if ((choices->hash_id = choose_hash(auth_types)) >= 0) {
293                         if (zc->verbose) {
294                                 fprintf(stderr, "using RSA, hash = %d (%s)\n",
295                                         choices->hash_id,
296                                         hash_function_name(choices->hash_id));
297                         }
298                         choices->auth_type = BR_AUTH_RSA;
299                         choices->chain = zc->chain;
300                         choices->chain_len = zc->chain_len;
301                         return;
302                 }
303                 break;
304         case BR_KEYTYPE_EC:
305                 if (zc->issuer_key_type != 0
306                         && scurve == zc->sk->key.ec.curve)
307                 {
308                         int x;
309
310                         x = (zc->issuer_key_type == BR_KEYTYPE_RSA) ? 16 : 17;
311                         if (((auth_types >> x) & 1) != 0) {
312                                 if (zc->verbose) {
313                                         fprintf(stderr, "using static ECDH\n");
314                                 }
315                                 choices->auth_type = BR_AUTH_ECDH;
316                                 choices->hash_id = -1;
317                                 choices->chain = zc->chain;
318                                 choices->chain_len = zc->chain_len;
319                                 return;
320                         }
321                 }
322                 if ((choices->hash_id = choose_hash(auth_types >> 8)) >= 0) {
323                         if (zc->verbose) {
324                                 fprintf(stderr, "using ECDSA, hash = %d (%s)\n",
325                                         choices->hash_id,
326                                         hash_function_name(choices->hash_id));
327                         }
328                         choices->auth_type = BR_AUTH_ECDSA;
329                         choices->chain = zc->chain;
330                         choices->chain_len = zc->chain_len;
331                         return;
332                 }
333                 break;
334         }
335         if (zc->verbose) {
336                 fprintf(stderr, "no matching client certificate\n");
337         }
338         choices->chain = NULL;
339         choices->chain_len = 0;
340 }
341
342 static uint32_t
343 cc_do_keyx(const br_ssl_client_certificate_class **pctx,
344         unsigned char *data, size_t *len)
345 {
346         const br_ec_impl *iec;
347         ccert_context *zc;
348         size_t xoff, xlen;
349         uint32_t r;
350
351         zc = (ccert_context *)pctx;
352         iec = br_ec_get_default();
353         r = iec->mul(data, *len, zc->sk->key.ec.x,
354                 zc->sk->key.ec.xlen, zc->sk->key.ec.curve);
355         xoff = iec->xoff(zc->sk->key.ec.curve, &xlen);
356         memmove(data, data + xoff, xlen);
357         *len = xlen;
358         return r;
359 }
360
361 static size_t
362 cc_do_sign(const br_ssl_client_certificate_class **pctx,
363         int hash_id, size_t hv_len, unsigned char *data, size_t len)
364 {
365         ccert_context *zc;
366         unsigned char hv[64];
367
368         zc = (ccert_context *)pctx;
369         memcpy(hv, data, hv_len);
370         switch (zc->sk->key_type) {
371                 const br_hash_class *hc;
372                 const unsigned char *hash_oid;
373                 uint32_t x;
374                 size_t sig_len;
375
376         case BR_KEYTYPE_RSA:
377                 hash_oid = get_hash_oid(hash_id);
378                 if (hash_oid == NULL && hash_id != 0) {
379                         if (zc->verbose) {
380                                 fprintf(stderr, "ERROR: cannot RSA-sign with"
381                                         " unknown hash function: %d\n",
382                                         hash_id);
383                         }
384                         return 0;
385                 }
386                 sig_len = (zc->sk->key.rsa.n_bitlen + 7) >> 3;
387                 if (len < sig_len) {
388                         if (zc->verbose) {
389                                 fprintf(stderr, "ERROR: cannot RSA-sign,"
390                                         " buffer is too small"
391                                         " (sig=%lu, buf=%lu)\n",
392                                         (unsigned long)sig_len,
393                                         (unsigned long)len);
394                         }
395                         return 0;
396                 }
397                 x = br_rsa_pkcs1_sign_get_default()(
398                         hash_oid, hv, hv_len, &zc->sk->key.rsa, data);
399                 if (!x) {
400                         if (zc->verbose) {
401                                 fprintf(stderr, "ERROR: RSA-sign failure\n");
402                         }
403                         return 0;
404                 }
405                 return sig_len;
406
407         case BR_KEYTYPE_EC:
408                 hc = get_hash_impl(hash_id);
409                 if (hc == NULL) {
410                         if (zc->verbose) {
411                                 fprintf(stderr, "ERROR: cannot ECDSA-sign with"
412                                         " unknown hash function: %d\n",
413                                         hash_id);
414                         }
415                         return 0;
416                 }
417                 if (len < 139) {
418                         if (zc->verbose) {
419                                 fprintf(stderr, "ERROR: cannot ECDSA-sign"
420                                         " (output buffer = %lu)\n",
421                                         (unsigned long)len);
422                         }
423                         return 0;
424                 }
425                 sig_len = br_ecdsa_sign_asn1_get_default()(
426                         br_ec_get_default(), hc, hv, &zc->sk->key.ec, data);
427                 if (sig_len == 0) {
428                         if (zc->verbose) {
429                                 fprintf(stderr, "ERROR: ECDSA-sign failure\n");
430                         }
431                         return 0;
432                 }
433                 return sig_len;
434
435         default:
436                 return 0;
437         }
438 }
439
440 static const br_ssl_client_certificate_class ccert_vtable = {
441         sizeof(ccert_context),
442         cc_start_name_list,
443         cc_start_name,
444         cc_append_name,
445         cc_end_name,
446         cc_end_name_list,
447         cc_choose,
448         cc_do_keyx,
449         cc_do_sign
450 };
451
452 static void
453 free_alpn(void *alpn)
454 {
455         xfree(*(char **)alpn);
456 }
457
458 static void
459 usage_client(void)
460 {
461         fprintf(stderr,
462 "usage: brssl client server[:port] [ options ]\n");
463         fprintf(stderr,
464 "options:\n");
465         fprintf(stderr,
466 "   -q              suppress verbose messages\n");
467         fprintf(stderr,
468 "   -trace          activate extra debug messages (dump of all packets)\n");
469         fprintf(stderr,
470 "   -sni name       use this specific name for SNI\n");
471         fprintf(stderr,
472 "   -nosni          do not send any SNI\n");
473         fprintf(stderr,
474 "   -mono           use monodirectional buffering\n");
475         fprintf(stderr,
476 "   -buf length     set the I/O buffer length (in bytes)\n");
477         fprintf(stderr,
478 "   -CA file        add certificates in 'file' to trust anchors\n");
479         fprintf(stderr,
480 "   -cert file      set client certificate chain\n");
481         fprintf(stderr,
482 "   -key file       set client private key (for certificate authentication)\n");
483         fprintf(stderr,
484 "   -nostaticecdh   prohibit full-static ECDH (client certificate)\n");
485         fprintf(stderr,
486 "   -list           list supported names (protocols, algorithms...)\n");
487         fprintf(stderr,
488 "   -vmin name      set minimum supported version (default: TLS-1.0)\n");
489         fprintf(stderr,
490 "   -vmax name      set maximum supported version (default: TLS-1.2)\n");
491         fprintf(stderr,
492 "   -cs names       set list of supported cipher suites (comma-separated)\n");
493         fprintf(stderr,
494 "   -hf names       add support for some hash functions (comma-separated)\n");
495         fprintf(stderr,
496 "   -minhello len   set minimum ClientHello length (in bytes)\n");
497         fprintf(stderr,
498 "   -fallback       send the TLS_FALLBACK_SCSV (i.e. claim a downgrade)\n");
499         fprintf(stderr,
500 "   -noreneg        prohibit renegotiations\n");
501         fprintf(stderr,
502 "   -alpn name      add protocol name to list of protocols (ALPN extension)\n");
503         fprintf(stderr,
504 "   -strictalpn     fail on ALPN mismatch\n");
505 }
506
507 /* see brssl.h */
508 int
509 do_client(int argc, char *argv[])
510 {
511         int retcode;
512         int verbose;
513         int trace;
514         int i, bidi;
515         const char *server_name;
516         char *host;
517         char *port;
518         const char *sni;
519         anchor_list anchors = VEC_INIT;
520         unsigned vmin, vmax;
521         VECTOR(char *) alpn_names = VEC_INIT;
522         cipher_suite *suites;
523         size_t num_suites;
524         uint16_t *suite_ids;
525         unsigned hfuns;
526         size_t u;
527         br_ssl_client_context cc;
528         br_x509_minimal_context xc;
529         x509_noanchor_context xwc;
530         const br_hash_class *dnhash;
531         ccert_context zc;
532         br_x509_certificate *chain;
533         size_t chain_len;
534         private_key *sk;
535         int nostaticecdh;
536         unsigned char *iobuf;
537         size_t iobuf_len;
538         size_t minhello_len;
539         int fallback;
540         uint32_t flags;
541         SOCKET fd;
542
543         retcode = 0;
544         verbose = 1;
545         trace = 0;
546         server_name = NULL;
547         host = NULL;
548         port = NULL;
549         sni = NULL;
550         bidi = 1;
551         vmin = 0;
552         vmax = 0;
553         suites = NULL;
554         num_suites = 0;
555         hfuns = 0;
556         suite_ids = NULL;
557         chain = NULL;
558         chain_len = 0;
559         sk = NULL;
560         nostaticecdh = 0;
561         iobuf = NULL;
562         iobuf_len = 0;
563         minhello_len = (size_t)-1;
564         fallback = 0;
565         flags = 0;
566         fd = INVALID_SOCKET;
567         for (i = 0; i < argc; i ++) {
568                 const char *arg;
569
570                 arg = argv[i];
571                 if (arg[0] != '-') {
572                         if (server_name != NULL) {
573                                 fprintf(stderr,
574                                         "ERROR: duplicate server name\n");
575                                 usage_client();
576                                 goto client_exit_error;
577                         }
578                         server_name = arg;
579                         continue;
580                 }
581                 if (eqstr(arg, "-v") || eqstr(arg, "-verbose")) {
582                         verbose = 1;
583                 } else if (eqstr(arg, "-q") || eqstr(arg, "-quiet")) {
584                         verbose = 0;
585                 } else if (eqstr(arg, "-trace")) {
586                         trace = 1;
587                 } else if (eqstr(arg, "-sni")) {
588                         if (++ i >= argc) {
589                                 fprintf(stderr,
590                                         "ERROR: no argument for '-sni'\n");
591                                 usage_client();
592                                 goto client_exit_error;
593                         }
594                         if (sni != NULL) {
595                                 fprintf(stderr, "ERROR: duplicate SNI\n");
596                                 usage_client();
597                                 goto client_exit_error;
598                         }
599                         sni = argv[i];
600                 } else if (eqstr(arg, "-nosni")) {
601                         if (sni != NULL) {
602                                 fprintf(stderr, "ERROR: duplicate SNI\n");
603                                 usage_client();
604                                 goto client_exit_error;
605                         }
606                         sni = "";
607                 } else if (eqstr(arg, "-mono")) {
608                         bidi = 0;
609                 } else if (eqstr(arg, "-buf")) {
610                         if (++ i >= argc) {
611                                 fprintf(stderr,
612                                         "ERROR: no argument for '-buf'\n");
613                                 usage_client();
614                                 goto client_exit_error;
615                         }
616                         arg = argv[i];
617                         if (iobuf_len != 0) {
618                                 fprintf(stderr,
619                                         "ERROR: duplicate I/O buffer length\n");
620                                 usage_client();
621                                 goto client_exit_error;
622                         }
623                         iobuf_len = parse_size(arg);
624                         if (iobuf_len == (size_t)-1) {
625                                 usage_client();
626                                 goto client_exit_error;
627                         }
628                 } else if (eqstr(arg, "-CA")) {
629                         if (++ i >= argc) {
630                                 fprintf(stderr,
631                                         "ERROR: no argument for '-CA'\n");
632                                 usage_client();
633                                 goto client_exit_error;
634                         }
635                         arg = argv[i];
636                         if (read_trust_anchors(&anchors, arg) == 0) {
637                                 usage_client();
638                                 goto client_exit_error;
639                         }
640                 } else if (eqstr(arg, "-cert")) {
641                         if (++ i >= argc) {
642                                 fprintf(stderr,
643                                         "ERROR: no argument for '-cert'\n");
644                                 usage_client();
645                                 goto client_exit_error;
646                         }
647                         if (chain != NULL) {
648                                 fprintf(stderr,
649                                         "ERROR: duplicate certificate chain\n");
650                                 usage_client();
651                                 goto client_exit_error;
652                         }
653                         arg = argv[i];
654                         chain = read_certificates(arg, &chain_len);
655                         if (chain == NULL || chain_len == 0) {
656                                 goto client_exit_error;
657                         }
658                 } else if (eqstr(arg, "-key")) {
659                         if (++ i >= argc) {
660                                 fprintf(stderr,
661                                         "ERROR: no argument for '-key'\n");
662                                 usage_client();
663                                 goto client_exit_error;
664                         }
665                         if (sk != NULL) {
666                                 fprintf(stderr,
667                                         "ERROR: duplicate private key\n");
668                                 usage_client();
669                                 goto client_exit_error;
670                         }
671                         arg = argv[i];
672                         sk = read_private_key(arg);
673                         if (sk == NULL) {
674                                 goto client_exit_error;
675                         }
676                 } else if (eqstr(arg, "-nostaticecdh")) {
677                         nostaticecdh = 1;
678                 } else if (eqstr(arg, "-list")) {
679                         list_names();
680                         goto client_exit;
681                 } else if (eqstr(arg, "-vmin")) {
682                         if (++ i >= argc) {
683                                 fprintf(stderr,
684                                         "ERROR: no argument for '-vmin'\n");
685                                 usage_client();
686                                 goto client_exit_error;
687                         }
688                         arg = argv[i];
689                         if (vmin != 0) {
690                                 fprintf(stderr,
691                                         "ERROR: duplicate minimum version\n");
692                                 usage_client();
693                                 goto client_exit_error;
694                         }
695                         vmin = parse_version(arg, strlen(arg));
696                         if (vmin == 0) {
697                                 fprintf(stderr,
698                                         "ERROR: unrecognised version '%s'\n",
699                                         arg);
700                                 usage_client();
701                                 goto client_exit_error;
702                         }
703                 } else if (eqstr(arg, "-vmax")) {
704                         if (++ i >= argc) {
705                                 fprintf(stderr,
706                                         "ERROR: no argument for '-vmax'\n");
707                                 usage_client();
708                                 goto client_exit_error;
709                         }
710                         arg = argv[i];
711                         if (vmax != 0) {
712                                 fprintf(stderr,
713                                         "ERROR: duplicate maximum version\n");
714                                 usage_client();
715                                 goto client_exit_error;
716                         }
717                         vmax = parse_version(arg, strlen(arg));
718                         if (vmax == 0) {
719                                 fprintf(stderr,
720                                         "ERROR: unrecognised version '%s'\n",
721                                         arg);
722                                 usage_client();
723                                 goto client_exit_error;
724                         }
725                 } else if (eqstr(arg, "-cs")) {
726                         if (++ i >= argc) {
727                                 fprintf(stderr,
728                                         "ERROR: no argument for '-cs'\n");
729                                 usage_client();
730                                 goto client_exit_error;
731                         }
732                         arg = argv[i];
733                         if (suites != NULL) {
734                                 fprintf(stderr, "ERROR: duplicate list"
735                                         " of cipher suites\n");
736                                 usage_client();
737                                 goto client_exit_error;
738                         }
739                         suites = parse_suites(arg, &num_suites);
740                         if (suites == NULL) {
741                                 usage_client();
742                                 goto client_exit_error;
743                         }
744                 } else if (eqstr(arg, "-hf")) {
745                         unsigned x;
746
747                         if (++ i >= argc) {
748                                 fprintf(stderr,
749                                         "ERROR: no argument for '-hf'\n");
750                                 usage_client();
751                                 goto client_exit_error;
752                         }
753                         arg = argv[i];
754                         x = parse_hash_functions(arg);
755                         if (x == 0) {
756                                 usage_client();
757                                 goto client_exit_error;
758                         }
759                         hfuns |= x;
760                 } else if (eqstr(arg, "-minhello")) {
761                         if (++ i >= argc) {
762                                 fprintf(stderr,
763                                         "ERROR: no argument for '-minhello'\n");
764                                 usage_client();
765                                 goto client_exit_error;
766                         }
767                         arg = argv[i];
768                         if (minhello_len != (size_t)-1) {
769                                 fprintf(stderr, "ERROR: duplicate minimum"
770                                         " ClientHello length\n");
771                                 usage_client();
772                                 goto client_exit_error;
773                         }
774                         minhello_len = parse_size(arg);
775                         /*
776                          * Minimum ClientHello length must fit on 16 bits.
777                          */
778                         if (minhello_len == (size_t)-1
779                                 || (((minhello_len >> 12) >> 4) != 0))
780                         {
781                                 usage_client();
782                                 goto client_exit_error;
783                         }
784                 } else if (eqstr(arg, "-fallback")) {
785                         fallback = 1;
786                 } else if (eqstr(arg, "-noreneg")) {
787                         flags |= BR_OPT_NO_RENEGOTIATION;
788                 } else if (eqstr(arg, "-alpn")) {
789                         if (++ i >= argc) {
790                                 fprintf(stderr,
791                                         "ERROR: no argument for '-alpn'\n");
792                                 usage_client();
793                                 goto client_exit_error;
794                         }
795                         VEC_ADD(alpn_names, xstrdup(argv[i]));
796                 } else if (eqstr(arg, "-strictalpn")) {
797                         flags |= BR_OPT_FAIL_ON_ALPN_MISMATCH;
798                 } else {
799                         fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
800                         usage_client();
801                         goto client_exit_error;
802                 }
803         }
804         if (server_name == NULL) {
805                 fprintf(stderr, "ERROR: no server name/address provided\n");
806                 usage_client();
807                 goto client_exit_error;
808         }
809         for (u = strlen(server_name); u > 0; u --) {
810                 int c = server_name[u - 1];
811                 if (c == ':') {
812                         break;
813                 }
814                 if (c < '0' || c > '9') {
815                         u = 0;
816                         break;
817                 }
818         }
819         if (u == 0) {
820                 host = xstrdup(server_name);
821                 port = xstrdup("443");
822         } else {
823                 port = xstrdup(server_name + u);
824                 host = xmalloc(u);
825                 memcpy(host, server_name, u - 1);
826                 host[u - 1] = 0;
827         }
828         if (sni == NULL) {
829                 sni = host;
830         }
831
832         if (chain == NULL && sk != NULL) {
833                 fprintf(stderr, "ERROR: private key specified, but"
834                         " no certificate chain\n");
835                 usage_client();
836                 goto client_exit_error;
837         }
838         if (chain != NULL && sk == NULL) {
839                 fprintf(stderr, "ERROR: certificate chain specified, but"
840                         " no private key\n");
841                 usage_client();
842                 goto client_exit_error;
843         }
844
845         if (vmin == 0) {
846                 vmin = BR_TLS10;
847         }
848         if (vmax == 0) {
849                 vmax = BR_TLS12;
850         }
851         if (vmax < vmin) {
852                 fprintf(stderr, "ERROR: impossible minimum/maximum protocol"
853                         " version combination\n");
854                 usage_client();
855                 goto client_exit_error;
856         }
857         if (suites == NULL) {
858                 num_suites = 0;
859
860                 for (u = 0; cipher_suites[u].name; u ++) {
861                         if ((cipher_suites[u].req & REQ_TLS12) == 0
862                                 || vmax >= BR_TLS12)
863                         {
864                                 num_suites ++;
865                         }
866                 }
867                 suites = xmalloc(num_suites * sizeof *suites);
868                 num_suites = 0;
869                 for (u = 0; cipher_suites[u].name; u ++) {
870                         if ((cipher_suites[u].req & REQ_TLS12) == 0
871                                 || vmax >= BR_TLS12)
872                         {
873                                 suites[num_suites ++] = cipher_suites[u];
874                         }
875                 }
876         }
877         if (hfuns == 0) {
878                 hfuns = (unsigned)-1;
879         }
880         if (iobuf_len == 0) {
881                 if (bidi) {
882                         iobuf_len = BR_SSL_BUFSIZE_BIDI;
883                 } else {
884                         iobuf_len = BR_SSL_BUFSIZE_MONO;
885                 }
886         }
887         iobuf = xmalloc(iobuf_len);
888
889         /*
890          * Compute implementation requirements and inject implementations.
891          */
892         suite_ids = xmalloc((num_suites + 1) * sizeof *suite_ids);
893         br_ssl_client_zero(&cc);
894         br_ssl_engine_set_versions(&cc.eng, vmin, vmax);
895         dnhash = NULL;
896         for (u = 0; hash_functions[u].name; u ++) {
897                 const br_hash_class *hc;
898                 int id;
899
900                 hc = hash_functions[u].hclass;
901                 id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
902                 if ((hfuns & ((unsigned)1 << id)) != 0) {
903                         dnhash = hc;
904                 }
905         }
906         if (dnhash == NULL) {
907                 fprintf(stderr, "ERROR: no supported hash function\n");
908                 goto client_exit_error;
909         }
910         br_x509_minimal_init(&xc, dnhash,
911                 &VEC_ELT(anchors, 0), VEC_LEN(anchors));
912         if (vmin <= BR_TLS11) {
913                 if (!(hfuns & (1 << br_md5_ID))) {
914                         fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need MD5\n");
915                         goto client_exit_error;
916                 }
917                 if (!(hfuns & (1 << br_sha1_ID))) {
918                         fprintf(stderr, "ERROR: TLS 1.0 and 1.1 need SHA-1\n");
919                         goto client_exit_error;
920                 }
921         }
922         for (u = 0; u < num_suites; u ++) {
923                 unsigned req;
924
925                 req = suites[u].req;
926                 suite_ids[u] = suites[u].suite;
927                 if ((req & REQ_TLS12) != 0 && vmax < BR_TLS12) {
928                         fprintf(stderr,
929                                 "ERROR: cipher suite %s requires TLS 1.2\n",
930                                 suites[u].name);
931                         goto client_exit_error;
932                 }
933                 if ((req & REQ_SHA1) != 0 && !(hfuns & (1 << br_sha1_ID))) {
934                         fprintf(stderr,
935                                 "ERROR: cipher suite %s requires SHA-1\n",
936                                 suites[u].name);
937                         goto client_exit_error;
938                 }
939                 if ((req & REQ_SHA256) != 0 && !(hfuns & (1 << br_sha256_ID))) {
940                         fprintf(stderr,
941                                 "ERROR: cipher suite %s requires SHA-256\n",
942                                 suites[u].name);
943                         goto client_exit_error;
944                 }
945                 if ((req & REQ_SHA384) != 0 && !(hfuns & (1 << br_sha384_ID))) {
946                         fprintf(stderr,
947                                 "ERROR: cipher suite %s requires SHA-384\n",
948                                 suites[u].name);
949                         goto client_exit_error;
950                 }
951                 /* TODO: algorithm implementation selection */
952                 if ((req & REQ_AESCBC) != 0) {
953                         br_ssl_engine_set_default_aes_cbc(&cc.eng);
954                 }
955                 if ((req & REQ_AESCCM) != 0) {
956                         br_ssl_engine_set_default_aes_ccm(&cc.eng);
957                 }
958                 if ((req & REQ_AESGCM) != 0) {
959                         br_ssl_engine_set_default_aes_gcm(&cc.eng);
960                 }
961                 if ((req & REQ_CHAPOL) != 0) {
962                         br_ssl_engine_set_default_chapol(&cc.eng);
963                 }
964                 if ((req & REQ_3DESCBC) != 0) {
965                         br_ssl_engine_set_default_des_cbc(&cc.eng);
966                 }
967                 if ((req & REQ_RSAKEYX) != 0) {
968                         br_ssl_client_set_default_rsapub(&cc);
969                 }
970                 if ((req & REQ_ECDHE_RSA) != 0) {
971                         br_ssl_engine_set_default_ec(&cc.eng);
972                         br_ssl_engine_set_default_rsavrfy(&cc.eng);
973                 }
974                 if ((req & REQ_ECDHE_ECDSA) != 0) {
975                         br_ssl_engine_set_default_ecdsa(&cc.eng);
976                 }
977                 if ((req & REQ_ECDH) != 0) {
978                         br_ssl_engine_set_default_ec(&cc.eng);
979                 }
980         }
981         if (fallback) {
982                 suite_ids[num_suites ++] = 0x5600;
983         }
984         br_ssl_engine_set_suites(&cc.eng, suite_ids, num_suites);
985
986         for (u = 0; hash_functions[u].name; u ++) {
987                 const br_hash_class *hc;
988                 int id;
989
990                 hc = hash_functions[u].hclass;
991                 id = (hc->desc >> BR_HASHDESC_ID_OFF) & BR_HASHDESC_ID_MASK;
992                 if ((hfuns & ((unsigned)1 << id)) != 0) {
993                         br_ssl_engine_set_hash(&cc.eng, id, hc);
994                         br_x509_minimal_set_hash(&xc, id, hc);
995                 }
996         }
997         if (vmin <= BR_TLS11) {
998                 br_ssl_engine_set_prf10(&cc.eng, &br_tls10_prf);
999         }
1000         if (vmax >= BR_TLS12) {
1001                 if ((hfuns & ((unsigned)1 << br_sha256_ID)) != 0) {
1002                         br_ssl_engine_set_prf_sha256(&cc.eng,
1003                                 &br_tls12_sha256_prf);
1004                 }
1005                 if ((hfuns & ((unsigned)1 << br_sha384_ID)) != 0) {
1006                         br_ssl_engine_set_prf_sha384(&cc.eng,
1007                                 &br_tls12_sha384_prf);
1008                 }
1009         }
1010         br_x509_minimal_set_rsa(&xc, br_rsa_pkcs1_vrfy_get_default());
1011         br_x509_minimal_set_ecdsa(&xc,
1012                 br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
1013
1014         /*
1015          * If there is no provided trust anchor, then certificate validation
1016          * will always fail. In that situation, we use our custom wrapper
1017          * that tolerates unknown anchors.
1018          */
1019         if (VEC_LEN(anchors) == 0) {
1020                 if (verbose) {
1021                         fprintf(stderr,
1022                                 "WARNING: no configured trust anchor\n");
1023                 }
1024                 x509_noanchor_init(&xwc, &xc.vtable);
1025                 br_ssl_engine_set_x509(&cc.eng, &xwc.vtable);
1026         } else {
1027                 br_ssl_engine_set_x509(&cc.eng, &xc.vtable);
1028         }
1029
1030         if (minhello_len != (size_t)-1) {
1031                 br_ssl_client_set_min_clienthello_len(&cc, minhello_len);
1032         }
1033         br_ssl_engine_set_all_flags(&cc.eng, flags);
1034         if (VEC_LEN(alpn_names) != 0) {
1035                 br_ssl_engine_set_protocol_names(&cc.eng,
1036                         (const char **)&VEC_ELT(alpn_names, 0),
1037                         VEC_LEN(alpn_names));
1038         }
1039
1040         if (chain != NULL) {
1041                 zc.vtable = &ccert_vtable;
1042                 zc.verbose = verbose;
1043                 zc.chain = chain;
1044                 zc.chain_len = chain_len;
1045                 zc.sk = sk;
1046                 if (nostaticecdh || sk->key_type != BR_KEYTYPE_EC) {
1047                         zc.issuer_key_type = 0;
1048                 } else {
1049                         zc.issuer_key_type = get_cert_signer_algo(&chain[0]);
1050                         if (zc.issuer_key_type == 0) {
1051                                 goto client_exit_error;
1052                         }
1053                 }
1054                 br_ssl_client_set_client_certificate(&cc, &zc.vtable);
1055         }
1056
1057         br_ssl_engine_set_buffer(&cc.eng, iobuf, iobuf_len, bidi);
1058         br_ssl_client_reset(&cc, sni, 0);
1059
1060         /*
1061          * On Unix systems, we need to avoid SIGPIPE.
1062          */
1063 #ifndef _WIN32
1064         signal(SIGPIPE, SIG_IGN);
1065 #endif
1066
1067         /*
1068          * Connect to the peer.
1069          */
1070         fd = host_connect(host, port, verbose);
1071         if (fd == INVALID_SOCKET) {
1072                 goto client_exit_error;
1073         }
1074
1075         /*
1076          * Run the engine until completion.
1077          */
1078         if (run_ssl_engine(&cc.eng, fd,
1079                 (verbose ? RUN_ENGINE_VERBOSE : 0)
1080                 | (trace ? RUN_ENGINE_TRACE : 0)) != 0)
1081         {
1082                 goto client_exit_error;
1083         } else {
1084                 goto client_exit;
1085         }
1086
1087         /*
1088          * Release allocated structures.
1089          */
1090 client_exit:
1091         xfree(host);
1092         xfree(port);
1093         xfree(suites);
1094         xfree(suite_ids);
1095         VEC_CLEAREXT(anchors, &free_ta_contents);
1096         VEC_CLEAREXT(alpn_names, &free_alpn);
1097         free_certificates(chain, chain_len);
1098         free_private_key(sk);
1099         xfree(iobuf);
1100         if (fd != INVALID_SOCKET) {
1101 #ifdef _WIN32
1102                 closesocket(fd);
1103 #else
1104                 close(fd);
1105 #endif
1106         }
1107         return retcode;
1108
1109 client_exit_error:
1110         retcode = -1;
1111         goto client_exit;
1112 }