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

📄 tasn_dec.c

📁 openssl包含TLS
💻 C
📖 第 1 页 / 共 2 页
字号:
/* tasn_dec.c *//* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL * project 2000. *//* ==================================================================== * Copyright (c) 2000 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(unsigned char **in, long len);static int asn1_find_end(unsigned char **in, long len, char inf);static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, int tag, int aclass);static int collect_data(BUF_MEM *buf, unsigned char **p, long plen);static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, char *cst,			unsigned char **in, long len, int exptag, int expclass, char opt, ASN1_TLC *ctx);static int asn1_template_ex_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx);static int asn1_template_noexp_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx);static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, 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 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 */0,	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, unsigned char **in, long len, const ASN1_ITEM *it){	ASN1_TLC c;	ASN1_VALUE *ptmpval = NULL;	if(!pval) pval = &ptmpval;	asn1_tlc_clear(&c);	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, unsigned char **in, long len, const ASN1_TEMPLATE *tt){	ASN1_TLC c;	asn1_tlc_clear(&c);	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, 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;	unsigned char *p, *q, 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) {			p = *in;			imphack = *p;			*p = (unsigned char)((*p & V_ASN1_CONSTRUCTED) | it->utype);		}		ptmpval = cf->asn1_d2i(pval, in, len);		if(tag != -1) *p = 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) {			if(!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_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;		} else seq_nolen = seq_eoc;	/* If indefinite we don't do a length check */		if(!cst) {			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED);			goto err;		}		if(!*pval) {			if(!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)) isopt = 0;			else isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL);			/* attempt to read in field, allowing each to be OPTIONAL */			ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx);			if(!ret) {				errtt = seqtt;				goto err;			} else if(ret == -1) {				/* OPTIONAL component absent. Free and zero the field				 */				ASN1_template_free(pseqval, seqtt);				continue;			}			/* Update length */			len -= p - q;		}		/* Check for EOC if expecting one */		if(seq_eoc && !asn1_check_eoc(&p, len)) {			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MISSING_EOC);			goto err;		}		/* Check all data read */		if(!seq_nolen && len) {			ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH);			goto err;		}		/* If we get here we've got no more data in the SEQUENCE,		 * however we may not have read all fields so check all		 * remaining are OPTIONAL and clear any that are.		 */		for(; i < it->tcount; tt++, i++) {			const ASN1_TEMPLATE *seqtt;			seqtt = asn1_do_adb(pval, tt, 1);			if(!seqtt) goto err;			if(seqtt->flags & ASN1_TFLG_OPTIONAL) {				ASN1_VALUE **pseqval;				pseqval = asn1_get_field_ptr(pval, seqtt);				ASN1_template_free(pseqval, seqtt);			} else {				errtt = seqtt;				ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_FIELD_MISSING);				goto err;			}		}		/* Save encoding */		if(!asn1_enc_save(pval, *in, p - *in, it)) goto auxerr;		*in = p;		if(asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it))				goto auxerr;		return 1;		default:		return 0;	}	auxerr:	ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_AUX_ERROR);	err:	ASN1_item_ex_free(pval, it);	if(errtt) ERR_add_error_data(4, "Field=", errtt->field_name, ", Type=", it->sname);	else ERR_add_error_data(2, "Type=", it->sname);	return 0;}/* Templates are handled with two separate functions. One handles any EXPLICIT tag and the other handles the * rest. */static int asn1_template_ex_d2i(ASN1_VALUE **val, unsigned char **in, long inlen, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx){	int flags, aclass;	int ret;	long len;	unsigned char *p, *q;	char exp_eoc;	if(!val) return 0;	flags = tt->flags;	aclass = flags & ASN1_TFLG_TAG_CLASS;	p = *in;	/* Check if EXPLICIT tag expected */	if(flags & ASN1_TFLG_EXPTAG) {		char cst;		/* Need to work out amount of data available to the inner content and where it		 * starts: so read in EXPLICIT header to get the info.		 */		ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, &p, inlen, tt->tag, aclass, opt, ctx);		q = p;		if(!ret) {			ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR);			return 0;		} else if(ret == -1) return -1;		if(!cst) {			ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);			return 0;		}		/* We've found the field so it can't be OPTIONAL now */		ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx);		if(!ret) {			ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR);			return 0;		}		/* We read the field in OK so update length */		len -= p - q;		if(exp_eoc) {			/* If NDEF we must have an EOC here */			if(!asn1_check_eoc(&p, len)) {				ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ASN1_R_MISSING_EOC);				goto err;			}		} else {			/* Otherwise we must hit the EXPLICIT tag end or its an error */			if(len) {				ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ASN1_R_EXPLICIT_LENGTH_MISMATCH);				goto err;			}		}	} else 		return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx);	*in = p;	return 1;	err:	ASN1_template_free(val, tt);	*val = NULL;	return 0;}static int asn1_template_noexp_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx){	int flags, aclass;	int ret;	unsigned char *p, *q;	if(!val) return 0;	flags = tt->flags;	aclass = flags & ASN1_TFLG_TAG_CLASS;	p = *in;	q = p;	if(flags & ASN1_TFLG_SK_MASK) {		/* SET OF, SEQUENCE OF */		int sktag, skaclass;		char sk_eoc;		/* First work out expected inner tag value */		if(flags & ASN1_TFLG_IMPTAG) {			sktag = tt->tag;			skaclass = aclass;		} else {			skaclass = V_ASN1_UNIVERSAL;			if(flags & ASN1_TFLG_SET_OF) sktag = V_ASN1_SET;			else sktag = V_ASN1_SEQUENCE;		}		/* Get the tag */		ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, &p, len, sktag, skaclass, opt, ctx);		if(!ret) {			ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR);			return 0;		} else if(ret == -1) return -1;

⌨️ 快捷键说明

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