Coverage Report

Created: 2026-10-16 07:07

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-2026 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
#if defined(__has_feature)
17
#if __has_feature(address_sanitizer)
18
#define ASN1_HAVE_ASAN 1
19
#endif
20
#if __has_feature(memory_sanitizer)
21
#define ASN1_HAVE_MSAN 1
22
#endif
23
#endif /* defined(__has_feature) */
24
#if defined(__SANITIZE_ADDRESS__) && !defined(ASN1_HAVE_ASAN)
25
#define ASN1_HAVE_ASAN 1
26
#endif
27
#if defined(ASN1_HAVE_ASAN)
28
#include <sanitizer/asan_interface.h>
29
#endif
30
#if defined(ASN1_HAVE_MSAN)
31
#include <sanitizer/msan_interface.h>
32
#endif
33
#if !defined OPENSSL_NO_VALGRIND_CHECK && defined __has_include
34
/* Any compiler you're going to run valgrind on has this */
35
#if __has_include(<valgrind/memcheck.h>)
36
#include <valgrind/memcheck.h>
37
#include "internal/thread_once.h"
38
#define ASN1_HAVE_VALGRIND 1
39
#endif
40
#endif /* defined(__has_include) */
41
42
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
43
    long max);
44
static void asn1_put_length(unsigned char **pp, int length);
45
46
static int _asn1_check_infinite_end(const unsigned char **p, long len)
47
0
{
48
    /*
49
     * If there is 0 or 1 byte left, the length check should pick things up
50
     */
51
0
    if (len <= 0) {
52
0
        return 1;
53
0
    } else {
54
0
        if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
55
0
            (*p) += 2;
56
0
            return 1;
57
0
        }
58
0
    }
59
0
    return 0;
60
0
}
61
62
int ASN1_check_infinite_end(unsigned char **p, long len)
63
0
{
64
0
    return _asn1_check_infinite_end((const unsigned char **)p, len);
65
0
}
66
67
int ASN1_const_check_infinite_end(const unsigned char **p, long len)
68
0
{
69
0
    return _asn1_check_infinite_end(p, len);
70
0
}
71
72
int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
73
    int *pclass, long omax)
74
0
{
75
0
    int i, ret;
76
0
    long len;
77
0
    const unsigned char *p = *pp;
78
0
    int tag, xclass, inf;
79
0
    long max = omax;
80
81
0
    if (omax <= 0) {
82
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
83
0
        return 0x80;
84
0
    }
85
0
    ret = (*p & V_ASN1_CONSTRUCTED);
86
0
    xclass = (*p & V_ASN1_PRIVATE);
87
0
    i = *p & V_ASN1_PRIMITIVE_TAG;
88
0
    if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */
89
0
        p++;
90
0
        if (--max == 0)
91
0
            goto err;
92
0
        len = 0;
93
0
        while (*p & 0x80) {
94
0
            len <<= 7L;
95
0
            len |= *(p++) & 0x7f;
96
0
            if (--max == 0)
97
0
                goto err;
98
0
            if (len > (INT_MAX >> 7L))
99
0
                goto err;
100
0
        }
101
0
        len <<= 7L;
102
0
        len |= *(p++) & 0x7f;
103
0
        tag = (int)len;
104
0
        if (--max == 0)
105
0
            goto err;
106
0
    } else {
107
0
        tag = i;
108
0
        p++;
109
0
        if (--max == 0)
110
0
            goto err;
111
0
    }
112
0
    *ptag = tag;
113
0
    *pclass = xclass;
114
0
    if (!asn1_get_length(&p, &inf, plength, max))
115
0
        goto err;
116
117
0
    if (inf && !(ret & V_ASN1_CONSTRUCTED))
118
0
        goto err;
119
120
0
    if (*plength > (omax - (p - *pp))) {
121
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
122
        /*
123
         * Set this so that even if things are not long enough the values are
124
         * set correctly
125
         */
126
0
        ret |= 0x80;
127
0
    }
128
0
    *pp = p;
