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 "crypto_mbedtls.h"
38
39#include "ssl_verify.h"
40#include <mbedtls/asn1.h>
41#include <mbedtls/error.h>
42#include <mbedtls/oid.h>
43
44#define MAX_SUBJECT_LENGTH 256
45
46int
47verify_callback(void *session_obj, mbedtls_x509_crt *cert, int cert_depth, uint32_t *flags)
48{
49 struct tls_session *session = (struct tls_session *)session_obj;
50 struct gc_arena gc = gc_new();
51
52 ASSERT(cert);
54
55 session->verified = false;
56
57 /* Remember certificate hash */
60
61 if (session->opt->verify_hash_no_ca)
62 {
63 /*
64 * If we decide to verify the peer certificate based on the fingerprint
65 * we ignore wrong dates and the certificate not being trusted.
66 * Any other problem with the certificate (wrong key, bad cert,...)
67 * will still trigger an error.
68 * Clearing these flags relies on verify_cert will later rejecting a
69 * certificate that has no matching fingerprint.
70 */
73 *flags = *flags & ~flags_ignore;
74 }
75
76 /* did peer present cert which was signed by our root cert? */
77 if (*flags != 0)
78 {
79 int ret = 0;
80 char errstr[512] = { 0 };
81 char *subject = x509_get_subject(cert, &gc);
82 char *serial = backend_x509_get_serial(cert, &gc);
83
84 ret = mbedtls_x509_crt_verify_info(errstr, sizeof(errstr) - 1, "", *flags);
85 if (ret <= 0
86 && !checked_snprintf(errstr, sizeof(errstr), "Could not retrieve error string, flags=%" PRIx32, *flags))
87 {
88 errstr[0] = '\0';
89 }
90 else
91 {
93 }
94
95 if (subject)
96 {
97 msg(D_TLS_ERRORS, "VERIFY ERROR: depth=%d, subject=%s, serial=%s: %s", cert_depth,
98 subject, serial ? serial : "<not available>", errstr);
99 }
100 else
101 {
103 "VERIFY ERROR: depth=%d, (could not extract X509 "
104 "subject string from certificate): %s",
106 }
107
108 /* Leave flags set to non-zero to indicate that the cert is not ok */
109 }
110 else if (SUCCESS != verify_cert(session, cert, cert_depth))
111 {
113 }
114
115 gc_free(&gc);
116
117 /*
118 * PolarSSL/mbed TLS-1.2.0+ expects 0 on anything except fatal errors.
119 */
120 return 0;
121}
122
123/* not supported for mbedTLS yet */
124bool
126{
127 return false;
128}
129
130static const char *
131fieldname_to_oid(const char *fieldname)
132{
133 if (strcmp(fieldname, "C") == 0)
134 {
136 }
137 else if (strcmp(fieldname, "ST") == 0)
138 {
140 }
141 else if (strcmp(fieldname, "LOCALITY") == 0)
142 {
144 }
145 else if (strcmp(fieldname, "O") == 0)
146 {
148 }
149 else if (strcmp(fieldname, "OU") == 0)
150 {
152 }
153 else if (strcmp(fieldname, "CN") == 0)
154 {
155 return MBEDTLS_OID_AT_CN;
156 }
157 else if (strcmp(fieldname, "GN") == 0)
158 {
160 }
161 else if (strcmp(fieldname, "SN") == 0)
162 {
164 }
165 else if (strcmp(fieldname, "initials") == 0)
166 {
168 }
169 else if (strcmp(fieldname, "pseudonym") == 0)
170 {
172 }
173 else if (strcmp(fieldname, "title") == 0)
174 {
176 }
177 else if (strcmp(fieldname, "generationQualifier") == 0)
178 {
180 }
181 else if (strcmp(fieldname, "postalAddress") == 0)
182 {
184 }
185 else if (strcmp(fieldname, "postalCode") == 0)
186 {
188 }
189 else if (strcmp(fieldname, "emailAddress") == 0)
190 {
192 }
193 else if (strcmp(fieldname, "uid") == 0)
194 {
196 }
197 else if (strcmp(fieldname, "dnQualifier") == 0)
198 {
200 }
201 else
202 {
203 return NULL;
204 }
205}
206
207static bool
209{
212 {
213 return false;
214 }
215 for (size_t i = 0; i < asn1_buf->len; i++)
216 {
217 if (asn1_buf->p[i] == '\0')
218 {
219 return false;
220 }
221 }
222 return true;
223}
224
226backend_x509_get_username(char *cn, size_t cn_len, char *x509_username_field, mbedtls_x509_crt *cert)
227{
228 ASSERT(cn != NULL && cn_len > 0 && cert != NULL);
229
230 if (x509_username_field == NULL)
231 {
232 goto fail;
233 }
234
235 if (strcmp(x509_username_field, "serialNumber") == 0)
236 {
237 if (cn_len < 2)
238 {
239 goto fail;
240 }
241 cn[0] = '0';
242 cn[1] = 'x';
243 size_t cn_index = 2;
244 bool leading_zeros = true;
245 for (size_t i = 0; i < cert->serial.len; i++)
246 {
247 uint8_t serial_byte = cert->serial.p[i];
248 if (leading_zeros && serial_byte == 0)
249 {
250 continue;
251 }
252 leading_zeros = false;
253 if (cn_index > cn_len - 3)
254 {
255 goto fail;
256 }
258 cn_index += 2;
259 }
260 return SUCCESS;
261 }
262
263 const char *field_oid = fieldname_to_oid(x509_username_field);
264 if (field_oid == NULL)
265 {
266 goto fail;
267 }
268
269 /* Find field_oid in the subject name. */
270 mbedtls_x509_name *name = NULL;
271 mbedtls_x509_name *next = &cert->subject;
272 while (next != NULL)
273 {
274 if (strlen(field_oid) == next->oid.len
275 && 0 == memcmp(next->oid.p, field_oid, next->oid.len))
276 {
277 name = next;
278 }
279
280 next = next->next;
281 }
282
283 /* Not found, return an error if this is the peer's certificate */
284 if (name == NULL)
285 {
286 goto fail;
287 }
288
289 if (!asn1_buf_is_cstr_compatible(&name->val))
290 {
291 goto fail;
292 }
293
294 /* Check that we have room in the buffer, including the terminating '/0' byte. */
295 if (cn_len <= name->val.len)
296 {
297 goto fail;
298 }
299
300 memcpy(cn, name->val.p, name->val.len);
301 cn[name->val.len] = '\0';
302
303 return SUCCESS;
304
305fail:
306 cn[0] = '\0';
307 return FAILURE;
308}
309
310/* Mbed TLS 4 has no function to print the certificate serial number and does
311 * not expose the bignum functions anymore. So in order to write the serial
312 * number as a decimal string, we implement bignum % 10 and bignum / 10. */
313static char
315{
316 int result = 0;
317 for (size_t i = 0; i < bignum_length; i++)
318 {
319 result = (result * 256) % 10;
320 result = (result + bignum[i]) % 10;
321 }
322 return (char)result;
323}
324
325/* Divide bignum by 10 rounded down, in place. */
326static void
328{
329 /*
330 * Some intuition for the algorithm below:
331 *
332 * We want to calculate
333 *
334 * (bignum[0] * 256^n + bignum[1] * 256^(n-1) + ... + bignum[n]) / 10.
335 *
336 * Let remainder = bignum[0] % 10 and carry = remainder * 256.
337 * Then we can write the above as
338 *
339 * (bignum[0] / 10) * 256^n
340 * + ((carry + bignum[1]) * 256^(n-1) + ... + bignum[n]) / 10.
341 *
342 * So now we have the first byte of our result. The second byte will be
343 * (carry + bignum[1]) / 10. Note that this fits into one byte because
344 * 0 <= remainder < 10. We calculate the next remainder and carry as
345 * remainder = (carry + bignum[1]) % 10 and carry = remainder * 256 and
346 * move on to the next byte until we are done.
347 */
348 size_t new_length = 0;
349 int carry = 0;
350 for (size_t i = 0; i < *bignum_length; i++)
351 {
352 uint8_t next_byte = (uint8_t)((bignum[i] + carry) / 10);
353 int remainder = (bignum[i] + carry) % 10;
354 carry = remainder * 256;
355
356 /* Write the byte unless it's a leading zero. */
357 if (new_length != 0 || next_byte != 0)
358 {
360 }
361 }
363}
364
365/* Write the decimal representation of bignum to out, if enough space is available.
366 * Returns the number of bytes needed in out, or 0 on error. To calculate the
367 * necessary buffer size, the function can be called with out = NULL. */
368static size_t
369write_bignum(char *out, size_t out_size, const uint8_t *bignum, size_t bignum_length)
370{
371 if (bignum_length == 0)
372 {
373 /* We want out to be "0". */
374 if (out != NULL)
375 {
376 if (out_size >= 2)
377 {
378 out[0] = '0';
379 out[1] = '\0';
380 }
381 else if (out_size > 0)
382 {
383 out[0] = '\0';
384 }
385 }
386 return 2;
387 }
388
390 if (bignum_copy == NULL)
391 {
392 return 0;
393 }
395
396 size_t bytes_needed = 0;
397 size_t bytes_written = 0;
398 while (bignum_length > 0)
399 {
400 /* We're writing the digits in reverse order. We put them in the right order later. */
402 if (out != NULL && bytes_written < out_size - 1)
403 {
404 out[bytes_written++] = '0' + (char)digit;
405 }
406 bytes_needed += 1;
408 }
409
410 if (out != NULL)
411 {
413 {
414 /* We had space for all digits. Now reverse them. */
415 for (size_t i = 0; i < bytes_written / 2; i++)
416 {
417 char tmp = out[i];
418 out[i] = out[bytes_written - 1 - i];
419 out[bytes_written - 1 - i] = tmp;
420 }
421 out[bytes_written] = '\0';
422 }
423 else if (out_size > 0)
424 {
425 out[0] = '\0';
426 }
427 }
428 bytes_needed += 1;
429
430 free(bignum_copy);
431 return bytes_needed;
432}
433
434char *
436{
437 char *buf = NULL;
438 size_t buflen = 0;
439
440 buflen = write_bignum(NULL, 0, cert->serial.p, cert->serial.len);
441 if (buflen == 0)
442 {
443 msg(M_WARN, "Failed to write serial to string.");
444 return NULL;
445 }
446 buf = gc_malloc(buflen, true, gc);
447 if (write_bignum(buf, buflen, cert->serial.p, cert->serial.len) != buflen)
448 {
449 msg(M_WARN, "Failed to write serial to string.");
450 return NULL;
451 }
452 return buf;
453}
454
455char *
457{
458 char *buf = NULL;
459 size_t len = cert->serial.len * 3 + 1;
460
461 buf = gc_malloc(len, true, gc);
462
463 if (mbedtls_x509_serial_gets(buf, len - 1, &cert->serial) < 0)
464 {
465 buf = NULL;
466 }
467
468 return buf;
469}
470
472backend_x509_write_pem(openvpn_x509_cert_t *cert, const char *filename)
473{
474 /* mbed TLS does not make it easy to write a certificate in PEM format.
475 * The only way is to directly access the DER encoded raw certificate
476 * and PEM encode it ourselves */
477
478 struct gc_arena gc = gc_new();
479 /* just do a very loose upper bound for the base64 based PEM encoding
480 * using 3 times the space for the base64 and 100 bytes for the
481 * headers and footer */
482 struct buffer pem = alloc_buf_gc(cert->raw.len * 3 + 100, &gc);
483
484 struct buffer der = { 0 };
485 buf_set_read(&der, cert->raw.p, cert->raw.len);
486
487 if (!crypto_pem_encode("CERTIFICATE", &pem, &der, &gc))
488 {
489 goto err;
490 }
491
492 if (!buffer_write_file(filename, &pem))
493 {
494 goto err;
495 }
496
497 gc_free(&gc);
498 return SUCCESS;
499err:
500 msg(D_TLS_DEBUG_LOW, "Error writing X509 certificate to file %s", filename);
501 gc_free(&gc);
502 return FAILURE;
503}
504
505static struct buffer
507{
508 const size_t md_size = mbedtls_md_get_size(md_info);
510 mbedtls_md(md_info, cert->raw.p, cert->raw.len, BPTR(&fingerprint));
512 return fingerprint;
513}
514
515struct buffer
517{
518 return x509_get_fingerprint(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), cert, gc);
519}
520
521struct buffer
523{
524 return x509_get_fingerprint(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), cert, gc);
525}
526
527char *
528x509_get_subject(mbedtls_x509_crt *cert, struct gc_arena *gc)
529{
530 char tmp_subject[MAX_SUBJECT_LENGTH] = { 0 };
531 char *subject = NULL;
532
533 int ret = 0;
534
535 ret = mbedtls_x509_dn_gets(tmp_subject, MAX_SUBJECT_LENGTH - 1, &cert->subject);
536 if (ret > 0)
537 {
538 /* Allocate the required space for the subject */
539 subject = string_alloc(tmp_subject, gc);
540 }
541
542 return subject;
543}
544
545static void
546do_setenv_x509(struct env_set *es, const char *name, char *value, int depth)
547{
548 char *name_expand;
549 size_t name_expand_size;
550
551 string_mod(value, CC_ANY, CC_CRLF, '?');
552 msg(D_X509_ATTR, "X509 ATTRIBUTE name='%s' value='%s' depth=%d", name, value, depth);
553 name_expand_size = 64 + strlen(name);
554 name_expand = (char *)malloc(name_expand_size);
555 check_malloc_return(name_expand);
556 snprintf(name_expand, name_expand_size, "X509_%d_%s", depth, name);
557 setenv_str(es, name_expand, value);
558 free(name_expand);
559}
560
561static char *
562asn1_buf_to_c_string(const mbedtls_asn1_buf *orig, struct gc_arena *gc)
563{
564 char *val;
565
566 if (!asn1_buf_is_cstr_compatible(orig))
567 {
568 return string_alloc("ERROR: Unsupported string type or embedded null bytes.", gc);
569 }
570 val = gc_malloc(orig->len + 1, false, gc);
571 memcpy(val, orig->p, orig->len);
572 val[orig->len] = '\0';
573 return val;
574}
575
576static inline int
577oid_get_attr_short_name(const mbedtls_asn1_buf *oid, const char **desc)
578{
579 /* The relevant OIDs all have equal length. */
580 if (oid->tag != MBEDTLS_ASN1_OID || oid->len != strlen(MBEDTLS_OID_AT_CN))
581 {
582 *desc = NULL;
583 return -1;
584 }
585
586 if (memcmp(oid->p, MBEDTLS_OID_AT_CN, oid->len) == 0)
587 {
588 *desc = "CN";
589 }
590 else if (memcmp(oid->p, MBEDTLS_OID_AT_SUR_NAME, oid->len) == 0)
591 {
592 *desc = "SN";
593 }
594 else if (memcmp(oid->p, MBEDTLS_OID_AT_SERIAL_NUMBER, oid->len) == 0)
595 {
596 *desc = "serialNumber";
597 }
598 else if (memcmp(oid->p, MBEDTLS_OID_AT_COUNTRY, oid->len) == 0)
599 {
600 *desc = "C";
601 }
602 else if (memcmp(oid->p, MBEDTLS_OID_AT_LOCALITY, oid->len) == 0)
603 {
604 *desc = "L";
605 }
606 else if (memcmp(oid->p, MBEDTLS_OID_AT_STATE, oid->len) == 0)
607 {
608 *desc = "ST";
609 }
610 else if (memcmp(oid->p, MBEDTLS_OID_AT_ORGANIZATION, oid->len) == 0)
611 {
612 *desc = "O";
613 }
614 else if (memcmp(oid->p, MBEDTLS_OID_AT_ORG_UNIT, oid->len) == 0)
615 {
616 *desc = "OU";
617 }
618 else if (memcmp(oid->p, MBEDTLS_OID_AT_TITLE, oid->len) == 0)
619 {
620 *desc = "title";
621 }
622 else if (memcmp(oid->p, MBEDTLS_OID_AT_POSTAL_ADDRESS, oid->len) == 0)
623 {
624 *desc = "postalAddress";
625 }
626 else if (memcmp(oid->p, MBEDTLS_OID_AT_POSTAL_CODE, oid->len) == 0)
627 {
628 *desc = "postalCode";
629 }
630 else if (memcmp(oid->p, MBEDTLS_OID_AT_GIVEN_NAME, oid->len) == 0)
631 {
632 *desc = "GN";
633 }
634 else if (memcmp(oid->p, MBEDTLS_OID_AT_INITIALS, oid->len) == 0)
635 {
636 *desc = "initials";
637 }
638 else if (memcmp(oid->p, MBEDTLS_OID_AT_GENERATION_QUALIFIER, oid->len) == 0)
639 {
640 *desc = "generationQualifier";
641 }
642 else if (memcmp(oid->p, MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, oid->len) == 0)
643 {
644 *desc = "uniqueIdentifier";
645 }
646 else if (memcmp(oid->p, MBEDTLS_OID_AT_DN_QUALIFIER, oid->len) == 0)
647 {
648 *desc = "dnQualifier";
649 }
650 else if (memcmp(oid->p, MBEDTLS_OID_AT_PSEUDONYM, oid->len) == 0)
651 {
652 *desc = "pseudonym";
653 }
654 else
655 {
656 *desc = NULL;
657 return -1;
658 }
659 return 0;
660}
661
662static void
663do_setenv_name(struct env_set *es, const struct x509_track *xt, const mbedtls_x509_crt *cert,
664 int depth, struct gc_arena *gc)
665{
666 const mbedtls_x509_name *xn;
667 for (xn = &cert->subject; xn != NULL; xn = xn->next)
668 {
669 const char *xn_short_name = NULL;
670 if (0 == oid_get_attr_short_name(&xn->oid, &xn_short_name)
671 && 0 == strcmp(xt->name, xn_short_name))
672 {
673 char *val_str = asn1_buf_to_c_string(&xn->val, gc);
674 do_setenv_x509(es, xt->name, val_str, depth);
675 }
676 }
677}
678
679void
680x509_track_add(const struct x509_track **ll_head, const char *name, msglvl_t msglevel,
681 struct gc_arena *gc)
682{
683 struct x509_track *xt;
684 ALLOC_OBJ_CLEAR_GC(xt, struct x509_track, gc);
685 if (*name == '+')
686 {
687 xt->flags |= XT_FULL_CHAIN;
688 ++name;
689 }
690 xt->name = name;
691 xt->next = *ll_head;
692 *ll_head = xt;
693}
694
695void
696x509_setenv_track(const struct x509_track *xt, struct env_set *es, const int depth,
697 mbedtls_x509_crt *cert)
698{
699 struct gc_arena gc = gc_new();
700 while (xt)
701 {
702 if (depth == 0 || (xt->flags & XT_FULL_CHAIN))
703 {
704 if (0 == strcmp(xt->name, "SHA1") || 0 == strcmp(xt->name, "SHA256"))
705 {
706 /* Fingerprint is not part of X509 structure */
707 struct buffer cert_hash;
708 char *fingerprint;
709
710 if (0 == strcmp(xt->name, "SHA1"))
711 {
713 }
714 else
715 {
717 }
718
720 format_hex_ex(BPTR(&cert_hash), BLEN(&cert_hash), 0, 1 | FHE_CAPS, ":", &gc);
721 do_setenv_x509(es, xt->name, fingerprint, depth);
722 }
723 else
724 {
725 do_setenv_name(es, xt, cert, depth, &gc);
726 }
727 }
728 xt = xt->next;
729 }
730 gc_free(&gc);
731}
732
733/*
734 * Save X509 fields to environment, using the naming convention:
735 *
736 * X509_{cert_depth}_{name}={value}
737 */
738void
739x509_setenv(struct env_set *es, int cert_depth, mbedtls_x509_crt *cert)
740{
741 const mbedtls_x509_name *name;
742 char s[128] = { 0 };
743
744 name = &cert->subject;
745
746 while (name != NULL)
747 {
748 char name_expand[64 + 8];
749 const char *shortname;
750
751 if (0 == oid_get_attr_short_name(&name->oid, &shortname))
752 {
753 snprintf(name_expand, sizeof(name_expand), "X509_%d_%s", cert_depth, shortname);
754 }
755 else
756 {
757 snprintf(name_expand, sizeof(name_expand), "X509_%d_\?\?", cert_depth);
758 }
759
760 size_t i;
761 for (i = 0; i < name->val.len; i++)
762 {
763 if (i >= sizeof(s) - 1)
764 {
765 break;
766 }
767
768 const unsigned char c = name->val.p[i];
769 if (c < 32 || c == 127 || (c > 128 && c < 160))
770 {
771 s[i] = '?';
772 }
773 else
774 {
775 s[i] = c;
776 }
777 }
778 s[i] = '\0';
779
780 /* Check both strings, set environment variable */
782 string_mod((char *)s, CC_PRINT, CC_CRLF, '_');
783 setenv_str_incr(es, name_expand, (char *)s);
784
785 name = name->next;
786 }
787}
788
789/* Dummy function because Netscape certificate types are not supported in OpenVPN with mbedtls.
790 * Returns SUCCESS if usage is NS_CERT_CHECK_NONE, FAILURE otherwise. */
793{
795 {
796 return SUCCESS;
797 }
798
799 return FAILURE;
800}
801
803x509_verify_cert_ku(mbedtls_x509_crt *cert, const unsigned int *const expected_ku, size_t expected_len)
804{
805 msg(D_HANDSHAKE, "Validating certificate key usage");
806
808 {
809 msg(D_TLS_ERRORS, "ERROR: Certificate does not have key usage extension");
810 return FAILURE;
811 }
812
814 {
815 /* Extension required, value checked by TLS library */
816 return SUCCESS;
817 }
818
820 for (size_t i = 0; SUCCESS != fFound && i < expected_len; i++)
821 {
823 {
824 fFound = SUCCESS;
825 }
826 }
827
828 if (fFound != SUCCESS)
829 {
830 msg(D_TLS_ERRORS, "ERROR: Certificate has invalid key usage, expected one of:");
831 for (size_t i = 0; i < expected_len && expected_ku[i]; i++)
832 {
833 msg(D_TLS_ERRORS, " * %04x", expected_ku[i]);
834 }
835 }
836
837 return fFound;
838}
839
840static inline int
842{
843 /* The relevant OIDs all have equal length. */
844 if (oid->tag != MBEDTLS_ASN1_OID || oid->len != strlen(MBEDTLS_OID_SERVER_AUTH))
845 {
846 *desc = NULL;
847 return -1;
848 }
849
850 if (memcmp(oid->p, MBEDTLS_OID_SERVER_AUTH, oid->len) == 0)
851 {
852 *desc = "TLS Web Server Authentication";
853 }
854 else if (memcmp(oid->p, MBEDTLS_OID_CLIENT_AUTH, oid->len) == 0)
855 {
856 *desc = "TLS Web Client Authentication";
857 }
858 else if (memcmp(oid->p, MBEDTLS_OID_CODE_SIGNING, oid->len) == 0)
859 {
860 *desc = "Code Signing";
861 }
862 else if (memcmp(oid->p, MBEDTLS_OID_EMAIL_PROTECTION, oid->len) == 0)
863 {
864 *desc = "E-mail Protection";
865 }
866 else if (memcmp(oid->p, MBEDTLS_OID_TIME_STAMPING, oid->len) == 0)
867 {
868 *desc = "Time Stamping";
869 }
870 else if (memcmp(oid->p, MBEDTLS_OID_OCSP_SIGNING, oid->len) == 0)
871 {
872 *desc = "OCSP Signing";
873 }
874 else
875 {
876 *desc = NULL;
877 return -1;
878 }
879
880 return 0;
881}
882
884x509_verify_cert_eku(mbedtls_x509_crt *cert, const char *const expected_oid)
885{
887
889 {
890 msg(D_HANDSHAKE, "Certificate does not have extended key usage extension");
891 }
892 else
893 {
894 mbedtls_x509_sequence *oid_seq = &(cert->ext_key_usage);
895
896 msg(D_HANDSHAKE, "Validating certificate extended key usage");
897 while (oid_seq != NULL)
898 {
900 char oid_num_str[1024];
901 const char *oid_str;
902
904 {
905 msg(D_HANDSHAKE, "++ Certificate has EKU (str) %s, expects %s", oid_str,
908 {
909 fFound = SUCCESS;
910 break;
911 }
912 }
913
915 {
916 msg(D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s", oid_num_str,
919 {
920 fFound = SUCCESS;
921 break;
922 }
923 }
924 oid_seq = oid_seq->next;
925 }
926 }
927
928 return fFound;
929}
930
931bool
932tls_verify_crl_missing(const struct tls_options *opt)
933{
934 if (opt->crl_file && !(opt->ssl_flags & SSLF_CRL_VERIFY_DIR)
935 && (opt->ssl_ctx->crl == NULL || opt->ssl_ctx->crl->version == 0))
936 {
937 return true;
938 }
939 return false;
940}
941
942#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:281
void chomp(char *str)
Remove trailing newline and carriage-return characters from a string.
Definition buffer.c:579
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Allocate memory and, optionally, zero it.
Definition buffer.c:313
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:447
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:986
bool checked_snprintf(char *str, size_t size, const char *format,...)
Like snprintf() but returns an boolean.
Definition buffer.c:1115
char * string_alloc(const char *str, struct gc_arena *gc)
Duplicate a string, allocating memory under garbage collection.
Definition buffer.c:601
#define CC_ANY
any character
Definition buffer.h:1677
#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:1119
#define CC_CRLF
carriage return or newline
Definition buffer.h:1714
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:687
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Allocate and zero-initialise a garbage-collected object of the given type.
Definition buffer.h:2123
#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:2135
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
Definition buffer.h:1965
#define CC_PRINT
printable (>= 32, != 127)
Definition buffer.h:1685
#define FHE_CAPS
Flag for format_hex_ex(): output hex digits in upper case.
Definition buffer.h:927
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Definition buffer.h:1949
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.
void setenv_str(struct env_set *es, const char *name, const char *value)
Definition env_set.c:305
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:327
#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.
X509 openvpn_x509_cert_t
#define msg(flags,...)
Definition error.h:152
unsigned int msglvl_t
Definition error.h:77
#define ASSERT(x)
Definition error.h:221
#define M_WARN
Definition error.h:92
#define SSLF_CRL_VERIFY_DIR
Definition ssl_common.h:433
result_t verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_depth)
Definition ssl_verify.c:586
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)
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)
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:439
struct tls_root_ctx * ssl_ctx
Definition ssl_common.h:310
const char * crl_file
Definition ssl_common.h:360
mbedtls_x509_crl * crl
Certificate Revocation List.
Definition ssl_mbedtls.h:92
Security parameter state of a single session within a VPN tunnel.
Definition ssl_common.h:497
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:138