Home | History | Annotate | Download | only in asn1
      1 /* tasn_enc.c */
      2 /* Written by Dr Stephen N Henson (steve (at) 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 (at) 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 (at) cryptsoft.com).  This product includes software written by Tim
     55  * Hudson (tjh (at) 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, NULL))
    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, NULL))
    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, NULL))
    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, NULL))
    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 	const unsigned char *cont;
    573 	unsigned char c;
    574 	int len;
    575 	const ASN1_PRIMITIVE_FUNCS *pf;
    576 	pf = it->funcs;
    577 	if (pf && pf->prim_i2c)
    578 		return pf->prim_i2c(pval, cout, putype, it);
    579 
    580 	/* Should type be omitted? */
    581 	if ((it->itype != ASN1_ITYPE_PRIMITIVE)
    582 		|| (it->utype != V_ASN1_BOOLEAN))
    583 		{
    584 		if (!*pval) return -1;
    585 		}
    586 
    587 	if (it->itype == ASN1_ITYPE_MSTRING)
    588 		{
    589 		/* If MSTRING type set the underlying type */
    590 		strtmp = (ASN1_STRING *)*pval;
    591 		utype = strtmp->type;
    592 		*putype = utype;
    593 		}
    594 	else if (it->utype == V_ASN1_ANY)
    595 		{
    596 		/* If ANY set type and pointer to value */
    597 		ASN1_TYPE *typ;
    598 		typ = (ASN1_TYPE *)*pval;
    599 		utype = typ->type;
    600 		*putype = utype;
    601 		pval = &typ->value.asn1_value;
    602 		}
    603 	else utype = *putype;
    604 
    605 	switch(utype)
    606 		{
    607 		case V_ASN1_OBJECT:
    608 		otmp = (ASN1_OBJECT *)*pval;
    609 		cont = otmp->data;
    610 		len = otmp->length;
    611 		break;
    612 
    613 		case V_ASN1_NULL:
    614 		cont = NULL;
    615 		len = 0;
    616 		break;
    617 
    618 		case V_ASN1_BOOLEAN:
    619 		tbool = (ASN1_BOOLEAN *)pval;
    620 		if (*tbool == -1)
    621 			return -1;
    622 		if (it->utype != V_ASN1_ANY)
    623 			{
    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_NEG_INTEGER:
    642 		case V_ASN1_ENUMERATED:
    643 		case V_ASN1_NEG_ENUMERATED:
    644 		/* These are all have the same content format
    645 		 * as ASN1_INTEGER
    646 		 */
    647 		return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval,
    648 							cout ? &cout : NULL);
    649 		break;
    650 
    651 		case V_ASN1_OCTET_STRING:
    652 		case V_ASN1_NUMERICSTRING:
    653 		case V_ASN1_PRINTABLESTRING:
    654 		case V_ASN1_T61STRING:
    655 		case V_ASN1_VIDEOTEXSTRING:
    656 		case V_ASN1_IA5STRING:
    657 		case V_ASN1_UTCTIME:
    658 		case V_ASN1_GENERALIZEDTIME:
    659 		case V_ASN1_GRAPHICSTRING:
    660 		case V_ASN1_VISIBLESTRING:
    661 		case V_ASN1_GENERALSTRING:
    662 		case V_ASN1_UNIVERSALSTRING:
    663 		case V_ASN1_BMPSTRING:
    664 		case V_ASN1_UTF8STRING:
    665 		case V_ASN1_SEQUENCE:
    666 		case V_ASN1_SET:
    667 		default:
    668 		/* All based on ASN1_STRING and handled the same */
    669 		strtmp = (ASN1_STRING *)*pval;
    670 		/* Special handling for NDEF */
    671 		if ((it->size == ASN1_TFLG_NDEF)
    672 			&& (strtmp->flags & ASN1_STRING_FLAG_NDEF))
    673 			{
    674 			if (cout)
    675 				{
    676 				strtmp->data = cout;
    677 				strtmp->length = 0;
    678 				}
    679 			/* Special return code */
    680 			return -2;
    681 			}
    682 		cont = strtmp->data;
    683 		len = strtmp->length;
    684 
    685 		break;
    686 
    687 		}
    688 	if (cout && len)
    689 		memcpy(cout, cont, len);
    690 	return len;
    691 	}
    692