195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * All rights reserved.
395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This package is an SSL implementation written
595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * by Eric Young (eay@cryptsoft.com).
695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The implementation was written so as to conform with Netscapes SSL.
795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This library is free for commercial and non-commercial use as long as
995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the following conditions are aheared to.  The following conditions
1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * apply to all code found in this distribution, be it the RC4, RSA,
1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * included with this distribution is covered by the same copyright terms
1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright remains Eric Young's, and as such any Copyright notices in
1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the code are not to be removed.
1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * If this package is used in a product, Eric Young should be given attribution
1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * as the author of the parts of the library used.
1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This can be in the form of a textual message at program startup or
2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * in documentation (online or textual) provided with the package.
2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without
2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions
2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met:
2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the copyright
2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer.
2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright
2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer in the
2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    documentation and/or other materials provided with the distribution.
3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this software
3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    must display the following acknowledgement:
3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes cryptographic software written by
3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *     Eric Young (eay@cryptsoft.com)"
3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    The word 'cryptographic' can be left out if the rouines from the library
3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    being used are not cryptographic related :-).
3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. If you include any Windows specific code (or a derivative thereof) from
3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    the apps directory (application code) you must include an acknowledgement:
3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SUCH DAMAGE.
5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The licence and distribution terms for any publically available version or
5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * derivative of this code cannot be changed.  i.e. this code cannot simply be
5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * copied and put under another distribution licence
5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * [including the GNU Public Licence.] */
5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/asn1.h>
5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/asn1t.h>
6095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/mem.h>
6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					const ASN1_ITEM *it,
6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					int tag, int aclass);
6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					int skcontlen, const ASN1_ITEM *item,
6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					int do_sort, int iclass);
6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					const ASN1_TEMPLATE *tt,
7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					int tag, int aclass);
7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					const ASN1_ITEM *it, int flags);
7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Top level i2d equivalents: the 'ndef' variant instructs the encoder
7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * to use indefinite length constructed encoding, where appropriate
7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						const ASN1_ITEM *it)
8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return asn1_item_flags_i2d(val, out, it, 0);
8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Encode an ASN1 item, this is use by the
9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * standard 'i2d' function. 'out' points to
9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * a buffer to output the data to.
9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The new i2d has one additional feature. If the output
9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * buffer is NULL (i.e. *out == NULL) then a buffer is
9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * allocated and populated with the encoding.
9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					const ASN1_ITEM *it, int flags)
10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (out && !*out)
10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		unsigned char *p, *buf;
10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		int len;
10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (len <= 0)
10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return len;
10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		buf = OPENSSL_malloc(len);
11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!buf)
11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -1;
11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		p = buf;
11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ASN1_item_ex_i2d(&val, &p, it, -1, flags);
11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*out = buf;
11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return len;
11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return ASN1_item_ex_i2d(&val, out, it, -1, flags);
11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Encode an item, taking care of IMPLICIT tagging (if any).
12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This function performs the normal item handling: it can be
12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * used in external types.
12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			const ASN1_ITEM *it, int tag, int aclass)
12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const ASN1_TEMPLATE *tt = NULL;
13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char *p = NULL;
13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i, seqcontlen, seqlen, ndef = 1;
13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const ASN1_COMPAT_FUNCS *cf;
13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const ASN1_EXTERN_FUNCS *ef;
13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const ASN1_AUX *aux = it->funcs;
13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_aux_cb *asn1_cb = 0;
13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (aux && aux->asn1_cb)
14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 asn1_cb = aux->asn1_cb;
14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	switch(it->itype)
14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_PRIMITIVE:
14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (it->templates)
14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return asn1_template_ex_i2d(pval, out, it->templates,
14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley								tag, aclass);
15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_MSTRING:
15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_CHOICE:
15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		i = asn1_get_choice_selector(pval, it);
16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ((i >= 0) && (i < it->tcount))
16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_VALUE **pchval;
16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			const ASN1_TEMPLATE *chtt;
16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			chtt = it->templates + i;
16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			pchval = asn1_get_field_ptr(pval, chtt);
16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return asn1_template_ex_i2d(pchval, out, chtt,
16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley								-1, aclass);
16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Fixme: error condition if selector out of range */
17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_EXTERN:
17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If new style i2d it does all the work */
17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ef = it->funcs;
17795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
17895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_COMPAT:
18095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* old style hackery... */
18195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cf = it->funcs;
18295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (out)
18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			p = *out;
18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		i = cf->asn1_i2d(*pval, out);
18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Fixup for IMPLICIT tag: note this messes up for tags > 30,
18695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * but so did the old code. Tags > 30 are very rare anyway.
18795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (out && (tag != -1))
18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
19095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return i;
19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_NDEF_SEQUENCE:
19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Use indefinite length constructed if requested */
19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (aclass & ASN1_TFLG_NDEF) ndef = 2;
19595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* fall through */
19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_SEQUENCE:
19895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		i = asn1_enc_restore(&seqcontlen, out, pval, it);
19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* An error occurred */
20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (i < 0)
20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* We have a valid cached encoding... */
20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (i > 0)
20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return seqcontlen;
20595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Otherwise carry on */
20695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		seqcontlen = 0;
20795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
20895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (tag == -1)
20995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
21095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			tag = V_ASN1_SEQUENCE;
21195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Retain any other flags in aclass */
21295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
21395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					| V_ASN1_UNIVERSAL;
21495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
21595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
21695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
21795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* First work out sequence content length */
21895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
21995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
22095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			const ASN1_TEMPLATE *seqtt;
22195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_VALUE **pseqval;
22295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			seqtt = asn1_do_adb(pval, tt, 1);
22395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!seqtt)
22495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
22595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			pseqval = asn1_get_field_ptr(pval, seqtt);
22695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* FIXME: check for errors in enhanced version */
22795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
22895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley								-1, aclass);
22995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
23095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		seqlen = ASN1_object_size(ndef, seqcontlen, tag);
23295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!out)
23395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return seqlen;
23495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Output SEQUENCE header */
23595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
23695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
23795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
23895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			const ASN1_TEMPLATE *seqtt;
23995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_VALUE **pseqval;
24095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			seqtt = asn1_do_adb(pval, tt, 1);
24195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!seqtt)
24295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
24395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			pseqval = asn1_get_field_ptr(pval, seqtt);
24495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* FIXME: check for errors in enhanced version */
24595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
24695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
24795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (ndef == 2)
24895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_put_eoc(out);
24995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
25095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
25195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return seqlen;
25295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		default:
25495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
25595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
25795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 0;
25895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
25995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
26195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley							const ASN1_TEMPLATE *tt)
26295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
26395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return asn1_template_ex_i2d(pval, out, tt, -1, 0);
26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
26795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const ASN1_TEMPLATE *tt, int tag, int iclass)
26895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
26995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i, ret, flags, ttag, tclass, ndef;
27095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	size_t j;
27195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	flags = tt->flags;
27295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Work out tag and class to use: tagging may come
27395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * either from the template or the arguments, not both
27495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * because this would create ambiguity. Additionally
27595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * the iclass argument may contain some additional flags
27695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * which should be noted and passed down to other levels.
27795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (flags & ASN1_TFLG_TAG_MASK)
27995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
28095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Error if argument and template tagging */
28195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (tag != -1)
28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* FIXME: error code here */
28395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -1;
28495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Get tagging from template */
28595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ttag = tt->tag;
28695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		tclass = flags & ASN1_TFLG_TAG_CLASS;
28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
28895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else if (tag != -1)
28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* No template tagging, get from arguments */
29195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ttag = tag;
29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		tclass = iclass & ASN1_TFLG_TAG_CLASS;
29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
29695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ttag = -1;
29795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		tclass = 0;
29895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
29995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/*
30095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * Remove any class mask from iflag.
30195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
30295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	iclass &= ~ASN1_TFLG_TAG_CLASS;
30395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* At this point 'ttag' contains the outer tag to use,
30595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * 'tclass' is the class and iclass is any flags passed
30695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * to this function.
30795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
30895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* if template and arguments require ndef, use it */
31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ndef = 2;
31295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else ndef = 1;
31395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
31495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (flags & ASN1_TFLG_SK_MASK)
31595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
31695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* SET OF, SEQUENCE OF */
31795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
31895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		int isset, sktag, skaclass;
31995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		int skcontlen, sklen;
32095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ASN1_VALUE *skitem;
32195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
32295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!*pval)
32395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
32495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
32595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (flags & ASN1_TFLG_SET_OF)
32695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
32795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			isset = 1;
32895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* 2 means we reorder */
32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (flags & ASN1_TFLG_SEQUENCE_OF)
33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				isset = 2;
33195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else isset = 0;
33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
33495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Work out inner tag value: if EXPLICIT
33595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * or no tagging use underlying type.
33695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
33795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG))
33895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
33995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			sktag = ttag;
34095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			skaclass = tclass;
34195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
34295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
34395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
34495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			skaclass = V_ASN1_UNIVERSAL;
34595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (isset)
34695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				sktag = V_ASN1_SET;
34795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			else sktag = V_ASN1_SEQUENCE;
34895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
34995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
35095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Determine total length of items */
35195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		skcontlen = 0;
35295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (j = 0; j < sk_ASN1_VALUE_num(sk); j++)
35395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
35495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			skitem = sk_ASN1_VALUE_value(sk, j);
35595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
35695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						ASN1_ITEM_ptr(tt->item),
35795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley							-1, iclass);
35895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
35995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		sklen = ASN1_object_size(ndef, skcontlen, sktag);
36095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If EXPLICIT need length of surrounding tag */
36195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (flags & ASN1_TFLG_EXPTAG)
36295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ret = ASN1_object_size(ndef, sklen, ttag);
36395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else ret = sklen;
36495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
36595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!out)
36695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return ret;
36795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
36895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Now encode this lot... */
36995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* EXPLICIT tag */
37095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (flags & ASN1_TFLG_EXPTAG)
37195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_put_object(out, ndef, sklen, ttag, tclass);
37295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* SET or SEQUENCE and IMPLICIT tag */
37395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
37495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* And the stuff itself */
37595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
37695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley								isset, iclass);
37795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (ndef == 2)
37895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
37995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_put_eoc(out);
38095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (flags & ASN1_TFLG_EXPTAG)
38195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_put_eoc(out);
38295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
38395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
38495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return ret;
38595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
38695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
38795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (flags & ASN1_TFLG_EXPTAG)
38895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
38995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* EXPLICIT tagging */
39095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Find length of tagged item */
39195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item),
39295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley								-1, iclass);
39395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!i)
39495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
39595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Find length of EXPLICIT tag */
39695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret = ASN1_object_size(ndef, i, ttag);
39795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (out)
39895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
39995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Output tag and item */
40095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_put_object(out, ndef, i, ttag, tclass);
40195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
40295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley								-1, iclass);
40395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (ndef == 2)
40495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_put_eoc(out);
40595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
40695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return ret;
40795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
40895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
40995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Either normal or IMPLICIT tagging: combine class and flags */
41095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
41195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						ttag, tclass | iclass);
41295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
41395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
41495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
41595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Temporary structure used to hold DER encoding of items for SET OF */
41695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
41795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleytypedef	struct {
41895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char *data;
41995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int length;
42095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_VALUE *field;
42195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} DER_ENC;
42295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
42395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int der_cmp(const void *a, const void *b)
42495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
42595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const DER_ENC *d1 = a, *d2 = b;
42695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int cmplen, i;
42795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	cmplen = (d1->length < d2->length) ? d1->length : d2->length;
42895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	i = memcmp(d1->data, d2->data, cmplen);
42995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (i)
43095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return i;
43195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return d1->length - d2->length;
43295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
43395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
43495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Output the content octets of SET OF or SEQUENCE OF */
43595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
43695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
43795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					int skcontlen, const ASN1_ITEM *item,
43895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					int do_sort, int iclass)
43995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
44095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	size_t i;
44195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_VALUE *skitem;
44295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char *tmpdat = NULL, *p = NULL;
44395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	DER_ENC *derlst = NULL, *tder;
44495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (do_sort)
44595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 {
44695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Don't need to sort less than 2 items */
44795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (sk_ASN1_VALUE_num(sk) < 2)
44895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			do_sort = 0;
44995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
45095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
45195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
45295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						* sizeof(*derlst));
4537893c008e673bd157b698ac5ebd6e43ce8cce409Adam Langley			if (!derlst)
4547893c008e673bd157b698ac5ebd6e43ce8cce409Adam Langley				return 0;
45595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			tmpdat = OPENSSL_malloc(skcontlen);
4567893c008e673bd157b698ac5ebd6e43ce8cce409Adam Langley			if (!tmpdat)
4577893c008e673bd157b698ac5ebd6e43ce8cce409Adam Langley				{
4587893c008e673bd157b698ac5ebd6e43ce8cce409Adam Langley				OPENSSL_free(derlst);
45995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
4607893c008e673bd157b698ac5ebd6e43ce8cce409Adam Langley				}
46195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
46295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
46395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If not sorting just output each item */
46495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!do_sort)
46595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
46695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
46795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
46895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			skitem = sk_ASN1_VALUE_value(sk, i);
46995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
47095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
47195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
47295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
47395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	p = tmpdat;
47495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
47595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Doing sort: build up a list of each member's DER encoding */
47695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
47795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
47895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		skitem = sk_ASN1_VALUE_value(sk, i);
47995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		tder->data = p;
48095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
48195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		tder->field = skitem;
48295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
48395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
48495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Now sort them */
48595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
48695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Output sorted DER encoding */
48795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	p = *out;
48895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
48995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
49095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		memcpy(p, tder->data, tder->length);
49195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		p += tder->length;
49295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
49395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*out = p;
49495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If do_sort is 2 then reorder the STACK */
49595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (do_sort == 2)
49695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
49795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk);
49895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley							i++, tder++)
49995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			(void)sk_ASN1_VALUE_set(sk, i, tder->field);
50095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
50195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	OPENSSL_free(derlst);
50295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	OPENSSL_free(tmpdat);
50395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
50495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
50595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
50695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
50795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const ASN1_ITEM *it, int tag, int aclass)
50895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
50995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int len;
51095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int utype;
51195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int usetag;
51295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ndef = 0;
51395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
51495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	utype = it->utype;
51595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
51695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Get length of content octets and maybe find
51795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * out the underlying type.
51895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
51995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
52095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	len = asn1_ex_i2c(pval, NULL, &utype, it);
52195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
52295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If SEQUENCE, SET or OTHER then header is
52395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * included in pseudo content octets so don't
52495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * include tag+length. We need to check here
52595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * because the call to asn1_ex_i2c() could change
52695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * utype.
52795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
52895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
52995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	   (utype == V_ASN1_OTHER))
53095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		usetag = 0;
53195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else usetag = 1;
53295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
53395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* -1 means omit type */
53495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
53595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (len == -1)
53695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
53795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
53895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* -2 return is special meaning use ndef */
53995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (len == -2)
54095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
54195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ndef = 2;
54295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len = 0;
54395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
54495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
54595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If not implicitly tagged get tag from underlying type */
54695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (tag == -1) tag = utype;
54795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
54895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Output tag+length followed by content octets */
54995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (out)
55095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
55195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (usetag)
55295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_put_object(out, ndef, len, tag, aclass);
55395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		asn1_ex_i2c(pval, *out, &utype, it);
55495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (ndef)
55595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_put_eoc(out);
55695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
55795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*out += len;
55895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
55995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
56095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (usetag)
56195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return ASN1_object_size(ndef, len, tag);
56295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return len;
56395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
56495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
56595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Produce content octets from a structure */
56695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
56795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
56895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const ASN1_ITEM *it)
56995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
57095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_BOOLEAN *tbool = NULL;
57195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_STRING *strtmp;
57295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_OBJECT *otmp;
57395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int utype;
57495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const unsigned char *cont;
57595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char c;
57695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int len;
57795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const ASN1_PRIMITIVE_FUNCS *pf;
57895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	pf = it->funcs;
57995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (pf && pf->prim_i2c)
58095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return pf->prim_i2c(pval, cout, putype, it);
58195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
58295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Should type be omitted? */
58395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ((it->itype != ASN1_ITYPE_PRIMITIVE)
58495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		|| (it->utype != V_ASN1_BOOLEAN))
58595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
58695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!*pval) return -1;
58795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
58895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
58995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (it->itype == ASN1_ITYPE_MSTRING)
59095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
59195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If MSTRING type set the underlying type */
59295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		strtmp = (ASN1_STRING *)*pval;
59395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		utype = strtmp->type;
59495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*putype = utype;
59595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
59695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else if (it->utype == V_ASN1_ANY)
59795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
59895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If ANY set type and pointer to value */
59995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ASN1_TYPE *typ;
60095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		typ = (ASN1_TYPE *)*pval;
60195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		utype = typ->type;
60295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*putype = utype;
60395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		pval = &typ->value.asn1_value;
60495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
60595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else utype = *putype;
60695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
60795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	switch(utype)
60895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
60995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_OBJECT:
61095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		otmp = (ASN1_OBJECT *)*pval;
61195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cont = otmp->data;
61295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len = otmp->length;
61395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
61495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
61595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_NULL:
61695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cont = NULL;
61795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len = 0;
61895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
61995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
62095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_BOOLEAN:
62195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		tbool = (ASN1_BOOLEAN *)pval;
62295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (*tbool == -1)
62395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -1;
62495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (it->utype != V_ASN1_ANY)
62595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
62695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Default handling if value == size field then omit */
62795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (*tbool && (it->size > 0))
62895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return -1;
62995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!*tbool && !it->size)
63095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return -1;
63195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
63295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		c = (unsigned char)*tbool;
63395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cont = &c;
63495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len = 1;
63595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
63695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
63795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_BIT_STRING:
63895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
63995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley							cout ? &cout : NULL);
64095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
64195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
64295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_INTEGER:
64395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_NEG_INTEGER:
64495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_ENUMERATED:
64595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_NEG_ENUMERATED:
64695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* These are all have the same content format
64795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * as ASN1_INTEGER
64895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
64995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval,
65095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley							cout ? &cout : NULL);
65195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
65295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
65395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_OCTET_STRING:
65495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_NUMERICSTRING:
65595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_PRINTABLESTRING:
65695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_T61STRING:
65795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_VIDEOTEXSTRING:
65895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_IA5STRING:
65995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_UTCTIME:
66095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_GENERALIZEDTIME:
66195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_GRAPHICSTRING:
66295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_VISIBLESTRING:
66395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_GENERALSTRING:
66495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_UNIVERSALSTRING:
66595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_BMPSTRING:
66695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_UTF8STRING:
66795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_SEQUENCE:
66895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_SET:
66995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		default:
67095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* All based on ASN1_STRING and handled the same */
67195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		strtmp = (ASN1_STRING *)*pval;
67295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Special handling for NDEF */
67395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ((it->size == ASN1_TFLG_NDEF)
67495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			&& (strtmp->flags & ASN1_STRING_FLAG_NDEF))
67595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
67695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (cout)
67795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
67895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				strtmp->data = cout;
67995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				strtmp->length = 0;
68095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
68195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Special return code */
68295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -2;
68395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
68495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cont = strtmp->data;
68595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len = strtmp->length;
68695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
68795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
68895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
68995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
69095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (cout && len)
69195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		memcpy(cout, cont, len);
69295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return len;
69395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
694