⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tasn_dec.c

📁 开源的ssl算法openssl,版本0.9.8H
💻 C
📖 第 1 页 / 共 3 页
字号:
/* tasn_dec.c *//* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL * project 2000. *//* ==================================================================== * Copyright (c) 2000-2005 The OpenSSL Project.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * 3. All advertising materials mentioning features or use of this *    software must display the following acknowledgment: *    "This product includes software developed by the OpenSSL Project *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to *    endorse or promote products derived from this software without *    prior written permission. For written permission, please contact *    licensing@OpenSSL.org. * * 5. Products derived from this software may not be called "OpenSSL" *    nor may "OpenSSL" appear in their names without prior written *    permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following *    acknowledgment: *    "This product includes software developed by the OpenSSL Project *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com).  This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */#include <stddef.h>#include <string.h>#include <openssl/asn1.h>#include <openssl/asn1t.h>#include <openssl/objects.h>#include <openssl/buffer.h>#include <openssl/err.h>static int asn1_check_eoc(const unsigned char **in, long len);static int asn1_find_end(const unsigned char **in, long len, char inf);static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,				char inf, int tag, int aclass);static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen);static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,				char *inf, char *cst,				const unsigned char **in, long len,				int exptag, int expclass, char opt,				ASN1_TLC *ctx);static int asn1_template_ex_d2i(ASN1_VALUE **pval,				const unsigned char **in, long len,				const ASN1_TEMPLATE *tt, char opt,				ASN1_TLC *ctx);static int asn1_template_noexp_d2i(ASN1_VALUE **val,				const unsigned char **in, long len,				const ASN1_TEMPLATE *tt, char opt,				ASN1_TLC *ctx);static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,				const unsigned char **in, long len,				const ASN1_ITEM *it,				int tag, int aclass, char opt, ASN1_TLC *ctx);/* Table to convert tags to bit values, used for MSTRING type */static const unsigned long tag2bit[32] = {0,	0,	0,	B_ASN1_BIT_STRING,	/* tags  0 -  3 */B_ASN1_OCTET_STRING,	0,	0,		B_ASN1_UNKNOWN,/* tags  4- 7 */B_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,/* tags  8-11 */B_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */B_ASN1_SEQUENCE,0,B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING,       /* tags 20-22 */B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME,			       /* tags 23-24 */	B_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING,  /* tags 25-27 */B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */	};unsigned long ASN1_tag2bit(int tag)	{	if ((tag < 0) || (tag > 30)) return 0;	return tag2bit[tag];	}/* Macro to initialize and invalidate the cache */#define asn1_tlc_clear(c)	if (c) (c)->valid = 0/* Decode an ASN1 item, this currently behaves just  * like a standard 'd2i' function. 'in' points to  * a buffer to read the data from, in future we will * have more advanced versions that can input data * a piece at a time and this will simply be a special * case. */ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,		const unsigned char **in, long len, const ASN1_ITEM *it)	{	ASN1_TLC c;	ASN1_VALUE *ptmpval = NULL;	if (!pval)		pval = &ptmpval;	c.valid = 0;	if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) 		return *pval;	return NULL;	}int ASN1_template_d2i(ASN1_VALUE **pval,		const unsigned char **in, long len, const ASN1_TEMPLATE *tt)	{	ASN1_TLC c;	c.valid = 0;	return asn1_template_ex_d2i(pval, in, len, tt, 0, &c);	}/* Decode an item, taking care of IMPLICIT tagging, if any. * If 'opt' set and tag mismatch return -1 to handle OPTIONAL */int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,			const ASN1_ITEM *it,			int tag, int aclass, char opt, ASN1_TLC *ctx)	{	const ASN1_TEMPLATE *tt, *errtt = NULL;	const ASN1_COMPAT_FUNCS *cf;	const ASN1_EXTERN_FUNCS *ef;	const ASN1_AUX *aux = it->funcs;	ASN1_aux_cb *asn1_cb;	const unsigned char *p = NULL, *q;	unsigned char *wp=NULL;	/* BIG FAT WARNING!  BREAKS CONST WHERE USED */	unsigned char imphack = 0, oclass;	char seq_eoc, seq_nolen, cst, isopt;	long tmplen;	int i;	int otag;	int ret = 0;	ASN1_VALUE *pchval, **pchptr, *ptmpval;	if (!pval)		return 0;	if (aux && aux->asn1_cb)		asn1_cb = aux->asn1_cb;	else asn1_cb = 0;	switch(it->itype)		{		case ASN1_ITYPE_PRIMITIVE:		if (it->templates)			{			/* tagging or OPTIONAL is currently illegal on an item			 * template because the flags can't get passed down.			 * In practice this isn't a problem: we include the			 * relevant flags from the item template in the			 * template itself.			 */			if ((tag != -1) || opt)				{				ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,				ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);				goto err;				}			return asn1_template_ex_d2i(pval, in, len,					it->templates, opt, ctx);		}		return asn1_d2i_ex_primitive(pval, in, len, it,						tag, aclass, opt, ctx);		break;		case ASN1_ITYPE_MSTRING:		p = *in;		/* Just read in tag and class */		ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,						&p, len, -1, 0, 1, ctx);		if (!ret)			{			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,					ERR_R_NESTED_ASN1_ERROR);			goto err;			}		/* Must be UNIVERSAL class */		if (oclass != V_ASN1_UNIVERSAL)			{			/* If OPTIONAL, assume this is OK */			if (opt) return -1;			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,					ASN1_R_MSTRING_NOT_UNIVERSAL);			goto err;			}		/* Check tag matches bit map */		if (!(ASN1_tag2bit(otag) & it->utype))			{			/* If OPTIONAL, assume this is OK */			if (opt)				return -1;			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,					ASN1_R_MSTRING_WRONG_TAG);			goto err;			}		return asn1_d2i_ex_primitive(pval, in, len,						it, otag, 0, 0, ctx);		case ASN1_ITYPE_EXTERN:		/* Use new style d2i */		ef = it->funcs;		return ef->asn1_ex_d2i(pval, in, len,						it, tag, aclass, opt, ctx);		case ASN1_ITYPE_COMPAT:		/* we must resort to old style evil hackery */		cf = it->funcs;		/* If OPTIONAL see if it is there */		if (opt)			{			int exptag;			p = *in;			if (tag == -1)				exptag = it->utype;			else exptag = tag;			/* Don't care about anything other than presence			 * of expected tag */			ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL,					&p, len, exptag, aclass, 1, ctx);			if (!ret)				{				ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,					ERR_R_NESTED_ASN1_ERROR);				goto err;				}			if (ret == -1)				return -1;			}		/* This is the old style evil hack IMPLICIT handling:		 * since the underlying code is expecting a tag and		 * class other than the one present we change the		 * buffer temporarily then change it back afterwards.		 * This doesn't and never did work for tags > 30.		 *		 * Yes this is *horrible* but it is only needed for		 * old style d2i which will hopefully not be around		 * for much longer.		 * FIXME: should copy the buffer then modify it so		 * the input buffer can be const: we should *always*		 * copy because the old style d2i might modify the		 * buffer.		 */		if (tag != -1)			{			wp = *(unsigned char **)in;			imphack = *wp;			if (p == NULL)				{				ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,					ERR_R_NESTED_ASN1_ERROR);				goto err;				}			*wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED)								| it->utype);			}		ptmpval = cf->asn1_d2i(pval, in, len);		if (tag != -1)			*wp = imphack;		if (ptmpval)			return 1;		ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR);		goto err;		case ASN1_ITYPE_CHOICE:		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it))				goto auxerr;		/* Allocate structure */		if (!*pval && !ASN1_item_ex_new(pval, it))			{			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,						ERR_R_NESTED_ASN1_ERROR);			goto err;			}		/* CHOICE type, try each possibility in turn */		pchval = NULL;		p = *in;		for (i = 0, tt=it->templates; i < it->tcount; i++, tt++)			{			pchptr = asn1_get_field_ptr(pval, tt);			/* We mark field as OPTIONAL so its absence			 * can be recognised.			 */			ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx);			/* If field not present, try the next one */			if (ret == -1)				continue;			/* If positive return, read OK, break loop */			if (ret > 0)				break;			/* Otherwise must be an ASN1 parsing error */			errtt = tt;			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,						ERR_R_NESTED_ASN1_ERROR);			goto err;			}		/* Did we fall off the end without reading anything? */		if (i == it->tcount)			{			/* If OPTIONAL, this is OK */			if (opt)				{				/* Free and zero it */				ASN1_item_ex_free(pval, it);				return -1;				}			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,					ASN1_R_NO_MATCHING_CHOICE_TYPE);			goto err;			}		asn1_set_choice_selector(pval, i, it);		*in = p;		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it))				goto auxerr;		return 1;		case ASN1_ITYPE_NDEF_SEQUENCE:		case ASN1_ITYPE_SEQUENCE:		p = *in;		tmplen = len;		/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */		if (tag == -1)			{			tag = V_ASN1_SEQUENCE;			aclass = V_ASN1_UNIVERSAL;			}		/* Get SEQUENCE length and update len, p */		ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst,					&p, len, tag, aclass, opt, ctx);		if (!ret)			{			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,					ERR_R_NESTED_ASN1_ERROR);			goto err;			}		else if (ret == -1)			return -1;		if (aux && (aux->flags & ASN1_AFLG_BROKEN))			{			len = tmplen - (p - *in);			seq_nolen = 1;			}		/* If indefinite we don't do a length check */		else seq_nolen = seq_eoc;		if (!cst)			{			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,				ASN1_R_SEQUENCE_NOT_CONSTRUCTED);			goto err;			}		if (!*pval && !ASN1_item_ex_new(pval, it))			{			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,				ERR_R_NESTED_ASN1_ERROR);			goto err;			}		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it))				goto auxerr;		/* Get each field entry */		for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)			{			const ASN1_TEMPLATE *seqtt;			ASN1_VALUE **pseqval;			seqtt = asn1_do_adb(pval, tt, 1);			if (!seqtt)				goto err;			pseqval = asn1_get_field_ptr(pval, seqtt);			/* Have we ran out of data? */			if (!len)				break;			q = p;			if (asn1_check_eoc(&p, len))				{				if (!seq_eoc)					{					ASN1err(ASN1_F_ASN1_ITEM_EX_D2I,							ASN1_R_UNEXPECTED_EOC);					goto err;					}				len -= p - q;				seq_eoc = 0;				q = p;				break;				}			/* This determines the OPTIONAL flag value. The field			 * cannot be omitted if it is the last of a SEQUENCE			 * and there is still data to be read. This isn't			 * strictly necessary but it increases efficiency in			 * some cases.			 */			if (i == (it->tcount - 1))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -