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