2 * librb: a library used by ircd-ratbox and other things
3 * openssl.c: OpenSSL backend
5 * Copyright (C) 2007-2008 ircd-ratbox development team
6 * Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
7 * Copyright (C) 2015-2016 Aaron Jones <aaronmdjones@gmail.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
26 #include <librb_config.h>
31 #include <commio-int.h>
32 #include <commio-ssl.h>
34 #include "openssl_ratbox.h"
38 RB_FD_TLS_DIRECTION_IN
= 0,
39 RB_FD_TLS_DIRECTION_OUT
= 1
40 } rb_fd_tls_direction
;
42 #define SSL_P(x) ((SSL *)((x)->ssl))
46 static SSL_CTX
*ssl_ctx
= NULL
;
55 static const char *rb_ssl_strerror(unsigned long);
56 static void rb_ssl_connect_realcb(rb_fde_t
*, int, struct ssl_connect
*);
61 * Internal OpenSSL-specific code
67 unsigned long err_saved
, err
= 0;
69 while((err_saved
= ERR_get_error()) != 0)
76 rb_ssl_init_fd(rb_fde_t
*const F
, const rb_fd_tls_direction dir
)
78 (void) rb_ssl_last_err();
80 F
->ssl
= SSL_new(ssl_ctx
);
84 rb_lib_log("%s: SSL_new: %s", __func__
, rb_ssl_strerror(rb_ssl_last_err()));
91 case RB_FD_TLS_DIRECTION_IN
:
92 SSL_set_accept_state(SSL_P(F
));
94 case RB_FD_TLS_DIRECTION_OUT
:
95 SSL_set_connect_state(SSL_P(F
));
99 SSL_set_fd(SSL_P(F
), rb_get_fd(F
));
103 rb_ssl_accept_common(rb_fde_t
*const F
, void *const data
)
105 lrb_assert(F
!= NULL
);
106 lrb_assert(F
->accept
!= NULL
);
107 lrb_assert(F
->accept
->callback
!= NULL
);
108 lrb_assert(F
->ssl
!= NULL
);
110 (void) rb_ssl_last_err();
112 int ret
= SSL_do_handshake(SSL_P(F
));
113 int err
= SSL_get_error(SSL_P(F
), ret
);
117 F
->handshake_count
++;
119 rb_settimeout(F
, 0, NULL
, NULL
);
120 rb_setselect(F
, RB_SELECT_READ
| RB_SELECT_WRITE
, NULL
, NULL
);
122 struct acceptdata
*const ad
= F
->accept
;
124 ad
->callback(F
, RB_OK
, (struct sockaddr
*)&ad
->S
, ad
->addrlen
, ad
->data
);
129 if(ret
== -1 && err
== SSL_ERROR_WANT_READ
)
131 rb_setselect(F
, RB_SELECT_READ
, rb_ssl_accept_common
, NULL
);
134 if(ret
== -1 && err
== SSL_ERROR_WANT_WRITE
)
136 rb_setselect(F
, RB_SELECT_WRITE
, rb_ssl_accept_common
, NULL
);
141 F
->ssl_errno
= (unsigned long) err
;
142 F
->accept
->callback(F
, RB_ERROR_SSL
, NULL
, 0, F
->accept
->data
);
146 rb_ssl_connect_common(rb_fde_t
*const F
, void *const data
)
148 lrb_assert(F
!= NULL
);
149 lrb_assert(F
->ssl
!= NULL
);
151 (void) rb_ssl_last_err();
153 int ret
= SSL_do_handshake(SSL_P(F
));
154 int err
= SSL_get_error(SSL_P(F
), ret
);
158 F
->handshake_count
++;
160 rb_settimeout(F
, 0, NULL
, NULL
);
161 rb_setselect(F
, RB_SELECT_READ
| RB_SELECT_WRITE
, NULL
, NULL
);
163 rb_ssl_connect_realcb(F
, RB_OK
, data
);
167 if(ret
== -1 && err
== SSL_ERROR_WANT_READ
)
169 rb_setselect(F
, RB_SELECT_READ
, rb_ssl_connect_common
, data
);
172 if(ret
== -1 && err
== SSL_ERROR_WANT_WRITE
)
174 rb_setselect(F
, RB_SELECT_WRITE
, rb_ssl_connect_common
, data
);
179 F
->ssl_errno
= (unsigned long) err
;
180 rb_ssl_connect_realcb(F
, RB_ERROR_SSL
, data
);
184 rb_ssl_strerror(const unsigned long err
)
186 static char errbuf
[512];
188 ERR_error_string_n(err
, errbuf
, sizeof errbuf
);
194 verify_accept_all_cb(const int preverify_ok
, X509_STORE_CTX
*const x509_ctx
)
200 rb_ssl_read_or_write(const int r_or_w
, rb_fde_t
*const F
, void *const rbuf
, const void *const wbuf
, const size_t count
)
205 (void) rb_ssl_last_err();
208 ret
= (ssize_t
) SSL_read(SSL_P(F
), rbuf
, (int)count
);
210 ret
= (ssize_t
) SSL_write(SSL_P(F
), wbuf
, (int)count
);
214 switch(SSL_get_error(SSL_P(F
), ret
))
216 case SSL_ERROR_WANT_READ
:
218 return RB_RW_SSL_NEED_READ
;
219 case SSL_ERROR_WANT_WRITE
:
221 return RB_RW_SSL_NEED_WRITE
;
222 case SSL_ERROR_ZERO_RETURN
:
224 case SSL_ERROR_SYSCALL
:
225 err
= rb_ssl_last_err();
229 return RB_RW_IO_ERROR
;
233 err
= rb_ssl_last_err();
240 errno
= EIO
; /* not great but... */
241 return RB_RW_SSL_ERROR
;
243 return RB_RW_IO_ERROR
;
249 make_certfp(X509
*const cert
, uint8_t certfp
[const RB_SSL_CERTFP_LEN
], const int method
)
251 unsigned int hashlen
= 0;
252 const EVP_MD
*md_type
= NULL
;
253 const ASN1_ITEM
*item
= NULL
;
258 case RB_SSL_CERTFP_METH_CERT_SHA1
:
259 hashlen
= RB_SSL_CERTFP_LEN_SHA1
;
260 md_type
= EVP_sha1();
261 item
= ASN1_ITEM_rptr(X509
);
264 case RB_SSL_CERTFP_METH_CERT_SHA256
:
265 hashlen
= RB_SSL_CERTFP_LEN_SHA256
;
266 md_type
= EVP_sha256();
267 item
= ASN1_ITEM_rptr(X509
);
270 case RB_SSL_CERTFP_METH_CERT_SHA512
:
271 hashlen
= RB_SSL_CERTFP_LEN_SHA512
;
272 md_type
= EVP_sha512();
273 item
= ASN1_ITEM_rptr(X509
);
276 case RB_SSL_CERTFP_METH_SPKI_SHA256
:
277 hashlen
= RB_SSL_CERTFP_LEN_SHA256
;
278 md_type
= EVP_sha256();
279 item
= ASN1_ITEM_rptr(X509_PUBKEY
);
280 data
= X509_get_X509_PUBKEY(cert
);
282 case RB_SSL_CERTFP_METH_SPKI_SHA512
:
283 hashlen
= RB_SSL_CERTFP_LEN_SHA512
;
284 md_type
= EVP_sha512();
285 item
= ASN1_ITEM_rptr(X509_PUBKEY
);
286 data
= X509_get_X509_PUBKEY(cert
);
292 if(ASN1_item_digest(item
, md_type
, data
, certfp
, &hashlen
) != 1)
295 return (int) hashlen
;
301 * External OpenSSL-specific code
305 rb_ssl_shutdown(rb_fde_t
*const F
)
307 if(F
== NULL
|| F
->ssl
== NULL
)
310 (void) rb_ssl_last_err();
312 for(int i
= 0; i
< 4; i
++)
314 int ret
= SSL_shutdown(SSL_P(F
));
315 int err
= SSL_get_error(SSL_P(F
), ret
);
317 if(ret
>= 0 || (err
!= SSL_ERROR_WANT_READ
&& err
!= SSL_ERROR_WANT_WRITE
))
328 #ifndef LRB_SSL_NO_EXPLICIT_INIT
329 (void) SSL_library_init();
330 SSL_load_error_strings();
333 rb_lib_log("%s: OpenSSL backend initialised", __func__
);
338 rb_setup_ssl_server(const char *const certfile
, const char *keyfile
,
339 const char *const dhfile
, const char *cipherlist
)
343 rb_lib_log("%s: no certificate file specified", __func__
);
350 if(cipherlist
== NULL
)
351 cipherlist
= rb_default_ciphers
;
354 (void) rb_ssl_last_err();
356 #ifdef LRB_HAVE_TLS_METHOD_API
357 SSL_CTX
*const ssl_ctx_new
= SSL_CTX_new(TLS_method());
359 SSL_CTX
*const ssl_ctx_new
= SSL_CTX_new(SSLv23_method());
362 if(ssl_ctx_new
== NULL
)
364 rb_lib_log("%s: SSL_CTX_new: %s", __func__
, rb_ssl_strerror(rb_ssl_last_err()));
368 if(SSL_CTX_use_certificate_chain_file(ssl_ctx_new
, certfile
) != 1)
370 rb_lib_log("%s: SSL_CTX_use_certificate_chain_file ('%s'): %s", __func__
, certfile
,
371 rb_ssl_strerror(rb_ssl_last_err()));
373 SSL_CTX_free(ssl_ctx_new
);
377 if(SSL_CTX_use_PrivateKey_file(ssl_ctx_new
, keyfile
, SSL_FILETYPE_PEM
) != 1)
379 rb_lib_log("%s: SSL_CTX_use_PrivateKey_file ('%s'): %s", __func__
, keyfile
,
380 rb_ssl_strerror(rb_ssl_last_err()));
382 SSL_CTX_free(ssl_ctx_new
);
388 rb_lib_log("%s: no DH parameters file specified", __func__
);
392 FILE *const dhf
= fopen(dhfile
, "r");
397 rb_lib_log("%s: fopen ('%s'): %s", __func__
, dhfile
, strerror(errno
));
399 else if(PEM_read_DHparams(dhf
, &dhp
, NULL
, NULL
) == NULL
)
401 rb_lib_log("%s: PEM_read_DHparams ('%s'): %s", __func__
, dhfile
,
402 rb_ssl_strerror(rb_ssl_last_err()));
407 SSL_CTX_set_tmp_dh(ssl_ctx_new
, dhp
);
413 if(SSL_CTX_set_cipher_list(ssl_ctx_new
, cipherlist
) != 1)
415 rb_lib_log("%s: SSL_CTX_set_cipher_list: could not configure any ciphers", __func__
);
416 SSL_CTX_free(ssl_ctx_new
);
420 SSL_CTX_set_session_cache_mode(ssl_ctx_new
, SSL_SESS_CACHE_OFF
);
421 SSL_CTX_set_verify(ssl_ctx_new
, SSL_VERIFY_PEER
| SSL_VERIFY_CLIENT_ONCE
, verify_accept_all_cb
);
423 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
424 (void) SSL_CTX_clear_options(ssl_ctx_new
, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
);
427 #ifndef LRB_HAVE_TLS_METHOD_API
428 (void) SSL_CTX_set_options(ssl_ctx_new
, SSL_OP_NO_SSLv2
| SSL_OP_NO_SSLv3
);
431 #ifdef SSL_OP_NO_TICKET
432 (void) SSL_CTX_set_options(ssl_ctx_new
, SSL_OP_NO_TICKET
);
435 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
436 (void) SSL_CTX_set_options(ssl_ctx_new
, SSL_OP_CIPHER_SERVER_PREFERENCE
);
439 #ifdef SSL_OP_SINGLE_DH_USE
440 (void) SSL_CTX_set_options(ssl_ctx_new
, SSL_OP_SINGLE_DH_USE
);
443 #ifdef SSL_OP_SINGLE_ECDH_USE
444 (void) SSL_CTX_set_options(ssl_ctx_new
, SSL_OP_SINGLE_ECDH_USE
);
447 #ifdef LRB_HAVE_TLS_ECDH_AUTO
448 (void) SSL_CTX_set_ecdh_auto(ssl_ctx_new
, 1);
451 #ifdef LRB_HAVE_TLS_SET_CURVES
452 (void) SSL_CTX_set1_curves_list(ssl_ctx_new
, rb_default_curves
);
454 # if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && !defined(OPENSSL_NO_ECDH) && defined(NID_secp384r1)
455 EC_KEY
*const ec_key
= EC_KEY_new_by_curve_name(NID_secp384r1
);
458 SSL_CTX_set_tmp_ecdh(ssl_ctx_new
, ec_key
);
462 rb_lib_log("%s: EC_KEY_new_by_curve_name failed; will not enable ECDHE- ciphers", __func__
);
464 rb_lib_log("%s: OpenSSL built without ECDH support; will not enable ECDHE- ciphers", __func__
);
470 SSL_CTX_free(ssl_ctx
);
472 ssl_ctx
= ssl_ctx_new
;
475 rb_lib_log("%s: TLS configuration successful", __func__
);
480 rb_init_prng(const char *const path
, prng_seed_t seed_type
)
482 (void) rb_ssl_last_err();
484 if(seed_type
== RB_PRNG_FILE
&& RAND_load_file(path
, -1) < 0)
485 rb_lib_log("%s: RAND_load_file: %s", __func__
, rb_ssl_strerror(rb_ssl_last_err()));
487 if(RAND_status() != 1)
489 rb_lib_log("%s: RAND_status: %s", __func__
, rb_ssl_strerror(rb_ssl_last_err()));
493 rb_lib_log("%s: PRNG initialised", __func__
);
498 rb_get_random(void *const buf
, const size_t length
)
500 (void) rb_ssl_last_err();
502 if(RAND_bytes(buf
, (int) length
) != 1)
504 rb_lib_log("%s: RAND_bytes: %s", __func__
, rb_ssl_strerror(rb_ssl_last_err()));
512 rb_get_ssl_strerror(rb_fde_t
*const F
)
514 return rb_ssl_strerror(F
->ssl_errno
);
518 rb_get_ssl_certfp(rb_fde_t
*const F
, uint8_t certfp
[const RB_SSL_CERTFP_LEN
], const int method
)
523 X509
*const peer_cert
= SSL_get_peer_certificate(SSL_P(F
));
524 if(peer_cert
== NULL
)
529 switch(SSL_get_verify_result(SSL_P(F
)))
532 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
:
533 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
:
534 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
:
535 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
:
536 case X509_V_ERR_CERT_UNTRUSTED
:
537 len
= make_certfp(peer_cert
, certfp
, method
);
539 X509_free(peer_cert
);
545 rb_get_ssl_certfp_file(const char *const filename
, uint8_t certfp
[const RB_SSL_CERTFP_LEN
], const int method
)
547 FILE *const fp
= fopen(filename
, "r");
551 X509
*const cert
= PEM_read_X509(fp
, NULL
, NULL
, NULL
);
558 int len
= make_certfp(cert
, certfp
, method
);
567 rb_get_ssl_info(char *const buf
, const size_t len
)
569 #ifdef LRB_SSL_FULL_VERSION_INFO
570 if(LRB_SSL_VNUM_RUNTIME
== LRB_SSL_VNUM_COMPILETIME
)
571 (void) snprintf(buf
, len
, "OpenSSL: compiled 0x%lx, library %s",
572 LRB_SSL_VNUM_COMPILETIME
, LRB_SSL_VTEXT_COMPILETIME
);
574 (void) snprintf(buf
, len
, "OpenSSL: compiled (0x%lx, %s), library (0x%lx, %s)",
575 LRB_SSL_VNUM_COMPILETIME
, LRB_SSL_VTEXT_COMPILETIME
,
576 LRB_SSL_VNUM_RUNTIME
, LRB_SSL_VTEXT_RUNTIME
);
578 (void) snprintf(buf
, len
, "OpenSSL: compiled 0x%lx, library %s",
579 LRB_SSL_VNUM_COMPILETIME
, LRB_SSL_VTEXT_RUNTIME
);
584 rb_ssl_get_cipher(rb_fde_t
*const F
)
586 if(F
== NULL
|| F
->ssl
== NULL
)
589 static char buf
[512];
591 const char *const version
= SSL_get_version(SSL_P(F
));
592 const char *const cipher
= SSL_get_cipher_name(SSL_P(F
));
594 (void) snprintf(buf
, sizeof buf
, "%s, %s", version
, cipher
);
600 rb_ssl_read(rb_fde_t
*const F
, void *const buf
, const size_t count
)
602 return rb_ssl_read_or_write(0, F
, buf
, NULL
, count
);
606 rb_ssl_write(rb_fde_t
*const F
, const void *const buf
, const size_t count
)
608 return rb_ssl_read_or_write(1, F
, NULL
, buf
, count
);
614 * Internal library-agnostic code
618 rb_ssl_connect_realcb(rb_fde_t
*const F
, const int status
, struct ssl_connect
*const sconn
)
620 lrb_assert(F
->connect
!= NULL
);
622 F
->connect
->callback
= sconn
->callback
;
623 F
->connect
->data
= sconn
->data
;
625 rb_connect_callback(F
, status
);
630 rb_ssl_timeout_cb(rb_fde_t
*const F
, void *const data
)
632 lrb_assert(F
->accept
!= NULL
);
633 lrb_assert(F
->accept
->callback
!= NULL
);
635 F
->accept
->callback(F
, RB_ERR_TIMEOUT
, NULL
, 0, F
->accept
->data
);
639 rb_ssl_tryconn_timeout_cb(rb_fde_t
*const F
, void *const data
)
641 rb_ssl_connect_realcb(F
, RB_ERR_TIMEOUT
, data
);
645 rb_ssl_tryconn(rb_fde_t
*const F
, const int status
, void *const data
)
647 lrb_assert(F
!= NULL
);
649 struct ssl_connect
*const sconn
= data
;
653 rb_ssl_connect_realcb(F
, status
, sconn
);
657 F
->type
|= RB_FD_SSL
;
659 rb_settimeout(F
, sconn
->timeout
, rb_ssl_tryconn_timeout_cb
, sconn
);
660 rb_ssl_init_fd(F
, RB_FD_TLS_DIRECTION_OUT
);
661 rb_ssl_connect_common(F
, sconn
);
667 * External library-agnostic code
671 rb_supports_ssl(void)
677 rb_ssl_handshake_count(rb_fde_t
*const F
)
679 return F
->handshake_count
;
683 rb_ssl_clear_handshake_count(rb_fde_t
*const F
)
685 F
->handshake_count
= 0;
689 rb_ssl_start_accepted(rb_fde_t
*const F
, ACCB
*const cb
, void *const data
, const int timeout
)
691 F
->type
|= RB_FD_SSL
;
693 F
->accept
= rb_malloc(sizeof(struct acceptdata
));
694 F
->accept
->callback
= cb
;
695 F
->accept
->data
= data
;
696 F
->accept
->addrlen
= 0;
697 (void) memset(&F
->accept
->S
, 0x00, sizeof F
->accept
->S
);
699 rb_settimeout(F
, timeout
, rb_ssl_timeout_cb
, NULL
);
700 rb_ssl_init_fd(F
, RB_FD_TLS_DIRECTION_IN
);
701 rb_ssl_accept_common(F
, NULL
);
705 rb_ssl_accept_setup(rb_fde_t
*const srv_F
, rb_fde_t
*const cli_F
, struct sockaddr
*const st
, const int addrlen
)
707 cli_F
->type
|= RB_FD_SSL
;
709 cli_F
->accept
= rb_malloc(sizeof(struct acceptdata
));
710 cli_F
->accept
->callback
= srv_F
->accept
->callback
;
711 cli_F
->accept
->data
= srv_F
->accept
->data
;
712 cli_F
->accept
->addrlen
= (rb_socklen_t
) addrlen
;
713 (void) memset(&cli_F
->accept
->S
, 0x00, sizeof cli_F
->accept
->S
);
714 (void) memcpy(&cli_F
->accept
->S
, st
, (size_t) addrlen
);
716 rb_settimeout(cli_F
, 10, rb_ssl_timeout_cb
, NULL
);
717 rb_ssl_init_fd(cli_F
, RB_FD_TLS_DIRECTION_IN
);
718 rb_ssl_accept_common(cli_F
, NULL
);
722 rb_ssl_listen(rb_fde_t
*const F
, const int backlog
, const int defer_accept
)
724 int result
= rb_listen(F
, backlog
, defer_accept
);
726 F
->type
= RB_FD_SOCKET
| RB_FD_LISTEN
| RB_FD_SSL
;
732 rb_connect_tcp_ssl(rb_fde_t
*const F
, struct sockaddr
*const dest
, struct sockaddr
*const clocal
,
733 CNCB
*const callback
, void *const data
, const int timeout
)
738 struct ssl_connect
*const sconn
= rb_malloc(sizeof *sconn
);
740 sconn
->callback
= callback
;
741 sconn
->timeout
= timeout
;
743 rb_connect_tcp(F
, dest
, clocal
, rb_ssl_tryconn
, sconn
, timeout
);
747 rb_ssl_start_connected(rb_fde_t
*const F
, CNCB
*const callback
, void *const data
, const int timeout
)
752 struct ssl_connect
*const sconn
= rb_malloc(sizeof *sconn
);
754 sconn
->callback
= callback
;
755 sconn
->timeout
= timeout
;
757 F
->connect
= rb_malloc(sizeof(struct conndata
));
758 F
->connect
->callback
= callback
;
759 F
->connect
->data
= data
;
760 F
->type
|= RB_FD_SSL
;
762 rb_settimeout(F
, sconn
->timeout
, rb_ssl_tryconn_timeout_cb
, sconn
);
763 rb_ssl_init_fd(F
, RB_FD_TLS_DIRECTION_OUT
);
764 rb_ssl_connect_common(F
, sconn
);
767 #endif /* HAVE_OPENSSL */