Coverage Report

Created: 2022-11-30 06:20

/src/openssl/crypto/asn1/tasn_enc.c
Line
Count
Source (jump to first uncovered line)
1
/* tasn_enc.c */
2
/*
3
 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4
 * 2000.
5
 */
6
/* ====================================================================
7
 * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 *
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 *
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in
18
 *    the documentation and/or other materials provided with the
19
 *    distribution.
20
 *
21
 * 3. All advertising materials mentioning features or use of this
22
 *    software must display the following acknowledgment:
23
 *    "This product includes software developed by the OpenSSL Project
24
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25
 *
26
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27
 *    endorse or promote products derived from this software without
28
 *    prior written permission. For written permission, please contact
29
 *    licensing@OpenSSL.org.
30
 *
31
 * 5. Products derived from this software may not be called "OpenSSL"
32
 *    nor may "OpenSSL" appear in their names without prior written
33
 *    permission of the OpenSSL Project.
34
 *
35
 * 6. Redistributions of any form whatsoever must retain the following
36
 *    acknowledgment:
37
 *    "This product includes software developed by the OpenSSL Project
38
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
 * OF THE POSSIBILITY OF SUCH DAMAGE.
52
 * ====================================================================
53
 *
54
 * This product includes cryptographic software written by Eric Young
55
 * (eay@cryptsoft.com).  This product includes software written by Tim
56
 * Hudson (tjh@cryptsoft.com).
57
 *
58
 */
59
60
#include <stddef.h>
61
#include <string.h>
62
#include <limits.h>
63
#include "cryptlib.h"
64
#include <openssl/asn1.h>
65
#include <openssl/asn1t.h>
66
#include <openssl/objects.h>
67
68
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
69
                                 const ASN1_ITEM *it, int tag, int aclass);
70
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
71
                            int skcontlen, const ASN1_ITEM *item,
72
                            int do_sort, int iclass);
73
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
74
                                const ASN1_TEMPLATE *tt, int tag, int aclass);
75
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
76
                               const ASN1_ITEM *it, int flags);
77
78
/*
79
 * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
80
 * indefinite length constructed encoding, where appropriate
81
 */
82
83
int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
84
                       const ASN1_ITEM *it)
85
0
{
86
0
    return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
87
0
}
88
89
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
90
0
{
91
0
    return asn1_item_flags_i2d(val, out, it, 0);
92
0
}
93
94
/*
95
 * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
96
 * points to a buffer to output the data to. The new i2d has one additional
97
 * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
98
 * allocated and populated with the encoding.
99
 */
100
101
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
102
                               const ASN1_ITEM *it, int flags)
103
0
{
104
0
    if (out && !*out) {
105
0
        unsigned char *p, *buf;
106
0
        int len;
107
0
        len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
108
0
        if (len <= 0)
109
0
            return len;
110
0
        buf = OPENSSL_malloc(len);
111
0
        if (!buf)
112
0
            return -1;
113
0
        p = buf;
114
0
        ASN1_item_ex_i2d(&val, &p, it, -1, flags);
115
0
        *out = buf;
116
0
        return len;
117
0
    }
118
119
0
    return ASN1_item_ex_i2d(&val, out, it, -1, flags);
120
0
}
121
122
/*
123
 * Encode an item, taking care of IMPLICIT tagging (if any). This function
124
 * performs the normal item handling: it can be used in external types.
125
 */
126
127
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
128
                     const ASN1_ITEM *it, int tag, int aclass)
