]> jfr.im git - solanum.git/blob - librb/src/mbedtls.c
mbedtls backend: indicate reason for TLS session termination
[solanum.git] / librb / src / mbedtls.c
1 /*
2 * librb: a library used by ircd-ratbox and other things
3 * mbedtls.c: ARM mbedTLS backend
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 * Copyright (C) 2016 Aaron Jones <aaronmdjones@gmail.com>
9 *
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.
14 *
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.
19 *
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
23 * USA
24 *
25 */
26
27 #include <librb_config.h>
28 #include <rb_lib.h>
29 #include <commio-int.h>
30 #include <commio-ssl.h>
31 #include <stdbool.h>
32
33 #ifdef HAVE_MBEDTLS
34
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"
45
46 #include "mbedtls_embedded_data.h"
47
48 typedef struct
49 {
50 mbedtls_x509_crt crt;
51 mbedtls_pk_context key;
52 mbedtls_dhm_context dhp;
53 mbedtls_ssl_config server_cfg;
54 mbedtls_ssl_config client_cfg;
55 size_t refcount;
56 } rb_mbedtls_cfg_context;
57
58 typedef struct
59 {
60 rb_mbedtls_cfg_context *cfg;
61 mbedtls_ssl_context ssl;
62 } rb_mbedtls_ssl_context;
63
64 #define SSL_C(x) ((rb_mbedtls_ssl_context *) (x)->ssl)->cfg
65 #define SSL_P(x) &((rb_mbedtls_ssl_context *) (x)->ssl)->ssl
66
67 static mbedtls_ctr_drbg_context ctr_drbg_ctx;
68 static mbedtls_entropy_context entropy_ctx;
69
70 static mbedtls_x509_crt dummy_ca_ctx;
71 static rb_mbedtls_cfg_context *rb_mbedtls_cfg = NULL;
72
73 static const char *
74 rb_get_ssl_strerror_internal(int err)
75 {
76 static char errbuf[512];
77
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);
82 #else
83 snprintf(errbuf, sizeof errbuf, "-0x%x", -err);
84 #endif
85
86 return errbuf;
87 }
88
89 const char *
90 rb_get_ssl_strerror(rb_fde_t *F)
91 {
92 return rb_get_ssl_strerror_internal(F->ssl_errno);
93 }
94
95 static void rb_mbedtls_cfg_incref(rb_mbedtls_cfg_context *cfg)
96 {
97 lrb_assert(cfg->refcount > 0);
98
99 cfg->refcount++;
100 }
101
102 static void rb_mbedtls_cfg_decref(rb_mbedtls_cfg_context *cfg)
103 {
104 if(cfg == NULL)
105 return;
106
107 lrb_assert(cfg->refcount > 0);
108
109 if((--cfg->refcount) > 0)
110 return;
111
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);
117
118 rb_free(cfg);
119 }
120
121 static rb_mbedtls_cfg_context *rb_mbedtls_cfg_new(void)
122 {
123 rb_mbedtls_cfg_context *cfg;
124 int ret;
125
126 if((cfg = rb_malloc(sizeof(rb_mbedtls_cfg_context))) == NULL)
127 return NULL;
128
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);
134
135 cfg->refcount = 1;
136
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)
140 {
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);
144 return NULL;
145 }
146
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)
150 {
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);
154 return NULL;
155 }
156
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);
159
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);
162
163 mbedtls_ssl_conf_authmode(&cfg->server_cfg, MBEDTLS_SSL_VERIFY_OPTIONAL);
164 mbedtls_ssl_conf_authmode(&cfg->client_cfg, MBEDTLS_SSL_VERIFY_NONE);
165
166 return cfg;
167 }
168
169 void
170 rb_ssl_shutdown(rb_fde_t *F)
171 {
172 if(F == NULL || F->ssl == NULL)
173 return;
174
175 if(SSL_P(F) != NULL)
176 {
177 for(int i = 0; i < 4; i++)
178 {
179 int r = mbedtls_ssl_close_notify(SSL_P(F));
180 if(r != MBEDTLS_ERR_SSL_WANT_READ && r != MBEDTLS_ERR_SSL_WANT_WRITE)
181 break;
182 }
183 mbedtls_ssl_free(SSL_P(F));
184 }
185
186 if(SSL_C(F) != NULL)
187 rb_mbedtls_cfg_decref(SSL_C(F));
188
189 rb_free(F->ssl);
190 }
191
192 unsigned int
193 rb_ssl_handshake_count(rb_fde_t *F)
194 {
195 return F->handshake_count;
196 }
197
198 void
199 rb_ssl_clear_handshake_count(rb_fde_t *F)
200 {
201 F->handshake_count = 0;
202 }
203
204 static void
205 rb_ssl_timeout(rb_fde_t *F, void *notused)
206 {
207 lrb_assert(F->accept != NULL);
208 F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data);
209 }
210
211 static int
212 do_ssl_handshake(rb_fde_t *F, PF * callback, void *data)
213 {
214 int ret = mbedtls_ssl_handshake(SSL_P(F));
215
216 if(ret == 0)
217 {
218 F->handshake_count++;
219 return 1;
220 }
221
222 if(ret == -1 && rb_ignore_errno(errno))
223 ret = MBEDTLS_ERR_SSL_WANT_READ;
224
225 switch(ret)
226 {
227 case MBEDTLS_ERR_SSL_WANT_READ:
228 rb_setselect(F, RB_SELECT_READ, callback, data);
229 return 0;
230 case MBEDTLS_ERR_SSL_WANT_WRITE:
231 rb_setselect(F, RB_SELECT_WRITE, callback, data);
232 return 0;
233 default:
234 F->ssl_errno = ret;
235 return -1;
236 }
237 }
238
239 static void
240 rb_ssl_tryaccept(rb_fde_t *F, void *data)
241 {
242 lrb_assert(F->accept != NULL);
243
244 int ret = do_ssl_handshake(F, rb_ssl_tryaccept, NULL);
245
246 /* do_ssl_handshake does the rb_setselect */
247 if(ret == 0)
248 return;
249
250 struct acceptdata *ad = F->accept;
251 F->accept = NULL;
252 rb_settimeout(F, 0, NULL, NULL);
253 rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL);
254
255 if(ret > 0)
256 ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
257 else
258 ad->callback(F, RB_ERROR_SSL, NULL, 0, ad->data);
259
260 rb_free(ad);
261 }
262
263 static int
264 rb_ssl_read_cb(void *opaque, unsigned char *buf, size_t size)
265 {
266 rb_fde_t *F = opaque;
267
268 int ret = (int) read(F->fd, buf, size);
269 if(ret < 0 && rb_ignore_errno(errno))
270 return MBEDTLS_ERR_SSL_WANT_READ;
271
272 return ret;
273 }
274
275 static int
276 rb_ssl_write_cb(void *opaque, const unsigned char *buf, size_t size)
277 {
278 rb_fde_t *F = opaque;
279
280 int ret = (int) write(F->fd, buf, size);
281 if(ret < 0 && rb_ignore_errno(errno))
282 return MBEDTLS_ERR_SSL_WANT_WRITE;
283
284 return ret;
285 }
286
287 static void
288 rb_ssl_setup_mbed_context(rb_fde_t *F, bool is_server)
289 {
290 rb_mbedtls_ssl_context *mbed_ssl_ctx;
291 mbedtls_ssl_config *mbed_config;
292 int ret;
293
294 if((mbed_ssl_ctx = rb_malloc(sizeof(rb_mbedtls_ssl_context))) == NULL)
295 {
296 rb_lib_log("rb_ssl_setup_mbed_context: rb_malloc: allocation failure");
297 rb_close(F);
298 return;
299 }
300
301 if(is_server)
302 mbed_config = &rb_mbedtls_cfg->server_cfg;
303 else
304 mbed_config = &rb_mbedtls_cfg->client_cfg;
305
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);
308
309 if((ret = mbedtls_ssl_setup(&mbed_ssl_ctx->ssl, mbed_config)) != 0)
310 {
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);
315 rb_close(F);
316 return;
317 }
318
319 mbed_ssl_ctx->cfg = rb_mbedtls_cfg;
320 rb_mbedtls_cfg_incref(mbed_ssl_ctx->cfg);
321 F->ssl = mbed_ssl_ctx;
322 }
323
324 void
325 rb_ssl_start_accepted(rb_fde_t *F, ACCB * cb, void *data, int timeout)
326 {
327 F->type |= RB_FD_SSL;
328 F->accept = rb_malloc(sizeof(struct acceptdata));
329
330 F->accept->callback = cb;
331 F->accept->data = data;
332 rb_settimeout(F, timeout, rb_ssl_timeout, NULL);
333
334 F->accept->addrlen = 0;
335
336 rb_ssl_setup_mbed_context(F, true);
337 if(do_ssl_handshake(F, rb_ssl_tryaccept, NULL))
338 {
339 struct acceptdata *ad = F->accept;
340 F->accept = NULL;
341 ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
342 rb_free(ad);
343 }
344 }
345
346 void
347 rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen)
348 {
349 new_F->type |= RB_FD_SSL;
350 new_F->accept = rb_malloc(sizeof(struct acceptdata));
351
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);
355
356 memcpy(&new_F->accept->S, st, addrlen);
357 new_F->accept->addrlen = addrlen;
358
359 rb_ssl_setup_mbed_context(new_F, true);
360 if(do_ssl_handshake(F, rb_ssl_tryaccept, NULL))
361 {
362 struct acceptdata *ad = F->accept;
363 F->accept = NULL;
364 ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
365 rb_free(ad);
366 }
367 }
368
369 static ssize_t
370 rb_ssl_read_or_write(bool do_read, rb_fde_t *F, void *rbuf, const void *wbuf, size_t count)
371 {
372 ssize_t ret;
373
374 if(do_read)
375 ret = mbedtls_ssl_read(SSL_P(F), rbuf, count);
376 else
377 ret = mbedtls_ssl_write(SSL_P(F), wbuf, count);
378
379 if(ret < 0)
380 {
381 switch(ret)
382 {
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;
387 default:
388 F->ssl_errno = ret;
389 errno = EIO;
390 return RB_RW_SSL_ERROR;
391 }
392 }
393
394 return ret;
395 }
396
397 ssize_t
398 rb_ssl_read(rb_fde_t *F, void *buf, size_t count)
399 {
400 return rb_ssl_read_or_write(true, F, buf, NULL, count);
401 }
402
403 ssize_t
404 rb_ssl_write(rb_fde_t *F, const void *buf, size_t count)
405 {
406 return rb_ssl_read_or_write(false, F, NULL, buf, count);
407 }
408
409 int
410 rb_init_ssl(void)
411 {
412 int ret;
413
414 mbedtls_ctr_drbg_init(&ctr_drbg_ctx);
415 mbedtls_entropy_init(&entropy_ctx);
416
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)
419 {
420 rb_lib_log("rb_init_ssl: ctr_drbg_seed: %s",
421 rb_get_ssl_strerror_internal(ret));
422 return 0;
423 }
424
425 if((ret = mbedtls_x509_crt_parse_der(&dummy_ca_ctx, rb_mbedtls_dummy_ca_certificate,
426 sizeof(rb_mbedtls_dummy_ca_certificate))) != 0)
427 {
428 rb_lib_log("rb_init_ssl: x509_crt_parse_der (Dummy CA): %s",
429 rb_get_ssl_strerror_internal(ret));
430 return 0;
431 }
432
433 return 1;
434 }
435
436 int
437 rb_setup_ssl_server(const char *certfile, const char *keyfile, const char *dhfile, const char *cipher_list)
438 {
439 rb_mbedtls_cfg_context *newcfg;
440 int ret;
441
442 if(certfile == NULL)
443 {
444 rb_lib_log("rb_setup_ssl_server: no certificate file specified");
445 return 0;
446 }
447
448 if(keyfile == NULL)
449 keyfile = certfile;
450
451 if((newcfg = rb_mbedtls_cfg_new()) == NULL)
452 {
453 rb_lib_log("rb_setup_ssl_server: rb_mbedtls_cfg_new: allocation failed");
454 return 0;
455 }
456
457 if((ret = mbedtls_x509_crt_parse_file(&newcfg->crt, certfile)) != 0)
458 {
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);
462 return 0;
463 }
464 if((ret = mbedtls_pk_parse_keyfile(&newcfg->key, keyfile, NULL)) != 0)
465 {
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);
469 return 0;
470 }
471
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 */
475 if(dhfile == NULL)
476 {
477 rb_lib_log("rb_setup_ssl_server: no DH parameters file specified");
478 }
479 else
480 {
481 if((ret = mbedtls_dhm_parse_dhmfile(&newcfg->dhp, dhfile)) != 0)
482 {
483 rb_lib_log("rb_setup_ssl_server: dhm_parse_dhmfile ('%s'): %s",
484 dhfile, rb_get_ssl_strerror_internal(ret));
485 }
486 else if((ret = mbedtls_ssl_conf_dh_param_ctx(&newcfg->server_cfg, &newcfg->dhp)) != 0)
487 {
488 rb_lib_log("rb_setup_ssl_server: ssl_conf_dh_param_ctx: %s",
489 rb_get_ssl_strerror_internal(ret));
490 }
491 }
492
493 if((ret = mbedtls_ssl_conf_own_cert(&newcfg->server_cfg, &newcfg->crt, &newcfg->key)) != 0)
494 {
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);
498 return 0;
499 }
500 if((ret = mbedtls_ssl_conf_own_cert(&newcfg->client_cfg, &newcfg->crt, &newcfg->key)) != 0)
501 {
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);
505 return 0;
506 }
507
508 /* XXX support cipher lists when added to mbedtls */
509
510 rb_mbedtls_cfg_decref(rb_mbedtls_cfg);
511 rb_mbedtls_cfg = newcfg;
512
513 return 1;
514 }
515
516 int
517 rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept)
518 {
519 int result = rb_listen(F, backlog, defer_accept);
520 F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
521
522 return result;
523 }
524
525 struct ssl_connect
526 {
527 CNCB *callback;
528 void *data;
529 int timeout;
530 };
531
532 static void
533 rb_ssl_connect_realcb(rb_fde_t *F, int status, struct ssl_connect *sconn)
534 {
535 F->connect->callback = sconn->callback;
536 F->connect->data = sconn->data;
537 rb_free(sconn);
538 rb_connect_callback(F, status);
539 }
540
541 static void
542 rb_ssl_tryconn_timeout_cb(rb_fde_t *F, void *data)
543 {
544 rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
545 }
546
547 static void
548 rb_ssl_tryconn_cb(rb_fde_t *F, void *data)
549 {
550 int ret = do_ssl_handshake(F, rb_ssl_tryconn_cb, data);
551
552 switch(ret)
553 {
554 case -1:
555 rb_ssl_connect_realcb(F, RB_ERROR_SSL, data);
556 break;
557 case 0:
558 /* do_ssl_handshake does the rb_setselect stuff */
559 return;
560 default:
561 break;
562 }
563 rb_ssl_connect_realcb(F, RB_OK, data);
564 }
565
566 static void
567 rb_ssl_tryconn(rb_fde_t *F, int status, void *data)
568 {
569 if(status != RB_OK)
570 {
571 rb_ssl_connect_realcb(F, status, data);
572 return;
573 }
574
575 F->type |= RB_FD_SSL;
576
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);
580 }
581
582 void
583 rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest,
584 struct sockaddr *clocal, CNCB * callback, void *data, int timeout)
585 {
586 if(F == NULL)
587 return;
588
589 struct ssl_connect *sconn = rb_malloc(sizeof(struct ssl_connect));
590 sconn->data = data;
591 sconn->callback = callback;
592 sconn->timeout = timeout;
593
594 rb_connect_tcp(F, dest, clocal, rb_ssl_tryconn, sconn, timeout);
595 }
596
597 void
598 rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout)
599 {
600 if(F == NULL)
601 return;
602
603 struct ssl_connect *sconn = rb_malloc(sizeof(struct ssl_connect));
604 sconn->data = data;
605 sconn->callback = callback;
606 sconn->timeout = timeout;
607
608 F->connect = rb_malloc(sizeof(struct conndata));
609 F->connect->callback = callback;
610 F->connect->data = data;
611 F->type |= RB_FD_SSL;
612
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);
616 }
617
618 int
619 rb_init_prng(const char *path, prng_seed_t seed_type)
620 {
621 return 1;
622 }
623
624 int
625 rb_get_random(void *buf, size_t length)
626 {
627 if(mbedtls_ctr_drbg_random(&ctr_drbg_ctx, buf, length))
628 return 0;
629
630 return 1;
631 }
632
633 static size_t
634 rb_make_certfp(const mbedtls_x509_crt *peer_cert, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
635 {
636 const mbedtls_md_info_t *md_info;
637 mbedtls_md_type_t md_type;
638 bool spki = false;
639 size_t hashlen;
640 int ret;
641
642 uint8_t der_pubkey[8192];
643 void* data = peer_cert->raw.p;
644 size_t datalen = peer_cert->raw.len;
645
646 switch(method)
647 {
648 case RB_SSL_CERTFP_METH_CERT_SHA1:
649 md_type = MBEDTLS_MD_SHA1;
650 hashlen = RB_SSL_CERTFP_LEN_SHA1;
651 break;
652
653 case RB_SSL_CERTFP_METH_SPKI_SHA256:
654 spki = true;
655 case RB_SSL_CERTFP_METH_CERT_SHA256:
656 md_type = MBEDTLS_MD_SHA256;
657 hashlen = RB_SSL_CERTFP_LEN_SHA256;
658 break;
659
660 case RB_SSL_CERTFP_METH_SPKI_SHA512:
661 spki = true;
662 case RB_SSL_CERTFP_METH_CERT_SHA512:
663 md_type = MBEDTLS_MD_SHA512;
664 hashlen = RB_SSL_CERTFP_LEN_SHA512;
665 break;
666
667 default:
668 return 0;
669 }
670
671 if((md_info = mbedtls_md_info_from_type(md_type)) == NULL)
672 return 0;
673
674 if(spki)
675 {
676 if ((ret = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)&peer_cert->pk,
677 der_pubkey, sizeof(der_pubkey))) < 0)
678 {
679 rb_lib_log("rb_get_ssl_certfp: pk_write_pubkey_der: %s",
680 rb_get_ssl_strerror_internal(ret));
681 return 0;
682 }
683 data = der_pubkey + (sizeof(der_pubkey) - ret);
684 datalen = ret;
685 }
686
687 if((ret = mbedtls_md(md_info, data, datalen, certfp)) != 0)
688 {
689 rb_lib_log("rb_get_ssl_certfp: mbedtls_md: %s",
690 rb_get_ssl_strerror_internal(ret));
691 return 0;
692 }
693
694 return hashlen;
695 }
696
697 int
698 rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
699 {
700 const mbedtls_x509_crt *peer_cert;
701
702 if ((peer_cert = mbedtls_ssl_get_peer_cert(SSL_P(F))) == NULL)
703 return 0;
704
705 return (int) rb_make_certfp(peer_cert, certfp, method);
706 }
707
708 int
709 rb_get_ssl_certfp_file(const char *filename, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
710 {
711 mbedtls_x509_crt cert;
712 int ret;
713
714 mbedtls_x509_crt_init(&cert);
715
716 if ((ret = mbedtls_x509_crt_parse_file(&cert, filename)) != 0)
717 return -1;
718
719 size_t len = rb_make_certfp(&cert, certfp, method);
720
721 mbedtls_x509_crt_free(&cert);
722
723 return (int) len;
724 }
725
726 int
727 rb_supports_ssl(void)
728 {
729 return 1;
730 }
731
732 void
733 rb_get_ssl_info(char *buf, size_t len)
734 {
735 char version_str[512];
736 mbedtls_version_get_string(version_str);
737
738 snprintf(buf, len, "ARM mbedTLS: compiled (v%s), library (v%s)",
739 MBEDTLS_VERSION_STRING, version_str);
740 }
741
742 const char *
743 rb_ssl_get_cipher(rb_fde_t *F)
744 {
745 if(F == NULL || F->ssl == NULL || SSL_P(F) == NULL)
746 return NULL;
747 return mbedtls_ssl_get_ciphersuite(SSL_P(F));
748 }
749
750 #endif /* HAVE_MBEDTLS */