129
0
    return ret | inf;
130
0
err:
131
0
    ERR_raise(ERR_LIB_ASN1, ASN1_R_HEADER_TOO_LONG);
132
0
    return 0x80;
133
0
}
134
135
/*
136
 * Decode a length field.
137
 * The short form is a single byte defining a length 0 - 127.
138
 * The long form is a byte 0 - 127 with the top bit set and this indicates
139
 * the number of following octets that contain the length.  These octets
140
 * are stored most significant digit first.
141
 */
142
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
143
    long max)
144
0
{
145
0
    const unsigned char *p = *pp;
146
0
    unsigned long ret = 0;
147
0
    int i;
148
149
0
    if (max-- < 1)
150
0
        return 0;
151
0
    if (*p == 0x80) {
152
0
        *inf = 1;
153
0
        p++;
154
0
    } else {
155
0
        *inf = 0;
156
0
        i = *p & 0x7f;
157
0
        if (*p++ & 0x80) {
158
0
            if (max < i)
159
0
                return 0;
160
            /* Skip leading zeroes */
161
0
            while (i > 0 && *p == 0) {
162
0
                p++;
163
0
                i--;
164
0
            }
165
0
            if (i > (int)sizeof(long))
166
0
                return 0;
167
0
            while (i > 0) {
168
0
                ret <<= 8;
169
0
                ret |= *p++;
170
0
                i--;
171
0
            }
172
0
            if (ret > LONG_MAX)
173
0
                return 0;
174
0
        } else {
175
0
            ret = i;
176
0
        }
177
0
    }
178
0
    *pp = p;
179
0
    *rl = (long)ret;
180
0
    return 1;
181
0
}
182
183
/*
184
 * constructed == 2 for indefinite length constructed
185
 */
186
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
187
    int xclass)
