Coverage Report

Created: 2025-07-01 06:54

/work/mbedtls-2.28.8/library/asn1write.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * ASN.1 buffer writing functionality
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_WRITE_C)
11
12
#include "mbedtls/asn1write.h"
13
#include "mbedtls/error.h"
14
15
#include <string.h>
16
17
#include "mbedtls/platform.h"
18
19
int mbedtls_asn1_write_len(unsigned char **p, unsigned char *start, size_t len)
20
0
{
21
0
    if (len < 0x80) {
22
0
        if (*p - start < 1) {
23
0
            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
24
0
        }
25
26
0
        *--(*p) = (unsigned char) len;
27
0
        return 1;
28
0
    }
29
30
0
    if (len <= 0xFF) {
31
0
        if (*p - start < 2) {
32
0
            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
33
0
        }
34
35
0
        *--(*p) = (unsigned char) len;
36
0
        *--(*p) = 0x81;
37
0
        return 2;
38
0
    }
39
40
0
    if (len <= 0xFFFF) {
41
0
        if (*p - start < 3) {
42
0
            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
43
0
        }
44
45
0
        *--(*p) = MBEDTLS_BYTE_0(len);
46
0
        *--(*p) = MBEDTLS_BYTE_1(len);
47
0
        *--(*p) = 0x82;
48
0
        return 3;
49
0
    }
50
51
0
    if (len <= 0xFFFFFF) {
52
0
        if (*p - start < 4) {
53
0
            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
54
0
        }
55
56
0
        *--(*p) = MBEDTLS_BYTE_0(len);
57
0
        *--(*p) = MBEDTLS_BYTE_1(len);
58
0
        *--(*p) = MBEDTLS_BYTE_2(len);
59
0
        *--(*p) = 0x83;
60
0
        return 4;
61
0
    }
62
63
0
    int len_is_valid = 1;
64
0
#if SIZE_MAX > 0xFFFFFFFF
65
0
    len_is_valid = (len <= 0xFFFFFFFF);
66
0
#endif
67
0
    if (len_is_valid) {
68
0
        if (*p - start < 5) {
69
0
            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
70
0
        }
71
72
0
        *--(*p) = MBEDTLS_BYTE_0(len);
73
0
        *--(*p) = MBEDTLS_BYTE_1(len);
74
0
        *--(*p) = MBEDTLS_BYTE_2(len);
75
0
        *--(*p) = MBEDTLS_BYTE_3(len);
76
0
        *--(*p) = 0x84;
77
0
        return 5;
78
0
    }
79
80
0
    return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
81
0
}
82
83
int mbedtls_asn1_write_tag(unsigned char **p, unsigned char *start, unsigned char tag)
84
0
{
85
0
    if (*p - start < 1) {
86
0
        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
87
0
    }
88
89
0
    *--(*p) = tag;
90
91
0
    return 1;
92
0
}
93
94
int mbedtls_asn1_write_raw_buffer(unsigned char **p, unsigned char *start,
95
                                  const unsigned char *buf, size_t size)
96
0
{
97
0
    size_t len = 0;
98
99
0
    if (*p < start || (size_t) (*p - start) < size) {
100
0
        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
101
0
    }
102
103
0
    len = size;
104
0
    (*p) -= len;
105
0
    memcpy(*p, buf, len);
106
107
0
    return (int) len;
108
0
}
109
110
#if defined(MBEDTLS_BIGNUM_C)
111
int mbedtls_asn1_write_mpi(unsigned char **p, unsigned char *start, const mbedtls_mpi *X)
112
0
{
113
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
114
0
    size_t len = 0;
115
116
    // Write the MPI
117
    //
118
0
    len = mbedtls_mpi_size(X);
119
120
    /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not
121
     * as 0 digits. We need to end up with 020100, not with 0200. */
122
0
    if (len == 0) {
123
0
        len = 1;
124
0
    }
125
126
0
    if (*p < start || (size_t) (*p - start) < len) {
127
0
        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
128
0
    }
129
130
0
    (*p) -= len;
131
0
    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len));
132
133
    // DER format assumes 2s complement for numbers, so the leftmost bit
134
    // should be 0 for positive numbers and 1 for negative numbers.
135
    //
136
0
    if (X->s == 1 && **p & 0x80) {
137
0
        if (*p - start < 1) {
138
0
            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
139
0
        }
140
141
0
        *--(*p) = 0x00;
142
0
        len += 1;
143
0
    }
144
145
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
146
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_INTEGER));
147
148
0
    ret = (int) len;
149
150
0
cleanup:
151
0
    return ret;
152
0
}
153
#endif /* MBEDTLS_BIGNUM_C */
154
155
int mbedtls_asn1_write_null(unsigned char **p, unsigned char *start)
156
0
{
157
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
158
0
    size_t len = 0;
159
160
    // Write NULL
161
    //
162
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, 0));
163
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_NULL));
164
165
0
    return (int) len;
