1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  X.509 common functions for 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
18a8e1175bSopenharmony_ci#include "common.h"
19a8e1175bSopenharmony_ci
20a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_USE_C)
21a8e1175bSopenharmony_ci
22a8e1175bSopenharmony_ci#include "x509_internal.h"
23a8e1175bSopenharmony_ci#include "mbedtls/asn1.h"
24a8e1175bSopenharmony_ci#include "mbedtls/error.h"
25a8e1175bSopenharmony_ci#include "mbedtls/oid.h"
26a8e1175bSopenharmony_ci
27a8e1175bSopenharmony_ci#include <stdio.h>
28a8e1175bSopenharmony_ci#include <string.h>
29a8e1175bSopenharmony_ci
30a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C)
31a8e1175bSopenharmony_ci#include "mbedtls/pem.h"
32a8e1175bSopenharmony_ci#endif
33a8e1175bSopenharmony_ci
34a8e1175bSopenharmony_ci#include "mbedtls/asn1write.h"
35a8e1175bSopenharmony_ci
36a8e1175bSopenharmony_ci#include "mbedtls/platform.h"
37a8e1175bSopenharmony_ci
38a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME)
39a8e1175bSopenharmony_ci#include "mbedtls/platform_time.h"
40a8e1175bSopenharmony_ci#endif
41a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME_DATE)
42a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h"
43a8e1175bSopenharmony_ci#include <time.h>
44a8e1175bSopenharmony_ci#endif
45a8e1175bSopenharmony_ci
46a8e1175bSopenharmony_ci#define CHECK(code)                                     \
47a8e1175bSopenharmony_ci    do {                                                \
48a8e1175bSopenharmony_ci        if ((ret = (code)) != 0) {                      \
49a8e1175bSopenharmony_ci            return ret;                                 \
50a8e1175bSopenharmony_ci        }                                               \
51a8e1175bSopenharmony_ci    } while (0)
52a8e1175bSopenharmony_ci
53a8e1175bSopenharmony_ci#define CHECK_RANGE(min, max, val)                      \
54a8e1175bSopenharmony_ci    do {                                                \
55a8e1175bSopenharmony_ci        if ((val) < (min) || (val) > (max)) {           \
56a8e1175bSopenharmony_ci            return ret;                                 \
57a8e1175bSopenharmony_ci        }                                               \
58a8e1175bSopenharmony_ci    } while (0)
59a8e1175bSopenharmony_ci
60a8e1175bSopenharmony_ci/*
61a8e1175bSopenharmony_ci *  CertificateSerialNumber  ::=  INTEGER
62a8e1175bSopenharmony_ci */
63a8e1175bSopenharmony_ciint mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end,
64a8e1175bSopenharmony_ci                            mbedtls_x509_buf *serial)
65a8e1175bSopenharmony_ci{
66a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
67a8e1175bSopenharmony_ci
68a8e1175bSopenharmony_ci    if ((end - *p) < 1) {
69a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
70a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
71a8e1175bSopenharmony_ci    }
72a8e1175bSopenharmony_ci
73a8e1175bSopenharmony_ci    if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) &&
74a8e1175bSopenharmony_ci        **p !=   MBEDTLS_ASN1_INTEGER) {
75a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
76a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
77a8e1175bSopenharmony_ci    }
78a8e1175bSopenharmony_ci
79a8e1175bSopenharmony_ci    serial->tag = *(*p)++;
80a8e1175bSopenharmony_ci
81a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) {
82a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret);
83a8e1175bSopenharmony_ci    }
84a8e1175bSopenharmony_ci
85a8e1175bSopenharmony_ci    serial->p = *p;
86a8e1175bSopenharmony_ci    *p += serial->len;
87a8e1175bSopenharmony_ci
88a8e1175bSopenharmony_ci    return 0;
89a8e1175bSopenharmony_ci}
90a8e1175bSopenharmony_ci
91a8e1175bSopenharmony_ci/* Get an algorithm identifier without parameters (eg for signatures)
92a8e1175bSopenharmony_ci *
93a8e1175bSopenharmony_ci *  AlgorithmIdentifier  ::=  SEQUENCE  {
94a8e1175bSopenharmony_ci *       algorithm               OBJECT IDENTIFIER,
95a8e1175bSopenharmony_ci *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
96a8e1175bSopenharmony_ci */
97a8e1175bSopenharmony_ciint mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,
98a8e1175bSopenharmony_ci                              mbedtls_x509_buf *alg)
99a8e1175bSopenharmony_ci{
100a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101a8e1175bSopenharmony_ci
102a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
103a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
104a8e1175bSopenharmony_ci    }
105a8e1175bSopenharmony_ci
106a8e1175bSopenharmony_ci    return 0;
107a8e1175bSopenharmony_ci}
108a8e1175bSopenharmony_ci
109a8e1175bSopenharmony_ci/*
110a8e1175bSopenharmony_ci * Parse an algorithm identifier with (optional) parameters
111a8e1175bSopenharmony_ci */
112a8e1175bSopenharmony_ciint mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,
113a8e1175bSopenharmony_ci                         mbedtls_x509_buf *alg, mbedtls_x509_buf *params)
114a8e1175bSopenharmony_ci{
115a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
116a8e1175bSopenharmony_ci
117a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) {
118a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
119a8e1175bSopenharmony_ci    }
120a8e1175bSopenharmony_ci
121a8e1175bSopenharmony_ci    return 0;
122a8e1175bSopenharmony_ci}
123a8e1175bSopenharmony_ci
124a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
125a8e1175bSopenharmony_ci/*
126a8e1175bSopenharmony_ci * Convert md type to string
127a8e1175bSopenharmony_ci */
128a8e1175bSopenharmony_ci#if !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
129a8e1175bSopenharmony_ci
130a8e1175bSopenharmony_cistatic inline const char *md_type_to_string(mbedtls_md_type_t md_alg)
131a8e1175bSopenharmony_ci{
132a8e1175bSopenharmony_ci    switch (md_alg) {
133a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_MD5)
134a8e1175bSopenharmony_ci        case MBEDTLS_MD_MD5:
135a8e1175bSopenharmony_ci            return "MD5";
136a8e1175bSopenharmony_ci#endif
137a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA1)
138a8e1175bSopenharmony_ci        case MBEDTLS_MD_SHA1:
139a8e1175bSopenharmony_ci            return "SHA1";
140a8e1175bSopenharmony_ci#endif
141a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA224)
142a8e1175bSopenharmony_ci        case MBEDTLS_MD_SHA224:
143a8e1175bSopenharmony_ci            return "SHA224";
144a8e1175bSopenharmony_ci#endif
145a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA256)
146a8e1175bSopenharmony_ci        case MBEDTLS_MD_SHA256:
147a8e1175bSopenharmony_ci            return "SHA256";
148a8e1175bSopenharmony_ci#endif
149a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA384)
150a8e1175bSopenharmony_ci        case MBEDTLS_MD_SHA384:
151a8e1175bSopenharmony_ci            return "SHA384";
152a8e1175bSopenharmony_ci#endif
153a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA512)
154a8e1175bSopenharmony_ci        case MBEDTLS_MD_SHA512:
155a8e1175bSopenharmony_ci            return "SHA512";
156a8e1175bSopenharmony_ci#endif
157a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_RIPEMD160)
158a8e1175bSopenharmony_ci        case MBEDTLS_MD_RIPEMD160:
159a8e1175bSopenharmony_ci            return "RIPEMD160";
160a8e1175bSopenharmony_ci#endif
161a8e1175bSopenharmony_ci        case MBEDTLS_MD_NONE:
162a8e1175bSopenharmony_ci            return NULL;
163a8e1175bSopenharmony_ci        default:
164a8e1175bSopenharmony_ci            return NULL;
165a8e1175bSopenharmony_ci    }
166a8e1175bSopenharmony_ci}
167a8e1175bSopenharmony_ci
168a8e1175bSopenharmony_ci#endif /* !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) */
169a8e1175bSopenharmony_ci/*
170a8e1175bSopenharmony_ci * HashAlgorithm ::= AlgorithmIdentifier
171a8e1175bSopenharmony_ci *
172a8e1175bSopenharmony_ci * AlgorithmIdentifier  ::=  SEQUENCE  {
173a8e1175bSopenharmony_ci *      algorithm               OBJECT IDENTIFIER,
174a8e1175bSopenharmony_ci *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
175a8e1175bSopenharmony_ci *
176a8e1175bSopenharmony_ci * For HashAlgorithm, parameters MUST be NULL or absent.
177a8e1175bSopenharmony_ci */
178a8e1175bSopenharmony_cistatic int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg)
179a8e1175bSopenharmony_ci{
180a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
181a8e1175bSopenharmony_ci    unsigned char *p;
182a8e1175bSopenharmony_ci    const unsigned char *end;
183a8e1175bSopenharmony_ci    mbedtls_x509_buf md_oid;
184a8e1175bSopenharmony_ci    size_t len;
185a8e1175bSopenharmony_ci
186a8e1175bSopenharmony_ci    /* Make sure we got a SEQUENCE and setup bounds */
187a8e1175bSopenharmony_ci    if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
188a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
189a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
190a8e1175bSopenharmony_ci    }
191a8e1175bSopenharmony_ci
192a8e1175bSopenharmony_ci    p = alg->p;
193a8e1175bSopenharmony_ci    end = p + alg->len;
194a8e1175bSopenharmony_ci
195a8e1175bSopenharmony_ci    if (p >= end) {
196a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
197a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
198a8e1175bSopenharmony_ci    }
199a8e1175bSopenharmony_ci
200a8e1175bSopenharmony_ci    /* Parse md_oid */
201a8e1175bSopenharmony_ci    md_oid.tag = *p;
202a8e1175bSopenharmony_ci
203a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) {
204a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
205a8e1175bSopenharmony_ci    }
206a8e1175bSopenharmony_ci
207a8e1175bSopenharmony_ci    md_oid.p = p;
208a8e1175bSopenharmony_ci    p += md_oid.len;
209a8e1175bSopenharmony_ci
210a8e1175bSopenharmony_ci    /* Get md_alg from md_oid */
211a8e1175bSopenharmony_ci    if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) {
212a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
213a8e1175bSopenharmony_ci    }
214a8e1175bSopenharmony_ci
215a8e1175bSopenharmony_ci    /* Make sure params is absent of NULL */
216a8e1175bSopenharmony_ci    if (p == end) {
217a8e1175bSopenharmony_ci        return 0;
218a8e1175bSopenharmony_ci    }
219a8e1175bSopenharmony_ci
220a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) {
221a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
222a8e1175bSopenharmony_ci    }
223a8e1175bSopenharmony_ci
224a8e1175bSopenharmony_ci    if (p != end) {
225a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
226a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
227a8e1175bSopenharmony_ci    }
228a8e1175bSopenharmony_ci
229a8e1175bSopenharmony_ci    return 0;
230a8e1175bSopenharmony_ci}
231a8e1175bSopenharmony_ci
232a8e1175bSopenharmony_ci/*
233a8e1175bSopenharmony_ci *    RSASSA-PSS-params  ::=  SEQUENCE  {
234a8e1175bSopenharmony_ci *       hashAlgorithm     [0] HashAlgorithm DEFAULT sha1Identifier,
235a8e1175bSopenharmony_ci *       maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
236a8e1175bSopenharmony_ci *       saltLength        [2] INTEGER DEFAULT 20,
237a8e1175bSopenharmony_ci *       trailerField      [3] INTEGER DEFAULT 1  }
238a8e1175bSopenharmony_ci *    -- Note that the tags in this Sequence are explicit.
239a8e1175bSopenharmony_ci *
240a8e1175bSopenharmony_ci * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
241a8e1175bSopenharmony_ci * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
242a8e1175bSopenharmony_ci * option. Enforce this at parsing time.
243a8e1175bSopenharmony_ci */
244a8e1175bSopenharmony_ciint mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params,
245a8e1175bSopenharmony_ci                                       mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
246a8e1175bSopenharmony_ci                                       int *salt_len)
247a8e1175bSopenharmony_ci{
248a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
249a8e1175bSopenharmony_ci    unsigned char *p;
250a8e1175bSopenharmony_ci    const unsigned char *end, *end2;
251a8e1175bSopenharmony_ci    size_t len;
252a8e1175bSopenharmony_ci    mbedtls_x509_buf alg_id, alg_params;
253a8e1175bSopenharmony_ci
254a8e1175bSopenharmony_ci    /* First set everything to defaults */
255a8e1175bSopenharmony_ci    *md_alg = MBEDTLS_MD_SHA1;
256a8e1175bSopenharmony_ci    *mgf_md = MBEDTLS_MD_SHA1;
257a8e1175bSopenharmony_ci    *salt_len = 20;
258a8e1175bSopenharmony_ci
259a8e1175bSopenharmony_ci    /* Make sure params is a SEQUENCE and setup bounds */
260a8e1175bSopenharmony_ci    if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
261a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
262a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
263a8e1175bSopenharmony_ci    }
264a8e1175bSopenharmony_ci
265a8e1175bSopenharmony_ci    p = (unsigned char *) params->p;
266a8e1175bSopenharmony_ci    end = p + params->len;
267a8e1175bSopenharmony_ci
268a8e1175bSopenharmony_ci    if (p == end) {
269a8e1175bSopenharmony_ci        return 0;
270a8e1175bSopenharmony_ci    }
271a8e1175bSopenharmony_ci
272a8e1175bSopenharmony_ci    /*
273a8e1175bSopenharmony_ci     * HashAlgorithm
274a8e1175bSopenharmony_ci     */
275a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
276a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
277a8e1175bSopenharmony_ci                                    0)) == 0) {
278a8e1175bSopenharmony_ci        end2 = p + len;
279a8e1175bSopenharmony_ci
280a8e1175bSopenharmony_ci        /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
281a8e1175bSopenharmony_ci        if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) {
282a8e1175bSopenharmony_ci            return ret;
283a8e1175bSopenharmony_ci        }
284a8e1175bSopenharmony_ci
285a8e1175bSopenharmony_ci        if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) {
286a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
287a8e1175bSopenharmony_ci        }
288a8e1175bSopenharmony_ci
289a8e1175bSopenharmony_ci        if (p != end2) {
290a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
291a8e1175bSopenharmony_ci                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
292a8e1175bSopenharmony_ci        }
293a8e1175bSopenharmony_ci    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
294a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
295a8e1175bSopenharmony_ci    }
296a8e1175bSopenharmony_ci
297a8e1175bSopenharmony_ci    if (p == end) {
298a8e1175bSopenharmony_ci        return 0;
299a8e1175bSopenharmony_ci    }
300a8e1175bSopenharmony_ci
301a8e1175bSopenharmony_ci    /*
302a8e1175bSopenharmony_ci     * MaskGenAlgorithm
303a8e1175bSopenharmony_ci     */
304a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
305a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
306a8e1175bSopenharmony_ci                                    1)) == 0) {
307a8e1175bSopenharmony_ci        end2 = p + len;
308a8e1175bSopenharmony_ci
309a8e1175bSopenharmony_ci        /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
310a8e1175bSopenharmony_ci        if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) {
311a8e1175bSopenharmony_ci            return ret;
312a8e1175bSopenharmony_ci        }
313a8e1175bSopenharmony_ci
314a8e1175bSopenharmony_ci        /* Only MFG1 is recognised for now */
315a8e1175bSopenharmony_ci        if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) {
316a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE,
317a8e1175bSopenharmony_ci                                     MBEDTLS_ERR_OID_NOT_FOUND);
318a8e1175bSopenharmony_ci        }
319a8e1175bSopenharmony_ci
320a8e1175bSopenharmony_ci        /* Parse HashAlgorithm */
321a8e1175bSopenharmony_ci        if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) {
322a8e1175bSopenharmony_ci            return ret;
323a8e1175bSopenharmony_ci        }
324a8e1175bSopenharmony_ci
325a8e1175bSopenharmony_ci        if (p != end2) {
326a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
327a8e1175bSopenharmony_ci                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
328a8e1175bSopenharmony_ci        }
329a8e1175bSopenharmony_ci    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
330a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
331a8e1175bSopenharmony_ci    }
332a8e1175bSopenharmony_ci
333a8e1175bSopenharmony_ci    if (p == end) {
334a8e1175bSopenharmony_ci        return 0;
335a8e1175bSopenharmony_ci    }
336a8e1175bSopenharmony_ci
337a8e1175bSopenharmony_ci    /*
338a8e1175bSopenharmony_ci     * salt_len
339a8e1175bSopenharmony_ci     */
340a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
341a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
342a8e1175bSopenharmony_ci                                    2)) == 0) {
343a8e1175bSopenharmony_ci        end2 = p + len;
344a8e1175bSopenharmony_ci
345a8e1175bSopenharmony_ci        if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) {
346a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
347a8e1175bSopenharmony_ci        }
348a8e1175bSopenharmony_ci
349a8e1175bSopenharmony_ci        if (p != end2) {
350a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
351a8e1175bSopenharmony_ci                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
352a8e1175bSopenharmony_ci        }
353a8e1175bSopenharmony_ci    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
354a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
355a8e1175bSopenharmony_ci    }
356a8e1175bSopenharmony_ci
357a8e1175bSopenharmony_ci    if (p == end) {
358a8e1175bSopenharmony_ci        return 0;
359a8e1175bSopenharmony_ci    }
360a8e1175bSopenharmony_ci
361a8e1175bSopenharmony_ci    /*
362a8e1175bSopenharmony_ci     * trailer_field (if present, must be 1)
363a8e1175bSopenharmony_ci     */
364a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
365a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
366a8e1175bSopenharmony_ci                                    3)) == 0) {
367a8e1175bSopenharmony_ci        int trailer_field;
368a8e1175bSopenharmony_ci
369a8e1175bSopenharmony_ci        end2 = p + len;
370a8e1175bSopenharmony_ci
371a8e1175bSopenharmony_ci        if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) {
372a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
373a8e1175bSopenharmony_ci        }
374a8e1175bSopenharmony_ci
375a8e1175bSopenharmony_ci        if (p != end2) {
376a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
377a8e1175bSopenharmony_ci                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
378a8e1175bSopenharmony_ci        }
379a8e1175bSopenharmony_ci
380a8e1175bSopenharmony_ci        if (trailer_field != 1) {
381a8e1175bSopenharmony_ci            return MBEDTLS_ERR_X509_INVALID_ALG;
382a8e1175bSopenharmony_ci        }
383a8e1175bSopenharmony_ci    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
384a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
385a8e1175bSopenharmony_ci    }
386a8e1175bSopenharmony_ci
387a8e1175bSopenharmony_ci    if (p != end) {
388a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
389a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
390a8e1175bSopenharmony_ci    }
391a8e1175bSopenharmony_ci
392a8e1175bSopenharmony_ci    return 0;
393a8e1175bSopenharmony_ci}
394a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
395a8e1175bSopenharmony_ci
396a8e1175bSopenharmony_ci/*
397a8e1175bSopenharmony_ci *  AttributeTypeAndValue ::= SEQUENCE {
398a8e1175bSopenharmony_ci *    type     AttributeType,
399a8e1175bSopenharmony_ci *    value    AttributeValue }
400a8e1175bSopenharmony_ci *
401a8e1175bSopenharmony_ci *  AttributeType ::= OBJECT IDENTIFIER
402a8e1175bSopenharmony_ci *
403a8e1175bSopenharmony_ci *  AttributeValue ::= ANY DEFINED BY AttributeType
404a8e1175bSopenharmony_ci */
405a8e1175bSopenharmony_cistatic int x509_get_attr_type_value(unsigned char **p,
406a8e1175bSopenharmony_ci                                    const unsigned char *end,
407a8e1175bSopenharmony_ci                                    mbedtls_x509_name *cur)
408a8e1175bSopenharmony_ci{
409a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
410a8e1175bSopenharmony_ci    size_t len;
411a8e1175bSopenharmony_ci    mbedtls_x509_buf *oid;
412a8e1175bSopenharmony_ci    mbedtls_x509_buf *val;
413a8e1175bSopenharmony_ci
414a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
415a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
416a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
417a8e1175bSopenharmony_ci    }
418a8e1175bSopenharmony_ci
419a8e1175bSopenharmony_ci    end = *p + len;
420a8e1175bSopenharmony_ci
421a8e1175bSopenharmony_ci    if ((end - *p) < 1) {
422a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
423a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
424a8e1175bSopenharmony_ci    }
425a8e1175bSopenharmony_ci
426a8e1175bSopenharmony_ci    oid = &cur->oid;
427a8e1175bSopenharmony_ci    oid->tag = **p;
428a8e1175bSopenharmony_ci
429a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) {
430a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
431a8e1175bSopenharmony_ci    }
432a8e1175bSopenharmony_ci
433a8e1175bSopenharmony_ci    oid->p = *p;
434a8e1175bSopenharmony_ci    *p += oid->len;
435a8e1175bSopenharmony_ci
436a8e1175bSopenharmony_ci    if ((end - *p) < 1) {
437a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
438a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
439a8e1175bSopenharmony_ci    }
440a8e1175bSopenharmony_ci
441a8e1175bSopenharmony_ci    if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING      &&
442a8e1175bSopenharmony_ci        **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
443a8e1175bSopenharmony_ci        **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
444a8e1175bSopenharmony_ci        **p != MBEDTLS_ASN1_BIT_STRING) {
445a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
446a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
447a8e1175bSopenharmony_ci    }
448a8e1175bSopenharmony_ci
449a8e1175bSopenharmony_ci    val = &cur->val;
450a8e1175bSopenharmony_ci    val->tag = *(*p)++;
451a8e1175bSopenharmony_ci
452a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) {
453a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
454a8e1175bSopenharmony_ci    }
455a8e1175bSopenharmony_ci
456a8e1175bSopenharmony_ci    val->p = *p;
457a8e1175bSopenharmony_ci    *p += val->len;
458a8e1175bSopenharmony_ci
459a8e1175bSopenharmony_ci    if (*p != end) {
460a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
461a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
462a8e1175bSopenharmony_ci    }
463a8e1175bSopenharmony_ci
464a8e1175bSopenharmony_ci    cur->next = NULL;
465a8e1175bSopenharmony_ci
466a8e1175bSopenharmony_ci    return 0;
467a8e1175bSopenharmony_ci}
468a8e1175bSopenharmony_ci
469a8e1175bSopenharmony_ci/*
470a8e1175bSopenharmony_ci *  Name ::= CHOICE { -- only one possibility for now --
471a8e1175bSopenharmony_ci *       rdnSequence  RDNSequence }
472a8e1175bSopenharmony_ci *
473a8e1175bSopenharmony_ci *  RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
474a8e1175bSopenharmony_ci *
475a8e1175bSopenharmony_ci *  RelativeDistinguishedName ::=
476a8e1175bSopenharmony_ci *    SET OF AttributeTypeAndValue
477a8e1175bSopenharmony_ci *
478a8e1175bSopenharmony_ci *  AttributeTypeAndValue ::= SEQUENCE {
479a8e1175bSopenharmony_ci *    type     AttributeType,
480a8e1175bSopenharmony_ci *    value    AttributeValue }
481a8e1175bSopenharmony_ci *
482a8e1175bSopenharmony_ci *  AttributeType ::= OBJECT IDENTIFIER
483a8e1175bSopenharmony_ci *
484a8e1175bSopenharmony_ci *  AttributeValue ::= ANY DEFINED BY AttributeType
485a8e1175bSopenharmony_ci *
486a8e1175bSopenharmony_ci * The data structure is optimized for the common case where each RDN has only
487a8e1175bSopenharmony_ci * one element, which is represented as a list of AttributeTypeAndValue.
488a8e1175bSopenharmony_ci * For the general case we still use a flat list, but we mark elements of the
489a8e1175bSopenharmony_ci * same set so that they are "merged" together in the functions that consume
490a8e1175bSopenharmony_ci * this list, eg mbedtls_x509_dn_gets().
491a8e1175bSopenharmony_ci *
492a8e1175bSopenharmony_ci * On success, this function may allocate a linked list starting at cur->next
493a8e1175bSopenharmony_ci * that must later be free'd by the caller using mbedtls_free(). In error
494a8e1175bSopenharmony_ci * cases, this function frees all allocated memory internally and the caller
495a8e1175bSopenharmony_ci * has no freeing responsibilities.
496a8e1175bSopenharmony_ci */
497a8e1175bSopenharmony_ciint mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
498a8e1175bSopenharmony_ci                          mbedtls_x509_name *cur)
499a8e1175bSopenharmony_ci{
500a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
501a8e1175bSopenharmony_ci    size_t set_len;
502a8e1175bSopenharmony_ci    const unsigned char *end_set;
503a8e1175bSopenharmony_ci    mbedtls_x509_name *head = cur;
504a8e1175bSopenharmony_ci
505a8e1175bSopenharmony_ci    /* don't use recursion, we'd risk stack overflow if not optimized */
506a8e1175bSopenharmony_ci    while (1) {
507a8e1175bSopenharmony_ci        /*
508a8e1175bSopenharmony_ci         * parse SET
509a8e1175bSopenharmony_ci         */
510a8e1175bSopenharmony_ci        if ((ret = mbedtls_asn1_get_tag(p, end, &set_len,
511a8e1175bSopenharmony_ci                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
512a8e1175bSopenharmony_ci            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
513a8e1175bSopenharmony_ci            goto error;
514a8e1175bSopenharmony_ci        }
515a8e1175bSopenharmony_ci
516a8e1175bSopenharmony_ci        end_set  = *p + set_len;
517a8e1175bSopenharmony_ci
518a8e1175bSopenharmony_ci        while (1) {
519a8e1175bSopenharmony_ci            if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) {
520a8e1175bSopenharmony_ci                goto error;
521a8e1175bSopenharmony_ci            }
522a8e1175bSopenharmony_ci
523a8e1175bSopenharmony_ci            if (*p == end_set) {
524a8e1175bSopenharmony_ci                break;
525a8e1175bSopenharmony_ci            }
526a8e1175bSopenharmony_ci
527a8e1175bSopenharmony_ci            /* Mark this item as being no the only one in a set */
528a8e1175bSopenharmony_ci            cur->next_merged = 1;
529a8e1175bSopenharmony_ci
530a8e1175bSopenharmony_ci            cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
531a8e1175bSopenharmony_ci
532a8e1175bSopenharmony_ci            if (cur->next == NULL) {
533a8e1175bSopenharmony_ci                ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
534a8e1175bSopenharmony_ci                goto error;
535a8e1175bSopenharmony_ci            }
536a8e1175bSopenharmony_ci
537a8e1175bSopenharmony_ci            cur = cur->next;
538a8e1175bSopenharmony_ci        }
539a8e1175bSopenharmony_ci
540a8e1175bSopenharmony_ci        /*
541a8e1175bSopenharmony_ci         * continue until end of SEQUENCE is reached
542a8e1175bSopenharmony_ci         */
543a8e1175bSopenharmony_ci        if (*p == end) {
544a8e1175bSopenharmony_ci            return 0;
545a8e1175bSopenharmony_ci        }
546a8e1175bSopenharmony_ci
547a8e1175bSopenharmony_ci        cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
548a8e1175bSopenharmony_ci
549a8e1175bSopenharmony_ci        if (cur->next == NULL) {
550a8e1175bSopenharmony_ci            ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
551a8e1175bSopenharmony_ci            goto error;
552a8e1175bSopenharmony_ci        }
553a8e1175bSopenharmony_ci
554a8e1175bSopenharmony_ci        cur = cur->next;
555a8e1175bSopenharmony_ci    }
556a8e1175bSopenharmony_ci
557a8e1175bSopenharmony_cierror:
558a8e1175bSopenharmony_ci    /* Skip the first element as we did not allocate it */
559a8e1175bSopenharmony_ci    mbedtls_asn1_free_named_data_list_shallow(head->next);
560a8e1175bSopenharmony_ci    head->next = NULL;
561a8e1175bSopenharmony_ci
562a8e1175bSopenharmony_ci    return ret;
563a8e1175bSopenharmony_ci}
564a8e1175bSopenharmony_ci
565a8e1175bSopenharmony_cistatic int x509_date_is_valid(const mbedtls_x509_time *t)
566a8e1175bSopenharmony_ci{
567a8e1175bSopenharmony_ci    unsigned int month_days;
568a8e1175bSopenharmony_ci    unsigned int year;
569a8e1175bSopenharmony_ci    switch (t->mon) {
570a8e1175bSopenharmony_ci        case 1: case 3: case 5: case 7: case 8: case 10: case 12:
571a8e1175bSopenharmony_ci            month_days = 31;
572a8e1175bSopenharmony_ci            break;
573a8e1175bSopenharmony_ci        case 4: case 6: case 9: case 11:
574a8e1175bSopenharmony_ci            month_days = 30;
575a8e1175bSopenharmony_ci            break;
576a8e1175bSopenharmony_ci        case 2:
577a8e1175bSopenharmony_ci            year = (unsigned int) t->year;
578a8e1175bSopenharmony_ci            month_days = ((year & 3) || (!(year % 100)
579a8e1175bSopenharmony_ci                                         && (year % 400)))
580a8e1175bSopenharmony_ci                          ? 28 : 29;
581a8e1175bSopenharmony_ci            break;
582a8e1175bSopenharmony_ci        default:
583a8e1175bSopenharmony_ci            return MBEDTLS_ERR_X509_INVALID_DATE;
584a8e1175bSopenharmony_ci    }
585a8e1175bSopenharmony_ci
586a8e1175bSopenharmony_ci    if ((unsigned int) (t->day - 1) >= month_days ||      /* (1 - days in month) */
587a8e1175bSopenharmony_ci        /* (unsigned int) (t->mon - 1) >= 12 || */  /* (1 - 12) checked above */
588a8e1175bSopenharmony_ci        (unsigned int) t->year > 9999 ||         /* (0 - 9999) */
589a8e1175bSopenharmony_ci        (unsigned int) t->hour > 23 ||           /* (0 - 23) */
590a8e1175bSopenharmony_ci        (unsigned int) t->min  > 59 ||           /* (0 - 59) */
591a8e1175bSopenharmony_ci        (unsigned int) t->sec  > 59) {           /* (0 - 59) */
592a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_INVALID_DATE;
593a8e1175bSopenharmony_ci    }
594a8e1175bSopenharmony_ci
595a8e1175bSopenharmony_ci    return 0;
596a8e1175bSopenharmony_ci}
597a8e1175bSopenharmony_ci
598a8e1175bSopenharmony_cistatic int x509_parse2_int(const unsigned char *p)
599a8e1175bSopenharmony_ci{
600a8e1175bSopenharmony_ci    uint32_t d1 = p[0] - '0';
601a8e1175bSopenharmony_ci    uint32_t d2 = p[1] - '0';
602a8e1175bSopenharmony_ci    return (d1 < 10 && d2 < 10) ? (int) (d1 * 10 + d2) : -1;
603a8e1175bSopenharmony_ci}
604a8e1175bSopenharmony_ci
605a8e1175bSopenharmony_ci/*
606a8e1175bSopenharmony_ci * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
607a8e1175bSopenharmony_ci * field.
608a8e1175bSopenharmony_ci */
609a8e1175bSopenharmony_cistatic int x509_parse_time(const unsigned char *p, mbedtls_x509_time *tm,
610a8e1175bSopenharmony_ci                           size_t yearlen)
611a8e1175bSopenharmony_ci{
612a8e1175bSopenharmony_ci    int x;
613a8e1175bSopenharmony_ci
614a8e1175bSopenharmony_ci    /*
615a8e1175bSopenharmony_ci     * Parse year, month, day, hour, minute, second
616a8e1175bSopenharmony_ci     */
617a8e1175bSopenharmony_ci    tm->year = x509_parse2_int(p);
618a8e1175bSopenharmony_ci    if (tm->year < 0) {
619a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_INVALID_DATE;
620a8e1175bSopenharmony_ci    }
621a8e1175bSopenharmony_ci
622a8e1175bSopenharmony_ci    if (4 == yearlen) {
623a8e1175bSopenharmony_ci        x = tm->year * 100;
624a8e1175bSopenharmony_ci        p += 2;
625a8e1175bSopenharmony_ci        tm->year = x509_parse2_int(p);
626a8e1175bSopenharmony_ci        if (tm->year < 0) {
627a8e1175bSopenharmony_ci            return MBEDTLS_ERR_X509_INVALID_DATE;
628a8e1175bSopenharmony_ci        }
629a8e1175bSopenharmony_ci    } else {
630a8e1175bSopenharmony_ci        x = (tm->year < 50) ? 2000 : 1900;
631a8e1175bSopenharmony_ci    }
632a8e1175bSopenharmony_ci    tm->year += x;
633a8e1175bSopenharmony_ci
634a8e1175bSopenharmony_ci    tm->mon  = x509_parse2_int(p + 2);
635a8e1175bSopenharmony_ci    tm->day  = x509_parse2_int(p + 4);
636a8e1175bSopenharmony_ci    tm->hour = x509_parse2_int(p + 6);
637a8e1175bSopenharmony_ci    tm->min  = x509_parse2_int(p + 8);
638a8e1175bSopenharmony_ci    tm->sec  = x509_parse2_int(p + 10);
639a8e1175bSopenharmony_ci
640a8e1175bSopenharmony_ci    return x509_date_is_valid(tm);
641a8e1175bSopenharmony_ci}
642a8e1175bSopenharmony_ci
643a8e1175bSopenharmony_ci/*
644a8e1175bSopenharmony_ci *  Time ::= CHOICE {
645a8e1175bSopenharmony_ci *       utcTime        UTCTime,
646a8e1175bSopenharmony_ci *       generalTime    GeneralizedTime }
647a8e1175bSopenharmony_ci */
648a8e1175bSopenharmony_ciint mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,
649a8e1175bSopenharmony_ci                          mbedtls_x509_time *tm)
650a8e1175bSopenharmony_ci{
651a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
652a8e1175bSopenharmony_ci    size_t len, year_len;
653a8e1175bSopenharmony_ci    unsigned char tag;
654a8e1175bSopenharmony_ci
655a8e1175bSopenharmony_ci    if ((end - *p) < 1) {
656a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
657a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
658a8e1175bSopenharmony_ci    }
659a8e1175bSopenharmony_ci
660a8e1175bSopenharmony_ci    tag = **p;
661a8e1175bSopenharmony_ci
662a8e1175bSopenharmony_ci    if (tag == MBEDTLS_ASN1_UTC_TIME) {
663a8e1175bSopenharmony_ci        year_len = 2;
664a8e1175bSopenharmony_ci    } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) {
665a8e1175bSopenharmony_ci        year_len = 4;
666a8e1175bSopenharmony_ci    } else {
667a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
668a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
669a8e1175bSopenharmony_ci    }
670a8e1175bSopenharmony_ci
671a8e1175bSopenharmony_ci    (*p)++;
672a8e1175bSopenharmony_ci    ret = mbedtls_asn1_get_len(p, end, &len);
673a8e1175bSopenharmony_ci
674a8e1175bSopenharmony_ci    if (ret != 0) {
675a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret);
676a8e1175bSopenharmony_ci    }
677a8e1175bSopenharmony_ci
678a8e1175bSopenharmony_ci    /* len is 12 or 14 depending on year_len, plus optional trailing 'Z' */
679a8e1175bSopenharmony_ci    if (len != year_len + 10 &&
680a8e1175bSopenharmony_ci        !(len == year_len + 11 && (*p)[(len - 1)] == 'Z')) {
681a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_INVALID_DATE;
682a8e1175bSopenharmony_ci    }
683a8e1175bSopenharmony_ci
684a8e1175bSopenharmony_ci    (*p) += len;
685a8e1175bSopenharmony_ci    return x509_parse_time(*p - len, tm, year_len);
686a8e1175bSopenharmony_ci}
687a8e1175bSopenharmony_ci
688a8e1175bSopenharmony_ciint mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig)
689a8e1175bSopenharmony_ci{
690a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
691a8e1175bSopenharmony_ci    size_t len;
692a8e1175bSopenharmony_ci    int tag_type;
693a8e1175bSopenharmony_ci
694a8e1175bSopenharmony_ci    if ((end - *p) < 1) {
695a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE,
696a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
697a8e1175bSopenharmony_ci    }
698a8e1175bSopenharmony_ci
699a8e1175bSopenharmony_ci    tag_type = **p;
700a8e1175bSopenharmony_ci
701a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
702a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret);
703a8e1175bSopenharmony_ci    }
704a8e1175bSopenharmony_ci
705a8e1175bSopenharmony_ci    sig->tag = tag_type;
706a8e1175bSopenharmony_ci    sig->len = len;
707a8e1175bSopenharmony_ci    sig->p = *p;
708a8e1175bSopenharmony_ci
709a8e1175bSopenharmony_ci    *p += len;
710a8e1175bSopenharmony_ci
711a8e1175bSopenharmony_ci    return 0;
712a8e1175bSopenharmony_ci}
713a8e1175bSopenharmony_ci
714a8e1175bSopenharmony_ci/*
715a8e1175bSopenharmony_ci * Get signature algorithm from alg OID and optional parameters
716a8e1175bSopenharmony_ci */
717a8e1175bSopenharmony_ciint mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
718a8e1175bSopenharmony_ci                             mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
719a8e1175bSopenharmony_ci                             void **sig_opts)
720a8e1175bSopenharmony_ci{
721a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
722a8e1175bSopenharmony_ci
723a8e1175bSopenharmony_ci    if (*sig_opts != NULL) {
724a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
725a8e1175bSopenharmony_ci    }
726a8e1175bSopenharmony_ci
727a8e1175bSopenharmony_ci    if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) {
728a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret);
729a8e1175bSopenharmony_ci    }
730a8e1175bSopenharmony_ci
731a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
732a8e1175bSopenharmony_ci    if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) {
733a8e1175bSopenharmony_ci        mbedtls_pk_rsassa_pss_options *pss_opts;
734a8e1175bSopenharmony_ci
735a8e1175bSopenharmony_ci        pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options));
736a8e1175bSopenharmony_ci        if (pss_opts == NULL) {
737a8e1175bSopenharmony_ci            return MBEDTLS_ERR_X509_ALLOC_FAILED;
738a8e1175bSopenharmony_ci        }
739a8e1175bSopenharmony_ci
740a8e1175bSopenharmony_ci        ret = mbedtls_x509_get_rsassa_pss_params(sig_params,
741a8e1175bSopenharmony_ci                                                 md_alg,
742a8e1175bSopenharmony_ci                                                 &pss_opts->mgf1_hash_id,
743a8e1175bSopenharmony_ci                                                 &pss_opts->expected_salt_len);
744a8e1175bSopenharmony_ci        if (ret != 0) {
745a8e1175bSopenharmony_ci            mbedtls_free(pss_opts);
746a8e1175bSopenharmony_ci            return ret;
747a8e1175bSopenharmony_ci        }
748a8e1175bSopenharmony_ci
749a8e1175bSopenharmony_ci        *sig_opts = (void *) pss_opts;
750a8e1175bSopenharmony_ci    } else
751a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
752a8e1175bSopenharmony_ci    {
753a8e1175bSopenharmony_ci        /* Make sure parameters are absent or NULL */
754a8e1175bSopenharmony_ci        if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) ||
755a8e1175bSopenharmony_ci            sig_params->len != 0) {
756a8e1175bSopenharmony_ci            return MBEDTLS_ERR_X509_INVALID_ALG;
757a8e1175bSopenharmony_ci        }
758a8e1175bSopenharmony_ci    }
759a8e1175bSopenharmony_ci
760a8e1175bSopenharmony_ci    return 0;
761a8e1175bSopenharmony_ci}
762a8e1175bSopenharmony_ci
763a8e1175bSopenharmony_ci/*
764a8e1175bSopenharmony_ci * X.509 Extensions (No parsing of extensions, pointer should
765a8e1175bSopenharmony_ci * be either manually updated or extensions should be parsed!)
766a8e1175bSopenharmony_ci */
767a8e1175bSopenharmony_ciint mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,
768a8e1175bSopenharmony_ci                         mbedtls_x509_buf *ext, int tag)
769a8e1175bSopenharmony_ci{
770a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
771a8e1175bSopenharmony_ci    size_t len;
772a8e1175bSopenharmony_ci
773a8e1175bSopenharmony_ci    /* Extension structure use EXPLICIT tagging. That is, the actual
774a8e1175bSopenharmony_ci     * `Extensions` structure is wrapped by a tag-length pair using
775a8e1175bSopenharmony_ci     * the respective context-specific tag. */
776a8e1175bSopenharmony_ci    ret = mbedtls_asn1_get_tag(p, end, &ext->len,
777a8e1175bSopenharmony_ci                               MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag);
778a8e1175bSopenharmony_ci    if (ret != 0) {
779a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
780a8e1175bSopenharmony_ci    }
781a8e1175bSopenharmony_ci
782a8e1175bSopenharmony_ci    ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag;
783a8e1175bSopenharmony_ci    ext->p   = *p;
784a8e1175bSopenharmony_ci    end      = *p + ext->len;
785a8e1175bSopenharmony_ci
786a8e1175bSopenharmony_ci    /*
787a8e1175bSopenharmony_ci     * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
788a8e1175bSopenharmony_ci     */
789a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
790a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
791a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
792a8e1175bSopenharmony_ci    }
793a8e1175bSopenharmony_ci
794a8e1175bSopenharmony_ci    if (end != *p + len) {
795a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
796a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
797a8e1175bSopenharmony_ci    }
798a8e1175bSopenharmony_ci
799a8e1175bSopenharmony_ci    return 0;
800a8e1175bSopenharmony_ci}
801a8e1175bSopenharmony_ci
802a8e1175bSopenharmony_cistatic char nibble_to_hex_digit(int i)
803a8e1175bSopenharmony_ci{
804a8e1175bSopenharmony_ci    return (i < 10) ? (i + '0') : (i - 10 + 'A');
805a8e1175bSopenharmony_ci}
806a8e1175bSopenharmony_ci
807a8e1175bSopenharmony_ci/*
808a8e1175bSopenharmony_ci * Store the name in printable form into buf; no more
809a8e1175bSopenharmony_ci * than size characters will be written
810a8e1175bSopenharmony_ci */
811a8e1175bSopenharmony_ciint mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn)
812a8e1175bSopenharmony_ci{
813a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
814a8e1175bSopenharmony_ci    size_t i, j, n, asn1_len_size, asn1_tag_size, asn1_tag_len_buf_start;
815a8e1175bSopenharmony_ci    /* 6 is enough as our asn1 write functions only write one byte for the tag and at most five bytes for the length*/
816a8e1175bSopenharmony_ci    unsigned char asn1_tag_len_buf[6];
817a8e1175bSopenharmony_ci    unsigned char *asn1_len_p;
818a8e1175bSopenharmony_ci    unsigned char c, merge = 0;
819a8e1175bSopenharmony_ci    const mbedtls_x509_name *name;
820a8e1175bSopenharmony_ci    const char *short_name = NULL;
821a8e1175bSopenharmony_ci    char lowbits, highbits;
822a8e1175bSopenharmony_ci    char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
823a8e1175bSopenharmony_ci    int print_hexstring;
824a8e1175bSopenharmony_ci
825a8e1175bSopenharmony_ci    memset(s, 0, sizeof(s));
826a8e1175bSopenharmony_ci
827a8e1175bSopenharmony_ci    name = dn;
828a8e1175bSopenharmony_ci    p = buf;
829a8e1175bSopenharmony_ci    n = size;
830a8e1175bSopenharmony_ci
831a8e1175bSopenharmony_ci    while (name != NULL) {
832a8e1175bSopenharmony_ci        if (!name->oid.p) {
833a8e1175bSopenharmony_ci            name = name->next;
834a8e1175bSopenharmony_ci            continue;
835a8e1175bSopenharmony_ci        }
836a8e1175bSopenharmony_ci
837a8e1175bSopenharmony_ci        if (name != dn) {
838a8e1175bSopenharmony_ci            ret = mbedtls_snprintf(p, n, merge ? " + " : ", ");
839a8e1175bSopenharmony_ci            MBEDTLS_X509_SAFE_SNPRINTF;
840a8e1175bSopenharmony_ci        }
841a8e1175bSopenharmony_ci
842a8e1175bSopenharmony_ci        print_hexstring = (name->val.tag != MBEDTLS_ASN1_UTF8_STRING) &&
843a8e1175bSopenharmony_ci                          (name->val.tag != MBEDTLS_ASN1_PRINTABLE_STRING) &&
844a8e1175bSopenharmony_ci                          (name->val.tag != MBEDTLS_ASN1_IA5_STRING);
845a8e1175bSopenharmony_ci
846a8e1175bSopenharmony_ci        if ((ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name)) == 0) {
847a8e1175bSopenharmony_ci            ret = mbedtls_snprintf(p, n, "%s=", short_name);
848a8e1175bSopenharmony_ci        } else {
849a8e1175bSopenharmony_ci            if ((ret = mbedtls_oid_get_numeric_string(p, n, &name->oid)) > 0) {
850a8e1175bSopenharmony_ci                n -= ret;
851a8e1175bSopenharmony_ci                p += ret;
852a8e1175bSopenharmony_ci                ret = mbedtls_snprintf(p, n, "=");
853a8e1175bSopenharmony_ci                print_hexstring = 1;
854a8e1175bSopenharmony_ci            } else if (ret == MBEDTLS_ERR_OID_BUF_TOO_SMALL) {
855a8e1175bSopenharmony_ci                return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
856a8e1175bSopenharmony_ci            } else {
857a8e1175bSopenharmony_ci                ret = mbedtls_snprintf(p, n, "\?\?=");
858a8e1175bSopenharmony_ci            }
859a8e1175bSopenharmony_ci        }
860a8e1175bSopenharmony_ci        MBEDTLS_X509_SAFE_SNPRINTF;
861a8e1175bSopenharmony_ci
862a8e1175bSopenharmony_ci        if (print_hexstring) {
863a8e1175bSopenharmony_ci            s[0] = '#';
864a8e1175bSopenharmony_ci
865a8e1175bSopenharmony_ci            asn1_len_p = asn1_tag_len_buf + sizeof(asn1_tag_len_buf);
866a8e1175bSopenharmony_ci            if ((ret = mbedtls_asn1_write_len(&asn1_len_p, asn1_tag_len_buf, name->val.len)) < 0) {
867a8e1175bSopenharmony_ci                return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
868a8e1175bSopenharmony_ci            }
869a8e1175bSopenharmony_ci            asn1_len_size = ret;
870a8e1175bSopenharmony_ci            if ((ret = mbedtls_asn1_write_tag(&asn1_len_p, asn1_tag_len_buf, name->val.tag)) < 0) {
871a8e1175bSopenharmony_ci                return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
872a8e1175bSopenharmony_ci            }
873a8e1175bSopenharmony_ci            asn1_tag_size = ret;
874a8e1175bSopenharmony_ci            asn1_tag_len_buf_start = sizeof(asn1_tag_len_buf) - asn1_len_size - asn1_tag_size;
875a8e1175bSopenharmony_ci            for (i = 0, j = 1; i < asn1_len_size + asn1_tag_size; i++) {
876a8e1175bSopenharmony_ci                if (j + 1 >= sizeof(s) - 1) {
877a8e1175bSopenharmony_ci                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
878a8e1175bSopenharmony_ci                }
879a8e1175bSopenharmony_ci                c = asn1_tag_len_buf[asn1_tag_len_buf_start+i];
880a8e1175bSopenharmony_ci                lowbits = (c & 0x0F);
881a8e1175bSopenharmony_ci                highbits = c >> 4;
882a8e1175bSopenharmony_ci                s[j++] = nibble_to_hex_digit(highbits);
883a8e1175bSopenharmony_ci                s[j++] = nibble_to_hex_digit(lowbits);
884a8e1175bSopenharmony_ci            }
885a8e1175bSopenharmony_ci            for (i = 0; i < name->val.len; i++) {
886a8e1175bSopenharmony_ci                if (j + 1 >= sizeof(s) - 1) {
887a8e1175bSopenharmony_ci                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
888a8e1175bSopenharmony_ci                }
889a8e1175bSopenharmony_ci                c = name->val.p[i];
890a8e1175bSopenharmony_ci                lowbits = (c & 0x0F);
891a8e1175bSopenharmony_ci                highbits = c >> 4;
892a8e1175bSopenharmony_ci                s[j++] = nibble_to_hex_digit(highbits);
893a8e1175bSopenharmony_ci                s[j++] = nibble_to_hex_digit(lowbits);
894a8e1175bSopenharmony_ci            }
895a8e1175bSopenharmony_ci        } else {
896a8e1175bSopenharmony_ci            for (i = 0, j = 0; i < name->val.len; i++, j++) {
897a8e1175bSopenharmony_ci                if (j >= sizeof(s) - 1) {
898a8e1175bSopenharmony_ci                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
899a8e1175bSopenharmony_ci                }
900a8e1175bSopenharmony_ci
901a8e1175bSopenharmony_ci                c = name->val.p[i];
902a8e1175bSopenharmony_ci                // Special characters requiring escaping, RFC 4514 Section 2.4
903a8e1175bSopenharmony_ci                if (c == '\0') {
904a8e1175bSopenharmony_ci                    return MBEDTLS_ERR_X509_INVALID_NAME;
905a8e1175bSopenharmony_ci                } else {
906a8e1175bSopenharmony_ci                    if (strchr(",=+<>;\"\\", c) ||
907a8e1175bSopenharmony_ci                        ((i == 0) && strchr("# ", c)) ||
908a8e1175bSopenharmony_ci                        ((i == name->val.len-1) && (c == ' '))) {
909a8e1175bSopenharmony_ci                        if (j + 1 >= sizeof(s) - 1) {
910a8e1175bSopenharmony_ci                            return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
911a8e1175bSopenharmony_ci                        }
912a8e1175bSopenharmony_ci                        s[j++] = '\\';
913a8e1175bSopenharmony_ci                    }
914a8e1175bSopenharmony_ci                }
915a8e1175bSopenharmony_ci                if (c < 32 || c >= 127) {
916a8e1175bSopenharmony_ci                    if (j + 3 >= sizeof(s) - 1) {
917a8e1175bSopenharmony_ci                        return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
918a8e1175bSopenharmony_ci                    }
919a8e1175bSopenharmony_ci                    s[j++] = '\\';
920a8e1175bSopenharmony_ci                    lowbits = (c & 0x0F);
921a8e1175bSopenharmony_ci                    highbits = c >> 4;
922a8e1175bSopenharmony_ci                    s[j++] = nibble_to_hex_digit(highbits);
923a8e1175bSopenharmony_ci                    s[j] = nibble_to_hex_digit(lowbits);
924a8e1175bSopenharmony_ci                } else {
925a8e1175bSopenharmony_ci                    s[j] = c;
926a8e1175bSopenharmony_ci                }
927a8e1175bSopenharmony_ci            }
928a8e1175bSopenharmony_ci        }
929a8e1175bSopenharmony_ci        s[j] = '\0';
930a8e1175bSopenharmony_ci        ret = mbedtls_snprintf(p, n, "%s", s);
931a8e1175bSopenharmony_ci        MBEDTLS_X509_SAFE_SNPRINTF;
932a8e1175bSopenharmony_ci
933a8e1175bSopenharmony_ci        merge = name->next_merged;
934a8e1175bSopenharmony_ci        name = name->next;
935a8e1175bSopenharmony_ci    }
936a8e1175bSopenharmony_ci
937a8e1175bSopenharmony_ci    return (int) (size - n);
938a8e1175bSopenharmony_ci}
939a8e1175bSopenharmony_ci
940a8e1175bSopenharmony_ci/*
941a8e1175bSopenharmony_ci * Store the serial in printable form into buf; no more
942a8e1175bSopenharmony_ci * than size characters will be written
943a8e1175bSopenharmony_ci */
944a8e1175bSopenharmony_ciint mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial)
945a8e1175bSopenharmony_ci{
946a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
947a8e1175bSopenharmony_ci    size_t i, n, nr;
948a8e1175bSopenharmony_ci    char *p;
949a8e1175bSopenharmony_ci
950a8e1175bSopenharmony_ci    p = buf;
951a8e1175bSopenharmony_ci    n = size;
952a8e1175bSopenharmony_ci
953a8e1175bSopenharmony_ci    nr = (serial->len <= 32)
954a8e1175bSopenharmony_ci        ? serial->len  : 28;
955a8e1175bSopenharmony_ci
956a8e1175bSopenharmony_ci    for (i = 0; i < nr; i++) {
957a8e1175bSopenharmony_ci        if (i == 0 && nr > 1 && serial->p[i] == 0x0) {
958a8e1175bSopenharmony_ci            continue;
959a8e1175bSopenharmony_ci        }
960a8e1175bSopenharmony_ci
961a8e1175bSopenharmony_ci        ret = mbedtls_snprintf(p, n, "%02X%s",
962a8e1175bSopenharmony_ci                               serial->p[i], (i < nr - 1) ? ":" : "");
963a8e1175bSopenharmony_ci        MBEDTLS_X509_SAFE_SNPRINTF;
964a8e1175bSopenharmony_ci    }
965a8e1175bSopenharmony_ci
966a8e1175bSopenharmony_ci    if (nr != serial->len) {
967a8e1175bSopenharmony_ci        ret = mbedtls_snprintf(p, n, "....");
968a8e1175bSopenharmony_ci        MBEDTLS_X509_SAFE_SNPRINTF;
969a8e1175bSopenharmony_ci    }
970a8e1175bSopenharmony_ci
971a8e1175bSopenharmony_ci    return (int) (size - n);
972a8e1175bSopenharmony_ci}
973a8e1175bSopenharmony_ci
974a8e1175bSopenharmony_ci#if !defined(MBEDTLS_X509_REMOVE_INFO)
975a8e1175bSopenharmony_ci/*
976a8e1175bSopenharmony_ci * Helper for writing signature algorithms
977a8e1175bSopenharmony_ci */
978a8e1175bSopenharmony_ciint mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
979a8e1175bSopenharmony_ci                              mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
980a8e1175bSopenharmony_ci                              const void *sig_opts)
981a8e1175bSopenharmony_ci{
982a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
983a8e1175bSopenharmony_ci    char *p = buf;
984a8e1175bSopenharmony_ci    size_t n = size;
985a8e1175bSopenharmony_ci    const char *desc = NULL;
986a8e1175bSopenharmony_ci
987a8e1175bSopenharmony_ci    ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc);
988a8e1175bSopenharmony_ci    if (ret != 0) {
989a8e1175bSopenharmony_ci        ret = mbedtls_snprintf(p, n, "???");
990a8e1175bSopenharmony_ci    } else {
991a8e1175bSopenharmony_ci        ret = mbedtls_snprintf(p, n, "%s", desc);
992a8e1175bSopenharmony_ci    }
993a8e1175bSopenharmony_ci    MBEDTLS_X509_SAFE_SNPRINTF;
994a8e1175bSopenharmony_ci
995a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
996a8e1175bSopenharmony_ci    if (pk_alg == MBEDTLS_PK_RSASSA_PSS) {
997a8e1175bSopenharmony_ci        const mbedtls_pk_rsassa_pss_options *pss_opts;
998a8e1175bSopenharmony_ci
999a8e1175bSopenharmony_ci        pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
1000a8e1175bSopenharmony_ci
1001a8e1175bSopenharmony_ci        const char *name = md_type_to_string(md_alg);
1002a8e1175bSopenharmony_ci        const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id);
1003a8e1175bSopenharmony_ci
1004a8e1175bSopenharmony_ci        ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)",
1005a8e1175bSopenharmony_ci                               name ? name : "???",
1006a8e1175bSopenharmony_ci                               mgf_name ? mgf_name : "???",
1007a8e1175bSopenharmony_ci                               (unsigned int) pss_opts->expected_salt_len);
1008a8e1175bSopenharmony_ci        MBEDTLS_X509_SAFE_SNPRINTF;
1009a8e1175bSopenharmony_ci    }
1010a8e1175bSopenharmony_ci#else
1011a8e1175bSopenharmony_ci    ((void) pk_alg);
1012a8e1175bSopenharmony_ci    ((void) md_alg);
1013a8e1175bSopenharmony_ci    ((void) sig_opts);
1014a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
1015a8e1175bSopenharmony_ci
1016a8e1175bSopenharmony_ci    return (int) (size - n);
1017a8e1175bSopenharmony_ci}
1018a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_REMOVE_INFO */
1019a8e1175bSopenharmony_ci
1020a8e1175bSopenharmony_ci/*
1021a8e1175bSopenharmony_ci * Helper for writing "RSA key size", "EC key size", etc
1022a8e1175bSopenharmony_ci */
1023a8e1175bSopenharmony_ciint mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name)
1024a8e1175bSopenharmony_ci{
1025a8e1175bSopenharmony_ci    char *p = buf;
1026a8e1175bSopenharmony_ci    size_t n = buf_size;
1027a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1028a8e1175bSopenharmony_ci
1029a8e1175bSopenharmony_ci    ret = mbedtls_snprintf(p, n, "%s key size", name);
1030a8e1175bSopenharmony_ci    MBEDTLS_X509_SAFE_SNPRINTF;
1031a8e1175bSopenharmony_ci
1032a8e1175bSopenharmony_ci    return 0;
1033a8e1175bSopenharmony_ci}
1034a8e1175bSopenharmony_ci
1035a8e1175bSopenharmony_ciint mbedtls_x509_time_cmp(const mbedtls_x509_time *t1,
1036a8e1175bSopenharmony_ci                          const mbedtls_x509_time *t2)
1037a8e1175bSopenharmony_ci{
1038a8e1175bSopenharmony_ci    int x;
1039a8e1175bSopenharmony_ci
1040a8e1175bSopenharmony_ci    x = (((t1->year << 9) | (t1->mon << 5) | (t1->day)) -
1041a8e1175bSopenharmony_ci         ((t2->year << 9) | (t2->mon << 5) | (t2->day)));
1042a8e1175bSopenharmony_ci    if (x != 0) {
1043a8e1175bSopenharmony_ci        return x;
1044a8e1175bSopenharmony_ci    }
1045a8e1175bSopenharmony_ci
1046a8e1175bSopenharmony_ci    x = (((t1->hour << 12) | (t1->min << 6) | (t1->sec)) -
1047a8e1175bSopenharmony_ci         ((t2->hour << 12) | (t2->min << 6) | (t2->sec)));
1048a8e1175bSopenharmony_ci    return x;
1049a8e1175bSopenharmony_ci}
1050a8e1175bSopenharmony_ci
1051a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME_DATE)
1052a8e1175bSopenharmony_ciint mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now)
1053a8e1175bSopenharmony_ci{
1054a8e1175bSopenharmony_ci    struct tm tm;
1055a8e1175bSopenharmony_ci
1056a8e1175bSopenharmony_ci    if (mbedtls_platform_gmtime_r(&tt, &tm) == NULL) {
1057a8e1175bSopenharmony_ci        return -1;
1058a8e1175bSopenharmony_ci    }
1059a8e1175bSopenharmony_ci
1060a8e1175bSopenharmony_ci    now->year = tm.tm_year + 1900;
1061a8e1175bSopenharmony_ci    now->mon  = tm.tm_mon  + 1;
1062a8e1175bSopenharmony_ci    now->day  = tm.tm_mday;
1063a8e1175bSopenharmony_ci    now->hour = tm.tm_hour;
1064a8e1175bSopenharmony_ci    now->min  = tm.tm_min;
1065a8e1175bSopenharmony_ci    now->sec  = tm.tm_sec;
1066a8e1175bSopenharmony_ci    return 0;
1067a8e1175bSopenharmony_ci}
1068a8e1175bSopenharmony_ci
1069a8e1175bSopenharmony_cistatic int x509_get_current_time(mbedtls_x509_time *now)
1070a8e1175bSopenharmony_ci{
1071a8e1175bSopenharmony_ci    return mbedtls_x509_time_gmtime(mbedtls_time(NULL), now);
1072a8e1175bSopenharmony_ci}
1073a8e1175bSopenharmony_ci
1074a8e1175bSopenharmony_ciint mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
1075a8e1175bSopenharmony_ci{
1076a8e1175bSopenharmony_ci    mbedtls_x509_time now;
1077a8e1175bSopenharmony_ci
1078a8e1175bSopenharmony_ci    if (x509_get_current_time(&now) != 0) {
1079a8e1175bSopenharmony_ci        return 1;
1080a8e1175bSopenharmony_ci    }
1081a8e1175bSopenharmony_ci
1082a8e1175bSopenharmony_ci    return mbedtls_x509_time_cmp(to, &now) < 0;
1083a8e1175bSopenharmony_ci}
1084a8e1175bSopenharmony_ci
1085a8e1175bSopenharmony_ciint mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
1086a8e1175bSopenharmony_ci{
1087a8e1175bSopenharmony_ci    mbedtls_x509_time now;
1088a8e1175bSopenharmony_ci
1089a8e1175bSopenharmony_ci    if (x509_get_current_time(&now) != 0) {
1090a8e1175bSopenharmony_ci        return 1;
1091a8e1175bSopenharmony_ci    }
1092a8e1175bSopenharmony_ci
1093a8e1175bSopenharmony_ci    return mbedtls_x509_time_cmp(from, &now) > 0;
1094a8e1175bSopenharmony_ci}
1095a8e1175bSopenharmony_ci
1096a8e1175bSopenharmony_ci#else  /* MBEDTLS_HAVE_TIME_DATE */
1097a8e1175bSopenharmony_ci
1098a8e1175bSopenharmony_ciint mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
1099a8e1175bSopenharmony_ci{
1100a8e1175bSopenharmony_ci    ((void) to);
1101a8e1175bSopenharmony_ci    return 0;
1102a8e1175bSopenharmony_ci}
1103a8e1175bSopenharmony_ci
1104a8e1175bSopenharmony_ciint mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
1105a8e1175bSopenharmony_ci{
1106a8e1175bSopenharmony_ci    ((void) from);
1107a8e1175bSopenharmony_ci    return 0;
1108a8e1175bSopenharmony_ci}
1109a8e1175bSopenharmony_ci#endif /* MBEDTLS_HAVE_TIME_DATE */
1110a8e1175bSopenharmony_ci
1111a8e1175bSopenharmony_ci/* Common functions for parsing CRT and CSR. */
1112a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C)
1113a8e1175bSopenharmony_ci/*
1114a8e1175bSopenharmony_ci * OtherName ::= SEQUENCE {
1115a8e1175bSopenharmony_ci *      type-id    OBJECT IDENTIFIER,
1116a8e1175bSopenharmony_ci *      value      [0] EXPLICIT ANY DEFINED BY type-id }
1117a8e1175bSopenharmony_ci *
1118a8e1175bSopenharmony_ci * HardwareModuleName ::= SEQUENCE {
1119a8e1175bSopenharmony_ci *                           hwType OBJECT IDENTIFIER,
1120a8e1175bSopenharmony_ci *                           hwSerialNum OCTET STRING }
1121a8e1175bSopenharmony_ci *
1122a8e1175bSopenharmony_ci * NOTE: we currently only parse and use otherName of type HwModuleName,
1123a8e1175bSopenharmony_ci * as defined in RFC 4108.
1124a8e1175bSopenharmony_ci */
1125a8e1175bSopenharmony_cistatic int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name,
1126a8e1175bSopenharmony_ci                               mbedtls_x509_san_other_name *other_name)
1127a8e1175bSopenharmony_ci{
1128a8e1175bSopenharmony_ci    int ret = 0;
1129a8e1175bSopenharmony_ci    size_t len;
1130a8e1175bSopenharmony_ci    unsigned char *p = subject_alt_name->p;
1131a8e1175bSopenharmony_ci    const unsigned char *end = p + subject_alt_name->len;
1132a8e1175bSopenharmony_ci    mbedtls_x509_buf cur_oid;
1133a8e1175bSopenharmony_ci
1134a8e1175bSopenharmony_ci    if ((subject_alt_name->tag &
1135a8e1175bSopenharmony_ci         (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) !=
1136a8e1175bSopenharmony_ci        (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) {
1137a8e1175bSopenharmony_ci        /*
1138a8e1175bSopenharmony_ci         * The given subject alternative name is not of type "othername".
1139a8e1175bSopenharmony_ci         */
1140a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1141a8e1175bSopenharmony_ci    }
1142a8e1175bSopenharmony_ci
1143a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1144a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_OID)) != 0) {
1145a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1146a8e1175bSopenharmony_ci    }
1147a8e1175bSopenharmony_ci
1148a8e1175bSopenharmony_ci    cur_oid.tag = MBEDTLS_ASN1_OID;
1149a8e1175bSopenharmony_ci    cur_oid.p = p;
1150a8e1175bSopenharmony_ci    cur_oid.len = len;
1151a8e1175bSopenharmony_ci
1152a8e1175bSopenharmony_ci    /*
1153a8e1175bSopenharmony_ci     * Only HwModuleName is currently supported.
1154a8e1175bSopenharmony_ci     */
1155a8e1175bSopenharmony_ci    if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) {
1156a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
1157a8e1175bSopenharmony_ci    }
1158a8e1175bSopenharmony_ci    other_name->type_id = cur_oid;
1159a8e1175bSopenharmony_ci
1160a8e1175bSopenharmony_ci    p += len;
1161a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1162a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
1163a8e1175bSopenharmony_ci        0) {
1164a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1165a8e1175bSopenharmony_ci    }
1166a8e1175bSopenharmony_ci
1167a8e1175bSopenharmony_ci    if (end != p + len) {
1168a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1169a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1170a8e1175bSopenharmony_ci    }
1171a8e1175bSopenharmony_ci
1172a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1173a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1174a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1175a8e1175bSopenharmony_ci    }
1176a8e1175bSopenharmony_ci
1177a8e1175bSopenharmony_ci    if (end != p + len) {
1178a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1179a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1180a8e1175bSopenharmony_ci    }
1181a8e1175bSopenharmony_ci
1182a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
1183a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1184a8e1175bSopenharmony_ci    }
1185a8e1175bSopenharmony_ci
1186a8e1175bSopenharmony_ci    other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
1187a8e1175bSopenharmony_ci    other_name->value.hardware_module_name.oid.p = p;
1188a8e1175bSopenharmony_ci    other_name->value.hardware_module_name.oid.len = len;
1189a8e1175bSopenharmony_ci
1190a8e1175bSopenharmony_ci    p += len;
1191a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1192a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_OCTET_STRING)) != 0) {
1193a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1194a8e1175bSopenharmony_ci    }
1195a8e1175bSopenharmony_ci
1196a8e1175bSopenharmony_ci    other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
1197a8e1175bSopenharmony_ci    other_name->value.hardware_module_name.val.p = p;
1198a8e1175bSopenharmony_ci    other_name->value.hardware_module_name.val.len = len;
1199a8e1175bSopenharmony_ci    p += len;
1200a8e1175bSopenharmony_ci    if (p != end) {
1201a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1202a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1203a8e1175bSopenharmony_ci    }
1204a8e1175bSopenharmony_ci    return 0;
1205a8e1175bSopenharmony_ci}
1206a8e1175bSopenharmony_ci
1207a8e1175bSopenharmony_ci/* Check mbedtls_x509_get_subject_alt_name for detailed description.
1208a8e1175bSopenharmony_ci *
1209a8e1175bSopenharmony_ci * In some cases while parsing subject alternative names the sequence tag is optional
1210a8e1175bSopenharmony_ci * (e.g. CertSerialNumber). This function is designed to handle such case.
1211a8e1175bSopenharmony_ci */
1212a8e1175bSopenharmony_ciint mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,
1213a8e1175bSopenharmony_ci                                          const unsigned char *end,
1214a8e1175bSopenharmony_ci                                          mbedtls_x509_sequence *subject_alt_name)
1215a8e1175bSopenharmony_ci{
1216a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1217a8e1175bSopenharmony_ci    size_t tag_len;
1218a8e1175bSopenharmony_ci    mbedtls_asn1_sequence *cur = subject_alt_name;
1219a8e1175bSopenharmony_ci
1220a8e1175bSopenharmony_ci    while (*p < end) {
1221a8e1175bSopenharmony_ci        mbedtls_x509_subject_alternative_name tmp_san_name;
1222a8e1175bSopenharmony_ci        mbedtls_x509_buf tmp_san_buf;
1223a8e1175bSopenharmony_ci        memset(&tmp_san_name, 0, sizeof(tmp_san_name));
1224a8e1175bSopenharmony_ci
1225a8e1175bSopenharmony_ci        tmp_san_buf.tag = **p;
1226a8e1175bSopenharmony_ci        (*p)++;
1227a8e1175bSopenharmony_ci
1228a8e1175bSopenharmony_ci        if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) {
1229a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1230a8e1175bSopenharmony_ci        }
1231a8e1175bSopenharmony_ci
1232a8e1175bSopenharmony_ci        tmp_san_buf.p = *p;
1233a8e1175bSopenharmony_ci        tmp_san_buf.len = tag_len;
1234a8e1175bSopenharmony_ci
1235a8e1175bSopenharmony_ci        if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
1236a8e1175bSopenharmony_ci            MBEDTLS_ASN1_CONTEXT_SPECIFIC) {
1237a8e1175bSopenharmony_ci            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1238a8e1175bSopenharmony_ci                                     MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
1239a8e1175bSopenharmony_ci        }
1240a8e1175bSopenharmony_ci
1241a8e1175bSopenharmony_ci        /*
1242a8e1175bSopenharmony_ci         * Check that the SAN is structured correctly by parsing it.
1243a8e1175bSopenharmony_ci         * The SAN structure is discarded afterwards.
1244a8e1175bSopenharmony_ci         */
1245a8e1175bSopenharmony_ci        ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &tmp_san_name);
1246a8e1175bSopenharmony_ci        /*
1247a8e1175bSopenharmony_ci         * In case the extension is malformed, return an error,
1248a8e1175bSopenharmony_ci         * and clear the allocated sequences.
1249a8e1175bSopenharmony_ci         */
1250a8e1175bSopenharmony_ci        if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
1251a8e1175bSopenharmony_ci            mbedtls_asn1_sequence_free(subject_alt_name->next);
1252a8e1175bSopenharmony_ci            subject_alt_name->next = NULL;
1253a8e1175bSopenharmony_ci            return ret;
1254a8e1175bSopenharmony_ci        }
1255a8e1175bSopenharmony_ci
1256a8e1175bSopenharmony_ci        mbedtls_x509_free_subject_alt_name(&tmp_san_name);
1257a8e1175bSopenharmony_ci        /* Allocate and assign next pointer */
1258a8e1175bSopenharmony_ci        if (cur->buf.p != NULL) {
1259a8e1175bSopenharmony_ci            if (cur->next != NULL) {
1260a8e1175bSopenharmony_ci                return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1261a8e1175bSopenharmony_ci            }
1262a8e1175bSopenharmony_ci
1263a8e1175bSopenharmony_ci            cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
1264a8e1175bSopenharmony_ci
1265a8e1175bSopenharmony_ci            if (cur->next == NULL) {
1266a8e1175bSopenharmony_ci                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1267a8e1175bSopenharmony_ci                                         MBEDTLS_ERR_ASN1_ALLOC_FAILED);
1268a8e1175bSopenharmony_ci            }
1269a8e1175bSopenharmony_ci
1270a8e1175bSopenharmony_ci            cur = cur->next;
1271a8e1175bSopenharmony_ci        }
1272a8e1175bSopenharmony_ci
1273a8e1175bSopenharmony_ci        cur->buf = tmp_san_buf;
1274a8e1175bSopenharmony_ci        *p += tmp_san_buf.len;
1275a8e1175bSopenharmony_ci    }
1276a8e1175bSopenharmony_ci
1277a8e1175bSopenharmony_ci    /* Set final sequence entry's next pointer to NULL */
1278a8e1175bSopenharmony_ci    cur->next = NULL;
1279a8e1175bSopenharmony_ci
1280a8e1175bSopenharmony_ci    if (*p != end) {
1281a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1282a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1283a8e1175bSopenharmony_ci    }
1284a8e1175bSopenharmony_ci
1285a8e1175bSopenharmony_ci    return 0;
1286a8e1175bSopenharmony_ci}
1287a8e1175bSopenharmony_ci
1288a8e1175bSopenharmony_ci/*
1289a8e1175bSopenharmony_ci * SubjectAltName ::= GeneralNames
1290a8e1175bSopenharmony_ci *
1291a8e1175bSopenharmony_ci * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
1292a8e1175bSopenharmony_ci *
1293a8e1175bSopenharmony_ci * GeneralName ::= CHOICE {
1294a8e1175bSopenharmony_ci *      otherName                       [0]     OtherName,
1295a8e1175bSopenharmony_ci *      rfc822Name                      [1]     IA5String,
1296a8e1175bSopenharmony_ci *      dNSName                         [2]     IA5String,
1297a8e1175bSopenharmony_ci *      x400Address                     [3]     ORAddress,
1298a8e1175bSopenharmony_ci *      directoryName                   [4]     Name,
1299a8e1175bSopenharmony_ci *      ediPartyName                    [5]     EDIPartyName,
1300a8e1175bSopenharmony_ci *      uniformResourceIdentifier       [6]     IA5String,
1301a8e1175bSopenharmony_ci *      iPAddress                       [7]     OCTET STRING,
1302a8e1175bSopenharmony_ci *      registeredID                    [8]     OBJECT IDENTIFIER }
1303a8e1175bSopenharmony_ci *
1304a8e1175bSopenharmony_ci * OtherName ::= SEQUENCE {
1305a8e1175bSopenharmony_ci *      type-id    OBJECT IDENTIFIER,
1306a8e1175bSopenharmony_ci *      value      [0] EXPLICIT ANY DEFINED BY type-id }
1307a8e1175bSopenharmony_ci *
1308a8e1175bSopenharmony_ci * EDIPartyName ::= SEQUENCE {
1309a8e1175bSopenharmony_ci *      nameAssigner            [0]     DirectoryString OPTIONAL,
1310a8e1175bSopenharmony_ci *      partyName               [1]     DirectoryString }
1311a8e1175bSopenharmony_ci *
1312a8e1175bSopenharmony_ci * We list all types, but use the following GeneralName types from RFC 5280:
1313a8e1175bSopenharmony_ci * "dnsName", "uniformResourceIdentifier" and "hardware_module_name"
1314a8e1175bSopenharmony_ci * of type "otherName", as defined in RFC 4108.
1315a8e1175bSopenharmony_ci */
1316a8e1175bSopenharmony_ciint mbedtls_x509_get_subject_alt_name(unsigned char **p,
1317a8e1175bSopenharmony_ci                                      const unsigned char *end,
1318a8e1175bSopenharmony_ci                                      mbedtls_x509_sequence *subject_alt_name)
1319a8e1175bSopenharmony_ci{
1320a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1321a8e1175bSopenharmony_ci    size_t len;
1322a8e1175bSopenharmony_ci
1323a8e1175bSopenharmony_ci    /* Get main sequence tag */
1324a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
1325a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1326a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1327a8e1175bSopenharmony_ci    }
1328a8e1175bSopenharmony_ci
1329a8e1175bSopenharmony_ci    if (*p + len != end) {
1330a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1331a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1332a8e1175bSopenharmony_ci    }
1333a8e1175bSopenharmony_ci
1334a8e1175bSopenharmony_ci    return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name);
1335a8e1175bSopenharmony_ci}
1336a8e1175bSopenharmony_ci
1337a8e1175bSopenharmony_ciint mbedtls_x509_get_ns_cert_type(unsigned char **p,
1338a8e1175bSopenharmony_ci                                  const unsigned char *end,
1339a8e1175bSopenharmony_ci                                  unsigned char *ns_cert_type)
1340a8e1175bSopenharmony_ci{
1341a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1342a8e1175bSopenharmony_ci    mbedtls_x509_bitstring bs = { 0, 0, NULL };
1343a8e1175bSopenharmony_ci
1344a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
1345a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1346a8e1175bSopenharmony_ci    }
1347a8e1175bSopenharmony_ci
1348a8e1175bSopenharmony_ci    /* A bitstring with no flags set is still technically valid, as it will mean
1349a8e1175bSopenharmony_ci       that the certificate has no designated purpose at the time of creation. */
1350a8e1175bSopenharmony_ci    if (bs.len == 0) {
1351a8e1175bSopenharmony_ci        *ns_cert_type = 0;
1352a8e1175bSopenharmony_ci        return 0;
1353a8e1175bSopenharmony_ci    }
1354a8e1175bSopenharmony_ci
1355a8e1175bSopenharmony_ci    if (bs.len != 1) {
1356a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1357a8e1175bSopenharmony_ci                                 MBEDTLS_ERR_ASN1_INVALID_LENGTH);
1358a8e1175bSopenharmony_ci    }
1359a8e1175bSopenharmony_ci
1360a8e1175bSopenharmony_ci    /* Get actual bitstring */
1361a8e1175bSopenharmony_ci    *ns_cert_type = *bs.p;
1362a8e1175bSopenharmony_ci    return 0;
1363a8e1175bSopenharmony_ci}
1364a8e1175bSopenharmony_ci
1365a8e1175bSopenharmony_ciint mbedtls_x509_get_key_usage(unsigned char **p,
1366a8e1175bSopenharmony_ci                               const unsigned char *end,
1367a8e1175bSopenharmony_ci                               unsigned int *key_usage)
1368a8e1175bSopenharmony_ci{
1369a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1370a8e1175bSopenharmony_ci    size_t i;
1371a8e1175bSopenharmony_ci    mbedtls_x509_bitstring bs = { 0, 0, NULL };
1372a8e1175bSopenharmony_ci
1373a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
1374a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1375a8e1175bSopenharmony_ci    }
1376a8e1175bSopenharmony_ci
1377a8e1175bSopenharmony_ci    /* A bitstring with no flags set is still technically valid, as it will mean
1378a8e1175bSopenharmony_ci       that the certificate has no designated purpose at the time of creation. */
1379a8e1175bSopenharmony_ci    if (bs.len == 0) {
1380a8e1175bSopenharmony_ci        *key_usage = 0;
1381a8e1175bSopenharmony_ci        return 0;
1382a8e1175bSopenharmony_ci    }
1383a8e1175bSopenharmony_ci
1384a8e1175bSopenharmony_ci    /* Get actual bitstring */
1385a8e1175bSopenharmony_ci    *key_usage = 0;
1386a8e1175bSopenharmony_ci    for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) {
1387a8e1175bSopenharmony_ci        *key_usage |= (unsigned int) bs.p[i] << (8*i);
1388a8e1175bSopenharmony_ci    }
1389a8e1175bSopenharmony_ci
1390a8e1175bSopenharmony_ci    return 0;
1391a8e1175bSopenharmony_ci}
1392a8e1175bSopenharmony_ci
1393a8e1175bSopenharmony_ciint mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
1394a8e1175bSopenharmony_ci                                        mbedtls_x509_subject_alternative_name *san)
1395a8e1175bSopenharmony_ci{
1396a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1397a8e1175bSopenharmony_ci    switch (san_buf->tag &
1398a8e1175bSopenharmony_ci            (MBEDTLS_ASN1_TAG_CLASS_MASK |
1399a8e1175bSopenharmony_ci             MBEDTLS_ASN1_TAG_VALUE_MASK)) {
1400a8e1175bSopenharmony_ci        /*
1401a8e1175bSopenharmony_ci         * otherName
1402a8e1175bSopenharmony_ci         */
1403a8e1175bSopenharmony_ci        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME):
1404a8e1175bSopenharmony_ci        {
1405a8e1175bSopenharmony_ci            mbedtls_x509_san_other_name other_name;
1406a8e1175bSopenharmony_ci
1407a8e1175bSopenharmony_ci            ret = x509_get_other_name(san_buf, &other_name);
1408a8e1175bSopenharmony_ci            if (ret != 0) {
1409a8e1175bSopenharmony_ci                return ret;
1410a8e1175bSopenharmony_ci            }
1411a8e1175bSopenharmony_ci
1412a8e1175bSopenharmony_ci            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1413a8e1175bSopenharmony_ci            san->type = MBEDTLS_X509_SAN_OTHER_NAME;
1414a8e1175bSopenharmony_ci            memcpy(&san->san.other_name,
1415a8e1175bSopenharmony_ci                   &other_name, sizeof(other_name));
1416a8e1175bSopenharmony_ci
1417a8e1175bSopenharmony_ci        }
1418a8e1175bSopenharmony_ci        break;
1419a8e1175bSopenharmony_ci        /*
1420a8e1175bSopenharmony_ci         * uniformResourceIdentifier
1421a8e1175bSopenharmony_ci         */
1422a8e1175bSopenharmony_ci        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER):
1423a8e1175bSopenharmony_ci        {
1424a8e1175bSopenharmony_ci            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1425a8e1175bSopenharmony_ci            san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;
1426a8e1175bSopenharmony_ci
1427a8e1175bSopenharmony_ci            memcpy(&san->san.unstructured_name,
1428a8e1175bSopenharmony_ci                   san_buf, sizeof(*san_buf));
1429a8e1175bSopenharmony_ci
1430a8e1175bSopenharmony_ci        }
1431a8e1175bSopenharmony_ci        break;
1432a8e1175bSopenharmony_ci        /*
1433a8e1175bSopenharmony_ci         * dNSName
1434a8e1175bSopenharmony_ci         */
1435a8e1175bSopenharmony_ci        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME):
1436a8e1175bSopenharmony_ci        {
1437a8e1175bSopenharmony_ci            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1438a8e1175bSopenharmony_ci            san->type = MBEDTLS_X509_SAN_DNS_NAME;
1439a8e1175bSopenharmony_ci
1440a8e1175bSopenharmony_ci            memcpy(&san->san.unstructured_name,
1441a8e1175bSopenharmony_ci                   san_buf, sizeof(*san_buf));
1442a8e1175bSopenharmony_ci        }
1443a8e1175bSopenharmony_ci        break;
1444a8e1175bSopenharmony_ci        /*
1445a8e1175bSopenharmony_ci         * IP address
1446a8e1175bSopenharmony_ci         */
1447a8e1175bSopenharmony_ci        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS):
1448a8e1175bSopenharmony_ci        {
1449a8e1175bSopenharmony_ci            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1450a8e1175bSopenharmony_ci            san->type = MBEDTLS_X509_SAN_IP_ADDRESS;
1451a8e1175bSopenharmony_ci            // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported
1452a8e1175bSopenharmony_ci            if (san_buf->len == 4 || san_buf->len == 16) {
1453a8e1175bSopenharmony_ci                memcpy(&san->san.unstructured_name,
1454a8e1175bSopenharmony_ci                       san_buf, sizeof(*san_buf));
1455a8e1175bSopenharmony_ci            } else {
1456a8e1175bSopenharmony_ci                return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1457a8e1175bSopenharmony_ci            }
1458a8e1175bSopenharmony_ci        }
1459a8e1175bSopenharmony_ci        break;
1460a8e1175bSopenharmony_ci        /*
1461a8e1175bSopenharmony_ci         * rfc822Name
1462a8e1175bSopenharmony_ci         */
1463a8e1175bSopenharmony_ci        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME):
1464a8e1175bSopenharmony_ci        {
1465a8e1175bSopenharmony_ci            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1466a8e1175bSopenharmony_ci            san->type = MBEDTLS_X509_SAN_RFC822_NAME;
1467a8e1175bSopenharmony_ci            memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf));
1468a8e1175bSopenharmony_ci        }
1469a8e1175bSopenharmony_ci        break;
1470a8e1175bSopenharmony_ci        /*
1471a8e1175bSopenharmony_ci         * directoryName
1472a8e1175bSopenharmony_ci         */
1473a8e1175bSopenharmony_ci        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DIRECTORY_NAME):
1474a8e1175bSopenharmony_ci        {
1475a8e1175bSopenharmony_ci            size_t name_len;
1476a8e1175bSopenharmony_ci            unsigned char *p = san_buf->p;
1477a8e1175bSopenharmony_ci            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1478a8e1175bSopenharmony_ci            san->type = MBEDTLS_X509_SAN_DIRECTORY_NAME;
1479a8e1175bSopenharmony_ci
1480a8e1175bSopenharmony_ci            ret = mbedtls_asn1_get_tag(&p, p + san_buf->len, &name_len,
1481a8e1175bSopenharmony_ci                                       MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
1482a8e1175bSopenharmony_ci
1483a8e1175bSopenharmony_ci            if (ret != 0) {
1484a8e1175bSopenharmony_ci                return ret;
1485a8e1175bSopenharmony_ci            }
1486a8e1175bSopenharmony_ci
1487a8e1175bSopenharmony_ci            if ((ret = mbedtls_x509_get_name(&p, p + name_len,
1488a8e1175bSopenharmony_ci                                             &san->san.directory_name)) != 0) {
1489a8e1175bSopenharmony_ci                return ret;
1490a8e1175bSopenharmony_ci            }
1491a8e1175bSopenharmony_ci        }
1492a8e1175bSopenharmony_ci        break;
1493a8e1175bSopenharmony_ci        /*
1494a8e1175bSopenharmony_ci         * Type not supported
1495a8e1175bSopenharmony_ci         */
1496a8e1175bSopenharmony_ci        default:
1497a8e1175bSopenharmony_ci            return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
1498a8e1175bSopenharmony_ci    }
1499a8e1175bSopenharmony_ci    return 0;
1500a8e1175bSopenharmony_ci}
1501a8e1175bSopenharmony_ci
1502a8e1175bSopenharmony_civoid mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san)
1503a8e1175bSopenharmony_ci{
1504a8e1175bSopenharmony_ci    if (san->type == MBEDTLS_X509_SAN_DIRECTORY_NAME) {
1505a8e1175bSopenharmony_ci        mbedtls_asn1_free_named_data_list_shallow(san->san.directory_name.next);
1506a8e1175bSopenharmony_ci    }
1507a8e1175bSopenharmony_ci}
1508a8e1175bSopenharmony_ci
1509a8e1175bSopenharmony_ci#if !defined(MBEDTLS_X509_REMOVE_INFO)
1510a8e1175bSopenharmony_ciint mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
1511a8e1175bSopenharmony_ci                                       const mbedtls_x509_sequence
1512a8e1175bSopenharmony_ci                                       *subject_alt_name,
1513a8e1175bSopenharmony_ci                                       const char *prefix)
1514a8e1175bSopenharmony_ci{
1515a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1516a8e1175bSopenharmony_ci    size_t i;
1517a8e1175bSopenharmony_ci    size_t n = *size;
1518a8e1175bSopenharmony_ci    char *p = *buf;
1519a8e1175bSopenharmony_ci    const mbedtls_x509_sequence *cur = subject_alt_name;
1520a8e1175bSopenharmony_ci    mbedtls_x509_subject_alternative_name san;
1521a8e1175bSopenharmony_ci    int parse_ret;
1522a8e1175bSopenharmony_ci
1523a8e1175bSopenharmony_ci    while (cur != NULL) {
1524a8e1175bSopenharmony_ci        memset(&san, 0, sizeof(san));
1525a8e1175bSopenharmony_ci        parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san);
1526a8e1175bSopenharmony_ci        if (parse_ret != 0) {
1527a8e1175bSopenharmony_ci            if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
1528a8e1175bSopenharmony_ci                ret = mbedtls_snprintf(p, n, "\n%s    <unsupported>", prefix);
1529a8e1175bSopenharmony_ci                MBEDTLS_X509_SAFE_SNPRINTF;
1530a8e1175bSopenharmony_ci            } else {
1531a8e1175bSopenharmony_ci                ret = mbedtls_snprintf(p, n, "\n%s    <malformed>", prefix);
1532a8e1175bSopenharmony_ci                MBEDTLS_X509_SAFE_SNPRINTF;
1533a8e1175bSopenharmony_ci            }
1534a8e1175bSopenharmony_ci            cur = cur->next;
1535a8e1175bSopenharmony_ci            continue;
1536a8e1175bSopenharmony_ci        }
1537a8e1175bSopenharmony_ci
1538a8e1175bSopenharmony_ci        switch (san.type) {
1539a8e1175bSopenharmony_ci            /*
1540a8e1175bSopenharmony_ci             * otherName
1541a8e1175bSopenharmony_ci             */
1542a8e1175bSopenharmony_ci            case MBEDTLS_X509_SAN_OTHER_NAME:
1543a8e1175bSopenharmony_ci            {
1544a8e1175bSopenharmony_ci                mbedtls_x509_san_other_name *other_name = &san.san.other_name;
1545a8e1175bSopenharmony_ci
1546a8e1175bSopenharmony_ci                ret = mbedtls_snprintf(p, n, "\n%s    otherName :", prefix);
1547a8e1175bSopenharmony_ci                MBEDTLS_X509_SAFE_SNPRINTF;
1548a8e1175bSopenharmony_ci
1549a8e1175bSopenharmony_ci                if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME,
1550a8e1175bSopenharmony_ci                                    &other_name->type_id) == 0) {
1551a8e1175bSopenharmony_ci                    ret = mbedtls_snprintf(p, n, "\n%s        hardware module name :", prefix);
1552a8e1175bSopenharmony_ci                    MBEDTLS_X509_SAFE_SNPRINTF;
1553a8e1175bSopenharmony_ci                    ret =
1554a8e1175bSopenharmony_ci                        mbedtls_snprintf(p, n, "\n%s            hardware type          : ", prefix);
1555a8e1175bSopenharmony_ci                    MBEDTLS_X509_SAFE_SNPRINTF;
1556a8e1175bSopenharmony_ci
1557a8e1175bSopenharmony_ci                    ret = mbedtls_oid_get_numeric_string(p,
1558a8e1175bSopenharmony_ci                                                         n,
1559a8e1175bSopenharmony_ci                                                         &other_name->value.hardware_module_name.oid);
1560a8e1175bSopenharmony_ci                    MBEDTLS_X509_SAFE_SNPRINTF;
1561a8e1175bSopenharmony_ci
1562a8e1175bSopenharmony_ci                    ret =
1563a8e1175bSopenharmony_ci                        mbedtls_snprintf(p, n, "\n%s            hardware serial number : ", prefix);
1564a8e1175bSopenharmony_ci                    MBEDTLS_X509_SAFE_SNPRINTF;
1565a8e1175bSopenharmony_ci
1566a8e1175bSopenharmony_ci                    for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) {
1567a8e1175bSopenharmony_ci                        ret = mbedtls_snprintf(p,
1568a8e1175bSopenharmony_ci                                               n,
1569a8e1175bSopenharmony_ci                                               "%02X",
1570a8e1175bSopenharmony_ci                                               other_name->value.hardware_module_name.val.p[i]);
1571a8e1175bSopenharmony_ci                        MBEDTLS_X509_SAFE_SNPRINTF;
1572a8e1175bSopenharmony_ci                    }
1573a8e1175bSopenharmony_ci                }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
1574a8e1175bSopenharmony_ci            }
1575a8e1175bSopenharmony_ci            break;
1576a8e1175bSopenharmony_ci            /*
1577a8e1175bSopenharmony_ci             * uniformResourceIdentifier
1578a8e1175bSopenharmony_ci             */
1579a8e1175bSopenharmony_ci            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
1580a8e1175bSopenharmony_ci            {
1581a8e1175bSopenharmony_ci                ret = mbedtls_snprintf(p, n, "\n%s    uniformResourceIdentifier : ", prefix);
1582a8e1175bSopenharmony_ci                MBEDTLS_X509_SAFE_SNPRINTF;
1583a8e1175bSopenharmony_ci                if (san.san.unstructured_name.len >= n) {
1584a8e1175bSopenharmony_ci                    if (n > 0) {
1585a8e1175bSopenharmony_ci                        *p = '\0';
1586a8e1175bSopenharmony_ci                    }
1587a8e1175bSopenharmony_ci                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1588a8e1175bSopenharmony_ci                }
1589a8e1175bSopenharmony_ci
1590a8e1175bSopenharmony_ci                memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
1591a8e1175bSopenharmony_ci                p += san.san.unstructured_name.len;
1592a8e1175bSopenharmony_ci                n -= san.san.unstructured_name.len;
1593a8e1175bSopenharmony_ci            }
1594a8e1175bSopenharmony_ci            break;
1595a8e1175bSopenharmony_ci            /*
1596a8e1175bSopenharmony_ci             * dNSName
1597a8e1175bSopenharmony_ci             * RFC822 Name
1598a8e1175bSopenharmony_ci             */
1599a8e1175bSopenharmony_ci            case MBEDTLS_X509_SAN_DNS_NAME:
1600a8e1175bSopenharmony_ci            case MBEDTLS_X509_SAN_RFC822_NAME:
1601a8e1175bSopenharmony_ci            {
1602a8e1175bSopenharmony_ci                const char *dns_name = "dNSName";
1603a8e1175bSopenharmony_ci                const char *rfc822_name = "rfc822Name";
1604a8e1175bSopenharmony_ci
1605a8e1175bSopenharmony_ci                ret = mbedtls_snprintf(p, n,
1606a8e1175bSopenharmony_ci                                       "\n%s    %s : ",
1607a8e1175bSopenharmony_ci                                       prefix,
1608a8e1175bSopenharmony_ci                                       san.type ==
1609a8e1175bSopenharmony_ci                                       MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name);
1610a8e1175bSopenharmony_ci                MBEDTLS_X509_SAFE_SNPRINTF;
1611a8e1175bSopenharmony_ci                if (san.san.unstructured_name.len >= n) {
1612a8e1175bSopenharmony_ci                    if (n > 0) {
1613a8e1175bSopenharmony_ci                        *p = '\0';
1614a8e1175bSopenharmony_ci                    }
1615a8e1175bSopenharmony_ci                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1616a8e1175bSopenharmony_ci                }
1617a8e1175bSopenharmony_ci
1618a8e1175bSopenharmony_ci                memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
1619a8e1175bSopenharmony_ci                p += san.san.unstructured_name.len;
1620a8e1175bSopenharmony_ci                n -= san.san.unstructured_name.len;
1621a8e1175bSopenharmony_ci            }
1622a8e1175bSopenharmony_ci            break;
1623a8e1175bSopenharmony_ci            /*
1624a8e1175bSopenharmony_ci             * iPAddress
1625a8e1175bSopenharmony_ci             */
1626a8e1175bSopenharmony_ci            case MBEDTLS_X509_SAN_IP_ADDRESS:
1627a8e1175bSopenharmony_ci            {
1628a8e1175bSopenharmony_ci                ret = mbedtls_snprintf(p, n, "\n%s    %s : ",
1629a8e1175bSopenharmony_ci                                       prefix, "iPAddress");
1630a8e1175bSopenharmony_ci                MBEDTLS_X509_SAFE_SNPRINTF;
1631a8e1175bSopenharmony_ci                if (san.san.unstructured_name.len >= n) {
1632a8e1175bSopenharmony_ci                    if (n > 0) {
1633a8e1175bSopenharmony_ci                        *p = '\0';
1634a8e1175bSopenharmony_ci                    }
1635a8e1175bSopenharmony_ci                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1636a8e1175bSopenharmony_ci                }
1637a8e1175bSopenharmony_ci
1638a8e1175bSopenharmony_ci                unsigned char *ip = san.san.unstructured_name.p;
1639a8e1175bSopenharmony_ci                // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported
1640a8e1175bSopenharmony_ci                if (san.san.unstructured_name.len == 4) {
1641a8e1175bSopenharmony_ci                    ret = mbedtls_snprintf(p, n, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
1642a8e1175bSopenharmony_ci                    MBEDTLS_X509_SAFE_SNPRINTF;
1643a8e1175bSopenharmony_ci                } else if (san.san.unstructured_name.len == 16) {
1644a8e1175bSopenharmony_ci                    ret = mbedtls_snprintf(p, n,
1645a8e1175bSopenharmony_ci                                           "%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X",
1646a8e1175bSopenharmony_ci                                           ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6],
1647a8e1175bSopenharmony_ci                                           ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13],
1648a8e1175bSopenharmony_ci                                           ip[14], ip[15]);
1649a8e1175bSopenharmony_ci                    MBEDTLS_X509_SAFE_SNPRINTF;
1650a8e1175bSopenharmony_ci                } else {
1651a8e1175bSopenharmony_ci                    if (n > 0) {
1652a8e1175bSopenharmony_ci                        *p = '\0';
1653a8e1175bSopenharmony_ci                    }
1654a8e1175bSopenharmony_ci                    return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1655a8e1175bSopenharmony_ci                }
1656a8e1175bSopenharmony_ci            }
1657a8e1175bSopenharmony_ci            break;
1658a8e1175bSopenharmony_ci            /*
1659a8e1175bSopenharmony_ci             * directoryName
1660a8e1175bSopenharmony_ci             */
1661a8e1175bSopenharmony_ci            case MBEDTLS_X509_SAN_DIRECTORY_NAME:
1662a8e1175bSopenharmony_ci            {
1663a8e1175bSopenharmony_ci                ret = mbedtls_snprintf(p, n, "\n%s    directoryName : ", prefix);
1664a8e1175bSopenharmony_ci                if (ret < 0 || (size_t) ret >= n) {
1665a8e1175bSopenharmony_ci                    mbedtls_x509_free_subject_alt_name(&san);
1666a8e1175bSopenharmony_ci                }
1667a8e1175bSopenharmony_ci
1668a8e1175bSopenharmony_ci                MBEDTLS_X509_SAFE_SNPRINTF;
1669a8e1175bSopenharmony_ci                ret = mbedtls_x509_dn_gets(p, n, &san.san.directory_name);
1670a8e1175bSopenharmony_ci
1671a8e1175bSopenharmony_ci                if (ret < 0) {
1672a8e1175bSopenharmony_ci                    mbedtls_x509_free_subject_alt_name(&san);
1673a8e1175bSopenharmony_ci                    if (n > 0) {
1674a8e1175bSopenharmony_ci                        *p = '\0';
1675a8e1175bSopenharmony_ci                    }
1676a8e1175bSopenharmony_ci                    return ret;
1677a8e1175bSopenharmony_ci                }
1678a8e1175bSopenharmony_ci
1679a8e1175bSopenharmony_ci                p += ret;
1680a8e1175bSopenharmony_ci                n -= ret;
1681a8e1175bSopenharmony_ci            }
1682a8e1175bSopenharmony_ci            break;
1683a8e1175bSopenharmony_ci            /*
1684a8e1175bSopenharmony_ci             * Type not supported, skip item.
1685a8e1175bSopenharmony_ci             */
1686a8e1175bSopenharmony_ci            default:
1687a8e1175bSopenharmony_ci                ret = mbedtls_snprintf(p, n, "\n%s    <unsupported>", prefix);
1688a8e1175bSopenharmony_ci                MBEDTLS_X509_SAFE_SNPRINTF;
1689a8e1175bSopenharmony_ci                break;
1690a8e1175bSopenharmony_ci        }
1691a8e1175bSopenharmony_ci
1692a8e1175bSopenharmony_ci        /* So far memory is freed only in the case of directoryName
1693a8e1175bSopenharmony_ci         * parsing succeeding, as mbedtls_x509_get_name allocates memory. */
1694a8e1175bSopenharmony_ci        mbedtls_x509_free_subject_alt_name(&san);
1695a8e1175bSopenharmony_ci        cur = cur->next;
1696a8e1175bSopenharmony_ci    }
1697a8e1175bSopenharmony_ci
1698a8e1175bSopenharmony_ci    *p = '\0';
1699a8e1175bSopenharmony_ci
1700a8e1175bSopenharmony_ci    *size = n;
1701a8e1175bSopenharmony_ci    *buf = p;
1702a8e1175bSopenharmony_ci
1703a8e1175bSopenharmony_ci    return 0;
1704a8e1175bSopenharmony_ci}
1705a8e1175bSopenharmony_ci
1706a8e1175bSopenharmony_ci#define PRINT_ITEM(i)                                   \
1707a8e1175bSopenharmony_ci    do {                                                \
1708a8e1175bSopenharmony_ci        ret = mbedtls_snprintf(p, n, "%s" i, sep);      \
1709a8e1175bSopenharmony_ci        MBEDTLS_X509_SAFE_SNPRINTF;                     \
1710a8e1175bSopenharmony_ci        sep = ", ";                                     \
1711a8e1175bSopenharmony_ci    } while (0)
1712a8e1175bSopenharmony_ci
1713a8e1175bSopenharmony_ci#define CERT_TYPE(type, name)                           \
1714a8e1175bSopenharmony_ci    do {                                                \
1715a8e1175bSopenharmony_ci        if (ns_cert_type & (type)) {                    \
1716a8e1175bSopenharmony_ci            PRINT_ITEM(name);                           \
1717a8e1175bSopenharmony_ci        }                                               \
1718a8e1175bSopenharmony_ci    } while (0)
1719a8e1175bSopenharmony_ci
1720a8e1175bSopenharmony_ciint mbedtls_x509_info_cert_type(char **buf, size_t *size,
1721a8e1175bSopenharmony_ci                                unsigned char ns_cert_type)
1722a8e1175bSopenharmony_ci{
1723a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1724a8e1175bSopenharmony_ci    size_t n = *size;
1725a8e1175bSopenharmony_ci    char *p = *buf;
1726a8e1175bSopenharmony_ci    const char *sep = "";
1727a8e1175bSopenharmony_ci
1728a8e1175bSopenharmony_ci    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT,         "SSL Client");
1729a8e1175bSopenharmony_ci    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER,         "SSL Server");
1730a8e1175bSopenharmony_ci    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL,              "Email");
1731a8e1175bSopenharmony_ci    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING,     "Object Signing");
1732a8e1175bSopenharmony_ci    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED,           "Reserved");
1733a8e1175bSopenharmony_ci    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA,             "SSL CA");
1734a8e1175bSopenharmony_ci    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA,           "Email CA");
1735a8e1175bSopenharmony_ci    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA,  "Object Signing CA");
1736a8e1175bSopenharmony_ci
1737a8e1175bSopenharmony_ci    *size = n;
1738a8e1175bSopenharmony_ci    *buf = p;
1739a8e1175bSopenharmony_ci
1740a8e1175bSopenharmony_ci    return 0;
1741a8e1175bSopenharmony_ci}
1742a8e1175bSopenharmony_ci
1743a8e1175bSopenharmony_ci#define KEY_USAGE(code, name)       \
1744a8e1175bSopenharmony_ci    do {                            \
1745a8e1175bSopenharmony_ci        if ((key_usage) & (code)) { \
1746a8e1175bSopenharmony_ci            PRINT_ITEM(name);       \
1747a8e1175bSopenharmony_ci        }                           \
1748a8e1175bSopenharmony_ci    } while (0)
1749a8e1175bSopenharmony_ci
1750a8e1175bSopenharmony_ciint mbedtls_x509_info_key_usage(char **buf, size_t *size,
1751a8e1175bSopenharmony_ci                                unsigned int key_usage)
1752a8e1175bSopenharmony_ci{
1753a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1754a8e1175bSopenharmony_ci    size_t n = *size;
1755a8e1175bSopenharmony_ci    char *p = *buf;
1756a8e1175bSopenharmony_ci    const char *sep = "";
1757a8e1175bSopenharmony_ci
1758a8e1175bSopenharmony_ci    KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE,    "Digital Signature");
1759a8e1175bSopenharmony_ci    KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION,      "Non Repudiation");
1760a8e1175bSopenharmony_ci    KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT,     "Key Encipherment");
1761a8e1175bSopenharmony_ci    KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT,    "Data Encipherment");
1762a8e1175bSopenharmony_ci    KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT,        "Key Agreement");
1763a8e1175bSopenharmony_ci    KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN,        "Key Cert Sign");
1764a8e1175bSopenharmony_ci    KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN,             "CRL Sign");
1765a8e1175bSopenharmony_ci    KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY,        "Encipher Only");
1766a8e1175bSopenharmony_ci    KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY,        "Decipher Only");
1767a8e1175bSopenharmony_ci
1768a8e1175bSopenharmony_ci    *size = n;
1769a8e1175bSopenharmony_ci    *buf = p;
1770a8e1175bSopenharmony_ci
1771a8e1175bSopenharmony_ci    return 0;
1772a8e1175bSopenharmony_ci}
1773a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_REMOVE_INFO */
1774a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */
1775a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_USE_C */
1776