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