year 2003
[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                 /* Use indefinite length constructed if requested */
189                 if (aclass & ASN1_TFLG_NDEF) ndef = 2;
190                 /* fall through */
191
192                 case ASN1_ITYPE_SEQUENCE:
193                 i = asn1_enc_restore(&seqcontlen, out, pval, it);
194                 /* An error occurred */
195                 if(i < 0) return 0;
196                 /* We have a valid cached encoding... */
197                 if(i > 0) return seqcontlen;
198                 /* Otherwise carry on */
199                 seqcontlen = 0;
200                 /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
201                 if(tag == -1) {
202                         tag = V_ASN1_SEQUENCE;
203                         /* Retain any other flags in aclass */
204                         aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
205                                         | V_ASN1_UNIVERSAL;
206                 }
207                 if(asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it))
208                                 return 0;
209                 /* First work out sequence content length */
210                 for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
211                         const ASN1_TEMPLATE *seqtt;
212                         ASN1_VALUE **pseqval;
213                         seqtt = asn1_do_adb(pval, tt, 1);
214                         if(!seqtt) return 0;
215                         pseqval = asn1_get_field_ptr(pval, seqtt);
216                         /* FIXME: check for errors in enhanced version */
217                         seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
218                                                                 -1, aclass);
219                 }
220                 seqlen = ASN1_object_size(ndef, seqcontlen, tag);
221                 if(!out) return seqlen;
222                 /* Output SEQUENCE header */
223                 ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
224                 for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
225                         const ASN1_TEMPLATE *seqtt;
226                         ASN1_VALUE **pseqval;
227                         seqtt = asn1_do_adb(pval, tt, 1);
228                         if(!seqtt) return 0;
229                         pseqval = asn1_get_field_ptr(pval, seqtt);
230                         /* FIXME: check for errors in enhanced version */
231                         asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
232                 }
233                 if (ndef == 2) ASN1_put_eoc(out);
234                 if(asn1_cb  && !asn1_cb(ASN1_OP_I2D_POST, pval, it))
235                                 return 0;
236                 return seqlen;
237
238                 default:
239                 return 0;
240         }
241         return 0;
242 }
243
244 int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt)
245         {
246         return asn1_template_ex_i2d(pval, out, tt, -1, 0);
247         }
248
249 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt, int tag, int iclass)
250 {
251         int i, ret, flags, ttag, tclass, ndef;
252         flags = tt->flags;
253         /* Work out tag and class to use: tagging may come
254          * either from the template or the arguments, not both
255          * because this would create ambiguity. Additionally
256          * the iclass argument may contain some additional flags
257          * which should be noted and passed down to other levels.
258          */
259         if (flags & ASN1_TFLG_TAG_MASK)
260                 {
261                 /* Error if argument and template tagging */
262                 if (tag != -1)
263                         /* FIXME: error code here */
264                         return -1;
265                 /* Get tagging from template */
266                 ttag = tt->tag;
267                 tclass = flags & ASN1_TFLG_TAG_CLASS;
268                 }
269         else if (tag != -1)
270                 {
271                 /* No template tagging, get from arguments */
272                 ttag = tag;
273                 tclass = iclass & ASN1_TFLG_TAG_CLASS;
274                 }
275         else
276                 {
277                 ttag = -1;
278                 tclass = 0;
279                 }
280         /* 
281          * Remove any class mask from iflag.
282          */
283         iclass &= ~ASN1_TFLG_TAG_CLASS;
284
285         /* At this point 'ttag' contains the outer tag to use,
286          * 'tclass' is the class and iclass is any flags passed
287          * to this function.
288          */
289
290         /* if template and arguments require ndef, use it */
291         if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
292                 ndef = 2;
293         else ndef = 1;
294
295         if(flags & ASN1_TFLG_SK_MASK) {
296                 /* SET OF, SEQUENCE OF */
297                 STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
298                 int isset, sktag, skaclass;
299                 int skcontlen, sklen;
300                 ASN1_VALUE *skitem;
301
302                 if(!*pval) return 0;
303
304                 if(flags & ASN1_TFLG_SET_OF) {
305                         isset = 1;
306                         /* 2 means we reorder */
307                         if(flags & ASN1_TFLG_SEQUENCE_OF) isset = 2;
308                 } else isset = 0;
309
310                 /* Work out inner tag value: if EXPLICIT
311                  * or no tagging use underlying type.
312                  */
313                 if((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
314                         sktag = ttag;
315                         skaclass = tclass;
316                 } else {
317                         skaclass = V_ASN1_UNIVERSAL;
318                         if(isset) sktag = V_ASN1_SET;
319                         else sktag = V_ASN1_SEQUENCE;
320                 }
321
322                 /* Determine total length of items */
323                 skcontlen = 0;
324                 for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
325                         skitem = sk_ASN1_VALUE_value(sk, i);
326                         skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
327                                                         ASN1_ITEM_ptr(tt->item),
328                                                         -1, iclass);
329                 }
330                 sklen = ASN1_object_size(ndef, skcontlen, sktag);
331                 /* If EXPLICIT need length of surrounding tag */
332                 if(flags & ASN1_TFLG_EXPTAG)
333                         ret = ASN1_object_size(ndef, sklen, ttag);
334                 else ret = sklen;
335
336                 if(!out) return ret;
337
338                 /* Now encode this lot... */
339                 /* EXPLICIT tag */
340                 if(flags & ASN1_TFLG_EXPTAG)
341                         ASN1_put_object(out, ndef, sklen, ttag, tclass);
342                 /* SET or SEQUENCE and IMPLICIT tag */
343                 ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
344                 /* And the stuff itself */
345                 asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
346                                                                 isset, iclass);
347                 if (ndef == 2) {
348                         ASN1_put_eoc(out);
349                         if(flags & ASN1_TFLG_EXPTAG)
350                                 ASN1_put_eoc(out);
351                 }
352
353                 return ret;
354         }
355
356         if(flags & ASN1_TFLG_EXPTAG) {
357                 /* EXPLICIT tagging */
358                 /* Find length of tagged item */
359                 i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item),
360                                                                 -1, iclass);
361                 if(!i) return 0;
362                 /* Find length of EXPLICIT tag */
363                 ret = ASN1_object_size(ndef, i, ttag);
364                 if(out) {
365                         /* Output tag and item */
366                         ASN1_put_object(out, ndef, i, ttag, tclass);
367                         ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
368                                                                 -1, iclass);
369                         if (ndef == 2) ASN1_put_eoc(out);
370                 }
371                 return ret;
372         }
373
374         /* Either normal or IMPLICIT tagging: combine class and flags */
375         return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
376                                                 ttag, tclass | iclass);
377
378 }
379
380 /* Temporary structure used to hold DER encoding of items for SET OF */
381
382 typedef struct {
383         unsigned char *data;
384         int length;
385         ASN1_VALUE *field;
386 } DER_ENC;
387
388 static int der_cmp(const void *a, const void *b)
389 {
390         const DER_ENC *d1 = a, *d2 = b;
391         int cmplen, i;
392         cmplen = (d1->length < d2->length) ? d1->length : d2->length;
393         i = memcmp(d1->data, d2->data, cmplen);
394         if(i) return i;
395         return d1->length - d2->length;
396 }
397
398 /* Output the content octets of SET OF or SEQUENCE OF */
399
400 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
401                                         int skcontlen, const ASN1_ITEM *item,
402                                         int do_sort, int iclass)
403 {
404         int i;
405         ASN1_VALUE *skitem;
406         unsigned char *tmpdat = NULL, *p = NULL;
407         DER_ENC *derlst = NULL, *tder;
408         if(do_sort) {
409                 /* Don't need to sort less than 2 items */
410                 if(sk_ASN1_VALUE_num(sk) < 2) do_sort = 0;
411                 else {
412                         derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) * sizeof(*derlst));
413                         tmpdat = OPENSSL_malloc(skcontlen);
414                         if(!derlst || !tmpdat) return 0;
415                 }
416         }
417         /* If not sorting just output each item */
418         if(!do_sort) {
419                 for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
420                         skitem = sk_ASN1_VALUE_value(sk, i);
421                         ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
422                 }
423                 return 1;
424         }
425         p = tmpdat;
426         /* Doing sort: build up a list of each member's DER encoding */
427         for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
428                 skitem = sk_ASN1_VALUE_value(sk, i);
429                 tder->data = p;
430                 tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
431                 tder->field = skitem;
432         }
433         /* Now sort them */
434         qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
435         /* Output sorted DER encoding */        
436         p = *out;
437         for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
438                 memcpy(p, tder->data, tder->length);
439                 p += tder->length;
440         }
441         *out = p;
442         /* If do_sort is 2 then reorder the STACK */
443         if(do_sort == 2) {
444                 for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
445                         sk_ASN1_VALUE_set(sk, i, tder->field);
446         }
447         OPENSSL_free(derlst);
448         OPENSSL_free(tmpdat);
449         return 1;
450 }
451
452 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass)
453 {
454         int len;
455         int utype;
456         int usetag;
457         int ndef = 0;
458
459         utype = it->utype;
460
461         /* Get length of content octets and maybe find
462          * out the underlying type.
463          */
464
465         len = asn1_ex_i2c(pval, NULL, &utype, it);
466
467         /* If SEQUENCE, SET or OTHER then header is
468          * included in pseudo content octets so don't
469          * include tag+length. We need to check here
470          * because the call to asn1_ex_i2c() could change
471          * utype.
472          */
473         if((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
474            (utype == V_ASN1_OTHER))
475                 usetag = 0;
476         else usetag = 1;
477
478         /* -1 means omit type */
479
480         if(len == -1)
481                 return 0;
482
483         /* -2 return is special meaning use ndef */
484         if (len == -2)
485                 {
486                 ndef = 2;
487                 len = 0;
488                 }
489
490         /* If not implicitly tagged get tag from underlying type */
491         if(tag == -1) tag = utype;
492
493         /* Output tag+length followed by content octets */
494         if(out) {
495                 if(usetag) ASN1_put_object(out, ndef, len, tag, aclass);
496                 asn1_ex_i2c(pval, *out, &utype, it);
497                 *out += len;
498         }
499
500         if(usetag) return ASN1_object_size(ndef, len, tag);
501         return len;
502 }
503
504 /* Produce content octets from a structure */
505
506 int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, const ASN1_ITEM *it)
507 {
508         ASN1_BOOLEAN *tbool = NULL;
509         ASN1_STRING *strtmp;
510         ASN1_OBJECT *otmp;
511         int utype;
512         unsigned char *cont, c;
513         int len;
514         const ASN1_PRIMITIVE_FUNCS *pf;
515         pf = it->funcs;
516         if(pf && pf->prim_i2c) return pf->prim_i2c(pval, cout, putype, it);
517
518         /* Should type be omitted? */
519         if((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) {
520                 if(!*pval) return -1;
521         }
522
523         if(it->itype == ASN1_ITYPE_MSTRING) {
524                 /* If MSTRING type set the underlying type */
525                 strtmp = (ASN1_STRING *)*pval;
526                 utype = strtmp->type;
527                 *putype = utype;
528         } else if(it->utype == V_ASN1_ANY) {
529                 /* If ANY set type and pointer to value */
530                 ASN1_TYPE *typ;
531                 typ = (ASN1_TYPE *)*pval;
532                 utype = typ->type;
533                 *putype = utype;
534                 pval = (ASN1_VALUE **)&typ->value.ptr;
535         } else utype = *putype;
536
537         switch(utype) {
538                 case V_ASN1_OBJECT:
539                 otmp = (ASN1_OBJECT *)*pval;
540                 cont = otmp->data;
541                 len = otmp->length;
542                 break;
543
544                 case V_ASN1_NULL:
545                 cont = NULL;
546                 len = 0;
547                 break;
548
549                 case V_ASN1_BOOLEAN:
550                 tbool = (ASN1_BOOLEAN *)pval;
551                 if(*tbool == -1) return -1;
552                 /* Default handling if value == size field then omit */
553                 if(*tbool && (it->size > 0)) return -1;
554                 if(!*tbool && !it->size) return -1;
555                 c = (unsigned char)*tbool;
556                 cont = &c;
557                 len = 1;
558                 break;
559
560                 case V_ASN1_BIT_STRING:
561                 return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL);
562                 break;
563
564                 case V_ASN1_INTEGER:
565                 case V_ASN1_NEG_INTEGER:
566                 case V_ASN1_ENUMERATED:
567                 case V_ASN1_NEG_ENUMERATED:
568                 /* These are all have the same content format
569                  * as ASN1_INTEGER
570                  */
571                 return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
572                 break;
573
574                 case V_ASN1_OCTET_STRING:
575                 case V_ASN1_NUMERICSTRING:
576                 case V_ASN1_PRINTABLESTRING:
577                 case V_ASN1_T61STRING:
578                 case V_ASN1_VIDEOTEXSTRING:
579                 case V_ASN1_IA5STRING:
580                 case V_ASN1_UTCTIME:
581                 case V_ASN1_GENERALIZEDTIME:
582                 case V_ASN1_GRAPHICSTRING:
583                 case V_ASN1_VISIBLESTRING:
584                 case V_ASN1_GENERALSTRING:
585                 case V_ASN1_UNIVERSALSTRING:
586                 case V_ASN1_BMPSTRING:
587                 case V_ASN1_UTF8STRING:
588                 case V_ASN1_SEQUENCE:
589                 case V_ASN1_SET:
590                 default:
591                 /* All based on ASN1_STRING and handled the same */
592                 strtmp = (ASN1_STRING *)*pval;
593                 /* Special handling for NDEF */
594                 if ((it->size == ASN1_TFLG_NDEF)
595                         && (strtmp->flags & ASN1_STRING_FLAG_NDEF))
596                         {
597                         if (cout)
598                                 {
599                                 strtmp->data = cout;
600                                 strtmp->length = 0;
601                                 ASN1_put_eoc(&cout);
602                                 }
603                         /* Special return code */
604                         return -2;
605                         }
606                 cont = strtmp->data;
607                 len = strtmp->length;
608
609                 break;
610
611         }
612         if(cout && len) memcpy(cout, cont, len);
613         return len;
614 }