2 * librb: a library used by ircd-ratbox and other things
3 * mbedtls.c: ARM MbedTLS backend
5 * Copyright (C) 2007-2008 ircd-ratbox development team
6 * Copyright (C) 2007-2008 Aaron Sethman <androsyn@ratbox.org>
7 * Copyright (C) 2015 William Pitcock <nenolod@dereferenced.org>
8 * Copyright (C) 2016 Aaron Jones <aaronmdjones@gmail.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
27 #include <librb_config.h>
32 #include <commio-int.h>
33 #include <commio-ssl.h>
36 #include "mbedtls_ratbox.h"
40 RB_FD_TLS_DIRECTION_IN
= 0,
41 RB_FD_TLS_DIRECTION_OUT
= 1
42 } rb_fd_tls_direction
;
44 #define RB_MAX_CIPHERSUITES 512
49 mbedtls_pk_context key
;
50 mbedtls_dhm_context dhp
;
51 mbedtls_ssl_config server_cfg
;
52 mbedtls_ssl_config client_cfg
;
54 int suites
[RB_MAX_CIPHERSUITES
+ 1];
55 } rb_mbedtls_cfg_context
;
59 rb_mbedtls_cfg_context
*cfg
;
60 mbedtls_ssl_context ssl
;
61 } rb_mbedtls_ssl_context
;
63 #define SSL_C(x) ((rb_mbedtls_ssl_context *) (x)->ssl)->cfg
64 #define SSL_P(x) &((rb_mbedtls_ssl_context *) (x)->ssl)->ssl
66 static mbedtls_ctr_drbg_context ctr_drbg_ctx
;
67 static mbedtls_entropy_context entropy_ctx
;
69 static mbedtls_x509_crt dummy_ca_ctx
;
70 static rb_mbedtls_cfg_context
*rb_mbedtls_cfg
= NULL
;
81 static const char *rb_ssl_strerror(int);
82 static void rb_ssl_connect_realcb(rb_fde_t
*, int, struct ssl_connect
*);
87 * Internal MbedTLS-specific code
91 rb_mbedtls_cfg_incref(rb_mbedtls_cfg_context
*const cfg
)
93 lrb_assert(cfg
->refcount
> 0);
99 rb_mbedtls_cfg_decref(rb_mbedtls_cfg_context
*const cfg
)
104 lrb_assert(cfg
->refcount
> 0);
106 if((--cfg
->refcount
) > 0)
109 mbedtls_ssl_config_free(&cfg
->client_cfg
);
110 mbedtls_ssl_config_free(&cfg
->server_cfg
);
111 mbedtls_dhm_free(&cfg
->dhp
);
112 mbedtls_pk_free(&cfg
->key
);
113 mbedtls_x509_crt_free(&cfg
->crt
);
119 rb_sock_net_recv(void *const context_ptr
, unsigned char *const buf
, const size_t count
)
121 const int fd
= rb_get_fd((rb_fde_t
*)context_ptr
);
123 const int ret
= (int) read(fd
, buf
, count
);
125 if(ret
< 0 && rb_ignore_errno(errno
))
126 return MBEDTLS_ERR_SSL_WANT_READ
;
132 rb_sock_net_xmit(void *const context_ptr
, const unsigned char *const buf
, const size_t count
)
134 const int fd
= rb_get_fd((rb_fde_t
*)context_ptr
);
136 const int ret
= (int) write(fd
, buf
, count
);
138 if(ret
< 0 && rb_ignore_errno(errno
))
139 return MBEDTLS_ERR_SSL_WANT_WRITE
;
145 rb_ssl_init_fd(rb_fde_t
*const F
, const rb_fd_tls_direction dir
)
147 rb_mbedtls_ssl_context
*const mbed_ssl_ctx
= rb_malloc(sizeof *mbed_ssl_ctx
);
149 if(mbed_ssl_ctx
== NULL
)
151 rb_lib_log("%s: rb_malloc: allocation failure", __func__
);
156 mbedtls_ssl_config
*mbed_config
= NULL
;
160 case RB_FD_TLS_DIRECTION_IN
:
161 mbed_config
= &rb_mbedtls_cfg
->server_cfg
;
163 case RB_FD_TLS_DIRECTION_OUT
:
164 mbed_config
= &rb_mbedtls_cfg
->client_cfg
;
168 mbedtls_ssl_init(&mbed_ssl_ctx
->ssl
);
172 if((ret
= mbedtls_ssl_setup(&mbed_ssl_ctx
->ssl
, mbed_config
)) != 0)
174 rb_lib_log("%s: ssl_setup: %s", __func__
, rb_ssl_strerror(ret
));
175 mbedtls_ssl_free(&mbed_ssl_ctx
->ssl
);
176 rb_free(mbed_ssl_ctx
);
181 mbedtls_ssl_set_bio(&mbed_ssl_ctx
->ssl
, F
, rb_sock_net_xmit
, rb_sock_net_recv
, NULL
);
183 rb_mbedtls_cfg_incref(rb_mbedtls_cfg
);
184 mbed_ssl_ctx
->cfg
= rb_mbedtls_cfg
;
186 F
->ssl
= mbed_ssl_ctx
;
189 static rb_mbedtls_cfg_context
*
190 rb_mbedtls_cfg_new(void)
192 rb_mbedtls_cfg_context
*const cfg
= rb_malloc(sizeof *cfg
);
197 mbedtls_x509_crt_init(&cfg
->crt
);
198 mbedtls_pk_init(&cfg
->key
);
199 mbedtls_dhm_init(&cfg
->dhp
);
200 mbedtls_ssl_config_init(&cfg
->server_cfg
);
201 mbedtls_ssl_config_init(&cfg
->client_cfg
);
203 (void) memset(cfg
->suites
, 0x00, sizeof cfg
->suites
);
209 if((ret
= mbedtls_ssl_config_defaults(&cfg
->server_cfg
,
210 MBEDTLS_SSL_IS_SERVER
, MBEDTLS_SSL_TRANSPORT_STREAM
,
211 MBEDTLS_SSL_PRESET_DEFAULT
)) != 0)
213 rb_lib_log("%s: ssl_config_defaults (server): %s", __func__
, rb_ssl_strerror(ret
));
214 rb_mbedtls_cfg_decref(cfg
);
218 if((ret
= mbedtls_ssl_config_defaults(&cfg
->client_cfg
,
219 MBEDTLS_SSL_IS_CLIENT
, MBEDTLS_SSL_TRANSPORT_STREAM
,
220 MBEDTLS_SSL_PRESET_DEFAULT
)) != 0)
222 rb_lib_log("%s: ssl_config_defaults (client): %s", __func__
, rb_ssl_strerror(ret
));
223 rb_mbedtls_cfg_decref(cfg
);
227 mbedtls_ssl_conf_rng(&cfg
->server_cfg
, mbedtls_ctr_drbg_random
, &ctr_drbg_ctx
);
228 mbedtls_ssl_conf_rng(&cfg
->client_cfg
, mbedtls_ctr_drbg_random
, &ctr_drbg_ctx
);
230 mbedtls_ssl_conf_ca_chain(&cfg
->server_cfg
, &dummy_ca_ctx
, NULL
);
231 mbedtls_ssl_conf_ca_chain(&cfg
->client_cfg
, &dummy_ca_ctx
, NULL
);
233 mbedtls_ssl_conf_authmode(&cfg
->server_cfg
, MBEDTLS_SSL_VERIFY_OPTIONAL
);
234 mbedtls_ssl_conf_authmode(&cfg
->client_cfg
, MBEDTLS_SSL_VERIFY_NONE
);
236 mbedtls_ssl_conf_min_version(&cfg
->server_cfg
, MBEDTLS_SSL_MAJOR_VERSION_3
, MBEDTLS_SSL_MINOR_VERSION_1
);
237 mbedtls_ssl_conf_min_version(&cfg
->client_cfg
, MBEDTLS_SSL_MAJOR_VERSION_3
, MBEDTLS_SSL_MINOR_VERSION_1
);
239 #ifdef MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE
240 mbedtls_ssl_conf_legacy_renegotiation(&cfg
->client_cfg
, MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE
);
243 #ifdef MBEDTLS_SSL_SESSION_TICKETS_DISABLED
244 mbedtls_ssl_conf_session_tickets(&cfg
->client_cfg
, MBEDTLS_SSL_SESSION_TICKETS_DISABLED
);
251 rb_ssl_accept_common(rb_fde_t
*const F
, void *const data
)
253 lrb_assert(F
!= NULL
);
254 lrb_assert(F
->accept
!= NULL
);
255 lrb_assert(F
->accept
->callback
!= NULL
);
256 lrb_assert(F
->ssl
!= NULL
);
260 const int ret
= mbedtls_ssl_handshake(SSL_P(F
));
265 F
->handshake_count
++;
267 case MBEDTLS_ERR_SSL_WANT_READ
:
268 rb_setselect(F
, RB_SELECT_READ
, rb_ssl_accept_common
, NULL
);
270 case MBEDTLS_ERR_SSL_WANT_WRITE
:
271 rb_setselect(F
, RB_SELECT_WRITE
, rb_ssl_accept_common
, NULL
);
275 F
->ssl_errno
= (unsigned long) -ret
;
276 F
->accept
->callback(F
, RB_ERROR_SSL
, NULL
, 0, F
->accept
->data
);
280 rb_settimeout(F
, 0, NULL
, NULL
);
281 rb_setselect(F
, RB_SELECT_READ
| RB_SELECT_WRITE
, NULL
, NULL
);
283 struct acceptdata
*const ad
= F
->accept
;
285 ad
->callback(F
, RB_OK
, (struct sockaddr
*)&ad
->S
, ad
->addrlen
, ad
->data
);
290 rb_ssl_connect_common(rb_fde_t
*const F
, void *const data
)
292 lrb_assert(F
!= NULL
);
293 lrb_assert(F
->ssl
!= NULL
);
295 const int ret
= mbedtls_ssl_handshake(SSL_P(F
));
300 F
->handshake_count
++;
302 case MBEDTLS_ERR_SSL_WANT_READ
:
303 rb_setselect(F
, RB_SELECT_READ
, rb_ssl_connect_common
, data
);
305 case MBEDTLS_ERR_SSL_WANT_WRITE
:
306 rb_setselect(F
, RB_SELECT_WRITE
, rb_ssl_connect_common
, data
);
310 F
->ssl_errno
= (unsigned long) -ret
;
311 rb_ssl_connect_realcb(F
, RB_ERROR_SSL
, data
);
315 rb_ssl_connect_realcb(F
, RB_OK
, data
);
319 rb_ssl_strerror(int err
)
321 static char errbuf
[512];
326 #ifdef MBEDTLS_ERROR_C
327 char mbed_errbuf
[512];
328 mbedtls_strerror(err
, mbed_errbuf
, sizeof mbed_errbuf
);
329 (void) snprintf(errbuf
, sizeof errbuf
, "-0x%X: %s", (unsigned int) err
, mbed_errbuf
);
331 (void) snprintf(errbuf
, sizeof errbuf
, "-0x%X", (unsigned int) err
);
338 rb_make_certfp(const mbedtls_x509_crt
*const peer_cert
, uint8_t certfp
[const RB_SSL_CERTFP_LEN
], const int method
)
341 mbedtls_md_type_t md_type
;
346 case RB_SSL_CERTFP_METH_CERT_SHA1
:
347 md_type
= MBEDTLS_MD_SHA1
;
348 hashlen
= RB_SSL_CERTFP_LEN_SHA1
;
350 case RB_SSL_CERTFP_METH_SPKI_SHA256
:
352 case RB_SSL_CERTFP_METH_CERT_SHA256
:
353 md_type
= MBEDTLS_MD_SHA256
;
354 hashlen
= RB_SSL_CERTFP_LEN_SHA256
;
356 case RB_SSL_CERTFP_METH_SPKI_SHA512
:
358 case RB_SSL_CERTFP_METH_CERT_SHA512
:
359 md_type
= MBEDTLS_MD_SHA512
;
360 hashlen
= RB_SSL_CERTFP_LEN_SHA512
;
366 const mbedtls_md_info_t
*const md_info
= mbedtls_md_info_from_type(md_type
);
371 void* data
= peer_cert
->raw
.p
;
372 size_t datalen
= peer_cert
->raw
.len
;
376 // Compiler may complain about dropping const qualifier on the cast below
377 // See <https://github.com/ARMmbed/mbedtls/issues/396> -- this is okay
379 unsigned char der_pubkey
[8192];
380 if((ret
= mbedtls_pk_write_pubkey_der((mbedtls_pk_context
*)&peer_cert
->pk
,
381 der_pubkey
, sizeof der_pubkey
)) < 0)
383 rb_lib_log("rb_get_ssl_certfp: pk_write_pubkey_der: %s", rb_ssl_strerror(ret
));
386 data
= der_pubkey
+ (sizeof(der_pubkey
) - (size_t)ret
);
387 datalen
= (size_t)ret
;
390 if((ret
= mbedtls_md(md_info
, data
, datalen
, certfp
)) != 0)
392 rb_lib_log("rb_get_ssl_certfp: mbedtls_md: %s", rb_ssl_strerror(ret
));
396 return (int) hashlen
;
402 * External MbedTLS-specific code
406 rb_ssl_shutdown(rb_fde_t
*const F
)
408 if(F
== NULL
|| F
->ssl
== NULL
)
411 for(int i
= 0; i
< 4; i
++)
413 int ret
= mbedtls_ssl_close_notify(SSL_P(F
));
415 if(ret
!= MBEDTLS_ERR_SSL_WANT_READ
&& ret
!= MBEDTLS_ERR_SSL_WANT_WRITE
)
419 mbedtls_ssl_free(SSL_P(F
));
420 rb_mbedtls_cfg_decref(SSL_C(F
));
429 mbedtls_ctr_drbg_init(&ctr_drbg_ctx
);
430 mbedtls_entropy_init(&entropy_ctx
);
434 if((ret
= mbedtls_ctr_drbg_seed(&ctr_drbg_ctx
, mbedtls_entropy_func
, &entropy_ctx
,
435 (const unsigned char *)rb_mbedtls_personal_str
, sizeof(rb_mbedtls_personal_str
))) != 0)
437 rb_lib_log("%s: ctr_drbg_seed: %s", __func__
, rb_ssl_strerror(ret
));
441 if((ret
= mbedtls_x509_crt_parse_der(&dummy_ca_ctx
, rb_mbedtls_dummy_ca_certificate
,
442 sizeof(rb_mbedtls_dummy_ca_certificate
))) != 0)
444 rb_lib_log("%s: x509_crt_parse_der (Dummy CA): %s", __func__
, rb_ssl_strerror(ret
));
448 rb_lib_log("%s: MbedTLS backend initialised", __func__
);
453 rb_setup_ssl_server(const char *const certfile
, const char *keyfile
,
454 const char *const dhfile
, const char *const cipherlist
)
458 rb_lib_log("%s: no certificate file specified", __func__
);
465 rb_mbedtls_cfg_context
*const newcfg
= rb_mbedtls_cfg_new();
469 rb_lib_log("%s: rb_mbedtls_cfg_new: allocation failed", __func__
);
475 if((ret
= mbedtls_x509_crt_parse_file(&newcfg
->crt
, certfile
)) != 0)
477 rb_lib_log("%s: x509_crt_parse_file ('%s'): %s", __func__
, certfile
, rb_ssl_strerror(ret
));
478 rb_mbedtls_cfg_decref(newcfg
);
481 if((ret
= mbedtls_pk_parse_keyfile(&newcfg
->key
, keyfile
, NULL
)) != 0)
483 rb_lib_log("%s: pk_parse_keyfile ('%s'): %s", __func__
, keyfile
, rb_ssl_strerror(ret
));
484 rb_mbedtls_cfg_decref(newcfg
);
487 if((ret
= mbedtls_pk_check_pair(&newcfg
->crt
.pk
, &newcfg
->key
)) != 0)
489 rb_lib_log("%s: pk_check_pair: public/private key mismatch", __func__
);
490 rb_mbedtls_cfg_decref(newcfg
);
493 if((ret
= mbedtls_ssl_conf_own_cert(&newcfg
->server_cfg
, &newcfg
->crt
, &newcfg
->key
)) != 0)
495 rb_lib_log("%s: ssl_conf_own_cert (server): %s", __func__
, rb_ssl_strerror(ret
));
496 rb_mbedtls_cfg_decref(newcfg
);
499 if((ret
= mbedtls_ssl_conf_own_cert(&newcfg
->client_cfg
, &newcfg
->crt
, &newcfg
->key
)) != 0)
501 rb_lib_log("%s: ssl_conf_own_cert (client): %s", __func__
, rb_ssl_strerror(ret
));
502 rb_mbedtls_cfg_decref(newcfg
);
507 /* Absense of DH parameters does not matter with mbedTLS, as it comes with its own defaults
508 Thus, clients can still use DHE- ciphersuites, just over a weaker, common DH group
509 So, we do not consider failure to parse DH parameters as fatal */
512 rb_lib_log("%s: no DH parameters file specified", __func__
);
516 if((ret
= mbedtls_dhm_parse_dhmfile(&newcfg
->dhp
, dhfile
)) != 0)
518 rb_lib_log("%s: dhm_parse_dhmfile ('%s'): %s", __func__
, dhfile
, rb_ssl_strerror(ret
));
520 else if((ret
= mbedtls_ssl_conf_dh_param_ctx(&newcfg
->server_cfg
, &newcfg
->dhp
)) != 0)
522 rb_lib_log("%s: ssl_conf_dh_param_ctx: %s", __func__
, rb_ssl_strerror(ret
));
527 const int *rb_ciphersuites
= newcfg
->suites
;
528 size_t suites_count
= 0;
530 if(cipherlist
!= NULL
)
532 // The cipherlist is (const char *) -- we should not modify it
533 char *const cipherlist_dup
= strdup(cipherlist
);
535 if(cipherlist_dup
!= NULL
)
537 char *cipher_str
= cipherlist_dup
;
542 // Arbitrary, but the same separator as OpenSSL uses
543 cipher_idx
= strchr(cipher_str
, ':');
545 // This could legitimately be NULL (last ciphersuite in the list)
546 if(cipher_idx
!= NULL
)
549 size_t cipher_len
= strlen(cipher_str
);
552 // All MbedTLS ciphersuite names begin with these 4 characters
553 if(cipher_len
> 4 && strncmp(cipher_str
, "TLS-", 4) == 0)
554 cipher_idn
= mbedtls_ssl_get_ciphersuite_id(cipher_str
);
556 // Prevent the same ciphersuite being added multiple times
557 for(size_t x
= 0; cipher_idn
!= 0 && newcfg
->suites
[x
] != 0; x
++)
558 if(newcfg
->suites
[x
] == cipher_idn
)
561 // Add the suite to the list
563 newcfg
->suites
[suites_count
++] = cipher_idn
;
565 // Advance the string to the next entry
567 cipher_str
= cipher_idx
+ 1;
569 } while(cipher_idx
&& suites_count
< RB_MAX_CIPHERSUITES
);
571 if(suites_count
== 0)
572 rb_lib_log("%s: Ciphersuites provided, but could not parse any", __func__
);
574 free(cipherlist_dup
);
578 rb_lib_log("%s: strdup: %s", __func__
, strerror(errno
));
583 rb_lib_log("%s: No ciphersuite list provided", __func__
);
586 if(suites_count
== 0)
588 rb_lib_log("%s: Using default ciphersuites", __func__
);
590 rb_ciphersuites
= rb_mbedtls_ciphersuites
;
591 suites_count
= (sizeof(rb_mbedtls_ciphersuites
) / sizeof(rb_mbedtls_ciphersuites
[0])) - 1;
594 mbedtls_ssl_conf_ciphersuites(&newcfg
->server_cfg
, rb_ciphersuites
);
595 mbedtls_ssl_conf_ciphersuites(&newcfg
->client_cfg
, rb_ciphersuites
);
596 rb_lib_log("%s: Configured %zu ciphersuites", __func__
, suites_count
);
599 rb_mbedtls_cfg_decref(rb_mbedtls_cfg
);
600 rb_mbedtls_cfg
= newcfg
;
602 rb_lib_log("%s: TLS configuration successful", __func__
);
607 rb_init_prng(const char *const path
, prng_seed_t seed_type
)
612 rb_lib_log("%s: Skipping PRNG initialisation; not required by MbedTLS backend", __func__
);
617 rb_get_random(void *const buf
, const size_t length
)
621 if((ret
= mbedtls_ctr_drbg_random(&ctr_drbg_ctx
, buf
, length
)) != 0)
623 rb_lib_log("%s: ctr_drbg_random: %s", __func__
, rb_ssl_strerror(ret
));
631 rb_get_ssl_strerror(rb_fde_t
*const F
)
633 const int err
= (int) F
->ssl_errno
;
634 return rb_ssl_strerror(err
);
638 rb_get_ssl_certfp(rb_fde_t
*const F
, uint8_t certfp
[const RB_SSL_CERTFP_LEN
], const int method
)
640 const mbedtls_x509_crt
*const peer_cert
= mbedtls_ssl_get_peer_cert(SSL_P(F
));
642 if(peer_cert
== NULL
)
645 return rb_make_certfp(peer_cert
, certfp
, method
);
649 rb_get_ssl_certfp_file(const char *const filename
, uint8_t certfp
[const RB_SSL_CERTFP_LEN
], const int method
)
651 mbedtls_x509_crt cert
;
653 mbedtls_x509_crt_init(&cert
);
655 const int ret
= mbedtls_x509_crt_parse_file(&cert
, filename
);
660 const int len
= rb_make_certfp(&cert
, certfp
, method
);
662 mbedtls_x509_crt_free(&cert
);
667 rb_get_ssl_info(char *const buf
, const size_t len
)
669 char version_str
[512];
671 mbedtls_version_get_string(version_str
);
673 (void) snprintf(buf
, len
, "ARM mbedTLS: compiled (v%s), library (v%s)",
674 MBEDTLS_VERSION_STRING
, version_str
);
678 rb_ssl_get_cipher(rb_fde_t
*const F
)
680 if(F
== NULL
|| F
->ssl
== NULL
)
683 static char buf
[512];
685 const char *const version
= mbedtls_ssl_get_version(SSL_P(F
));
686 const char *const cipher
= mbedtls_ssl_get_ciphersuite(SSL_P(F
));
688 (void) snprintf(buf
, sizeof buf
, "%s, %s", version
, cipher
);
694 rb_ssl_read(rb_fde_t
*const F
, void *const buf
, const size_t count
)
696 lrb_assert(F
!= NULL
);
697 lrb_assert(F
->ssl
!= NULL
);
699 const int ret
= mbedtls_ssl_read(SSL_P(F
), buf
, count
);
702 return (ssize_t
) ret
;
706 case MBEDTLS_ERR_SSL_WANT_READ
:
708 return RB_RW_SSL_NEED_READ
;
709 case MBEDTLS_ERR_SSL_WANT_WRITE
:
711 return RB_RW_SSL_NEED_WRITE
;
714 F
->ssl_errno
= (unsigned long) -ret
;
715 return RB_RW_SSL_ERROR
;
720 rb_ssl_write(rb_fde_t
*const F
, const void *const buf
, const size_t count
)
722 lrb_assert(F
!= NULL
);
723 lrb_assert(F
->ssl
!= NULL
);
725 const int ret
= mbedtls_ssl_write(SSL_P(F
), buf
, count
);
728 return (ssize_t
) ret
;
732 case MBEDTLS_ERR_SSL_WANT_READ
:
734 return RB_RW_SSL_NEED_READ
;
735 case MBEDTLS_ERR_SSL_WANT_WRITE
:
737 return RB_RW_SSL_NEED_WRITE
;
740 F
->ssl_errno
= (unsigned long) -ret
;
741 return RB_RW_SSL_ERROR
;
748 * Internal library-agnostic code
752 rb_ssl_connect_realcb(rb_fde_t
*const F
, const int status
, struct ssl_connect
*const sconn
)
754 lrb_assert(F
!= NULL
);
755 lrb_assert(F
->connect
!= NULL
);
757 F
->connect
->callback
= sconn
->callback
;
758 F
->connect
->data
= sconn
->data
;
760 rb_connect_callback(F
, status
);
765 rb_ssl_timeout_cb(rb_fde_t
*const F
, void *const data
)
769 lrb_assert(F
->accept
!= NULL
);
770 lrb_assert(F
->accept
->callback
!= NULL
);
772 F
->accept
->callback(F
, RB_ERR_TIMEOUT
, NULL
, 0, F
->accept
->data
);
776 rb_ssl_tryconn_timeout_cb(rb_fde_t
*const F
, void *const data
)
778 rb_ssl_connect_realcb(F
, RB_ERR_TIMEOUT
, data
);
782 rb_ssl_tryconn(rb_fde_t
*const F
, const int status
, void *const data
)
784 lrb_assert(F
!= NULL
);
786 struct ssl_connect
*const sconn
= data
;
790 rb_ssl_connect_realcb(F
, status
, sconn
);
794 F
->type
|= RB_FD_SSL
;
796 rb_settimeout(F
, sconn
->timeout
, rb_ssl_tryconn_timeout_cb
, sconn
);
797 rb_ssl_init_fd(F
, RB_FD_TLS_DIRECTION_OUT
);
798 rb_ssl_connect_common(F
, sconn
);
804 * External library-agnostic code
808 rb_supports_ssl(void)
814 rb_ssl_handshake_count(rb_fde_t
*const F
)
816 return F
->handshake_count
;
820 rb_ssl_clear_handshake_count(rb_fde_t
*const F
)
822 F
->handshake_count
= 0;
826 rb_ssl_start_accepted(rb_fde_t
*const F
, ACCB
*const cb
, void *const data
, const int timeout
)
828 F
->type
|= RB_FD_SSL
;
830 F
->accept
= rb_malloc(sizeof(struct acceptdata
));
831 F
->accept
->callback
= cb
;
832 F
->accept
->data
= data
;
833 F
->accept
->addrlen
= 0;
834 (void) memset(&F
->accept
->S
, 0x00, sizeof F
->accept
->S
);
836 rb_settimeout(F
, timeout
, rb_ssl_timeout_cb
, NULL
);
837 rb_ssl_init_fd(F
, RB_FD_TLS_DIRECTION_IN
);
838 rb_ssl_accept_common(F
, NULL
);
842 rb_ssl_accept_setup(rb_fde_t
*const srv_F
, rb_fde_t
*const cli_F
, struct sockaddr
*const st
, const int addrlen
)
844 cli_F
->type
|= RB_FD_SSL
;
846 cli_F
->accept
= rb_malloc(sizeof(struct acceptdata
));
847 cli_F
->accept
->callback
= srv_F
->accept
->callback
;
848 cli_F
->accept
->data
= srv_F
->accept
->data
;
849 cli_F
->accept
->addrlen
= (rb_socklen_t
) addrlen
;
850 (void) memset(&cli_F
->accept
->S
, 0x00, sizeof cli_F
->accept
->S
);
851 (void) memcpy(&cli_F
->accept
->S
, st
, (size_t) addrlen
);
853 rb_settimeout(cli_F
, 10, rb_ssl_timeout_cb
, NULL
);
854 rb_ssl_init_fd(cli_F
, RB_FD_TLS_DIRECTION_IN
);
855 rb_ssl_accept_common(cli_F
, NULL
);
859 rb_ssl_listen(rb_fde_t
*const F
, const int backlog
, const int defer_accept
)
861 int result
= rb_listen(F
, backlog
, defer_accept
);
863 F
->type
= RB_FD_SOCKET
| RB_FD_LISTEN
| RB_FD_SSL
;
869 rb_connect_tcp_ssl(rb_fde_t
*const F
, struct sockaddr
*const dest
, struct sockaddr
*const clocal
,
870 CNCB
*const callback
, void *const data
, const int timeout
)
875 struct ssl_connect
*const sconn
= rb_malloc(sizeof *sconn
);
877 sconn
->callback
= callback
;
878 sconn
->timeout
= timeout
;
880 rb_connect_tcp(F
, dest
, clocal
, rb_ssl_tryconn
, sconn
, timeout
);
884 rb_ssl_start_connected(rb_fde_t
*const F
, CNCB
*const callback
, void *const data
, const int timeout
)
889 struct ssl_connect
*const sconn
= rb_malloc(sizeof *sconn
);
891 sconn
->callback
= callback
;
892 sconn
->timeout
= timeout
;
894 F
->connect
= rb_malloc(sizeof(struct conndata
));
895 F
->connect
->callback
= callback
;
896 F
->connect
->data
= data
;
898 F
->type
|= RB_FD_SSL
;
900 rb_settimeout(F
, sconn
->timeout
, rb_ssl_tryconn_timeout_cb
, sconn
);
901 rb_ssl_init_fd(F
, RB_FD_TLS_DIRECTION_OUT
);
902 rb_ssl_connect_common(F
, sconn
);
905 #endif /* HAVE_MBEDTLS */