blob: 49eb8c1494410e23301c3c2502171280a76d5a02 [file] [log] [blame]
romanb00f4322024-04-04 09:26:18 +02001#define _GNU_SOURCE
2
romanc1124572024-04-23 15:08:06 +02003#include <ctype.h>
romanb00f4322024-04-04 09:26:18 +02004#include <dirent.h>
5#include <errno.h>
6#include <poll.h>
romanb00f4322024-04-04 09:26:18 +02007#include <stdint.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
roman008cfe72024-04-05 12:36:18 +020011#include <sys/stat.h>
romanb00f4322024-04-04 09:26:18 +020012#include <unistd.h>
13
14#include <curl/curl.h>
15
16#include "compat.h"
17#include "config.h"
18#include "log_p.h"
19#include "session.h"
20#include "session_p.h"
21#include "session_wrapper.h"
22
romanb00f4322024-04-04 09:26:18 +020023#include <mbedtls/base64.h>
roman008cfe72024-04-05 12:36:18 +020024#include <mbedtls/bignum.h>
25#include <mbedtls/ctr_drbg.h>
26#include <mbedtls/debug.h>
27#include <mbedtls/entropy.h>
28#include <mbedtls/error.h>
29#include <mbedtls/net_sockets.h>
30#include <mbedtls/oid.h>
31#include <mbedtls/pem.h>
32#include <mbedtls/ssl.h>
33#include <mbedtls/x509.h>
34#include <mbedtls/x509_crl.h>
35#include <mbedtls/x509_crt.h>
36#include <mbedtls/x509_csr.h>
romanb00f4322024-04-04 09:26:18 +020037
romanc1124572024-04-23 15:08:06 +020038/* some mbedTLS functions may return 'high' and some 'low' level errors, try to handle both cases this way */
39static const char *
40nc_get_mbedtls_str_err(int err)
41{
42 const char *err_str;
43
44 err_str = mbedtls_high_level_strerr(err);
45 if (err_str) {
46 return err_str;
47 }
48
49 err_str = mbedtls_low_level_strerr(err);
50 if (err_str) {
51 return err_str;
52 }
53
54 return "unknown error";
55}
56
57/**
58 * @brief Converts DN to a string.
59 *
60 * @param[in] dn Internal DN representation.
61 * @return DN string on success, NULL of fail.
62 */
63static char *
64nc_server_tls_dn2str(const mbedtls_x509_name *dn)
65{
66 char *str;
67 size_t len = 64;
68 int r;
69
70 str = malloc(len);
71 NC_CHECK_ERRMEM_RET(!str, NULL);
72
73 while ((r = mbedtls_x509_dn_gets(str, len, dn)) == MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) {
74 len <<= 1;
75 str = nc_realloc(str, len);
76 NC_CHECK_ERRMEM_RET(!str, NULL);
77 }
78 if (r < 1) {
79 free(str);
80 ERR(NULL, "Failed to convert DN to string (%s).", nc_get_mbedtls_str_err(r));
81 return NULL;
82 }
83
84 return str;
85}
86
87/* creates a new rng context needed for PK operations and for ssl config */
88static int
89nc_tls_rng_new(mbedtls_ctr_drbg_context **ctr_drbg, mbedtls_entropy_context **entropy)
90{
91 int rc;
92
93 *ctr_drbg = NULL;
94 *entropy = NULL;
95
96 *entropy = malloc(sizeof **entropy);
97 NC_CHECK_ERRMEM_GOTO(!*entropy, , fail);
98 *ctr_drbg = malloc(sizeof **ctr_drbg);
99 NC_CHECK_ERRMEM_GOTO(!*ctr_drbg, , fail);
100
101 mbedtls_entropy_init(*entropy);
102 mbedtls_ctr_drbg_init(*ctr_drbg);
103
104 rc = mbedtls_ctr_drbg_seed(*ctr_drbg, mbedtls_entropy_func, *entropy, NULL, 0);
105 if (rc) {
106 ERR(NULL, "Seeding ctr_drbg failed (%s).", nc_get_mbedtls_str_err(rc));
107 goto fail;
108 }
109
110 return 0;
111
112fail:
113 mbedtls_ctr_drbg_free(*ctr_drbg);
114 free(*ctr_drbg);
115 if (*entropy) {
116 mbedtls_entropy_free(*entropy);
117 free(*entropy);
118 }
119 *ctr_drbg = NULL;
120 *entropy = NULL;
121 return 1;
122}
123
124static void
125nc_tls_rng_destroy(mbedtls_ctr_drbg_context *ctr_drbg, mbedtls_entropy_context *entropy)
126{
127 mbedtls_ctr_drbg_free(ctr_drbg);
128 free(ctr_drbg);
129 if (entropy) {
130 mbedtls_entropy_free(entropy);
131 free(entropy);
132 }
133}
134
135/* get verify err string, caller is responsible for freeing it, 256B should be more than enough */
136static char *
137nc_tls_get_verify_err_str(int err)
138{
139 int ret;
140 char *err_buf = NULL;
141
142 err_buf = malloc(256);
143 NC_CHECK_ERRMEM_RET(!err_buf, NULL);
144
145 ret = mbedtls_x509_crt_verify_info(err_buf, 256, "", err);
146 if (ret < 0) {
147 free(err_buf);
148 return NULL;
149 }
150
151 /* strip the NL */
152 err_buf[ret - 1] = '\0';
153
154 return err_buf;
155}
romanb00f4322024-04-04 09:26:18 +0200156
157void *
158nc_tls_session_new_wrap(void *tls_cfg)
159{
160 int rc;
161 mbedtls_ssl_context *session;
162
163 session = malloc(sizeof *session);
164 NC_CHECK_ERRMEM_RET(!session, NULL);
165
166 mbedtls_ssl_init(session);
167
168 rc = mbedtls_ssl_setup(session, tls_cfg);
169 if (rc) {
romanc1124572024-04-23 15:08:06 +0200170 ERR(NULL, "Setting up TLS session failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200171 mbedtls_ssl_free(session);
172 free(session);
173 return NULL;
174 }
175
176 return session;
177}
178
179void
180nc_tls_session_destroy_wrap(void *tls_session)
181{
182 mbedtls_ssl_free(tls_session);
183 free(tls_session);
184}
185
186void *
romanc1124572024-04-23 15:08:06 +0200187nc_tls_config_new_wrap(int UNUSED(side))
romanb00f4322024-04-04 09:26:18 +0200188{
189 mbedtls_ssl_config *tls_cfg;
190
191 tls_cfg = malloc(sizeof *tls_cfg);
192 NC_CHECK_ERRMEM_RET(!tls_cfg, NULL);
193
194 mbedtls_ssl_config_init(tls_cfg);
195 return tls_cfg;
196}
197
198void
199nc_tls_config_destroy_wrap(void *tls_cfg)
200{
201 if (!tls_cfg) {
202 return;
203 }
204
205 mbedtls_ssl_config_free(tls_cfg);
206 free(tls_cfg);
207}
208
209void *
210nc_tls_cert_new_wrap()
211{
212 mbedtls_x509_crt *cert;
213
214 cert = malloc(sizeof *cert);
215 NC_CHECK_ERRMEM_RET(!cert, NULL);
216
217 mbedtls_x509_crt_init(cert);
218 return cert;
219}
220
221void
222nc_tls_cert_destroy_wrap(void *cert)
223{
224 mbedtls_x509_crt_free(cert);
225 free(cert);
226}
227
romanc1124572024-04-23 15:08:06 +0200228static void *
229nc_tls_pkey_new_wrap(void)
romanb00f4322024-04-04 09:26:18 +0200230{
231 mbedtls_pk_context *pkey;
232
233 pkey = malloc(sizeof *pkey);
234 NC_CHECK_ERRMEM_RET(!pkey, NULL);
235
236 mbedtls_pk_init(pkey);
237 return pkey;
238}
239
240void
241nc_tls_privkey_destroy_wrap(void *pkey)
242{
243 mbedtls_pk_free(pkey);
244 free(pkey);
245}
246
247void *
248nc_tls_cert_store_new_wrap()
249{
romanc1124572024-04-23 15:08:06 +0200250 /* certificate is the same as a certificate store in MbedTLS */
romanb00f4322024-04-04 09:26:18 +0200251 return nc_tls_cert_new_wrap();
252}
253
254void
255nc_tls_cert_store_destroy_wrap(void *cert_store)
256{
romanc1124572024-04-23 15:08:06 +0200257 /* certificate is the same as a certificate store in MbedTLS */
romanb00f4322024-04-04 09:26:18 +0200258 nc_tls_cert_destroy_wrap(cert_store);
259}
260
261void *
262nc_tls_crl_store_new_wrap()
263{
264 mbedtls_x509_crl *crl;
265
266 crl = malloc(sizeof *crl);
267 NC_CHECK_ERRMEM_RET(!crl, NULL);
268
269 mbedtls_x509_crl_init(crl);
270 return crl;
271}
272
273void
romanc1124572024-04-23 15:08:06 +0200274nc_tls_crl_store_destroy_wrap(void *crl_store)
romanb00f4322024-04-04 09:26:18 +0200275{
romanc1124572024-04-23 15:08:06 +0200276 mbedtls_x509_crl_free(crl_store);
277 free(crl_store);
romanb00f4322024-04-04 09:26:18 +0200278}
279
280void *
281nc_tls_pem_to_cert_wrap(const char *cert_data)
282{
283 int rc;
284 mbedtls_x509_crt *cert;
285
286 cert = nc_tls_cert_new_wrap();
287 if (!cert) {
288 return NULL;
289 }
290
291 rc = mbedtls_x509_crt_parse(cert, (const unsigned char *)cert_data, strlen(cert_data) + 1);
292 if (rc) {
romanc1124572024-04-23 15:08:06 +0200293 ERR(NULL, "Parsing certificate data failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200294 nc_tls_cert_destroy_wrap(cert);
295 return NULL;
296 }
297
298 return cert;
299}
300
301int
romanc1124572024-04-23 15:08:06 +0200302nc_tls_add_cert_to_store_wrap(void *cert, void *cert_store)
romanb00f4322024-04-04 09:26:18 +0200303{
romanc1124572024-04-23 15:08:06 +0200304 mbedtls_x509_crt *iter;
romanb00f4322024-04-04 09:26:18 +0200305
romanc1124572024-04-23 15:08:06 +0200306 /* store is a linked list */
307 iter = cert_store;
308 while (iter->next) {
309 iter = iter->next;
romanb00f4322024-04-04 09:26:18 +0200310 }
romanc1124572024-04-23 15:08:06 +0200311 iter->next = cert;
romanb00f4322024-04-04 09:26:18 +0200312
313 return 0;
314}
315
316void *
317nc_tls_pem_to_privkey_wrap(const char *privkey_data)
318{
romanc1124572024-04-23 15:08:06 +0200319 int rc, ret = 0;
320 mbedtls_pk_context *pkey = NULL;
321 mbedtls_ctr_drbg_context *ctr_drbg = NULL;
322 mbedtls_entropy_context *entropy = NULL;
romanb00f4322024-04-04 09:26:18 +0200323
romanc1124572024-04-23 15:08:06 +0200324 ret = nc_tls_rng_new(&ctr_drbg, &entropy);
325 if (ret) {
326 goto cleanup;
romanb00f4322024-04-04 09:26:18 +0200327 }
328
romanc1124572024-04-23 15:08:06 +0200329 pkey = nc_tls_pkey_new_wrap();
romanb00f4322024-04-04 09:26:18 +0200330 if (!pkey) {
romanc1124572024-04-23 15:08:06 +0200331 ret = 1;
332 goto cleanup;
romanb00f4322024-04-04 09:26:18 +0200333 }
334
335 rc = mbedtls_pk_parse_key(pkey, (const unsigned char *)privkey_data, strlen(privkey_data) + 1, NULL, 0, mbedtls_ctr_drbg_random, ctr_drbg);
romanb00f4322024-04-04 09:26:18 +0200336 if (rc) {
romanc1124572024-04-23 15:08:06 +0200337 ERR(NULL, "Parsing private key data failed (%s).", nc_get_mbedtls_str_err(rc));
338 ret = 1;
339 goto cleanup;
romanb00f4322024-04-04 09:26:18 +0200340 }
romanc1124572024-04-23 15:08:06 +0200341
342cleanup:
343 if (ret) {
344 nc_tls_privkey_destroy_wrap(pkey);
345 }
346 nc_tls_rng_destroy(ctr_drbg, entropy);
romanb00f4322024-04-04 09:26:18 +0200347 return pkey;
348}
349
350int
romanc1124572024-04-23 15:08:06 +0200351nc_tls_import_crl_path_wrap(const char *path, void *crl_store)
romanb00f4322024-04-04 09:26:18 +0200352{
353 int rc;
354
romanc1124572024-04-23 15:08:06 +0200355 rc = mbedtls_x509_crl_parse_file(crl_store, path);
romanb00f4322024-04-04 09:26:18 +0200356 if (rc) {
romanc1124572024-04-23 15:08:06 +0200357 ERR(NULL, "Failed to import CRL from file \"%s\" (%s).", path, nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200358 return 1;
359 }
360
361 return 0;
362}
363
364int
romanc1124572024-04-23 15:08:06 +0200365nc_server_tls_add_crl_to_store_wrap(const unsigned char *crl_data, size_t size, void *crl_store)
romanb00f4322024-04-04 09:26:18 +0200366{
367 int rc;
368
romanb00f4322024-04-04 09:26:18 +0200369 /* try DER first */
370 rc = mbedtls_x509_crl_parse_der(crl_store, crl_data, size);
371 if (!rc) {
372 /* success, it was DER */
373 return 0;
374 }
375
376 /* DER failed, try PEM */
romanc1124572024-04-23 15:08:06 +0200377 rc = mbedtls_x509_crl_parse(crl_store, crl_data, size + 1);
romanb00f4322024-04-04 09:26:18 +0200378 if (!rc) {
379 /* success, it was PEM */
380 return 0;
381 }
382
383 /* failed to parse it */
384 ERR(NULL, "Reading downloaded CRL failed.");
385 return 1;
386}
387
romanb00f4322024-04-04 09:26:18 +0200388int
389nc_server_tls_set_tls_versions_wrap(void *tls_cfg, unsigned int tls_versions)
390{
391 if ((tls_versions & NC_TLS_VERSION_10) || ((tls_versions & NC_TLS_VERSION_11))) {
392 /* skip TLS versions 1.0 and 1.1 */
393 WRN(NULL, "mbedTLS does not support TLS1.0 and TLS1.1");
394 }
395
396 /* first set the minimum version */
397 if (tls_versions & NC_TLS_VERSION_12) {
398 mbedtls_ssl_conf_min_tls_version(tls_cfg, MBEDTLS_SSL_VERSION_TLS1_2);
399 } else if (tls_versions & NC_TLS_VERSION_13) {
400 mbedtls_ssl_conf_min_tls_version(tls_cfg, MBEDTLS_SSL_VERSION_TLS1_3);
401 }
402
403 /* then set the maximum version */
404 if (tls_versions & NC_TLS_VERSION_13) {
405 mbedtls_ssl_conf_max_tls_version(tls_cfg, MBEDTLS_SSL_VERSION_TLS1_3);
406 } else if (tls_versions & NC_TLS_VERSION_12) {
407 mbedtls_ssl_conf_max_tls_version(tls_cfg, MBEDTLS_SSL_VERSION_TLS1_2);
408 }
409
410 return 0;
411}
412
413static int
414nc_server_tls_verify_cb(void *cb_data, mbedtls_x509_crt *cert, int depth, uint32_t *flags)
415{
416 int ret = 0;
417 struct nc_tls_verify_cb_data *data = cb_data;
romanc1124572024-04-23 15:08:06 +0200418 char *err;
romanb00f4322024-04-04 09:26:18 +0200419
420 if (!*flags) {
421 /* in-built verification was successful */
422 ret = nc_server_tls_verify_cert(cert, depth, 0, data);
423 } else {
romanc1124572024-04-23 15:08:06 +0200424 /* in-built verification failed, but the client still may be authenticated if:
425 * 1) the peer cert matches any configured end-entity cert
426 * 2) the peer cert has a valid chain of trust to any configured certificate authority cert
427 * otherwise just continue until we reach the peer cert (depth = 0)
romanb00f4322024-04-04 09:26:18 +0200428 */
429 if ((depth == 0) && (*flags == MBEDTLS_X509_BADCERT_NOT_TRUSTED)) {
romanc1124572024-04-23 15:08:06 +0200430 /* not trusted self-signed peer certificate, case 1) */
romanb00f4322024-04-04 09:26:18 +0200431 ret = nc_server_tls_verify_cert(cert, depth, 1, data);
432 if (!ret) {
433 *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
434 }
romanc1124572024-04-23 15:08:06 +0200435 } else if (*flags == MBEDTLS_X509_BADCERT_MISSING) {
436 /* full chain of trust is invalid, but it may be valid partially, case 2) */
437 ret = nc_server_tls_verify_cert(cert, depth, 1, data);
438 if (!ret) {
439 *flags &= ~MBEDTLS_X509_BADCERT_MISSING;
romanb00f4322024-04-04 09:26:18 +0200440 }
romanc1124572024-04-23 15:08:06 +0200441 } else {
442 err = nc_tls_get_verify_err_str(*flags);
443 ERR(data->session, "Cert verify: fail (%s).", err);
444 free(err);
romanb00f4322024-04-04 09:26:18 +0200445 ret = 1;
446 }
447 }
448
449 if (ret == -1) {
450 /* fatal error */
451 return MBEDTLS_ERR_X509_ALLOC_FAILED;
452 } else if (!ret) {
453 /* success */
454 return 0;
455 } else {
456 if (depth > 0) {
457 /* chain verify failed, but peer cert can still match */
458 return 0;
459 } else {
romanc1124572024-04-23 15:08:06 +0200460 /* failed to verify peer cert, but return 0 so that we can propagate the error via the flags */
461 if (!*flags) {
462 *flags |= MBEDTLS_X509_BADCERT_OTHER;
463 }
464 return 0;
romanb00f4322024-04-04 09:26:18 +0200465 }
466 }
467}
468
469void
romanc1124572024-04-23 15:08:06 +0200470nc_server_tls_set_verify_wrap(void *tls_cfg, struct nc_tls_verify_cb_data *cb_data)
romanb00f4322024-04-04 09:26:18 +0200471{
romanc1124572024-04-23 15:08:06 +0200472 mbedtls_ssl_conf_authmode(tls_cfg, MBEDTLS_SSL_VERIFY_REQUIRED);
473 mbedtls_ssl_conf_verify(tls_cfg, nc_server_tls_verify_cb, cb_data);
romanb00f4322024-04-04 09:26:18 +0200474}
475
romanc1124572024-04-23 15:08:06 +0200476void
477nc_client_tls_set_verify_wrap(void *tls_cfg)
romanb00f4322024-04-04 09:26:18 +0200478{
romanc1124572024-04-23 15:08:06 +0200479 mbedtls_ssl_conf_authmode(tls_cfg, MBEDTLS_SSL_VERIFY_REQUIRED);
romanb00f4322024-04-04 09:26:18 +0200480}
481
482char *
483nc_server_tls_get_subject_wrap(void *cert)
484{
485 return nc_server_tls_dn2str(&(((mbedtls_x509_crt *)cert)->subject));
486}
487
488char *
489nc_server_tls_get_issuer_wrap(void *cert)
490{
491 return nc_server_tls_dn2str(&(((mbedtls_x509_crt *)cert)->issuer));
492}
493
romanc1124572024-04-23 15:08:06 +0200494void *
495nc_tls_get_sans_wrap(void *cert)
romanb00f4322024-04-04 09:26:18 +0200496{
romanc1124572024-04-23 15:08:06 +0200497 return &(((mbedtls_x509_crt *)cert)->subject_alt_names);
498}
romanb00f4322024-04-04 09:26:18 +0200499
romanc1124572024-04-23 15:08:06 +0200500void
501nc_tls_sans_destroy_wrap(void *UNUSED(sans))
502{
503 return;
504}
romanb00f4322024-04-04 09:26:18 +0200505
romanc1124572024-04-23 15:08:06 +0200506int
507nc_tls_get_num_sans_wrap(void *sans)
508{
509 mbedtls_x509_sequence *iter;
510 int n = 0;
romanb00f4322024-04-04 09:26:18 +0200511
romanc1124572024-04-23 15:08:06 +0200512 /* sans are a linked list */
513 iter = sans;
514 while (iter) {
515 ++n;
516 iter = iter->next;
romanb00f4322024-04-04 09:26:18 +0200517 }
518
romanc1124572024-04-23 15:08:06 +0200519 return n;
520}
521
522int
523nc_tls_get_san_value_type_wrap(void *sans, int idx, char **san_value, NC_TLS_CTN_MAPTYPE *san_type)
524{
525 int i, rc, ret = 0;
526 mbedtls_x509_sequence *iter;
527 mbedtls_x509_subject_alternative_name san = {0};
528 const mbedtls_x509_buf *ip;
529
530 *san_value = NULL;
531 *san_type = NC_TLS_CTN_UNKNOWN;
532
533 /* find the SAN */
534 iter = sans;
535 for (i = 0; i < idx; i++) {
536 iter = iter->next;
537 }
538
539 /* parse it */
540 rc = mbedtls_x509_parse_subject_alt_name(&iter->buf, &san);
541 if (rc && (rc != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE)) {
542 return -1;
543 }
544
545 /* get its type and value */
546 switch (san.type) {
547 case MBEDTLS_X509_SAN_DNS_NAME:
548 *san_type = NC_TLS_CTN_SAN_DNS_NAME;
549 *san_value = strndup((const char *)san.san.unstructured_name.p, san.san.unstructured_name.len);
550 NC_CHECK_ERRMEM_GOTO(!*san_value, ret = -1, cleanup);
551 break;
552 case MBEDTLS_X509_SAN_RFC822_NAME:
553 *san_type = NC_TLS_CTN_SAN_RFC822_NAME;
554 *san_value = strndup((const char *)san.san.unstructured_name.p, san.san.unstructured_name.len);
555 NC_CHECK_ERRMEM_GOTO(!*san_value, ret = -1, cleanup);
556 break;
557 case MBEDTLS_X509_SAN_IP_ADDRESS:
558 *san_type = NC_TLS_CTN_SAN_IP_ADDRESS;
559 ip = &san.san.unstructured_name;
560 if (ip->len == 4) {
561 rc = asprintf(san_value, "%d.%d.%d.%d", ip->p[0], ip->p[1], ip->p[2], ip->p[3]) == -1;
562 NC_CHECK_ERRMEM_GOTO(rc == -1, ret = -1, cleanup);
563 } else if (ip->len == 16) {
564 rc = asprintf(san_value, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
565 ip->p[0], ip->p[1], ip->p[2], ip->p[3], ip->p[4], ip->p[5],
566 ip->p[6], ip->p[7], ip->p[8], ip->p[9], ip->p[10], ip->p[11],
567 ip->p[12], ip->p[13], ip->p[14], ip->p[15]);
568 NC_CHECK_ERRMEM_GOTO(rc == -1, ret = -1, cleanup);
569 } else {
570 WRN(NULL, "SAN IP address in an unknown format (length is %d).", ip->len);
571 ret = 1;
572 }
573 break;
574 default:
575 /* we dont care about other types */
576 *san_type = NC_TLS_CTN_UNKNOWN;
577 ret = 1;
578 break;
579 }
580
581cleanup:
582 mbedtls_x509_free_subject_alt_name(&san);
583 return ret;
romanb00f4322024-04-04 09:26:18 +0200584}
585
586int
587nc_server_tls_certs_match_wrap(void *cert1, void *cert2)
588{
589 mbedtls_x509_crt *c1 = cert1;
590 mbedtls_x509_crt *c2 = cert2;
591
592 if (!c1 || !c2) {
593 return 0;
594 }
595
596 /* compare raw DER encoded data */
597 if (!c1->raw.p || !c2->raw.p || (c1->raw.len != c2->raw.len) ||
598 memcmp(c1->raw.p, c2->raw.p, c1->raw.len)) {
599 return 0;
600 }
601
602 return 1;
603}
604
605int
606nc_server_tls_md5_wrap(void *cert, unsigned char *buf)
607{
608 int rc;
609 mbedtls_x509_crt *c = cert;
610
611 rc = mbedtls_md5(c->raw.p, c->raw.len, buf);
612 if (rc) {
romanc1124572024-04-23 15:08:06 +0200613 ERR(NULL, "Calculating MD5 digest failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200614 return 1;
615 }
616
617 return 0;
618}
619
620int
621nc_server_tls_sha1_wrap(void *cert, unsigned char *buf)
622{
623 int rc;
624 mbedtls_x509_crt *c = cert;
625
626 rc = mbedtls_sha1(c->raw.p, c->raw.len, buf);
627 if (rc) {
romanc1124572024-04-23 15:08:06 +0200628 ERR(NULL, "Calculating SHA-1 digest failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200629 return 1;
630 }
631
632 return 0;
633}
634
635int
636nc_server_tls_sha224_wrap(void *cert, unsigned char *buf)
637{
638 int rc;
639 mbedtls_x509_crt *c = cert;
640
641 rc = mbedtls_sha256(c->raw.p, c->raw.len, buf, 1);
642 if (rc) {
romanc1124572024-04-23 15:08:06 +0200643 ERR(NULL, "Calculating SHA-224 digest failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200644 return 1;
645 }
646
647 return 0;
648}
649
650int
651nc_server_tls_sha256_wrap(void *cert, unsigned char *buf)
652{
653 int rc;
654 mbedtls_x509_crt *c = cert;
655
656 rc = mbedtls_sha256(c->raw.p, c->raw.len, buf, 0);
657 if (rc) {
romanc1124572024-04-23 15:08:06 +0200658 ERR(NULL, "Calculating SHA-256 digest failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200659 return 1;
660 }
661
662 return 0;
663}
664
665int
666nc_server_tls_sha384_wrap(void *cert, unsigned char *buf)
667{
668 int rc;
669 mbedtls_x509_crt *c = cert;
670
671 rc = mbedtls_sha512(c->raw.p, c->raw.len, buf, 1);
672 if (rc) {
romanc1124572024-04-23 15:08:06 +0200673 ERR(NULL, "Calculating SHA-384 digest failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200674 return 1;
675 }
676
677 return 0;
678}
679
680int
681nc_server_tls_sha512_wrap(void *cert, unsigned char *buf)
682{
683 int rc;
684 mbedtls_x509_crt *c = cert;
685
686 rc = mbedtls_sha512(c->raw.p, c->raw.len, buf, 0);
687 if (rc) {
romanc1124572024-04-23 15:08:06 +0200688 ERR(NULL, "Calculating SHA-512 digest failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200689 return 1;
690 }
691
692 return 0;
693}
694
romanc1124572024-04-23 15:08:06 +0200695static int
696nc_server_tls_send(void *ctx, const unsigned char *buf, size_t len)
697{
698 int sock, ret;
699
700 NC_CHECK_ARG_RET(NULL, ctx, MBEDTLS_ERR_NET_INVALID_CONTEXT);
701
702 sock = *(int *)ctx;
703
704 ret = send(sock, buf, len, MSG_NOSIGNAL);
705 if (ret < 0) {
706 if ((errno == EWOULDBLOCK) || (errno = EAGAIN) || (errno == EINTR)) {
707 return MBEDTLS_ERR_SSL_WANT_WRITE;
708 } else if ((errno == EPIPE) || (errno == ECONNRESET)) {
709 return MBEDTLS_ERR_NET_CONN_RESET;
710 } else {
711 return MBEDTLS_ERR_NET_SEND_FAILED;
712 }
713 }
714
715 return ret;
716}
717
718static int
719nc_server_tls_recv(void *ctx, unsigned char *buf, size_t len)
720{
721 int sock, ret;
722
723 NC_CHECK_ARG_RET(NULL, ctx, MBEDTLS_ERR_NET_INVALID_CONTEXT);
724
725 sock = *(int *)ctx;
726
727 ret = recv(sock, buf, len, 0);
728 if (ret < 0) {
729 if ((errno == EWOULDBLOCK) || (errno = EAGAIN) || (errno == EINTR)) {
730 return MBEDTLS_ERR_SSL_WANT_READ;
731 } else if ((errno == EPIPE) || (errno == ECONNRESET)) {
732 return MBEDTLS_ERR_NET_CONN_RESET;
733 } else {
734 return MBEDTLS_ERR_NET_RECV_FAILED;
735 }
736 }
737
738 return ret;
739}
740
romanb00f4322024-04-04 09:26:18 +0200741void
742nc_server_tls_set_fd_wrap(void *tls_session, int UNUSED(sock), struct nc_tls_ctx *tls_ctx)
743{
romanc1124572024-04-23 15:08:06 +0200744 /* mbedtls sets a pointer to the sock, which is stored in tls_ctx */
745 mbedtls_ssl_set_bio(tls_session, tls_ctx->sock, nc_server_tls_send, nc_server_tls_recv, NULL);
romanb00f4322024-04-04 09:26:18 +0200746}
747
748int
749nc_server_tls_handshake_step_wrap(void *tls_session)
750{
751 int rc = 0;
752
753 rc = mbedtls_ssl_handshake(tls_session);
754 if (!rc) {
755 return 1;
roman008cfe72024-04-05 12:36:18 +0200756 } else if ((rc == MBEDTLS_ERR_SSL_WANT_READ) || (rc == MBEDTLS_ERR_SSL_WANT_WRITE)) {
romanb00f4322024-04-04 09:26:18 +0200757 return 0;
758 } else {
romanc1124572024-04-23 15:08:06 +0200759 return rc;
romanb00f4322024-04-04 09:26:18 +0200760 }
761}
762
763int
romanc1124572024-04-23 15:08:06 +0200764nc_client_tls_handshake_step_wrap(void *tls_session, int sock)
romanb00f4322024-04-04 09:26:18 +0200765{
romanc1124572024-04-23 15:08:06 +0200766 int rc = 0;
767 struct pollfd pfd = {sock, 0, 0};
romanb00f4322024-04-04 09:26:18 +0200768
romanc1124572024-04-23 15:08:06 +0200769 rc = mbedtls_ssl_handshake(tls_session);
770 if (!rc) {
romanb00f4322024-04-04 09:26:18 +0200771 return 1;
romanc1124572024-04-23 15:08:06 +0200772 } else if ((rc == MBEDTLS_ERR_SSL_WANT_READ) || (rc == MBEDTLS_ERR_SSL_WANT_WRITE)) {
773 /* check for EPIPE */
774 if (poll(&pfd, 1, 0) < 0) {
775 return -1;
776 } else {
777 if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
778 return -1;
779 } else {
780 return 0;
781 }
782 }
783 } else {
784 return rc;
romanb00f4322024-04-04 09:26:18 +0200785 }
romanb00f4322024-04-04 09:26:18 +0200786}
787
788void
789nc_tls_ctx_destroy_wrap(struct nc_tls_ctx *tls_ctx)
790{
romanc1124572024-04-23 15:08:06 +0200791 nc_tls_rng_destroy(tls_ctx->ctr_drbg, tls_ctx->entropy);
romanb00f4322024-04-04 09:26:18 +0200792 nc_tls_cert_destroy_wrap(tls_ctx->cert);
793 nc_tls_privkey_destroy_wrap(tls_ctx->pkey);
794 nc_tls_cert_store_destroy_wrap(tls_ctx->cert_store);
795 nc_tls_crl_store_destroy_wrap(tls_ctx->crl_store);
796 free(tls_ctx->sock);
797}
798
romanc1124572024-04-23 15:08:06 +0200799void *
800nc_tls_import_privkey_file_wrap(const char *privkey_path)
romanb00f4322024-04-04 09:26:18 +0200801{
802 int rc;
803 mbedtls_pk_context *pkey;
804 mbedtls_ctr_drbg_context *ctr_drbg;
805 mbedtls_entropy_context *entropy;
806
807 if (nc_tls_rng_new(&ctr_drbg, &entropy)) {
808 return NULL;
809 }
810
romanc1124572024-04-23 15:08:06 +0200811 pkey = nc_tls_pkey_new_wrap();
romanb00f4322024-04-04 09:26:18 +0200812 if (!pkey) {
813 nc_tls_rng_destroy(ctr_drbg, entropy);
814 return NULL;
815 }
816
817 rc = mbedtls_pk_parse_keyfile(pkey, privkey_path, NULL, mbedtls_ctr_drbg_random, ctr_drbg);
818 nc_tls_rng_destroy(ctr_drbg, entropy);
819 if (rc) {
romanc1124572024-04-23 15:08:06 +0200820 ERR(NULL, "Parsing private key from file \"%s\" failed (%s).", privkey_path, nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200821 nc_tls_privkey_destroy_wrap(pkey);
822 return NULL;
823 }
824 return pkey;
825}
826
romanb00f4322024-04-04 09:26:18 +0200827int
828nc_client_tls_load_cert_key_wrap(const char *cert_path, const char *key_path, void **cert, void **pkey)
829{
830 int ret = 0;
831 mbedtls_x509_crt *c;
832 mbedtls_pk_context *pk;
romanc1124572024-04-23 15:08:06 +0200833
834 NC_CHECK_ARG_RET(NULL, cert_path, key_path, cert, pkey, 1);
romanb00f4322024-04-04 09:26:18 +0200835
836 c = nc_tls_cert_new_wrap();
837 if (!c) {
838 return 1;
839 }
840
841 ret = mbedtls_x509_crt_parse_file(c, cert_path);
842 if (ret) {
romanc1124572024-04-23 15:08:06 +0200843 ERR(NULL, "Parsing certificate from file \"%s\" failed (%s).", cert_path, nc_get_mbedtls_str_err(ret));
romanb00f4322024-04-04 09:26:18 +0200844 goto cleanup;
845 }
846
romanc1124572024-04-23 15:08:06 +0200847 pk = nc_tls_import_privkey_file_wrap(key_path);
848 if (!pk) {
849 ret = 1;
850 goto cleanup;
romanb00f4322024-04-04 09:26:18 +0200851 }
852
853 *cert = c;
854 *pkey = pk;
855
856cleanup:
857 return ret;
858}
859
860int
861nc_client_tls_load_trusted_certs_wrap(void *cert_store, const char *file_path, const char *dir_path)
862{
863 int rc;
864
865 if (file_path && ((rc = mbedtls_x509_crt_parse_file(cert_store, file_path)) < 0)) {
romanc1124572024-04-23 15:08:06 +0200866 ERR(NULL, "Loading CA certificate from file \"%s\" failed (%s).", file_path, nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200867 return 1;
868 }
869
870 if (dir_path && ((rc = mbedtls_x509_crt_parse_path(cert_store, dir_path)) < 0)) {
romanc1124572024-04-23 15:08:06 +0200871 ERR(NULL, "Loading CA certificate from directory \"%s\" failed (%s).", dir_path, nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200872 return 1;
873 }
874
875 return 0;
876}
877
878int
romanc1124572024-04-23 15:08:06 +0200879nc_client_tls_load_crl_wrap(void *crl_store, const char *file_path, const char *dir_path)
romanb00f4322024-04-04 09:26:18 +0200880{
romanc1124572024-04-23 15:08:06 +0200881 int rc, ret = 0;
882 DIR *dir = NULL;
romanb00f4322024-04-04 09:26:18 +0200883 struct dirent *entry;
884 struct stat st = {0};
romanc1124572024-04-23 15:08:06 +0200885 char *path = NULL;
romanb00f4322024-04-04 09:26:18 +0200886
887 if (file_path && (rc = mbedtls_x509_crl_parse_file(crl_store, file_path))) {
romanc1124572024-04-23 15:08:06 +0200888 ERR(NULL, "Loading CRL from file \"%s\" failed (%s).", file_path, nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200889 return 1;
890 }
891
892 if (dir_path) {
893 /* parse the CRLs in the directory one by one */
894 dir = opendir(dir_path);
895 if (!dir) {
896 ERR(NULL, "Failed to open directory \"%s\" (%s).", dir_path, strerror(errno));
romanc1124572024-04-23 15:08:06 +0200897 return 1;
romanb00f4322024-04-04 09:26:18 +0200898 }
899
900 while ((entry = readdir(dir))) {
901 if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
902 /* skip current and parent directory */
903 continue;
904 }
905
romanc1124572024-04-23 15:08:06 +0200906 rc = asprintf(&path, "%s/%s", dir_path, entry->d_name);
907 NC_CHECK_ERRMEM_GOTO(rc == -1, ret = 1; path = NULL, cleanup);
romanb00f4322024-04-04 09:26:18 +0200908
909 if (stat(path, &st) == -1) {
910 if (errno == ENOENT) {
911 /* broken symbolic link, ignore */
912 free(path);
913 continue;
914 } else {
915 ERR(NULL, "Failed to get information about \"%s\" (%s).", path, strerror(errno));
romanc1124572024-04-23 15:08:06 +0200916 ret = 1;
917 goto cleanup;
romanb00f4322024-04-04 09:26:18 +0200918 }
919 }
920
921 if (!S_ISREG(st.st_mode)) {
922 /* not a regular file, ignore */
923 free(path);
924 continue;
925 }
926
927 rc = mbedtls_x509_crl_parse_file(crl_store, path);
928 if (rc) {
romanc1124572024-04-23 15:08:06 +0200929 WRN(NULL, "Loading CRL from file \"%s\" failed (%s), skipping.", path, nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200930 }
931
932 free(path);
romanc1124572024-04-23 15:08:06 +0200933 path = NULL;
romanb00f4322024-04-04 09:26:18 +0200934 }
935 }
936
romanc1124572024-04-23 15:08:06 +0200937cleanup:
938 free(path);
939 closedir(dir);
940 return ret;
romanb00f4322024-04-04 09:26:18 +0200941}
942
943int
944nc_client_tls_set_hostname_wrap(void *tls_session, const char *hostname)
945{
946 int rc;
947
948 rc = mbedtls_ssl_set_hostname(tls_session, hostname);
949 if (rc) {
romanc1124572024-04-23 15:08:06 +0200950 ERR(NULL, "Setting hostname failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +0200951 return 1;
952 }
953
954 return 0;
955}
956
957int
romanc1124572024-04-23 15:08:06 +0200958nc_tls_init_ctx_wrap(int sock, void *cert, void *pkey, void *cert_store, void *crl_store, struct nc_tls_ctx *tls_ctx)
romanb00f4322024-04-04 09:26:18 +0200959{
960 /* setup rng */
961 if (nc_tls_rng_new(&tls_ctx->ctr_drbg, &tls_ctx->entropy)) {
962 return 1;
963 }
964
965 /* fill the context */
966 tls_ctx->sock = malloc(sizeof *tls_ctx->sock);
967 NC_CHECK_ERRMEM_RET(!tls_ctx->sock, 1);
968 *tls_ctx->sock = sock;
romanc1124572024-04-23 15:08:06 +0200969 tls_ctx->cert = cert;
970 tls_ctx->pkey = pkey;
romanb00f4322024-04-04 09:26:18 +0200971 tls_ctx->cert_store = cert_store;
972 tls_ctx->crl_store = crl_store;
973 return 0;
974}
975
976int
romanc1124572024-04-23 15:08:06 +0200977nc_tls_setup_config_from_ctx_wrap(struct nc_tls_ctx *tls_ctx, int side, void *tls_cfg)
romanb00f4322024-04-04 09:26:18 +0200978{
romanc1124572024-04-23 15:08:06 +0200979 int rc;
romanb00f4322024-04-04 09:26:18 +0200980
romanc1124572024-04-23 15:08:06 +0200981 /* set default config data */
982 if (side == NC_SERVER) {
983 rc = mbedtls_ssl_config_defaults(tls_cfg, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
romanb00f4322024-04-04 09:26:18 +0200984 } else {
romanc1124572024-04-23 15:08:06 +0200985 rc = mbedtls_ssl_config_defaults(tls_cfg, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
romanb00f4322024-04-04 09:26:18 +0200986 }
romanc1124572024-04-23 15:08:06 +0200987 if (rc) {
988 ERR(NULL, "Setting default TLS config failed (%s).", nc_get_mbedtls_str_err(rc));
989 return 1;
990 }
991
992 /* set config's rng */
993 mbedtls_ssl_conf_rng(tls_cfg, mbedtls_ctr_drbg_random, tls_ctx->ctr_drbg);
994 /* set config's cert and key */
995 mbedtls_ssl_conf_own_cert(tls_cfg, tls_ctx->cert, tls_ctx->pkey);
996 /* set config's CA and CRL cert store */
997 mbedtls_ssl_conf_ca_chain(tls_cfg, tls_ctx->cert_store, tls_ctx->crl_store);
998 return 0;
romanb00f4322024-04-04 09:26:18 +0200999}
1000
1001uint32_t
1002nc_tls_get_verify_result_wrap(void *tls_session)
1003{
1004 return mbedtls_ssl_get_verify_result(tls_session);
1005}
1006
romanc1124572024-04-23 15:08:06 +02001007char *
romanb00f4322024-04-04 09:26:18 +02001008nc_tls_verify_error_string_wrap(uint32_t err_code)
1009{
romanc1124572024-04-23 15:08:06 +02001010 return nc_tls_get_verify_err_str(err_code);
romanb00f4322024-04-04 09:26:18 +02001011}
1012
1013void
romanc1124572024-04-23 15:08:06 +02001014nc_client_tls_print_connect_err_wrap(int connect_ret, const char *peername, void *UNUSED(tls_session))
romanb00f4322024-04-04 09:26:18 +02001015{
romanc1124572024-04-23 15:08:06 +02001016 const char *err = nc_get_mbedtls_str_err(connect_ret);
romanb00f4322024-04-04 09:26:18 +02001017
romanc1124572024-04-23 15:08:06 +02001018 if (err) {
1019 ERR(NULL, "TLS connection to \"%s\" failed (%s).", peername, err);
romanb00f4322024-04-04 09:26:18 +02001020 } else {
romanc1124572024-04-23 15:08:06 +02001021 ERR(NULL, "TLS connection to \"%s\" failed.", peername);
1022 }
1023}
1024
1025void
1026nc_server_tls_print_accept_err_wrap(int accept_ret, void *UNUSED(tls_session))
1027{
1028 const char *err = nc_get_mbedtls_str_err(accept_ret);
1029
1030 if (err) {
1031 ERR(NULL, "TLS accept failed (%s).", err);
1032 } else {
1033 ERR(NULL, "TLS accept failed.");
romanb00f4322024-04-04 09:26:18 +02001034 }
1035}
1036
1037int
romanc1124572024-04-23 15:08:06 +02001038nc_tls_is_der_subpubkey_wrap(unsigned char *der, long len)
1039{
1040 int ret;
1041 mbedtls_pk_context *pkey;
1042
1043 pkey = nc_tls_pkey_new_wrap();
1044 if (!pkey) {
1045 return -1;
1046 }
1047
1048 ret = mbedtls_pk_parse_subpubkey(&der, der + len, pkey);
1049 nc_tls_privkey_destroy_wrap(pkey);
1050 if (!ret) {
1051 /* success */
1052 return 1;
1053 } else {
1054 /* fail */
1055 return 0;
1056 }
1057}
1058
1059int
1060nc_base64_decode_wrap(const char *base64, unsigned char **bin)
romanb00f4322024-04-04 09:26:18 +02001061{
1062 size_t size;
romanc1124572024-04-23 15:08:06 +02001063 int rc;
romanb00f4322024-04-04 09:26:18 +02001064
romanc1124572024-04-23 15:08:06 +02001065 /* get the size of the decoded data */
1066 rc = mbedtls_base64_decode(NULL, 0, &size, (const unsigned char *)base64, strlen(base64));
1067 if (rc != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
1068 ERR(NULL, "Base64 decoding failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001069 return -1;
1070 }
1071
1072 *bin = malloc(size);
1073 NC_CHECK_ERRMEM_RET(!*bin, -1);
1074
romanc1124572024-04-23 15:08:06 +02001075 /* decode */
1076 rc = mbedtls_base64_decode(*bin, size, &size, (const unsigned char *)base64, strlen(base64));
1077 if (rc) {
1078 ERR(NULL, "Base64 decoding failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001079 free(*bin);
1080 *bin = NULL;
1081 return -1;
1082 }
1083
1084 return size;
1085}
1086
1087int
1088nc_base64_encode_wrap(const unsigned char *bin, size_t len, char **base64)
1089{
1090 size_t size;
romanc1124572024-04-23 15:08:06 +02001091 int rc;
romanb00f4322024-04-04 09:26:18 +02001092
romanc1124572024-04-23 15:08:06 +02001093 rc = mbedtls_base64_encode(NULL, 0, &size, bin, len);
1094 if (rc != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
1095 ERR(NULL, "Base64 encoding failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001096 return -1;
1097 }
1098
1099 *base64 = malloc(size);
1100 NC_CHECK_ERRMEM_RET(!*base64, -1);
1101
romanc1124572024-04-23 15:08:06 +02001102 rc = mbedtls_base64_encode((unsigned char *)*base64, size, &size, bin, len);
1103 if (rc) {
1104 ERR(NULL, "Base64 encoding failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001105 free(*base64);
1106 *base64 = NULL;
1107 return -1;
1108 }
1109
1110 return 0;
1111}
1112
1113int
1114nc_tls_read_wrap(struct nc_session *session, unsigned char *buf, size_t size)
1115{
1116 int rc;
1117 mbedtls_ssl_context *tls_session = session->ti.tls.session;
1118
1119 rc = mbedtls_ssl_read(tls_session, buf, size);
1120 if (rc <= 0) {
1121 switch (rc) {
1122 case MBEDTLS_ERR_SSL_WANT_READ:
1123 case MBEDTLS_ERR_SSL_WANT_WRITE:
1124 rc = 0;
1125 break;
1126 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
1127 ERR(session, "Communication socket unexpectedly closed (MbedTLS).");
1128 session->status = NC_STATUS_INVALID;
1129 session->term_reason = NC_SESSION_TERM_DROPPED;
1130 rc = -1;
1131 break;
1132 default:
romanc1124572024-04-23 15:08:06 +02001133 ERR(session, "TLS communication error occurred (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001134 session->status = NC_STATUS_INVALID;
1135 session->term_reason = NC_SESSION_TERM_OTHER;
1136 rc = -1;
1137 break;
1138 }
1139 }
1140
1141 return rc;
1142}
1143
1144int
1145nc_tls_write_wrap(struct nc_session *session, const unsigned char *buf, size_t size)
1146{
1147 int rc = 0;
1148 mbedtls_ssl_context *tls_session = session->ti.tls.session;
1149
1150 rc = mbedtls_ssl_write(tls_session, buf, size);
1151 if (rc < 0) {
1152 switch (rc) {
1153 case MBEDTLS_ERR_SSL_WANT_READ:
1154 case MBEDTLS_ERR_SSL_WANT_WRITE:
1155 rc = 0;
1156 break;
1157 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
1158 ERR(session, "TLS connection was properly closed.");
1159 rc = -1;
1160 break;
1161 default:
romanc1124572024-04-23 15:08:06 +02001162 ERR(session, "TLS communication error occurred (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001163 rc = -1;
1164 break;
1165 }
1166 }
1167
1168 return rc;
1169}
1170
1171int
romanc1124572024-04-23 15:08:06 +02001172nc_tls_get_num_pending_bytes_wrap(void *tls_session)
romanb00f4322024-04-04 09:26:18 +02001173{
1174 return mbedtls_ssl_get_bytes_avail(tls_session);
1175}
1176
1177int
1178nc_tls_get_fd_wrap(const struct nc_session *session)
1179{
romanc1124572024-04-23 15:08:06 +02001180 return session->ti.tls.ctx.sock ? *session->ti.tls.ctx.sock : -1;
romanb00f4322024-04-04 09:26:18 +02001181}
1182
1183void
1184nc_tls_close_notify_wrap(void *tls_session)
1185{
1186 int rc;
1187
1188 while ((rc = mbedtls_ssl_close_notify(tls_session))) {
1189 if ((rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_WANT_WRITE)) {
1190 /* some error occurred */
romanc1124572024-04-23 15:08:06 +02001191 ERR(NULL, "Sending TLS close notify failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001192 return;
1193 }
1194 }
1195}
1196
1197void *
romanb00f4322024-04-04 09:26:18 +02001198nc_tls_import_cert_file_wrap(const char *cert_path)
1199{
1200 int rc;
1201 mbedtls_x509_crt *c;
1202
1203 c = nc_tls_cert_new_wrap();
1204 if (!c) {
1205 return NULL;
1206 }
1207
1208 rc = mbedtls_x509_crt_parse_file(c, cert_path);
1209 if (rc) {
romanc1124572024-04-23 15:08:06 +02001210 ERR(NULL, "Parsing certificate from file \"%s\" failed (%s).", cert_path, nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001211 nc_tls_cert_destroy_wrap(c);
1212 return NULL;
1213 }
1214
1215 return c;
1216}
1217
1218char *
romanc1124572024-04-23 15:08:06 +02001219nc_tls_export_privkey_pem_wrap(void *pkey)
romanb00f4322024-04-04 09:26:18 +02001220{
1221 int rc;
1222 char *pem;
1223 size_t size = 128;
romanb00f4322024-04-04 09:26:18 +02001224
1225 pem = malloc(size);
1226 NC_CHECK_ERRMEM_RET(!pem, NULL);
1227
1228 while ((rc = mbedtls_pk_write_key_pem(pkey, (unsigned char *)pem, size)) == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
1229 size <<= 1;
romanc1124572024-04-23 15:08:06 +02001230 pem = nc_realloc(pem, size);
1231 NC_CHECK_ERRMEM_RET(!pem, NULL);
romanb00f4322024-04-04 09:26:18 +02001232 }
1233 if (rc < 0) {
romanc1124572024-04-23 15:08:06 +02001234 ERR(NULL, "Exporting private key to PEM format failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001235 free(pem);
1236 return NULL;
1237 }
1238
1239 return pem;
1240}
1241
1242char *
romanc1124572024-04-23 15:08:06 +02001243nc_tls_export_cert_pem_wrap(void *cert)
romanb00f4322024-04-04 09:26:18 +02001244{
1245 char *b64 = NULL, *pem = NULL;
1246
romanc1124572024-04-23 15:08:06 +02001247 /* encode the certificate */
romanb00f4322024-04-04 09:26:18 +02001248 if (nc_base64_encode_wrap(((mbedtls_x509_crt *)cert)->raw.p, ((mbedtls_x509_crt *)cert)->raw.len, &b64)) {
1249 goto cleanup;
1250 }
1251
1252 if (asprintf(&pem, "-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----\n", b64) == -1) {
1253 ERRMEM;
1254 pem = NULL;
1255 goto cleanup;
1256 }
1257
1258cleanup:
1259 free(b64);
1260 return pem;
1261}
1262
1263char *
romanc1124572024-04-23 15:08:06 +02001264nc_tls_export_pubkey_pem_wrap(void *pkey)
romanb00f4322024-04-04 09:26:18 +02001265{
1266 int rc;
1267 char *pem;
1268 size_t size = 128;
romanb00f4322024-04-04 09:26:18 +02001269
1270 pem = malloc(size);
1271 NC_CHECK_ERRMEM_RET(!pem, NULL);
1272
1273 while ((rc = mbedtls_pk_write_pubkey_pem(pkey, (unsigned char *)pem, size)) == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
1274 size <<= 1;
romanc1124572024-04-23 15:08:06 +02001275 pem = nc_realloc(pem, size);
1276 NC_CHECK_ERRMEM_RET(!pem, NULL);
romanb00f4322024-04-04 09:26:18 +02001277 }
1278 if (rc < 0) {
romanc1124572024-04-23 15:08:06 +02001279 ERR(NULL, "Exporting public key to PEM format failed (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001280 free(pem);
1281 return NULL;
1282 }
1283
1284 return pem;
1285}
1286
1287int
romanb00f4322024-04-04 09:26:18 +02001288nc_tls_privkey_is_rsa_wrap(void *pkey)
1289{
1290 return mbedtls_pk_get_type(pkey) == MBEDTLS_PK_RSA;
1291}
1292
1293int
1294nc_tls_get_rsa_pubkey_params_wrap(void *pkey, void **e, void **n)
1295{
1296 int rc;
1297 mbedtls_mpi *exp = NULL, *mod = NULL;
1298
1299 exp = malloc(sizeof *exp);
1300 mod = malloc(sizeof *mod);
1301 if (!exp || !mod) {
1302 ERRMEM;
1303 goto fail;
1304 }
1305 mbedtls_mpi_init(exp);
1306 mbedtls_mpi_init(mod);
1307
1308 if ((rc = mbedtls_rsa_export(mbedtls_pk_rsa(*(mbedtls_pk_context *)pkey), mod, NULL, NULL, NULL, exp))) {
romanc1124572024-04-23 15:08:06 +02001309 ERR(NULL, "Failed to export RSA public key parameters (%s).", nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001310 goto fail;
1311 }
1312
1313 *e = exp;
1314 *n = mod;
1315 return 0;
1316
1317fail:
1318 mbedtls_mpi_free(exp);
1319 mbedtls_mpi_free(mod);
1320 free(exp);
1321 free(mod);
1322 return 1;
1323}
1324
romanc1124572024-04-23 15:08:06 +02001325void
1326nc_tls_destroy_mpi_wrap(void *mpi)
1327{
1328 mbedtls_mpi_free(mpi);
1329 free(mpi);
1330}
1331
romanb00f4322024-04-04 09:26:18 +02001332int
1333nc_tls_privkey_is_ec_wrap(void *pkey)
1334{
1335 return mbedtls_pk_get_type(pkey) == MBEDTLS_PK_ECKEY;
1336}
1337
1338char *
1339nc_tls_get_ec_group_wrap(void *pkey)
1340{
1341 const mbedtls_ecp_curve_info *curve_info;
1342 mbedtls_ecp_group_id group_id;
1343 mbedtls_ecp_keypair *ec;
1344
romanc1124572024-04-23 15:08:06 +02001345 /* get the group ID from the EC key */
romanb00f4322024-04-04 09:26:18 +02001346 ec = mbedtls_pk_ec(*(mbedtls_pk_context *)pkey);
1347 group_id = ec->private_grp.id;
romanc1124572024-04-23 15:08:06 +02001348
1349 /* get the group name based on the id */
romanb00f4322024-04-04 09:26:18 +02001350 curve_info = mbedtls_ecp_curve_info_from_grp_id(group_id);
1351 return strdup(curve_info->name);
1352}
1353
1354int
romanc1124572024-04-23 15:08:06 +02001355nc_tls_get_ec_pubkey_params_wrap(void *pkey, void **q, void **q_grp)
romanb00f4322024-04-04 09:26:18 +02001356{
romanc1124572024-04-23 15:08:06 +02001357 int ret;
1358 mbedtls_ecp_group *grp = NULL;
1359 mbedtls_ecp_point *p = NULL;
1360 mbedtls_mpi *d = NULL;
romanb00f4322024-04-04 09:26:18 +02001361
romanc1124572024-04-23 15:08:06 +02001362 /* init group, mpi and point */
1363 grp = malloc(sizeof *grp);
1364 d = malloc(sizeof *d);
1365 p = malloc(sizeof *p);
1366 if (!grp || !p || !d) {
1367 ERRMEM;
1368 ret = 1;
1369 goto cleanup;
1370 }
1371 mbedtls_ecp_group_init(grp);
1372 mbedtls_mpi_init(d);
1373 mbedtls_ecp_point_init(p);
romanb00f4322024-04-04 09:26:18 +02001374
romanc1124572024-04-23 15:08:06 +02001375 /* get the group and public key */
1376 ret = mbedtls_ecp_export(mbedtls_pk_ec(*(mbedtls_pk_context *)pkey), grp, d, p);
1377 if (ret) {
1378 ERR(NULL, "Failed to export EC public key parameters (%s).", nc_get_mbedtls_str_err(ret));
1379 ret = 1;
1380 goto cleanup;
1381 }
1382
1383 *q_grp = grp;
1384 grp = NULL;
1385 *q = p;
1386 p = NULL;
1387
1388cleanup:
1389 mbedtls_ecp_group_free(grp);
1390 free(grp);
1391 mbedtls_mpi_free(d);
1392 free(d);
1393 mbedtls_ecp_point_free(p);
1394 free(p);
1395 return ret;
1396}
1397
1398int
1399nc_tls_ec_point_to_bin_wrap(void *q, void *q_grp, unsigned char **bin, int *bin_len)
1400{
1401 int rc;
1402 unsigned char *buf;
1403 size_t buf_len = 32, out_len;
1404
1405 buf = malloc(buf_len);
1406 NC_CHECK_ERRMEM_RET(!buf, 1);
1407
1408 while ((rc = (mbedtls_ecp_point_write_binary(q_grp, q, MBEDTLS_ECP_PF_COMPRESSED, &out_len, buf, buf_len)))) {
1409 if (rc != MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) {
1410 break;
romanb00f4322024-04-04 09:26:18 +02001411 }
romanc1124572024-04-23 15:08:06 +02001412 buf_len <<= 1;
1413 buf = nc_realloc(buf, buf_len);
1414 NC_CHECK_ERRMEM_RET(!buf, 1);
romanb00f4322024-04-04 09:26:18 +02001415 }
1416 if (rc) {
romanc1124572024-04-23 15:08:06 +02001417 ERR(NULL, "Failed to write EC public key binary (%s).", nc_get_mbedtls_str_err(rc));
1418 free(buf);
romanb00f4322024-04-04 09:26:18 +02001419 return 1;
1420 }
1421
romanc1124572024-04-23 15:08:06 +02001422 *bin = buf;
romanb00f4322024-04-04 09:26:18 +02001423 *bin_len = out_len;
1424 return 0;
1425}
1426
romanc1124572024-04-23 15:08:06 +02001427void
1428nc_tls_ec_point_destroy_wrap(void *p)
romanb00f4322024-04-04 09:26:18 +02001429{
romanc1124572024-04-23 15:08:06 +02001430 mbedtls_ecp_point_free(p);
1431 free(p);
romanb00f4322024-04-04 09:26:18 +02001432}
1433
1434void
romanc1124572024-04-23 15:08:06 +02001435nc_tls_ec_group_destroy_wrap(void *grp)
romanb00f4322024-04-04 09:26:18 +02001436{
romanc1124572024-04-23 15:08:06 +02001437 mbedtls_ecp_group_free(grp);
1438 free(grp);
romanb00f4322024-04-04 09:26:18 +02001439}
1440
1441int
romanc1124572024-04-23 15:08:06 +02001442nc_tls_mpi2bin_wrap(void *mpi, unsigned char **bin, int *bin_len)
romanb00f4322024-04-04 09:26:18 +02001443{
romanc1124572024-04-23 15:08:06 +02001444 int rc;
1445 unsigned char *buf;
1446 int buf_len;
romanb00f4322024-04-04 09:26:18 +02001447
romanc1124572024-04-23 15:08:06 +02001448 buf_len = mbedtls_mpi_size(mpi);
1449 buf = malloc(buf_len);
1450 NC_CHECK_ERRMEM_RET(!buf, 1);
1451
1452 rc = mbedtls_mpi_write_binary(mpi, buf, buf_len);
1453 if (rc) {
1454 ERR(NULL, "Failed to convert MPI to binary (%s).", nc_get_mbedtls_str_err(rc));
1455 free(buf);
romanb00f4322024-04-04 09:26:18 +02001456 return 1;
1457 }
1458
romanc1124572024-04-23 15:08:06 +02001459 *bin = buf;
1460 *bin_len = buf_len;
1461 return 0;
romanb00f4322024-04-04 09:26:18 +02001462}
1463
1464void *
1465nc_tls_import_pubkey_file_wrap(const char *pubkey_path)
1466{
1467 int rc = 0;
1468 mbedtls_pk_context *pk = NULL;
1469
romanc1124572024-04-23 15:08:06 +02001470 pk = nc_tls_pkey_new_wrap();
romanb00f4322024-04-04 09:26:18 +02001471 if (!pk) {
1472 return NULL;
1473 }
1474
1475 rc = mbedtls_pk_parse_public_keyfile(pk, pubkey_path);
1476 if (rc) {
romanc1124572024-04-23 15:08:06 +02001477 ERR(NULL, "Parsing public key from file \"%s\" failed (%s).", pubkey_path, nc_get_mbedtls_str_err(rc));
romanb00f4322024-04-04 09:26:18 +02001478 nc_tls_privkey_destroy_wrap(pk);
1479 return NULL;
1480 }
1481
1482 return pk;
1483}
roman275c3fb2024-04-05 12:29:11 +02001484
1485int
1486nc_server_tls_get_crl_distpoint_uris_wrap(void *cert_store, char ***uris, int *uri_count)
1487{
1488 int ret = 0;
1489 mbedtls_x509_crt *cert;
1490 unsigned char *p, *end_v3_ext, *end_ext, *end_ext_octet, *end_crl_dist_points;
1491 size_t len;
1492 mbedtls_x509_buf ext_oid = {0};
1493 int is_critical = 0;
1494 mbedtls_x509_sequence general_names = {0};
1495 mbedtls_x509_sequence *iter = NULL;
1496 mbedtls_x509_subject_alternative_name san = {0};
1497 void *tmp;
1498
1499 NC_CHECK_ARG_RET(NULL, cert_store, uris, uri_count, 1);
1500
1501 *uris = NULL;
1502 *uri_count = 0;
1503
1504 /* iterate over all the CAs */
1505 cert = cert_store;
1506 while (cert) {
1507 if (!cert->v3_ext.len) {
1508 /* no extensions, skip this cert */
1509 cert = cert->next;
1510 continue;
1511 }
1512
1513 /* go over all the extensions and try to find the CRL distribution points */
1514 p = cert->v3_ext.p;
1515 end_v3_ext = p + cert->v3_ext.len;
1516
1517 /*
1518 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
1519 */
1520 ret = mbedtls_asn1_get_tag(&p, end_v3_ext, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
1521 if (ret) {
romanc1124572024-04-23 15:08:06 +02001522 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001523 goto cleanup;
1524 }
1525
1526 while (p < end_v3_ext) {
1527 /*
1528 * Extension ::= SEQUENCE {
1529 * extnID OBJECT IDENTIFIER,
1530 * critical BOOLEAN DEFAULT FALSE,
1531 * extnValue OCTET STRING }
1532 */
1533 ret = mbedtls_asn1_get_tag(&p, end_v3_ext, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
1534 if (ret) {
romanc1124572024-04-23 15:08:06 +02001535 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001536 goto cleanup;
1537 }
1538
1539 end_ext = p + len;
1540
1541 /* parse extnID */
1542 ret = mbedtls_asn1_get_tag(&p, end_ext, &ext_oid.len, MBEDTLS_ASN1_OID);
1543 if (ret) {
romanc1124572024-04-23 15:08:06 +02001544 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001545 goto cleanup;
1546 }
1547 ext_oid.tag = MBEDTLS_ASN1_OID;
1548 ext_oid.p = p;
1549
1550 if (memcmp(ext_oid.p, MBEDTLS_OID_CRL_DISTRIBUTION_POINTS, ext_oid.len)) {
1551 /* not the extension we are looking for */
1552 p = end_ext;
1553 continue;
1554 }
1555
1556 p += ext_oid.len;
1557
1558 /* parse optional critical */
1559 ret = mbedtls_asn1_get_bool(&p, end_ext, &is_critical);
1560 if (ret && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
romanc1124572024-04-23 15:08:06 +02001561 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001562 goto cleanup;
1563 }
1564
1565 /* parse extnValue */
1566 ret = mbedtls_asn1_get_tag(&p, end_ext, &len, MBEDTLS_ASN1_OCTET_STRING);
1567 if (ret) {
romanc1124572024-04-23 15:08:06 +02001568 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001569 goto cleanup;
1570 }
1571
1572 end_ext_octet = p + len;
1573
1574 /*
1575 * parse extnValue, that is CRLDistributionPoints
1576 *
1577 * CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
1578 */
1579 ret = mbedtls_asn1_get_tag(&p, end_ext_octet, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
1580 if (ret) {
romanc1124572024-04-23 15:08:06 +02001581 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001582 goto cleanup;
1583 }
1584 if (p + len != end_ext_octet) {
1585 /* length mismatch */
romanc1124572024-04-23 15:08:06 +02001586 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001587 goto cleanup;
1588 } else if (!len) {
1589 /* empty sequence, but size is 1..max */
1590 ERR(NULL, "Failed to parse CRL distribution points extension (empty sequence).");
1591 goto cleanup;
1592 }
1593
1594 end_crl_dist_points = p + len;
1595
1596 while (p < end_crl_dist_points) {
1597 /*
1598 * DistributionPoint ::= SEQUENCE {
1599 * distributionPoint [0] DistributionPointName OPTIONAL,
1600 * reasons [1] ReasonFlags OPTIONAL,
1601 * cRLIssuer [2] GeneralNames OPTIONAL }
1602 */
1603 ret = mbedtls_asn1_get_tag(&p, end_ext_octet, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
1604 if (ret) {
romanc1124572024-04-23 15:08:06 +02001605 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001606 goto cleanup;
1607 }
1608 if (!len) {
1609 /* empty sequence */
1610 continue;
1611 }
1612
1613 /* parse distributionPoint */
1614 ret = mbedtls_asn1_get_tag(&p, end_ext_octet, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0);
1615 if (!ret) {
1616 /*
1617 * DistributionPointName ::= CHOICE {
1618 * fullName [0] GeneralNames,
1619 * nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
1620 */
1621 ret = mbedtls_asn1_get_tag(&p, end_ext_octet, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0);
1622 if (ret) {
1623 if ((ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) && (*p == (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1))) {
1624 /* it's nameRelativeToCRLIssuer, but we don't support it */
romanc1124572024-04-23 15:08:06 +02001625 ERR(NULL, "Failed to parse CRL distribution points extension (nameRelativeToCRLIssuer not yet supported).");
roman275c3fb2024-04-05 12:29:11 +02001626 goto cleanup;
1627 } else {
romanc1124572024-04-23 15:08:06 +02001628 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001629 goto cleanup;
1630 }
1631 }
1632
1633 /* parse GeneralNames, but thankfully there is an api for this */
1634 ret = mbedtls_x509_get_subject_alt_name_ext(&p, p + len, &general_names);
1635 if (ret) {
romanc1124572024-04-23 15:08:06 +02001636 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001637 goto cleanup;
1638 }
1639
1640 /* iterate over all the GeneralNames */
1641 iter = &general_names;
1642 while (iter) {
1643 ret = mbedtls_x509_parse_subject_alt_name(&iter->buf, &san);
1644 if (ret && (ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE)) {
romanc1124572024-04-23 15:08:06 +02001645 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001646 goto cleanup;
1647 }
1648
1649 if (san.type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER) {
1650 /* found an URI */
1651 tmp = realloc(*uris, (*uri_count + 1) * sizeof **uris);
romanc1124572024-04-23 15:08:06 +02001652 if (!tmp) {
1653 ERRMEM;
1654 ret = 1;
1655 mbedtls_x509_free_subject_alt_name(&san);
1656 goto cleanup;
1657 }
roman275c3fb2024-04-05 12:29:11 +02001658 *uris = tmp;
1659
1660 *uris[*uri_count] = strndup((const char *)san.san.unstructured_name.p, san.san.unstructured_name.len);
romanc1124572024-04-23 15:08:06 +02001661 if (!*uris[*uri_count]) {
1662 ERRMEM;
1663 ret = 1;
1664 mbedtls_x509_free_subject_alt_name(&san);
1665 goto cleanup;
1666 }
roman275c3fb2024-04-05 12:29:11 +02001667 ++(*uri_count);
1668 }
romanc1124572024-04-23 15:08:06 +02001669
1670 mbedtls_x509_free_subject_alt_name(&san);
roman275c3fb2024-04-05 12:29:11 +02001671 iter = iter->next;
1672 }
1673
1674 } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
1675 /* failed to parse it, but not because it's optional */
romanc1124572024-04-23 15:08:06 +02001676 ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
roman275c3fb2024-04-05 12:29:11 +02001677 goto cleanup;
1678 }
1679 }
1680 }
1681 cert = cert->next;
1682 }
1683
1684cleanup:
1685 return ret;
1686}
romanc1124572024-04-23 15:08:06 +02001687
1688int
1689nc_tls_process_cipher_suite_wrap(const char *cipher, char **out)
1690{
1691 const char *begin, *ptr;
1692
1693 /* check if it's a TLS 1.3 cipher suite */
1694 if (!strcmp(cipher, "tls-aes-256-gcm-sha384") || !strcmp(cipher, "tls-aes-128-gcm-sha256") ||
1695 !strcmp(cipher, "tls-chacha20-poly1305-sha256") || !strcmp(cipher, "tls-aes-128-ccm-sha256") ||
1696 !strcmp(cipher, "tls-aes-128-ccm-8-sha256")) {
1697 /* + 3 because mbedtls has "TLS1-3" prefix for 1.3 suites */
1698 *out = malloc(strlen(cipher) + 3 + 1);
1699 NC_CHECK_ERRMEM_RET(!*out, 1);
1700 sprintf(*out, "TLS1-3");
1701 begin = cipher + 4;
1702 } else {
1703 *out = malloc(strlen(cipher) + 1);
1704 NC_CHECK_ERRMEM_RET(!*out, 1);
1705 begin = cipher;
1706 }
1707
1708 /* convert to uppercase */
1709 for (ptr = begin; *ptr; ptr++) {
1710 (*out)[ptr - begin] = toupper(*ptr);
1711 }
1712
1713 (*out)[ptr - begin] = '\0';
1714 return 0;
1715}
1716
1717int
1718nc_tls_append_cipher_suite_wrap(struct nc_server_tls_opts *opts, const char *cipher_suite)
1719{
1720 int cipher_id;
1721
1722 cipher_id = mbedtls_ssl_get_ciphersuite_id(cipher_suite);
1723 if (!cipher_id) {
1724 return 1;
1725 }
1726
1727 /* append the cipher suite to a zero terminated array */
1728 if (!opts->ciphers) {
1729 /* first entry, account for terminating 0 */
1730 opts->ciphers = malloc(2 * sizeof *opts->ciphers);
1731 NC_CHECK_ERRMEM_RET(!opts->ciphers, 1);
1732 ((int *)opts->ciphers)[0] = cipher_id;
1733 opts->cipher_count = 1;
1734 } else {
1735 /* +2 because of terminating 0 */
1736 opts->ciphers = nc_realloc(opts->ciphers, (opts->cipher_count + 2) * sizeof *opts->ciphers);
1737 NC_CHECK_ERRMEM_RET(!opts->ciphers, 1);
1738 ((int *)opts->ciphers)[opts->cipher_count] = cipher_id;
1739 opts->cipher_count++;
1740 }
1741
1742 /* terminate the array */
1743 ((int *)opts->ciphers)[opts->cipher_count] = 0;
1744 return 0;
1745}
1746
1747void
1748nc_server_tls_set_cipher_suites_wrap(void *tls_cfg, void *cipher_suites)
1749{
1750 mbedtls_ssl_conf_ciphersuites(tls_cfg, cipher_suites);
1751}