188
0
{
189
0
    unsigned char *p = *pp;
190
0
    int i, ttag;
191
192
0
    i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
193
0
    i |= (xclass & V_ASN1_PRIVATE);
194
0
    if (tag < 31) {
195
0
        *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
196
0
    } else {
197
0
        *(p++) = i | V_ASN1_PRIMITIVE_TAG;
198
0
        for (i = 0, ttag = tag; ttag > 0; i++)
199
0
            ttag >>= 7;
200
0
        ttag = i;
201
0
        while (i-- > 0) {
202
0
            p[i] = tag & 0x7f;
203
0
            if (i != (ttag - 1))
204
0
                p[i] |= 0x80;
205
0
            tag >>= 7;
206
0
        }
207
0
        p += ttag;
208
0
    }
209
0
    if (constructed == 2)
210
0
        *(p++) = 0x80;
211
0
    else
212
0
        asn1_put_length(&p, length);
213
0
    *pp = p;
214
0
}
215
216
int ASN1_put_eoc(unsigned char **pp)
217
0
{
218
0
    unsigned char *p = *pp;
219
220
0
    *p++ = 0;
221
0
    *p++ = 0;
222
0
    *pp = p;
223
0
    return 2;
224
0
}
225
226
static void asn1_put_length(unsigned char **pp, int length)
227
0
{
228
0
    unsigned char *p = *pp;
229
0
    int i, len;
230
231
0
    if (length <= 127) {
232
0
        *(p++) = (unsigned char)length;
233
0
    } else {
234
0
        len = length;
235
0
        for (i = 0; len > 0; i++)
236
0
            len >>= 8;
237
0
        *(p++) = i | 0x80;
238
0
        len = i;
239
0
        while (i-- > 0) {
240
0
            p[i] = length & 0xff;
241
0
            length >>= 8;
242
0
        }
243
0
        p += len;
244
0
    }
245
0
    *pp = p;
246
0
}
247
248
int ASN1_object_size(int constructed, int length, int tag)
249
0
{
250
0
    int ret = 1;
251
252
0
    if (length < 0)
253
0
        return -1;
254
0
    if (tag >= 31) {
255
0
        while (tag > 0) {
256
0
            tag >>= 7;
257
0
            ret++;
258
0
        }
259
0
    }
260
0
    if (constructed == 2) {
261
0
        ret += 3;
262
0
    } else {
263
0
        ret++;
264
0
        if (length > 127) {
265
0
            int tmplen = length;
266
0
            while (tmplen > 0) {
267
0
                tmplen >>= 8;
268
0
                ret++;
269
0
            }
270
0
        }
271
0
    }
272
0
    if (ret >= INT_MAX - length)
273
0
        return -1;
274
0
    return ret + length;
275
0
}
276
277
void ossl_asn1_bit_string_clear_unused_bits(ASN1_STRING *str)
278
0
{
279
0
    str->flags &= ~0x07;
280
0
    str->flags &= ~ASN1_STRING_FLAG_BITS_LEFT;
281
0
}
282
283
void ossl_asn1_bit_string_set_unused_bits(ASN1_STRING *str, unsigned int num)
284
0
{
285
0
    ossl_asn1_bit_string_clear_unused_bits(str);
286
0
    str->flags |= ASN1_STRING_FLAG_BITS_LEFT | (num & 0x07);
287
0
}
288
289
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
290
0
{
291
0
    if (str == NULL || str->length < 0)
292
0
        return 0;
293
0
    dst->type = str->type;
294
0
    if (!ossl_asn1_string_set_internal(dst, str->data, str->length,
295
0
            /*add_nul_byte=*/1))
296
0
        return 0;
297
    /* Copy flags but preserve embed value */
298
0
    dst->flags &= ASN1_STRING_FLAG_EMBED;
299
0
    dst->flags |= str->flags & ~ASN1_STRING_FLAG_EMBED;
300
0
    return 1;
301
0
}
302
303
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
304
0
{
305
0
    ASN1_STRING *ret;
306
307
0
    if (!str)
308
0
        return NULL;
309
0
    ret = ASN1_STRING_new();
310
0
    if (ret == NULL)
311
0
        return NULL;
312
0
    if (!ASN1_STRING_copy(ret, str)) {
313
0
        ASN1_STRING_free(ret);
314
0
        return NULL;
315
0
    }
316
0
    return ret;
317
0
}
318
319
#if defined(ASN1_HAVE_VALGRIND)
320
static CRYPTO_ONCE valgrind_once = CRYPTO_ONCE_STATIC_INIT;
321
static int valgrind_present = 0;
322
323
DEFINE_RUN_ONCE_STATIC(detect_valgrind)
324
{
325
    valgrind_present = RUNNING_ON_VALGRIND != 0;
326
    return 1;
327
}
328
329
static int under_valgrind(void)
330
{
331
    return RUN_ONCE(&valgrind_once, detect_valgrind) && valgrind_present;
332
}
333
#endif /* defined(ASN1_HAVE_VALGRIND) */
334
335
/**
336
 * @brief Mark the NUL terminator at p as inaccessible to memory checkers.
337
 * Under AddressSanitizer, MemorySanitizer and Valgrind memcheck a read of
338
 * the byte is reported as an error, so C-string use of ASN1_STRING data is
339
 * caught while the byte stays present for builds without a checker. The
340
 * Valgrind client requests are compiled in wherever its header is found and
341
 * are issued only when the process is running under Valgrind.
342
 * A poisoned byte needs no unpoisoning before free(): every checker marks
343
 * the whole block on free without regard to its previous state.
344
 * @param p the terminator byte
345
 */
346
static void poison_terminator(uint8_t *p)
347
0
{
348
#if defined(ASN1_HAVE_ASAN)
349
    ASAN_POISON_MEMORY_REGION(p, 1);
350
#endif
351
#if defined(ASN1_HAVE_MSAN)
352
    __msan_poison(p, 1);
353
#endif
354
#if defined(ASN1_HAVE_VALGRIND)
355
    if (under_valgrind())
356
        VALGRIND_MAKE_MEM_NOACCESS(p, 1);
357
#endif
358
0
}
359
360
/**
361
 * @brief Make the byte at p accessible again before it is written.
362
 * @param p the byte about to hold a NUL terminator
363
 */
