xref: /freebsd/crypto/openssl/crypto/asn1/tasn_enc.c (revision b077aed3)
1 /*
2  * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stddef.h>
11 #include <string.h>
12 #include "internal/cryptlib.h"
13 #include <openssl/asn1.h>
14 #include <openssl/asn1t.h>
15 #include <openssl/objects.h>
16 #include "crypto/asn1.h"
17 #include "asn1_local.h"
18 
19 static int asn1_i2d_ex_primitive(const ASN1_VALUE **pval, unsigned char **out,
20                                  const ASN1_ITEM *it, int tag, int aclass);
21 static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE) *sk,
22                             unsigned char **out,
23                             int skcontlen, const ASN1_ITEM *item,
24                             int do_sort, int iclass);
25 static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
26                                 const ASN1_TEMPLATE *tt, int tag, int aclass);
27 static int asn1_item_flags_i2d(const ASN1_VALUE *val, unsigned char **out,
28                                const ASN1_ITEM *it, int flags);
29 static int asn1_ex_i2c(const ASN1_VALUE **pval, unsigned char *cout, int *putype,
30                        const ASN1_ITEM *it);
31 
32 /*
33  * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
34  * indefinite length constructed encoding, where appropriate
35  */
36 
ASN1_item_ndef_i2d(const ASN1_VALUE * val,unsigned char ** out,const ASN1_ITEM * it)37 int ASN1_item_ndef_i2d(const ASN1_VALUE *val, unsigned char **out,
38                        const ASN1_ITEM *it)
39 {
40     return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
41 }
42 
ASN1_item_i2d(const ASN1_VALUE * val,unsigned char ** out,const ASN1_ITEM * it)43 int ASN1_item_i2d(const ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
44 {
45     return asn1_item_flags_i2d(val, out, it, 0);
46 }
47 
48 /*
49  * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
50  * points to a buffer to output the data to. The new i2d has one additional
51  * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
52  * allocated and populated with the encoding.
53  */
54 
asn1_item_flags_i2d(const ASN1_VALUE * val,unsigned char ** out,const ASN1_ITEM * it,int flags)55 static int asn1_item_flags_i2d(const ASN1_VALUE *val, unsigned char **out,
56                                const ASN1_ITEM *it, int flags)
57 {
58     if (out != NULL && *out == NULL) {
59         unsigned char *p, *buf;
60         int len;
61 
62         len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
63         if (len <= 0)
64             return len;
65         if ((buf = OPENSSL_malloc(len)) == NULL) {
66             ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
67             return -1;
68         }
69         p = buf;
70         ASN1_item_ex_i2d(&val, &p, it, -1, flags);
71         *out = buf;
72         return len;
73     }
74 
75     return ASN1_item_ex_i2d(&val, out, it, -1, flags);
76 }
77 
78 /*
79  * Encode an item, taking care of IMPLICIT tagging (if any). This function
80  * performs the normal item handling: it can be used in external types.
81  */
82 
ASN1_item_ex_i2d(const ASN1_VALUE ** pval,unsigned char ** out,const ASN1_ITEM * it,int tag,int aclass)83 int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
84                      const ASN1_ITEM *it, int tag, int aclass)
85 {
86     const ASN1_TEMPLATE *tt = NULL;
87     int i, seqcontlen, seqlen, ndef = 1;
88     const ASN1_EXTERN_FUNCS *ef;
89     const ASN1_AUX *aux = it->funcs;
90     ASN1_aux_const_cb *asn1_cb = NULL;
91 
92     if ((it->itype != ASN1_ITYPE_PRIMITIVE) && *pval == NULL)
93         return 0;
94 
95     if (aux != NULL) {
96         asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb
97             : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */
98     }
99 
100     switch (it->itype) {
101 
102     case ASN1_ITYPE_PRIMITIVE:
103         if (it->templates)
104             return asn1_template_ex_i2d(pval, out, it->templates,
105                                         tag, aclass);
106         return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
107 
108     case ASN1_ITYPE_MSTRING:
109         /*
110          * It never makes sense for multi-strings to have implicit tagging, so
111          * if tag != -1, then this looks like an error in the template.
112          */
113         if (tag != -1) {
114             ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
115             return -1;
116         }
117         return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
118 
119     case ASN1_ITYPE_CHOICE:
120         /*
121          * It never makes sense for CHOICE types to have implicit tagging, so
122          * if tag != -1, then this looks like an error in the template.
123          */
124         if (tag != -1) {
125             ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
126             return -1;
127         }
128         if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
129             return 0;
130         i = ossl_asn1_get_choice_selector_const(pval, it);
131         if ((i >= 0) && (i < it->tcount)) {
132             const ASN1_VALUE **pchval;
133             const ASN1_TEMPLATE *chtt;
134             chtt = it->templates + i;
135             pchval = ossl_asn1_get_const_field_ptr(pval, chtt);
136             return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
137         }
138         /* Fixme: error condition if selector out of range */
139         if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
140             return 0;
141         break;
142 
143     case ASN1_ITYPE_EXTERN:
144         /* If new style i2d it does all the work */
145         ef = it->funcs;
146         return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
147 
148     case ASN1_ITYPE_NDEF_SEQUENCE:
149         /* Use indefinite length constructed if requested */
150         if (aclass & ASN1_TFLG_NDEF)
151             ndef = 2;
152         /* fall through */
153 
154     case ASN1_ITYPE_SEQUENCE:
155         i = ossl_asn1_enc_restore(&seqcontlen, out, pval, it);
156         /* An error occurred */
157         if (i < 0)
158             return 0;
159         /* We have a valid cached encoding... */
160         if (i > 0)
161             return seqcontlen;
162         /* Otherwise carry on */
163         seqcontlen = 0;
164         /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
165         if (tag == -1) {
166             tag = V_ASN1_SEQUENCE;
167             /* Retain any other flags in aclass */
168             aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
169                 | V_ASN1_UNIVERSAL;
170         }
171         if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
172             return 0;
173         /* First work out sequence content length */
174         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
175             const ASN1_TEMPLATE *seqtt;
176             const ASN1_VALUE **pseqval;
177             int tmplen;
178             seqtt = ossl_asn1_do_adb(*pval, tt, 1);
179             if (!seqtt)
180                 return 0;
181             pseqval = ossl_asn1_get_const_field_ptr(pval, seqtt);
182             tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
183             if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
184                 return -1;
185             seqcontlen += tmplen;
186         }
187 
188         seqlen = ASN1_object_size(ndef, seqcontlen, tag);
189         if (!out || seqlen == -1)
190             return seqlen;
191         /* Output SEQUENCE header */
192         ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
193         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
194             const ASN1_TEMPLATE *seqtt;
195             const ASN1_VALUE **pseqval;
196             seqtt = ossl_asn1_do_adb(*pval, tt, 1);
197             if (!seqtt)
198                 return 0;
199             pseqval = ossl_asn1_get_const_field_ptr(pval, seqtt);
200             /* FIXME: check for errors in enhanced version */
201             asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
202         }
203         if (ndef == 2)
204             ASN1_put_eoc(out);
205         if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
206             return 0;
207         return seqlen;
208 
209     default:
210         return 0;
211 
212     }
213     return 0;
214 }
215 
asn1_template_ex_i2d(const ASN1_VALUE ** pval,unsigned char ** out,const ASN1_TEMPLATE * tt,int tag,int iclass)216 static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
217                                 const ASN1_TEMPLATE *tt, int tag, int iclass)
218 {
219     const int flags = tt->flags;
220     int i, ret, ttag, tclass, ndef, len;
221     const ASN1_VALUE *tval;
222 
223     /*
224      * If field is embedded then val needs fixing so it is a pointer to
225      * a pointer to a field.
226      */
227     if (flags & ASN1_TFLG_EMBED) {
228         tval = (ASN1_VALUE *)pval;
229         pval = &tval;
230     }
231     /*
232      * Work out tag and class to use: tagging may come either from the
233      * template or the arguments, not both because this would create
234      * ambiguity. Additionally the iclass argument may contain some
235      * additional flags which should be noted and passed down to other
236      * levels.
237      */
238     if (flags & ASN1_TFLG_TAG_MASK) {
239         /* Error if argument and template tagging */
240         if (tag != -1)
241             /* FIXME: error code here */
242             return -1;
243         /* Get tagging from template */
244         ttag = tt->tag;
245         tclass = flags & ASN1_TFLG_TAG_CLASS;
246     } else if (tag != -1) {
247         /* No template tagging, get from arguments */
248         ttag = tag;
249         tclass = iclass & ASN1_TFLG_TAG_CLASS;
250     } else {
251         ttag = -1;
252         tclass = 0;
253     }
254     /*
255      * Remove any class mask from iflag.
256      */
257     iclass &= ~ASN1_TFLG_TAG_CLASS;
258 
259     /*
260      * At this point 'ttag' contains the outer tag to use, 'tclass' is the
261      * class and iclass is any flags passed to this function.
262      */
263 
264     /* if template and arguments require ndef, use it */
265     if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
266         ndef = 2;
267     else
268         ndef = 1;
269 
270     if (flags & ASN1_TFLG_SK_MASK) {
271         /* SET OF, SEQUENCE OF */
272         STACK_OF(const_ASN1_VALUE) *sk = (STACK_OF(const_ASN1_VALUE) *)*pval;
273         int isset, sktag, skaclass;
274         int skcontlen, sklen;
275         const ASN1_VALUE *skitem;
276 
277         if (*pval == NULL)
278             return 0;
279 
280         if (flags & ASN1_TFLG_SET_OF) {
281             isset = 1;
282             /* 2 means we reorder */
283             if (flags & ASN1_TFLG_SEQUENCE_OF)
284                 isset = 2;
285         } else
286             isset = 0;
287 
288         /*
289          * Work out inner tag value: if EXPLICIT or no tagging use underlying
290          * type.
291          */
292         if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
293             sktag = ttag;
294             skaclass = tclass;
295         } else {
296             skaclass = V_ASN1_UNIVERSAL;
297             if (isset)
298                 sktag = V_ASN1_SET;
299             else
300                 sktag = V_ASN1_SEQUENCE;
301         }
302 
303         /* Determine total length of items */
304         skcontlen = 0;
305         for (i = 0; i < sk_const_ASN1_VALUE_num(sk); i++) {
306             skitem = sk_const_ASN1_VALUE_value(sk, i);
307             len = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
308                                    -1, iclass);
309             if (len == -1 || (skcontlen > INT_MAX - len))
310                 return -1;
311             if (len == 0 && (tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
312                 ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
313                 return -1;
314             }
315             skcontlen += len;
316         }
317         sklen = ASN1_object_size(ndef, skcontlen, sktag);
318         if (sklen == -1)
319             return -1;
320         /* If EXPLICIT need length of surrounding tag */
321         if (flags & ASN1_TFLG_EXPTAG)
322             ret = ASN1_object_size(ndef, sklen, ttag);
323         else
324             ret = sklen;
325 
326         if (!out || ret == -1)
327             return ret;
328 
329         /* Now encode this lot... */
330         /* EXPLICIT tag */
331         if (flags & ASN1_TFLG_EXPTAG)
332             ASN1_put_object(out, ndef, sklen, ttag, tclass);
333         /* SET or SEQUENCE and IMPLICIT tag */
334         ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
335         /* And the stuff itself */
336         asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
337                          isset, iclass);
338         if (ndef == 2) {
339             ASN1_put_eoc(out);
340             if (flags & ASN1_TFLG_EXPTAG)
341                 ASN1_put_eoc(out);
342         }
343 
344         return ret;
345     }
346 
347     if (flags & ASN1_TFLG_EXPTAG) {
348         /* EXPLICIT tagging */
349         /* Find length of tagged item */
350         i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
351         if (i == 0) {
352             if ((tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
353                 ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
354                 return -1;
355             }
356             return 0;
357         }
358         /* Find length of EXPLICIT tag */
359         ret = ASN1_object_size(ndef, i, ttag);
360         if (out && ret != -1) {
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), -1, iclass);
364             if (ndef == 2)
365                 ASN1_put_eoc(out);
366         }
367         return ret;
368     }
369 
370     /* Either normal or IMPLICIT tagging: combine class and flags */
371     len = ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
372                               ttag, tclass | iclass);
373     if (len == 0 && (tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
374         ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
375         return -1;
376     }
377     return len;
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     const ASN1_VALUE *field;
386 } DER_ENC;
387 
der_cmp(const void * a,const void * b)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)
395         return i;
396     return d1->length - d2->length;
397 }
398 
399 /* Output the content octets of SET OF or SEQUENCE OF */
400 
asn1_set_seq_out(STACK_OF (const_ASN1_VALUE)* sk,unsigned char ** out,int skcontlen,const ASN1_ITEM * item,int do_sort,int iclass)401 static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE) *sk,
402                             unsigned char **out,
403                             int skcontlen, const ASN1_ITEM *item,
404                             int do_sort, int iclass)
405 {
406     int i, ret = 0;
407     const ASN1_VALUE *skitem;
408     unsigned char *tmpdat = NULL, *p = NULL;
409     DER_ENC *derlst = NULL, *tder;
410 
411     if (do_sort) {
412         /* Don't need to sort less than 2 items */
413         if (sk_const_ASN1_VALUE_num(sk) < 2)
414             do_sort = 0;
415         else {
416             derlst = OPENSSL_malloc(sk_const_ASN1_VALUE_num(sk)
417                                     * sizeof(*derlst));
418             if (derlst == NULL) {
419                 ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
420                 return 0;
421             }
422             tmpdat = OPENSSL_malloc(skcontlen);
423             if (tmpdat == NULL) {
424                 ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
425                 goto err;
426             }
427         }
428     }
429     /* If not sorting just output each item */
430     if (!do_sort) {
431         for (i = 0; i < sk_const_ASN1_VALUE_num(sk); i++) {
432             skitem = sk_const_ASN1_VALUE_value(sk, i);
433             ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
434         }
435         return 1;
436     }
437     p = tmpdat;
438 
439     /* Doing sort: build up a list of each member's DER encoding */
440     for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++) {
441         skitem = sk_const_ASN1_VALUE_value(sk, i);
442         tder->data = p;
443         tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
444         tder->field = skitem;
445     }
446 
447     /* Now sort them */
448     qsort(derlst, sk_const_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
449     /* Output sorted DER encoding */
450     p = *out;
451     for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++) {
452         memcpy(p, tder->data, tder->length);
453         p += tder->length;
454     }
455     *out = p;
456     /* If do_sort is 2 then reorder the STACK */
457     if (do_sort == 2) {
458         for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++)
459             (void)sk_const_ASN1_VALUE_set(sk, i, tder->field);
460     }
461     ret = 1;
462 err:
463     OPENSSL_free(derlst);
464     OPENSSL_free(tmpdat);
465     return ret;
466 }
467 
asn1_i2d_ex_primitive(const ASN1_VALUE ** pval,unsigned char ** out,const ASN1_ITEM * it,int tag,int aclass)468 static int asn1_i2d_ex_primitive(const ASN1_VALUE **pval, unsigned char **out,
469                                  const ASN1_ITEM *it, int tag, int aclass)
470 {
471     int len;
472     int utype;
473     int usetag;
474     int ndef = 0;
475 
476     utype = it->utype;
477 
478     /*
479      * Get length of content octets and maybe find out the underlying type.
480      */
481 
482     len = asn1_ex_i2c(pval, NULL, &utype, it);
483 
484     /*
485      * If SEQUENCE, SET or OTHER then header is included in pseudo content
486      * octets so don't include tag+length. We need to check here because the
487      * call to asn1_ex_i2c() could change utype.
488      */
489     if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
490         (utype == V_ASN1_OTHER))
491         usetag = 0;
492     else
493         usetag = 1;
494 
495     /* -1 means omit type */
496 
497     if (len == -1)
498         return 0;
499 
500     /* -2 return is special meaning use ndef */
501     if (len == -2) {
502         ndef = 2;
503         len = 0;
504     }
505 
506     /* If not implicitly tagged get tag from underlying type */
507     if (tag == -1)
508         tag = utype;
509 
510     /* Output tag+length followed by content octets */
511     if (out) {
512         if (usetag)
513             ASN1_put_object(out, ndef, len, tag, aclass);
514         asn1_ex_i2c(pval, *out, &utype, it);
515         if (ndef)
516             ASN1_put_eoc(out);
517         else
518             *out += len;
519     }
520 
521     if (usetag)
522         return ASN1_object_size(ndef, len, tag);
523     return len;
524 }
525 
526 /* Produce content octets from a structure */
527 
asn1_ex_i2c(const ASN1_VALUE ** pval,unsigned char * cout,int * putype,const ASN1_ITEM * it)528 static int asn1_ex_i2c(const ASN1_VALUE **pval, unsigned char *cout, int *putype,
529                        const ASN1_ITEM *it)
530 {
531     ASN1_BOOLEAN *tbool = NULL;
532     ASN1_STRING *strtmp;
533     ASN1_OBJECT *otmp;
534     int utype;
535     const unsigned char *cont;
536     unsigned char c;
537     int len;
538     const ASN1_PRIMITIVE_FUNCS *pf;
539     pf = it->funcs;
540     if (pf && pf->prim_i2c)
541         return pf->prim_i2c(pval, cout, putype, it);
542 
543     /* Should type be omitted? */
544     if ((it->itype != ASN1_ITYPE_PRIMITIVE)
545         || (it->utype != V_ASN1_BOOLEAN)) {
546         if (*pval == NULL)
547             return -1;
548     }
549 
550     if (it->itype == ASN1_ITYPE_MSTRING) {
551         /* If MSTRING type set the underlying type */
552         strtmp = (ASN1_STRING *)*pval;
553         utype = strtmp->type;
554         *putype = utype;
555     } else if (it->utype == V_ASN1_ANY) {
556         /* If ANY set type and pointer to value */
557         ASN1_TYPE *typ;
558         typ = (ASN1_TYPE *)*pval;
559         utype = typ->type;
560         *putype = utype;
561         pval = (const ASN1_VALUE **)&typ->value.asn1_value; /* actually is const */
562     } else
563         utype = *putype;
564 
565     switch (utype) {
566     case V_ASN1_OBJECT:
567         otmp = (ASN1_OBJECT *)*pval;
568         cont = otmp->data;
569         len = otmp->length;
570         if (cont == NULL || len == 0)
571             return -1;
572         break;
573 
574     case V_ASN1_NULL:
575         cont = NULL;
576         len = 0;
577         break;
578 
579     case V_ASN1_BOOLEAN:
580         tbool = (ASN1_BOOLEAN *)pval;
581         if (*tbool == -1)
582             return -1;
583         if (it->utype != V_ASN1_ANY) {
584             /*
585              * Default handling if value == size field then omit
586              */
587             if (*tbool && (it->size > 0))
588                 return -1;
589             if (!*tbool && !it->size)
590                 return -1;
591         }
592         c = (unsigned char)*tbool;
593         cont = &c;
594         len = 1;
595         break;
596 
597     case V_ASN1_BIT_STRING:
598         return ossl_i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
599                                         cout ? &cout : NULL);
600 
601     case V_ASN1_INTEGER:
602     case V_ASN1_ENUMERATED:
603         /*
604          * These are all have the same content format as ASN1_INTEGER
605          */
606         return ossl_i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
607 
608     case V_ASN1_OCTET_STRING:
609     case V_ASN1_NUMERICSTRING:
610     case V_ASN1_PRINTABLESTRING:
611     case V_ASN1_T61STRING:
612     case V_ASN1_VIDEOTEXSTRING:
613     case V_ASN1_IA5STRING:
614     case V_ASN1_UTCTIME:
615     case V_ASN1_GENERALIZEDTIME:
616     case V_ASN1_GRAPHICSTRING:
617     case V_ASN1_VISIBLESTRING:
618     case V_ASN1_GENERALSTRING:
619     case V_ASN1_UNIVERSALSTRING:
620     case V_ASN1_BMPSTRING:
621     case V_ASN1_UTF8STRING:
622     case V_ASN1_SEQUENCE:
623     case V_ASN1_SET:
624     default:
625         /* All based on ASN1_STRING and handled the same */
626         strtmp = (ASN1_STRING *)*pval;
627         /* Special handling for NDEF */
628         if ((it->size == ASN1_TFLG_NDEF)
629             && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
630             if (cout) {
631                 strtmp->data = cout;
632                 strtmp->length = 0;
633             }
634             /* Special return code */
635             return -2;
636         }
637         cont = strtmp->data;
638         len = strtmp->length;
639 
640         break;
641 
642     }
643     if (cout && len)
644         memcpy(cout, cont, len);
645     return len;
646 }
647