X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Fasn1%2Ftasn_dec.c;h=75bbafacd723d093184c7e4e7d77e833520ff893;hb=536b73e78e5f0d5d81644742591d7e58ed5ddc07;hp=6b0c2481732ac2f96323ecfabeef33d0ca385adc;hpb=a9daa46758d6150e42c925d42807e6ae20182d89;p=oweals%2Fopenssl.git diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index 6b0c248173..75bbafacd7 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -75,6 +75,25 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, unsigned char **in, long le 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 @@ -132,8 +151,18 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1 switch(it->itype) { case ASN1_ITYPE_PRIMITIVE: - if(it->templates) + 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; @@ -217,14 +246,23 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1 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(&pchval, &p, len, tt, 1, ctx); + 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 */ @@ -232,31 +270,26 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1 /* Otherwise must be an ASN1 parsing error */ errtt = tt; ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); - return 0; + goto err; } /* Did we fall off the end without reading anything? */ if(i == it->tcount) { /* If OPTIONAL, this is OK */ - if(opt) return -1; - ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE); - return 0; - } - /* Otherwise we got a match, allocate structure and populate it */ - if(!*pval) { - if(!ASN1_item_ex_new(pval, it)) { - errtt = tt; - ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); - return 0; + 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; } - pchptr = asn1_get_field_ptr(pval, tt); - *pchptr = pchval; 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; @@ -383,7 +416,7 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1 * rest. */ -int asn1_template_ex_d2i(ASN1_VALUE **val, unsigned char **in, long inlen, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx) +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; @@ -483,7 +516,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, unsigned char **in, long le ASN1_VALUE *vtmp; while(sk_num(sktmp) > 0) { vtmp = (ASN1_VALUE *)sk_pop(sktmp); - ASN1_item_ex_free(&vtmp, tt->item); + ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); } } @@ -506,7 +539,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, unsigned char **in, long le break; } skfield = NULL; - if(!ASN1_item_ex_d2i(&skfield, &p, len, tt->item, -1, 0, 0, ctx)) { + if(!ASN1_item_ex_d2i(&skfield, &p, len, ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx)) { ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ERR_R_NESTED_ASN1_ERROR); goto err; } @@ -522,14 +555,14 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, unsigned char **in, long le } } else if(flags & ASN1_TFLG_IMPTAG) { /* IMPLICIT tagging */ - ret = ASN1_item_ex_d2i(val, &p, len, tt->item, tt->tag, aclass, opt, ctx); + ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx); if(!ret) { ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ERR_R_NESTED_ASN1_ERROR); goto err; } else if(ret == -1) return -1; } else { /* Nothing special */ - ret = ASN1_item_ex_d2i(val, &p, len, tt->item, -1, 0, opt, ctx); + ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), -1, 0, opt, ctx); if(!ret) { ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ERR_R_NESTED_ASN1_ERROR); goto err; @@ -598,8 +631,13 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, unsigned char **in, long inl } else if(ret == -1) return -1; /* SEQUENCE, SET and "OTHER" are left in encoded form */ if((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) { + /* Clear context cache for type OTHER because the auto clear when + * we have a exact match wont work + */ + if(utype == V_ASN1_OTHER) { + asn1_tlc_clear(ctx); /* SEQUENCE and SET must be constructed */ - if((utype != V_ASN1_OTHER) && !cst) { + } else if(!cst) { ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_TYPE_NOT_CONSTRUCTED); return 0; } @@ -627,7 +665,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, unsigned char **in, long inl if(!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL)) goto err; len = buf.length; /* Append a final null to string */ - if(!BUF_MEM_grow(&buf, len + 1)) { + if(!BUF_MEM_grow_clean(&buf, len + 1)) { ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); return 0; } @@ -820,7 +858,7 @@ static int collect_data(BUF_MEM *buf, unsigned char **p, long plen) int len; if(buf) { len = buf->length; - if(!BUF_MEM_grow(buf, len + plen)) { + if(!BUF_MEM_grow_clean(buf, len + plen)) { ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE); return 0; } @@ -876,17 +914,17 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *i ctx->ptag = ptag; ctx->hdrlen = p - q; ctx->valid = 1; - /* If definite length, length + header can't exceed total - * amount of data available. + /* If definite length, and no error, length + + * header can't exceed total amount of data available. */ - if(!(i & 1) && ((plen + ctx->hdrlen) > len)) { + if(!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_TOO_LONG); asn1_tlc_clear(ctx); return 0; } } } - + if(i & 0x80) { ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER); asn1_tlc_clear(ctx);