364
static void unpoison_terminator(uint8_t *p)
365
0
{
366
#if defined(ASN1_HAVE_ASAN)
367
    ASAN_UNPOISON_MEMORY_REGION(p, 1);
368
#endif
369
#if defined(ASN1_HAVE_MSAN)
370
    __msan_unpoison(p, 1);
371
#endif
372
#if defined(ASN1_HAVE_VALGRIND)
373
    if (under_valgrind())
374
        VALGRIND_MAKE_MEM_UNDEFINED(p, 1);
375
#endif
376
0
}
377
378
static void unpoison_buffer(uint8_t *buf, size_t buf_len)
379
0
{
380
#if defined(ASN1_HAVE_VALGRIND)
381
    if (under_valgrind())
382
        VALGRIND_MAKE_MEM_UNDEFINED(buf, buf_len);
383
#endif
384
0
}
385
386
int ossl_asn1_string_set_internal(ASN1_STRING *str, const uint8_t *data,
387
    int len_in, int add_nul_byte)
388
0
{
389
0
    size_t len, alloc_len;
390
391
0
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
392
    /*
393
     * Force no NUL byte for callers that are requesting it
394
     * 0 length object data will be NULL
395
     */
396
0
    add_nul_byte = 0;
397
0
#endif
398
0
    if (len_in < -1) {
399
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
400
0
        return 0;
401
0
    }
402
0
    if (len_in == -1) {
403
0
        if (data == NULL)
404
0
            return 0;
405
0
        len = strlen((const char *)data);
406
0
    } else {
407
0
        len = (size_t)len_in;
408
0
    }
409
    /*
410
     * Add one to the length to allow for adding an a '\0' terminator
411
     * "even though this isn't strictly necessary".
412
     */
413
0
    alloc_len = add_nul_byte ? len + 1 : len;
414
415
0
    if (alloc_len > INT_MAX) {
416
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
417
0
        return 0;
418
0
    }
419
420
0
    if ((str->flags & ASN1_STRING_FLAG_DATA_NOT_OWNED)) {
421
0
        str->data = NULL;
422
0
        str->length = 0;
423
0
        str->flags &= ~ASN1_STRING_FLAG_DATA_NOT_OWNED;
424
0
    }
425
426
    /* Ensure copying a 0 length data field is defined. */
427
0
    if (alloc_len == 0) {
428
0
        OPENSSL_free(str->data);
429
0
        str->data = NULL;
430
0
        str->length = 0;
431
0
        return 1;
432
0
    }
433
434
0
    if ((size_t)str->length != alloc_len) {
435
0
        uint8_t *c;
436
0
        c = OPENSSL_realloc(str->length == 0 ? NULL : str->data, alloc_len);
437
0
        if (c == NULL)
438
0
            return 0;
439
0
        str->data = c;
440
0
        unpoison_buffer(str->data, alloc_len);
441
0
    }
442
    /* length never includes the added \0 byte */
443
0
    str->length = (int)len;
444
445
0
    if (data != NULL && str->data != NULL)
446
0
        memcpy(str->data, data, len);
447
0
    if (add_nul_byte) {
448
        /*
449
         * The terminator byte lies beyond str->length. It is written only
450
         * when data is supplied, and is inaccessible to memory checkers
451
         * either way; see poison_terminator().
452
         */
453
0
        unpoison_terminator(&str->data[len]);
454
0
        if (data != NULL)
455
0
            str->data[len] = '\0';
456
0
        poison_terminator(&str->data[len]);
457
0
    }
458
0
    ossl_asn1_bit_string_clear_unused_bits(str);
459
460
0
    return 1;
461
0
}
462
463
#ifndef OPENSSL_NO_DEPRECATED_4_1
464
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in)
465
0
{
466
0
    return ossl_asn1_string_set_internal(str, (const uint8_t *)_data, len_in,
467
0
        /*add_nul_byte=*/1);
468
0
}
469
#endif
470
471
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
472
0
{
473
0
    if (!(str->flags & ASN1_STRING_FLAG_DATA_NOT_OWNED)) {
474
0
        if (str->length > 0)
475
0
            OPENSSL_clear_free(str->data, str->length);
476
0
        else
477
0
            OPENSSL_free(str->data);
478
0
    }
479
0
    str->flags &= ~ASN1_STRING_FLAG_DATA_NOT_OWNED;
480
0
    str->data = data;
481
0
    str->length = len < 0 ? 0 : len;
482
0
}
483
484
int ASN1_STRING_set1_data(ASN1_STRING *str, const uint8_t *data, size_t len_in)
485
0
{
486
0
    if (str->type == V_ASN1_BIT_STRING) {
487
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
488
0
        return 0;
489
0
    }
490
    /* This will go away once ASN1_STRING can size_t internally */
491
0
    if (len_in > INT_MAX) {
492
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
493
0
        return 0;
494
0
    }
495
0
    return ossl_asn1_string_set_internal(str, data, (int)len_in, /*add_nul_byte=*/0);
496
0
}
497
498
int ASN1_STRING_set1_string(ASN1_STRING *str, const char *c_string)
499
0
{
500
0
    return ASN1_STRING_set1_data(str, (const uint8_t *)c_string,
501
0
        strlen(c_string));
502
0
}
503
504
int ossl_asn1_string_set1_data(ASN1_STRING *str, const uint8_t *data,
505
    size_t len_in)
