Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/bearssl/tools/client.c
39534 views
1
/*
2
* Copyright (c) 2016 Thomas Pornin <[email protected]>
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
}
1113
1114