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/buf.h>
6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/err.h>
6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/mem.h>
6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_check_eoc(const unsigned char **in, long len);
6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_find_end(const unsigned char **in, long len, char inf);
6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			char inf, int tag, int aclass, int depth);
7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int collect_data(BUF_MEM *buf, const unsigned char **p, long plen);
7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				char *inf, char *cst,
7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const unsigned char **in, long len,
7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				int exptag, int expclass, char opt,
7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_TLC *ctx);
7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_template_ex_d2i(ASN1_VALUE **pval,
8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const unsigned char **in, long len,
8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const ASN1_TEMPLATE *tt, char opt,
8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_TLC *ctx);
8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_template_noexp_d2i(ASN1_VALUE **val,
8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const unsigned char **in, long len,
8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const ASN1_TEMPLATE *tt, char opt,
8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_TLC *ctx);
8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const unsigned char **in, long len,
8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const ASN1_ITEM *it,
9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				int tag, int aclass, char opt, ASN1_TLC *ctx);
9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Table to convert tags to bit values, used for MSTRING type */
9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic const unsigned long tag2bit[32] = {
9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley0,	0,	0,	B_ASN1_BIT_STRING,	/* tags  0 -  3 */
9595c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyB_ASN1_OCTET_STRING,	0,	0,		B_ASN1_UNKNOWN,/* tags  4- 7 */
9695c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyB_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,/* tags  8-11 */
9795c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyB_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */
9895c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyB_ASN1_SEQUENCE,0,B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */
9995c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyB_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING,       /* tags 20-22 */
10095c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyB_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME,			       /* tags 23-24 */
10195c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyB_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING,  /* tags 25-27 */
10295c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyB_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */
10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	};
10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyunsigned long ASN1_tag2bit(int tag)
10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ((tag < 0) || (tag > 30)) return 0;
10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return tag2bit[tag];
10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Macro to initialize and invalidate the cache */
11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define asn1_tlc_clear(c)	if (c) (c)->valid = 0
11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Version to avoid compiler warning about 'c' always non-NULL */
11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define asn1_tlc_clear_nc(c)	(c)->valid = 0
11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Decode an ASN1 item, this currently behaves just
11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * like a standard 'd2i' function. 'in' points to
11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * a buffer to read the data from, in future we will
12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * have more advanced versions that can input data
12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * a piece at a time and this will simply be a special
12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * case.
12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12595c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		const unsigned char **in, long len, const ASN1_ITEM *it)
12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_TLC c;
12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_VALUE *ptmpval = NULL;
13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!pval)
13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		pval = &ptmpval;
13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	asn1_tlc_clear_nc(&c);
13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0)
13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return *pval;
13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return NULL;
13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint ASN1_template_d2i(ASN1_VALUE **pval,
13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		const unsigned char **in, long len, const ASN1_TEMPLATE *tt)
14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_TLC c;
14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	asn1_tlc_clear_nc(&c);
14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return asn1_template_ex_d2i(pval, in, len, tt, 0, &c);
14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Decode an item, taking care of IMPLICIT tagging, if any.
14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * If 'opt' set and tag mismatch return -1 to handle OPTIONAL
14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			const ASN1_ITEM *it,
15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			int tag, int aclass, char opt, ASN1_TLC *ctx)
15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const ASN1_TEMPLATE *tt, *errtt = NULL;
15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const ASN1_COMPAT_FUNCS *cf;
15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const ASN1_EXTERN_FUNCS *ef;
15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const ASN1_AUX *aux = it->funcs;
15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_aux_cb *asn1_cb;
16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const unsigned char *p = NULL, *q;
16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char *wp=NULL;	/* BIG FAT WARNING!  BREAKS CONST WHERE USED */
16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	unsigned char imphack = 0, oclass;
16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	char seq_eoc, seq_nolen, cst, isopt;
16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	long tmplen;
16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i;
16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int otag;
16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ret = 0;
16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_VALUE **pchptr, *ptmpval;
16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!pval)
17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (aux && aux->asn1_cb)
17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		asn1_cb = aux->asn1_cb;
17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else asn1_cb = 0;
17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	switch(it->itype)
17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
17795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_PRIMITIVE:
17895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (it->templates)
17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
18095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* tagging or OPTIONAL is currently illegal on an item
18195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * template because the flags can't get passed down.
18295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * In practice this isn't a problem: we include the
18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * relevant flags from the item template in the
18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * template itself.
18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 */
18695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if ((tag != -1) || opt)
18795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
19095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return asn1_template_ex_d2i(pval, in, len,
19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					it->templates, opt, ctx);
19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return asn1_d2i_ex_primitive(pval, in, len, it,
19595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						tag, aclass, opt, ctx);
19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
19895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_MSTRING:
19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		p = *in;
20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Just read in tag and class */
20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						&p, len, -1, 0, 1, ctx);
20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!ret)
20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
20595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_NESTED_ASN1_ERROR);
20695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
20795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
20895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
20995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Must be UNIVERSAL class */
21095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (oclass != V_ASN1_UNIVERSAL)
21195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
21295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* If OPTIONAL, assume this is OK */
21395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (opt) return -1;
21495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_MSTRING_NOT_UNIVERSAL);
21595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
21695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
21795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Check tag matches bit map */
21895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!(ASN1_tag2bit(otag) & it->utype))
21995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
22095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* If OPTIONAL, assume this is OK */
22195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (opt)
22295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return -1;
22395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_MSTRING_WRONG_TAG);
22495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
22595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
22695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return asn1_d2i_ex_primitive(pval, in, len,
22795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						it, otag, 0, 0, ctx);
22895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
22995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_EXTERN:
23095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Use new style d2i */
23195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ef = it->funcs;
23295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return ef->asn1_ex_d2i(pval, in, len,
23395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						it, tag, aclass, opt, ctx);
23495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_COMPAT:
23695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* we must resort to old style evil hackery */
23795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cf = it->funcs;
23895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If OPTIONAL see if it is there */
24095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (opt)
24195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
24295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			int exptag;
24395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			p = *in;
24495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (tag == -1)
24595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				exptag = it->utype;
24695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			else exptag = tag;
24795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Don't care about anything other than presence
24895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * of expected tag */
24995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL,
25195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					&p, len, exptag, aclass, 1, ctx);
25295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!ret)
25395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
25495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_NESTED_ASN1_ERROR);
25595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
25695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
25795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (ret == -1)
25895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return -1;
25995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
26095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* This is the old style evil hack IMPLICIT handling:
26295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * since the underlying code is expecting a tag and
26395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * class other than the one present we change the
26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * buffer temporarily then change it back afterwards.
26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * This doesn't and never did work for tags > 30.
26695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 *
26795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * Yes this is *horrible* but it is only needed for
26895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * old style d2i which will hopefully not be around
26995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * for much longer.
27095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * FIXME: should copy the buffer then modify it so
27195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * the input buffer can be const: we should *always*
27295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * copy because the old style d2i might modify the
27395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * buffer.
27495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
27595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
27695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (tag != -1)
27795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			wp = *(unsigned char **)in;
27995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			imphack = *wp;
28095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (p == NULL)
28195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_NESTED_ASN1_ERROR);
28395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
28495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
28595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED)
28695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley								| it->utype);
28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
28895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ptmpval = cf->asn1_d2i(pval, in, len);
29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
29195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (tag != -1)
29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*wp = imphack;
29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (ptmpval)
29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 1;
29695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
29795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_NESTED_ASN1_ERROR);
29895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto err;
29995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_CHOICE:
30295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
30395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto auxerr;
30495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Allocate structure */
30695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!*pval && !ASN1_item_ex_new(pval, it))
30795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
30895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_NESTED_ASN1_ERROR);
30995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* CHOICE type, try each possibility in turn */
31295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		p = *in;
31395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (i = 0, tt=it->templates; i < it->tcount; i++, tt++)
31495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
31595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			pchptr = asn1_get_field_ptr(pval, tt);
31695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* We mark field as OPTIONAL so its absence
31795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * can be recognised.
31895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 */
31995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx);
32095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* If field not present, try the next one */
32195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (ret == -1)
32295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				continue;
32395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* If positive return, read OK, break loop */
32495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (ret > 0)
32595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				break;
32695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Otherwise must be an ASN1 parsing error */
32795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			errtt = tt;
32895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_NESTED_ASN1_ERROR);
32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
33195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Did we fall off the end without reading anything? */
33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (i == it->tcount)
33495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
33595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* If OPTIONAL, this is OK */
33695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (opt)
33795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
33895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				/* Free and zero it */
33995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_item_ex_free(pval, it);
34095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return -1;
34195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
34295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_NO_MATCHING_CHOICE_TYPE);
34395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
34495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
34595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
34695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		asn1_set_choice_selector(pval, i, it);
34795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*in = p;
34895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
34995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto auxerr;
35095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
35195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
35295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_NDEF_SEQUENCE:
35395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case ASN1_ITYPE_SEQUENCE:
35495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		p = *in;
35595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		tmplen = len;
35695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
35795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
35895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (tag == -1)
35995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
36095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			tag = V_ASN1_SEQUENCE;
36195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			aclass = V_ASN1_UNIVERSAL;
36295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
36395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Get SEQUENCE length and update len, p */
36495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst,
36595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					&p, len, tag, aclass, opt, ctx);
36695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!ret)
36795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
36895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_NESTED_ASN1_ERROR);
36995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
37095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
37195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else if (ret == -1)
37295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -1;
37395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (aux && (aux->flags & ASN1_AFLG_BROKEN))
37495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
37595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			len = tmplen - (p - *in);
37695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			seq_nolen = 1;
37795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
37895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If indefinite we don't do a length check */
37995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else seq_nolen = seq_eoc;
38095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!cst)
38195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
38295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
38395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
38495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
38595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
38695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!*pval && !ASN1_item_ex_new(pval, it))
38795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
38895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_NESTED_ASN1_ERROR);
38995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
39095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
39195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
39295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
39395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto auxerr;
39495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
39595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Get each field entry */
39695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)
39795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
39895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			const ASN1_TEMPLATE *seqtt;
39995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_VALUE **pseqval;
40095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			seqtt = asn1_do_adb(pval, tt, 1);
40195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!seqtt)
40295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
40395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			pseqval = asn1_get_field_ptr(pval, seqtt);
40495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Have we ran out of data? */
40595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!len)
40695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				break;
40795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			q = p;
40895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (asn1_check_eoc(&p, len))
40995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
41095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				if (!seq_eoc)
41195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					{
41295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_UNEXPECTED_EOC);
41395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					goto err;
41495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					}
41595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				len -= p - q;
41695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				seq_eoc = 0;
41795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				q = p;
41895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				break;
41995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
42095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* This determines the OPTIONAL flag value. The field
42195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * cannot be omitted if it is the last of a SEQUENCE
42295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * and there is still data to be read. This isn't
42395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * strictly necessary but it increases efficiency in
42495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * some cases.
42595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 */
42695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (i == (it->tcount - 1))
42795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				isopt = 0;
42895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			else isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL);
42995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* attempt to read in field, allowing each to be
43095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * OPTIONAL */
43195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
43295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ret = asn1_template_ex_d2i(pseqval, &p, len,
43395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley							seqtt, isopt, ctx);
43495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!ret)
43595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
43695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				errtt = seqtt;
43795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
43895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
43995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			else if (ret == -1)
44095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
44195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				/* OPTIONAL component absent.
44295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				 * Free and zero the field.
44395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				 */
44495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_template_free(pseqval, seqtt);
44595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				continue;
44695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
44795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Update length */
44895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			len -= p - q;
44995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
45095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
45195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Check for EOC if expecting one */
45295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (seq_eoc && !asn1_check_eoc(&p, len))
45395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
45495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_MISSING_EOC);
45595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
45695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
45795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Check all data read */
45895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!seq_nolen && len)
45995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
46095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_SEQUENCE_LENGTH_MISMATCH);
46195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
46295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
46395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
46495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If we get here we've got no more data in the SEQUENCE,
46595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * however we may not have read all fields so check all
46695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * remaining are OPTIONAL and clear any that are.
46795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
46895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		for (; i < it->tcount; tt++, i++)
46995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
47095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			const ASN1_TEMPLATE *seqtt;
47195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			seqtt = asn1_do_adb(pval, tt, 1);
47295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!seqtt)
47395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
47495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (seqtt->flags & ASN1_TFLG_OPTIONAL)
47595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
47695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_VALUE **pseqval;
47795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				pseqval = asn1_get_field_ptr(pval, seqtt);
47895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_template_free(pseqval, seqtt);
47995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
48095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			else
48195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
48295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				errtt = seqtt;
48395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_FIELD_MISSING);
48495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
48595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
48695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
48795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Save encoding */
48895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!asn1_enc_save(pval, *in, p - *in, it))
48995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto auxerr;
49095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*in = p;
49195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
49295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto auxerr;
49395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
49495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
49595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		default:
49695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
49795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
49895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	auxerr:
49995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	OPENSSL_PUT_ERROR(ASN1, ASN1_item_ex_d2i,  ASN1_R_AUX_ERROR);
50095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	err:
50195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_item_ex_free(pval, it);
50295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (errtt)
50395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ERR_add_error_data(4, "Field=", errtt->field_name,
50495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					", Type=", it->sname);
50595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
50695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ERR_add_error_data(2, "Type=", it->sname);
50795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 0;
50895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
50995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
51095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Templates are handled with two separate functions.
51195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * One handles any EXPLICIT tag and the other handles the rest.
51295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
51395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
51495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_template_ex_d2i(ASN1_VALUE **val,
51595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const unsigned char **in, long inlen,
51695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const ASN1_TEMPLATE *tt, char opt,
51795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley							ASN1_TLC *ctx)
51895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
51995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int flags, aclass;
52095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ret;
52195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	long len;
52295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const unsigned char *p, *q;
52395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	char exp_eoc;
52495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!val)
52595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
52695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	flags = tt->flags;
52795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	aclass = flags & ASN1_TFLG_TAG_CLASS;
52895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
52995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	p = *in;
53095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
53195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Check if EXPLICIT tag expected */
53295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (flags & ASN1_TFLG_EXPTAG)
53395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
53495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		char cst;
53595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Need to work out amount of data available to the inner
53695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * content and where it starts: so read in EXPLICIT header to
53795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * get the info.
53895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
53995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst,
54095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					&p, inlen, tt->tag, aclass, opt, ctx);
54195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		q = p;
54295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!ret)
54395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
54495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_template_ex_d2i,  ASN1_R_NESTED_ASN1_ERROR);
54595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
54695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
54795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else if (ret == -1)
54895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -1;
54995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!cst)
55095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
55195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_template_ex_d2i,  ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
55295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
55395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
55495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* We've found the field so it can't be OPTIONAL now */
55595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx);
55695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!ret)
55795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
55895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_template_ex_d2i,  ASN1_R_NESTED_ASN1_ERROR);
55995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
56095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
56195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* We read the field in OK so update length */
56295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len -= p - q;
56395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (exp_eoc)
56495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
56595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* If NDEF we must have an EOC here */
56695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!asn1_check_eoc(&p, len))
56795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
56895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, asn1_template_ex_d2i,  ASN1_R_MISSING_EOC);
56995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
57095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
57195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
57295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
57395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
57495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* Otherwise we must hit the EXPLICIT tag end or its
57595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * an error */
57695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (len)
57795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
57895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, asn1_template_ex_d2i,  ASN1_R_EXPLICIT_LENGTH_MISMATCH);
57995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
58095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
58195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
58295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
58395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
58495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return asn1_template_noexp_d2i(val, in, inlen,
58595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley								tt, opt, ctx);
58695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
58795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*in = p;
58895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
58995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
59095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	err:
59195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_template_free(val, tt);
59295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 0;
59395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
59495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
59595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_template_noexp_d2i(ASN1_VALUE **val,
59695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const unsigned char **in, long len,
59795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const ASN1_TEMPLATE *tt, char opt,
59895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_TLC *ctx)
59995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
60095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int flags, aclass;
60195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ret;
60295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const unsigned char *p, *q;
60395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!val)
60495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
60595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	flags = tt->flags;
60695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	aclass = flags & ASN1_TFLG_TAG_CLASS;
60795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
60895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	p = *in;
60995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	q = p;
61095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
61195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (flags & ASN1_TFLG_SK_MASK)
61295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
61395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* SET OF, SEQUENCE OF */
61495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		int sktag, skaclass;
61595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		char sk_eoc;
61695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* First work out expected inner tag value */
61795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (flags & ASN1_TFLG_IMPTAG)
61895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
61995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			sktag = tt->tag;
62095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			skaclass = aclass;
62195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
62295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
62395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
62495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			skaclass = V_ASN1_UNIVERSAL;
62595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (flags & ASN1_TFLG_SET_OF)
62695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				sktag = V_ASN1_SET;
62795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			else
62895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				sktag = V_ASN1_SEQUENCE;
62995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
63095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Get the tag */
63195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL,
63295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					&p, len, sktag, skaclass, opt, ctx);
63395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!ret)
63495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
63595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i,  ASN1_R_NESTED_ASN1_ERROR);
63695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
63795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
63895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else if (ret == -1)
63995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -1;
64095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!*val)
64195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*val = (ASN1_VALUE *)sk_new_null();
64295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
64395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
64495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* We've got a valid STACK: free up any items present */
64595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			STACK_OF(ASN1_VALUE) *sktmp
64695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			    = (STACK_OF(ASN1_VALUE) *)*val;
64795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_VALUE *vtmp;
64895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			while(sk_ASN1_VALUE_num(sktmp) > 0)
64995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
65095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				vtmp = sk_ASN1_VALUE_pop(sktmp);
65195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_item_ex_free(&vtmp,
65295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						ASN1_ITEM_ptr(tt->item));
65395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
65495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
65595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
65695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!*val)
65795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
65895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i,  ERR_R_MALLOC_FAILURE);
65995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
66095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
66195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
66295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Read as many items as we can */
66395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		while(len > 0)
66495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
66595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_VALUE *skfield;
66695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			q = p;
66795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* See if EOC found */
66895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (asn1_check_eoc(&p, len))
66995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
67095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				if (!sk_eoc)
67195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					{
67295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i,  ASN1_R_UNEXPECTED_EOC);
67395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					goto err;
67495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					}
67595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				len -= p - q;
67695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				sk_eoc = 0;
67795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				break;
67895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
67995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			skfield = NULL;
68095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!ASN1_item_ex_d2i(&skfield, &p, len,
68195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						ASN1_ITEM_ptr(tt->item),
68295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						-1, 0, 0, ctx))
68395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
68495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i,  ASN1_R_NESTED_ASN1_ERROR);
68595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
68695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
68795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			len -= p - q;
68895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val,
68995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						skfield))
69095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
69195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i,  ERR_R_MALLOC_FAILURE);
69295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
69395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
69495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
69595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (sk_eoc)
69695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
69795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i,  ASN1_R_MISSING_EOC);
69895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
69995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
70095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
70195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else if (flags & ASN1_TFLG_IMPTAG)
70295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
70395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* IMPLICIT tagging */
70495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret = ASN1_item_ex_d2i(val, &p, len,
70595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx);
70695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!ret)
70795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
70895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i,  ASN1_R_NESTED_ASN1_ERROR);
70995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
71095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
71195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else if (ret == -1)
71295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -1;
71395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
71495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
71595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
71695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Nothing special */
71795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
71895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley							-1, 0, opt, ctx);
71995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!ret)
72095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
72195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_template_noexp_d2i,  ASN1_R_NESTED_ASN1_ERROR);
72295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
72395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
72495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else if (ret == -1)
72595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return -1;
72695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
72795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
72895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*in = p;
72995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
73095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
73195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	err:
73295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_template_free(val, tt);
73395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 0;
73495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
73595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
73695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
73795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const unsigned char **in, long inlen,
73895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const ASN1_ITEM *it,
73995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				int tag, int aclass, char opt, ASN1_TLC *ctx)
74095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
74195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ret = 0, utype;
74295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	long plen;
74395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	char cst, inf, free_cont = 0;
74495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const unsigned char *p;
74595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	BUF_MEM buf;
74695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const unsigned char *cont = NULL;
74795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	long len;
74895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!pval)
74995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
75095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive,  ASN1_R_ILLEGAL_NULL);
75195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0; /* Should never happen */
75295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
75395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
75495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (it->itype == ASN1_ITYPE_MSTRING)
75595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
75695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		utype = tag;
75795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		tag = -1;
75895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
75995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
76095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		utype = it->utype;
76195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
76295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (utype == V_ASN1_ANY)
76395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
76495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If type is ANY need to figure out type from tag */
76595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		unsigned char oclass;
76695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (tag >= 0)
76795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
76895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive,  ASN1_R_ILLEGAL_TAGGED_ANY);
76995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
77095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
77195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (opt)
77295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
77395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive,  ASN1_R_ILLEGAL_OPTIONAL_ANY);
77495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
77595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
77695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		p = *in;
77795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL,
77895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					&p, inlen, -1, 0, 0, ctx);
77995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!ret)
78095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
78195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive,  ASN1_R_NESTED_ASN1_ERROR);
78295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
78395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
78495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (oclass != V_ASN1_UNIVERSAL)
78595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			utype = V_ASN1_OTHER;
78695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
78795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (tag == -1)
78895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
78995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		tag = utype;
79095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		aclass = V_ASN1_UNIVERSAL;
79195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
79295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	p = *in;
79395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Check header */
79495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst,
79595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				&p, inlen, tag, aclass, opt, ctx);
79695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!ret)
79795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
79895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive,  ASN1_R_NESTED_ASN1_ERROR);
79995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
80095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
80195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else if (ret == -1)
80295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return -1;
80395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        ret = 0;
80495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* SEQUENCE, SET and "OTHER" are left in encoded form */
80595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if ((utype == V_ASN1_SEQUENCE)
80695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		|| (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER))
80795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
80895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Clear context cache for type OTHER because the auto clear
80995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * when we have a exact match wont work
81095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
81195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (utype == V_ASN1_OTHER)
81295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
81395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			asn1_tlc_clear(ctx);
81495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
81595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* SEQUENCE and SET must be constructed */
81695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else if (!cst)
81795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
81895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive,  ASN1_R_TYPE_NOT_CONSTRUCTED);
81995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
82095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
82195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
82295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cont = *in;
82395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If indefinite length constructed find the real end */
82495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (inf)
82595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
82695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!asn1_find_end(&p, plen, inf))
82795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				 goto err;
82895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			len = p - cont;
82995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
83095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
83195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
83295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			len = p - cont + plen;
83395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			p += plen;
83495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			buf.data = NULL;
83595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
83695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
83795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else if (cst)
83895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
83995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		buf.length = 0;
84095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		buf.max = 0;
84195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		buf.data = NULL;
84295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Should really check the internal tags are correct but
84395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * some things may get this wrong. The relevant specs
84495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * say that constructed string types should be OCTET STRINGs
84595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * internally irrespective of the type. So instead just check
84695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * for UNIVERSAL class and ignore the tag.
84795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 */
84895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0))
84995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
85095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			free_cont = 1;
85195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
85295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
85395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len = buf.length;
85495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Append a final null to string */
85595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!BUF_MEM_grow_clean(&buf, len + 1))
85695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
85795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_d2i_ex_primitive,  ERR_R_MALLOC_FAILURE);
85895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
85995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
86095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		buf.data[len] = 0;
86195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cont = (const unsigned char *)buf.data;
86295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		free_cont = 1;
86395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
86495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
86595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
86695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		cont = p;
86795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len = plen;
86895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		p += plen;
86995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
87095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
87195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* We now have content length and type: translate into a structure */
87295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it))
87395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		goto err;
87495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
87595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*in = p;
87695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ret = 1;
87795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	err:
87895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (free_cont && buf.data) OPENSSL_free(buf.data);
87995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return ret;
88095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
88195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
88295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Translate ASN1 content octets into a structure */
88395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
88495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
88595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			int utype, char *free_cont, const ASN1_ITEM *it)
88695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
88795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_VALUE **opval = NULL;
88895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_STRING *stmp;
88995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_TYPE *typ = NULL;
89095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ret = 0;
89195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const ASN1_PRIMITIVE_FUNCS *pf;
89295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ASN1_INTEGER **tint;
89395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	pf = it->funcs;
89495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
89595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (pf && pf->prim_c2i)
89695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return pf->prim_c2i(pval, cont, len, utype, free_cont, it);
89795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If ANY type clear type and set pointer to internal value */
89895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (it->utype == V_ASN1_ANY)
89995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
90095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!*pval)
90195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
90295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			typ = ASN1_TYPE_new();
90395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (typ == NULL)
90495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
90595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*pval = (ASN1_VALUE *)typ;
90695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
90795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
90895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			typ = (ASN1_TYPE *)*pval;
90995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
91095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (utype != typ->type)
91195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_TYPE_set(typ, utype, NULL);
91295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		opval = pval;
91395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		pval = &typ->value.asn1_value;
91495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
91595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	switch(utype)
91695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
91795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_OBJECT:
91895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
91995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
92095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
92195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
92295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_NULL:
92395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (len)
92495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
92595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i,  ASN1_R_NULL_IS_WRONG_LENGTH);
92695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
92795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
92895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*pval = (ASN1_VALUE *)1;
92995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
93095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
93195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_BOOLEAN:
93295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (len != 1)
93395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
93495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i,  ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
93595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
93695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
93795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
93895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
93995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ASN1_BOOLEAN *tbool;
94095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			tbool = (ASN1_BOOLEAN *)pval;
94195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*tbool = *cont;
94295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
94395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
94495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
94595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_BIT_STRING:
94695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
94795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
94895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
94995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
95095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_INTEGER:
95195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_NEG_INTEGER:
95295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_ENUMERATED:
95395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_NEG_ENUMERATED:
95495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		tint = (ASN1_INTEGER **)pval;
95595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!c2i_ASN1_INTEGER(tint, &cont, len))
95695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
95795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Fixup type to match the expected form */
95895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		(*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
95995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
96095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
96195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_OCTET_STRING:
96295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_NUMERICSTRING:
96395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_PRINTABLESTRING:
96495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_T61STRING:
96595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_VIDEOTEXSTRING:
96695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_IA5STRING:
96795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_UTCTIME:
96895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_GENERALIZEDTIME:
96995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_GRAPHICSTRING:
97095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_VISIBLESTRING:
97195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_GENERALSTRING:
97295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_UNIVERSALSTRING:
97395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_BMPSTRING:
97495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_UTF8STRING:
97595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_OTHER:
97695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_SET:
97795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		case V_ASN1_SEQUENCE:
97895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		default:
97995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (utype == V_ASN1_BMPSTRING && (len & 1))
98095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
98195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i,  ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
98295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
98395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
98495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (utype == V_ASN1_UNIVERSALSTRING && (len & 3))
98595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
98695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i,  ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
98795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			goto err;
98895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
98995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* All based on ASN1_STRING and handled the same */
99095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!*pval)
99195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
99295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			stmp = ASN1_STRING_type_new(utype);
99395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!stmp)
99495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
99595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i,  ERR_R_MALLOC_FAILURE);
99695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
99795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
99895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*pval = (ASN1_VALUE *)stmp;
99995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
100095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
100195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
100295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			stmp = (ASN1_STRING *)*pval;
100395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			stmp->type = utype;
100495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
100595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If we've already allocated a buffer use it */
100695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (*free_cont)
100795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
100895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (stmp->data)
100995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_free(stmp->data);
101095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */
101195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			stmp->length = len;
101295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*free_cont = 0;
101395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
101495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
101595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
101695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!ASN1_STRING_set(stmp, cont, len))
101795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
101895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, asn1_ex_c2i,  ERR_R_MALLOC_FAILURE);
101995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_STRING_free(stmp);
102095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				*pval = NULL;
102195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				goto err;
102295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
102395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
102495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		break;
102595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
102695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If ASN1_ANY and NULL type fix up value */
102795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (typ && (utype == V_ASN1_NULL))
102895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 typ->value.ptr = NULL;
102995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
103095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	ret = 1;
103195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	err:
103295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!ret)
103395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
103495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ASN1_TYPE_free(typ);
103595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (opval)
103695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			*opval = NULL;
103795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
103895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return ret;
103995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
104095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
104195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
104295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* This function finds the end of an ASN1 structure when passed its maximum
104395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * length, whether it is indefinite length and a pointer to the content.
104495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This is more efficient than calling asn1_collect because it does not
104595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * recurse on each indefinite length header.
104695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
104795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
104895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_find_end(const unsigned char **in, long len, char inf)
104995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
105095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int expected_eoc;
105195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	long plen;
105295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const unsigned char *p = *in, *q;
105395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If not indefinite length constructed just add length */
105495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (inf == 0)
105595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
105695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*in += len;
105795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
105895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
105995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	expected_eoc = 1;
106095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* Indefinite length constructed form. Find the end when enough EOCs
106195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * are found. If more indefinite length constructed headers
106295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * are encountered increment the expected eoc count otherwise just
106395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * skip to the end of the data.
106495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 */
106595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	while (len > 0)
106695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
106795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if(asn1_check_eoc(&p, len))
106895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
106995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			expected_eoc--;
107095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (expected_eoc == 0)
107195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				break;
107295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			len -= 2;
107395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			continue;
107495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
107595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		q = p;
107695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Just read in a header: only care about the length */
107795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if(!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len,
107895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				-1, 0, 0, NULL))
107995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
108095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_find_end,  ASN1_R_NESTED_ASN1_ERROR);
108195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
108295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
108395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (inf)
108495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			expected_eoc++;
108595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else
108695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			p += plen;
108795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len -= p - q;
108895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
108995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (expected_eoc)
109095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
109195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_PUT_ERROR(ASN1, asn1_find_end,  ASN1_R_MISSING_EOC);
109295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
109395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
109495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*in = p;
109595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
109695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
109795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* This function collects the asn1 data from a constructred string
109895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * type into a buffer. The values of 'in' and 'len' should refer
109995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * to the contents of the constructed type and 'inf' should be set
110095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * if it is indefinite length.
110195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
110295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
110395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#ifndef ASN1_MAX_STRING_NEST
110495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* This determines how many levels of recursion are permitted in ASN1
110595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * string types. If it is not limited stack overflows can occur. If set
110695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * to zero no recursion is allowed at all. Although zero should be adequate
110795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * examples exist that require a value of 1. So 5 should be more than enough.
110895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
110995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define ASN1_MAX_STRING_NEST 5
111095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif
111195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
111295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
111395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
111495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			char inf, int tag, int aclass, int depth)
111595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
111695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const unsigned char *p, *q;
111795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	long plen;
111895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	char cst, ininf;
111995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	p = *in;
112095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	inf &= 1;
112195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	/* If no buffer and not indefinite length constructed just pass over
112295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	 * the encoded data */
112395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!buf && !inf)
112495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
112595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*in += len;
112695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
112795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
112895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	while(len > 0)
112995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
113095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		q = p;
113195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* Check for EOC */
113295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (asn1_check_eoc(&p, len))
113395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
113495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* EOC is illegal outside indefinite length
113595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * constructed form */
113695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!inf)
113795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
113895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, asn1_collect,  ASN1_R_UNEXPECTED_EOC);
113995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
114095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
114195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			inf = 0;
114295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			break;
114395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
114495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
114595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p,
114695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley					len, tag, aclass, 0, NULL))
114795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
114895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_collect,  ASN1_R_NESTED_ASN1_ERROR);
114995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
115095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
115195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
115295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* If indefinite length constructed update max length */
115395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (cst)
115495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
115595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (depth >= ASN1_MAX_STRING_NEST)
115695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
115795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, asn1_collect,  ASN1_R_NESTED_ASN1_STRING);
115895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
115995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
116095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!asn1_collect(buf, &p, plen, ininf, tag, aclass,
116195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley						depth + 1))
116295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
116395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
116495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		else if (plen && !collect_data(buf, &p, plen))
116595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
116695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len -= p - q;
116795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
116895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (inf)
116995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
117095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_PUT_ERROR(ASN1, asn1_collect,  ASN1_R_MISSING_EOC);
117195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
117295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
117395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*in = p;
117495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
117595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
117695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
117795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
117895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
117995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int len;
118095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (buf)
118195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
118295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		len = buf->length;
118395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (!BUF_MEM_grow_clean(buf, len + plen))
118495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
118595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_collect,  ERR_R_MALLOC_FAILURE);
118695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
118795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
118895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		memcpy(buf->data + len, *p, plen);
118995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
119095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*p += plen;
119195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
119295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
119395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
119495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Check for ASN1 EOC and swallow it if found */
119595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
119695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_check_eoc(const unsigned char **in, long len)
119795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
119895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const unsigned char *p;
119995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (len < 2) return 0;
120095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	p = *in;
120195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (!p[0] && !p[1])
120295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
120395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*in += 2;
120495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 1;
120595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
120695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 0;
120795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
120895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
120995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Check an ASN1 tag and length: a bit like ASN1_get_object
121095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * but it sets the length for indefinite length constructed
121195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * form, we don't know the exact length but we can set an
121295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * upper bound to the amount of data available minus the
121395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * header length just read.
121495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
121595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
121695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
121795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				char *inf, char *cst,
121895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				const unsigned char **in, long len,
121995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				int exptag, int expclass, char opt,
122095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				ASN1_TLC *ctx)
122195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	{
122295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int i;
122395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	int ptag, pclass;
122495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	long plen;
122595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	const unsigned char *p, *q;
122695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	p = *in;
122795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	q = p;
122895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
122995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (ctx && ctx->valid)
123095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
123195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		i = ctx->ret;
123295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		plen = ctx->plen;
123395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		pclass = ctx->pclass;
123495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		ptag = ctx->ptag;
123595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		p += ctx->hdrlen;
123695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
123795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	else
123895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
123995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		i = ASN1_get_object(&p, &plen, &ptag, &pclass, len);
124095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if (ctx)
124195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
124295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ctx->ret = i;
124395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ctx->plen = plen;
124495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ctx->pclass = pclass;
124595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ctx->ptag = ptag;
124695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ctx->hdrlen = p - q;
124795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			ctx->valid = 1;
124895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* If definite length, and no error, length +
124995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * header can't exceed total amount of data available.
125095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 */
125195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (!(i & 0x81) && ((plen + ctx->hdrlen) > len))
125295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				{
125395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				OPENSSL_PUT_ERROR(ASN1, asn1_check_tlen,  ASN1_R_TOO_LONG);
125495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				asn1_tlc_clear(ctx);
125595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				return 0;
125695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley				}
125795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
125895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
125995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
126095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (i & 0x80)
126195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
126295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		OPENSSL_PUT_ERROR(ASN1, asn1_check_tlen,  ASN1_R_BAD_OBJECT_HEADER);
126395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		asn1_tlc_clear(ctx);
126495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		return 0;
126595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
126695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (exptag >= 0)
126795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		{
126895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		if ((exptag != ptag) || (expclass != pclass))
126995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			{
127095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			/* If type is OPTIONAL, not an error:
127195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 * indicate missing type.
127295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			 */
127395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			if (opt) return -1;
127495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			asn1_tlc_clear(ctx);
127595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			OPENSSL_PUT_ERROR(ASN1, asn1_check_tlen,  ASN1_R_WRONG_TAG);
127695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			return 0;
127795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley			}
127895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		/* We have a tag and class match:
127995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		 * assume we are going to do something with it */
128095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		asn1_tlc_clear(ctx);
128195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		}
128295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
128395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (i & 1)
128495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		plen = len - (p - q);
128595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
128695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (inf)
128795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*inf = i & 1;
128895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
128995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (cst)
129095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*cst = i & V_ASN1_CONSTRUCTED;
129195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
129295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (olen)
129395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*olen = plen;
129495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
129595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (oclass)
129695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*oclass = pclass;
129795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
129895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	if (otag)
129995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley		*otag = ptag;
130095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
130195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	*in = p;
130295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	return 1;
130395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley	}
1304