mbedtls: handle session tickets for TLS 1.3
[project/ustream-ssl.git] / ustream-mbedtls.c
1 /*
2 * ustream-ssl - library for SSL over ustream
3 *
4 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/types.h>
20 #include <sys/random.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "ustream-ssl.h"
27 #include "ustream-internal.h"
28 #include <psa/crypto.h>
29 #include <mbedtls/debug.h>
30
31 static void debug_cb(void *ctx_p, int level,
32 const char *file, int line,
33 const char *str)
34 {
35 struct ustream_ssl_ctx *ctx = ctx_p;
36 const char *fstr;
37 char buf[512];
38 int len;
39
40 if (!ctx->debug_cb)
41 return;
42
43 while ((fstr = strstr(file + 1, "library/")) != NULL)
44 file = fstr;
45
46 len = snprintf(buf, sizeof(buf), "%s:%04d: %s", file, line, str);
47 if (len >= (int)sizeof(buf))
48 len = (int)sizeof(buf) - 1;
49 if (buf[len - 1] == '\n')
50 buf[len - 1] = 0;
51 ctx->debug_cb(ctx->debug_cb_priv, level, buf);
52 }
53
54 static int s_ustream_read(void *ctx, unsigned char *buf, size_t len)
55 {
56 struct ustream *s = ctx;
57 char *sbuf;
58 int slen;
59
60 if (s->eof)
61 return 0;
62
63 sbuf = ustream_get_read_buf(s, &slen);
64 if ((size_t) slen > len)
65 slen = len;
66
67 if (!slen)
68 return MBEDTLS_ERR_SSL_WANT_READ;
69
70 memcpy(buf, sbuf, slen);
71 ustream_consume(s, slen);
72
73 return slen;
74 }
75
76 static int s_ustream_write(void *ctx, const unsigned char *buf, size_t len)
77 {
78 struct ustream *s = ctx;
79 int ret;
80
81 ret = ustream_write(s, (const char *) buf, len, false);
82 if (ret < 0 || s->write_error)
83 return MBEDTLS_ERR_NET_SEND_FAILED;
84
85 return ret;
86 }
87
88 __hidden void ustream_set_io(struct ustream_ssl_ctx *ctx, void *ssl, struct ustream *conn)
89 {
90 mbedtls_ssl_set_bio(ssl, conn, s_ustream_write, s_ustream_read, NULL);
91 }
92
93 static int _random(void *ctx, unsigned char *out, size_t len)
94 {
95 #ifdef linux
96 if (getrandom(out, len, 0) != (ssize_t) len)
97 return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
98 #else
99 static FILE *f;
100
101 if (!f)
102 f = fopen("/dev/urandom", "r");
103 if (fread(out, len, 1, f) != 1)
104 return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
105 #endif
106
107 return 0;
108 }
109
110 #define AES_GCM_CIPHERS(v) \
111 MBEDTLS_TLS_##v##_WITH_AES_128_GCM_SHA256, \
112 MBEDTLS_TLS_##v##_WITH_AES_256_GCM_SHA384
113
114 #define AES_CBC_CIPHERS(v) \
115 MBEDTLS_TLS_##v##_WITH_AES_128_CBC_SHA, \
116 MBEDTLS_TLS_##v##_WITH_AES_256_CBC_SHA
117
118 #define AES_CIPHERS(v) \
119 AES_GCM_CIPHERS(v), \
120 AES_CBC_CIPHERS(v)
121
122 static const int default_ciphersuites_server[] =
123 {
124 #ifdef MBEDTLS_SSL_PROTO_TLS1_3
125 MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256,
126 MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
127 MBEDTLS_TLS1_3_AES_128_GCM_SHA256,
128 MBEDTLS_TLS1_3_AES_128_CCM_SHA256,
129 MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256,
130 #endif
131
132 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
133 AES_GCM_CIPHERS(ECDHE_ECDSA),
134 MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
135 AES_GCM_CIPHERS(ECDHE_RSA),
136 AES_CBC_CIPHERS(ECDHE_RSA),
137 AES_CIPHERS(RSA),
138 0
139 };
140
141 static const int default_ciphersuites_client[] =
142 {
143 #ifdef MBEDTLS_SSL_PROTO_TLS1_3
144 MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256,
145 MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
146 MBEDTLS_TLS1_3_AES_128_GCM_SHA256,
147 MBEDTLS_TLS1_3_AES_128_CCM_SHA256,
148 MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256,
149 #endif
150
151 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
152 AES_GCM_CIPHERS(ECDHE_ECDSA),
153 MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
154 AES_GCM_CIPHERS(ECDHE_RSA),
155 MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
156 AES_GCM_CIPHERS(DHE_RSA),
157 AES_CBC_CIPHERS(ECDHE_ECDSA),
158 AES_CBC_CIPHERS(ECDHE_RSA),
159 AES_CBC_CIPHERS(DHE_RSA),
160 /* Removed in Mbed TLS 3.0.0 */
161 #ifdef MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
162 MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
163 #endif
164 AES_CIPHERS(RSA),
165 /* Removed in Mbed TLS 3.0.0 */
166 #ifdef MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
167 MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
168 #endif
169 0
170 };
171
172
173 __hidden struct ustream_ssl_ctx *
174 __ustream_ssl_context_new(bool server)
175 {
176 struct ustream_ssl_ctx *ctx;
177 mbedtls_ssl_config *conf;
178 int ep;
179
180 #ifdef MBEDTLS_PSA_CRYPTO_C
181 static bool psa_init;
182
183 if (!psa_init && !psa_crypto_init())
184 psa_init = true;
185 #endif
186
187 ctx = calloc(1, sizeof(*ctx));
188 if (!ctx)
189 return NULL;
190
191 ctx->server = server;
192 mbedtls_pk_init(&ctx->key);
193 mbedtls_x509_crt_init(&ctx->cert);
194 mbedtls_x509_crt_init(&ctx->ca_cert);
195
196 #if defined(MBEDTLS_SSL_CACHE_C)
197 mbedtls_ssl_cache_init(&ctx->cache);
198 mbedtls_ssl_cache_set_timeout(&ctx->cache, 30 * 60);
199 mbedtls_ssl_cache_set_max_entries(&ctx->cache, 5);
200 #endif
201
202 conf = &ctx->conf;
203 mbedtls_ssl_config_init(conf);
204
205 ep = server ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT;
206
207 mbedtls_ssl_config_defaults(conf, ep, MBEDTLS_SSL_TRANSPORT_STREAM,
208 MBEDTLS_SSL_PRESET_DEFAULT);
209 mbedtls_ssl_conf_rng(conf, _random, NULL);
210
211 if (server) {
212 mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_NONE);
213 mbedtls_ssl_conf_ciphersuites(conf, default_ciphersuites_server);
214 mbedtls_ssl_conf_min_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3,
215 MBEDTLS_SSL_MINOR_VERSION_3);
216 } else {
217 mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
218 mbedtls_ssl_conf_ciphersuites(conf, default_ciphersuites_client);
219 }
220
221 #if defined(MBEDTLS_SSL_CACHE_C)
222 mbedtls_ssl_conf_session_cache(conf, &ctx->cache,
223 mbedtls_ssl_cache_get,
224 mbedtls_ssl_cache_set);
225 #endif
226 return ctx;
227 }
228
229 static void ustream_ssl_update_own_cert(struct ustream_ssl_ctx *ctx)
230 {
231 if (!ctx->cert.version)
232 return;
233
234 if (mbedtls_pk_get_type(&ctx->key) == MBEDTLS_PK_NONE)
235 return;
236
237 mbedtls_ssl_conf_own_cert(&ctx->conf, &ctx->cert, &ctx->key);
238 }
239
240 __hidden int __ustream_ssl_add_ca_crt_file(struct ustream_ssl_ctx *ctx, const char *file)
241 {
242 int ret;
243
244 ret = mbedtls_x509_crt_parse_file(&ctx->ca_cert, file);
245 if (ret)
246 return -1;
247
248 mbedtls_ssl_conf_ca_chain(&ctx->conf, &ctx->ca_cert, NULL);
249 mbedtls_ssl_conf_authmode(&ctx->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
250 return 0;
251 }
252
253 __hidden int __ustream_ssl_set_crt_file(struct ustream_ssl_ctx *ctx, const char *file)
254 {
255 int ret;
256
257 ret = mbedtls_x509_crt_parse_file(&ctx->cert, file);
258 if (ret)
259 return -1;
260
261 ustream_ssl_update_own_cert(ctx);
262 return 0;
263 }
264
265 __hidden int __ustream_ssl_set_key_file(struct ustream_ssl_ctx *ctx, const char *file)
266 {
267 int ret;
268
269 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
270 ret = mbedtls_pk_parse_keyfile(&ctx->key, file, NULL, _random, NULL);
271 #else
272 ret = mbedtls_pk_parse_keyfile(&ctx->key, file, NULL);
273 #endif
274 if (ret)
275 return -1;
276
277 ustream_ssl_update_own_cert(ctx);
278 return 0;
279 }
280
281 __hidden int __ustream_ssl_set_ciphers(struct ustream_ssl_ctx *ctx, const char *ciphers)
282 {
283 int *ciphersuites = NULL, *tmp, id;
284 char *cipherstr, *p, *last, c;
285 size_t len = 0;
286
287 if (ciphers == NULL)
288 return -1;
289
290 cipherstr = strdup(ciphers);
291
292 if (cipherstr == NULL)
293 return -1;
294
295 for (p = cipherstr, last = p;; p++) {
296 if (*p == ':' || *p == 0) {
297 c = *p;
298 *p = 0;
299
300 id = mbedtls_ssl_get_ciphersuite_id(last);
301
302 if (id != 0) {
303 tmp = realloc(ciphersuites, (len + 2) * sizeof(int));
304
305 if (tmp == NULL) {
306 free(ciphersuites);
307 free(cipherstr);
308
309 return -1;
310 }
311
312 ciphersuites = tmp;
313 ciphersuites[len++] = id;
314 ciphersuites[len] = 0;
315 }
316
317 if (c == 0)
318 break;
319
320 last = p + 1;
321 }
322
323 /*
324 * mbedTLS expects cipher names with dashes while many sources elsewhere
325 * like the Firefox wiki or Wireshark specify ciphers with underscores,
326 * so simply convert all underscores to dashes to accept both notations.
327 */
328 else if (*p == '_') {
329 *p = '-';
330 }
331 }
332
333 free(cipherstr);
334
335 if (len == 0)
336 return -1;
337
338 mbedtls_ssl_conf_ciphersuites(&ctx->conf, ciphersuites);
339 free(ctx->ciphersuites);
340
341 ctx->ciphersuites = ciphersuites;
342
343 return 0;
344 }
345
346 __hidden int __ustream_ssl_set_require_validation(struct ustream_ssl_ctx *ctx, bool require)
347 {
348 int mode = MBEDTLS_SSL_VERIFY_OPTIONAL;
349
350 if (!require)
351 mode = MBEDTLS_SSL_VERIFY_NONE;
352
353 /* force TLS 1.2 when not requiring validation for now */
354 if (!require && !ctx->server)
355 mbedtls_ssl_conf_max_version(&ctx->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
356 MBEDTLS_SSL_MINOR_VERSION_3);
357 mbedtls_ssl_conf_authmode(&ctx->conf, mode);
358
359 return 0;
360 }
361
362 __hidden void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx)
363 {
364 free(ctx->session_data);
365 #if defined(MBEDTLS_SSL_CACHE_C)
366 mbedtls_ssl_cache_free(&ctx->cache);
367 #endif
368 mbedtls_pk_free(&ctx->key);
369 mbedtls_x509_crt_free(&ctx->ca_cert);
370 mbedtls_x509_crt_free(&ctx->cert);
371 mbedtls_ssl_config_free(&ctx->conf);
372 free(ctx->ciphersuites);
373 free(ctx);
374 }
375
376 static void ustream_ssl_error(struct ustream_ssl *us, int ret)
377 {
378 us->error = ret;
379 uloop_timeout_set(&us->error_timer, 0);
380 }
381
382 static void
383 __ustream_ssl_save_session(struct ustream_ssl *us)
384 {
385 struct ustream_ssl_ctx *ctx = us->ctx;
386 mbedtls_ssl_session sess;
387
388 if (ctx->server)
389 return;
390
391 free(ctx->session_data);
392 ctx->session_data = NULL;
393
394 mbedtls_ssl_session_init(&sess);
395 if (mbedtls_ssl_get_session(us->ssl, &sess) != 0)
396 return;
397
398 mbedtls_ssl_session_save(&sess, NULL, 0, &ctx->session_data_len);
399 ctx->session_data = malloc(ctx->session_data_len);
400 if (mbedtls_ssl_session_save(&sess, ctx->session_data, ctx->session_data_len,
401 &ctx->session_data_len))
402 ctx->session_data_len = 0;
403 mbedtls_ssl_session_free(&sess);
404 }
405
406 static int ssl_check_return(struct ustream_ssl *us, int ret)
407 {
408 switch(ret) {
409 case MBEDTLS_ERR_SSL_WANT_READ:
410 case MBEDTLS_ERR_SSL_WANT_WRITE:
411 return U_SSL_PENDING;
412 case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET:
413 #ifdef MBEDTLS_ECP_RESTARTABLE
414 case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
415 #endif
416 __ustream_ssl_save_session(us);
417 return U_SSL_RETRY;
418 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
419 case MBEDTLS_ERR_NET_CONN_RESET:
420 return 0;
421 default:
422 ustream_ssl_error(us, ret);
423 return U_SSL_ERROR;
424 }
425 }
426
427 static void ustream_ssl_verify_cert(struct ustream_ssl *us)
428 {
429 void *ssl = us->ssl;
430 const char *msg = NULL;
431 bool cn_mismatch;
432 int r;
433
434 r = mbedtls_ssl_get_verify_result(ssl);
435 cn_mismatch = r & MBEDTLS_X509_BADCERT_CN_MISMATCH;
436 r &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
437
438 if (r & MBEDTLS_X509_BADCERT_EXPIRED)
439 msg = "certificate has expired";
440 else if (r & MBEDTLS_X509_BADCERT_REVOKED)
441 msg = "certificate has been revoked";
442 else if (r & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
443 msg = "certificate is self-signed or not signed by a trusted CA";
444 else
445 msg = "unknown error";
446
447 if (r) {
448 if (us->notify_verify_error)
449 us->notify_verify_error(us, r, msg);
450 return;
451 }
452
453 if (!cn_mismatch)
454 us->valid_cn = true;
455 }
456
457 __hidden enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us)
458 {
459 void *ssl = us->ssl;
460 int r;
461
462 do {
463 r = mbedtls_ssl_handshake(ssl);
464 if (r == 0) {
465 ustream_ssl_verify_cert(us);
466 return U_SSL_OK;
467 }
468
469 r = ssl_check_return(us, r);
470 } while (r == U_SSL_RETRY);
471
472 return r;
473 }
474
475 __hidden int __ustream_ssl_write(struct ustream_ssl *us, const char *buf, int len)
476 {
477 void *ssl = us->ssl;
478 int done = 0, ret = 0;
479
480 while (done != len) {
481 ret = mbedtls_ssl_write(ssl, (const unsigned char *) buf + done, len - done);
482 if (ret < 0) {
483 ret = ssl_check_return(us, ret);
484 if (ret == U_SSL_RETRY)
485 continue;
486
487 if (ret == U_SSL_PENDING)
488 return done;
489
490 return -1;
491 }
492
493 done += ret;
494 }
495
496 return done;
497 }
498
499 __hidden int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len)
500 {
501 int ret;
502
503 do {
504 ret = mbedtls_ssl_read(us->ssl, (unsigned char *) buf, len);
505 if (ret >= 0)
506 return ret;
507
508 ret = ssl_check_return(us, ret);
509 } while (ret == U_SSL_RETRY);
510
511 return ret;
512 }
513
514 __hidden void __ustream_ssl_set_debug(struct ustream_ssl_ctx *ctx, int level,
515 ustream_ssl_debug_cb cb, void *cb_priv)
516 {
517 ctx->debug_cb = cb;
518 ctx->debug_cb_priv = cb_priv;
519 mbedtls_ssl_conf_dbg(&ctx->conf, debug_cb, ctx);
520 #ifdef MBEDTLS_DEBUG_C
521 mbedtls_debug_set_threshold(level);
522 #endif
523 }
524
525 __hidden void *__ustream_ssl_session_new(struct ustream_ssl_ctx *ctx)
526 {
527 mbedtls_ssl_context *ssl;
528 mbedtls_ssl_session sess;
529
530 ssl = calloc(1, sizeof(*ssl));
531 if (!ssl)
532 return NULL;
533
534 mbedtls_ssl_init(ssl);
535
536 if (mbedtls_ssl_setup(ssl, &ctx->conf)) {
537 free(ssl);
538 return NULL;
539 }
540
541 if (!ctx->session_data_len)
542 return ssl;
543
544 mbedtls_ssl_session_init(&sess);
545 if (mbedtls_ssl_session_load(&sess, ctx->session_data, ctx->session_data_len) == 0)
546 mbedtls_ssl_set_session(ssl, &sess);
547
548 return ssl;
549 }
550
551 __hidden void __ustream_ssl_session_free(void *ssl)
552 {
553 mbedtls_ssl_free(ssl);
554 free(ssl);
555 }