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