#include <stddef.h>
+#include <string.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
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))
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;
ASN1_TYPE *typ = NULL;
int ret = 0;
const ASN1_PRIMITIVE_FUNCS *pf;
+ ASN1_INTEGER **tint;
pf = it->funcs;
if(pf && pf->prim_c2i) return pf->prim_c2i(pval, cont, len, utype, free_cont, it);
/* If ANY type clear type and set pointer to internal value */
case V_ASN1_NEG_INTEGER:
case V_ASN1_ENUMERATED:
case V_ASN1_NEG_ENUMERATED:
- if(!c2i_ASN1_INTEGER((ASN1_INTEGER **)pval, &cont, len)) goto err;
+ tint = (ASN1_INTEGER **)pval;
+ if(!c2i_ASN1_INTEGER(tint, &cont, len)) goto err;
+ /* Fixup type to match the expected form */
+ (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
break;
case V_ASN1_OCTET_STRING: