1109998Smarkm/* tasn_dec.c */ 2194206Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3109998Smarkm * project 2000. 4109998Smarkm */ 5109998Smarkm/* ==================================================================== 6160814Ssimon * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. 7109998Smarkm * 8109998Smarkm * Redistribution and use in source and binary forms, with or without 9109998Smarkm * modification, are permitted provided that the following conditions 10109998Smarkm * are met: 11109998Smarkm * 12109998Smarkm * 1. Redistributions of source code must retain the above copyright 13109998Smarkm * notice, this list of conditions and the following disclaimer. 14109998Smarkm * 15109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 16109998Smarkm * notice, this list of conditions and the following disclaimer in 17109998Smarkm * the documentation and/or other materials provided with the 18109998Smarkm * distribution. 19109998Smarkm * 20109998Smarkm * 3. All advertising materials mentioning features or use of this 21109998Smarkm * software must display the following acknowledgment: 22109998Smarkm * "This product includes software developed by the OpenSSL Project 23109998Smarkm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24109998Smarkm * 25109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26109998Smarkm * endorse or promote products derived from this software without 27109998Smarkm * prior written permission. For written permission, please contact 28109998Smarkm * licensing@OpenSSL.org. 29109998Smarkm * 30109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 31109998Smarkm * nor may "OpenSSL" appear in their names without prior written 32109998Smarkm * permission of the OpenSSL Project. 33109998Smarkm * 34109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 35109998Smarkm * acknowledgment: 36109998Smarkm * "This product includes software developed by the OpenSSL Project 37109998Smarkm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38109998Smarkm * 39109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 51109998Smarkm * ==================================================================== 52109998Smarkm * 53109998Smarkm * This product includes cryptographic software written by Eric Young 54109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 55109998Smarkm * Hudson (tjh@cryptsoft.com). 56109998Smarkm * 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, 72194206Ssimon 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, 77160814Ssimon char *inf, char *cst, 78160814Ssimon const unsigned char **in, long len, 79160814Ssimon int exptag, int expclass, char opt, 80160814Ssimon ASN1_TLC *ctx); 81160814Ssimon 82160814Ssimonstatic int asn1_template_ex_d2i(ASN1_VALUE **pval, 83160814Ssimon const unsigned char **in, long len, 84160814Ssimon const ASN1_TEMPLATE *tt, char opt, 85160814Ssimon ASN1_TLC *ctx); 86160814Ssimonstatic int asn1_template_noexp_d2i(ASN1_VALUE **val, 87160814Ssimon const unsigned char **in, long len, 88160814Ssimon const ASN1_TEMPLATE *tt, char opt, 89160814Ssimon ASN1_TLC *ctx); 90160814Ssimonstatic int asn1_d2i_ex_primitive(ASN1_VALUE **pval, 91160814Ssimon const unsigned char **in, long len, 92160814Ssimon const ASN1_ITEM *it, 93160814Ssimon int tag, int aclass, char opt, ASN1_TLC *ctx); 94160814Ssimon 95109998Smarkm/* Table to convert tags to bit values, used for MSTRING type */ 96167612Ssimonstatic const unsigned long tag2bit[32] = { 97109998Smarkm0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */ 98109998SmarkmB_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN,/* tags 4- 7 */ 99109998SmarkmB_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,/* tags 8-11 */ 100109998SmarkmB_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */ 101160814SsimonB_ASN1_SEQUENCE,0,B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */ 102109998SmarkmB_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING, /* tags 20-22 */ 103109998SmarkmB_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, /* tags 23-24 */ 104109998SmarkmB_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING, /* tags 25-27 */ 105109998SmarkmB_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */ 106109998Smarkm }; 107109998Smarkm 108109998Smarkmunsigned long ASN1_tag2bit(int tag) 109160814Ssimon { 110160814Ssimon if ((tag < 0) || (tag > 30)) return 0; 111109998Smarkm return tag2bit[tag]; 112160814Ssimon } 113109998Smarkm 114109998Smarkm/* Macro to initialize and invalidate the cache */ 115109998Smarkm 116160814Ssimon#define asn1_tlc_clear(c) if (c) (c)->valid = 0 117238405Sjkim/* Version to avoid compiler warning about 'c' always non-NULL */ 118238405Sjkim#define asn1_tlc_clear_nc(c) (c)->valid = 0 119109998Smarkm 120109998Smarkm/* Decode an ASN1 item, this currently behaves just 121109998Smarkm * like a standard 'd2i' function. 'in' points to 122109998Smarkm * a buffer to read the data from, in future we will 123109998Smarkm * have more advanced versions that can input data 124109998Smarkm * a piece at a time and this will simply be a special 125109998Smarkm * case. 126109998Smarkm */ 127109998Smarkm 128160814SsimonASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, 129160814Ssimon const unsigned char **in, long len, const ASN1_ITEM *it) 130160814Ssimon { 131109998Smarkm ASN1_TLC c; 132109998Smarkm ASN1_VALUE *ptmpval = NULL; 133160814Ssimon if (!pval) 134160814Ssimon pval = &ptmpval; 135238405Sjkim asn1_tlc_clear_nc(&c); 136160814Ssimon if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) 137109998Smarkm return *pval; 138109998Smarkm return NULL; 139160814Ssimon } 140109998Smarkm 141160814Ssimonint ASN1_template_d2i(ASN1_VALUE **pval, 142160814Ssimon const unsigned char **in, long len, const ASN1_TEMPLATE *tt) 143160814Ssimon { 144109998Smarkm ASN1_TLC c; 145238405Sjkim asn1_tlc_clear_nc(&c); 146109998Smarkm return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); 147160814Ssimon } 148109998Smarkm 149109998Smarkm 150109998Smarkm/* Decode an item, taking care of IMPLICIT tagging, if any. 151109998Smarkm * If 'opt' set and tag mismatch return -1 to handle OPTIONAL 152109998Smarkm */ 153109998Smarkm 154160814Ssimonint ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, 155160814Ssimon const ASN1_ITEM *it, 156160814Ssimon int tag, int aclass, char opt, ASN1_TLC *ctx) 157160814Ssimon { 158109998Smarkm const ASN1_TEMPLATE *tt, *errtt = NULL; 159109998Smarkm const ASN1_COMPAT_FUNCS *cf; 160109998Smarkm const ASN1_EXTERN_FUNCS *ef; 161109998Smarkm const ASN1_AUX *aux = it->funcs; 162109998Smarkm ASN1_aux_cb *asn1_cb; 163160814Ssimon const unsigned char *p = NULL, *q; 164160814Ssimon unsigned char *wp=NULL; /* BIG FAT WARNING! BREAKS CONST WHERE USED */ 165160814Ssimon unsigned char imphack = 0, oclass; 166109998Smarkm char seq_eoc, seq_nolen, cst, isopt; 167109998Smarkm long tmplen; 168109998Smarkm int i; 169109998Smarkm int otag; 170109998Smarkm int ret = 0; 171215697Ssimon ASN1_VALUE **pchptr, *ptmpval; 172160814Ssimon if (!pval) 173160814Ssimon return 0; 174160814Ssimon if (aux && aux->asn1_cb) 175160814Ssimon asn1_cb = aux->asn1_cb; 176109998Smarkm else asn1_cb = 0; 177109998Smarkm 178160814Ssimon switch(it->itype) 179160814Ssimon { 180109998Smarkm case ASN1_ITYPE_PRIMITIVE: 181160814Ssimon if (it->templates) 182160814Ssimon { 183160814Ssimon /* tagging or OPTIONAL is currently illegal on an item 184160814Ssimon * template because the flags can't get passed down. 185160814Ssimon * In practice this isn't a problem: we include the 186160814Ssimon * relevant flags from the item template in the 187160814Ssimon * template itself. 188109998Smarkm */ 189160814Ssimon if ((tag != -1) || opt) 190160814Ssimon { 191160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 192160814Ssimon ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); 193109998Smarkm goto err; 194160814Ssimon } 195160814Ssimon return asn1_template_ex_d2i(pval, in, len, 196160814Ssimon it->templates, opt, ctx); 197109998Smarkm } 198160814Ssimon return asn1_d2i_ex_primitive(pval, in, len, it, 199160814Ssimon tag, aclass, opt, ctx); 200109998Smarkm break; 201109998Smarkm 202109998Smarkm case ASN1_ITYPE_MSTRING: 203109998Smarkm p = *in; 204109998Smarkm /* Just read in tag and class */ 205160814Ssimon ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, 206160814Ssimon &p, len, -1, 0, 1, ctx); 207160814Ssimon if (!ret) 208160814Ssimon { 209160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 210160814Ssimon ERR_R_NESTED_ASN1_ERROR); 211109998Smarkm goto err; 212160814Ssimon } 213160814Ssimon 214109998Smarkm /* Must be UNIVERSAL class */ 215160814Ssimon if (oclass != V_ASN1_UNIVERSAL) 216160814Ssimon { 217109998Smarkm /* If OPTIONAL, assume this is OK */ 218160814Ssimon if (opt) return -1; 219160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 220160814Ssimon ASN1_R_MSTRING_NOT_UNIVERSAL); 221109998Smarkm goto err; 222160814Ssimon } 223109998Smarkm /* Check tag matches bit map */ 224160814Ssimon if (!(ASN1_tag2bit(otag) & it->utype)) 225160814Ssimon { 226109998Smarkm /* If OPTIONAL, assume this is OK */ 227160814Ssimon if (opt) 228160814Ssimon return -1; 229160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 230160814Ssimon ASN1_R_MSTRING_WRONG_TAG); 231109998Smarkm goto err; 232160814Ssimon } 233160814Ssimon return asn1_d2i_ex_primitive(pval, in, len, 234160814Ssimon it, otag, 0, 0, ctx); 235109998Smarkm 236109998Smarkm case ASN1_ITYPE_EXTERN: 237109998Smarkm /* Use new style d2i */ 238109998Smarkm ef = it->funcs; 239160814Ssimon return ef->asn1_ex_d2i(pval, in, len, 240160814Ssimon it, tag, aclass, opt, ctx); 241109998Smarkm 242109998Smarkm case ASN1_ITYPE_COMPAT: 243109998Smarkm /* we must resort to old style evil hackery */ 244109998Smarkm cf = it->funcs; 245109998Smarkm 246109998Smarkm /* If OPTIONAL see if it is there */ 247160814Ssimon if (opt) 248160814Ssimon { 249109998Smarkm int exptag; 250109998Smarkm p = *in; 251160814Ssimon if (tag == -1) 252160814Ssimon exptag = it->utype; 253109998Smarkm else exptag = tag; 254160814Ssimon /* Don't care about anything other than presence 255160814Ssimon * of expected tag */ 256160814Ssimon 257160814Ssimon ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL, 258160814Ssimon &p, len, exptag, aclass, 1, ctx); 259160814Ssimon if (!ret) 260160814Ssimon { 261160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 262160814Ssimon ERR_R_NESTED_ASN1_ERROR); 263109998Smarkm goto err; 264160814Ssimon } 265160814Ssimon if (ret == -1) 266160814Ssimon return -1; 267109998Smarkm } 268160814Ssimon 269109998Smarkm /* This is the old style evil hack IMPLICIT handling: 270109998Smarkm * since the underlying code is expecting a tag and 271109998Smarkm * class other than the one present we change the 272109998Smarkm * buffer temporarily then change it back afterwards. 273109998Smarkm * This doesn't and never did work for tags > 30. 274109998Smarkm * 275109998Smarkm * Yes this is *horrible* but it is only needed for 276109998Smarkm * old style d2i which will hopefully not be around 277109998Smarkm * for much longer. 278109998Smarkm * FIXME: should copy the buffer then modify it so 279109998Smarkm * the input buffer can be const: we should *always* 280109998Smarkm * copy because the old style d2i might modify the 281109998Smarkm * buffer. 282109998Smarkm */ 283109998Smarkm 284160814Ssimon if (tag != -1) 285160814Ssimon { 286160814Ssimon wp = *(unsigned char **)in; 287160814Ssimon imphack = *wp; 288160814Ssimon if (p == NULL) 289160814Ssimon { 290160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 291160814Ssimon ERR_R_NESTED_ASN1_ERROR); 292160814Ssimon goto err; 293160814Ssimon } 294160814Ssimon *wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED) 295160814Ssimon | it->utype); 296160814Ssimon } 297109998Smarkm 298109998Smarkm ptmpval = cf->asn1_d2i(pval, in, len); 299109998Smarkm 300160814Ssimon if (tag != -1) 301160814Ssimon *wp = imphack; 302109998Smarkm 303160814Ssimon if (ptmpval) 304160814Ssimon return 1; 305160814Ssimon 306109998Smarkm ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 307109998Smarkm goto err; 308109998Smarkm 309109998Smarkm 310109998Smarkm case ASN1_ITYPE_CHOICE: 311238405Sjkim if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) 312109998Smarkm goto auxerr; 313109998Smarkm 314109998Smarkm /* Allocate structure */ 315160814Ssimon if (!*pval && !ASN1_item_ex_new(pval, it)) 316160814Ssimon { 317160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 318160814Ssimon ERR_R_NESTED_ASN1_ERROR); 319160814Ssimon goto err; 320109998Smarkm } 321109998Smarkm /* CHOICE type, try each possibility in turn */ 322109998Smarkm p = *in; 323160814Ssimon for (i = 0, tt=it->templates; i < it->tcount; i++, tt++) 324160814Ssimon { 325109998Smarkm pchptr = asn1_get_field_ptr(pval, tt); 326109998Smarkm /* We mark field as OPTIONAL so its absence 327109998Smarkm * can be recognised. 328109998Smarkm */ 329109998Smarkm ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx); 330109998Smarkm /* If field not present, try the next one */ 331160814Ssimon if (ret == -1) 332160814Ssimon continue; 333109998Smarkm /* If positive return, read OK, break loop */ 334160814Ssimon if (ret > 0) 335160814Ssimon break; 336109998Smarkm /* Otherwise must be an ASN1 parsing error */ 337109998Smarkm errtt = tt; 338160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 339160814Ssimon ERR_R_NESTED_ASN1_ERROR); 340109998Smarkm goto err; 341160814Ssimon } 342160814Ssimon 343109998Smarkm /* Did we fall off the end without reading anything? */ 344160814Ssimon if (i == it->tcount) 345160814Ssimon { 346109998Smarkm /* If OPTIONAL, this is OK */ 347160814Ssimon if (opt) 348160814Ssimon { 349109998Smarkm /* Free and zero it */ 350109998Smarkm ASN1_item_ex_free(pval, it); 351109998Smarkm return -1; 352160814Ssimon } 353160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 354160814Ssimon ASN1_R_NO_MATCHING_CHOICE_TYPE); 355160814Ssimon goto err; 356109998Smarkm } 357160814Ssimon 358109998Smarkm asn1_set_choice_selector(pval, i, it); 359109998Smarkm *in = p; 360238405Sjkim if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) 361109998Smarkm goto auxerr; 362109998Smarkm return 1; 363109998Smarkm 364160814Ssimon case ASN1_ITYPE_NDEF_SEQUENCE: 365109998Smarkm case ASN1_ITYPE_SEQUENCE: 366109998Smarkm p = *in; 367109998Smarkm tmplen = len; 368109998Smarkm 369109998Smarkm /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ 370160814Ssimon if (tag == -1) 371160814Ssimon { 372109998Smarkm tag = V_ASN1_SEQUENCE; 373109998Smarkm aclass = V_ASN1_UNIVERSAL; 374160814Ssimon } 375109998Smarkm /* Get SEQUENCE length and update len, p */ 376160814Ssimon ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, 377160814Ssimon &p, len, tag, aclass, opt, ctx); 378160814Ssimon if (!ret) 379160814Ssimon { 380160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 381160814Ssimon ERR_R_NESTED_ASN1_ERROR); 382109998Smarkm goto err; 383160814Ssimon } 384160814Ssimon else if (ret == -1) 385160814Ssimon return -1; 386160814Ssimon if (aux && (aux->flags & ASN1_AFLG_BROKEN)) 387160814Ssimon { 388109998Smarkm len = tmplen - (p - *in); 389109998Smarkm seq_nolen = 1; 390160814Ssimon } 391160814Ssimon /* If indefinite we don't do a length check */ 392160814Ssimon else seq_nolen = seq_eoc; 393160814Ssimon if (!cst) 394160814Ssimon { 395160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 396160814Ssimon ASN1_R_SEQUENCE_NOT_CONSTRUCTED); 397109998Smarkm goto err; 398160814Ssimon } 399109998Smarkm 400160814Ssimon if (!*pval && !ASN1_item_ex_new(pval, it)) 401160814Ssimon { 402160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 403160814Ssimon ERR_R_NESTED_ASN1_ERROR); 404160814Ssimon goto err; 405109998Smarkm } 406160814Ssimon 407238405Sjkim if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) 408109998Smarkm goto auxerr; 409109998Smarkm 410109998Smarkm /* Get each field entry */ 411160814Ssimon for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) 412160814Ssimon { 413109998Smarkm const ASN1_TEMPLATE *seqtt; 414109998Smarkm ASN1_VALUE **pseqval; 415109998Smarkm seqtt = asn1_do_adb(pval, tt, 1); 416160814Ssimon if (!seqtt) 417160814Ssimon goto err; 418109998Smarkm pseqval = asn1_get_field_ptr(pval, seqtt); 419109998Smarkm /* Have we ran out of data? */ 420160814Ssimon if (!len) 421160814Ssimon break; 422109998Smarkm q = p; 423160814Ssimon if (asn1_check_eoc(&p, len)) 424160814Ssimon { 425160814Ssimon if (!seq_eoc) 426160814Ssimon { 427160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 428160814Ssimon ASN1_R_UNEXPECTED_EOC); 429109998Smarkm goto err; 430160814Ssimon } 431109998Smarkm len -= p - q; 432109998Smarkm seq_eoc = 0; 433109998Smarkm q = p; 434109998Smarkm break; 435160814Ssimon } 436160814Ssimon /* This determines the OPTIONAL flag value. The field 437160814Ssimon * cannot be omitted if it is the last of a SEQUENCE 438160814Ssimon * and there is still data to be read. This isn't 439160814Ssimon * strictly necessary but it increases efficiency in 440160814Ssimon * some cases. 441109998Smarkm */ 442160814Ssimon if (i == (it->tcount - 1)) 443160814Ssimon isopt = 0; 444109998Smarkm else isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); 445160814Ssimon /* attempt to read in field, allowing each to be 446160814Ssimon * OPTIONAL */ 447160814Ssimon 448160814Ssimon ret = asn1_template_ex_d2i(pseqval, &p, len, 449160814Ssimon seqtt, isopt, ctx); 450160814Ssimon if (!ret) 451160814Ssimon { 452109998Smarkm errtt = seqtt; 453109998Smarkm goto err; 454160814Ssimon } 455160814Ssimon else if (ret == -1) 456160814Ssimon { 457160814Ssimon /* OPTIONAL component absent. 458160814Ssimon * Free and zero the field. 459109998Smarkm */ 460109998Smarkm ASN1_template_free(pseqval, seqtt); 461109998Smarkm continue; 462160814Ssimon } 463109998Smarkm /* Update length */ 464109998Smarkm len -= p - q; 465160814Ssimon } 466160814Ssimon 467109998Smarkm /* Check for EOC if expecting one */ 468160814Ssimon if (seq_eoc && !asn1_check_eoc(&p, len)) 469160814Ssimon { 470109998Smarkm ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MISSING_EOC); 471109998Smarkm goto err; 472160814Ssimon } 473109998Smarkm /* Check all data read */ 474160814Ssimon if (!seq_nolen && len) 475160814Ssimon { 476160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 477160814Ssimon ASN1_R_SEQUENCE_LENGTH_MISMATCH); 478109998Smarkm goto err; 479160814Ssimon } 480109998Smarkm 481109998Smarkm /* If we get here we've got no more data in the SEQUENCE, 482109998Smarkm * however we may not have read all fields so check all 483109998Smarkm * remaining are OPTIONAL and clear any that are. 484109998Smarkm */ 485160814Ssimon for (; i < it->tcount; tt++, i++) 486160814Ssimon { 487109998Smarkm const ASN1_TEMPLATE *seqtt; 488109998Smarkm seqtt = asn1_do_adb(pval, tt, 1); 489160814Ssimon if (!seqtt) 490160814Ssimon goto err; 491160814Ssimon if (seqtt->flags & ASN1_TFLG_OPTIONAL) 492160814Ssimon { 493109998Smarkm ASN1_VALUE **pseqval; 494109998Smarkm pseqval = asn1_get_field_ptr(pval, seqtt); 495109998Smarkm ASN1_template_free(pseqval, seqtt); 496160814Ssimon } 497160814Ssimon else 498160814Ssimon { 499109998Smarkm errtt = seqtt; 500160814Ssimon ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 501160814Ssimon ASN1_R_FIELD_MISSING); 502109998Smarkm goto err; 503160814Ssimon } 504109998Smarkm } 505109998Smarkm /* Save encoding */ 506160814Ssimon if (!asn1_enc_save(pval, *in, p - *in, it)) 507160814Ssimon goto auxerr; 508109998Smarkm *in = p; 509238405Sjkim if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) 510109998Smarkm goto auxerr; 511109998Smarkm return 1; 512109998Smarkm 513109998Smarkm default: 514109998Smarkm return 0; 515160814Ssimon } 516109998Smarkm auxerr: 517109998Smarkm ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_AUX_ERROR); 518109998Smarkm err: 519109998Smarkm ASN1_item_ex_free(pval, it); 520160814Ssimon if (errtt) 521160814Ssimon ERR_add_error_data(4, "Field=", errtt->field_name, 522160814Ssimon ", Type=", it->sname); 523160814Ssimon else 524160814Ssimon ERR_add_error_data(2, "Type=", it->sname); 525109998Smarkm return 0; 526160814Ssimon } 527109998Smarkm 528160814Ssimon/* Templates are handled with two separate functions. 529160814Ssimon * One handles any EXPLICIT tag and the other handles the rest. 530109998Smarkm */ 531109998Smarkm 532160814Ssimonstatic int asn1_template_ex_d2i(ASN1_VALUE **val, 533160814Ssimon const unsigned char **in, long inlen, 534160814Ssimon const ASN1_TEMPLATE *tt, char opt, 535160814Ssimon ASN1_TLC *ctx) 536160814Ssimon { 537109998Smarkm int flags, aclass; 538109998Smarkm int ret; 539109998Smarkm long len; 540160814Ssimon const unsigned char *p, *q; 541109998Smarkm char exp_eoc; 542160814Ssimon if (!val) 543160814Ssimon return 0; 544109998Smarkm flags = tt->flags; 545109998Smarkm aclass = flags & ASN1_TFLG_TAG_CLASS; 546109998Smarkm 547109998Smarkm p = *in; 548109998Smarkm 549109998Smarkm /* Check if EXPLICIT tag expected */ 550160814Ssimon if (flags & ASN1_TFLG_EXPTAG) 551160814Ssimon { 552109998Smarkm char cst; 553160814Ssimon /* Need to work out amount of data available to the inner 554160814Ssimon * content and where it starts: so read in EXPLICIT header to 555160814Ssimon * get the info. 556109998Smarkm */ 557160814Ssimon ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, 558160814Ssimon &p, inlen, tt->tag, aclass, opt, ctx); 559109998Smarkm q = p; 560160814Ssimon if (!ret) 561160814Ssimon { 562160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, 563160814Ssimon ERR_R_NESTED_ASN1_ERROR); 564109998Smarkm return 0; 565160814Ssimon } 566160814Ssimon else if (ret == -1) 567160814Ssimon return -1; 568160814Ssimon if (!cst) 569160814Ssimon { 570160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, 571160814Ssimon ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); 572109998Smarkm return 0; 573160814Ssimon } 574109998Smarkm /* We've found the field so it can't be OPTIONAL now */ 575109998Smarkm ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx); 576160814Ssimon if (!ret) 577160814Ssimon { 578160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, 579160814Ssimon ERR_R_NESTED_ASN1_ERROR); 580109998Smarkm return 0; 581160814Ssimon } 582109998Smarkm /* We read the field in OK so update length */ 583109998Smarkm len -= p - q; 584160814Ssimon if (exp_eoc) 585160814Ssimon { 586109998Smarkm /* If NDEF we must have an EOC here */ 587160814Ssimon if (!asn1_check_eoc(&p, len)) 588160814Ssimon { 589160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, 590160814Ssimon ASN1_R_MISSING_EOC); 591109998Smarkm goto err; 592160814Ssimon } 593109998Smarkm } 594160814Ssimon else 595160814Ssimon { 596160814Ssimon /* Otherwise we must hit the EXPLICIT tag end or its 597160814Ssimon * an error */ 598160814Ssimon if (len) 599160814Ssimon { 600160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, 601160814Ssimon ASN1_R_EXPLICIT_LENGTH_MISMATCH); 602109998Smarkm goto err; 603160814Ssimon } 604109998Smarkm } 605109998Smarkm } 606160814Ssimon else 607160814Ssimon return asn1_template_noexp_d2i(val, in, inlen, 608160814Ssimon tt, opt, ctx); 609109998Smarkm 610109998Smarkm *in = p; 611109998Smarkm return 1; 612109998Smarkm 613109998Smarkm err: 614109998Smarkm ASN1_template_free(val, tt); 615109998Smarkm return 0; 616160814Ssimon } 617109998Smarkm 618160814Ssimonstatic int asn1_template_noexp_d2i(ASN1_VALUE **val, 619160814Ssimon const unsigned char **in, long len, 620160814Ssimon const ASN1_TEMPLATE *tt, char opt, 621160814Ssimon ASN1_TLC *ctx) 622160814Ssimon { 623109998Smarkm int flags, aclass; 624109998Smarkm int ret; 625160814Ssimon const unsigned char *p, *q; 626160814Ssimon if (!val) 627160814Ssimon return 0; 628109998Smarkm flags = tt->flags; 629109998Smarkm aclass = flags & ASN1_TFLG_TAG_CLASS; 630109998Smarkm 631109998Smarkm p = *in; 632109998Smarkm q = p; 633109998Smarkm 634160814Ssimon if (flags & ASN1_TFLG_SK_MASK) 635160814Ssimon { 636109998Smarkm /* SET OF, SEQUENCE OF */ 637109998Smarkm int sktag, skaclass; 638109998Smarkm char sk_eoc; 639109998Smarkm /* First work out expected inner tag value */ 640160814Ssimon if (flags & ASN1_TFLG_IMPTAG) 641160814Ssimon { 642109998Smarkm sktag = tt->tag; 643109998Smarkm skaclass = aclass; 644160814Ssimon } 645160814Ssimon else 646160814Ssimon { 647109998Smarkm skaclass = V_ASN1_UNIVERSAL; 648160814Ssimon if (flags & ASN1_TFLG_SET_OF) 649160814Ssimon sktag = V_ASN1_SET; 650160814Ssimon else 651160814Ssimon sktag = V_ASN1_SEQUENCE; 652160814Ssimon } 653109998Smarkm /* Get the tag */ 654160814Ssimon ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, 655160814Ssimon &p, len, sktag, skaclass, opt, ctx); 656160814Ssimon if (!ret) 657160814Ssimon { 658160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 659160814Ssimon ERR_R_NESTED_ASN1_ERROR); 660109998Smarkm return 0; 661160814Ssimon } 662160814Ssimon else if (ret == -1) 663160814Ssimon return -1; 664160814Ssimon if (!*val) 665160814Ssimon *val = (ASN1_VALUE *)sk_new_null(); 666160814Ssimon else 667160814Ssimon { 668109998Smarkm /* We've got a valid STACK: free up any items present */ 669238405Sjkim STACK_OF(ASN1_VALUE) *sktmp 670238405Sjkim = (STACK_OF(ASN1_VALUE) *)*val; 671109998Smarkm ASN1_VALUE *vtmp; 672238405Sjkim while(sk_ASN1_VALUE_num(sktmp) > 0) 673160814Ssimon { 674238405Sjkim vtmp = sk_ASN1_VALUE_pop(sktmp); 675160814Ssimon ASN1_item_ex_free(&vtmp, 676160814Ssimon ASN1_ITEM_ptr(tt->item)); 677160814Ssimon } 678109998Smarkm } 679109998Smarkm 680160814Ssimon if (!*val) 681160814Ssimon { 682160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 683160814Ssimon ERR_R_MALLOC_FAILURE); 684109998Smarkm goto err; 685160814Ssimon } 686160814Ssimon 687109998Smarkm /* Read as many items as we can */ 688160814Ssimon while(len > 0) 689160814Ssimon { 690109998Smarkm ASN1_VALUE *skfield; 691109998Smarkm q = p; 692109998Smarkm /* See if EOC found */ 693160814Ssimon if (asn1_check_eoc(&p, len)) 694160814Ssimon { 695160814Ssimon if (!sk_eoc) 696160814Ssimon { 697160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 698160814Ssimon ASN1_R_UNEXPECTED_EOC); 699109998Smarkm goto err; 700160814Ssimon } 701109998Smarkm len -= p - q; 702109998Smarkm sk_eoc = 0; 703109998Smarkm break; 704160814Ssimon } 705109998Smarkm skfield = NULL; 706160814Ssimon if (!ASN1_item_ex_d2i(&skfield, &p, len, 707160814Ssimon ASN1_ITEM_ptr(tt->item), 708160814Ssimon -1, 0, 0, ctx)) 709160814Ssimon { 710160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 711160814Ssimon ERR_R_NESTED_ASN1_ERROR); 712109998Smarkm goto err; 713160814Ssimon } 714109998Smarkm len -= p - q; 715238405Sjkim if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, 716238405Sjkim skfield)) 717160814Ssimon { 718160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 719160814Ssimon ERR_R_MALLOC_FAILURE); 720109998Smarkm goto err; 721160814Ssimon } 722109998Smarkm } 723160814Ssimon if (sk_eoc) 724160814Ssimon { 725160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ASN1_R_MISSING_EOC); 726109998Smarkm goto err; 727160814Ssimon } 728109998Smarkm } 729160814Ssimon else if (flags & ASN1_TFLG_IMPTAG) 730160814Ssimon { 731109998Smarkm /* IMPLICIT tagging */ 732160814Ssimon ret = ASN1_item_ex_d2i(val, &p, len, 733160814Ssimon ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx); 734160814Ssimon if (!ret) 735160814Ssimon { 736160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 737160814Ssimon ERR_R_NESTED_ASN1_ERROR); 738109998Smarkm goto err; 739160814Ssimon } 740160814Ssimon else if (ret == -1) 741160814Ssimon return -1; 742160814Ssimon } 743160814Ssimon else 744160814Ssimon { 745109998Smarkm /* Nothing special */ 746160814Ssimon ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), 747160814Ssimon -1, 0, opt, ctx); 748160814Ssimon if (!ret) 749160814Ssimon { 750160814Ssimon ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 751160814Ssimon ERR_R_NESTED_ASN1_ERROR); 752109998Smarkm goto err; 753160814Ssimon } 754160814Ssimon else if (ret == -1) 755160814Ssimon return -1; 756160814Ssimon } 757109998Smarkm 758109998Smarkm *in = p; 759109998Smarkm return 1; 760109998Smarkm 761109998Smarkm err: 762109998Smarkm ASN1_template_free(val, tt); 763109998Smarkm return 0; 764160814Ssimon } 765109998Smarkm 766160814Ssimonstatic int asn1_d2i_ex_primitive(ASN1_VALUE **pval, 767160814Ssimon const unsigned char **in, long inlen, 768160814Ssimon const ASN1_ITEM *it, 769160814Ssimon int tag, int aclass, char opt, ASN1_TLC *ctx) 770160814Ssimon { 771109998Smarkm int ret = 0, utype; 772109998Smarkm long plen; 773109998Smarkm char cst, inf, free_cont = 0; 774160814Ssimon const unsigned char *p; 775109998Smarkm BUF_MEM buf; 776160814Ssimon const unsigned char *cont = NULL; 777109998Smarkm long len; 778160814Ssimon if (!pval) 779160814Ssimon { 780109998Smarkm ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL); 781109998Smarkm return 0; /* Should never happen */ 782160814Ssimon } 783109998Smarkm 784160814Ssimon if (it->itype == ASN1_ITYPE_MSTRING) 785160814Ssimon { 786109998Smarkm utype = tag; 787109998Smarkm tag = -1; 788160814Ssimon } 789160814Ssimon else 790160814Ssimon utype = it->utype; 791109998Smarkm 792160814Ssimon if (utype == V_ASN1_ANY) 793160814Ssimon { 794109998Smarkm /* If type is ANY need to figure out type from tag */ 795109998Smarkm unsigned char oclass; 796160814Ssimon if (tag >= 0) 797160814Ssimon { 798160814Ssimon ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, 799160814Ssimon ASN1_R_ILLEGAL_TAGGED_ANY); 800109998Smarkm return 0; 801160814Ssimon } 802160814Ssimon if (opt) 803160814Ssimon { 804160814Ssimon ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, 805160814Ssimon ASN1_R_ILLEGAL_OPTIONAL_ANY); 806109998Smarkm return 0; 807160814Ssimon } 808109998Smarkm p = *in; 809160814Ssimon ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, 810160814Ssimon &p, inlen, -1, 0, 0, ctx); 811160814Ssimon if (!ret) 812160814Ssimon { 813160814Ssimon ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, 814160814Ssimon ERR_R_NESTED_ASN1_ERROR); 815109998Smarkm return 0; 816160814Ssimon } 817160814Ssimon if (oclass != V_ASN1_UNIVERSAL) 818160814Ssimon utype = V_ASN1_OTHER; 819109998Smarkm } 820160814Ssimon if (tag == -1) 821160814Ssimon { 822109998Smarkm tag = utype; 823109998Smarkm aclass = V_ASN1_UNIVERSAL; 824160814Ssimon } 825109998Smarkm p = *in; 826109998Smarkm /* Check header */ 827160814Ssimon ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, 828160814Ssimon &p, inlen, tag, aclass, opt, ctx); 829160814Ssimon if (!ret) 830160814Ssimon { 831109998Smarkm ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); 832109998Smarkm return 0; 833160814Ssimon } 834160814Ssimon else if (ret == -1) 835160814Ssimon return -1; 836162911Ssimon ret = 0; 837109998Smarkm /* SEQUENCE, SET and "OTHER" are left in encoded form */ 838160814Ssimon if ((utype == V_ASN1_SEQUENCE) 839160814Ssimon || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) 840160814Ssimon { 841160814Ssimon /* Clear context cache for type OTHER because the auto clear 842160814Ssimon * when we have a exact match wont work 843109998Smarkm */ 844160814Ssimon if (utype == V_ASN1_OTHER) 845160814Ssimon { 846109998Smarkm asn1_tlc_clear(ctx); 847160814Ssimon } 848109998Smarkm /* SEQUENCE and SET must be constructed */ 849160814Ssimon else if (!cst) 850160814Ssimon { 851160814Ssimon ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, 852160814Ssimon ASN1_R_TYPE_NOT_CONSTRUCTED); 853109998Smarkm return 0; 854160814Ssimon } 855109998Smarkm 856109998Smarkm cont = *in; 857109998Smarkm /* If indefinite length constructed find the real end */ 858160814Ssimon if (inf) 859160814Ssimon { 860160814Ssimon if (!asn1_find_end(&p, plen, inf)) 861160814Ssimon goto err; 862109998Smarkm len = p - cont; 863160814Ssimon } 864160814Ssimon else 865160814Ssimon { 866109998Smarkm len = p - cont + plen; 867109998Smarkm p += plen; 868109998Smarkm buf.data = NULL; 869160814Ssimon } 870109998Smarkm } 871160814Ssimon else if (cst) 872160814Ssimon { 873279264Sdelphij if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN 874279264Sdelphij || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER 875279264Sdelphij || utype == V_ASN1_ENUMERATED) 876279264Sdelphij { 877279264Sdelphij ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, 878279264Sdelphij ASN1_R_TYPE_NOT_PRIMITIVE); 879279264Sdelphij return 0; 880279264Sdelphij } 881109998Smarkm buf.length = 0; 882109998Smarkm buf.max = 0; 883109998Smarkm buf.data = NULL; 884109998Smarkm /* Should really check the internal tags are correct but 885109998Smarkm * some things may get this wrong. The relevant specs 886109998Smarkm * say that constructed string types should be OCTET STRINGs 887109998Smarkm * internally irrespective of the type. So instead just check 888109998Smarkm * for UNIVERSAL class and ignore the tag. 889109998Smarkm */ 890194206Ssimon if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) 891162911Ssimon { 892162911Ssimon free_cont = 1; 893160814Ssimon goto err; 894162911Ssimon } 895109998Smarkm len = buf.length; 896109998Smarkm /* Append a final null to string */ 897160814Ssimon if (!BUF_MEM_grow_clean(&buf, len + 1)) 898160814Ssimon { 899160814Ssimon ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, 900160814Ssimon ERR_R_MALLOC_FAILURE); 901109998Smarkm return 0; 902160814Ssimon } 903109998Smarkm buf.data[len] = 0; 904160814Ssimon cont = (const unsigned char *)buf.data; 905109998Smarkm free_cont = 1; 906160814Ssimon } 907160814Ssimon else 908160814Ssimon { 909109998Smarkm cont = p; 910109998Smarkm len = plen; 911109998Smarkm p += plen; 912160814Ssimon } 913109998Smarkm 914109998Smarkm /* We now have content length and type: translate into a structure */ 915160814Ssimon if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it)) 916160814Ssimon goto err; 917109998Smarkm 918109998Smarkm *in = p; 919109998Smarkm ret = 1; 920109998Smarkm err: 921160814Ssimon if (free_cont && buf.data) OPENSSL_free(buf.data); 922109998Smarkm return ret; 923160814Ssimon } 924109998Smarkm 925109998Smarkm/* Translate ASN1 content octets into a structure */ 926109998Smarkm 927160814Ssimonint asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, 928160814Ssimon int utype, char *free_cont, const ASN1_ITEM *it) 929160814Ssimon { 930120631Snectar ASN1_VALUE **opval = NULL; 931109998Smarkm ASN1_STRING *stmp; 932109998Smarkm ASN1_TYPE *typ = NULL; 933109998Smarkm int ret = 0; 934109998Smarkm const ASN1_PRIMITIVE_FUNCS *pf; 935109998Smarkm ASN1_INTEGER **tint; 936109998Smarkm pf = it->funcs; 937160814Ssimon 938160814Ssimon if (pf && pf->prim_c2i) 939160814Ssimon return pf->prim_c2i(pval, cont, len, utype, free_cont, it); 940109998Smarkm /* If ANY type clear type and set pointer to internal value */ 941160814Ssimon if (it->utype == V_ASN1_ANY) 942160814Ssimon { 943160814Ssimon if (!*pval) 944160814Ssimon { 945109998Smarkm typ = ASN1_TYPE_new(); 946160814Ssimon if (typ == NULL) 947160814Ssimon goto err; 948109998Smarkm *pval = (ASN1_VALUE *)typ; 949160814Ssimon } 950160814Ssimon else 951160814Ssimon typ = (ASN1_TYPE *)*pval; 952160814Ssimon 953160814Ssimon if (utype != typ->type) 954160814Ssimon ASN1_TYPE_set(typ, utype, NULL); 955120631Snectar opval = pval; 956194206Ssimon pval = &typ->value.asn1_value; 957160814Ssimon } 958160814Ssimon switch(utype) 959160814Ssimon { 960109998Smarkm case V_ASN1_OBJECT: 961160814Ssimon if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) 962160814Ssimon goto err; 963109998Smarkm break; 964109998Smarkm 965109998Smarkm case V_ASN1_NULL: 966160814Ssimon if (len) 967160814Ssimon { 968160814Ssimon ASN1err(ASN1_F_ASN1_EX_C2I, 969160814Ssimon ASN1_R_NULL_IS_WRONG_LENGTH); 970109998Smarkm goto err; 971160814Ssimon } 972109998Smarkm *pval = (ASN1_VALUE *)1; 973109998Smarkm break; 974109998Smarkm 975109998Smarkm case V_ASN1_BOOLEAN: 976160814Ssimon if (len != 1) 977160814Ssimon { 978160814Ssimon ASN1err(ASN1_F_ASN1_EX_C2I, 979160814Ssimon ASN1_R_BOOLEAN_IS_WRONG_LENGTH); 980109998Smarkm goto err; 981160814Ssimon } 982160814Ssimon else 983160814Ssimon { 984109998Smarkm ASN1_BOOLEAN *tbool; 985109998Smarkm tbool = (ASN1_BOOLEAN *)pval; 986109998Smarkm *tbool = *cont; 987160814Ssimon } 988109998Smarkm break; 989109998Smarkm 990109998Smarkm case V_ASN1_BIT_STRING: 991160814Ssimon if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) 992160814Ssimon goto err; 993109998Smarkm break; 994109998Smarkm 995109998Smarkm case V_ASN1_INTEGER: 996109998Smarkm case V_ASN1_NEG_INTEGER: 997109998Smarkm case V_ASN1_ENUMERATED: 998109998Smarkm case V_ASN1_NEG_ENUMERATED: 999109998Smarkm tint = (ASN1_INTEGER **)pval; 1000160814Ssimon if (!c2i_ASN1_INTEGER(tint, &cont, len)) 1001160814Ssimon goto err; 1002109998Smarkm /* Fixup type to match the expected form */ 1003109998Smarkm (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); 1004109998Smarkm break; 1005109998Smarkm 1006109998Smarkm case V_ASN1_OCTET_STRING: 1007109998Smarkm case V_ASN1_NUMERICSTRING: 1008109998Smarkm case V_ASN1_PRINTABLESTRING: 1009109998Smarkm case V_ASN1_T61STRING: 1010109998Smarkm case V_ASN1_VIDEOTEXSTRING: 1011109998Smarkm case V_ASN1_IA5STRING: 1012109998Smarkm case V_ASN1_UTCTIME: 1013109998Smarkm case V_ASN1_GENERALIZEDTIME: 1014109998Smarkm case V_ASN1_GRAPHICSTRING: 1015109998Smarkm case V_ASN1_VISIBLESTRING: 1016109998Smarkm case V_ASN1_GENERALSTRING: 1017109998Smarkm case V_ASN1_UNIVERSALSTRING: 1018109998Smarkm case V_ASN1_BMPSTRING: 1019109998Smarkm case V_ASN1_UTF8STRING: 1020109998Smarkm case V_ASN1_OTHER: 1021109998Smarkm case V_ASN1_SET: 1022109998Smarkm case V_ASN1_SEQUENCE: 1023109998Smarkm default: 1024191381Scperciva if (utype == V_ASN1_BMPSTRING && (len & 1)) 1025191381Scperciva { 1026191381Scperciva ASN1err(ASN1_F_ASN1_EX_C2I, 1027191381Scperciva ASN1_R_BMPSTRING_IS_WRONG_LENGTH); 1028191381Scperciva goto err; 1029191381Scperciva } 1030191381Scperciva if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) 1031191381Scperciva { 1032191381Scperciva ASN1err(ASN1_F_ASN1_EX_C2I, 1033191381Scperciva ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); 1034191381Scperciva goto err; 1035191381Scperciva } 1036109998Smarkm /* All based on ASN1_STRING and handled the same */ 1037160814Ssimon if (!*pval) 1038160814Ssimon { 1039109998Smarkm stmp = ASN1_STRING_type_new(utype); 1040160814Ssimon if (!stmp) 1041160814Ssimon { 1042160814Ssimon ASN1err(ASN1_F_ASN1_EX_C2I, 1043160814Ssimon ERR_R_MALLOC_FAILURE); 1044109998Smarkm goto err; 1045160814Ssimon } 1046160814Ssimon *pval = (ASN1_VALUE *)stmp; 1047109998Smarkm } 1048160814Ssimon else 1049160814Ssimon { 1050109998Smarkm stmp = (ASN1_STRING *)*pval; 1051109998Smarkm stmp->type = utype; 1052160814Ssimon } 1053109998Smarkm /* If we've already allocated a buffer use it */ 1054160814Ssimon if (*free_cont) 1055160814Ssimon { 1056160814Ssimon if (stmp->data) 1057160814Ssimon OPENSSL_free(stmp->data); 1058160814Ssimon stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */ 1059109998Smarkm stmp->length = len; 1060109998Smarkm *free_cont = 0; 1061160814Ssimon } 1062160814Ssimon else 1063160814Ssimon { 1064160814Ssimon if (!ASN1_STRING_set(stmp, cont, len)) 1065160814Ssimon { 1066160814Ssimon ASN1err(ASN1_F_ASN1_EX_C2I, 1067160814Ssimon ERR_R_MALLOC_FAILURE); 1068109998Smarkm ASN1_STRING_free(stmp); 1069109998Smarkm *pval = NULL; 1070109998Smarkm goto err; 1071160814Ssimon } 1072109998Smarkm } 1073160814Ssimon break; 1074109998Smarkm } 1075109998Smarkm /* If ASN1_ANY and NULL type fix up value */ 1076160814Ssimon if (typ && (utype == V_ASN1_NULL)) 1077160814Ssimon typ->value.ptr = NULL; 1078109998Smarkm 1079109998Smarkm ret = 1; 1080109998Smarkm err: 1081160814Ssimon if (!ret) 1082120631Snectar { 1083120631Snectar ASN1_TYPE_free(typ); 1084120631Snectar if (opval) 1085120631Snectar *opval = NULL; 1086120631Snectar } 1087109998Smarkm return ret; 1088160814Ssimon } 1089109998Smarkm 1090160814Ssimon 1091160814Ssimon/* This function finds the end of an ASN1 structure when passed its maximum 1092160814Ssimon * length, whether it is indefinite length and a pointer to the content. 1093160814Ssimon * This is more efficient than calling asn1_collect because it does not 1094160814Ssimon * recurse on each indefinite length header. 1095160814Ssimon */ 1096160814Ssimon 1097160814Ssimonstatic int asn1_find_end(const unsigned char **in, long len, char inf) 1098160814Ssimon { 1099160814Ssimon int expected_eoc; 1100160814Ssimon long plen; 1101160814Ssimon const unsigned char *p = *in, *q; 1102160814Ssimon /* If not indefinite length constructed just add length */ 1103160814Ssimon if (inf == 0) 1104160814Ssimon { 1105160814Ssimon *in += len; 1106160814Ssimon return 1; 1107160814Ssimon } 1108160814Ssimon expected_eoc = 1; 1109160814Ssimon /* Indefinite length constructed form. Find the end when enough EOCs 1110160814Ssimon * are found. If more indefinite length constructed headers 1111160814Ssimon * are encountered increment the expected eoc count otherwise just 1112160814Ssimon * skip to the end of the data. 1113160814Ssimon */ 1114160814Ssimon while (len > 0) 1115160814Ssimon { 1116160814Ssimon if(asn1_check_eoc(&p, len)) 1117160814Ssimon { 1118160814Ssimon expected_eoc--; 1119160814Ssimon if (expected_eoc == 0) 1120160814Ssimon break; 1121160814Ssimon len -= 2; 1122160814Ssimon continue; 1123160814Ssimon } 1124160814Ssimon q = p; 1125160814Ssimon /* Just read in a header: only care about the length */ 1126160814Ssimon if(!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len, 1127160814Ssimon -1, 0, 0, NULL)) 1128160814Ssimon { 1129160814Ssimon ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR); 1130160814Ssimon return 0; 1131160814Ssimon } 1132160814Ssimon if (inf) 1133160814Ssimon expected_eoc++; 1134160814Ssimon else 1135160814Ssimon p += plen; 1136160814Ssimon len -= p - q; 1137160814Ssimon } 1138160814Ssimon if (expected_eoc) 1139160814Ssimon { 1140160814Ssimon ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC); 1141160814Ssimon return 0; 1142160814Ssimon } 1143160814Ssimon *in = p; 1144160814Ssimon return 1; 1145160814Ssimon } 1146109998Smarkm/* This function collects the asn1 data from a constructred string 1147109998Smarkm * type into a buffer. The values of 'in' and 'len' should refer 1148109998Smarkm * to the contents of the constructed type and 'inf' should be set 1149160814Ssimon * if it is indefinite length. 1150109998Smarkm */ 1151109998Smarkm 1152194206Ssimon#ifndef ASN1_MAX_STRING_NEST 1153194206Ssimon/* This determines how many levels of recursion are permitted in ASN1 1154194206Ssimon * string types. If it is not limited stack overflows can occur. If set 1155194206Ssimon * to zero no recursion is allowed at all. Although zero should be adequate 1156194206Ssimon * examples exist that require a value of 1. So 5 should be more than enough. 1157194206Ssimon */ 1158194206Ssimon#define ASN1_MAX_STRING_NEST 5 1159194206Ssimon#endif 1160194206Ssimon 1161194206Ssimon 1162160814Ssimonstatic int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, 1163194206Ssimon char inf, int tag, int aclass, int depth) 1164160814Ssimon { 1165160814Ssimon const unsigned char *p, *q; 1166109998Smarkm long plen; 1167109998Smarkm char cst, ininf; 1168109998Smarkm p = *in; 1169109998Smarkm inf &= 1; 1170160814Ssimon /* If no buffer and not indefinite length constructed just pass over 1171160814Ssimon * the encoded data */ 1172160814Ssimon if (!buf && !inf) 1173160814Ssimon { 1174109998Smarkm *in += len; 1175109998Smarkm return 1; 1176160814Ssimon } 1177160814Ssimon while(len > 0) 1178160814Ssimon { 1179109998Smarkm q = p; 1180109998Smarkm /* Check for EOC */ 1181160814Ssimon if (asn1_check_eoc(&p, len)) 1182160814Ssimon { 1183160814Ssimon /* EOC is illegal outside indefinite length 1184160814Ssimon * constructed form */ 1185160814Ssimon if (!inf) 1186160814Ssimon { 1187160814Ssimon ASN1err(ASN1_F_ASN1_COLLECT, 1188160814Ssimon ASN1_R_UNEXPECTED_EOC); 1189109998Smarkm return 0; 1190160814Ssimon } 1191109998Smarkm inf = 0; 1192109998Smarkm break; 1193160814Ssimon } 1194160814Ssimon 1195160814Ssimon if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p, 1196160814Ssimon len, tag, aclass, 0, NULL)) 1197160814Ssimon { 1198109998Smarkm ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR); 1199109998Smarkm return 0; 1200160814Ssimon } 1201160814Ssimon 1202109998Smarkm /* If indefinite length constructed update max length */ 1203160814Ssimon if (cst) 1204160814Ssimon { 1205194206Ssimon if (depth >= ASN1_MAX_STRING_NEST) 1206194206Ssimon { 1207194206Ssimon ASN1err(ASN1_F_ASN1_COLLECT, 1208194206Ssimon ASN1_R_NESTED_ASN1_STRING); 1209160814Ssimon return 0; 1210194206Ssimon } 1211194206Ssimon if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, 1212194206Ssimon depth + 1)) 1213194206Ssimon return 0; 1214160814Ssimon } 1215160814Ssimon else if (plen && !collect_data(buf, &p, plen)) 1216160814Ssimon return 0; 1217160814Ssimon len -= p - q; 1218109998Smarkm } 1219160814Ssimon if (inf) 1220160814Ssimon { 1221109998Smarkm ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC); 1222109998Smarkm return 0; 1223160814Ssimon } 1224109998Smarkm *in = p; 1225109998Smarkm return 1; 1226160814Ssimon } 1227109998Smarkm 1228160814Ssimonstatic int collect_data(BUF_MEM *buf, const unsigned char **p, long plen) 1229160814Ssimon { 1230160814Ssimon int len; 1231160814Ssimon if (buf) 1232160814Ssimon { 1233160814Ssimon len = buf->length; 1234160814Ssimon if (!BUF_MEM_grow_clean(buf, len + plen)) 1235160814Ssimon { 1236160814Ssimon ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE); 1237160814Ssimon return 0; 1238109998Smarkm } 1239160814Ssimon memcpy(buf->data + len, *p, plen); 1240109998Smarkm } 1241160814Ssimon *p += plen; 1242160814Ssimon return 1; 1243160814Ssimon } 1244109998Smarkm 1245109998Smarkm/* Check for ASN1 EOC and swallow it if found */ 1246109998Smarkm 1247160814Ssimonstatic int asn1_check_eoc(const unsigned char **in, long len) 1248160814Ssimon { 1249160814Ssimon const unsigned char *p; 1250160814Ssimon if (len < 2) return 0; 1251109998Smarkm p = *in; 1252160814Ssimon if (!p[0] && !p[1]) 1253160814Ssimon { 1254109998Smarkm *in += 2; 1255109998Smarkm return 1; 1256160814Ssimon } 1257160814Ssimon return 0; 1258109998Smarkm } 1259109998Smarkm 1260109998Smarkm/* Check an ASN1 tag and length: a bit like ASN1_get_object 1261109998Smarkm * but it sets the length for indefinite length constructed 1262109998Smarkm * form, we don't know the exact length but we can set an 1263109998Smarkm * upper bound to the amount of data available minus the 1264109998Smarkm * header length just read. 1265109998Smarkm */ 1266109998Smarkm 1267160814Ssimonstatic int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, 1268160814Ssimon char *inf, char *cst, 1269160814Ssimon const unsigned char **in, long len, 1270160814Ssimon int exptag, int expclass, char opt, 1271160814Ssimon ASN1_TLC *ctx) 1272160814Ssimon { 1273109998Smarkm int i; 1274109998Smarkm int ptag, pclass; 1275109998Smarkm long plen; 1276160814Ssimon const unsigned char *p, *q; 1277109998Smarkm p = *in; 1278109998Smarkm q = p; 1279109998Smarkm 1280160814Ssimon if (ctx && ctx->valid) 1281160814Ssimon { 1282109998Smarkm i = ctx->ret; 1283109998Smarkm plen = ctx->plen; 1284109998Smarkm pclass = ctx->pclass; 1285109998Smarkm ptag = ctx->ptag; 1286109998Smarkm p += ctx->hdrlen; 1287160814Ssimon } 1288160814Ssimon else 1289160814Ssimon { 1290109998Smarkm i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); 1291160814Ssimon if (ctx) 1292160814Ssimon { 1293109998Smarkm ctx->ret = i; 1294109998Smarkm ctx->plen = plen; 1295109998Smarkm ctx->pclass = pclass; 1296109998Smarkm ctx->ptag = ptag; 1297109998Smarkm ctx->hdrlen = p - q; 1298109998Smarkm ctx->valid = 1; 1299109998Smarkm /* If definite length, and no error, length + 1300109998Smarkm * header can't exceed total amount of data available. 1301109998Smarkm */ 1302160814Ssimon if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) 1303160814Ssimon { 1304160814Ssimon ASN1err(ASN1_F_ASN1_CHECK_TLEN, 1305160814Ssimon ASN1_R_TOO_LONG); 1306109998Smarkm asn1_tlc_clear(ctx); 1307109998Smarkm return 0; 1308160814Ssimon } 1309109998Smarkm } 1310109998Smarkm } 1311109998Smarkm 1312160814Ssimon if (i & 0x80) 1313160814Ssimon { 1314109998Smarkm ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER); 1315109998Smarkm asn1_tlc_clear(ctx); 1316109998Smarkm return 0; 1317160814Ssimon } 1318160814Ssimon if (exptag >= 0) 1319160814Ssimon { 1320160814Ssimon if ((exptag != ptag) || (expclass != pclass)) 1321160814Ssimon { 1322160814Ssimon /* If type is OPTIONAL, not an error: 1323160814Ssimon * indicate missing type. 1324109998Smarkm */ 1325160814Ssimon if (opt) return -1; 1326109998Smarkm asn1_tlc_clear(ctx); 1327109998Smarkm ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG); 1328109998Smarkm return 0; 1329160814Ssimon } 1330160814Ssimon /* We have a tag and class match: 1331160814Ssimon * assume we are going to do something with it */ 1332160814Ssimon asn1_tlc_clear(ctx); 1333109998Smarkm } 1334109998Smarkm 1335160814Ssimon if (i & 1) 1336160814Ssimon plen = len - (p - q); 1337109998Smarkm 1338160814Ssimon if (inf) 1339160814Ssimon *inf = i & 1; 1340109998Smarkm 1341160814Ssimon if (cst) 1342160814Ssimon *cst = i & V_ASN1_CONSTRUCTED; 1343109998Smarkm 1344160814Ssimon if (olen) 1345160814Ssimon *olen = plen; 1346109998Smarkm 1347160814Ssimon if (oclass) 1348160814Ssimon *oclass = pclass; 1349160814Ssimon 1350160814Ssimon if (otag) 1351160814Ssimon *otag = ptag; 1352160814Ssimon 1353109998Smarkm *in = p; 1354109998Smarkm return 1; 1355160814Ssimon } 1356