2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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
35 #include <sys/types.h>
36 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
45 #define INVALID_SOCKET (-1)
51 dump_blob(const char *name
, const void *data
, size_t len
)
53 const unsigned char *buf
;
57 fprintf(stderr
, "%s (len = %lu)", name
, (unsigned long)len
);
58 for (u
= 0; u
< len
; u
++) {
60 fprintf(stderr
, "\n%08lX ", (unsigned long)u
);
61 } else if ((u
& 7) == 0) {
64 fprintf(stderr
, " %02x", buf
[u
]);
66 fprintf(stderr
, "\n");
70 * Inspect the provided data in case it is a "command" to trigger a
71 * special behaviour. If the command is recognised, then it is executed
72 * and this function returns 1. Otherwise, this function returns 0.
75 run_command(br_ssl_engine_context
*cc
, unsigned char *buf
, size_t len
)
78 * A single static slot for saving session parameters.
80 static br_ssl_session_parameters slot
;
81 static int slot_used
= 0;
85 if (len
< 2 || len
> 3) {
88 if (len
== 3 && (buf
[1] != '\r' || buf
[2] != '\n')) {
91 if (len
== 2 && buf
[1] != '\n') {
96 fprintf(stderr
, "closing...\n");
97 br_ssl_engine_close(cc
);
100 if (br_ssl_engine_renegotiate(cc
)) {
101 fprintf(stderr
, "renegotiating...\n");
103 fprintf(stderr
, "not renegotiating.\n");
108 * Session forget is nominally client-only. But the
109 * session parameters are in the engine structure, which
110 * is the first field of the client context, so the cast
111 * still works properly. On the server, this forgetting
114 fprintf(stderr
, "forgetting session...\n");
115 br_ssl_client_forget_session((br_ssl_client_context
*)cc
);
118 fprintf(stderr
, "saving session parameters...\n");
119 br_ssl_engine_get_session_parameters(cc
, &slot
);
120 fprintf(stderr
, " id = ");
121 for (u
= 0; u
< slot
.session_id_len
; u
++) {
122 fprintf(stderr
, "%02X", slot
.session_id
[u
]);
124 fprintf(stderr
, "\n");
129 fprintf(stderr
, "restoring session parameters...\n");
130 fprintf(stderr
, " id = ");
131 for (u
= 0; u
< slot
.session_id_len
; u
++) {
132 fprintf(stderr
, "%02X", slot
.session_id
[u
]);
134 fprintf(stderr
, "\n");
135 br_ssl_engine_set_session_parameters(cc
, &slot
);
147 unsigned char buf
[1024];
152 in_return_bytes(in_buffer
*bb
, unsigned char *buf
, size_t len
)
154 if (bb
->ptr
< bb
->len
) {
160 clen
= bb
->len
- bb
->ptr
;
164 memcpy(buf
, bb
->buf
+ bb
->ptr
, clen
);
166 if (bb
->ptr
== bb
->len
) {
167 bb
->ptr
= bb
->len
= 0;
175 * A buffered version of in_read(), using a buffer to return only
176 * full lines when feasible.
179 in_read_buffered(HANDLE h_in
, in_buffer
*bb
, unsigned char *buf
, size_t len
)
186 n
= in_return_bytes(bb
, buf
, len
);
194 if (!PeekConsoleInput(h_in
, &inrec
, 1, &v
)) {
195 fprintf(stderr
, "ERROR: PeekConsoleInput()"
196 " failed with 0x%08lX\n",
197 (unsigned long)GetLastError());
203 if (!ReadConsoleInput(h_in
, &inrec
, 1, &v
)) {
204 fprintf(stderr
, "ERROR: ReadConsoleInput()"
205 " failed with 0x%08lX\n",
206 (unsigned long)GetLastError());
212 if (inrec
.EventType
== KEY_EVENT
213 && inrec
.Event
.KeyEvent
.bKeyDown
)
217 c
= inrec
.Event
.KeyEvent
.uChar
.AsciiChar
;
218 if (c
== '\n' || c
== '\r' || c
== '\t'
219 || (c
>= 32 && c
!= 127))
224 bb
->buf
[bb
->ptr
++] = (unsigned char)c
;
228 if (bb
->len
== sizeof bb
->buf
|| c
== '\n') {
230 return in_return_bytes(bb
, buf
, len
);
238 in_avail_buffered(HANDLE h_in
, in_buffer
*bb
)
240 return in_read_buffered(h_in
, bb
, NULL
, 1);
247 run_ssl_engine(br_ssl_engine_context
*cc
, unsigned long fd
, unsigned flags
)
255 int can_send
, can_recv
;
262 verbose
= (flags
& RUN_ENGINE_VERBOSE
) != 0;
263 trace
= (flags
& RUN_ENGINE_TRACE
) != 0;
266 * Print algorithm details.
271 fprintf(stderr
, "Algorithms:\n");
272 br_prng_seeder_system(&rngname
);
273 fprintf(stderr
, " RNG: %s\n", rngname
);
274 if (cc
->iaes_cbcenc
!= 0) {
275 fprintf(stderr
, " AES/CBC (enc): %s\n",
276 get_algo_name(cc
->iaes_cbcenc
, 0));
278 if (cc
->iaes_cbcdec
!= 0) {
279 fprintf(stderr
, " AES/CBC (dec): %s\n",
280 get_algo_name(cc
->iaes_cbcdec
, 0));
282 if (cc
->iaes_ctr
!= 0) {
283 fprintf(stderr
, " AES/CTR: %s\n",
284 get_algo_name(cc
->iaes_ctr
, 0));
286 if (cc
->iaes_ctrcbc
!= 0) {
287 fprintf(stderr
, " AES/CCM: %s\n",
288 get_algo_name(cc
->iaes_ctrcbc
, 0));
290 if (cc
->ides_cbcenc
!= 0) {
291 fprintf(stderr
, " DES/CBC (enc): %s\n",
292 get_algo_name(cc
->ides_cbcenc
, 0));
294 if (cc
->ides_cbcdec
!= 0) {
295 fprintf(stderr
, " DES/CBC (dec): %s\n",
296 get_algo_name(cc
->ides_cbcdec
, 0));
298 if (cc
->ighash
!= 0) {
299 fprintf(stderr
, " GHASH (GCM): %s\n",
300 get_algo_name(cc
->ighash
, 0));
302 if (cc
->ichacha
!= 0) {
303 fprintf(stderr
, " ChaCha20: %s\n",
304 get_algo_name(cc
->ichacha
, 0));
306 if (cc
->ipoly
!= 0) {
307 fprintf(stderr
, " Poly1305: %s\n",
308 get_algo_name(cc
->ipoly
, 0));
311 fprintf(stderr
, " EC: %s\n",
312 get_algo_name(cc
->iec
, 0));
314 if (cc
->iecdsa
!= 0) {
315 fprintf(stderr
, " ECDSA: %s\n",
316 get_algo_name(cc
->iecdsa
, 0));
318 if (cc
->irsavrfy
!= 0) {
319 fprintf(stderr
, " RSA (vrfy): %s\n",
320 get_algo_name(cc
->irsavrfy
, 0));
325 fd_event
= WSA_INVALID_EVENT
;
332 * On Unix systems, we need to follow three descriptors:
333 * standard input (0), standard output (1), and the socket
334 * itself (for both read and write). This is done with a poll()
337 * On Windows systems, we use WSAEventSelect() to associate
338 * an event handle with the network activity, and we use
339 * WaitForMultipleObjectsEx() on that handle and the standard
340 * input handle, when appropriate. Standard output is assumed
341 * to be always writeable, and standard input to be the console;
342 * this does not work well (or at all) with redirections (to
343 * pipes or files) but it should be enough for a debug tool
344 * (TODO: make something that handles redirections as well).
348 fd_event
= WSACreateEvent();
349 if (fd_event
== WSA_INVALID_EVENT
) {
350 fprintf(stderr
, "ERROR: WSACreateEvent() failed with %d\n",
355 WSAEventSelect(fd
, fd_event
, FD_READ
| FD_WRITE
| FD_CLOSE
);
356 h_in
= GetStdHandle(STD_INPUT_HANDLE
);
357 h_out
= GetStdHandle(STD_OUTPUT_HANDLE
);
358 SetConsoleMode(h_in
, ENABLE_ECHO_INPUT
360 | ENABLE_PROCESSED_INPUT
361 | ENABLE_PROCESSED_OUTPUT
362 | ENABLE_WRAP_AT_EOL_OUTPUT
);
365 * Make sure that stdin and stdout are non-blocking.
367 fcntl(0, F_SETFL
, O_NONBLOCK
);
368 fcntl(1, F_SETFL
, O_NONBLOCK
);
376 int sendrec
, recvrec
, sendapp
, recvapp
;
381 struct pollfd pfd
[3];
384 size_t u
, k_fd
, k_in
, k_out
;
385 int sendrec_ok
, recvrec_ok
, sendapp_ok
, recvapp_ok
;
388 * Get current engine state.
390 st
= br_ssl_engine_current_state(cc
);
391 if (st
== BR_SSL_CLOSED
) {
394 err
= br_ssl_engine_last_error(cc
);
395 if (err
== BR_ERR_OK
) {
398 "SSL closed normally\n");
403 fprintf(stderr
, "ERROR: SSL error %d", err
);
405 if (err
>= BR_ERR_SEND_FATAL_ALERT
) {
406 err
-= BR_ERR_SEND_FATAL_ALERT
;
408 " (sent alert %d)\n", err
);
409 } else if (err
>= BR_ERR_RECV_FATAL_ALERT
) {
410 err
-= BR_ERR_RECV_FATAL_ALERT
;
412 " (received alert %d)\n", err
);
416 ename
= find_error_name(err
, NULL
);
420 fprintf(stderr
, " (%s)\n", ename
);
427 * Compute descriptors that must be polled, depending
430 sendrec
= ((st
& BR_SSL_SENDREC
) != 0);
431 recvrec
= ((st
& BR_SSL_RECVREC
) != 0);
432 sendapp
= ((st
& BR_SSL_SENDAPP
) != 0);
433 recvapp
= ((st
& BR_SSL_RECVAPP
) != 0);
434 if (verbose
&& sendapp
&& !hsdetails
) {
438 fprintf(stderr
, "Handshake completed\n");
439 fprintf(stderr
, " version: ");
440 switch (cc
->session
.version
) {
442 fprintf(stderr
, "SSL 3.0");
445 fprintf(stderr
, "TLS 1.0");
448 fprintf(stderr
, "TLS 1.1");
451 fprintf(stderr
, "TLS 1.2");
454 fprintf(stderr
, "unknown (0x%04X)",
455 (unsigned)cc
->session
.version
);
458 fprintf(stderr
, "\n");
460 cc
->session
.cipher_suite
, csn
, sizeof csn
);
461 fprintf(stderr
, " cipher suite: %s\n", csn
);
462 if (uses_ecdhe(cc
->session
.cipher_suite
)) {
464 br_ssl_engine_get_ecdhe_curve(cc
),
467 " ECDHE curve: %s\n", csn
);
469 fprintf(stderr
, " secure renegotiation: %s\n",
470 cc
->reneg
== 1 ? "no" : "yes");
471 pname
= br_ssl_engine_get_selected_protocol(cc
);
474 " protocol name (ALPN): %s\n",
487 * If we recorded that we can send or receive data, and we
488 * want to do exactly that, then we don't wait; we just do
496 if (sendrec
&& can_send
) {
498 } else if (recvrec
&& can_recv
) {
500 } else if (recvapp
) {
502 } else if (sendapp
&& in_avail_buffered(h_in
, &bb
)) {
506 * If we cannot do I/O right away, then we must
507 * wait for some event, and try again.
509 pfd
[u
] = (HANDLE
)fd_event
;
517 wt
= WaitForMultipleObjectsEx(u
, pfd
,
518 FALSE
, INFINITE
, FALSE
);
519 if (wt
== WAIT_FAILED
) {
520 fprintf(stderr
, "ERROR:"
521 " WaitForMultipleObjectsEx()"
522 " failed with 0x%08lX",
523 (unsigned long)GetLastError());
530 if (WSAEnumNetworkEvents(fd
, fd_event
, &e
)) {
531 fprintf(stderr
, "ERROR:"
532 " WSAEnumNetworkEvents()"
538 if (e
.lNetworkEvents
& (FD_WRITE
| FD_CLOSE
)) {
541 if (e
.lNetworkEvents
& (FD_READ
| FD_CLOSE
)) {
548 if (sendrec
|| recvrec
) {
553 pfd
[u
].events
|= POLLOUT
;
556 pfd
[u
].events
|= POLLIN
;
564 pfd
[u
].events
= POLLIN
;
571 pfd
[u
].events
= POLLOUT
;
575 n
= poll(pfd
, u
, -1);
577 if (errno
== EINTR
) {
580 perror("ERROR: poll()");
589 * We transform closures/errors into read+write accesses
590 * so as to force the read() or write() call that will
591 * detect the situation.
594 if (pfd
[u
].revents
& (POLLERR
| POLLHUP
)) {
595 pfd
[u
].revents
|= POLLIN
| POLLOUT
;
599 recvapp_ok
= recvapp
&& (pfd
[k_out
].revents
& POLLOUT
) != 0;
600 sendrec_ok
= sendrec
&& (pfd
[k_fd
].revents
& POLLOUT
) != 0;
601 recvrec_ok
= recvrec
&& (pfd
[k_fd
].revents
& POLLIN
) != 0;
602 sendapp_ok
= sendapp
&& (pfd
[k_in
].revents
& POLLIN
) != 0;
606 * We give preference to outgoing data, on stdout and on
618 buf
= br_ssl_engine_recvapp_buf(cc
, &len
);
620 if (!WriteFile(h_out
, buf
, len
, &wlen
, NULL
)) {
622 fprintf(stderr
, "stdout closed...\n");
628 wlen
= write(1, buf
, len
);
631 fprintf(stderr
, "stdout closed...\n");
637 br_ssl_engine_recvapp_ack(cc
, wlen
);
645 buf
= br_ssl_engine_sendrec_buf(cc
, &len
);
646 wlen
= send(fd
, buf
, len
, 0);
651 err
= WSAGetLastError();
652 if (err
== EWOULDBLOCK
653 || err
== WSAEWOULDBLOCK
)
659 if (errno
== EINTR
|| errno
== EWOULDBLOCK
) {
664 fprintf(stderr
, "socket closed...\n");
670 dump_blob("Outgoing bytes", buf
, wlen
);
672 br_ssl_engine_sendrec_ack(cc
, wlen
);
680 buf
= br_ssl_engine_recvrec_buf(cc
, &len
);
681 rlen
= recv(fd
, buf
, len
, 0);
684 fprintf(stderr
, "socket closed...\n");
693 err
= WSAGetLastError();
694 if (err
== EWOULDBLOCK
695 || err
== WSAEWOULDBLOCK
)
701 if (errno
== EINTR
|| errno
== EWOULDBLOCK
) {
706 fprintf(stderr
, "socket broke...\n");
712 dump_blob("Incoming bytes", buf
, rlen
);
714 br_ssl_engine_recvrec_ack(cc
, rlen
);
726 buf
= br_ssl_engine_sendapp_buf(cc
, &len
);
728 rlen
= in_read_buffered(h_in
, &bb
, buf
, len
);
730 rlen
= read(0, buf
, len
);
734 fprintf(stderr
, "stdin closed...\n");
736 br_ssl_engine_close(cc
);
737 } else if (!run_command(cc
, buf
, rlen
)) {
738 br_ssl_engine_sendapp_ack(cc
, rlen
);
740 br_ssl_engine_flush(cc
, 0);
744 /* We should never reach that point. */
745 fprintf(stderr
, "ERROR: poll() misbehaves\n");
751 * Release allocated structures.
755 if (fd_event
!= WSA_INVALID_EVENT
) {
756 WSACloseEvent(fd_event
);