129
15.4M
{
130
15.4M
    const ASN1_TEMPLATE *tt = NULL;
131
15.4M
    unsigned char *p = NULL;
132
15.4M
    int i, seqcontlen, seqlen, ndef = 1;
133
15.4M
    const ASN1_COMPAT_FUNCS *cf;
134
15.4M
    const ASN1_EXTERN_FUNCS *ef;
135
15.4M
    const ASN1_AUX *aux = it->funcs;
136
15.4M
    ASN1_aux_cb *asn1_cb = 0;
137
138
15.4M
    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
139
0
        return 0;
140
141
15.4M
    if (aux && aux->asn1_cb)
142
0
        asn1_cb = aux->asn1_cb;
143
144
15.4M
    switch (it->itype) {
145
146
7.12M
    case ASN1_ITYPE_PRIMITIVE:
147
7.12M
        if (it->templates)
148
2.37M
            return asn1_template_ex_i2d(pval, out, it->templates,
149
2.37M
                                        tag, aclass);
150
4.75M
        return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
151
0
        break;
152
153
4.75M
    case ASN1_ITYPE_MSTRING:
154
4.75M
        return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
155
156
0
    case ASN1_ITYPE_CHOICE:
157
0
        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
158
0
            return 0;
159
0
        i = asn1_get_choice_selector(pval, it);
160
0
        if ((i >= 0) && (i < it->tcount)) {
161
0
            ASN1_VALUE **pchval;
162
0
            const ASN1_TEMPLATE *chtt;
163
0
            chtt = it->templates + i;
164
0
            pchval = asn1_get_field_ptr(pval, chtt);
165
0
            return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
166
0
        }
167
        /* Fixme: error condition if selector out of range */
168
0
        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
169
0
            return 0;
170
0
        break;
171
172
0
    case ASN1_ITYPE_EXTERN:
173
        /* If new style i2d it does all the work */
174
0
        ef = it->funcs;
175
0
        return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
176
177
0
    case ASN1_ITYPE_COMPAT:
178
        /* old style hackery... */
179
0
        cf = it->funcs;
180
0
        if (out)
181
0
            p = *out;
182
0
        i = cf->asn1_i2d(*pval, out);
183
        /*
184
         * Fixup for IMPLICIT tag: note this messes up for tags > 30, but so
185
         * did the old code. Tags > 30 are very rare anyway.
186
         */
187
0
        if (out && (tag != -1))
188
0
            *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
189
0
        return i;
190
191
0
    case ASN1_ITYPE_NDEF_SEQUENCE:
192
        /* Use indefinite length constructed if requested */
193
0
        if (aclass & ASN1_TFLG_NDEF)
194
0
            ndef = 2;
195
        /* fall through */
196
197
3.56M
    case ASN1_ITYPE_SEQUENCE:
198
3.56M
        i = asn1_enc_restore(&seqcontlen, out, pval, it);
199
        /* An error occurred */
200
3.56M
        if (i < 0)
201
0
            return 0;
202
        /* We have a valid cached encoding... */
203
3.56M
        if (i > 0)
204
0
            return seqcontlen;
205
        /* Otherwise carry on */
206
3.56M
        seqcontlen = 0;
207
        /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
208
3.56M
        if (tag == -1) {
209
3.56M
            tag = V_ASN1_SEQUENCE;
210
            /* Retain any other flags in aclass */
211
3.56M
            aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
212
3.56M
                | V_ASN1_UNIVERSAL;
213
3.56M
        }
214
3.56M
        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
215
0
            return 0;
216
        /* First work out sequence content length */
217
10.6M
        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
218
7.12M
            const ASN1_TEMPLATE *seqtt;
219
7.12M
            ASN1_VALUE **pseqval;
220
7.12M
            int tmplen;
221
7.12M
            seqtt = asn1_do_adb(pval, tt, 1);
222
7.12M
            if (!seqtt)
223
0
                return 0;
224
7.12M
            pseqval = asn1_get_field_ptr(pval, seqtt);
225
7.12M
            tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
226
7.12M
            if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
227
0
                return -1;
228
7.12M
            seqcontlen += tmplen;
229
7.12M
        }
230
231
3.56M
        seqlen = ASN1_object_size(ndef, seqcontlen, tag);
232
3.56M
        if (!out || seqlen == -1)
233
2.37M
            return seqlen;
234
        /* Output SEQUENCE header */
235
1.18M
        ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
236
3.56M
        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
237
2.37M
            const ASN1_TEMPLATE *seqtt;
238
2.37M
            ASN1_VALUE **pseqval;
239
2.37M
            seqtt = asn1_do_adb(pval, tt, 1);
240
2.37M
            if (!seqtt)
241
0
                return 0;
242
2.37M
            pseqval = asn1_get_field_ptr(pval, seqtt);
243
            /* FIXME: check for errors in enhanced version */
244
2.37M
            asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
245
2.37M
        }
