1109998Smarkm/* tasn_dec.c */
2194206Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3109998Smarkm * project 2000.
4109998Smarkm */
5109998Smarkm/* ====================================================================
6160814Ssimon * Copyright (c) 2000-2005 The OpenSSL Project.  All rights reserved.
7109998Smarkm *
8109998Smarkm * Redistribution and use in source and binary forms, with or without
9109998Smarkm * modification, are permitted provided that the following conditions
10109998Smarkm * are met:
11109998Smarkm *
12109998Smarkm * 1. Redistributions of source code must retain the above copyright
13109998Smarkm *    notice, this list of conditions and the following disclaimer.
14109998Smarkm *
15109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright
16109998Smarkm *    notice, this list of conditions and the following disclaimer in
17109998Smarkm *    the documentation and/or other materials provided with the
18109998Smarkm *    distribution.
19109998Smarkm *
20109998Smarkm * 3. All advertising materials mentioning features or use of this
21109998Smarkm *    software must display the following acknowledgment:
22109998Smarkm *    "This product includes software developed by the OpenSSL Project
23109998Smarkm *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24109998Smarkm *
25109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26109998Smarkm *    endorse or promote products derived from this software without
27109998Smarkm *    prior written permission. For written permission, please contact
28109998Smarkm *    licensing@OpenSSL.org.
29109998Smarkm *
30109998Smarkm * 5. Products derived from this software may not be called "OpenSSL"
31109998Smarkm *    nor may "OpenSSL" appear in their names without prior written
32109998Smarkm *    permission of the OpenSSL Project.
33109998Smarkm *
34109998Smarkm * 6. Redistributions of any form whatsoever must retain the following
35109998Smarkm *    acknowledgment:
36109998Smarkm *    "This product includes software developed by the OpenSSL Project
37109998Smarkm *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38109998Smarkm *
39109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42109998Smarkm * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE.
51109998Smarkm * ====================================================================
52109998Smarkm *
53109998Smarkm * This product includes cryptographic software written by Eric Young
54109998Smarkm * (eay@cryptsoft.com).  This product includes software written by Tim
55109998Smarkm * Hudson (tjh@cryptsoft.com).
56109998Smarkm *
57109998Smarkm */
58109998Smarkm
59109998Smarkm
60109998Smarkm#include <stddef.h>
61109998Smarkm#include <string.h>
62109998Smarkm#include <openssl/asn1.h>
63109998Smarkm#include <openssl/asn1t.h>
64109998Smarkm#include <openssl/objects.h>
65109998Smarkm#include <openssl/buffer.h>
66109998Smarkm#include <openssl/err.h>
67109998Smarkm
68160814Ssimonstatic int asn1_check_eoc(const unsigned char **in, long len);
69160814Ssimonstatic int asn1_find_end(const unsigned char **in, long len, char inf);
70109998Smarkm
71160814Ssimonstatic int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
72194206Ssimon			char inf, int tag, int aclass, int depth);
73160814Ssimon
74160814Ssimonstatic int collect_data(BUF_MEM *buf, const unsigned char **p, long plen);
75160814Ssimon
76160814Ssimonstatic int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
77160814Ssimon				char *inf, char *cst,
78160814Ssimon				const unsigned char **in, long len,
79160814Ssimon				int exptag, int expclass, char opt,
80160814Ssimon				ASN1_TLC *ctx);
81160814Ssimon
82160814Ssimonstatic int asn1_template_ex_d2i(ASN1_VALUE **pval,
83160814Ssimon				const unsigned char **in, long len,
84160814Ssimon				const ASN1_TEMPLATE *tt, char opt,
85160814Ssimon				ASN1_TLC *ctx);
86160814Ssimonstatic int asn1_template_noexp_d2i(ASN1_VALUE **val,
87160814Ssimon				const unsigned char **in, long len,
88160814Ssimon				const ASN1_TEMPLATE *tt, char opt,
89160814Ssimon				ASN1_TLC *ctx);
90160814Ssimonstatic int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
91160814Ssimon				const unsigned char **in, long len,
92160814Ssimon				const ASN1_ITEM *it,
93160814Ssimon				int tag, int aclass, char opt, ASN1_TLC *ctx);
94160814Ssimon
95109998Smarkm/* Table to convert tags to bit values, used for MSTRING type */
96167612Ssimonstatic const unsigned long tag2bit[32] = {
97109998Smarkm0,	0,	0,	B_ASN1_BIT_STRING,	/* tags  0 -  3 */
98109998SmarkmB_ASN1_OCTET_STRING,	0,	0,		B_ASN1_UNKNOWN,/* tags  4- 7 */
99109998SmarkmB_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,/* tags  8-11 */
100109998SmarkmB_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */
101160814SsimonB_ASN1_SEQUENCE,0,B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */
102109998SmarkmB_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING,       /* tags 20-22 */
103109998SmarkmB_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME,			       /* tags 23-24 */
104109998SmarkmB_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING,  /* tags 25-27 */
105109998SmarkmB_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */
106109998Smarkm	};
107109998Smarkm
108109998Smarkmunsigned long ASN1_tag2bit(int tag)
109160814Ssimon	{
110160814Ssimon	if ((tag < 0) || (tag > 30)) return 0;
111109998Smarkm	return tag2bit[tag];
112160814Ssimon	}
113109998Smarkm
114109998Smarkm/* Macro to initialize and invalidate the cache */
115109998Smarkm
116160814Ssimon#define asn1_tlc_clear(c)	if (c) (c)->valid = 0
117238405Sjkim/* Version to avoid compiler warning about 'c' always non-NULL */
118238405Sjkim#define asn1_tlc_clear_nc(c)	(c)->valid = 0
119109998Smarkm
120109998Smarkm/* Decode an ASN1 item, this currently behaves just
121109998Smarkm * like a standard 'd2i' function. 'in' points to
122109998Smarkm * a buffer to read the data from, in future we will
123109998Smarkm * have more advanced versions that can input data
124109998Smarkm * a piece at a time and this will simply be a special
125109998Smarkm * case.
126109998Smarkm */
127109998Smarkm
128160814SsimonASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
129160814Ssimon		const unsigned char **in, long len, const ASN1_ITEM *it)
130160814Ssimon	{
131109998Smarkm	ASN1_TLC c;
132109998Smarkm	ASN1_VALUE *ptmpval = NULL;
133160814Ssimon	if (!pval)
134160814Ssimon		pval = &ptmpval;
135238405Sjkim	asn1_tlc_clear_nc(&c);
136160814Ssimon	if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0)
137109998Smarkm		return *pval;
138109998Smarkm	return NULL;
139160814Ssimon	}
140109998Smarkm
141160814Ssimonint ASN1_template_d2i(ASN1_VALUE **pval,
142160814Ssimon		const unsigned char **in, long len, const ASN1_TEMPLATE *tt)
143160814Ssimon	{
144109998Smarkm	ASN1_TLC c;
145238405Sjkim	asn1_tlc_clear_nc(&c);
146109998Smarkm	return asn1_template_ex_d2i(pval, in, len, tt, 0, &c);
147160814Ssimon	}
148109998Smarkm
149109998Smarkm
150109998Smarkm/* Decode an item, taking care of IMPLICIT tagging, if any.
151109998Smarkm * If 'opt' set and tag mismatch return -1 to handle OPTIONAL
152109998Smarkm */
153109998Smarkm
154160814Ssimonint ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
155160814Ssimon			const ASN1_ITEM *it,
156160814Ssimon			int tag, int aclass, char opt, ASN1_TLC *ctx)
157160814Ssimon	{
158109998Smarkm	const ASN1_TEMPLATE *tt, *errtt = NULL;
159109998Smarkm	const ASN1_COMPAT_FUNCS *cf;
160109998Smarkm	const ASN1_EXTERN_FUNCS *ef;
161109998Smarkm	const ASN1_AUX *aux = it->funcs;
162109998Smarkm	ASN1_aux_cb *asn1_cb;
163160814Ssimon	const unsigned char *p = NULL, *q;
164160814Ssimon	unsigned char *wp=NULL;	/* BIG FAT WARNING!  BREAKS CONST WHERE USED */
165160814Ssimon	unsigned char imphack = 0, oclass;
166109998Smarkm	char seq_eoc, seq_nolen, cst, isopt;
167109998Smarkm	long tmplen;
168109998Smarkm	int i;
169109998Smarkm	int otag;
170109998Smarkm	int ret = 0;
171215697Ssimon	ASN1_VALUE **pchptr, *ptmpval;
172160814Ssimon	if (!pval)
173160814Ssimon		return 0;
174160814Ssimon	if (aux && aux->asn1_cb)
175160814Ssimon		asn1_cb = aux->asn1_cb;
176109998Smarkm	else asn1_cb = 0;
177109998Smarkm
178160814Ssimon	switch(it->itype)
179160814Ssimon		{
180109998Smarkm		case ASN1_ITYPE_PRIMITIVE:
181160814Ssimon		if (it->templates)
182160814Ssimon			{
183160814Ssimon			/* tagging or OPTIONAL is currently illegal on an item
184160814Ssimon			 * template because the flags can't get passed down.
185160814Ssimon			 * In practice this isn't a problem: we include the
186160814Ssimon			 * relevant flags from the item template in the
187160814Ssimon			 * template itself.
188109998Smarkm			 */
189160814Ssimon			if ((tag != -1) || opt)
190160814Ssimon				{
191160814Ssimon				ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
192160814Ssimon				ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
193109998Smarkm				goto err;
194160814Ssimon				}
195160814Ssimon			return asn1_template_ex_d2i(pval, in, len,
196160814Ssimon					it->templates, opt, ctx);
197109998Smarkm		}
198160814Ssimon		return asn1_d2i_ex_primitive(pval, in, len, it,
199160814Ssimon						tag, aclass, opt, ctx);
200109998Smarkm		break;
201109998Smarkm
202109998Smarkm		case ASN1_ITYPE_MSTRING:
203109998Smarkm		p = *in;
204109998Smarkm		/* Just read in tag and class */
205160814Ssimon		ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
206160814Ssimon						&p, len, -1, 0, 1, ctx);
207160814Ssimon		if (!ret)
208160814Ssimon			{
209160814Ssimon			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
210160814Ssimon					ERR_R_NESTED_ASN1_ERROR);
211109998Smarkm			goto err;
212160814Ssimon			}
213160814Ssimon
214109998Smarkm		/* Must be UNIVERSAL class */
215160814Ssimon		if (oclass != V_ASN1_UNIVERSAL)
216160814Ssimon			{
217109998Smarkm			/* If OPTIONAL, assume this is OK */
218160814Ssimon			if (opt) return -1;
219160814Ssimon			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
220160814Ssimon					ASN1_R_MSTRING_NOT_UNIVERSAL);
221109998Smarkm			goto err;
222160814Ssimon			}
223109998Smarkm		/* Check tag matches bit map */
224160814Ssimon		if (!(ASN1_tag2bit(otag) & it->utype))
225160814Ssimon			{
226109998Smarkm			/* If OPTIONAL, assume this is OK */
227160814Ssimon			if (opt)
228160814Ssimon				return -1;
229160814Ssimon			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
230160814Ssimon					ASN1_R_MSTRING_WRONG_TAG);
231109998Smarkm			goto err;
232160814Ssimon			}
233160814Ssimon		return asn1_d2i_ex_primitive(pval, in, len,
234160814Ssimon						it, otag, 0, 0, ctx);
235109998Smarkm
236109998Smarkm		case ASN1_ITYPE_EXTERN:
237109998Smarkm		/* Use new style d2i */
238109998Smarkm		ef = it->funcs;
239160814Ssimon		return ef->asn1_ex_d2i(pval, in, len,
240160814Ssimon						it, tag, aclass, opt, ctx);
241109998Smarkm
242109998Smarkm		case ASN1_ITYPE_COMPAT:
243109998Smarkm		/* we must resort to old style evil hackery */
244109998Smarkm		cf = it->funcs;
245109998Smarkm
246109998Smarkm		/* If OPTIONAL see if it is there */
247160814Ssimon		if (opt)
248160814Ssimon			{
249109998Smarkm			int exptag;
250109998Smarkm			p = *in;
251160814Ssimon			if (tag == -1)
252160814Ssimon				exptag = it->utype;
253109998Smarkm			else exptag = tag;
254160814Ssimon			/* Don't care about anything other than presence
255160814Ssimon			 * of expected tag */
256160814Ssimon
257160814Ssimon			ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL,
258160814Ssimon					&p, len, exptag, aclass, 1, ctx);
259160814Ssimon			if (!ret)
260160814Ssimon				{
261160814Ssimon				ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
262160814Ssimon					ERR_R_NESTED_ASN1_ERROR);
263109998Smarkm				goto err;
264160814Ssimon				}
265160814Ssimon			if (ret == -1)
266160814Ssimon				return -1;
267109998Smarkm			}
268160814Ssimon
269109998Smarkm		/* This is the old style evil hack IMPLICIT handling:
270109998Smarkm		 * since the underlying code is expecting a tag and
271109998Smarkm		 * class other than the one present we change the
272109998Smarkm		 * buffer temporarily then change it back afterwards.
273109998Smarkm		 * This doesn't and never did work for tags > 30.
274109998Smarkm		 *
275109998Smarkm		 * Yes this is *horrible* but it is only needed for
276109998Smarkm		 * old style d2i which will hopefully not be around
277109998Smarkm		 * for much longer.
278109998Smarkm		 * FIXME: should copy the buffer then modify it so
279109998Smarkm		 * the input buffer can be const: we should *always*
280109998Smarkm		 * copy because the old style d2i might modify the
281109998Smarkm		 * buffer.
282109998Smarkm		 */
283109998Smarkm
284160814Ssimon		if (tag != -1)
285160814Ssimon			{
286160814Ssimon			wp = *(unsigned char **)in;
287160814Ssimon			imphack = *wp;
288160814Ssimon			if (p == NULL)
289160814Ssimon				{
290160814Ssimon				ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
291160814Ssimon					ERR_R_NESTED_ASN1_ERROR);
292160814Ssimon				goto err;
293160814Ssimon				}
294160814Ssimon			*wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED)
295160814Ssimon								| it->utype);
296160814Ssimon			}
297109998Smarkm
298109998Smarkm		ptmpval = cf->asn1_d2i(pval, in, len);
299109998Smarkm
300160814Ssimon		if (tag != -1)
301160814Ssimon			*wp = imphack;
302109998Smarkm
303160814Ssimon		if (ptmpval)
304160814Ssimon			return 1;
305160814Ssimon
306109998Smarkm		ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR);
307109998Smarkm		goto err;
308109998Smarkm
309109998Smarkm
310109998Smarkm		case ASN1_ITYPE_CHOICE:
311238405Sjkim		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
312109998Smarkm				goto auxerr;
313109998Smarkm
314109998Smarkm		/* Allocate structure */
315160814Ssimon		if (!*pval && !ASN1_item_ex_new(pval, it))
316160814Ssimon			{
317160814Ssimon			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
318160814Ssimon						ERR_R_NESTED_ASN1_ERROR);
319160814Ssimon			goto err;
320109998Smarkm			}
321109998Smarkm		/* CHOICE type, try each possibility in turn */
322109998Smarkm		p = *in;
323160814Ssimon		for (i = 0, tt=it->templates; i < it->tcount; i++, tt++)
324160814Ssimon			{
325109998Smarkm			pchptr = asn1_get_field_ptr(pval, tt);
326109998Smarkm			/* We mark field as OPTIONAL so its absence
327109998Smarkm			 * can be recognised.
328109998Smarkm			 */
329109998Smarkm			ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx);
330109998Smarkm			/* If field not present, try the next one */
331160814Ssimon			if (ret == -1)
332160814Ssimon				continue;
333109998Smarkm			/* If positive return, read OK, break loop */
334160814Ssimon			if (ret > 0)
335160814Ssimon				break;
336109998Smarkm			/* Otherwise must be an ASN1 parsing error */
337109998Smarkm			errtt = tt;
338160814Ssimon			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
339160814Ssimon						ERR_R_NESTED_ASN1_ERROR);
340109998Smarkm			goto err;
341160814Ssimon			}
342160814Ssimon
343109998Smarkm		/* Did we fall off the end without reading anything? */
344160814Ssimon		if (i == it->tcount)
345160814Ssimon			{
346109998Smarkm			/* If OPTIONAL, this is OK */
347160814Ssimon			if (opt)
348160814Ssimon				{
349109998Smarkm				/* Free and zero it */
350109998Smarkm				ASN1_item_ex_free(pval, it);
351109998Smarkm				return -1;
352160814Ssimon				}
353160814Ssimon			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
354160814Ssimon					ASN1_R_NO_MATCHING_CHOICE_TYPE);
355160814Ssimon			goto err;
356109998Smarkm			}
357160814Ssimon
358109998Smarkm		asn1_set_choice_selector(pval, i, it);
359109998Smarkm		*in = p;
360238405Sjkim		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
361109998Smarkm				goto auxerr;
362109998Smarkm		return 1;
363109998Smarkm
364160814Ssimon		case ASN1_ITYPE_NDEF_SEQUENCE:
365109998Smarkm		case ASN1_ITYPE_SEQUENCE:
366109998Smarkm		p = *in;
367109998Smarkm		tmplen = len;
368109998Smarkm
369109998Smarkm		/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
370160814Ssimon		if (tag == -1)
371160814Ssimon			{
372109998Smarkm			tag = V_ASN1_SEQUENCE;
373109998Smarkm			aclass = V_ASN1_UNIVERSAL;
374160814Ssimon			}
375109998Smarkm		/* Get SEQUENCE length and update len, p */
376160814Ssimon		ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst,
377160814Ssimon					&p, len, tag, aclass, opt, ctx);
378160814Ssimon		if (!ret)
379160814Ssimon			{
380160814Ssimon			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
381160814Ssimon					ERR_R_NESTED_ASN1_ERROR);
382109998Smarkm			goto err;
383160814Ssimon			}
384160814Ssimon		else if (ret == -1)
385160814Ssimon			return -1;
386160814Ssimon		if (aux && (aux->flags & ASN1_AFLG_BROKEN))
387160814Ssimon			{
388109998Smarkm			len = tmplen - (p - *in);
389109998Smarkm			seq_nolen = 1;
390160814Ssimon			}
391160814Ssimon		/* If indefinite we don't do a length check */
392160814Ssimon		else seq_nolen = seq_eoc;
393160814Ssimon		if (!cst)
394160814Ssimon			{
395160814Ssimon			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
396160814Ssimon				ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
397109998Smarkm			goto err;
398160814Ssimon			}
399109998Smarkm
400160814Ssimon		if (!*pval && !ASN1_item_ex_new(pval, it))
401160814Ssimon			{
402160814Ssimon			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
403160814Ssimon				ERR_R_NESTED_ASN1_ERROR);
404160814Ssimon			goto err;
405109998Smarkm			}
406160814Ssimon
407238405Sjkim		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
408109998Smarkm				goto auxerr;
409109998Smarkm
410109998Smarkm		/* Get each field entry */
411160814Ssimon		for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)
412160814Ssimon			{
413109998Smarkm			const ASN1_TEMPLATE *seqtt;
414109998Smarkm			ASN1_VALUE **pseqval;
415109998Smarkm			seqtt = asn1_do_adb(pval, tt, 1);
416160814Ssimon			if (!seqtt)
417160814Ssimon				goto err;
418109998Smarkm			pseqval = asn1_get_field_ptr(pval, seqtt);
419109998Smarkm			/* Have we ran out of data? */
420160814Ssimon			if (!len)
421160814Ssimon				break;
422109998Smarkm			q = p;
423160814Ssimon			if (asn1_check_eoc(&p, len))
424160814Ssimon				{
425160814Ssimon				if (!seq_eoc)
426160814Ssimon					{
427160814Ssimon					ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
428160814Ssimon							ASN1_R_UNEXPECTED_EOC);
429109998Smarkm					goto err;
430160814Ssimon					}
431109998Smarkm				len -= p - q;
432109998Smarkm				seq_eoc = 0;
433109998Smarkm				q = p;
434109998Smarkm				break;
435160814Ssimon				}
436160814Ssimon			/* This determines the OPTIONAL flag value. The field
437160814Ssimon			 * cannot be omitted if it is the last of a SEQUENCE
438160814Ssimon			 * and there is still data to be read. This isn't
439160814Ssimon			 * strictly necessary but it increases efficiency in
440160814Ssimon			 * some cases.
441109998Smarkm			 */
442160814Ssimon			if (i == (it->tcount - 1))
443160814Ssimon				isopt = 0;
444109998Smarkm			else isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL);
445160814Ssimon			/* attempt to read in field, allowing each to be
446160814Ssimon			 * OPTIONAL */
447160814Ssimon
448160814Ssimon			ret = asn1_template_ex_d2i(pseqval, &p, len,
449160814Ssimon							seqtt, isopt, ctx);
450160814Ssimon			if (!ret)
451160814Ssimon				{
452109998Smarkm				errtt = seqtt;
453109998Smarkm				goto err;
454160814Ssimon				}
455160814Ssimon			else if (ret == -1)
456160814Ssimon				{
457160814Ssimon				/* OPTIONAL component absent.
458160814Ssimon				 * Free and zero the field.
459109998Smarkm				 */
460109998Smarkm				ASN1_template_free(pseqval, seqtt);
461109998Smarkm				continue;
462160814Ssimon				}
463109998Smarkm			/* Update length */
464109998Smarkm			len -= p - q;
465160814Ssimon			}
466160814Ssimon
467109998Smarkm		/* Check for EOC if expecting one */
468160814Ssimon		if (seq_eoc && !asn1_check_eoc(&p, len))
469160814Ssimon			{
470109998Smarkm			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MISSING_EOC);
471109998Smarkm			goto err;
472160814Ssimon			}
473109998Smarkm		/* Check all data read */
474160814Ssimon		if (!seq_nolen && len)
475160814Ssimon			{
476160814Ssimon			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
477160814Ssimon					ASN1_R_SEQUENCE_LENGTH_MISMATCH);
478109998Smarkm			goto err;
479160814Ssimon			}
480109998Smarkm
481109998Smarkm		/* If we get here we've got no more data in the SEQUENCE,
482109998Smarkm		 * however we may not have read all fields so check all
483109998Smarkm		 * remaining are OPTIONAL and clear any that are.
484109998Smarkm		 */
485160814Ssimon		for (; i < it->tcount; tt++, i++)
486160814Ssimon			{
487109998Smarkm			const ASN1_TEMPLATE *seqtt;
488109998Smarkm			seqtt = asn1_do_adb(pval, tt, 1);
489160814Ssimon			if (!seqtt)
490160814Ssimon				goto err;
491160814Ssimon			if (seqtt->flags & ASN1_TFLG_OPTIONAL)
492160814Ssimon				{
493109998Smarkm				ASN1_VALUE **pseqval;
494109998Smarkm				pseqval = asn1_get_field_ptr(pval, seqtt);
495109998Smarkm				ASN1_template_free(pseqval, seqtt);
496160814Ssimon				}
497160814Ssimon			else
498160814Ssimon				{
499109998Smarkm				errtt = seqtt;
500160814Ssimon				ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,
501160814Ssimon							ASN1_R_FIELD_MISSING);
502109998Smarkm				goto err;
503160814Ssimon				}
504109998Smarkm			}
505109998Smarkm		/* Save encoding */
506160814Ssimon		if (!asn1_enc_save(pval, *in, p - *in, it))
507160814Ssimon			goto auxerr;
508109998Smarkm		*in = p;
509238405Sjkim		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
510109998Smarkm				goto auxerr;
511109998Smarkm		return 1;
512109998Smarkm
513109998Smarkm		default:
514109998Smarkm		return 0;
515160814Ssimon		}
516109998Smarkm	auxerr:
517109998Smarkm	ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_AUX_ERROR);
518109998Smarkm	err:
519109998Smarkm	ASN1_item_ex_free(pval, it);
520160814Ssimon	if (errtt)
521160814Ssimon		ERR_add_error_data(4, "Field=", errtt->field_name,
522160814Ssimon					", Type=", it->sname);
523160814Ssimon	else
524160814Ssimon		ERR_add_error_data(2, "Type=", it->sname);
525109998Smarkm	return 0;
526160814Ssimon	}
527109998Smarkm
528160814Ssimon/* Templates are handled with two separate functions.
529160814Ssimon * One handles any EXPLICIT tag and the other handles the rest.
530109998Smarkm */
531109998Smarkm
532160814Ssimonstatic int asn1_template_ex_d2i(ASN1_VALUE **val,
533160814Ssimon				const unsigned char **in, long inlen,
534160814Ssimon				const ASN1_TEMPLATE *tt, char opt,
535160814Ssimon							ASN1_TLC *ctx)
536160814Ssimon	{
537109998Smarkm	int flags, aclass;
538109998Smarkm	int ret;
539109998Smarkm	long len;
540160814Ssimon	const unsigned char *p, *q;
541109998Smarkm	char exp_eoc;
542160814Ssimon	if (!val)
543160814Ssimon		return 0;
544109998Smarkm	flags = tt->flags;
545109998Smarkm	aclass = flags & ASN1_TFLG_TAG_CLASS;
546109998Smarkm
547109998Smarkm	p = *in;
548109998Smarkm
549109998Smarkm	/* Check if EXPLICIT tag expected */
550160814Ssimon	if (flags & ASN1_TFLG_EXPTAG)
551160814Ssimon		{
552109998Smarkm		char cst;
553160814Ssimon		/* Need to work out amount of data available to the inner
554160814Ssimon		 * content and where it starts: so read in EXPLICIT header to
555160814Ssimon		 * get the info.
556109998Smarkm		 */
557160814Ssimon		ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst,
558160814Ssimon					&p, inlen, tt->tag, aclass, opt, ctx);
559109998Smarkm		q = p;
560160814Ssimon		if (!ret)
561160814Ssimon			{
562160814Ssimon			ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I,
563160814Ssimon					ERR_R_NESTED_ASN1_ERROR);
564109998Smarkm			return 0;
565160814Ssimon			}
566160814Ssimon		else if (ret == -1)
567160814Ssimon			return -1;
568160814Ssimon		if (!cst)
569160814Ssimon			{
570160814Ssimon			ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I,
571160814Ssimon					ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
572109998Smarkm			return 0;
573160814Ssimon			}
574109998Smarkm		/* We've found the field so it can't be OPTIONAL now */
575109998Smarkm		ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx);
576160814Ssimon		if (!ret)
577160814Ssimon			{
578160814Ssimon			ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I,
579160814Ssimon					ERR_R_NESTED_ASN1_ERROR);
580109998Smarkm			return 0;
581160814Ssimon			}
582109998Smarkm		/* We read the field in OK so update length */
583109998Smarkm		len -= p - q;
584160814Ssimon		if (exp_eoc)
585160814Ssimon			{
586109998Smarkm			/* If NDEF we must have an EOC here */
587160814Ssimon			if (!asn1_check_eoc(&p, len))
588160814Ssimon				{
589160814Ssimon				ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I,
590160814Ssimon						ASN1_R_MISSING_EOC);
591109998Smarkm				goto err;
592160814Ssimon				}
593109998Smarkm			}
594160814Ssimon		else
595160814Ssimon			{
596160814Ssimon			/* Otherwise we must hit the EXPLICIT tag end or its
597160814Ssimon			 * an error */
598160814Ssimon			if (len)
599160814Ssimon				{
600160814Ssimon				ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I,
601160814Ssimon					ASN1_R_EXPLICIT_LENGTH_MISMATCH);
602109998Smarkm				goto err;
603160814Ssimon				}
604109998Smarkm			}
605109998Smarkm		}
606160814Ssimon		else
607160814Ssimon			return asn1_template_noexp_d2i(val, in, inlen,
608160814Ssimon								tt, opt, ctx);
609109998Smarkm
610109998Smarkm	*in = p;
611109998Smarkm	return 1;
612109998Smarkm
613109998Smarkm	err:
614109998Smarkm	ASN1_template_free(val, tt);
615109998Smarkm	return 0;
616160814Ssimon	}
617109998Smarkm
618160814Ssimonstatic int asn1_template_noexp_d2i(ASN1_VALUE **val,
619160814Ssimon				const unsigned char **in, long len,
620160814Ssimon				const ASN1_TEMPLATE *tt, char opt,
621160814Ssimon				ASN1_TLC *ctx)
622160814Ssimon	{
623109998Smarkm	int flags, aclass;
624109998Smarkm	int ret;
625160814Ssimon	const unsigned char *p, *q;
626160814Ssimon	if (!val)
627160814Ssimon		return 0;
628109998Smarkm	flags = tt->flags;
629109998Smarkm	aclass = flags & ASN1_TFLG_TAG_CLASS;
630109998Smarkm
631109998Smarkm	p = *in;
632109998Smarkm	q = p;
633109998Smarkm
634160814Ssimon	if (flags & ASN1_TFLG_SK_MASK)
635160814Ssimon		{
636109998Smarkm		/* SET OF, SEQUENCE OF */
637109998Smarkm		int sktag, skaclass;
638109998Smarkm		char sk_eoc;
639109998Smarkm		/* First work out expected inner tag value */
640160814Ssimon		if (flags & ASN1_TFLG_IMPTAG)
641160814Ssimon			{
642109998Smarkm			sktag = tt->tag;
643109998Smarkm			skaclass = aclass;
644160814Ssimon			}
645160814Ssimon		else
646160814Ssimon			{
647109998Smarkm			skaclass = V_ASN1_UNIVERSAL;
648160814Ssimon			if (flags & ASN1_TFLG_SET_OF)
649160814Ssimon				sktag = V_ASN1_SET;
650160814Ssimon			else
651160814Ssimon				sktag = V_ASN1_SEQUENCE;
652160814Ssimon			}
653109998Smarkm		/* Get the tag */
654160814Ssimon		ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL,
655160814Ssimon					&p, len, sktag, skaclass, opt, ctx);
656160814Ssimon		if (!ret)
657160814Ssimon			{
658160814Ssimon			ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
659160814Ssimon						ERR_R_NESTED_ASN1_ERROR);
660109998Smarkm			return 0;
661160814Ssimon			}
662160814Ssimon		else if (ret == -1)
663160814Ssimon			return -1;
664160814Ssimon		if (!*val)
665160814Ssimon			*val = (ASN1_VALUE *)sk_new_null();
666160814Ssimon		else
667160814Ssimon			{
668109998Smarkm			/* We've got a valid STACK: free up any items present */
669238405Sjkim			STACK_OF(ASN1_VALUE) *sktmp
670238405Sjkim			    = (STACK_OF(ASN1_VALUE) *)*val;
671109998Smarkm			ASN1_VALUE *vtmp;
672238405Sjkim			while(sk_ASN1_VALUE_num(sktmp) > 0)
673160814Ssimon				{
674238405Sjkim				vtmp = sk_ASN1_VALUE_pop(sktmp);
675160814Ssimon				ASN1_item_ex_free(&vtmp,
676160814Ssimon						ASN1_ITEM_ptr(tt->item));
677160814Ssimon				}
678109998Smarkm			}
679109998Smarkm
680160814Ssimon		if (!*val)
681160814Ssimon			{
682160814Ssimon			ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
683160814Ssimon						ERR_R_MALLOC_FAILURE);
684109998Smarkm			goto err;
685160814Ssimon			}
686160814Ssimon
687109998Smarkm		/* Read as many items as we can */
688160814Ssimon		while(len > 0)
689160814Ssimon			{
690109998Smarkm			ASN1_VALUE *skfield;
691109998Smarkm			q = p;
692109998Smarkm			/* See if EOC found */
693160814Ssimon			if (asn1_check_eoc(&p, len))
694160814Ssimon				{
695160814Ssimon				if (!sk_eoc)
696160814Ssimon					{
697160814Ssimon					ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
698160814Ssimon							ASN1_R_UNEXPECTED_EOC);
699109998Smarkm					goto err;
700160814Ssimon					}
701109998Smarkm				len -= p - q;
702109998Smarkm				sk_eoc = 0;
703109998Smarkm				break;
704160814Ssimon				}
705109998Smarkm			skfield = NULL;
706160814Ssimon			if (!ASN1_item_ex_d2i(&skfield, &p, len,
707160814Ssimon						ASN1_ITEM_ptr(tt->item),
708160814Ssimon						-1, 0, 0, ctx))
709160814Ssimon				{
710160814Ssimon				ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
711160814Ssimon					ERR_R_NESTED_ASN1_ERROR);
712109998Smarkm				goto err;
713160814Ssimon				}
714109998Smarkm			len -= p - q;
715238405Sjkim			if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val,
716238405Sjkim						skfield))
717160814Ssimon				{
718160814Ssimon				ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
719160814Ssimon						ERR_R_MALLOC_FAILURE);
720109998Smarkm				goto err;
721160814Ssimon				}
722109998Smarkm			}
723160814Ssimon		if (sk_eoc)
724160814Ssimon			{
725160814Ssimon			ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ASN1_R_MISSING_EOC);
726109998Smarkm			goto err;
727160814Ssimon			}
728109998Smarkm		}
729160814Ssimon	else if (flags & ASN1_TFLG_IMPTAG)
730160814Ssimon		{
731109998Smarkm		/* IMPLICIT tagging */
732160814Ssimon		ret = ASN1_item_ex_d2i(val, &p, len,
733160814Ssimon			ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx);
734160814Ssimon		if (!ret)
735160814Ssimon			{
736160814Ssimon			ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
737160814Ssimon						ERR_R_NESTED_ASN1_ERROR);
738109998Smarkm			goto err;
739160814Ssimon			}
740160814Ssimon		else if (ret == -1)
741160814Ssimon			return -1;
742160814Ssimon		}
743160814Ssimon	else
744160814Ssimon		{
745109998Smarkm		/* Nothing special */
746160814Ssimon		ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
747160814Ssimon							-1, 0, opt, ctx);
748160814Ssimon		if (!ret)
749160814Ssimon			{
750160814Ssimon			ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
751160814Ssimon					ERR_R_NESTED_ASN1_ERROR);
752109998Smarkm			goto err;
753160814Ssimon			}
754160814Ssimon		else if (ret == -1)
755160814Ssimon			return -1;
756160814Ssimon		}
757109998Smarkm
758109998Smarkm	*in = p;
759109998Smarkm	return 1;
760109998Smarkm
761109998Smarkm	err:
762109998Smarkm	ASN1_template_free(val, tt);
763109998Smarkm	return 0;
764160814Ssimon	}
765109998Smarkm
766160814Ssimonstatic int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
767160814Ssimon				const unsigned char **in, long inlen,
768160814Ssimon				const ASN1_ITEM *it,
769160814Ssimon				int tag, int aclass, char opt, ASN1_TLC *ctx)
770160814Ssimon	{
771109998Smarkm	int ret = 0, utype;
772109998Smarkm	long plen;
773109998Smarkm	char cst, inf, free_cont = 0;
774160814Ssimon	const unsigned char *p;
775109998Smarkm	BUF_MEM buf;
776160814Ssimon	const unsigned char *cont = NULL;
777109998Smarkm	long len;
778160814Ssimon	if (!pval)
779160814Ssimon		{
780109998Smarkm		ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL);
781109998Smarkm		return 0; /* Should never happen */
782160814Ssimon		}
783109998Smarkm
784160814Ssimon	if (it->itype == ASN1_ITYPE_MSTRING)
785160814Ssimon		{
786109998Smarkm		utype = tag;
787109998Smarkm		tag = -1;
788160814Ssimon		}
789160814Ssimon	else
790160814Ssimon		utype = it->utype;
791109998Smarkm
792160814Ssimon	if (utype == V_ASN1_ANY)
793160814Ssimon		{
794109998Smarkm		/* If type is ANY need to figure out type from tag */
795109998Smarkm		unsigned char oclass;
796160814Ssimon		if (tag >= 0)
797160814Ssimon			{
798160814Ssimon			ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
799160814Ssimon					ASN1_R_ILLEGAL_TAGGED_ANY);
800109998Smarkm			return 0;
801160814Ssimon			}
802160814Ssimon		if (opt)
803160814Ssimon			{
804160814Ssimon			ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
805160814Ssimon					ASN1_R_ILLEGAL_OPTIONAL_ANY);
806109998Smarkm			return 0;
807160814Ssimon			}
808109998Smarkm		p = *in;
809160814Ssimon		ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL,
810160814Ssimon					&p, inlen, -1, 0, 0, ctx);
811160814Ssimon		if (!ret)
812160814Ssimon			{
813160814Ssimon			ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
814160814Ssimon					ERR_R_NESTED_ASN1_ERROR);
815109998Smarkm			return 0;
816160814Ssimon			}
817160814Ssimon		if (oclass != V_ASN1_UNIVERSAL)
818160814Ssimon			utype = V_ASN1_OTHER;
819109998Smarkm		}
820160814Ssimon	if (tag == -1)
821160814Ssimon		{
822109998Smarkm		tag = utype;
823109998Smarkm		aclass = V_ASN1_UNIVERSAL;
824160814Ssimon		}
825109998Smarkm	p = *in;
826109998Smarkm	/* Check header */
827160814Ssimon	ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst,
828160814Ssimon				&p, inlen, tag, aclass, opt, ctx);
829160814Ssimon	if (!ret)
830160814Ssimon		{
831109998Smarkm		ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR);
832109998Smarkm		return 0;
833160814Ssimon		}
834160814Ssimon	else if (ret == -1)
835160814Ssimon		return -1;
836162911Ssimon        ret = 0;
837109998Smarkm	/* SEQUENCE, SET and "OTHER" are left in encoded form */
838160814Ssimon	if ((utype == V_ASN1_SEQUENCE)
839160814Ssimon		|| (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER))
840160814Ssimon		{
841160814Ssimon		/* Clear context cache for type OTHER because the auto clear
842160814Ssimon		 * when we have a exact match wont work
843109998Smarkm		 */
844160814Ssimon		if (utype == V_ASN1_OTHER)
845160814Ssimon			{
846109998Smarkm			asn1_tlc_clear(ctx);
847160814Ssimon			}
848109998Smarkm		/* SEQUENCE and SET must be constructed */
849160814Ssimon		else if (!cst)
850160814Ssimon			{
851160814Ssimon			ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
852160814Ssimon				ASN1_R_TYPE_NOT_CONSTRUCTED);
853109998Smarkm			return 0;
854160814Ssimon			}
855109998Smarkm
856109998Smarkm		cont = *in;
857109998Smarkm		/* If indefinite length constructed find the real end */
858160814Ssimon		if (inf)
859160814Ssimon			{
860160814Ssimon			if (!asn1_find_end(&p, plen, inf))
861160814Ssimon				 goto err;
862109998Smarkm			len = p - cont;
863160814Ssimon			}
864160814Ssimon		else
865160814Ssimon			{
866109998Smarkm			len = p - cont + plen;
867109998Smarkm			p += plen;
868109998Smarkm			buf.data = NULL;
869160814Ssimon			}
870109998Smarkm		}
871160814Ssimon	else if (cst)
872160814Ssimon		{
873279264Sdelphij		if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN
874279264Sdelphij			|| utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER
875279264Sdelphij			|| utype == V_ASN1_ENUMERATED)
876279264Sdelphij			{
877279264Sdelphij			ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
878279264Sdelphij				ASN1_R_TYPE_NOT_PRIMITIVE);
879279264Sdelphij			return 0;
880279264Sdelphij			}
881109998Smarkm		buf.length = 0;
882109998Smarkm		buf.max = 0;
883109998Smarkm		buf.data = NULL;
884109998Smarkm		/* Should really check the internal tags are correct but
885109998Smarkm		 * some things may get this wrong. The relevant specs
886109998Smarkm		 * say that constructed string types should be OCTET STRINGs
887109998Smarkm		 * internally irrespective of the type. So instead just check
888109998Smarkm		 * for UNIVERSAL class and ignore the tag.
889109998Smarkm		 */
890194206Ssimon		if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0))
891162911Ssimon			{
892162911Ssimon			free_cont = 1;
893160814Ssimon			goto err;
894162911Ssimon			}
895109998Smarkm		len = buf.length;
896109998Smarkm		/* Append a final null to string */
897160814Ssimon		if (!BUF_MEM_grow_clean(&buf, len + 1))
898160814Ssimon			{
899160814Ssimon			ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
900160814Ssimon						ERR_R_MALLOC_FAILURE);
901109998Smarkm			return 0;
902160814Ssimon			}
903109998Smarkm		buf.data[len] = 0;
904160814Ssimon		cont = (const unsigned char *)buf.data;
905109998Smarkm		free_cont = 1;
906160814Ssimon		}
907160814Ssimon	else
908160814Ssimon		{
909109998Smarkm		cont = p;
910109998Smarkm		len = plen;
911109998Smarkm		p += plen;
912160814Ssimon		}
913109998Smarkm
914109998Smarkm	/* We now have content length and type: translate into a structure */
915160814Ssimon	if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it))
916160814Ssimon		goto err;
917109998Smarkm
918109998Smarkm	*in = p;
919109998Smarkm	ret = 1;
920109998Smarkm	err:
921160814Ssimon	if (free_cont && buf.data) OPENSSL_free(buf.data);
922109998Smarkm	return ret;
923160814Ssimon	}
924109998Smarkm
925109998Smarkm/* Translate ASN1 content octets into a structure */
926109998Smarkm
927160814Ssimonint asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
928160814Ssimon			int utype, char *free_cont, const ASN1_ITEM *it)
929160814Ssimon	{
930120631Snectar	ASN1_VALUE **opval = NULL;
931109998Smarkm	ASN1_STRING *stmp;
932109998Smarkm	ASN1_TYPE *typ = NULL;
933109998Smarkm	int ret = 0;
934109998Smarkm	const ASN1_PRIMITIVE_FUNCS *pf;
935109998Smarkm	ASN1_INTEGER **tint;
936109998Smarkm	pf = it->funcs;
937160814Ssimon
938160814Ssimon	if (pf && pf->prim_c2i)
939160814Ssimon		return pf->prim_c2i(pval, cont, len, utype, free_cont, it);
940109998Smarkm	/* If ANY type clear type and set pointer to internal value */
941160814Ssimon	if (it->utype == V_ASN1_ANY)
942160814Ssimon		{
943160814Ssimon		if (!*pval)
944160814Ssimon			{
945109998Smarkm			typ = ASN1_TYPE_new();
946160814Ssimon			if (typ == NULL)
947160814Ssimon				goto err;
948109998Smarkm			*pval = (ASN1_VALUE *)typ;
949160814Ssimon			}
950160814Ssimon		else
951160814Ssimon			typ = (ASN1_TYPE *)*pval;
952160814Ssimon
953160814Ssimon		if (utype != typ->type)
954160814Ssimon			ASN1_TYPE_set(typ, utype, NULL);
955120631Snectar		opval = pval;
956194206Ssimon		pval = &typ->value.asn1_value;
957160814Ssimon		}
958160814Ssimon	switch(utype)
959160814Ssimon		{
960109998Smarkm		case V_ASN1_OBJECT:
961160814Ssimon		if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
962160814Ssimon			goto err;
963109998Smarkm		break;
964109998Smarkm
965109998Smarkm		case V_ASN1_NULL:
966160814Ssimon		if (len)
967160814Ssimon			{
968160814Ssimon			ASN1err(ASN1_F_ASN1_EX_C2I,
969160814Ssimon						ASN1_R_NULL_IS_WRONG_LENGTH);
970109998Smarkm			goto err;
971160814Ssimon			}
972109998Smarkm		*pval = (ASN1_VALUE *)1;
973109998Smarkm		break;
974109998Smarkm
975109998Smarkm		case V_ASN1_BOOLEAN:
976160814Ssimon		if (len != 1)
977160814Ssimon			{
978160814Ssimon			ASN1err(ASN1_F_ASN1_EX_C2I,
979160814Ssimon						ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
980109998Smarkm			goto err;
981160814Ssimon			}
982160814Ssimon		else
983160814Ssimon			{
984109998Smarkm			ASN1_BOOLEAN *tbool;
985109998Smarkm			tbool = (ASN1_BOOLEAN *)pval;
986109998Smarkm			*tbool = *cont;
987160814Ssimon			}
988109998Smarkm		break;
989109998Smarkm
990109998Smarkm		case V_ASN1_BIT_STRING:
991160814Ssimon		if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
992160814Ssimon			goto err;
993109998Smarkm		break;
994109998Smarkm
995109998Smarkm		case V_ASN1_INTEGER:
996109998Smarkm		case V_ASN1_NEG_INTEGER:
997109998Smarkm		case V_ASN1_ENUMERATED:
998109998Smarkm		case V_ASN1_NEG_ENUMERATED:
999109998Smarkm		tint = (ASN1_INTEGER **)pval;
1000160814Ssimon		if (!c2i_ASN1_INTEGER(tint, &cont, len))
1001160814Ssimon			goto err;
1002109998Smarkm		/* Fixup type to match the expected form */
1003109998Smarkm		(*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
1004109998Smarkm		break;
1005109998Smarkm
1006109998Smarkm		case V_ASN1_OCTET_STRING:
1007109998Smarkm		case V_ASN1_NUMERICSTRING:
1008109998Smarkm		case V_ASN1_PRINTABLESTRING:
1009109998Smarkm		case V_ASN1_T61STRING:
1010109998Smarkm		case V_ASN1_VIDEOTEXSTRING:
1011109998Smarkm		case V_ASN1_IA5STRING:
1012109998Smarkm		case V_ASN1_UTCTIME:
1013109998Smarkm		case V_ASN1_GENERALIZEDTIME:
1014109998Smarkm		case V_ASN1_GRAPHICSTRING:
1015109998Smarkm		case V_ASN1_VISIBLESTRING:
1016109998Smarkm		case V_ASN1_GENERALSTRING:
1017109998Smarkm		case V_ASN1_UNIVERSALSTRING:
1018109998Smarkm		case V_ASN1_BMPSTRING:
1019109998Smarkm		case V_ASN1_UTF8STRING:
1020109998Smarkm		case V_ASN1_OTHER:
1021109998Smarkm		case V_ASN1_SET:
1022109998Smarkm		case V_ASN1_SEQUENCE:
1023109998Smarkm		default:
1024191381Scperciva		if (utype == V_ASN1_BMPSTRING && (len & 1))
1025191381Scperciva			{
1026191381Scperciva			ASN1err(ASN1_F_ASN1_EX_C2I,
1027191381Scperciva					ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
1028191381Scperciva			goto err;
1029191381Scperciva			}
1030191381Scperciva		if (utype == V_ASN1_UNIVERSALSTRING && (len & 3))
1031191381Scperciva			{
1032191381Scperciva			ASN1err(ASN1_F_ASN1_EX_C2I,
1033191381Scperciva					ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
1034191381Scperciva			goto err;
1035191381Scperciva			}
1036109998Smarkm		/* All based on ASN1_STRING and handled the same */
1037160814Ssimon		if (!*pval)
1038160814Ssimon			{
1039109998Smarkm			stmp = ASN1_STRING_type_new(utype);
1040160814Ssimon			if (!stmp)
1041160814Ssimon				{
1042160814Ssimon				ASN1err(ASN1_F_ASN1_EX_C2I,
1043160814Ssimon							ERR_R_MALLOC_FAILURE);
1044109998Smarkm				goto err;
1045160814Ssimon				}
1046160814Ssimon			*pval = (ASN1_VALUE *)stmp;
1047109998Smarkm			}
1048160814Ssimon		else
1049160814Ssimon			{
1050109998Smarkm			stmp = (ASN1_STRING *)*pval;
1051109998Smarkm			stmp->type = utype;
1052160814Ssimon			}
1053109998Smarkm		/* If we've already allocated a buffer use it */
1054160814Ssimon		if (*free_cont)
1055160814Ssimon			{
1056160814Ssimon			if (stmp->data)
1057160814Ssimon				OPENSSL_free(stmp->data);
1058160814Ssimon			stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */
1059109998Smarkm			stmp->length = len;
1060109998Smarkm			*free_cont = 0;
1061160814Ssimon			}
1062160814Ssimon		else
1063160814Ssimon			{
1064160814Ssimon			if (!ASN1_STRING_set(stmp, cont, len))
1065160814Ssimon				{
1066160814Ssimon				ASN1err(ASN1_F_ASN1_EX_C2I,
1067160814Ssimon							ERR_R_MALLOC_FAILURE);
1068109998Smarkm				ASN1_STRING_free(stmp);
1069109998Smarkm				*pval = NULL;
1070109998Smarkm				goto err;
1071160814Ssimon				}
1072109998Smarkm			}
1073160814Ssimon		break;
1074109998Smarkm		}
1075109998Smarkm	/* If ASN1_ANY and NULL type fix up value */
1076160814Ssimon	if (typ && (utype == V_ASN1_NULL))
1077160814Ssimon		 typ->value.ptr = NULL;
1078109998Smarkm
1079109998Smarkm	ret = 1;
1080109998Smarkm	err:
1081160814Ssimon	if (!ret)
1082120631Snectar		{
1083120631Snectar		ASN1_TYPE_free(typ);
1084120631Snectar		if (opval)
1085120631Snectar			*opval = NULL;
1086120631Snectar		}
1087109998Smarkm	return ret;
1088160814Ssimon	}
1089109998Smarkm
1090160814Ssimon
1091160814Ssimon/* This function finds the end of an ASN1 structure when passed its maximum
1092160814Ssimon * length, whether it is indefinite length and a pointer to the content.
1093160814Ssimon * This is more efficient than calling asn1_collect because it does not
1094160814Ssimon * recurse on each indefinite length header.
1095160814Ssimon */
1096160814Ssimon
1097160814Ssimonstatic int asn1_find_end(const unsigned char **in, long len, char inf)
1098160814Ssimon	{
1099160814Ssimon	int expected_eoc;
1100160814Ssimon	long plen;
1101160814Ssimon	const unsigned char *p = *in, *q;
1102160814Ssimon	/* If not indefinite length constructed just add length */
1103160814Ssimon	if (inf == 0)
1104160814Ssimon		{
1105160814Ssimon		*in += len;
1106160814Ssimon		return 1;
1107160814Ssimon		}
1108160814Ssimon	expected_eoc = 1;
1109160814Ssimon	/* Indefinite length constructed form. Find the end when enough EOCs
1110160814Ssimon	 * are found. If more indefinite length constructed headers
1111160814Ssimon	 * are encountered increment the expected eoc count otherwise just
1112160814Ssimon	 * skip to the end of the data.
1113160814Ssimon	 */
1114160814Ssimon	while (len > 0)
1115160814Ssimon		{
1116160814Ssimon		if(asn1_check_eoc(&p, len))
1117160814Ssimon			{
1118160814Ssimon			expected_eoc--;
1119160814Ssimon			if (expected_eoc == 0)
1120160814Ssimon				break;
1121160814Ssimon			len -= 2;
1122160814Ssimon			continue;
1123160814Ssimon			}
1124160814Ssimon		q = p;
1125160814Ssimon		/* Just read in a header: only care about the length */
1126160814Ssimon		if(!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len,
1127160814Ssimon				-1, 0, 0, NULL))
1128160814Ssimon			{
1129160814Ssimon			ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR);
1130160814Ssimon			return 0;
1131160814Ssimon			}
1132160814Ssimon		if (inf)
1133160814Ssimon			expected_eoc++;
1134160814Ssimon		else
1135160814Ssimon			p += plen;
1136160814Ssimon		len -= p - q;
1137160814Ssimon		}
1138160814Ssimon	if (expected_eoc)
1139160814Ssimon		{
1140160814Ssimon		ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC);
1141160814Ssimon		return 0;
1142160814Ssimon		}
1143160814Ssimon	*in = p;
1144160814Ssimon	return 1;
1145160814Ssimon	}
1146109998Smarkm/* This function collects the asn1 data from a constructred string
1147109998Smarkm * type into a buffer. The values of 'in' and 'len' should refer
1148109998Smarkm * to the contents of the constructed type and 'inf' should be set
1149160814Ssimon * if it is indefinite length.
1150109998Smarkm */
1151109998Smarkm
1152194206Ssimon#ifndef ASN1_MAX_STRING_NEST
1153194206Ssimon/* This determines how many levels of recursion are permitted in ASN1
1154194206Ssimon * string types. If it is not limited stack overflows can occur. If set
1155194206Ssimon * to zero no recursion is allowed at all. Although zero should be adequate
1156194206Ssimon * examples exist that require a value of 1. So 5 should be more than enough.
1157194206Ssimon */
1158194206Ssimon#define ASN1_MAX_STRING_NEST 5
1159194206Ssimon#endif
1160194206Ssimon
1161194206Ssimon
1162160814Ssimonstatic int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
1163194206Ssimon			char inf, int tag, int aclass, int depth)
1164160814Ssimon	{
1165160814Ssimon	const unsigned char *p, *q;
1166109998Smarkm	long plen;
1167109998Smarkm	char cst, ininf;
1168109998Smarkm	p = *in;
1169109998Smarkm	inf &= 1;
1170160814Ssimon	/* If no buffer and not indefinite length constructed just pass over
1171160814Ssimon	 * the encoded data */
1172160814Ssimon	if (!buf && !inf)
1173160814Ssimon		{
1174109998Smarkm		*in += len;
1175109998Smarkm		return 1;
1176160814Ssimon		}
1177160814Ssimon	while(len > 0)
1178160814Ssimon		{
1179109998Smarkm		q = p;
1180109998Smarkm		/* Check for EOC */
1181160814Ssimon		if (asn1_check_eoc(&p, len))
1182160814Ssimon			{
1183160814Ssimon			/* EOC is illegal outside indefinite length
1184160814Ssimon			 * constructed form */
1185160814Ssimon			if (!inf)
1186160814Ssimon				{
1187160814Ssimon				ASN1err(ASN1_F_ASN1_COLLECT,
1188160814Ssimon					ASN1_R_UNEXPECTED_EOC);
1189109998Smarkm				return 0;
1190160814Ssimon				}
1191109998Smarkm			inf = 0;
1192109998Smarkm			break;
1193160814Ssimon			}
1194160814Ssimon
1195160814Ssimon		if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p,
1196160814Ssimon					len, tag, aclass, 0, NULL))
1197160814Ssimon			{
1198109998Smarkm			ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR);
1199109998Smarkm			return 0;
1200160814Ssimon			}
1201160814Ssimon
1202109998Smarkm		/* If indefinite length constructed update max length */
1203160814Ssimon		if (cst)
1204160814Ssimon			{
1205194206Ssimon			if (depth >= ASN1_MAX_STRING_NEST)
1206194206Ssimon				{
1207194206Ssimon				ASN1err(ASN1_F_ASN1_COLLECT,
1208194206Ssimon					ASN1_R_NESTED_ASN1_STRING);
1209160814Ssimon				return 0;
1210194206Ssimon				}
1211194206Ssimon			if (!asn1_collect(buf, &p, plen, ininf, tag, aclass,
1212194206Ssimon						depth + 1))
1213194206Ssimon				return 0;
1214160814Ssimon			}
1215160814Ssimon		else if (plen && !collect_data(buf, &p, plen))
1216160814Ssimon			return 0;
1217160814Ssimon		len -= p - q;
1218109998Smarkm		}
1219160814Ssimon	if (inf)
1220160814Ssimon		{
1221109998Smarkm		ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC);
1222109998Smarkm		return 0;
1223160814Ssimon		}
1224109998Smarkm	*in = p;
1225109998Smarkm	return 1;
1226160814Ssimon	}
1227109998Smarkm
1228160814Ssimonstatic int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
1229160814Ssimon	{
1230160814Ssimon	int len;
1231160814Ssimon	if (buf)
1232160814Ssimon		{
1233160814Ssimon		len = buf->length;
1234160814Ssimon		if (!BUF_MEM_grow_clean(buf, len + plen))
1235160814Ssimon			{
1236160814Ssimon			ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE);
1237160814Ssimon			return 0;
1238109998Smarkm			}
1239160814Ssimon		memcpy(buf->data + len, *p, plen);
1240109998Smarkm		}
1241160814Ssimon	*p += plen;
1242160814Ssimon	return 1;
1243160814Ssimon	}
1244109998Smarkm
1245109998Smarkm/* Check for ASN1 EOC and swallow it if found */
1246109998Smarkm
1247160814Ssimonstatic int asn1_check_eoc(const unsigned char **in, long len)
1248160814Ssimon	{
1249160814Ssimon	const unsigned char *p;
1250160814Ssimon	if (len < 2) return 0;
1251109998Smarkm	p = *in;
1252160814Ssimon	if (!p[0] && !p[1])
1253160814Ssimon		{
1254109998Smarkm		*in += 2;
1255109998Smarkm		return 1;
1256160814Ssimon		}
1257160814Ssimon	return 0;
1258109998Smarkm	}
1259109998Smarkm
1260109998Smarkm/* Check an ASN1 tag and length: a bit like ASN1_get_object
1261109998Smarkm * but it sets the length for indefinite length constructed
1262109998Smarkm * form, we don't know the exact length but we can set an
1263109998Smarkm * upper bound to the amount of data available minus the
1264109998Smarkm * header length just read.
1265109998Smarkm */
1266109998Smarkm
1267160814Ssimonstatic int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
1268160814Ssimon				char *inf, char *cst,
1269160814Ssimon				const unsigned char **in, long len,
1270160814Ssimon				int exptag, int expclass, char opt,
1271160814Ssimon				ASN1_TLC *ctx)
1272160814Ssimon	{
1273109998Smarkm	int i;
1274109998Smarkm	int ptag, pclass;
1275109998Smarkm	long plen;
1276160814Ssimon	const unsigned char *p, *q;
1277109998Smarkm	p = *in;
1278109998Smarkm	q = p;
1279109998Smarkm
1280160814Ssimon	if (ctx && ctx->valid)
1281160814Ssimon		{
1282109998Smarkm		i = ctx->ret;
1283109998Smarkm		plen = ctx->plen;
1284109998Smarkm		pclass = ctx->pclass;
1285109998Smarkm		ptag = ctx->ptag;
1286109998Smarkm		p += ctx->hdrlen;
1287160814Ssimon		}
1288160814Ssimon	else
1289160814Ssimon		{
1290109998Smarkm		i = ASN1_get_object(&p, &plen, &ptag, &pclass, len);
1291160814Ssimon		if (ctx)
1292160814Ssimon			{
1293109998Smarkm			ctx->ret = i;
1294109998Smarkm			ctx->plen = plen;
1295109998Smarkm			ctx->pclass = pclass;
1296109998Smarkm			ctx->ptag = ptag;
1297109998Smarkm			ctx->hdrlen = p - q;
1298109998Smarkm			ctx->valid = 1;
1299109998Smarkm			/* If definite length, and no error, length +
1300109998Smarkm			 * header can't exceed total amount of data available.
1301109998Smarkm			 */
1302160814Ssimon			if (!(i & 0x81) && ((plen + ctx->hdrlen) > len))
1303160814Ssimon				{
1304160814Ssimon				ASN1err(ASN1_F_ASN1_CHECK_TLEN,
1305160814Ssimon							ASN1_R_TOO_LONG);
1306109998Smarkm				asn1_tlc_clear(ctx);
1307109998Smarkm				return 0;
1308160814Ssimon				}
1309109998Smarkm			}
1310109998Smarkm		}
1311109998Smarkm
1312160814Ssimon	if (i & 0x80)
1313160814Ssimon		{
1314109998Smarkm		ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER);
1315109998Smarkm		asn1_tlc_clear(ctx);
1316109998Smarkm		return 0;
1317160814Ssimon		}
1318160814Ssimon	if (exptag >= 0)
1319160814Ssimon		{
1320160814Ssimon		if ((exptag != ptag) || (expclass != pclass))
1321160814Ssimon			{
1322160814Ssimon			/* If type is OPTIONAL, not an error:
1323160814Ssimon			 * indicate missing type.
1324109998Smarkm			 */
1325160814Ssimon			if (opt) return -1;
1326109998Smarkm			asn1_tlc_clear(ctx);
1327109998Smarkm			ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG);
1328109998Smarkm			return 0;
1329160814Ssimon			}
1330160814Ssimon		/* We have a tag and class match:
1331160814Ssimon		 * assume we are going to do something with it */
1332160814Ssimon		asn1_tlc_clear(ctx);
1333109998Smarkm		}
1334109998Smarkm
1335160814Ssimon	if (i & 1)
1336160814Ssimon		plen = len - (p - q);
1337109998Smarkm
1338160814Ssimon	if (inf)
1339160814Ssimon		*inf = i & 1;
1340109998Smarkm
1341160814Ssimon	if (cst)
1342160814Ssimon		*cst = i & V_ASN1_CONSTRUCTED;
1343109998Smarkm
1344160814Ssimon	if (olen)
1345160814Ssimon		*olen = plen;
1346109998Smarkm
1347160814Ssimon	if (oclass)
1348160814Ssimon		*oclass = pclass;
1349160814Ssimon
1350160814Ssimon	if (otag)
1351160814Ssimon		*otag = ptag;
1352160814Ssimon
1353109998Smarkm	*in = p;
1354109998Smarkm	return 1;
1355160814Ssimon	}
1356