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