Coverage Report

Created: 2025-03-01 06:26

/src/mbedtls/library/asn1parse.c
Line
Count
Source (jump to first uncovered line)
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
267
{
32
267
    if ((end - *p) < 1) {
33
0
        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
34
0
    }
35
36
267
    if ((**p & 0x80) == 0) {
37
236
        *len = *(*p)++;
38
236
    } else {
39
31
        int n = (**p) & 0x7F;
40
31
        if (n == 0 || n > 4) {
41
0
            return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
42
0
        }
43
31
        if ((end - *p) <= n) {
44
0
            return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
45
0
        }
46
31
        *len = 0;
47
31
        (*p)++;
48
88
        while (n--) {
49
57
            *len = (*len << 8) | **p;
50
57
            (*p)++;
51
57
        }
52
31
    }
53
54
267
    if (*len > (size_t) (end - *p)) {
55
0
        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
56
0
    }
57
58
267
    return 0;
59
267
}
60
61
int mbedtls_asn1_get_tag(unsigned char **p,
62
                         const unsigned char *end,
63
                         size_t *len, int tag)
64
238
{
65
238
    if ((end - *p) < 1) {
66
0
        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
67
0
    }
68
69
238
    if (**p != tag) {
70
19
        return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
71
19
    }
72
73
219
    (*p)++;
74
75
219
    return mbedtls_asn1_get_len(p, end, len);
76
238
}
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
15
{
84
15
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
85
15
    size_t len;
86
87
15
    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {
88
11
        return ret;
89
11
    }
90
91
4
    if (len != 1) {
92
0
        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
93
0
    }
94
95
4
    *val = (**p != 0) ? 1 : 0;
96
4
    (*p)++;
97
98
4
    return 0;
99
4
}
100
101
static int asn1_get_tagged_int(unsigned char **p,
102
                               const unsigned char *end,
103
                               int tag, int *val)
104
5
{
105
5
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
106
5
    size_t len;
107
108
5
    if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {
109
0
        return ret;
110
0
    }
111
112
    /*
113
     * len==0 is malformed (0 must be represented as 020100 for INTEGER,
114
     * or 0A0100 for ENUMERATED tags
115
     */
116
5
    if (len == 0) {
117
0
        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
118
0
    }
119
    /* This is a cryptography library. Reject negative integers. */
120
5
    if ((**p & 0x80) != 0) {
121
0
        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
122
0
    }
123
124
    /* Skip leading zeros. */
125
6
    while (len > 0 && **p == 0) {
126
1
        ++(*p);
127
1
        --len;
128
1
    }
129
130
    /* Reject integers that don't fit in an int. This code assumes that
131
     * the int type has no padding bit. */
132
5
    if (len > sizeof(int)) {
133
0
        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
134
0
    }
135
5
    if (len == sizeof(int) && (**p & 0x80) != 0) {
136
0
        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
137
0
    }
138
139
5
    *val = 0;
140
9
    while (len-- > 0) {
141
4
        *val = (*val << 8) | **p;
142
4
        (*p)++;
143
4
    }
144
145
5
    return 0;
146
5
}
147
148
int mbedtls_asn1_get_int(unsigned char **p,
149
                         const unsigned char *end,
150
                         int *val)
151
5
{
152
5
    return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);
153
5
}
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
8
{
167
8
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
168
8
    size_t len;
169
170
8
    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
171
0
        return ret;
172
0
    }
173
174
8
    ret = mbedtls_mpi_read_binary(X, *p, len);
175
176
8
    *p += len;
177
178
8
    return ret;
179
8
}
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
0
{
185
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
186
187
    /* Certificate type is a single byte bitstring */
188
0
    if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
189
0
        return ret;
190
0
    }
191
192
    /* Check length, subtract one for actual bit string length */
193
0
    if (bs->len < 1) {
194
0
        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
195
0
    }
196
0
    bs->len -= 1;
197
198
    /* Get number of unused bits, ensure unused bits <= 7 */
199
0
    bs->unused_bits = **p;
200
0
    if (bs->unused_bits > 7) {
201
0
        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
202
0
    }
203
0
    (*p)++;
204
205
    /* Get actual bitstring */
206
0
    bs->p = *p;
207
0
    *p += bs->len;
208
209
0
    if (*p != end) {
210
0
        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
211
0
    }
212
213
0
    return 0;
214
0
}
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
0
{
229
0
    int ret;
230
0
    size_t len;
231
232
    /* Get main sequence tag */
233
0
    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
234
0
                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
235
0
        return ret;
236
0
    }
