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>
29 #include <commio-int.h>
30 #include <commio-ssl.h>
35 #include "mbedtls/entropy.h"
36 #include "mbedtls/ctr_drbg.h"
37 #include "mbedtls/certs.h"
38 #include "mbedtls/x509.h"
39 #include "mbedtls/ssl.h"
40 #include "mbedtls/net.h"
41 #include "mbedtls/error.h"
42 #include "mbedtls/debug.h"
43 #include "mbedtls/dhm.h"
44 #include "mbedtls/version.h"
46 #include "mbedtls_embedded_data.h"
51 mbedtls_pk_context key
;
52 mbedtls_dhm_context dhp
;
53 mbedtls_ssl_config server_cfg
;
54 mbedtls_ssl_config client_cfg
;
56 } rb_mbedtls_cfg_context
;
60 rb_mbedtls_cfg_context
*cfg
;
61 mbedtls_ssl_context ssl
;
62 } rb_mbedtls_ssl_context
;
64 #define SSL_C(x) ((rb_mbedtls_ssl_context *) (x)->ssl)->cfg
65 #define SSL_P(x) &((rb_mbedtls_ssl_context *) (x)->ssl)->ssl
67 static mbedtls_ctr_drbg_context ctr_drbg_ctx
;
68 static mbedtls_entropy_context entropy_ctx
;
70 static mbedtls_x509_crt dummy_ca_ctx
;
71 static rb_mbedtls_cfg_context
*rb_mbedtls_cfg
= NULL
;
74 rb_get_ssl_strerror_internal(int err
)
76 static char errbuf
[512];
78 #ifdef MBEDTLS_ERROR_C
79 char mbed_errbuf
[512];
80 mbedtls_strerror(err
, mbed_errbuf
, sizeof mbed_errbuf
);
81 snprintf(errbuf
, sizeof errbuf
, "(-0x%x) %s", -err
, mbed_errbuf
);
83 snprintf(errbuf
, sizeof errbuf
, "-0x%x", -err
);
90 rb_get_ssl_strerror(rb_fde_t
*F
)
92 return rb_get_ssl_strerror_internal(F
->ssl_errno
);
95 static void rb_mbedtls_cfg_incref(rb_mbedtls_cfg_context
*cfg
)
97 lrb_assert(cfg
->refcount
> 0);
102 static void rb_mbedtls_cfg_decref(rb_mbedtls_cfg_context
*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
);
121 static rb_mbedtls_cfg_context
*rb_mbedtls_cfg_new(void)
123 rb_mbedtls_cfg_context
*cfg
;
126 if((cfg
= rb_malloc(sizeof(rb_mbedtls_cfg_context
))) == NULL
)
129 mbedtls_x509_crt_init(&cfg
->crt
);
130 mbedtls_pk_init(&cfg
->key
);
131 mbedtls_dhm_init(&cfg
->dhp
);
132 mbedtls_ssl_config_init(&cfg
->server_cfg
);
133 mbedtls_ssl_config_init(&cfg
->client_cfg
);
137 if((ret
= mbedtls_ssl_config_defaults(&cfg
->server_cfg
,
138 MBEDTLS_SSL_IS_SERVER
, MBEDTLS_SSL_TRANSPORT_STREAM
,
139 MBEDTLS_SSL_PRESET_DEFAULT
)) != 0)
141 rb_lib_log("rb_mbedtls_cfg_new: ssl_config_defaults (server): %s",
142 rb_get_ssl_strerror_internal(ret
));
143 rb_mbedtls_cfg_decref(cfg
);
147 if((ret
= mbedtls_ssl_config_defaults(&cfg
->client_cfg
,
148 MBEDTLS_SSL_IS_CLIENT
, MBEDTLS_SSL_TRANSPORT_STREAM
,
149 MBEDTLS_SSL_PRESET_DEFAULT
)) != 0)
151 rb_lib_log("rb_mbedtls_cfg_new: ssl_config_defaults (client): %s",
152 rb_get_ssl_strerror_internal(ret
));
153 rb_mbedtls_cfg_decref(cfg
);
157 mbedtls_ssl_conf_rng(&cfg
->server_cfg
, mbedtls_ctr_drbg_random
, &ctr_drbg_ctx
);
158 mbedtls_ssl_conf_rng(&cfg
->client_cfg
, mbedtls_ctr_drbg_random
, &ctr_drbg_ctx
);
160 mbedtls_ssl_conf_ca_chain(&cfg
->server_cfg
, &dummy_ca_ctx
, NULL
);
161 mbedtls_ssl_conf_ca_chain(&cfg
->client_cfg
, &dummy_ca_ctx
, NULL
);
163 mbedtls_ssl_conf_authmode(&cfg
->server_cfg
, MBEDTLS_SSL_VERIFY_OPTIONAL
);
164 mbedtls_ssl_conf_authmode(&cfg
->client_cfg
, MBEDTLS_SSL_VERIFY_NONE
);
170 rb_ssl_shutdown(rb_fde_t
*F
)
172 if(F
== NULL
|| F
->ssl
== NULL
)
177 for(int i
= 0; i
< 4; i
++)
179 int r
= mbedtls_ssl_close_notify(SSL_P(F
));
180 if(r
!= MBEDTLS_ERR_SSL_WANT_READ
&& r
!= MBEDTLS_ERR_SSL_WANT_WRITE
)
183 mbedtls_ssl_free(SSL_P(F
));
187 rb_mbedtls_cfg_decref(SSL_C(F
));
193 rb_ssl_handshake_count(rb_fde_t
*F
)
195 return F
->handshake_count
;
199 rb_ssl_clear_handshake_count(rb_fde_t
*F
)
201 F
->handshake_count
= 0;
205 rb_ssl_timeout(rb_fde_t
*F
, void *notused
)
207 lrb_assert(F
->accept
!= NULL
);
208 F
->accept
->callback(F
, RB_ERR_TIMEOUT
, NULL
, 0, F
->accept
->data
);
212 do_ssl_handshake(rb_fde_t
*F
, PF
* callback
, void *data
)
214 int ret
= mbedtls_ssl_handshake(SSL_P(F
));
218 F
->handshake_count
++;
222 if(ret
== -1 && rb_ignore_errno(errno
))
223 ret
= MBEDTLS_ERR_SSL_WANT_READ
;
227 case MBEDTLS_ERR_SSL_WANT_READ
:
228 rb_setselect(F
, RB_SELECT_READ
, callback
, data
);
230 case MBEDTLS_ERR_SSL_WANT_WRITE
:
231 rb_setselect(F
, RB_SELECT_WRITE
, callback
, data
);
240 rb_ssl_tryaccept(rb_fde_t
*F
, void *data
)
242 lrb_assert(F
->accept
!= NULL
);
244 int ret
= do_ssl_handshake(F
, rb_ssl_tryaccept
, NULL
);
246 /* do_ssl_handshake does the rb_setselect */
250 struct acceptdata
*ad
= F
->accept
;
252 rb_settimeout(F
, 0, NULL
, NULL
);
253 rb_setselect(F
, RB_SELECT_READ
| RB_SELECT_WRITE
, NULL
, NULL
);
256 ad
->callback(F
, RB_OK
, (struct sockaddr
*)&ad
->S
, ad
->addrlen
, ad
->data
);
258 ad
->callback(F
, RB_ERROR_SSL
, NULL
, 0, ad
->data
);
264 rb_ssl_read_cb(void *opaque
, unsigned char *buf
, size_t size
)
266 rb_fde_t
*F
= opaque
;
268 int ret
= (int) read(F
->fd
, buf
, size
);
269 if(ret
< 0 && rb_ignore_errno(errno
))
270 return MBEDTLS_ERR_SSL_WANT_READ
;
276 rb_ssl_write_cb(void *opaque
, const unsigned char *buf
, size_t size
)
278 rb_fde_t
*F
= opaque
;
280 int ret
= (int) write(F
->fd
, buf
, size
);
281 if(ret
< 0 && rb_ignore_errno(errno
))
282 return MBEDTLS_ERR_SSL_WANT_WRITE
;
288 rb_ssl_setup_mbed_context(rb_fde_t
*F
, bool is_server
)
290 rb_mbedtls_ssl_context
*mbed_ssl_ctx
;
291 mbedtls_ssl_config
*mbed_config
;
294 if((mbed_ssl_ctx
= rb_malloc(sizeof(rb_mbedtls_ssl_context
))) == NULL
)
296 rb_lib_log("rb_ssl_setup_mbed_context: rb_malloc: allocation failure");
302 mbed_config
= &rb_mbedtls_cfg
->server_cfg
;
304 mbed_config
= &rb_mbedtls_cfg
->client_cfg
;
306 mbedtls_ssl_init(&mbed_ssl_ctx
->ssl
);
307 mbedtls_ssl_set_bio(&mbed_ssl_ctx
->ssl
, F
, rb_ssl_write_cb
, rb_ssl_read_cb
, NULL
);
309 if((ret
= mbedtls_ssl_setup(&mbed_ssl_ctx
->ssl
, mbed_config
)) != 0)
311 rb_lib_log("rb_ssl_setup_mbed_context: ssl_setup: %s",
312 rb_get_ssl_strerror_internal(ret
));
313 mbedtls_ssl_free(&mbed_ssl_ctx
->ssl
);
314 rb_free(mbed_ssl_ctx
);
319 mbed_ssl_ctx
->cfg
= rb_mbedtls_cfg
;
320 rb_mbedtls_cfg_incref(mbed_ssl_ctx
->cfg
);
321 F
->ssl
= mbed_ssl_ctx
;
325 rb_ssl_start_accepted(rb_fde_t
*F
, ACCB
* cb
, void *data
, int timeout
)
327 F
->type
|= RB_FD_SSL
;
328 F
->accept
= rb_malloc(sizeof(struct acceptdata
));
330 F
->accept
->callback
= cb
;
331 F
->accept
->data
= data
;
332 rb_settimeout(F
, timeout
, rb_ssl_timeout
, NULL
);
334 F
->accept
->addrlen
= 0;
336 rb_ssl_setup_mbed_context(F
, true);
337 if(do_ssl_handshake(F
, rb_ssl_tryaccept
, NULL
))
339 struct acceptdata
*ad
= F
->accept
;
341 ad
->callback(F
, RB_OK
, (struct sockaddr
*)&ad
->S
, ad
->addrlen
, ad
->data
);
347 rb_ssl_accept_setup(rb_fde_t
*F
, rb_fde_t
*new_F
, struct sockaddr
*st
, int addrlen
)
349 new_F
->type
|= RB_FD_SSL
;
350 new_F
->accept
= rb_malloc(sizeof(struct acceptdata
));
352 new_F
->accept
->callback
= F
->accept
->callback
;
353 new_F
->accept
->data
= F
->accept
->data
;
354 rb_settimeout(new_F
, 10, rb_ssl_timeout
, NULL
);
356 memcpy(&new_F
->accept
->S
, st
, addrlen
);
357 new_F
->accept
->addrlen
= addrlen
;
359 rb_ssl_setup_mbed_context(new_F
, true);
360 if(do_ssl_handshake(F
, rb_ssl_tryaccept
, NULL
))
362 struct acceptdata
*ad
= F
->accept
;
364 ad
->callback(F
, RB_OK
, (struct sockaddr
*)&ad
->S
, ad
->addrlen
, ad
->data
);
370 rb_ssl_read_or_write(bool do_read
, rb_fde_t
*F
, void *rbuf
, const void *wbuf
, size_t count
)
375 ret
= mbedtls_ssl_read(SSL_P(F
), rbuf
, count
);
377 ret
= mbedtls_ssl_write(SSL_P(F
), wbuf
, count
);
383 case MBEDTLS_ERR_SSL_WANT_READ
:
384 return RB_RW_SSL_NEED_READ
;
385 case MBEDTLS_ERR_SSL_WANT_WRITE
:
386 return RB_RW_SSL_NEED_WRITE
;
390 return RB_RW_SSL_ERROR
;
398 rb_ssl_read(rb_fde_t
*F
, void *buf
, size_t count
)
400 return rb_ssl_read_or_write(true, F
, buf
, NULL
, count
);
404 rb_ssl_write(rb_fde_t
*F
, const void *buf
, size_t count
)
406 return rb_ssl_read_or_write(false, F
, NULL
, buf
, count
);
414 mbedtls_ctr_drbg_init(&ctr_drbg_ctx
);
415 mbedtls_entropy_init(&entropy_ctx
);
417 if((ret
= mbedtls_ctr_drbg_seed(&ctr_drbg_ctx
, mbedtls_entropy_func
, &entropy_ctx
,
418 (const unsigned char *)rb_mbedtls_personal_str
, sizeof(rb_mbedtls_personal_str
))) != 0)
420 rb_lib_log("rb_init_ssl: ctr_drbg_seed: %s",
421 rb_get_ssl_strerror_internal(ret
));
425 if((ret
= mbedtls_x509_crt_parse_der(&dummy_ca_ctx
, rb_mbedtls_dummy_ca_certificate
,
426 sizeof(rb_mbedtls_dummy_ca_certificate
))) != 0)
428 rb_lib_log("rb_init_ssl: x509_crt_parse_der (Dummy CA): %s",
429 rb_get_ssl_strerror_internal(ret
));
437 rb_setup_ssl_server(const char *certfile
, const char *keyfile
, const char *dhfile
, const char *cipher_list
)
439 rb_mbedtls_cfg_context
*newcfg
;
444 rb_lib_log("rb_setup_ssl_server: no certificate file specified");
451 if((newcfg
= rb_mbedtls_cfg_new()) == NULL
)
453 rb_lib_log("rb_setup_ssl_server: rb_mbedtls_cfg_new: allocation failed");
457 if((ret
= mbedtls_x509_crt_parse_file(&newcfg
->crt
, certfile
)) != 0)
459 rb_lib_log("rb_setup_ssl_server: x509_crt_parse_file ('%s'): %s",
460 certfile
, rb_get_ssl_strerror_internal(ret
));
461 rb_mbedtls_cfg_decref(newcfg
);
464 if((ret
= mbedtls_pk_parse_keyfile(&newcfg
->key
, keyfile
, NULL
)) != 0)
466 rb_lib_log("rb_setup_ssl_server: pk_parse_keyfile ('%s'): %s",
467 keyfile
, rb_get_ssl_strerror_internal(ret
));
468 rb_mbedtls_cfg_decref(newcfg
);
472 /* Absense of DH parameters does not matter with mbedTLS, as it comes with its own defaults
473 Thus, clients can still use DHE- ciphersuites, just over a weaker, common DH group
474 So, we do not consider failure to parse DH parameters as fatal */
477 rb_lib_log("rb_setup_ssl_server: no DH parameters file specified");
481 if((ret
= mbedtls_dhm_parse_dhmfile(&newcfg
->dhp
, dhfile
)) != 0)
483 rb_lib_log("rb_setup_ssl_server: dhm_parse_dhmfile ('%s'): %s",
484 dhfile
, rb_get_ssl_strerror_internal(ret
));
486 else if((ret
= mbedtls_ssl_conf_dh_param_ctx(&newcfg
->server_cfg
, &newcfg
->dhp
)) != 0)
488 rb_lib_log("rb_setup_ssl_server: ssl_conf_dh_param_ctx: %s",
489 rb_get_ssl_strerror_internal(ret
));
493 if((ret
= mbedtls_ssl_conf_own_cert(&newcfg
->server_cfg
, &newcfg
->crt
, &newcfg
->key
)) != 0)
495 rb_lib_log("rb_setup_ssl_server: ssl_conf_own_cert (server): %s",
496 rb_get_ssl_strerror_internal(ret
));
497 rb_mbedtls_cfg_decref(newcfg
);
500 if((ret
= mbedtls_ssl_conf_own_cert(&newcfg
->client_cfg
, &newcfg
->crt
, &newcfg
->key
)) != 0)
502 rb_lib_log("rb_setup_ssl_server: ssl_conf_own_cert (client): %s",
503 rb_get_ssl_strerror_internal(ret
));
504 rb_mbedtls_cfg_decref(newcfg
);
508 /* XXX support cipher lists when added to mbedtls */
510 rb_mbedtls_cfg_decref(rb_mbedtls_cfg
);
511 rb_mbedtls_cfg
= newcfg
;
517 rb_ssl_listen(rb_fde_t
*F
, int backlog
, int defer_accept
)
519 int result
= rb_listen(F
, backlog
, defer_accept
);
520 F
->type
= RB_FD_SOCKET
| RB_FD_LISTEN
| RB_FD_SSL
;
533 rb_ssl_connect_realcb(rb_fde_t
*F
, int status
, struct ssl_connect
*sconn
)
535 F
->connect
->callback
= sconn
->callback
;
536 F
->connect
->data
= sconn
->data
;
538 rb_connect_callback(F
, status
);
542 rb_ssl_tryconn_timeout_cb(rb_fde_t
*F
, void *data
)
544 rb_ssl_connect_realcb(F
, RB_ERR_TIMEOUT
, data
);
548 rb_ssl_tryconn_cb(rb_fde_t
*F
, void *data
)
550 int ret
= do_ssl_handshake(F
, rb_ssl_tryconn_cb
, data
);
555 rb_ssl_connect_realcb(F
, RB_ERROR_SSL
, data
);
558 /* do_ssl_handshake does the rb_setselect stuff */
563 rb_ssl_connect_realcb(F
, RB_OK
, data
);
567 rb_ssl_tryconn(rb_fde_t
*F
, int status
, void *data
)
571 rb_ssl_connect_realcb(F
, status
, data
);
575 F
->type
|= RB_FD_SSL
;
577 rb_ssl_setup_mbed_context(F
, false);
578 rb_settimeout(F
, ((struct ssl_connect
*)data
)->timeout
, rb_ssl_tryconn_timeout_cb
, data
);
579 do_ssl_handshake(F
, rb_ssl_tryconn_cb
, data
);
583 rb_connect_tcp_ssl(rb_fde_t
*F
, struct sockaddr
*dest
,
584 struct sockaddr
*clocal
, CNCB
* callback
, void *data
, int timeout
)
589 struct ssl_connect
*sconn
= rb_malloc(sizeof(struct ssl_connect
));
591 sconn
->callback
= callback
;
592 sconn
->timeout
= timeout
;
594 rb_connect_tcp(F
, dest
, clocal
, rb_ssl_tryconn
, sconn
, timeout
);
598 rb_ssl_start_connected(rb_fde_t
*F
, CNCB
* callback
, void *data
, int timeout
)
603 struct ssl_connect
*sconn
= rb_malloc(sizeof(struct ssl_connect
));
605 sconn
->callback
= callback
;
606 sconn
->timeout
= timeout
;
608 F
->connect
= rb_malloc(sizeof(struct conndata
));
609 F
->connect
->callback
= callback
;
610 F
->connect
->data
= data
;
611 F
->type
|= RB_FD_SSL
;
613 rb_ssl_setup_mbed_context(F
, false);
614 rb_settimeout(F
, sconn
->timeout
, rb_ssl_tryconn_timeout_cb
, sconn
);
615 do_ssl_handshake(F
, rb_ssl_tryconn_cb
, sconn
);
619 rb_init_prng(const char *path
, prng_seed_t seed_type
)
625 rb_get_random(void *buf
, size_t length
)
627 if(mbedtls_ctr_drbg_random(&ctr_drbg_ctx
, buf
, length
))
634 rb_make_certfp(const mbedtls_x509_crt
*peer_cert
, uint8_t certfp
[RB_SSL_CERTFP_LEN
], int method
)
636 const mbedtls_md_info_t
*md_info
;
637 mbedtls_md_type_t md_type
;
642 uint8_t der_pubkey
[8192];
643 void* data
= peer_cert
->raw
.p
;
644 size_t datalen
= peer_cert
->raw
.len
;
648 case RB_SSL_CERTFP_METH_CERT_SHA1
:
649 md_type
= MBEDTLS_MD_SHA1
;
650 hashlen
= RB_SSL_CERTFP_LEN_SHA1
;
653 case RB_SSL_CERTFP_METH_SPKI_SHA256
:
655 case RB_SSL_CERTFP_METH_CERT_SHA256
:
656 md_type
= MBEDTLS_MD_SHA256
;
657 hashlen
= RB_SSL_CERTFP_LEN_SHA256
;
660 case RB_SSL_CERTFP_METH_SPKI_SHA512
:
662 case RB_SSL_CERTFP_METH_CERT_SHA512
:
663 md_type
= MBEDTLS_MD_SHA512
;
664 hashlen
= RB_SSL_CERTFP_LEN_SHA512
;
671 if((md_info
= mbedtls_md_info_from_type(md_type
)) == NULL
)
676 if ((ret
= mbedtls_pk_write_pubkey_der((mbedtls_pk_context
*)&peer_cert
->pk
,
677 der_pubkey
, sizeof(der_pubkey
))) < 0)
679 rb_lib_log("rb_get_ssl_certfp: pk_write_pubkey_der: %s",
680 rb_get_ssl_strerror_internal(ret
));
683 data
= der_pubkey
+ (sizeof(der_pubkey
) - ret
);
687 if((ret
= mbedtls_md(md_info
, data
, datalen
, certfp
)) != 0)
689 rb_lib_log("rb_get_ssl_certfp: mbedtls_md: %s",
690 rb_get_ssl_strerror_internal(ret
));
698 rb_get_ssl_certfp(rb_fde_t
*F
, uint8_t certfp
[RB_SSL_CERTFP_LEN
], int method
)
700 const mbedtls_x509_crt
*peer_cert
;
702 if ((peer_cert
= mbedtls_ssl_get_peer_cert(SSL_P(F
))) == NULL
)
705 return (int) rb_make_certfp(peer_cert
, certfp
, method
);
709 rb_get_ssl_certfp_file(const char *filename
, uint8_t certfp
[RB_SSL_CERTFP_LEN
], int method
)
711 mbedtls_x509_crt cert
;
714 mbedtls_x509_crt_init(&cert
);
716 if ((ret
= mbedtls_x509_crt_parse_file(&cert
, filename
)) != 0)
719 size_t len
= rb_make_certfp(&cert
, certfp
, method
);
721 mbedtls_x509_crt_free(&cert
);
727 rb_supports_ssl(void)
733 rb_get_ssl_info(char *buf
, size_t len
)
735 char version_str
[512];
736 mbedtls_version_get_string(version_str
);
738 snprintf(buf
, len
, "ARM mbedTLS: compiled (v%s), library (v%s)",
739 MBEDTLS_VERSION_STRING
, version_str
);
743 rb_ssl_get_cipher(rb_fde_t
*F
)
745 if(F
== NULL
|| F
->ssl
== NULL
|| SSL_P(F
) == NULL
)
747 return mbedtls_ssl_get_ciphersuite(SSL_P(F
));
750 #endif /* HAVE_MBEDTLS */