Coverage Report

Created: 2025-07-01 06:54

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