Coverage Report

Created: 2026-07-19 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/asn1/asn1_lib.c
Line
Count
Source
1
/*
2
 * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include <limits.h>
12
#include "internal/cryptlib.h"
13
#include <openssl/asn1.h>
14
#include "asn1_local.h"
15
16
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
17
    long max);
18
static void asn1_put_length(unsigned char **pp, int length);
19
20
static int _asn1_check_infinite_end(const unsigned char **p, long len)
21
0
{
22
    /*
23
     * If there is 0 or 1 byte left, the length check should pick things up
24
     */
25
0
    if (len <= 0) {
26
0
        return 1;
27
0
    } else {
28
0
        if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
29
0
            (*p) += 2;
30
0
            return 1;
31
0
        }
32
0
    }
33
0
    return 0;
34
0
}
35
36
int ASN1_check_infinite_end(unsigned char **p, long len)
37
0
{
38
0
    return _asn1_check_infinite_end((const unsigned char **)p, len);
39
0
}
40
41
int ASN1_const_check_infinite_end(const unsigned char **p, long len)
42
0
{
43
0
    return _asn1_check_infinite_end(p, len);
44
0
}
45
46
int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
47
    int *pclass, long omax)
48
154k
{
49
154k
    int i, ret;
50
154k
    long len;
51
154k
    const unsigned char *p = *pp;
52
154k
    int tag, xclass, inf;
53
154k
    long max = omax;
54
55
154k
    if (omax <= 0) {
56
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
57
0
        return 0x80;
58
0
    }
59
154k
    ret = (*p & V_ASN1_CONSTRUCTED);
60
154k
    xclass = (*p & V_ASN1_PRIVATE);
61
154k
    i = *p & V_ASN1_PRIMITIVE_TAG;
62
154k
    if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */
63
6.95k
        p++;
64
6.95k
        if (--max == 0)
65
427
            goto err;
66
6.53k
        len = 0;
67
12.2k
        while (*p & 0x80) {
68
6.85k
            len <<= 7L;
69
6.85k
            len |= *(p++) & 0x7f;
70
6.85k
            if (--max == 0)
71
724
                goto err;
72
6.13k
            if (len > (INT_MAX >> 7L))
73
429
                goto err;
74
6.13k
        }
75
5.37k
        len <<= 7L;
76
5.37k
        len |= *(p++) & 0x7f;
77
5.37k
        tag = (int)len;
78
5.37k
        if (--max == 0)
79
544
            goto err;
80
148k
    } else {
81
148k
        tag = i;
82
148k
        p++;
83
148k
        if (--max == 0)
84
2.06k
            goto err;
85
148k
    }
86
150k
    *ptag = tag;
87
150k
    *pclass = xclass;
88
150k
    if (!asn1_get_length(&p, &inf, plength, max))
89
2.66k
        goto err;
90
91
148k
    if (inf && !(ret & V_ASN1_CONSTRUCTED))
92
465
        goto err;
93
94
147k
    if (*plength > (omax - (p - *pp))) {
95
2.48k
        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
96
        /*
97
         * Set this so that even if things are not long enough the values are
98
         * set correctly
99
         */
100
2.48k
        ret |= 0x80;
101
2.48k
    }
102
147k
    *pp = p;
103
147k
    return ret | inf;
104
7.31k
err:
105
7.31k
    ERR_raise(ERR_LIB_ASN1, ASN1_R_HEADER_TOO_LONG);
106
7.31k
    return 0x80;
107
148k
}
108
109
/*
110
 * Decode a length field.
111
 * The short form is a single byte defining a length 0 - 127.
112
 * The long form is a byte 0 - 127 with the top bit set and this indicates
113
 * the number of following octets that contain the length.  These octets
114
 * are stored most significant digit first.
115
 */
116
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
117
    long max)
