xref: /optee_os/lib/libmbedtls/mbedtls/library/x509.c (revision b0563631928755fe864b97785160fb3088e9efdc)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  X.509 common functions for parsing and verification
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
5*b0563631STom Van Eyck  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6817466cbSJens Wiklander  */
7817466cbSJens Wiklander /*
8817466cbSJens Wiklander  *  The ITU-T X.509 standard defines a certificate format for PKI.
9817466cbSJens Wiklander  *
10817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
11817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
12817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
13817466cbSJens Wiklander  *
14817466cbSJens Wiklander  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
15817466cbSJens Wiklander  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
16817466cbSJens Wiklander  */
17817466cbSJens Wiklander 
187901324dSJerome Forissier #include "common.h"
19817466cbSJens Wiklander 
20817466cbSJens Wiklander #if defined(MBEDTLS_X509_USE_C)
21817466cbSJens Wiklander 
22*b0563631STom Van Eyck #include "x509_internal.h"
23817466cbSJens Wiklander #include "mbedtls/asn1.h"
2411fa71b9SJerome Forissier #include "mbedtls/error.h"
25817466cbSJens Wiklander #include "mbedtls/oid.h"
26817466cbSJens Wiklander 
27817466cbSJens Wiklander #include <stdio.h>
28817466cbSJens Wiklander #include <string.h>
29817466cbSJens Wiklander 
30817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
31817466cbSJens Wiklander #include "mbedtls/pem.h"
32817466cbSJens Wiklander #endif
33817466cbSJens Wiklander 
34*b0563631STom Van Eyck #include "mbedtls/asn1write.h"
35*b0563631STom Van Eyck 
36817466cbSJens Wiklander #include "mbedtls/platform.h"
37817466cbSJens Wiklander 
38817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_TIME)
39817466cbSJens Wiklander #include "mbedtls/platform_time.h"
40817466cbSJens Wiklander #endif
413d3b0591SJens Wiklander #if defined(MBEDTLS_HAVE_TIME_DATE)
423d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
43817466cbSJens Wiklander #include <time.h>
44817466cbSJens Wiklander #endif
45817466cbSJens Wiklander 
46*b0563631STom Van Eyck #define CHECK(code)                                     \
47*b0563631STom Van Eyck     do {                                                \
48*b0563631STom Van Eyck         if ((ret = (code)) != 0) {                      \
49*b0563631STom Van Eyck             return ret;                                 \
50*b0563631STom Van Eyck         }                                               \
51*b0563631STom Van Eyck     } while (0)
5232b31808SJens Wiklander 
535b25c76aSJerome Forissier #define CHECK_RANGE(min, max, val)                      \
54*b0563631STom Van Eyck     do {                                                \
55*b0563631STom Van Eyck         if ((val) < (min) || (val) > (max)) {           \
5632b31808SJens Wiklander             return ret;                                 \
575b25c76aSJerome Forissier         }                                               \
585b25c76aSJerome Forissier     } while (0)
59817466cbSJens Wiklander 
60817466cbSJens Wiklander /*
61817466cbSJens Wiklander  *  CertificateSerialNumber  ::=  INTEGER
62817466cbSJens Wiklander  */
mbedtls_x509_get_serial(unsigned char ** p,const unsigned char * end,mbedtls_x509_buf * serial)63817466cbSJens Wiklander int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end,
64817466cbSJens Wiklander                             mbedtls_x509_buf *serial)
65817466cbSJens Wiklander {
6611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
67817466cbSJens Wiklander 
6832b31808SJens Wiklander     if ((end - *p) < 1) {
6932b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
7032b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
7132b31808SJens Wiklander     }
72817466cbSJens Wiklander 
73817466cbSJens Wiklander     if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) &&
7432b31808SJens Wiklander         **p !=   MBEDTLS_ASN1_INTEGER) {
7532b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
7632b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
7732b31808SJens Wiklander     }
78817466cbSJens Wiklander 
79817466cbSJens Wiklander     serial->tag = *(*p)++;
80817466cbSJens Wiklander 
8132b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) {
8232b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret);
8332b31808SJens Wiklander     }
84817466cbSJens Wiklander 
85817466cbSJens Wiklander     serial->p = *p;
86817466cbSJens Wiklander     *p += serial->len;
87817466cbSJens Wiklander 
8832b31808SJens Wiklander     return 0;
89817466cbSJens Wiklander }
90817466cbSJens Wiklander 
91817466cbSJens Wiklander /* Get an algorithm identifier without parameters (eg for signatures)
92817466cbSJens Wiklander  *
93817466cbSJens Wiklander  *  AlgorithmIdentifier  ::=  SEQUENCE  {
94817466cbSJens Wiklander  *       algorithm               OBJECT IDENTIFIER,
95817466cbSJens Wiklander  *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
96817466cbSJens Wiklander  */
mbedtls_x509_get_alg_null(unsigned char ** p,const unsigned char * end,mbedtls_x509_buf * alg)97817466cbSJens Wiklander int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,
98817466cbSJens Wiklander                               mbedtls_x509_buf *alg)
99817466cbSJens Wiklander {
10011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101817466cbSJens Wiklander 
10232b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
10332b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
10432b31808SJens Wiklander     }
105817466cbSJens Wiklander 
10632b31808SJens Wiklander     return 0;
107817466cbSJens Wiklander }
108817466cbSJens Wiklander 
109817466cbSJens Wiklander /*
1105b25c76aSJerome Forissier  * Parse an algorithm identifier with (optional) parameters
111817466cbSJens Wiklander  */
mbedtls_x509_get_alg(unsigned char ** p,const unsigned char * end,mbedtls_x509_buf * alg,mbedtls_x509_buf * params)112817466cbSJens Wiklander int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,
113817466cbSJens Wiklander                          mbedtls_x509_buf *alg, mbedtls_x509_buf *params)
114817466cbSJens Wiklander {
11511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
116817466cbSJens Wiklander 
11732b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) {
11832b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
11932b31808SJens Wiklander     }
120817466cbSJens Wiklander 
12132b31808SJens Wiklander     return 0;
12232b31808SJens Wiklander }
12332b31808SJens Wiklander 
12432b31808SJens Wiklander /*
12532b31808SJens Wiklander  * Convert md type to string
12632b31808SJens Wiklander  */
127*b0563631STom Van Eyck #if !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
128*b0563631STom Van Eyck 
md_type_to_string(mbedtls_md_type_t md_alg)12932b31808SJens Wiklander static inline const char *md_type_to_string(mbedtls_md_type_t md_alg)
13032b31808SJens Wiklander {
13132b31808SJens Wiklander     switch (md_alg) {
132*b0563631STom Van Eyck #if defined(MBEDTLS_MD_CAN_MD5)
13332b31808SJens Wiklander         case MBEDTLS_MD_MD5:
13432b31808SJens Wiklander             return "MD5";
13532b31808SJens Wiklander #endif
136*b0563631STom Van Eyck #if defined(MBEDTLS_MD_CAN_SHA1)
13732b31808SJens Wiklander         case MBEDTLS_MD_SHA1:
13832b31808SJens Wiklander             return "SHA1";
13932b31808SJens Wiklander #endif
140*b0563631STom Van Eyck #if defined(MBEDTLS_MD_CAN_SHA224)
14132b31808SJens Wiklander         case MBEDTLS_MD_SHA224:
14232b31808SJens Wiklander             return "SHA224";
14332b31808SJens Wiklander #endif
144*b0563631STom Van Eyck #if defined(MBEDTLS_MD_CAN_SHA256)
14532b31808SJens Wiklander         case MBEDTLS_MD_SHA256:
14632b31808SJens Wiklander             return "SHA256";
14732b31808SJens Wiklander #endif
148*b0563631STom Van Eyck #if defined(MBEDTLS_MD_CAN_SHA384)
14932b31808SJens Wiklander         case MBEDTLS_MD_SHA384:
15032b31808SJens Wiklander             return "SHA384";
15132b31808SJens Wiklander #endif
152*b0563631STom Van Eyck #if defined(MBEDTLS_MD_CAN_SHA512)
15332b31808SJens Wiklander         case MBEDTLS_MD_SHA512:
15432b31808SJens Wiklander             return "SHA512";
15532b31808SJens Wiklander #endif
156*b0563631STom Van Eyck #if defined(MBEDTLS_MD_CAN_RIPEMD160)
15732b31808SJens Wiklander         case MBEDTLS_MD_RIPEMD160:
15832b31808SJens Wiklander             return "RIPEMD160";
15932b31808SJens Wiklander #endif
16032b31808SJens Wiklander         case MBEDTLS_MD_NONE:
16132b31808SJens Wiklander             return NULL;
16232b31808SJens Wiklander         default:
16332b31808SJens Wiklander             return NULL;
16432b31808SJens Wiklander     }
165817466cbSJens Wiklander }
166817466cbSJens Wiklander 
167*b0563631STom Van Eyck #endif /* !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) */
168*b0563631STom Van Eyck 
169817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
170817466cbSJens Wiklander /*
171817466cbSJens Wiklander  * HashAlgorithm ::= AlgorithmIdentifier
172817466cbSJens Wiklander  *
173817466cbSJens Wiklander  * AlgorithmIdentifier  ::=  SEQUENCE  {
174817466cbSJens Wiklander  *      algorithm               OBJECT IDENTIFIER,
175817466cbSJens Wiklander  *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
176817466cbSJens Wiklander  *
177817466cbSJens Wiklander  * For HashAlgorithm, parameters MUST be NULL or absent.
178817466cbSJens Wiklander  */
x509_get_hash_alg(const mbedtls_x509_buf * alg,mbedtls_md_type_t * md_alg)179817466cbSJens Wiklander static int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg)
180817466cbSJens Wiklander {
18111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
182817466cbSJens Wiklander     unsigned char *p;
183817466cbSJens Wiklander     const unsigned char *end;
184817466cbSJens Wiklander     mbedtls_x509_buf md_oid;
185817466cbSJens Wiklander     size_t len;
186817466cbSJens Wiklander 
187817466cbSJens Wiklander     /* Make sure we got a SEQUENCE and setup bounds */
18832b31808SJens Wiklander     if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
18932b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
19032b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
19132b31808SJens Wiklander     }
192817466cbSJens Wiklander 
1937901324dSJerome Forissier     p = alg->p;
194817466cbSJens Wiklander     end = p + alg->len;
195817466cbSJens Wiklander 
19632b31808SJens Wiklander     if (p >= end) {
19732b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
19832b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
19932b31808SJens Wiklander     }
200817466cbSJens Wiklander 
201817466cbSJens Wiklander     /* Parse md_oid */
202817466cbSJens Wiklander     md_oid.tag = *p;
203817466cbSJens Wiklander 
20432b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) {
20532b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
20632b31808SJens Wiklander     }
207817466cbSJens Wiklander 
208817466cbSJens Wiklander     md_oid.p = p;
209817466cbSJens Wiklander     p += md_oid.len;
210817466cbSJens Wiklander 
211817466cbSJens Wiklander     /* Get md_alg from md_oid */
21232b31808SJens Wiklander     if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) {
21332b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
21432b31808SJens Wiklander     }
215817466cbSJens Wiklander 
216817466cbSJens Wiklander     /* Make sure params is absent of NULL */
21732b31808SJens Wiklander     if (p == end) {
21832b31808SJens Wiklander         return 0;
21932b31808SJens Wiklander     }
220817466cbSJens Wiklander 
22132b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) {
22232b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
22332b31808SJens Wiklander     }
224817466cbSJens Wiklander 
22532b31808SJens Wiklander     if (p != end) {
22632b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
22732b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
22832b31808SJens Wiklander     }
229817466cbSJens Wiklander 
23032b31808SJens Wiklander     return 0;
231817466cbSJens Wiklander }
232817466cbSJens Wiklander 
233817466cbSJens Wiklander /*
234817466cbSJens Wiklander  *    RSASSA-PSS-params  ::=  SEQUENCE  {
235817466cbSJens Wiklander  *       hashAlgorithm     [0] HashAlgorithm DEFAULT sha1Identifier,
236817466cbSJens Wiklander  *       maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
237817466cbSJens Wiklander  *       saltLength        [2] INTEGER DEFAULT 20,
238817466cbSJens Wiklander  *       trailerField      [3] INTEGER DEFAULT 1  }
239817466cbSJens Wiklander  *    -- Note that the tags in this Sequence are explicit.
240817466cbSJens Wiklander  *
241817466cbSJens Wiklander  * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
242817466cbSJens Wiklander  * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
24332b31808SJens Wiklander  * option. Enforce this at parsing time.
244817466cbSJens Wiklander  */
mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf * params,mbedtls_md_type_t * md_alg,mbedtls_md_type_t * mgf_md,int * salt_len)245817466cbSJens Wiklander int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params,
246817466cbSJens Wiklander                                        mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
247817466cbSJens Wiklander                                        int *salt_len)
248817466cbSJens Wiklander {
24911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
250817466cbSJens Wiklander     unsigned char *p;
251817466cbSJens Wiklander     const unsigned char *end, *end2;
252817466cbSJens Wiklander     size_t len;
253817466cbSJens Wiklander     mbedtls_x509_buf alg_id, alg_params;
254817466cbSJens Wiklander 
255817466cbSJens Wiklander     /* First set everything to defaults */
256817466cbSJens Wiklander     *md_alg = MBEDTLS_MD_SHA1;
257817466cbSJens Wiklander     *mgf_md = MBEDTLS_MD_SHA1;
258817466cbSJens Wiklander     *salt_len = 20;
259817466cbSJens Wiklander 
260817466cbSJens Wiklander     /* Make sure params is a SEQUENCE and setup bounds */
26132b31808SJens Wiklander     if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
26232b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
26332b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
26432b31808SJens Wiklander     }
265817466cbSJens Wiklander 
266817466cbSJens Wiklander     p = (unsigned char *) params->p;
267817466cbSJens Wiklander     end = p + params->len;
268817466cbSJens Wiklander 
26932b31808SJens Wiklander     if (p == end) {
27032b31808SJens Wiklander         return 0;
27132b31808SJens Wiklander     }
272817466cbSJens Wiklander 
273817466cbSJens Wiklander     /*
274817466cbSJens Wiklander      * HashAlgorithm
275817466cbSJens Wiklander      */
276817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
27732b31808SJens Wiklander                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
27832b31808SJens Wiklander                                     0)) == 0) {
279817466cbSJens Wiklander         end2 = p + len;
280817466cbSJens Wiklander 
281817466cbSJens Wiklander         /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
28232b31808SJens Wiklander         if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) {
28332b31808SJens Wiklander             return ret;
284817466cbSJens Wiklander         }
285817466cbSJens Wiklander 
28632b31808SJens Wiklander         if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) {
28732b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
28832b31808SJens Wiklander         }
28932b31808SJens Wiklander 
29032b31808SJens Wiklander         if (p != end2) {
29132b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
29232b31808SJens Wiklander                                      MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
29332b31808SJens Wiklander         }
29432b31808SJens Wiklander     } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
29532b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
29632b31808SJens Wiklander     }
29732b31808SJens Wiklander 
29832b31808SJens Wiklander     if (p == end) {
29932b31808SJens Wiklander         return 0;
30032b31808SJens Wiklander     }
301817466cbSJens Wiklander 
302817466cbSJens Wiklander     /*
303817466cbSJens Wiklander      * MaskGenAlgorithm
304817466cbSJens Wiklander      */
305817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
30632b31808SJens Wiklander                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
30732b31808SJens Wiklander                                     1)) == 0) {
308817466cbSJens Wiklander         end2 = p + len;
309817466cbSJens Wiklander 
310817466cbSJens Wiklander         /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
31132b31808SJens Wiklander         if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) {
31232b31808SJens Wiklander             return ret;
31332b31808SJens Wiklander         }
314817466cbSJens Wiklander 
315817466cbSJens Wiklander         /* Only MFG1 is recognised for now */
31632b31808SJens Wiklander         if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) {
31732b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE,
31832b31808SJens Wiklander                                      MBEDTLS_ERR_OID_NOT_FOUND);
31932b31808SJens Wiklander         }
320817466cbSJens Wiklander 
321817466cbSJens Wiklander         /* Parse HashAlgorithm */
32232b31808SJens Wiklander         if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) {
32332b31808SJens Wiklander             return ret;
324817466cbSJens Wiklander         }
325817466cbSJens Wiklander 
32632b31808SJens Wiklander         if (p != end2) {
32732b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
32832b31808SJens Wiklander                                      MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
32932b31808SJens Wiklander         }
33032b31808SJens Wiklander     } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
33132b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
33232b31808SJens Wiklander     }
33332b31808SJens Wiklander 
33432b31808SJens Wiklander     if (p == end) {
33532b31808SJens Wiklander         return 0;
33632b31808SJens Wiklander     }
337817466cbSJens Wiklander 
338817466cbSJens Wiklander     /*
339817466cbSJens Wiklander      * salt_len
340817466cbSJens Wiklander      */
341817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
34232b31808SJens Wiklander                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
34332b31808SJens Wiklander                                     2)) == 0) {
344817466cbSJens Wiklander         end2 = p + len;
345817466cbSJens Wiklander 
34632b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) {
34732b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
348817466cbSJens Wiklander         }
349817466cbSJens Wiklander 
35032b31808SJens Wiklander         if (p != end2) {
35132b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
35232b31808SJens Wiklander                                      MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
35332b31808SJens Wiklander         }
35432b31808SJens Wiklander     } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
35532b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
35632b31808SJens Wiklander     }
35732b31808SJens Wiklander 
35832b31808SJens Wiklander     if (p == end) {
35932b31808SJens Wiklander         return 0;
36032b31808SJens Wiklander     }
361817466cbSJens Wiklander 
362817466cbSJens Wiklander     /*
363817466cbSJens Wiklander      * trailer_field (if present, must be 1)
364817466cbSJens Wiklander      */
365817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
36632b31808SJens Wiklander                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
36732b31808SJens Wiklander                                     3)) == 0) {
368817466cbSJens Wiklander         int trailer_field;
369817466cbSJens Wiklander 
370817466cbSJens Wiklander         end2 = p + len;
371817466cbSJens Wiklander 
37232b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) {
37332b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
374817466cbSJens Wiklander         }
375817466cbSJens Wiklander 
37632b31808SJens Wiklander         if (p != end2) {
37732b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
37832b31808SJens Wiklander                                      MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
37932b31808SJens Wiklander         }
380817466cbSJens Wiklander 
38132b31808SJens Wiklander         if (trailer_field != 1) {
38232b31808SJens Wiklander             return MBEDTLS_ERR_X509_INVALID_ALG;
38332b31808SJens Wiklander         }
38432b31808SJens Wiklander     } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
38532b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
38632b31808SJens Wiklander     }
38732b31808SJens Wiklander 
38832b31808SJens Wiklander     if (p != end) {
38932b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
39032b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
39132b31808SJens Wiklander     }
39232b31808SJens Wiklander 
39332b31808SJens Wiklander     return 0;
394817466cbSJens Wiklander }
395817466cbSJens Wiklander #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
396817466cbSJens Wiklander 
397817466cbSJens Wiklander /*
398817466cbSJens Wiklander  *  AttributeTypeAndValue ::= SEQUENCE {
399817466cbSJens Wiklander  *    type     AttributeType,
400817466cbSJens Wiklander  *    value    AttributeValue }
401817466cbSJens Wiklander  *
402817466cbSJens Wiklander  *  AttributeType ::= OBJECT IDENTIFIER
403817466cbSJens Wiklander  *
404817466cbSJens Wiklander  *  AttributeValue ::= ANY DEFINED BY AttributeType
405817466cbSJens Wiklander  */
x509_get_attr_type_value(unsigned char ** p,const unsigned char * end,mbedtls_x509_name * cur)406817466cbSJens Wiklander static int x509_get_attr_type_value(unsigned char **p,
407817466cbSJens Wiklander                                     const unsigned char *end,
408817466cbSJens Wiklander                                     mbedtls_x509_name *cur)
409817466cbSJens Wiklander {
41011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
411817466cbSJens Wiklander     size_t len;
412817466cbSJens Wiklander     mbedtls_x509_buf *oid;
413817466cbSJens Wiklander     mbedtls_x509_buf *val;
414817466cbSJens Wiklander 
415817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
41632b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
41732b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
41832b31808SJens Wiklander     }
419817466cbSJens Wiklander 
4205b25c76aSJerome Forissier     end = *p + len;
4215b25c76aSJerome Forissier 
42232b31808SJens Wiklander     if ((end - *p) < 1) {
42332b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
42432b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
42532b31808SJens Wiklander     }
426817466cbSJens Wiklander 
427817466cbSJens Wiklander     oid = &cur->oid;
428817466cbSJens Wiklander     oid->tag = **p;
429817466cbSJens Wiklander 
43032b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) {
43132b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
43232b31808SJens Wiklander     }
433817466cbSJens Wiklander 
434817466cbSJens Wiklander     oid->p = *p;
435817466cbSJens Wiklander     *p += oid->len;
436817466cbSJens Wiklander 
43732b31808SJens Wiklander     if ((end - *p) < 1) {
43832b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
43932b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
44032b31808SJens Wiklander     }
441817466cbSJens Wiklander 
442817466cbSJens Wiklander     if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING      &&
443817466cbSJens Wiklander         **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
444817466cbSJens Wiklander         **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
44532b31808SJens Wiklander         **p != MBEDTLS_ASN1_BIT_STRING) {
44632b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
44732b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
44832b31808SJens Wiklander     }
449817466cbSJens Wiklander 
450817466cbSJens Wiklander     val = &cur->val;
451817466cbSJens Wiklander     val->tag = *(*p)++;
452817466cbSJens Wiklander 
45332b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) {
45432b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
45532b31808SJens Wiklander     }
456817466cbSJens Wiklander 
457817466cbSJens Wiklander     val->p = *p;
458817466cbSJens Wiklander     *p += val->len;
459817466cbSJens Wiklander 
46032b31808SJens Wiklander     if (*p != end) {
46132b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
46232b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
4635b25c76aSJerome Forissier     }
4645b25c76aSJerome Forissier 
465817466cbSJens Wiklander     cur->next = NULL;
466817466cbSJens Wiklander 
46732b31808SJens Wiklander     return 0;
468817466cbSJens Wiklander }
469817466cbSJens Wiklander 
470817466cbSJens Wiklander /*
471817466cbSJens Wiklander  *  Name ::= CHOICE { -- only one possibility for now --
472817466cbSJens Wiklander  *       rdnSequence  RDNSequence }
473817466cbSJens Wiklander  *
474817466cbSJens Wiklander  *  RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
475817466cbSJens Wiklander  *
476817466cbSJens Wiklander  *  RelativeDistinguishedName ::=
477817466cbSJens Wiklander  *    SET OF AttributeTypeAndValue
478817466cbSJens Wiklander  *
479817466cbSJens Wiklander  *  AttributeTypeAndValue ::= SEQUENCE {
480817466cbSJens Wiklander  *    type     AttributeType,
481817466cbSJens Wiklander  *    value    AttributeValue }
482817466cbSJens Wiklander  *
483817466cbSJens Wiklander  *  AttributeType ::= OBJECT IDENTIFIER
484817466cbSJens Wiklander  *
485817466cbSJens Wiklander  *  AttributeValue ::= ANY DEFINED BY AttributeType
486817466cbSJens Wiklander  *
487817466cbSJens Wiklander  * The data structure is optimized for the common case where each RDN has only
488817466cbSJens Wiklander  * one element, which is represented as a list of AttributeTypeAndValue.
489817466cbSJens Wiklander  * For the general case we still use a flat list, but we mark elements of the
490817466cbSJens Wiklander  * same set so that they are "merged" together in the functions that consume
491817466cbSJens Wiklander  * this list, eg mbedtls_x509_dn_gets().
49232b31808SJens Wiklander  *
49332b31808SJens Wiklander  * On success, this function may allocate a linked list starting at cur->next
49432b31808SJens Wiklander  * that must later be free'd by the caller using mbedtls_free(). In error
49532b31808SJens Wiklander  * cases, this function frees all allocated memory internally and the caller
49632b31808SJens Wiklander  * has no freeing responsibilities.
497817466cbSJens Wiklander  */
mbedtls_x509_get_name(unsigned char ** p,const unsigned char * end,mbedtls_x509_name * cur)498817466cbSJens Wiklander int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
499817466cbSJens Wiklander                           mbedtls_x509_name *cur)
500817466cbSJens Wiklander {
50111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
502817466cbSJens Wiklander     size_t set_len;
503817466cbSJens Wiklander     const unsigned char *end_set;
50432b31808SJens Wiklander     mbedtls_x509_name *head = cur;
505817466cbSJens Wiklander 
506817466cbSJens Wiklander     /* don't use recursion, we'd risk stack overflow if not optimized */
50732b31808SJens Wiklander     while (1) {
508817466cbSJens Wiklander         /*
509817466cbSJens Wiklander          * parse SET
510817466cbSJens Wiklander          */
511817466cbSJens Wiklander         if ((ret = mbedtls_asn1_get_tag(p, end, &set_len,
51232b31808SJens Wiklander                                         MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
51332b31808SJens Wiklander             ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
51432b31808SJens Wiklander             goto error;
51532b31808SJens Wiklander         }
516817466cbSJens Wiklander 
517817466cbSJens Wiklander         end_set  = *p + set_len;
518817466cbSJens Wiklander 
51932b31808SJens Wiklander         while (1) {
52032b31808SJens Wiklander             if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) {
52132b31808SJens Wiklander                 goto error;
52232b31808SJens Wiklander             }
523817466cbSJens Wiklander 
52432b31808SJens Wiklander             if (*p == end_set) {
525817466cbSJens Wiklander                 break;
52632b31808SJens Wiklander             }
527817466cbSJens Wiklander 
528817466cbSJens Wiklander             /* Mark this item as being no the only one in a set */
529817466cbSJens Wiklander             cur->next_merged = 1;
530817466cbSJens Wiklander 
531817466cbSJens Wiklander             cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
532817466cbSJens Wiklander 
53332b31808SJens Wiklander             if (cur->next == NULL) {
53432b31808SJens Wiklander                 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
53532b31808SJens Wiklander                 goto error;
53632b31808SJens Wiklander             }
537817466cbSJens Wiklander 
538817466cbSJens Wiklander             cur = cur->next;
539817466cbSJens Wiklander         }
540817466cbSJens Wiklander 
541817466cbSJens Wiklander         /*
542817466cbSJens Wiklander          * continue until end of SEQUENCE is reached
543817466cbSJens Wiklander          */
54432b31808SJens Wiklander         if (*p == end) {
54532b31808SJens Wiklander             return 0;
54632b31808SJens Wiklander         }
547817466cbSJens Wiklander 
548817466cbSJens Wiklander         cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
549817466cbSJens Wiklander 
55032b31808SJens Wiklander         if (cur->next == NULL) {
55132b31808SJens Wiklander             ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
55232b31808SJens Wiklander             goto error;
55332b31808SJens Wiklander         }
554817466cbSJens Wiklander 
555817466cbSJens Wiklander         cur = cur->next;
556817466cbSJens Wiklander     }
55732b31808SJens Wiklander 
55832b31808SJens Wiklander error:
55932b31808SJens Wiklander     /* Skip the first element as we did not allocate it */
56032b31808SJens Wiklander     mbedtls_asn1_free_named_data_list_shallow(head->next);
56132b31808SJens Wiklander     head->next = NULL;
56232b31808SJens Wiklander 
56332b31808SJens Wiklander     return ret;
564817466cbSJens Wiklander }
565817466cbSJens Wiklander 
x509_date_is_valid(const mbedtls_x509_time * t)566*b0563631STom Van Eyck static int x509_date_is_valid(const mbedtls_x509_time *t)
567817466cbSJens Wiklander {
568*b0563631STom Van Eyck     unsigned int month_days;
569*b0563631STom Van Eyck     unsigned int year;
570*b0563631STom Van Eyck     switch (t->mon) {
571*b0563631STom Van Eyck         case 1: case 3: case 5: case 7: case 8: case 10: case 12:
572*b0563631STom Van Eyck             month_days = 31;
573*b0563631STom Van Eyck             break;
574*b0563631STom Van Eyck         case 4: case 6: case 9: case 11:
575*b0563631STom Van Eyck             month_days = 30;
576*b0563631STom Van Eyck             break;
577*b0563631STom Van Eyck         case 2:
578*b0563631STom Van Eyck             year = (unsigned int) t->year;
579*b0563631STom Van Eyck             month_days = ((year & 3) || (!(year % 100)
580*b0563631STom Van Eyck                                          && (year % 400)))
581*b0563631STom Van Eyck                           ? 28 : 29;
582*b0563631STom Van Eyck             break;
583*b0563631STom Van Eyck         default:
58432b31808SJens Wiklander             return MBEDTLS_ERR_X509_INVALID_DATE;
58532b31808SJens Wiklander     }
586817466cbSJens Wiklander 
587*b0563631STom Van Eyck     if ((unsigned int) (t->day - 1) >= month_days ||      /* (1 - days in month) */
588*b0563631STom Van Eyck         /* (unsigned int) (t->mon - 1) >= 12 || */  /* (1 - 12) checked above */
589*b0563631STom Van Eyck         (unsigned int) t->year > 9999 ||         /* (0 - 9999) */
590*b0563631STom Van Eyck         (unsigned int) t->hour > 23 ||           /* (0 - 23) */
591*b0563631STom Van Eyck         (unsigned int) t->min  > 59 ||           /* (0 - 59) */
592*b0563631STom Van Eyck         (unsigned int) t->sec  > 59) {           /* (0 - 59) */
593*b0563631STom Van Eyck         return MBEDTLS_ERR_X509_INVALID_DATE;
594817466cbSJens Wiklander     }
595817466cbSJens Wiklander 
59632b31808SJens Wiklander     return 0;
597817466cbSJens Wiklander }
598817466cbSJens Wiklander 
x509_parse2_int(const unsigned char * p)599*b0563631STom Van Eyck static int x509_parse2_int(const unsigned char *p)
600817466cbSJens Wiklander {
601*b0563631STom Van Eyck     uint32_t d1 = p[0] - '0';
602*b0563631STom Van Eyck     uint32_t d2 = p[1] - '0';
603*b0563631STom Van Eyck     return (d1 < 10 && d2 < 10) ? (int) (d1 * 10 + d2) : -1;
604817466cbSJens Wiklander }
605817466cbSJens Wiklander 
606817466cbSJens Wiklander /*
607817466cbSJens Wiklander  * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
608817466cbSJens Wiklander  * field.
609817466cbSJens Wiklander  */
x509_parse_time(const unsigned char * p,mbedtls_x509_time * tm,size_t yearlen)610*b0563631STom Van Eyck static int x509_parse_time(const unsigned char *p, mbedtls_x509_time *tm,
611*b0563631STom Van Eyck                            size_t yearlen)
612817466cbSJens Wiklander {
613*b0563631STom Van Eyck     int x;
614817466cbSJens Wiklander 
615817466cbSJens Wiklander     /*
616*b0563631STom Van Eyck      * Parse year, month, day, hour, minute, second
617817466cbSJens Wiklander      */
618*b0563631STom Van Eyck     tm->year = x509_parse2_int(p);
619*b0563631STom Van Eyck     if (tm->year < 0) {
62032b31808SJens Wiklander         return MBEDTLS_ERR_X509_INVALID_DATE;
62132b31808SJens Wiklander     }
622817466cbSJens Wiklander 
623*b0563631STom Van Eyck     if (4 == yearlen) {
624*b0563631STom Van Eyck         x = tm->year * 100;
625*b0563631STom Van Eyck         p += 2;
626*b0563631STom Van Eyck         tm->year = x509_parse2_int(p);
627*b0563631STom Van Eyck         if (tm->year < 0) {
628*b0563631STom Van Eyck             return MBEDTLS_ERR_X509_INVALID_DATE;
62932b31808SJens Wiklander         }
63032b31808SJens Wiklander     } else {
631*b0563631STom Van Eyck         x = (tm->year < 50) ? 2000 : 1900;
632817466cbSJens Wiklander     }
633*b0563631STom Van Eyck     tm->year += x;
634817466cbSJens Wiklander 
635*b0563631STom Van Eyck     tm->mon  = x509_parse2_int(p + 2);
636*b0563631STom Van Eyck     tm->day  = x509_parse2_int(p + 4);
637*b0563631STom Van Eyck     tm->hour = x509_parse2_int(p + 6);
638*b0563631STom Van Eyck     tm->min  = x509_parse2_int(p + 8);
639*b0563631STom Van Eyck     tm->sec  = x509_parse2_int(p + 10);
640817466cbSJens Wiklander 
641*b0563631STom Van Eyck     return x509_date_is_valid(tm);
642817466cbSJens Wiklander }
643817466cbSJens Wiklander 
644817466cbSJens Wiklander /*
645817466cbSJens Wiklander  *  Time ::= CHOICE {
646817466cbSJens Wiklander  *       utcTime        UTCTime,
647817466cbSJens Wiklander  *       generalTime    GeneralizedTime }
648817466cbSJens Wiklander  */
mbedtls_x509_get_time(unsigned char ** p,const unsigned char * end,mbedtls_x509_time * tm)649817466cbSJens Wiklander int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,
650817466cbSJens Wiklander                           mbedtls_x509_time *tm)
651817466cbSJens Wiklander {
65211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
653817466cbSJens Wiklander     size_t len, year_len;
654817466cbSJens Wiklander     unsigned char tag;
655817466cbSJens Wiklander 
65632b31808SJens Wiklander     if ((end - *p) < 1) {
65732b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
65832b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
65932b31808SJens Wiklander     }
660817466cbSJens Wiklander 
661817466cbSJens Wiklander     tag = **p;
662817466cbSJens Wiklander 
66332b31808SJens Wiklander     if (tag == MBEDTLS_ASN1_UTC_TIME) {
664817466cbSJens Wiklander         year_len = 2;
66532b31808SJens Wiklander     } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) {
666817466cbSJens Wiklander         year_len = 4;
66732b31808SJens Wiklander     } else {
66832b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
66932b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
67032b31808SJens Wiklander     }
671817466cbSJens Wiklander 
672817466cbSJens Wiklander     (*p)++;
673817466cbSJens Wiklander     ret = mbedtls_asn1_get_len(p, end, &len);
674817466cbSJens Wiklander 
67532b31808SJens Wiklander     if (ret != 0) {
67632b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret);
67732b31808SJens Wiklander     }
678817466cbSJens Wiklander 
679*b0563631STom Van Eyck     /* len is 12 or 14 depending on year_len, plus optional trailing 'Z' */
680*b0563631STom Van Eyck     if (len != year_len + 10 &&
681*b0563631STom Van Eyck         !(len == year_len + 11 && (*p)[(len - 1)] == 'Z')) {
682*b0563631STom Van Eyck         return MBEDTLS_ERR_X509_INVALID_DATE;
683*b0563631STom Van Eyck     }
684*b0563631STom Van Eyck 
685*b0563631STom Van Eyck     (*p) += len;
686*b0563631STom Van Eyck     return x509_parse_time(*p - len, tm, year_len);
687817466cbSJens Wiklander }
688817466cbSJens Wiklander 
mbedtls_x509_get_sig(unsigned char ** p,const unsigned char * end,mbedtls_x509_buf * sig)689817466cbSJens Wiklander int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig)
690817466cbSJens Wiklander {
69111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
692817466cbSJens Wiklander     size_t len;
693817466cbSJens Wiklander     int tag_type;
694817466cbSJens Wiklander 
69532b31808SJens Wiklander     if ((end - *p) < 1) {
69632b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE,
69732b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_OUT_OF_DATA);
69832b31808SJens Wiklander     }
699817466cbSJens Wiklander 
700817466cbSJens Wiklander     tag_type = **p;
701817466cbSJens Wiklander 
70232b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
70332b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret);
70432b31808SJens Wiklander     }
705817466cbSJens Wiklander 
706817466cbSJens Wiklander     sig->tag = tag_type;
707817466cbSJens Wiklander     sig->len = len;
708817466cbSJens Wiklander     sig->p = *p;
709817466cbSJens Wiklander 
710817466cbSJens Wiklander     *p += len;
711817466cbSJens Wiklander 
71232b31808SJens Wiklander     return 0;
713817466cbSJens Wiklander }
714817466cbSJens Wiklander 
715817466cbSJens Wiklander /*
716817466cbSJens Wiklander  * Get signature algorithm from alg OID and optional parameters
717817466cbSJens Wiklander  */
mbedtls_x509_get_sig_alg(const mbedtls_x509_buf * sig_oid,const mbedtls_x509_buf * sig_params,mbedtls_md_type_t * md_alg,mbedtls_pk_type_t * pk_alg,void ** sig_opts)718817466cbSJens Wiklander int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
719817466cbSJens Wiklander                              mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
720817466cbSJens Wiklander                              void **sig_opts)
721817466cbSJens Wiklander {
72211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
723817466cbSJens Wiklander 
72432b31808SJens Wiklander     if (*sig_opts != NULL) {
72532b31808SJens Wiklander         return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
72632b31808SJens Wiklander     }
727817466cbSJens Wiklander 
72832b31808SJens Wiklander     if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) {
72932b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret);
73032b31808SJens Wiklander     }
731817466cbSJens Wiklander 
732817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
73332b31808SJens Wiklander     if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) {
734817466cbSJens Wiklander         mbedtls_pk_rsassa_pss_options *pss_opts;
735817466cbSJens Wiklander 
736817466cbSJens Wiklander         pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options));
73732b31808SJens Wiklander         if (pss_opts == NULL) {
73832b31808SJens Wiklander             return MBEDTLS_ERR_X509_ALLOC_FAILED;
73932b31808SJens Wiklander         }
740817466cbSJens Wiklander 
741817466cbSJens Wiklander         ret = mbedtls_x509_get_rsassa_pss_params(sig_params,
742817466cbSJens Wiklander                                                  md_alg,
743817466cbSJens Wiklander                                                  &pss_opts->mgf1_hash_id,
744817466cbSJens Wiklander                                                  &pss_opts->expected_salt_len);
74532b31808SJens Wiklander         if (ret != 0) {
746817466cbSJens Wiklander             mbedtls_free(pss_opts);
74732b31808SJens Wiklander             return ret;
748817466cbSJens Wiklander         }
749817466cbSJens Wiklander 
750817466cbSJens Wiklander         *sig_opts = (void *) pss_opts;
75132b31808SJens Wiklander     } else
752817466cbSJens Wiklander #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
753817466cbSJens Wiklander     {
754817466cbSJens Wiklander         /* Make sure parameters are absent or NULL */
755817466cbSJens Wiklander         if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) ||
75632b31808SJens Wiklander             sig_params->len != 0) {
75732b31808SJens Wiklander             return MBEDTLS_ERR_X509_INVALID_ALG;
75832b31808SJens Wiklander         }
759817466cbSJens Wiklander     }
760817466cbSJens Wiklander 
76132b31808SJens Wiklander     return 0;
762817466cbSJens Wiklander }
763817466cbSJens Wiklander 
764817466cbSJens Wiklander /*
765817466cbSJens Wiklander  * X.509 Extensions (No parsing of extensions, pointer should
766817466cbSJens Wiklander  * be either manually updated or extensions should be parsed!)
767817466cbSJens Wiklander  */
mbedtls_x509_get_ext(unsigned char ** p,const unsigned char * end,mbedtls_x509_buf * ext,int tag)768817466cbSJens Wiklander int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,
769817466cbSJens Wiklander                          mbedtls_x509_buf *ext, int tag)
770817466cbSJens Wiklander {
77111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
772817466cbSJens Wiklander     size_t len;
773817466cbSJens Wiklander 
7745b25c76aSJerome Forissier     /* Extension structure use EXPLICIT tagging. That is, the actual
7755b25c76aSJerome Forissier      * `Extensions` structure is wrapped by a tag-length pair using
7765b25c76aSJerome Forissier      * the respective context-specific tag. */
7775b25c76aSJerome Forissier     ret = mbedtls_asn1_get_tag(p, end, &ext->len,
7785b25c76aSJerome Forissier                                MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag);
77932b31808SJens Wiklander     if (ret != 0) {
78032b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
78132b31808SJens Wiklander     }
782817466cbSJens Wiklander 
7835b25c76aSJerome Forissier     ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag;
784817466cbSJens Wiklander     ext->p   = *p;
785817466cbSJens Wiklander     end      = *p + ext->len;
786817466cbSJens Wiklander 
787817466cbSJens Wiklander     /*
788817466cbSJens Wiklander      * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
789817466cbSJens Wiklander      */
790817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
79132b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
79232b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
79332b31808SJens Wiklander     }
794817466cbSJens Wiklander 
79532b31808SJens Wiklander     if (end != *p + len) {
79632b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
79732b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
79832b31808SJens Wiklander     }
799817466cbSJens Wiklander 
80032b31808SJens Wiklander     return 0;
801817466cbSJens Wiklander }
802817466cbSJens Wiklander 
nibble_to_hex_digit(int i)803*b0563631STom Van Eyck static char nibble_to_hex_digit(int i)
804*b0563631STom Van Eyck {
805*b0563631STom Van Eyck     return (i < 10) ? (i + '0') : (i - 10 + 'A');
806*b0563631STom Van Eyck }
807*b0563631STom Van Eyck 
808817466cbSJens Wiklander /*
809817466cbSJens Wiklander  * Store the name in printable form into buf; no more
810817466cbSJens Wiklander  * than size characters will be written
811817466cbSJens Wiklander  */
mbedtls_x509_dn_gets(char * buf,size_t size,const mbedtls_x509_name * dn)812817466cbSJens Wiklander int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn)
813817466cbSJens Wiklander {
81411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
815*b0563631STom Van Eyck     size_t i, j, n, asn1_len_size, asn1_tag_size, asn1_tag_len_buf_start;
816*b0563631STom Van Eyck     /* 6 is enough as our asn1 write functions only write one byte for the tag and at most five bytes for the length*/
817*b0563631STom Van Eyck     unsigned char asn1_tag_len_buf[6];
818*b0563631STom Van Eyck     unsigned char *asn1_len_p;
819817466cbSJens Wiklander     unsigned char c, merge = 0;
820817466cbSJens Wiklander     const mbedtls_x509_name *name;
821817466cbSJens Wiklander     const char *short_name = NULL;
822*b0563631STom Van Eyck     char lowbits, highbits;
823817466cbSJens Wiklander     char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
824*b0563631STom Van Eyck     int print_hexstring;
825817466cbSJens Wiklander 
826817466cbSJens Wiklander     memset(s, 0, sizeof(s));
827817466cbSJens Wiklander 
828817466cbSJens Wiklander     name = dn;
829817466cbSJens Wiklander     p = buf;
830817466cbSJens Wiklander     n = size;
831817466cbSJens Wiklander 
83232b31808SJens Wiklander     while (name != NULL) {
83332b31808SJens Wiklander         if (!name->oid.p) {
834817466cbSJens Wiklander             name = name->next;
835817466cbSJens Wiklander             continue;
836817466cbSJens Wiklander         }
837817466cbSJens Wiklander 
83832b31808SJens Wiklander         if (name != dn) {
839817466cbSJens Wiklander             ret = mbedtls_snprintf(p, n, merge ? " + " : ", ");
840817466cbSJens Wiklander             MBEDTLS_X509_SAFE_SNPRINTF;
841817466cbSJens Wiklander         }
842817466cbSJens Wiklander 
843*b0563631STom Van Eyck         print_hexstring = (name->val.tag != MBEDTLS_ASN1_UTF8_STRING) &&
844*b0563631STom Van Eyck                           (name->val.tag != MBEDTLS_ASN1_PRINTABLE_STRING) &&
845*b0563631STom Van Eyck                           (name->val.tag != MBEDTLS_ASN1_IA5_STRING);
846817466cbSJens Wiklander 
847*b0563631STom Van Eyck         if ((ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name)) == 0) {
848817466cbSJens Wiklander             ret = mbedtls_snprintf(p, n, "%s=", short_name);
84932b31808SJens Wiklander         } else {
850*b0563631STom Van Eyck             if ((ret = mbedtls_oid_get_numeric_string(p, n, &name->oid)) > 0) {
851*b0563631STom Van Eyck                 n -= ret;
852*b0563631STom Van Eyck                 p += ret;
853*b0563631STom Van Eyck                 ret = mbedtls_snprintf(p, n, "=");
854*b0563631STom Van Eyck                 print_hexstring = 1;
855*b0563631STom Van Eyck             } else if (ret == MBEDTLS_ERR_OID_BUF_TOO_SMALL) {
856*b0563631STom Van Eyck                 return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
857*b0563631STom Van Eyck             } else {
858817466cbSJens Wiklander                 ret = mbedtls_snprintf(p, n, "\?\?=");
85932b31808SJens Wiklander             }
860*b0563631STom Van Eyck         }
861817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
862817466cbSJens Wiklander 
863*b0563631STom Van Eyck         if (print_hexstring) {
864*b0563631STom Van Eyck             s[0] = '#';
865*b0563631STom Van Eyck 
866*b0563631STom Van Eyck             asn1_len_p = asn1_tag_len_buf + sizeof(asn1_tag_len_buf);
867*b0563631STom Van Eyck             if ((ret = mbedtls_asn1_write_len(&asn1_len_p, asn1_tag_len_buf, name->val.len)) < 0) {
868*b0563631STom Van Eyck                 return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
869*b0563631STom Van Eyck             }
870*b0563631STom Van Eyck             asn1_len_size = ret;
871*b0563631STom Van Eyck             if ((ret = mbedtls_asn1_write_tag(&asn1_len_p, asn1_tag_len_buf, name->val.tag)) < 0) {
872*b0563631STom Van Eyck                 return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
873*b0563631STom Van Eyck             }
874*b0563631STom Van Eyck             asn1_tag_size = ret;
875*b0563631STom Van Eyck             asn1_tag_len_buf_start = sizeof(asn1_tag_len_buf) - asn1_len_size - asn1_tag_size;
876*b0563631STom Van Eyck             for (i = 0, j = 1; i < asn1_len_size + asn1_tag_size; i++) {
877*b0563631STom Van Eyck                 if (j + 1 >= sizeof(s) - 1) {
878*b0563631STom Van Eyck                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
879*b0563631STom Van Eyck                 }
880*b0563631STom Van Eyck                 c = asn1_tag_len_buf[asn1_tag_len_buf_start+i];
881*b0563631STom Van Eyck                 lowbits = (c & 0x0F);
882*b0563631STom Van Eyck                 highbits = c >> 4;
883*b0563631STom Van Eyck                 s[j++] = nibble_to_hex_digit(highbits);
884*b0563631STom Van Eyck                 s[j++] = nibble_to_hex_digit(lowbits);
885*b0563631STom Van Eyck             }
886*b0563631STom Van Eyck             for (i = 0; i < name->val.len; i++) {
887*b0563631STom Van Eyck                 if (j + 1 >= sizeof(s) - 1) {
888*b0563631STom Van Eyck                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
889*b0563631STom Van Eyck                 }
890*b0563631STom Van Eyck                 c = name->val.p[i];
891*b0563631STom Van Eyck                 lowbits = (c & 0x0F);
892*b0563631STom Van Eyck                 highbits = c >> 4;
893*b0563631STom Van Eyck                 s[j++] = nibble_to_hex_digit(highbits);
894*b0563631STom Van Eyck                 s[j++] = nibble_to_hex_digit(lowbits);
895*b0563631STom Van Eyck             }
896*b0563631STom Van Eyck         } else {
89732b31808SJens Wiklander             for (i = 0, j = 0; i < name->val.len; i++, j++) {
89832b31808SJens Wiklander                 if (j >= sizeof(s) - 1) {
89932b31808SJens Wiklander                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
90032b31808SJens Wiklander                 }
901817466cbSJens Wiklander 
902817466cbSJens Wiklander                 c = name->val.p[i];
903*b0563631STom Van Eyck                 // Special characters requiring escaping, RFC 4514 Section 2.4
904*b0563631STom Van Eyck                 if (c == '\0') {
905*b0563631STom Van Eyck                     return MBEDTLS_ERR_X509_INVALID_NAME;
906*b0563631STom Van Eyck                 } else {
907*b0563631STom Van Eyck                     if (strchr(",=+<>;\"\\", c) ||
908*b0563631STom Van Eyck                         ((i == 0) && strchr("# ", c)) ||
909*b0563631STom Van Eyck                         ((i == name->val.len-1) && (c == ' '))) {
91032b31808SJens Wiklander                         if (j + 1 >= sizeof(s) - 1) {
91132b31808SJens Wiklander                             return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
91232b31808SJens Wiklander                         }
913039e02dfSJerome Forissier                         s[j++] = '\\';
914817466cbSJens Wiklander                     }
915*b0563631STom Van Eyck                 }
91632b31808SJens Wiklander                 if (c < 32 || c >= 127) {
917*b0563631STom Van Eyck                     if (j + 3 >= sizeof(s) - 1) {
918*b0563631STom Van Eyck                         return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
919*b0563631STom Van Eyck                     }
920*b0563631STom Van Eyck                     s[j++] = '\\';
921*b0563631STom Van Eyck                     lowbits = (c & 0x0F);
922*b0563631STom Van Eyck                     highbits = c >> 4;
923*b0563631STom Van Eyck                     s[j++] = nibble_to_hex_digit(highbits);
924*b0563631STom Van Eyck                     s[j] = nibble_to_hex_digit(lowbits);
92532b31808SJens Wiklander                 } else {
92632b31808SJens Wiklander                     s[j] = c;
92732b31808SJens Wiklander                 }
928039e02dfSJerome Forissier             }
929*b0563631STom Van Eyck         }
930039e02dfSJerome Forissier         s[j] = '\0';
931817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, "%s", s);
932817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
933817466cbSJens Wiklander 
934817466cbSJens Wiklander         merge = name->next_merged;
935817466cbSJens Wiklander         name = name->next;
936817466cbSJens Wiklander     }
937817466cbSJens Wiklander 
93832b31808SJens Wiklander     return (int) (size - n);
939817466cbSJens Wiklander }
940817466cbSJens Wiklander 
941817466cbSJens Wiklander /*
942817466cbSJens Wiklander  * Store the serial in printable form into buf; no more
943817466cbSJens Wiklander  * than size characters will be written
944817466cbSJens Wiklander  */
mbedtls_x509_serial_gets(char * buf,size_t size,const mbedtls_x509_buf * serial)945817466cbSJens Wiklander int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial)
946817466cbSJens Wiklander {
94711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
948817466cbSJens Wiklander     size_t i, n, nr;
949817466cbSJens Wiklander     char *p;
950817466cbSJens Wiklander 
951817466cbSJens Wiklander     p = buf;
952817466cbSJens Wiklander     n = size;
953817466cbSJens Wiklander 
954817466cbSJens Wiklander     nr = (serial->len <= 32)
955817466cbSJens Wiklander         ? serial->len  : 28;
956817466cbSJens Wiklander 
95732b31808SJens Wiklander     for (i = 0; i < nr; i++) {
95832b31808SJens Wiklander         if (i == 0 && nr > 1 && serial->p[i] == 0x0) {
959817466cbSJens Wiklander             continue;
96032b31808SJens Wiklander         }
961817466cbSJens Wiklander 
962817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, "%02X%s",
963817466cbSJens Wiklander                                serial->p[i], (i < nr - 1) ? ":" : "");
964817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
965817466cbSJens Wiklander     }
966817466cbSJens Wiklander 
96732b31808SJens Wiklander     if (nr != serial->len) {
968817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, "....");
969817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
970817466cbSJens Wiklander     }
971817466cbSJens Wiklander 
97232b31808SJens Wiklander     return (int) (size - n);
973817466cbSJens Wiklander }
974817466cbSJens Wiklander 
97532b31808SJens Wiklander #if !defined(MBEDTLS_X509_REMOVE_INFO)
976817466cbSJens Wiklander /*
977817466cbSJens Wiklander  * Helper for writing signature algorithms
978817466cbSJens Wiklander  */
mbedtls_x509_sig_alg_gets(char * buf,size_t size,const mbedtls_x509_buf * sig_oid,mbedtls_pk_type_t pk_alg,mbedtls_md_type_t md_alg,const void * sig_opts)979817466cbSJens Wiklander int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
980817466cbSJens Wiklander                               mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
981817466cbSJens Wiklander                               const void *sig_opts)
982817466cbSJens Wiklander {
98311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
984817466cbSJens Wiklander     char *p = buf;
985817466cbSJens Wiklander     size_t n = size;
986817466cbSJens Wiklander     const char *desc = NULL;
987817466cbSJens Wiklander 
988817466cbSJens Wiklander     ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc);
98932b31808SJens Wiklander     if (ret != 0) {
990817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, "???");
99132b31808SJens Wiklander     } else {
992817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, "%s", desc);
99332b31808SJens Wiklander     }
994817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
995817466cbSJens Wiklander 
996817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
99732b31808SJens Wiklander     if (pk_alg == MBEDTLS_PK_RSASSA_PSS) {
998817466cbSJens Wiklander         const mbedtls_pk_rsassa_pss_options *pss_opts;
999817466cbSJens Wiklander 
1000817466cbSJens Wiklander         pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
1001817466cbSJens Wiklander 
100232b31808SJens Wiklander         const char *name = md_type_to_string(md_alg);
100332b31808SJens Wiklander         const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id);
1004817466cbSJens Wiklander 
1005817466cbSJens Wiklander         ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)",
100632b31808SJens Wiklander                                name ? name : "???",
100732b31808SJens Wiklander                                mgf_name ? mgf_name : "???",
10087901324dSJerome Forissier                                (unsigned int) pss_opts->expected_salt_len);
1009817466cbSJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
1010817466cbSJens Wiklander     }
1011817466cbSJens Wiklander #else
1012817466cbSJens Wiklander     ((void) pk_alg);
1013817466cbSJens Wiklander     ((void) md_alg);
1014817466cbSJens Wiklander     ((void) sig_opts);
1015817466cbSJens Wiklander #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
1016817466cbSJens Wiklander 
101732b31808SJens Wiklander     return (int) (size - n);
1018817466cbSJens Wiklander }
101932b31808SJens Wiklander #endif /* MBEDTLS_X509_REMOVE_INFO */
1020817466cbSJens Wiklander 
1021817466cbSJens Wiklander /*
1022817466cbSJens Wiklander  * Helper for writing "RSA key size", "EC key size", etc
1023817466cbSJens Wiklander  */
mbedtls_x509_key_size_helper(char * buf,size_t buf_size,const char * name)1024817466cbSJens Wiklander int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name)
1025817466cbSJens Wiklander {
1026817466cbSJens Wiklander     char *p = buf;
1027817466cbSJens Wiklander     size_t n = buf_size;
102811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1029817466cbSJens Wiklander 
1030817466cbSJens Wiklander     ret = mbedtls_snprintf(p, n, "%s key size", name);
1031817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
1032817466cbSJens Wiklander 
103332b31808SJens Wiklander     return 0;
1034817466cbSJens Wiklander }
1035817466cbSJens Wiklander 
mbedtls_x509_time_cmp(const mbedtls_x509_time * t1,const mbedtls_x509_time * t2)1036*b0563631STom Van Eyck int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1,
1037*b0563631STom Van Eyck                           const mbedtls_x509_time *t2)
1038*b0563631STom Van Eyck {
1039*b0563631STom Van Eyck     int x;
1040*b0563631STom Van Eyck 
1041*b0563631STom Van Eyck     x = (((t1->year << 9) | (t1->mon << 5) | (t1->day)) -
1042*b0563631STom Van Eyck          ((t2->year << 9) | (t2->mon << 5) | (t2->day)));
1043*b0563631STom Van Eyck     if (x != 0) {
1044*b0563631STom Van Eyck         return x;
1045*b0563631STom Van Eyck     }
1046*b0563631STom Van Eyck 
1047*b0563631STom Van Eyck     x = (((t1->hour << 12) | (t1->min << 6) | (t1->sec)) -
1048*b0563631STom Van Eyck          ((t2->hour << 12) | (t2->min << 6) | (t2->sec)));
1049*b0563631STom Van Eyck     return x;
1050*b0563631STom Van Eyck }
1051*b0563631STom Van Eyck 
1052817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_TIME_DATE)
mbedtls_x509_time_gmtime(mbedtls_time_t tt,mbedtls_x509_time * now)1053*b0563631STom Van Eyck int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now)
1054*b0563631STom Van Eyck {
1055*b0563631STom Van Eyck     struct tm tm;
1056*b0563631STom Van Eyck 
1057*b0563631STom Van Eyck     if (mbedtls_platform_gmtime_r(&tt, &tm) == NULL) {
1058*b0563631STom Van Eyck         return -1;
1059*b0563631STom Van Eyck     }
1060*b0563631STom Van Eyck 
1061*b0563631STom Van Eyck     now->year = tm.tm_year + 1900;
1062*b0563631STom Van Eyck     now->mon  = tm.tm_mon  + 1;
1063*b0563631STom Van Eyck     now->day  = tm.tm_mday;
1064*b0563631STom Van Eyck     now->hour = tm.tm_hour;
1065*b0563631STom Van Eyck     now->min  = tm.tm_min;
1066*b0563631STom Van Eyck     now->sec  = tm.tm_sec;
1067*b0563631STom Van Eyck     return 0;
1068*b0563631STom Van Eyck }
1069*b0563631STom Van Eyck 
x509_get_current_time(mbedtls_x509_time * now)1070817466cbSJens Wiklander static int x509_get_current_time(mbedtls_x509_time *now)
1071817466cbSJens Wiklander {
1072*b0563631STom Van Eyck     return mbedtls_x509_time_gmtime(mbedtls_time(NULL), now);
1073817466cbSJens Wiklander }
1074817466cbSJens Wiklander 
mbedtls_x509_time_is_past(const mbedtls_x509_time * to)1075817466cbSJens Wiklander int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
1076817466cbSJens Wiklander {
1077817466cbSJens Wiklander     mbedtls_x509_time now;
1078817466cbSJens Wiklander 
107932b31808SJens Wiklander     if (x509_get_current_time(&now) != 0) {
108032b31808SJens Wiklander         return 1;
108132b31808SJens Wiklander     }
1082817466cbSJens Wiklander 
1083*b0563631STom Van Eyck     return mbedtls_x509_time_cmp(to, &now) < 0;
1084817466cbSJens Wiklander }
1085817466cbSJens Wiklander 
mbedtls_x509_time_is_future(const mbedtls_x509_time * from)1086817466cbSJens Wiklander int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
1087817466cbSJens Wiklander {
1088817466cbSJens Wiklander     mbedtls_x509_time now;
1089817466cbSJens Wiklander 
109032b31808SJens Wiklander     if (x509_get_current_time(&now) != 0) {
109132b31808SJens Wiklander         return 1;
109232b31808SJens Wiklander     }
1093817466cbSJens Wiklander 
1094*b0563631STom Van Eyck     return mbedtls_x509_time_cmp(from, &now) > 0;
1095817466cbSJens Wiklander }
1096817466cbSJens Wiklander 
1097817466cbSJens Wiklander #else  /* MBEDTLS_HAVE_TIME_DATE */
1098817466cbSJens Wiklander 
mbedtls_x509_time_is_past(const mbedtls_x509_time * to)1099817466cbSJens Wiklander int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
1100817466cbSJens Wiklander {
1101817466cbSJens Wiklander     ((void) to);
110232b31808SJens Wiklander     return 0;
1103817466cbSJens Wiklander }
1104817466cbSJens Wiklander 
mbedtls_x509_time_is_future(const mbedtls_x509_time * from)1105817466cbSJens Wiklander int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
1106817466cbSJens Wiklander {
1107817466cbSJens Wiklander     ((void) from);
110832b31808SJens Wiklander     return 0;
1109817466cbSJens Wiklander }
1110817466cbSJens Wiklander #endif /* MBEDTLS_HAVE_TIME_DATE */
1111817466cbSJens Wiklander 
111232b31808SJens Wiklander /* Common functions for parsing CRT and CSR. */
111332b31808SJens Wiklander #if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C)
1114817466cbSJens Wiklander /*
111532b31808SJens Wiklander  * OtherName ::= SEQUENCE {
111632b31808SJens Wiklander  *      type-id    OBJECT IDENTIFIER,
111732b31808SJens Wiklander  *      value      [0] EXPLICIT ANY DEFINED BY type-id }
111832b31808SJens Wiklander  *
111932b31808SJens Wiklander  * HardwareModuleName ::= SEQUENCE {
112032b31808SJens Wiklander  *                           hwType OBJECT IDENTIFIER,
112132b31808SJens Wiklander  *                           hwSerialNum OCTET STRING }
112232b31808SJens Wiklander  *
112332b31808SJens Wiklander  * NOTE: we currently only parse and use otherName of type HwModuleName,
112432b31808SJens Wiklander  * as defined in RFC 4108.
1125817466cbSJens Wiklander  */
x509_get_other_name(const mbedtls_x509_buf * subject_alt_name,mbedtls_x509_san_other_name * other_name)112632b31808SJens Wiklander static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name,
112732b31808SJens Wiklander                                mbedtls_x509_san_other_name *other_name)
1128817466cbSJens Wiklander {
11295b25c76aSJerome Forissier     int ret = 0;
113032b31808SJens Wiklander     size_t len;
113132b31808SJens Wiklander     unsigned char *p = subject_alt_name->p;
113232b31808SJens Wiklander     const unsigned char *end = p + subject_alt_name->len;
113332b31808SJens Wiklander     mbedtls_x509_buf cur_oid;
1134817466cbSJens Wiklander 
113532b31808SJens Wiklander     if ((subject_alt_name->tag &
113632b31808SJens Wiklander          (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) !=
113732b31808SJens Wiklander         (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) {
113832b31808SJens Wiklander         /*
113932b31808SJens Wiklander          * The given subject alternative name is not of type "othername".
114032b31808SJens Wiklander          */
114132b31808SJens Wiklander         return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
114232b31808SJens Wiklander     }
1143817466cbSJens Wiklander 
114432b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
114532b31808SJens Wiklander                                     MBEDTLS_ASN1_OID)) != 0) {
114632b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
114732b31808SJens Wiklander     }
1148817466cbSJens Wiklander 
114932b31808SJens Wiklander     cur_oid.tag = MBEDTLS_ASN1_OID;
115032b31808SJens Wiklander     cur_oid.p = p;
115132b31808SJens Wiklander     cur_oid.len = len;
115232b31808SJens Wiklander 
115332b31808SJens Wiklander     /*
115432b31808SJens Wiklander      * Only HwModuleName is currently supported.
115532b31808SJens Wiklander      */
115632b31808SJens Wiklander     if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) {
115732b31808SJens Wiklander         return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
115832b31808SJens Wiklander     }
1159*b0563631STom Van Eyck     other_name->type_id = cur_oid;
116032b31808SJens Wiklander 
116132b31808SJens Wiklander     p += len;
116232b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
116332b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
116432b31808SJens Wiklander         0) {
116532b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
116632b31808SJens Wiklander     }
116732b31808SJens Wiklander 
116832b31808SJens Wiklander     if (end != p + len) {
116932b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
117032b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
117132b31808SJens Wiklander     }
117232b31808SJens Wiklander 
117332b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
117432b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
117532b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
117632b31808SJens Wiklander     }
117732b31808SJens Wiklander 
117832b31808SJens Wiklander     if (end != p + len) {
117932b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
118032b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
118132b31808SJens Wiklander     }
118232b31808SJens Wiklander 
118332b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
118432b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
118532b31808SJens Wiklander     }
118632b31808SJens Wiklander 
118732b31808SJens Wiklander     other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
118832b31808SJens Wiklander     other_name->value.hardware_module_name.oid.p = p;
118932b31808SJens Wiklander     other_name->value.hardware_module_name.oid.len = len;
119032b31808SJens Wiklander 
119132b31808SJens Wiklander     p += len;
119232b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
119332b31808SJens Wiklander                                     MBEDTLS_ASN1_OCTET_STRING)) != 0) {
119432b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
119532b31808SJens Wiklander     }
119632b31808SJens Wiklander 
119732b31808SJens Wiklander     other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
119832b31808SJens Wiklander     other_name->value.hardware_module_name.val.p = p;
119932b31808SJens Wiklander     other_name->value.hardware_module_name.val.len = len;
120032b31808SJens Wiklander     p += len;
120132b31808SJens Wiklander     if (p != end) {
120232b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
120332b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
120432b31808SJens Wiklander     }
120532b31808SJens Wiklander     return 0;
120632b31808SJens Wiklander }
120732b31808SJens Wiklander 
1208*b0563631STom Van Eyck /* Check mbedtls_x509_get_subject_alt_name for detailed description.
1209*b0563631STom Van Eyck  *
1210*b0563631STom Van Eyck  * In some cases while parsing subject alternative names the sequence tag is optional
1211*b0563631STom Van Eyck  * (e.g. CertSerialNumber). This function is designed to handle such case.
1212*b0563631STom Van Eyck  */
mbedtls_x509_get_subject_alt_name_ext(unsigned char ** p,const unsigned char * end,mbedtls_x509_sequence * subject_alt_name)1213*b0563631STom Van Eyck int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,
1214*b0563631STom Van Eyck                                           const unsigned char *end,
1215*b0563631STom Van Eyck                                           mbedtls_x509_sequence *subject_alt_name)
1216*b0563631STom Van Eyck {
1217*b0563631STom Van Eyck     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1218*b0563631STom Van Eyck     size_t tag_len;
1219*b0563631STom Van Eyck     mbedtls_asn1_sequence *cur = subject_alt_name;
1220*b0563631STom Van Eyck 
1221*b0563631STom Van Eyck     while (*p < end) {
1222*b0563631STom Van Eyck         mbedtls_x509_subject_alternative_name tmp_san_name;
1223*b0563631STom Van Eyck         mbedtls_x509_buf tmp_san_buf;
1224*b0563631STom Van Eyck         memset(&tmp_san_name, 0, sizeof(tmp_san_name));
1225*b0563631STom Van Eyck 
1226*b0563631STom Van Eyck         tmp_san_buf.tag = **p;
1227*b0563631STom Van Eyck         (*p)++;
1228*b0563631STom Van Eyck 
1229*b0563631STom Van Eyck         if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) {
1230*b0563631STom Van Eyck             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1231*b0563631STom Van Eyck         }
1232*b0563631STom Van Eyck 
1233*b0563631STom Van Eyck         tmp_san_buf.p = *p;
1234*b0563631STom Van Eyck         tmp_san_buf.len = tag_len;
1235*b0563631STom Van Eyck 
1236*b0563631STom Van Eyck         if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
1237*b0563631STom Van Eyck             MBEDTLS_ASN1_CONTEXT_SPECIFIC) {
1238*b0563631STom Van Eyck             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1239*b0563631STom Van Eyck                                      MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
1240*b0563631STom Van Eyck         }
1241*b0563631STom Van Eyck 
1242*b0563631STom Van Eyck         /*
1243*b0563631STom Van Eyck          * Check that the SAN is structured correctly by parsing it.
1244*b0563631STom Van Eyck          * The SAN structure is discarded afterwards.
1245*b0563631STom Van Eyck          */
1246*b0563631STom Van Eyck         ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &tmp_san_name);
1247*b0563631STom Van Eyck         /*
1248*b0563631STom Van Eyck          * In case the extension is malformed, return an error,
1249*b0563631STom Van Eyck          * and clear the allocated sequences.
1250*b0563631STom Van Eyck          */
1251*b0563631STom Van Eyck         if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
1252*b0563631STom Van Eyck             mbedtls_asn1_sequence_free(subject_alt_name->next);
1253*b0563631STom Van Eyck             subject_alt_name->next = NULL;
1254*b0563631STom Van Eyck             return ret;
1255*b0563631STom Van Eyck         }
1256*b0563631STom Van Eyck 
1257*b0563631STom Van Eyck         mbedtls_x509_free_subject_alt_name(&tmp_san_name);
1258*b0563631STom Van Eyck         /* Allocate and assign next pointer */
1259*b0563631STom Van Eyck         if (cur->buf.p != NULL) {
1260*b0563631STom Van Eyck             if (cur->next != NULL) {
1261*b0563631STom Van Eyck                 return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1262*b0563631STom Van Eyck             }
1263*b0563631STom Van Eyck 
1264*b0563631STom Van Eyck             cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
1265*b0563631STom Van Eyck 
1266*b0563631STom Van Eyck             if (cur->next == NULL) {
1267*b0563631STom Van Eyck                 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1268*b0563631STom Van Eyck                                          MBEDTLS_ERR_ASN1_ALLOC_FAILED);
1269*b0563631STom Van Eyck             }
1270*b0563631STom Van Eyck 
1271*b0563631STom Van Eyck             cur = cur->next;
1272*b0563631STom Van Eyck         }
1273*b0563631STom Van Eyck 
1274*b0563631STom Van Eyck         cur->buf = tmp_san_buf;
1275*b0563631STom Van Eyck         *p += tmp_san_buf.len;
1276*b0563631STom Van Eyck     }
1277*b0563631STom Van Eyck 
1278*b0563631STom Van Eyck     /* Set final sequence entry's next pointer to NULL */
1279*b0563631STom Van Eyck     cur->next = NULL;
1280*b0563631STom Van Eyck 
1281*b0563631STom Van Eyck     if (*p != end) {
1282*b0563631STom Van Eyck         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1283*b0563631STom Van Eyck                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1284*b0563631STom Van Eyck     }
1285*b0563631STom Van Eyck 
1286*b0563631STom Van Eyck     return 0;
1287*b0563631STom Van Eyck }
1288*b0563631STom Van Eyck 
128932b31808SJens Wiklander /*
129032b31808SJens Wiklander  * SubjectAltName ::= GeneralNames
129132b31808SJens Wiklander  *
129232b31808SJens Wiklander  * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
129332b31808SJens Wiklander  *
129432b31808SJens Wiklander  * GeneralName ::= CHOICE {
129532b31808SJens Wiklander  *      otherName                       [0]     OtherName,
129632b31808SJens Wiklander  *      rfc822Name                      [1]     IA5String,
129732b31808SJens Wiklander  *      dNSName                         [2]     IA5String,
129832b31808SJens Wiklander  *      x400Address                     [3]     ORAddress,
129932b31808SJens Wiklander  *      directoryName                   [4]     Name,
130032b31808SJens Wiklander  *      ediPartyName                    [5]     EDIPartyName,
130132b31808SJens Wiklander  *      uniformResourceIdentifier       [6]     IA5String,
130232b31808SJens Wiklander  *      iPAddress                       [7]     OCTET STRING,
130332b31808SJens Wiklander  *      registeredID                    [8]     OBJECT IDENTIFIER }
130432b31808SJens Wiklander  *
130532b31808SJens Wiklander  * OtherName ::= SEQUENCE {
130632b31808SJens Wiklander  *      type-id    OBJECT IDENTIFIER,
130732b31808SJens Wiklander  *      value      [0] EXPLICIT ANY DEFINED BY type-id }
130832b31808SJens Wiklander  *
130932b31808SJens Wiklander  * EDIPartyName ::= SEQUENCE {
131032b31808SJens Wiklander  *      nameAssigner            [0]     DirectoryString OPTIONAL,
131132b31808SJens Wiklander  *      partyName               [1]     DirectoryString }
131232b31808SJens Wiklander  *
131332b31808SJens Wiklander  * We list all types, but use the following GeneralName types from RFC 5280:
131432b31808SJens Wiklander  * "dnsName", "uniformResourceIdentifier" and "hardware_module_name"
131532b31808SJens Wiklander  * of type "otherName", as defined in RFC 4108.
131632b31808SJens Wiklander  */
mbedtls_x509_get_subject_alt_name(unsigned char ** p,const unsigned char * end,mbedtls_x509_sequence * subject_alt_name)131732b31808SJens Wiklander int mbedtls_x509_get_subject_alt_name(unsigned char **p,
131832b31808SJens Wiklander                                       const unsigned char *end,
131932b31808SJens Wiklander                                       mbedtls_x509_sequence *subject_alt_name)
1320817466cbSJens Wiklander {
132132b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1322*b0563631STom Van Eyck     size_t len;
1323817466cbSJens Wiklander 
132432b31808SJens Wiklander     /* Get main sequence tag */
132532b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
132632b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
132732b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1328817466cbSJens Wiklander     }
1329817466cbSJens Wiklander 
133032b31808SJens Wiklander     if (*p + len != end) {
133132b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
133232b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
133332b31808SJens Wiklander     }
133432b31808SJens Wiklander 
1335*b0563631STom Van Eyck     return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name);
133632b31808SJens Wiklander }
133732b31808SJens Wiklander 
mbedtls_x509_get_ns_cert_type(unsigned char ** p,const unsigned char * end,unsigned char * ns_cert_type)133832b31808SJens Wiklander int mbedtls_x509_get_ns_cert_type(unsigned char **p,
133932b31808SJens Wiklander                                   const unsigned char *end,
134032b31808SJens Wiklander                                   unsigned char *ns_cert_type)
1341817466cbSJens Wiklander {
134232b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
134332b31808SJens Wiklander     mbedtls_x509_bitstring bs = { 0, 0, NULL };
1344817466cbSJens Wiklander 
134532b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
134632b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1347817466cbSJens Wiklander     }
1348817466cbSJens Wiklander 
134932b31808SJens Wiklander     /* A bitstring with no flags set is still technically valid, as it will mean
135032b31808SJens Wiklander        that the certificate has no designated purpose at the time of creation. */
135132b31808SJens Wiklander     if (bs.len == 0) {
135232b31808SJens Wiklander         *ns_cert_type = 0;
135332b31808SJens Wiklander         return 0;
135432b31808SJens Wiklander     }
1355817466cbSJens Wiklander 
135632b31808SJens Wiklander     if (bs.len != 1) {
135732b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
135832b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_INVALID_LENGTH);
135932b31808SJens Wiklander     }
136032b31808SJens Wiklander 
136132b31808SJens Wiklander     /* Get actual bitstring */
136232b31808SJens Wiklander     *ns_cert_type = *bs.p;
136332b31808SJens Wiklander     return 0;
136432b31808SJens Wiklander }
136532b31808SJens Wiklander 
mbedtls_x509_get_key_usage(unsigned char ** p,const unsigned char * end,unsigned int * key_usage)136632b31808SJens Wiklander int mbedtls_x509_get_key_usage(unsigned char **p,
136732b31808SJens Wiklander                                const unsigned char *end,
136832b31808SJens Wiklander                                unsigned int *key_usage)
1369817466cbSJens Wiklander {
137032b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
137132b31808SJens Wiklander     size_t i;
137232b31808SJens Wiklander     mbedtls_x509_bitstring bs = { 0, 0, NULL };
1373817466cbSJens Wiklander 
137432b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
137532b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1376817466cbSJens Wiklander     }
1377817466cbSJens Wiklander 
137832b31808SJens Wiklander     /* A bitstring with no flags set is still technically valid, as it will mean
137932b31808SJens Wiklander        that the certificate has no designated purpose at the time of creation. */
138032b31808SJens Wiklander     if (bs.len == 0) {
138132b31808SJens Wiklander         *key_usage = 0;
138232b31808SJens Wiklander         return 0;
1383817466cbSJens Wiklander     }
1384817466cbSJens Wiklander 
138532b31808SJens Wiklander     /* Get actual bitstring */
138632b31808SJens Wiklander     *key_usage = 0;
138732b31808SJens Wiklander     for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) {
138832b31808SJens Wiklander         *key_usage |= (unsigned int) bs.p[i] << (8*i);
138932b31808SJens Wiklander     }
1390817466cbSJens Wiklander 
139132b31808SJens Wiklander     return 0;
139232b31808SJens Wiklander }
139332b31808SJens Wiklander 
mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf * san_buf,mbedtls_x509_subject_alternative_name * san)139432b31808SJens Wiklander int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
139532b31808SJens Wiklander                                         mbedtls_x509_subject_alternative_name *san)
139632b31808SJens Wiklander {
139732b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
139832b31808SJens Wiklander     switch (san_buf->tag &
139932b31808SJens Wiklander             (MBEDTLS_ASN1_TAG_CLASS_MASK |
140032b31808SJens Wiklander              MBEDTLS_ASN1_TAG_VALUE_MASK)) {
140132b31808SJens Wiklander         /*
140232b31808SJens Wiklander          * otherName
140332b31808SJens Wiklander          */
140432b31808SJens Wiklander         case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME):
140532b31808SJens Wiklander         {
140632b31808SJens Wiklander             mbedtls_x509_san_other_name other_name;
140732b31808SJens Wiklander 
140832b31808SJens Wiklander             ret = x509_get_other_name(san_buf, &other_name);
140932b31808SJens Wiklander             if (ret != 0) {
141032b31808SJens Wiklander                 return ret;
141132b31808SJens Wiklander             }
141232b31808SJens Wiklander 
141332b31808SJens Wiklander             memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
141432b31808SJens Wiklander             san->type = MBEDTLS_X509_SAN_OTHER_NAME;
141532b31808SJens Wiklander             memcpy(&san->san.other_name,
141632b31808SJens Wiklander                    &other_name, sizeof(other_name));
141732b31808SJens Wiklander 
141832b31808SJens Wiklander         }
141932b31808SJens Wiklander         break;
142032b31808SJens Wiklander         /*
142132b31808SJens Wiklander          * uniformResourceIdentifier
142232b31808SJens Wiklander          */
142332b31808SJens Wiklander         case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER):
142432b31808SJens Wiklander         {
142532b31808SJens Wiklander             memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
142632b31808SJens Wiklander             san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;
142732b31808SJens Wiklander 
142832b31808SJens Wiklander             memcpy(&san->san.unstructured_name,
142932b31808SJens Wiklander                    san_buf, sizeof(*san_buf));
143032b31808SJens Wiklander 
143132b31808SJens Wiklander         }
143232b31808SJens Wiklander         break;
143332b31808SJens Wiklander         /*
143432b31808SJens Wiklander          * dNSName
143532b31808SJens Wiklander          */
143632b31808SJens Wiklander         case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME):
143732b31808SJens Wiklander         {
143832b31808SJens Wiklander             memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
143932b31808SJens Wiklander             san->type = MBEDTLS_X509_SAN_DNS_NAME;
144032b31808SJens Wiklander 
144132b31808SJens Wiklander             memcpy(&san->san.unstructured_name,
144232b31808SJens Wiklander                    san_buf, sizeof(*san_buf));
144332b31808SJens Wiklander         }
144432b31808SJens Wiklander         break;
144532b31808SJens Wiklander         /*
1446*b0563631STom Van Eyck          * IP address
1447*b0563631STom Van Eyck          */
1448*b0563631STom Van Eyck         case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS):
1449*b0563631STom Van Eyck         {
1450*b0563631STom Van Eyck             memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1451*b0563631STom Van Eyck             san->type = MBEDTLS_X509_SAN_IP_ADDRESS;
1452*b0563631STom Van Eyck             // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported
1453*b0563631STom Van Eyck             if (san_buf->len == 4 || san_buf->len == 16) {
1454*b0563631STom Van Eyck                 memcpy(&san->san.unstructured_name,
1455*b0563631STom Van Eyck                        san_buf, sizeof(*san_buf));
1456*b0563631STom Van Eyck             } else {
1457*b0563631STom Van Eyck                 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1458*b0563631STom Van Eyck             }
1459*b0563631STom Van Eyck         }
1460*b0563631STom Van Eyck         break;
1461*b0563631STom Van Eyck         /*
1462*b0563631STom Van Eyck          * rfc822Name
146332b31808SJens Wiklander          */
146432b31808SJens Wiklander         case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME):
146532b31808SJens Wiklander         {
146632b31808SJens Wiklander             memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
146732b31808SJens Wiklander             san->type = MBEDTLS_X509_SAN_RFC822_NAME;
146832b31808SJens Wiklander             memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf));
146932b31808SJens Wiklander         }
147032b31808SJens Wiklander         break;
1471*b0563631STom Van Eyck         /*
1472*b0563631STom Van Eyck          * directoryName
1473*b0563631STom Van Eyck          */
1474*b0563631STom Van Eyck         case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DIRECTORY_NAME):
1475*b0563631STom Van Eyck         {
1476*b0563631STom Van Eyck             size_t name_len;
1477*b0563631STom Van Eyck             unsigned char *p = san_buf->p;
1478*b0563631STom Van Eyck             memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1479*b0563631STom Van Eyck             san->type = MBEDTLS_X509_SAN_DIRECTORY_NAME;
148032b31808SJens Wiklander 
1481*b0563631STom Van Eyck             ret = mbedtls_asn1_get_tag(&p, p + san_buf->len, &name_len,
1482*b0563631STom Van Eyck                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
1483*b0563631STom Van Eyck 
1484*b0563631STom Van Eyck             if (ret != 0) {
1485*b0563631STom Van Eyck                 return ret;
1486*b0563631STom Van Eyck             }
1487*b0563631STom Van Eyck 
1488*b0563631STom Van Eyck             if ((ret = mbedtls_x509_get_name(&p, p + name_len,
1489*b0563631STom Van Eyck                                              &san->san.directory_name)) != 0) {
1490*b0563631STom Van Eyck                 return ret;
1491*b0563631STom Van Eyck             }
1492*b0563631STom Van Eyck         }
1493*b0563631STom Van Eyck         break;
149432b31808SJens Wiklander         /*
149532b31808SJens Wiklander          * Type not supported
149632b31808SJens Wiklander          */
149732b31808SJens Wiklander         default:
149832b31808SJens Wiklander             return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
149932b31808SJens Wiklander     }
150032b31808SJens Wiklander     return 0;
150132b31808SJens Wiklander }
150232b31808SJens Wiklander 
mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name * san)1503*b0563631STom Van Eyck void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san)
1504*b0563631STom Van Eyck {
1505*b0563631STom Van Eyck     if (san->type == MBEDTLS_X509_SAN_DIRECTORY_NAME) {
1506*b0563631STom Van Eyck         mbedtls_asn1_free_named_data_list_shallow(san->san.directory_name.next);
1507*b0563631STom Van Eyck     }
1508*b0563631STom Van Eyck }
1509*b0563631STom Van Eyck 
151032b31808SJens Wiklander #if !defined(MBEDTLS_X509_REMOVE_INFO)
mbedtls_x509_info_subject_alt_name(char ** buf,size_t * size,const mbedtls_x509_sequence * subject_alt_name,const char * prefix)151132b31808SJens Wiklander int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
151232b31808SJens Wiklander                                        const mbedtls_x509_sequence
151332b31808SJens Wiklander                                        *subject_alt_name,
151432b31808SJens Wiklander                                        const char *prefix)
151532b31808SJens Wiklander {
151632b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
151732b31808SJens Wiklander     size_t i;
151832b31808SJens Wiklander     size_t n = *size;
151932b31808SJens Wiklander     char *p = *buf;
152032b31808SJens Wiklander     const mbedtls_x509_sequence *cur = subject_alt_name;
152132b31808SJens Wiklander     mbedtls_x509_subject_alternative_name san;
152232b31808SJens Wiklander     int parse_ret;
152332b31808SJens Wiklander 
152432b31808SJens Wiklander     while (cur != NULL) {
152532b31808SJens Wiklander         memset(&san, 0, sizeof(san));
152632b31808SJens Wiklander         parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san);
152732b31808SJens Wiklander         if (parse_ret != 0) {
152832b31808SJens Wiklander             if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
152932b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n, "\n%s    <unsupported>", prefix);
153032b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
153132b31808SJens Wiklander             } else {
153232b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n, "\n%s    <malformed>", prefix);
153332b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
153432b31808SJens Wiklander             }
153532b31808SJens Wiklander             cur = cur->next;
153632b31808SJens Wiklander             continue;
153732b31808SJens Wiklander         }
153832b31808SJens Wiklander 
153932b31808SJens Wiklander         switch (san.type) {
154032b31808SJens Wiklander             /*
154132b31808SJens Wiklander              * otherName
154232b31808SJens Wiklander              */
154332b31808SJens Wiklander             case MBEDTLS_X509_SAN_OTHER_NAME:
154432b31808SJens Wiklander             {
154532b31808SJens Wiklander                 mbedtls_x509_san_other_name *other_name = &san.san.other_name;
154632b31808SJens Wiklander 
154732b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n, "\n%s    otherName :", prefix);
154832b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
154932b31808SJens Wiklander 
155032b31808SJens Wiklander                 if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME,
1551*b0563631STom Van Eyck                                     &other_name->type_id) == 0) {
155232b31808SJens Wiklander                     ret = mbedtls_snprintf(p, n, "\n%s        hardware module name :", prefix);
155332b31808SJens Wiklander                     MBEDTLS_X509_SAFE_SNPRINTF;
155432b31808SJens Wiklander                     ret =
155532b31808SJens Wiklander                         mbedtls_snprintf(p, n, "\n%s            hardware type          : ", prefix);
155632b31808SJens Wiklander                     MBEDTLS_X509_SAFE_SNPRINTF;
155732b31808SJens Wiklander 
155832b31808SJens Wiklander                     ret = mbedtls_oid_get_numeric_string(p,
155932b31808SJens Wiklander                                                          n,
156032b31808SJens Wiklander                                                          &other_name->value.hardware_module_name.oid);
156132b31808SJens Wiklander                     MBEDTLS_X509_SAFE_SNPRINTF;
156232b31808SJens Wiklander 
156332b31808SJens Wiklander                     ret =
156432b31808SJens Wiklander                         mbedtls_snprintf(p, n, "\n%s            hardware serial number : ", prefix);
156532b31808SJens Wiklander                     MBEDTLS_X509_SAFE_SNPRINTF;
156632b31808SJens Wiklander 
156732b31808SJens Wiklander                     for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) {
156832b31808SJens Wiklander                         ret = mbedtls_snprintf(p,
156932b31808SJens Wiklander                                                n,
157032b31808SJens Wiklander                                                "%02X",
157132b31808SJens Wiklander                                                other_name->value.hardware_module_name.val.p[i]);
157232b31808SJens Wiklander                         MBEDTLS_X509_SAFE_SNPRINTF;
157332b31808SJens Wiklander                     }
157432b31808SJens Wiklander                 }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
157532b31808SJens Wiklander             }
157632b31808SJens Wiklander             break;
157732b31808SJens Wiklander             /*
157832b31808SJens Wiklander              * uniformResourceIdentifier
157932b31808SJens Wiklander              */
158032b31808SJens Wiklander             case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
158132b31808SJens Wiklander             {
158232b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n, "\n%s    uniformResourceIdentifier : ", prefix);
158332b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
158432b31808SJens Wiklander                 if (san.san.unstructured_name.len >= n) {
1585*b0563631STom Van Eyck                     if (n > 0) {
158632b31808SJens Wiklander                         *p = '\0';
1587*b0563631STom Van Eyck                     }
158832b31808SJens Wiklander                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
158932b31808SJens Wiklander                 }
159032b31808SJens Wiklander 
159132b31808SJens Wiklander                 memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
159232b31808SJens Wiklander                 p += san.san.unstructured_name.len;
159332b31808SJens Wiklander                 n -= san.san.unstructured_name.len;
159432b31808SJens Wiklander             }
159532b31808SJens Wiklander             break;
159632b31808SJens Wiklander             /*
159732b31808SJens Wiklander              * dNSName
159832b31808SJens Wiklander              * RFC822 Name
159932b31808SJens Wiklander              */
160032b31808SJens Wiklander             case MBEDTLS_X509_SAN_DNS_NAME:
160132b31808SJens Wiklander             case MBEDTLS_X509_SAN_RFC822_NAME:
160232b31808SJens Wiklander             {
160332b31808SJens Wiklander                 const char *dns_name = "dNSName";
160432b31808SJens Wiklander                 const char *rfc822_name = "rfc822Name";
160532b31808SJens Wiklander 
160632b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n,
160732b31808SJens Wiklander                                        "\n%s    %s : ",
160832b31808SJens Wiklander                                        prefix,
160932b31808SJens Wiklander                                        san.type ==
161032b31808SJens Wiklander                                        MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name);
161132b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
161232b31808SJens Wiklander                 if (san.san.unstructured_name.len >= n) {
1613*b0563631STom Van Eyck                     if (n > 0) {
161432b31808SJens Wiklander                         *p = '\0';
1615*b0563631STom Van Eyck                     }
161632b31808SJens Wiklander                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
161732b31808SJens Wiklander                 }
161832b31808SJens Wiklander 
161932b31808SJens Wiklander                 memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
162032b31808SJens Wiklander                 p += san.san.unstructured_name.len;
162132b31808SJens Wiklander                 n -= san.san.unstructured_name.len;
162232b31808SJens Wiklander             }
162332b31808SJens Wiklander             break;
1624*b0563631STom Van Eyck             /*
1625*b0563631STom Van Eyck              * iPAddress
1626*b0563631STom Van Eyck              */
1627*b0563631STom Van Eyck             case MBEDTLS_X509_SAN_IP_ADDRESS:
1628*b0563631STom Van Eyck             {
1629*b0563631STom Van Eyck                 ret = mbedtls_snprintf(p, n, "\n%s    %s : ",
1630*b0563631STom Van Eyck                                        prefix, "iPAddress");
1631*b0563631STom Van Eyck                 MBEDTLS_X509_SAFE_SNPRINTF;
1632*b0563631STom Van Eyck                 if (san.san.unstructured_name.len >= n) {
1633*b0563631STom Van Eyck                     if (n > 0) {
1634*b0563631STom Van Eyck                         *p = '\0';
1635*b0563631STom Van Eyck                     }
1636*b0563631STom Van Eyck                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1637*b0563631STom Van Eyck                 }
163832b31808SJens Wiklander 
1639*b0563631STom Van Eyck                 unsigned char *ip = san.san.unstructured_name.p;
1640*b0563631STom Van Eyck                 // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported
1641*b0563631STom Van Eyck                 if (san.san.unstructured_name.len == 4) {
1642*b0563631STom Van Eyck                     ret = mbedtls_snprintf(p, n, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
1643*b0563631STom Van Eyck                     MBEDTLS_X509_SAFE_SNPRINTF;
1644*b0563631STom Van Eyck                 } else if (san.san.unstructured_name.len == 16) {
1645*b0563631STom Van Eyck                     ret = mbedtls_snprintf(p, n,
1646*b0563631STom Van Eyck                                            "%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X",
1647*b0563631STom Van Eyck                                            ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6],
1648*b0563631STom Van Eyck                                            ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13],
1649*b0563631STom Van Eyck                                            ip[14], ip[15]);
1650*b0563631STom Van Eyck                     MBEDTLS_X509_SAFE_SNPRINTF;
1651*b0563631STom Van Eyck                 } else {
1652*b0563631STom Van Eyck                     if (n > 0) {
1653*b0563631STom Van Eyck                         *p = '\0';
1654*b0563631STom Van Eyck                     }
1655*b0563631STom Van Eyck                     return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1656*b0563631STom Van Eyck                 }
1657*b0563631STom Van Eyck             }
1658*b0563631STom Van Eyck             break;
1659*b0563631STom Van Eyck             /*
1660*b0563631STom Van Eyck              * directoryName
1661*b0563631STom Van Eyck              */
1662*b0563631STom Van Eyck             case MBEDTLS_X509_SAN_DIRECTORY_NAME:
1663*b0563631STom Van Eyck             {
1664*b0563631STom Van Eyck                 ret = mbedtls_snprintf(p, n, "\n%s    directoryName : ", prefix);
1665*b0563631STom Van Eyck                 if (ret < 0 || (size_t) ret >= n) {
1666*b0563631STom Van Eyck                     mbedtls_x509_free_subject_alt_name(&san);
1667*b0563631STom Van Eyck                 }
1668*b0563631STom Van Eyck 
1669*b0563631STom Van Eyck                 MBEDTLS_X509_SAFE_SNPRINTF;
1670*b0563631STom Van Eyck                 ret = mbedtls_x509_dn_gets(p, n, &san.san.directory_name);
1671*b0563631STom Van Eyck 
1672*b0563631STom Van Eyck                 if (ret < 0) {
1673*b0563631STom Van Eyck                     mbedtls_x509_free_subject_alt_name(&san);
1674*b0563631STom Van Eyck                     if (n > 0) {
1675*b0563631STom Van Eyck                         *p = '\0';
1676*b0563631STom Van Eyck                     }
1677*b0563631STom Van Eyck                     return ret;
1678*b0563631STom Van Eyck                 }
1679*b0563631STom Van Eyck 
1680*b0563631STom Van Eyck                 p += ret;
1681*b0563631STom Van Eyck                 n -= ret;
1682*b0563631STom Van Eyck             }
1683*b0563631STom Van Eyck             break;
168432b31808SJens Wiklander             /*
168532b31808SJens Wiklander              * Type not supported, skip item.
168632b31808SJens Wiklander              */
168732b31808SJens Wiklander             default:
168832b31808SJens Wiklander                 ret = mbedtls_snprintf(p, n, "\n%s    <unsupported>", prefix);
168932b31808SJens Wiklander                 MBEDTLS_X509_SAFE_SNPRINTF;
169032b31808SJens Wiklander                 break;
169132b31808SJens Wiklander         }
169232b31808SJens Wiklander 
1693*b0563631STom Van Eyck         /* So far memory is freed only in the case of directoryName
1694*b0563631STom Van Eyck          * parsing succeeding, as mbedtls_x509_get_name allocates memory. */
1695*b0563631STom Van Eyck         mbedtls_x509_free_subject_alt_name(&san);
169632b31808SJens Wiklander         cur = cur->next;
169732b31808SJens Wiklander     }
169832b31808SJens Wiklander 
169932b31808SJens Wiklander     *p = '\0';
170032b31808SJens Wiklander 
170132b31808SJens Wiklander     *size = n;
170232b31808SJens Wiklander     *buf = p;
170332b31808SJens Wiklander 
170432b31808SJens Wiklander     return 0;
170532b31808SJens Wiklander }
170632b31808SJens Wiklander 
170732b31808SJens Wiklander #define PRINT_ITEM(i)                                   \
1708*b0563631STom Van Eyck     do {                                                \
170932b31808SJens Wiklander         ret = mbedtls_snprintf(p, n, "%s" i, sep);      \
171032b31808SJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;                     \
171132b31808SJens Wiklander         sep = ", ";                                     \
1712*b0563631STom Van Eyck     } while (0)
171332b31808SJens Wiklander 
171432b31808SJens Wiklander #define CERT_TYPE(type, name)                           \
1715*b0563631STom Van Eyck     do {                                                \
1716*b0563631STom Van Eyck         if (ns_cert_type & (type)) {                    \
1717*b0563631STom Van Eyck             PRINT_ITEM(name);                           \
1718*b0563631STom Van Eyck         }                                               \
1719*b0563631STom Van Eyck     } while (0)
172032b31808SJens Wiklander 
mbedtls_x509_info_cert_type(char ** buf,size_t * size,unsigned char ns_cert_type)172132b31808SJens Wiklander int mbedtls_x509_info_cert_type(char **buf, size_t *size,
172232b31808SJens Wiklander                                 unsigned char ns_cert_type)
172332b31808SJens Wiklander {
172432b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
172532b31808SJens Wiklander     size_t n = *size;
172632b31808SJens Wiklander     char *p = *buf;
172732b31808SJens Wiklander     const char *sep = "";
172832b31808SJens Wiklander 
172932b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT,         "SSL Client");
173032b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER,         "SSL Server");
173132b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL,              "Email");
173232b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING,     "Object Signing");
173332b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED,           "Reserved");
173432b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA,             "SSL CA");
173532b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA,           "Email CA");
173632b31808SJens Wiklander     CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA,  "Object Signing CA");
173732b31808SJens Wiklander 
173832b31808SJens Wiklander     *size = n;
173932b31808SJens Wiklander     *buf = p;
174032b31808SJens Wiklander 
174132b31808SJens Wiklander     return 0;
174232b31808SJens Wiklander }
174332b31808SJens Wiklander 
174432b31808SJens Wiklander #define KEY_USAGE(code, name)       \
1745*b0563631STom Van Eyck     do {                            \
1746*b0563631STom Van Eyck         if ((key_usage) & (code)) { \
1747*b0563631STom Van Eyck             PRINT_ITEM(name);       \
1748*b0563631STom Van Eyck         }                           \
1749*b0563631STom Van Eyck     } while (0)
175032b31808SJens Wiklander 
mbedtls_x509_info_key_usage(char ** buf,size_t * size,unsigned int key_usage)175132b31808SJens Wiklander int mbedtls_x509_info_key_usage(char **buf, size_t *size,
175232b31808SJens Wiklander                                 unsigned int key_usage)
175332b31808SJens Wiklander {
175432b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
175532b31808SJens Wiklander     size_t n = *size;
175632b31808SJens Wiklander     char *p = *buf;
175732b31808SJens Wiklander     const char *sep = "";
175832b31808SJens Wiklander 
175932b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE,    "Digital Signature");
176032b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION,      "Non Repudiation");
176132b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT,     "Key Encipherment");
176232b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT,    "Data Encipherment");
176332b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT,        "Key Agreement");
176432b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN,        "Key Cert Sign");
176532b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN,             "CRL Sign");
176632b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY,        "Encipher Only");
176732b31808SJens Wiklander     KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY,        "Decipher Only");
176832b31808SJens Wiklander 
176932b31808SJens Wiklander     *size = n;
177032b31808SJens Wiklander     *buf = p;
177132b31808SJens Wiklander 
177232b31808SJens Wiklander     return 0;
177332b31808SJens Wiklander }
177432b31808SJens Wiklander #endif /* MBEDTLS_X509_REMOVE_INFO */
177532b31808SJens Wiklander #endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */
1776817466cbSJens Wiklander #endif /* MBEDTLS_X509_USE_C */
1777