]> jfr.im git - solanum.git/blob - librb/src/mbedtls.c
rename libratbox to librb, since its pretty modified anyway
[solanum.git] / librb / src / mbedtls.c
1 /*
2 * libratbox: a library used by ircd-ratbox and other things
3 * mbedtls.c: mbedtls related code
4 *
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 *
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.
13 *
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.
18 *
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
22 * USA
23 *
24 * $Id$
25 */
26
27 #include <libratbox_config.h>
28 #include <ratbox_lib.h>
29 #include <commio-int.h>
30 #include <commio-ssl.h>
31
32 #ifdef HAVE_MBEDTLS
33
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"
44
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;
52
53 #define SSL_P(x) ((mbedtls_ssl_context *)F->ssl)
54
55 void
56 rb_ssl_shutdown(rb_fde_t *F)
57 {
58 int i;
59 if(F == NULL || F->ssl == NULL)
60 return;
61 for(i = 0; i < 4; i++)
62 {
63 int r = mbedtls_ssl_close_notify(SSL_P(F));
64 if(r != MBEDTLS_ERR_SSL_WANT_READ && r != MBEDTLS_ERR_SSL_WANT_WRITE)
65 break;
66 }
67 mbedtls_ssl_free(SSL_P(F));
68 rb_free(F->ssl);
69 }
70
71 unsigned int
72 rb_ssl_handshake_count(rb_fde_t *F)
73 {
74 return F->handshake_count;
75 }
76
77 void
78 rb_ssl_clear_handshake_count(rb_fde_t *F)
79 {
80 F->handshake_count = 0;
81 }
82
83 static void
84 rb_ssl_timeout(rb_fde_t *F, void *notused)
85 {
86 lrb_assert(F->accept != NULL);
87 F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
88 }
89
90
91 static int
92 do_ssl_handshake(rb_fde_t *F, PF * callback, void *data)
93 {
94 int ret;
95 int flags;
96
97 ret = mbedtls_ssl_handshake(SSL_P(F));
98 if(ret < 0)
99 {
100 if (ret == -1 && rb_ignore_errno(errno))
101 ret = MBEDTLS_ERR_SSL_WANT_READ;
102
103 if((ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE))
104 {
105 if(ret == MBEDTLS_ERR_SSL_WANT_READ)
106 flags = RB_SELECT_READ;
107 else
108 flags = RB_SELECT_WRITE;
109 rb_setselect(F, flags, callback, data);
110 return 0;
111 }
112
113 F->ssl_errno = ret;
114 return -1;
115 }
116 return 1; /* handshake is finished..go about life */
117 }
118
119 static void
120 rb_ssl_tryaccept(rb_fde_t *F, void *data)
121 {
122 int ret;
123 struct acceptdata *ad;
124
125 lrb_assert(F->accept != NULL);
126
127 ret = do_ssl_handshake(F, rb_ssl_tryaccept, NULL);
128
129 /* do_ssl_handshake does the rb_setselect */
130 if(ret == 0)
131 return;
132
133 ad = F->accept;
134 F->accept = NULL;
135 rb_settimeout(F, 0, NULL, NULL);
136 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
137
138 if(ret > 0)
139 ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
140 else
141 ad->callback(F, RB_ERROR_SSL, NULL, 0, ad->data);
142
143 rb_free(ad);
144 }
145
146 static int
147 rb_ssl_read_cb(void *opaque, unsigned char *buf, size_t size)
148 {
149 int ret;
150 rb_fde_t *F = opaque;
151
152 ret = read(F->fd, buf, size);
153 if (ret < 0 && rb_ignore_errno(errno))
154 return MBEDTLS_ERR_SSL_WANT_READ;
155
156 return ret;
157 }
158
159 static int
160 rb_ssl_write_cb(void *opaque, const unsigned char *buf, size_t size)
161 {
162 rb_fde_t *F = opaque;
163 int ret;
164
165 ret = write(F->fd, buf, size);
166 if (ret < 0 && rb_ignore_errno(errno))
167 return MBEDTLS_ERR_SSL_WANT_WRITE;
168
169 return ret;
170 }
171
172 static void
173 rb_ssl_setup_srv_context(rb_fde_t *F, mbedtls_ssl_context *ssl)
174 {
175 int ret;
176
177 mbedtls_ssl_init(ssl);
178 if ((ret = mbedtls_ssl_setup(ssl, &serv_config)) != 0)
179 {
180 rb_lib_log("rb_ssl_setup_srv_context: failed to set up ssl context: -0x%x", -ret);
181 rb_close(F);
182 return;
183 }
184
185 mbedtls_ssl_set_bio(ssl, F, rb_ssl_write_cb, rb_ssl_read_cb, NULL);
186 }
187
188 void
189 rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout)
190 {
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));
195
196 new_F->accept->callback = cb;
197 new_F->accept->data = data;
198 rb_settimeout(new_F, timeout, rb_ssl_timeout, NULL);
199
200 new_F->accept->addrlen = 0;
201
202 rb_ssl_setup_srv_context(new_F, ssl);
203 if(do_ssl_handshake(new_F, rb_ssl_tryaccept, NULL))
204 {
205 struct acceptdata *ad = new_F->accept;
206 new_F->accept = NULL;
207
208 ad->callback(new_F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
209 rb_free(ad);
210 }
211 }
212
213 void
214 rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen)
215 {
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));
219
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;
225
226 rb_ssl_setup_srv_context(new_F, new_F->ssl);
227 if(do_ssl_handshake(F, rb_ssl_tryaccept, NULL))
228 {
229 struct acceptdata *ad = F->accept;
230 F->accept = NULL;
231
232 ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
233 rb_free(ad);
234 }
235 }
236
237 static ssize_t
238 rb_ssl_read_or_write(int r_or_w, rb_fde_t *F, void *rbuf, const void *wbuf, size_t count)
239 {
240 ssize_t ret;
241
242 if(r_or_w == 0)
243 ret = mbedtls_ssl_read(F->ssl, rbuf, count);
244 else
245 ret = mbedtls_ssl_write(F->ssl, wbuf, count);
246
247 if(ret < 0)
248 {
249 switch (ret)
250 {
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;
255 default:
256 F->ssl_errno = ret;
257 errno = EIO;
258 return RB_RW_IO_ERROR;
259 }
260 }
261
262 return ret;
263 }
264
265 ssize_t
266 rb_ssl_read(rb_fde_t *F, void *buf, size_t count)
267 {
268 return rb_ssl_read_or_write(0, F, buf, NULL, count);
269 }
270
271 ssize_t
272 rb_ssl_write(rb_fde_t *F, const void *buf, size_t count)
273 {
274 return rb_ssl_read_or_write(1, F, NULL, buf, count);
275 }
276
277 int
278 rb_init_ssl(void)
279 {
280 int ret;
281
282 mbedtls_entropy_init(&entropy);
283 mbedtls_ctr_drbg_init(&ctr_drbg);
284
285 if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0)) != 0)
286 {
287 rb_lib_log("rb_init_prng: unable to initialize PRNG, mbedtls_ctr_drbg_seed() returned -0x%x", -ret);
288 return 0;
289 }
290
291 mbedtls_ssl_config_init(&serv_config);
292
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)
297 {
298 rb_lib_log("rb_init_ssl: unable to initialize default SSL parameters for server context: -0x%x", -ret);
299 return 0;
300 }
301
302 mbedtls_ssl_conf_rng(&serv_config, mbedtls_ctr_drbg_random, &ctr_drbg);
303
304 /***************************************************************************************************************/
305
306 mbedtls_ssl_config_init(&client_config);
307
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)
312 {
313 rb_lib_log("rb_init_ssl: unable to initialize default SSL parameters for client context: -0x%x", -ret);
314 return 0;
315 }
316
317 mbedtls_ssl_conf_rng(&client_config, mbedtls_ctr_drbg_random, &ctr_drbg);
318 mbedtls_ssl_conf_authmode(&client_config, MBEDTLS_SSL_VERIFY_NONE);
319
320 return 1;
321 }
322
323 int
324 rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list)
325 {
326 int ret;
327
328 mbedtls_x509_crt_init(&x509);
329 ret = mbedtls_x509_crt_parse_file(&x509, cert);
330 if (ret != 0)
331 {
332 rb_lib_log("rb_setup_ssl_server: failed to parse certificate '%s': -0x%x", cert, -ret);
333 return 0;
334 }
335
336 mbedtls_pk_init(&serv_pk);
337 ret = mbedtls_pk_parse_keyfile(&serv_pk, keyfile, NULL);
338 if (ret != 0)
339 {
340 rb_lib_log("rb_setup_ssl_server: failed to parse private key '%s': -0x%x", keyfile, -ret);
341 return 0;
342 }
343
344 mbedtls_dhm_init(&dh_params);
345 ret = mbedtls_dhm_parse_dhmfile(&dh_params, dhfile);
346 if (ret != 0)
347 {
348 rb_lib_log("rb_setup_ssl_server: failed to parse DH parameters '%s': -0x%x", dhfile, -ret);
349 return 0;
350 }
351
352 ret = mbedtls_ssl_conf_dh_param_ctx(&serv_config, &dh_params);
353 if (ret != 0)
354 {
355 rb_lib_log("rb_setup_ssl_server: failed to set DH parameters on SSL config context: -0x%x", -ret);
356 return 0;
357 }
358
359 if (x509.next)
360 {
361 mbedtls_ssl_conf_ca_chain(&serv_config, x509.next, NULL);
362 mbedtls_ssl_conf_ca_chain(&client_config, x509.next, NULL);
363 }
364
365 if ((ret = mbedtls_ssl_conf_own_cert(&serv_config, &x509, &serv_pk)) != 0)
366 {
367 rb_lib_log("rb_setup_ssl_server: failed to set up own certificate: -0x%x", -ret);
368 return 0;
369 }
370
371 if ((ret = mbedtls_ssl_conf_own_cert(&client_config, &x509, &serv_pk)) != 0)
372 {
373 rb_lib_log("rb_setup_ssl_server: failed to set up own certificate: -0x%x", -ret);
374 return 0;
375 }
376
377 /* XXX support cipher lists when added to mbedtls */
378
379 return 1;
380 }
381
382 int
383 rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept)
384 {
385 int result;
386
387 result = rb_listen(F, backlog, defer_accept);
388 F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
389
390 return result;
391 }
392
393 struct ssl_connect
394 {
395 CNCB *callback;
396 void *data;
397 int timeout;
398 };
399
400 static void
401 rb_ssl_connect_realcb(rb_fde_t *F, int status, struct ssl_connect *sconn)
402 {
403 F->connect->callback = sconn->callback;
404 F->connect->data = sconn->data;
405 rb_free(sconn);
406 rb_connect_callback(F, status);
407 }
408
409 static void
410 rb_ssl_tryconn_timeout_cb(rb_fde_t *F, void *data)
411 {
412 rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
413 }
414
415 static void
416 rb_ssl_tryconn_cb(rb_fde_t *F, void *data)
417 {
418 struct ssl_connect *sconn = data;
419 int ret;
420
421 ret = do_ssl_handshake(F, rb_ssl_tryconn_cb, (void *)sconn);
422
423 switch (ret)
424 {
425 case -1:
426 rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn);
427 break;
428 case 0:
429 /* do_ssl_handshake does the rb_setselect stuff */
430 return;
431 default:
432 break;
433
434
435 }
436 rb_ssl_connect_realcb(F, RB_OK, sconn);
437 }
438
439 static void
440 rb_ssl_setup_client_context(rb_fde_t *F, mbedtls_ssl_context *ssl)
441 {
442 int ret;
443
444 mbedtls_ssl_init(ssl);
445 if ((ret = mbedtls_ssl_setup(ssl, &client_config)) != 0)
446 {
447 rb_lib_log("rb_ssl_setup_client_context: failed to set up ssl context: -0x%x", -ret);
448 rb_close(F);
449 return;
450 }
451
452 mbedtls_ssl_set_bio(ssl, F, rb_ssl_write_cb, rb_ssl_read_cb, NULL);
453 }
454
455 static void
456 rb_ssl_tryconn(rb_fde_t *F, int status, void *data)
457 {
458 struct ssl_connect *sconn = data;
459 if(status != RB_OK)
460 {
461 rb_ssl_connect_realcb(F, status, sconn);
462 return;
463 }
464
465 F->type |= RB_FD_SSL;
466
467
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);
471
472 do_ssl_handshake(F, rb_ssl_tryconn_cb, (void *)sconn);
473 }
474
475 void
476 rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest,
477 struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout)
478 {
479 struct ssl_connect *sconn;
480 if(F == NULL)
481 return;
482
483 sconn = rb_malloc(sizeof(struct ssl_connect));
484 sconn->data = data;
485 sconn->callback = callback;
486 sconn->timeout = timeout;
487 rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout);
488 }
489
490 void
491 rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout)
492 {
493 struct ssl_connect *sconn;
494 if(F == NULL)
495 return;
496
497 sconn = rb_malloc(sizeof(struct ssl_connect));
498 sconn->data = data;
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));
506
507 rb_ssl_setup_client_context(F, F->ssl);
508 rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
509
510 do_ssl_handshake(F, rb_ssl_tryconn_cb, (void *)sconn);
511 }
512
513 int
514 rb_init_prng(const char *path, prng_seed_t seed_type)
515 {
516 return 1;
517 }
518
519 int
520 rb_get_random(void *buf, size_t length)
521 {
522 if (mbedtls_ctr_drbg_random(&ctr_drbg, buf, length))
523 return 0;
524
525 return 1;
526 }
527
528 const char *
529 rb_get_ssl_strerror(rb_fde_t *F)
530 {
531 #ifdef MBEDTLS_ERROR_C
532 static char errbuf[512];
533 mbedtls_strerror(F->ssl_errno, errbuf, sizeof errbuf);
534 return errbuf;
535 #else
536 return "???";
537 #endif
538 }
539
540 int
541 rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
542 {
543 const mbedtls_x509_crt *peer_cert;
544 uint8_t hash[RB_SSL_CERTFP_LEN];
545 size_t hashlen;
546 const mbedtls_md_info_t *md_info;
547 mbedtls_md_type_t md_type;
548 int ret;
549
550 switch (method)
551 {
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;
561 default:
562 return 0;
563 }
564
565 peer_cert = mbedtls_ssl_get_peer_cert(SSL_P(F));
566 if (peer_cert == NULL)
567 return 0;
568
569 md_info = mbedtls_md_info_from_type(md_type);
570 if (md_info == NULL)
571 return 0;
572
573 if ((ret = mbedtls_md(md_info, peer_cert->raw.p, peer_cert->raw.len, hash)) != 0)
574 {
575 rb_lib_log("rb_get_ssl_certfp: unable to get certfp for F: %p, -0x%x", -ret);
576 return 0;
577 }
578
579 memcpy(certfp, hash, hashlen);
580
581 return 1;
582 }
583
584 int
585 rb_supports_ssl(void)
586 {
587 return 1;
588 }
589
590 void
591 rb_get_ssl_info(char *buf, size_t len)
592 {
593 char version_str[512];
594 mbedtls_version_get_string(version_str);
595
596 snprintf(buf, len, "MBEDTLS: compiled (%s), library(%s)",
597 MBEDTLS_VERSION_STRING, version_str);
598 }
599
600 const char *
601 rb_ssl_get_cipher(rb_fde_t *F)
602 {
603 if(F == NULL || F->ssl == NULL)
604 return NULL;
605 return mbedtls_ssl_get_ciphersuite(SSL_P(F));
606 }
607
608 #endif /* HAVE_GNUTLS */