1109998Smarkm/* tasn_dec.c */ 2296465Sdelphij/* 3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4296465Sdelphij * 2000. 5109998Smarkm */ 6109998Smarkm/* ==================================================================== 7160814Ssimon * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. 8109998Smarkm * 9109998Smarkm * Redistribution and use in source and binary forms, with or without 10109998Smarkm * modification, are permitted provided that the following conditions 11109998Smarkm * are met: 12109998Smarkm * 13109998Smarkm * 1. Redistributions of source code must retain the above copyright 14296465Sdelphij * notice, this list of conditions and the following disclaimer. 15109998Smarkm * 16109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 17109998Smarkm * notice, this list of conditions and the following disclaimer in 18109998Smarkm * the documentation and/or other materials provided with the 19109998Smarkm * distribution. 20109998Smarkm * 21109998Smarkm * 3. All advertising materials mentioning features or use of this 22109998Smarkm * software must display the following acknowledgment: 23109998Smarkm * "This product includes software developed by the OpenSSL Project 24109998Smarkm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25109998Smarkm * 26109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27109998Smarkm * endorse or promote products derived from this software without 28109998Smarkm * prior written permission. For written permission, please contact 29109998Smarkm * licensing@OpenSSL.org. 30109998Smarkm * 31109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 32109998Smarkm * nor may "OpenSSL" appear in their names without prior written 33109998Smarkm * permission of the OpenSSL Project. 34109998Smarkm * 35109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 36109998Smarkm * acknowledgment: 37109998Smarkm * "This product includes software developed by the OpenSSL Project 38109998Smarkm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39109998Smarkm * 40109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 52109998Smarkm * ==================================================================== 53109998Smarkm * 54109998Smarkm * This product includes cryptographic software written by Eric Young 55109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 56109998Smarkm * Hudson (tjh@cryptsoft.com). 57109998Smarkm * 58109998Smarkm */ 59109998Smarkm 60109998Smarkm#include <stddef.h> 61109998Smarkm#include <string.h> 62109998Smarkm#include <openssl/asn1.h> 63109998Smarkm#include <openssl/asn1t.h> 64109998Smarkm#include <openssl/objects.h> 65109998Smarkm#include <openssl/buffer.h> 66109998Smarkm#include <openssl/err.h> 67109998Smarkm 68160814Ssimonstatic int asn1_check_eoc(const unsigned char **in, long len); 69160814Ssimonstatic int asn1_find_end(const unsigned char **in, long len, char inf); 70109998Smarkm 71160814Ssimonstatic int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, 72296465Sdelphij char inf, int tag, int aclass, int depth); 73160814Ssimon 74160814Ssimonstatic int collect_data(BUF_MEM *buf, const unsigned char **p, long plen); 75160814Ssimon 76160814Ssimonstatic int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, 77296465Sdelphij char *inf, char *cst, 78296465Sdelphij const unsigned char **in, long len, 79296465Sdelphij int exptag, int expclass, char opt, ASN1_TLC *ctx); 80160814Ssimon 81160814Ssimonstatic int asn1_template_ex_d2i(ASN1_VALUE **pval, 82296465Sdelphij const unsigned char **in, long len, 83296465Sdelphij const ASN1_TEMPLATE *tt, char opt, 84296465Sdelphij ASN1_TLC *ctx); 85160814Ssimonstatic int asn1_template_noexp_d2i(ASN1_VALUE **val, 86296465Sdelphij const unsigned char **in, long len, 87296465Sdelphij const ASN1_TEMPLATE *tt, char opt, 88296465Sdelphij ASN1_TLC *ctx); 89160814Ssimonstatic int asn1_d2i_ex_primitive(ASN1_VALUE **pval, 90296465Sdelphij const unsigned char **in, long len, 91296465Sdelphij const ASN1_ITEM *it, 92296465Sdelphij int tag, int aclass, char opt, 93296465Sdelphij ASN1_TLC *ctx); 94160814Ssimon 95109998Smarkm/* Table to convert tags to bit values, used for MSTRING type */ 96167612Ssimonstatic const unsigned long tag2bit[32] = { 97296465Sdelphij /* tags 0 - 3 */ 98296465Sdelphij 0, 0, 0, B_ASN1_BIT_STRING, 99296465Sdelphij /* tags 4- 7 */ 100296465Sdelphij B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN, 101296465Sdelphij /* tags 8-11 */ 102296465Sdelphij B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, 103296465Sdelphij /* tags 12-15 */ 104296465Sdelphij B_ASN1_UTF8STRING, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, 105296465Sdelphij /* tags 16-19 */ 106296465Sdelphij B_ASN1_SEQUENCE, 0, B_ASN1_NUMERICSTRING, B_ASN1_PRINTABLESTRING, 107296465Sdelphij /* tags 20-22 */ 108296465Sdelphij B_ASN1_T61STRING, B_ASN1_VIDEOTEXSTRING, B_ASN1_IA5STRING, 109296465Sdelphij /* tags 23-24 */ 110296465Sdelphij B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, 111296465Sdelphij /* tags 25-27 */ 112296465Sdelphij B_ASN1_GRAPHICSTRING, B_ASN1_ISO64STRING, B_ASN1_GENERALSTRING, 113296465Sdelphij /* tags 28-31 */ 114296465Sdelphij B_ASN1_UNIVERSALSTRING, B_ASN1_UNKNOWN, B_ASN1_BMPSTRING, B_ASN1_UNKNOWN, 115296465Sdelphij}; 116109998Smarkm 117109998Smarkmunsigned long ASN1_tag2bit(int tag) 118296465Sdelphij{ 119296465Sdelphij if ((tag < 0) || (tag > 30)) 120296465Sdelphij return 0; 121296465Sdelphij return tag2bit[tag]; 122296465Sdelphij} 123109998Smarkm 124109998Smarkm/* Macro to initialize and invalidate the cache */ 125109998Smarkm 126296465Sdelphij#define asn1_tlc_clear(c) if (c) (c)->valid = 0 127109998Smarkm 128296465Sdelphij/* 129296465Sdelphij * Decode an ASN1 item, this currently behaves just like a standard 'd2i' 130296465Sdelphij * function. 'in' points to a buffer to read the data from, in future we 131296465Sdelphij * will have more advanced versions that can input data a piece at a time and 132296465Sdelphij * this will simply be a special case. 133109998Smarkm */ 134109998Smarkm 135160814SsimonASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, 136296465Sdelphij const unsigned char **in, long len, 137296465Sdelphij const ASN1_ITEM *it) 138296465Sdelphij{ 139296465Sdelphij ASN1_TLC c; 140296465Sdelphij ASN1_VALUE *ptmpval = NULL; 141296465Sdelphij if (!pval) 142296465Sdelphij pval = &ptmpval; 143296465Sdelphij c.valid = 0; 144296465Sdelphij if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) 145296465Sdelphij return *pval; 146296465Sdelphij return NULL; 147296465Sdelphij} 148109998Smarkm 149160814Ssimonint ASN1_template_d2i(ASN1_VALUE **pval, 150296465Sdelphij const unsigned char **in, long len, 151296465Sdelphij const ASN1_TEMPLATE *tt) 152296465Sdelphij{ 153296465Sdelphij ASN1_TLC c; 154296465Sdelphij c.valid = 0; 155296465Sdelphij return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); 156296465Sdelphij} 157109998Smarkm 158296465Sdelphij/* 159296465Sdelphij * Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and 160296465Sdelphij * tag mismatch return -1 to handle OPTIONAL 161109998Smarkm */ 162109998Smarkm 163160814Ssimonint ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, 164296465Sdelphij const ASN1_ITEM *it, 165296465Sdelphij int tag, int aclass, char opt, ASN1_TLC *ctx) 166296465Sdelphij{ 167296465Sdelphij const ASN1_TEMPLATE *tt, *errtt = NULL; 168296465Sdelphij const ASN1_COMPAT_FUNCS *cf; 169296465Sdelphij const ASN1_EXTERN_FUNCS *ef; 170296465Sdelphij const ASN1_AUX *aux = it->funcs; 171296465Sdelphij ASN1_aux_cb *asn1_cb; 172296465Sdelphij const unsigned char *p = NULL, *q; 173296465Sdelphij unsigned char *wp = NULL; /* BIG FAT WARNING! BREAKS CONST WHERE USED */ 174296465Sdelphij unsigned char imphack = 0, oclass; 175296465Sdelphij char seq_eoc, seq_nolen, cst, isopt; 176296465Sdelphij long tmplen; 177296465Sdelphij int i; 178296465Sdelphij int otag; 179296465Sdelphij int ret = 0; 180296465Sdelphij ASN1_VALUE **pchptr, *ptmpval; 181296465Sdelphij int combine = aclass & ASN1_TFLG_COMBINE; 182296465Sdelphij aclass &= ~ASN1_TFLG_COMBINE; 183296465Sdelphij if (!pval) 184296465Sdelphij return 0; 185296465Sdelphij if (aux && aux->asn1_cb) 186296465Sdelphij asn1_cb = aux->asn1_cb; 187296465Sdelphij else 188296465Sdelphij asn1_cb = 0; 189109998Smarkm 190296465Sdelphij switch (it->itype) { 191296465Sdelphij case ASN1_ITYPE_PRIMITIVE: 192296465Sdelphij if (it->templates) { 193296465Sdelphij /* 194296465Sdelphij * tagging or OPTIONAL is currently illegal on an item template 195296465Sdelphij * because the flags can't get passed down. In practice this 196296465Sdelphij * isn't a problem: we include the relevant flags from the item 197296465Sdelphij * template in the template itself. 198296465Sdelphij */ 199296465Sdelphij if ((tag != -1) || opt) { 200296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 201296465Sdelphij ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); 202296465Sdelphij goto err; 203296465Sdelphij } 204296465Sdelphij return asn1_template_ex_d2i(pval, in, len, 205296465Sdelphij it->templates, opt, ctx); 206296465Sdelphij } 207296465Sdelphij return asn1_d2i_ex_primitive(pval, in, len, it, 208296465Sdelphij tag, aclass, opt, ctx); 209296465Sdelphij break; 210109998Smarkm 211296465Sdelphij case ASN1_ITYPE_MSTRING: 212296465Sdelphij p = *in; 213296465Sdelphij /* Just read in tag and class */ 214296465Sdelphij ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, 215296465Sdelphij &p, len, -1, 0, 1, ctx); 216296465Sdelphij if (!ret) { 217296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 218296465Sdelphij goto err; 219296465Sdelphij } 220160814Ssimon 221296465Sdelphij /* Must be UNIVERSAL class */ 222296465Sdelphij if (oclass != V_ASN1_UNIVERSAL) { 223296465Sdelphij /* If OPTIONAL, assume this is OK */ 224296465Sdelphij if (opt) 225296465Sdelphij return -1; 226296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL); 227296465Sdelphij goto err; 228296465Sdelphij } 229296465Sdelphij /* Check tag matches bit map */ 230296465Sdelphij if (!(ASN1_tag2bit(otag) & it->utype)) { 231296465Sdelphij /* If OPTIONAL, assume this is OK */ 232296465Sdelphij if (opt) 233296465Sdelphij return -1; 234296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MSTRING_WRONG_TAG); 235296465Sdelphij goto err; 236296465Sdelphij } 237296465Sdelphij return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx); 238109998Smarkm 239296465Sdelphij case ASN1_ITYPE_EXTERN: 240296465Sdelphij /* Use new style d2i */ 241296465Sdelphij ef = it->funcs; 242296465Sdelphij return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx); 243109998Smarkm 244296465Sdelphij case ASN1_ITYPE_COMPAT: 245296465Sdelphij /* we must resort to old style evil hackery */ 246296465Sdelphij cf = it->funcs; 247109998Smarkm 248296465Sdelphij /* If OPTIONAL see if it is there */ 249296465Sdelphij if (opt) { 250296465Sdelphij int exptag; 251296465Sdelphij p = *in; 252296465Sdelphij if (tag == -1) 253296465Sdelphij exptag = it->utype; 254296465Sdelphij else 255296465Sdelphij exptag = tag; 256296465Sdelphij /* 257296465Sdelphij * Don't care about anything other than presence of expected tag 258296465Sdelphij */ 259160814Ssimon 260296465Sdelphij ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL, 261296465Sdelphij &p, len, exptag, aclass, 1, ctx); 262296465Sdelphij if (!ret) { 263296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 264296465Sdelphij goto err; 265296465Sdelphij } 266296465Sdelphij if (ret == -1) 267296465Sdelphij return -1; 268296465Sdelphij } 269160814Ssimon 270296465Sdelphij /* 271296465Sdelphij * This is the old style evil hack IMPLICIT handling: since the 272296465Sdelphij * underlying code is expecting a tag and class other than the one 273296465Sdelphij * present we change the buffer temporarily then change it back 274296465Sdelphij * afterwards. This doesn't and never did work for tags > 30. Yes 275296465Sdelphij * this is *horrible* but it is only needed for old style d2i which 276296465Sdelphij * will hopefully not be around for much longer. FIXME: should copy 277296465Sdelphij * the buffer then modify it so the input buffer can be const: we 278296465Sdelphij * should *always* copy because the old style d2i might modify the 279296465Sdelphij * buffer. 280296465Sdelphij */ 281109998Smarkm 282296465Sdelphij if (tag != -1) { 283296465Sdelphij wp = *(unsigned char **)in; 284296465Sdelphij imphack = *wp; 285296465Sdelphij if (p == NULL) { 286296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 287296465Sdelphij goto err; 288296465Sdelphij } 289296465Sdelphij *wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED) 290296465Sdelphij | it->utype); 291296465Sdelphij } 292109998Smarkm 293296465Sdelphij ptmpval = cf->asn1_d2i(pval, in, len); 294109998Smarkm 295296465Sdelphij if (tag != -1) 296296465Sdelphij *wp = imphack; 297109998Smarkm 298296465Sdelphij if (ptmpval) 299296465Sdelphij return 1; 300160814Ssimon 301296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 302296465Sdelphij goto err; 303109998Smarkm 304296465Sdelphij case ASN1_ITYPE_CHOICE: 305296465Sdelphij if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it)) 306296465Sdelphij goto auxerr; 307296465Sdelphij if (*pval) { 308296465Sdelphij /* Free up and zero CHOICE value if initialised */ 309296465Sdelphij i = asn1_get_choice_selector(pval, it); 310296465Sdelphij if ((i >= 0) && (i < it->tcount)) { 311296465Sdelphij tt = it->templates + i; 312296465Sdelphij pchptr = asn1_get_field_ptr(pval, tt); 313296465Sdelphij ASN1_template_free(pchptr, tt); 314296465Sdelphij asn1_set_choice_selector(pval, -1, it); 315296465Sdelphij } 316296465Sdelphij } else if (!ASN1_item_ex_new(pval, it)) { 317296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 318296465Sdelphij goto err; 319296465Sdelphij } 320296465Sdelphij /* CHOICE type, try each possibility in turn */ 321296465Sdelphij p = *in; 322296465Sdelphij for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { 323296465Sdelphij pchptr = asn1_get_field_ptr(pval, tt); 324296465Sdelphij /* 325296465Sdelphij * We mark field as OPTIONAL so its absence can be recognised. 326296465Sdelphij */ 327296465Sdelphij ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx); 328296465Sdelphij /* If field not present, try the next one */ 329296465Sdelphij if (ret == -1) 330296465Sdelphij continue; 331296465Sdelphij /* If positive return, read OK, break loop */ 332296465Sdelphij if (ret > 0) 333296465Sdelphij break; 334296465Sdelphij /* Otherwise must be an ASN1 parsing error */ 335296465Sdelphij errtt = tt; 336296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 337296465Sdelphij goto err; 338296465Sdelphij } 339109998Smarkm 340296465Sdelphij /* Did we fall off the end without reading anything? */ 341296465Sdelphij if (i == it->tcount) { 342296465Sdelphij /* If OPTIONAL, this is OK */ 343296465Sdelphij if (opt) { 344296465Sdelphij /* Free and zero it */ 345296465Sdelphij ASN1_item_ex_free(pval, it); 346296465Sdelphij return -1; 347296465Sdelphij } 348296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE); 349296465Sdelphij goto err; 350296465Sdelphij } 351109998Smarkm 352296465Sdelphij asn1_set_choice_selector(pval, i, it); 353296465Sdelphij *in = p; 354296465Sdelphij if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it)) 355296465Sdelphij goto auxerr; 356296465Sdelphij return 1; 357160814Ssimon 358296465Sdelphij case ASN1_ITYPE_NDEF_SEQUENCE: 359296465Sdelphij case ASN1_ITYPE_SEQUENCE: 360296465Sdelphij p = *in; 361296465Sdelphij tmplen = len; 362160814Ssimon 363296465Sdelphij /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ 364296465Sdelphij if (tag == -1) { 365296465Sdelphij tag = V_ASN1_SEQUENCE; 366296465Sdelphij aclass = V_ASN1_UNIVERSAL; 367296465Sdelphij } 368296465Sdelphij /* Get SEQUENCE length and update len, p */ 369296465Sdelphij ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, 370296465Sdelphij &p, len, tag, aclass, opt, ctx); 371296465Sdelphij if (!ret) { 372296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 373296465Sdelphij goto err; 374296465Sdelphij } else if (ret == -1) 375296465Sdelphij return -1; 376296465Sdelphij if (aux && (aux->flags & ASN1_AFLG_BROKEN)) { 377296465Sdelphij len = tmplen - (p - *in); 378296465Sdelphij seq_nolen = 1; 379296465Sdelphij } 380296465Sdelphij /* If indefinite we don't do a length check */ 381296465Sdelphij else 382296465Sdelphij seq_nolen = seq_eoc; 383296465Sdelphij if (!cst) { 384296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); 385296465Sdelphij goto err; 386296465Sdelphij } 387109998Smarkm 388296465Sdelphij if (!*pval && !ASN1_item_ex_new(pval, it)) { 389296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 390296465Sdelphij goto err; 391296465Sdelphij } 392109998Smarkm 393296465Sdelphij if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it)) 394296465Sdelphij goto auxerr; 395109998Smarkm 396296465Sdelphij /* Free up and zero any ADB found */ 397296465Sdelphij for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { 398296465Sdelphij if (tt->flags & ASN1_TFLG_ADB_MASK) { 399296465Sdelphij const ASN1_TEMPLATE *seqtt; 400296465Sdelphij ASN1_VALUE **pseqval; 401296465Sdelphij seqtt = asn1_do_adb(pval, tt, 1); 402296465Sdelphij pseqval = asn1_get_field_ptr(pval, seqtt); 403296465Sdelphij ASN1_template_free(pseqval, seqtt); 404296465Sdelphij } 405296465Sdelphij } 406160814Ssimon 407296465Sdelphij /* Get each field entry */ 408296465Sdelphij for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { 409296465Sdelphij const ASN1_TEMPLATE *seqtt; 410296465Sdelphij ASN1_VALUE **pseqval; 411296465Sdelphij seqtt = asn1_do_adb(pval, tt, 1); 412296465Sdelphij if (!seqtt) 413296465Sdelphij goto err; 414296465Sdelphij pseqval = asn1_get_field_ptr(pval, seqtt); 415296465Sdelphij /* Have we ran out of data? */ 416296465Sdelphij if (!len) 417296465Sdelphij break; 418296465Sdelphij q = p; 419296465Sdelphij if (asn1_check_eoc(&p, len)) { 420296465Sdelphij if (!seq_eoc) { 421296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_UNEXPECTED_EOC); 422296465Sdelphij goto err; 423296465Sdelphij } 424296465Sdelphij len -= p - q; 425296465Sdelphij seq_eoc = 0; 426296465Sdelphij q = p; 427296465Sdelphij break; 428296465Sdelphij } 429296465Sdelphij /* 430296465Sdelphij * This determines the OPTIONAL flag value. The field cannot be 431296465Sdelphij * omitted if it is the last of a SEQUENCE and there is still 432296465Sdelphij * data to be read. This isn't strictly necessary but it 433296465Sdelphij * increases efficiency in some cases. 434296465Sdelphij */ 435296465Sdelphij if (i == (it->tcount - 1)) 436296465Sdelphij isopt = 0; 437296465Sdelphij else 438296465Sdelphij isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); 439296465Sdelphij /* 440296465Sdelphij * attempt to read in field, allowing each to be OPTIONAL 441296465Sdelphij */ 442109998Smarkm 443296465Sdelphij ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx); 444296465Sdelphij if (!ret) { 445296465Sdelphij errtt = seqtt; 446296465Sdelphij goto err; 447296465Sdelphij } else if (ret == -1) { 448296465Sdelphij /* 449296465Sdelphij * OPTIONAL component absent. Free and zero the field. 450296465Sdelphij */ 451296465Sdelphij ASN1_template_free(pseqval, seqtt); 452296465Sdelphij continue; 453296465Sdelphij } 454296465Sdelphij /* Update length */ 455296465Sdelphij len -= p - q; 456296465Sdelphij } 457280268Sdelphij 458296465Sdelphij /* Check for EOC if expecting one */ 459296465Sdelphij if (seq_eoc && !asn1_check_eoc(&p, len)) { 460296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MISSING_EOC); 461296465Sdelphij goto err; 462296465Sdelphij } 463296465Sdelphij /* Check all data read */ 464296465Sdelphij if (!seq_nolen && len) { 465296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH); 466296465Sdelphij goto err; 467296465Sdelphij } 468160814Ssimon 469296465Sdelphij /* 470296465Sdelphij * If we get here we've got no more data in the SEQUENCE, however we 471296465Sdelphij * may not have read all fields so check all remaining are OPTIONAL 472296465Sdelphij * and clear any that are. 473296465Sdelphij */ 474296465Sdelphij for (; i < it->tcount; tt++, i++) { 475296465Sdelphij const ASN1_TEMPLATE *seqtt; 476296465Sdelphij seqtt = asn1_do_adb(pval, tt, 1); 477296465Sdelphij if (!seqtt) 478296465Sdelphij goto err; 479296465Sdelphij if (seqtt->flags & ASN1_TFLG_OPTIONAL) { 480296465Sdelphij ASN1_VALUE **pseqval; 481296465Sdelphij pseqval = asn1_get_field_ptr(pval, seqtt); 482296465Sdelphij ASN1_template_free(pseqval, seqtt); 483296465Sdelphij } else { 484296465Sdelphij errtt = seqtt; 485296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_FIELD_MISSING); 486296465Sdelphij goto err; 487296465Sdelphij } 488296465Sdelphij } 489296465Sdelphij /* Save encoding */ 490296465Sdelphij if (!asn1_enc_save(pval, *in, p - *in, it)) 491296465Sdelphij goto auxerr; 492296465Sdelphij *in = p; 493296465Sdelphij if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it)) 494296465Sdelphij goto auxerr; 495296465Sdelphij return 1; 496160814Ssimon 497296465Sdelphij default: 498296465Sdelphij return 0; 499296465Sdelphij } 500296465Sdelphij auxerr: 501296465Sdelphij ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_AUX_ERROR); 502296465Sdelphij err: 503296465Sdelphij if (combine == 0) 504296465Sdelphij ASN1_item_ex_free(pval, it); 505296465Sdelphij if (errtt) 506296465Sdelphij ERR_add_error_data(4, "Field=", errtt->field_name, 507296465Sdelphij ", Type=", it->sname); 508296465Sdelphij else 509296465Sdelphij ERR_add_error_data(2, "Type=", it->sname); 510296465Sdelphij return 0; 511296465Sdelphij} 512109998Smarkm 513296465Sdelphij/* 514296465Sdelphij * Templates are handled with two separate functions. One handles any 515296465Sdelphij * EXPLICIT tag and the other handles the rest. 516109998Smarkm */ 517109998Smarkm 518160814Ssimonstatic int asn1_template_ex_d2i(ASN1_VALUE **val, 519296465Sdelphij const unsigned char **in, long inlen, 520296465Sdelphij const ASN1_TEMPLATE *tt, char opt, 521296465Sdelphij ASN1_TLC *ctx) 522296465Sdelphij{ 523296465Sdelphij int flags, aclass; 524296465Sdelphij int ret; 525296465Sdelphij long len; 526296465Sdelphij const unsigned char *p, *q; 527296465Sdelphij char exp_eoc; 528296465Sdelphij if (!val) 529296465Sdelphij return 0; 530296465Sdelphij flags = tt->flags; 531296465Sdelphij aclass = flags & ASN1_TFLG_TAG_CLASS; 532109998Smarkm 533296465Sdelphij p = *in; 534109998Smarkm 535296465Sdelphij /* Check if EXPLICIT tag expected */ 536296465Sdelphij if (flags & ASN1_TFLG_EXPTAG) { 537296465Sdelphij char cst; 538296465Sdelphij /* 539296465Sdelphij * Need to work out amount of data available to the inner content and 540296465Sdelphij * where it starts: so read in EXPLICIT header to get the info. 541296465Sdelphij */ 542296465Sdelphij ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, 543296465Sdelphij &p, inlen, tt->tag, aclass, opt, ctx); 544296465Sdelphij q = p; 545296465Sdelphij if (!ret) { 546296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 547296465Sdelphij return 0; 548296465Sdelphij } else if (ret == -1) 549296465Sdelphij return -1; 550296465Sdelphij if (!cst) { 551296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, 552296465Sdelphij ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); 553296465Sdelphij return 0; 554296465Sdelphij } 555296465Sdelphij /* We've found the field so it can't be OPTIONAL now */ 556296465Sdelphij ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx); 557296465Sdelphij if (!ret) { 558296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 559296465Sdelphij return 0; 560296465Sdelphij } 561296465Sdelphij /* We read the field in OK so update length */ 562296465Sdelphij len -= p - q; 563296465Sdelphij if (exp_eoc) { 564296465Sdelphij /* If NDEF we must have an EOC here */ 565296465Sdelphij if (!asn1_check_eoc(&p, len)) { 566296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ASN1_R_MISSING_EOC); 567296465Sdelphij goto err; 568296465Sdelphij } 569296465Sdelphij } else { 570296465Sdelphij /* 571296465Sdelphij * Otherwise we must hit the EXPLICIT tag end or its an error 572296465Sdelphij */ 573296465Sdelphij if (len) { 574296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, 575296465Sdelphij ASN1_R_EXPLICIT_LENGTH_MISMATCH); 576296465Sdelphij goto err; 577296465Sdelphij } 578296465Sdelphij } 579296465Sdelphij } else 580296465Sdelphij return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx); 581109998Smarkm 582296465Sdelphij *in = p; 583296465Sdelphij return 1; 584109998Smarkm 585296465Sdelphij err: 586296465Sdelphij ASN1_template_free(val, tt); 587296465Sdelphij return 0; 588296465Sdelphij} 589109998Smarkm 590160814Ssimonstatic int asn1_template_noexp_d2i(ASN1_VALUE **val, 591296465Sdelphij const unsigned char **in, long len, 592296465Sdelphij const ASN1_TEMPLATE *tt, char opt, 593296465Sdelphij ASN1_TLC *ctx) 594296465Sdelphij{ 595296465Sdelphij int flags, aclass; 596296465Sdelphij int ret; 597296465Sdelphij const unsigned char *p, *q; 598296465Sdelphij if (!val) 599296465Sdelphij return 0; 600296465Sdelphij flags = tt->flags; 601296465Sdelphij aclass = flags & ASN1_TFLG_TAG_CLASS; 602109998Smarkm 603296465Sdelphij p = *in; 604296465Sdelphij q = p; 605109998Smarkm 606296465Sdelphij if (flags & ASN1_TFLG_SK_MASK) { 607296465Sdelphij /* SET OF, SEQUENCE OF */ 608296465Sdelphij int sktag, skaclass; 609296465Sdelphij char sk_eoc; 610296465Sdelphij /* First work out expected inner tag value */ 611296465Sdelphij if (flags & ASN1_TFLG_IMPTAG) { 612296465Sdelphij sktag = tt->tag; 613296465Sdelphij skaclass = aclass; 614296465Sdelphij } else { 615296465Sdelphij skaclass = V_ASN1_UNIVERSAL; 616296465Sdelphij if (flags & ASN1_TFLG_SET_OF) 617296465Sdelphij sktag = V_ASN1_SET; 618296465Sdelphij else 619296465Sdelphij sktag = V_ASN1_SEQUENCE; 620296465Sdelphij } 621296465Sdelphij /* Get the tag */ 622296465Sdelphij ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, 623296465Sdelphij &p, len, sktag, skaclass, opt, ctx); 624296465Sdelphij if (!ret) { 625296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); 626296465Sdelphij return 0; 627296465Sdelphij } else if (ret == -1) 628296465Sdelphij return -1; 629296465Sdelphij if (!*val) 630296465Sdelphij *val = (ASN1_VALUE *)sk_new_null(); 631296465Sdelphij else { 632296465Sdelphij /* 633296465Sdelphij * We've got a valid STACK: free up any items present 634296465Sdelphij */ 635296465Sdelphij STACK *sktmp = (STACK *) * val; 636296465Sdelphij ASN1_VALUE *vtmp; 637296465Sdelphij while (sk_num(sktmp) > 0) { 638296465Sdelphij vtmp = (ASN1_VALUE *)sk_pop(sktmp); 639296465Sdelphij ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); 640296465Sdelphij } 641296465Sdelphij } 642160814Ssimon 643296465Sdelphij if (!*val) { 644296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE); 645296465Sdelphij goto err; 646296465Sdelphij } 647109998Smarkm 648296465Sdelphij /* Read as many items as we can */ 649296465Sdelphij while (len > 0) { 650296465Sdelphij ASN1_VALUE *skfield; 651296465Sdelphij q = p; 652296465Sdelphij /* See if EOC found */ 653296465Sdelphij if (asn1_check_eoc(&p, len)) { 654296465Sdelphij if (!sk_eoc) { 655296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 656296465Sdelphij ASN1_R_UNEXPECTED_EOC); 657296465Sdelphij goto err; 658296465Sdelphij } 659296465Sdelphij len -= p - q; 660296465Sdelphij sk_eoc = 0; 661296465Sdelphij break; 662296465Sdelphij } 663296465Sdelphij skfield = NULL; 664296465Sdelphij if (!ASN1_item_ex_d2i(&skfield, &p, len, 665296465Sdelphij ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx)) { 666296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 667296465Sdelphij ERR_R_NESTED_ASN1_ERROR); 668296465Sdelphij goto err; 669296465Sdelphij } 670296465Sdelphij len -= p - q; 671296465Sdelphij if (!sk_push((STACK *) * val, (char *)skfield)) { 672296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE); 673296465Sdelphij goto err; 674296465Sdelphij } 675296465Sdelphij } 676296465Sdelphij if (sk_eoc) { 677296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ASN1_R_MISSING_EOC); 678296465Sdelphij goto err; 679296465Sdelphij } 680296465Sdelphij } else if (flags & ASN1_TFLG_IMPTAG) { 681296465Sdelphij /* IMPLICIT tagging */ 682296465Sdelphij ret = ASN1_item_ex_d2i(val, &p, len, 683296465Sdelphij ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, 684296465Sdelphij ctx); 685296465Sdelphij if (!ret) { 686296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); 687296465Sdelphij goto err; 688296465Sdelphij } else if (ret == -1) 689296465Sdelphij return -1; 690296465Sdelphij } else { 691296465Sdelphij /* Nothing special */ 692296465Sdelphij ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), 693296465Sdelphij -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx); 694296465Sdelphij if (!ret) { 695296465Sdelphij ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); 696296465Sdelphij goto err; 697296465Sdelphij } else if (ret == -1) 698296465Sdelphij return -1; 699296465Sdelphij } 700109998Smarkm 701296465Sdelphij *in = p; 702296465Sdelphij return 1; 703109998Smarkm 704296465Sdelphij err: 705296465Sdelphij ASN1_template_free(val, tt); 706296465Sdelphij return 0; 707296465Sdelphij} 708296465Sdelphij 709160814Ssimonstatic int asn1_d2i_ex_primitive(ASN1_VALUE **pval, 710296465Sdelphij const unsigned char **in, long inlen, 711296465Sdelphij const ASN1_ITEM *it, 712296465Sdelphij int tag, int aclass, char opt, ASN1_TLC *ctx) 713296465Sdelphij{ 714296465Sdelphij int ret = 0, utype; 715296465Sdelphij long plen; 716296465Sdelphij char cst, inf, free_cont = 0; 717296465Sdelphij const unsigned char *p; 718296465Sdelphij BUF_MEM buf; 719296465Sdelphij const unsigned char *cont = NULL; 720296465Sdelphij long len; 721296465Sdelphij if (!pval) { 722296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL); 723296465Sdelphij return 0; /* Should never happen */ 724296465Sdelphij } 725109998Smarkm 726296465Sdelphij if (it->itype == ASN1_ITYPE_MSTRING) { 727296465Sdelphij utype = tag; 728296465Sdelphij tag = -1; 729296465Sdelphij } else 730296465Sdelphij utype = it->utype; 731109998Smarkm 732296465Sdelphij if (utype == V_ASN1_ANY) { 733296465Sdelphij /* If type is ANY need to figure out type from tag */ 734296465Sdelphij unsigned char oclass; 735296465Sdelphij if (tag >= 0) { 736296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_TAGGED_ANY); 737296465Sdelphij return 0; 738296465Sdelphij } 739296465Sdelphij if (opt) { 740296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, 741296465Sdelphij ASN1_R_ILLEGAL_OPTIONAL_ANY); 742296465Sdelphij return 0; 743296465Sdelphij } 744296465Sdelphij p = *in; 745296465Sdelphij ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, 746296465Sdelphij &p, inlen, -1, 0, 0, ctx); 747296465Sdelphij if (!ret) { 748296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); 749296465Sdelphij return 0; 750296465Sdelphij } 751296465Sdelphij if (oclass != V_ASN1_UNIVERSAL) 752296465Sdelphij utype = V_ASN1_OTHER; 753296465Sdelphij } 754296465Sdelphij if (tag == -1) { 755296465Sdelphij tag = utype; 756296465Sdelphij aclass = V_ASN1_UNIVERSAL; 757296465Sdelphij } 758296465Sdelphij p = *in; 759296465Sdelphij /* Check header */ 760296465Sdelphij ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, 761296465Sdelphij &p, inlen, tag, aclass, opt, ctx); 762296465Sdelphij if (!ret) { 763296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); 764296465Sdelphij return 0; 765296465Sdelphij } else if (ret == -1) 766296465Sdelphij return -1; 767296465Sdelphij ret = 0; 768296465Sdelphij /* SEQUENCE, SET and "OTHER" are left in encoded form */ 769296465Sdelphij if ((utype == V_ASN1_SEQUENCE) 770296465Sdelphij || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) { 771296465Sdelphij /* 772296465Sdelphij * Clear context cache for type OTHER because the auto clear when we 773296465Sdelphij * have a exact match wont work 774296465Sdelphij */ 775296465Sdelphij if (utype == V_ASN1_OTHER) { 776296465Sdelphij asn1_tlc_clear(ctx); 777296465Sdelphij } 778296465Sdelphij /* SEQUENCE and SET must be constructed */ 779296465Sdelphij else if (!cst) { 780296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, 781296465Sdelphij ASN1_R_TYPE_NOT_CONSTRUCTED); 782296465Sdelphij return 0; 783296465Sdelphij } 784109998Smarkm 785296465Sdelphij cont = *in; 786296465Sdelphij /* If indefinite length constructed find the real end */ 787296465Sdelphij if (inf) { 788296465Sdelphij if (!asn1_find_end(&p, plen, inf)) 789296465Sdelphij goto err; 790296465Sdelphij len = p - cont; 791296465Sdelphij } else { 792296465Sdelphij len = p - cont + plen; 793296465Sdelphij p += plen; 794296465Sdelphij buf.data = NULL; 795296465Sdelphij } 796296465Sdelphij } else if (cst) { 797296465Sdelphij if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN 798296465Sdelphij || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER 799296465Sdelphij || utype == V_ASN1_ENUMERATED) { 800296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_TYPE_NOT_PRIMITIVE); 801296465Sdelphij return 0; 802296465Sdelphij } 803296465Sdelphij buf.length = 0; 804296465Sdelphij buf.max = 0; 805296465Sdelphij buf.data = NULL; 806296465Sdelphij /* 807296465Sdelphij * Should really check the internal tags are correct but some things 808296465Sdelphij * may get this wrong. The relevant specs say that constructed string 809296465Sdelphij * types should be OCTET STRINGs internally irrespective of the type. 810296465Sdelphij * So instead just check for UNIVERSAL class and ignore the tag. 811296465Sdelphij */ 812296465Sdelphij if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) { 813296465Sdelphij free_cont = 1; 814296465Sdelphij goto err; 815296465Sdelphij } 816296465Sdelphij len = buf.length; 817296465Sdelphij /* Append a final null to string */ 818296465Sdelphij if (!BUF_MEM_grow_clean(&buf, len + 1)) { 819296465Sdelphij ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); 820296465Sdelphij return 0; 821296465Sdelphij } 822296465Sdelphij buf.data[len] = 0; 823296465Sdelphij cont = (const unsigned char *)buf.data; 824296465Sdelphij free_cont = 1; 825296465Sdelphij } else { 826296465Sdelphij cont = p; 827296465Sdelphij len = plen; 828296465Sdelphij p += plen; 829296465Sdelphij } 830109998Smarkm 831296465Sdelphij /* We now have content length and type: translate into a structure */ 832296465Sdelphij if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it)) 833296465Sdelphij goto err; 834109998Smarkm 835296465Sdelphij *in = p; 836296465Sdelphij ret = 1; 837296465Sdelphij err: 838296465Sdelphij if (free_cont && buf.data) 839296465Sdelphij OPENSSL_free(buf.data); 840296465Sdelphij return ret; 841296465Sdelphij} 842109998Smarkm 843109998Smarkm/* Translate ASN1 content octets into a structure */ 844109998Smarkm 845160814Ssimonint asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, 846296465Sdelphij int utype, char *free_cont, const ASN1_ITEM *it) 847296465Sdelphij{ 848296465Sdelphij ASN1_VALUE **opval = NULL; 849296465Sdelphij ASN1_STRING *stmp; 850296465Sdelphij ASN1_TYPE *typ = NULL; 851296465Sdelphij int ret = 0; 852296465Sdelphij const ASN1_PRIMITIVE_FUNCS *pf; 853296465Sdelphij ASN1_INTEGER **tint; 854296465Sdelphij pf = it->funcs; 855160814Ssimon 856296465Sdelphij if (pf && pf->prim_c2i) 857296465Sdelphij return pf->prim_c2i(pval, cont, len, utype, free_cont, it); 858296465Sdelphij /* If ANY type clear type and set pointer to internal value */ 859296465Sdelphij if (it->utype == V_ASN1_ANY) { 860296465Sdelphij if (!*pval) { 861296465Sdelphij typ = ASN1_TYPE_new(); 862296465Sdelphij if (typ == NULL) 863296465Sdelphij goto err; 864296465Sdelphij *pval = (ASN1_VALUE *)typ; 865296465Sdelphij } else 866296465Sdelphij typ = (ASN1_TYPE *)*pval; 867160814Ssimon 868296465Sdelphij if (utype != typ->type) 869296465Sdelphij ASN1_TYPE_set(typ, utype, NULL); 870296465Sdelphij opval = pval; 871296465Sdelphij pval = &typ->value.asn1_value; 872296465Sdelphij } 873296465Sdelphij switch (utype) { 874296465Sdelphij case V_ASN1_OBJECT: 875296465Sdelphij if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) 876296465Sdelphij goto err; 877296465Sdelphij break; 878109998Smarkm 879296465Sdelphij case V_ASN1_NULL: 880296465Sdelphij if (len) { 881296465Sdelphij ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_NULL_IS_WRONG_LENGTH); 882296465Sdelphij goto err; 883296465Sdelphij } 884296465Sdelphij *pval = (ASN1_VALUE *)1; 885296465Sdelphij break; 886109998Smarkm 887296465Sdelphij case V_ASN1_BOOLEAN: 888296465Sdelphij if (len != 1) { 889296465Sdelphij ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); 890296465Sdelphij goto err; 891296465Sdelphij } else { 892296465Sdelphij ASN1_BOOLEAN *tbool; 893296465Sdelphij tbool = (ASN1_BOOLEAN *)pval; 894296465Sdelphij *tbool = *cont; 895296465Sdelphij } 896296465Sdelphij break; 897109998Smarkm 898296465Sdelphij case V_ASN1_BIT_STRING: 899296465Sdelphij if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) 900296465Sdelphij goto err; 901296465Sdelphij break; 902109998Smarkm 903296465Sdelphij case V_ASN1_INTEGER: 904296465Sdelphij case V_ASN1_ENUMERATED: 905296465Sdelphij tint = (ASN1_INTEGER **)pval; 906296465Sdelphij if (!c2i_ASN1_INTEGER(tint, &cont, len)) 907296465Sdelphij goto err; 908296465Sdelphij /* Fixup type to match the expected form */ 909296465Sdelphij (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); 910296465Sdelphij break; 911109998Smarkm 912296465Sdelphij case V_ASN1_OCTET_STRING: 913296465Sdelphij case V_ASN1_NUMERICSTRING: 914296465Sdelphij case V_ASN1_PRINTABLESTRING: 915296465Sdelphij case V_ASN1_T61STRING: 916296465Sdelphij case V_ASN1_VIDEOTEXSTRING: 917296465Sdelphij case V_ASN1_IA5STRING: 918296465Sdelphij case V_ASN1_UTCTIME: 919296465Sdelphij case V_ASN1_GENERALIZEDTIME: 920296465Sdelphij case V_ASN1_GRAPHICSTRING: 921296465Sdelphij case V_ASN1_VISIBLESTRING: 922296465Sdelphij case V_ASN1_GENERALSTRING: 923296465Sdelphij case V_ASN1_UNIVERSALSTRING: 924296465Sdelphij case V_ASN1_BMPSTRING: 925296465Sdelphij case V_ASN1_UTF8STRING: 926296465Sdelphij case V_ASN1_OTHER: 927296465Sdelphij case V_ASN1_SET: 928296465Sdelphij case V_ASN1_SEQUENCE: 929296465Sdelphij default: 930296465Sdelphij if (utype == V_ASN1_BMPSTRING && (len & 1)) { 931296465Sdelphij ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BMPSTRING_IS_WRONG_LENGTH); 932296465Sdelphij goto err; 933296465Sdelphij } 934296465Sdelphij if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) { 935296465Sdelphij ASN1err(ASN1_F_ASN1_EX_C2I, 936296465Sdelphij ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); 937296465Sdelphij goto err; 938296465Sdelphij } 939296465Sdelphij /* All based on ASN1_STRING and handled the same */ 940296465Sdelphij if (!*pval) { 941296465Sdelphij stmp = ASN1_STRING_type_new(utype); 942296465Sdelphij if (!stmp) { 943296465Sdelphij ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE); 944296465Sdelphij goto err; 945296465Sdelphij } 946296465Sdelphij *pval = (ASN1_VALUE *)stmp; 947296465Sdelphij } else { 948296465Sdelphij stmp = (ASN1_STRING *)*pval; 949296465Sdelphij stmp->type = utype; 950296465Sdelphij } 951296465Sdelphij /* If we've already allocated a buffer use it */ 952296465Sdelphij if (*free_cont) { 953296465Sdelphij if (stmp->data) 954296465Sdelphij OPENSSL_free(stmp->data); 955296465Sdelphij stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */ 956296465Sdelphij stmp->length = len; 957296465Sdelphij *free_cont = 0; 958296465Sdelphij } else { 959296465Sdelphij if (!ASN1_STRING_set(stmp, cont, len)) { 960296465Sdelphij ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE); 961296465Sdelphij ASN1_STRING_free(stmp); 962296465Sdelphij *pval = NULL; 963296465Sdelphij goto err; 964296465Sdelphij } 965296465Sdelphij } 966296465Sdelphij break; 967296465Sdelphij } 968296465Sdelphij /* If ASN1_ANY and NULL type fix up value */ 969296465Sdelphij if (typ && (utype == V_ASN1_NULL)) 970296465Sdelphij typ->value.ptr = NULL; 971109998Smarkm 972296465Sdelphij ret = 1; 973296465Sdelphij err: 974296465Sdelphij if (!ret) { 975296465Sdelphij ASN1_TYPE_free(typ); 976296465Sdelphij if (opval) 977296465Sdelphij *opval = NULL; 978296465Sdelphij } 979296465Sdelphij return ret; 980296465Sdelphij} 981109998Smarkm 982296465Sdelphij/* 983296465Sdelphij * This function finds the end of an ASN1 structure when passed its maximum 984296465Sdelphij * length, whether it is indefinite length and a pointer to the content. This 985296465Sdelphij * is more efficient than calling asn1_collect because it does not recurse on 986296465Sdelphij * each indefinite length header. 987160814Ssimon */ 988160814Ssimon 989160814Ssimonstatic int asn1_find_end(const unsigned char **in, long len, char inf) 990296465Sdelphij{ 991296465Sdelphij int expected_eoc; 992296465Sdelphij long plen; 993296465Sdelphij const unsigned char *p = *in, *q; 994296465Sdelphij /* If not indefinite length constructed just add length */ 995296465Sdelphij if (inf == 0) { 996296465Sdelphij *in += len; 997296465Sdelphij return 1; 998296465Sdelphij } 999296465Sdelphij expected_eoc = 1; 1000296465Sdelphij /* 1001296465Sdelphij * Indefinite length constructed form. Find the end when enough EOCs are 1002296465Sdelphij * found. If more indefinite length constructed headers are encountered 1003296465Sdelphij * increment the expected eoc count otherwise just skip to the end of the 1004296465Sdelphij * data. 1005296465Sdelphij */ 1006296465Sdelphij while (len > 0) { 1007296465Sdelphij if (asn1_check_eoc(&p, len)) { 1008296465Sdelphij expected_eoc--; 1009296465Sdelphij if (expected_eoc == 0) 1010296465Sdelphij break; 1011296465Sdelphij len -= 2; 1012296465Sdelphij continue; 1013296465Sdelphij } 1014296465Sdelphij q = p; 1015296465Sdelphij /* Just read in a header: only care about the length */ 1016296465Sdelphij if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len, 1017296465Sdelphij -1, 0, 0, NULL)) { 1018296465Sdelphij ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR); 1019296465Sdelphij return 0; 1020296465Sdelphij } 1021296465Sdelphij if (inf) 1022296465Sdelphij expected_eoc++; 1023296465Sdelphij else 1024296465Sdelphij p += plen; 1025296465Sdelphij len -= p - q; 1026296465Sdelphij } 1027296465Sdelphij if (expected_eoc) { 1028296465Sdelphij ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC); 1029296465Sdelphij return 0; 1030296465Sdelphij } 1031296465Sdelphij *in = p; 1032296465Sdelphij return 1; 1033296465Sdelphij} 1034296465Sdelphij 1035296465Sdelphij/* 1036296465Sdelphij * This function collects the asn1 data from a constructred string type into 1037296465Sdelphij * a buffer. The values of 'in' and 'len' should refer to the contents of the 1038296465Sdelphij * constructed type and 'inf' should be set if it is indefinite length. 1039109998Smarkm */ 1040109998Smarkm 1041194206Ssimon#ifndef ASN1_MAX_STRING_NEST 1042296465Sdelphij/* 1043296465Sdelphij * This determines how many levels of recursion are permitted in ASN1 string 1044296465Sdelphij * types. If it is not limited stack overflows can occur. If set to zero no 1045296465Sdelphij * recursion is allowed at all. Although zero should be adequate examples 1046296465Sdelphij * exist that require a value of 1. So 5 should be more than enough. 1047194206Ssimon */ 1048296465Sdelphij# define ASN1_MAX_STRING_NEST 5 1049194206Ssimon#endif 1050194206Ssimon 1051160814Ssimonstatic int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, 1052296465Sdelphij char inf, int tag, int aclass, int depth) 1053296465Sdelphij{ 1054296465Sdelphij const unsigned char *p, *q; 1055296465Sdelphij long plen; 1056296465Sdelphij char cst, ininf; 1057296465Sdelphij p = *in; 1058296465Sdelphij inf &= 1; 1059296465Sdelphij /* 1060296465Sdelphij * If no buffer and not indefinite length constructed just pass over the 1061296465Sdelphij * encoded data 1062296465Sdelphij */ 1063296465Sdelphij if (!buf && !inf) { 1064296465Sdelphij *in += len; 1065296465Sdelphij return 1; 1066296465Sdelphij } 1067296465Sdelphij while (len > 0) { 1068296465Sdelphij q = p; 1069296465Sdelphij /* Check for EOC */ 1070296465Sdelphij if (asn1_check_eoc(&p, len)) { 1071296465Sdelphij /* 1072296465Sdelphij * EOC is illegal outside indefinite length constructed form 1073296465Sdelphij */ 1074296465Sdelphij if (!inf) { 1075296465Sdelphij ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_UNEXPECTED_EOC); 1076296465Sdelphij return 0; 1077296465Sdelphij } 1078296465Sdelphij inf = 0; 1079296465Sdelphij break; 1080296465Sdelphij } 1081160814Ssimon 1082296465Sdelphij if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p, 1083296465Sdelphij len, tag, aclass, 0, NULL)) { 1084296465Sdelphij ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR); 1085296465Sdelphij return 0; 1086296465Sdelphij } 1087160814Ssimon 1088296465Sdelphij /* If indefinite length constructed update max length */ 1089296465Sdelphij if (cst) { 1090296465Sdelphij if (depth >= ASN1_MAX_STRING_NEST) { 1091296465Sdelphij ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_NESTED_ASN1_STRING); 1092296465Sdelphij return 0; 1093296465Sdelphij } 1094296465Sdelphij if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, depth + 1)) 1095296465Sdelphij return 0; 1096296465Sdelphij } else if (plen && !collect_data(buf, &p, plen)) 1097296465Sdelphij return 0; 1098296465Sdelphij len -= p - q; 1099296465Sdelphij } 1100296465Sdelphij if (inf) { 1101296465Sdelphij ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC); 1102296465Sdelphij return 0; 1103296465Sdelphij } 1104296465Sdelphij *in = p; 1105296465Sdelphij return 1; 1106296465Sdelphij} 1107109998Smarkm 1108160814Ssimonstatic int collect_data(BUF_MEM *buf, const unsigned char **p, long plen) 1109296465Sdelphij{ 1110296465Sdelphij int len; 1111296465Sdelphij if (buf) { 1112296465Sdelphij len = buf->length; 1113296465Sdelphij if (!BUF_MEM_grow_clean(buf, len + plen)) { 1114296465Sdelphij ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE); 1115296465Sdelphij return 0; 1116296465Sdelphij } 1117296465Sdelphij memcpy(buf->data + len, *p, plen); 1118296465Sdelphij } 1119296465Sdelphij *p += plen; 1120296465Sdelphij return 1; 1121296465Sdelphij} 1122109998Smarkm 1123109998Smarkm/* Check for ASN1 EOC and swallow it if found */ 1124109998Smarkm 1125160814Ssimonstatic int asn1_check_eoc(const unsigned char **in, long len) 1126296465Sdelphij{ 1127296465Sdelphij const unsigned char *p; 1128296465Sdelphij if (len < 2) 1129296465Sdelphij return 0; 1130296465Sdelphij p = *in; 1131296465Sdelphij if (!p[0] && !p[1]) { 1132296465Sdelphij *in += 2; 1133296465Sdelphij return 1; 1134296465Sdelphij } 1135296465Sdelphij return 0; 1136296465Sdelphij} 1137109998Smarkm 1138296465Sdelphij/* 1139296465Sdelphij * Check an ASN1 tag and length: a bit like ASN1_get_object but it sets the 1140296465Sdelphij * length for indefinite length constructed form, we don't know the exact 1141296465Sdelphij * length but we can set an upper bound to the amount of data available minus 1142296465Sdelphij * the header length just read. 1143109998Smarkm */ 1144109998Smarkm 1145160814Ssimonstatic int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, 1146296465Sdelphij char *inf, char *cst, 1147296465Sdelphij const unsigned char **in, long len, 1148296465Sdelphij int exptag, int expclass, char opt, ASN1_TLC *ctx) 1149296465Sdelphij{ 1150296465Sdelphij int i; 1151296465Sdelphij int ptag, pclass; 1152296465Sdelphij long plen; 1153296465Sdelphij const unsigned char *p, *q; 1154296465Sdelphij p = *in; 1155296465Sdelphij q = p; 1156109998Smarkm 1157296465Sdelphij if (ctx && ctx->valid) { 1158296465Sdelphij i = ctx->ret; 1159296465Sdelphij plen = ctx->plen; 1160296465Sdelphij pclass = ctx->pclass; 1161296465Sdelphij ptag = ctx->ptag; 1162296465Sdelphij p += ctx->hdrlen; 1163296465Sdelphij } else { 1164296465Sdelphij i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); 1165296465Sdelphij if (ctx) { 1166296465Sdelphij ctx->ret = i; 1167296465Sdelphij ctx->plen = plen; 1168296465Sdelphij ctx->pclass = pclass; 1169296465Sdelphij ctx->ptag = ptag; 1170296465Sdelphij ctx->hdrlen = p - q; 1171296465Sdelphij ctx->valid = 1; 1172296465Sdelphij /* 1173296465Sdelphij * If definite length, and no error, length + header can't exceed 1174296465Sdelphij * total amount of data available. 1175296465Sdelphij */ 1176296465Sdelphij if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { 1177296465Sdelphij ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_TOO_LONG); 1178296465Sdelphij asn1_tlc_clear(ctx); 1179296465Sdelphij return 0; 1180296465Sdelphij } 1181296465Sdelphij } 1182296465Sdelphij } 1183109998Smarkm 1184296465Sdelphij if (i & 0x80) { 1185296465Sdelphij ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER); 1186296465Sdelphij asn1_tlc_clear(ctx); 1187296465Sdelphij return 0; 1188296465Sdelphij } 1189296465Sdelphij if (exptag >= 0) { 1190296465Sdelphij if ((exptag != ptag) || (expclass != pclass)) { 1191296465Sdelphij /* 1192296465Sdelphij * If type is OPTIONAL, not an error: indicate missing type. 1193296465Sdelphij */ 1194296465Sdelphij if (opt) 1195296465Sdelphij return -1; 1196296465Sdelphij asn1_tlc_clear(ctx); 1197296465Sdelphij ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG); 1198296465Sdelphij return 0; 1199296465Sdelphij } 1200296465Sdelphij /* 1201296465Sdelphij * We have a tag and class match: assume we are going to do something 1202296465Sdelphij * with it 1203296465Sdelphij */ 1204296465Sdelphij asn1_tlc_clear(ctx); 1205296465Sdelphij } 1206109998Smarkm 1207296465Sdelphij if (i & 1) 1208296465Sdelphij plen = len - (p - q); 1209109998Smarkm 1210296465Sdelphij if (inf) 1211296465Sdelphij *inf = i & 1; 1212109998Smarkm 1213296465Sdelphij if (cst) 1214296465Sdelphij *cst = i & V_ASN1_CONSTRUCTED; 1215109998Smarkm 1216296465Sdelphij if (olen) 1217296465Sdelphij *olen = plen; 1218109998Smarkm 1219296465Sdelphij if (oclass) 1220296465Sdelphij *oclass = pclass; 1221160814Ssimon 1222296465Sdelphij if (otag) 1223296465Sdelphij *otag = ptag; 1224160814Ssimon 1225296465Sdelphij *in = p; 1226296465Sdelphij return 1; 1227296465Sdelphij} 1228