blob: d863c16b104412471bfc133092b2c7128f7f9365 [file] [log] [blame]
roman163f1662024-04-04 09:26:42 +02001#define _GNU_SOURCE
2
roman7ef57992024-04-23 15:08:45 +02003#include <ctype.h>
roman163f1662024-04-04 09:26:42 +02004#include <poll.h>
5#include <stdint.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <unistd.h>
10
11#include <curl/curl.h>
12
13#include "compat.h"
14#include "config.h"
15#include "log_p.h"
16#include "session.h"
17#include "session_p.h"
18#include "session_wrapper.h"
19
20#include <openssl/bio.h>
21#include <openssl/err.h>
22#include <openssl/evp.h>
23#include <openssl/ssl.h>
24#include <openssl/x509.h>
25#include <openssl/x509v3.h>
26
27void *
28nc_tls_session_new_wrap(void *tls_cfg)
29{
30 SSL *session;
31
32 session = SSL_new(tls_cfg);
33 if (!session) {
roman7ef57992024-04-23 15:08:45 +020034 ERR(NULL, "Setting up TLS session failed (%s).", ERR_reason_error_string(ERR_get_error()));
roman163f1662024-04-04 09:26:42 +020035 return NULL;
36 }
37
38 return session;
39}
40
41void
42nc_tls_session_destroy_wrap(void *tls_session)
43{
44 SSL_free(tls_session);
45}
46
47void *
roman7ef57992024-04-23 15:08:45 +020048nc_tls_config_new_wrap(int side)
roman163f1662024-04-04 09:26:42 +020049{
50 SSL_CTX *tls_cfg;
51
roman7ef57992024-04-23 15:08:45 +020052 if ((side != NC_SERVER) && (side != NC_CLIENT)) {
53 ERRINT;
54 return NULL;
55 }
roman163f1662024-04-04 09:26:42 +020056
roman7ef57992024-04-23 15:08:45 +020057 if (side == NC_SERVER) {
58 tls_cfg = SSL_CTX_new(TLS_server_method());
59 } else {
60 tls_cfg = SSL_CTX_new(TLS_client_method());
61 }
roman163f1662024-04-04 09:26:42 +020062 NC_CHECK_ERRMEM_RET(!tls_cfg, NULL)
63
64 return tls_cfg;
65}
66
67void
68nc_tls_config_destroy_wrap(void *tls_cfg)
69{
70 SSL_CTX_free(tls_cfg);
71}
72
73void *
74nc_tls_cert_new_wrap()
75{
76 X509 *cert;
77
78 cert = X509_new();
79 NC_CHECK_ERRMEM_RET(!cert, NULL)
80
81 return cert;
82}
83
84void
85nc_tls_cert_destroy_wrap(void *cert)
86{
87 X509_free(cert);
88}
89
roman163f1662024-04-04 09:26:42 +020090void
91nc_tls_privkey_destroy_wrap(void *pkey)
92{
93 EVP_PKEY_free(pkey);
94}
95
96void *
97nc_tls_cert_store_new_wrap()
98{
99 X509_STORE *store;
100
101 store = X509_STORE_new();
102 NC_CHECK_ERRMEM_RET(!store, NULL);
103
104 return store;
105}
106
107void
108nc_tls_cert_store_destroy_wrap(void *cert_store)
109{
110 X509_STORE_free(cert_store);
111}
112
113void *
114nc_tls_crl_store_new_wrap()
115{
roman7ef57992024-04-23 15:08:45 +0200116 return nc_tls_cert_store_new_wrap();
roman163f1662024-04-04 09:26:42 +0200117}
118
119void
roman7ef57992024-04-23 15:08:45 +0200120nc_tls_crl_store_destroy_wrap(void *crl_store)
roman163f1662024-04-04 09:26:42 +0200121{
roman7ef57992024-04-23 15:08:45 +0200122 X509_STORE_free(crl_store);
roman163f1662024-04-04 09:26:42 +0200123}
124
125void *
126nc_tls_pem_to_cert_wrap(const char *cert_data)
127{
128 BIO *bio;
129 X509 *cert;
130
131 bio = BIO_new_mem_buf(cert_data, strlen(cert_data));
132 if (!bio) {
133 ERR(NULL, "Creating new bio failed (%s).", ERR_reason_error_string(ERR_get_error()));
134 return NULL;
135 }
136
137 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
138 if (!cert) {
139 ERR(NULL, "Parsing certificate data failed (%s).", ERR_reason_error_string(ERR_get_error()));
140 }
141 BIO_free(bio);
142 return cert;
143}
144
145int
roman7ef57992024-04-23 15:08:45 +0200146nc_tls_add_cert_to_store_wrap(void *cert, void *cert_store)
roman163f1662024-04-04 09:26:42 +0200147{
148 int rc;
roman163f1662024-04-04 09:26:42 +0200149
roman7ef57992024-04-23 15:08:45 +0200150 /* on success increases ref count to cert, so free it */
roman163f1662024-04-04 09:26:42 +0200151 rc = X509_STORE_add_cert(cert_store, cert);
roman163f1662024-04-04 09:26:42 +0200152 if (!rc) {
153 ERR(NULL, "Adding certificate to store failed (%s).", ERR_reason_error_string(ERR_get_error()));
154 return 1;
155 }
roman7ef57992024-04-23 15:08:45 +0200156
157 X509_free(cert);
roman163f1662024-04-04 09:26:42 +0200158 return 0;
159}
160
161void *
162nc_tls_pem_to_privkey_wrap(const char *privkey_data)
163{
164 BIO *bio;
165 EVP_PKEY *pkey;
166
167 bio = BIO_new_mem_buf(privkey_data, strlen(privkey_data));
168 if (!bio) {
169 ERR(NULL, "Creating new bio failed (%s).", ERR_reason_error_string(ERR_get_error()));
170 return NULL;
171 }
172
173 pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
174 if (!pkey) {
175 ERR(NULL, "Parsing certificate data failed (%s).", ERR_reason_error_string(ERR_get_error()));
176 }
177 BIO_free(bio);
178 return pkey;
179}
180
181int
roman7ef57992024-04-23 15:08:45 +0200182nc_tls_import_crl_path_wrap(const char *path, void *crl_store)
roman163f1662024-04-04 09:26:42 +0200183{
roman7ef57992024-04-23 15:08:45 +0200184 int ret = 0, rc;
roman163f1662024-04-04 09:26:42 +0200185 X509_CRL *crl = NULL;
186 FILE *f;
187
roman7ef57992024-04-23 15:08:45 +0200188 f = fopen(path, "r");
roman163f1662024-04-04 09:26:42 +0200189 if (!f) {
roman7ef57992024-04-23 15:08:45 +0200190 ERR(NULL, "Unable to open CRL file \"%s\".", path);
roman163f1662024-04-04 09:26:42 +0200191 return 1;
192 }
193
194 /* try PEM first */
195 crl = PEM_read_X509_CRL(f, NULL, NULL, NULL);
196 if (crl) {
197 /* success */
198 goto ok;
199 }
200
201 /* PEM failed, try DER */
202 rewind(f);
203 crl = d2i_X509_CRL_fp(f, NULL);
204 if (!crl) {
roman7ef57992024-04-23 15:08:45 +0200205 ERR(NULL, "Reading CRL from file \"%s\" failed.", path);
roman163f1662024-04-04 09:26:42 +0200206 ret = 1;
207 goto cleanup;
208 }
209
210ok:
roman7ef57992024-04-23 15:08:45 +0200211 rc = X509_STORE_add_crl(crl_store, crl);
212 if (!rc) {
roman163f1662024-04-04 09:26:42 +0200213 ERR(NULL, "Error adding CRL to store (%s).", ERR_reason_error_string(ERR_get_error()));
214 ret = 1;
215 goto cleanup;
216 }
roman163f1662024-04-04 09:26:42 +0200217
218cleanup:
219 fclose(f);
220 X509_CRL_free(crl);
221 return ret;
222}
223
224int
roman7ef57992024-04-23 15:08:45 +0200225nc_server_tls_add_crl_to_store_wrap(const unsigned char *crl_data, size_t size, void *crl_store)
roman163f1662024-04-04 09:26:42 +0200226{
227 int ret = 0;
228 X509_CRL *crl = NULL;
229 BIO *bio = NULL;
230
roman163f1662024-04-04 09:26:42 +0200231 bio = BIO_new_mem_buf(crl_data, size);
232 if (!bio) {
233 ERR(NULL, "Creating new bio failed (%s).", ERR_reason_error_string(ERR_get_error()));
234 ret = 1;
235 goto cleanup;
236 }
237
238 /* try DER first */
239 crl = d2i_X509_CRL_bio(bio, NULL);
240 if (crl) {
241 /* it was DER */
242 goto ok;
243 }
244
245 /* DER failed, try PEM next */
246 crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
247 if (!crl) {
248 ERR(NULL, "Parsing downloaded CRL failed (%s).", ERR_reason_error_string(ERR_get_error()));
249 ret = 1;
250 goto cleanup;
251 }
252
253ok:
254 /* we obtained the CRL, now add it to the CRL store */
roman7ef57992024-04-23 15:08:45 +0200255 ret = X509_STORE_add_crl(crl_store, crl);
roman163f1662024-04-04 09:26:42 +0200256 if (!ret) {
257 ERR(NULL, "Error adding CRL to store (%s).", ERR_reason_error_string(ERR_get_error()));
258 ret = 1;
259 goto cleanup;
260 }
261 /* ok */
262 ret = 0;
263
264cleanup:
265 X509_CRL_free(crl);
266 BIO_free(bio);
267 return ret;
268}
269
roman163f1662024-04-04 09:26:42 +0200270int
271nc_server_tls_set_tls_versions_wrap(void *tls_cfg, unsigned int tls_versions)
272{
273 int rc = 1;
274
275 /* first set the minimum version */
276 if (tls_versions & NC_TLS_VERSION_10) {
277 rc = SSL_CTX_set_min_proto_version(tls_cfg, TLS1_VERSION);
278 } else if (tls_versions & NC_TLS_VERSION_11) {
279 rc = SSL_CTX_set_min_proto_version(tls_cfg, TLS1_1_VERSION);
280 } else if (tls_versions & NC_TLS_VERSION_12) {
281 rc = SSL_CTX_set_min_proto_version(tls_cfg, TLS1_2_VERSION);
282 } else if (tls_versions & NC_TLS_VERSION_13) {
283 rc = SSL_CTX_set_min_proto_version(tls_cfg, TLS1_3_VERSION);
284 }
285 if (!rc) {
286 ERR(NULL, "Setting TLS min version failed (%s).", ERR_reason_error_string(ERR_get_error()));
287 return 1;
288 }
289
290 /* then set the maximum version */
291 if (tls_versions & NC_TLS_VERSION_13) {
292 rc = SSL_CTX_set_max_proto_version(tls_cfg, TLS1_3_VERSION);
293 } else if (tls_versions & NC_TLS_VERSION_12) {
294 rc = SSL_CTX_set_max_proto_version(tls_cfg, TLS1_2_VERSION);
295 } else if (tls_versions & NC_TLS_VERSION_11) {
296 rc = SSL_CTX_set_max_proto_version(tls_cfg, TLS1_1_VERSION);
297 } else if (tls_versions & NC_TLS_VERSION_10) {
298 rc = SSL_CTX_set_max_proto_version(tls_cfg, TLS1_VERSION);
299 }
300 if (!rc) {
301 ERR(NULL, "Setting TLS max version failed (%s).", ERR_reason_error_string(ERR_get_error()));
302 return 1;
303 }
304
305 return 0;
306}
307
308static int
309nc_server_tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
310{
311 int ret = 0, depth, err;
312 struct nc_tls_verify_cb_data *data;
313 SSL *ssl;
roman7ef57992024-04-23 15:08:45 +0200314 SSL_CTX *ctx;
roman163f1662024-04-04 09:26:42 +0200315 X509 *cert;
316
317 /* retrieve callback data stored in the SSL struct */
318 ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
roman7ef57992024-04-23 15:08:45 +0200319 ctx = SSL_get_SSL_CTX(ssl);
320 data = SSL_CTX_get_ex_data(ctx, 0);
roman163f1662024-04-04 09:26:42 +0200321
322 /* get current cert and its depth */
323 cert = X509_STORE_CTX_get_current_cert(x509_ctx);
324 depth = X509_STORE_CTX_get_error_depth(x509_ctx);
325
326 if (preverify_ok) {
327 /* in-built verification was successful */
328 ret = nc_server_tls_verify_cert(cert, depth, 0, data);
329 } else {
330 /* in-built verification failed, but the client still may be authenticated if:
331 * 1) the peer cert matches any configured end-entity cert
332 * 2) the peer cert has a valid chain of trust to any configured certificate authority cert
333 * otherwise just continue until we reach the peer cert (depth = 0)
334 */
335 err = X509_STORE_CTX_get_error(x509_ctx);
336 if ((depth == 0) && (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)) {
337 /* not trusted self-signed peer certificate, case 1) */
338 ret = nc_server_tls_verify_cert(cert, depth, 1, data);
339 } else if ((err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) || (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)) {
340 /* full chain of trust is invalid, but it may be valid partially, case 2) */
341 ret = nc_server_tls_verify_cert(cert, depth, 0, data);
roman7ef57992024-04-23 15:08:45 +0200342 } else if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
343 /* self-signed certificate in the chain, check if peer cert complies with 1) in order to continue,
344 * if yes, this callback will be called again with the same cert, but with preverify_ok = 1
345 */
346 cert = X509_STORE_CTX_get0_cert(x509_ctx);
347 ret = nc_server_tls_verify_peer_cert(cert, data->opts);
348 if (ret) {
349 VRB(NULL, "Cert verify: fail (%s).", X509_verify_cert_error_string(X509_STORE_CTX_get_error(x509_ctx)));
350 ret = -1;
351 } else {
352 X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
353 }
roman163f1662024-04-04 09:26:42 +0200354 } else {
355 VRB(NULL, "Cert verify: fail (%s).", X509_verify_cert_error_string(X509_STORE_CTX_get_error(x509_ctx)));
356 ret = 1;
357 }
358 }
359
360 if (ret == -1) {
361 /* fatal error */
362 return 0;
363 } else if (!ret) {
364 /* success */
365 return 1;
366 } else {
367 if (depth > 0) {
368 /* chain verify failed */
369 return 1;
370 } else {
371 /* peer cert did not match */
372 return 0;
373 }
374 }
375}
376
377void
roman7ef57992024-04-23 15:08:45 +0200378nc_server_tls_set_verify_wrap(void *tls_cfg, struct nc_tls_verify_cb_data *cb_data)
roman163f1662024-04-04 09:26:42 +0200379{
roman7ef57992024-04-23 15:08:45 +0200380 /* set verify cb and its data */
381 SSL_CTX_set_ex_data(tls_cfg, 0, cb_data);
382 SSL_CTX_set_verify(tls_cfg, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nc_server_tls_verify_cb);
383}
384
385void
386nc_client_tls_set_verify_wrap(void *tls_cfg)
387{
388 SSL_CTX_set_verify(tls_cfg, SSL_VERIFY_PEER, NULL);
roman163f1662024-04-04 09:26:42 +0200389}
390
391char *
392nc_server_tls_get_subject_wrap(void *cert)
393{
394 return X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
395}
396
397char *
398nc_server_tls_get_issuer_wrap(void *cert)
399{
400 return X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
401}
402
roman7ef57992024-04-23 15:08:45 +0200403void *
404nc_tls_get_sans_wrap(void *cert)
roman163f1662024-04-04 09:26:42 +0200405{
roman7ef57992024-04-23 15:08:45 +0200406 return X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
407}
408
409void
410nc_tls_sans_destroy_wrap(void *sans)
411{
412 sk_GENERAL_NAME_pop_free(sans, GENERAL_NAME_free);
413}
414
415int
416nc_tls_get_num_sans_wrap(void *sans)
417{
418 return sk_GENERAL_NAME_num(sans);
419}
420
421int
422nc_tls_get_san_value_type_wrap(void *sans, int idx, char **san_value, NC_TLS_CTN_MAPTYPE *san_type)
423{
424 int ret = 0;
425 GENERAL_NAME *san;
roman163f1662024-04-04 09:26:42 +0200426 ASN1_OCTET_STRING *ip;
roman163f1662024-04-04 09:26:42 +0200427
roman7ef57992024-04-23 15:08:45 +0200428 *san_value = NULL;
429 *san_type = NC_TLS_CTN_UNKNOWN;
roman163f1662024-04-04 09:26:42 +0200430
roman7ef57992024-04-23 15:08:45 +0200431 /* find the san */
432 san = sk_GENERAL_NAME_value(sans, idx);
433 if (!san) {
434 return -1;
roman163f1662024-04-04 09:26:42 +0200435 }
436
roman7ef57992024-04-23 15:08:45 +0200437 /* get its type and value */
438 switch (san->type) {
439 case GEN_EMAIL:
440 *san_type = NC_TLS_CTN_SAN_RFC822_NAME;
441 *san_value = strdup((char *)ASN1_STRING_get0_data(san->d.rfc822Name));
442 NC_CHECK_ERRMEM_RET(!*san_value, -1);
443 break;
444 case GEN_DNS:
445 *san_type = NC_TLS_CTN_SAN_DNS_NAME;
446 *san_value = strdup((char *)ASN1_STRING_get0_data(san->d.dNSName));
447 NC_CHECK_ERRMEM_RET(!*san_value, -1);
448 break;
449 case GEN_IPADD:
450 *san_type = NC_TLS_CTN_SAN_IP_ADDRESS;
451 ip = san->d.iPAddress;
452 if (ip->length == 4) {
453 if (asprintf(san_value, "%d.%d.%d.%d", ip->data[0], ip->data[1], ip->data[2], ip->data[3]) == -1) {
454 ERRMEM;
455 *san_value = NULL;
456 ret = -1;
457 }
458 } else if (ip->length == 16) {
459 if (asprintf(san_value, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
460 ip->data[0], ip->data[1], ip->data[2], ip->data[3], ip->data[4], ip->data[5],
461 ip->data[6], ip->data[7], ip->data[8], ip->data[9], ip->data[10], ip->data[11],
462 ip->data[12], ip->data[13], ip->data[14], ip->data[15]) == -1) {
463 ERRMEM;
464 *san_value = NULL;
465 ret = -1;
466 }
467 } else {
468 WRN(NULL, "SAN IP address in an unknown format (length is %d).", ip->length);
469 ret = 1;
470 }
471 break;
472 default:
473 /* we dont care about other types */
474 *san_type = NC_TLS_CTN_UNKNOWN;
475 ret = 1;
476 break;
477 }
478
479 return ret;
roman163f1662024-04-04 09:26:42 +0200480}
481
482int
483nc_server_tls_certs_match_wrap(void *cert1, void *cert2)
484{
485 return !X509_cmp(cert1, cert2);
486}
487
488int
489nc_server_tls_md5_wrap(void *cert, unsigned char *buf)
490{
491 int rc;
492
493 rc = X509_digest(cert, EVP_md5(), buf, NULL);
roman7ef57992024-04-23 15:08:45 +0200494 if (!rc) {
roman163f1662024-04-04 09:26:42 +0200495 ERR(NULL, "Calculating MD-5 digest failed (%s).", ERR_reason_error_string(ERR_get_error()));
496 return 1;
497 }
498
499 return 0;
500}
501
502int
503nc_server_tls_sha1_wrap(void *cert, unsigned char *buf)
504{
505 int rc;
506
507 rc = X509_digest(cert, EVP_sha1(), buf, NULL);
roman7ef57992024-04-23 15:08:45 +0200508 if (!rc) {
roman163f1662024-04-04 09:26:42 +0200509 ERR(NULL, "Calculating SHA-1 digest failed (%s).", ERR_reason_error_string(ERR_get_error()));
510 return 1;
511 }
512
513 return 0;
514}
515
516int
517nc_server_tls_sha224_wrap(void *cert, unsigned char *buf)
518{
519 int rc;
520
521 rc = X509_digest(cert, EVP_sha224(), buf, NULL);
roman7ef57992024-04-23 15:08:45 +0200522 if (!rc) {
roman163f1662024-04-04 09:26:42 +0200523 ERR(NULL, "Calculating SHA-224 digest failed (%s).", ERR_reason_error_string(ERR_get_error()));
524 return 1;
525 }
526
527 return 0;
528}
529
530int
531nc_server_tls_sha256_wrap(void *cert, unsigned char *buf)
532{
533 int rc;
534
535 rc = X509_digest(cert, EVP_sha256(), buf, NULL);
roman7ef57992024-04-23 15:08:45 +0200536 if (!rc) {
roman163f1662024-04-04 09:26:42 +0200537 ERR(NULL, "Calculating SHA-256 digest failed (%s).", ERR_reason_error_string(ERR_get_error()));
538 return 1;
539 }
540
541 return 0;
542}
543
544int
545nc_server_tls_sha384_wrap(void *cert, unsigned char *buf)
546{
547 int rc;
548
549 rc = X509_digest(cert, EVP_sha384(), buf, NULL);
roman7ef57992024-04-23 15:08:45 +0200550 if (!rc) {
roman163f1662024-04-04 09:26:42 +0200551 ERR(NULL, "Calculating SHA-384 digest failed (%s).", ERR_reason_error_string(ERR_get_error()));
552 return 1;
553 }
554
555 return 0;
556}
557
558int
559nc_server_tls_sha512_wrap(void *cert, unsigned char *buf)
560{
561 int rc;
562
563 rc = X509_digest(cert, EVP_sha512(), buf, NULL);
roman7ef57992024-04-23 15:08:45 +0200564 if (!rc) {
roman163f1662024-04-04 09:26:42 +0200565 ERR(NULL, "Calculating SHA-512 digest failed (%s).", ERR_reason_error_string(ERR_get_error()));
566 return 1;
567 }
568
569 return 0;
570}
571
572void
573nc_server_tls_set_fd_wrap(void *tls_session, int sock, struct nc_tls_ctx *UNUSED(tls_ctx))
574{
575 SSL_set_fd(tls_session, sock);
576}
577
578int
579nc_server_tls_handshake_step_wrap(void *tls_session)
580{
581 int ret = 0;
582
583 ret = SSL_accept(tls_session);
584 if (ret == 1) {
585 return 1;
586 } else if (ret == -1) {
587 if ((SSL_get_error(tls_session, ret) == SSL_ERROR_WANT_READ) || (SSL_get_error(tls_session, ret) == SSL_ERROR_WANT_WRITE)) {
588 return 0;
589 }
590 }
591
592 return -1;
593}
594
595int
roman7ef57992024-04-23 15:08:45 +0200596nc_client_tls_handshake_step_wrap(void *tls_session, int UNUSED(sock))
roman163f1662024-04-04 09:26:42 +0200597{
598 int ret = 0;
599
600 ret = SSL_connect(tls_session);
601 if (ret == 1) {
602 return 1;
603 } else if (ret == -1) {
604 if ((SSL_get_error(tls_session, ret) == SSL_ERROR_WANT_READ) || (SSL_get_error(tls_session, ret) == SSL_ERROR_WANT_WRITE)) {
605 return 0;
606 }
607 }
608
609 return -1;
610}
611
612void
613nc_tls_ctx_destroy_wrap(struct nc_tls_ctx *UNUSED(tls_ctx))
614{
615 return;
616}
617
618int
619nc_client_tls_load_cert_key_wrap(const char *cert_path, const char *key_path, void **cert, void **pkey)
620{
621 BIO *bio;
622 X509 *cert_tmp;
623 EVP_PKEY *pkey_tmp;
624
roman7ef57992024-04-23 15:08:45 +0200625 NC_CHECK_ARG_RET(NULL, cert_path, key_path, cert, pkey, 1);
626
roman163f1662024-04-04 09:26:42 +0200627 bio = BIO_new_file(cert_path, "r");
628 if (!bio) {
629 ERR(NULL, "Opening the client certificate file \"%s\" failed.", cert_path);
630 return 1;
631 }
632
633 cert_tmp = PEM_read_bio_X509(bio, NULL, NULL, NULL);
634 BIO_free(bio);
635 if (!cert_tmp) {
636 ERR(NULL, "Parsing the client certificate file \"%s\" failed.", cert_path);
637 return 1;
638 }
639
640 bio = BIO_new_file(key_path, "r");
641 if (!bio) {
642 ERR(NULL, "Opening the client private key file \"%s\" failed.", key_path);
643 X509_free(cert_tmp);
644 return 1;
645 }
646
647 pkey_tmp = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
648 BIO_free(bio);
649 if (!pkey_tmp) {
650 ERR(NULL, "Parsing the client private key file \"%s\" failed.", key_path);
651 X509_free(cert_tmp);
652 return 1;
653 }
654
655 *cert = cert_tmp;
656 *pkey = pkey_tmp;
657
658 return 0;
659}
660
661int
662nc_client_tls_load_trusted_certs_wrap(void *cert_store, const char *file_path, const char *dir_path)
663{
664 if (!X509_STORE_load_locations(cert_store, file_path, dir_path)) {
665 ERR(NULL, "Loading CA certs from file \"%s\" or directory \"%s\" failed (%s).", file_path, dir_path, ERR_reason_error_string(ERR_get_error()));
666 return 1;
667 }
668
669 return 0;
670}
671
672int
roman7ef57992024-04-23 15:08:45 +0200673nc_client_tls_load_crl_wrap(void *crl_store, const char *file_path, const char *dir_path)
roman163f1662024-04-04 09:26:42 +0200674{
roman7ef57992024-04-23 15:08:45 +0200675 if (!X509_STORE_load_locations(crl_store, file_path, dir_path)) {
roman163f1662024-04-04 09:26:42 +0200676 ERR(NULL, "Loading CRLs from file \"%s\" or directory \"%s\" failed (%s).", file_path, dir_path, ERR_reason_error_string(ERR_get_error()));
677 return 1;
678 }
679
680 return 0;
681}
682
683int
684nc_client_tls_set_hostname_wrap(void *tls_session, const char *hostname)
685{
686 int ret = 0;
687 X509_VERIFY_PARAM *vpm = NULL;
688
689 vpm = X509_VERIFY_PARAM_new();
690 NC_CHECK_ERRMEM_RET(!vpm, 1);
691
692 if (!X509_VERIFY_PARAM_set1_host(vpm, hostname, 0)) {
693 ERR(NULL, "Failed to set expected hostname (%s).", ERR_reason_error_string(ERR_get_error()));
694 ret = 1;
695 goto cleanup;
696 }
roman7ef57992024-04-23 15:08:45 +0200697 if (!SSL_set1_param(tls_session, vpm)) {
roman163f1662024-04-04 09:26:42 +0200698 ERR(NULL, "Failed to set verify param (%s).", ERR_reason_error_string(ERR_get_error()));
699 ret = 1;
700 goto cleanup;
701 }
702
703cleanup:
704 X509_VERIFY_PARAM_free(vpm);
705 return ret;
706}
707
roman7ef57992024-04-23 15:08:45 +0200708int
709nc_tls_init_ctx_wrap(int UNUSED(sock), void *cert, void *pkey, void *cert_store, void *crl_store, struct nc_tls_ctx *tls_ctx)
710{
711 tls_ctx->cert = cert;
712 tls_ctx->pkey = pkey;
713 tls_ctx->cert_store = cert_store;
714 tls_ctx->crl_store = crl_store;
715 return 0;
716}
717
718static int
719nc_tls_move_crls_to_store(const X509_STORE *src, X509_STORE *dst)
720{
721 int i, nobjs = 0;
722
723 STACK_OF(X509_OBJECT) * objs;
724 X509_OBJECT *obj;
725 X509_CRL *crl;
726
727 objs = X509_STORE_get0_objects(src);
728 nobjs = sk_X509_OBJECT_num(objs);
729 for (i = 0; i < nobjs; i++) {
730 obj = sk_X509_OBJECT_value(objs, i);
731 crl = X509_OBJECT_get0_X509_CRL(obj);
732 if (!crl) {
733 /* not a CRL */
734 continue;
735 }
736 if (!X509_STORE_add_crl(dst, crl)) {
737 ERR(NULL, "Adding CRL to the store failed (%s).", ERR_reason_error_string(ERR_get_error()));
738 return 1;
739 }
740 }
741
742 return 0;
743}
744
745int
746nc_tls_setup_config_from_ctx_wrap(struct nc_tls_ctx *tls_ctx, int UNUSED(side), void *tls_cfg)
747{
748 if (SSL_CTX_use_certificate(tls_cfg, tls_ctx->cert) != 1) {
749 return 1;
750 }
751
752 if (SSL_CTX_use_PrivateKey(tls_cfg, tls_ctx->pkey) != 1) {
753 return 1;
754 }
755
756 SSL_CTX_set_mode(tls_cfg, SSL_MODE_AUTO_RETRY);
757
758 if (tls_ctx->crl_store) {
759 /* move CRLs from crl_store to cert_store, because SSL_CTX can only have one store */
760 if (nc_tls_move_crls_to_store(tls_ctx->crl_store, tls_ctx->cert_store)) {
761 return 1;
762 }
763
764 /* enable CRL checks */
765 X509_STORE_set_flags(tls_ctx->cert_store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
766 }
767
768 SSL_CTX_set_cert_store(tls_cfg, tls_ctx->cert_store);
769
770 X509_free(tls_ctx->cert);
771 tls_ctx->cert = NULL;
772 EVP_PKEY_free(tls_ctx->pkey);
773 tls_ctx->pkey = NULL;
774 X509_STORE_free(tls_ctx->crl_store);
775 tls_ctx->crl_store = NULL;
776
777 return 0;
778}
779
roman163f1662024-04-04 09:26:42 +0200780uint32_t
781nc_tls_get_verify_result_wrap(void *tls_session)
782{
783 return SSL_get_verify_result(tls_session);
784}
785
roman7ef57992024-04-23 15:08:45 +0200786char *
roman163f1662024-04-04 09:26:42 +0200787nc_tls_verify_error_string_wrap(uint32_t err_code)
788{
roman7ef57992024-04-23 15:08:45 +0200789 return strdup(X509_verify_cert_error_string(err_code));
roman163f1662024-04-04 09:26:42 +0200790}
791
792void
roman7ef57992024-04-23 15:08:45 +0200793nc_client_tls_print_connect_err_wrap(int connect_ret, const char *peername, void *tls_session)
roman163f1662024-04-04 09:26:42 +0200794{
795 switch (SSL_get_error(tls_session, connect_ret)) {
796 case SSL_ERROR_SYSCALL:
797 ERR(NULL, "TLS connection to \"%s\" failed (%s).", peername, errno ? strerror(errno) : "unexpected EOF");
798 break;
799 case SSL_ERROR_SSL:
800 ERR(NULL, "TLS connection to \"%s\" failed (%s).", peername, ERR_reason_error_string(ERR_get_error()));
801 break;
802 default:
803 ERR(NULL, "TLS connection to \"%s\" failed.", peername);
804 break;
805 }
806}
807
808void
roman7ef57992024-04-23 15:08:45 +0200809nc_server_tls_print_accept_err_wrap(int accept_ret, void *tls_session)
roman163f1662024-04-04 09:26:42 +0200810{
811 switch (SSL_get_error(tls_session, accept_ret)) {
812 case SSL_ERROR_SYSCALL:
813 ERR(NULL, "TLS accept failed (%s).", strerror(errno));
814 break;
815 case SSL_ERROR_SSL:
816 ERR(NULL, "TLS accept failed (%s).", ERR_reason_error_string(ERR_get_error()));
817 break;
818 default:
819 ERR(NULL, "TLS accept failed.");
820 break;
821 }
822}
823
824int
roman7ef57992024-04-23 15:08:45 +0200825nc_tls_is_der_subpubkey_wrap(unsigned char *der, long len)
roman163f1662024-04-04 09:26:42 +0200826{
827 int ret;
828 EVP_PKEY *pkey;
829
roman7ef57992024-04-23 15:08:45 +0200830 pkey = d2i_PUBKEY(NULL, (const unsigned char **)&der, len);
roman163f1662024-04-04 09:26:42 +0200831 if (pkey) {
832 /* success */
roman7ef57992024-04-23 15:08:45 +0200833 ret = 1;
roman163f1662024-04-04 09:26:42 +0200834 } else {
835 /* fail */
roman7ef57992024-04-23 15:08:45 +0200836 ret = 0;
roman163f1662024-04-04 09:26:42 +0200837 }
838
839 EVP_PKEY_free(pkey);
840 return ret;
841}
842
843int
roman7ef57992024-04-23 15:08:45 +0200844nc_base64_decode_wrap(const char *base64, unsigned char **bin)
roman163f1662024-04-04 09:26:42 +0200845{
roman7ef57992024-04-23 15:08:45 +0200846 int ret;
roman163f1662024-04-04 09:26:42 +0200847
roman7ef57992024-04-23 15:08:45 +0200848 *bin = malloc((strlen(base64) / 4) * 3);
849 NC_CHECK_ERRMEM_RET(!*bin, -1);
roman163f1662024-04-04 09:26:42 +0200850
roman7ef57992024-04-23 15:08:45 +0200851 ret = EVP_DecodeBlock(*bin, (const unsigned char *)base64, strlen(base64));
852 if (ret == -1) {
853 ERR(NULL, "Base64 decoding failed (%s).", ERR_reason_error_string(ERR_get_error()));
854 free(*bin);
855 *bin = NULL;
roman163f1662024-04-04 09:26:42 +0200856 }
roman163f1662024-04-04 09:26:42 +0200857 return ret;
858}
859
860int
861nc_base64_encode_wrap(const unsigned char *bin, size_t len, char **base64)
862{
roman7ef57992024-04-23 15:08:45 +0200863 int ret, size;
roman163f1662024-04-04 09:26:42 +0200864
roman7ef57992024-04-23 15:08:45 +0200865 /* calculate the size, for every 3B of in 4B of out, + padding if not divisible + null terminator */
866 if (len % 3) {
867 size = (len / 3) * 4 + 4 + 1;
868 } else {
869 size = (len / 3) * 4 + 1;
roman163f1662024-04-04 09:26:42 +0200870 }
871
roman7ef57992024-04-23 15:08:45 +0200872 *base64 = malloc(size);
873 NC_CHECK_ERRMEM_RET(!*base64, -1);
874
875 ret = EVP_EncodeBlock((unsigned char *)*base64, bin, len);
876 if (ret == -1) {
877 ERR(NULL, "Base64 encoding failed (%s).", ERR_reason_error_string(ERR_get_error()));
878 free(*base64);
879 *base64 = NULL;
880 return -1;
roman163f1662024-04-04 09:26:42 +0200881 }
882
roman7ef57992024-04-23 15:08:45 +0200883 return 0;
roman163f1662024-04-04 09:26:42 +0200884}
885
886static char *
roman7ef57992024-04-23 15:08:45 +0200887nc_tls_get_err_reasons(void)
roman163f1662024-04-04 09:26:42 +0200888{
889 unsigned int e;
890 int reason_size, reason_len;
891 char *reasons = NULL;
892
893 reason_size = 1;
894 reason_len = 0;
895 while ((e = ERR_get_error())) {
896 if (reason_len) {
897 /* add "; " */
898 reason_size += 2;
899 reasons = nc_realloc(reasons, reason_size);
900 NC_CHECK_ERRMEM_RET(!reasons, NULL);
901 reason_len += sprintf(reasons + reason_len, "; ");
902 }
903 reason_size += strlen(ERR_reason_error_string(e));
904 reasons = nc_realloc(reasons, reason_size);
905 NC_CHECK_ERRMEM_RET(!reasons, NULL);
906 reason_len += sprintf(reasons + reason_len, "%s", ERR_reason_error_string(e));
907 }
908
909 return reasons;
910}
911
912int
913nc_tls_read_wrap(struct nc_session *session, unsigned char *buf, size_t size)
914{
915 int rc, err;
916 char *reasons;
917 SSL *tls_session = session->ti.tls.session;
918
919 ERR_clear_error();
920 rc = SSL_read(tls_session, buf, size);
921 if (rc <= 0) {
922 err = SSL_get_error(tls_session, rc);
923 switch (err) {
924 case SSL_ERROR_WANT_READ:
925 case SSL_ERROR_WANT_WRITE:
926 rc = 0;
927 break;
928 case SSL_ERROR_ZERO_RETURN:
929 ERR(session, "Communication socket unexpectedly closed (OpenSSL).");
930 session->status = NC_STATUS_INVALID;
931 session->term_reason = NC_SESSION_TERM_DROPPED;
932 rc = -1;
933 break;
934 case SSL_ERROR_SYSCALL:
935 ERR(session, "TLS socket error (%s).", errno ? strerror(errno) : "unexpected EOF");
936 session->status = NC_STATUS_INVALID;
937 session->term_reason = NC_SESSION_TERM_OTHER;
938 rc = -1;
939 break;
940 case SSL_ERROR_SSL:
roman7ef57992024-04-23 15:08:45 +0200941 reasons = nc_tls_get_err_reasons();
roman163f1662024-04-04 09:26:42 +0200942 ERR(session, "TLS communication error (%s).", reasons);
943 free(reasons);
944 session->status = NC_STATUS_INVALID;
945 session->term_reason = NC_SESSION_TERM_OTHER;
946 rc = -1;
947 break;
948 default:
949 ERR(session, "Unknown TLS error occurred (err code %d).", err);
950 session->status = NC_STATUS_INVALID;
951 session->term_reason = NC_SESSION_TERM_OTHER;
952 rc = -1;
953 break;
954 }
955 }
956
957 return rc;
958}
959
960int
961nc_tls_write_wrap(struct nc_session *session, const unsigned char *buf, size_t size)
962{
963 int rc, err;
964 char *reasons;
965 SSL *tls_session = session->ti.tls.session;
966
967 ERR_clear_error();
968 rc = SSL_write(tls_session, buf, size);
969 if (rc < 1) {
970 err = SSL_get_error(tls_session, rc);
971 switch (err) {
972 case SSL_ERROR_WANT_WRITE:
973 case SSL_ERROR_WANT_READ:
974 rc = 0;
975 break;
976 case SSL_ERROR_ZERO_RETURN:
977 ERR(session, "TLS connection was properly closed.");
978 rc = -1;
979 break;
980 case SSL_ERROR_SYSCALL:
981 ERR(session, "TLS socket error (%s).", errno ? strerror(errno) : "unexpected EOF");
982 rc = -1;
983 break;
984 case SSL_ERROR_SSL:
roman7ef57992024-04-23 15:08:45 +0200985 reasons = nc_tls_get_err_reasons();
roman163f1662024-04-04 09:26:42 +0200986 ERR(session, "TLS communication error (%s).", reasons);
987 free(reasons);
988 rc = -1;
989 break;
990 default:
991 ERR(session, "Unknown TLS error occurred (err code %d).", err);
992 rc = -1;
993 break;
994 }
995 }
996
997 return rc;
998}
999
1000int
roman7ef57992024-04-23 15:08:45 +02001001nc_tls_get_num_pending_bytes_wrap(void *tls_session)
roman163f1662024-04-04 09:26:42 +02001002{
1003 return SSL_pending(tls_session);
1004}
1005
1006int
1007nc_tls_get_fd_wrap(const struct nc_session *session)
1008{
roman7ef57992024-04-23 15:08:45 +02001009 return session->ti.tls.session ? SSL_get_fd(session->ti.tls.session) : -1;
roman163f1662024-04-04 09:26:42 +02001010}
1011
1012void
1013nc_tls_close_notify_wrap(void *tls_session)
1014{
1015 SSL_shutdown(tls_session);
1016}
1017
1018void *
roman7ef57992024-04-23 15:08:45 +02001019nc_tls_import_privkey_file_wrap(const char *key_path)
roman163f1662024-04-04 09:26:42 +02001020{
1021 EVP_PKEY *pkey;
roman7ef57992024-04-23 15:08:45 +02001022 FILE *file;
1023
1024 file = fopen(key_path, "r");
1025 if (!file) {
1026 ERR(NULL, "Opening the private key file \"%s\" failed.", key_path);
1027 return NULL;
1028 }
roman163f1662024-04-04 09:26:42 +02001029
1030 pkey = PEM_read_PrivateKey(file, NULL, NULL, NULL);
roman7ef57992024-04-23 15:08:45 +02001031 fclose(file);
roman163f1662024-04-04 09:26:42 +02001032 if (!pkey) {
1033 ERR(NULL, "Parsing the private key file \"%s\" failed (%s).", key_path, ERR_reason_error_string(ERR_get_error()));
1034 }
1035
1036 return pkey;
1037}
1038
1039void *
1040nc_tls_import_cert_file_wrap(const char *cert_path)
1041{
1042 X509 *cert;
1043 FILE *file;
1044
1045 file = fopen(cert_path, "r");
1046 if (!file) {
1047 ERR(NULL, "Opening the certificate file \"%s\" failed.", cert_path);
1048 return NULL;
1049 }
1050
1051 cert = PEM_read_X509(file, NULL, NULL, NULL);
1052 fclose(file);
1053 if (!cert) {
1054 ERR(NULL, "Parsing the certificate file \"%s\" failed (%s).", cert_path, ERR_reason_error_string(ERR_get_error()));
1055 }
1056 return cert;
1057}
1058
1059char *
roman7ef57992024-04-23 15:08:45 +02001060nc_tls_export_privkey_pem_wrap(void *pkey)
roman163f1662024-04-04 09:26:42 +02001061{
1062 BIO *bio = NULL;
1063 char *pem = NULL;
1064
1065 bio = BIO_new(BIO_s_mem());
1066 if (!bio) {
1067 ERR(NULL, "Creating new bio failed (%s).", ERR_reason_error_string(ERR_get_error()));
1068 goto cleanup;
1069 }
1070
1071 if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) {
1072 ERR(NULL, "Exporting the private key failed (%s).", ERR_reason_error_string(ERR_get_error()));
1073 goto cleanup;
1074 }
1075
1076 pem = malloc(BIO_number_written(bio) + 1);
1077 NC_CHECK_ERRMEM_GOTO(!pem, , cleanup);
1078
1079 BIO_read(bio, pem, BIO_number_written(bio));
1080 pem[BIO_number_written(bio)] = '\0';
1081
1082cleanup:
1083 BIO_free(bio);
1084 return pem;
1085}
1086
1087char *
roman7ef57992024-04-23 15:08:45 +02001088nc_tls_export_cert_pem_wrap(void *cert)
roman163f1662024-04-04 09:26:42 +02001089{
roman163f1662024-04-04 09:26:42 +02001090 BIO *bio = NULL;
1091 char *pem = NULL;
1092
1093 bio = BIO_new(BIO_s_mem());
1094 if (!bio) {
1095 ERR(NULL, "Creating new bio failed (%s).", ERR_reason_error_string(ERR_get_error()));
1096 goto cleanup;
1097 }
1098
roman7ef57992024-04-23 15:08:45 +02001099 if (!PEM_write_bio_X509(bio, cert)) {
roman163f1662024-04-04 09:26:42 +02001100 ERR(NULL, "Exporting the certificate failed (%s).", ERR_reason_error_string(ERR_get_error()));
1101 goto cleanup;
1102 }
1103
roman7ef57992024-04-23 15:08:45 +02001104 pem = malloc(BIO_number_written(bio) + 1);
roman163f1662024-04-04 09:26:42 +02001105 NC_CHECK_ERRMEM_GOTO(!pem, , cleanup);
1106
roman7ef57992024-04-23 15:08:45 +02001107 BIO_read(bio, pem, BIO_number_written(bio));
1108 pem[BIO_number_written(bio)] = '\0';
roman163f1662024-04-04 09:26:42 +02001109
1110cleanup:
1111 BIO_free(bio);
1112 return pem;
1113}
1114
1115char *
roman7ef57992024-04-23 15:08:45 +02001116nc_tls_export_pubkey_pem_wrap(void *pkey)
roman163f1662024-04-04 09:26:42 +02001117{
1118 BIO *bio = NULL;
1119 char *pem = NULL;
1120
1121 bio = BIO_new(BIO_s_mem());
1122 if (!bio) {
1123 ERR(NULL, "Creating new bio failed (%s).", ERR_reason_error_string(ERR_get_error()));
1124 goto cleanup;
1125 }
1126
1127 if (!PEM_write_bio_PUBKEY(bio, pkey)) {
1128 ERR(NULL, "Exporting the public key failed (%s).", ERR_reason_error_string(ERR_get_error()));
1129 goto cleanup;
1130 }
1131
1132 pem = malloc(BIO_number_written(bio) + 1);
1133 NC_CHECK_ERRMEM_GOTO(!pem, , cleanup);
1134
1135 BIO_read(bio, pem, BIO_number_written(bio));
1136 pem[BIO_number_written(bio)] = '\0';
1137
1138cleanup:
1139 BIO_free(bio);
1140 return pem;
1141}
1142
1143int
roman163f1662024-04-04 09:26:42 +02001144nc_tls_privkey_is_rsa_wrap(void *pkey)
1145{
1146 return EVP_PKEY_is_a(pkey, "RSA");
1147}
1148
1149int
1150nc_tls_get_rsa_pubkey_params_wrap(void *pkey, void **e, void **n)
1151{
roman7ef57992024-04-23 15:08:45 +02001152 BIGNUM *exp = NULL, *mod = NULL;
roman163f1662024-04-04 09:26:42 +02001153
1154 if (!EVP_PKEY_get_bn_param(pkey, "e", &exp)) {
1155 ERR(NULL, "Getting the RSA public exponent failed (%s).", ERR_reason_error_string(ERR_get_error()));
1156 return 1;
1157 }
1158
1159 if (!EVP_PKEY_get_bn_param(pkey, "n", &mod)) {
1160 ERR(NULL, "Getting the RSA modulus failed (%s).", ERR_reason_error_string(ERR_get_error()));
1161 BN_free(exp);
1162 return 1;
1163 }
1164
1165 *e = exp;
1166 *n = mod;
1167 return 0;
1168}
1169
roman7ef57992024-04-23 15:08:45 +02001170void
1171nc_tls_destroy_mpi_wrap(void *mpi)
1172{
1173 BN_free(mpi);
1174}
1175
roman163f1662024-04-04 09:26:42 +02001176int
1177nc_tls_privkey_is_ec_wrap(void *pkey)
1178{
1179 return EVP_PKEY_is_a(pkey, "EC");
1180}
1181
1182char *
1183nc_tls_get_ec_group_wrap(void *pkey)
1184{
1185 size_t ec_group_len = 0;
1186 char *ec_group = NULL;
1187
1188 if (!EVP_PKEY_get_utf8_string_param(pkey, "group", NULL, 0, &ec_group_len)) {
1189 ERR(NULL, "Getting EC group length failed (%s).", ERR_reason_error_string(ERR_get_error()));
1190 return NULL;
1191 }
1192
1193 /* alloc mem for group + 1 for \0 */
1194 ec_group = malloc(ec_group_len + 1);
1195 NC_CHECK_ERRMEM_RET(!ec_group, NULL);
1196
1197 /* get the group */
1198 if (!EVP_PKEY_get_utf8_string_param(pkey, "group", ec_group, ec_group_len + 1, NULL)) {
1199 ERR(NULL, "Getting EC group failed (%s).", ERR_reason_error_string(ERR_get_error()));
1200 free(ec_group);
1201 return NULL;
1202 }
1203
1204 return ec_group;
1205}
1206
1207int
roman7ef57992024-04-23 15:08:45 +02001208nc_tls_get_ec_pubkey_params_wrap(void *pkey, void **q, void **UNUSED(q_grp))
roman163f1662024-04-04 09:26:42 +02001209{
roman7ef57992024-04-23 15:08:45 +02001210 BIGNUM *p = NULL;
roman163f1662024-04-04 09:26:42 +02001211
1212 if (!EVP_PKEY_get_bn_param(pkey, "p", &p)) {
1213 ERR(NULL, "Getting public key point from the EC private key failed (%s).", ERR_reason_error_string(ERR_get_error()));
roman7ef57992024-04-23 15:08:45 +02001214 return 1;
roman163f1662024-04-04 09:26:42 +02001215 }
1216
roman7ef57992024-04-23 15:08:45 +02001217 *q = p;
roman163f1662024-04-04 09:26:42 +02001218
roman7ef57992024-04-23 15:08:45 +02001219 return 0;
roman163f1662024-04-04 09:26:42 +02001220}
1221
1222int
roman7ef57992024-04-23 15:08:45 +02001223nc_tls_ec_point_to_bin_wrap(void *q, void *UNUSED(q_grp), unsigned char **bin, int *bin_len)
roman163f1662024-04-04 09:26:42 +02001224{
roman7ef57992024-04-23 15:08:45 +02001225 /* prepare buffer for converting p to binary */
1226 *bin = malloc(BN_num_bytes(q));
1227 NC_CHECK_ERRMEM_RET(!*bin, 1);
1228
1229 /* convert to binary */
1230 *bin_len = BN_bn2bin(q, *bin);
1231 return 0;
roman163f1662024-04-04 09:26:42 +02001232}
1233
1234void
roman7ef57992024-04-23 15:08:45 +02001235nc_tls_ec_point_destroy_wrap(void *p)
roman163f1662024-04-04 09:26:42 +02001236{
roman7ef57992024-04-23 15:08:45 +02001237 BN_free(p);
1238}
1239
1240void
1241nc_tls_ec_group_destroy_wrap(void *UNUSED(grp))
1242{
1243 return;
1244}
1245
1246int
1247nc_tls_mpi2bin_wrap(void *mpi, unsigned char **bin, int *bin_len)
1248{
1249 /* prepare buffer for converting mpi to binary */
1250 *bin = malloc(BN_num_bytes(mpi));
1251 NC_CHECK_ERRMEM_RET(!*bin, 1);
1252
1253 /* convert to binary */
1254 *bin_len = BN_bn2bin(mpi, *bin);
1255 return 0;
roman163f1662024-04-04 09:26:42 +02001256}
1257
1258void *
1259nc_tls_import_pubkey_file_wrap(const char *pubkey_path)
1260{
1261 FILE *f;
1262 EVP_PKEY *pk = NULL;
1263
1264 f = fopen(pubkey_path, "r");
1265 if (!f) {
1266 ERR(NULL, "Unable to open file \"%s\".", pubkey_path);
1267 return NULL;
1268 }
1269
1270 /* read the pubkey from file */
1271 pk = PEM_read_PUBKEY(f, NULL, NULL, NULL);
1272 fclose(f);
1273 if (!pk) {
1274 ERR(NULL, "Reading public key from file \"%s\" failed (%s).", pubkey_path, ERR_reason_error_string(ERR_get_error()));
1275 return NULL;
1276 }
1277
1278 return pk;
1279}
roman275c3fb2024-04-05 12:29:11 +02001280
1281int
1282nc_server_tls_get_crl_distpoint_uris_wrap(void *cert_store, char ***uris, int *uri_count)
1283{
1284 int ret = 0, i, j, k, gtype;
roman275c3fb2024-04-05 12:29:11 +02001285
1286 STACK_OF(X509_OBJECT) * objs;
1287 X509_OBJECT *obj;
1288 X509 *cert;
1289
1290 STACK_OF(DIST_POINT) * dist_points;
1291 DIST_POINT *dist_point;
1292 GENERAL_NAMES *general_names;
1293 GENERAL_NAME *general_name;
1294 ASN1_STRING *asn_string_uri;
roman275c3fb2024-04-05 12:29:11 +02001295 void *tmp;
1296
1297 NC_CHECK_ARG_RET(NULL, cert_store, uris, uri_count, 1);
1298
1299 *uris = NULL;
1300 *uri_count = 0;
1301
1302 /* treat all entries in the cert_store as X509_OBJECTs */
1303 objs = X509_STORE_get0_objects(cert_store);
1304 if (!objs) {
1305 ERR(NULL, "Getting certificates from store failed (%s).", ERR_reason_error_string(ERR_get_error()));
1306 ret = -1;
1307 goto cleanup;
1308 }
1309
1310 /* iterate over all the CAs */
1311 for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
1312 obj = sk_X509_OBJECT_value(objs, i);
1313 cert = X509_OBJECT_get0_X509(obj);
1314 if (!cert) {
1315 /* the object on this index was not a certificate */
1316 continue;
1317 }
1318
1319 /* get all the distribution points for this CA */
1320 dist_points = X509_get_ext_d2i(cert, NID_crl_distribution_points, NULL, NULL);
1321
1322 /* iterate over all the dist points (there can be multiple for a single cert) */
1323 for (j = 0; j < sk_DIST_POINT_num(dist_points); j++) {
1324 dist_point = sk_DIST_POINT_value(dist_points, j);
1325 if (!dist_point) {
1326 continue;
1327 }
1328 general_names = dist_point->distpoint->name.fullname;
1329
1330 /* iterate over all the GeneralesNames in the distribution point */
1331 for (k = 0; k < sk_GENERAL_NAME_num(general_names); k++) {
1332 general_name = sk_GENERAL_NAME_value(general_names, k);
1333 asn_string_uri = GENERAL_NAME_get0_value(general_name, &gtype);
1334
1335 /* check if the general name is a URI and has a valid length */
1336 if ((gtype != GEN_URI) || (ASN1_STRING_length(asn_string_uri) <= 6)) {
1337 continue;
1338 }
1339
1340 /* found an URI */
1341 tmp = realloc(*uris, (*uri_count + 1) * sizeof **uris);
1342 NC_CHECK_ERRMEM_GOTO(!tmp, ret = 1, cleanup);
1343 *uris = tmp;
1344
1345 *uris[*uri_count] = strdup((const char *) ASN1_STRING_get0_data(asn_string_uri));
1346 NC_CHECK_ERRMEM_GOTO(!*uris[*uri_count], ret = 1, cleanup);
1347 ++(*uri_count);
1348 }
1349 }
1350 }
1351
1352cleanup:
1353 return ret;
1354}
roman7ef57992024-04-23 15:08:45 +02001355
1356int
1357nc_tls_process_cipher_suite_wrap(const char *cipher, char **out)
1358{
1359 int i;
1360
1361 *out = malloc(strlen(cipher) + 1);
1362 NC_CHECK_ERRMEM_RET(!*out, 1);
1363
1364 /* convert to uppercase */
1365 for (i = 0; cipher[i]; i++) {
1366 if (cipher[i] == '-') {
1367 /* OpenSSL requires _ instead of - in cipher names */
1368 (*out)[i] = '_';
1369 } else {
1370 (*out)[i] = toupper(cipher[i]);
1371 }
1372 }
1373
1374 (*out)[i] = '\0';
1375 return 0;
1376}
1377
1378int
1379nc_tls_append_cipher_suite_wrap(struct nc_server_tls_opts *opts, const char *cipher_suite)
1380{
1381 if (!opts->ciphers) {
1382 /* first entry */
1383 opts->ciphers = strdup(cipher_suite);
1384 NC_CHECK_ERRMEM_RET(!opts->ciphers, 1);
1385 } else {
1386 /* + 1 because of : between entries */
1387 opts->ciphers = nc_realloc(opts->ciphers, strlen(opts->ciphers) + strlen(cipher_suite) + 1 + 1);
1388 NC_CHECK_ERRMEM_RET(!opts->ciphers, 1);
1389 strcat(opts->ciphers, ":");
1390 strcat(opts->ciphers, cipher_suite);
1391 }
1392
1393 return 0;
1394}
1395
1396void
1397nc_server_tls_set_cipher_suites_wrap(void *tls_cfg, void *cipher_suites)
1398{
1399 /* set for TLS1.2 and lower */
1400 SSL_CTX_set_cipher_list(tls_cfg, cipher_suites);
1401 /* set for TLS1.3 */
1402 SSL_CTX_set_ciphersuites(tls_cfg, cipher_suites);
1403}