]> jfr.im git - solanum.git/blame - librb/src/mbedtls.c
librb: silence some fairly harmless compiler warnings
[solanum.git] / librb / src / mbedtls.c
CommitLineData
cd492e44 1/*
fe037171 2 * librb: a library used by ircd-ratbox and other things
1e7342d0 3 * mbedtls.c: ARM mbedTLS backend
cd492e44
AC
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>
1e7342d0 8 * Copyright (C) 2016 Aaron Jones <aaronmdjones@gmail.com>
cd492e44
AC
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 *
cd492e44
AC
25 */
26
fe037171
EM
27#include <librb_config.h>
28#include <rb_lib.h>
cd492e44
AC
29#include <commio-int.h>
30#include <commio-ssl.h>
cf430c1a 31#include <stdbool.h>
cd492e44
AC
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
1e7342d0 46#include "mbedtls_embedded_data.h"
cd492e44 47
1e7342d0
AJ
48typedef 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
58typedef 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
67static mbedtls_ctr_drbg_context ctr_drbg_ctx;
68static mbedtls_entropy_context entropy_ctx;
69
70static mbedtls_x509_crt dummy_ca_ctx;
71static rb_mbedtls_cfg_context *rb_mbedtls_cfg = NULL;
72
73static const char *
74rb_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
89const char *
90rb_get_ssl_strerror(rb_fde_t *F)
91{
92 return rb_get_ssl_strerror_internal(F->ssl_errno);
93}
94
95static void rb_mbedtls_cfg_incref(rb_mbedtls_cfg_context *cfg)
96{
97 lrb_assert(cfg->refcount > 0);
98
99 cfg->refcount++;
100}
101
102static 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
121static 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}
cd492e44
AC
168
169void
170rb_ssl_shutdown(rb_fde_t *F)
171{
cd492e44
AC
172 if(F == NULL || F->ssl == NULL)
173 return;
1e7342d0
AJ
174
175 if(SSL_P(F) != NULL)
cd492e44 176 {
1e7342d0
AJ
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));
cd492e44 184 }
1e7342d0
AJ
185
186 if(SSL_C(F) != NULL)
187 rb_mbedtls_cfg_decref(SSL_C(F));
188
cd492e44
AC
189 rb_free(F->ssl);
190}
191
192unsigned int
193rb_ssl_handshake_count(rb_fde_t *F)
194{
195 return F->handshake_count;
196}
197
198void
199rb_ssl_clear_handshake_count(rb_fde_t *F)
200{
201 F->handshake_count = 0;
202}
203
204static void
205rb_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
cd492e44
AC
211static int
212do_ssl_handshake(rb_fde_t *F, PF * callback, void *data)
213{
1e7342d0 214 int ret = mbedtls_ssl_handshake(SSL_P(F));
cd492e44 215
1e7342d0 216 if(ret == 0)
cd492e44 217 {
1e7342d0
AJ
218 F->handshake_count++;
219 return 1;
220 }
539d912b 221
1e7342d0
AJ
222 if(ret == -1 && rb_ignore_errno(errno))
223 ret = MBEDTLS_ERR_SSL_WANT_READ;
539d912b 224
1e7342d0
AJ
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:
cd492e44
AC
234 F->ssl_errno = ret;
235 return -1;
236 }
cd492e44
AC
237}
238
239static void
240rb_ssl_tryaccept(rb_fde_t *F, void *data)
241{
cd492e44
AC
242 lrb_assert(F->accept != NULL);
243
1e7342d0 244 int ret = do_ssl_handshake(F, rb_ssl_tryaccept, NULL);
cd492e44
AC
245
246 /* do_ssl_handshake does the rb_setselect */
247 if(ret == 0)
248 return;
249
1e7342d0 250 struct acceptdata *ad = F->accept;
cd492e44
AC
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
263static int
264rb_ssl_read_cb(void *opaque, unsigned char *buf, size_t size)
265{
266 rb_fde_t *F = opaque;
267
1e7342d0
AJ
268 int ret = (int) read(F->fd, buf, size);
269 if(ret < 0 && rb_ignore_errno(errno))
539d912b
AC
270 return MBEDTLS_ERR_SSL_WANT_READ;
271
272 return ret;
cd492e44
AC
273}
274
275static int
276rb_ssl_write_cb(void *opaque, const unsigned char *buf, size_t size)
277{
278 rb_fde_t *F = opaque;
279
1e7342d0
AJ
280 int ret = (int) write(F->fd, buf, size);
281 if(ret < 0 && rb_ignore_errno(errno))
539d912b
AC
282 return MBEDTLS_ERR_SSL_WANT_WRITE;
283
284 return ret;
cd492e44
AC
285}
286
287static void
1e7342d0 288rb_ssl_setup_mbed_context(rb_fde_t *F, bool is_server)
cd492e44 289{
1e7342d0
AJ
290 rb_mbedtls_ssl_context *mbed_ssl_ctx;
291 mbedtls_ssl_config *mbed_config;
cd492e44
AC
292 int ret;
293
1e7342d0
AJ
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)
cd492e44 310 {
1e7342d0
AJ
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);
cd492e44
AC
315 rb_close(F);
316 return;
317 }
318
1e7342d0
AJ
319 mbed_ssl_ctx->cfg = rb_mbedtls_cfg;
320 rb_mbedtls_cfg_incref(mbed_ssl_ctx->cfg);
321 F->ssl = mbed_ssl_ctx;
cd492e44
AC
322}
323
324void
1e7342d0 325rb_ssl_start_accepted(rb_fde_t *F, ACCB * cb, void *data, int timeout)
cd492e44 326{
1e7342d0
AJ
327 F->type |= RB_FD_SSL;
328 F->accept = rb_malloc(sizeof(struct acceptdata));
cd492e44 329
1e7342d0
AJ
330 F->accept->callback = cb;
331 F->accept->data = data;
332 rb_settimeout(F, timeout, rb_ssl_timeout, NULL);
cd492e44 333
1e7342d0 334 F->accept->addrlen = 0;
cd492e44 335
1e7342d0
AJ
336 rb_ssl_setup_mbed_context(F, true);
337 if(do_ssl_handshake(F, rb_ssl_tryaccept, NULL))
cd492e44 338 {
1e7342d0
AJ
339 struct acceptdata *ad = F->accept;
340 F->accept = NULL;
341 ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data);
cd492e44
AC
342 rb_free(ad);
343 }
344}
345
346void
347rb_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;
cd492e44
AC
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);
1e7342d0 355
cd492e44
AC
356 memcpy(&new_F->accept->S, st, addrlen);
357 new_F->accept->addrlen = addrlen;
358
1e7342d0 359 rb_ssl_setup_mbed_context(new_F, true);
cd492e44
AC
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
369static ssize_t
1e7342d0 370rb_ssl_read_or_write(bool do_read, rb_fde_t *F, void *rbuf, const void *wbuf, size_t count)
cd492e44
AC
371{
372 ssize_t ret;
373
1e7342d0
AJ
374 if(do_read)
375 ret = mbedtls_ssl_read(SSL_P(F), rbuf, count);
cd492e44 376 else
1e7342d0 377 ret = mbedtls_ssl_write(SSL_P(F), wbuf, count);
cd492e44
AC
378
379 if(ret < 0)
380 {
1e7342d0 381 switch(ret)
cd492e44
AC
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_IO_ERROR;
391 }
392 }
393
394 return ret;
395}
396
397ssize_t
398rb_ssl_read(rb_fde_t *F, void *buf, size_t count)
399{
1e7342d0 400 return rb_ssl_read_or_write(true, F, buf, NULL, count);
cd492e44
AC
401}
402
403ssize_t
404rb_ssl_write(rb_fde_t *F, const void *buf, size_t count)
405{
1e7342d0 406 return rb_ssl_read_or_write(false, F, NULL, buf, count);
cd492e44
AC
407}
408
409int
410rb_init_ssl(void)
411{
412 int ret;
413
1e7342d0
AJ
414 mbedtls_ctr_drbg_init(&ctr_drbg_ctx);
415 mbedtls_entropy_init(&entropy_ctx);
cd492e44 416
1e7342d0
AJ
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)
cd492e44 419 {
1e7342d0
AJ
420 rb_lib_log("rb_init_ssl: ctr_drbg_seed: %s",
421 rb_get_ssl_strerror_internal(ret));
cd492e44
AC
422 return 0;
423 }
424
1e7342d0
AJ
425 if((ret = mbedtls_x509_crt_parse_der(&dummy_ca_ctx, rb_mbedtls_dummy_ca_certificate,
426 sizeof(rb_mbedtls_dummy_ca_certificate))) != 0)
cd492e44 427 {
1e7342d0
AJ
428 rb_lib_log("rb_init_ssl: x509_crt_parse_der (Dummy CA): %s",
429 rb_get_ssl_strerror_internal(ret));
cd492e44
AC
430 return 0;
431 }
432
cd492e44
AC
433 return 1;
434}
435
436int
1e7342d0 437rb_setup_ssl_server(const char *certfile, const char *keyfile, const char *dhfile, const char *cipher_list)
cd492e44 438{
1e7342d0 439 rb_mbedtls_cfg_context *newcfg;
cd492e44
AC
440 int ret;
441
1e7342d0 442 if(certfile == NULL)
cd492e44 443 {
1e7342d0 444 rb_lib_log("rb_setup_ssl_server: no certificate file specified");
cd492e44
AC
445 return 0;
446 }
447
1e7342d0
AJ
448 if(keyfile == NULL)
449 keyfile = certfile;
450
451 if((newcfg = rb_mbedtls_cfg_new()) == NULL)
cd492e44 452 {
1e7342d0 453 rb_lib_log("rb_setup_ssl_server: rb_mbedtls_cfg_new: allocation failed");
cd492e44
AC
454 return 0;
455 }
456
1e7342d0 457 if((ret = mbedtls_x509_crt_parse_file(&newcfg->crt, certfile)) != 0)
cd492e44 458 {
1e7342d0
AJ
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);
cd492e44
AC
462 return 0;
463 }
1e7342d0 464 if((ret = mbedtls_pk_parse_keyfile(&newcfg->key, keyfile, NULL)) != 0)
cd492e44 465 {
1e7342d0
AJ
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);
cd492e44
AC
469 return 0;
470 }
471
1e7342d0
AJ
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
493897d6 480 {
1e7342d0
AJ
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 }
493897d6 491 }
cd492e44 492
1e7342d0 493 if((ret = mbedtls_ssl_conf_own_cert(&newcfg->server_cfg, &newcfg->crt, &newcfg->key)) != 0)
cd492e44 494 {
1e7342d0
AJ
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);
cd492e44
AC
498 return 0;
499 }
1e7342d0 500 if((ret = mbedtls_ssl_conf_own_cert(&newcfg->client_cfg, &newcfg->crt, &newcfg->key)) != 0)
493897d6 501 {
1e7342d0
AJ
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);
493897d6
AC
505 return 0;
506 }
507
c1725bda
AC
508 /* XXX support cipher lists when added to mbedtls */
509
1e7342d0
AJ
510 rb_mbedtls_cfg_decref(rb_mbedtls_cfg);
511 rb_mbedtls_cfg = newcfg;
512
cd492e44
AC
513 return 1;
514}
515
516int
517rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept)
518{
1e7342d0 519 int result = rb_listen(F, backlog, defer_accept);
cd492e44
AC
520 F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL;
521
522 return result;
523}
524
525struct ssl_connect
526{
527 CNCB *callback;
528 void *data;
529 int timeout;
530};
531
532static void
533rb_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
541static void
542rb_ssl_tryconn_timeout_cb(rb_fde_t *F, void *data)
543{
544 rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data);
545}
546
547static void
548rb_ssl_tryconn_cb(rb_fde_t *F, void *data)
549{
1e7342d0 550 int ret = do_ssl_handshake(F, rb_ssl_tryconn_cb, data);
cd492e44 551
1e7342d0 552 switch(ret)
cd492e44
AC
553 {
554 case -1:
1e7342d0 555 rb_ssl_connect_realcb(F, RB_ERROR_SSL, data);
cd492e44
AC
556 break;
557 case 0:
558 /* do_ssl_handshake does the rb_setselect stuff */
559 return;
560 default:
561 break;
cd492e44 562 }
1e7342d0 563 rb_ssl_connect_realcb(F, RB_OK, data);
cd492e44
AC
564}
565
566static void
567rb_ssl_tryconn(rb_fde_t *F, int status, void *data)
568{
cd492e44
AC
569 if(status != RB_OK)
570 {
1e7342d0 571 rb_ssl_connect_realcb(F, status, data);
cd492e44
AC
572 return;
573 }
574
575 F->type |= RB_FD_SSL;
576
1e7342d0
AJ
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);
cd492e44
AC
580}
581
582void
583rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest,
5ad62c80 584 struct sockaddr *clocal, CNCB * callback, void *data, int timeout)
cd492e44 585{
cd492e44
AC
586 if(F == NULL)
587 return;
588
1e7342d0 589 struct ssl_connect *sconn = rb_malloc(sizeof(struct ssl_connect));
cd492e44
AC
590 sconn->data = data;
591 sconn->callback = callback;
592 sconn->timeout = timeout;
1e7342d0 593
5ad62c80 594 rb_connect_tcp(F, dest, clocal, rb_ssl_tryconn, sconn, timeout);
cd492e44
AC
595}
596
597void
598rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout)
599{
cd492e44
AC
600 if(F == NULL)
601 return;
602
1e7342d0 603 struct ssl_connect *sconn = rb_malloc(sizeof(struct ssl_connect));
cd492e44
AC
604 sconn->data = data;
605 sconn->callback = callback;
606 sconn->timeout = timeout;
1e7342d0 607
cd492e44
AC
608 F->connect = rb_malloc(sizeof(struct conndata));
609 F->connect->callback = callback;
610 F->connect->data = data;
611 F->type |= RB_FD_SSL;
cd492e44 612
1e7342d0 613 rb_ssl_setup_mbed_context(F, false);
cd492e44 614 rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
1e7342d0 615 do_ssl_handshake(F, rb_ssl_tryconn_cb, sconn);
cd492e44
AC
616}
617
618int
619rb_init_prng(const char *path, prng_seed_t seed_type)
620{
621 return 1;
622}
623
624int
625rb_get_random(void *buf, size_t length)
626{
1e7342d0 627 if(mbedtls_ctr_drbg_random(&ctr_drbg_ctx, buf, length))
cd492e44
AC
628 return 0;
629
630 return 1;
631}
632
03469187 633static size_t
1e7342d0 634rb_make_certfp(const mbedtls_x509_crt *peer_cert, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
cd492e44 635{
677d3cb1 636 const mbedtls_md_info_t *md_info;
e6bbb410 637 mbedtls_md_type_t md_type;
cf430c1a 638 bool spki = false;
1e7342d0 639 size_t hashlen;
03469187 640 int ret;
cd492e44 641
1e7342d0
AJ
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)
e6bbb410 647 {
cf430c1a 648 case RB_SSL_CERTFP_METH_CERT_SHA1:
e6bbb410 649 md_type = MBEDTLS_MD_SHA1;
1e7342d0 650 hashlen = RB_SSL_CERTFP_LEN_SHA1;
7da82465 651 break;
1e7342d0 652
cf430c1a
SA
653 case RB_SSL_CERTFP_METH_SPKI_SHA256:
654 spki = true;
655 case RB_SSL_CERTFP_METH_CERT_SHA256:
e6bbb410 656 md_type = MBEDTLS_MD_SHA256;
1e7342d0 657 hashlen = RB_SSL_CERTFP_LEN_SHA256;
7da82465 658 break;
1e7342d0 659
cf430c1a
SA
660 case RB_SSL_CERTFP_METH_SPKI_SHA512:
661 spki = true;
662 case RB_SSL_CERTFP_METH_CERT_SHA512:
e6bbb410 663 md_type = MBEDTLS_MD_SHA512;
1e7342d0 664 hashlen = RB_SSL_CERTFP_LEN_SHA512;
7da82465 665 break;
1e7342d0 666
e6bbb410
EM
667 default:
668 return 0;
669 }
670
1e7342d0 671 if((md_info = mbedtls_md_info_from_type(md_type)) == NULL)
cd492e44 672 return 0;
cd492e44 673
1e7342d0 674 if(spki)
cd492e44 675 {
1e7342d0
AJ
676 if ((ret = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)&peer_cert->pk,
677 der_pubkey, sizeof(der_pubkey))) < 0)
cf430c1a 678 {
1e7342d0
AJ
679 rb_lib_log("rb_get_ssl_certfp: pk_write_pubkey_der: %s",
680 rb_get_ssl_strerror_internal(ret));
681 return 0;
cf430c1a 682 }
1e7342d0
AJ
683 data = der_pubkey + (sizeof(der_pubkey) - ret);
684 datalen = ret;
cf430c1a 685 }
cf430c1a 686
1e7342d0
AJ
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;
cd492e44
AC
692 }
693
1e7342d0 694 return hashlen;
03469187
SA
695}
696
697int
698rb_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
1e7342d0 702 if ((peer_cert = mbedtls_ssl_get_peer_cert(SSL_P(F))) == NULL)
03469187
SA
703 return 0;
704
1e7342d0 705 return (int) rb_make_certfp(peer_cert, certfp, method);
03469187
SA
706}
707
708int
709rb_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
1e7342d0 716 if ((ret = mbedtls_x509_crt_parse_file(&cert, filename)) != 0)
03469187 717 return -1;
cd492e44 718
1e7342d0
AJ
719 size_t len = rb_make_certfp(&cert, certfp, method);
720
721 mbedtls_x509_crt_free(&cert);
722
723 return (int) len;
cd492e44
AC
724}
725
726int
727rb_supports_ssl(void)
728{
729 return 1;
730}
731
732void
733rb_get_ssl_info(char *buf, size_t len)
734{
735 char version_str[512];
736 mbedtls_version_get_string(version_str);
737
c40eede1
AJ
738 snprintf(buf, len, "ARM mbedTLS: compiled (v%s), library (v%s)",
739 MBEDTLS_VERSION_STRING, version_str);
cd492e44
AC
740}
741
833b2f9c
AC
742const char *
743rb_ssl_get_cipher(rb_fde_t *F)
744{
1e7342d0 745 if(F == NULL || F->ssl == NULL || SSL_P(F) == NULL)
833b2f9c
AC
746 return NULL;
747 return mbedtls_ssl_get_ciphersuite(SSL_P(F));
748}
cd492e44 749
1e7342d0 750#endif /* HAVE_MBEDTLS */