Coverage Report

Created: 2026-05-24 06:21

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