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