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
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;
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 */
/* 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))
* 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;
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));
}
}
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;
}
}
} 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;
} 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;
}
}
}
}
-
+
if(i & 0x80) {
ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER);
asn1_tlc_clear(ctx);