xref: /optee_os/lib/libmbedtls/mbedtls/library/asn1parse.c (revision b0563631928755fe864b97785160fb3088e9efdc)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Generic ASN.1 parsing
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 
87901324dSJerome Forissier #include "common.h"
9817466cbSJens Wiklander 
10*b0563631STom Van Eyck #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \
11*b0563631STom Van Eyck     defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
12817466cbSJens Wiklander 
13817466cbSJens Wiklander #include "mbedtls/asn1.h"
143d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
1511fa71b9SJerome Forissier #include "mbedtls/error.h"
16817466cbSJens Wiklander 
17817466cbSJens Wiklander #include <string.h>
18817466cbSJens Wiklander 
19817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C)
20817466cbSJens Wiklander #include "mbedtls/bignum.h"
21817466cbSJens Wiklander #endif
22817466cbSJens Wiklander 
23817466cbSJens Wiklander #include "mbedtls/platform.h"
24817466cbSJens Wiklander 
25817466cbSJens Wiklander /*
26817466cbSJens Wiklander  * ASN.1 DER decoding routines
27817466cbSJens Wiklander  */
mbedtls_asn1_get_len(unsigned char ** p,const unsigned char * end,size_t * len)28817466cbSJens Wiklander int mbedtls_asn1_get_len(unsigned char **p,
29817466cbSJens Wiklander                          const unsigned char *end,
30817466cbSJens Wiklander                          size_t *len)
31817466cbSJens Wiklander {
3232b31808SJens Wiklander     if ((end - *p) < 1) {
3332b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
3432b31808SJens Wiklander     }
35817466cbSJens Wiklander 
3632b31808SJens Wiklander     if ((**p & 0x80) == 0) {
37817466cbSJens Wiklander         *len = *(*p)++;
3832b31808SJens Wiklander     } else {
39*b0563631STom Van Eyck         int n = (**p) & 0x7F;
40*b0563631STom Van Eyck         if (n == 0 || n > 4) {
4132b31808SJens Wiklander             return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
42817466cbSJens Wiklander         }
43*b0563631STom Van Eyck         if ((end - *p) <= n) {
44*b0563631STom Van Eyck             return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
45*b0563631STom Van Eyck         }
46*b0563631STom Van Eyck         *len = 0;
47*b0563631STom Van Eyck         (*p)++;
48*b0563631STom Van Eyck         while (n--) {
49*b0563631STom Van Eyck             *len = (*len << 8) | **p;
50*b0563631STom Van Eyck             (*p)++;
51*b0563631STom Van Eyck         }
52817466cbSJens Wiklander     }
53817466cbSJens Wiklander 
5432b31808SJens Wiklander     if (*len > (size_t) (end - *p)) {
5532b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
5632b31808SJens Wiklander     }
57817466cbSJens Wiklander 
5832b31808SJens Wiklander     return 0;
59817466cbSJens Wiklander }
60817466cbSJens Wiklander 
mbedtls_asn1_get_tag(unsigned char ** p,const unsigned char * end,size_t * len,int tag)61817466cbSJens Wiklander int mbedtls_asn1_get_tag(unsigned char **p,
62817466cbSJens Wiklander                          const unsigned char *end,
63817466cbSJens Wiklander                          size_t *len, int tag)
64817466cbSJens Wiklander {
6532b31808SJens Wiklander     if ((end - *p) < 1) {
6632b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
6732b31808SJens Wiklander     }
68817466cbSJens Wiklander 
6932b31808SJens Wiklander     if (**p != tag) {
7032b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
7132b31808SJens Wiklander     }
72817466cbSJens Wiklander 
73817466cbSJens Wiklander     (*p)++;
74817466cbSJens Wiklander 
7532b31808SJens Wiklander     return mbedtls_asn1_get_len(p, end, len);
76817466cbSJens Wiklander }
77*b0563631STom Van Eyck #endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */
78817466cbSJens Wiklander 
79*b0563631STom Van Eyck #if defined(MBEDTLS_ASN1_PARSE_C)
mbedtls_asn1_get_bool(unsigned char ** p,const unsigned char * end,int * val)80817466cbSJens Wiklander int mbedtls_asn1_get_bool(unsigned char **p,
81817466cbSJens Wiklander                           const unsigned char *end,
82817466cbSJens Wiklander                           int *val)
83817466cbSJens Wiklander {
8411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
85817466cbSJens Wiklander     size_t len;
86817466cbSJens Wiklander 
8732b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {
8832b31808SJens Wiklander         return ret;
8932b31808SJens Wiklander     }
90817466cbSJens Wiklander 
9132b31808SJens Wiklander     if (len != 1) {
9232b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
9332b31808SJens Wiklander     }
94817466cbSJens Wiklander 
95817466cbSJens Wiklander     *val = (**p != 0) ? 1 : 0;
96817466cbSJens Wiklander     (*p)++;
97817466cbSJens Wiklander 
9832b31808SJens Wiklander     return 0;
99817466cbSJens Wiklander }
100817466cbSJens Wiklander 
asn1_get_tagged_int(unsigned char ** p,const unsigned char * end,int tag,int * val)10111fa71b9SJerome Forissier static int asn1_get_tagged_int(unsigned char **p,
102817466cbSJens Wiklander                                const unsigned char *end,
10311fa71b9SJerome Forissier                                int tag, int *val)
104817466cbSJens Wiklander {
10511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
106817466cbSJens Wiklander     size_t len;
107817466cbSJens Wiklander 
10832b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {
10932b31808SJens Wiklander         return ret;
11032b31808SJens Wiklander     }
111817466cbSJens Wiklander 
11211fa71b9SJerome Forissier     /*
11311fa71b9SJerome Forissier      * len==0 is malformed (0 must be represented as 020100 for INTEGER,
11411fa71b9SJerome Forissier      * or 0A0100 for ENUMERATED tags
11511fa71b9SJerome Forissier      */
11632b31808SJens Wiklander     if (len == 0) {
11732b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
11832b31808SJens Wiklander     }
11911fa71b9SJerome Forissier     /* This is a cryptography library. Reject negative integers. */
12032b31808SJens Wiklander     if ((**p & 0x80) != 0) {
12132b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
12232b31808SJens Wiklander     }
12311fa71b9SJerome Forissier 
12411fa71b9SJerome Forissier     /* Skip leading zeros. */
12532b31808SJens Wiklander     while (len > 0 && **p == 0) {
12611fa71b9SJerome Forissier         ++(*p);
12711fa71b9SJerome Forissier         --len;
12811fa71b9SJerome Forissier     }
12911fa71b9SJerome Forissier 
13011fa71b9SJerome Forissier     /* Reject integers that don't fit in an int. This code assumes that
13111fa71b9SJerome Forissier      * the int type has no padding bit. */
13232b31808SJens Wiklander     if (len > sizeof(int)) {
13332b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
13432b31808SJens Wiklander     }
13532b31808SJens Wiklander     if (len == sizeof(int) && (**p & 0x80) != 0) {
13632b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
13732b31808SJens Wiklander     }
138817466cbSJens Wiklander 
139817466cbSJens Wiklander     *val = 0;
14032b31808SJens Wiklander     while (len-- > 0) {
141817466cbSJens Wiklander         *val = (*val << 8) | **p;
142817466cbSJens Wiklander         (*p)++;
143817466cbSJens Wiklander     }
144817466cbSJens Wiklander 
14532b31808SJens Wiklander     return 0;
146817466cbSJens Wiklander }
147817466cbSJens Wiklander 
mbedtls_asn1_get_int(unsigned char ** p,const unsigned char * end,int * val)14811fa71b9SJerome Forissier int mbedtls_asn1_get_int(unsigned char **p,
14911fa71b9SJerome Forissier                          const unsigned char *end,
15011fa71b9SJerome Forissier                          int *val)
15111fa71b9SJerome Forissier {
15232b31808SJens Wiklander     return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);
15311fa71b9SJerome Forissier }
15411fa71b9SJerome Forissier 
mbedtls_asn1_get_enum(unsigned char ** p,const unsigned char * end,int * val)15511fa71b9SJerome Forissier int mbedtls_asn1_get_enum(unsigned char **p,
15611fa71b9SJerome Forissier                           const unsigned char *end,
15711fa71b9SJerome Forissier                           int *val)
15811fa71b9SJerome Forissier {
15932b31808SJens Wiklander     return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val);
16011fa71b9SJerome Forissier }
16111fa71b9SJerome Forissier 
162817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C)
mbedtls_asn1_get_mpi(unsigned char ** p,const unsigned char * end,mbedtls_mpi * X)163817466cbSJens Wiklander int mbedtls_asn1_get_mpi(unsigned char **p,
164817466cbSJens Wiklander                          const unsigned char *end,
165817466cbSJens Wiklander                          mbedtls_mpi *X)
166817466cbSJens Wiklander {
16711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
168817466cbSJens Wiklander     size_t len;
169817466cbSJens Wiklander 
17032b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
17132b31808SJens Wiklander         return ret;
17232b31808SJens Wiklander     }
173817466cbSJens Wiklander 
174817466cbSJens Wiklander     ret = mbedtls_mpi_read_binary(X, *p, len);
175817466cbSJens Wiklander 
176817466cbSJens Wiklander     *p += len;
177817466cbSJens Wiklander 
17832b31808SJens Wiklander     return ret;
179817466cbSJens Wiklander }
180817466cbSJens Wiklander #endif /* MBEDTLS_BIGNUM_C */
181817466cbSJens Wiklander 
mbedtls_asn1_get_bitstring(unsigned char ** p,const unsigned char * end,mbedtls_asn1_bitstring * bs)182817466cbSJens Wiklander int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,
183817466cbSJens Wiklander                                mbedtls_asn1_bitstring *bs)
184817466cbSJens Wiklander {
18511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
186817466cbSJens Wiklander 
187817466cbSJens Wiklander     /* Certificate type is a single byte bitstring */
18832b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
18932b31808SJens Wiklander         return ret;
19032b31808SJens Wiklander     }
191817466cbSJens Wiklander 
192817466cbSJens Wiklander     /* Check length, subtract one for actual bit string length */
19332b31808SJens Wiklander     if (bs->len < 1) {
19432b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
19532b31808SJens Wiklander     }
196817466cbSJens Wiklander     bs->len -= 1;
197817466cbSJens Wiklander 
198817466cbSJens Wiklander     /* Get number of unused bits, ensure unused bits <= 7 */
199817466cbSJens Wiklander     bs->unused_bits = **p;
20032b31808SJens Wiklander     if (bs->unused_bits > 7) {
20132b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
20232b31808SJens Wiklander     }
203817466cbSJens Wiklander     (*p)++;
204817466cbSJens Wiklander 
205817466cbSJens Wiklander     /* Get actual bitstring */
206817466cbSJens Wiklander     bs->p = *p;
207817466cbSJens Wiklander     *p += bs->len;
208817466cbSJens Wiklander 
20932b31808SJens Wiklander     if (*p != end) {
21032b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
21132b31808SJens Wiklander     }
212817466cbSJens Wiklander 
21332b31808SJens Wiklander     return 0;
214817466cbSJens Wiklander }
215817466cbSJens Wiklander 
216817466cbSJens Wiklander /*
21711fa71b9SJerome Forissier  * Traverse an ASN.1 "SEQUENCE OF <tag>"
21811fa71b9SJerome Forissier  * and call a callback for each entry found.
21911fa71b9SJerome Forissier  */
mbedtls_asn1_traverse_sequence_of(unsigned char ** p,const unsigned char * end,unsigned char tag_must_mask,unsigned char tag_must_val,unsigned char tag_may_mask,unsigned char tag_may_val,int (* cb)(void * ctx,int tag,unsigned char * start,size_t len),void * ctx)22011fa71b9SJerome Forissier int mbedtls_asn1_traverse_sequence_of(
22111fa71b9SJerome Forissier     unsigned char **p,
22211fa71b9SJerome Forissier     const unsigned char *end,
22311fa71b9SJerome Forissier     unsigned char tag_must_mask, unsigned char tag_must_val,
22411fa71b9SJerome Forissier     unsigned char tag_may_mask, unsigned char tag_may_val,
22511fa71b9SJerome Forissier     int (*cb)(void *ctx, int tag,
22611fa71b9SJerome Forissier               unsigned char *start, size_t len),
22711fa71b9SJerome Forissier     void *ctx)
22811fa71b9SJerome Forissier {
22911fa71b9SJerome Forissier     int ret;
23011fa71b9SJerome Forissier     size_t len;
23111fa71b9SJerome Forissier 
23211fa71b9SJerome Forissier     /* Get main sequence tag */
23311fa71b9SJerome Forissier     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
23432b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
23532b31808SJens Wiklander         return ret;
23611fa71b9SJerome Forissier     }
23711fa71b9SJerome Forissier 
23832b31808SJens Wiklander     if (*p + len != end) {
23932b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
24032b31808SJens Wiklander     }
24111fa71b9SJerome Forissier 
24232b31808SJens Wiklander     while (*p < end) {
24311fa71b9SJerome Forissier         unsigned char const tag = *(*p)++;
24411fa71b9SJerome Forissier 
24532b31808SJens Wiklander         if ((tag & tag_must_mask) != tag_must_val) {
24632b31808SJens Wiklander             return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
24732b31808SJens Wiklander         }
24811fa71b9SJerome Forissier 
24932b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {
25032b31808SJens Wiklander             return ret;
25132b31808SJens Wiklander         }
25211fa71b9SJerome Forissier 
25332b31808SJens Wiklander         if ((tag & tag_may_mask) == tag_may_val) {
25432b31808SJens Wiklander             if (cb != NULL) {
25511fa71b9SJerome Forissier                 ret = cb(ctx, tag, *p, len);
25632b31808SJens Wiklander                 if (ret != 0) {
25732b31808SJens Wiklander                     return ret;
25832b31808SJens Wiklander                 }
25911fa71b9SJerome Forissier             }
26011fa71b9SJerome Forissier         }
26111fa71b9SJerome Forissier 
26211fa71b9SJerome Forissier         *p += len;
26311fa71b9SJerome Forissier     }
26411fa71b9SJerome Forissier 
26532b31808SJens Wiklander     return 0;
26611fa71b9SJerome Forissier }
26711fa71b9SJerome Forissier 
26811fa71b9SJerome Forissier /*
269817466cbSJens Wiklander  * Get a bit string without unused bits
270817466cbSJens Wiklander  */
mbedtls_asn1_get_bitstring_null(unsigned char ** p,const unsigned char * end,size_t * len)271817466cbSJens Wiklander int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,
272817466cbSJens Wiklander                                     size_t *len)
273817466cbSJens Wiklander {
27411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
275817466cbSJens Wiklander 
27632b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
27732b31808SJens Wiklander         return ret;
27832b31808SJens Wiklander     }
279817466cbSJens Wiklander 
28032b31808SJens Wiklander     if (*len == 0) {
28132b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_DATA;
28232b31808SJens Wiklander     }
28311fa71b9SJerome Forissier     --(*len);
28411fa71b9SJerome Forissier 
28532b31808SJens Wiklander     if (**p != 0) {
28632b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_DATA;
28732b31808SJens Wiklander     }
28811fa71b9SJerome Forissier     ++(*p);
289817466cbSJens Wiklander 
29032b31808SJens Wiklander     return 0;
291817466cbSJens Wiklander }
292817466cbSJens Wiklander 
mbedtls_asn1_sequence_free(mbedtls_asn1_sequence * seq)29311fa71b9SJerome Forissier void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)
29411fa71b9SJerome Forissier {
29532b31808SJens Wiklander     while (seq != NULL) {
29611fa71b9SJerome Forissier         mbedtls_asn1_sequence *next = seq->next;
29711fa71b9SJerome Forissier         mbedtls_free(seq);
29811fa71b9SJerome Forissier         seq = next;
29911fa71b9SJerome Forissier     }
30011fa71b9SJerome Forissier }
301817466cbSJens Wiklander 
30232b31808SJens Wiklander typedef struct {
30311fa71b9SJerome Forissier     int tag;
30411fa71b9SJerome Forissier     mbedtls_asn1_sequence *cur;
30511fa71b9SJerome Forissier } asn1_get_sequence_of_cb_ctx_t;
30611fa71b9SJerome Forissier 
asn1_get_sequence_of_cb(void * ctx,int tag,unsigned char * start,size_t len)30711fa71b9SJerome Forissier static int asn1_get_sequence_of_cb(void *ctx,
30811fa71b9SJerome Forissier                                    int tag,
30911fa71b9SJerome Forissier                                    unsigned char *start,
31011fa71b9SJerome Forissier                                    size_t len)
31111fa71b9SJerome Forissier {
31211fa71b9SJerome Forissier     asn1_get_sequence_of_cb_ctx_t *cb_ctx =
31311fa71b9SJerome Forissier         (asn1_get_sequence_of_cb_ctx_t *) ctx;
31411fa71b9SJerome Forissier     mbedtls_asn1_sequence *cur =
31511fa71b9SJerome Forissier         cb_ctx->cur;
31611fa71b9SJerome Forissier 
31732b31808SJens Wiklander     if (cur->buf.p != NULL) {
31811fa71b9SJerome Forissier         cur->next =
31911fa71b9SJerome Forissier             mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
32011fa71b9SJerome Forissier 
32132b31808SJens Wiklander         if (cur->next == NULL) {
32232b31808SJens Wiklander             return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
32332b31808SJens Wiklander         }
32411fa71b9SJerome Forissier 
32511fa71b9SJerome Forissier         cur = cur->next;
32611fa71b9SJerome Forissier     }
32711fa71b9SJerome Forissier 
32811fa71b9SJerome Forissier     cur->buf.p = start;
32911fa71b9SJerome Forissier     cur->buf.len = len;
33011fa71b9SJerome Forissier     cur->buf.tag = tag;
33111fa71b9SJerome Forissier 
33211fa71b9SJerome Forissier     cb_ctx->cur = cur;
33332b31808SJens Wiklander     return 0;
33411fa71b9SJerome Forissier }
335817466cbSJens Wiklander 
336817466cbSJens Wiklander /*
337817466cbSJens Wiklander  *  Parses and splits an ASN.1 "SEQUENCE OF <tag>"
338817466cbSJens Wiklander  */
mbedtls_asn1_get_sequence_of(unsigned char ** p,const unsigned char * end,mbedtls_asn1_sequence * cur,int tag)339817466cbSJens Wiklander int mbedtls_asn1_get_sequence_of(unsigned char **p,
340817466cbSJens Wiklander                                  const unsigned char *end,
341817466cbSJens Wiklander                                  mbedtls_asn1_sequence *cur,
342817466cbSJens Wiklander                                  int tag)
343817466cbSJens Wiklander {
34411fa71b9SJerome Forissier     asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
34511fa71b9SJerome Forissier     memset(cur, 0, sizeof(mbedtls_asn1_sequence));
34632b31808SJens Wiklander     return mbedtls_asn1_traverse_sequence_of(
34711fa71b9SJerome Forissier         p, end, 0xFF, tag, 0, 0,
34832b31808SJens Wiklander         asn1_get_sequence_of_cb, &cb_ctx);
349817466cbSJens Wiklander }
350817466cbSJens Wiklander 
mbedtls_asn1_get_alg(unsigned char ** p,const unsigned char * end,mbedtls_asn1_buf * alg,mbedtls_asn1_buf * params)351817466cbSJens Wiklander int mbedtls_asn1_get_alg(unsigned char **p,
352817466cbSJens Wiklander                          const unsigned char *end,
353817466cbSJens Wiklander                          mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params)
354817466cbSJens Wiklander {
35511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
356817466cbSJens Wiklander     size_t len;
357817466cbSJens Wiklander 
358817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
35932b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
36032b31808SJens Wiklander         return ret;
36132b31808SJens Wiklander     }
362817466cbSJens Wiklander 
36332b31808SJens Wiklander     if ((end - *p) < 1) {
36432b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
36532b31808SJens Wiklander     }
366817466cbSJens Wiklander 
367817466cbSJens Wiklander     alg->tag = **p;
368817466cbSJens Wiklander     end = *p + len;
369817466cbSJens Wiklander 
37032b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {
37132b31808SJens Wiklander         return ret;
37232b31808SJens Wiklander     }
373817466cbSJens Wiklander 
374817466cbSJens Wiklander     alg->p = *p;
375817466cbSJens Wiklander     *p += alg->len;
376817466cbSJens Wiklander 
37732b31808SJens Wiklander     if (*p == end) {
3783d3b0591SJens Wiklander         mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));
37932b31808SJens Wiklander         return 0;
380817466cbSJens Wiklander     }
381817466cbSJens Wiklander 
382817466cbSJens Wiklander     params->tag = **p;
383817466cbSJens Wiklander     (*p)++;
384817466cbSJens Wiklander 
38532b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_len(p, end, &params->len)) != 0) {
38632b31808SJens Wiklander         return ret;
38732b31808SJens Wiklander     }
388817466cbSJens Wiklander 
389817466cbSJens Wiklander     params->p = *p;
390817466cbSJens Wiklander     *p += params->len;
391817466cbSJens Wiklander 
39232b31808SJens Wiklander     if (*p != end) {
39332b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
39432b31808SJens Wiklander     }
395817466cbSJens Wiklander 
39632b31808SJens Wiklander     return 0;
397817466cbSJens Wiklander }
398817466cbSJens Wiklander 
mbedtls_asn1_get_alg_null(unsigned char ** p,const unsigned char * end,mbedtls_asn1_buf * alg)399817466cbSJens Wiklander int mbedtls_asn1_get_alg_null(unsigned char **p,
400817466cbSJens Wiklander                               const unsigned char *end,
401817466cbSJens Wiklander                               mbedtls_asn1_buf *alg)
402817466cbSJens Wiklander {
40311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
404817466cbSJens Wiklander     mbedtls_asn1_buf params;
405817466cbSJens Wiklander 
406817466cbSJens Wiklander     memset(&params, 0, sizeof(mbedtls_asn1_buf));
407817466cbSJens Wiklander 
40832b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 0) {
40932b31808SJens Wiklander         return ret;
410817466cbSJens Wiklander     }
411817466cbSJens Wiklander 
41232b31808SJens Wiklander     if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {
41332b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_DATA;
41432b31808SJens Wiklander     }
41532b31808SJens Wiklander 
41632b31808SJens Wiklander     return 0;
41732b31808SJens Wiklander }
41832b31808SJens Wiklander 
41932b31808SJens Wiklander #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_asn1_free_named_data(mbedtls_asn1_named_data * cur)420817466cbSJens Wiklander void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur)
421817466cbSJens Wiklander {
42232b31808SJens Wiklander     if (cur == NULL) {
423817466cbSJens Wiklander         return;
42432b31808SJens Wiklander     }
425817466cbSJens Wiklander 
426817466cbSJens Wiklander     mbedtls_free(cur->oid.p);
427817466cbSJens Wiklander     mbedtls_free(cur->val.p);
428817466cbSJens Wiklander 
4293d3b0591SJens Wiklander     mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));
430817466cbSJens Wiklander }
43132b31808SJens Wiklander #endif /* MBEDTLS_DEPRECATED_REMOVED */
432817466cbSJens Wiklander 
mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data ** head)433817466cbSJens Wiklander void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head)
434817466cbSJens Wiklander {
435817466cbSJens Wiklander     mbedtls_asn1_named_data *cur;
436817466cbSJens Wiklander 
43732b31808SJens Wiklander     while ((cur = *head) != NULL) {
438817466cbSJens Wiklander         *head = cur->next;
43932b31808SJens Wiklander         mbedtls_free(cur->oid.p);
44032b31808SJens Wiklander         mbedtls_free(cur->val.p);
441817466cbSJens Wiklander         mbedtls_free(cur);
442817466cbSJens Wiklander     }
443817466cbSJens Wiklander }
444817466cbSJens Wiklander 
mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data * name)44532b31808SJens Wiklander void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name)
44632b31808SJens Wiklander {
44732b31808SJens Wiklander     for (mbedtls_asn1_named_data *next; name != NULL; name = next) {
44832b31808SJens Wiklander         next = name->next;
44932b31808SJens Wiklander         mbedtls_free(name);
45032b31808SJens Wiklander     }
45132b31808SJens Wiklander }
45232b31808SJens Wiklander 
mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data * list,const char * oid,size_t len)45332b31808SJens Wiklander const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list,
454817466cbSJens Wiklander                                                             const char *oid, size_t len)
455817466cbSJens Wiklander {
45632b31808SJens Wiklander     while (list != NULL) {
457817466cbSJens Wiklander         if (list->oid.len == len &&
45832b31808SJens Wiklander             memcmp(list->oid.p, oid, len) == 0) {
459817466cbSJens Wiklander             break;
460817466cbSJens Wiklander         }
461817466cbSJens Wiklander 
462817466cbSJens Wiklander         list = list->next;
463817466cbSJens Wiklander     }
464817466cbSJens Wiklander 
46532b31808SJens Wiklander     return list;
466817466cbSJens Wiklander }
467817466cbSJens Wiklander 
468817466cbSJens Wiklander #endif /* MBEDTLS_ASN1_PARSE_C */
469