246
1.18M
        if (ndef == 2)
247
0
            ASN1_put_eoc(out);
248
1.18M
        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
249
0
            return 0;
250
1.18M
        return seqlen;
251
252
0
    default:
253
0
        return 0;
254
255
15.4M
    }
256
0
    return 0;
257
15.4M
}
258
259
int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
260
                      const ASN1_TEMPLATE *tt)
261
0
{
262
0
    return asn1_template_ex_i2d(pval, out, tt, -1, 0);
263
0
}
264
265
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
266
                                const ASN1_TEMPLATE *tt, int tag, int iclass)
267
11.8M
{
268
11.8M
    int i, ret, flags, ttag, tclass, ndef;
269
11.8M
    flags = tt->flags;
270
    /*
271
     * Work out tag and class to use: tagging may come either from the
272
     * template or the arguments, not both because this would create
273
     * ambiguity. Additionally the iclass argument may contain some
274
     * additional flags which should be noted and passed down to other
275
     * levels.
276
     */
277
11.8M
    if (flags & ASN1_TFLG_TAG_MASK) {
278
        /* Error if argument and template tagging */
279
0
        if (tag != -1)
280
            /* FIXME: error code here */
281
0
            return -1;
282
        /* Get tagging from template */
283
0
        ttag = tt->tag;
284
0
        tclass = flags & ASN1_TFLG_TAG_CLASS;
285
11.8M
    } else if (tag != -1) {
286
        /* No template tagging, get from arguments */
287
0
        ttag = tag;
288
0
        tclass = iclass & ASN1_TFLG_TAG_CLASS;
289
11.8M
    } else {
290
11.8M
        ttag = -1;
291
11.8M
        tclass = 0;
292
11.8M
    }
293
    /*
294
     * Remove any class mask from iflag.
295
     */
296
11.8M
    iclass &= ~ASN1_TFLG_TAG_CLASS;
297
298
    /*
299
     * At this point 'ttag' contains the outer tag to use, 'tclass' is the
300
     * class and iclass is any flags passed to this function.
301
     */
302
303
    /* if template and arguments require ndef, use it */
304
11.8M
    if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
305
0
        ndef = 2;
306
11.8M
    else
307
11.8M
        ndef = 1;
308
309
11.8M
    if (flags & ASN1_TFLG_SK_MASK) {
310
        /* SET OF, SEQUENCE OF */
311
2.37M
        STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
312
2.37M
        int isset, sktag, skaclass;
313
2.37M
        int skcontlen, sklen;
314
2.37M
        ASN1_VALUE *skitem;
315
316
2.37M
        if (!*pval)
317
0
            return 0;
318
319
2.37M
        if (flags & ASN1_TFLG_SET_OF) {
320
2.37M
            isset = 1;
321
            /* 2 means we reorder */
322
2.37M
            if (flags & ASN1_TFLG_SEQUENCE_OF)
323
0
                isset = 2;
324
2.37M
        } else
325
0
            isset = 0;
326
327
        /*
328
         * Work out inner tag value: if EXPLICIT or no tagging use underlying
329
         * type.
330
         */
331
2.37M
        if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
332
0
            sktag = ttag;
333
0
            skaclass = tclass;
334
2.37M
        } else {
335
2.37M
            skaclass = V_ASN1_UNIVERSAL;
336
2.37M
            if (isset)
337
2.37M
                sktag = V_ASN1_SET;
338
0
            else
339
0
                sktag = V_ASN1_SEQUENCE;
340
2.37M
        }
341
342
        /* Determine total length of items */
343
2.37M
        skcontlen = 0;
344
4.75M
        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
345
2.37M
            int tmplen;
346
2.37M
            skitem = sk_ASN1_VALUE_value(sk, i);
347
2.37M
            tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
348
2.37M
                                      -1, iclass);