118
150k
{
119
150k
    const unsigned char *p = *pp;
120
150k
    unsigned long ret = 0;
121
150k
    int i;
122
123
150k
    if (max-- < 1)
124
0
        return 0;
125
150k
    if (*p == 0x80) {
126
22.1k
        *inf = 1;
127
22.1k
        p++;
128
128k
    } else {
129
128k
        *inf = 0;
130
128k
        i = *p & 0x7f;
131
128k
        if (*p++ & 0x80) {
132
33.0k
            if (max < i)
133
847
                return 0;
134
            /* Skip leading zeroes */
135
39.9k
            while (i > 0 && *p == 0) {
136
7.74k
                p++;
137
7.74k
                i--;
138
7.74k
            }
139
32.2k
            if (i > (int)sizeof(long))
140
749
                return 0;
141
84.0k
            while (i > 0) {
142
52.5k
                ret <<= 8;
143
52.5k
                ret |= *p++;
144
52.5k
                i--;
145
52.5k
            }
146
31.4k
            if (ret > LONG_MAX)
147
1.06k
                return 0;
148
95.5k
        } else {
149
95.5k
            ret = i;
150
95.5k
        }
151
128k
    }
152
148k
    *pp = p;
153
148k
    *rl = (long)ret;
154
148k
    return 1;
155
150k
}
156
157
/*
158
 * constructed == 2 for indefinite length constructed
159
 */
160
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
161
    int xclass)
162
17.3k
{
163
17.3k
    unsigned char *p = *pp;
164
17.3k
    int i, ttag;
165
166
17.3k
    i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
167
17.3k
    i |= (xclass & V_ASN1_PRIVATE);
168
17.3k
    if (tag < 31) {
169
17.3k
        *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
170
17.3k
    } else {
171
0
        *(p++) = i | V_ASN1_PRIMITIVE_TAG;
172
0
        for (i = 0, ttag = tag; ttag > 0; i++)
173
0
            ttag >>= 7;
174
0
        ttag = i;
175
0
        while (i-- > 0) {
176
0
            p[i] = tag & 0x7f;
177
0
            if (i != (ttag - 1))
178
0
                p[i] |= 0x80;
179
0
            tag >>= 7;
180
0
        }
181
0
        p += ttag;
182
0
    }
183
17.3k
    if (constructed == 2)
184
0
        *(p++) = 0x80;
185
17.3k
    else
186
17.3k
        asn1_put_length(&p, length);
187
17.3k
    *pp = p;
188
17.3k
}
189
190
int ASN1_put_eoc(unsigned char **pp)
191
0
{
192
0
    unsigned char *p = *pp;
193
194
0
    *p++ = 0;
195
0
    *p++ = 0;
196
0
    *pp = p;
197
0
    return 2;
198
0
}
199
200
static void asn1_put_length(unsigned char **pp, int length)
201
17.3k
{
202
17.3k
    unsigned char *p = *pp;
203
17.3k
    int i, len;
204
205
17.3k
    if (length <= 127) {
206
6.38k
        *(p++) = (unsigned char)length;
207
10.9k
    } else {
208
10.9k
        len = length;
209
25.5k
        for (i = 0; len > 0; i++)
210
14.5k
            len >>= 8;
211
10.9k
        *(p++) = i | 0x80;
212
10.9k
        len = i;
213
25.5k
        while (i-- > 0) {
214
14.5k
            p[i] = length & 0xff;
215
14.5k
            length >>= 8;
216
14.5k
        }
217
10.9k
        p += len;
218
10.9k
    }
219
17.3k
    *pp = p;
220
17.3k
}
221
222
int ASN1_object_size(int constructed, int length, int tag)
223
46.2k
{
224
46.2k
    int ret = 1;
225
226
46.2k
    if (length < 0)
227
0
        return -1;
228
46.2k
    if (tag >= 31) {
229
0
        while (tag > 0) {
230
0
            tag >>= 7;
231
0
            ret++;
232
0
        }
233
0
    }
234
46.2k
    if (constructed == 2) {
235
0
        ret += 3;
236
46.2k
    } else {
237
46.2k
        ret++;
238
46.2k
        if (length > 127) {
239
27.4k
            int tmplen = length;
240
63.8k
            while (tmplen > 0) {
241
36.3k
                tmplen >>= 8;
242
36.3k
                ret++;
243
36.3k
            }
244
27.4k
        }
245
46.2k
    }
246
46.2k
    if (ret >= INT_MAX - length)
247
0
        return -1;
248
46.2k
    return ret + length;
249
46.2k
}
250
251
void ossl_asn1_bit_string_clear_unused_bits(ASN1_STRING *str)
252
0
{
253
0
    str->flags &= ~0x07;
254
0
    str->flags &= ~ASN1_STRING_FLAG_BITS_LEFT;
255
0
}
256
257
void ossl_asn1_bit_string_set_unused_bits(ASN1_STRING *str, unsigned int num)
258
0
{
259
0
    ossl_asn1_bit_string_clear_unused_bits(str);
260
0
    str->flags |= ASN1_STRING_FLAG_BITS_LEFT | (num & 0x07);
261
0
}
262
263
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
264
0
{
265
0
    if (str == NULL)
266
0
        return 0;
267
0
    dst->type = str->type;
268
0
    if (!ossl_asn1_string_set_internal(dst, str->data, str->length,
269
0
            /*add_nul_byte=*/0))
270
0
        return 0;
271
    /* Copy flags but preserve embed value */
272
0
    dst->flags &= ASN1_STRING_FLAG_EMBED;
273
0
    dst->flags |= str->flags & ~ASN1_STRING_FLAG_EMBED;
274
0
    return 1;
275
0
}
276
277
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
278
0
{
279
0
    ASN1_STRING *ret;
280
281
0
    if (!str)
282
0
        return NULL;
283
0
    ret = ASN1_STRING_new();
284
0
    if (ret == NULL)
285
0
        return NULL;
286
0
    if (!ASN1_STRING_copy(ret, str)) {
287
0
        ASN1_STRING_free(ret);
288
0
        return NULL;
289
0
    }
290
0
    return ret;
291
0
}
292
293
int ossl_asn1_string_set_internal(ASN1_STRING *str, const uint8_t *data,
294
    int len_in, int add_nul_byte)
