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