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
;
53 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
*);
84 static int rb_sock_net_recv(void *, unsigned char *, size_t);
85 static int rb_sock_net_xmit(void *, const unsigned char *, size_t);
90 * Internal MbedTLS-specific code
94 rb_mbedtls_cfg_incref(rb_mbedtls_cfg_context
*const cfg
)
96 lrb_assert(cfg
->refcount
> 0);
102 rb_mbedtls_cfg_decref(rb_mbedtls_cfg_context
*const cfg
)
107 lrb_assert(cfg
->refcount
> 0);
109 if((--cfg
->refcount
) > 0)
112 mbedtls_ssl_config_free(&cfg
->client_cfg
);
113 mbedtls_ssl_config_free(&cfg
->server_cfg
);
114 mbedtls_dhm_free(&cfg
->dhp
);
115 mbedtls_pk_free(&cfg
->key
);
116 mbedtls_x509_crt_free(&cfg
->crt
);
122 rb_ssl_init_fd(rb_fde_t
*const F
, const rb_fd_tls_direction dir
)
124 rb_mbedtls_ssl_context
*const mbed_ssl_ctx
= rb_malloc(sizeof *mbed_ssl_ctx
);
126 if(mbed_ssl_ctx
== NULL
)
128 rb_lib_log("%s: rb_malloc: allocation failure", __func__
);
133 mbedtls_ssl_config
*mbed_config
;
137 case RB_FD_TLS_DIRECTION_IN
:
138 mbed_config
= &rb_mbedtls_cfg
->server_cfg
;
140 case RB_FD_TLS_DIRECTION_OUT
:
141 mbed_config
= &rb_mbedtls_cfg
->client_cfg
;
145 mbedtls_ssl_init(&mbed_ssl_ctx
->ssl
);
149 if((ret
= mbedtls_ssl_setup(&mbed_ssl_ctx
->ssl
, mbed_config
)) != 0)
151 rb_lib_log("%s: ssl_setup: %s", __func__
, rb_ssl_strerror(ret
));
152 mbedtls_ssl_free(&mbed_ssl_ctx
->ssl
);
153 rb_free(mbed_ssl_ctx
);
158 mbedtls_ssl_set_bio(&mbed_ssl_ctx
->ssl
, F
, rb_sock_net_xmit
, rb_sock_net_recv
, NULL
);
160 rb_mbedtls_cfg_incref(rb_mbedtls_cfg
);
161 mbed_ssl_ctx
->cfg
= rb_mbedtls_cfg
;
163 F
->ssl
= mbed_ssl_ctx
;
166 static rb_mbedtls_cfg_context
*
167 rb_mbedtls_cfg_new(void)
169 rb_mbedtls_cfg_context
*const cfg
= rb_malloc(sizeof *cfg
);
174 mbedtls_x509_crt_init(&cfg
->crt
);
175 mbedtls_pk_init(&cfg
->key
);
176 mbedtls_dhm_init(&cfg
->dhp
);
177 mbedtls_ssl_config_init(&cfg
->server_cfg
);
178 mbedtls_ssl_config_init(&cfg
->client_cfg
);
180 (void) memset(cfg
->suites
, 0x00, sizeof cfg
->suites
);
186 if((ret
= mbedtls_ssl_config_defaults(&cfg
->server_cfg
,
187 MBEDTLS_SSL_IS_SERVER
, MBEDTLS_SSL_TRANSPORT_STREAM
,
188 MBEDTLS_SSL_PRESET_DEFAULT
)) != 0)
190 rb_lib_log("%s: ssl_config_defaults (server): %s", __func__
, rb_ssl_strerror(ret
));
191 rb_mbedtls_cfg_decref(cfg
);
195 if((ret
= mbedtls_ssl_config_defaults(&cfg
->client_cfg
,
196 MBEDTLS_SSL_IS_CLIENT
, MBEDTLS_SSL_TRANSPORT_STREAM
,
197 MBEDTLS_SSL_PRESET_DEFAULT
)) != 0)
199 rb_lib_log("%s: ssl_config_defaults (client): %s", __func__
, rb_ssl_strerror(ret
));
200 rb_mbedtls_cfg_decref(cfg
);
204 mbedtls_ssl_conf_rng(&cfg
->server_cfg
, mbedtls_ctr_drbg_random
, &ctr_drbg_ctx
);
205 mbedtls_ssl_conf_rng(&cfg
->client_cfg
, mbedtls_ctr_drbg_random
, &ctr_drbg_ctx
);
207 mbedtls_ssl_conf_ca_chain(&cfg
->server_cfg
, &dummy_ca_ctx
, NULL
);
208 mbedtls_ssl_conf_ca_chain(&cfg
->client_cfg
, &dummy_ca_ctx
, NULL
);
210 mbedtls_ssl_conf_authmode(&cfg
->server_cfg
, MBEDTLS_SSL_VERIFY_OPTIONAL
);
211 mbedtls_ssl_conf_authmode(&cfg
->client_cfg
, MBEDTLS_SSL_VERIFY_NONE
);
213 #ifdef MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE
214 mbedtls_ssl_conf_legacy_renegotiation(&cfg
->client_cfg
, MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE
);
217 #ifdef MBEDTLS_SSL_SESSION_TICKETS_DISABLED
218 mbedtls_ssl_conf_session_tickets(&cfg
->client_cfg
, MBEDTLS_SSL_SESSION_TICKETS_DISABLED
);
225 rb_ssl_accept_common(rb_fde_t
*const F
, void *const data
)
227 lrb_assert(F
!= NULL
);
228 lrb_assert(F
->accept
!= NULL
);
229 lrb_assert(F
->accept
->callback
!= NULL
);
230 lrb_assert(F
->ssl
!= NULL
);
232 const int ret
= mbedtls_ssl_handshake(SSL_P(F
));
237 F
->handshake_count
++;
239 case MBEDTLS_ERR_SSL_WANT_READ
:
240 rb_setselect(F
, RB_SELECT_READ
, rb_ssl_accept_common
, NULL
);
242 case MBEDTLS_ERR_SSL_WANT_WRITE
:
243 rb_setselect(F
, RB_SELECT_WRITE
, rb_ssl_accept_common
, NULL
);
247 F
->ssl_errno
= (unsigned long) -ret
;
248 F
->accept
->callback(F
, RB_ERROR_SSL
, NULL
, 0, F
->accept
->data
);
252 rb_settimeout(F
, 0, NULL
, NULL
);
253 rb_setselect(F
, RB_SELECT_READ
| RB_SELECT_WRITE
, NULL
, NULL
);
255 struct acceptdata
*const ad
= F
->accept
;
257 ad
->callback(F
, RB_OK
, (struct sockaddr
*)&ad
->S
, ad
->addrlen
, ad
->data
);
262 rb_ssl_connect_common(rb_fde_t
*const F
, void *const data
)
264 lrb_assert(F
!= NULL
);
265 lrb_assert(F
->ssl
!= NULL
);
267 const int ret
= mbedtls_ssl_handshake(SSL_P(F
));
272 F
->handshake_count
++;
274 case MBEDTLS_ERR_SSL_WANT_READ
:
275 rb_setselect(F
, RB_SELECT_READ
, rb_ssl_connect_common
, data
);
277 case MBEDTLS_ERR_SSL_WANT_WRITE
:
278 rb_setselect(F
, RB_SELECT_WRITE
, rb_ssl_connect_common
, data
);
282 F
->ssl_errno
= (unsigned long) -ret
;
283 rb_ssl_connect_realcb(F
, RB_ERROR_SSL
, data
);
287 rb_ssl_connect_realcb(F
, RB_OK
, data
);
291 rb_ssl_strerror(const int err
)
293 static char errbuf
[512];
295 #ifdef MBEDTLS_ERROR_C
296 char mbed_errbuf
[512];
297 mbedtls_strerror(err
, mbed_errbuf
, sizeof mbed_errbuf
);
298 (void) snprintf(errbuf
, sizeof errbuf
, "-0x%x: %s", -err
, mbed_errbuf
);
300 (void) snprintf(errbuf
, sizeof errbuf
, "-0x%x", -err
);
307 rb_make_certfp(const mbedtls_x509_crt
*const peer_cert
, uint8_t certfp
[const RB_SSL_CERTFP_LEN
], const int method
)
310 mbedtls_md_type_t md_type
;
315 case RB_SSL_CERTFP_METH_CERT_SHA1
:
316 md_type
= MBEDTLS_MD_SHA1
;
317 hashlen
= RB_SSL_CERTFP_LEN_SHA1
;
319 case RB_SSL_CERTFP_METH_SPKI_SHA256
:
321 case RB_SSL_CERTFP_METH_CERT_SHA256
:
322 md_type
= MBEDTLS_MD_SHA256
;
323 hashlen
= RB_SSL_CERTFP_LEN_SHA256
;
325 case RB_SSL_CERTFP_METH_SPKI_SHA512
:
327 case RB_SSL_CERTFP_METH_CERT_SHA512
:
328 md_type
= MBEDTLS_MD_SHA512
;
329 hashlen
= RB_SSL_CERTFP_LEN_SHA512
;
335 const mbedtls_md_info_t
*const md_info
= mbedtls_md_info_from_type(md_type
);
340 void* data
= peer_cert
->raw
.p
;
341 size_t datalen
= peer_cert
->raw
.len
;
345 unsigned char der_pubkey
[8192];
346 if((ret
= mbedtls_pk_write_pubkey_der((mbedtls_pk_context
*)&peer_cert
->pk
,
347 der_pubkey
, sizeof der_pubkey
)) < 0)
349 rb_lib_log("rb_get_ssl_certfp: pk_write_pubkey_der: %s", rb_ssl_strerror(ret
));
352 data
= der_pubkey
+ (sizeof(der_pubkey
) - (size_t)ret
);
353 datalen
= (size_t)ret
;
356 if((ret
= mbedtls_md(md_info
, data
, datalen
, certfp
)) != 0)
358 rb_lib_log("rb_get_ssl_certfp: mbedtls_md: %s", rb_ssl_strerror(ret
));
362 return (int) hashlen
;
368 * External MbedTLS-specific code
372 rb_ssl_shutdown(rb_fde_t
*const F
)
374 if(F
== NULL
|| F
->ssl
== NULL
)
377 for(int i
= 0; i
< 4; i
++)
379 int ret
= mbedtls_ssl_close_notify(SSL_P(F
));
381 if(ret
!= MBEDTLS_ERR_SSL_WANT_READ
&& ret
!= MBEDTLS_ERR_SSL_WANT_WRITE
)
385 mbedtls_ssl_free(SSL_P(F
));
386 rb_mbedtls_cfg_decref(SSL_C(F
));
395 mbedtls_ctr_drbg_init(&ctr_drbg_ctx
);
396 mbedtls_entropy_init(&entropy_ctx
);
400 if((ret
= mbedtls_ctr_drbg_seed(&ctr_drbg_ctx
, mbedtls_entropy_func
, &entropy_ctx
,
401 (const unsigned char *)rb_mbedtls_personal_str
, sizeof(rb_mbedtls_personal_str
))) != 0)
403 rb_lib_log("%s: ctr_drbg_seed: %s", __func__
, rb_ssl_strerror(ret
));
407 if((ret
= mbedtls_x509_crt_parse_der(&dummy_ca_ctx
, rb_mbedtls_dummy_ca_certificate
,
408 sizeof(rb_mbedtls_dummy_ca_certificate
))) != 0)
410 rb_lib_log("%s: x509_crt_parse_der (Dummy CA): %s", __func__
, rb_ssl_strerror(ret
));
414 rb_lib_log("%s: MbedTLS backend initialised", __func__
);
419 rb_setup_ssl_server(const char *const certfile
, const char *keyfile
,
420 const char *const dhfile
, const char *const cipherlist
)
424 rb_lib_log("%s: no certificate file specified", __func__
);
431 rb_mbedtls_cfg_context
*const newcfg
= rb_mbedtls_cfg_new();
435 rb_lib_log("%s: rb_mbedtls_cfg_new: allocation failed", __func__
);
441 if((ret
= mbedtls_x509_crt_parse_file(&newcfg
->crt
, certfile
)) != 0)
443 rb_lib_log("%s: x509_crt_parse_file ('%s'): %s", __func__
, certfile
, rb_ssl_strerror(ret
));
444 rb_mbedtls_cfg_decref(newcfg
);
447 if((ret
= mbedtls_pk_parse_keyfile(&newcfg
->key
, keyfile
, NULL
)) != 0)
449 rb_lib_log("%s: pk_parse_keyfile ('%s'): %s", __func__
, keyfile
, rb_ssl_strerror(ret
));
450 rb_mbedtls_cfg_decref(newcfg
);
453 if((ret
= mbedtls_ssl_conf_own_cert(&newcfg
->server_cfg
, &newcfg
->crt
, &newcfg
->key
)) != 0)
455 rb_lib_log("%s: ssl_conf_own_cert (server): %s", __func__
, rb_ssl_strerror(ret
));
456 rb_mbedtls_cfg_decref(newcfg
);
459 if((ret
= mbedtls_ssl_conf_own_cert(&newcfg
->client_cfg
, &newcfg
->crt
, &newcfg
->key
)) != 0)
461 rb_lib_log("%s: ssl_conf_own_cert (client): %s", __func__
, rb_ssl_strerror(ret
));
462 rb_mbedtls_cfg_decref(newcfg
);
467 /* Absense of DH parameters does not matter with mbedTLS, as it comes with its own defaults
468 Thus, clients can still use DHE- ciphersuites, just over a weaker, common DH group
469 So, we do not consider failure to parse DH parameters as fatal */
472 rb_lib_log("%s: no DH parameters file specified", __func__
);
476 if((ret
= mbedtls_dhm_parse_dhmfile(&newcfg
->dhp
, dhfile
)) != 0)
478 rb_lib_log("%s: dhm_parse_dhmfile ('%s'): %s", __func__
, dhfile
, rb_ssl_strerror(ret
));
480 else if((ret
= mbedtls_ssl_conf_dh_param_ctx(&newcfg
->server_cfg
, &newcfg
->dhp
)) != 0)
482 rb_lib_log("%s: ssl_conf_dh_param_ctx: %s", __func__
, rb_ssl_strerror(ret
));
487 const int *rb_ciphersuites
= newcfg
->suites
;
488 size_t suites_count
= 0;
490 if(cipherlist
!= NULL
)
492 // The cipherlist is (const char *) -- we should not modify it
493 char *const cipherlist_dup
= strdup(cipherlist
);
495 if(cipherlist_dup
!= NULL
)
497 char *cipher_str
= cipherlist_dup
;
502 // Arbitrary, but the same separator as OpenSSL uses
503 cipher_idx
= strchr(cipher_str
, ':');
505 // This could legitimately be NULL (last ciphersuite in the list)
506 if(cipher_idx
!= NULL
)
509 size_t cipher_len
= strlen(cipher_str
);
512 // All MbedTLS ciphersuite names begin with these 4 characters
513 if(cipher_len
> 4 && strncmp(cipher_str
, "TLS-", 4) == 0)
514 cipher_idn
= mbedtls_ssl_get_ciphersuite_id(cipher_str
);
516 // Prevent the same ciphersuite being added multiple times
517 for(size_t x
= 0; cipher_idn
!= 0 && newcfg
->suites
[x
] != 0; x
++)
518 if(newcfg
->suites
[x
] == cipher_idn
)
521 // Add the suite to the list
523 newcfg
->suites
[suites_count
++] = cipher_idn
;
525 // Advance the string to the next entry
527 cipher_str
= cipher_idx
+ 1;
529 } while(cipher_idx
&& suites_count
< RB_MAX_CIPHERSUITES
);
531 if(suites_count
== 0)
532 rb_lib_log("%s: Ciphersuites provided, but could not parse any", __func__
);
534 free(cipherlist_dup
);
538 rb_lib_log("%s: strdup: %s", __func__
, strerror(errno
));
543 rb_lib_log("%s: No ciphersuite list provided", __func__
);
546 if(suites_count
== 0)
548 rb_lib_log("%s: Using default ciphersuites", __func__
);
550 rb_ciphersuites
= rb_mbedtls_ciphersuites
;
551 suites_count
= (sizeof(rb_mbedtls_ciphersuites
) / sizeof(rb_mbedtls_ciphersuites
[0])) - 1;
554 mbedtls_ssl_conf_ciphersuites(&newcfg
->server_cfg
, rb_ciphersuites
);
555 mbedtls_ssl_conf_ciphersuites(&newcfg
->client_cfg
, rb_ciphersuites
);
556 rb_lib_log("%s: Configured %zu ciphersuites", __func__
, suites_count
);
559 rb_mbedtls_cfg_decref(rb_mbedtls_cfg
);
560 rb_mbedtls_cfg
= newcfg
;
562 rb_lib_log("%s: TLS configuration successful", __func__
);
567 rb_init_prng(const char *const path
, prng_seed_t seed_type
)
569 rb_lib_log("%s: Skipping PRNG initialisation; not required by MbedTLS backend", __func__
);
574 rb_get_random(void *const buf
, const size_t length
)
578 if((ret
= mbedtls_ctr_drbg_random(&ctr_drbg_ctx
, buf
, length
)) != 0)
580 rb_lib_log("%s: ctr_drbg_random: %s", __func__
, rb_ssl_strerror(ret
));
588 rb_get_ssl_strerror(rb_fde_t
*const F
)
590 const int err
= (int) F
->ssl_errno
;
591 return rb_ssl_strerror(-err
);
595 rb_get_ssl_certfp(rb_fde_t
*const F
, uint8_t certfp
[const RB_SSL_CERTFP_LEN
], const int method
)
597 const mbedtls_x509_crt
*const peer_cert
= mbedtls_ssl_get_peer_cert(SSL_P(F
));
599 if(peer_cert
== NULL
)
602 return rb_make_certfp(peer_cert
, certfp
, method
);
606 rb_get_ssl_certfp_file(const char *const filename
, uint8_t certfp
[const RB_SSL_CERTFP_LEN
], const int method
)
608 mbedtls_x509_crt cert
;
610 mbedtls_x509_crt_init(&cert
);
612 const int ret
= mbedtls_x509_crt_parse_file(&cert
, filename
);
617 const int len
= rb_make_certfp(&cert
, certfp
, method
);
619 mbedtls_x509_crt_free(&cert
);
624 rb_get_ssl_info(char *const buf
, const size_t len
)
626 char version_str
[512];
628 mbedtls_version_get_string(version_str
);
630 (void) snprintf(buf
, len
, "ARM mbedTLS: compiled (v%s), library (v%s)",
631 MBEDTLS_VERSION_STRING
, version_str
);
635 rb_ssl_get_cipher(rb_fde_t
*const F
)
637 if(F
== NULL
|| F
->ssl
== NULL
)
640 static char buf
[512];
642 const char *const version
= mbedtls_ssl_get_version(SSL_P(F
));
643 const char *const cipher
= mbedtls_ssl_get_ciphersuite(SSL_P(F
));
645 (void) snprintf(buf
, sizeof buf
, "%s, %s", version
, cipher
);
651 rb_ssl_read(rb_fde_t
*const F
, void *const buf
, const size_t count
)
653 lrb_assert(F
!= NULL
);
654 lrb_assert(F
->ssl
!= NULL
);
656 const int ret
= mbedtls_ssl_read(SSL_P(F
), buf
, count
);
659 return (ssize_t
) ret
;
663 case MBEDTLS_ERR_SSL_WANT_READ
:
665 return RB_RW_SSL_NEED_READ
;
666 case MBEDTLS_ERR_SSL_WANT_WRITE
:
668 return RB_RW_SSL_NEED_WRITE
;
671 F
->ssl_errno
= (unsigned long) -ret
;
672 return RB_RW_SSL_ERROR
;
677 rb_ssl_write(rb_fde_t
*const F
, const void *const buf
, const size_t count
)
679 lrb_assert(F
!= NULL
);
680 lrb_assert(F
->ssl
!= NULL
);
682 const int ret
= mbedtls_ssl_write(SSL_P(F
), buf
, count
);
685 return (ssize_t
) ret
;
689 case MBEDTLS_ERR_SSL_WANT_READ
:
691 return RB_RW_SSL_NEED_READ
;
692 case MBEDTLS_ERR_SSL_WANT_WRITE
:
694 return RB_RW_SSL_NEED_WRITE
;
697 F
->ssl_errno
= (unsigned long) -ret
;
698 return RB_RW_SSL_ERROR
;
705 * Internal library-agnostic code
709 rb_ssl_connect_realcb(rb_fde_t
*const F
, const int status
, struct ssl_connect
*const sconn
)
711 lrb_assert(F
!= NULL
);
712 lrb_assert(F
->connect
!= NULL
);
714 F
->connect
->callback
= sconn
->callback
;
715 F
->connect
->data
= sconn
->data
;
717 rb_connect_callback(F
, status
);
722 rb_ssl_timeout_cb(rb_fde_t
*const F
, void *const data
)
724 lrb_assert(F
->accept
!= NULL
);
725 lrb_assert(F
->accept
->callback
!= NULL
);
727 F
->accept
->callback(F
, RB_ERR_TIMEOUT
, NULL
, 0, F
->accept
->data
);
731 rb_ssl_tryconn_timeout_cb(rb_fde_t
*const F
, void *const data
)
733 rb_ssl_connect_realcb(F
, RB_ERR_TIMEOUT
, data
);
737 rb_ssl_tryconn(rb_fde_t
*const F
, const int status
, void *const data
)
739 lrb_assert(F
!= NULL
);
741 struct ssl_connect
*const sconn
= data
;
745 rb_ssl_connect_realcb(F
, status
, sconn
);
749 F
->type
|= RB_FD_SSL
;
751 rb_settimeout(F
, sconn
->timeout
, rb_ssl_tryconn_timeout_cb
, sconn
);
752 rb_ssl_init_fd(F
, RB_FD_TLS_DIRECTION_OUT
);
753 rb_ssl_connect_common(F
, sconn
);
757 rb_sock_net_recv(void *const context_ptr
, unsigned char *const buf
, const size_t count
)
759 const int fd
= rb_get_fd((rb_fde_t
*)context_ptr
);
761 const int ret
= (int) read(fd
, buf
, count
);
763 if(ret
< 0 && rb_ignore_errno(errno
))
764 return MBEDTLS_ERR_SSL_WANT_READ
;
770 rb_sock_net_xmit(void *const context_ptr
, const unsigned char *const buf
, const size_t count
)
772 const int fd
= rb_get_fd((rb_fde_t
*)context_ptr
);
774 const int ret
= (int) write(fd
, buf
, count
);
776 if(ret
< 0 && rb_ignore_errno(errno
))
777 return MBEDTLS_ERR_SSL_WANT_WRITE
;
785 * External library-agnostic code
789 rb_supports_ssl(void)
795 rb_ssl_handshake_count(rb_fde_t
*const F
)
797 return F
->handshake_count
;
801 rb_ssl_clear_handshake_count(rb_fde_t
*const F
)
803 F
->handshake_count
= 0;
807 rb_ssl_start_accepted(rb_fde_t
*const F
, ACCB
*const cb
, void *const data
, const int timeout
)
809 F
->type
|= RB_FD_SSL
;
811 F
->accept
= rb_malloc(sizeof(struct acceptdata
));
812 F
->accept
->callback
= cb
;
813 F
->accept
->data
= data
;
814 F
->accept
->addrlen
= 0;
815 (void) memset(&F
->accept
->S
, 0x00, sizeof F
->accept
->S
);
817 rb_settimeout(F
, timeout
, rb_ssl_timeout_cb
, NULL
);
818 rb_ssl_init_fd(F
, RB_FD_TLS_DIRECTION_IN
);
819 rb_ssl_accept_common(F
, NULL
);
823 rb_ssl_accept_setup(rb_fde_t
*const srv_F
, rb_fde_t
*const cli_F
, struct sockaddr
*const st
, const int addrlen
)
825 cli_F
->type
|= RB_FD_SSL
;
827 cli_F
->accept
= rb_malloc(sizeof(struct acceptdata
));
828 cli_F
->accept
->callback
= srv_F
->accept
->callback
;
829 cli_F
->accept
->data
= srv_F
->accept
->data
;
830 cli_F
->accept
->addrlen
= (rb_socklen_t
) addrlen
;
831 (void) memset(&cli_F
->accept
->S
, 0x00, sizeof cli_F
->accept
->S
);
832 (void) memcpy(&cli_F
->accept
->S
, st
, (size_t) addrlen
);
834 rb_settimeout(cli_F
, 10, rb_ssl_timeout_cb
, NULL
);
835 rb_ssl_init_fd(cli_F
, RB_FD_TLS_DIRECTION_IN
);
836 rb_ssl_accept_common(cli_F
, NULL
);
840 rb_ssl_listen(rb_fde_t
*const F
, const int backlog
, const int defer_accept
)
842 int result
= rb_listen(F
, backlog
, defer_accept
);
844 F
->type
= RB_FD_SOCKET
| RB_FD_LISTEN
| RB_FD_SSL
;
850 rb_connect_tcp_ssl(rb_fde_t
*const F
, struct sockaddr
*const dest
, struct sockaddr
*const clocal
,
851 CNCB
*const callback
, void *const data
, const int timeout
)
856 struct ssl_connect
*const sconn
= rb_malloc(sizeof *sconn
);
858 sconn
->callback
= callback
;
859 sconn
->timeout
= timeout
;
861 rb_connect_tcp(F
, dest
, clocal
, rb_ssl_tryconn
, sconn
, timeout
);
865 rb_ssl_start_connected(rb_fde_t
*const F
, CNCB
*const callback
, void *const data
, const int timeout
)
870 struct ssl_connect
*const sconn
= rb_malloc(sizeof *sconn
);
872 sconn
->callback
= callback
;
873 sconn
->timeout
= timeout
;
875 F
->connect
= rb_malloc(sizeof(struct conndata
));
876 F
->connect
->callback
= callback
;
877 F
->connect
->data
= data
;
879 F
->type
|= RB_FD_SSL
;
881 rb_settimeout(F
, sconn
->timeout
, rb_ssl_tryconn_timeout_cb
, sconn
);
882 rb_ssl_init_fd(F
, RB_FD_TLS_DIRECTION_OUT
);
883 rb_ssl_connect_common(F
, sconn
);
886 #endif /* HAVE_MBEDTLS */