295
0
{
296
0
    size_t len, alloc_len;
297
298
0
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
299
    /*
300
     * Force no NUL byte for callers that are requesting it
301
     * 0 length object data will be NULL
302
     */
303
0
    add_nul_byte = 0;
304
0
#endif
305
0
    if (len_in < -1) {
306
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
307
0
        return 0;
308
0
    }
309
0
    if (len_in == -1) {
310
0
        if (data == NULL)
311
0
            return 0;
312
0
        len = strlen((const char *)data);
313
0
    } else {
314
0
        len = (size_t)len_in;
315
0
    }
316
    /*
317
     * Add one to the length to allow for adding an a '\0' terminator
318
     * "even though this isn't strictly necessary".
319
     */
320
0
    alloc_len = add_nul_byte ? len + 1 : len;
321
322
0
    if (alloc_len > INT_MAX) {
323
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
324
0
        return 0;
325
0
    }
326
327
0
    if ((str->flags & ASN1_STRING_FLAG_DATA_NOT_OWNED)) {
328
0
        str->data = NULL;
329
0
        str->length = 0;
330
0
        str->flags &= ~ASN1_STRING_FLAG_DATA_NOT_OWNED;
331
0
    }
332
333
    /* Ensure copying a 0 length data field is defined. */
334
0
    if (alloc_len == 0) {
335
0
        OPENSSL_free(str->data);
336
0
        str->data = NULL;
337
0
        str->length = 0;
338
0
        return 1;
339
0
    }
340
341
0
    if ((size_t)str->length != alloc_len) {
342
0
        uint8_t *c;
343
0
        c = OPENSSL_realloc(str->length == 0 ? NULL : str->data, alloc_len);
344
0
        if (c == NULL)
345
0
            return 0;
346
0
        str->data = c;
347
0
    }
348
    /* length never includes the added \0 byte */
349
0
    str->length = (int)len;
350
351
0
    if (data != NULL && str->data != NULL) {
352
0
        memcpy(str->data, data, len);
353
0
        if (add_nul_byte) {
354
            /*
355
             * Add a '\0' terminator. This should not be necessary - but we add it as
356
             * a safety precaution
357
             */
358
0
            str->data[len] = '\0';
359
0
        }
360
0
    }
361
0
    ossl_asn1_bit_string_clear_unused_bits(str);
362
363
0
    return 1;
364
0
}
365
366
#ifndef OPENSSL_NO_DEPRECATED_4_1
367
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in)
368
0
{
369
0
    return ossl_asn1_string_set_internal(str, (const uint8_t *)_data, len_in,
370
0
        /*add_nul_byte=*/1);
371
0
}
372
#endif
373
374
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
375
0
{
376
0
    if (!(str->flags & ASN1_STRING_FLAG_DATA_NOT_OWNED)) {
377
0
        OPENSSL_clear_free(str->data, str->length);
378
0
    }
379
0
    str->flags &= ~ASN1_STRING_FLAG_DATA_NOT_OWNED;
380
0
    str->data = data;
381
0
    str->length = len;
382
0
}
383
384
int ASN1_STRING_set_data(ASN1_STRING *str, const uint8_t *data, size_t len_in)
385
0
{
386
0
    if (str->type == V_ASN1_BIT_STRING) {
387
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
388
0
        return 0;
389
0
    }
390
    /* This will go away once ASN1_STRING can size_t internally */
391
0
    if (len_in > INT_MAX) {
392
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
393
0
        return 0;
394
0
    }
395
0
    return ossl_asn1_string_set_internal(str, data, (int)len_in, /*add_nul_byte=*/0);
396
0
}
397
398
int ASN1_STRING_set_string(ASN1_STRING *str, const char *c_string)
399
0
{
400
0
    return ASN1_STRING_set_data(str, (const uint8_t *)c_string,
401
0
        strlen(c_string));
402
0
}
403
404
ASN1_STRING *ASN1_STRING_new(void)
405
0
{
406
0
    return ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
407
0
}
408
409
ASN1_STRING *ASN1_STRING_type_new(int type)
410
0
{
411
0
    ASN1_STRING *ret;
412
413
0
    ret = OPENSSL_zalloc(sizeof(*ret));
414
0
    if (ret == NULL)
415
0
        return NULL;
416
0
    ret->type = type;
417
0
    return ret;
418
0
}
419
420
ASN1_STRING *ASN1_STRING_new_not_owned(int type, const uint8_t *data,
421
    size_t length)