349
2.37M
            if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
350
0
                return -1;
351
2.37M
            skcontlen += tmplen;
352
2.37M
        }
353
2.37M
        sklen = ASN1_object_size(ndef, skcontlen, sktag);
354
2.37M
        if (sklen == -1)
355
0
            return -1;
356
        /* If EXPLICIT need length of surrounding tag */
357
2.37M
        if (flags & ASN1_TFLG_EXPTAG)
358
0
            ret = ASN1_object_size(ndef, sklen, ttag);
359
2.37M
        else
360
2.37M
            ret = sklen;
361
362
2.37M
        if (!out || ret == -1)
363
1.18M
            return ret;
364
365
        /* Now encode this lot... */
366
        /* EXPLICIT tag */
367
1.18M
        if (flags & ASN1_TFLG_EXPTAG)
368
0
            ASN1_put_object(out, ndef, sklen, ttag, tclass);
369
        /* SET or SEQUENCE and IMPLICIT tag */
370
1.18M
        ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
371
        /* And the stuff itself */
372
1.18M
        asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
373
1.18M
                         isset, iclass);
374
1.18M
        if (ndef == 2) {
375
0
            ASN1_put_eoc(out);
376
0
            if (flags & ASN1_TFLG_EXPTAG)
377
0
                ASN1_put_eoc(out);
378
0
        }
379
380
1.18M
        return ret;
381
2.37M
    }
382
383
9.50M
    if (flags & ASN1_TFLG_EXPTAG) {
384
        /* EXPLICIT tagging */
385
        /* Find length of tagged item */
386
0
        i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
387
0
        if (!i)
388
0
            return 0;
389
        /* Find length of EXPLICIT tag */
390
0
        ret = ASN1_object_size(ndef, i, ttag);
391
0
        if (out && ret != -1) {
392
            /* Output tag and item */
393
0
            ASN1_put_object(out, ndef, i, ttag, tclass);
394
0
            ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
395
0
            if (ndef == 2)
396
0
                ASN1_put_eoc(out);
397
0
        }
398
0
        return ret;
399
0
    }
400
401
    /* Either normal or IMPLICIT tagging: combine class and flags */
402
9.50M
    return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
403
9.50M
                            ttag, tclass | iclass);
404
405
9.50M
}
406
407
/* Temporary structure used to hold DER encoding of items for SET OF */
408
409
typedef struct {
410
    unsigned char *data;
411
    int length;
412
    ASN1_VALUE *field;
413
} DER_ENC;
414
415
static int der_cmp(const void *a, const void *b)
416
0
{
417
0
    const DER_ENC *d1 = a, *d2 = b;
418
0
    int cmplen, i;
419
0
    cmplen = (d1->length < d2->length) ? d1->length : d2->length;
420
0
    i = memcmp(d1->data, d2->data, cmplen);
421
0
    if (i)
422
0
        return i;
423
0
    return d1->length - d2->length;
424
0
}
425
426
/* Output the content octets of SET OF or SEQUENCE OF */
427
428
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
429
                            int skcontlen, const ASN1_ITEM *item,
430
                            int do_sort, int iclass)
431
1.18M
{
432
1.18M
    int i;
433
1.18M
    ASN1_VALUE *skitem;
434
1.18M
    unsigned char *tmpdat = NULL, *p = NULL;
435
1.18M
    DER_ENC *derlst = NULL, *tder;
436
1.18M
    if (do_sort) {
437
        /* Don't need to sort less than 2 items */
438
1.18M
        if (sk_ASN1_VALUE_num(sk) < 2)
439
1.18M
            do_sort = 0;
440
0
        else {
441
0
            derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
442
0
                                    * sizeof(*derlst));
443
0
            if (!derlst)
444
0
                return 0;
445
0
            tmpdat = OPENSSL_malloc(skcontlen);
446
0
            if (!tmpdat) {
447
0
                OPENSSL_free(derlst);
448
0
                return 0;
449
0
            }
450
0
        }
451
1.18M
    }
452
    /* If not sorting just output each item */
