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