422
0
{
423
0
    ASN1_STRING *ret;
424
425
0
    if (type == V_ASN1_BIT_STRING)
426
0
        return NULL;
427
428
0
    if (data == NULL || length == 0)
429
0
        return NULL;
430
431
0
    if (length > INT_MAX)
432
0
        return NULL;
433
434
0
    ret = OPENSSL_zalloc(sizeof(*ret));
435
0
    if (ret == NULL)
436
0
        return NULL;
437
438
0
    ret->type = type;
439
0
    ret->data = (unsigned char *)data;
440
0
    ret->length = (int)length;
441
0
    ret->flags |= ASN1_STRING_FLAG_DATA_NOT_OWNED;
442
443
0
    return ret;
444
0
}
445
446
void ossl_asn1_string_free_internal(ASN1_STRING *a, int clear, int embed)
447
0
{
448
0
    if (a == NULL)
449
0
        return;
450
451
0
    if ((a->flags & ASN1_STRING_FLAG_DATA_NOT_OWNED)) {
452
0
        a->data = NULL;
453
0
        a->length = 0;
454
0
        a->flags &= ~ASN1_STRING_FLAG_DATA_NOT_OWNED;
455
0
    }
456
457
0
    if (!(a->flags & ASN1_STRING_FLAG_NDEF)) {
458
0
        if (clear)
459
0
            OPENSSL_clear_free(a->data, a->length);
460
0
        else
461
0
            OPENSSL_free(a->data);
462
0
    }
463
    /*
464
     * TODO(beck): Add an assert here to verify that the embed arg is
465
     * always set to match the flag, and then get rid of the arg.
466
     */
467
0
    if (!embed && !(a->flags & ASN1_STRING_FLAG_EMBED)) {
468
0
        if (clear)
469
0
            OPENSSL_clear_free(a, sizeof(*a));
470
0
        else
471
0
            OPENSSL_free(a);
472
0
    }
473
0
}
474
475
void ASN1_STRING_free(ASN1_STRING *a)
476
0
{
477
0
    if (a == NULL)
478
0
        return;
479
480
0
    ossl_asn1_string_free_internal(a, 0, a->flags & ASN1_STRING_FLAG_EMBED);
481
0
}
482
483
void ASN1_STRING_clear_free(ASN1_STRING *a)
484
0
{
485
0
    if (a == NULL)
486
0
        return;
487
488
0
    ossl_asn1_string_free_internal(a, 1, a->flags & ASN1_STRING_FLAG_EMBED);
489
0
}
490
491
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
492
0
{
493
0
    int i;
494
495
0
    i = (a->length - b->length);
496
0
    if (i == 0) {
497
0
        if (a->length != 0)
498
0
            i = memcmp(a->data, b->data, a->length);
499
0
        if (i == 0)
500
0
            return a->type - b->type;
501
0
        else
502
0
            return i;
503
0
    } else {
504
0
        return i;
505
0
    }
506
0
}
507
508
#ifndef OPENSSL_NO_DEPRECATED_4_1
509
int ASN1_STRING_length(const ASN1_STRING *x)
510
0
{
511
0
    return x->length;
512
0
}
513
#endif
514
515
size_t ASN1_STRING_length_ex(const ASN1_STRING *x)
516
0
{
517
0
    return (size_t)x->length;
518
0
}
519
520
#ifndef OPENSSL_NO_DEPRECATED_3_0
521
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
522
0
{
523
0
    x->length = len;
524
0
}
525
#endif
526
527
int ASN1_STRING_type(const ASN1_STRING *x)
528
0
{
529
0
    return x->type;
530
0
}
531
532
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
533
0
{
534
0
    return x->data;
535
0
}
536
537
/* |max_len| excludes NUL terminator and may be 0 to indicate no restriction */
538
char *ossl_sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text,
539
    const char *sep, size_t max_len)