453
1.18M
    if (!do_sort) {
454
2.37M
        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
455
1.18M
            skitem = sk_ASN1_VALUE_value(sk, i);
456
1.18M
            ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
457
1.18M
        }
458
1.18M
        return 1;
459
1.18M
    }
460
0
    p = tmpdat;
461
462
    /* Doing sort: build up a list of each member's DER encoding */
463
0
    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
464
0
        skitem = sk_ASN1_VALUE_value(sk, i);
465
0
        tder->data = p;
466
0
        tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
467
0
        tder->field = skitem;
468
0
    }
469
470
    /* Now sort them */
471
0
    qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
472
    /* Output sorted DER encoding */
473
0
    p = *out;
474
0
    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
475
0
        memcpy(p, tder->data, tder->length);
476
0
        p += tder->length;
477
0
    }
478
0
    *out = p;
479
    /* If do_sort is 2 then reorder the STACK */
480
0
    if (do_sort == 2) {
481
0
        for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
482
0
            (void)sk_ASN1_VALUE_set(sk, i, tder->field);
483
0
    }
484
0
    OPENSSL_free(derlst);
485
0
    OPENSSL_free(tmpdat);
486
0
    return 1;
487
1.18M
}
488
489
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
490
                                 const ASN1_ITEM *it, int tag, int aclass)
491
9.50M
{
492
9.50M
    int len;
493
9.50M
    int utype;
494
9.50M
    int usetag;
495
9.50M
    int ndef = 0;
496
497
9.50M
    utype = it->utype;
498
499
    /*
500
     * Get length of content octets and maybe find out the underlying type.
501
     */
502
503
9.50M
    len = asn1_ex_i2c(pval, NULL, &utype, it);
504
505
    /*
506
     * If SEQUENCE, SET or OTHER then header is included in pseudo content
507
     * octets so don't include tag+length. We need to check here because the
508
     * call to asn1_ex_i2c() could change utype.
509
     */
510
9.50M
    if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
511
9.50M
        (utype == V_ASN1_OTHER))
512
0
        usetag = 0;
513
9.50M
    else
514
9.50M
        usetag = 1;
515
516
    /* -1 means omit type */
517
518
9.50M
    if (len == -1)
519
0
        return 0;
520
521
    /* -2 return is special meaning use ndef */
522
9.50M
    if (len == -2) {
523
0
        ndef = 2;
524
0
        len = 0;
525
0
    }
526
527
    /* If not implicitly tagged get tag from underlying type */
528
9.50M
    if (tag == -1)
529
9.50M
        tag = utype;
530
531
    /* Output tag+length followed by content octets */
532
9.50M
    if (out) {
533
2.37M
        if (usetag)
534
2.37M
            ASN1_put_object(out, ndef, len, tag, aclass);
535
2.37M
        asn1_ex_i2c(pval, *out, &utype, it);
536
2.37M
        if (ndef)
537
0
            ASN1_put_eoc(out);
538
2.37M
        else
539
2.37M
            *out += len;
540
2.37M
    }
541
542
9.50M
    if (usetag)
543
9.50M
        return ASN1_object_size(ndef, len, tag);
544
0
    return len;
545
9.50M
}
546
547
/* Produce content octets from a structure */
548
549
int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
550
                const ASN1_ITEM *it)
