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