xref: /third_party/mbedtls/library/asn1parse.c (revision a8e1175b)
1/*
2 *  Generic ASN.1 parsing
3 *
4 *  Copyright The Mbed TLS Contributors
5 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 */
7
8#include "common.h"
9
10#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \
11    defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
12
13#include "mbedtls/asn1.h"
14#include "mbedtls/platform_util.h"
15#include "mbedtls/error.h"
16
17#include <string.h>
18
19#if defined(MBEDTLS_BIGNUM_C)
20#include "mbedtls/bignum.h"
21#endif
22
23#include "mbedtls/platform.h"
24
25/*
26 * ASN.1 DER decoding routines
27 */
28int mbedtls_asn1_get_len(unsigned char **p,
29                         const unsigned char *end,
30                         size_t *len)
31{
32    if ((end - *p) < 1) {
33        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
34    }
35
36    if ((**p & 0x80) == 0) {
37        *len = *(*p)++;
38    } else {
39        int n = (**p) & 0x7F;
40        if (n == 0 || n > 4) {
41            return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
42        }
43        if ((end - *p) <= n) {
44            return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
45        }
46        *len = 0;
47        (*p)++;
48        while (n--) {
49            *len = (*len << 8) | **p;
50            (*p)++;
51        }
52    }
53
54    if (*len > (size_t) (end - *p)) {
55        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
56    }
57
58    return 0;
59}
60
61int mbedtls_asn1_get_tag(unsigned char **p,
62                         const unsigned char *end,
63                         size_t *len, int tag)
64{
65    if ((end - *p) < 1) {
66        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
67    }
68
69    if (**p != tag) {
70        return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
71    }
72
73    (*p)++;
74
75    return mbedtls_asn1_get_len(p, end, len);
76}
77#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */
78
79#if defined(MBEDTLS_ASN1_PARSE_C)
80int mbedtls_asn1_get_bool(unsigned char **p,
81                          const unsigned char *end,
82                          int *val)
83{
84    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
85    size_t len;
86
87    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {
88        return ret;
89    }
90
91    if (len != 1) {
92        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
93    }
94
95    *val = (**p != 0) ? 1 : 0;
96    (*p)++;
97
98    return 0;
99}
100
101static int asn1_get_tagged_int(unsigned char **p,
102                               const unsigned char *end,
103                               int tag, int *val)
104{
105    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
106    size_t len;
107
108    if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {
109        return ret;
110    }
111
112    /*
113     * len==0 is malformed (0 must be represented as 020100 for INTEGER,
114     * or 0A0100 for ENUMERATED tags
115     */
116    if (len == 0) {
117        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
118    }
119    /* This is a cryptography library. Reject negative integers. */
120    if ((**p & 0x80) != 0) {
121        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
122    }
123
124    /* Skip leading zeros. */
125    while (len > 0 && **p == 0) {
126        ++(*p);
127        --len;
128    }
129
130    /* Reject integers that don't fit in an int. This code assumes that
131     * the int type has no padding bit. */
132    if (len > sizeof(int)) {
133        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
134    }
135    if (len == sizeof(int) && (**p & 0x80) != 0) {
136        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
137    }
138
139    *val = 0;
140    while (len-- > 0) {
141        *val = (*val << 8) | **p;
142        (*p)++;
143    }
144
145    return 0;
146}
147
148int mbedtls_asn1_get_int(unsigned char **p,
149                         const unsigned char *end,
150                         int *val)
151{
152    return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);
153}
154
155int mbedtls_asn1_get_enum(unsigned char **p,
156                          const unsigned char *end,
157                          int *val)
158{
159    return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val);
160}
161
162#if defined(MBEDTLS_BIGNUM_C)
163int mbedtls_asn1_get_mpi(unsigned char **p,
164                         const unsigned char *end,
165                         mbedtls_mpi *X)
166{
167    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
168    size_t len;
169
170    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
171        return ret;
172    }
173
174    ret = mbedtls_mpi_read_binary(X, *p, len);
175
176    *p += len;
177
178    return ret;
179}
180#endif /* MBEDTLS_BIGNUM_C */
181
182int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,
183                               mbedtls_asn1_bitstring *bs)
184{
185    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
186
187    /* Certificate type is a single byte bitstring */
188    if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
189        return ret;
190    }
191
192    /* Check length, subtract one for actual bit string length */
193    if (bs->len < 1) {
194        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
195    }
196    bs->len -= 1;
197
198    /* Get number of unused bits, ensure unused bits <= 7 */
199    bs->unused_bits = **p;
200    if (bs->unused_bits > 7) {
201        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
202    }
203    (*p)++;
204
205    /* Get actual bitstring */
206    bs->p = *p;
207    *p += bs->len;
208
209    if (*p != end) {
210        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
211    }
212
213    return 0;
214}
215
216/*
217 * Traverse an ASN.1 "SEQUENCE OF <tag>"
218 * and call a callback for each entry found.
219 */
220int mbedtls_asn1_traverse_sequence_of(
221    unsigned char **p,
222    const unsigned char *end,
223    unsigned char tag_must_mask, unsigned char tag_must_val,
224    unsigned char tag_may_mask, unsigned char tag_may_val,
225    int (*cb)(void *ctx, int tag,
226              unsigned char *start, size_t len),
227    void *ctx)
228{
229    int ret;
230    size_t len;
231
232    /* Get main sequence tag */
233    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
234                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
235        return ret;
236    }
237
238    if (*p + len != end) {
239        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
240    }
241
242    while (*p < end) {
243        unsigned char const tag = *(*p)++;
244
245        if ((tag & tag_must_mask) != tag_must_val) {
246            return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
247        }
248
249        if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {
250            return ret;
251        }
252
253        if ((tag & tag_may_mask) == tag_may_val) {
254            if (cb != NULL) {
255                ret = cb(ctx, tag, *p, len);
256                if (ret != 0) {
257                    return ret;
258                }
259            }
260        }
261
262        *p += len;
263    }
264
265    return 0;
266}
267
268/*
269 * Get a bit string without unused bits
270 */
271int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,
272                                    size_t *len)
273{
274    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
275
276    if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
277        return ret;
278    }
279
280    if (*len == 0) {
281        return MBEDTLS_ERR_ASN1_INVALID_DATA;
282    }
283    --(*len);
284
285    if (**p != 0) {
286        return MBEDTLS_ERR_ASN1_INVALID_DATA;
287    }
288    ++(*p);
289
290    return 0;
291}
292
293void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)
294{
295    while (seq != NULL) {
296        mbedtls_asn1_sequence *next = seq->next;
297        mbedtls_free(seq);
298        seq = next;
299    }
300}
301
302typedef struct {
303    int tag;
304    mbedtls_asn1_sequence *cur;
305} asn1_get_sequence_of_cb_ctx_t;
306
307static int asn1_get_sequence_of_cb(void *ctx,
308                                   int tag,
309                                   unsigned char *start,
310                                   size_t len)
311{
312    asn1_get_sequence_of_cb_ctx_t *cb_ctx =
313        (asn1_get_sequence_of_cb_ctx_t *) ctx;
314    mbedtls_asn1_sequence *cur =
315        cb_ctx->cur;
316
317    if (cur->buf.p != NULL) {
318        cur->next =
319            mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
320
321        if (cur->next == NULL) {
322            return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
323        }
324
325        cur = cur->next;
326    }
327
328    cur->buf.p = start;
329    cur->buf.len = len;
330    cur->buf.tag = tag;
331
332    cb_ctx->cur = cur;
333    return 0;
334}
335
336/*
337 *  Parses and splits an ASN.1 "SEQUENCE OF <tag>"
338 */
339int mbedtls_asn1_get_sequence_of(unsigned char **p,
340                                 const unsigned char *end,
341                                 mbedtls_asn1_sequence *cur,
342                                 int tag)
343{
344    asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
345    memset(cur, 0, sizeof(mbedtls_asn1_sequence));
346    return mbedtls_asn1_traverse_sequence_of(
347        p, end, 0xFF, tag, 0, 0,
348        asn1_get_sequence_of_cb, &cb_ctx);
349}
350
351int mbedtls_asn1_get_alg(unsigned char **p,
352                         const unsigned char *end,
353                         mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params)
354{
355    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
356    size_t len;
357
358    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
359                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
360        return ret;
361    }
362
363    if ((end - *p) < 1) {
364        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
365    }
366
367    alg->tag = **p;
368    end = *p + len;
369
370    if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {
371        return ret;
372    }
373
374    alg->p = *p;
375    *p += alg->len;
376
377    if (*p == end) {
378        mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));
379        return 0;
380    }
381
382    params->tag = **p;
383    (*p)++;
384
385    if ((ret = mbedtls_asn1_get_len(p, end, &params->len)) != 0) {
386        return ret;
387    }
388
389    params->p = *p;
390    *p += params->len;
391
392    if (*p != end) {
393        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
394    }
395
396    return 0;
397}
398
399int mbedtls_asn1_get_alg_null(unsigned char **p,
400                              const unsigned char *end,
401                              mbedtls_asn1_buf *alg)
402{
403    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
404    mbedtls_asn1_buf params;
405
406    memset(&params, 0, sizeof(mbedtls_asn1_buf));
407
408    if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 0) {
409        return ret;
410    }
411
412    if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {
413        return MBEDTLS_ERR_ASN1_INVALID_DATA;
414    }
415
416    return 0;
417}
418
419#if !defined(MBEDTLS_DEPRECATED_REMOVED)
420void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur)
421{
422    if (cur == NULL) {
423        return;
424    }
425
426    mbedtls_free(cur->oid.p);
427    mbedtls_free(cur->val.p);
428
429    mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));
430}
431#endif /* MBEDTLS_DEPRECATED_REMOVED */
432
433void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head)
434{
435    mbedtls_asn1_named_data *cur;
436
437    while ((cur = *head) != NULL) {
438        *head = cur->next;
439        mbedtls_free(cur->oid.p);
440        mbedtls_free(cur->val.p);
441        mbedtls_free(cur);
442    }
443}
444
445void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name)
446{
447    for (mbedtls_asn1_named_data *next; name != NULL; name = next) {
448        next = name->next;
449        mbedtls_free(name);
450    }
451}
452
453const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list,
454                                                            const char *oid, size_t len)
455{
456    while (list != NULL) {
457        if (list->oid.len == len &&
458            memcmp(list->oid.p, oid, len) == 0) {
459            break;
460        }
461
462        list = list->next;
463    }
464
465    return list;
466}
467
468#endif /* MBEDTLS_ASN1_PARSE_C */
469