506
0
{
507
0
    if (str->type == V_ASN1_BIT_STRING) {
508
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
509
0
        return 0;
510
0
    }
511
    /* This will go away once ASN1_STRING can size_t internally */
512
0
    if (len_in > INT_MAX) {
513
0
        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
514
0
        return 0;
515
0
    }
516
0
    return ossl_asn1_string_set_internal(str, data, (int)len_in, /*add_nul_byte=*/1);
517
0
}
518
519
int ossl_asn1_string_set1_string(ASN1_STRING *str, const char *c_string)
520
0
{
521
0
    return ossl_asn1_string_set1_data(str, (const uint8_t *)c_string,
522
0
        strlen(c_string));
523
0
}
524
525
ASN1_STRING *ASN1_STRING_new(void)
526
0
{
527
0
    return ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
528
0
}
529
530
ASN1_STRING *ASN1_STRING_type_new(int type)
531
0
{
532
0
    ASN1_STRING *ret;
533
534
0
    ret = OPENSSL_zalloc(sizeof(*ret));
535
0
    if (ret == NULL)
536
0
        return NULL;
537
0
    ret->type = type;
538
0
    return ret;
539
0
}
540
541
ASN1_STRING *ASN1_STRING_new_not_owned(int type, const uint8_t *data,
542
    size_t length)
