2 * libratbox: a library used by ircd-ratbox and other things
3 * mbedtls.c: mbedtls related code
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>
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
27 #include <libratbox_config.h>
28 #include <ratbox_lib.h>
29 #include <commio-int.h>
30 #include <commio-ssl.h>
34 #include "mbedtls/entropy.h"
35 #include "mbedtls/ctr_drbg.h"
36 #include "mbedtls/certs.h"
37 #include "mbedtls/x509.h"
38 #include "mbedtls/ssl.h"
39 #include "mbedtls/net.h"
40 #include "mbedtls/error.h"
41 #include "mbedtls/debug.h"
42 #include "mbedtls/dhm.h"
43 #include "mbedtls/version.h"
45 static mbedtls_x509_crt x509
;
46 static mbedtls_pk_context serv_pk
;
47 static mbedtls_dhm_context dh_params
;
48 static mbedtls_ctr_drbg_context ctr_drbg
;
49 static mbedtls_entropy_context entropy
;
50 static mbedtls_ssl_config serv_config
;
51 static mbedtls_ssl_config client_config
;
53 #define SSL_P(x) ((mbedtls_ssl_context *)F->ssl)
56 rb_ssl_shutdown(rb_fde_t
*F
)
59 if(F
== NULL
|| F
->ssl
== NULL
)
61 for(i
= 0; i
< 4; i
++)
63 int r
= mbedtls_ssl_close_notify(SSL_P(F
));
64 if(r
!= MBEDTLS_ERR_SSL_WANT_READ
&& r
!= MBEDTLS_ERR_SSL_WANT_WRITE
)
67 mbedtls_ssl_free(SSL_P(F
));
72 rb_ssl_handshake_count(rb_fde_t
*F
)
74 return F
->handshake_count
;
78 rb_ssl_clear_handshake_count(rb_fde_t
*F
)
80 F
->handshake_count
= 0;
84 rb_ssl_timeout(rb_fde_t
*F
, void *notused
)
86 lrb_assert(F
->accept
!= NULL
);
87 F
->accept
->callback(F
, RB_ERR_TIMEOUT
, NULL
, 0, F
->accept
->data
);
92 do_ssl_handshake(rb_fde_t
*F
, PF
* callback
, void *data
)
97 ret
= mbedtls_ssl_handshake(SSL_P(F
));
100 if (ret
== -1 && rb_ignore_errno(errno
))
101 ret
= MBEDTLS_ERR_SSL_WANT_READ
;
103 if((ret
== MBEDTLS_ERR_SSL_WANT_READ
|| ret
== MBEDTLS_ERR_SSL_WANT_WRITE
))
105 if(ret
== MBEDTLS_ERR_SSL_WANT_READ
)
106 flags
= RB_SELECT_READ
;
108 flags
= RB_SELECT_WRITE
;
109 rb_setselect(F
, flags
, callback
, data
);
116 return 1; /* handshake is finished..go about life */
120 rb_ssl_tryaccept(rb_fde_t
*F
, void *data
)
123 struct acceptdata
*ad
;
125 lrb_assert(F
->accept
!= NULL
);
127 ret
= do_ssl_handshake(F
, rb_ssl_tryaccept
, NULL
);
129 /* do_ssl_handshake does the rb_setselect */
135 rb_settimeout(F
, 0, NULL
, NULL
);
136 rb_setselect(F
, RB_SELECT_READ
| RB_SELECT_WRITE
, NULL
, NULL
);
139 ad
->callback(F
, RB_OK
, (struct sockaddr
*)&ad
->S
, ad
->addrlen
, ad
->data
);
141 ad
->callback(F
, RB_ERROR_SSL
, NULL
, 0, ad
->data
);
147 rb_ssl_read_cb(void *opaque
, unsigned char *buf
, size_t size
)
150 rb_fde_t
*F
= opaque
;
152 ret
= read(F
->fd
, buf
, size
);
153 if (ret
< 0 && rb_ignore_errno(errno
))
154 return MBEDTLS_ERR_SSL_WANT_READ
;
160 rb_ssl_write_cb(void *opaque
, const unsigned char *buf
, size_t size
)
162 rb_fde_t
*F
= opaque
;
165 ret
= write(F
->fd
, buf
, size
);
166 if (ret
< 0 && rb_ignore_errno(errno
))
167 return MBEDTLS_ERR_SSL_WANT_WRITE
;
173 rb_ssl_setup_srv_context(rb_fde_t
*F
, mbedtls_ssl_context
*ssl
)
177 mbedtls_ssl_init(ssl
);
178 if ((ret
= mbedtls_ssl_setup(ssl
, &serv_config
)) != 0)
180 rb_lib_log("rb_ssl_setup_srv_context: failed to set up ssl context: -0x%x", -ret
);
185 mbedtls_ssl_set_bio(ssl
, F
, rb_ssl_write_cb
, rb_ssl_read_cb
, NULL
);
189 rb_ssl_start_accepted(rb_fde_t
*new_F
, ACCB
* cb
, void *data
, int timeout
)
191 mbedtls_ssl_context
*ssl
;
192 new_F
->type
|= RB_FD_SSL
;
193 ssl
= new_F
->ssl
= rb_malloc(sizeof(mbedtls_ssl_context
));
194 new_F
->accept
= rb_malloc(sizeof(struct acceptdata
));
196 new_F
->accept
->callback
= cb
;
197 new_F
->accept
->data
= data
;
198 rb_settimeout(new_F
, timeout
, rb_ssl_timeout
, NULL
);
200 new_F
->accept
->addrlen
= 0;
202 rb_ssl_setup_srv_context(new_F
, ssl
);
203 if(do_ssl_handshake(new_F
, rb_ssl_tryaccept
, NULL
))
205 struct acceptdata
*ad
= new_F
->accept
;
206 new_F
->accept
= NULL
;
208 ad
->callback(new_F
, RB_OK
, (struct sockaddr
*)&ad
->S
, ad
->addrlen
, ad
->data
);
214 rb_ssl_accept_setup(rb_fde_t
*F
, rb_fde_t
*new_F
, struct sockaddr
*st
, int addrlen
)
216 new_F
->type
|= RB_FD_SSL
;
217 new_F
->ssl
= rb_malloc(sizeof(mbedtls_ssl_context
));
218 new_F
->accept
= rb_malloc(sizeof(struct acceptdata
));
220 new_F
->accept
->callback
= F
->accept
->callback
;
221 new_F
->accept
->data
= F
->accept
->data
;
222 rb_settimeout(new_F
, 10, rb_ssl_timeout
, NULL
);
223 memcpy(&new_F
->accept
->S
, st
, addrlen
);
224 new_F
->accept
->addrlen
= addrlen
;
226 rb_ssl_setup_srv_context(new_F
, new_F
->ssl
);
227 if(do_ssl_handshake(F
, rb_ssl_tryaccept
, NULL
))
229 struct acceptdata
*ad
= F
->accept
;
232 ad
->callback(F
, RB_OK
, (struct sockaddr
*)&ad
->S
, ad
->addrlen
, ad
->data
);
238 rb_ssl_read_or_write(int r_or_w
, rb_fde_t
*F
, void *rbuf
, const void *wbuf
, size_t count
)
243 ret
= mbedtls_ssl_read(F
->ssl
, rbuf
, count
);
245 ret
= mbedtls_ssl_write(F
->ssl
, wbuf
, count
);
251 case MBEDTLS_ERR_SSL_WANT_READ
:
252 return RB_RW_SSL_NEED_READ
;
253 case MBEDTLS_ERR_SSL_WANT_WRITE
:
254 return RB_RW_SSL_NEED_WRITE
;
258 return RB_RW_IO_ERROR
;
266 rb_ssl_read(rb_fde_t
*F
, void *buf
, size_t count
)
268 return rb_ssl_read_or_write(0, F
, buf
, NULL
, count
);
272 rb_ssl_write(rb_fde_t
*F
, const void *buf
, size_t count
)
274 return rb_ssl_read_or_write(1, F
, NULL
, buf
, count
);
282 mbedtls_entropy_init(&entropy
);
283 mbedtls_ctr_drbg_init(&ctr_drbg
);
285 if((ret
= mbedtls_ctr_drbg_seed(&ctr_drbg
, mbedtls_entropy_func
, &entropy
, NULL
, 0)) != 0)
287 rb_lib_log("rb_init_prng: unable to initialize PRNG, mbedtls_ctr_drbg_seed() returned -0x%x", -ret
);
291 mbedtls_ssl_config_init(&serv_config
);
293 if ((ret
= mbedtls_ssl_config_defaults(&serv_config
,
294 MBEDTLS_SSL_IS_SERVER
,
295 MBEDTLS_SSL_TRANSPORT_STREAM
,
296 MBEDTLS_SSL_PRESET_DEFAULT
)) != 0)
298 rb_lib_log("rb_init_ssl: unable to initialize default SSL parameters for server context: -0x%x", -ret
);
302 mbedtls_ssl_conf_rng(&serv_config
, mbedtls_ctr_drbg_random
, &ctr_drbg
);
304 /***************************************************************************************************************/
306 mbedtls_ssl_config_init(&client_config
);
308 if ((ret
= mbedtls_ssl_config_defaults(&client_config
,
309 MBEDTLS_SSL_IS_CLIENT
,
310 MBEDTLS_SSL_TRANSPORT_STREAM
,
311 MBEDTLS_SSL_PRESET_DEFAULT
)) != 0)
313 rb_lib_log("rb_init_ssl: unable to initialize default SSL parameters for client context: -0x%x", -ret
);
317 mbedtls_ssl_conf_rng(&client_config
, mbedtls_ctr_drbg_random
, &ctr_drbg
);
318 mbedtls_ssl_conf_authmode(&client_config
, MBEDTLS_SSL_VERIFY_NONE
);
324 rb_setup_ssl_server(const char *cert
, const char *keyfile
, const char *dhfile
, const char *cipher_list
)
328 mbedtls_x509_crt_init(&x509
);
329 ret
= mbedtls_x509_crt_parse_file(&x509
, cert
);
332 rb_lib_log("rb_setup_ssl_server: failed to parse certificate '%s': -0x%x", cert
, -ret
);
336 mbedtls_pk_init(&serv_pk
);
337 ret
= mbedtls_pk_parse_keyfile(&serv_pk
, keyfile
, NULL
);
340 rb_lib_log("rb_setup_ssl_server: failed to parse private key '%s': -0x%x", keyfile
, -ret
);
344 mbedtls_dhm_init(&dh_params
);
345 ret
= mbedtls_dhm_parse_dhmfile(&dh_params
, dhfile
);
348 rb_lib_log("rb_setup_ssl_server: failed to parse DH parameters '%s': -0x%x", dhfile
, -ret
);
352 ret
= mbedtls_ssl_conf_dh_param_ctx(&serv_config
, &dh_params
);
355 rb_lib_log("rb_setup_ssl_server: failed to set DH parameters on SSL config context: -0x%x", -ret
);
361 mbedtls_ssl_conf_ca_chain(&serv_config
, x509
.next
, NULL
);
362 mbedtls_ssl_conf_ca_chain(&client_config
, x509
.next
, NULL
);
365 if ((ret
= mbedtls_ssl_conf_own_cert(&serv_config
, &x509
, &serv_pk
)) != 0)
367 rb_lib_log("rb_setup_ssl_server: failed to set up own certificate: -0x%x", -ret
);
371 if ((ret
= mbedtls_ssl_conf_own_cert(&client_config
, &x509
, &serv_pk
)) != 0)
373 rb_lib_log("rb_setup_ssl_server: failed to set up own certificate: -0x%x", -ret
);
377 /* XXX support cipher lists when added to mbedtls */
383 rb_ssl_listen(rb_fde_t
*F
, int backlog
, int defer_accept
)
387 result
= rb_listen(F
, backlog
, defer_accept
);
388 F
->type
= RB_FD_SOCKET
| RB_FD_LISTEN
| RB_FD_SSL
;
401 rb_ssl_connect_realcb(rb_fde_t
*F
, int status
, struct ssl_connect
*sconn
)
403 F
->connect
->callback
= sconn
->callback
;
404 F
->connect
->data
= sconn
->data
;
406 rb_connect_callback(F
, status
);
410 rb_ssl_tryconn_timeout_cb(rb_fde_t
*F
, void *data
)
412 rb_ssl_connect_realcb(F
, RB_ERR_TIMEOUT
, data
);
416 rb_ssl_tryconn_cb(rb_fde_t
*F
, void *data
)
418 struct ssl_connect
*sconn
= data
;
421 ret
= do_ssl_handshake(F
, rb_ssl_tryconn_cb
, (void *)sconn
);
426 rb_ssl_connect_realcb(F
, RB_ERROR_SSL
, sconn
);
429 /* do_ssl_handshake does the rb_setselect stuff */
436 rb_ssl_connect_realcb(F
, RB_OK
, sconn
);
440 rb_ssl_setup_client_context(rb_fde_t
*F
, mbedtls_ssl_context
*ssl
)
444 mbedtls_ssl_init(ssl
);
445 if ((ret
= mbedtls_ssl_setup(ssl
, &client_config
)) != 0)
447 rb_lib_log("rb_ssl_setup_client_context: failed to set up ssl context: -0x%x", -ret
);
452 mbedtls_ssl_set_bio(ssl
, F
, rb_ssl_write_cb
, rb_ssl_read_cb
, NULL
);
456 rb_ssl_tryconn(rb_fde_t
*F
, int status
, void *data
)
458 struct ssl_connect
*sconn
= data
;
461 rb_ssl_connect_realcb(F
, status
, sconn
);
465 F
->type
|= RB_FD_SSL
;
468 rb_settimeout(F
, sconn
->timeout
, rb_ssl_tryconn_timeout_cb
, sconn
);
469 F
->ssl
= rb_malloc(sizeof(mbedtls_ssl_context
));
470 rb_ssl_setup_client_context(F
, F
->ssl
);
472 do_ssl_handshake(F
, rb_ssl_tryconn_cb
, (void *)sconn
);
476 rb_connect_tcp_ssl(rb_fde_t
*F
, struct sockaddr
*dest
,
477 struct sockaddr
*clocal
, int socklen
, CNCB
* callback
, void *data
, int timeout
)
479 struct ssl_connect
*sconn
;
483 sconn
= rb_malloc(sizeof(struct ssl_connect
));
485 sconn
->callback
= callback
;
486 sconn
->timeout
= timeout
;
487 rb_connect_tcp(F
, dest
, clocal
, socklen
, rb_ssl_tryconn
, sconn
, timeout
);
491 rb_ssl_start_connected(rb_fde_t
*F
, CNCB
* callback
, void *data
, int timeout
)
493 struct ssl_connect
*sconn
;
497 sconn
= rb_malloc(sizeof(struct ssl_connect
));
499 sconn
->callback
= callback
;
500 sconn
->timeout
= timeout
;
501 F
->connect
= rb_malloc(sizeof(struct conndata
));
502 F
->connect
->callback
= callback
;
503 F
->connect
->data
= data
;
504 F
->type
|= RB_FD_SSL
;
505 F
->ssl
= rb_malloc(sizeof(mbedtls_ssl_context
));
507 rb_ssl_setup_client_context(F
, F
->ssl
);
508 rb_settimeout(F
, sconn
->timeout
, rb_ssl_tryconn_timeout_cb
, sconn
);
510 do_ssl_handshake(F
, rb_ssl_tryconn_cb
, (void *)sconn
);
514 rb_init_prng(const char *path
, prng_seed_t seed_type
)
520 rb_get_random(void *buf
, size_t length
)
522 if (mbedtls_ctr_drbg_random(&ctr_drbg
, buf
, length
))
529 rb_get_ssl_strerror(rb_fde_t
*F
)
531 #ifdef MBEDTLS_ERROR_C
532 static char errbuf
[512];
533 mbedtls_strerror(F
->ssl_errno
, errbuf
, sizeof errbuf
);
541 rb_get_ssl_certfp(rb_fde_t
*F
, uint8_t certfp
[RB_SSL_CERTFP_LEN
], int method
)
543 const mbedtls_x509_crt
*peer_cert
;
544 uint8_t hash
[RB_SSL_CERTFP_LEN
];
546 const mbedtls_md_info_t
*md_info
;
547 mbedtls_md_type_t md_type
;
552 case RB_SSL_CERTFP_METH_SHA1
:
553 md_type
= MBEDTLS_MD_SHA1
;
554 hashlen
= RB_SSL_CERTFP_LEN_SHA1
;
555 case RB_SSL_CERTFP_METH_SHA256
:
556 md_type
= MBEDTLS_MD_SHA256
;
557 hashlen
= RB_SSL_CERTFP_LEN_SHA256
;
558 case RB_SSL_CERTFP_METH_SHA512
:
559 md_type
= MBEDTLS_MD_SHA512
;
560 hashlen
= RB_SSL_CERTFP_LEN_SHA512
;
565 peer_cert
= mbedtls_ssl_get_peer_cert(SSL_P(F
));
566 if (peer_cert
== NULL
)
569 md_info
= mbedtls_md_info_from_type(md_type
);
573 if ((ret
= mbedtls_md(md_info
, peer_cert
->raw
.p
, peer_cert
->raw
.len
, hash
)) != 0)
575 rb_lib_log("rb_get_ssl_certfp: unable to get certfp for F: %p, -0x%x", -ret
);
579 memcpy(certfp
, hash
, hashlen
);
585 rb_supports_ssl(void)
591 rb_get_ssl_info(char *buf
, size_t len
)
593 char version_str
[512];
594 mbedtls_version_get_string(version_str
);
596 snprintf(buf
, len
, "MBEDTLS: compiled (%s), library(%s)",
597 MBEDTLS_VERSION_STRING
, version_str
);
601 rb_ssl_get_cipher(rb_fde_t
*F
)
603 if(F
== NULL
|| F
->ssl
== NULL
)
605 return mbedtls_ssl_get_ciphersuite(SSL_P(F
));
608 #endif /* HAVE_GNUTLS */