OpenVPN
ssl_verify_mbedtls.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2026 OpenVPN Inc <sales@openvpn.net>
9 * Copyright (C) 2010-2026 Sentyron B.V. <openvpn@sentyron.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2
13 * as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, see <https://www.gnu.org/licenses/>.
22 */
23
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "syshead.h"
34
35#if defined(ENABLE_CRYPTO_MBEDTLS)
36
37#include <mbedtls/version.h>
38
39#if MBEDTLS_VERSION_NUMBER < 0x04000000
41#include <mbedtls/bignum.h>
42#include <mbedtls/sha1.h>
43#else
44#include "crypto_mbedtls.h"
45#endif
46
47#include "mbedtls_compat.h"
48
49#include "ssl_verify.h"
50#include <mbedtls/asn1.h>
51#include <mbedtls/error.h>
52#include <mbedtls/oid.h>
53
54#define MAX_SUBJECT_LENGTH 256
55
56int
57verify_callback(void *session_obj, mbedtls_x509_crt *cert, int cert_depth, uint32_t *flags)
58{
59 struct tls_session *session = (struct tls_session *)session_obj;
60 struct gc_arena gc = gc_new();
61
62 ASSERT(cert);
64
65 session->verified = false;
66
67 /* Remember certificate hash */
70
71 if (session->opt->verify_hash_no_ca)
72 {
73 /*
74 * If we decide to verify the peer certificate based on the fingerprint
75 * we ignore wrong dates and the certificate not being trusted.
76 * Any other problem with the certificate (wrong key, bad cert,...)
77 * will still trigger an error.
78 * Clearing these flags relies on verify_cert will later rejecting a
79 * certificate that has no matching fingerprint.
80 */
83 *flags = *flags & ~flags_ignore;
84 }
85
86 /* did peer present cert which was signed by our root cert? */
87 if (*flags != 0)
88 {
89 int ret = 0;
90 char errstr[512] = { 0 };
91 char *subject = x509_get_subject(cert, &gc);
92 char *serial = backend_x509_get_serial(cert, &gc);
93
94 ret = mbedtls_x509_crt_verify_info(errstr, sizeof(errstr) - 1, "", *flags);
95 if (ret <= 0
96 && !checked_snprintf(errstr, sizeof(errstr), "Could not retrieve error string, flags=%" PRIx32, *flags))
97 {
98 errstr[0] = '\0';
99 }
100 else
101 {
102 chomp(errstr);
103 }
104
105 if (subject)
106 {
107 msg(D_TLS_ERRORS, "VERIFY ERROR: depth=%d, subject=%s, serial=%s: %s", cert_depth,
108 subject, serial ? serial : "<not available>", errstr);
109 }
110 else
111 {
113 "VERIFY ERROR: depth=%d, (could not extract X509 "
114 "subject string from certificate): %s",
116 }
117
118 /* Leave flags set to non-zero to indicate that the cert is not ok */
119 }
120 else if (SUCCESS != verify_cert(session, cert, cert_depth))
121 {
123 }
124
125 gc_free(&gc);
126
127 /*
128 * PolarSSL/mbed TLS-1.2.0+ expects 0 on anything except fatal errors.
129 */
130 return 0;
131}
132
133/* not supported for mbedTLS yet */
134bool
136{
137 return false;
138}
139
140static const char *
141fieldname_to_oid(const char *fieldname)
142{
143 if (strcmp(fieldname, "C") == 0)
144 {
146 }
147 else if (strcmp(fieldname, "ST") == 0)
148 {
150 }
151 else if (strcmp(fieldname, "LOCALITY") == 0)
152 {
154 }
155 else if (strcmp(fieldname, "O") == 0)
156 {
158 }
159 else if (strcmp(fieldname, "OU") == 0)
160 {
162 }
163 else if (strcmp(fieldname, "CN") == 0)
164 {
165 return MBEDTLS_OID_AT_CN;
166 }
167 else if (strcmp(fieldname, "GN") == 0)
168 {
170 }
171 else if (strcmp(fieldname, "SN") == 0)
172 {
174 }
175 else if (strcmp(fieldname, "initials") == 0)
176 {
178 }
179 else if (strcmp(fieldname, "pseudonym") == 0)
180 {
182 }
183 else if (strcmp(fieldname, "title") == 0)
184 {
186 }
187 else if (strcmp(fieldname, "generationQualifier") == 0)
188 {
190 }
191 else if (strcmp(fieldname, "postalAddress") == 0)
192 {
194 }
195 else if (strcmp(fieldname, "postalCode") == 0)
196 {
198 }
199 else if (strcmp(fieldname, "emailAddress") == 0)
200 {
202 }
203 else if (strcmp(fieldname, "uid") == 0)
204 {
206 }
207 else if (strcmp(fieldname, "dnQualifier") == 0)
208 {
210 }
211 else
212 {
213 return NULL;
214 }
215}
216
217static bool
219{
222 {
223 return false;
224 }
225 for (size_t i = 0; i < asn1_buf->len; i++)
226 {
227 if (asn1_buf->p[i] == '\0')
228 {
229 return false;
230 }
231 }
232 return true;
233}
234
236backend_x509_get_username(char *cn, size_t cn_len, char *x509_username_field, mbedtls_x509_crt *cert)
237{
238 ASSERT(cn != NULL && cn_len > 0 && cert != NULL);
239
240 if (x509_username_field == NULL)
241 {
242 goto fail;
243 }
244
245 if (strcmp(x509_username_field, "serialNumber") == 0)
246 {
247 if (cn_len < 2)
248 {
249 goto fail;
250 }
251 cn[0] = '0';
252 cn[1] = 'x';
253 size_t cn_index = 2;
254 bool leading_zeros = true;
255 for (size_t i = 0; i < cert->serial.len; i++)
256 {
257 uint8_t serial_byte = cert->serial.p[i];
258 if (leading_zeros && serial_byte == 0)
259 {
260 continue;
261 }
262 leading_zeros = false;
263 if (cn_index > cn_len - 3)
264 {
265 goto fail;
266 }
268 cn_index += 2;
269 }
270 return SUCCESS;
271 }
272
273 const char *field_oid = fieldname_to_oid(x509_username_field);
274 if (field_oid == NULL)
275 {
276 goto fail;
277 }
278
279 /* Find field_oid in the subject name. */
280 mbedtls_x509_name *name = NULL;
281 mbedtls_x509_name *next = &cert->subject;
282 while (next != NULL)
283 {
284 if (strlen(field_oid) == next->oid.len
285 && 0 == memcmp(next->oid.p, field_oid, next->oid.len))
286 {
287 name = next;
288 }
289
290 next = next->next;
291 }
292
293 /* Not found, return an error if this is the peer's certificate */
294 if (name == NULL)
295 {
296 goto fail;
297 }
298
299 if (!asn1_buf_is_cstr_compatible(&name->val))
300 {
301 goto fail;
302 }
303
304 /* Check that we have room in the buffer, including the terminating '/0' byte. */
305 if (cn_len <= name->val.len)
306 {
307 goto fail;
308 }
309
310 memcpy(cn, name->val.p, name->val.len);
311 cn[name->val.len] = '\0';
312
313 return SUCCESS;
314
315fail:
316 cn[0] = '\0';
317 return FAILURE;
318}
319
320#if MBEDTLS_VERSION_NUMBER >= 0x04000000
321/* Mbed TLS 4 has no function to print the certificate serial number and does
322 * not expose the bignum functions anymore. So in order to write the serial
323 * number as a decimal string, we implement bignum % 10 and bignum / 10. */
324static char
326{
327 int result = 0;
328 for (size_t i = 0; i < bignum_length; i++)
329 {
330 result = (result * 256) % 10;
331 result = (result + bignum[i]) % 10;
332 }
333 return (char)result;
334}
335
336/* Divide bignum by 10 rounded down, in place. */
337static void
339{
340 /*
341 * Some intuition for the algorithm below:
342 *
343 * We want to calculate
344 *
345 * (bignum[0] * 256^n + bignum[1] * 256^(n-1) + ... + bignum[n]) / 10.
346 *
347 * Let remainder = bignum[0] % 10 and carry = remainder * 256.
348 * Then we can write the above as
349 *
350 * (bignum[0] / 10) * 256^n
351 * + ((carry + bignum[1]) * 256^(n-1) + ... + bignum[n]) / 10.
352 *
353 * So now we have the first byte of our result. The second byte will be
354 * (carry + bignum[1]) / 10. Note that this fits into one byte because
355 * 0 <= remainder < 10. We calculate the next remainder and carry as
356 * remainder = (carry + bignum[1]) % 10 and carry = remainder * 256 and
357 * move on to the next byte until we are done.
358 */
359 size_t new_length = 0;
360 int carry = 0;
361 for (size_t i = 0; i < *bignum_length; i++)
362 {
363 uint8_t next_byte = (uint8_t)((bignum[i] + carry) / 10);
364 int remainder = (bignum[i] + carry) % 10;
365 carry = remainder * 256;
366
367 /* Write the byte unless it's a leading zero. */
368 if (new_length != 0 || next_byte != 0)
369 {
371 }
372 }
374}
375
376/* Write the decimal representation of bignum to out, if enough space is available.
377 * Returns the number of bytes needed in out, or 0 on error. To calculate the
378 * necessary buffer size, the function can be called with out = NULL. */
379static size_t
380write_bignum(char *out, size_t out_size, const uint8_t *bignum, size_t bignum_length)
381{
382 if (bignum_length == 0)
383 {
384 /* We want out to be "0". */
385 if (out != NULL)
386 {
387 if (out_size >= 2)
388 {
389 out[0] = '0';
390 out[1] = '\0';
391 }
392 else if (out_size > 0)
393 {
394 out[0] = '\0';
395 }
396 }
397 return 2;
398 }
399
401 if (bignum_copy == NULL)
402 {
403 return 0;
404 }
406
407 size_t bytes_needed = 0;
408 size_t bytes_written = 0;
409 while (bignum_length > 0)
410 {
411 /* We're writing the digits in reverse order. We put them in the right order later. */
413 if (out != NULL && bytes_written < out_size - 1)
414 {
415 out[bytes_written++] = '0' + (char)digit;
416 }
417 bytes_needed += 1;
419 }
420
421 if (out != NULL)
422 {
424 {
425 /* We had space for all digits. Now reverse them. */
426 for (size_t i = 0; i < bytes_written / 2; i++)
427 {
428 char tmp = out[i];
429 out[i] = out[bytes_written - 1 - i];
430 out[bytes_written - 1 - i] = tmp;
431 }
432 out[bytes_written] = '\0';
433 }
434 else if (out_size > 0)
435 {
436 out[0] = '\0';
437 }
438 }
439 bytes_needed += 1;
440
441 free(bignum_copy);
442 return bytes_needed;
443}
444#endif /* MBEDTLS_VERSION_NUMBER >= 0x04000000 */
445
446char *
448{
449 char *buf = NULL;
450 size_t buflen = 0;
451
452#if MBEDTLS_VERSION_NUMBER < 0x04000000
453 mbedtls_mpi serial_mpi = { 0 };
454
455 /* Transform asn1 integer serial into mbed TLS MPI */
457 if (!mbed_ok(mbedtls_mpi_read_binary(&serial_mpi, cert->serial.p, cert->serial.len)))
458 {
459 msg(M_WARN, "Failed to retrieve serial from certificate.");
460 goto end;
461 }
462
463 /* Determine decimal representation length, allocate buffer */
465 buf = gc_malloc(buflen, true, gc);
466
467 /* Write MPI serial as decimal string into buffer */
469 {
470 msg(M_WARN, "Failed to write serial to string.");
471 buf = NULL;
472 goto end;
473 }
474
475end:
477 return buf;
478#else
479 buflen = write_bignum(NULL, 0, cert->serial.p, cert->serial.len);
480 if (buflen == 0)
481 {
482 msg(M_WARN, "Failed to write serial to string.");
483 return NULL;
484 }
485 buf = gc_malloc(buflen, true, gc);
486 if (write_bignum(buf, buflen, cert->serial.p, cert->serial.len) != buflen)
487 {
488 msg(M_WARN, "Failed to write serial to string.");
489 return NULL;
490 }
491 return buf;
492#endif /* MBEDTLS_VERSION_NUMBER < 0x04000000 */
493}
494
495char *
497{
498 char *buf = NULL;
499 size_t len = cert->serial.len * 3 + 1;
500
501 buf = gc_malloc(len, true, gc);
502
503 if (mbedtls_x509_serial_gets(buf, len - 1, &cert->serial) < 0)
504 {
505 buf = NULL;
506 }
507
508 return buf;
509}
510
512backend_x509_write_pem(openvpn_x509_cert_t *cert, const char *filename)
513{
514 /* mbed TLS does not make it easy to write a certificate in PEM format.
515 * The only way is to directly access the DER encoded raw certificate
516 * and PEM encode it ourselves */
517
518 struct gc_arena gc = gc_new();
519 /* just do a very loose upper bound for the base64 based PEM encoding
520 * using 3 times the space for the base64 and 100 bytes for the
521 * headers and footer */
522 struct buffer pem = alloc_buf_gc(cert->raw.len * 3 + 100, &gc);
523
524 struct buffer der = { 0 };
525 buf_set_read(&der, cert->raw.p, cert->raw.len);
526
527 if (!crypto_pem_encode("CERTIFICATE", &pem, &der, &gc))
528 {
529 goto err;
530 }
531
532 if (!buffer_write_file(filename, &pem))
533 {
534 goto err;
535 }
536
537 gc_free(&gc);
538 return SUCCESS;
539err:
540 msg(D_TLS_DEBUG_LOW, "Error writing X509 certificate to file %s", filename);
541 gc_free(&gc);
542 return FAILURE;
543}
544
545#if defined(__GNUC__) || defined(__clang__)
546#pragma GCC diagnostic push
547#pragma GCC diagnostic ignored "-Wconversion"
548#endif
549
550static struct buffer
552{
553 const size_t md_size = mbedtls_md_get_size(md_info);
555 mbedtls_md(md_info, cert->raw.p, cert->raw.len, BPTR(&fingerprint));
557 return fingerprint;
558}
559
560#if defined(__GNUC__) || defined(__clang__)
561#pragma GCC diagnostic pop
562#endif
563
564struct buffer
566{
567 return x509_get_fingerprint(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), cert, gc);
568}
569
570struct buffer
572{
573 return x509_get_fingerprint(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), cert, gc);
574}
575
576char *
577x509_get_subject(mbedtls_x509_crt *cert, struct gc_arena *gc)
578{
579 char tmp_subject[MAX_SUBJECT_LENGTH] = { 0 };
580 char *subject = NULL;
581
582 int ret = 0;
583
584 ret = mbedtls_x509_dn_gets(tmp_subject, MAX_SUBJECT_LENGTH - 1, &cert->subject);
585 if (ret > 0)
586 {
587 /* Allocate the required space for the subject */
588 subject = string_alloc(tmp_subject, gc);
589 }
590
591 return subject;
592}
593
594static void
595do_setenv_x509(struct env_set *es, const char *name, char *value, int depth)
596{
597 char *name_expand;
598 size_t name_expand_size;
599
600 string_mod(value, CC_ANY, CC_CRLF, '?');
601 msg(D_X509_ATTR, "X509 ATTRIBUTE name='%s' value='%s' depth=%d", name, value, depth);
602 name_expand_size = 64 + strlen(name);
603 name_expand = (char *)malloc(name_expand_size);
604 check_malloc_return(name_expand);
605 snprintf(name_expand, name_expand_size, "X509_%d_%s", depth, name);
606 setenv_str(es, name_expand, value);
607 free(name_expand);
608}
609
610static char *
611asn1_buf_to_c_string(const mbedtls_asn1_buf *orig, struct gc_arena *gc)
612{
613 char *val;
614
615 if (!asn1_buf_is_cstr_compatible(orig))
616 {
617 return string_alloc("ERROR: Unsupported string type or embedded null bytes.", gc);
618 }
619 val = gc_malloc(orig->len + 1, false, gc);
620 memcpy(val, orig->p, orig->len);
621 val[orig->len] = '\0';
622 return val;
623}
624
625static void
626do_setenv_name(struct env_set *es, const struct x509_track *xt, const mbedtls_x509_crt *cert,
627 int depth, struct gc_arena *gc)
628{
629 const mbedtls_x509_name *xn;
630 for (xn = &cert->subject; xn != NULL; xn = xn->next)
631 {
632 const char *xn_short_name = NULL;
633 if (0 == mbedtls_oid_get_attr_short_name(&xn->oid, &xn_short_name)
634 && 0 == strcmp(xt->name, xn_short_name))
635 {
636 char *val_str = asn1_buf_to_c_string(&xn->val, gc);
637 do_setenv_x509(es, xt->name, val_str, depth);
638 }
639 }
640}
641
642void
643x509_track_add(const struct x509_track **ll_head, const char *name, msglvl_t msglevel,
644 struct gc_arena *gc)
645{
646 struct x509_track *xt;
647 ALLOC_OBJ_CLEAR_GC(xt, struct x509_track, gc);
648 if (*name == '+')
649 {
650 xt->flags |= XT_FULL_CHAIN;
651 ++name;
652 }
653 xt->name = name;
654 xt->next = *ll_head;
655 *ll_head = xt;
656}
657
658void
659x509_setenv_track(const struct x509_track *xt, struct env_set *es, const int depth,
660 mbedtls_x509_crt *cert)
661{
662 struct gc_arena gc = gc_new();
663 while (xt)
664 {
665 if (depth == 0 || (xt->flags & XT_FULL_CHAIN))
666 {
667 if (0 == strcmp(xt->name, "SHA1") || 0 == strcmp(xt->name, "SHA256"))
668 {
669 /* Fingerprint is not part of X509 structure */
670 struct buffer cert_hash;
671 char *fingerprint;
672
673 if (0 == strcmp(xt->name, "SHA1"))
674 {
676 }
677 else
678 {
680 }
681
683 format_hex_ex(BPTR(&cert_hash), BLEN(&cert_hash), 0, 1 | FHE_CAPS, ":", &gc);
684 do_setenv_x509(es, xt->name, fingerprint, depth);
685 }
686 else
687 {
688 do_setenv_name(es, xt, cert, depth, &gc);
689 }
690 }
691 xt = xt->next;
692 }
693 gc_free(&gc);
694}
695
696/*
697 * Save X509 fields to environment, using the naming convention:
698 *
699 * X509_{cert_depth}_{name}={value}
700 */
701void
702x509_setenv(struct env_set *es, int cert_depth, mbedtls_x509_crt *cert)
703{
704 unsigned char c;
705 const mbedtls_x509_name *name;
706 char s[128] = { 0 };
707
708 name = &cert->subject;
709
710 while (name != NULL)
711 {
712 char name_expand[64 + 8];
713 const char *shortname;
714
715 if (0 == mbedtls_oid_get_attr_short_name(&name->oid, &shortname))
716 {
717 snprintf(name_expand, sizeof(name_expand), "X509_%d_%s", cert_depth, shortname);
718 }
719 else
720 {
721 snprintf(name_expand, sizeof(name_expand), "X509_%d_\?\?", cert_depth);
722 }
723
724 size_t i;
725 for (i = 0; i < name->val.len; i++)
726 {
727 if (i >= sizeof(s) - 1)
728 {
729 break;
730 }
731
732 c = name->val.p[i];
733 if (c < 32 || c == 127 || (c > 128 && c < 160))
734 {
735 s[i] = '?';
736 }
737 else
738 {
739 s[i] = c;
740 }
741 }
742 s[i] = '\0';
743
744 /* Check both strings, set environment variable */
746 string_mod((char *)s, CC_PRINT, CC_CRLF, '_');
747 setenv_str_incr(es, name_expand, (char *)s);
748
749 name = name->next;
750 }
751}
752
753/* Dummy function because Netscape certificate types are not supported in OpenVPN with mbedtls.
754 * Returns SUCCESS if usage is NS_CERT_CHECK_NONE, FAILURE otherwise. */
757{
759 {
760 return SUCCESS;
761 }
762
763 return FAILURE;
764}
765
767x509_verify_cert_ku(mbedtls_x509_crt *cert, const unsigned int *const expected_ku, size_t expected_len)
768{
769 msg(D_HANDSHAKE, "Validating certificate key usage");
770
772 {
773 msg(D_TLS_ERRORS, "ERROR: Certificate does not have key usage extension");
774 return FAILURE;
775 }
776
778 {
779 /* Extension required, value checked by TLS library */
780 return SUCCESS;
781 }
782
784 for (size_t i = 0; SUCCESS != fFound && i < expected_len; i++)
785 {
787 {
788 fFound = SUCCESS;
789 }
790 }
791
792 if (fFound != SUCCESS)
793 {
794 msg(D_TLS_ERRORS, "ERROR: Certificate has invalid key usage, expected one of:");
795 for (size_t i = 0; i < expected_len && expected_ku[i]; i++)
796 {
797 msg(D_TLS_ERRORS, " * %04x", expected_ku[i]);
798 }
799 }
800
801 return fFound;
802}
803
805x509_verify_cert_eku(mbedtls_x509_crt *cert, const char *const expected_oid)
806{
808
810 {
811 msg(D_HANDSHAKE, "Certificate does not have extended key usage extension");
812 }
813 else
814 {
815 mbedtls_x509_sequence *oid_seq = &(cert->ext_key_usage);
816
817 msg(D_HANDSHAKE, "Validating certificate extended key usage");
818 while (oid_seq != NULL)
819 {
821 char oid_num_str[1024];
822 const char *oid_str;
823
825 {
826 msg(D_HANDSHAKE, "++ Certificate has EKU (str) %s, expects %s", oid_str,
829 {
830 fFound = SUCCESS;
831 break;
832 }
833 }
834
836 {
837 msg(D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s", oid_num_str,
840 {
841 fFound = SUCCESS;
842 break;
843 }
844 }
845 oid_seq = oid_seq->next;
846 }
847 }
848
849 return fFound;
850}
851
852bool
853tls_verify_crl_missing(const struct tls_options *opt)
854{
855 if (opt->crl_file && !(opt->ssl_flags & SSLF_CRL_VERIFY_DIR)
856 && (opt->ssl_ctx->crl == NULL || opt->ssl_ctx->crl->version == 0))
857 {
858 return true;
859 }
860 return false;
861}
862
863#endif /* #if defined(ENABLE_CRYPTO_MBEDTLS) */
bool buffer_write_file(const char *filename, const struct buffer *buf)
Write buffer contents to file.
Definition buffer.c:286
void chomp(char *str)
Remove trailing newline and carriage-return characters from a string.
Definition buffer.c:584
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Allocate memory and, optionally, zero it.
Definition buffer.c:318
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
Definition buffer.c:77
char * format_hex_ex(const uint8_t *data, size_t size, size_t maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
Format a binary buffer as a hex string.
Definition buffer.c:452
bool string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
Modifies a string in place by replacing certain classes of characters of it with a specified characte...
Definition buffer.c:1005
bool checked_snprintf(char *str, size_t size, const char *format,...)
Like snprintf() but returns an boolean.
Definition buffer.c:1121
char * string_alloc(const char *str, struct gc_arena *gc)
Duplicate a string, allocating memory under garbage collection.
Definition buffer.c:616
#define CC_ANY
any character
Definition buffer.h:1698
#define BPTR(buf)
Return a pointer to the start of the buffer content.
Definition buffer.h:139
static bool buf_inc_len(struct buffer *buf, int inc)
Increase or decrease the length of a buffer.
Definition buffer.h:1140
#define CC_CRLF
carriage return or newline
Definition buffer.h:1735
static void buf_set_read(struct buffer *buf, const uint8_t *data, size_t size)
Initialise a buffer with an externally provided read-only memory region.
Definition buffer.h:685
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Allocate and zero-initialise a garbage-collected object of the given type.
Definition buffer.h:2132
#define BLEN(buf)
Return the length of the buffer content in bytes.
Definition buffer.h:151
static void check_malloc_return(void *p)
Abort if a memory allocation returned NULL.
Definition buffer.h:2144
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
Definition buffer.h:1974
#define CC_PRINT
printable (>= 32, != 127)
Definition buffer.h:1706
#define FHE_CAPS
Flag for format_hex_ex(): output hex digits in upper case.
Definition buffer.h:948
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Definition buffer.h:1958
bool crypto_pem_encode(const char *name, struct buffer *dst, const struct buffer *src, struct gc_arena *gc)
Encode binary data as PEM.
Data Channel Cryptography backend interface using the TF-PSA-Crypto library part of Mbed TLS 4.
#define mbed_ok(errval)
Check errval and log on error.
Data Channel Cryptography mbed TLS-specific backend interface.
void setenv_str(struct env_set *es, const char *name, const char *value)
Definition env_set.c:307
void setenv_str_incr(struct env_set *es, const char *name, const char *value)
Store the supplied name value pair in the env_set.
Definition env_set.c:329
#define D_TLS_DEBUG_LOW
Definition errlevel.h:76
#define D_X509_ATTR
Definition errlevel.h:102
#define D_HANDSHAKE
Definition errlevel.h:71
#define D_TLS_ERRORS
Definition errlevel.h:58
int verify_callback(void *session_obj, mbedtls_x509_crt *cert, int cert_depth, uint32_t *flags)
Verify that the remote OpenVPN peer's certificate allows setting up a VPN tunnel.
mbedtls compatibility stub.
#define msg(flags,...)
Definition error.h:152
unsigned int msglvl_t
Definition error.h:77
#define ASSERT(x)
Definition error.h:219
#define M_WARN
Definition error.h:92
#define SSLF_CRL_VERIFY_DIR
Definition ssl_common.h:428
result_t verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_depth)
Definition ssl_verify.c:588
void cert_hash_remember(struct tls_session *session, const int error_depth, const struct buffer *cert_hash)
Definition ssl_verify.c:194
Control Channel Verification Module.
#define OPENVPN_KU_REQUIRED
Require keyUsage to be present in cert (0xFFFF is an invalid KU value)
Definition ssl_verify.h:257
#define XT_FULL_CHAIN
Definition ssl_verify.h:241
#define NS_CERT_CHECK_NONE
Do not perform Netscape certificate type verification.
Definition ssl_verify.h:250
struct buffer x509_get_sha256_fingerprint(openvpn_x509_cert_t *cert, struct gc_arena *gc)
Retrieve the certificate's SHA256 fingerprint.
bool x509_username_field_ext_supported(const char *extname)
Return true iff the supplied extension field is supported by the –x509-username-field option.
void x509_setenv_track(const struct x509_track *xt, struct env_set *es, const int depth, openvpn_x509_cert_t *x509)
void x509_setenv(struct env_set *es, int cert_depth, openvpn_x509_cert_t *cert)
bool tls_verify_crl_missing(const struct tls_options *opt)
Return true iff a CRL is configured, but is not loaded.
result_t backend_x509_write_pem(openvpn_x509_cert_t *cert, const char *filename)
result_t x509_verify_ns_cert_type(openvpn_x509_cert_t *cert, const int cert_type)
char * backend_x509_get_serial_hex(openvpn_x509_cert_t *cert, struct gc_arena *gc)
struct buffer x509_get_sha1_fingerprint(openvpn_x509_cert_t *cert, struct gc_arena *gc)
Retrieve the certificate's SHA1 fingerprint.
result_t x509_verify_cert_ku(openvpn_x509_cert_t *x509, const unsigned *const expected_ku, size_t expected_len)
char * x509_get_subject(openvpn_x509_cert_t *cert, struct gc_arena *gc)
Definition test_pkcs11.c:70
char * backend_x509_get_serial(openvpn_x509_cert_t *cert, struct gc_arena *gc)
result_t backend_x509_get_username(char *common_name, size_t cn_len, char *x509_username_field, openvpn_x509_cert_t *peer_cert)
void x509_track_add(const struct x509_track **ll_head, const char *name, msglvl_t msglevel, struct gc_arena *gc)
result_t
Result of verification function.
@ FAILURE
@ SUCCESS
result_t x509_verify_cert_eku(openvpn_x509_cert_t *x509, const char *const expected_oid)
mbedtls_x509_crt openvpn_x509_cert_t
static void do_setenv_x509(struct env_set *es, const char *name, char *value, int depth)
Wrapper structure for dynamically allocated memory.
Definition buffer.h:71
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:76
Structure containing the hash for a single certificate.
Definition ssl_verify.h:58
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:127
unsigned int ssl_flags
Definition ssl_common.h:434
struct tls_root_ctx * ssl_ctx
Definition ssl_common.h:310
const char * crl_file
Definition ssl_common.h:355
mbedtls_x509_crl * crl
Certificate Revocation List.
Security parameter state of a single session within a VPN tunnel.
Definition ssl_common.h:489
unsigned int flags
Definition ssl_verify.h:242
const struct x509_track * next
Definition ssl_verify.h:239
const char * name
Definition ssl_verify.h:240
struct gc_arena gc
Definition test_ssl.c:122