xref: /optee_os/lib/libmbedtls/mbedtls/library/asn1parse.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Generic ASN.1 parsing
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander 
207901324dSJerome Forissier #include "common.h"
21817466cbSJens Wiklander 
22817466cbSJens Wiklander #if defined(MBEDTLS_ASN1_PARSE_C)
23817466cbSJens Wiklander 
24817466cbSJens Wiklander #include "mbedtls/asn1.h"
253d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
2611fa71b9SJerome Forissier #include "mbedtls/error.h"
27817466cbSJens Wiklander 
28817466cbSJens Wiklander #include <string.h>
29817466cbSJens Wiklander 
30817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C)
31817466cbSJens Wiklander #include "mbedtls/bignum.h"
32817466cbSJens Wiklander #endif
33817466cbSJens Wiklander 
34817466cbSJens Wiklander #include "mbedtls/platform.h"
35817466cbSJens Wiklander 
36817466cbSJens Wiklander /*
37817466cbSJens Wiklander  * ASN.1 DER decoding routines
38817466cbSJens Wiklander  */
39817466cbSJens Wiklander int mbedtls_asn1_get_len(unsigned char **p,
40817466cbSJens Wiklander                          const unsigned char *end,
41817466cbSJens Wiklander                          size_t *len)
42817466cbSJens Wiklander {
43*32b31808SJens Wiklander     if ((end - *p) < 1) {
44*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
45*32b31808SJens Wiklander     }
46817466cbSJens Wiklander 
47*32b31808SJens Wiklander     if ((**p & 0x80) == 0) {
48817466cbSJens Wiklander         *len = *(*p)++;
49*32b31808SJens Wiklander     } else {
50*32b31808SJens Wiklander         switch (**p & 0x7F) {
51817466cbSJens Wiklander             case 1:
52*32b31808SJens Wiklander                 if ((end - *p) < 2) {
53*32b31808SJens Wiklander                     return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
54*32b31808SJens Wiklander                 }
55817466cbSJens Wiklander 
56817466cbSJens Wiklander                 *len = (*p)[1];
57817466cbSJens Wiklander                 (*p) += 2;
58817466cbSJens Wiklander                 break;
59817466cbSJens Wiklander 
60817466cbSJens Wiklander             case 2:
61*32b31808SJens Wiklander                 if ((end - *p) < 3) {
62*32b31808SJens Wiklander                     return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
63*32b31808SJens Wiklander                 }
64817466cbSJens Wiklander 
65817466cbSJens Wiklander                 *len = ((size_t) (*p)[1] << 8) | (*p)[2];
66817466cbSJens Wiklander                 (*p) += 3;
67817466cbSJens Wiklander                 break;
68817466cbSJens Wiklander 
69817466cbSJens Wiklander             case 3:
70*32b31808SJens Wiklander                 if ((end - *p) < 4) {
71*32b31808SJens Wiklander                     return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
72*32b31808SJens Wiklander                 }
73817466cbSJens Wiklander 
74817466cbSJens Wiklander                 *len = ((size_t) (*p)[1] << 16) |
75817466cbSJens Wiklander                        ((size_t) (*p)[2] << 8) | (*p)[3];
76817466cbSJens Wiklander                 (*p) += 4;
77817466cbSJens Wiklander                 break;
78817466cbSJens Wiklander 
79817466cbSJens Wiklander             case 4:
80*32b31808SJens Wiklander                 if ((end - *p) < 5) {
81*32b31808SJens Wiklander                     return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
82*32b31808SJens Wiklander                 }
83817466cbSJens Wiklander 
84817466cbSJens Wiklander                 *len = ((size_t) (*p)[1] << 24) | ((size_t) (*p)[2] << 16) |
85817466cbSJens Wiklander                        ((size_t) (*p)[3] << 8) |           (*p)[4];
86817466cbSJens Wiklander                 (*p) += 5;
87817466cbSJens Wiklander                 break;
88817466cbSJens Wiklander 
89817466cbSJens Wiklander             default:
90*32b31808SJens Wiklander                 return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
91817466cbSJens Wiklander         }
92817466cbSJens Wiklander     }
93817466cbSJens Wiklander 
94*32b31808SJens Wiklander     if (*len > (size_t) (end - *p)) {
95*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
96*32b31808SJens Wiklander     }
97817466cbSJens Wiklander 
98*32b31808SJens Wiklander     return 0;
99817466cbSJens Wiklander }
100817466cbSJens Wiklander 
101817466cbSJens Wiklander int mbedtls_asn1_get_tag(unsigned char **p,
102817466cbSJens Wiklander                          const unsigned char *end,
103817466cbSJens Wiklander                          size_t *len, int tag)
104817466cbSJens Wiklander {
105*32b31808SJens Wiklander     if ((end - *p) < 1) {
106*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
107*32b31808SJens Wiklander     }
108817466cbSJens Wiklander 
109*32b31808SJens Wiklander     if (**p != tag) {
110*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
111*32b31808SJens Wiklander     }
112817466cbSJens Wiklander 
113817466cbSJens Wiklander     (*p)++;
114817466cbSJens Wiklander 
115*32b31808SJens Wiklander     return mbedtls_asn1_get_len(p, end, len);
116817466cbSJens Wiklander }
117817466cbSJens Wiklander 
118817466cbSJens Wiklander int mbedtls_asn1_get_bool(unsigned char **p,
119817466cbSJens Wiklander                           const unsigned char *end,
120817466cbSJens Wiklander                           int *val)
121817466cbSJens Wiklander {
12211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
123817466cbSJens Wiklander     size_t len;
124817466cbSJens Wiklander 
125*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {
126*32b31808SJens Wiklander         return ret;
127*32b31808SJens Wiklander     }
128817466cbSJens Wiklander 
129*32b31808SJens Wiklander     if (len != 1) {
130*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
131*32b31808SJens Wiklander     }
132817466cbSJens Wiklander 
133817466cbSJens Wiklander     *val = (**p != 0) ? 1 : 0;
134817466cbSJens Wiklander     (*p)++;
135817466cbSJens Wiklander 
136*32b31808SJens Wiklander     return 0;
137817466cbSJens Wiklander }
138817466cbSJens Wiklander 
13911fa71b9SJerome Forissier static int asn1_get_tagged_int(unsigned char **p,
140817466cbSJens Wiklander                                const unsigned char *end,
14111fa71b9SJerome Forissier                                int tag, int *val)
142817466cbSJens Wiklander {
14311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
144817466cbSJens Wiklander     size_t len;
145817466cbSJens Wiklander 
146*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {
147*32b31808SJens Wiklander         return ret;
148*32b31808SJens Wiklander     }
149817466cbSJens Wiklander 
15011fa71b9SJerome Forissier     /*
15111fa71b9SJerome Forissier      * len==0 is malformed (0 must be represented as 020100 for INTEGER,
15211fa71b9SJerome Forissier      * or 0A0100 for ENUMERATED tags
15311fa71b9SJerome Forissier      */
154*32b31808SJens Wiklander     if (len == 0) {
155*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
156*32b31808SJens Wiklander     }
15711fa71b9SJerome Forissier     /* This is a cryptography library. Reject negative integers. */
158*32b31808SJens Wiklander     if ((**p & 0x80) != 0) {
159*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
160*32b31808SJens Wiklander     }
16111fa71b9SJerome Forissier 
16211fa71b9SJerome Forissier     /* Skip leading zeros. */
163*32b31808SJens Wiklander     while (len > 0 && **p == 0) {
16411fa71b9SJerome Forissier         ++(*p);
16511fa71b9SJerome Forissier         --len;
16611fa71b9SJerome Forissier     }
16711fa71b9SJerome Forissier 
16811fa71b9SJerome Forissier     /* Reject integers that don't fit in an int. This code assumes that
16911fa71b9SJerome Forissier      * the int type has no padding bit. */
170*32b31808SJens Wiklander     if (len > sizeof(int)) {
171*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
172*32b31808SJens Wiklander     }
173*32b31808SJens Wiklander     if (len == sizeof(int) && (**p & 0x80) != 0) {
174*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
175*32b31808SJens Wiklander     }
176817466cbSJens Wiklander 
177817466cbSJens Wiklander     *val = 0;
178*32b31808SJens Wiklander     while (len-- > 0) {
179817466cbSJens Wiklander         *val = (*val << 8) | **p;
180817466cbSJens Wiklander         (*p)++;
181817466cbSJens Wiklander     }
182817466cbSJens Wiklander 
183*32b31808SJens Wiklander     return 0;
184817466cbSJens Wiklander }
185817466cbSJens Wiklander 
18611fa71b9SJerome Forissier int mbedtls_asn1_get_int(unsigned char **p,
18711fa71b9SJerome Forissier                          const unsigned char *end,
18811fa71b9SJerome Forissier                          int *val)
18911fa71b9SJerome Forissier {
190*32b31808SJens Wiklander     return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);
19111fa71b9SJerome Forissier }
19211fa71b9SJerome Forissier 
19311fa71b9SJerome Forissier int mbedtls_asn1_get_enum(unsigned char **p,
19411fa71b9SJerome Forissier                           const unsigned char *end,
19511fa71b9SJerome Forissier                           int *val)
19611fa71b9SJerome Forissier {
197*32b31808SJens Wiklander     return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val);
19811fa71b9SJerome Forissier }
19911fa71b9SJerome Forissier 
200817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C)
201817466cbSJens Wiklander int mbedtls_asn1_get_mpi(unsigned char **p,
202817466cbSJens Wiklander                          const unsigned char *end,
203817466cbSJens Wiklander                          mbedtls_mpi *X)
204817466cbSJens Wiklander {
20511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
206817466cbSJens Wiklander     size_t len;
207817466cbSJens Wiklander 
208*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
209*32b31808SJens Wiklander         return ret;
210*32b31808SJens Wiklander     }
211817466cbSJens Wiklander 
212817466cbSJens Wiklander     ret = mbedtls_mpi_read_binary(X, *p, len);
213817466cbSJens Wiklander 
214817466cbSJens Wiklander     *p += len;
215817466cbSJens Wiklander 
216*32b31808SJens Wiklander     return ret;
217817466cbSJens Wiklander }
218817466cbSJens Wiklander #endif /* MBEDTLS_BIGNUM_C */
219817466cbSJens Wiklander 
220817466cbSJens Wiklander int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,
221817466cbSJens Wiklander                                mbedtls_asn1_bitstring *bs)
222817466cbSJens Wiklander {
22311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
224817466cbSJens Wiklander 
225817466cbSJens Wiklander     /* Certificate type is a single byte bitstring */
226*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
227*32b31808SJens Wiklander         return ret;
228*32b31808SJens Wiklander     }
229817466cbSJens Wiklander 
230817466cbSJens Wiklander     /* Check length, subtract one for actual bit string length */
231*32b31808SJens Wiklander     if (bs->len < 1) {
232*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
233*32b31808SJens Wiklander     }
234817466cbSJens Wiklander     bs->len -= 1;
235817466cbSJens Wiklander 
236817466cbSJens Wiklander     /* Get number of unused bits, ensure unused bits <= 7 */
237817466cbSJens Wiklander     bs->unused_bits = **p;
238*32b31808SJens Wiklander     if (bs->unused_bits > 7) {
239*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
240*32b31808SJens Wiklander     }
241817466cbSJens Wiklander     (*p)++;
242817466cbSJens Wiklander 
243817466cbSJens Wiklander     /* Get actual bitstring */
244817466cbSJens Wiklander     bs->p = *p;
245817466cbSJens Wiklander     *p += bs->len;
246817466cbSJens Wiklander 
247*32b31808SJens Wiklander     if (*p != end) {
248*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
249*32b31808SJens Wiklander     }
250817466cbSJens Wiklander 
251*32b31808SJens Wiklander     return 0;
252817466cbSJens Wiklander }
253817466cbSJens Wiklander 
254817466cbSJens Wiklander /*
25511fa71b9SJerome Forissier  * Traverse an ASN.1 "SEQUENCE OF <tag>"
25611fa71b9SJerome Forissier  * and call a callback for each entry found.
25711fa71b9SJerome Forissier  */
25811fa71b9SJerome Forissier int mbedtls_asn1_traverse_sequence_of(
25911fa71b9SJerome Forissier     unsigned char **p,
26011fa71b9SJerome Forissier     const unsigned char *end,
26111fa71b9SJerome Forissier     unsigned char tag_must_mask, unsigned char tag_must_val,
26211fa71b9SJerome Forissier     unsigned char tag_may_mask, unsigned char tag_may_val,
26311fa71b9SJerome Forissier     int (*cb)(void *ctx, int tag,
26411fa71b9SJerome Forissier               unsigned char *start, size_t len),
26511fa71b9SJerome Forissier     void *ctx)
26611fa71b9SJerome Forissier {
26711fa71b9SJerome Forissier     int ret;
26811fa71b9SJerome Forissier     size_t len;
26911fa71b9SJerome Forissier 
27011fa71b9SJerome Forissier     /* Get main sequence tag */
27111fa71b9SJerome Forissier     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
272*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
273*32b31808SJens Wiklander         return ret;
27411fa71b9SJerome Forissier     }
27511fa71b9SJerome Forissier 
276*32b31808SJens Wiklander     if (*p + len != end) {
277*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
278*32b31808SJens Wiklander     }
27911fa71b9SJerome Forissier 
280*32b31808SJens Wiklander     while (*p < end) {
28111fa71b9SJerome Forissier         unsigned char const tag = *(*p)++;
28211fa71b9SJerome Forissier 
283*32b31808SJens Wiklander         if ((tag & tag_must_mask) != tag_must_val) {
284*32b31808SJens Wiklander             return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
285*32b31808SJens Wiklander         }
28611fa71b9SJerome Forissier 
287*32b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {
288*32b31808SJens Wiklander             return ret;
289*32b31808SJens Wiklander         }
29011fa71b9SJerome Forissier 
291*32b31808SJens Wiklander         if ((tag & tag_may_mask) == tag_may_val) {
292*32b31808SJens Wiklander             if (cb != NULL) {
29311fa71b9SJerome Forissier                 ret = cb(ctx, tag, *p, len);
294*32b31808SJens Wiklander                 if (ret != 0) {
295*32b31808SJens Wiklander                     return ret;
296*32b31808SJens Wiklander                 }
29711fa71b9SJerome Forissier             }
29811fa71b9SJerome Forissier         }
29911fa71b9SJerome Forissier 
30011fa71b9SJerome Forissier         *p += len;
30111fa71b9SJerome Forissier     }
30211fa71b9SJerome Forissier 
303*32b31808SJens Wiklander     return 0;
30411fa71b9SJerome Forissier }
30511fa71b9SJerome Forissier 
30611fa71b9SJerome Forissier /*
307817466cbSJens Wiklander  * Get a bit string without unused bits
308817466cbSJens Wiklander  */
309817466cbSJens Wiklander int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,
310817466cbSJens Wiklander                                     size_t *len)
311817466cbSJens Wiklander {
31211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
313817466cbSJens Wiklander 
314*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
315*32b31808SJens Wiklander         return ret;
316*32b31808SJens Wiklander     }
317817466cbSJens Wiklander 
318*32b31808SJens Wiklander     if (*len == 0) {
319*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_DATA;
320*32b31808SJens Wiklander     }
32111fa71b9SJerome Forissier     --(*len);
32211fa71b9SJerome Forissier 
323*32b31808SJens Wiklander     if (**p != 0) {
324*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_DATA;
325*32b31808SJens Wiklander     }
32611fa71b9SJerome Forissier     ++(*p);
327817466cbSJens Wiklander 
328*32b31808SJens Wiklander     return 0;
329817466cbSJens Wiklander }
330817466cbSJens Wiklander 
33111fa71b9SJerome Forissier void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)
33211fa71b9SJerome Forissier {
333*32b31808SJens Wiklander     while (seq != NULL) {
33411fa71b9SJerome Forissier         mbedtls_asn1_sequence *next = seq->next;
33511fa71b9SJerome Forissier         mbedtls_free(seq);
33611fa71b9SJerome Forissier         seq = next;
33711fa71b9SJerome Forissier     }
33811fa71b9SJerome Forissier }
339817466cbSJens Wiklander 
340*32b31808SJens Wiklander typedef struct {
34111fa71b9SJerome Forissier     int tag;
34211fa71b9SJerome Forissier     mbedtls_asn1_sequence *cur;
34311fa71b9SJerome Forissier } asn1_get_sequence_of_cb_ctx_t;
34411fa71b9SJerome Forissier 
34511fa71b9SJerome Forissier static int asn1_get_sequence_of_cb(void *ctx,
34611fa71b9SJerome Forissier                                    int tag,
34711fa71b9SJerome Forissier                                    unsigned char *start,
34811fa71b9SJerome Forissier                                    size_t len)
34911fa71b9SJerome Forissier {
35011fa71b9SJerome Forissier     asn1_get_sequence_of_cb_ctx_t *cb_ctx =
35111fa71b9SJerome Forissier         (asn1_get_sequence_of_cb_ctx_t *) ctx;
35211fa71b9SJerome Forissier     mbedtls_asn1_sequence *cur =
35311fa71b9SJerome Forissier         cb_ctx->cur;
35411fa71b9SJerome Forissier 
355*32b31808SJens Wiklander     if (cur->buf.p != NULL) {
35611fa71b9SJerome Forissier         cur->next =
35711fa71b9SJerome Forissier             mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
35811fa71b9SJerome Forissier 
359*32b31808SJens Wiklander         if (cur->next == NULL) {
360*32b31808SJens Wiklander             return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
361*32b31808SJens Wiklander         }
36211fa71b9SJerome Forissier 
36311fa71b9SJerome Forissier         cur = cur->next;
36411fa71b9SJerome Forissier     }
36511fa71b9SJerome Forissier 
36611fa71b9SJerome Forissier     cur->buf.p = start;
36711fa71b9SJerome Forissier     cur->buf.len = len;
36811fa71b9SJerome Forissier     cur->buf.tag = tag;
36911fa71b9SJerome Forissier 
37011fa71b9SJerome Forissier     cb_ctx->cur = cur;
371*32b31808SJens Wiklander     return 0;
37211fa71b9SJerome Forissier }
373817466cbSJens Wiklander 
374817466cbSJens Wiklander /*
375817466cbSJens Wiklander  *  Parses and splits an ASN.1 "SEQUENCE OF <tag>"
376817466cbSJens Wiklander  */
377817466cbSJens Wiklander int mbedtls_asn1_get_sequence_of(unsigned char **p,
378817466cbSJens Wiklander                                  const unsigned char *end,
379817466cbSJens Wiklander                                  mbedtls_asn1_sequence *cur,
380817466cbSJens Wiklander                                  int tag)
381817466cbSJens Wiklander {
38211fa71b9SJerome Forissier     asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
38311fa71b9SJerome Forissier     memset(cur, 0, sizeof(mbedtls_asn1_sequence));
384*32b31808SJens Wiklander     return mbedtls_asn1_traverse_sequence_of(
38511fa71b9SJerome Forissier         p, end, 0xFF, tag, 0, 0,
386*32b31808SJens Wiklander         asn1_get_sequence_of_cb, &cb_ctx);
387817466cbSJens Wiklander }
388817466cbSJens Wiklander 
389817466cbSJens Wiklander int mbedtls_asn1_get_alg(unsigned char **p,
390817466cbSJens Wiklander                          const unsigned char *end,
391817466cbSJens Wiklander                          mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params)
392817466cbSJens Wiklander {
39311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
394817466cbSJens Wiklander     size_t len;
395817466cbSJens Wiklander 
396817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
397*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
398*32b31808SJens Wiklander         return ret;
399*32b31808SJens Wiklander     }
400817466cbSJens Wiklander 
401*32b31808SJens Wiklander     if ((end - *p) < 1) {
402*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
403*32b31808SJens Wiklander     }
404817466cbSJens Wiklander 
405817466cbSJens Wiklander     alg->tag = **p;
406817466cbSJens Wiklander     end = *p + len;
407817466cbSJens Wiklander 
408*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {
409*32b31808SJens Wiklander         return ret;
410*32b31808SJens Wiklander     }
411817466cbSJens Wiklander 
412817466cbSJens Wiklander     alg->p = *p;
413817466cbSJens Wiklander     *p += alg->len;
414817466cbSJens Wiklander 
415*32b31808SJens Wiklander     if (*p == end) {
4163d3b0591SJens Wiklander         mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));
417*32b31808SJens Wiklander         return 0;
418817466cbSJens Wiklander     }
419817466cbSJens Wiklander 
420817466cbSJens Wiklander     params->tag = **p;
421817466cbSJens Wiklander     (*p)++;
422817466cbSJens Wiklander 
423*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_len(p, end, &params->len)) != 0) {
424*32b31808SJens Wiklander         return ret;
425*32b31808SJens Wiklander     }
426817466cbSJens Wiklander 
427817466cbSJens Wiklander     params->p = *p;
428817466cbSJens Wiklander     *p += params->len;
429817466cbSJens Wiklander 
430*32b31808SJens Wiklander     if (*p != end) {
431*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
432*32b31808SJens Wiklander     }
433817466cbSJens Wiklander 
434*32b31808SJens Wiklander     return 0;
435817466cbSJens Wiklander }
436817466cbSJens Wiklander 
437817466cbSJens Wiklander int mbedtls_asn1_get_alg_null(unsigned char **p,
438817466cbSJens Wiklander                               const unsigned char *end,
439817466cbSJens Wiklander                               mbedtls_asn1_buf *alg)
440817466cbSJens Wiklander {
44111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
442817466cbSJens Wiklander     mbedtls_asn1_buf params;
443817466cbSJens Wiklander 
444817466cbSJens Wiklander     memset(&params, 0, sizeof(mbedtls_asn1_buf));
445817466cbSJens Wiklander 
446*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 0) {
447*32b31808SJens Wiklander         return ret;
448817466cbSJens Wiklander     }
449817466cbSJens Wiklander 
450*32b31808SJens Wiklander     if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {
451*32b31808SJens Wiklander         return MBEDTLS_ERR_ASN1_INVALID_DATA;
452*32b31808SJens Wiklander     }
453*32b31808SJens Wiklander 
454*32b31808SJens Wiklander     return 0;
455*32b31808SJens Wiklander }
456*32b31808SJens Wiklander 
457*32b31808SJens Wiklander #if !defined(MBEDTLS_DEPRECATED_REMOVED)
458817466cbSJens Wiklander void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur)
459817466cbSJens Wiklander {
460*32b31808SJens Wiklander     if (cur == NULL) {
461817466cbSJens Wiklander         return;
462*32b31808SJens Wiklander     }
463817466cbSJens Wiklander 
464817466cbSJens Wiklander     mbedtls_free(cur->oid.p);
465817466cbSJens Wiklander     mbedtls_free(cur->val.p);
466817466cbSJens Wiklander 
4673d3b0591SJens Wiklander     mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));
468817466cbSJens Wiklander }
469*32b31808SJens Wiklander #endif /* MBEDTLS_DEPRECATED_REMOVED */
470817466cbSJens Wiklander 
471817466cbSJens Wiklander void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head)
472817466cbSJens Wiklander {
473817466cbSJens Wiklander     mbedtls_asn1_named_data *cur;
474817466cbSJens Wiklander 
475*32b31808SJens Wiklander     while ((cur = *head) != NULL) {
476817466cbSJens Wiklander         *head = cur->next;
477*32b31808SJens Wiklander         mbedtls_free(cur->oid.p);
478*32b31808SJens Wiklander         mbedtls_free(cur->val.p);
479817466cbSJens Wiklander         mbedtls_free(cur);
480817466cbSJens Wiklander     }
481817466cbSJens Wiklander }
482817466cbSJens Wiklander 
483*32b31808SJens Wiklander void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name)
484*32b31808SJens Wiklander {
485*32b31808SJens Wiklander     for (mbedtls_asn1_named_data *next; name != NULL; name = next) {
486*32b31808SJens Wiklander         next = name->next;
487*32b31808SJens Wiklander         mbedtls_free(name);
488*32b31808SJens Wiklander     }
489*32b31808SJens Wiklander }
490*32b31808SJens Wiklander 
491*32b31808SJens Wiklander const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list,
492817466cbSJens Wiklander                                                             const char *oid, size_t len)
493817466cbSJens Wiklander {
494*32b31808SJens Wiklander     while (list != NULL) {
495817466cbSJens Wiklander         if (list->oid.len == len &&
496*32b31808SJens Wiklander             memcmp(list->oid.p, oid, len) == 0) {
497817466cbSJens Wiklander             break;
498817466cbSJens Wiklander         }
499817466cbSJens Wiklander 
500817466cbSJens Wiklander         list = list->next;
501817466cbSJens Wiklander     }
502817466cbSJens Wiklander 
503*32b31808SJens Wiklander     return list;
504817466cbSJens Wiklander }
505817466cbSJens Wiklander 
506817466cbSJens Wiklander #endif /* MBEDTLS_ASN1_PARSE_C */
507