1/*
2 * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (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 <stddef.h>
11#include <string.h>
12#include "internal/cryptlib.h"
13#include <openssl/asn1.h>
14#include <openssl/asn1t.h>
15#include <openssl/objects.h>
16#include "crypto/asn1.h"
17#include "asn1_local.h"
18
19static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
20                                 const ASN1_ITEM *it, int tag, int aclass);
21static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
22                            int skcontlen, const ASN1_ITEM *item,
23                            int do_sort, int iclass);
24static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
25                                const ASN1_TEMPLATE *tt, int tag, int aclass);
26static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
27                               const ASN1_ITEM *it, int flags);
28static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
29                       const ASN1_ITEM *it);
30
31/*
32 * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
33 * indefinite length constructed encoding, where appropriate
34 */
35
36int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
37                       const ASN1_ITEM *it)
38{
39    return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
40}
41
42int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
43{
44    return asn1_item_flags_i2d(val, out, it, 0);
45}
46
47/*
48 * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
49 * points to a buffer to output the data to. The new i2d has one additional
50 * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
51 * allocated and populated with the encoding.
52 */
53
54static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
55                               const ASN1_ITEM *it, int flags)
56{
57    if (out && !*out) {
58        unsigned char *p, *buf;
59        int len;
60
61        len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
62        if (len <= 0)
63            return len;
64        if ((buf = OPENSSL_malloc(len)) == NULL) {
65            ASN1err(ASN1_F_ASN1_ITEM_FLAGS_I2D, ERR_R_MALLOC_FAILURE);
66            return -1;
67        }
68        p = buf;
69        ASN1_item_ex_i2d(&val, &p, it, -1, flags);
70        *out = buf;
71        return len;
72    }
73
74    return ASN1_item_ex_i2d(&val, out, it, -1, flags);
75}
76
77/*
78 * Encode an item, taking care of IMPLICIT tagging (if any). This function
79 * performs the normal item handling: it can be used in external types.
80 */
81
82int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
83                     const ASN1_ITEM *it, int tag, int aclass)
84{
85    const ASN1_TEMPLATE *tt = NULL;
86    int i, seqcontlen, seqlen, ndef = 1;
87    const ASN1_EXTERN_FUNCS *ef;
88    const ASN1_AUX *aux = it->funcs;
89    ASN1_aux_cb *asn1_cb = 0;
90
91    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
92        return 0;
93
94    if (aux && aux->asn1_cb)
95        asn1_cb = aux->asn1_cb;
96
97    switch (it->itype) {
98
99    case ASN1_ITYPE_PRIMITIVE:
100        if (it->templates)
101            return asn1_template_ex_i2d(pval, out, it->templates,
102                                        tag, aclass);
103        return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
104
105    case ASN1_ITYPE_MSTRING:
106        /*
107         * It never makes sense for multi-strings to have implicit tagging, so
108         * if tag != -1, then this looks like an error in the template.
109         */
110        if (tag != -1) {
111            ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE);
112            return -1;
113        }
114        return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
115
116    case ASN1_ITYPE_CHOICE:
117        /*
118         * It never makes sense for CHOICE types to have implicit tagging, so
119         * if tag != -1, then this looks like an error in the template.
120         */
121        if (tag != -1) {
122            ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE);
123            return -1;
124        }
125        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
126            return 0;
127        i = asn1_get_choice_selector(pval, it);
128        if ((i >= 0) && (i < it->tcount)) {
129            ASN1_VALUE **pchval;
130            const ASN1_TEMPLATE *chtt;
131            chtt = it->templates + i;
132            pchval = asn1_get_field_ptr(pval, chtt);
133            return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
134        }
135        /* Fixme: error condition if selector out of range */
136        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
137            return 0;
138        break;
139
140    case ASN1_ITYPE_EXTERN:
141        /* If new style i2d it does all the work */
142        ef = it->funcs;
143        return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
144
145    case ASN1_ITYPE_NDEF_SEQUENCE:
146        /* Use indefinite length constructed if requested */
147        if (aclass & ASN1_TFLG_NDEF)
148            ndef = 2;
149        /* fall through */
150
151    case ASN1_ITYPE_SEQUENCE:
152        i = asn1_enc_restore(&seqcontlen, out, pval, it);
153        /* An error occurred */
154        if (i < 0)
155            return 0;
156        /* We have a valid cached encoding... */
157        if (i > 0)
158            return seqcontlen;
159        /* Otherwise carry on */
160        seqcontlen = 0;
161        /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
162        if (tag == -1) {
163            tag = V_ASN1_SEQUENCE;
164            /* Retain any other flags in aclass */
165            aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
166                | V_ASN1_UNIVERSAL;
167        }
168        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
169            return 0;
170        /* First work out sequence content length */
171        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
172            const ASN1_TEMPLATE *seqtt;
173            ASN1_VALUE **pseqval;
174            int tmplen;
175            seqtt = asn1_do_adb(pval, tt, 1);
176            if (!seqtt)
177                return 0;
178            pseqval = asn1_get_field_ptr(pval, seqtt);
179            tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
180            if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
181                return -1;
182            seqcontlen += tmplen;
183        }
184
185        seqlen = ASN1_object_size(ndef, seqcontlen, tag);
186        if (!out || seqlen == -1)
187            return seqlen;
188        /* Output SEQUENCE header */
189        ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
190        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
191            const ASN1_TEMPLATE *seqtt;
192            ASN1_VALUE **pseqval;
193            seqtt = asn1_do_adb(pval, tt, 1);
194            if (!seqtt)
195                return 0;
196            pseqval = asn1_get_field_ptr(pval, seqtt);
197            /* FIXME: check for errors in enhanced version */
198            asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
199        }
200        if (ndef == 2)
201            ASN1_put_eoc(out);
202        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
203            return 0;
204        return seqlen;
205
206    default:
207        return 0;
208
209    }
210    return 0;
211}
212
213static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
214                                const ASN1_TEMPLATE *tt, int tag, int iclass)
215{
216    int i, ret, flags, ttag, tclass, ndef;
217    ASN1_VALUE *tval;
218    flags = tt->flags;
219
220    /*
221     * If field is embedded then val needs fixing so it is a pointer to
222     * a pointer to a field.
223     */
224    if (flags & ASN1_TFLG_EMBED) {
225        tval = (ASN1_VALUE *)pval;
226        pval = &tval;
227    }
228    /*
229     * Work out tag and class to use: tagging may come either from the
230     * template or the arguments, not both because this would create
231     * ambiguity. Additionally the iclass argument may contain some
232     * additional flags which should be noted and passed down to other
233     * levels.
234     */
235    if (flags & ASN1_TFLG_TAG_MASK) {
236        /* Error if argument and template tagging */
237        if (tag != -1)
238            /* FIXME: error code here */
239            return -1;
240        /* Get tagging from template */
241        ttag = tt->tag;
242        tclass = flags & ASN1_TFLG_TAG_CLASS;
243    } else if (tag != -1) {
244        /* No template tagging, get from arguments */
245        ttag = tag;
246        tclass = iclass & ASN1_TFLG_TAG_CLASS;
247    } else {
248        ttag = -1;
249        tclass = 0;
250    }
251    /*
252     * Remove any class mask from iflag.
253     */
254    iclass &= ~ASN1_TFLG_TAG_CLASS;
255
256    /*
257     * At this point 'ttag' contains the outer tag to use, 'tclass' is the
258     * class and iclass is any flags passed to this function.
259     */
260
261    /* if template and arguments require ndef, use it */
262    if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
263        ndef = 2;
264    else
265        ndef = 1;
266
267    if (flags & ASN1_TFLG_SK_MASK) {
268        /* SET OF, SEQUENCE OF */
269        STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
270        int isset, sktag, skaclass;
271        int skcontlen, sklen;
272        ASN1_VALUE *skitem;
273
274        if (!*pval)
275            return 0;
276
277        if (flags & ASN1_TFLG_SET_OF) {
278            isset = 1;
279            /* 2 means we reorder */
280            if (flags & ASN1_TFLG_SEQUENCE_OF)
281                isset = 2;
282        } else
283            isset = 0;
284
285        /*
286         * Work out inner tag value: if EXPLICIT or no tagging use underlying
287         * type.
288         */
289        if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
290            sktag = ttag;
291            skaclass = tclass;
292        } else {
293            skaclass = V_ASN1_UNIVERSAL;
294            if (isset)
295                sktag = V_ASN1_SET;
296            else
297                sktag = V_ASN1_SEQUENCE;
298        }
299
300        /* Determine total length of items */
301        skcontlen = 0;
302        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
303            int tmplen;
304            skitem = sk_ASN1_VALUE_value(sk, i);
305            tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
306                                      -1, iclass);
307            if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
308                return -1;
309            skcontlen += tmplen;
310        }
311        sklen = ASN1_object_size(ndef, skcontlen, sktag);
312        if (sklen == -1)
313            return -1;
314        /* If EXPLICIT need length of surrounding tag */
315        if (flags & ASN1_TFLG_EXPTAG)
316            ret = ASN1_object_size(ndef, sklen, ttag);
317        else
318            ret = sklen;
319
320        if (!out || ret == -1)
321            return ret;
322
323        /* Now encode this lot... */
324        /* EXPLICIT tag */
325        if (flags & ASN1_TFLG_EXPTAG)
326            ASN1_put_object(out, ndef, sklen, ttag, tclass);
327        /* SET or SEQUENCE and IMPLICIT tag */
328        ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
329        /* And the stuff itself */
330        asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
331                         isset, iclass);
332        if (ndef == 2) {
333            ASN1_put_eoc(out);
334            if (flags & ASN1_TFLG_EXPTAG)
335                ASN1_put_eoc(out);
336        }
337
338        return ret;
339    }
340
341    if (flags & ASN1_TFLG_EXPTAG) {
342        /* EXPLICIT tagging */
343        /* Find length of tagged item */
344        i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
345        if (!i)
346            return 0;
347        /* Find length of EXPLICIT tag */
348        ret = ASN1_object_size(ndef, i, ttag);
349        if (out && ret != -1) {
350            /* Output tag and item */
351            ASN1_put_object(out, ndef, i, ttag, tclass);
352            ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
353            if (ndef == 2)
354                ASN1_put_eoc(out);
355        }
356        return ret;
357    }
358
359    /* Either normal or IMPLICIT tagging: combine class and flags */
360    return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
361                            ttag, tclass | iclass);
362
363}
364
365/* Temporary structure used to hold DER encoding of items for SET OF */
366
367typedef struct {
368    unsigned char *data;
369    int length;
370    ASN1_VALUE *field;
371} DER_ENC;
372
373static int der_cmp(const void *a, const void *b)
374{
375    const DER_ENC *d1 = a, *d2 = b;
376    int cmplen, i;
377    cmplen = (d1->length < d2->length) ? d1->length : d2->length;
378    i = memcmp(d1->data, d2->data, cmplen);
379    if (i)
380        return i;
381    return d1->length - d2->length;
382}
383
384/* Output the content octets of SET OF or SEQUENCE OF */
385
386static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
387                            int skcontlen, const ASN1_ITEM *item,
388                            int do_sort, int iclass)
389{
390    int i;
391    ASN1_VALUE *skitem;
392    unsigned char *tmpdat = NULL, *p = NULL;
393    DER_ENC *derlst = NULL, *tder;
394    if (do_sort) {
395        /* Don't need to sort less than 2 items */
396        if (sk_ASN1_VALUE_num(sk) < 2)
397            do_sort = 0;
398        else {
399            derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
400                                    * sizeof(*derlst));
401            if (derlst == NULL)
402                return 0;
403            tmpdat = OPENSSL_malloc(skcontlen);
404            if (tmpdat == NULL) {
405                OPENSSL_free(derlst);
406                return 0;
407            }
408        }
409    }
410    /* If not sorting just output each item */
411    if (!do_sort) {
412        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
413            skitem = sk_ASN1_VALUE_value(sk, i);
414            ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
415        }
416        return 1;
417    }
418    p = tmpdat;
419
420    /* Doing sort: build up a list of each member's DER encoding */
421    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
422        skitem = sk_ASN1_VALUE_value(sk, i);
423        tder->data = p;
424        tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
425        tder->field = skitem;
426    }
427
428    /* Now sort them */
429    qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
430    /* Output sorted DER encoding */
431    p = *out;
432    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
433        memcpy(p, tder->data, tder->length);
434        p += tder->length;
435    }
436    *out = p;
437    /* If do_sort is 2 then reorder the STACK */
438    if (do_sort == 2) {
439        for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
440            (void)sk_ASN1_VALUE_set(sk, i, tder->field);
441    }
442    OPENSSL_free(derlst);
443    OPENSSL_free(tmpdat);
444    return 1;
445}
446
447static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
448                                 const ASN1_ITEM *it, int tag, int aclass)
449{
450    int len;
451    int utype;
452    int usetag;
453    int ndef = 0;
454
455    utype = it->utype;
456
457    /*
458     * Get length of content octets and maybe find out the underlying type.
459     */
460
461    len = asn1_ex_i2c(pval, NULL, &utype, it);
462
463    /*
464     * If SEQUENCE, SET or OTHER then header is included in pseudo content
465     * octets so don't include tag+length. We need to check here because the
466     * call to asn1_ex_i2c() could change utype.
467     */
468    if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
469        (utype == V_ASN1_OTHER))
470        usetag = 0;
471    else
472        usetag = 1;
473
474    /* -1 means omit type */
475
476    if (len == -1)
477        return 0;
478
479    /* -2 return is special meaning use ndef */
480    if (len == -2) {
481        ndef = 2;
482        len = 0;
483    }
484
485    /* If not implicitly tagged get tag from underlying type */
486    if (tag == -1)
487        tag = utype;
488
489    /* Output tag+length followed by content octets */
490    if (out) {
491        if (usetag)
492            ASN1_put_object(out, ndef, len, tag, aclass);
493        asn1_ex_i2c(pval, *out, &utype, it);
494        if (ndef)
495            ASN1_put_eoc(out);
496        else
497            *out += len;
498    }
499
500    if (usetag)
501        return ASN1_object_size(ndef, len, tag);
502    return len;
503}
504
505/* Produce content octets from a structure */
506
507static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
508                       const ASN1_ITEM *it)
509{
510    ASN1_BOOLEAN *tbool = NULL;
511    ASN1_STRING *strtmp;
512    ASN1_OBJECT *otmp;
513    int utype;
514    const unsigned char *cont;
515    unsigned char c;
516    int len;
517    const ASN1_PRIMITIVE_FUNCS *pf;
518    pf = it->funcs;
519    if (pf && pf->prim_i2c)
520        return pf->prim_i2c(pval, cout, putype, it);
521
522    /* Should type be omitted? */
523    if ((it->itype != ASN1_ITYPE_PRIMITIVE)
524        || (it->utype != V_ASN1_BOOLEAN)) {
525        if (!*pval)
526            return -1;
527    }
528
529    if (it->itype == ASN1_ITYPE_MSTRING) {
530        /* If MSTRING type set the underlying type */
531        strtmp = (ASN1_STRING *)*pval;
532        utype = strtmp->type;
533        *putype = utype;
534    } else if (it->utype == V_ASN1_ANY) {
535        /* If ANY set type and pointer to value */
536        ASN1_TYPE *typ;
537        typ = (ASN1_TYPE *)*pval;
538        utype = typ->type;
539        *putype = utype;
540        pval = &typ->value.asn1_value;
541    } else
542        utype = *putype;
543
544    switch (utype) {
545    case V_ASN1_OBJECT:
546        otmp = (ASN1_OBJECT *)*pval;
547        cont = otmp->data;
548        len = otmp->length;
549        if (cont == NULL || len == 0)
550            return -1;
551        break;
552
553    case V_ASN1_NULL:
554        cont = NULL;
555        len = 0;
556        break;
557
558    case V_ASN1_BOOLEAN:
559        tbool = (ASN1_BOOLEAN *)pval;
560        if (*tbool == -1)
561            return -1;
562        if (it->utype != V_ASN1_ANY) {
563            /*
564             * Default handling if value == size field then omit
565             */
566            if (*tbool && (it->size > 0))
567                return -1;
568            if (!*tbool && !it->size)
569                return -1;
570        }
571        c = (unsigned char)*tbool;
572        cont = &c;
573        len = 1;
574        break;
575
576    case V_ASN1_BIT_STRING:
577        return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
578                                   cout ? &cout : NULL);
579
580    case V_ASN1_INTEGER:
581    case V_ASN1_ENUMERATED:
582        /*
583         * These are all have the same content format as ASN1_INTEGER
584         */
585        return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
586
587    case V_ASN1_OCTET_STRING:
588    case V_ASN1_NUMERICSTRING:
589    case V_ASN1_PRINTABLESTRING:
590    case V_ASN1_T61STRING:
591    case V_ASN1_VIDEOTEXSTRING:
592    case V_ASN1_IA5STRING:
593    case V_ASN1_UTCTIME:
594    case V_ASN1_GENERALIZEDTIME:
595    case V_ASN1_GRAPHICSTRING:
596    case V_ASN1_VISIBLESTRING:
597    case V_ASN1_GENERALSTRING:
598    case V_ASN1_UNIVERSALSTRING:
599    case V_ASN1_BMPSTRING:
600    case V_ASN1_UTF8STRING:
601    case V_ASN1_SEQUENCE:
602    case V_ASN1_SET:
603    default:
604        /* All based on ASN1_STRING and handled the same */
605        strtmp = (ASN1_STRING *)*pval;
606        /* Special handling for NDEF */
607        if ((it->size == ASN1_TFLG_NDEF)
608            && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
609            if (cout) {
610                strtmp->data = cout;
611                strtmp->length = 0;
612            }
613            /* Special return code */
614            return -2;
615        }
616        cont = strtmp->data;
617        len = strtmp->length;
618
619        break;
620
621    }
622    if (cout && len)
623        memcpy(cout, cont, len);
624    return len;
625}
626