237
238
0
    if (*p + len != end) {
239
0
        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
240
0
    }
241
242
0
    while (*p < end) {
243
0
        unsigned char const tag = *(*p)++;
244
245
0
        if ((tag & tag_must_mask) != tag_must_val) {
246
0
            return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
247
0
        }
248
249
0
        if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {
250
0
            return ret;
251
0
        }
252
253
0
        if ((tag & tag_may_mask) == tag_may_val) {
254
0
            if (cb != NULL) {
255
0
                ret = cb(ctx, tag, *p, len);
256
0
                if (ret != 0) {
257
0
                    return ret;
258
0
                }
259
0
            }
260
0
        }
261
262
0
        *p += len;
263
0
    }
264
265
0
    return 0;
266
0
}
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
8
{
274
8
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
275
276
8
    if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
277
0
        return ret;
278
0
    }
279
280
8
    if (*len == 0) {
281
0
        return MBEDTLS_ERR_ASN1_INVALID_DATA;
282
0
    }
283
8
    --(*len);
284
285
8
    if (**p != 0) {
286
0
        return MBEDTLS_ERR_ASN1_INVALID_DATA;
287
0
    }
288
8
    ++(*p);
289
290
8
    return 0;
291
8
}
292
293
void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)
294
6.40k
{
295
6.40k
    while (seq != NULL) {
296
0
        mbedtls_asn1_sequence *next = seq->next;
297
0
        mbedtls_free(seq);
298
0
        seq = next;
299
0
    }
300
6.40k
}
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
0
{
312
0
    asn1_get_sequence_of_cb_ctx_t *cb_ctx =
313
0
        (asn1_get_sequence_of_cb_ctx_t *) ctx;
314
0
    mbedtls_asn1_sequence *cur =
315
0
        cb_ctx->cur;
316
317
0
    if (cur->buf.p != NULL) {
318
0
        cur->next =
319
0
            mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
320
321
0
        if (cur->next == NULL) {
322
0
            return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
323
0
        }
324
325
0
        cur = cur->next;
326
0
    }
327
328
0
    cur->buf.p = start;
329
0
    cur->buf.len = len;
330
0
    cur->buf.tag = tag;
331
332
0
    cb_ctx->cur = cur;
333
0
    return 0;
334
0
}
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
0
{
344
0
    asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
345
0
    memset(cur, 0, sizeof(mbedtls_asn1_sequence));
346
0
    return mbedtls_asn1_traverse_sequence_of(
347
0
        p, end, 0xFF, tag, 0, 0,
348
0
        asn1_get_sequence_of_cb, &cb_ctx);
349
0
}
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
12
{
355
12
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
356
12
    size_t len;
357
358
12
    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
359
12
                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
360
0
        return ret;
361
0
    }
362
363
12
    if ((end - *p) < 1) {
364
0
        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
365
0
    }
366
367
12
    alg->tag = **p;
368
12
    end = *p + len;
369
370
12
    if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {
371
0
        return ret;
372
0
    }
373
374
12
    alg->p = *p;
375
12
    *p += alg->len;
376
377
12
    if (*p == end) {
378
0
        mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));
379
0
        return 0;
380
0
    }
381
382
12
    params->tag = **p;
383
12
    (*p)++;
384
385
12
    if ((ret = mbedtls_asn1_get_len(p, end, &params->len)) != 0) {
386
0
        return ret;
387
0
    }
388
389
12
    params->p = *p;
390
12
    *p += params->len;
391
392
12
    if (*p != end) {
393
0
        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
394
0
    }
395
396
12
    return 0;
397
12
}
398
399
int mbedtls_asn1_get_alg_null(unsigned char **p,
400
                              const unsigned char *end,
401
                              mbedtls_asn1_buf *alg)
402
0
{
403
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
404
0
    mbedtls_asn1_buf params;
405
406
0
    memset(&params, 0, sizeof(mbedtls_asn1_buf));
407
408
0
    if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 0) {
409
0
        return ret;
410
0
    }
411
412
0
    if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {
413
0
        return MBEDTLS_ERR_ASN1_INVALID_DATA;
414
0
    }
415
416
0
    return 0;
417
0
}
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
3.20k
{
447
3.22k
    for (mbedtls_asn1_named_data *next; name != NULL; name = next) {
448
16
        next = name->next;
449
16
        mbedtls_free(name);
450
16
    }
451
3.20k
}
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 */