166
0
}
167
168
int mbedtls_asn1_write_oid(unsigned char **p, unsigned char *start,
169
                           const char *oid, size_t oid_len)
170
0
{
171
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
172
0
    size_t len = 0;
173
174
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
175
0
                                                            (const unsigned char *) oid, oid_len));
176
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
177
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID));
178
179
0
    return (int) len;
180
0
}
181
182
int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, unsigned char *start,
183
                                            const char *oid, size_t oid_len,
184
                                            size_t par_len)
185
0
{
186
0
    return mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, par_len, 1);
187
0
}
188
189
int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, unsigned char *start,
190
                                                const char *oid, size_t oid_len,
191
                                                size_t par_len, int has_par)
192
0
{
193
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
194
0
    size_t len = 0;
195
196
0
    if (has_par) {
197
0
        if (par_len == 0) {
198
0
            MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start));
199
0
        } else {
200
0
            len += par_len;
201
0
        }
202
0
    }
203
204
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
205
206
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
207
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
208
0
                                                     MBEDTLS_ASN1_CONSTRUCTED |
209
0
                                                     MBEDTLS_ASN1_SEQUENCE));
210
211
0
    return (int) len;
212
0
}
213
214
int mbedtls_asn1_write_bool(unsigned char **p, unsigned char *start, int boolean)
215
0
{
216
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
217
0
    size_t len = 0;
218
219
0
    if (*p - start < 1) {
220
0
        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
221
0
    }
222
223
0
    *--(*p) = (boolean) ? 255 : 0;
224
0
    len++;
225
226
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
227
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BOOLEAN));
228
229
0
    return (int) len;
230
0
}
231
232
static int asn1_write_tagged_int(unsigned char **p, unsigned char *start, int val, int tag)
233
0
{
234
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
235
0
    size_t len = 0;
236
237
0
    do {
238
0
        if (*p - start < 1) {
239
0
            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
240
0
        }
241
0
        len += 1;
242
0
        *--(*p) = val & 0xff;
243
0
        val >>= 8;
244
0
    } while (val > 0);
245
246
0
    if (**p & 0x80) {
247
0
        if (*p - start < 1) {
248
0
            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
249
0
        }
250
0
        *--(*p) = 0x00;
251
0
        len += 1;
252
0
    }
253
254
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
255
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
256
257
0
    return (int) len;
258
0
}
259
260
int mbedtls_asn1_write_int(unsigned char **p, unsigned char *start, int val)
261
0
{
262
0
    return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER);
263
0
}
264
265
int mbedtls_asn1_write_enum(unsigned char **p, unsigned char *start, int val)
266
0
{
267
0
    return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED);
268
0
}
269
270
int mbedtls_asn1_write_tagged_string(unsigned char **p, unsigned char *start, int tag,
271
                                     const char *text, size_t text_len)
272
0
{
273
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
274
0
    size_t len = 0;
275
276
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
277
0
                                                            (const unsigned char *) text,
278
0
                                                            text_len));
279
280
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
281
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
282
283
0
    return (int) len;
284
0
}
285
286
int mbedtls_asn1_write_utf8_string(unsigned char **p, unsigned char *start,
287
                                   const char *text, size_t text_len)
288
0
{
289
0
    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len);
290
0
}
291
292
int mbedtls_asn1_write_printable_string(unsigned char **p, unsigned char *start,
293
                                        const char *text, size_t text_len)
294
0
{
295
0
    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text,
296
0
                                            text_len);
297
0
}
298
299
int mbedtls_asn1_write_ia5_string(unsigned char **p, unsigned char *start,
300
                                  const char *text, size_t text_len)
301
0
{
302
0
    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len);
303
0
}
304
305
int mbedtls_asn1_write_named_bitstring(unsigned char **p,
306
                                       unsigned char *start,
307
                                       const unsigned char *buf,
308
                                       size_t bits)
309
0
{
310
0
    size_t unused_bits, byte_len;
311
0
    const unsigned char *cur_byte;
312
0
    unsigned char cur_byte_shifted;
313
0
    unsigned char bit;
314
315
0
    byte_len = (bits + 7) / 8;
316
0
    unused_bits = (byte_len * 8) - bits;
317
318
    /*
319
     * Named bitstrings require that trailing 0s are excluded in the encoding
320
     * of the bitstring. Trailing 0s are considered part of the 'unused' bits
321
     * when encoding this value in the first content octet
322
     */
323
0
    if (bits != 0) {
324
0
        cur_byte = buf + byte_len - 1;
325
0
        cur_byte_shifted = *cur_byte >> unused_bits;
326
327
0
        for (;;) {
328
0
            bit = cur_byte_shifted & 0x1;
329
0
            cur_byte_shifted >>= 1;
330
331
0
            if (bit != 0) {
332
0
                break;
333
0
            }
334
335
0
            bits--;
336
0
            if (bits == 0) {
337
0
                break;
338
0
            }
339
340
0
            if (bits % 8 == 0) {
341
0
                cur_byte_shifted = *--cur_byte;
342
0
            }
343
0
        }
344
0
    }
345
346
0
    return mbedtls_asn1_write_bitstring(p, start, buf, bits);
347
0
}
348
349
int mbedtls_asn1_write_bitstring(unsigned char **p, unsigned char *start,
350
                                 const unsigned char *buf, size_t bits)
