1*62c56f98SSadaf Ebrahimi /*
2*62c56f98SSadaf Ebrahimi * X.509 certificate parsing and verification
3*62c56f98SSadaf Ebrahimi *
4*62c56f98SSadaf Ebrahimi * Copyright The Mbed TLS Contributors
5*62c56f98SSadaf Ebrahimi * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6*62c56f98SSadaf Ebrahimi */
7*62c56f98SSadaf Ebrahimi /*
8*62c56f98SSadaf Ebrahimi * The ITU-T X.509 standard defines a certificate format for PKI.
9*62c56f98SSadaf Ebrahimi *
10*62c56f98SSadaf Ebrahimi * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
11*62c56f98SSadaf Ebrahimi * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
12*62c56f98SSadaf Ebrahimi * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
13*62c56f98SSadaf Ebrahimi *
14*62c56f98SSadaf Ebrahimi * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
15*62c56f98SSadaf Ebrahimi * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
16*62c56f98SSadaf Ebrahimi *
17*62c56f98SSadaf Ebrahimi * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf
18*62c56f98SSadaf Ebrahimi */
19*62c56f98SSadaf Ebrahimi
20*62c56f98SSadaf Ebrahimi #include "common.h"
21*62c56f98SSadaf Ebrahimi
22*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_X509_CRT_PARSE_C)
23*62c56f98SSadaf Ebrahimi
24*62c56f98SSadaf Ebrahimi #include "mbedtls/x509_crt.h"
25*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
26*62c56f98SSadaf Ebrahimi #include "mbedtls/oid.h"
27*62c56f98SSadaf Ebrahimi #include "mbedtls/platform_util.h"
28*62c56f98SSadaf Ebrahimi
29*62c56f98SSadaf Ebrahimi #include <string.h>
30*62c56f98SSadaf Ebrahimi
31*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PEM_PARSE_C)
32*62c56f98SSadaf Ebrahimi #include "mbedtls/pem.h"
33*62c56f98SSadaf Ebrahimi #endif
34*62c56f98SSadaf Ebrahimi
35*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
36*62c56f98SSadaf Ebrahimi #include "psa/crypto.h"
37*62c56f98SSadaf Ebrahimi #include "psa_util_internal.h"
38*62c56f98SSadaf Ebrahimi #include "md_psa.h"
39*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
40*62c56f98SSadaf Ebrahimi #include "pk_internal.h"
41*62c56f98SSadaf Ebrahimi
42*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
43*62c56f98SSadaf Ebrahimi
44*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
45*62c56f98SSadaf Ebrahimi #include "mbedtls/threading.h"
46*62c56f98SSadaf Ebrahimi #endif
47*62c56f98SSadaf Ebrahimi
48*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_HAVE_TIME)
49*62c56f98SSadaf Ebrahimi #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
50*62c56f98SSadaf Ebrahimi #define WIN32_LEAN_AND_MEAN
51*62c56f98SSadaf Ebrahimi #include <windows.h>
52*62c56f98SSadaf Ebrahimi #else
53*62c56f98SSadaf Ebrahimi #include <time.h>
54*62c56f98SSadaf Ebrahimi #endif
55*62c56f98SSadaf Ebrahimi #endif
56*62c56f98SSadaf Ebrahimi
57*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_FS_IO)
58*62c56f98SSadaf Ebrahimi #include <stdio.h>
59*62c56f98SSadaf Ebrahimi #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
60*62c56f98SSadaf Ebrahimi #include <sys/types.h>
61*62c56f98SSadaf Ebrahimi #include <sys/stat.h>
62*62c56f98SSadaf Ebrahimi #if defined(__MBED__)
63*62c56f98SSadaf Ebrahimi #include <platform/mbed_retarget.h>
64*62c56f98SSadaf Ebrahimi #else
65*62c56f98SSadaf Ebrahimi #include <dirent.h>
66*62c56f98SSadaf Ebrahimi #endif /* __MBED__ */
67*62c56f98SSadaf Ebrahimi #include <errno.h>
68*62c56f98SSadaf Ebrahimi #endif /* !_WIN32 || EFIX64 || EFI32 */
69*62c56f98SSadaf Ebrahimi #endif
70*62c56f98SSadaf Ebrahimi
71*62c56f98SSadaf Ebrahimi /*
72*62c56f98SSadaf Ebrahimi * Item in a verification chain: cert and flags for it
73*62c56f98SSadaf Ebrahimi */
74*62c56f98SSadaf Ebrahimi typedef struct {
75*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *crt;
76*62c56f98SSadaf Ebrahimi uint32_t flags;
77*62c56f98SSadaf Ebrahimi } x509_crt_verify_chain_item;
78*62c56f98SSadaf Ebrahimi
79*62c56f98SSadaf Ebrahimi /*
80*62c56f98SSadaf Ebrahimi * Max size of verification chain: end-entity + intermediates + trusted root
81*62c56f98SSadaf Ebrahimi */
82*62c56f98SSadaf Ebrahimi #define X509_MAX_VERIFY_CHAIN_SIZE (MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2)
83*62c56f98SSadaf Ebrahimi
84*62c56f98SSadaf Ebrahimi /* Default profile. Do not remove items unless there are serious security
85*62c56f98SSadaf Ebrahimi * concerns. */
86*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
87*62c56f98SSadaf Ebrahimi {
88*62c56f98SSadaf Ebrahimi /* Hashes from SHA-256 and above. Note that this selection
89*62c56f98SSadaf Ebrahimi * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */
90*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
91*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
92*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
93*62c56f98SSadaf Ebrahimi 0xFFFFFFF, /* Any PK alg */
94*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
95*62c56f98SSadaf Ebrahimi /* Curves at or above 128-bit security level. Note that this selection
96*62c56f98SSadaf Ebrahimi * should be aligned with ssl_preset_default_curves in ssl_tls.c. */
97*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
98*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) |
99*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) |
100*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) |
101*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) |
102*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) |
103*62c56f98SSadaf Ebrahimi 0,
104*62c56f98SSadaf Ebrahimi #else /* MBEDTLS_PK_HAVE_ECC_KEYS */
105*62c56f98SSadaf Ebrahimi 0,
106*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
107*62c56f98SSadaf Ebrahimi 2048,
108*62c56f98SSadaf Ebrahimi };
109*62c56f98SSadaf Ebrahimi
110*62c56f98SSadaf Ebrahimi /* Next-generation profile. Currently identical to the default, but may
111*62c56f98SSadaf Ebrahimi * be tightened at any time. */
112*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
113*62c56f98SSadaf Ebrahimi {
114*62c56f98SSadaf Ebrahimi /* Hashes from SHA-256 and above. */
115*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
116*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
117*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
118*62c56f98SSadaf Ebrahimi 0xFFFFFFF, /* Any PK alg */
119*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_C)
120*62c56f98SSadaf Ebrahimi /* Curves at or above 128-bit security level. */
121*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
122*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) |
123*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) |
124*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) |
125*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) |
126*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) |
127*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256K1),
128*62c56f98SSadaf Ebrahimi #else
129*62c56f98SSadaf Ebrahimi 0,
130*62c56f98SSadaf Ebrahimi #endif
131*62c56f98SSadaf Ebrahimi 2048,
132*62c56f98SSadaf Ebrahimi };
133*62c56f98SSadaf Ebrahimi
134*62c56f98SSadaf Ebrahimi /*
135*62c56f98SSadaf Ebrahimi * NSA Suite B Profile
136*62c56f98SSadaf Ebrahimi */
137*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
138*62c56f98SSadaf Ebrahimi {
139*62c56f98SSadaf Ebrahimi /* Only SHA-256 and 384 */
140*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
141*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384),
142*62c56f98SSadaf Ebrahimi /* Only ECDSA */
143*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA) |
144*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY),
145*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
146*62c56f98SSadaf Ebrahimi /* Only NIST P-256 and P-384 */
147*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
148*62c56f98SSadaf Ebrahimi MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1),
149*62c56f98SSadaf Ebrahimi #else /* MBEDTLS_PK_HAVE_ECC_KEYS */
150*62c56f98SSadaf Ebrahimi 0,
151*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
152*62c56f98SSadaf Ebrahimi 0,
153*62c56f98SSadaf Ebrahimi };
154*62c56f98SSadaf Ebrahimi
155*62c56f98SSadaf Ebrahimi /*
156*62c56f98SSadaf Ebrahimi * Empty / all-forbidden profile
157*62c56f98SSadaf Ebrahimi */
158*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none =
159*62c56f98SSadaf Ebrahimi {
160*62c56f98SSadaf Ebrahimi 0,
161*62c56f98SSadaf Ebrahimi 0,
162*62c56f98SSadaf Ebrahimi 0,
163*62c56f98SSadaf Ebrahimi (uint32_t) -1,
164*62c56f98SSadaf Ebrahimi };
165*62c56f98SSadaf Ebrahimi
166*62c56f98SSadaf Ebrahimi /*
167*62c56f98SSadaf Ebrahimi * Check md_alg against profile
168*62c56f98SSadaf Ebrahimi * Return 0 if md_alg is acceptable for this profile, -1 otherwise
169*62c56f98SSadaf Ebrahimi */
x509_profile_check_md_alg(const mbedtls_x509_crt_profile * profile,mbedtls_md_type_t md_alg)170*62c56f98SSadaf Ebrahimi static int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile,
171*62c56f98SSadaf Ebrahimi mbedtls_md_type_t md_alg)
172*62c56f98SSadaf Ebrahimi {
173*62c56f98SSadaf Ebrahimi if (md_alg == MBEDTLS_MD_NONE) {
174*62c56f98SSadaf Ebrahimi return -1;
175*62c56f98SSadaf Ebrahimi }
176*62c56f98SSadaf Ebrahimi
177*62c56f98SSadaf Ebrahimi if ((profile->allowed_mds & MBEDTLS_X509_ID_FLAG(md_alg)) != 0) {
178*62c56f98SSadaf Ebrahimi return 0;
179*62c56f98SSadaf Ebrahimi }
180*62c56f98SSadaf Ebrahimi
181*62c56f98SSadaf Ebrahimi return -1;
182*62c56f98SSadaf Ebrahimi }
183*62c56f98SSadaf Ebrahimi
184*62c56f98SSadaf Ebrahimi /*
185*62c56f98SSadaf Ebrahimi * Check pk_alg against profile
186*62c56f98SSadaf Ebrahimi * Return 0 if pk_alg is acceptable for this profile, -1 otherwise
187*62c56f98SSadaf Ebrahimi */
x509_profile_check_pk_alg(const mbedtls_x509_crt_profile * profile,mbedtls_pk_type_t pk_alg)188*62c56f98SSadaf Ebrahimi static int x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile,
189*62c56f98SSadaf Ebrahimi mbedtls_pk_type_t pk_alg)
190*62c56f98SSadaf Ebrahimi {
191*62c56f98SSadaf Ebrahimi if (pk_alg == MBEDTLS_PK_NONE) {
192*62c56f98SSadaf Ebrahimi return -1;
193*62c56f98SSadaf Ebrahimi }
194*62c56f98SSadaf Ebrahimi
195*62c56f98SSadaf Ebrahimi if ((profile->allowed_pks & MBEDTLS_X509_ID_FLAG(pk_alg)) != 0) {
196*62c56f98SSadaf Ebrahimi return 0;
197*62c56f98SSadaf Ebrahimi }
198*62c56f98SSadaf Ebrahimi
199*62c56f98SSadaf Ebrahimi return -1;
200*62c56f98SSadaf Ebrahimi }
201*62c56f98SSadaf Ebrahimi
202*62c56f98SSadaf Ebrahimi /*
203*62c56f98SSadaf Ebrahimi * Check key against profile
204*62c56f98SSadaf Ebrahimi * Return 0 if pk is acceptable for this profile, -1 otherwise
205*62c56f98SSadaf Ebrahimi */
x509_profile_check_key(const mbedtls_x509_crt_profile * profile,const mbedtls_pk_context * pk)206*62c56f98SSadaf Ebrahimi static int x509_profile_check_key(const mbedtls_x509_crt_profile *profile,
207*62c56f98SSadaf Ebrahimi const mbedtls_pk_context *pk)
208*62c56f98SSadaf Ebrahimi {
209*62c56f98SSadaf Ebrahimi const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(pk);
210*62c56f98SSadaf Ebrahimi
211*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_RSA_C)
212*62c56f98SSadaf Ebrahimi if (pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS) {
213*62c56f98SSadaf Ebrahimi if (mbedtls_pk_get_bitlen(pk) >= profile->rsa_min_bitlen) {
214*62c56f98SSadaf Ebrahimi return 0;
215*62c56f98SSadaf Ebrahimi }
216*62c56f98SSadaf Ebrahimi
217*62c56f98SSadaf Ebrahimi return -1;
218*62c56f98SSadaf Ebrahimi }
219*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_RSA_C */
220*62c56f98SSadaf Ebrahimi
221*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
222*62c56f98SSadaf Ebrahimi if (pk_alg == MBEDTLS_PK_ECDSA ||
223*62c56f98SSadaf Ebrahimi pk_alg == MBEDTLS_PK_ECKEY ||
224*62c56f98SSadaf Ebrahimi pk_alg == MBEDTLS_PK_ECKEY_DH) {
225*62c56f98SSadaf Ebrahimi const mbedtls_ecp_group_id gid = mbedtls_pk_get_group_id(pk);
226*62c56f98SSadaf Ebrahimi
227*62c56f98SSadaf Ebrahimi if (gid == MBEDTLS_ECP_DP_NONE) {
228*62c56f98SSadaf Ebrahimi return -1;
229*62c56f98SSadaf Ebrahimi }
230*62c56f98SSadaf Ebrahimi
231*62c56f98SSadaf Ebrahimi if ((profile->allowed_curves & MBEDTLS_X509_ID_FLAG(gid)) != 0) {
232*62c56f98SSadaf Ebrahimi return 0;
233*62c56f98SSadaf Ebrahimi }
234*62c56f98SSadaf Ebrahimi
235*62c56f98SSadaf Ebrahimi return -1;
236*62c56f98SSadaf Ebrahimi }
237*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
238*62c56f98SSadaf Ebrahimi
239*62c56f98SSadaf Ebrahimi return -1;
240*62c56f98SSadaf Ebrahimi }
241*62c56f98SSadaf Ebrahimi
242*62c56f98SSadaf Ebrahimi /*
243*62c56f98SSadaf Ebrahimi * Like memcmp, but case-insensitive and always returns -1 if different
244*62c56f98SSadaf Ebrahimi */
x509_memcasecmp(const void * s1,const void * s2,size_t len)245*62c56f98SSadaf Ebrahimi static int x509_memcasecmp(const void *s1, const void *s2, size_t len)
246*62c56f98SSadaf Ebrahimi {
247*62c56f98SSadaf Ebrahimi size_t i;
248*62c56f98SSadaf Ebrahimi unsigned char diff;
249*62c56f98SSadaf Ebrahimi const unsigned char *n1 = s1, *n2 = s2;
250*62c56f98SSadaf Ebrahimi
251*62c56f98SSadaf Ebrahimi for (i = 0; i < len; i++) {
252*62c56f98SSadaf Ebrahimi diff = n1[i] ^ n2[i];
253*62c56f98SSadaf Ebrahimi
254*62c56f98SSadaf Ebrahimi if (diff == 0) {
255*62c56f98SSadaf Ebrahimi continue;
256*62c56f98SSadaf Ebrahimi }
257*62c56f98SSadaf Ebrahimi
258*62c56f98SSadaf Ebrahimi if (diff == 32 &&
259*62c56f98SSadaf Ebrahimi ((n1[i] >= 'a' && n1[i] <= 'z') ||
260*62c56f98SSadaf Ebrahimi (n1[i] >= 'A' && n1[i] <= 'Z'))) {
261*62c56f98SSadaf Ebrahimi continue;
262*62c56f98SSadaf Ebrahimi }
263*62c56f98SSadaf Ebrahimi
264*62c56f98SSadaf Ebrahimi return -1;
265*62c56f98SSadaf Ebrahimi }
266*62c56f98SSadaf Ebrahimi
267*62c56f98SSadaf Ebrahimi return 0;
268*62c56f98SSadaf Ebrahimi }
269*62c56f98SSadaf Ebrahimi
270*62c56f98SSadaf Ebrahimi /*
271*62c56f98SSadaf Ebrahimi * Return 0 if name matches wildcard, -1 otherwise
272*62c56f98SSadaf Ebrahimi */
x509_check_wildcard(const char * cn,const mbedtls_x509_buf * name)273*62c56f98SSadaf Ebrahimi static int x509_check_wildcard(const char *cn, const mbedtls_x509_buf *name)
274*62c56f98SSadaf Ebrahimi {
275*62c56f98SSadaf Ebrahimi size_t i;
276*62c56f98SSadaf Ebrahimi size_t cn_idx = 0, cn_len = strlen(cn);
277*62c56f98SSadaf Ebrahimi
278*62c56f98SSadaf Ebrahimi /* We can't have a match if there is no wildcard to match */
279*62c56f98SSadaf Ebrahimi if (name->len < 3 || name->p[0] != '*' || name->p[1] != '.') {
280*62c56f98SSadaf Ebrahimi return -1;
281*62c56f98SSadaf Ebrahimi }
282*62c56f98SSadaf Ebrahimi
283*62c56f98SSadaf Ebrahimi for (i = 0; i < cn_len; ++i) {
284*62c56f98SSadaf Ebrahimi if (cn[i] == '.') {
285*62c56f98SSadaf Ebrahimi cn_idx = i;
286*62c56f98SSadaf Ebrahimi break;
287*62c56f98SSadaf Ebrahimi }
288*62c56f98SSadaf Ebrahimi }
289*62c56f98SSadaf Ebrahimi
290*62c56f98SSadaf Ebrahimi if (cn_idx == 0) {
291*62c56f98SSadaf Ebrahimi return -1;
292*62c56f98SSadaf Ebrahimi }
293*62c56f98SSadaf Ebrahimi
294*62c56f98SSadaf Ebrahimi if (cn_len - cn_idx == name->len - 1 &&
295*62c56f98SSadaf Ebrahimi x509_memcasecmp(name->p + 1, cn + cn_idx, name->len - 1) == 0) {
296*62c56f98SSadaf Ebrahimi return 0;
297*62c56f98SSadaf Ebrahimi }
298*62c56f98SSadaf Ebrahimi
299*62c56f98SSadaf Ebrahimi return -1;
300*62c56f98SSadaf Ebrahimi }
301*62c56f98SSadaf Ebrahimi
302*62c56f98SSadaf Ebrahimi /*
303*62c56f98SSadaf Ebrahimi * Compare two X.509 strings, case-insensitive, and allowing for some encoding
304*62c56f98SSadaf Ebrahimi * variations (but not all).
305*62c56f98SSadaf Ebrahimi *
306*62c56f98SSadaf Ebrahimi * Return 0 if equal, -1 otherwise.
307*62c56f98SSadaf Ebrahimi */
x509_string_cmp(const mbedtls_x509_buf * a,const mbedtls_x509_buf * b)308*62c56f98SSadaf Ebrahimi static int x509_string_cmp(const mbedtls_x509_buf *a, const mbedtls_x509_buf *b)
309*62c56f98SSadaf Ebrahimi {
310*62c56f98SSadaf Ebrahimi if (a->tag == b->tag &&
311*62c56f98SSadaf Ebrahimi a->len == b->len &&
312*62c56f98SSadaf Ebrahimi memcmp(a->p, b->p, b->len) == 0) {
313*62c56f98SSadaf Ebrahimi return 0;
314*62c56f98SSadaf Ebrahimi }
315*62c56f98SSadaf Ebrahimi
316*62c56f98SSadaf Ebrahimi if ((a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING) &&
317*62c56f98SSadaf Ebrahimi (b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING) &&
318*62c56f98SSadaf Ebrahimi a->len == b->len &&
319*62c56f98SSadaf Ebrahimi x509_memcasecmp(a->p, b->p, b->len) == 0) {
320*62c56f98SSadaf Ebrahimi return 0;
321*62c56f98SSadaf Ebrahimi }
322*62c56f98SSadaf Ebrahimi
323*62c56f98SSadaf Ebrahimi return -1;
324*62c56f98SSadaf Ebrahimi }
325*62c56f98SSadaf Ebrahimi
326*62c56f98SSadaf Ebrahimi /*
327*62c56f98SSadaf Ebrahimi * Compare two X.509 Names (aka rdnSequence).
328*62c56f98SSadaf Ebrahimi *
329*62c56f98SSadaf Ebrahimi * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
330*62c56f98SSadaf Ebrahimi * we sometimes return unequal when the full algorithm would return equal,
331*62c56f98SSadaf Ebrahimi * but never the other way. (In particular, we don't do Unicode normalisation
332*62c56f98SSadaf Ebrahimi * or space folding.)
333*62c56f98SSadaf Ebrahimi *
334*62c56f98SSadaf Ebrahimi * Return 0 if equal, -1 otherwise.
335*62c56f98SSadaf Ebrahimi */
x509_name_cmp(const mbedtls_x509_name * a,const mbedtls_x509_name * b)336*62c56f98SSadaf Ebrahimi static int x509_name_cmp(const mbedtls_x509_name *a, const mbedtls_x509_name *b)
337*62c56f98SSadaf Ebrahimi {
338*62c56f98SSadaf Ebrahimi /* Avoid recursion, it might not be optimised by the compiler */
339*62c56f98SSadaf Ebrahimi while (a != NULL || b != NULL) {
340*62c56f98SSadaf Ebrahimi if (a == NULL || b == NULL) {
341*62c56f98SSadaf Ebrahimi return -1;
342*62c56f98SSadaf Ebrahimi }
343*62c56f98SSadaf Ebrahimi
344*62c56f98SSadaf Ebrahimi /* type */
345*62c56f98SSadaf Ebrahimi if (a->oid.tag != b->oid.tag ||
346*62c56f98SSadaf Ebrahimi a->oid.len != b->oid.len ||
347*62c56f98SSadaf Ebrahimi memcmp(a->oid.p, b->oid.p, b->oid.len) != 0) {
348*62c56f98SSadaf Ebrahimi return -1;
349*62c56f98SSadaf Ebrahimi }
350*62c56f98SSadaf Ebrahimi
351*62c56f98SSadaf Ebrahimi /* value */
352*62c56f98SSadaf Ebrahimi if (x509_string_cmp(&a->val, &b->val) != 0) {
353*62c56f98SSadaf Ebrahimi return -1;
354*62c56f98SSadaf Ebrahimi }
355*62c56f98SSadaf Ebrahimi
356*62c56f98SSadaf Ebrahimi /* structure of the list of sets */
357*62c56f98SSadaf Ebrahimi if (a->next_merged != b->next_merged) {
358*62c56f98SSadaf Ebrahimi return -1;
359*62c56f98SSadaf Ebrahimi }
360*62c56f98SSadaf Ebrahimi
361*62c56f98SSadaf Ebrahimi a = a->next;
362*62c56f98SSadaf Ebrahimi b = b->next;
363*62c56f98SSadaf Ebrahimi }
364*62c56f98SSadaf Ebrahimi
365*62c56f98SSadaf Ebrahimi /* a == NULL == b */
366*62c56f98SSadaf Ebrahimi return 0;
367*62c56f98SSadaf Ebrahimi }
368*62c56f98SSadaf Ebrahimi
369*62c56f98SSadaf Ebrahimi /*
370*62c56f98SSadaf Ebrahimi * Reset (init or clear) a verify_chain
371*62c56f98SSadaf Ebrahimi */
x509_crt_verify_chain_reset(mbedtls_x509_crt_verify_chain * ver_chain)372*62c56f98SSadaf Ebrahimi static void x509_crt_verify_chain_reset(
373*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_verify_chain *ver_chain)
374*62c56f98SSadaf Ebrahimi {
375*62c56f98SSadaf Ebrahimi size_t i;
376*62c56f98SSadaf Ebrahimi
377*62c56f98SSadaf Ebrahimi for (i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++) {
378*62c56f98SSadaf Ebrahimi ver_chain->items[i].crt = NULL;
379*62c56f98SSadaf Ebrahimi ver_chain->items[i].flags = (uint32_t) -1;
380*62c56f98SSadaf Ebrahimi }
381*62c56f98SSadaf Ebrahimi
382*62c56f98SSadaf Ebrahimi ver_chain->len = 0;
383*62c56f98SSadaf Ebrahimi
384*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
385*62c56f98SSadaf Ebrahimi ver_chain->trust_ca_cb_result = NULL;
386*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
387*62c56f98SSadaf Ebrahimi }
388*62c56f98SSadaf Ebrahimi
389*62c56f98SSadaf Ebrahimi /*
390*62c56f98SSadaf Ebrahimi * Version ::= INTEGER { v1(0), v2(1), v3(2) }
391*62c56f98SSadaf Ebrahimi */
x509_get_version(unsigned char ** p,const unsigned char * end,int * ver)392*62c56f98SSadaf Ebrahimi static int x509_get_version(unsigned char **p,
393*62c56f98SSadaf Ebrahimi const unsigned char *end,
394*62c56f98SSadaf Ebrahimi int *ver)
395*62c56f98SSadaf Ebrahimi {
396*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
397*62c56f98SSadaf Ebrahimi size_t len;
398*62c56f98SSadaf Ebrahimi
399*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end, &len,
400*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
401*62c56f98SSadaf Ebrahimi 0)) != 0) {
402*62c56f98SSadaf Ebrahimi if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
403*62c56f98SSadaf Ebrahimi *ver = 0;
404*62c56f98SSadaf Ebrahimi return 0;
405*62c56f98SSadaf Ebrahimi }
406*62c56f98SSadaf Ebrahimi
407*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
408*62c56f98SSadaf Ebrahimi }
409*62c56f98SSadaf Ebrahimi
410*62c56f98SSadaf Ebrahimi end = *p + len;
411*62c56f98SSadaf Ebrahimi
412*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {
413*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);
414*62c56f98SSadaf Ebrahimi }
415*62c56f98SSadaf Ebrahimi
416*62c56f98SSadaf Ebrahimi if (*p != end) {
417*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION,
418*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
419*62c56f98SSadaf Ebrahimi }
420*62c56f98SSadaf Ebrahimi
421*62c56f98SSadaf Ebrahimi return 0;
422*62c56f98SSadaf Ebrahimi }
423*62c56f98SSadaf Ebrahimi
424*62c56f98SSadaf Ebrahimi /*
425*62c56f98SSadaf Ebrahimi * Validity ::= SEQUENCE {
426*62c56f98SSadaf Ebrahimi * notBefore Time,
427*62c56f98SSadaf Ebrahimi * notAfter Time }
428*62c56f98SSadaf Ebrahimi */
x509_get_dates(unsigned char ** p,const unsigned char * end,mbedtls_x509_time * from,mbedtls_x509_time * to)429*62c56f98SSadaf Ebrahimi static int x509_get_dates(unsigned char **p,
430*62c56f98SSadaf Ebrahimi const unsigned char *end,
431*62c56f98SSadaf Ebrahimi mbedtls_x509_time *from,
432*62c56f98SSadaf Ebrahimi mbedtls_x509_time *to)
433*62c56f98SSadaf Ebrahimi {
434*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
435*62c56f98SSadaf Ebrahimi size_t len;
436*62c56f98SSadaf Ebrahimi
437*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end, &len,
438*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
439*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret);
440*62c56f98SSadaf Ebrahimi }
441*62c56f98SSadaf Ebrahimi
442*62c56f98SSadaf Ebrahimi end = *p + len;
443*62c56f98SSadaf Ebrahimi
444*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_get_time(p, end, from)) != 0) {
445*62c56f98SSadaf Ebrahimi return ret;
446*62c56f98SSadaf Ebrahimi }
447*62c56f98SSadaf Ebrahimi
448*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_get_time(p, end, to)) != 0) {
449*62c56f98SSadaf Ebrahimi return ret;
450*62c56f98SSadaf Ebrahimi }
451*62c56f98SSadaf Ebrahimi
452*62c56f98SSadaf Ebrahimi if (*p != end) {
453*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
454*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
455*62c56f98SSadaf Ebrahimi }
456*62c56f98SSadaf Ebrahimi
457*62c56f98SSadaf Ebrahimi return 0;
458*62c56f98SSadaf Ebrahimi }
459*62c56f98SSadaf Ebrahimi
460*62c56f98SSadaf Ebrahimi /*
461*62c56f98SSadaf Ebrahimi * X.509 v2/v3 unique identifier (not parsed)
462*62c56f98SSadaf Ebrahimi */
x509_get_uid(unsigned char ** p,const unsigned char * end,mbedtls_x509_buf * uid,int n)463*62c56f98SSadaf Ebrahimi static int x509_get_uid(unsigned char **p,
464*62c56f98SSadaf Ebrahimi const unsigned char *end,
465*62c56f98SSadaf Ebrahimi mbedtls_x509_buf *uid, int n)
466*62c56f98SSadaf Ebrahimi {
467*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
468*62c56f98SSadaf Ebrahimi
469*62c56f98SSadaf Ebrahimi if (*p == end) {
470*62c56f98SSadaf Ebrahimi return 0;
471*62c56f98SSadaf Ebrahimi }
472*62c56f98SSadaf Ebrahimi
473*62c56f98SSadaf Ebrahimi uid->tag = **p;
474*62c56f98SSadaf Ebrahimi
475*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end, &uid->len,
476*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
477*62c56f98SSadaf Ebrahimi n)) != 0) {
478*62c56f98SSadaf Ebrahimi if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
479*62c56f98SSadaf Ebrahimi return 0;
480*62c56f98SSadaf Ebrahimi }
481*62c56f98SSadaf Ebrahimi
482*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
483*62c56f98SSadaf Ebrahimi }
484*62c56f98SSadaf Ebrahimi
485*62c56f98SSadaf Ebrahimi uid->p = *p;
486*62c56f98SSadaf Ebrahimi *p += uid->len;
487*62c56f98SSadaf Ebrahimi
488*62c56f98SSadaf Ebrahimi return 0;
489*62c56f98SSadaf Ebrahimi }
490*62c56f98SSadaf Ebrahimi
x509_get_basic_constraints(unsigned char ** p,const unsigned char * end,int * ca_istrue,int * max_pathlen)491*62c56f98SSadaf Ebrahimi static int x509_get_basic_constraints(unsigned char **p,
492*62c56f98SSadaf Ebrahimi const unsigned char *end,
493*62c56f98SSadaf Ebrahimi int *ca_istrue,
494*62c56f98SSadaf Ebrahimi int *max_pathlen)
495*62c56f98SSadaf Ebrahimi {
496*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
497*62c56f98SSadaf Ebrahimi size_t len;
498*62c56f98SSadaf Ebrahimi
499*62c56f98SSadaf Ebrahimi /*
500*62c56f98SSadaf Ebrahimi * BasicConstraints ::= SEQUENCE {
501*62c56f98SSadaf Ebrahimi * cA BOOLEAN DEFAULT FALSE,
502*62c56f98SSadaf Ebrahimi * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
503*62c56f98SSadaf Ebrahimi */
504*62c56f98SSadaf Ebrahimi *ca_istrue = 0; /* DEFAULT FALSE */
505*62c56f98SSadaf Ebrahimi *max_pathlen = 0; /* endless */
506*62c56f98SSadaf Ebrahimi
507*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end, &len,
508*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
509*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
510*62c56f98SSadaf Ebrahimi }
511*62c56f98SSadaf Ebrahimi
512*62c56f98SSadaf Ebrahimi if (*p == end) {
513*62c56f98SSadaf Ebrahimi return 0;
514*62c56f98SSadaf Ebrahimi }
515*62c56f98SSadaf Ebrahimi
516*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_bool(p, end, ca_istrue)) != 0) {
517*62c56f98SSadaf Ebrahimi if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
518*62c56f98SSadaf Ebrahimi ret = mbedtls_asn1_get_int(p, end, ca_istrue);
519*62c56f98SSadaf Ebrahimi }
520*62c56f98SSadaf Ebrahimi
521*62c56f98SSadaf Ebrahimi if (ret != 0) {
522*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
523*62c56f98SSadaf Ebrahimi }
524*62c56f98SSadaf Ebrahimi
525*62c56f98SSadaf Ebrahimi if (*ca_istrue != 0) {
526*62c56f98SSadaf Ebrahimi *ca_istrue = 1;
527*62c56f98SSadaf Ebrahimi }
528*62c56f98SSadaf Ebrahimi }
529*62c56f98SSadaf Ebrahimi
530*62c56f98SSadaf Ebrahimi if (*p == end) {
531*62c56f98SSadaf Ebrahimi return 0;
532*62c56f98SSadaf Ebrahimi }
533*62c56f98SSadaf Ebrahimi
534*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_int(p, end, max_pathlen)) != 0) {
535*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
536*62c56f98SSadaf Ebrahimi }
537*62c56f98SSadaf Ebrahimi
538*62c56f98SSadaf Ebrahimi if (*p != end) {
539*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
540*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
541*62c56f98SSadaf Ebrahimi }
542*62c56f98SSadaf Ebrahimi
543*62c56f98SSadaf Ebrahimi /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer
544*62c56f98SSadaf Ebrahimi * overflow, which is an undefined behavior. */
545*62c56f98SSadaf Ebrahimi if (*max_pathlen == INT_MAX) {
546*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
547*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_INVALID_LENGTH);
548*62c56f98SSadaf Ebrahimi }
549*62c56f98SSadaf Ebrahimi
550*62c56f98SSadaf Ebrahimi (*max_pathlen)++;
551*62c56f98SSadaf Ebrahimi
552*62c56f98SSadaf Ebrahimi return 0;
553*62c56f98SSadaf Ebrahimi }
554*62c56f98SSadaf Ebrahimi
555*62c56f98SSadaf Ebrahimi /*
556*62c56f98SSadaf Ebrahimi * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
557*62c56f98SSadaf Ebrahimi *
558*62c56f98SSadaf Ebrahimi * KeyPurposeId ::= OBJECT IDENTIFIER
559*62c56f98SSadaf Ebrahimi */
x509_get_ext_key_usage(unsigned char ** p,const unsigned char * end,mbedtls_x509_sequence * ext_key_usage)560*62c56f98SSadaf Ebrahimi static int x509_get_ext_key_usage(unsigned char **p,
561*62c56f98SSadaf Ebrahimi const unsigned char *end,
562*62c56f98SSadaf Ebrahimi mbedtls_x509_sequence *ext_key_usage)
563*62c56f98SSadaf Ebrahimi {
564*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
565*62c56f98SSadaf Ebrahimi
566*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_sequence_of(p, end, ext_key_usage, MBEDTLS_ASN1_OID)) != 0) {
567*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
568*62c56f98SSadaf Ebrahimi }
569*62c56f98SSadaf Ebrahimi
570*62c56f98SSadaf Ebrahimi /* Sequence length must be >= 1 */
571*62c56f98SSadaf Ebrahimi if (ext_key_usage->buf.p == NULL) {
572*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
573*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_INVALID_LENGTH);
574*62c56f98SSadaf Ebrahimi }
575*62c56f98SSadaf Ebrahimi
576*62c56f98SSadaf Ebrahimi return 0;
577*62c56f98SSadaf Ebrahimi }
578*62c56f98SSadaf Ebrahimi
579*62c56f98SSadaf Ebrahimi /*
580*62c56f98SSadaf Ebrahimi * SubjectKeyIdentifier ::= KeyIdentifier
581*62c56f98SSadaf Ebrahimi *
582*62c56f98SSadaf Ebrahimi * KeyIdentifier ::= OCTET STRING
583*62c56f98SSadaf Ebrahimi */
x509_get_subject_key_id(unsigned char ** p,const unsigned char * end,mbedtls_x509_buf * subject_key_id)584*62c56f98SSadaf Ebrahimi static int x509_get_subject_key_id(unsigned char **p,
585*62c56f98SSadaf Ebrahimi const unsigned char *end,
586*62c56f98SSadaf Ebrahimi mbedtls_x509_buf *subject_key_id)
587*62c56f98SSadaf Ebrahimi {
588*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
589*62c56f98SSadaf Ebrahimi size_t len = 0u;
590*62c56f98SSadaf Ebrahimi
591*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end, &len,
592*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_OCTET_STRING)) != 0) {
593*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
594*62c56f98SSadaf Ebrahimi }
595*62c56f98SSadaf Ebrahimi
596*62c56f98SSadaf Ebrahimi subject_key_id->len = len;
597*62c56f98SSadaf Ebrahimi subject_key_id->tag = MBEDTLS_ASN1_OCTET_STRING;
598*62c56f98SSadaf Ebrahimi subject_key_id->p = *p;
599*62c56f98SSadaf Ebrahimi *p += len;
600*62c56f98SSadaf Ebrahimi
601*62c56f98SSadaf Ebrahimi if (*p != end) {
602*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
603*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
604*62c56f98SSadaf Ebrahimi }
605*62c56f98SSadaf Ebrahimi
606*62c56f98SSadaf Ebrahimi return 0;
607*62c56f98SSadaf Ebrahimi }
608*62c56f98SSadaf Ebrahimi
609*62c56f98SSadaf Ebrahimi /*
610*62c56f98SSadaf Ebrahimi * AuthorityKeyIdentifier ::= SEQUENCE {
611*62c56f98SSadaf Ebrahimi * keyIdentifier [0] KeyIdentifier OPTIONAL,
612*62c56f98SSadaf Ebrahimi * authorityCertIssuer [1] GeneralNames OPTIONAL,
613*62c56f98SSadaf Ebrahimi * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
614*62c56f98SSadaf Ebrahimi *
615*62c56f98SSadaf Ebrahimi * KeyIdentifier ::= OCTET STRING
616*62c56f98SSadaf Ebrahimi */
x509_get_authority_key_id(unsigned char ** p,unsigned char * end,mbedtls_x509_authority * authority_key_id)617*62c56f98SSadaf Ebrahimi static int x509_get_authority_key_id(unsigned char **p,
618*62c56f98SSadaf Ebrahimi unsigned char *end,
619*62c56f98SSadaf Ebrahimi mbedtls_x509_authority *authority_key_id)
620*62c56f98SSadaf Ebrahimi {
621*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
622*62c56f98SSadaf Ebrahimi size_t len = 0u;
623*62c56f98SSadaf Ebrahimi
624*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end, &len,
625*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
626*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
627*62c56f98SSadaf Ebrahimi }
628*62c56f98SSadaf Ebrahimi
629*62c56f98SSadaf Ebrahimi if (*p + len != end) {
630*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
631*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
632*62c56f98SSadaf Ebrahimi }
633*62c56f98SSadaf Ebrahimi
634*62c56f98SSadaf Ebrahimi ret = mbedtls_asn1_get_tag(p, end, &len,
635*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONTEXT_SPECIFIC);
636*62c56f98SSadaf Ebrahimi
637*62c56f98SSadaf Ebrahimi /* KeyIdentifier is an OPTIONAL field */
638*62c56f98SSadaf Ebrahimi if (ret == 0) {
639*62c56f98SSadaf Ebrahimi authority_key_id->keyIdentifier.len = len;
640*62c56f98SSadaf Ebrahimi authority_key_id->keyIdentifier.p = *p;
641*62c56f98SSadaf Ebrahimi /* Setting tag of the keyIdentfier intentionally to 0x04.
642*62c56f98SSadaf Ebrahimi * Although the .keyIdentfier field is CONTEXT_SPECIFIC ([0] OPTIONAL),
643*62c56f98SSadaf Ebrahimi * its tag with the content is the payload of on OCTET STRING primitive */
644*62c56f98SSadaf Ebrahimi authority_key_id->keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING;
645*62c56f98SSadaf Ebrahimi
646*62c56f98SSadaf Ebrahimi *p += len;
647*62c56f98SSadaf Ebrahimi } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
648*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
649*62c56f98SSadaf Ebrahimi }
650*62c56f98SSadaf Ebrahimi
651*62c56f98SSadaf Ebrahimi if (*p < end) {
652*62c56f98SSadaf Ebrahimi /* Getting authorityCertIssuer using the required specific class tag [1] */
653*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end, &len,
654*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
655*62c56f98SSadaf Ebrahimi 1)) != 0) {
656*62c56f98SSadaf Ebrahimi /* authorityCertIssuer and authorityCertSerialNumber MUST both
657*62c56f98SSadaf Ebrahimi be present or both be absent. At this point we expect to have both. */
658*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
659*62c56f98SSadaf Ebrahimi }
660*62c56f98SSadaf Ebrahimi /* "end" also includes the CertSerialNumber field so "len" shall be used */
661*62c56f98SSadaf Ebrahimi ret = mbedtls_x509_get_subject_alt_name_ext(p,
662*62c56f98SSadaf Ebrahimi (*p+len),
663*62c56f98SSadaf Ebrahimi &authority_key_id->authorityCertIssuer);
664*62c56f98SSadaf Ebrahimi if (ret != 0) {
665*62c56f98SSadaf Ebrahimi return ret;
666*62c56f98SSadaf Ebrahimi }
667*62c56f98SSadaf Ebrahimi
668*62c56f98SSadaf Ebrahimi /* Getting authorityCertSerialNumber using the required specific class tag [2] */
669*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end, &len,
670*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2)) != 0) {
671*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
672*62c56f98SSadaf Ebrahimi }
673*62c56f98SSadaf Ebrahimi authority_key_id->authorityCertSerialNumber.len = len;
674*62c56f98SSadaf Ebrahimi authority_key_id->authorityCertSerialNumber.p = *p;
675*62c56f98SSadaf Ebrahimi authority_key_id->authorityCertSerialNumber.tag = MBEDTLS_ASN1_INTEGER;
676*62c56f98SSadaf Ebrahimi *p += len;
677*62c56f98SSadaf Ebrahimi }
678*62c56f98SSadaf Ebrahimi
679*62c56f98SSadaf Ebrahimi if (*p != end) {
680*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
681*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
682*62c56f98SSadaf Ebrahimi }
683*62c56f98SSadaf Ebrahimi
684*62c56f98SSadaf Ebrahimi return 0;
685*62c56f98SSadaf Ebrahimi }
686*62c56f98SSadaf Ebrahimi
687*62c56f98SSadaf Ebrahimi /*
688*62c56f98SSadaf Ebrahimi * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 }
689*62c56f98SSadaf Ebrahimi *
690*62c56f98SSadaf Ebrahimi * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 }
691*62c56f98SSadaf Ebrahimi *
692*62c56f98SSadaf Ebrahimi * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
693*62c56f98SSadaf Ebrahimi *
694*62c56f98SSadaf Ebrahimi * PolicyInformation ::= SEQUENCE {
695*62c56f98SSadaf Ebrahimi * policyIdentifier CertPolicyId,
696*62c56f98SSadaf Ebrahimi * policyQualifiers SEQUENCE SIZE (1..MAX) OF
697*62c56f98SSadaf Ebrahimi * PolicyQualifierInfo OPTIONAL }
698*62c56f98SSadaf Ebrahimi *
699*62c56f98SSadaf Ebrahimi * CertPolicyId ::= OBJECT IDENTIFIER
700*62c56f98SSadaf Ebrahimi *
701*62c56f98SSadaf Ebrahimi * PolicyQualifierInfo ::= SEQUENCE {
702*62c56f98SSadaf Ebrahimi * policyQualifierId PolicyQualifierId,
703*62c56f98SSadaf Ebrahimi * qualifier ANY DEFINED BY policyQualifierId }
704*62c56f98SSadaf Ebrahimi *
705*62c56f98SSadaf Ebrahimi * -- policyQualifierIds for Internet policy qualifiers
706*62c56f98SSadaf Ebrahimi *
707*62c56f98SSadaf Ebrahimi * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
708*62c56f98SSadaf Ebrahimi * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
709*62c56f98SSadaf Ebrahimi * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
710*62c56f98SSadaf Ebrahimi *
711*62c56f98SSadaf Ebrahimi * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
712*62c56f98SSadaf Ebrahimi *
713*62c56f98SSadaf Ebrahimi * Qualifier ::= CHOICE {
714*62c56f98SSadaf Ebrahimi * cPSuri CPSuri,
715*62c56f98SSadaf Ebrahimi * userNotice UserNotice }
716*62c56f98SSadaf Ebrahimi *
717*62c56f98SSadaf Ebrahimi * CPSuri ::= IA5String
718*62c56f98SSadaf Ebrahimi *
719*62c56f98SSadaf Ebrahimi * UserNotice ::= SEQUENCE {
720*62c56f98SSadaf Ebrahimi * noticeRef NoticeReference OPTIONAL,
721*62c56f98SSadaf Ebrahimi * explicitText DisplayText OPTIONAL }
722*62c56f98SSadaf Ebrahimi *
723*62c56f98SSadaf Ebrahimi * NoticeReference ::= SEQUENCE {
724*62c56f98SSadaf Ebrahimi * organization DisplayText,
725*62c56f98SSadaf Ebrahimi * noticeNumbers SEQUENCE OF INTEGER }
726*62c56f98SSadaf Ebrahimi *
727*62c56f98SSadaf Ebrahimi * DisplayText ::= CHOICE {
728*62c56f98SSadaf Ebrahimi * ia5String IA5String (SIZE (1..200)),
729*62c56f98SSadaf Ebrahimi * visibleString VisibleString (SIZE (1..200)),
730*62c56f98SSadaf Ebrahimi * bmpString BMPString (SIZE (1..200)),
731*62c56f98SSadaf Ebrahimi * utf8String UTF8String (SIZE (1..200)) }
732*62c56f98SSadaf Ebrahimi *
733*62c56f98SSadaf Ebrahimi * NOTE: we only parse and use anyPolicy without qualifiers at this point
734*62c56f98SSadaf Ebrahimi * as defined in RFC 5280.
735*62c56f98SSadaf Ebrahimi */
x509_get_certificate_policies(unsigned char ** p,const unsigned char * end,mbedtls_x509_sequence * certificate_policies)736*62c56f98SSadaf Ebrahimi static int x509_get_certificate_policies(unsigned char **p,
737*62c56f98SSadaf Ebrahimi const unsigned char *end,
738*62c56f98SSadaf Ebrahimi mbedtls_x509_sequence *certificate_policies)
739*62c56f98SSadaf Ebrahimi {
740*62c56f98SSadaf Ebrahimi int ret, parse_ret = 0;
741*62c56f98SSadaf Ebrahimi size_t len;
742*62c56f98SSadaf Ebrahimi mbedtls_asn1_buf *buf;
743*62c56f98SSadaf Ebrahimi mbedtls_asn1_sequence *cur = certificate_policies;
744*62c56f98SSadaf Ebrahimi
745*62c56f98SSadaf Ebrahimi /* Get main sequence tag */
746*62c56f98SSadaf Ebrahimi ret = mbedtls_asn1_get_tag(p, end, &len,
747*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
748*62c56f98SSadaf Ebrahimi if (ret != 0) {
749*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
750*62c56f98SSadaf Ebrahimi }
751*62c56f98SSadaf Ebrahimi
752*62c56f98SSadaf Ebrahimi if (*p + len != end) {
753*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
754*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
755*62c56f98SSadaf Ebrahimi }
756*62c56f98SSadaf Ebrahimi
757*62c56f98SSadaf Ebrahimi /*
758*62c56f98SSadaf Ebrahimi * Cannot be an empty sequence.
759*62c56f98SSadaf Ebrahimi */
760*62c56f98SSadaf Ebrahimi if (len == 0) {
761*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
762*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
763*62c56f98SSadaf Ebrahimi }
764*62c56f98SSadaf Ebrahimi
765*62c56f98SSadaf Ebrahimi while (*p < end) {
766*62c56f98SSadaf Ebrahimi mbedtls_x509_buf policy_oid;
767*62c56f98SSadaf Ebrahimi const unsigned char *policy_end;
768*62c56f98SSadaf Ebrahimi
769*62c56f98SSadaf Ebrahimi /*
770*62c56f98SSadaf Ebrahimi * Get the policy sequence
771*62c56f98SSadaf Ebrahimi */
772*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end, &len,
773*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
774*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
775*62c56f98SSadaf Ebrahimi }
776*62c56f98SSadaf Ebrahimi
777*62c56f98SSadaf Ebrahimi policy_end = *p + len;
778*62c56f98SSadaf Ebrahimi
779*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len,
780*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_OID)) != 0) {
781*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
782*62c56f98SSadaf Ebrahimi }
783*62c56f98SSadaf Ebrahimi
784*62c56f98SSadaf Ebrahimi policy_oid.tag = MBEDTLS_ASN1_OID;
785*62c56f98SSadaf Ebrahimi policy_oid.len = len;
786*62c56f98SSadaf Ebrahimi policy_oid.p = *p;
787*62c56f98SSadaf Ebrahimi
788*62c56f98SSadaf Ebrahimi /*
789*62c56f98SSadaf Ebrahimi * Only AnyPolicy is currently supported when enforcing policy.
790*62c56f98SSadaf Ebrahimi */
791*62c56f98SSadaf Ebrahimi if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_POLICY, &policy_oid) != 0) {
792*62c56f98SSadaf Ebrahimi /*
793*62c56f98SSadaf Ebrahimi * Set the parsing return code but continue parsing, in case this
794*62c56f98SSadaf Ebrahimi * extension is critical.
795*62c56f98SSadaf Ebrahimi */
796*62c56f98SSadaf Ebrahimi parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
797*62c56f98SSadaf Ebrahimi }
798*62c56f98SSadaf Ebrahimi
799*62c56f98SSadaf Ebrahimi /* Allocate and assign next pointer */
800*62c56f98SSadaf Ebrahimi if (cur->buf.p != NULL) {
801*62c56f98SSadaf Ebrahimi if (cur->next != NULL) {
802*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
803*62c56f98SSadaf Ebrahimi }
804*62c56f98SSadaf Ebrahimi
805*62c56f98SSadaf Ebrahimi cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
806*62c56f98SSadaf Ebrahimi
807*62c56f98SSadaf Ebrahimi if (cur->next == NULL) {
808*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
809*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_ALLOC_FAILED);
810*62c56f98SSadaf Ebrahimi }
811*62c56f98SSadaf Ebrahimi
812*62c56f98SSadaf Ebrahimi cur = cur->next;
813*62c56f98SSadaf Ebrahimi }
814*62c56f98SSadaf Ebrahimi
815*62c56f98SSadaf Ebrahimi buf = &(cur->buf);
816*62c56f98SSadaf Ebrahimi buf->tag = policy_oid.tag;
817*62c56f98SSadaf Ebrahimi buf->p = policy_oid.p;
818*62c56f98SSadaf Ebrahimi buf->len = policy_oid.len;
819*62c56f98SSadaf Ebrahimi
820*62c56f98SSadaf Ebrahimi *p += len;
821*62c56f98SSadaf Ebrahimi
822*62c56f98SSadaf Ebrahimi /*
823*62c56f98SSadaf Ebrahimi * If there is an optional qualifier, then *p < policy_end
824*62c56f98SSadaf Ebrahimi * Check the Qualifier len to verify it doesn't exceed policy_end.
825*62c56f98SSadaf Ebrahimi */
826*62c56f98SSadaf Ebrahimi if (*p < policy_end) {
827*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len,
828*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
829*62c56f98SSadaf Ebrahimi 0) {
830*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
831*62c56f98SSadaf Ebrahimi }
832*62c56f98SSadaf Ebrahimi /*
833*62c56f98SSadaf Ebrahimi * Skip the optional policy qualifiers.
834*62c56f98SSadaf Ebrahimi */
835*62c56f98SSadaf Ebrahimi *p += len;
836*62c56f98SSadaf Ebrahimi }
837*62c56f98SSadaf Ebrahimi
838*62c56f98SSadaf Ebrahimi if (*p != policy_end) {
839*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
840*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
841*62c56f98SSadaf Ebrahimi }
842*62c56f98SSadaf Ebrahimi }
843*62c56f98SSadaf Ebrahimi
844*62c56f98SSadaf Ebrahimi /* Set final sequence entry's next pointer to NULL */
845*62c56f98SSadaf Ebrahimi cur->next = NULL;
846*62c56f98SSadaf Ebrahimi
847*62c56f98SSadaf Ebrahimi if (*p != end) {
848*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
849*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
850*62c56f98SSadaf Ebrahimi }
851*62c56f98SSadaf Ebrahimi
852*62c56f98SSadaf Ebrahimi return parse_ret;
853*62c56f98SSadaf Ebrahimi }
854*62c56f98SSadaf Ebrahimi
855*62c56f98SSadaf Ebrahimi /*
856*62c56f98SSadaf Ebrahimi * X.509 v3 extensions
857*62c56f98SSadaf Ebrahimi *
858*62c56f98SSadaf Ebrahimi */
x509_get_crt_ext(unsigned char ** p,const unsigned char * end,mbedtls_x509_crt * crt,mbedtls_x509_crt_ext_cb_t cb,void * p_ctx)859*62c56f98SSadaf Ebrahimi static int x509_get_crt_ext(unsigned char **p,
860*62c56f98SSadaf Ebrahimi const unsigned char *end,
861*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *crt,
862*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_ext_cb_t cb,
863*62c56f98SSadaf Ebrahimi void *p_ctx)
864*62c56f98SSadaf Ebrahimi {
865*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
866*62c56f98SSadaf Ebrahimi size_t len;
867*62c56f98SSadaf Ebrahimi unsigned char *end_ext_data, *start_ext_octet, *end_ext_octet;
868*62c56f98SSadaf Ebrahimi
869*62c56f98SSadaf Ebrahimi if (*p == end) {
870*62c56f98SSadaf Ebrahimi return 0;
871*62c56f98SSadaf Ebrahimi }
872*62c56f98SSadaf Ebrahimi
873*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_get_ext(p, end, &crt->v3_ext, 3)) != 0) {
874*62c56f98SSadaf Ebrahimi return ret;
875*62c56f98SSadaf Ebrahimi }
876*62c56f98SSadaf Ebrahimi
877*62c56f98SSadaf Ebrahimi end = crt->v3_ext.p + crt->v3_ext.len;
878*62c56f98SSadaf Ebrahimi while (*p < end) {
879*62c56f98SSadaf Ebrahimi /*
880*62c56f98SSadaf Ebrahimi * Extension ::= SEQUENCE {
881*62c56f98SSadaf Ebrahimi * extnID OBJECT IDENTIFIER,
882*62c56f98SSadaf Ebrahimi * critical BOOLEAN DEFAULT FALSE,
883*62c56f98SSadaf Ebrahimi * extnValue OCTET STRING }
884*62c56f98SSadaf Ebrahimi */
885*62c56f98SSadaf Ebrahimi mbedtls_x509_buf extn_oid = { 0, 0, NULL };
886*62c56f98SSadaf Ebrahimi int is_critical = 0; /* DEFAULT FALSE */
887*62c56f98SSadaf Ebrahimi int ext_type = 0;
888*62c56f98SSadaf Ebrahimi
889*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end, &len,
890*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
891*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
892*62c56f98SSadaf Ebrahimi }
893*62c56f98SSadaf Ebrahimi
894*62c56f98SSadaf Ebrahimi end_ext_data = *p + len;
895*62c56f98SSadaf Ebrahimi
896*62c56f98SSadaf Ebrahimi /* Get extension ID */
897*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len,
898*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_OID)) != 0) {
899*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
900*62c56f98SSadaf Ebrahimi }
901*62c56f98SSadaf Ebrahimi
902*62c56f98SSadaf Ebrahimi extn_oid.tag = MBEDTLS_ASN1_OID;
903*62c56f98SSadaf Ebrahimi extn_oid.p = *p;
904*62c56f98SSadaf Ebrahimi *p += extn_oid.len;
905*62c56f98SSadaf Ebrahimi
906*62c56f98SSadaf Ebrahimi /* Get optional critical */
907*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 &&
908*62c56f98SSadaf Ebrahimi (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
909*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
910*62c56f98SSadaf Ebrahimi }
911*62c56f98SSadaf Ebrahimi
912*62c56f98SSadaf Ebrahimi /* Data should be octet string type */
913*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
914*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_OCTET_STRING)) != 0) {
915*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
916*62c56f98SSadaf Ebrahimi }
917*62c56f98SSadaf Ebrahimi
918*62c56f98SSadaf Ebrahimi start_ext_octet = *p;
919*62c56f98SSadaf Ebrahimi end_ext_octet = *p + len;
920*62c56f98SSadaf Ebrahimi
921*62c56f98SSadaf Ebrahimi if (end_ext_octet != end_ext_data) {
922*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
923*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
924*62c56f98SSadaf Ebrahimi }
925*62c56f98SSadaf Ebrahimi
926*62c56f98SSadaf Ebrahimi /*
927*62c56f98SSadaf Ebrahimi * Detect supported extensions
928*62c56f98SSadaf Ebrahimi */
929*62c56f98SSadaf Ebrahimi ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
930*62c56f98SSadaf Ebrahimi
931*62c56f98SSadaf Ebrahimi if (ret != 0) {
932*62c56f98SSadaf Ebrahimi /* Give the callback (if any) a chance to handle the extension */
933*62c56f98SSadaf Ebrahimi if (cb != NULL) {
934*62c56f98SSadaf Ebrahimi ret = cb(p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet);
935*62c56f98SSadaf Ebrahimi if (ret != 0 && is_critical) {
936*62c56f98SSadaf Ebrahimi return ret;
937*62c56f98SSadaf Ebrahimi }
938*62c56f98SSadaf Ebrahimi *p = end_ext_octet;
939*62c56f98SSadaf Ebrahimi continue;
940*62c56f98SSadaf Ebrahimi }
941*62c56f98SSadaf Ebrahimi
942*62c56f98SSadaf Ebrahimi /* No parser found, skip extension */
943*62c56f98SSadaf Ebrahimi *p = end_ext_octet;
944*62c56f98SSadaf Ebrahimi
945*62c56f98SSadaf Ebrahimi if (is_critical) {
946*62c56f98SSadaf Ebrahimi /* Data is marked as critical: fail */
947*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
948*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
949*62c56f98SSadaf Ebrahimi }
950*62c56f98SSadaf Ebrahimi continue;
951*62c56f98SSadaf Ebrahimi }
952*62c56f98SSadaf Ebrahimi
953*62c56f98SSadaf Ebrahimi /* Forbid repeated extensions */
954*62c56f98SSadaf Ebrahimi if ((crt->ext_types & ext_type) != 0) {
955*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
956*62c56f98SSadaf Ebrahimi }
957*62c56f98SSadaf Ebrahimi
958*62c56f98SSadaf Ebrahimi crt->ext_types |= ext_type;
959*62c56f98SSadaf Ebrahimi
960*62c56f98SSadaf Ebrahimi switch (ext_type) {
961*62c56f98SSadaf Ebrahimi case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
962*62c56f98SSadaf Ebrahimi /* Parse basic constraints */
963*62c56f98SSadaf Ebrahimi if ((ret = x509_get_basic_constraints(p, end_ext_octet,
964*62c56f98SSadaf Ebrahimi &crt->ca_istrue, &crt->max_pathlen)) != 0) {
965*62c56f98SSadaf Ebrahimi return ret;
966*62c56f98SSadaf Ebrahimi }
967*62c56f98SSadaf Ebrahimi break;
968*62c56f98SSadaf Ebrahimi
969*62c56f98SSadaf Ebrahimi case MBEDTLS_X509_EXT_KEY_USAGE:
970*62c56f98SSadaf Ebrahimi /* Parse key usage */
971*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_get_key_usage(p, end_ext_octet,
972*62c56f98SSadaf Ebrahimi &crt->key_usage)) != 0) {
973*62c56f98SSadaf Ebrahimi return ret;
974*62c56f98SSadaf Ebrahimi }
975*62c56f98SSadaf Ebrahimi break;
976*62c56f98SSadaf Ebrahimi
977*62c56f98SSadaf Ebrahimi case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
978*62c56f98SSadaf Ebrahimi /* Parse extended key usage */
979*62c56f98SSadaf Ebrahimi if ((ret = x509_get_ext_key_usage(p, end_ext_octet,
980*62c56f98SSadaf Ebrahimi &crt->ext_key_usage)) != 0) {
981*62c56f98SSadaf Ebrahimi return ret;
982*62c56f98SSadaf Ebrahimi }
983*62c56f98SSadaf Ebrahimi break;
984*62c56f98SSadaf Ebrahimi
985*62c56f98SSadaf Ebrahimi case MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER:
986*62c56f98SSadaf Ebrahimi /* Parse subject key identifier */
987*62c56f98SSadaf Ebrahimi if ((ret = x509_get_subject_key_id(p, end_ext_data,
988*62c56f98SSadaf Ebrahimi &crt->subject_key_id)) != 0) {
989*62c56f98SSadaf Ebrahimi return ret;
990*62c56f98SSadaf Ebrahimi }
991*62c56f98SSadaf Ebrahimi break;
992*62c56f98SSadaf Ebrahimi
993*62c56f98SSadaf Ebrahimi case MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER:
994*62c56f98SSadaf Ebrahimi /* Parse authority key identifier */
995*62c56f98SSadaf Ebrahimi if ((ret = x509_get_authority_key_id(p, end_ext_octet,
996*62c56f98SSadaf Ebrahimi &crt->authority_key_id)) != 0) {
997*62c56f98SSadaf Ebrahimi return ret;
998*62c56f98SSadaf Ebrahimi }
999*62c56f98SSadaf Ebrahimi break;
1000*62c56f98SSadaf Ebrahimi case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
1001*62c56f98SSadaf Ebrahimi /* Parse subject alt name
1002*62c56f98SSadaf Ebrahimi * SubjectAltName ::= GeneralNames
1003*62c56f98SSadaf Ebrahimi */
1004*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_octet,
1005*62c56f98SSadaf Ebrahimi &crt->subject_alt_names)) != 0) {
1006*62c56f98SSadaf Ebrahimi return ret;
1007*62c56f98SSadaf Ebrahimi }
1008*62c56f98SSadaf Ebrahimi break;
1009*62c56f98SSadaf Ebrahimi
1010*62c56f98SSadaf Ebrahimi case MBEDTLS_X509_EXT_NS_CERT_TYPE:
1011*62c56f98SSadaf Ebrahimi /* Parse netscape certificate type */
1012*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_octet,
1013*62c56f98SSadaf Ebrahimi &crt->ns_cert_type)) != 0) {
1014*62c56f98SSadaf Ebrahimi return ret;
1015*62c56f98SSadaf Ebrahimi }
1016*62c56f98SSadaf Ebrahimi break;
1017*62c56f98SSadaf Ebrahimi
1018*62c56f98SSadaf Ebrahimi case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES:
1019*62c56f98SSadaf Ebrahimi /* Parse certificate policies type */
1020*62c56f98SSadaf Ebrahimi if ((ret = x509_get_certificate_policies(p, end_ext_octet,
1021*62c56f98SSadaf Ebrahimi &crt->certificate_policies)) != 0) {
1022*62c56f98SSadaf Ebrahimi /* Give the callback (if any) a chance to handle the extension
1023*62c56f98SSadaf Ebrahimi * if it contains unsupported policies */
1024*62c56f98SSadaf Ebrahimi if (ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL &&
1025*62c56f98SSadaf Ebrahimi cb(p_ctx, crt, &extn_oid, is_critical,
1026*62c56f98SSadaf Ebrahimi start_ext_octet, end_ext_octet) == 0) {
1027*62c56f98SSadaf Ebrahimi break;
1028*62c56f98SSadaf Ebrahimi }
1029*62c56f98SSadaf Ebrahimi
1030*62c56f98SSadaf Ebrahimi if (is_critical) {
1031*62c56f98SSadaf Ebrahimi return ret;
1032*62c56f98SSadaf Ebrahimi } else
1033*62c56f98SSadaf Ebrahimi /*
1034*62c56f98SSadaf Ebrahimi * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we
1035*62c56f98SSadaf Ebrahimi * cannot interpret or enforce the policy. However, it is up to
1036*62c56f98SSadaf Ebrahimi * the user to choose how to enforce the policies,
1037*62c56f98SSadaf Ebrahimi * unless the extension is critical.
1038*62c56f98SSadaf Ebrahimi */
1039*62c56f98SSadaf Ebrahimi if (ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
1040*62c56f98SSadaf Ebrahimi return ret;
1041*62c56f98SSadaf Ebrahimi }
1042*62c56f98SSadaf Ebrahimi }
1043*62c56f98SSadaf Ebrahimi break;
1044*62c56f98SSadaf Ebrahimi
1045*62c56f98SSadaf Ebrahimi default:
1046*62c56f98SSadaf Ebrahimi /*
1047*62c56f98SSadaf Ebrahimi * If this is a non-critical extension, which the oid layer
1048*62c56f98SSadaf Ebrahimi * supports, but there isn't an x509 parser for it,
1049*62c56f98SSadaf Ebrahimi * skip the extension.
1050*62c56f98SSadaf Ebrahimi */
1051*62c56f98SSadaf Ebrahimi if (is_critical) {
1052*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
1053*62c56f98SSadaf Ebrahimi } else {
1054*62c56f98SSadaf Ebrahimi *p = end_ext_octet;
1055*62c56f98SSadaf Ebrahimi }
1056*62c56f98SSadaf Ebrahimi }
1057*62c56f98SSadaf Ebrahimi }
1058*62c56f98SSadaf Ebrahimi
1059*62c56f98SSadaf Ebrahimi if (*p != end) {
1060*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1061*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1062*62c56f98SSadaf Ebrahimi }
1063*62c56f98SSadaf Ebrahimi
1064*62c56f98SSadaf Ebrahimi return 0;
1065*62c56f98SSadaf Ebrahimi }
1066*62c56f98SSadaf Ebrahimi
1067*62c56f98SSadaf Ebrahimi /*
1068*62c56f98SSadaf Ebrahimi * Parse and fill a single X.509 certificate in DER format
1069*62c56f98SSadaf Ebrahimi */
x509_crt_parse_der_core(mbedtls_x509_crt * crt,const unsigned char * buf,size_t buflen,int make_copy,mbedtls_x509_crt_ext_cb_t cb,void * p_ctx)1070*62c56f98SSadaf Ebrahimi static int x509_crt_parse_der_core(mbedtls_x509_crt *crt,
1071*62c56f98SSadaf Ebrahimi const unsigned char *buf,
1072*62c56f98SSadaf Ebrahimi size_t buflen,
1073*62c56f98SSadaf Ebrahimi int make_copy,
1074*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_ext_cb_t cb,
1075*62c56f98SSadaf Ebrahimi void *p_ctx)
1076*62c56f98SSadaf Ebrahimi {
1077*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1078*62c56f98SSadaf Ebrahimi size_t len;
1079*62c56f98SSadaf Ebrahimi unsigned char *p, *end, *crt_end;
1080*62c56f98SSadaf Ebrahimi mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
1081*62c56f98SSadaf Ebrahimi
1082*62c56f98SSadaf Ebrahimi memset(&sig_params1, 0, sizeof(mbedtls_x509_buf));
1083*62c56f98SSadaf Ebrahimi memset(&sig_params2, 0, sizeof(mbedtls_x509_buf));
1084*62c56f98SSadaf Ebrahimi memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf));
1085*62c56f98SSadaf Ebrahimi
1086*62c56f98SSadaf Ebrahimi /*
1087*62c56f98SSadaf Ebrahimi * Check for valid input
1088*62c56f98SSadaf Ebrahimi */
1089*62c56f98SSadaf Ebrahimi if (crt == NULL || buf == NULL) {
1090*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1091*62c56f98SSadaf Ebrahimi }
1092*62c56f98SSadaf Ebrahimi
1093*62c56f98SSadaf Ebrahimi /* Use the original buffer until we figure out actual length. */
1094*62c56f98SSadaf Ebrahimi p = (unsigned char *) buf;
1095*62c56f98SSadaf Ebrahimi len = buflen;
1096*62c56f98SSadaf Ebrahimi end = p + len;
1097*62c56f98SSadaf Ebrahimi
1098*62c56f98SSadaf Ebrahimi /*
1099*62c56f98SSadaf Ebrahimi * Certificate ::= SEQUENCE {
1100*62c56f98SSadaf Ebrahimi * tbsCertificate TBSCertificate,
1101*62c56f98SSadaf Ebrahimi * signatureAlgorithm AlgorithmIdentifier,
1102*62c56f98SSadaf Ebrahimi * signatureValue BIT STRING }
1103*62c56f98SSadaf Ebrahimi */
1104*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1105*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1106*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1107*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_INVALID_FORMAT;
1108*62c56f98SSadaf Ebrahimi }
1109*62c56f98SSadaf Ebrahimi
1110*62c56f98SSadaf Ebrahimi end = crt_end = p + len;
1111*62c56f98SSadaf Ebrahimi crt->raw.len = crt_end - buf;
1112*62c56f98SSadaf Ebrahimi if (make_copy != 0) {
1113*62c56f98SSadaf Ebrahimi /* Create and populate a new buffer for the raw field. */
1114*62c56f98SSadaf Ebrahimi crt->raw.p = p = mbedtls_calloc(1, crt->raw.len);
1115*62c56f98SSadaf Ebrahimi if (crt->raw.p == NULL) {
1116*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_ALLOC_FAILED;
1117*62c56f98SSadaf Ebrahimi }
1118*62c56f98SSadaf Ebrahimi
1119*62c56f98SSadaf Ebrahimi memcpy(crt->raw.p, buf, crt->raw.len);
1120*62c56f98SSadaf Ebrahimi crt->own_buffer = 1;
1121*62c56f98SSadaf Ebrahimi
1122*62c56f98SSadaf Ebrahimi p += crt->raw.len - len;
1123*62c56f98SSadaf Ebrahimi end = crt_end = p + len;
1124*62c56f98SSadaf Ebrahimi } else {
1125*62c56f98SSadaf Ebrahimi crt->raw.p = (unsigned char *) buf;
1126*62c56f98SSadaf Ebrahimi crt->own_buffer = 0;
1127*62c56f98SSadaf Ebrahimi }
1128*62c56f98SSadaf Ebrahimi
1129*62c56f98SSadaf Ebrahimi /*
1130*62c56f98SSadaf Ebrahimi * TBSCertificate ::= SEQUENCE {
1131*62c56f98SSadaf Ebrahimi */
1132*62c56f98SSadaf Ebrahimi crt->tbs.p = p;
1133*62c56f98SSadaf Ebrahimi
1134*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1135*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1136*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1137*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
1138*62c56f98SSadaf Ebrahimi }
1139*62c56f98SSadaf Ebrahimi
1140*62c56f98SSadaf Ebrahimi end = p + len;
1141*62c56f98SSadaf Ebrahimi crt->tbs.len = end - crt->tbs.p;
1142*62c56f98SSadaf Ebrahimi
1143*62c56f98SSadaf Ebrahimi /*
1144*62c56f98SSadaf Ebrahimi * Version ::= INTEGER { v1(0), v2(1), v3(2) }
1145*62c56f98SSadaf Ebrahimi *
1146*62c56f98SSadaf Ebrahimi * CertificateSerialNumber ::= INTEGER
1147*62c56f98SSadaf Ebrahimi *
1148*62c56f98SSadaf Ebrahimi * signature AlgorithmIdentifier
1149*62c56f98SSadaf Ebrahimi */
1150*62c56f98SSadaf Ebrahimi if ((ret = x509_get_version(&p, end, &crt->version)) != 0 ||
1151*62c56f98SSadaf Ebrahimi (ret = mbedtls_x509_get_serial(&p, end, &crt->serial)) != 0 ||
1152*62c56f98SSadaf Ebrahimi (ret = mbedtls_x509_get_alg(&p, end, &crt->sig_oid,
1153*62c56f98SSadaf Ebrahimi &sig_params1)) != 0) {
1154*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1155*62c56f98SSadaf Ebrahimi return ret;
1156*62c56f98SSadaf Ebrahimi }
1157*62c56f98SSadaf Ebrahimi
1158*62c56f98SSadaf Ebrahimi if (crt->version < 0 || crt->version > 2) {
1159*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1160*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_UNKNOWN_VERSION;
1161*62c56f98SSadaf Ebrahimi }
1162*62c56f98SSadaf Ebrahimi
1163*62c56f98SSadaf Ebrahimi crt->version++;
1164*62c56f98SSadaf Ebrahimi
1165*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_get_sig_alg(&crt->sig_oid, &sig_params1,
1166*62c56f98SSadaf Ebrahimi &crt->sig_md, &crt->sig_pk,
1167*62c56f98SSadaf Ebrahimi &crt->sig_opts)) != 0) {
1168*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1169*62c56f98SSadaf Ebrahimi return ret;
1170*62c56f98SSadaf Ebrahimi }
1171*62c56f98SSadaf Ebrahimi
1172*62c56f98SSadaf Ebrahimi /*
1173*62c56f98SSadaf Ebrahimi * issuer Name
1174*62c56f98SSadaf Ebrahimi */
1175*62c56f98SSadaf Ebrahimi crt->issuer_raw.p = p;
1176*62c56f98SSadaf Ebrahimi
1177*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1178*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1179*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1180*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
1181*62c56f98SSadaf Ebrahimi }
1182*62c56f98SSadaf Ebrahimi
1183*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_get_name(&p, p + len, &crt->issuer)) != 0) {
1184*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1185*62c56f98SSadaf Ebrahimi return ret;
1186*62c56f98SSadaf Ebrahimi }
1187*62c56f98SSadaf Ebrahimi
1188*62c56f98SSadaf Ebrahimi crt->issuer_raw.len = p - crt->issuer_raw.p;
1189*62c56f98SSadaf Ebrahimi
1190*62c56f98SSadaf Ebrahimi /*
1191*62c56f98SSadaf Ebrahimi * Validity ::= SEQUENCE {
1192*62c56f98SSadaf Ebrahimi * notBefore Time,
1193*62c56f98SSadaf Ebrahimi * notAfter Time }
1194*62c56f98SSadaf Ebrahimi *
1195*62c56f98SSadaf Ebrahimi */
1196*62c56f98SSadaf Ebrahimi if ((ret = x509_get_dates(&p, end, &crt->valid_from,
1197*62c56f98SSadaf Ebrahimi &crt->valid_to)) != 0) {
1198*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1199*62c56f98SSadaf Ebrahimi return ret;
1200*62c56f98SSadaf Ebrahimi }
1201*62c56f98SSadaf Ebrahimi
1202*62c56f98SSadaf Ebrahimi /*
1203*62c56f98SSadaf Ebrahimi * subject Name
1204*62c56f98SSadaf Ebrahimi */
1205*62c56f98SSadaf Ebrahimi crt->subject_raw.p = p;
1206*62c56f98SSadaf Ebrahimi
1207*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1208*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1209*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1210*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
1211*62c56f98SSadaf Ebrahimi }
1212*62c56f98SSadaf Ebrahimi
1213*62c56f98SSadaf Ebrahimi if (len && (ret = mbedtls_x509_get_name(&p, p + len, &crt->subject)) != 0) {
1214*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1215*62c56f98SSadaf Ebrahimi return ret;
1216*62c56f98SSadaf Ebrahimi }
1217*62c56f98SSadaf Ebrahimi
1218*62c56f98SSadaf Ebrahimi crt->subject_raw.len = p - crt->subject_raw.p;
1219*62c56f98SSadaf Ebrahimi
1220*62c56f98SSadaf Ebrahimi /*
1221*62c56f98SSadaf Ebrahimi * SubjectPublicKeyInfo
1222*62c56f98SSadaf Ebrahimi */
1223*62c56f98SSadaf Ebrahimi crt->pk_raw.p = p;
1224*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &crt->pk)) != 0) {
1225*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1226*62c56f98SSadaf Ebrahimi return ret;
1227*62c56f98SSadaf Ebrahimi }
1228*62c56f98SSadaf Ebrahimi crt->pk_raw.len = p - crt->pk_raw.p;
1229*62c56f98SSadaf Ebrahimi
1230*62c56f98SSadaf Ebrahimi /*
1231*62c56f98SSadaf Ebrahimi * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1232*62c56f98SSadaf Ebrahimi * -- If present, version shall be v2 or v3
1233*62c56f98SSadaf Ebrahimi * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1234*62c56f98SSadaf Ebrahimi * -- If present, version shall be v2 or v3
1235*62c56f98SSadaf Ebrahimi * extensions [3] EXPLICIT Extensions OPTIONAL
1236*62c56f98SSadaf Ebrahimi * -- If present, version shall be v3
1237*62c56f98SSadaf Ebrahimi */
1238*62c56f98SSadaf Ebrahimi if (crt->version == 2 || crt->version == 3) {
1239*62c56f98SSadaf Ebrahimi ret = x509_get_uid(&p, end, &crt->issuer_id, 1);
1240*62c56f98SSadaf Ebrahimi if (ret != 0) {
1241*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1242*62c56f98SSadaf Ebrahimi return ret;
1243*62c56f98SSadaf Ebrahimi }
1244*62c56f98SSadaf Ebrahimi }
1245*62c56f98SSadaf Ebrahimi
1246*62c56f98SSadaf Ebrahimi if (crt->version == 2 || crt->version == 3) {
1247*62c56f98SSadaf Ebrahimi ret = x509_get_uid(&p, end, &crt->subject_id, 2);
1248*62c56f98SSadaf Ebrahimi if (ret != 0) {
1249*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1250*62c56f98SSadaf Ebrahimi return ret;
1251*62c56f98SSadaf Ebrahimi }
1252*62c56f98SSadaf Ebrahimi }
1253*62c56f98SSadaf Ebrahimi
1254*62c56f98SSadaf Ebrahimi if (crt->version == 3) {
1255*62c56f98SSadaf Ebrahimi ret = x509_get_crt_ext(&p, end, crt, cb, p_ctx);
1256*62c56f98SSadaf Ebrahimi if (ret != 0) {
1257*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1258*62c56f98SSadaf Ebrahimi return ret;
1259*62c56f98SSadaf Ebrahimi }
1260*62c56f98SSadaf Ebrahimi }
1261*62c56f98SSadaf Ebrahimi
1262*62c56f98SSadaf Ebrahimi if (p != end) {
1263*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1264*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
1265*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1266*62c56f98SSadaf Ebrahimi }
1267*62c56f98SSadaf Ebrahimi
1268*62c56f98SSadaf Ebrahimi end = crt_end;
1269*62c56f98SSadaf Ebrahimi
1270*62c56f98SSadaf Ebrahimi /*
1271*62c56f98SSadaf Ebrahimi * }
1272*62c56f98SSadaf Ebrahimi * -- end of TBSCertificate
1273*62c56f98SSadaf Ebrahimi *
1274*62c56f98SSadaf Ebrahimi * signatureAlgorithm AlgorithmIdentifier,
1275*62c56f98SSadaf Ebrahimi * signatureValue BIT STRING
1276*62c56f98SSadaf Ebrahimi */
1277*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) {
1278*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1279*62c56f98SSadaf Ebrahimi return ret;
1280*62c56f98SSadaf Ebrahimi }
1281*62c56f98SSadaf Ebrahimi
1282*62c56f98SSadaf Ebrahimi if (crt->sig_oid.len != sig_oid2.len ||
1283*62c56f98SSadaf Ebrahimi memcmp(crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len) != 0 ||
1284*62c56f98SSadaf Ebrahimi sig_params1.tag != sig_params2.tag ||
1285*62c56f98SSadaf Ebrahimi sig_params1.len != sig_params2.len ||
1286*62c56f98SSadaf Ebrahimi (sig_params1.len != 0 &&
1287*62c56f98SSadaf Ebrahimi memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) {
1288*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1289*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_SIG_MISMATCH;
1290*62c56f98SSadaf Ebrahimi }
1291*62c56f98SSadaf Ebrahimi
1292*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_get_sig(&p, end, &crt->sig)) != 0) {
1293*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1294*62c56f98SSadaf Ebrahimi return ret;
1295*62c56f98SSadaf Ebrahimi }
1296*62c56f98SSadaf Ebrahimi
1297*62c56f98SSadaf Ebrahimi if (p != end) {
1298*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(crt);
1299*62c56f98SSadaf Ebrahimi return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
1300*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1301*62c56f98SSadaf Ebrahimi }
1302*62c56f98SSadaf Ebrahimi
1303*62c56f98SSadaf Ebrahimi return 0;
1304*62c56f98SSadaf Ebrahimi }
1305*62c56f98SSadaf Ebrahimi
1306*62c56f98SSadaf Ebrahimi /*
1307*62c56f98SSadaf Ebrahimi * Parse one X.509 certificate in DER format from a buffer and add them to a
1308*62c56f98SSadaf Ebrahimi * chained list
1309*62c56f98SSadaf Ebrahimi */
mbedtls_x509_crt_parse_der_internal(mbedtls_x509_crt * chain,const unsigned char * buf,size_t buflen,int make_copy,mbedtls_x509_crt_ext_cb_t cb,void * p_ctx)1310*62c56f98SSadaf Ebrahimi static int mbedtls_x509_crt_parse_der_internal(mbedtls_x509_crt *chain,
1311*62c56f98SSadaf Ebrahimi const unsigned char *buf,
1312*62c56f98SSadaf Ebrahimi size_t buflen,
1313*62c56f98SSadaf Ebrahimi int make_copy,
1314*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_ext_cb_t cb,
1315*62c56f98SSadaf Ebrahimi void *p_ctx)
1316*62c56f98SSadaf Ebrahimi {
1317*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1318*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *crt = chain, *prev = NULL;
1319*62c56f98SSadaf Ebrahimi
1320*62c56f98SSadaf Ebrahimi /*
1321*62c56f98SSadaf Ebrahimi * Check for valid input
1322*62c56f98SSadaf Ebrahimi */
1323*62c56f98SSadaf Ebrahimi if (crt == NULL || buf == NULL) {
1324*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1325*62c56f98SSadaf Ebrahimi }
1326*62c56f98SSadaf Ebrahimi
1327*62c56f98SSadaf Ebrahimi while (crt->version != 0 && crt->next != NULL) {
1328*62c56f98SSadaf Ebrahimi prev = crt;
1329*62c56f98SSadaf Ebrahimi crt = crt->next;
1330*62c56f98SSadaf Ebrahimi }
1331*62c56f98SSadaf Ebrahimi
1332*62c56f98SSadaf Ebrahimi /*
1333*62c56f98SSadaf Ebrahimi * Add new certificate on the end of the chain if needed.
1334*62c56f98SSadaf Ebrahimi */
1335*62c56f98SSadaf Ebrahimi if (crt->version != 0 && crt->next == NULL) {
1336*62c56f98SSadaf Ebrahimi crt->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
1337*62c56f98SSadaf Ebrahimi
1338*62c56f98SSadaf Ebrahimi if (crt->next == NULL) {
1339*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_ALLOC_FAILED;
1340*62c56f98SSadaf Ebrahimi }
1341*62c56f98SSadaf Ebrahimi
1342*62c56f98SSadaf Ebrahimi prev = crt;
1343*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_init(crt->next);
1344*62c56f98SSadaf Ebrahimi crt = crt->next;
1345*62c56f98SSadaf Ebrahimi }
1346*62c56f98SSadaf Ebrahimi
1347*62c56f98SSadaf Ebrahimi ret = x509_crt_parse_der_core(crt, buf, buflen, make_copy, cb, p_ctx);
1348*62c56f98SSadaf Ebrahimi if (ret != 0) {
1349*62c56f98SSadaf Ebrahimi if (prev) {
1350*62c56f98SSadaf Ebrahimi prev->next = NULL;
1351*62c56f98SSadaf Ebrahimi }
1352*62c56f98SSadaf Ebrahimi
1353*62c56f98SSadaf Ebrahimi if (crt != chain) {
1354*62c56f98SSadaf Ebrahimi mbedtls_free(crt);
1355*62c56f98SSadaf Ebrahimi }
1356*62c56f98SSadaf Ebrahimi
1357*62c56f98SSadaf Ebrahimi return ret;
1358*62c56f98SSadaf Ebrahimi }
1359*62c56f98SSadaf Ebrahimi
1360*62c56f98SSadaf Ebrahimi return 0;
1361*62c56f98SSadaf Ebrahimi }
1362*62c56f98SSadaf Ebrahimi
mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt * chain,const unsigned char * buf,size_t buflen)1363*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain,
1364*62c56f98SSadaf Ebrahimi const unsigned char *buf,
1365*62c56f98SSadaf Ebrahimi size_t buflen)
1366*62c56f98SSadaf Ebrahimi {
1367*62c56f98SSadaf Ebrahimi return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 0, NULL, NULL);
1368*62c56f98SSadaf Ebrahimi }
1369*62c56f98SSadaf Ebrahimi
mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt * chain,const unsigned char * buf,size_t buflen,int make_copy,mbedtls_x509_crt_ext_cb_t cb,void * p_ctx)1370*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain,
1371*62c56f98SSadaf Ebrahimi const unsigned char *buf,
1372*62c56f98SSadaf Ebrahimi size_t buflen,
1373*62c56f98SSadaf Ebrahimi int make_copy,
1374*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_ext_cb_t cb,
1375*62c56f98SSadaf Ebrahimi void *p_ctx)
1376*62c56f98SSadaf Ebrahimi {
1377*62c56f98SSadaf Ebrahimi return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, make_copy, cb, p_ctx);
1378*62c56f98SSadaf Ebrahimi }
1379*62c56f98SSadaf Ebrahimi
mbedtls_x509_crt_parse_der(mbedtls_x509_crt * chain,const unsigned char * buf,size_t buflen)1380*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain,
1381*62c56f98SSadaf Ebrahimi const unsigned char *buf,
1382*62c56f98SSadaf Ebrahimi size_t buflen)
1383*62c56f98SSadaf Ebrahimi {
1384*62c56f98SSadaf Ebrahimi return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 1, NULL, NULL);
1385*62c56f98SSadaf Ebrahimi }
1386*62c56f98SSadaf Ebrahimi
1387*62c56f98SSadaf Ebrahimi /*
1388*62c56f98SSadaf Ebrahimi * Parse one or more PEM certificates from a buffer and add them to the chained
1389*62c56f98SSadaf Ebrahimi * list
1390*62c56f98SSadaf Ebrahimi */
mbedtls_x509_crt_parse(mbedtls_x509_crt * chain,const unsigned char * buf,size_t buflen)1391*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain,
1392*62c56f98SSadaf Ebrahimi const unsigned char *buf,
1393*62c56f98SSadaf Ebrahimi size_t buflen)
1394*62c56f98SSadaf Ebrahimi {
1395*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PEM_PARSE_C)
1396*62c56f98SSadaf Ebrahimi int success = 0, first_error = 0, total_failed = 0;
1397*62c56f98SSadaf Ebrahimi int buf_format = MBEDTLS_X509_FORMAT_DER;
1398*62c56f98SSadaf Ebrahimi #endif
1399*62c56f98SSadaf Ebrahimi
1400*62c56f98SSadaf Ebrahimi /*
1401*62c56f98SSadaf Ebrahimi * Check for valid input
1402*62c56f98SSadaf Ebrahimi */
1403*62c56f98SSadaf Ebrahimi if (chain == NULL || buf == NULL) {
1404*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1405*62c56f98SSadaf Ebrahimi }
1406*62c56f98SSadaf Ebrahimi
1407*62c56f98SSadaf Ebrahimi /*
1408*62c56f98SSadaf Ebrahimi * Determine buffer content. Buffer contains either one DER certificate or
1409*62c56f98SSadaf Ebrahimi * one or more PEM certificates.
1410*62c56f98SSadaf Ebrahimi */
1411*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PEM_PARSE_C)
1412*62c56f98SSadaf Ebrahimi if (buflen != 0 && buf[buflen - 1] == '\0' &&
1413*62c56f98SSadaf Ebrahimi strstr((const char *) buf, "-----BEGIN CERTIFICATE-----") != NULL) {
1414*62c56f98SSadaf Ebrahimi buf_format = MBEDTLS_X509_FORMAT_PEM;
1415*62c56f98SSadaf Ebrahimi }
1416*62c56f98SSadaf Ebrahimi
1417*62c56f98SSadaf Ebrahimi if (buf_format == MBEDTLS_X509_FORMAT_DER) {
1418*62c56f98SSadaf Ebrahimi return mbedtls_x509_crt_parse_der(chain, buf, buflen);
1419*62c56f98SSadaf Ebrahimi }
1420*62c56f98SSadaf Ebrahimi #else
1421*62c56f98SSadaf Ebrahimi return mbedtls_x509_crt_parse_der(chain, buf, buflen);
1422*62c56f98SSadaf Ebrahimi #endif
1423*62c56f98SSadaf Ebrahimi
1424*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PEM_PARSE_C)
1425*62c56f98SSadaf Ebrahimi if (buf_format == MBEDTLS_X509_FORMAT_PEM) {
1426*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1427*62c56f98SSadaf Ebrahimi mbedtls_pem_context pem;
1428*62c56f98SSadaf Ebrahimi
1429*62c56f98SSadaf Ebrahimi /* 1 rather than 0 since the terminating NULL byte is counted in */
1430*62c56f98SSadaf Ebrahimi while (buflen > 1) {
1431*62c56f98SSadaf Ebrahimi size_t use_len;
1432*62c56f98SSadaf Ebrahimi mbedtls_pem_init(&pem);
1433*62c56f98SSadaf Ebrahimi
1434*62c56f98SSadaf Ebrahimi /* If we get there, we know the string is null-terminated */
1435*62c56f98SSadaf Ebrahimi ret = mbedtls_pem_read_buffer(&pem,
1436*62c56f98SSadaf Ebrahimi "-----BEGIN CERTIFICATE-----",
1437*62c56f98SSadaf Ebrahimi "-----END CERTIFICATE-----",
1438*62c56f98SSadaf Ebrahimi buf, NULL, 0, &use_len);
1439*62c56f98SSadaf Ebrahimi
1440*62c56f98SSadaf Ebrahimi if (ret == 0) {
1441*62c56f98SSadaf Ebrahimi /*
1442*62c56f98SSadaf Ebrahimi * Was PEM encoded
1443*62c56f98SSadaf Ebrahimi */
1444*62c56f98SSadaf Ebrahimi buflen -= use_len;
1445*62c56f98SSadaf Ebrahimi buf += use_len;
1446*62c56f98SSadaf Ebrahimi } else if (ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA) {
1447*62c56f98SSadaf Ebrahimi return ret;
1448*62c56f98SSadaf Ebrahimi } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
1449*62c56f98SSadaf Ebrahimi mbedtls_pem_free(&pem);
1450*62c56f98SSadaf Ebrahimi
1451*62c56f98SSadaf Ebrahimi /*
1452*62c56f98SSadaf Ebrahimi * PEM header and footer were found
1453*62c56f98SSadaf Ebrahimi */
1454*62c56f98SSadaf Ebrahimi buflen -= use_len;
1455*62c56f98SSadaf Ebrahimi buf += use_len;
1456*62c56f98SSadaf Ebrahimi
1457*62c56f98SSadaf Ebrahimi if (first_error == 0) {
1458*62c56f98SSadaf Ebrahimi first_error = ret;
1459*62c56f98SSadaf Ebrahimi }
1460*62c56f98SSadaf Ebrahimi
1461*62c56f98SSadaf Ebrahimi total_failed++;
1462*62c56f98SSadaf Ebrahimi continue;
1463*62c56f98SSadaf Ebrahimi } else {
1464*62c56f98SSadaf Ebrahimi break;
1465*62c56f98SSadaf Ebrahimi }
1466*62c56f98SSadaf Ebrahimi
1467*62c56f98SSadaf Ebrahimi ret = mbedtls_x509_crt_parse_der(chain, pem.buf, pem.buflen);
1468*62c56f98SSadaf Ebrahimi
1469*62c56f98SSadaf Ebrahimi mbedtls_pem_free(&pem);
1470*62c56f98SSadaf Ebrahimi
1471*62c56f98SSadaf Ebrahimi if (ret != 0) {
1472*62c56f98SSadaf Ebrahimi /*
1473*62c56f98SSadaf Ebrahimi * Quit parsing on a memory error
1474*62c56f98SSadaf Ebrahimi */
1475*62c56f98SSadaf Ebrahimi if (ret == MBEDTLS_ERR_X509_ALLOC_FAILED) {
1476*62c56f98SSadaf Ebrahimi return ret;
1477*62c56f98SSadaf Ebrahimi }
1478*62c56f98SSadaf Ebrahimi
1479*62c56f98SSadaf Ebrahimi if (first_error == 0) {
1480*62c56f98SSadaf Ebrahimi first_error = ret;
1481*62c56f98SSadaf Ebrahimi }
1482*62c56f98SSadaf Ebrahimi
1483*62c56f98SSadaf Ebrahimi total_failed++;
1484*62c56f98SSadaf Ebrahimi continue;
1485*62c56f98SSadaf Ebrahimi }
1486*62c56f98SSadaf Ebrahimi
1487*62c56f98SSadaf Ebrahimi success = 1;
1488*62c56f98SSadaf Ebrahimi }
1489*62c56f98SSadaf Ebrahimi }
1490*62c56f98SSadaf Ebrahimi
1491*62c56f98SSadaf Ebrahimi if (success) {
1492*62c56f98SSadaf Ebrahimi return total_failed;
1493*62c56f98SSadaf Ebrahimi } else if (first_error) {
1494*62c56f98SSadaf Ebrahimi return first_error;
1495*62c56f98SSadaf Ebrahimi } else {
1496*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
1497*62c56f98SSadaf Ebrahimi }
1498*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PEM_PARSE_C */
1499*62c56f98SSadaf Ebrahimi }
1500*62c56f98SSadaf Ebrahimi
1501*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_FS_IO)
1502*62c56f98SSadaf Ebrahimi /*
1503*62c56f98SSadaf Ebrahimi * Load one or more certificates and add them to the chained list
1504*62c56f98SSadaf Ebrahimi */
mbedtls_x509_crt_parse_file(mbedtls_x509_crt * chain,const char * path)1505*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path)
1506*62c56f98SSadaf Ebrahimi {
1507*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1508*62c56f98SSadaf Ebrahimi size_t n;
1509*62c56f98SSadaf Ebrahimi unsigned char *buf;
1510*62c56f98SSadaf Ebrahimi
1511*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
1512*62c56f98SSadaf Ebrahimi return ret;
1513*62c56f98SSadaf Ebrahimi }
1514*62c56f98SSadaf Ebrahimi
1515*62c56f98SSadaf Ebrahimi ret = mbedtls_x509_crt_parse(chain, buf, n);
1516*62c56f98SSadaf Ebrahimi
1517*62c56f98SSadaf Ebrahimi mbedtls_zeroize_and_free(buf, n);
1518*62c56f98SSadaf Ebrahimi
1519*62c56f98SSadaf Ebrahimi return ret;
1520*62c56f98SSadaf Ebrahimi }
1521*62c56f98SSadaf Ebrahimi
mbedtls_x509_crt_parse_path(mbedtls_x509_crt * chain,const char * path)1522*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path)
1523*62c56f98SSadaf Ebrahimi {
1524*62c56f98SSadaf Ebrahimi int ret = 0;
1525*62c56f98SSadaf Ebrahimi #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
1526*62c56f98SSadaf Ebrahimi int w_ret;
1527*62c56f98SSadaf Ebrahimi WCHAR szDir[MAX_PATH];
1528*62c56f98SSadaf Ebrahimi char filename[MAX_PATH];
1529*62c56f98SSadaf Ebrahimi char *p;
1530*62c56f98SSadaf Ebrahimi size_t len = strlen(path);
1531*62c56f98SSadaf Ebrahimi
1532*62c56f98SSadaf Ebrahimi WIN32_FIND_DATAW file_data;
1533*62c56f98SSadaf Ebrahimi HANDLE hFind;
1534*62c56f98SSadaf Ebrahimi
1535*62c56f98SSadaf Ebrahimi if (len > MAX_PATH - 3) {
1536*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1537*62c56f98SSadaf Ebrahimi }
1538*62c56f98SSadaf Ebrahimi
1539*62c56f98SSadaf Ebrahimi memset(szDir, 0, sizeof(szDir));
1540*62c56f98SSadaf Ebrahimi memset(filename, 0, MAX_PATH);
1541*62c56f98SSadaf Ebrahimi memcpy(filename, path, len);
1542*62c56f98SSadaf Ebrahimi filename[len++] = '\\';
1543*62c56f98SSadaf Ebrahimi p = filename + len;
1544*62c56f98SSadaf Ebrahimi filename[len++] = '*';
1545*62c56f98SSadaf Ebrahimi
1546*62c56f98SSadaf Ebrahimi /*
1547*62c56f98SSadaf Ebrahimi * Note this function uses the code page CP_ACP which is the system default
1548*62c56f98SSadaf Ebrahimi * ANSI codepage. The input string is always described in BYTES and the
1549*62c56f98SSadaf Ebrahimi * output length is described in WCHARs.
1550*62c56f98SSadaf Ebrahimi */
1551*62c56f98SSadaf Ebrahimi w_ret = MultiByteToWideChar(CP_ACP, 0, filename, (int) len, szDir,
1552*62c56f98SSadaf Ebrahimi MAX_PATH - 3);
1553*62c56f98SSadaf Ebrahimi if (w_ret == 0) {
1554*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1555*62c56f98SSadaf Ebrahimi }
1556*62c56f98SSadaf Ebrahimi
1557*62c56f98SSadaf Ebrahimi hFind = FindFirstFileW(szDir, &file_data);
1558*62c56f98SSadaf Ebrahimi if (hFind == INVALID_HANDLE_VALUE) {
1559*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_FILE_IO_ERROR;
1560*62c56f98SSadaf Ebrahimi }
1561*62c56f98SSadaf Ebrahimi
1562*62c56f98SSadaf Ebrahimi len = MAX_PATH - len;
1563*62c56f98SSadaf Ebrahimi do {
1564*62c56f98SSadaf Ebrahimi memset(p, 0, len);
1565*62c56f98SSadaf Ebrahimi
1566*62c56f98SSadaf Ebrahimi if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1567*62c56f98SSadaf Ebrahimi continue;
1568*62c56f98SSadaf Ebrahimi }
1569*62c56f98SSadaf Ebrahimi w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName,
1570*62c56f98SSadaf Ebrahimi -1, p, (int) len, NULL, NULL);
1571*62c56f98SSadaf Ebrahimi if (w_ret == 0) {
1572*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
1573*62c56f98SSadaf Ebrahimi goto cleanup;
1574*62c56f98SSadaf Ebrahimi }
1575*62c56f98SSadaf Ebrahimi
1576*62c56f98SSadaf Ebrahimi w_ret = mbedtls_x509_crt_parse_file(chain, filename);
1577*62c56f98SSadaf Ebrahimi if (w_ret < 0) {
1578*62c56f98SSadaf Ebrahimi ret++;
1579*62c56f98SSadaf Ebrahimi } else {
1580*62c56f98SSadaf Ebrahimi ret += w_ret;
1581*62c56f98SSadaf Ebrahimi }
1582*62c56f98SSadaf Ebrahimi } while (FindNextFileW(hFind, &file_data) != 0);
1583*62c56f98SSadaf Ebrahimi
1584*62c56f98SSadaf Ebrahimi if (GetLastError() != ERROR_NO_MORE_FILES) {
1585*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
1586*62c56f98SSadaf Ebrahimi }
1587*62c56f98SSadaf Ebrahimi
1588*62c56f98SSadaf Ebrahimi cleanup:
1589*62c56f98SSadaf Ebrahimi FindClose(hFind);
1590*62c56f98SSadaf Ebrahimi #else /* _WIN32 */
1591*62c56f98SSadaf Ebrahimi int t_ret;
1592*62c56f98SSadaf Ebrahimi int snp_ret;
1593*62c56f98SSadaf Ebrahimi struct stat sb;
1594*62c56f98SSadaf Ebrahimi struct dirent *entry;
1595*62c56f98SSadaf Ebrahimi char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];
1596*62c56f98SSadaf Ebrahimi DIR *dir = opendir(path);
1597*62c56f98SSadaf Ebrahimi
1598*62c56f98SSadaf Ebrahimi if (dir == NULL) {
1599*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_FILE_IO_ERROR;
1600*62c56f98SSadaf Ebrahimi }
1601*62c56f98SSadaf Ebrahimi
1602*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
1603*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_mutex_lock(&mbedtls_threading_readdir_mutex)) != 0) {
1604*62c56f98SSadaf Ebrahimi closedir(dir);
1605*62c56f98SSadaf Ebrahimi return ret;
1606*62c56f98SSadaf Ebrahimi }
1607*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_THREADING_C */
1608*62c56f98SSadaf Ebrahimi
1609*62c56f98SSadaf Ebrahimi memset(&sb, 0, sizeof(sb));
1610*62c56f98SSadaf Ebrahimi
1611*62c56f98SSadaf Ebrahimi while ((entry = readdir(dir)) != NULL) {
1612*62c56f98SSadaf Ebrahimi snp_ret = mbedtls_snprintf(entry_name, sizeof(entry_name),
1613*62c56f98SSadaf Ebrahimi "%s/%s", path, entry->d_name);
1614*62c56f98SSadaf Ebrahimi
1615*62c56f98SSadaf Ebrahimi if (snp_ret < 0 || (size_t) snp_ret >= sizeof(entry_name)) {
1616*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1617*62c56f98SSadaf Ebrahimi goto cleanup;
1618*62c56f98SSadaf Ebrahimi } else if (stat(entry_name, &sb) == -1) {
1619*62c56f98SSadaf Ebrahimi if (errno == ENOENT) {
1620*62c56f98SSadaf Ebrahimi /* Broken symbolic link - ignore this entry.
1621*62c56f98SSadaf Ebrahimi stat(2) will return this error for either (a) a dangling
1622*62c56f98SSadaf Ebrahimi symlink or (b) a missing file.
1623*62c56f98SSadaf Ebrahimi Given that we have just obtained the filename from readdir,
1624*62c56f98SSadaf Ebrahimi assume that it does exist and therefore treat this as a
1625*62c56f98SSadaf Ebrahimi dangling symlink. */
1626*62c56f98SSadaf Ebrahimi continue;
1627*62c56f98SSadaf Ebrahimi } else {
1628*62c56f98SSadaf Ebrahimi /* Some other file error; report the error. */
1629*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
1630*62c56f98SSadaf Ebrahimi goto cleanup;
1631*62c56f98SSadaf Ebrahimi }
1632*62c56f98SSadaf Ebrahimi }
1633*62c56f98SSadaf Ebrahimi
1634*62c56f98SSadaf Ebrahimi if (!S_ISREG(sb.st_mode)) {
1635*62c56f98SSadaf Ebrahimi continue;
1636*62c56f98SSadaf Ebrahimi }
1637*62c56f98SSadaf Ebrahimi
1638*62c56f98SSadaf Ebrahimi // Ignore parse errors
1639*62c56f98SSadaf Ebrahimi //
1640*62c56f98SSadaf Ebrahimi t_ret = mbedtls_x509_crt_parse_file(chain, entry_name);
1641*62c56f98SSadaf Ebrahimi if (t_ret < 0) {
1642*62c56f98SSadaf Ebrahimi ret++;
1643*62c56f98SSadaf Ebrahimi } else {
1644*62c56f98SSadaf Ebrahimi ret += t_ret;
1645*62c56f98SSadaf Ebrahimi }
1646*62c56f98SSadaf Ebrahimi }
1647*62c56f98SSadaf Ebrahimi
1648*62c56f98SSadaf Ebrahimi cleanup:
1649*62c56f98SSadaf Ebrahimi closedir(dir);
1650*62c56f98SSadaf Ebrahimi
1651*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
1652*62c56f98SSadaf Ebrahimi if (mbedtls_mutex_unlock(&mbedtls_threading_readdir_mutex) != 0) {
1653*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
1654*62c56f98SSadaf Ebrahimi }
1655*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_THREADING_C */
1656*62c56f98SSadaf Ebrahimi
1657*62c56f98SSadaf Ebrahimi #endif /* _WIN32 */
1658*62c56f98SSadaf Ebrahimi
1659*62c56f98SSadaf Ebrahimi return ret;
1660*62c56f98SSadaf Ebrahimi }
1661*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_FS_IO */
1662*62c56f98SSadaf Ebrahimi
1663*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_X509_REMOVE_INFO)
1664*62c56f98SSadaf Ebrahimi #define PRINT_ITEM(i) \
1665*62c56f98SSadaf Ebrahimi do { \
1666*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "%s" i, sep); \
1667*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF; \
1668*62c56f98SSadaf Ebrahimi sep = ", "; \
1669*62c56f98SSadaf Ebrahimi } while (0)
1670*62c56f98SSadaf Ebrahimi
1671*62c56f98SSadaf Ebrahimi #define CERT_TYPE(type, name) \
1672*62c56f98SSadaf Ebrahimi do { \
1673*62c56f98SSadaf Ebrahimi if (ns_cert_type & (type)) { \
1674*62c56f98SSadaf Ebrahimi PRINT_ITEM(name); \
1675*62c56f98SSadaf Ebrahimi } \
1676*62c56f98SSadaf Ebrahimi } while (0)
1677*62c56f98SSadaf Ebrahimi
1678*62c56f98SSadaf Ebrahimi #define KEY_USAGE(code, name) \
1679*62c56f98SSadaf Ebrahimi do { \
1680*62c56f98SSadaf Ebrahimi if (key_usage & (code)) { \
1681*62c56f98SSadaf Ebrahimi PRINT_ITEM(name); \
1682*62c56f98SSadaf Ebrahimi } \
1683*62c56f98SSadaf Ebrahimi } while (0)
1684*62c56f98SSadaf Ebrahimi
x509_info_ext_key_usage(char ** buf,size_t * size,const mbedtls_x509_sequence * extended_key_usage)1685*62c56f98SSadaf Ebrahimi static int x509_info_ext_key_usage(char **buf, size_t *size,
1686*62c56f98SSadaf Ebrahimi const mbedtls_x509_sequence *extended_key_usage)
1687*62c56f98SSadaf Ebrahimi {
1688*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1689*62c56f98SSadaf Ebrahimi const char *desc;
1690*62c56f98SSadaf Ebrahimi size_t n = *size;
1691*62c56f98SSadaf Ebrahimi char *p = *buf;
1692*62c56f98SSadaf Ebrahimi const mbedtls_x509_sequence *cur = extended_key_usage;
1693*62c56f98SSadaf Ebrahimi const char *sep = "";
1694*62c56f98SSadaf Ebrahimi
1695*62c56f98SSadaf Ebrahimi while (cur != NULL) {
1696*62c56f98SSadaf Ebrahimi if (mbedtls_oid_get_extended_key_usage(&cur->buf, &desc) != 0) {
1697*62c56f98SSadaf Ebrahimi desc = "???";
1698*62c56f98SSadaf Ebrahimi }
1699*62c56f98SSadaf Ebrahimi
1700*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "%s%s", sep, desc);
1701*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1702*62c56f98SSadaf Ebrahimi
1703*62c56f98SSadaf Ebrahimi sep = ", ";
1704*62c56f98SSadaf Ebrahimi
1705*62c56f98SSadaf Ebrahimi cur = cur->next;
1706*62c56f98SSadaf Ebrahimi }
1707*62c56f98SSadaf Ebrahimi
1708*62c56f98SSadaf Ebrahimi *size = n;
1709*62c56f98SSadaf Ebrahimi *buf = p;
1710*62c56f98SSadaf Ebrahimi
1711*62c56f98SSadaf Ebrahimi return 0;
1712*62c56f98SSadaf Ebrahimi }
1713*62c56f98SSadaf Ebrahimi
x509_info_cert_policies(char ** buf,size_t * size,const mbedtls_x509_sequence * certificate_policies)1714*62c56f98SSadaf Ebrahimi static int x509_info_cert_policies(char **buf, size_t *size,
1715*62c56f98SSadaf Ebrahimi const mbedtls_x509_sequence *certificate_policies)
1716*62c56f98SSadaf Ebrahimi {
1717*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1718*62c56f98SSadaf Ebrahimi const char *desc;
1719*62c56f98SSadaf Ebrahimi size_t n = *size;
1720*62c56f98SSadaf Ebrahimi char *p = *buf;
1721*62c56f98SSadaf Ebrahimi const mbedtls_x509_sequence *cur = certificate_policies;
1722*62c56f98SSadaf Ebrahimi const char *sep = "";
1723*62c56f98SSadaf Ebrahimi
1724*62c56f98SSadaf Ebrahimi while (cur != NULL) {
1725*62c56f98SSadaf Ebrahimi if (mbedtls_oid_get_certificate_policies(&cur->buf, &desc) != 0) {
1726*62c56f98SSadaf Ebrahimi desc = "???";
1727*62c56f98SSadaf Ebrahimi }
1728*62c56f98SSadaf Ebrahimi
1729*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "%s%s", sep, desc);
1730*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1731*62c56f98SSadaf Ebrahimi
1732*62c56f98SSadaf Ebrahimi sep = ", ";
1733*62c56f98SSadaf Ebrahimi
1734*62c56f98SSadaf Ebrahimi cur = cur->next;
1735*62c56f98SSadaf Ebrahimi }
1736*62c56f98SSadaf Ebrahimi
1737*62c56f98SSadaf Ebrahimi *size = n;
1738*62c56f98SSadaf Ebrahimi *buf = p;
1739*62c56f98SSadaf Ebrahimi
1740*62c56f98SSadaf Ebrahimi return 0;
1741*62c56f98SSadaf Ebrahimi }
1742*62c56f98SSadaf Ebrahimi
1743*62c56f98SSadaf Ebrahimi /*
1744*62c56f98SSadaf Ebrahimi * Return an informational string about the certificate.
1745*62c56f98SSadaf Ebrahimi */
1746*62c56f98SSadaf Ebrahimi #define BEFORE_COLON 18
1747*62c56f98SSadaf Ebrahimi #define BC "18"
mbedtls_x509_crt_info(char * buf,size_t size,const char * prefix,const mbedtls_x509_crt * crt)1748*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix,
1749*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt *crt)
1750*62c56f98SSadaf Ebrahimi {
1751*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1752*62c56f98SSadaf Ebrahimi size_t n;
1753*62c56f98SSadaf Ebrahimi char *p;
1754*62c56f98SSadaf Ebrahimi char key_size_str[BEFORE_COLON];
1755*62c56f98SSadaf Ebrahimi
1756*62c56f98SSadaf Ebrahimi p = buf;
1757*62c56f98SSadaf Ebrahimi n = size;
1758*62c56f98SSadaf Ebrahimi
1759*62c56f98SSadaf Ebrahimi if (NULL == crt) {
1760*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\nCertificate is uninitialised!\n");
1761*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1762*62c56f98SSadaf Ebrahimi
1763*62c56f98SSadaf Ebrahimi return (int) (size - n);
1764*62c56f98SSadaf Ebrahimi }
1765*62c56f98SSadaf Ebrahimi
1766*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "%scert. version : %d\n",
1767*62c56f98SSadaf Ebrahimi prefix, crt->version);
1768*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1769*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "%sserial number : ",
1770*62c56f98SSadaf Ebrahimi prefix);
1771*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1772*62c56f98SSadaf Ebrahimi
1773*62c56f98SSadaf Ebrahimi ret = mbedtls_x509_serial_gets(p, n, &crt->serial);
1774*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1775*62c56f98SSadaf Ebrahimi
1776*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%sissuer name : ", prefix);
1777*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1778*62c56f98SSadaf Ebrahimi ret = mbedtls_x509_dn_gets(p, n, &crt->issuer);
1779*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1780*62c56f98SSadaf Ebrahimi
1781*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%ssubject name : ", prefix);
1782*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1783*62c56f98SSadaf Ebrahimi ret = mbedtls_x509_dn_gets(p, n, &crt->subject);
1784*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1785*62c56f98SSadaf Ebrahimi
1786*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%sissued on : " \
1787*62c56f98SSadaf Ebrahimi "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1788*62c56f98SSadaf Ebrahimi crt->valid_from.year, crt->valid_from.mon,
1789*62c56f98SSadaf Ebrahimi crt->valid_from.day, crt->valid_from.hour,
1790*62c56f98SSadaf Ebrahimi crt->valid_from.min, crt->valid_from.sec);
1791*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1792*62c56f98SSadaf Ebrahimi
1793*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%sexpires on : " \
1794*62c56f98SSadaf Ebrahimi "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1795*62c56f98SSadaf Ebrahimi crt->valid_to.year, crt->valid_to.mon,
1796*62c56f98SSadaf Ebrahimi crt->valid_to.day, crt->valid_to.hour,
1797*62c56f98SSadaf Ebrahimi crt->valid_to.min, crt->valid_to.sec);
1798*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1799*62c56f98SSadaf Ebrahimi
1800*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix);
1801*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1802*62c56f98SSadaf Ebrahimi
1803*62c56f98SSadaf Ebrahimi ret = mbedtls_x509_sig_alg_gets(p, n, &crt->sig_oid, crt->sig_pk,
1804*62c56f98SSadaf Ebrahimi crt->sig_md, crt->sig_opts);
1805*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1806*62c56f98SSadaf Ebrahimi
1807*62c56f98SSadaf Ebrahimi /* Key size */
1808*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON,
1809*62c56f98SSadaf Ebrahimi mbedtls_pk_get_name(&crt->pk))) != 0) {
1810*62c56f98SSadaf Ebrahimi return ret;
1811*62c56f98SSadaf Ebrahimi }
1812*62c56f98SSadaf Ebrahimi
1813*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
1814*62c56f98SSadaf Ebrahimi (int) mbedtls_pk_get_bitlen(&crt->pk));
1815*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1816*62c56f98SSadaf Ebrahimi
1817*62c56f98SSadaf Ebrahimi /*
1818*62c56f98SSadaf Ebrahimi * Optional extensions
1819*62c56f98SSadaf Ebrahimi */
1820*62c56f98SSadaf Ebrahimi
1821*62c56f98SSadaf Ebrahimi if (crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) {
1822*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%sbasic constraints : CA=%s", prefix,
1823*62c56f98SSadaf Ebrahimi crt->ca_istrue ? "true" : "false");
1824*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1825*62c56f98SSadaf Ebrahimi
1826*62c56f98SSadaf Ebrahimi if (crt->max_pathlen > 0) {
1827*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, ", max_pathlen=%d", crt->max_pathlen - 1);
1828*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1829*62c56f98SSadaf Ebrahimi }
1830*62c56f98SSadaf Ebrahimi }
1831*62c56f98SSadaf Ebrahimi
1832*62c56f98SSadaf Ebrahimi if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
1833*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix);
1834*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1835*62c56f98SSadaf Ebrahimi
1836*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n,
1837*62c56f98SSadaf Ebrahimi &crt->subject_alt_names,
1838*62c56f98SSadaf Ebrahimi prefix)) != 0) {
1839*62c56f98SSadaf Ebrahimi return ret;
1840*62c56f98SSadaf Ebrahimi }
1841*62c56f98SSadaf Ebrahimi }
1842*62c56f98SSadaf Ebrahimi
1843*62c56f98SSadaf Ebrahimi if (crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) {
1844*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix);
1845*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1846*62c56f98SSadaf Ebrahimi
1847*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_info_cert_type(&p, &n, crt->ns_cert_type)) != 0) {
1848*62c56f98SSadaf Ebrahimi return ret;
1849*62c56f98SSadaf Ebrahimi }
1850*62c56f98SSadaf Ebrahimi }
1851*62c56f98SSadaf Ebrahimi
1852*62c56f98SSadaf Ebrahimi if (crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) {
1853*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix);
1854*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1855*62c56f98SSadaf Ebrahimi
1856*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_x509_info_key_usage(&p, &n, crt->key_usage)) != 0) {
1857*62c56f98SSadaf Ebrahimi return ret;
1858*62c56f98SSadaf Ebrahimi }
1859*62c56f98SSadaf Ebrahimi }
1860*62c56f98SSadaf Ebrahimi
1861*62c56f98SSadaf Ebrahimi if (crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) {
1862*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%sext key usage : ", prefix);
1863*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1864*62c56f98SSadaf Ebrahimi
1865*62c56f98SSadaf Ebrahimi if ((ret = x509_info_ext_key_usage(&p, &n,
1866*62c56f98SSadaf Ebrahimi &crt->ext_key_usage)) != 0) {
1867*62c56f98SSadaf Ebrahimi return ret;
1868*62c56f98SSadaf Ebrahimi }
1869*62c56f98SSadaf Ebrahimi }
1870*62c56f98SSadaf Ebrahimi
1871*62c56f98SSadaf Ebrahimi if (crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES) {
1872*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n%scertificate policies : ", prefix);
1873*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1874*62c56f98SSadaf Ebrahimi
1875*62c56f98SSadaf Ebrahimi if ((ret = x509_info_cert_policies(&p, &n,
1876*62c56f98SSadaf Ebrahimi &crt->certificate_policies)) != 0) {
1877*62c56f98SSadaf Ebrahimi return ret;
1878*62c56f98SSadaf Ebrahimi }
1879*62c56f98SSadaf Ebrahimi }
1880*62c56f98SSadaf Ebrahimi
1881*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "\n");
1882*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1883*62c56f98SSadaf Ebrahimi
1884*62c56f98SSadaf Ebrahimi return (int) (size - n);
1885*62c56f98SSadaf Ebrahimi }
1886*62c56f98SSadaf Ebrahimi
1887*62c56f98SSadaf Ebrahimi struct x509_crt_verify_string {
1888*62c56f98SSadaf Ebrahimi int code;
1889*62c56f98SSadaf Ebrahimi const char *string;
1890*62c56f98SSadaf Ebrahimi };
1891*62c56f98SSadaf Ebrahimi
1892*62c56f98SSadaf Ebrahimi #define X509_CRT_ERROR_INFO(err, err_str, info) { err, info },
1893*62c56f98SSadaf Ebrahimi static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
1894*62c56f98SSadaf Ebrahimi MBEDTLS_X509_CRT_ERROR_INFO_LIST
1895*62c56f98SSadaf Ebrahimi { 0, NULL }
1896*62c56f98SSadaf Ebrahimi };
1897*62c56f98SSadaf Ebrahimi #undef X509_CRT_ERROR_INFO
1898*62c56f98SSadaf Ebrahimi
mbedtls_x509_crt_verify_info(char * buf,size_t size,const char * prefix,uint32_t flags)1899*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix,
1900*62c56f98SSadaf Ebrahimi uint32_t flags)
1901*62c56f98SSadaf Ebrahimi {
1902*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1903*62c56f98SSadaf Ebrahimi const struct x509_crt_verify_string *cur;
1904*62c56f98SSadaf Ebrahimi char *p = buf;
1905*62c56f98SSadaf Ebrahimi size_t n = size;
1906*62c56f98SSadaf Ebrahimi
1907*62c56f98SSadaf Ebrahimi for (cur = x509_crt_verify_strings; cur->string != NULL; cur++) {
1908*62c56f98SSadaf Ebrahimi if ((flags & cur->code) == 0) {
1909*62c56f98SSadaf Ebrahimi continue;
1910*62c56f98SSadaf Ebrahimi }
1911*62c56f98SSadaf Ebrahimi
1912*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "%s%s\n", prefix, cur->string);
1913*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1914*62c56f98SSadaf Ebrahimi flags ^= cur->code;
1915*62c56f98SSadaf Ebrahimi }
1916*62c56f98SSadaf Ebrahimi
1917*62c56f98SSadaf Ebrahimi if (flags != 0) {
1918*62c56f98SSadaf Ebrahimi ret = mbedtls_snprintf(p, n, "%sUnknown reason "
1919*62c56f98SSadaf Ebrahimi "(this should not happen)\n", prefix);
1920*62c56f98SSadaf Ebrahimi MBEDTLS_X509_SAFE_SNPRINTF;
1921*62c56f98SSadaf Ebrahimi }
1922*62c56f98SSadaf Ebrahimi
1923*62c56f98SSadaf Ebrahimi return (int) (size - n);
1924*62c56f98SSadaf Ebrahimi }
1925*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_X509_REMOVE_INFO */
1926*62c56f98SSadaf Ebrahimi
mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt * crt,unsigned int usage)1927*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt,
1928*62c56f98SSadaf Ebrahimi unsigned int usage)
1929*62c56f98SSadaf Ebrahimi {
1930*62c56f98SSadaf Ebrahimi unsigned int usage_must, usage_may;
1931*62c56f98SSadaf Ebrahimi unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
1932*62c56f98SSadaf Ebrahimi | MBEDTLS_X509_KU_DECIPHER_ONLY;
1933*62c56f98SSadaf Ebrahimi
1934*62c56f98SSadaf Ebrahimi if ((crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) == 0) {
1935*62c56f98SSadaf Ebrahimi return 0;
1936*62c56f98SSadaf Ebrahimi }
1937*62c56f98SSadaf Ebrahimi
1938*62c56f98SSadaf Ebrahimi usage_must = usage & ~may_mask;
1939*62c56f98SSadaf Ebrahimi
1940*62c56f98SSadaf Ebrahimi if (((crt->key_usage & ~may_mask) & usage_must) != usage_must) {
1941*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1942*62c56f98SSadaf Ebrahimi }
1943*62c56f98SSadaf Ebrahimi
1944*62c56f98SSadaf Ebrahimi usage_may = usage & may_mask;
1945*62c56f98SSadaf Ebrahimi
1946*62c56f98SSadaf Ebrahimi if (((crt->key_usage & may_mask) | usage_may) != usage_may) {
1947*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1948*62c56f98SSadaf Ebrahimi }
1949*62c56f98SSadaf Ebrahimi
1950*62c56f98SSadaf Ebrahimi return 0;
1951*62c56f98SSadaf Ebrahimi }
1952*62c56f98SSadaf Ebrahimi
mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt * crt,const char * usage_oid,size_t usage_len)1953*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt,
1954*62c56f98SSadaf Ebrahimi const char *usage_oid,
1955*62c56f98SSadaf Ebrahimi size_t usage_len)
1956*62c56f98SSadaf Ebrahimi {
1957*62c56f98SSadaf Ebrahimi const mbedtls_x509_sequence *cur;
1958*62c56f98SSadaf Ebrahimi
1959*62c56f98SSadaf Ebrahimi /* Extension is not mandatory, absent means no restriction */
1960*62c56f98SSadaf Ebrahimi if ((crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) == 0) {
1961*62c56f98SSadaf Ebrahimi return 0;
1962*62c56f98SSadaf Ebrahimi }
1963*62c56f98SSadaf Ebrahimi
1964*62c56f98SSadaf Ebrahimi /*
1965*62c56f98SSadaf Ebrahimi * Look for the requested usage (or wildcard ANY) in our list
1966*62c56f98SSadaf Ebrahimi */
1967*62c56f98SSadaf Ebrahimi for (cur = &crt->ext_key_usage; cur != NULL; cur = cur->next) {
1968*62c56f98SSadaf Ebrahimi const mbedtls_x509_buf *cur_oid = &cur->buf;
1969*62c56f98SSadaf Ebrahimi
1970*62c56f98SSadaf Ebrahimi if (cur_oid->len == usage_len &&
1971*62c56f98SSadaf Ebrahimi memcmp(cur_oid->p, usage_oid, usage_len) == 0) {
1972*62c56f98SSadaf Ebrahimi return 0;
1973*62c56f98SSadaf Ebrahimi }
1974*62c56f98SSadaf Ebrahimi
1975*62c56f98SSadaf Ebrahimi if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid) == 0) {
1976*62c56f98SSadaf Ebrahimi return 0;
1977*62c56f98SSadaf Ebrahimi }
1978*62c56f98SSadaf Ebrahimi }
1979*62c56f98SSadaf Ebrahimi
1980*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1981*62c56f98SSadaf Ebrahimi }
1982*62c56f98SSadaf Ebrahimi
1983*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_X509_CRL_PARSE_C)
1984*62c56f98SSadaf Ebrahimi /*
1985*62c56f98SSadaf Ebrahimi * Return 1 if the certificate is revoked, or 0 otherwise.
1986*62c56f98SSadaf Ebrahimi */
mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt * crt,const mbedtls_x509_crl * crl)1987*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl)
1988*62c56f98SSadaf Ebrahimi {
1989*62c56f98SSadaf Ebrahimi const mbedtls_x509_crl_entry *cur = &crl->entry;
1990*62c56f98SSadaf Ebrahimi
1991*62c56f98SSadaf Ebrahimi while (cur != NULL && cur->serial.len != 0) {
1992*62c56f98SSadaf Ebrahimi if (crt->serial.len == cur->serial.len &&
1993*62c56f98SSadaf Ebrahimi memcmp(crt->serial.p, cur->serial.p, crt->serial.len) == 0) {
1994*62c56f98SSadaf Ebrahimi return 1;
1995*62c56f98SSadaf Ebrahimi }
1996*62c56f98SSadaf Ebrahimi
1997*62c56f98SSadaf Ebrahimi cur = cur->next;
1998*62c56f98SSadaf Ebrahimi }
1999*62c56f98SSadaf Ebrahimi
2000*62c56f98SSadaf Ebrahimi return 0;
2001*62c56f98SSadaf Ebrahimi }
2002*62c56f98SSadaf Ebrahimi
2003*62c56f98SSadaf Ebrahimi /*
2004*62c56f98SSadaf Ebrahimi * Check that the given certificate is not revoked according to the CRL.
2005*62c56f98SSadaf Ebrahimi * Skip validation if no CRL for the given CA is present.
2006*62c56f98SSadaf Ebrahimi */
x509_crt_verifycrl(mbedtls_x509_crt * crt,mbedtls_x509_crt * ca,mbedtls_x509_crl * crl_list,const mbedtls_x509_crt_profile * profile,const mbedtls_x509_time * now)2007*62c56f98SSadaf Ebrahimi static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
2008*62c56f98SSadaf Ebrahimi mbedtls_x509_crl *crl_list,
2009*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_profile *profile,
2010*62c56f98SSadaf Ebrahimi const mbedtls_x509_time *now)
2011*62c56f98SSadaf Ebrahimi {
2012*62c56f98SSadaf Ebrahimi int flags = 0;
2013*62c56f98SSadaf Ebrahimi unsigned char hash[MBEDTLS_MD_MAX_SIZE];
2014*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
2015*62c56f98SSadaf Ebrahimi psa_algorithm_t psa_algorithm;
2016*62c56f98SSadaf Ebrahimi #else
2017*62c56f98SSadaf Ebrahimi const mbedtls_md_info_t *md_info;
2018*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
2019*62c56f98SSadaf Ebrahimi size_t hash_length;
2020*62c56f98SSadaf Ebrahimi
2021*62c56f98SSadaf Ebrahimi if (ca == NULL) {
2022*62c56f98SSadaf Ebrahimi return flags;
2023*62c56f98SSadaf Ebrahimi }
2024*62c56f98SSadaf Ebrahimi
2025*62c56f98SSadaf Ebrahimi while (crl_list != NULL) {
2026*62c56f98SSadaf Ebrahimi if (crl_list->version == 0 ||
2027*62c56f98SSadaf Ebrahimi x509_name_cmp(&crl_list->issuer, &ca->subject) != 0) {
2028*62c56f98SSadaf Ebrahimi crl_list = crl_list->next;
2029*62c56f98SSadaf Ebrahimi continue;
2030*62c56f98SSadaf Ebrahimi }
2031*62c56f98SSadaf Ebrahimi
2032*62c56f98SSadaf Ebrahimi /*
2033*62c56f98SSadaf Ebrahimi * Check if the CA is configured to sign CRLs
2034*62c56f98SSadaf Ebrahimi */
2035*62c56f98SSadaf Ebrahimi if (mbedtls_x509_crt_check_key_usage(ca,
2036*62c56f98SSadaf Ebrahimi MBEDTLS_X509_KU_CRL_SIGN) != 0) {
2037*62c56f98SSadaf Ebrahimi flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
2038*62c56f98SSadaf Ebrahimi break;
2039*62c56f98SSadaf Ebrahimi }
2040*62c56f98SSadaf Ebrahimi
2041*62c56f98SSadaf Ebrahimi /*
2042*62c56f98SSadaf Ebrahimi * Check if CRL is correctly signed by the trusted CA
2043*62c56f98SSadaf Ebrahimi */
2044*62c56f98SSadaf Ebrahimi if (x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) {
2045*62c56f98SSadaf Ebrahimi flags |= MBEDTLS_X509_BADCRL_BAD_MD;
2046*62c56f98SSadaf Ebrahimi }
2047*62c56f98SSadaf Ebrahimi
2048*62c56f98SSadaf Ebrahimi if (x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) {
2049*62c56f98SSadaf Ebrahimi flags |= MBEDTLS_X509_BADCRL_BAD_PK;
2050*62c56f98SSadaf Ebrahimi }
2051*62c56f98SSadaf Ebrahimi
2052*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_USE_PSA_CRYPTO)
2053*62c56f98SSadaf Ebrahimi psa_algorithm = mbedtls_md_psa_alg_from_type(crl_list->sig_md);
2054*62c56f98SSadaf Ebrahimi if (psa_hash_compute(psa_algorithm,
2055*62c56f98SSadaf Ebrahimi crl_list->tbs.p,
2056*62c56f98SSadaf Ebrahimi crl_list->tbs.len,
2057*62c56f98SSadaf Ebrahimi hash,
2058*62c56f98SSadaf Ebrahimi sizeof(hash),
2059*62c56f98SSadaf Ebrahimi &hash_length) != PSA_SUCCESS) {
2060*62c56f98SSadaf Ebrahimi /* Note: this can't happen except after an internal error */
2061*62c56f98SSadaf Ebrahimi flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
2062*62c56f98SSadaf Ebrahimi break;
2063*62c56f98SSadaf Ebrahimi }
2064*62c56f98SSadaf Ebrahimi #else
2065*62c56f98SSadaf Ebrahimi md_info = mbedtls_md_info_from_type(crl_list->sig_md);
2066*62c56f98SSadaf Ebrahimi hash_length = mbedtls_md_get_size(md_info);
2067*62c56f98SSadaf Ebrahimi if (mbedtls_md(md_info,
2068*62c56f98SSadaf Ebrahimi crl_list->tbs.p,
2069*62c56f98SSadaf Ebrahimi crl_list->tbs.len,
2070*62c56f98SSadaf Ebrahimi hash) != 0) {
2071*62c56f98SSadaf Ebrahimi /* Note: this can't happen except after an internal error */
2072*62c56f98SSadaf Ebrahimi flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
2073*62c56f98SSadaf Ebrahimi break;
2074*62c56f98SSadaf Ebrahimi }
2075*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
2076*62c56f98SSadaf Ebrahimi
2077*62c56f98SSadaf Ebrahimi if (x509_profile_check_key(profile, &ca->pk) != 0) {
2078*62c56f98SSadaf Ebrahimi flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
2079*62c56f98SSadaf Ebrahimi }
2080*62c56f98SSadaf Ebrahimi
2081*62c56f98SSadaf Ebrahimi if (mbedtls_pk_verify_ext(crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
2082*62c56f98SSadaf Ebrahimi crl_list->sig_md, hash, hash_length,
2083*62c56f98SSadaf Ebrahimi crl_list->sig.p, crl_list->sig.len) != 0) {
2084*62c56f98SSadaf Ebrahimi flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
2085*62c56f98SSadaf Ebrahimi break;
2086*62c56f98SSadaf Ebrahimi }
2087*62c56f98SSadaf Ebrahimi
2088*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_HAVE_TIME_DATE)
2089*62c56f98SSadaf Ebrahimi /*
2090*62c56f98SSadaf Ebrahimi * Check for validity of CRL (Do not drop out)
2091*62c56f98SSadaf Ebrahimi */
2092*62c56f98SSadaf Ebrahimi if (mbedtls_x509_time_cmp(&crl_list->next_update, now) < 0) {
2093*62c56f98SSadaf Ebrahimi flags |= MBEDTLS_X509_BADCRL_EXPIRED;
2094*62c56f98SSadaf Ebrahimi }
2095*62c56f98SSadaf Ebrahimi
2096*62c56f98SSadaf Ebrahimi if (mbedtls_x509_time_cmp(&crl_list->this_update, now) > 0) {
2097*62c56f98SSadaf Ebrahimi flags |= MBEDTLS_X509_BADCRL_FUTURE;
2098*62c56f98SSadaf Ebrahimi }
2099*62c56f98SSadaf Ebrahimi #else
2100*62c56f98SSadaf Ebrahimi ((void) now);
2101*62c56f98SSadaf Ebrahimi #endif
2102*62c56f98SSadaf Ebrahimi
2103*62c56f98SSadaf Ebrahimi /*
2104*62c56f98SSadaf Ebrahimi * Check if certificate is revoked
2105*62c56f98SSadaf Ebrahimi */
2106*62c56f98SSadaf Ebrahimi if (mbedtls_x509_crt_is_revoked(crt, crl_list)) {
2107*62c56f98SSadaf Ebrahimi flags |= MBEDTLS_X509_BADCERT_REVOKED;
2108*62c56f98SSadaf Ebrahimi break;
2109*62c56f98SSadaf Ebrahimi }
2110*62c56f98SSadaf Ebrahimi
2111*62c56f98SSadaf Ebrahimi crl_list = crl_list->next;
2112*62c56f98SSadaf Ebrahimi }
2113*62c56f98SSadaf Ebrahimi
2114*62c56f98SSadaf Ebrahimi return flags;
2115*62c56f98SSadaf Ebrahimi }
2116*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_X509_CRL_PARSE_C */
2117*62c56f98SSadaf Ebrahimi
2118*62c56f98SSadaf Ebrahimi /*
2119*62c56f98SSadaf Ebrahimi * Check the signature of a certificate by its parent
2120*62c56f98SSadaf Ebrahimi */
x509_crt_check_signature(const mbedtls_x509_crt * child,mbedtls_x509_crt * parent,mbedtls_x509_crt_restart_ctx * rs_ctx)2121*62c56f98SSadaf Ebrahimi static int x509_crt_check_signature(const mbedtls_x509_crt *child,
2122*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *parent,
2123*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_restart_ctx *rs_ctx)
2124*62c56f98SSadaf Ebrahimi {
2125*62c56f98SSadaf Ebrahimi size_t hash_len;
2126*62c56f98SSadaf Ebrahimi unsigned char hash[MBEDTLS_MD_MAX_SIZE];
2127*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_USE_PSA_CRYPTO)
2128*62c56f98SSadaf Ebrahimi const mbedtls_md_info_t *md_info;
2129*62c56f98SSadaf Ebrahimi md_info = mbedtls_md_info_from_type(child->sig_md);
2130*62c56f98SSadaf Ebrahimi hash_len = mbedtls_md_get_size(md_info);
2131*62c56f98SSadaf Ebrahimi
2132*62c56f98SSadaf Ebrahimi /* Note: hash errors can happen only after an internal error */
2133*62c56f98SSadaf Ebrahimi if (mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash) != 0) {
2134*62c56f98SSadaf Ebrahimi return -1;
2135*62c56f98SSadaf Ebrahimi }
2136*62c56f98SSadaf Ebrahimi #else
2137*62c56f98SSadaf Ebrahimi psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(child->sig_md);
2138*62c56f98SSadaf Ebrahimi psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
2139*62c56f98SSadaf Ebrahimi
2140*62c56f98SSadaf Ebrahimi status = psa_hash_compute(hash_alg,
2141*62c56f98SSadaf Ebrahimi child->tbs.p,
2142*62c56f98SSadaf Ebrahimi child->tbs.len,
2143*62c56f98SSadaf Ebrahimi hash,
2144*62c56f98SSadaf Ebrahimi sizeof(hash),
2145*62c56f98SSadaf Ebrahimi &hash_len);
2146*62c56f98SSadaf Ebrahimi if (status != PSA_SUCCESS) {
2147*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
2148*62c56f98SSadaf Ebrahimi }
2149*62c56f98SSadaf Ebrahimi
2150*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_USE_PSA_CRYPTO */
2151*62c56f98SSadaf Ebrahimi /* Skip expensive computation on obvious mismatch */
2152*62c56f98SSadaf Ebrahimi if (!mbedtls_pk_can_do(&parent->pk, child->sig_pk)) {
2153*62c56f98SSadaf Ebrahimi return -1;
2154*62c56f98SSadaf Ebrahimi }
2155*62c56f98SSadaf Ebrahimi
2156*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2157*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA) {
2158*62c56f98SSadaf Ebrahimi return mbedtls_pk_verify_restartable(&parent->pk,
2159*62c56f98SSadaf Ebrahimi child->sig_md, hash, hash_len,
2160*62c56f98SSadaf Ebrahimi child->sig.p, child->sig.len, &rs_ctx->pk);
2161*62c56f98SSadaf Ebrahimi }
2162*62c56f98SSadaf Ebrahimi #else
2163*62c56f98SSadaf Ebrahimi (void) rs_ctx;
2164*62c56f98SSadaf Ebrahimi #endif
2165*62c56f98SSadaf Ebrahimi
2166*62c56f98SSadaf Ebrahimi return mbedtls_pk_verify_ext(child->sig_pk, child->sig_opts, &parent->pk,
2167*62c56f98SSadaf Ebrahimi child->sig_md, hash, hash_len,
2168*62c56f98SSadaf Ebrahimi child->sig.p, child->sig.len);
2169*62c56f98SSadaf Ebrahimi }
2170*62c56f98SSadaf Ebrahimi
2171*62c56f98SSadaf Ebrahimi /*
2172*62c56f98SSadaf Ebrahimi * Check if 'parent' is a suitable parent (signing CA) for 'child'.
2173*62c56f98SSadaf Ebrahimi * Return 0 if yes, -1 if not.
2174*62c56f98SSadaf Ebrahimi *
2175*62c56f98SSadaf Ebrahimi * top means parent is a locally-trusted certificate
2176*62c56f98SSadaf Ebrahimi */
x509_crt_check_parent(const mbedtls_x509_crt * child,const mbedtls_x509_crt * parent,int top)2177*62c56f98SSadaf Ebrahimi static int x509_crt_check_parent(const mbedtls_x509_crt *child,
2178*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt *parent,
2179*62c56f98SSadaf Ebrahimi int top)
2180*62c56f98SSadaf Ebrahimi {
2181*62c56f98SSadaf Ebrahimi int need_ca_bit;
2182*62c56f98SSadaf Ebrahimi
2183*62c56f98SSadaf Ebrahimi /* Parent must be the issuer */
2184*62c56f98SSadaf Ebrahimi if (x509_name_cmp(&child->issuer, &parent->subject) != 0) {
2185*62c56f98SSadaf Ebrahimi return -1;
2186*62c56f98SSadaf Ebrahimi }
2187*62c56f98SSadaf Ebrahimi
2188*62c56f98SSadaf Ebrahimi /* Parent must have the basicConstraints CA bit set as a general rule */
2189*62c56f98SSadaf Ebrahimi need_ca_bit = 1;
2190*62c56f98SSadaf Ebrahimi
2191*62c56f98SSadaf Ebrahimi /* Exception: v1/v2 certificates that are locally trusted. */
2192*62c56f98SSadaf Ebrahimi if (top && parent->version < 3) {
2193*62c56f98SSadaf Ebrahimi need_ca_bit = 0;
2194*62c56f98SSadaf Ebrahimi }
2195*62c56f98SSadaf Ebrahimi
2196*62c56f98SSadaf Ebrahimi if (need_ca_bit && !parent->ca_istrue) {
2197*62c56f98SSadaf Ebrahimi return -1;
2198*62c56f98SSadaf Ebrahimi }
2199*62c56f98SSadaf Ebrahimi
2200*62c56f98SSadaf Ebrahimi if (need_ca_bit &&
2201*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_check_key_usage(parent, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0) {
2202*62c56f98SSadaf Ebrahimi return -1;
2203*62c56f98SSadaf Ebrahimi }
2204*62c56f98SSadaf Ebrahimi
2205*62c56f98SSadaf Ebrahimi return 0;
2206*62c56f98SSadaf Ebrahimi }
2207*62c56f98SSadaf Ebrahimi
2208*62c56f98SSadaf Ebrahimi /*
2209*62c56f98SSadaf Ebrahimi * Find a suitable parent for child in candidates, or return NULL.
2210*62c56f98SSadaf Ebrahimi *
2211*62c56f98SSadaf Ebrahimi * Here suitable is defined as:
2212*62c56f98SSadaf Ebrahimi * 1. subject name matches child's issuer
2213*62c56f98SSadaf Ebrahimi * 2. if necessary, the CA bit is set and key usage allows signing certs
2214*62c56f98SSadaf Ebrahimi * 3. for trusted roots, the signature is correct
2215*62c56f98SSadaf Ebrahimi * (for intermediates, the signature is checked and the result reported)
2216*62c56f98SSadaf Ebrahimi * 4. pathlen constraints are satisfied
2217*62c56f98SSadaf Ebrahimi *
2218*62c56f98SSadaf Ebrahimi * If there's a suitable candidate which is also time-valid, return the first
2219*62c56f98SSadaf Ebrahimi * such. Otherwise, return the first suitable candidate (or NULL if there is
2220*62c56f98SSadaf Ebrahimi * none).
2221*62c56f98SSadaf Ebrahimi *
2222*62c56f98SSadaf Ebrahimi * The rationale for this rule is that someone could have a list of trusted
2223*62c56f98SSadaf Ebrahimi * roots with two versions on the same root with different validity periods.
2224*62c56f98SSadaf Ebrahimi * (At least one user reported having such a list and wanted it to just work.)
2225*62c56f98SSadaf Ebrahimi * The reason we don't just require time-validity is that generally there is
2226*62c56f98SSadaf Ebrahimi * only one version, and if it's expired we want the flags to state that
2227*62c56f98SSadaf Ebrahimi * rather than NOT_TRUSTED, as would be the case if we required it here.
2228*62c56f98SSadaf Ebrahimi *
2229*62c56f98SSadaf Ebrahimi * The rationale for rule 3 (signature for trusted roots) is that users might
2230*62c56f98SSadaf Ebrahimi * have two versions of the same CA with different keys in their list, and the
2231*62c56f98SSadaf Ebrahimi * way we select the correct one is by checking the signature (as we don't
2232*62c56f98SSadaf Ebrahimi * rely on key identifier extensions). (This is one way users might choose to
2233*62c56f98SSadaf Ebrahimi * handle key rollover, another relies on self-issued certs, see [SIRO].)
2234*62c56f98SSadaf Ebrahimi *
2235*62c56f98SSadaf Ebrahimi * Arguments:
2236*62c56f98SSadaf Ebrahimi * - [in] child: certificate for which we're looking for a parent
2237*62c56f98SSadaf Ebrahimi * - [in] candidates: chained list of potential parents
2238*62c56f98SSadaf Ebrahimi * - [out] r_parent: parent found (or NULL)
2239*62c56f98SSadaf Ebrahimi * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0
2240*62c56f98SSadaf Ebrahimi * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
2241*62c56f98SSadaf Ebrahimi * of the chain, 0 otherwise
2242*62c56f98SSadaf Ebrahimi * - [in] path_cnt: number of intermediates seen so far
2243*62c56f98SSadaf Ebrahimi * - [in] self_cnt: number of self-signed intermediates seen so far
2244*62c56f98SSadaf Ebrahimi * (will never be greater than path_cnt)
2245*62c56f98SSadaf Ebrahimi * - [in-out] rs_ctx: context for restarting operations
2246*62c56f98SSadaf Ebrahimi *
2247*62c56f98SSadaf Ebrahimi * Return value:
2248*62c56f98SSadaf Ebrahimi * - 0 on success
2249*62c56f98SSadaf Ebrahimi * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
2250*62c56f98SSadaf Ebrahimi */
x509_crt_find_parent_in(mbedtls_x509_crt * child,mbedtls_x509_crt * candidates,mbedtls_x509_crt ** r_parent,int * r_signature_is_good,int top,unsigned path_cnt,unsigned self_cnt,mbedtls_x509_crt_restart_ctx * rs_ctx,const mbedtls_x509_time * now)2251*62c56f98SSadaf Ebrahimi static int x509_crt_find_parent_in(
2252*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *child,
2253*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *candidates,
2254*62c56f98SSadaf Ebrahimi mbedtls_x509_crt **r_parent,
2255*62c56f98SSadaf Ebrahimi int *r_signature_is_good,
2256*62c56f98SSadaf Ebrahimi int top,
2257*62c56f98SSadaf Ebrahimi unsigned path_cnt,
2258*62c56f98SSadaf Ebrahimi unsigned self_cnt,
2259*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_restart_ctx *rs_ctx,
2260*62c56f98SSadaf Ebrahimi const mbedtls_x509_time *now)
2261*62c56f98SSadaf Ebrahimi {
2262*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2263*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *parent, *fallback_parent;
2264*62c56f98SSadaf Ebrahimi int signature_is_good = 0, fallback_signature_is_good;
2265*62c56f98SSadaf Ebrahimi
2266*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2267*62c56f98SSadaf Ebrahimi /* did we have something in progress? */
2268*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->parent != NULL) {
2269*62c56f98SSadaf Ebrahimi /* restore saved state */
2270*62c56f98SSadaf Ebrahimi parent = rs_ctx->parent;
2271*62c56f98SSadaf Ebrahimi fallback_parent = rs_ctx->fallback_parent;
2272*62c56f98SSadaf Ebrahimi fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
2273*62c56f98SSadaf Ebrahimi
2274*62c56f98SSadaf Ebrahimi /* clear saved state */
2275*62c56f98SSadaf Ebrahimi rs_ctx->parent = NULL;
2276*62c56f98SSadaf Ebrahimi rs_ctx->fallback_parent = NULL;
2277*62c56f98SSadaf Ebrahimi rs_ctx->fallback_signature_is_good = 0;
2278*62c56f98SSadaf Ebrahimi
2279*62c56f98SSadaf Ebrahimi /* resume where we left */
2280*62c56f98SSadaf Ebrahimi goto check_signature;
2281*62c56f98SSadaf Ebrahimi }
2282*62c56f98SSadaf Ebrahimi #endif
2283*62c56f98SSadaf Ebrahimi
2284*62c56f98SSadaf Ebrahimi fallback_parent = NULL;
2285*62c56f98SSadaf Ebrahimi fallback_signature_is_good = 0;
2286*62c56f98SSadaf Ebrahimi
2287*62c56f98SSadaf Ebrahimi for (parent = candidates; parent != NULL; parent = parent->next) {
2288*62c56f98SSadaf Ebrahimi /* basic parenting skills (name, CA bit, key usage) */
2289*62c56f98SSadaf Ebrahimi if (x509_crt_check_parent(child, parent, top) != 0) {
2290*62c56f98SSadaf Ebrahimi continue;
2291*62c56f98SSadaf Ebrahimi }
2292*62c56f98SSadaf Ebrahimi
2293*62c56f98SSadaf Ebrahimi /* +1 because stored max_pathlen is 1 higher that the actual value */
2294*62c56f98SSadaf Ebrahimi if (parent->max_pathlen > 0 &&
2295*62c56f98SSadaf Ebrahimi (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt) {
2296*62c56f98SSadaf Ebrahimi continue;
2297*62c56f98SSadaf Ebrahimi }
2298*62c56f98SSadaf Ebrahimi
2299*62c56f98SSadaf Ebrahimi /* Signature */
2300*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2301*62c56f98SSadaf Ebrahimi check_signature:
2302*62c56f98SSadaf Ebrahimi #endif
2303*62c56f98SSadaf Ebrahimi ret = x509_crt_check_signature(child, parent, rs_ctx);
2304*62c56f98SSadaf Ebrahimi
2305*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2306*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
2307*62c56f98SSadaf Ebrahimi /* save state */
2308*62c56f98SSadaf Ebrahimi rs_ctx->parent = parent;
2309*62c56f98SSadaf Ebrahimi rs_ctx->fallback_parent = fallback_parent;
2310*62c56f98SSadaf Ebrahimi rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
2311*62c56f98SSadaf Ebrahimi
2312*62c56f98SSadaf Ebrahimi return ret;
2313*62c56f98SSadaf Ebrahimi }
2314*62c56f98SSadaf Ebrahimi #else
2315*62c56f98SSadaf Ebrahimi (void) ret;
2316*62c56f98SSadaf Ebrahimi #endif
2317*62c56f98SSadaf Ebrahimi
2318*62c56f98SSadaf Ebrahimi signature_is_good = ret == 0;
2319*62c56f98SSadaf Ebrahimi if (top && !signature_is_good) {
2320*62c56f98SSadaf Ebrahimi continue;
2321*62c56f98SSadaf Ebrahimi }
2322*62c56f98SSadaf Ebrahimi
2323*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_HAVE_TIME_DATE)
2324*62c56f98SSadaf Ebrahimi /* optional time check */
2325*62c56f98SSadaf Ebrahimi if (mbedtls_x509_time_cmp(&parent->valid_to, now) < 0 || /* past */
2326*62c56f98SSadaf Ebrahimi mbedtls_x509_time_cmp(&parent->valid_from, now) > 0) { /* future */
2327*62c56f98SSadaf Ebrahimi if (fallback_parent == NULL) {
2328*62c56f98SSadaf Ebrahimi fallback_parent = parent;
2329*62c56f98SSadaf Ebrahimi fallback_signature_is_good = signature_is_good;
2330*62c56f98SSadaf Ebrahimi }
2331*62c56f98SSadaf Ebrahimi
2332*62c56f98SSadaf Ebrahimi continue;
2333*62c56f98SSadaf Ebrahimi }
2334*62c56f98SSadaf Ebrahimi #else
2335*62c56f98SSadaf Ebrahimi ((void) now);
2336*62c56f98SSadaf Ebrahimi #endif
2337*62c56f98SSadaf Ebrahimi
2338*62c56f98SSadaf Ebrahimi *r_parent = parent;
2339*62c56f98SSadaf Ebrahimi *r_signature_is_good = signature_is_good;
2340*62c56f98SSadaf Ebrahimi
2341*62c56f98SSadaf Ebrahimi break;
2342*62c56f98SSadaf Ebrahimi }
2343*62c56f98SSadaf Ebrahimi
2344*62c56f98SSadaf Ebrahimi if (parent == NULL) {
2345*62c56f98SSadaf Ebrahimi *r_parent = fallback_parent;
2346*62c56f98SSadaf Ebrahimi *r_signature_is_good = fallback_signature_is_good;
2347*62c56f98SSadaf Ebrahimi }
2348*62c56f98SSadaf Ebrahimi
2349*62c56f98SSadaf Ebrahimi return 0;
2350*62c56f98SSadaf Ebrahimi }
2351*62c56f98SSadaf Ebrahimi
2352*62c56f98SSadaf Ebrahimi /*
2353*62c56f98SSadaf Ebrahimi * Find a parent in trusted CAs or the provided chain, or return NULL.
2354*62c56f98SSadaf Ebrahimi *
2355*62c56f98SSadaf Ebrahimi * Searches in trusted CAs first, and return the first suitable parent found
2356*62c56f98SSadaf Ebrahimi * (see find_parent_in() for definition of suitable).
2357*62c56f98SSadaf Ebrahimi *
2358*62c56f98SSadaf Ebrahimi * Arguments:
2359*62c56f98SSadaf Ebrahimi * - [in] child: certificate for which we're looking for a parent, followed
2360*62c56f98SSadaf Ebrahimi * by a chain of possible intermediates
2361*62c56f98SSadaf Ebrahimi * - [in] trust_ca: list of locally trusted certificates
2362*62c56f98SSadaf Ebrahimi * - [out] parent: parent found (or NULL)
2363*62c56f98SSadaf Ebrahimi * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0
2364*62c56f98SSadaf Ebrahimi * - [out] signature_is_good: 1 if child signature by parent is valid, or 0
2365*62c56f98SSadaf Ebrahimi * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)
2366*62c56f98SSadaf Ebrahimi * - [in] self_cnt: number of self-signed certs in the chain so far
2367*62c56f98SSadaf Ebrahimi * (will always be no greater than path_cnt)
2368*62c56f98SSadaf Ebrahimi * - [in-out] rs_ctx: context for restarting operations
2369*62c56f98SSadaf Ebrahimi *
2370*62c56f98SSadaf Ebrahimi * Return value:
2371*62c56f98SSadaf Ebrahimi * - 0 on success
2372*62c56f98SSadaf Ebrahimi * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
2373*62c56f98SSadaf Ebrahimi */
x509_crt_find_parent(mbedtls_x509_crt * child,mbedtls_x509_crt * trust_ca,mbedtls_x509_crt ** parent,int * parent_is_trusted,int * signature_is_good,unsigned path_cnt,unsigned self_cnt,mbedtls_x509_crt_restart_ctx * rs_ctx,const mbedtls_x509_time * now)2374*62c56f98SSadaf Ebrahimi static int x509_crt_find_parent(
2375*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *child,
2376*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *trust_ca,
2377*62c56f98SSadaf Ebrahimi mbedtls_x509_crt **parent,
2378*62c56f98SSadaf Ebrahimi int *parent_is_trusted,
2379*62c56f98SSadaf Ebrahimi int *signature_is_good,
2380*62c56f98SSadaf Ebrahimi unsigned path_cnt,
2381*62c56f98SSadaf Ebrahimi unsigned self_cnt,
2382*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_restart_ctx *rs_ctx,
2383*62c56f98SSadaf Ebrahimi const mbedtls_x509_time *now)
2384*62c56f98SSadaf Ebrahimi {
2385*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2386*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *search_list;
2387*62c56f98SSadaf Ebrahimi
2388*62c56f98SSadaf Ebrahimi *parent_is_trusted = 1;
2389*62c56f98SSadaf Ebrahimi
2390*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2391*62c56f98SSadaf Ebrahimi /* restore then clear saved state if we have some stored */
2392*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->parent_is_trusted != -1) {
2393*62c56f98SSadaf Ebrahimi *parent_is_trusted = rs_ctx->parent_is_trusted;
2394*62c56f98SSadaf Ebrahimi rs_ctx->parent_is_trusted = -1;
2395*62c56f98SSadaf Ebrahimi }
2396*62c56f98SSadaf Ebrahimi #endif
2397*62c56f98SSadaf Ebrahimi
2398*62c56f98SSadaf Ebrahimi while (1) {
2399*62c56f98SSadaf Ebrahimi search_list = *parent_is_trusted ? trust_ca : child->next;
2400*62c56f98SSadaf Ebrahimi
2401*62c56f98SSadaf Ebrahimi ret = x509_crt_find_parent_in(child, search_list,
2402*62c56f98SSadaf Ebrahimi parent, signature_is_good,
2403*62c56f98SSadaf Ebrahimi *parent_is_trusted,
2404*62c56f98SSadaf Ebrahimi path_cnt, self_cnt, rs_ctx, now);
2405*62c56f98SSadaf Ebrahimi
2406*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2407*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
2408*62c56f98SSadaf Ebrahimi /* save state */
2409*62c56f98SSadaf Ebrahimi rs_ctx->parent_is_trusted = *parent_is_trusted;
2410*62c56f98SSadaf Ebrahimi return ret;
2411*62c56f98SSadaf Ebrahimi }
2412*62c56f98SSadaf Ebrahimi #else
2413*62c56f98SSadaf Ebrahimi (void) ret;
2414*62c56f98SSadaf Ebrahimi #endif
2415*62c56f98SSadaf Ebrahimi
2416*62c56f98SSadaf Ebrahimi /* stop here if found or already in second iteration */
2417*62c56f98SSadaf Ebrahimi if (*parent != NULL || *parent_is_trusted == 0) {
2418*62c56f98SSadaf Ebrahimi break;
2419*62c56f98SSadaf Ebrahimi }
2420*62c56f98SSadaf Ebrahimi
2421*62c56f98SSadaf Ebrahimi /* prepare second iteration */
2422*62c56f98SSadaf Ebrahimi *parent_is_trusted = 0;
2423*62c56f98SSadaf Ebrahimi }
2424*62c56f98SSadaf Ebrahimi
2425*62c56f98SSadaf Ebrahimi /* extra precaution against mistakes in the caller */
2426*62c56f98SSadaf Ebrahimi if (*parent == NULL) {
2427*62c56f98SSadaf Ebrahimi *parent_is_trusted = 0;
2428*62c56f98SSadaf Ebrahimi *signature_is_good = 0;
2429*62c56f98SSadaf Ebrahimi }
2430*62c56f98SSadaf Ebrahimi
2431*62c56f98SSadaf Ebrahimi return 0;
2432*62c56f98SSadaf Ebrahimi }
2433*62c56f98SSadaf Ebrahimi
2434*62c56f98SSadaf Ebrahimi /*
2435*62c56f98SSadaf Ebrahimi * Check if an end-entity certificate is locally trusted
2436*62c56f98SSadaf Ebrahimi *
2437*62c56f98SSadaf Ebrahimi * Currently we require such certificates to be self-signed (actually only
2438*62c56f98SSadaf Ebrahimi * check for self-issued as self-signatures are not checked)
2439*62c56f98SSadaf Ebrahimi */
x509_crt_check_ee_locally_trusted(mbedtls_x509_crt * crt,mbedtls_x509_crt * trust_ca)2440*62c56f98SSadaf Ebrahimi static int x509_crt_check_ee_locally_trusted(
2441*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *crt,
2442*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *trust_ca)
2443*62c56f98SSadaf Ebrahimi {
2444*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *cur;
2445*62c56f98SSadaf Ebrahimi
2446*62c56f98SSadaf Ebrahimi /* must be self-issued */
2447*62c56f98SSadaf Ebrahimi if (x509_name_cmp(&crt->issuer, &crt->subject) != 0) {
2448*62c56f98SSadaf Ebrahimi return -1;
2449*62c56f98SSadaf Ebrahimi }
2450*62c56f98SSadaf Ebrahimi
2451*62c56f98SSadaf Ebrahimi /* look for an exact match with trusted cert */
2452*62c56f98SSadaf Ebrahimi for (cur = trust_ca; cur != NULL; cur = cur->next) {
2453*62c56f98SSadaf Ebrahimi if (crt->raw.len == cur->raw.len &&
2454*62c56f98SSadaf Ebrahimi memcmp(crt->raw.p, cur->raw.p, crt->raw.len) == 0) {
2455*62c56f98SSadaf Ebrahimi return 0;
2456*62c56f98SSadaf Ebrahimi }
2457*62c56f98SSadaf Ebrahimi }
2458*62c56f98SSadaf Ebrahimi
2459*62c56f98SSadaf Ebrahimi /* too bad */
2460*62c56f98SSadaf Ebrahimi return -1;
2461*62c56f98SSadaf Ebrahimi }
2462*62c56f98SSadaf Ebrahimi
2463*62c56f98SSadaf Ebrahimi /*
2464*62c56f98SSadaf Ebrahimi * Build and verify a certificate chain
2465*62c56f98SSadaf Ebrahimi *
2466*62c56f98SSadaf Ebrahimi * Given a peer-provided list of certificates EE, C1, ..., Cn and
2467*62c56f98SSadaf Ebrahimi * a list of trusted certs R1, ... Rp, try to build and verify a chain
2468*62c56f98SSadaf Ebrahimi * EE, Ci1, ... Ciq [, Rj]
2469*62c56f98SSadaf Ebrahimi * such that every cert in the chain is a child of the next one,
2470*62c56f98SSadaf Ebrahimi * jumping to a trusted root as early as possible.
2471*62c56f98SSadaf Ebrahimi *
2472*62c56f98SSadaf Ebrahimi * Verify that chain and return it with flags for all issues found.
2473*62c56f98SSadaf Ebrahimi *
2474*62c56f98SSadaf Ebrahimi * Special cases:
2475*62c56f98SSadaf Ebrahimi * - EE == Rj -> return a one-element list containing it
2476*62c56f98SSadaf Ebrahimi * - EE, Ci1, ..., Ciq cannot be continued with a trusted root
2477*62c56f98SSadaf Ebrahimi * -> return that chain with NOT_TRUSTED set on Ciq
2478*62c56f98SSadaf Ebrahimi *
2479*62c56f98SSadaf Ebrahimi * Tests for (aspects of) this function should include at least:
2480*62c56f98SSadaf Ebrahimi * - trusted EE
2481*62c56f98SSadaf Ebrahimi * - EE -> trusted root
2482*62c56f98SSadaf Ebrahimi * - EE -> intermediate CA -> trusted root
2483*62c56f98SSadaf Ebrahimi * - if relevant: EE untrusted
2484*62c56f98SSadaf Ebrahimi * - if relevant: EE -> intermediate, untrusted
2485*62c56f98SSadaf Ebrahimi * with the aspect under test checked at each relevant level (EE, int, root).
2486*62c56f98SSadaf Ebrahimi * For some aspects longer chains are required, but usually length 2 is
2487*62c56f98SSadaf Ebrahimi * enough (but length 1 is not in general).
2488*62c56f98SSadaf Ebrahimi *
2489*62c56f98SSadaf Ebrahimi * Arguments:
2490*62c56f98SSadaf Ebrahimi * - [in] crt: the cert list EE, C1, ..., Cn
2491*62c56f98SSadaf Ebrahimi * - [in] trust_ca: the trusted list R1, ..., Rp
2492*62c56f98SSadaf Ebrahimi * - [in] ca_crl, profile: as in verify_with_profile()
2493*62c56f98SSadaf Ebrahimi * - [out] ver_chain: the built and verified chain
2494*62c56f98SSadaf Ebrahimi * Only valid when return value is 0, may contain garbage otherwise!
2495*62c56f98SSadaf Ebrahimi * Restart note: need not be the same when calling again to resume.
2496*62c56f98SSadaf Ebrahimi * - [in-out] rs_ctx: context for restarting operations
2497*62c56f98SSadaf Ebrahimi *
2498*62c56f98SSadaf Ebrahimi * Return value:
2499*62c56f98SSadaf Ebrahimi * - non-zero if the chain could not be fully built and examined
2500*62c56f98SSadaf Ebrahimi * - 0 is the chain was successfully built and examined,
2501*62c56f98SSadaf Ebrahimi * even if it was found to be invalid
2502*62c56f98SSadaf Ebrahimi */
x509_crt_verify_chain(mbedtls_x509_crt * crt,mbedtls_x509_crt * trust_ca,mbedtls_x509_crl * ca_crl,mbedtls_x509_crt_ca_cb_t f_ca_cb,void * p_ca_cb,const mbedtls_x509_crt_profile * profile,mbedtls_x509_crt_verify_chain * ver_chain,mbedtls_x509_crt_restart_ctx * rs_ctx)2503*62c56f98SSadaf Ebrahimi static int x509_crt_verify_chain(
2504*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *crt,
2505*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *trust_ca,
2506*62c56f98SSadaf Ebrahimi mbedtls_x509_crl *ca_crl,
2507*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_ca_cb_t f_ca_cb,
2508*62c56f98SSadaf Ebrahimi void *p_ca_cb,
2509*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_profile *profile,
2510*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_verify_chain *ver_chain,
2511*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_restart_ctx *rs_ctx)
2512*62c56f98SSadaf Ebrahimi {
2513*62c56f98SSadaf Ebrahimi /* Don't initialize any of those variables here, so that the compiler can
2514*62c56f98SSadaf Ebrahimi * catch potential issues with jumping ahead when restarting */
2515*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2516*62c56f98SSadaf Ebrahimi uint32_t *flags;
2517*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_verify_chain_item *cur;
2518*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *child;
2519*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *parent;
2520*62c56f98SSadaf Ebrahimi int parent_is_trusted;
2521*62c56f98SSadaf Ebrahimi int child_is_trusted;
2522*62c56f98SSadaf Ebrahimi int signature_is_good;
2523*62c56f98SSadaf Ebrahimi unsigned self_cnt;
2524*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *cur_trust_ca = NULL;
2525*62c56f98SSadaf Ebrahimi mbedtls_x509_time now;
2526*62c56f98SSadaf Ebrahimi
2527*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_HAVE_TIME_DATE)
2528*62c56f98SSadaf Ebrahimi if (mbedtls_x509_time_gmtime(mbedtls_time(NULL), &now) != 0) {
2529*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_FATAL_ERROR;
2530*62c56f98SSadaf Ebrahimi }
2531*62c56f98SSadaf Ebrahimi #endif
2532*62c56f98SSadaf Ebrahimi
2533*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2534*62c56f98SSadaf Ebrahimi /* resume if we had an operation in progress */
2535*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent) {
2536*62c56f98SSadaf Ebrahimi /* restore saved state */
2537*62c56f98SSadaf Ebrahimi *ver_chain = rs_ctx->ver_chain; /* struct copy */
2538*62c56f98SSadaf Ebrahimi self_cnt = rs_ctx->self_cnt;
2539*62c56f98SSadaf Ebrahimi
2540*62c56f98SSadaf Ebrahimi /* restore derived state */
2541*62c56f98SSadaf Ebrahimi cur = &ver_chain->items[ver_chain->len - 1];
2542*62c56f98SSadaf Ebrahimi child = cur->crt;
2543*62c56f98SSadaf Ebrahimi flags = &cur->flags;
2544*62c56f98SSadaf Ebrahimi
2545*62c56f98SSadaf Ebrahimi goto find_parent;
2546*62c56f98SSadaf Ebrahimi }
2547*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
2548*62c56f98SSadaf Ebrahimi
2549*62c56f98SSadaf Ebrahimi child = crt;
2550*62c56f98SSadaf Ebrahimi self_cnt = 0;
2551*62c56f98SSadaf Ebrahimi parent_is_trusted = 0;
2552*62c56f98SSadaf Ebrahimi child_is_trusted = 0;
2553*62c56f98SSadaf Ebrahimi
2554*62c56f98SSadaf Ebrahimi while (1) {
2555*62c56f98SSadaf Ebrahimi /* Add certificate to the verification chain */
2556*62c56f98SSadaf Ebrahimi cur = &ver_chain->items[ver_chain->len];
2557*62c56f98SSadaf Ebrahimi cur->crt = child;
2558*62c56f98SSadaf Ebrahimi cur->flags = 0;
2559*62c56f98SSadaf Ebrahimi ver_chain->len++;
2560*62c56f98SSadaf Ebrahimi flags = &cur->flags;
2561*62c56f98SSadaf Ebrahimi
2562*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_HAVE_TIME_DATE)
2563*62c56f98SSadaf Ebrahimi /* Check time-validity (all certificates) */
2564*62c56f98SSadaf Ebrahimi if (mbedtls_x509_time_cmp(&child->valid_to, &now) < 0) {
2565*62c56f98SSadaf Ebrahimi *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
2566*62c56f98SSadaf Ebrahimi }
2567*62c56f98SSadaf Ebrahimi
2568*62c56f98SSadaf Ebrahimi if (mbedtls_x509_time_cmp(&child->valid_from, &now) > 0) {
2569*62c56f98SSadaf Ebrahimi *flags |= MBEDTLS_X509_BADCERT_FUTURE;
2570*62c56f98SSadaf Ebrahimi }
2571*62c56f98SSadaf Ebrahimi #endif
2572*62c56f98SSadaf Ebrahimi
2573*62c56f98SSadaf Ebrahimi /* Stop here for trusted roots (but not for trusted EE certs) */
2574*62c56f98SSadaf Ebrahimi if (child_is_trusted) {
2575*62c56f98SSadaf Ebrahimi return 0;
2576*62c56f98SSadaf Ebrahimi }
2577*62c56f98SSadaf Ebrahimi
2578*62c56f98SSadaf Ebrahimi /* Check signature algorithm: MD & PK algs */
2579*62c56f98SSadaf Ebrahimi if (x509_profile_check_md_alg(profile, child->sig_md) != 0) {
2580*62c56f98SSadaf Ebrahimi *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
2581*62c56f98SSadaf Ebrahimi }
2582*62c56f98SSadaf Ebrahimi
2583*62c56f98SSadaf Ebrahimi if (x509_profile_check_pk_alg(profile, child->sig_pk) != 0) {
2584*62c56f98SSadaf Ebrahimi *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
2585*62c56f98SSadaf Ebrahimi }
2586*62c56f98SSadaf Ebrahimi
2587*62c56f98SSadaf Ebrahimi /* Special case: EE certs that are locally trusted */
2588*62c56f98SSadaf Ebrahimi if (ver_chain->len == 1 &&
2589*62c56f98SSadaf Ebrahimi x509_crt_check_ee_locally_trusted(child, trust_ca) == 0) {
2590*62c56f98SSadaf Ebrahimi return 0;
2591*62c56f98SSadaf Ebrahimi }
2592*62c56f98SSadaf Ebrahimi
2593*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2594*62c56f98SSadaf Ebrahimi find_parent:
2595*62c56f98SSadaf Ebrahimi #endif
2596*62c56f98SSadaf Ebrahimi
2597*62c56f98SSadaf Ebrahimi /* Obtain list of potential trusted signers from CA callback,
2598*62c56f98SSadaf Ebrahimi * or use statically provided list. */
2599*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
2600*62c56f98SSadaf Ebrahimi if (f_ca_cb != NULL) {
2601*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(ver_chain->trust_ca_cb_result);
2602*62c56f98SSadaf Ebrahimi mbedtls_free(ver_chain->trust_ca_cb_result);
2603*62c56f98SSadaf Ebrahimi ver_chain->trust_ca_cb_result = NULL;
2604*62c56f98SSadaf Ebrahimi
2605*62c56f98SSadaf Ebrahimi ret = f_ca_cb(p_ca_cb, child, &ver_chain->trust_ca_cb_result);
2606*62c56f98SSadaf Ebrahimi if (ret != 0) {
2607*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_FATAL_ERROR;
2608*62c56f98SSadaf Ebrahimi }
2609*62c56f98SSadaf Ebrahimi
2610*62c56f98SSadaf Ebrahimi cur_trust_ca = ver_chain->trust_ca_cb_result;
2611*62c56f98SSadaf Ebrahimi } else
2612*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
2613*62c56f98SSadaf Ebrahimi {
2614*62c56f98SSadaf Ebrahimi ((void) f_ca_cb);
2615*62c56f98SSadaf Ebrahimi ((void) p_ca_cb);
2616*62c56f98SSadaf Ebrahimi cur_trust_ca = trust_ca;
2617*62c56f98SSadaf Ebrahimi }
2618*62c56f98SSadaf Ebrahimi
2619*62c56f98SSadaf Ebrahimi /* Look for a parent in trusted CAs or up the chain */
2620*62c56f98SSadaf Ebrahimi ret = x509_crt_find_parent(child, cur_trust_ca, &parent,
2621*62c56f98SSadaf Ebrahimi &parent_is_trusted, &signature_is_good,
2622*62c56f98SSadaf Ebrahimi ver_chain->len - 1, self_cnt, rs_ctx,
2623*62c56f98SSadaf Ebrahimi &now);
2624*62c56f98SSadaf Ebrahimi
2625*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2626*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
2627*62c56f98SSadaf Ebrahimi /* save state */
2628*62c56f98SSadaf Ebrahimi rs_ctx->in_progress = x509_crt_rs_find_parent;
2629*62c56f98SSadaf Ebrahimi rs_ctx->self_cnt = self_cnt;
2630*62c56f98SSadaf Ebrahimi rs_ctx->ver_chain = *ver_chain; /* struct copy */
2631*62c56f98SSadaf Ebrahimi
2632*62c56f98SSadaf Ebrahimi return ret;
2633*62c56f98SSadaf Ebrahimi }
2634*62c56f98SSadaf Ebrahimi #else
2635*62c56f98SSadaf Ebrahimi (void) ret;
2636*62c56f98SSadaf Ebrahimi #endif
2637*62c56f98SSadaf Ebrahimi
2638*62c56f98SSadaf Ebrahimi /* No parent? We're done here */
2639*62c56f98SSadaf Ebrahimi if (parent == NULL) {
2640*62c56f98SSadaf Ebrahimi *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
2641*62c56f98SSadaf Ebrahimi return 0;
2642*62c56f98SSadaf Ebrahimi }
2643*62c56f98SSadaf Ebrahimi
2644*62c56f98SSadaf Ebrahimi /* Count intermediate self-issued (not necessarily self-signed) certs.
2645*62c56f98SSadaf Ebrahimi * These can occur with some strategies for key rollover, see [SIRO],
2646*62c56f98SSadaf Ebrahimi * and should be excluded from max_pathlen checks. */
2647*62c56f98SSadaf Ebrahimi if (ver_chain->len != 1 &&
2648*62c56f98SSadaf Ebrahimi x509_name_cmp(&child->issuer, &child->subject) == 0) {
2649*62c56f98SSadaf Ebrahimi self_cnt++;
2650*62c56f98SSadaf Ebrahimi }
2651*62c56f98SSadaf Ebrahimi
2652*62c56f98SSadaf Ebrahimi /* path_cnt is 0 for the first intermediate CA,
2653*62c56f98SSadaf Ebrahimi * and if parent is trusted it's not an intermediate CA */
2654*62c56f98SSadaf Ebrahimi if (!parent_is_trusted &&
2655*62c56f98SSadaf Ebrahimi ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA) {
2656*62c56f98SSadaf Ebrahimi /* return immediately to avoid overflow the chain array */
2657*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_FATAL_ERROR;
2658*62c56f98SSadaf Ebrahimi }
2659*62c56f98SSadaf Ebrahimi
2660*62c56f98SSadaf Ebrahimi /* signature was checked while searching parent */
2661*62c56f98SSadaf Ebrahimi if (!signature_is_good) {
2662*62c56f98SSadaf Ebrahimi *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
2663*62c56f98SSadaf Ebrahimi }
2664*62c56f98SSadaf Ebrahimi
2665*62c56f98SSadaf Ebrahimi /* check size of signing key */
2666*62c56f98SSadaf Ebrahimi if (x509_profile_check_key(profile, &parent->pk) != 0) {
2667*62c56f98SSadaf Ebrahimi *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
2668*62c56f98SSadaf Ebrahimi }
2669*62c56f98SSadaf Ebrahimi
2670*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_X509_CRL_PARSE_C)
2671*62c56f98SSadaf Ebrahimi /* Check trusted CA's CRL for the given crt */
2672*62c56f98SSadaf Ebrahimi *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile, &now);
2673*62c56f98SSadaf Ebrahimi #else
2674*62c56f98SSadaf Ebrahimi (void) ca_crl;
2675*62c56f98SSadaf Ebrahimi #endif
2676*62c56f98SSadaf Ebrahimi
2677*62c56f98SSadaf Ebrahimi /* prepare for next iteration */
2678*62c56f98SSadaf Ebrahimi child = parent;
2679*62c56f98SSadaf Ebrahimi parent = NULL;
2680*62c56f98SSadaf Ebrahimi child_is_trusted = parent_is_trusted;
2681*62c56f98SSadaf Ebrahimi signature_is_good = 0;
2682*62c56f98SSadaf Ebrahimi }
2683*62c56f98SSadaf Ebrahimi }
2684*62c56f98SSadaf Ebrahimi
2685*62c56f98SSadaf Ebrahimi #ifdef _WIN32
2686*62c56f98SSadaf Ebrahimi #ifdef _MSC_VER
2687*62c56f98SSadaf Ebrahimi #pragma comment(lib, "ws2_32.lib")
2688*62c56f98SSadaf Ebrahimi #include <winsock2.h>
2689*62c56f98SSadaf Ebrahimi #include <ws2tcpip.h>
2690*62c56f98SSadaf Ebrahimi #elif (defined(__MINGW32__) || defined(__MINGW64__)) && _WIN32_WINNT >= 0x0600
2691*62c56f98SSadaf Ebrahimi #include <winsock2.h>
2692*62c56f98SSadaf Ebrahimi #include <ws2tcpip.h>
2693*62c56f98SSadaf Ebrahimi #else
2694*62c56f98SSadaf Ebrahimi /* inet_pton() is not supported, fallback to software version */
2695*62c56f98SSadaf Ebrahimi #define MBEDTLS_TEST_SW_INET_PTON
2696*62c56f98SSadaf Ebrahimi #endif
2697*62c56f98SSadaf Ebrahimi #elif defined(__sun)
2698*62c56f98SSadaf Ebrahimi /* Solaris requires -lsocket -lnsl for inet_pton() */
2699*62c56f98SSadaf Ebrahimi #elif defined(__has_include)
2700*62c56f98SSadaf Ebrahimi #if __has_include(<sys/socket.h>)
2701*62c56f98SSadaf Ebrahimi #include <sys/socket.h>
2702*62c56f98SSadaf Ebrahimi #endif
2703*62c56f98SSadaf Ebrahimi #if __has_include(<arpa/inet.h>)
2704*62c56f98SSadaf Ebrahimi #include <arpa/inet.h>
2705*62c56f98SSadaf Ebrahimi #endif
2706*62c56f98SSadaf Ebrahimi #endif
2707*62c56f98SSadaf Ebrahimi
2708*62c56f98SSadaf Ebrahimi /* Use whether or not AF_INET6 is defined to indicate whether or not to use
2709*62c56f98SSadaf Ebrahimi * the platform inet_pton() or a local implementation (below). The local
2710*62c56f98SSadaf Ebrahimi * implementation may be used even in cases where the platform provides
2711*62c56f98SSadaf Ebrahimi * inet_pton(), e.g. when there are different includes required and/or the
2712*62c56f98SSadaf Ebrahimi * platform implementation requires dependencies on additional libraries.
2713*62c56f98SSadaf Ebrahimi * Specifically, Windows requires custom includes and additional link
2714*62c56f98SSadaf Ebrahimi * dependencies, and Solaris requires additional link dependencies.
2715*62c56f98SSadaf Ebrahimi * Also, as a coarse heuristic, use the local implementation if the compiler
2716*62c56f98SSadaf Ebrahimi * does not support __has_include(), or if the definition of AF_INET6 is not
2717*62c56f98SSadaf Ebrahimi * provided by headers included (or not) via __has_include() above.
2718*62c56f98SSadaf Ebrahimi * MBEDTLS_TEST_SW_INET_PTON is a bypass define to force testing of this code //no-check-names
2719*62c56f98SSadaf Ebrahimi * despite having a platform that has inet_pton. */
2720*62c56f98SSadaf Ebrahimi #if !defined(AF_INET6) || defined(MBEDTLS_TEST_SW_INET_PTON) //no-check-names
2721*62c56f98SSadaf Ebrahimi /* Definition located further below to possibly reduce compiler inlining */
2722*62c56f98SSadaf Ebrahimi static int x509_inet_pton_ipv4(const char *src, void *dst);
2723*62c56f98SSadaf Ebrahimi
2724*62c56f98SSadaf Ebrahimi #define li_cton(c, n) \
2725*62c56f98SSadaf Ebrahimi (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
2726*62c56f98SSadaf Ebrahimi
x509_inet_pton_ipv6(const char * src,void * dst)2727*62c56f98SSadaf Ebrahimi static int x509_inet_pton_ipv6(const char *src, void *dst)
2728*62c56f98SSadaf Ebrahimi {
2729*62c56f98SSadaf Ebrahimi const unsigned char *p = (const unsigned char *) src;
2730*62c56f98SSadaf Ebrahimi int nonzero_groups = 0, num_digits, zero_group_start = -1;
2731*62c56f98SSadaf Ebrahimi uint16_t addr[8];
2732*62c56f98SSadaf Ebrahimi do {
2733*62c56f98SSadaf Ebrahimi /* note: allows excess leading 0's, e.g. 1:0002:3:... */
2734*62c56f98SSadaf Ebrahimi uint16_t group = num_digits = 0;
2735*62c56f98SSadaf Ebrahimi for (uint8_t digit; num_digits < 4; num_digits++) {
2736*62c56f98SSadaf Ebrahimi if (li_cton(*p, digit) == 0) {
2737*62c56f98SSadaf Ebrahimi break;
2738*62c56f98SSadaf Ebrahimi }
2739*62c56f98SSadaf Ebrahimi group = (group << 4) | digit;
2740*62c56f98SSadaf Ebrahimi p++;
2741*62c56f98SSadaf Ebrahimi }
2742*62c56f98SSadaf Ebrahimi if (num_digits != 0) {
2743*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT16_BE(group, addr, nonzero_groups);
2744*62c56f98SSadaf Ebrahimi nonzero_groups++;
2745*62c56f98SSadaf Ebrahimi if (*p == '\0') {
2746*62c56f98SSadaf Ebrahimi break;
2747*62c56f98SSadaf Ebrahimi } else if (*p == '.') {
2748*62c56f98SSadaf Ebrahimi /* Don't accept IPv4 too early or late */
2749*62c56f98SSadaf Ebrahimi if ((nonzero_groups == 0 && zero_group_start == -1) ||
2750*62c56f98SSadaf Ebrahimi nonzero_groups >= 7) {
2751*62c56f98SSadaf Ebrahimi break;
2752*62c56f98SSadaf Ebrahimi }
2753*62c56f98SSadaf Ebrahimi
2754*62c56f98SSadaf Ebrahimi /* Walk back to prior ':', then parse as IPv4-mapped */
2755*62c56f98SSadaf Ebrahimi int steps = 4;
2756*62c56f98SSadaf Ebrahimi do {
2757*62c56f98SSadaf Ebrahimi p--;
2758*62c56f98SSadaf Ebrahimi steps--;
2759*62c56f98SSadaf Ebrahimi } while (*p != ':' && steps > 0);
2760*62c56f98SSadaf Ebrahimi
2761*62c56f98SSadaf Ebrahimi if (*p != ':') {
2762*62c56f98SSadaf Ebrahimi break;
2763*62c56f98SSadaf Ebrahimi }
2764*62c56f98SSadaf Ebrahimi p++;
2765*62c56f98SSadaf Ebrahimi nonzero_groups--;
2766*62c56f98SSadaf Ebrahimi if (x509_inet_pton_ipv4((const char *) p,
2767*62c56f98SSadaf Ebrahimi addr + nonzero_groups) != 0) {
2768*62c56f98SSadaf Ebrahimi break;
2769*62c56f98SSadaf Ebrahimi }
2770*62c56f98SSadaf Ebrahimi
2771*62c56f98SSadaf Ebrahimi nonzero_groups += 2;
2772*62c56f98SSadaf Ebrahimi p = (const unsigned char *) "";
2773*62c56f98SSadaf Ebrahimi break;
2774*62c56f98SSadaf Ebrahimi } else if (*p != ':') {
2775*62c56f98SSadaf Ebrahimi return -1;
2776*62c56f98SSadaf Ebrahimi }
2777*62c56f98SSadaf Ebrahimi } else {
2778*62c56f98SSadaf Ebrahimi /* Don't accept a second zero group or an invalid delimiter */
2779*62c56f98SSadaf Ebrahimi if (zero_group_start != -1 || *p != ':') {
2780*62c56f98SSadaf Ebrahimi return -1;
2781*62c56f98SSadaf Ebrahimi }
2782*62c56f98SSadaf Ebrahimi zero_group_start = nonzero_groups;
2783*62c56f98SSadaf Ebrahimi
2784*62c56f98SSadaf Ebrahimi /* Accept a zero group at start, but it has to be a double colon */
2785*62c56f98SSadaf Ebrahimi if (zero_group_start == 0 && *++p != ':') {
2786*62c56f98SSadaf Ebrahimi return -1;
2787*62c56f98SSadaf Ebrahimi }
2788*62c56f98SSadaf Ebrahimi
2789*62c56f98SSadaf Ebrahimi if (p[1] == '\0') {
2790*62c56f98SSadaf Ebrahimi ++p;
2791*62c56f98SSadaf Ebrahimi break;
2792*62c56f98SSadaf Ebrahimi }
2793*62c56f98SSadaf Ebrahimi }
2794*62c56f98SSadaf Ebrahimi ++p;
2795*62c56f98SSadaf Ebrahimi } while (nonzero_groups < 8);
2796*62c56f98SSadaf Ebrahimi
2797*62c56f98SSadaf Ebrahimi if (*p != '\0') {
2798*62c56f98SSadaf Ebrahimi return -1;
2799*62c56f98SSadaf Ebrahimi }
2800*62c56f98SSadaf Ebrahimi
2801*62c56f98SSadaf Ebrahimi if (zero_group_start != -1) {
2802*62c56f98SSadaf Ebrahimi if (nonzero_groups > 6) {
2803*62c56f98SSadaf Ebrahimi return -1;
2804*62c56f98SSadaf Ebrahimi }
2805*62c56f98SSadaf Ebrahimi int zero_groups = 8 - nonzero_groups;
2806*62c56f98SSadaf Ebrahimi int groups_after_zero = nonzero_groups - zero_group_start;
2807*62c56f98SSadaf Ebrahimi
2808*62c56f98SSadaf Ebrahimi /* Move the non-zero part to after the zeroes */
2809*62c56f98SSadaf Ebrahimi if (groups_after_zero) {
2810*62c56f98SSadaf Ebrahimi memmove(addr + zero_group_start + zero_groups,
2811*62c56f98SSadaf Ebrahimi addr + zero_group_start,
2812*62c56f98SSadaf Ebrahimi groups_after_zero * sizeof(*addr));
2813*62c56f98SSadaf Ebrahimi }
2814*62c56f98SSadaf Ebrahimi memset(addr + zero_group_start, 0, zero_groups * sizeof(*addr));
2815*62c56f98SSadaf Ebrahimi } else {
2816*62c56f98SSadaf Ebrahimi if (nonzero_groups != 8) {
2817*62c56f98SSadaf Ebrahimi return -1;
2818*62c56f98SSadaf Ebrahimi }
2819*62c56f98SSadaf Ebrahimi }
2820*62c56f98SSadaf Ebrahimi memcpy(dst, addr, sizeof(addr));
2821*62c56f98SSadaf Ebrahimi return 0;
2822*62c56f98SSadaf Ebrahimi }
2823*62c56f98SSadaf Ebrahimi
x509_inet_pton_ipv4(const char * src,void * dst)2824*62c56f98SSadaf Ebrahimi static int x509_inet_pton_ipv4(const char *src, void *dst)
2825*62c56f98SSadaf Ebrahimi {
2826*62c56f98SSadaf Ebrahimi const unsigned char *p = (const unsigned char *) src;
2827*62c56f98SSadaf Ebrahimi uint8_t *res = (uint8_t *) dst;
2828*62c56f98SSadaf Ebrahimi uint8_t digit, num_digits = 0;
2829*62c56f98SSadaf Ebrahimi uint8_t num_octets = 0;
2830*62c56f98SSadaf Ebrahimi uint16_t octet;
2831*62c56f98SSadaf Ebrahimi
2832*62c56f98SSadaf Ebrahimi do {
2833*62c56f98SSadaf Ebrahimi octet = num_digits = 0;
2834*62c56f98SSadaf Ebrahimi do {
2835*62c56f98SSadaf Ebrahimi digit = *p - '0';
2836*62c56f98SSadaf Ebrahimi if (digit > 9) {
2837*62c56f98SSadaf Ebrahimi break;
2838*62c56f98SSadaf Ebrahimi }
2839*62c56f98SSadaf Ebrahimi
2840*62c56f98SSadaf Ebrahimi /* Don't allow leading zeroes. These might mean octal format,
2841*62c56f98SSadaf Ebrahimi * which this implementation does not support. */
2842*62c56f98SSadaf Ebrahimi if (octet == 0 && num_digits > 0) {
2843*62c56f98SSadaf Ebrahimi return -1;
2844*62c56f98SSadaf Ebrahimi }
2845*62c56f98SSadaf Ebrahimi
2846*62c56f98SSadaf Ebrahimi octet = octet * 10 + digit;
2847*62c56f98SSadaf Ebrahimi num_digits++;
2848*62c56f98SSadaf Ebrahimi p++;
2849*62c56f98SSadaf Ebrahimi } while (num_digits < 3);
2850*62c56f98SSadaf Ebrahimi
2851*62c56f98SSadaf Ebrahimi if (octet >= 256 || num_digits > 3 || num_digits == 0) {
2852*62c56f98SSadaf Ebrahimi return -1;
2853*62c56f98SSadaf Ebrahimi }
2854*62c56f98SSadaf Ebrahimi *res++ = (uint8_t) octet;
2855*62c56f98SSadaf Ebrahimi num_octets++;
2856*62c56f98SSadaf Ebrahimi } while (num_octets < 4 && *p++ == '.');
2857*62c56f98SSadaf Ebrahimi return num_octets == 4 && *p == '\0' ? 0 : -1;
2858*62c56f98SSadaf Ebrahimi }
2859*62c56f98SSadaf Ebrahimi
2860*62c56f98SSadaf Ebrahimi #else
2861*62c56f98SSadaf Ebrahimi
x509_inet_pton_ipv6(const char * src,void * dst)2862*62c56f98SSadaf Ebrahimi static int x509_inet_pton_ipv6(const char *src, void *dst)
2863*62c56f98SSadaf Ebrahimi {
2864*62c56f98SSadaf Ebrahimi return inet_pton(AF_INET6, src, dst) == 1 ? 0 : -1;
2865*62c56f98SSadaf Ebrahimi }
2866*62c56f98SSadaf Ebrahimi
x509_inet_pton_ipv4(const char * src,void * dst)2867*62c56f98SSadaf Ebrahimi static int x509_inet_pton_ipv4(const char *src, void *dst)
2868*62c56f98SSadaf Ebrahimi {
2869*62c56f98SSadaf Ebrahimi return inet_pton(AF_INET, src, dst) == 1 ? 0 : -1;
2870*62c56f98SSadaf Ebrahimi }
2871*62c56f98SSadaf Ebrahimi
2872*62c56f98SSadaf Ebrahimi #endif /* !AF_INET6 || MBEDTLS_TEST_SW_INET_PTON */ //no-check-names
2873*62c56f98SSadaf Ebrahimi
mbedtls_x509_crt_parse_cn_inet_pton(const char * cn,void * dst)2874*62c56f98SSadaf Ebrahimi size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst)
2875*62c56f98SSadaf Ebrahimi {
2876*62c56f98SSadaf Ebrahimi return strchr(cn, ':') == NULL
2877*62c56f98SSadaf Ebrahimi ? x509_inet_pton_ipv4(cn, dst) == 0 ? 4 : 0
2878*62c56f98SSadaf Ebrahimi : x509_inet_pton_ipv6(cn, dst) == 0 ? 16 : 0;
2879*62c56f98SSadaf Ebrahimi }
2880*62c56f98SSadaf Ebrahimi
2881*62c56f98SSadaf Ebrahimi /*
2882*62c56f98SSadaf Ebrahimi * Check for CN match
2883*62c56f98SSadaf Ebrahimi */
x509_crt_check_cn(const mbedtls_x509_buf * name,const char * cn,size_t cn_len)2884*62c56f98SSadaf Ebrahimi static int x509_crt_check_cn(const mbedtls_x509_buf *name,
2885*62c56f98SSadaf Ebrahimi const char *cn, size_t cn_len)
2886*62c56f98SSadaf Ebrahimi {
2887*62c56f98SSadaf Ebrahimi /* try exact match */
2888*62c56f98SSadaf Ebrahimi if (name->len == cn_len &&
2889*62c56f98SSadaf Ebrahimi x509_memcasecmp(cn, name->p, cn_len) == 0) {
2890*62c56f98SSadaf Ebrahimi return 0;
2891*62c56f98SSadaf Ebrahimi }
2892*62c56f98SSadaf Ebrahimi
2893*62c56f98SSadaf Ebrahimi /* try wildcard match */
2894*62c56f98SSadaf Ebrahimi if (x509_check_wildcard(cn, name) == 0) {
2895*62c56f98SSadaf Ebrahimi return 0;
2896*62c56f98SSadaf Ebrahimi }
2897*62c56f98SSadaf Ebrahimi
2898*62c56f98SSadaf Ebrahimi return -1;
2899*62c56f98SSadaf Ebrahimi }
2900*62c56f98SSadaf Ebrahimi
x509_crt_check_san_ip(const mbedtls_x509_sequence * san,const char * cn,size_t cn_len)2901*62c56f98SSadaf Ebrahimi static int x509_crt_check_san_ip(const mbedtls_x509_sequence *san,
2902*62c56f98SSadaf Ebrahimi const char *cn, size_t cn_len)
2903*62c56f98SSadaf Ebrahimi {
2904*62c56f98SSadaf Ebrahimi uint32_t ip[4];
2905*62c56f98SSadaf Ebrahimi cn_len = mbedtls_x509_crt_parse_cn_inet_pton(cn, ip);
2906*62c56f98SSadaf Ebrahimi if (cn_len == 0) {
2907*62c56f98SSadaf Ebrahimi return -1;
2908*62c56f98SSadaf Ebrahimi }
2909*62c56f98SSadaf Ebrahimi
2910*62c56f98SSadaf Ebrahimi for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) {
2911*62c56f98SSadaf Ebrahimi const unsigned char san_type = (unsigned char) cur->buf.tag &
2912*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_TAG_VALUE_MASK;
2913*62c56f98SSadaf Ebrahimi if (san_type == MBEDTLS_X509_SAN_IP_ADDRESS &&
2914*62c56f98SSadaf Ebrahimi cur->buf.len == cn_len && memcmp(cur->buf.p, ip, cn_len) == 0) {
2915*62c56f98SSadaf Ebrahimi return 0;
2916*62c56f98SSadaf Ebrahimi }
2917*62c56f98SSadaf Ebrahimi }
2918*62c56f98SSadaf Ebrahimi
2919*62c56f98SSadaf Ebrahimi return -1;
2920*62c56f98SSadaf Ebrahimi }
2921*62c56f98SSadaf Ebrahimi
x509_crt_check_san_uri(const mbedtls_x509_sequence * san,const char * cn,size_t cn_len)2922*62c56f98SSadaf Ebrahimi static int x509_crt_check_san_uri(const mbedtls_x509_sequence *san,
2923*62c56f98SSadaf Ebrahimi const char *cn, size_t cn_len)
2924*62c56f98SSadaf Ebrahimi {
2925*62c56f98SSadaf Ebrahimi for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) {
2926*62c56f98SSadaf Ebrahimi const unsigned char san_type = (unsigned char) cur->buf.tag &
2927*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_TAG_VALUE_MASK;
2928*62c56f98SSadaf Ebrahimi if (san_type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER &&
2929*62c56f98SSadaf Ebrahimi cur->buf.len == cn_len && memcmp(cur->buf.p, cn, cn_len) == 0) {
2930*62c56f98SSadaf Ebrahimi return 0;
2931*62c56f98SSadaf Ebrahimi }
2932*62c56f98SSadaf Ebrahimi }
2933*62c56f98SSadaf Ebrahimi
2934*62c56f98SSadaf Ebrahimi return -1;
2935*62c56f98SSadaf Ebrahimi }
2936*62c56f98SSadaf Ebrahimi
2937*62c56f98SSadaf Ebrahimi /*
2938*62c56f98SSadaf Ebrahimi * Check for SAN match, see RFC 5280 Section 4.2.1.6
2939*62c56f98SSadaf Ebrahimi */
x509_crt_check_san(const mbedtls_x509_sequence * san,const char * cn,size_t cn_len)2940*62c56f98SSadaf Ebrahimi static int x509_crt_check_san(const mbedtls_x509_sequence *san,
2941*62c56f98SSadaf Ebrahimi const char *cn, size_t cn_len)
2942*62c56f98SSadaf Ebrahimi {
2943*62c56f98SSadaf Ebrahimi int san_ip = 0;
2944*62c56f98SSadaf Ebrahimi int san_uri = 0;
2945*62c56f98SSadaf Ebrahimi /* Prioritize DNS name over other subtypes due to popularity */
2946*62c56f98SSadaf Ebrahimi for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) {
2947*62c56f98SSadaf Ebrahimi switch ((unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) {
2948*62c56f98SSadaf Ebrahimi case MBEDTLS_X509_SAN_DNS_NAME:
2949*62c56f98SSadaf Ebrahimi if (x509_crt_check_cn(&cur->buf, cn, cn_len) == 0) {
2950*62c56f98SSadaf Ebrahimi return 0;
2951*62c56f98SSadaf Ebrahimi }
2952*62c56f98SSadaf Ebrahimi break;
2953*62c56f98SSadaf Ebrahimi case MBEDTLS_X509_SAN_IP_ADDRESS:
2954*62c56f98SSadaf Ebrahimi san_ip = 1;
2955*62c56f98SSadaf Ebrahimi break;
2956*62c56f98SSadaf Ebrahimi case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
2957*62c56f98SSadaf Ebrahimi san_uri = 1;
2958*62c56f98SSadaf Ebrahimi break;
2959*62c56f98SSadaf Ebrahimi /* (We may handle other types here later.) */
2960*62c56f98SSadaf Ebrahimi default: /* Unrecognized type */
2961*62c56f98SSadaf Ebrahimi break;
2962*62c56f98SSadaf Ebrahimi }
2963*62c56f98SSadaf Ebrahimi }
2964*62c56f98SSadaf Ebrahimi if (san_ip) {
2965*62c56f98SSadaf Ebrahimi if (x509_crt_check_san_ip(san, cn, cn_len) == 0) {
2966*62c56f98SSadaf Ebrahimi return 0;
2967*62c56f98SSadaf Ebrahimi }
2968*62c56f98SSadaf Ebrahimi }
2969*62c56f98SSadaf Ebrahimi if (san_uri) {
2970*62c56f98SSadaf Ebrahimi if (x509_crt_check_san_uri(san, cn, cn_len) == 0) {
2971*62c56f98SSadaf Ebrahimi return 0;
2972*62c56f98SSadaf Ebrahimi }
2973*62c56f98SSadaf Ebrahimi }
2974*62c56f98SSadaf Ebrahimi
2975*62c56f98SSadaf Ebrahimi return -1;
2976*62c56f98SSadaf Ebrahimi }
2977*62c56f98SSadaf Ebrahimi
2978*62c56f98SSadaf Ebrahimi /*
2979*62c56f98SSadaf Ebrahimi * Verify the requested CN - only call this if cn is not NULL!
2980*62c56f98SSadaf Ebrahimi */
x509_crt_verify_name(const mbedtls_x509_crt * crt,const char * cn,uint32_t * flags)2981*62c56f98SSadaf Ebrahimi static void x509_crt_verify_name(const mbedtls_x509_crt *crt,
2982*62c56f98SSadaf Ebrahimi const char *cn,
2983*62c56f98SSadaf Ebrahimi uint32_t *flags)
2984*62c56f98SSadaf Ebrahimi {
2985*62c56f98SSadaf Ebrahimi const mbedtls_x509_name *name;
2986*62c56f98SSadaf Ebrahimi size_t cn_len = strlen(cn);
2987*62c56f98SSadaf Ebrahimi
2988*62c56f98SSadaf Ebrahimi if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
2989*62c56f98SSadaf Ebrahimi if (x509_crt_check_san(&crt->subject_alt_names, cn, cn_len) == 0) {
2990*62c56f98SSadaf Ebrahimi return;
2991*62c56f98SSadaf Ebrahimi }
2992*62c56f98SSadaf Ebrahimi } else {
2993*62c56f98SSadaf Ebrahimi for (name = &crt->subject; name != NULL; name = name->next) {
2994*62c56f98SSadaf Ebrahimi if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 &&
2995*62c56f98SSadaf Ebrahimi x509_crt_check_cn(&name->val, cn, cn_len) == 0) {
2996*62c56f98SSadaf Ebrahimi return;
2997*62c56f98SSadaf Ebrahimi }
2998*62c56f98SSadaf Ebrahimi }
2999*62c56f98SSadaf Ebrahimi
3000*62c56f98SSadaf Ebrahimi }
3001*62c56f98SSadaf Ebrahimi
3002*62c56f98SSadaf Ebrahimi *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
3003*62c56f98SSadaf Ebrahimi }
3004*62c56f98SSadaf Ebrahimi
3005*62c56f98SSadaf Ebrahimi /*
3006*62c56f98SSadaf Ebrahimi * Merge the flags for all certs in the chain, after calling callback
3007*62c56f98SSadaf Ebrahimi */
x509_crt_merge_flags_with_cb(uint32_t * flags,const mbedtls_x509_crt_verify_chain * ver_chain,int (* f_vrfy)(void *,mbedtls_x509_crt *,int,uint32_t *),void * p_vrfy)3008*62c56f98SSadaf Ebrahimi static int x509_crt_merge_flags_with_cb(
3009*62c56f98SSadaf Ebrahimi uint32_t *flags,
3010*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_verify_chain *ver_chain,
3011*62c56f98SSadaf Ebrahimi int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3012*62c56f98SSadaf Ebrahimi void *p_vrfy)
3013*62c56f98SSadaf Ebrahimi {
3014*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3015*62c56f98SSadaf Ebrahimi unsigned i;
3016*62c56f98SSadaf Ebrahimi uint32_t cur_flags;
3017*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_verify_chain_item *cur;
3018*62c56f98SSadaf Ebrahimi
3019*62c56f98SSadaf Ebrahimi for (i = ver_chain->len; i != 0; --i) {
3020*62c56f98SSadaf Ebrahimi cur = &ver_chain->items[i-1];
3021*62c56f98SSadaf Ebrahimi cur_flags = cur->flags;
3022*62c56f98SSadaf Ebrahimi
3023*62c56f98SSadaf Ebrahimi if (NULL != f_vrfy) {
3024*62c56f98SSadaf Ebrahimi if ((ret = f_vrfy(p_vrfy, cur->crt, (int) i-1, &cur_flags)) != 0) {
3025*62c56f98SSadaf Ebrahimi return ret;
3026*62c56f98SSadaf Ebrahimi }
3027*62c56f98SSadaf Ebrahimi }
3028*62c56f98SSadaf Ebrahimi
3029*62c56f98SSadaf Ebrahimi *flags |= cur_flags;
3030*62c56f98SSadaf Ebrahimi }
3031*62c56f98SSadaf Ebrahimi
3032*62c56f98SSadaf Ebrahimi return 0;
3033*62c56f98SSadaf Ebrahimi }
3034*62c56f98SSadaf Ebrahimi
3035*62c56f98SSadaf Ebrahimi /*
3036*62c56f98SSadaf Ebrahimi * Verify the certificate validity, with profile, restartable version
3037*62c56f98SSadaf Ebrahimi *
3038*62c56f98SSadaf Ebrahimi * This function:
3039*62c56f98SSadaf Ebrahimi * - checks the requested CN (if any)
3040*62c56f98SSadaf Ebrahimi * - checks the type and size of the EE cert's key,
3041*62c56f98SSadaf Ebrahimi * as that isn't done as part of chain building/verification currently
3042*62c56f98SSadaf Ebrahimi * - builds and verifies the chain
3043*62c56f98SSadaf Ebrahimi * - then calls the callback and merges the flags
3044*62c56f98SSadaf Ebrahimi *
3045*62c56f98SSadaf Ebrahimi * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb`
3046*62c56f98SSadaf Ebrahimi * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the
3047*62c56f98SSadaf Ebrahimi * verification routine to search for trusted signers, and CRLs will
3048*62c56f98SSadaf Ebrahimi * be disabled. Otherwise, `trust_ca` will be used as the static list
3049*62c56f98SSadaf Ebrahimi * of trusted signers, and `ca_crl` will be use as the static list
3050*62c56f98SSadaf Ebrahimi * of CRLs.
3051*62c56f98SSadaf Ebrahimi */
x509_crt_verify_restartable_ca_cb(mbedtls_x509_crt * crt,mbedtls_x509_crt * trust_ca,mbedtls_x509_crl * ca_crl,mbedtls_x509_crt_ca_cb_t f_ca_cb,void * p_ca_cb,const mbedtls_x509_crt_profile * profile,const char * cn,uint32_t * flags,int (* f_vrfy)(void *,mbedtls_x509_crt *,int,uint32_t *),void * p_vrfy,mbedtls_x509_crt_restart_ctx * rs_ctx)3052*62c56f98SSadaf Ebrahimi static int x509_crt_verify_restartable_ca_cb(mbedtls_x509_crt *crt,
3053*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *trust_ca,
3054*62c56f98SSadaf Ebrahimi mbedtls_x509_crl *ca_crl,
3055*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_ca_cb_t f_ca_cb,
3056*62c56f98SSadaf Ebrahimi void *p_ca_cb,
3057*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_profile *profile,
3058*62c56f98SSadaf Ebrahimi const char *cn, uint32_t *flags,
3059*62c56f98SSadaf Ebrahimi int (*f_vrfy)(void *,
3060*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *,
3061*62c56f98SSadaf Ebrahimi int,
3062*62c56f98SSadaf Ebrahimi uint32_t *),
3063*62c56f98SSadaf Ebrahimi void *p_vrfy,
3064*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_restart_ctx *rs_ctx)
3065*62c56f98SSadaf Ebrahimi {
3066*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3067*62c56f98SSadaf Ebrahimi mbedtls_pk_type_t pk_type;
3068*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_verify_chain ver_chain;
3069*62c56f98SSadaf Ebrahimi uint32_t ee_flags;
3070*62c56f98SSadaf Ebrahimi
3071*62c56f98SSadaf Ebrahimi *flags = 0;
3072*62c56f98SSadaf Ebrahimi ee_flags = 0;
3073*62c56f98SSadaf Ebrahimi x509_crt_verify_chain_reset(&ver_chain);
3074*62c56f98SSadaf Ebrahimi
3075*62c56f98SSadaf Ebrahimi if (profile == NULL) {
3076*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
3077*62c56f98SSadaf Ebrahimi goto exit;
3078*62c56f98SSadaf Ebrahimi }
3079*62c56f98SSadaf Ebrahimi
3080*62c56f98SSadaf Ebrahimi /* check name if requested */
3081*62c56f98SSadaf Ebrahimi if (cn != NULL) {
3082*62c56f98SSadaf Ebrahimi x509_crt_verify_name(crt, cn, &ee_flags);
3083*62c56f98SSadaf Ebrahimi }
3084*62c56f98SSadaf Ebrahimi
3085*62c56f98SSadaf Ebrahimi /* Check the type and size of the key */
3086*62c56f98SSadaf Ebrahimi pk_type = mbedtls_pk_get_type(&crt->pk);
3087*62c56f98SSadaf Ebrahimi
3088*62c56f98SSadaf Ebrahimi if (x509_profile_check_pk_alg(profile, pk_type) != 0) {
3089*62c56f98SSadaf Ebrahimi ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
3090*62c56f98SSadaf Ebrahimi }
3091*62c56f98SSadaf Ebrahimi
3092*62c56f98SSadaf Ebrahimi if (x509_profile_check_key(profile, &crt->pk) != 0) {
3093*62c56f98SSadaf Ebrahimi ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
3094*62c56f98SSadaf Ebrahimi }
3095*62c56f98SSadaf Ebrahimi
3096*62c56f98SSadaf Ebrahimi /* Check the chain */
3097*62c56f98SSadaf Ebrahimi ret = x509_crt_verify_chain(crt, trust_ca, ca_crl,
3098*62c56f98SSadaf Ebrahimi f_ca_cb, p_ca_cb, profile,
3099*62c56f98SSadaf Ebrahimi &ver_chain, rs_ctx);
3100*62c56f98SSadaf Ebrahimi
3101*62c56f98SSadaf Ebrahimi if (ret != 0) {
3102*62c56f98SSadaf Ebrahimi goto exit;
3103*62c56f98SSadaf Ebrahimi }
3104*62c56f98SSadaf Ebrahimi
3105*62c56f98SSadaf Ebrahimi /* Merge end-entity flags */
3106*62c56f98SSadaf Ebrahimi ver_chain.items[0].flags |= ee_flags;
3107*62c56f98SSadaf Ebrahimi
3108*62c56f98SSadaf Ebrahimi /* Build final flags, calling callback on the way if any */
3109*62c56f98SSadaf Ebrahimi ret = x509_crt_merge_flags_with_cb(flags, &ver_chain, f_vrfy, p_vrfy);
3110*62c56f98SSadaf Ebrahimi
3111*62c56f98SSadaf Ebrahimi exit:
3112*62c56f98SSadaf Ebrahimi
3113*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
3114*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_free(ver_chain.trust_ca_cb_result);
3115*62c56f98SSadaf Ebrahimi mbedtls_free(ver_chain.trust_ca_cb_result);
3116*62c56f98SSadaf Ebrahimi ver_chain.trust_ca_cb_result = NULL;
3117*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
3118*62c56f98SSadaf Ebrahimi
3119*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3120*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {
3121*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_restart_free(rs_ctx);
3122*62c56f98SSadaf Ebrahimi }
3123*62c56f98SSadaf Ebrahimi #endif
3124*62c56f98SSadaf Ebrahimi
3125*62c56f98SSadaf Ebrahimi /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
3126*62c56f98SSadaf Ebrahimi * the SSL module for authmode optional, but non-zero return from the
3127*62c56f98SSadaf Ebrahimi * callback means a fatal error so it shouldn't be ignored */
3128*62c56f98SSadaf Ebrahimi if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
3129*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_X509_FATAL_ERROR;
3130*62c56f98SSadaf Ebrahimi }
3131*62c56f98SSadaf Ebrahimi
3132*62c56f98SSadaf Ebrahimi if (ret != 0) {
3133*62c56f98SSadaf Ebrahimi *flags = (uint32_t) -1;
3134*62c56f98SSadaf Ebrahimi return ret;
3135*62c56f98SSadaf Ebrahimi }
3136*62c56f98SSadaf Ebrahimi
3137*62c56f98SSadaf Ebrahimi if (*flags != 0) {
3138*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
3139*62c56f98SSadaf Ebrahimi }
3140*62c56f98SSadaf Ebrahimi
3141*62c56f98SSadaf Ebrahimi return 0;
3142*62c56f98SSadaf Ebrahimi }
3143*62c56f98SSadaf Ebrahimi
3144*62c56f98SSadaf Ebrahimi
3145*62c56f98SSadaf Ebrahimi /*
3146*62c56f98SSadaf Ebrahimi * Verify the certificate validity (default profile, not restartable)
3147*62c56f98SSadaf Ebrahimi */
mbedtls_x509_crt_verify(mbedtls_x509_crt * crt,mbedtls_x509_crt * trust_ca,mbedtls_x509_crl * ca_crl,const char * cn,uint32_t * flags,int (* f_vrfy)(void *,mbedtls_x509_crt *,int,uint32_t *),void * p_vrfy)3148*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_verify(mbedtls_x509_crt *crt,
3149*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *trust_ca,
3150*62c56f98SSadaf Ebrahimi mbedtls_x509_crl *ca_crl,
3151*62c56f98SSadaf Ebrahimi const char *cn, uint32_t *flags,
3152*62c56f98SSadaf Ebrahimi int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3153*62c56f98SSadaf Ebrahimi void *p_vrfy)
3154*62c56f98SSadaf Ebrahimi {
3155*62c56f98SSadaf Ebrahimi return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl,
3156*62c56f98SSadaf Ebrahimi NULL, NULL,
3157*62c56f98SSadaf Ebrahimi &mbedtls_x509_crt_profile_default,
3158*62c56f98SSadaf Ebrahimi cn, flags,
3159*62c56f98SSadaf Ebrahimi f_vrfy, p_vrfy, NULL);
3160*62c56f98SSadaf Ebrahimi }
3161*62c56f98SSadaf Ebrahimi
3162*62c56f98SSadaf Ebrahimi /*
3163*62c56f98SSadaf Ebrahimi * Verify the certificate validity (user-chosen profile, not restartable)
3164*62c56f98SSadaf Ebrahimi */
mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt * crt,mbedtls_x509_crt * trust_ca,mbedtls_x509_crl * ca_crl,const mbedtls_x509_crt_profile * profile,const char * cn,uint32_t * flags,int (* f_vrfy)(void *,mbedtls_x509_crt *,int,uint32_t *),void * p_vrfy)3165*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt *crt,
3166*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *trust_ca,
3167*62c56f98SSadaf Ebrahimi mbedtls_x509_crl *ca_crl,
3168*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_profile *profile,
3169*62c56f98SSadaf Ebrahimi const char *cn, uint32_t *flags,
3170*62c56f98SSadaf Ebrahimi int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3171*62c56f98SSadaf Ebrahimi void *p_vrfy)
3172*62c56f98SSadaf Ebrahimi {
3173*62c56f98SSadaf Ebrahimi return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl,
3174*62c56f98SSadaf Ebrahimi NULL, NULL,
3175*62c56f98SSadaf Ebrahimi profile, cn, flags,
3176*62c56f98SSadaf Ebrahimi f_vrfy, p_vrfy, NULL);
3177*62c56f98SSadaf Ebrahimi }
3178*62c56f98SSadaf Ebrahimi
3179*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
3180*62c56f98SSadaf Ebrahimi /*
3181*62c56f98SSadaf Ebrahimi * Verify the certificate validity (user-chosen profile, CA callback,
3182*62c56f98SSadaf Ebrahimi * not restartable).
3183*62c56f98SSadaf Ebrahimi */
mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt * crt,mbedtls_x509_crt_ca_cb_t f_ca_cb,void * p_ca_cb,const mbedtls_x509_crt_profile * profile,const char * cn,uint32_t * flags,int (* f_vrfy)(void *,mbedtls_x509_crt *,int,uint32_t *),void * p_vrfy)3184*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt,
3185*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_ca_cb_t f_ca_cb,
3186*62c56f98SSadaf Ebrahimi void *p_ca_cb,
3187*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_profile *profile,
3188*62c56f98SSadaf Ebrahimi const char *cn, uint32_t *flags,
3189*62c56f98SSadaf Ebrahimi int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3190*62c56f98SSadaf Ebrahimi void *p_vrfy)
3191*62c56f98SSadaf Ebrahimi {
3192*62c56f98SSadaf Ebrahimi return x509_crt_verify_restartable_ca_cb(crt, NULL, NULL,
3193*62c56f98SSadaf Ebrahimi f_ca_cb, p_ca_cb,
3194*62c56f98SSadaf Ebrahimi profile, cn, flags,
3195*62c56f98SSadaf Ebrahimi f_vrfy, p_vrfy, NULL);
3196*62c56f98SSadaf Ebrahimi }
3197*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
3198*62c56f98SSadaf Ebrahimi
mbedtls_x509_crt_verify_restartable(mbedtls_x509_crt * crt,mbedtls_x509_crt * trust_ca,mbedtls_x509_crl * ca_crl,const mbedtls_x509_crt_profile * profile,const char * cn,uint32_t * flags,int (* f_vrfy)(void *,mbedtls_x509_crt *,int,uint32_t *),void * p_vrfy,mbedtls_x509_crt_restart_ctx * rs_ctx)3199*62c56f98SSadaf Ebrahimi int mbedtls_x509_crt_verify_restartable(mbedtls_x509_crt *crt,
3200*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *trust_ca,
3201*62c56f98SSadaf Ebrahimi mbedtls_x509_crl *ca_crl,
3202*62c56f98SSadaf Ebrahimi const mbedtls_x509_crt_profile *profile,
3203*62c56f98SSadaf Ebrahimi const char *cn, uint32_t *flags,
3204*62c56f98SSadaf Ebrahimi int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3205*62c56f98SSadaf Ebrahimi void *p_vrfy,
3206*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_restart_ctx *rs_ctx)
3207*62c56f98SSadaf Ebrahimi {
3208*62c56f98SSadaf Ebrahimi return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl,
3209*62c56f98SSadaf Ebrahimi NULL, NULL,
3210*62c56f98SSadaf Ebrahimi profile, cn, flags,
3211*62c56f98SSadaf Ebrahimi f_vrfy, p_vrfy, rs_ctx);
3212*62c56f98SSadaf Ebrahimi }
3213*62c56f98SSadaf Ebrahimi
3214*62c56f98SSadaf Ebrahimi
3215*62c56f98SSadaf Ebrahimi /*
3216*62c56f98SSadaf Ebrahimi * Initialize a certificate chain
3217*62c56f98SSadaf Ebrahimi */
mbedtls_x509_crt_init(mbedtls_x509_crt * crt)3218*62c56f98SSadaf Ebrahimi void mbedtls_x509_crt_init(mbedtls_x509_crt *crt)
3219*62c56f98SSadaf Ebrahimi {
3220*62c56f98SSadaf Ebrahimi memset(crt, 0, sizeof(mbedtls_x509_crt));
3221*62c56f98SSadaf Ebrahimi }
3222*62c56f98SSadaf Ebrahimi
3223*62c56f98SSadaf Ebrahimi /*
3224*62c56f98SSadaf Ebrahimi * Unallocate all certificate data
3225*62c56f98SSadaf Ebrahimi */
mbedtls_x509_crt_free(mbedtls_x509_crt * crt)3226*62c56f98SSadaf Ebrahimi void mbedtls_x509_crt_free(mbedtls_x509_crt *crt)
3227*62c56f98SSadaf Ebrahimi {
3228*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *cert_cur = crt;
3229*62c56f98SSadaf Ebrahimi mbedtls_x509_crt *cert_prv;
3230*62c56f98SSadaf Ebrahimi
3231*62c56f98SSadaf Ebrahimi while (cert_cur != NULL) {
3232*62c56f98SSadaf Ebrahimi mbedtls_pk_free(&cert_cur->pk);
3233*62c56f98SSadaf Ebrahimi
3234*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
3235*62c56f98SSadaf Ebrahimi mbedtls_free(cert_cur->sig_opts);
3236*62c56f98SSadaf Ebrahimi #endif
3237*62c56f98SSadaf Ebrahimi
3238*62c56f98SSadaf Ebrahimi mbedtls_asn1_free_named_data_list_shallow(cert_cur->issuer.next);
3239*62c56f98SSadaf Ebrahimi mbedtls_asn1_free_named_data_list_shallow(cert_cur->subject.next);
3240*62c56f98SSadaf Ebrahimi mbedtls_asn1_sequence_free(cert_cur->ext_key_usage.next);
3241*62c56f98SSadaf Ebrahimi mbedtls_asn1_sequence_free(cert_cur->subject_alt_names.next);
3242*62c56f98SSadaf Ebrahimi mbedtls_asn1_sequence_free(cert_cur->certificate_policies.next);
3243*62c56f98SSadaf Ebrahimi mbedtls_asn1_sequence_free(cert_cur->authority_key_id.authorityCertIssuer.next);
3244*62c56f98SSadaf Ebrahimi
3245*62c56f98SSadaf Ebrahimi if (cert_cur->raw.p != NULL && cert_cur->own_buffer) {
3246*62c56f98SSadaf Ebrahimi mbedtls_zeroize_and_free(cert_cur->raw.p, cert_cur->raw.len);
3247*62c56f98SSadaf Ebrahimi }
3248*62c56f98SSadaf Ebrahimi
3249*62c56f98SSadaf Ebrahimi cert_prv = cert_cur;
3250*62c56f98SSadaf Ebrahimi cert_cur = cert_cur->next;
3251*62c56f98SSadaf Ebrahimi
3252*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(cert_prv, sizeof(mbedtls_x509_crt));
3253*62c56f98SSadaf Ebrahimi if (cert_prv != crt) {
3254*62c56f98SSadaf Ebrahimi mbedtls_free(cert_prv);
3255*62c56f98SSadaf Ebrahimi }
3256*62c56f98SSadaf Ebrahimi }
3257*62c56f98SSadaf Ebrahimi }
3258*62c56f98SSadaf Ebrahimi
3259*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3260*62c56f98SSadaf Ebrahimi /*
3261*62c56f98SSadaf Ebrahimi * Initialize a restart context
3262*62c56f98SSadaf Ebrahimi */
mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx * ctx)3263*62c56f98SSadaf Ebrahimi void mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx *ctx)
3264*62c56f98SSadaf Ebrahimi {
3265*62c56f98SSadaf Ebrahimi mbedtls_pk_restart_init(&ctx->pk);
3266*62c56f98SSadaf Ebrahimi
3267*62c56f98SSadaf Ebrahimi ctx->parent = NULL;
3268*62c56f98SSadaf Ebrahimi ctx->fallback_parent = NULL;
3269*62c56f98SSadaf Ebrahimi ctx->fallback_signature_is_good = 0;
3270*62c56f98SSadaf Ebrahimi
3271*62c56f98SSadaf Ebrahimi ctx->parent_is_trusted = -1;
3272*62c56f98SSadaf Ebrahimi
3273*62c56f98SSadaf Ebrahimi ctx->in_progress = x509_crt_rs_none;
3274*62c56f98SSadaf Ebrahimi ctx->self_cnt = 0;
3275*62c56f98SSadaf Ebrahimi x509_crt_verify_chain_reset(&ctx->ver_chain);
3276*62c56f98SSadaf Ebrahimi }
3277*62c56f98SSadaf Ebrahimi
3278*62c56f98SSadaf Ebrahimi /*
3279*62c56f98SSadaf Ebrahimi * Free the components of a restart context
3280*62c56f98SSadaf Ebrahimi */
mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx * ctx)3281*62c56f98SSadaf Ebrahimi void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx)
3282*62c56f98SSadaf Ebrahimi {
3283*62c56f98SSadaf Ebrahimi if (ctx == NULL) {
3284*62c56f98SSadaf Ebrahimi return;
3285*62c56f98SSadaf Ebrahimi }
3286*62c56f98SSadaf Ebrahimi
3287*62c56f98SSadaf Ebrahimi mbedtls_pk_restart_free(&ctx->pk);
3288*62c56f98SSadaf Ebrahimi mbedtls_x509_crt_restart_init(ctx);
3289*62c56f98SSadaf Ebrahimi }
3290*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
3291*62c56f98SSadaf Ebrahimi
3292*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_X509_CRT_PARSE_C */
3293