540
0
{
541
0
    int i;
542
0
    ASN1_UTF8STRING *current;
543
0
    size_t length = 0, sep_len;
544
0
    char *result = NULL;
545
0
    char *p;
546
547
0
    if (sep == NULL)
548
0
        sep = "";
549
0
    sep_len = strlen(sep);
550
551
0
    for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
552
0
        current = sk_ASN1_UTF8STRING_value(text, i);
553
0
        if (i > 0)
554
0
            length += sep_len;
555
0
        length += ASN1_STRING_length_ex(current);
556
0
        if (max_len != 0 && length > max_len)
557
0
            return NULL;
558
0
    }
559
0
    if ((result = OPENSSL_malloc(length + 1)) == NULL)
560
0
        return NULL;
561
562
0
    p = result;
563
0
    for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
564
0
        current = sk_ASN1_UTF8STRING_value(text, i);
565
0
        length = ASN1_STRING_length_ex(current);
566
0
        if (i > 0 && sep_len > 0) {
567
0
            strncpy(p, sep, sep_len + 1); /* using + 1 to silence gcc warning */
568
0
            p += sep_len;
569
0
        }
570
0
        strncpy(p, (const char *)ASN1_STRING_get0_data(current), length);
571
0
        p += length;
572
0
    }
573
0
    *p = '\0';
574
575
0
    return result;
576
0
}