351
0
{
352
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
353
0
    size_t len = 0;
354
0
    size_t unused_bits, byte_len;
355
356
0
    byte_len = (bits + 7) / 8;
357
0
    unused_bits = (byte_len * 8) - bits;
358
359
0
    if (*p < start || (size_t) (*p - start) < byte_len + 1) {
360
0
        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
361
0
    }
362
363
0
    len = byte_len + 1;
364
365
    /* Write the bitstring. Ensure the unused bits are zeroed */
366
0
    if (byte_len > 0) {
367
0
        byte_len--;
368
0
        *--(*p) = buf[byte_len] & ~((0x1 << unused_bits) - 1);
369
0
        (*p) -= byte_len;
370
0
        memcpy(*p, buf, byte_len);
371
0
    }
372
373
    /* Write unused bits */
374
0
    *--(*p) = (unsigned char) unused_bits;
375
376
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
377
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING));
378
379
0
    return (int) len;
380
0
}
381
382
int mbedtls_asn1_write_octet_string(unsigned char **p, unsigned char *start,
383
                                    const unsigned char *buf, size_t size)
384
0
{
385
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
386
0
    size_t len = 0;
387
388
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size));
389
390
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
391
0
    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING));
392
393
0
    return (int) len;
394
0
}
395
396
397
/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
398
 * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
399
static mbedtls_asn1_named_data *asn1_find_named_data(
400
    mbedtls_asn1_named_data *list,
401
    const char *oid, size_t len)
402
0
{
403
0
    while (list != NULL) {
404
0
        if (list->oid.len == len &&
405
0
            memcmp(list->oid.p, oid, len) == 0) {
406
0
            break;
407
0
        }
408
409
0
        list = list->next;
410
0
    }
411
412
0
    return list;
413
0
}
414
415
mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
416
    mbedtls_asn1_named_data **head,
417
    const char *oid, size_t oid_len,
418
    const unsigned char *val,
419
    size_t val_len)
420
0
{
421
0
    mbedtls_asn1_named_data *cur;
422
423
0
    if ((cur = asn1_find_named_data(*head, oid, oid_len)) == NULL) {
424
        // Add new entry if not present yet based on OID
425
        //
426
0
        cur = (mbedtls_asn1_named_data *) mbedtls_calloc(1,
427
0
                                                         sizeof(mbedtls_asn1_named_data));
428
0
        if (cur == NULL) {
429
0
            return NULL;
430
0
        }
431
432
0
        cur->oid.len = oid_len;
433
0
        cur->oid.p = mbedtls_calloc(1, oid_len);
434
0
        if (cur->oid.p == NULL) {
435
0
            mbedtls_free(cur);
436
0
            return NULL;
437
0
        }
438
439
0
        memcpy(cur->oid.p, oid, oid_len);
440
441
0
        cur->val.len = val_len;
442
0
        if (val_len != 0) {
443
0
            cur->val.p = mbedtls_calloc(1, val_len);
444
0
            if (cur->val.p == NULL) {
445
0
                mbedtls_free(cur->oid.p);
446
0
                mbedtls_free(cur);
447
0
                return NULL;
448
0
            }
449
0
        }
450
451
0
        cur->next = *head;
452
0
        *head = cur;
453
0
    } else if (val_len == 0) {
454
0
        mbedtls_free(cur->val.p);
455
0
        cur->val.p = NULL;
456
0
    } else if (cur->val.len != val_len) {
457
        /*
458
         * Enlarge existing value buffer if needed
459
         * Preserve old data until the allocation succeeded, to leave list in
460
         * a consistent state in case allocation fails.
461
         */
462
0
        void *p = mbedtls_calloc(1, val_len);
463
0
        if (p == NULL) {
464
0
            return NULL;
465
0
        }
466
467
0
        mbedtls_free(cur->val.p);
468
0
        cur->val.p = p;
469
0
        cur->val.len = val_len;
470
0
    }
471
472
0
    if (val != NULL && val_len != 0) {
473
0
        memcpy(cur->val.p, val, val_len);
474
0
    }
475
476
0
    return cur;
477
0
}
478
#endif /* MBEDTLS_ASN1_WRITE_C */