xref: /optee_os/lib/libmbedtls/mbedtls/library/x509.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  X.509 common functions for parsing and verification
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander /*
20817466cbSJens Wiklander  *  The ITU-T X.509 standard defines a certificate format for PKI.
21817466cbSJens Wiklander  *
22817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
23817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
24817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
25817466cbSJens Wiklander  *
26817466cbSJens Wiklander  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
27817466cbSJens Wiklander  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
28817466cbSJens Wiklander  */
29817466cbSJens Wiklander 
307901324dSJerome Forissier #include "common.h"
31817466cbSJens Wiklander 
32817466cbSJens Wiklander #if defined(MBEDTLS_X509_USE_C)
33817466cbSJens Wiklander 
34817466cbSJens Wiklander #include "mbedtls/x509.h"
35817466cbSJens Wiklander #include "mbedtls/asn1.h"
3611fa71b9SJerome Forissier #include "mbedtls/error.h"
37817466cbSJens Wiklander #include "mbedtls/oid.h"
38817466cbSJens Wiklander 
39817466cbSJens Wiklander #include <stdio.h>
40817466cbSJens Wiklander #include <string.h>
41817466cbSJens Wiklander 
42817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
43817466cbSJens Wiklander #include "mbedtls/pem.h"
44817466cbSJens Wiklander #endif
45817466cbSJens Wiklander 
46817466cbSJens Wiklander #include "mbedtls/platform.h"
47817466cbSJens Wiklander 
48817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_TIME)
49817466cbSJens Wiklander #include "mbedtls/platform_time.h"
50817466cbSJens Wiklander #endif
513d3b0591SJens Wiklander #if defined(MBEDTLS_HAVE_TIME_DATE)
523d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
53817466cbSJens Wiklander #include <time.h>
54817466cbSJens Wiklander #endif
55817466cbSJens Wiklander 
56*32b31808SJens Wiklander #include "mbedtls/legacy_or_psa.h"
57*32b31808SJens Wiklander 
58*32b31808SJens Wiklander #define CHECK(code) if ((ret = (code)) != 0) { return ret; }
595b25c76aSJerome Forissier #define CHECK_RANGE(min, max, val)                      \
605b25c76aSJerome Forissier     do                                                  \
615b25c76aSJerome Forissier     {                                                   \
625b25c76aSJerome Forissier         if ((val) < (min) || (val) > (max))    \
635b25c76aSJerome Forissier         {                                               \
64*32b31808SJens Wiklander             return ret;                              \
655b25c76aSJerome Forissier         }                                               \
665b25c76aSJerome Forissier     } while (0)
67817466cbSJens Wiklander 
68817466cbSJens Wiklander /*
69817466cbSJens Wiklander  *  CertificateSerialNumber  ::=  INTEGER
70817466cbSJens Wiklander  */
71817466cbSJens Wiklander int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end,
72817466cbSJens Wiklander                             mbedtls_x509_buf *serial)
73817466cbSJens Wiklander {
7411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
75817466cbSJens Wiklander 
76*32b31808SJens Wiklander     if ((end - *p) < 1) {
77*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
78*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
79*32b31808SJens Wiklander     }
80817466cbSJens Wiklander 
81817466cbSJens Wiklander     if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) &&
82*32b31808SJens Wiklander         **p !=   MBEDTLS_ASN1_INTEGER) {
83*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
84*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
85*32b31808SJens Wiklander     }
86817466cbSJens Wiklander 
87817466cbSJens Wiklander     serial->tag = *(*p)++;
88817466cbSJens Wiklander 
89*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) {
90*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret);
91*32b31808SJens Wiklander     }
92817466cbSJens Wiklander 
93817466cbSJens Wiklander     serial->p = *p;
94817466cbSJens Wiklander     *p += serial->len;
95817466cbSJens Wiklander 
96*32b31808SJens Wiklander     return 0;
97817466cbSJens Wiklander }
98817466cbSJens Wiklander 
99817466cbSJens Wiklander /* Get an algorithm identifier without parameters (eg for signatures)
100817466cbSJens Wiklander  *
101817466cbSJens Wiklander  *  AlgorithmIdentifier  ::=  SEQUENCE  {
102817466cbSJens Wiklander  *       algorithm               OBJECT IDENTIFIER,
103817466cbSJens Wiklander  *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
104817466cbSJens Wiklander  */
105817466cbSJens Wiklander int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,
106817466cbSJens Wiklander                               mbedtls_x509_buf *alg)
107817466cbSJens Wiklander {
10811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
109817466cbSJens Wiklander 
110*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
111*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
112*32b31808SJens Wiklander     }
113817466cbSJens Wiklander 
114*32b31808SJens Wiklander     return 0;
115817466cbSJens Wiklander }
116817466cbSJens Wiklander 
117817466cbSJens Wiklander /*
1185b25c76aSJerome Forissier  * Parse an algorithm identifier with (optional) parameters
119817466cbSJens Wiklander  */
120817466cbSJens Wiklander int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,
121817466cbSJens Wiklander                          mbedtls_x509_buf *alg, mbedtls_x509_buf *params)
122817466cbSJens Wiklander {
12311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
124817466cbSJens Wiklander 
125*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) {
126*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
127*32b31808SJens Wiklander     }
128817466cbSJens Wiklander 
129*32b31808SJens Wiklander     return 0;
130*32b31808SJens Wiklander }
131*32b31808SJens Wiklander 
132*32b31808SJens Wiklander /*
133*32b31808SJens Wiklander  * Convert md type to string
134*32b31808SJens Wiklander  */
135*32b31808SJens Wiklander static inline const char *md_type_to_string(mbedtls_md_type_t md_alg)
136*32b31808SJens Wiklander {
137*32b31808SJens Wiklander     switch (md_alg) {
138*32b31808SJens Wiklander #if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA)
139*32b31808SJens Wiklander         case MBEDTLS_MD_MD5:
140*32b31808SJens Wiklander             return "MD5";
141*32b31808SJens Wiklander #endif
142*32b31808SJens Wiklander #if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA)
143*32b31808SJens Wiklander         case MBEDTLS_MD_SHA1:
144*32b31808SJens Wiklander             return "SHA1";
145*32b31808SJens Wiklander #endif
146*32b31808SJens Wiklander #if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA)
147*32b31808SJens Wiklander         case MBEDTLS_MD_SHA224:
148*32b31808SJens Wiklander             return "SHA224";
149*32b31808SJens Wiklander #endif
150*32b31808SJens Wiklander #if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA)
151*32b31808SJens Wiklander         case MBEDTLS_MD_SHA256:
152*32b31808SJens Wiklander             return "SHA256";
153*32b31808SJens Wiklander #endif
154*32b31808SJens Wiklander #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA)
155*32b31808SJens Wiklander         case MBEDTLS_MD_SHA384:
156*32b31808SJens Wiklander             return "SHA384";
157*32b31808SJens Wiklander #endif
158*32b31808SJens Wiklander #if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA)
159*32b31808SJens Wiklander         case MBEDTLS_MD_SHA512:
160*32b31808SJens Wiklander             return "SHA512";
161*32b31808SJens Wiklander #endif
162*32b31808SJens Wiklander #if defined(MBEDTLS_HAS_ALG_RIPEMD160_VIA_MD_OR_PSA)
163*32b31808SJens Wiklander         case MBEDTLS_MD_RIPEMD160:
164*32b31808SJens Wiklander             return "RIPEMD160";
165*32b31808SJens Wiklander #endif
166*32b31808SJens Wiklander         case MBEDTLS_MD_NONE:
167*32b31808SJens Wiklander             return NULL;
168*32b31808SJens Wiklander         default:
169*32b31808SJens Wiklander             return NULL;
170*32b31808SJens Wiklander     }
171817466cbSJens Wiklander }
172817466cbSJens Wiklander 
173817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
174817466cbSJens Wiklander /*
175817466cbSJens Wiklander  * HashAlgorithm ::= AlgorithmIdentifier
176817466cbSJens Wiklander  *
177817466cbSJens Wiklander  * AlgorithmIdentifier  ::=  SEQUENCE  {
178817466cbSJens Wiklander  *      algorithm               OBJECT IDENTIFIER,
179817466cbSJens Wiklander  *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
180817466cbSJens Wiklander  *
181817466cbSJens Wiklander  * For HashAlgorithm, parameters MUST be NULL or absent.
182817466cbSJens Wiklander  */
183817466cbSJens Wiklander static int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg)
184817466cbSJens Wiklander {
18511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
186817466cbSJens Wiklander     unsigned char *p;
187817466cbSJens Wiklander     const unsigned char *end;
188817466cbSJens Wiklander     mbedtls_x509_buf md_oid;
189817466cbSJens Wiklander     size_t len;
190817466cbSJens Wiklander 
191817466cbSJens Wiklander     /* Make sure we got a SEQUENCE and setup bounds */
192*32b31808SJens Wiklander     if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
193*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
194*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
195*32b31808SJens Wiklander     }
196817466cbSJens Wiklander 
1977901324dSJerome Forissier     p = alg->p;
198817466cbSJens Wiklander     end = p + alg->len;
199817466cbSJens Wiklander 
200*32b31808SJens Wiklander     if (p >= end) {
201*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
202*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
203*32b31808SJens Wiklander     }
204817466cbSJens Wiklander 
205817466cbSJens Wiklander     /* Parse md_oid */
206817466cbSJens Wiklander     md_oid.tag = *p;
207817466cbSJens Wiklander 
208*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) {
209*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
210*32b31808SJens Wiklander     }
211817466cbSJens Wiklander 
212817466cbSJens Wiklander     md_oid.p = p;
213817466cbSJens Wiklander     p += md_oid.len;
214817466cbSJens Wiklander 
215817466cbSJens Wiklander     /* Get md_alg from md_oid */
216*32b31808SJens Wiklander     if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) {
217*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
218*32b31808SJens Wiklander     }
219817466cbSJens Wiklander 
220817466cbSJens Wiklander     /* Make sure params is absent of NULL */
221*32b31808SJens Wiklander     if (p == end) {
222*32b31808SJens Wiklander         return 0;
223*32b31808SJens Wiklander     }
224817466cbSJens Wiklander 
225*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) {
226*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
227*32b31808SJens Wiklander     }
228817466cbSJens Wiklander 
229*32b31808SJens Wiklander     if (p != end) {
230*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
231*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
232*32b31808SJens Wiklander     }
233817466cbSJens Wiklander 
234*32b31808SJens Wiklander     return 0;
235817466cbSJens Wiklander }
236817466cbSJens Wiklander 
237817466cbSJens Wiklander /*
238817466cbSJens Wiklander  *    RSASSA-PSS-params  ::=  SEQUENCE  {
239817466cbSJens Wiklander  *       hashAlgorithm     [0] HashAlgorithm DEFAULT sha1Identifier,
240817466cbSJens Wiklander  *       maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
241817466cbSJens Wiklander  *       saltLength        [2] INTEGER DEFAULT 20,
242817466cbSJens Wiklander  *       trailerField      [3] INTEGER DEFAULT 1  }
243817466cbSJens Wiklander  *    -- Note that the tags in this Sequence are explicit.
244817466cbSJens Wiklander  *
245817466cbSJens Wiklander  * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
246817466cbSJens Wiklander  * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
247*32b31808SJens Wiklander  * option. Enforce this at parsing time.
248817466cbSJens Wiklander  */
249817466cbSJens Wiklander int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params,
250817466cbSJens Wiklander                                        mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
251817466cbSJens Wiklander                                        int *salt_len)
252817466cbSJens Wiklander {
25311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
254817466cbSJens Wiklander     unsigned char *p;
255817466cbSJens Wiklander     const unsigned char *end, *end2;
256817466cbSJens Wiklander     size_t len;
257817466cbSJens Wiklander     mbedtls_x509_buf alg_id, alg_params;
258817466cbSJens Wiklander 
259817466cbSJens Wiklander     /* First set everything to defaults */
260817466cbSJens Wiklander     *md_alg = MBEDTLS_MD_SHA1;
261817466cbSJens Wiklander     *mgf_md = MBEDTLS_MD_SHA1;
262817466cbSJens Wiklander     *salt_len = 20;
263817466cbSJens Wiklander 
264817466cbSJens Wiklander     /* Make sure params is a SEQUENCE and setup bounds */
265*32b31808SJens Wiklander     if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
266*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
267*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
268*32b31808SJens Wiklander     }
269817466cbSJens Wiklander 
270817466cbSJens Wiklander     p = (unsigned char *) params->p;
271817466cbSJens Wiklander     end = p + params->len;
272817466cbSJens Wiklander 
273*32b31808SJens Wiklander     if (p == end) {
274*32b31808SJens Wiklander         return 0;
275*32b31808SJens Wiklander     }
276817466cbSJens Wiklander 
277817466cbSJens Wiklander     /*
278817466cbSJens Wiklander      * HashAlgorithm
279817466cbSJens Wiklander      */
280817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
281*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
282*32b31808SJens Wiklander                                     0)) == 0) {
283817466cbSJens Wiklander         end2 = p + len;
284817466cbSJens Wiklander 
285817466cbSJens Wiklander         /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
286*32b31808SJens Wiklander         if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) {
287*32b31808SJens Wiklander             return ret;
288817466cbSJens Wiklander         }
289817466cbSJens Wiklander 
290*32b31808SJens Wiklander         if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) {
291*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
292*32b31808SJens Wiklander         }
293*32b31808SJens Wiklander 
294*32b31808SJens Wiklander         if (p != end2) {
295*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
296*32b31808SJens Wiklander                                      MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
297*32b31808SJens Wiklander         }
298*32b31808SJens Wiklander     } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
299*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
300*32b31808SJens Wiklander     }
301*32b31808SJens Wiklander 
302*32b31808SJens Wiklander     if (p == end) {
303*32b31808SJens Wiklander         return 0;
304*32b31808SJens Wiklander     }
305817466cbSJens Wiklander 
306817466cbSJens Wiklander     /*
307817466cbSJens Wiklander      * MaskGenAlgorithm
308817466cbSJens Wiklander      */
309817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
310*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
311*32b31808SJens Wiklander                                     1)) == 0) {
312817466cbSJens Wiklander         end2 = p + len;
313817466cbSJens Wiklander 
314817466cbSJens Wiklander         /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
315*32b31808SJens Wiklander         if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) {
316*32b31808SJens Wiklander             return ret;
317*32b31808SJens Wiklander         }
318817466cbSJens Wiklander 
319817466cbSJens Wiklander         /* Only MFG1 is recognised for now */
320*32b31808SJens Wiklander         if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) {
321*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE,
322*32b31808SJens Wiklander                                      MBEDTLS_ERR_OID_NOT_FOUND);
323*32b31808SJens Wiklander         }
324817466cbSJens Wiklander 
325817466cbSJens Wiklander         /* Parse HashAlgorithm */
326*32b31808SJens Wiklander         if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) {
327*32b31808SJens Wiklander             return ret;
328817466cbSJens Wiklander         }
329817466cbSJens Wiklander 
330*32b31808SJens Wiklander         if (p != end2) {
331*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
332*32b31808SJens Wiklander                                      MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
333*32b31808SJens Wiklander         }
334*32b31808SJens Wiklander     } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
335*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
336*32b31808SJens Wiklander     }
337*32b31808SJens Wiklander 
338*32b31808SJens Wiklander     if (p == end) {
339*32b31808SJens Wiklander         return 0;
340*32b31808SJens Wiklander     }
341817466cbSJens Wiklander 
342817466cbSJens Wiklander     /*
343817466cbSJens Wiklander      * salt_len
344817466cbSJens Wiklander      */
345817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
346*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
347*32b31808SJens Wiklander                                     2)) == 0) {
348817466cbSJens Wiklander         end2 = p + len;
349817466cbSJens Wiklander 
350*32b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) {
351*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
352817466cbSJens Wiklander         }
353817466cbSJens Wiklander 
354*32b31808SJens Wiklander         if (p != end2) {
355*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
356*32b31808SJens Wiklander                                      MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
357*32b31808SJens Wiklander         }
358*32b31808SJens Wiklander     } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
359*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
360*32b31808SJens Wiklander     }
361*32b31808SJens Wiklander 
362*32b31808SJens Wiklander     if (p == end) {
363*32b31808SJens Wiklander         return 0;
364*32b31808SJens Wiklander     }
365817466cbSJens Wiklander 
366817466cbSJens Wiklander     /*
367817466cbSJens Wiklander      * trailer_field (if present, must be 1)
368817466cbSJens Wiklander      */
369817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
370*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
371*32b31808SJens Wiklander                                     3)) == 0) {
372817466cbSJens Wiklander         int trailer_field;
373817466cbSJens Wiklander 
374817466cbSJens Wiklander         end2 = p + len;
375817466cbSJens Wiklander 
376*32b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) {
377*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
378817466cbSJens Wiklander         }
379817466cbSJens Wiklander 
380*32b31808SJens Wiklander         if (p != end2) {
381*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
382*32b31808SJens Wiklander                                      MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
383*32b31808SJens Wiklander         }
384817466cbSJens Wiklander 
385*32b31808SJens Wiklander         if (trailer_field != 1) {
386*32b31808SJens Wiklander             return MBEDTLS_ERR_X509_INVALID_ALG;
387*32b31808SJens Wiklander         }
388*32b31808SJens Wiklander     } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
389*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
390*32b31808SJens Wiklander     }
391*32b31808SJens Wiklander 
392*32b31808SJens Wiklander     if (p != end) {
393*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
394*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
395*32b31808SJens Wiklander     }
396*32b31808SJens Wiklander 
397*32b31808SJens Wiklander     return 0;
398817466cbSJens Wiklander }
399817466cbSJens Wiklander #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
400817466cbSJens Wiklander 
401817466cbSJens Wiklander /*
402817466cbSJens Wiklander  *  AttributeTypeAndValue ::= SEQUENCE {
403817466cbSJens Wiklander  *    type     AttributeType,
404817466cbSJens Wiklander  *    value    AttributeValue }
405817466cbSJens Wiklander  *
406817466cbSJens Wiklander  *  AttributeType ::= OBJECT IDENTIFIER
407817466cbSJens Wiklander  *
408817466cbSJens Wiklander  *  AttributeValue ::= ANY DEFINED BY AttributeType
409817466cbSJens Wiklander  */
410817466cbSJens Wiklander static int x509_get_attr_type_value(unsigned char **p,
411817466cbSJens Wiklander                                     const unsigned char *end,
412817466cbSJens Wiklander                                     mbedtls_x509_name *cur)
413817466cbSJens Wiklander {
41411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
415817466cbSJens Wiklander     size_t len;
416817466cbSJens Wiklander     mbedtls_x509_buf *oid;
417817466cbSJens Wiklander     mbedtls_x509_buf *val;
418817466cbSJens Wiklander 
419817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
420*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
421*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
422*32b31808SJens Wiklander     }
423817466cbSJens Wiklander 
4245b25c76aSJerome Forissier     end = *p + len;
4255b25c76aSJerome Forissier 
426*32b31808SJens Wiklander     if ((end - *p) < 1) {
427*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
428*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
429*32b31808SJens Wiklander     }
430817466cbSJens Wiklander 
431817466cbSJens Wiklander     oid = &cur->oid;
432817466cbSJens Wiklander     oid->tag = **p;
433817466cbSJens Wiklander 
434*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) {
435*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
436*32b31808SJens Wiklander     }
437817466cbSJens Wiklander 
438817466cbSJens Wiklander     oid->p = *p;
439817466cbSJens Wiklander     *p += oid->len;
440817466cbSJens Wiklander 
441*32b31808SJens Wiklander     if ((end - *p) < 1) {
442*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
443*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
444*32b31808SJens Wiklander     }
445817466cbSJens Wiklander 
446817466cbSJens Wiklander     if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING      &&
447817466cbSJens Wiklander         **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
448817466cbSJens Wiklander         **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
449*32b31808SJens Wiklander         **p != MBEDTLS_ASN1_BIT_STRING) {
450*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
451*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
452*32b31808SJens Wiklander     }
453817466cbSJens Wiklander 
454817466cbSJens Wiklander     val = &cur->val;
455817466cbSJens Wiklander     val->tag = *(*p)++;
456817466cbSJens Wiklander 
457*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) {
458*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
459*32b31808SJens Wiklander     }
460817466cbSJens Wiklander 
461817466cbSJens Wiklander     val->p = *p;
462817466cbSJens Wiklander     *p += val->len;
463817466cbSJens Wiklander 
464*32b31808SJens Wiklander     if (*p != end) {
465*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
466*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
4675b25c76aSJerome Forissier     }
4685b25c76aSJerome Forissier 
469817466cbSJens Wiklander     cur->next = NULL;
470817466cbSJens Wiklander 
471*32b31808SJens Wiklander     return 0;
472817466cbSJens Wiklander }
473817466cbSJens Wiklander 
474817466cbSJens Wiklander /*
475817466cbSJens Wiklander  *  Name ::= CHOICE { -- only one possibility for now --
476817466cbSJens Wiklander  *       rdnSequence  RDNSequence }
477817466cbSJens Wiklander  *
478817466cbSJens Wiklander  *  RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
479817466cbSJens Wiklander  *
480817466cbSJens Wiklander  *  RelativeDistinguishedName ::=
481817466cbSJens Wiklander  *    SET OF AttributeTypeAndValue
482817466cbSJens Wiklander  *
483817466cbSJens Wiklander  *  AttributeTypeAndValue ::= SEQUENCE {
484817466cbSJens Wiklander  *    type     AttributeType,
485817466cbSJens Wiklander  *    value    AttributeValue }
486817466cbSJens Wiklander  *
487817466cbSJens Wiklander  *  AttributeType ::= OBJECT IDENTIFIER
488817466cbSJens Wiklander  *
489817466cbSJens Wiklander  *  AttributeValue ::= ANY DEFINED BY AttributeType
490817466cbSJens Wiklander  *
491817466cbSJens Wiklander  * The data structure is optimized for the common case where each RDN has only
492817466cbSJens Wiklander  * one element, which is represented as a list of AttributeTypeAndValue.
493817466cbSJens Wiklander  * For the general case we still use a flat list, but we mark elements of the
494817466cbSJens Wiklander  * same set so that they are "merged" together in the functions that consume
495817466cbSJens Wiklander  * this list, eg mbedtls_x509_dn_gets().
496*32b31808SJens Wiklander  *
497*32b31808SJens Wiklander  * On success, this function may allocate a linked list starting at cur->next
498*32b31808SJens Wiklander  * that must later be free'd by the caller using mbedtls_free(). In error
499*32b31808SJens Wiklander  * cases, this function frees all allocated memory internally and the caller
500*32b31808SJens Wiklander  * has no freeing responsibilities.
501817466cbSJens Wiklander  */
502817466cbSJens Wiklander int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
503817466cbSJens Wiklander                           mbedtls_x509_name *cur)
504817466cbSJens Wiklander {
50511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
506817466cbSJens Wiklander     size_t set_len;
507817466cbSJens Wiklander     const unsigned char *end_set;
508*32b31808SJens Wiklander     mbedtls_x509_name *head = cur;
509817466cbSJens Wiklander 
510817466cbSJens Wiklander     /* don't use recursion, we'd risk stack overflow if not optimized */
511*32b31808SJens Wiklander     while (1) {
512817466cbSJens Wiklander         /*
513817466cbSJens Wiklander          * parse SET
514817466cbSJens Wiklander          */
515817466cbSJens Wiklander         if ((ret = mbedtls_asn1_get_tag(p, end, &set_len,
516*32b31808SJens Wiklander                                         MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
517*32b31808SJens Wiklander             ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
518*32b31808SJens Wiklander             goto error;
519*32b31808SJens Wiklander         }
520817466cbSJens Wiklander 
521817466cbSJens Wiklander         end_set  = *p + set_len;
522817466cbSJens Wiklander 
523*32b31808SJens Wiklander         while (1) {
524*32b31808SJens Wiklander             if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) {
525*32b31808SJens Wiklander                 goto error;
526*32b31808SJens Wiklander             }
527817466cbSJens Wiklander 
528*32b31808SJens Wiklander             if (*p == end_set) {
529817466cbSJens Wiklander                 break;
530*32b31808SJens Wiklander             }
531817466cbSJens Wiklander 
532817466cbSJens Wiklander             /* Mark this item as being no the only one in a set */
533817466cbSJens Wiklander             cur->next_merged = 1;
534817466cbSJens Wiklander 
535817466cbSJens Wiklander             cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
536817466cbSJens Wiklander 
537*32b31808SJens Wiklander             if (cur->next == NULL) {
538*32b31808SJens Wiklander                 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
539*32b31808SJens Wiklander                 goto error;
540*32b31808SJens Wiklander             }
541817466cbSJens Wiklander 
542817466cbSJens Wiklander             cur = cur->next;
543817466cbSJens Wiklander         }
544817466cbSJens Wiklander 
545817466cbSJens Wiklander         /*
546817466cbSJens Wiklander          * continue until end of SEQUENCE is reached
547817466cbSJens Wiklander          */
548*32b31808SJens Wiklander         if (*p == end) {
549*32b31808SJens Wiklander             return 0;
550*32b31808SJens Wiklander         }
551817466cbSJens Wiklander 
552817466cbSJens Wiklander         cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
553817466cbSJens Wiklander 
554*32b31808SJens Wiklander         if (cur->next == NULL) {
555*32b31808SJens Wiklander             ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
556*32b31808SJens Wiklander             goto error;
557*32b31808SJens Wiklander         }
558817466cbSJens Wiklander 
559817466cbSJens Wiklander         cur = cur->next;
560817466cbSJens Wiklander     }
561*32b31808SJens Wiklander 
562*32b31808SJens Wiklander error:
563*32b31808SJens Wiklander     /* Skip the first element as we did not allocate it */
564*32b31808SJens Wiklander     mbedtls_asn1_free_named_data_list_shallow(head->next);
565*32b31808SJens Wiklander     head->next = NULL;
566*32b31808SJens Wiklander 
567*32b31808SJens Wiklander     return ret;
568817466cbSJens Wiklander }
569817466cbSJens Wiklander 
570817466cbSJens Wiklander static int x509_parse_int(unsigned char **p, size_t n, int *res)
571817466cbSJens Wiklander {
572817466cbSJens Wiklander     *res = 0;
573817466cbSJens Wiklander 
574*32b31808SJens Wiklander     for (; n > 0; --n) {
575*32b31808SJens Wiklander         if ((**p < '0') || (**p > '9')) {
576*32b31808SJens Wiklander             return MBEDTLS_ERR_X509_INVALID_DATE;
577*32b31808SJens Wiklander         }
578817466cbSJens Wiklander 
579817466cbSJens Wiklander         *res *= 10;
580817466cbSJens Wiklander         *res += (*(*p)++ - '0');
581817466cbSJens Wiklander     }
582817466cbSJens Wiklander 
583*32b31808SJens Wiklander     return 0;
584817466cbSJens Wiklander }
585817466cbSJens Wiklander 
586817466cbSJens Wiklander static int x509_date_is_valid(const mbedtls_x509_time *t)
587817466cbSJens Wiklander {
588817466cbSJens Wiklander     int ret = MBEDTLS_ERR_X509_INVALID_DATE;
5893d3b0591SJens Wiklander     int month_len;
590817466cbSJens Wiklander 
591817466cbSJens Wiklander     CHECK_RANGE(0, 9999, t->year);
592817466cbSJens Wiklander     CHECK_RANGE(0, 23,   t->hour);
593817466cbSJens Wiklander     CHECK_RANGE(0, 59,   t->min);
594817466cbSJens Wiklander     CHECK_RANGE(0, 59,   t->sec);
595817466cbSJens Wiklander 
596*32b31808SJens Wiklander     switch (t->mon) {
597817466cbSJens Wiklander         case 1: case 3: case 5: case 7: case 8: case 10: case 12:
5983d3b0591SJens Wiklander             month_len = 31;
599817466cbSJens Wiklander             break;
600817466cbSJens Wiklander         case 4: case 6: case 9: case 11:
6013d3b0591SJens Wiklander             month_len = 30;
602817466cbSJens Wiklander             break;
603817466cbSJens Wiklander         case 2:
6043d3b0591SJens Wiklander             if ((!(t->year % 4) && t->year % 100) ||
605*32b31808SJens Wiklander                 !(t->year % 400)) {
6063d3b0591SJens Wiklander                 month_len = 29;
607*32b31808SJens Wiklander             } else {
6083d3b0591SJens Wiklander                 month_len = 28;
609*32b31808SJens Wiklander             }
610817466cbSJens Wiklander             break;
611817466cbSJens Wiklander         default:
612*32b31808SJens Wiklander             return ret;
613817466cbSJens Wiklander     }
6143d3b0591SJens Wiklander     CHECK_RANGE(1, month_len, t->day);
615817466cbSJens Wiklander 
616*32b31808SJens Wiklander     return 0;
617817466cbSJens Wiklander }
618817466cbSJens Wiklander 
619817466cbSJens Wiklander /*
620817466cbSJens Wiklander  * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
621817466cbSJens Wiklander  * field.
622817466cbSJens Wiklander  */
623817466cbSJens Wiklander static int x509_parse_time(unsigned char **p, size_t len, size_t yearlen,
624817466cbSJens Wiklander                            mbedtls_x509_time *tm)
625817466cbSJens Wiklander {
62611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
627817466cbSJens Wiklander 
628817466cbSJens Wiklander     /*
629817466cbSJens Wiklander      * Minimum length is 10 or 12 depending on yearlen
630817466cbSJens Wiklander      */
631*32b31808SJens Wiklander     if (len < yearlen + 8) {
632*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_INVALID_DATE;
633*32b31808SJens Wiklander     }
634817466cbSJens Wiklander     len -= yearlen + 8;
635817466cbSJens Wiklander 
636817466cbSJens Wiklander     /*
637817466cbSJens Wiklander      * Parse year, month, day, hour, minute
638817466cbSJens Wiklander      */
639817466cbSJens Wiklander     CHECK(x509_parse_int(p, yearlen, &tm->year));
640*32b31808SJens Wiklander     if (2 == yearlen) {
641*32b31808SJens Wiklander         if (tm->year < 50) {
642817466cbSJens Wiklander             tm->year += 100;
643*32b31808SJens Wiklander         }
644817466cbSJens Wiklander 
645817466cbSJens Wiklander         tm->year += 1900;
646817466cbSJens Wiklander     }
647817466cbSJens Wiklander 
648817466cbSJens Wiklander     CHECK(x509_parse_int(p, 2, &tm->mon));
649817466cbSJens Wiklander     CHECK(x509_parse_int(p, 2, &tm->day));
650817466cbSJens Wiklander     CHECK(x509_parse_int(p, 2, &tm->hour));
651817466cbSJens Wiklander     CHECK(x509_parse_int(p, 2, &tm->min));
652817466cbSJens Wiklander 
653817466cbSJens Wiklander     /*
654817466cbSJens Wiklander      * Parse seconds if present
655817466cbSJens Wiklander      */
656*32b31808SJens Wiklander     if (len >= 2) {
657817466cbSJens Wiklander         CHECK(x509_parse_int(p, 2, &tm->sec));
658817466cbSJens Wiklander         len -= 2;
659*32b31808SJens Wiklander     } else {
660*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_INVALID_DATE;
661817466cbSJens Wiklander     }
662817466cbSJens Wiklander 
663817466cbSJens Wiklander     /*
664817466cbSJens Wiklander      * Parse trailing 'Z' if present
665817466cbSJens Wiklander      */
666*32b31808SJens Wiklander     if (1 == len && 'Z' == **p) {
667817466cbSJens Wiklander         (*p)++;
668817466cbSJens Wiklander         len--;
669817466cbSJens Wiklander     }
670817466cbSJens Wiklander 
671817466cbSJens Wiklander     /*
672817466cbSJens Wiklander      * We should have parsed all characters at this point
673817466cbSJens Wiklander      */
674*32b31808SJens Wiklander     if (0 != len) {
675*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_INVALID_DATE;
676*32b31808SJens Wiklander     }
677817466cbSJens Wiklander 
678817466cbSJens Wiklander     CHECK(x509_date_is_valid(tm));
679817466cbSJens Wiklander 
680*32b31808SJens Wiklander     return 0;
681817466cbSJens Wiklander }
682817466cbSJens Wiklander 
683817466cbSJens Wiklander /*
684817466cbSJens Wiklander  *  Time ::= CHOICE {
685817466cbSJens Wiklander  *       utcTime        UTCTime,
686817466cbSJens Wiklander  *       generalTime    GeneralizedTime }
687817466cbSJens Wiklander  */
688817466cbSJens Wiklander int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,
689817466cbSJens Wiklander                           mbedtls_x509_time *tm)
690817466cbSJens Wiklander {
69111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
692817466cbSJens Wiklander     size_t len, year_len;
693817466cbSJens Wiklander     unsigned char tag;
694817466cbSJens Wiklander 
695*32b31808SJens Wiklander     if ((end - *p) < 1) {
696*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
697*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
698*32b31808SJens Wiklander     }
699817466cbSJens Wiklander 
700817466cbSJens Wiklander     tag = **p;
701817466cbSJens Wiklander 
702*32b31808SJens Wiklander     if (tag == MBEDTLS_ASN1_UTC_TIME) {
703817466cbSJens Wiklander         year_len = 2;
704*32b31808SJens Wiklander     } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) {
705817466cbSJens Wiklander         year_len = 4;
706*32b31808SJens Wiklander     } else {
707*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
708*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
709*32b31808SJens Wiklander     }
710817466cbSJens Wiklander 
711817466cbSJens Wiklander     (*p)++;
712817466cbSJens Wiklander     ret = mbedtls_asn1_get_len(p, end, &len);
713817466cbSJens Wiklander 
714*32b31808SJens Wiklander     if (ret != 0) {
715*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret);
716*32b31808SJens Wiklander     }
717817466cbSJens Wiklander 
718817466cbSJens Wiklander     return x509_parse_time(p, len, year_len, tm);
719817466cbSJens Wiklander }
720817466cbSJens Wiklander 
721817466cbSJens Wiklander int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig)
722817466cbSJens Wiklander {
72311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
724817466cbSJens Wiklander     size_t len;
725817466cbSJens Wiklander     int tag_type;
726817466cbSJens Wiklander 
727*32b31808SJens Wiklander     if ((end - *p) < 1) {
728*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE,
729*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
730*32b31808SJens Wiklander     }
731817466cbSJens Wiklander 
732817466cbSJens Wiklander     tag_type = **p;
733817466cbSJens Wiklander 
734*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
735*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret);
736*32b31808SJens Wiklander     }
737817466cbSJens Wiklander 
738817466cbSJens Wiklander     sig->tag = tag_type;
739817466cbSJens Wiklander     sig->len = len;
740817466cbSJens Wiklander     sig->p = *p;
741817466cbSJens Wiklander 
742817466cbSJens Wiklander     *p += len;
743817466cbSJens Wiklander 
744*32b31808SJens Wiklander     return 0;
745817466cbSJens Wiklander }
746817466cbSJens Wiklander 
747817466cbSJens Wiklander /*
748817466cbSJens Wiklander  * Get signature algorithm from alg OID and optional parameters
749817466cbSJens Wiklander  */
750817466cbSJens Wiklander int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
751817466cbSJens Wiklander                              mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
752817466cbSJens Wiklander                              void **sig_opts)
753817466cbSJens Wiklander {
75411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
755817466cbSJens Wiklander 
756*32b31808SJens Wiklander     if (*sig_opts != NULL) {
757*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
758*32b31808SJens Wiklander     }
759817466cbSJens Wiklander 
760*32b31808SJens Wiklander     if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) {
761*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret);
762*32b31808SJens Wiklander     }
763817466cbSJens Wiklander 
764817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
765*32b31808SJens Wiklander     if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) {
766817466cbSJens Wiklander         mbedtls_pk_rsassa_pss_options *pss_opts;
767817466cbSJens Wiklander 
768817466cbSJens Wiklander         pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options));
769*32b31808SJens Wiklander         if (pss_opts == NULL) {
770*32b31808SJens Wiklander             return MBEDTLS_ERR_X509_ALLOC_FAILED;
771*32b31808SJens Wiklander         }
772817466cbSJens Wiklander 
773817466cbSJens Wiklander         ret = mbedtls_x509_get_rsassa_pss_params(sig_params,
774817466cbSJens Wiklander                                                  md_alg,
775817466cbSJens Wiklander                                                  &pss_opts->mgf1_hash_id,
776817466cbSJens Wiklander                                                  &pss_opts->expected_salt_len);
777*32b31808SJens Wiklander         if (ret != 0) {
778817466cbSJens Wiklander             mbedtls_free(pss_opts);
779*32b31808SJens Wiklander             return ret;
780817466cbSJens Wiklander         }
781817466cbSJens Wiklander 
782817466cbSJens Wiklander         *sig_opts = (void *) pss_opts;
783*32b31808SJens Wiklander     } else
784817466cbSJens Wiklander #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
785817466cbSJens Wiklander     {
786817466cbSJens Wiklander         /* Make sure parameters are absent or NULL */
787817466cbSJens Wiklander         if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) ||
788*32b31808SJens Wiklander             sig_params->len != 0) {
789*32b31808SJens Wiklander             return MBEDTLS_ERR_X509_INVALID_ALG;
790*32b31808SJens Wiklander         }
791817466cbSJens Wiklander     }
792817466cbSJens Wiklander 
793*32b31808SJens Wiklander     return 0;
794817466cbSJens Wiklander }
795817466cbSJens Wiklander 
796817466cbSJens Wiklander /*
797817466cbSJens Wiklander  * X.509 Extensions (No parsing of extensions, pointer should
798817466cbSJens Wiklander  * be either manually updated or extensions should be parsed!)
799817466cbSJens Wiklander  */
800817466cbSJens Wiklander int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,
801817466cbSJens Wiklander                          mbedtls_x509_buf *ext, int tag)
802817466cbSJens Wiklander {
80311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
804817466cbSJens Wiklander     size_t len;
805817466cbSJens Wiklander 
8065b25c76aSJerome Forissier     /* Extension structure use EXPLICIT tagging. That is, the actual
8075b25c76aSJerome Forissier      * `Extensions` structure is wrapped by a tag-length pair using
8085b25c76aSJerome Forissier      * the respective context-specific tag. */
8095b25c76aSJerome Forissier     ret = mbedtls_asn1_get_tag(p, end, &ext->len,
8105b25c76aSJerome Forissier                                MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag);
811*32b31808SJens Wiklander     if (ret != 0) {
812*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
813*32b31808SJens Wiklander     }
814817466cbSJens Wiklander 
8155b25c76aSJerome Forissier     ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag;
816817466cbSJens Wiklander     ext->p   = *p;
817817466cbSJens Wiklander     end      = *p + ext->len;
818817466cbSJens Wiklander 
819817466cbSJens Wiklander     /*
820817466cbSJens Wiklander      * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
821817466cbSJens Wiklander      */
822817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
823*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
824*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
825*32b31808SJens Wiklander     }
826817466cbSJens Wiklander 
827*32b31808SJens Wiklander     if (end != *p + len) {
828*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
829*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
830*32b31808SJens Wiklander     }
831817466cbSJens Wiklander 
832*32b31808SJens Wiklander     return 0;
833817466cbSJens Wiklander }
834817466cbSJens Wiklander 
835817466cbSJens Wiklander /*
836817466cbSJens Wiklander  * Store the name in printable form into buf; no more
837817466cbSJens Wiklander  * than size characters will be written
838817466cbSJens Wiklander  */
839817466cbSJens Wiklander int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn)
840817466cbSJens Wiklander {
84111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
842039e02dfSJerome Forissier     size_t i, j, n;
843817466cbSJens Wiklander     unsigned char c, merge = 0;
844817466cbSJens Wiklander     const mbedtls_x509_name *name;
845817466cbSJens Wiklander     const char *short_name = NULL;
846817466cbSJens Wiklander     char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
847817466cbSJens Wiklander 
848817466cbSJens Wiklander     memset(s, 0, sizeof(s));
849817466cbSJens Wiklander 
850817466cbSJens Wiklander     name = dn;
851817466cbSJens Wiklander     p = buf;
852817466cbSJens Wiklander     n = size;
853817466cbSJens Wiklander 
854*32b31808SJens Wiklander     while (name != NULL) {
855*32b31808SJens Wiklander         if (!name->oid.p) {
856817466cbSJens Wiklander             name = name->next;
857817466cbSJens Wiklander             continue;
858817466cbSJens Wiklander         }
859817466cbSJens Wiklander 
860*32b31808SJens Wiklander         if (name != dn) {
861817466cbSJens Wiklander             ret = mbedtls_snprintf(p, n, merge ? " + " : ", ");
862817466cbSJens Wiklander             MBEDTLS_X509_SAFE_SNPRINTF;
863817466cbSJens Wiklander         }
864817466cbSJens Wiklander 
865817466cbSJens Wiklander         ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name);
866817466cbSJens Wiklander 
867*32b31808SJens Wiklander         if (ret == 0) {
868817466cbSJens Wiklander             ret = mbedtls_snprintf(p, n, "%s=", short_name);
869*32b31808SJens Wiklander         } else {
870817466cbSJens Wiklander             ret = mbedtls_snprintf(p, n, "\?\?=");
871*32b31808SJens Wiklander         }
872817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
873817466cbSJens Wiklander 
874*32b31808SJens Wiklander         for (i = 0, j = 0; i < name->val.len; i++, j++) {
875*32b31808SJens Wiklander             if (j >= sizeof(s) - 1) {
876*32b31808SJens Wiklander                 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
877*32b31808SJens Wiklander             }
878817466cbSJens Wiklander 
879817466cbSJens Wiklander             c = name->val.p[i];
880039e02dfSJerome Forissier             // Special characters requiring escaping, RFC 1779
881*32b31808SJens Wiklander             if (c && strchr(",=+<>#;\"\\", c)) {
882*32b31808SJens Wiklander                 if (j + 1 >= sizeof(s) - 1) {
883*32b31808SJens Wiklander                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
884*32b31808SJens Wiklander                 }
885039e02dfSJerome Forissier                 s[j++] = '\\';
886817466cbSJens Wiklander             }
887*32b31808SJens Wiklander             if (c < 32 || c >= 127) {
888039e02dfSJerome Forissier                 s[j] = '?';
889*32b31808SJens Wiklander             } else {
890*32b31808SJens Wiklander                 s[j] = c;
891*32b31808SJens Wiklander             }
892039e02dfSJerome Forissier         }
893039e02dfSJerome Forissier         s[j] = '\0';
894817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, "%s", s);
895817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
896817466cbSJens Wiklander 
897817466cbSJens Wiklander         merge = name->next_merged;
898817466cbSJens Wiklander         name = name->next;
899817466cbSJens Wiklander     }
900817466cbSJens Wiklander 
901*32b31808SJens Wiklander     return (int) (size - n);
902817466cbSJens Wiklander }
903817466cbSJens Wiklander 
904817466cbSJens Wiklander /*
905817466cbSJens Wiklander  * Store the serial in printable form into buf; no more
906817466cbSJens Wiklander  * than size characters will be written
907817466cbSJens Wiklander  */
908817466cbSJens Wiklander int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial)
909817466cbSJens Wiklander {
91011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
911817466cbSJens Wiklander     size_t i, n, nr;
912817466cbSJens Wiklander     char *p;
913817466cbSJens Wiklander 
914817466cbSJens Wiklander     p = buf;
915817466cbSJens Wiklander     n = size;
916817466cbSJens Wiklander 
917817466cbSJens Wiklander     nr = (serial->len <= 32)
918817466cbSJens Wiklander         ? serial->len  : 28;
919817466cbSJens Wiklander 
920*32b31808SJens Wiklander     for (i = 0; i < nr; i++) {
921*32b31808SJens Wiklander         if (i == 0 && nr > 1 && serial->p[i] == 0x0) {
922817466cbSJens Wiklander             continue;
923*32b31808SJens Wiklander         }
924817466cbSJens Wiklander 
925817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, "%02X%s",
926817466cbSJens Wiklander                                serial->p[i], (i < nr - 1) ? ":" : "");
927817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
928817466cbSJens Wiklander     }
929817466cbSJens Wiklander 
930*32b31808SJens Wiklander     if (nr != serial->len) {
931817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, "....");
932817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
933817466cbSJens Wiklander     }
934817466cbSJens Wiklander 
935*32b31808SJens Wiklander     return (int) (size - n);
936817466cbSJens Wiklander }
937817466cbSJens Wiklander 
938*32b31808SJens Wiklander #if !defined(MBEDTLS_X509_REMOVE_INFO)
939817466cbSJens Wiklander /*
940817466cbSJens Wiklander  * Helper for writing signature algorithms
941817466cbSJens Wiklander  */
942817466cbSJens Wiklander int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
943817466cbSJens Wiklander                               mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
944817466cbSJens Wiklander                               const void *sig_opts)
945817466cbSJens Wiklander {
94611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
947817466cbSJens Wiklander     char *p = buf;
948817466cbSJens Wiklander     size_t n = size;
949817466cbSJens Wiklander     const char *desc = NULL;
950817466cbSJens Wiklander 
951817466cbSJens Wiklander     ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc);
952*32b31808SJens Wiklander     if (ret != 0) {
953817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, "???");
954*32b31808SJens Wiklander     } else {
955817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, "%s", desc);
956*32b31808SJens Wiklander     }
957817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
958817466cbSJens Wiklander 
959817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
960*32b31808SJens Wiklander     if (pk_alg == MBEDTLS_PK_RSASSA_PSS) {
961817466cbSJens Wiklander         const mbedtls_pk_rsassa_pss_options *pss_opts;
962817466cbSJens Wiklander 
963817466cbSJens Wiklander         pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
964817466cbSJens Wiklander 
965*32b31808SJens Wiklander         const char *name = md_type_to_string(md_alg);
966*32b31808SJens Wiklander         const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id);
967817466cbSJens Wiklander 
968817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)",
969*32b31808SJens Wiklander                                name ? name : "???",
970*32b31808SJens Wiklander                                mgf_name ? mgf_name : "???",
9717901324dSJerome Forissier                                (unsigned int) pss_opts->expected_salt_len);
972817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
973817466cbSJens Wiklander     }
974817466cbSJens Wiklander #else
975817466cbSJens Wiklander     ((void) pk_alg);
976817466cbSJens Wiklander     ((void) md_alg);
977817466cbSJens Wiklander     ((void) sig_opts);
978817466cbSJens Wiklander #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
979817466cbSJens Wiklander 
980*32b31808SJens Wiklander     return (int) (size - n);
981817466cbSJens Wiklander }
982*32b31808SJens Wiklander #endif /* MBEDTLS_X509_REMOVE_INFO */
983817466cbSJens Wiklander 
984817466cbSJens Wiklander /*
985817466cbSJens Wiklander  * Helper for writing "RSA key size", "EC key size", etc
986817466cbSJens Wiklander  */
987817466cbSJens Wiklander int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name)
988817466cbSJens Wiklander {
989817466cbSJens Wiklander     char *p = buf;
990817466cbSJens Wiklander     size_t n = buf_size;
99111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
992817466cbSJens Wiklander 
993817466cbSJens Wiklander     ret = mbedtls_snprintf(p, n, "%s key size", name);
994817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
995817466cbSJens Wiklander 
996*32b31808SJens Wiklander     return 0;
997817466cbSJens Wiklander }
998817466cbSJens Wiklander 
999817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_TIME_DATE)
1000817466cbSJens Wiklander /*
1001817466cbSJens Wiklander  * Set the time structure to the current time.
1002817466cbSJens Wiklander  * Return 0 on success, non-zero on failure.
1003817466cbSJens Wiklander  */
1004817466cbSJens Wiklander static int x509_get_current_time(mbedtls_x509_time *now)
1005817466cbSJens Wiklander {
10063d3b0591SJens Wiklander     struct tm *lt, tm_buf;
1007817466cbSJens Wiklander     mbedtls_time_t tt;
1008817466cbSJens Wiklander     int ret = 0;
1009817466cbSJens Wiklander 
1010817466cbSJens Wiklander     tt = mbedtls_time(NULL);
10113d3b0591SJens Wiklander     lt = mbedtls_platform_gmtime_r(&tt, &tm_buf);
1012817466cbSJens Wiklander 
1013*32b31808SJens Wiklander     if (lt == NULL) {
1014817466cbSJens Wiklander         ret = -1;
1015*32b31808SJens Wiklander     } else {
1016817466cbSJens Wiklander         now->year = lt->tm_year + 1900;
1017817466cbSJens Wiklander         now->mon  = lt->tm_mon  + 1;
1018817466cbSJens Wiklander         now->day  = lt->tm_mday;
1019817466cbSJens Wiklander         now->hour = lt->tm_hour;
1020817466cbSJens Wiklander         now->min  = lt->tm_min;
1021817466cbSJens Wiklander         now->sec  = lt->tm_sec;
1022817466cbSJens Wiklander     }
1023817466cbSJens Wiklander 
1024*32b31808SJens Wiklander     return ret;
1025817466cbSJens Wiklander }
1026817466cbSJens Wiklander 
1027817466cbSJens Wiklander /*
1028817466cbSJens Wiklander  * Return 0 if before <= after, 1 otherwise
1029817466cbSJens Wiklander  */
1030817466cbSJens Wiklander static int x509_check_time(const mbedtls_x509_time *before, const mbedtls_x509_time *after)
1031817466cbSJens Wiklander {
1032*32b31808SJens Wiklander     if (before->year  > after->year) {
1033*32b31808SJens Wiklander         return 1;
1034*32b31808SJens Wiklander     }
1035817466cbSJens Wiklander 
1036817466cbSJens Wiklander     if (before->year == after->year &&
1037*32b31808SJens Wiklander         before->mon   > after->mon) {
1038*32b31808SJens Wiklander         return 1;
1039*32b31808SJens Wiklander     }
1040817466cbSJens Wiklander 
1041817466cbSJens Wiklander     if (before->year == after->year &&
1042817466cbSJens Wiklander         before->mon  == after->mon  &&
1043*32b31808SJens Wiklander         before->day   > after->day) {
1044*32b31808SJens Wiklander         return 1;
1045*32b31808SJens Wiklander     }
1046817466cbSJens Wiklander 
1047817466cbSJens Wiklander     if (before->year == after->year &&
1048817466cbSJens Wiklander         before->mon  == after->mon  &&
1049817466cbSJens Wiklander         before->day  == after->day  &&
1050*32b31808SJens Wiklander         before->hour  > after->hour) {
1051*32b31808SJens Wiklander         return 1;
1052*32b31808SJens Wiklander     }
1053817466cbSJens Wiklander 
1054817466cbSJens Wiklander     if (before->year == after->year &&
1055817466cbSJens Wiklander         before->mon  == after->mon  &&
1056817466cbSJens Wiklander         before->day  == after->day  &&
1057817466cbSJens Wiklander         before->hour == after->hour &&
1058*32b31808SJens Wiklander         before->min   > after->min) {
1059*32b31808SJens Wiklander         return 1;
1060*32b31808SJens Wiklander     }
1061817466cbSJens Wiklander 
1062817466cbSJens Wiklander     if (before->year == after->year &&
1063817466cbSJens Wiklander         before->mon  == after->mon  &&
1064817466cbSJens Wiklander         before->day  == after->day  &&
1065817466cbSJens Wiklander         before->hour == after->hour &&
1066817466cbSJens Wiklander         before->min  == after->min  &&
1067*32b31808SJens Wiklander         before->sec   > after->sec) {
1068*32b31808SJens Wiklander         return 1;
1069*32b31808SJens Wiklander     }
1070817466cbSJens Wiklander 
1071*32b31808SJens Wiklander     return 0;
1072817466cbSJens Wiklander }
1073817466cbSJens Wiklander 
1074817466cbSJens Wiklander int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
1075817466cbSJens Wiklander {
1076817466cbSJens Wiklander     mbedtls_x509_time now;
1077817466cbSJens Wiklander 
1078*32b31808SJens Wiklander     if (x509_get_current_time(&now) != 0) {
1079*32b31808SJens Wiklander         return 1;
1080*32b31808SJens Wiklander     }
1081817466cbSJens Wiklander 
1082*32b31808SJens Wiklander     return x509_check_time(&now, to);
1083817466cbSJens Wiklander }
1084817466cbSJens Wiklander 
1085817466cbSJens Wiklander int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
1086817466cbSJens Wiklander {
1087817466cbSJens Wiklander     mbedtls_x509_time now;
1088817466cbSJens Wiklander 
1089*32b31808SJens Wiklander     if (x509_get_current_time(&now) != 0) {
1090*32b31808SJens Wiklander         return 1;
1091*32b31808SJens Wiklander     }
1092817466cbSJens Wiklander 
1093*32b31808SJens Wiklander     return x509_check_time(from, &now);
1094817466cbSJens Wiklander }
1095817466cbSJens Wiklander 
1096817466cbSJens Wiklander #else  /* MBEDTLS_HAVE_TIME_DATE */
1097817466cbSJens Wiklander 
1098817466cbSJens Wiklander int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
1099817466cbSJens Wiklander {
1100817466cbSJens Wiklander     ((void) to);
1101*32b31808SJens Wiklander     return 0;
1102817466cbSJens Wiklander }
1103817466cbSJens Wiklander 
1104817466cbSJens Wiklander int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
1105817466cbSJens Wiklander {
1106817466cbSJens Wiklander     ((void) from);
1107*32b31808SJens Wiklander     return 0;
1108817466cbSJens Wiklander }
1109817466cbSJens Wiklander #endif /* MBEDTLS_HAVE_TIME_DATE */
1110817466cbSJens Wiklander 
1111*32b31808SJens Wiklander /* Common functions for parsing CRT and CSR. */
1112*32b31808SJens Wiklander #if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C)
1113817466cbSJens Wiklander /*
1114*32b31808SJens Wiklander  * OtherName ::= SEQUENCE {
1115*32b31808SJens Wiklander  *      type-id    OBJECT IDENTIFIER,
1116*32b31808SJens Wiklander  *      value      [0] EXPLICIT ANY DEFINED BY type-id }
1117*32b31808SJens Wiklander  *
1118*32b31808SJens Wiklander  * HardwareModuleName ::= SEQUENCE {
1119*32b31808SJens Wiklander  *                           hwType OBJECT IDENTIFIER,
1120*32b31808SJens Wiklander  *                           hwSerialNum OCTET STRING }
1121*32b31808SJens Wiklander  *
1122*32b31808SJens Wiklander  * NOTE: we currently only parse and use otherName of type HwModuleName,
1123*32b31808SJens Wiklander  * as defined in RFC 4108.
1124817466cbSJens Wiklander  */
1125*32b31808SJens Wiklander static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name,
1126*32b31808SJens Wiklander                                mbedtls_x509_san_other_name *other_name)
1127817466cbSJens Wiklander {
11285b25c76aSJerome Forissier     int ret = 0;
1129*32b31808SJens Wiklander     size_t len;
1130*32b31808SJens Wiklander     unsigned char *p = subject_alt_name->p;
1131*32b31808SJens Wiklander     const unsigned char *end = p + subject_alt_name->len;
1132*32b31808SJens Wiklander     mbedtls_x509_buf cur_oid;
1133817466cbSJens Wiklander 
1134*32b31808SJens Wiklander     if ((subject_alt_name->tag &
1135*32b31808SJens Wiklander          (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) !=
1136*32b31808SJens Wiklander         (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) {
1137*32b31808SJens Wiklander         /*
1138*32b31808SJens Wiklander          * The given subject alternative name is not of type "othername".
1139*32b31808SJens Wiklander          */
1140*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1141*32b31808SJens Wiklander     }
1142817466cbSJens Wiklander 
1143*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1144*32b31808SJens Wiklander                                     MBEDTLS_ASN1_OID)) != 0) {
1145*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1146*32b31808SJens Wiklander     }
1147817466cbSJens Wiklander 
1148*32b31808SJens Wiklander     cur_oid.tag = MBEDTLS_ASN1_OID;
1149*32b31808SJens Wiklander     cur_oid.p = p;
1150*32b31808SJens Wiklander     cur_oid.len = len;
1151*32b31808SJens Wiklander 
1152*32b31808SJens Wiklander     /*
1153*32b31808SJens Wiklander      * Only HwModuleName is currently supported.
1154*32b31808SJens Wiklander      */
1155*32b31808SJens Wiklander     if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) {
1156*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
1157*32b31808SJens Wiklander     }
1158*32b31808SJens Wiklander 
1159*32b31808SJens Wiklander     p += len;
1160*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1161*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
1162*32b31808SJens Wiklander         0) {
1163*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1164*32b31808SJens Wiklander     }
1165*32b31808SJens Wiklander 
1166*32b31808SJens Wiklander     if (end != p + len) {
1167*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1168*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1169*32b31808SJens Wiklander     }
1170*32b31808SJens Wiklander 
1171*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1172*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1173*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1174*32b31808SJens Wiklander     }
1175*32b31808SJens Wiklander 
1176*32b31808SJens Wiklander     if (end != p + len) {
1177*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1178*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1179*32b31808SJens Wiklander     }
1180*32b31808SJens Wiklander 
1181*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
1182*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1183*32b31808SJens Wiklander     }
1184*32b31808SJens Wiklander 
1185*32b31808SJens Wiklander     other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
1186*32b31808SJens Wiklander     other_name->value.hardware_module_name.oid.p = p;
1187*32b31808SJens Wiklander     other_name->value.hardware_module_name.oid.len = len;
1188*32b31808SJens Wiklander 
1189*32b31808SJens Wiklander     p += len;
1190*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1191*32b31808SJens Wiklander                                     MBEDTLS_ASN1_OCTET_STRING)) != 0) {
1192*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1193*32b31808SJens Wiklander     }
1194*32b31808SJens Wiklander 
1195*32b31808SJens Wiklander     other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
1196*32b31808SJens Wiklander     other_name->value.hardware_module_name.val.p = p;
1197*32b31808SJens Wiklander     other_name->value.hardware_module_name.val.len = len;
1198*32b31808SJens Wiklander     p += len;
1199*32b31808SJens Wiklander     if (p != end) {
1200*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1201*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1202*32b31808SJens Wiklander     }
1203*32b31808SJens Wiklander     return 0;
1204*32b31808SJens Wiklander }
1205*32b31808SJens Wiklander 
1206*32b31808SJens Wiklander /*
1207*32b31808SJens Wiklander  * SubjectAltName ::= GeneralNames
1208*32b31808SJens Wiklander  *
1209*32b31808SJens Wiklander  * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
1210*32b31808SJens Wiklander  *
1211*32b31808SJens Wiklander  * GeneralName ::= CHOICE {
1212*32b31808SJens Wiklander  *      otherName                       [0]     OtherName,
1213*32b31808SJens Wiklander  *      rfc822Name                      [1]     IA5String,
1214*32b31808SJens Wiklander  *      dNSName                         [2]     IA5String,
1215*32b31808SJens Wiklander  *      x400Address                     [3]     ORAddress,
1216*32b31808SJens Wiklander  *      directoryName                   [4]     Name,
1217*32b31808SJens Wiklander  *      ediPartyName                    [5]     EDIPartyName,
1218*32b31808SJens Wiklander  *      uniformResourceIdentifier       [6]     IA5String,
1219*32b31808SJens Wiklander  *      iPAddress                       [7]     OCTET STRING,
1220*32b31808SJens Wiklander  *      registeredID                    [8]     OBJECT IDENTIFIER }
1221*32b31808SJens Wiklander  *
1222*32b31808SJens Wiklander  * OtherName ::= SEQUENCE {
1223*32b31808SJens Wiklander  *      type-id    OBJECT IDENTIFIER,
1224*32b31808SJens Wiklander  *      value      [0] EXPLICIT ANY DEFINED BY type-id }
1225*32b31808SJens Wiklander  *
1226*32b31808SJens Wiklander  * EDIPartyName ::= SEQUENCE {
1227*32b31808SJens Wiklander  *      nameAssigner            [0]     DirectoryString OPTIONAL,
1228*32b31808SJens Wiklander  *      partyName               [1]     DirectoryString }
1229*32b31808SJens Wiklander  *
1230*32b31808SJens Wiklander  * We list all types, but use the following GeneralName types from RFC 5280:
1231*32b31808SJens Wiklander  * "dnsName", "uniformResourceIdentifier" and "hardware_module_name"
1232*32b31808SJens Wiklander  * of type "otherName", as defined in RFC 4108.
1233*32b31808SJens Wiklander  */
1234*32b31808SJens Wiklander int mbedtls_x509_get_subject_alt_name(unsigned char **p,
1235*32b31808SJens Wiklander                                       const unsigned char *end,
1236*32b31808SJens Wiklander                                       mbedtls_x509_sequence *subject_alt_name)
1237817466cbSJens Wiklander {
1238*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1239*32b31808SJens Wiklander     size_t len, tag_len;
1240*32b31808SJens Wiklander     mbedtls_asn1_sequence *cur = subject_alt_name;
1241817466cbSJens Wiklander 
1242*32b31808SJens Wiklander     /* Get main sequence tag */
1243*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
1244*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1245*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1246817466cbSJens Wiklander     }
1247817466cbSJens Wiklander 
1248*32b31808SJens Wiklander     if (*p + len != end) {
1249*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1250*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1251*32b31808SJens Wiklander     }
1252*32b31808SJens Wiklander 
1253*32b31808SJens Wiklander     while (*p < end) {
1254*32b31808SJens Wiklander         mbedtls_x509_subject_alternative_name dummy_san_buf;
1255*32b31808SJens Wiklander         mbedtls_x509_buf tmp_san_buf;
1256*32b31808SJens Wiklander         memset(&dummy_san_buf, 0, sizeof(dummy_san_buf));
1257*32b31808SJens Wiklander 
1258*32b31808SJens Wiklander         tmp_san_buf.tag = **p;
1259*32b31808SJens Wiklander         (*p)++;
1260*32b31808SJens Wiklander 
1261*32b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) {
1262*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1263*32b31808SJens Wiklander         }
1264*32b31808SJens Wiklander 
1265*32b31808SJens Wiklander         tmp_san_buf.p = *p;
1266*32b31808SJens Wiklander         tmp_san_buf.len = tag_len;
1267*32b31808SJens Wiklander 
1268*32b31808SJens Wiklander         if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
1269*32b31808SJens Wiklander             MBEDTLS_ASN1_CONTEXT_SPECIFIC) {
1270*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1271*32b31808SJens Wiklander                                      MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
1272*32b31808SJens Wiklander         }
1273*32b31808SJens Wiklander 
1274*32b31808SJens Wiklander         /*
1275*32b31808SJens Wiklander          * Check that the SAN is structured correctly.
1276*32b31808SJens Wiklander          */
1277*32b31808SJens Wiklander         ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &dummy_san_buf);
1278*32b31808SJens Wiklander         /*
1279*32b31808SJens Wiklander          * In case the extension is malformed, return an error,
1280*32b31808SJens Wiklander          * and clear the allocated sequences.
1281*32b31808SJens Wiklander          */
1282*32b31808SJens Wiklander         if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
1283*32b31808SJens Wiklander             mbedtls_asn1_sequence_free(subject_alt_name->next);
1284*32b31808SJens Wiklander             subject_alt_name->next = NULL;
1285*32b31808SJens Wiklander             return ret;
1286*32b31808SJens Wiklander         }
1287*32b31808SJens Wiklander 
1288*32b31808SJens Wiklander         /* Allocate and assign next pointer */
1289*32b31808SJens Wiklander         if (cur->buf.p != NULL) {
1290*32b31808SJens Wiklander             if (cur->next != NULL) {
1291*32b31808SJens Wiklander                 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1292*32b31808SJens Wiklander             }
1293*32b31808SJens Wiklander 
1294*32b31808SJens Wiklander             cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
1295*32b31808SJens Wiklander 
1296*32b31808SJens Wiklander             if (cur->next == NULL) {
1297*32b31808SJens Wiklander                 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1298*32b31808SJens Wiklander                                          MBEDTLS_ERR_ASN1_ALLOC_FAILED);
1299*32b31808SJens Wiklander             }
1300*32b31808SJens Wiklander 
1301*32b31808SJens Wiklander             cur = cur->next;
1302*32b31808SJens Wiklander         }
1303*32b31808SJens Wiklander 
1304*32b31808SJens Wiklander         cur->buf = tmp_san_buf;
1305*32b31808SJens Wiklander         *p += tmp_san_buf.len;
1306*32b31808SJens Wiklander     }
1307*32b31808SJens Wiklander 
1308*32b31808SJens Wiklander     /* Set final sequence entry's next pointer to NULL */
1309*32b31808SJens Wiklander     cur->next = NULL;
1310*32b31808SJens Wiklander 
1311*32b31808SJens Wiklander     if (*p != end) {
1312*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1313*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1314*32b31808SJens Wiklander     }
1315*32b31808SJens Wiklander 
1316*32b31808SJens Wiklander     return 0;
1317*32b31808SJens Wiklander }
1318*32b31808SJens Wiklander 
1319*32b31808SJens Wiklander int mbedtls_x509_get_ns_cert_type(unsigned char **p,
1320*32b31808SJens Wiklander                                   const unsigned char *end,
1321*32b31808SJens Wiklander                                   unsigned char *ns_cert_type)
1322817466cbSJens Wiklander {
1323*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1324*32b31808SJens Wiklander     mbedtls_x509_bitstring bs = { 0, 0, NULL };
1325817466cbSJens Wiklander 
1326*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
1327*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1328817466cbSJens Wiklander     }
1329817466cbSJens Wiklander 
1330*32b31808SJens Wiklander     /* A bitstring with no flags set is still technically valid, as it will mean
1331*32b31808SJens Wiklander        that the certificate has no designated purpose at the time of creation. */
1332*32b31808SJens Wiklander     if (bs.len == 0) {
1333*32b31808SJens Wiklander         *ns_cert_type = 0;
1334*32b31808SJens Wiklander         return 0;
1335*32b31808SJens Wiklander     }
1336817466cbSJens Wiklander 
1337*32b31808SJens Wiklander     if (bs.len != 1) {
1338*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1339*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_INVALID_LENGTH);
1340*32b31808SJens Wiklander     }
1341*32b31808SJens Wiklander 
1342*32b31808SJens Wiklander     /* Get actual bitstring */
1343*32b31808SJens Wiklander     *ns_cert_type = *bs.p;
1344*32b31808SJens Wiklander     return 0;
1345*32b31808SJens Wiklander }
1346*32b31808SJens Wiklander 
1347*32b31808SJens Wiklander int mbedtls_x509_get_key_usage(unsigned char **p,
1348*32b31808SJens Wiklander                                const unsigned char *end,
1349*32b31808SJens Wiklander                                unsigned int *key_usage)
1350817466cbSJens Wiklander {
1351*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1352*32b31808SJens Wiklander     size_t i;
1353*32b31808SJens Wiklander     mbedtls_x509_bitstring bs = { 0, 0, NULL };
1354817466cbSJens Wiklander 
1355*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
1356*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1357817466cbSJens Wiklander     }
1358817466cbSJens Wiklander 
1359*32b31808SJens Wiklander     /* A bitstring with no flags set is still technically valid, as it will mean
1360*32b31808SJens Wiklander        that the certificate has no designated purpose at the time of creation. */
1361*32b31808SJens Wiklander     if (bs.len == 0) {
1362*32b31808SJens Wiklander         *key_usage = 0;
1363*32b31808SJens Wiklander         return 0;
1364817466cbSJens Wiklander     }
1365817466cbSJens Wiklander 
1366*32b31808SJens Wiklander     /* Get actual bitstring */
1367*32b31808SJens Wiklander     *key_usage = 0;
1368*32b31808SJens Wiklander     for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) {
1369*32b31808SJens Wiklander         *key_usage |= (unsigned int) bs.p[i] << (8*i);
1370*32b31808SJens Wiklander     }
1371817466cbSJens Wiklander 
1372*32b31808SJens Wiklander     return 0;
1373*32b31808SJens Wiklander }
1374*32b31808SJens Wiklander 
1375*32b31808SJens Wiklander int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
1376*32b31808SJens Wiklander                                         mbedtls_x509_subject_alternative_name *san)
1377*32b31808SJens Wiklander {
1378*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1379*32b31808SJens Wiklander     switch (san_buf->tag &
1380*32b31808SJens Wiklander             (MBEDTLS_ASN1_TAG_CLASS_MASK |
1381*32b31808SJens Wiklander              MBEDTLS_ASN1_TAG_VALUE_MASK)) {
1382*32b31808SJens Wiklander         /*
1383*32b31808SJens Wiklander          * otherName
1384*32b31808SJens Wiklander          */
1385*32b31808SJens Wiklander         case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME):
1386*32b31808SJens Wiklander         {
1387*32b31808SJens Wiklander             mbedtls_x509_san_other_name other_name;
1388*32b31808SJens Wiklander 
1389*32b31808SJens Wiklander             ret = x509_get_other_name(san_buf, &other_name);
1390*32b31808SJens Wiklander             if (ret != 0) {
1391*32b31808SJens Wiklander                 return ret;
1392*32b31808SJens Wiklander             }
1393*32b31808SJens Wiklander 
1394*32b31808SJens Wiklander             memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1395*32b31808SJens Wiklander             san->type = MBEDTLS_X509_SAN_OTHER_NAME;
1396*32b31808SJens Wiklander             memcpy(&san->san.other_name,
1397*32b31808SJens Wiklander                    &other_name, sizeof(other_name));
1398*32b31808SJens Wiklander 
1399*32b31808SJens Wiklander         }
1400*32b31808SJens Wiklander         break;
1401*32b31808SJens Wiklander         /*
1402*32b31808SJens Wiklander          * uniformResourceIdentifier
1403*32b31808SJens Wiklander          */
1404*32b31808SJens Wiklander         case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER):
1405*32b31808SJens Wiklander         {
1406*32b31808SJens Wiklander             memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1407*32b31808SJens Wiklander             san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;
1408*32b31808SJens Wiklander 
1409*32b31808SJens Wiklander             memcpy(&san->san.unstructured_name,
1410*32b31808SJens Wiklander                    san_buf, sizeof(*san_buf));
1411*32b31808SJens Wiklander 
1412*32b31808SJens Wiklander         }
1413*32b31808SJens Wiklander         break;
1414*32b31808SJens Wiklander         /*
1415*32b31808SJens Wiklander          * dNSName
1416*32b31808SJens Wiklander          */
1417*32b31808SJens Wiklander         case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME):
1418*32b31808SJens Wiklander         {
1419*32b31808SJens Wiklander             memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1420*32b31808SJens Wiklander             san->type = MBEDTLS_X509_SAN_DNS_NAME;
1421*32b31808SJens Wiklander 
1422*32b31808SJens Wiklander             memcpy(&san->san.unstructured_name,
1423*32b31808SJens Wiklander                    san_buf, sizeof(*san_buf));
1424*32b31808SJens Wiklander         }
1425*32b31808SJens Wiklander         break;
1426*32b31808SJens Wiklander 
1427*32b31808SJens Wiklander         /*
1428*32b31808SJens Wiklander          * RFC822 Name
1429*32b31808SJens Wiklander          */
1430*32b31808SJens Wiklander         case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME):
1431*32b31808SJens Wiklander         {
1432*32b31808SJens Wiklander             memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1433*32b31808SJens Wiklander             san->type = MBEDTLS_X509_SAN_RFC822_NAME;
1434*32b31808SJens Wiklander             memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf));
1435*32b31808SJens Wiklander         }
1436*32b31808SJens Wiklander         break;
1437*32b31808SJens Wiklander 
1438*32b31808SJens Wiklander         /*
1439*32b31808SJens Wiklander          * Type not supported
1440*32b31808SJens Wiklander          */
1441*32b31808SJens Wiklander         default:
1442*32b31808SJens Wiklander             return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
1443*32b31808SJens Wiklander     }
1444*32b31808SJens Wiklander     return 0;
1445*32b31808SJens Wiklander }
1446*32b31808SJens Wiklander 
1447*32b31808SJens Wiklander #if !defined(MBEDTLS_X509_REMOVE_INFO)
1448*32b31808SJens Wiklander int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
1449*32b31808SJens Wiklander                                        const mbedtls_x509_sequence
1450*32b31808SJens Wiklander                                        *subject_alt_name,
1451*32b31808SJens Wiklander                                        const char *prefix)
1452*32b31808SJens Wiklander {
1453*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1454*32b31808SJens Wiklander     size_t i;
1455*32b31808SJens Wiklander     size_t n = *size;
1456*32b31808SJens Wiklander     char *p = *buf;
1457*32b31808SJens Wiklander     const mbedtls_x509_sequence *cur = subject_alt_name;
1458*32b31808SJens Wiklander     mbedtls_x509_subject_alternative_name san;
1459*32b31808SJens Wiklander     int parse_ret;
1460*32b31808SJens Wiklander 
1461*32b31808SJens Wiklander     while (cur != NULL) {
1462*32b31808SJens Wiklander         memset(&san, 0, sizeof(san));
1463*32b31808SJens Wiklander         parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san);
1464*32b31808SJens Wiklander         if (parse_ret != 0) {
1465*32b31808SJens Wiklander             if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
1466*32b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n, "\n%s    <unsupported>", prefix);
1467*32b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
1468*32b31808SJens Wiklander             } else {
1469*32b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n, "\n%s    <malformed>", prefix);
1470*32b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
1471*32b31808SJens Wiklander             }
1472*32b31808SJens Wiklander             cur = cur->next;
1473*32b31808SJens Wiklander             continue;
1474*32b31808SJens Wiklander         }
1475*32b31808SJens Wiklander 
1476*32b31808SJens Wiklander         switch (san.type) {
1477*32b31808SJens Wiklander             /*
1478*32b31808SJens Wiklander              * otherName
1479*32b31808SJens Wiklander              */
1480*32b31808SJens Wiklander             case MBEDTLS_X509_SAN_OTHER_NAME:
1481*32b31808SJens Wiklander             {
1482*32b31808SJens Wiklander                 mbedtls_x509_san_other_name *other_name = &san.san.other_name;
1483*32b31808SJens Wiklander 
1484*32b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n, "\n%s    otherName :", prefix);
1485*32b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
1486*32b31808SJens Wiklander 
1487*32b31808SJens Wiklander                 if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME,
1488*32b31808SJens Wiklander                                     &other_name->value.hardware_module_name.oid) != 0) {
1489*32b31808SJens Wiklander                     ret = mbedtls_snprintf(p, n, "\n%s        hardware module name :", prefix);
1490*32b31808SJens Wiklander                     MBEDTLS_X509_SAFE_SNPRINTF;
1491*32b31808SJens Wiklander                     ret =
1492*32b31808SJens Wiklander                         mbedtls_snprintf(p, n, "\n%s            hardware type          : ", prefix);
1493*32b31808SJens Wiklander                     MBEDTLS_X509_SAFE_SNPRINTF;
1494*32b31808SJens Wiklander 
1495*32b31808SJens Wiklander                     ret = mbedtls_oid_get_numeric_string(p,
1496*32b31808SJens Wiklander                                                          n,
1497*32b31808SJens Wiklander                                                          &other_name->value.hardware_module_name.oid);
1498*32b31808SJens Wiklander                     MBEDTLS_X509_SAFE_SNPRINTF;
1499*32b31808SJens Wiklander 
1500*32b31808SJens Wiklander                     ret =
1501*32b31808SJens Wiklander                         mbedtls_snprintf(p, n, "\n%s            hardware serial number : ", prefix);
1502*32b31808SJens Wiklander                     MBEDTLS_X509_SAFE_SNPRINTF;
1503*32b31808SJens Wiklander 
1504*32b31808SJens Wiklander                     for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) {
1505*32b31808SJens Wiklander                         ret = mbedtls_snprintf(p,
1506*32b31808SJens Wiklander                                                n,
1507*32b31808SJens Wiklander                                                "%02X",
1508*32b31808SJens Wiklander                                                other_name->value.hardware_module_name.val.p[i]);
1509*32b31808SJens Wiklander                         MBEDTLS_X509_SAFE_SNPRINTF;
1510*32b31808SJens Wiklander                     }
1511*32b31808SJens Wiklander                 }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
1512*32b31808SJens Wiklander             }
1513*32b31808SJens Wiklander             break;
1514*32b31808SJens Wiklander             /*
1515*32b31808SJens Wiklander              * uniformResourceIdentifier
1516*32b31808SJens Wiklander              */
1517*32b31808SJens Wiklander             case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
1518*32b31808SJens Wiklander             {
1519*32b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n, "\n%s    uniformResourceIdentifier : ", prefix);
1520*32b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
1521*32b31808SJens Wiklander                 if (san.san.unstructured_name.len >= n) {
1522*32b31808SJens Wiklander                     *p = '\0';
1523*32b31808SJens Wiklander                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1524*32b31808SJens Wiklander                 }
1525*32b31808SJens Wiklander 
1526*32b31808SJens Wiklander                 memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
1527*32b31808SJens Wiklander                 p += san.san.unstructured_name.len;
1528*32b31808SJens Wiklander                 n -= san.san.unstructured_name.len;
1529*32b31808SJens Wiklander             }
1530*32b31808SJens Wiklander             break;
1531*32b31808SJens Wiklander             /*
1532*32b31808SJens Wiklander              * dNSName
1533*32b31808SJens Wiklander              * RFC822 Name
1534*32b31808SJens Wiklander              */
1535*32b31808SJens Wiklander             case MBEDTLS_X509_SAN_DNS_NAME:
1536*32b31808SJens Wiklander             case MBEDTLS_X509_SAN_RFC822_NAME:
1537*32b31808SJens Wiklander             {
1538*32b31808SJens Wiklander                 const char *dns_name = "dNSName";
1539*32b31808SJens Wiklander                 const char *rfc822_name = "rfc822Name";
1540*32b31808SJens Wiklander 
1541*32b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n,
1542*32b31808SJens Wiklander                                        "\n%s    %s : ",
1543*32b31808SJens Wiklander                                        prefix,
1544*32b31808SJens Wiklander                                        san.type ==
1545*32b31808SJens Wiklander                                        MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name);
1546*32b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
1547*32b31808SJens Wiklander                 if (san.san.unstructured_name.len >= n) {
1548*32b31808SJens Wiklander                     *p = '\0';
1549*32b31808SJens Wiklander                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1550*32b31808SJens Wiklander                 }
1551*32b31808SJens Wiklander 
1552*32b31808SJens Wiklander                 memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
1553*32b31808SJens Wiklander                 p += san.san.unstructured_name.len;
1554*32b31808SJens Wiklander                 n -= san.san.unstructured_name.len;
1555*32b31808SJens Wiklander             }
1556*32b31808SJens Wiklander             break;
1557*32b31808SJens Wiklander 
1558*32b31808SJens Wiklander             /*
1559*32b31808SJens Wiklander              * Type not supported, skip item.
1560*32b31808SJens Wiklander              */
1561*32b31808SJens Wiklander             default:
1562*32b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n, "\n%s    <unsupported>", prefix);
1563*32b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
1564*32b31808SJens Wiklander                 break;
1565*32b31808SJens Wiklander         }
1566*32b31808SJens Wiklander 
1567*32b31808SJens Wiklander         cur = cur->next;
1568*32b31808SJens Wiklander     }
1569*32b31808SJens Wiklander 
1570*32b31808SJens Wiklander     *p = '\0';
1571*32b31808SJens Wiklander 
1572*32b31808SJens Wiklander     *size = n;
1573*32b31808SJens Wiklander     *buf = p;
1574*32b31808SJens Wiklander 
1575*32b31808SJens Wiklander     return 0;
1576*32b31808SJens Wiklander }
1577*32b31808SJens Wiklander 
1578*32b31808SJens Wiklander #define PRINT_ITEM(i)                           \
1579*32b31808SJens Wiklander     {                                           \
1580*32b31808SJens Wiklander         ret = mbedtls_snprintf(p, n, "%s" i, sep);    \
1581*32b31808SJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;                        \
1582*32b31808SJens Wiklander         sep = ", ";                             \
1583*32b31808SJens Wiklander     }
1584*32b31808SJens Wiklander 
1585*32b31808SJens Wiklander #define CERT_TYPE(type, name)                    \
1586*32b31808SJens Wiklander     if (ns_cert_type & (type))                 \
1587*32b31808SJens Wiklander     PRINT_ITEM(name);
1588*32b31808SJens Wiklander 
1589*32b31808SJens Wiklander int mbedtls_x509_info_cert_type(char **buf, size_t *size,
1590*32b31808SJens Wiklander                                 unsigned char ns_cert_type)
1591*32b31808SJens Wiklander {
1592*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1593*32b31808SJens Wiklander     size_t n = *size;
1594*32b31808SJens Wiklander     char *p = *buf;
1595*32b31808SJens Wiklander     const char *sep = "";
1596*32b31808SJens Wiklander 
1597*32b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT,         "SSL Client");
1598*32b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER,         "SSL Server");
1599*32b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL,              "Email");
1600*32b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING,     "Object Signing");
1601*32b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED,           "Reserved");
1602*32b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA,             "SSL CA");
1603*32b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA,           "Email CA");
1604*32b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA,  "Object Signing CA");
1605*32b31808SJens Wiklander 
1606*32b31808SJens Wiklander     *size = n;
1607*32b31808SJens Wiklander     *buf = p;
1608*32b31808SJens Wiklander 
1609*32b31808SJens Wiklander     return 0;
1610*32b31808SJens Wiklander }
1611*32b31808SJens Wiklander 
1612*32b31808SJens Wiklander #define KEY_USAGE(code, name)    \
1613*32b31808SJens Wiklander     if (key_usage & (code))    \
1614*32b31808SJens Wiklander     PRINT_ITEM(name);
1615*32b31808SJens Wiklander 
1616*32b31808SJens Wiklander int mbedtls_x509_info_key_usage(char **buf, size_t *size,
1617*32b31808SJens Wiklander                                 unsigned int key_usage)
1618*32b31808SJens Wiklander {
1619*32b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1620*32b31808SJens Wiklander     size_t n = *size;
1621*32b31808SJens Wiklander     char *p = *buf;
1622*32b31808SJens Wiklander     const char *sep = "";
1623*32b31808SJens Wiklander 
1624*32b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE,    "Digital Signature");
1625*32b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION,      "Non Repudiation");
1626*32b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT,     "Key Encipherment");
1627*32b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT,    "Data Encipherment");
1628*32b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT,        "Key Agreement");
1629*32b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN,        "Key Cert Sign");
1630*32b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN,             "CRL Sign");
1631*32b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY,        "Encipher Only");
1632*32b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY,        "Decipher Only");
1633*32b31808SJens Wiklander 
1634*32b31808SJens Wiklander     *size = n;
1635*32b31808SJens Wiklander     *buf = p;
1636*32b31808SJens Wiklander 
1637*32b31808SJens Wiklander     return 0;
1638*32b31808SJens Wiklander }
1639*32b31808SJens Wiklander #endif /* MBEDTLS_X509_REMOVE_INFO */
1640*32b31808SJens Wiklander #endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */
1641817466cbSJens Wiklander #endif /* MBEDTLS_X509_USE_C */
1642