543
0
{
544
0
    ASN1_STRING *ret;
545
546
0
    if (type == V_ASN1_BIT_STRING)
547
0
        return NULL;
548
549
0
    if (data == NULL || length == 0)
550
0
        return NULL;
551
552
0
    if (length > INT_MAX)
553
0
        return NULL;
554
555
0
    ret = OPENSSL_zalloc(sizeof(*ret));
556
0
    if (ret == NULL)
557
0
        return NULL;
558
559
0
    ret->type = type;
560
0
    ret->data = (unsigned char *)data;
561
0
    ret->length = (int)length;
562
0
    ret->flags |= ASN1_STRING_FLAG_DATA_NOT_OWNED;
563
564
0
    return ret;
565
0
}
566
567
void ossl_asn1_string_free_internal(ASN1_STRING *a, int clear, int embed)
568
0
{
569
0
    if (a == NULL)
570
0
        return;
571
572
0
    if ((a->flags & ASN1_STRING_FLAG_DATA_NOT_OWNED)) {
573
0
        a->data = NULL;
574
0
        a->length = 0;
575
0
        a->flags &= ~ASN1_STRING_FLAG_DATA_NOT_OWNED;
576
0
    }
577
578
0
    if (!(a->flags & ASN1_STRING_FLAG_NDEF)) {
579
0
        if (clear && a->length > 0)
580
0
            OPENSSL_clear_free(a->data, a->length);
581
0
        else
582
0
            OPENSSL_free(a->data);
583
0
    }
584
    /*
585
     * TODO(beck): Add an assert here to verify that the embed arg is
586
     * always set to match the flag, and then get rid of the arg.
587
     */
588
0
    if (!embed && !(a->flags & ASN1_STRING_FLAG_EMBED)) {
589
0
        if (clear)
590
0
            OPENSSL_clear_free(a, sizeof(*a));
591
0
        else
592
0
            OPENSSL_free(a);
593
0
    }
594
0
}
595
596
void ASN1_STRING_free(ASN1_STRING *a)
597
0
{
598
0
    if (a == NULL)
599
0
        return;
600
601
0
    ossl_asn1_string_free_internal(a, 0, a->flags & ASN1_STRING_FLAG_EMBED);
602
0
}
603
604
void ASN1_STRING_clear_free(ASN1_STRING *a)
605
0
{
606
0
    if (a == NULL)
607
0
        return;
608
609
0
    ossl_asn1_string_free_internal(a, 1, a->flags & ASN1_STRING_FLAG_EMBED);
610
0
}
611
612
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
613
0
{
614
0
    int i;
615
616
0
    i = (a->length - b->length);
617
0
    if (i == 0) {
618
0
        if (a->length != 0)
619
0
            i = memcmp(a->data, b->data, a->length);
620
0
        if (i == 0)
621
0
            return a->type - b->type;
622
0
        else
623
0
            return i;
624
0
    } else {
625
0
        return i;
626
0
    }
627
0
}
628
629
#ifndef OPENSSL_NO_DEPRECATED_4_1
630
int ASN1_STRING_length(const ASN1_STRING *x)
631
0
{
632
0
    return x->length;
633
0
}
634
#endif
635
636
size_t ASN1_STRING_get_length(const ASN1_STRING *x)
637
0
{
638
0
    return x->length >= 0 ? (size_t)x->length : 0U;
639
0
}
640
641
#ifndef OPENSSL_NO_DEPRECATED_3_0
642
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
643
0
{
644
0
    x->length = len;
645
0
}
646
#endif
647
648
int ASN1_STRING_type(const ASN1_STRING *x)
649
0
{
650
0
    return x->type;
651
0
}
652
653
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
654
0
{
655
0
    return x->data;
656
0
}
657
658
char *ossl_sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text,
659
    const char *sep, size_t max_len)
660
0
{
661
0
    int i;
662
0
    ASN1_UTF8STRING *current;
663
0
    size_t length = 0, sep_len;
664
0
    char *result = NULL;
665
0
    char *p;
666
667
0
    if (sep == NULL)
668
0
        sep = "";
669
0
    sep_len = strlen(sep);
670
671
0
    for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
672
0
        current = sk_ASN1_UTF8STRING_value(text, i);
673
0
        if (i > 0)
674
0
            length += sep_len;
675
0
        length += ASN1_STRING_get_length(current);
676
0
        if (max_len != 0 && length > max_len)
677
0
            return NULL;
678
0
    }
679
0
    if ((result = OPENSSL_malloc(length + 1)) == NULL)
680
0
        return NULL;
681
682
0
    p = result;
683
0
    for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
684
0
        current = sk_ASN1_UTF8STRING_value(text, i);
685
0
        length = ASN1_STRING_get_length(current);
686
0
        if (i > 0 && sep_len > 0) {
687
0
            memcpy(p, sep, sep_len);
688
0
            p += sep_len;
689
0
        }
690
0
        if (length > 0) {
691
0
            memcpy(p, ASN1_STRING_get0_data(current), length);
692
0
            p += length;
693
0
        }
694
0
    }
695
0
    *p = '\0';
696
697
0
    return result;
698
0
}