OpenVPN
mbedtls_compat.h
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) 2023-2026 Sentyron B.V. <openvpn@sentyron.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
30#ifndef MBEDTLS_COMPAT_H_
31#define MBEDTLS_COMPAT_H_
32
33#include "syshead.h"
34
35#include "errlevel.h"
36
37#include <mbedtls/asn1.h>
38#include <mbedtls/pk.h>
39#include <mbedtls/version.h>
40
41#if MBEDTLS_VERSION_NUMBER < 0x04000000
42#include <mbedtls/ctr_drbg.h>
44#else
45#include <mbedtls/oid.h>
46#include "crypto_mbedtls.h"
47#endif /* MBEDTLS_VERSION_NUMBER < 0x04000000 */
48
49#ifdef HAVE_PSA_CRYPTO_H
50#include <psa/crypto.h>
51#endif
52
53static inline void
55{
56#if defined(HAVE_PSA_CRYPTO_H) && defined(MBEDTLS_PSA_CRYPTO_C)
57 if (psa_crypto_init() != PSA_SUCCESS)
58 {
59 msg(M_FATAL, "mbedtls: psa_crypto_init() failed");
60 }
61#else
62 return;
63#endif
64}
65
66#if MBEDTLS_VERSION_NUMBER >= 0x04000000
67typedef struct
68{
69 const char *name;
70 uint16_t tls_id;
71} mbedtls_ecp_curve_info;
72
73static inline int
74mbedtls_oid_get_attr_short_name(const mbedtls_asn1_buf *oid, const char **desc)
75{
76 /* The relevant OIDs all have equal length. */
77 if (oid->tag != MBEDTLS_ASN1_OID || oid->len != strlen(MBEDTLS_OID_AT_CN))
78 {
79 *desc = NULL;
80 return -1;
81 }
82
83 if (memcmp(oid->p, MBEDTLS_OID_AT_CN, oid->len) == 0)
84 {
85 *desc = "CN";
86 }
87 else if (memcmp(oid->p, MBEDTLS_OID_AT_SUR_NAME, oid->len) == 0)
88 {
89 *desc = "SN";
90 }
91 else if (memcmp(oid->p, MBEDTLS_OID_AT_SERIAL_NUMBER, oid->len) == 0)
92 {
93 *desc = "serialNumber";
94 }
95 else if (memcmp(oid->p, MBEDTLS_OID_AT_COUNTRY, oid->len) == 0)
96 {
97 *desc = "C";
98 }
99 else if (memcmp(oid->p, MBEDTLS_OID_AT_LOCALITY, oid->len) == 0)
100 {
101 *desc = "L";
102 }
103 else if (memcmp(oid->p, MBEDTLS_OID_AT_STATE, oid->len) == 0)
104 {
105 *desc = "ST";
106 }
107 else if (memcmp(oid->p, MBEDTLS_OID_AT_ORGANIZATION, oid->len) == 0)
108 {
109 *desc = "O";
110 }
111 else if (memcmp(oid->p, MBEDTLS_OID_AT_ORG_UNIT, oid->len) == 0)
112 {
113 *desc = "OU";
114 }
115 else if (memcmp(oid->p, MBEDTLS_OID_AT_TITLE, oid->len) == 0)
116 {
117 *desc = "title";
118 }
119 else if (memcmp(oid->p, MBEDTLS_OID_AT_POSTAL_ADDRESS, oid->len) == 0)
120 {
121 *desc = "postalAddress";
122 }
123 else if (memcmp(oid->p, MBEDTLS_OID_AT_POSTAL_CODE, oid->len) == 0)
124 {
125 *desc = "postalCode";
126 }
127 else if (memcmp(oid->p, MBEDTLS_OID_AT_GIVEN_NAME, oid->len) == 0)
128 {
129 *desc = "GN";
130 }
131 else if (memcmp(oid->p, MBEDTLS_OID_AT_INITIALS, oid->len) == 0)
132 {
133 *desc = "initials";
134 }
135 else if (memcmp(oid->p, MBEDTLS_OID_AT_GENERATION_QUALIFIER, oid->len) == 0)
136 {
137 *desc = "generationQualifier";
138 }
139 else if (memcmp(oid->p, MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, oid->len) == 0)
140 {
141 *desc = "uniqueIdentifier";
142 }
143 else if (memcmp(oid->p, MBEDTLS_OID_AT_DN_QUALIFIER, oid->len) == 0)
144 {
145 *desc = "dnQualifier";
146 }
147 else if (memcmp(oid->p, MBEDTLS_OID_AT_PSEUDONYM, oid->len) == 0)
148 {
149 *desc = "pseudonym";
150 }
151 else
152 {
153 *desc = NULL;
154 return -1;
155 }
156 return 0;
157}
158
159static inline int
160mbedtls_oid_get_extended_key_usage(const mbedtls_asn1_buf *oid, const char **desc)
161{
162 /* The relevant OIDs all have equal length. */
163 if (oid->tag != MBEDTLS_ASN1_OID || oid->len != strlen(MBEDTLS_OID_SERVER_AUTH))
164 {
165 *desc = NULL;
166 return -1;
167 }
168
169 if (memcmp(oid->p, MBEDTLS_OID_SERVER_AUTH, oid->len) == 0)
170 {
171 *desc = "TLS Web Server Authentication";
172 }
173 else if (memcmp(oid->p, MBEDTLS_OID_CLIENT_AUTH, oid->len) == 0)
174 {
175 *desc = "TLS Web Client Authentication";
176 }
177 else if (memcmp(oid->p, MBEDTLS_OID_CODE_SIGNING, oid->len) == 0)
178 {
179 *desc = "Code Signing";
180 }
181 else if (memcmp(oid->p, MBEDTLS_OID_EMAIL_PROTECTION, oid->len) == 0)
182 {
183 *desc = "E-mail Protection";
184 }
185 else if (memcmp(oid->p, MBEDTLS_OID_TIME_STAMPING, oid->len) == 0)
186 {
187 *desc = "Time Stamping";
188 }
189 else if (memcmp(oid->p, MBEDTLS_OID_OCSP_SIGNING, oid->len) == 0)
190 {
191 *desc = "OCSP Signing";
192 }
193 else
194 {
195 *desc = NULL;
196 return -1;
197 }
198
199 return 0;
200}
201#endif /* MBEDTLS_VERSION_NUMBER >= 0x04000000 */
202
203/* Some functions that operate on private keys use randomness to protect against
204 * side channels. In Mbed TLS 4, they automatically use the RNG in the PSA
205 * library, but in Mbed TLS 3, they require them as explicit arguments. */
206static inline int
207mbedtls_compat_pk_parse_key(mbedtls_pk_context *ctx,
208 const unsigned char *key, size_t keylen,
209 const unsigned char *pwd, size_t pwdlen)
210{
211#if MBEDTLS_VERSION_NUMBER >= 0x04000000
212 return mbedtls_pk_parse_key(ctx, key, keylen, pwd, pwdlen);
213#else
214 return mbedtls_pk_parse_key(ctx, key, keylen, pwd, pwdlen, mbedtls_ctr_drbg_random, rand_ctx_get());
215#endif /* MBEDTLS_VERSION_NUMBER < 0x04000000 */
216}
217
218static inline int
219mbedtls_compat_pk_parse_keyfile(mbedtls_pk_context *ctx, const char *path, const char *password)
220{
221#if MBEDTLS_VERSION_NUMBER >= 0x04000000
222 return mbedtls_pk_parse_keyfile(ctx, path, password);
223#else
224 return mbedtls_pk_parse_keyfile(ctx, path, password, mbedtls_ctr_drbg_random, rand_ctx_get());
225#endif /* MBEDTLS_VERSION_NUMBER < 0x04000000 */
226}
227
228static inline int
229mbedtls_compat_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv)
230{
231#if MBEDTLS_VERSION_NUMBER >= 0x04000000
232 /* work around bug in mbedtls 4.1.0 by adding missing public key information in prv
233 * cf. https://github.com/Mbed-TLS/TF-PSA-Crypto/issues/807 */
234#if MBEDTLS_VERSION_NUMBER >= 0x04010000
235 if (prv->MBEDTLS_PRIVATE(pub_raw_len) == 0)
236 {
237 mbedtls_pk_context *mut_prv = (mbedtls_pk_context *)prv; /* remove const */
238 ASSERT(mbed_ok(psa_export_public_key(mut_prv->MBEDTLS_PRIVATE(priv_id),
239 mut_prv->MBEDTLS_PRIVATE(pub_raw),
240 sizeof(mut_prv->MBEDTLS_PRIVATE(pub_raw)),
241 &mut_prv->MBEDTLS_PRIVATE(pub_raw_len))));
242 }
243#endif
244 return mbedtls_pk_check_pair(pub, prv);
245#else
246 return mbedtls_pk_check_pair(pub, prv, mbedtls_ctr_drbg_random, rand_ctx_get());
247#endif /* MBEDTLS_VERSION_NUMBER < 0x04000000 */
248}
249
250#endif /* MBEDTLS_COMPAT_H_ */
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.
mbedtls_ctr_drbg_context * rand_ctx_get(void)
Returns a singleton instance of the mbed TLS random number generator.
static int mbedtls_compat_pk_parse_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen)
static void mbedtls_compat_psa_crypto_init(void)
static int mbedtls_compat_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv)
static int mbedtls_compat_pk_parse_keyfile(mbedtls_pk_context *ctx, const char *path, const char *password)
#define M_FATAL
Definition error.h:90
#define msg(flags,...)
Definition error.h:152
#define ASSERT(x)
Definition error.h:219
Container for unidirectional cipher and HMAC key material.
Definition crypto.h:152