551
11.8M
{
552
11.8M
    ASN1_BOOLEAN *tbool = NULL;
553
11.8M
    ASN1_STRING *strtmp;
554
11.8M
    ASN1_OBJECT *otmp;
555
11.8M
    int utype;
556
11.8M
    const unsigned char *cont;
557
11.8M
    unsigned char c;
558
11.8M
    int len;
559
11.8M
    const ASN1_PRIMITIVE_FUNCS *pf;
560
11.8M
    pf = it->funcs;
561
11.8M
    if (pf && pf->prim_i2c)
562
0
        return pf->prim_i2c(pval, cout, putype, it);
563
564
    /* Should type be omitted? */
565
11.8M
    if ((it->itype != ASN1_ITYPE_PRIMITIVE)
566
11.8M
        || (it->utype != V_ASN1_BOOLEAN)) {
567
11.8M
        if (!*pval)
568
0
            return -1;
569
11.8M
    }
570
571
11.8M
    if (it->itype == ASN1_ITYPE_MSTRING) {
572
        /* If MSTRING type set the underlying type */
573
5.94M
        strtmp = (ASN1_STRING *)*pval;
574
5.94M
        utype = strtmp->type;
575
5.94M
        *putype = utype;
576
5.94M
    } else if (it->utype == V_ASN1_ANY) {
577
        /* If ANY set type and pointer to value */
578
0
        ASN1_TYPE *typ;
579
0
        typ = (ASN1_TYPE *)*pval;
580
0
        utype = typ->type;
581
0
        *putype = utype;
582
0
        pval = &typ->value.asn1_value;
583
0
    } else
584
5.94M
        utype = *putype;
585
586
11.8M
    switch (utype) {
587
5.94M
    case V_ASN1_OBJECT:
588
5.94M
        otmp = (ASN1_OBJECT *)*pval;
589
5.94M
        cont = otmp->data;
590
5.94M
        len = otmp->length;
591
5.94M
        break;
592
593
0
    case V_ASN1_NULL:
594
0
        cont = NULL;
595
0
        len = 0;
596
0
        break;
597
598
0
    case V_ASN1_BOOLEAN:
599
0
        tbool = (ASN1_BOOLEAN *)pval;
600
0
        if (*tbool == -1)
601
0
            return -1;
602
0
        if (it->utype != V_ASN1_ANY) {
603
            /*
604
             * Default handling if value == size field then omit
605
             */
606
0
            if (*tbool && (it->size > 0))
607
0
                return -1;
608
0
            if (!*tbool && !it->size)
609
0
                return -1;
610
0
        }
611
0
        c = (unsigned char)*tbool;
612
0
        cont = &c;
613
0
        len = 1;
614
0
        break;
615
616
0
    case V_ASN1_BIT_STRING:
617
0
        return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
618
0
                                   cout ? &cout : NULL);
619
0
        break;
620
621
0
    case V_ASN1_INTEGER:
622
0
    case V_ASN1_ENUMERATED:
623
        /*
624
         * These are all have the same content format as ASN1_INTEGER
625
         */
626
0
        return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
627
0
        break;
628
629
0
    case V_ASN1_OCTET_STRING:
630
0
    case V_ASN1_NUMERICSTRING:
631
0
    case V_ASN1_PRINTABLESTRING:
632
0
    case V_ASN1_T61STRING:
633
0
    case V_ASN1_VIDEOTEXSTRING:
634
0
    case V_ASN1_IA5STRING:
635
0
    case V_ASN1_UTCTIME:
636
0
    case V_ASN1_GENERALIZEDTIME:
637
0
    case V_ASN1_GRAPHICSTRING:
638
0
    case V_ASN1_VISIBLESTRING:
639
0
    case V_ASN1_GENERALSTRING:
640
0
    case V_ASN1_UNIVERSALSTRING:
641
0
    case V_ASN1_BMPSTRING:
642
5.94M
    case V_ASN1_UTF8STRING:
643
5.94M
    case V_ASN1_SEQUENCE:
644
5.94M
    case V_ASN1_SET:
645
5.94M
    default:
646
        /* All based on ASN1_STRING and handled the same */
647
5.94M
        strtmp = (ASN1_STRING *)*pval;
648
        /* Special handling for NDEF */
649
5.94M
        if ((it->size == ASN1_TFLG_NDEF)
650
5.94M
            && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
651
0
            if (cout) {
652
0
                strtmp->data = cout;
653
0
                strtmp->length = 0;
654
0
            }
655
            /* Special return code */
656
0
            return -2;
657
0
        }
658
5.94M
        cont = strtmp->data;
659
5.94M
        len = strtmp->length;
660
661
5.94M
        break;
662
663
11.8M
    }
664
11.8M
    if (cout && len)
665
2.37M
        memcpy(cout, cont, len);
666
11.8M
    return len;
667
11.8M
}