1109998Smarkm/* tasn_dec.c */ 2280304Sjkim/* 3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4280304Sjkim * 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 14280304Sjkim * 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, 72280304Sjkim 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, 77280304Sjkim char *inf, char *cst, 78280304Sjkim const unsigned char **in, long len, 79280304Sjkim int exptag, int expclass, char opt, ASN1_TLC *ctx); 80160814Ssimon 81160814Ssimonstatic int asn1_template_ex_d2i(ASN1_VALUE **pval, 82280304Sjkim const unsigned char **in, long len, 83280304Sjkim const ASN1_TEMPLATE *tt, char opt, 84280304Sjkim ASN1_TLC *ctx); 85160814Ssimonstatic int asn1_template_noexp_d2i(ASN1_VALUE **val, 86280304Sjkim const unsigned char **in, long len, 87280304Sjkim const ASN1_TEMPLATE *tt, char opt, 88280304Sjkim ASN1_TLC *ctx); 89160814Ssimonstatic int asn1_d2i_ex_primitive(ASN1_VALUE **pval, 90280304Sjkim const unsigned char **in, long len, 91280304Sjkim const ASN1_ITEM *it, 92280304Sjkim int tag, int aclass, char opt, 93280304Sjkim ASN1_TLC *ctx); 94160814Ssimon 95109998Smarkm/* Table to convert tags to bit values, used for MSTRING type */ 96167612Ssimonstatic const unsigned long tag2bit[32] = { 97280304Sjkim /* tags 0 - 3 */ 98280304Sjkim 0, 0, 0, B_ASN1_BIT_STRING, 99280304Sjkim /* tags 4- 7 */ 100280304Sjkim B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN, 101280304Sjkim /* tags 8-11 */ 102280304Sjkim B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, 103280304Sjkim /* tags 12-15 */ 104280304Sjkim B_ASN1_UTF8STRING, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, 105280304Sjkim /* tags 16-19 */ 106280304Sjkim B_ASN1_SEQUENCE, 0, B_ASN1_NUMERICSTRING, B_ASN1_PRINTABLESTRING, 107280304Sjkim /* tags 20-22 */ 108280304Sjkim B_ASN1_T61STRING, B_ASN1_VIDEOTEXSTRING, B_ASN1_IA5STRING, 109280304Sjkim /* tags 23-24 */ 110280304Sjkim B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, 111280304Sjkim /* tags 25-27 */ 112280304Sjkim B_ASN1_GRAPHICSTRING, B_ASN1_ISO64STRING, B_ASN1_GENERALSTRING, 113280304Sjkim /* tags 28-31 */ 114280304Sjkim B_ASN1_UNIVERSALSTRING, B_ASN1_UNKNOWN, B_ASN1_BMPSTRING, B_ASN1_UNKNOWN, 115280304Sjkim}; 116109998Smarkm 117109998Smarkmunsigned long ASN1_tag2bit(int tag) 118280304Sjkim{ 119280304Sjkim if ((tag < 0) || (tag > 30)) 120280304Sjkim return 0; 121280304Sjkim return tag2bit[tag]; 122280304Sjkim} 123109998Smarkm 124109998Smarkm/* Macro to initialize and invalidate the cache */ 125109998Smarkm 126280304Sjkim#define asn1_tlc_clear(c) if (c) (c)->valid = 0 127238405Sjkim/* Version to avoid compiler warning about 'c' always non-NULL */ 128280304Sjkim#define asn1_tlc_clear_nc(c) (c)->valid = 0 129109998Smarkm 130280304Sjkim/* 131280304Sjkim * Decode an ASN1 item, this currently behaves just like a standard 'd2i' 132280304Sjkim * function. 'in' points to a buffer to read the data from, in future we 133280304Sjkim * will have more advanced versions that can input data a piece at a time and 134280304Sjkim * this will simply be a special case. 135109998Smarkm */ 136109998Smarkm 137160814SsimonASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, 138280304Sjkim const unsigned char **in, long len, 139280304Sjkim const ASN1_ITEM *it) 140280304Sjkim{ 141280304Sjkim ASN1_TLC c; 142280304Sjkim ASN1_VALUE *ptmpval = NULL; 143280304Sjkim if (!pval) 144280304Sjkim pval = &ptmpval; 145280304Sjkim asn1_tlc_clear_nc(&c); 146280304Sjkim if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) 147280304Sjkim return *pval; 148280304Sjkim return NULL; 149280304Sjkim} 150109998Smarkm 151160814Ssimonint ASN1_template_d2i(ASN1_VALUE **pval, 152280304Sjkim const unsigned char **in, long len, 153280304Sjkim const ASN1_TEMPLATE *tt) 154280304Sjkim{ 155280304Sjkim ASN1_TLC c; 156280304Sjkim asn1_tlc_clear_nc(&c); 157280304Sjkim return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); 158280304Sjkim} 159109998Smarkm 160280304Sjkim/* 161280304Sjkim * Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and 162280304Sjkim * tag mismatch return -1 to handle OPTIONAL 163109998Smarkm */ 164109998Smarkm 165160814Ssimonint ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, 166280304Sjkim const ASN1_ITEM *it, 167280304Sjkim int tag, int aclass, char opt, ASN1_TLC *ctx) 168280304Sjkim{ 169280304Sjkim const ASN1_TEMPLATE *tt, *errtt = NULL; 170280304Sjkim const ASN1_COMPAT_FUNCS *cf; 171280304Sjkim const ASN1_EXTERN_FUNCS *ef; 172280304Sjkim const ASN1_AUX *aux = it->funcs; 173280304Sjkim ASN1_aux_cb *asn1_cb; 174280304Sjkim const unsigned char *p = NULL, *q; 175280304Sjkim unsigned char *wp = NULL; /* BIG FAT WARNING! BREAKS CONST WHERE USED */ 176280304Sjkim unsigned char imphack = 0, oclass; 177280304Sjkim char seq_eoc, seq_nolen, cst, isopt; 178280304Sjkim long tmplen; 179280304Sjkim int i; 180280304Sjkim int otag; 181280304Sjkim int ret = 0; 182280304Sjkim ASN1_VALUE **pchptr, *ptmpval; 183291721Sjkim int combine = aclass & ASN1_TFLG_COMBINE; 184291721Sjkim aclass &= ~ASN1_TFLG_COMBINE; 185280304Sjkim if (!pval) 186280304Sjkim return 0; 187280304Sjkim if (aux && aux->asn1_cb) 188280304Sjkim asn1_cb = aux->asn1_cb; 189280304Sjkim else 190280304Sjkim asn1_cb = 0; 191109998Smarkm 192280304Sjkim switch (it->itype) { 193280304Sjkim case ASN1_ITYPE_PRIMITIVE: 194280304Sjkim if (it->templates) { 195280304Sjkim /* 196280304Sjkim * tagging or OPTIONAL is currently illegal on an item template 197280304Sjkim * because the flags can't get passed down. In practice this 198280304Sjkim * isn't a problem: we include the relevant flags from the item 199280304Sjkim * template in the template itself. 200280304Sjkim */ 201280304Sjkim if ((tag != -1) || opt) { 202280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, 203280304Sjkim ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); 204280304Sjkim goto err; 205280304Sjkim } 206280304Sjkim return asn1_template_ex_d2i(pval, in, len, 207280304Sjkim it->templates, opt, ctx); 208280304Sjkim } 209280304Sjkim return asn1_d2i_ex_primitive(pval, in, len, it, 210280304Sjkim tag, aclass, opt, ctx); 211280304Sjkim break; 212109998Smarkm 213280304Sjkim case ASN1_ITYPE_MSTRING: 214280304Sjkim p = *in; 215280304Sjkim /* Just read in tag and class */ 216280304Sjkim ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, 217280304Sjkim &p, len, -1, 0, 1, ctx); 218280304Sjkim if (!ret) { 219280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 220280304Sjkim goto err; 221280304Sjkim } 222160814Ssimon 223280304Sjkim /* Must be UNIVERSAL class */ 224280304Sjkim if (oclass != V_ASN1_UNIVERSAL) { 225280304Sjkim /* If OPTIONAL, assume this is OK */ 226280304Sjkim if (opt) 227280304Sjkim return -1; 228280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL); 229280304Sjkim goto err; 230280304Sjkim } 231280304Sjkim /* Check tag matches bit map */ 232280304Sjkim if (!(ASN1_tag2bit(otag) & it->utype)) { 233280304Sjkim /* If OPTIONAL, assume this is OK */ 234280304Sjkim if (opt) 235280304Sjkim return -1; 236280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MSTRING_WRONG_TAG); 237280304Sjkim goto err; 238280304Sjkim } 239280304Sjkim return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx); 240109998Smarkm 241280304Sjkim case ASN1_ITYPE_EXTERN: 242280304Sjkim /* Use new style d2i */ 243280304Sjkim ef = it->funcs; 244280304Sjkim return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx); 245109998Smarkm 246280304Sjkim case ASN1_ITYPE_COMPAT: 247280304Sjkim /* we must resort to old style evil hackery */ 248280304Sjkim cf = it->funcs; 249109998Smarkm 250280304Sjkim /* If OPTIONAL see if it is there */ 251280304Sjkim if (opt) { 252280304Sjkim int exptag; 253280304Sjkim p = *in; 254280304Sjkim if (tag == -1) 255280304Sjkim exptag = it->utype; 256280304Sjkim else 257280304Sjkim exptag = tag; 258280304Sjkim /* 259280304Sjkim * Don't care about anything other than presence of expected tag 260280304Sjkim */ 261160814Ssimon 262280304Sjkim ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL, 263280304Sjkim &p, len, exptag, aclass, 1, ctx); 264280304Sjkim if (!ret) { 265280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 266280304Sjkim goto err; 267280304Sjkim } 268280304Sjkim if (ret == -1) 269280304Sjkim return -1; 270280304Sjkim } 271160814Ssimon 272280304Sjkim /* 273280304Sjkim * This is the old style evil hack IMPLICIT handling: since the 274280304Sjkim * underlying code is expecting a tag and class other than the one 275280304Sjkim * present we change the buffer temporarily then change it back 276280304Sjkim * afterwards. This doesn't and never did work for tags > 30. Yes 277280304Sjkim * this is *horrible* but it is only needed for old style d2i which 278280304Sjkim * will hopefully not be around for much longer. FIXME: should copy 279280304Sjkim * the buffer then modify it so the input buffer can be const: we 280280304Sjkim * should *always* copy because the old style d2i might modify the 281280304Sjkim * buffer. 282280304Sjkim */ 283109998Smarkm 284280304Sjkim if (tag != -1) { 285280304Sjkim wp = *(unsigned char **)in; 286280304Sjkim imphack = *wp; 287280304Sjkim if (p == NULL) { 288280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 289280304Sjkim goto err; 290280304Sjkim } 291280304Sjkim *wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED) 292280304Sjkim | it->utype); 293280304Sjkim } 294109998Smarkm 295280304Sjkim ptmpval = cf->asn1_d2i(pval, in, len); 296109998Smarkm 297280304Sjkim if (tag != -1) 298280304Sjkim *wp = imphack; 299109998Smarkm 300280304Sjkim if (ptmpval) 301280304Sjkim return 1; 302160814Ssimon 303280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 304280304Sjkim goto err; 305109998Smarkm 306280304Sjkim case ASN1_ITYPE_CHOICE: 307280304Sjkim if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) 308280304Sjkim goto auxerr; 309280304Sjkim if (*pval) { 310280304Sjkim /* Free up and zero CHOICE value if initialised */ 311280304Sjkim i = asn1_get_choice_selector(pval, it); 312280304Sjkim if ((i >= 0) && (i < it->tcount)) { 313280304Sjkim tt = it->templates + i; 314280304Sjkim pchptr = asn1_get_field_ptr(pval, tt); 315280304Sjkim ASN1_template_free(pchptr, tt); 316280304Sjkim asn1_set_choice_selector(pval, -1, it); 317280304Sjkim } 318280304Sjkim } else if (!ASN1_item_ex_new(pval, it)) { 319280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 320280304Sjkim goto err; 321280304Sjkim } 322280304Sjkim /* CHOICE type, try each possibility in turn */ 323280304Sjkim p = *in; 324280304Sjkim for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { 325280304Sjkim pchptr = asn1_get_field_ptr(pval, tt); 326280304Sjkim /* 327280304Sjkim * We mark field as OPTIONAL so its absence can be recognised. 328280304Sjkim */ 329280304Sjkim ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx); 330280304Sjkim /* If field not present, try the next one */ 331280304Sjkim if (ret == -1) 332280304Sjkim continue; 333280304Sjkim /* If positive return, read OK, break loop */ 334280304Sjkim if (ret > 0) 335280304Sjkim break; 336280304Sjkim /* Otherwise must be an ASN1 parsing error */ 337280304Sjkim errtt = tt; 338280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 339280304Sjkim goto err; 340280304Sjkim } 341109998Smarkm 342280304Sjkim /* Did we fall off the end without reading anything? */ 343280304Sjkim if (i == it->tcount) { 344280304Sjkim /* If OPTIONAL, this is OK */ 345280304Sjkim if (opt) { 346280304Sjkim /* Free and zero it */ 347280304Sjkim ASN1_item_ex_free(pval, it); 348280304Sjkim return -1; 349280304Sjkim } 350280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE); 351280304Sjkim goto err; 352280304Sjkim } 353109998Smarkm 354280304Sjkim asn1_set_choice_selector(pval, i, it); 355280304Sjkim if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) 356280304Sjkim goto auxerr; 357291721Sjkim *in = p; 358280304Sjkim return 1; 359160814Ssimon 360280304Sjkim case ASN1_ITYPE_NDEF_SEQUENCE: 361280304Sjkim case ASN1_ITYPE_SEQUENCE: 362280304Sjkim p = *in; 363280304Sjkim tmplen = len; 364160814Ssimon 365280304Sjkim /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ 366280304Sjkim if (tag == -1) { 367280304Sjkim tag = V_ASN1_SEQUENCE; 368280304Sjkim aclass = V_ASN1_UNIVERSAL; 369280304Sjkim } 370280304Sjkim /* Get SEQUENCE length and update len, p */ 371280304Sjkim ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, 372280304Sjkim &p, len, tag, aclass, opt, ctx); 373280304Sjkim if (!ret) { 374280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 375280304Sjkim goto err; 376280304Sjkim } else if (ret == -1) 377280304Sjkim return -1; 378280304Sjkim if (aux && (aux->flags & ASN1_AFLG_BROKEN)) { 379280304Sjkim len = tmplen - (p - *in); 380280304Sjkim seq_nolen = 1; 381280304Sjkim } 382280304Sjkim /* If indefinite we don't do a length check */ 383280304Sjkim else 384280304Sjkim seq_nolen = seq_eoc; 385280304Sjkim if (!cst) { 386280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); 387280304Sjkim goto err; 388280304Sjkim } 389109998Smarkm 390280304Sjkim if (!*pval && !ASN1_item_ex_new(pval, it)) { 391280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 392280304Sjkim goto err; 393280304Sjkim } 394109998Smarkm 395280304Sjkim if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) 396280304Sjkim goto auxerr; 397109998Smarkm 398280304Sjkim /* Free up and zero any ADB found */ 399280304Sjkim for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { 400280304Sjkim if (tt->flags & ASN1_TFLG_ADB_MASK) { 401280304Sjkim const ASN1_TEMPLATE *seqtt; 402280304Sjkim ASN1_VALUE **pseqval; 403280304Sjkim seqtt = asn1_do_adb(pval, tt, 1); 404280304Sjkim pseqval = asn1_get_field_ptr(pval, seqtt); 405280304Sjkim ASN1_template_free(pseqval, seqtt); 406280304Sjkim } 407280304Sjkim } 408160814Ssimon 409280304Sjkim /* Get each field entry */ 410280304Sjkim for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { 411280304Sjkim const ASN1_TEMPLATE *seqtt; 412280304Sjkim ASN1_VALUE **pseqval; 413280304Sjkim seqtt = asn1_do_adb(pval, tt, 1); 414280304Sjkim if (!seqtt) 415280304Sjkim goto err; 416280304Sjkim pseqval = asn1_get_field_ptr(pval, seqtt); 417280304Sjkim /* Have we ran out of data? */ 418280304Sjkim if (!len) 419280304Sjkim break; 420280304Sjkim q = p; 421280304Sjkim if (asn1_check_eoc(&p, len)) { 422280304Sjkim if (!seq_eoc) { 423280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_UNEXPECTED_EOC); 424280304Sjkim goto err; 425280304Sjkim } 426280304Sjkim len -= p - q; 427280304Sjkim seq_eoc = 0; 428280304Sjkim q = p; 429280304Sjkim break; 430280304Sjkim } 431280304Sjkim /* 432280304Sjkim * This determines the OPTIONAL flag value. The field cannot be 433280304Sjkim * omitted if it is the last of a SEQUENCE and there is still 434280304Sjkim * data to be read. This isn't strictly necessary but it 435280304Sjkim * increases efficiency in some cases. 436280304Sjkim */ 437280304Sjkim if (i == (it->tcount - 1)) 438280304Sjkim isopt = 0; 439280304Sjkim else 440280304Sjkim isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); 441280304Sjkim /* 442280304Sjkim * attempt to read in field, allowing each to be OPTIONAL 443280304Sjkim */ 444109998Smarkm 445280304Sjkim ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx); 446280304Sjkim if (!ret) { 447280304Sjkim errtt = seqtt; 448280304Sjkim goto err; 449280304Sjkim } else if (ret == -1) { 450280304Sjkim /* 451280304Sjkim * OPTIONAL component absent. Free and zero the field. 452280304Sjkim */ 453280304Sjkim ASN1_template_free(pseqval, seqtt); 454280304Sjkim continue; 455280304Sjkim } 456280304Sjkim /* Update length */ 457280304Sjkim len -= p - q; 458280304Sjkim } 459280266Sdelphij 460280304Sjkim /* Check for EOC if expecting one */ 461280304Sjkim if (seq_eoc && !asn1_check_eoc(&p, len)) { 462280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MISSING_EOC); 463280304Sjkim goto err; 464280304Sjkim } 465280304Sjkim /* Check all data read */ 466280304Sjkim if (!seq_nolen && len) { 467280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH); 468280304Sjkim goto err; 469280304Sjkim } 470160814Ssimon 471280304Sjkim /* 472280304Sjkim * If we get here we've got no more data in the SEQUENCE, however we 473280304Sjkim * may not have read all fields so check all remaining are OPTIONAL 474280304Sjkim * and clear any that are. 475280304Sjkim */ 476280304Sjkim for (; i < it->tcount; tt++, i++) { 477280304Sjkim const ASN1_TEMPLATE *seqtt; 478280304Sjkim seqtt = asn1_do_adb(pval, tt, 1); 479280304Sjkim if (!seqtt) 480280304Sjkim goto err; 481280304Sjkim if (seqtt->flags & ASN1_TFLG_OPTIONAL) { 482280304Sjkim ASN1_VALUE **pseqval; 483280304Sjkim pseqval = asn1_get_field_ptr(pval, seqtt); 484280304Sjkim ASN1_template_free(pseqval, seqtt); 485280304Sjkim } else { 486280304Sjkim errtt = seqtt; 487280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_FIELD_MISSING); 488280304Sjkim goto err; 489280304Sjkim } 490280304Sjkim } 491280304Sjkim /* Save encoding */ 492280304Sjkim if (!asn1_enc_save(pval, *in, p - *in, it)) 493280304Sjkim goto auxerr; 494280304Sjkim if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) 495280304Sjkim goto auxerr; 496291721Sjkim *in = p; 497280304Sjkim return 1; 498160814Ssimon 499280304Sjkim default: 500280304Sjkim return 0; 501280304Sjkim } 502280304Sjkim auxerr: 503280304Sjkim ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_AUX_ERROR); 504280304Sjkim err: 505291721Sjkim if (combine == 0) 506291721Sjkim ASN1_item_ex_free(pval, it); 507280304Sjkim if (errtt) 508280304Sjkim ERR_add_error_data(4, "Field=", errtt->field_name, 509280304Sjkim ", Type=", it->sname); 510280304Sjkim else 511280304Sjkim ERR_add_error_data(2, "Type=", it->sname); 512280304Sjkim return 0; 513280304Sjkim} 514109998Smarkm 515280304Sjkim/* 516280304Sjkim * Templates are handled with two separate functions. One handles any 517280304Sjkim * EXPLICIT tag and the other handles the rest. 518109998Smarkm */ 519109998Smarkm 520160814Ssimonstatic int asn1_template_ex_d2i(ASN1_VALUE **val, 521280304Sjkim const unsigned char **in, long inlen, 522280304Sjkim const ASN1_TEMPLATE *tt, char opt, 523280304Sjkim ASN1_TLC *ctx) 524280304Sjkim{ 525280304Sjkim int flags, aclass; 526280304Sjkim int ret; 527280304Sjkim long len; 528280304Sjkim const unsigned char *p, *q; 529280304Sjkim char exp_eoc; 530280304Sjkim if (!val) 531280304Sjkim return 0; 532280304Sjkim flags = tt->flags; 533280304Sjkim aclass = flags & ASN1_TFLG_TAG_CLASS; 534109998Smarkm 535280304Sjkim p = *in; 536109998Smarkm 537280304Sjkim /* Check if EXPLICIT tag expected */ 538280304Sjkim if (flags & ASN1_TFLG_EXPTAG) { 539280304Sjkim char cst; 540280304Sjkim /* 541280304Sjkim * Need to work out amount of data available to the inner content and 542280304Sjkim * where it starts: so read in EXPLICIT header to get the info. 543280304Sjkim */ 544280304Sjkim ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, 545280304Sjkim &p, inlen, tt->tag, aclass, opt, ctx); 546280304Sjkim q = p; 547280304Sjkim if (!ret) { 548280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 549280304Sjkim return 0; 550280304Sjkim } else if (ret == -1) 551280304Sjkim return -1; 552280304Sjkim if (!cst) { 553280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, 554280304Sjkim ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); 555280304Sjkim return 0; 556280304Sjkim } 557280304Sjkim /* We've found the field so it can't be OPTIONAL now */ 558280304Sjkim ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx); 559280304Sjkim if (!ret) { 560280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); 561280304Sjkim return 0; 562280304Sjkim } 563280304Sjkim /* We read the field in OK so update length */ 564280304Sjkim len -= p - q; 565280304Sjkim if (exp_eoc) { 566280304Sjkim /* If NDEF we must have an EOC here */ 567280304Sjkim if (!asn1_check_eoc(&p, len)) { 568280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ASN1_R_MISSING_EOC); 569280304Sjkim goto err; 570280304Sjkim } 571280304Sjkim } else { 572280304Sjkim /* 573280304Sjkim * Otherwise we must hit the EXPLICIT tag end or its an error 574280304Sjkim */ 575280304Sjkim if (len) { 576280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, 577280304Sjkim ASN1_R_EXPLICIT_LENGTH_MISMATCH); 578280304Sjkim goto err; 579280304Sjkim } 580280304Sjkim } 581280304Sjkim } else 582280304Sjkim return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx); 583109998Smarkm 584280304Sjkim *in = p; 585280304Sjkim return 1; 586109998Smarkm 587280304Sjkim err: 588280304Sjkim ASN1_template_free(val, tt); 589280304Sjkim return 0; 590280304Sjkim} 591109998Smarkm 592160814Ssimonstatic int asn1_template_noexp_d2i(ASN1_VALUE **val, 593280304Sjkim const unsigned char **in, long len, 594280304Sjkim const ASN1_TEMPLATE *tt, char opt, 595280304Sjkim ASN1_TLC *ctx) 596280304Sjkim{ 597280304Sjkim int flags, aclass; 598280304Sjkim int ret; 599280304Sjkim const unsigned char *p, *q; 600280304Sjkim if (!val) 601280304Sjkim return 0; 602280304Sjkim flags = tt->flags; 603280304Sjkim aclass = flags & ASN1_TFLG_TAG_CLASS; 604109998Smarkm 605280304Sjkim p = *in; 606280304Sjkim q = p; 607109998Smarkm 608280304Sjkim if (flags & ASN1_TFLG_SK_MASK) { 609280304Sjkim /* SET OF, SEQUENCE OF */ 610280304Sjkim int sktag, skaclass; 611280304Sjkim char sk_eoc; 612280304Sjkim /* First work out expected inner tag value */ 613280304Sjkim if (flags & ASN1_TFLG_IMPTAG) { 614280304Sjkim sktag = tt->tag; 615280304Sjkim skaclass = aclass; 616280304Sjkim } else { 617280304Sjkim skaclass = V_ASN1_UNIVERSAL; 618280304Sjkim if (flags & ASN1_TFLG_SET_OF) 619280304Sjkim sktag = V_ASN1_SET; 620280304Sjkim else 621280304Sjkim sktag = V_ASN1_SEQUENCE; 622280304Sjkim } 623280304Sjkim /* Get the tag */ 624280304Sjkim ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, 625280304Sjkim &p, len, sktag, skaclass, opt, ctx); 626280304Sjkim if (!ret) { 627280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); 628280304Sjkim return 0; 629280304Sjkim } else if (ret == -1) 630280304Sjkim return -1; 631280304Sjkim if (!*val) 632280304Sjkim *val = (ASN1_VALUE *)sk_new_null(); 633280304Sjkim else { 634280304Sjkim /* 635280304Sjkim * We've got a valid STACK: free up any items present 636280304Sjkim */ 637280304Sjkim STACK_OF(ASN1_VALUE) *sktmp = (STACK_OF(ASN1_VALUE) *)*val; 638280304Sjkim ASN1_VALUE *vtmp; 639280304Sjkim while (sk_ASN1_VALUE_num(sktmp) > 0) { 640280304Sjkim vtmp = sk_ASN1_VALUE_pop(sktmp); 641280304Sjkim ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); 642280304Sjkim } 643280304Sjkim } 644160814Ssimon 645280304Sjkim if (!*val) { 646280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE); 647280304Sjkim goto err; 648280304Sjkim } 649109998Smarkm 650280304Sjkim /* Read as many items as we can */ 651280304Sjkim while (len > 0) { 652280304Sjkim ASN1_VALUE *skfield; 653280304Sjkim q = p; 654280304Sjkim /* See if EOC found */ 655280304Sjkim if (asn1_check_eoc(&p, len)) { 656280304Sjkim if (!sk_eoc) { 657280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 658280304Sjkim ASN1_R_UNEXPECTED_EOC); 659280304Sjkim goto err; 660280304Sjkim } 661280304Sjkim len -= p - q; 662280304Sjkim sk_eoc = 0; 663280304Sjkim break; 664280304Sjkim } 665280304Sjkim skfield = NULL; 666280304Sjkim if (!ASN1_item_ex_d2i(&skfield, &p, len, 667280304Sjkim ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx)) { 668280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 669280304Sjkim ERR_R_NESTED_ASN1_ERROR); 670280304Sjkim goto err; 671280304Sjkim } 672280304Sjkim len -= p - q; 673280304Sjkim if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) { 674280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE); 675280304Sjkim goto err; 676280304Sjkim } 677280304Sjkim } 678280304Sjkim if (sk_eoc) { 679280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ASN1_R_MISSING_EOC); 680280304Sjkim goto err; 681280304Sjkim } 682280304Sjkim } else if (flags & ASN1_TFLG_IMPTAG) { 683280304Sjkim /* IMPLICIT tagging */ 684280304Sjkim ret = ASN1_item_ex_d2i(val, &p, len, 685280304Sjkim ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, 686280304Sjkim ctx); 687280304Sjkim if (!ret) { 688280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); 689280304Sjkim goto err; 690280304Sjkim } else if (ret == -1) 691280304Sjkim return -1; 692280304Sjkim } else { 693280304Sjkim /* Nothing special */ 694280304Sjkim ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), 695291721Sjkim -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx); 696280304Sjkim if (!ret) { 697280304Sjkim ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); 698280304Sjkim goto err; 699280304Sjkim } else if (ret == -1) 700280304Sjkim return -1; 701280304Sjkim } 702109998Smarkm 703280304Sjkim *in = p; 704280304Sjkim return 1; 705109998Smarkm 706280304Sjkim err: 707280304Sjkim ASN1_template_free(val, tt); 708280304Sjkim return 0; 709280304Sjkim} 710280304Sjkim 711160814Ssimonstatic int asn1_d2i_ex_primitive(ASN1_VALUE **pval, 712280304Sjkim const unsigned char **in, long inlen, 713280304Sjkim const ASN1_ITEM *it, 714280304Sjkim int tag, int aclass, char opt, ASN1_TLC *ctx) 715280304Sjkim{ 716280304Sjkim int ret = 0, utype; 717280304Sjkim long plen; 718280304Sjkim char cst, inf, free_cont = 0; 719280304Sjkim const unsigned char *p; 720280304Sjkim BUF_MEM buf; 721280304Sjkim const unsigned char *cont = NULL; 722280304Sjkim long len; 723280304Sjkim if (!pval) { 724280304Sjkim ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL); 725280304Sjkim return 0; /* Should never happen */ 726280304Sjkim } 727109998Smarkm 728280304Sjkim if (it->itype == ASN1_ITYPE_MSTRING) { 729280304Sjkim utype = tag; 730280304Sjkim tag = -1; 731280304Sjkim } else 732280304Sjkim utype = it->utype; 733109998Smarkm 734280304Sjkim if (utype == V_ASN1_ANY) { 735280304Sjkim /* If type is ANY need to figure out type from tag */ 736280304Sjkim unsigned char oclass; 737280304Sjkim if (tag >= 0) { 738280304Sjkim ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_TAGGED_ANY); 739280304Sjkim return 0; 740280304Sjkim } 741280304Sjkim if (opt) { 742280304Sjkim ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, 743280304Sjkim ASN1_R_ILLEGAL_OPTIONAL_ANY); 744280304Sjkim return 0; 745280304Sjkim } 746280304Sjkim p = *in; 747280304Sjkim ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, 748280304Sjkim &p, inlen, -1, 0, 0, ctx); 749280304Sjkim if (!ret) { 750280304Sjkim ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); 751280304Sjkim return 0; 752280304Sjkim } 753280304Sjkim if (oclass != V_ASN1_UNIVERSAL) 754280304Sjkim utype = V_ASN1_OTHER; 755280304Sjkim } 756280304Sjkim if (tag == -1) { 757280304Sjkim tag = utype; 758280304Sjkim aclass = V_ASN1_UNIVERSAL; 759280304Sjkim } 760280304Sjkim p = *in; 761280304Sjkim /* Check header */ 762280304Sjkim ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, 763280304Sjkim &p, inlen, tag, aclass, opt, ctx); 764280304Sjkim if (!ret) { 765280304Sjkim ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); 766280304Sjkim return 0; 767280304Sjkim } else if (ret == -1) 768280304Sjkim return -1; 769280304Sjkim ret = 0; 770280304Sjkim /* SEQUENCE, SET and "OTHER" are left in encoded form */ 771280304Sjkim if ((utype == V_ASN1_SEQUENCE) 772280304Sjkim || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) { 773280304Sjkim /* 774280304Sjkim * Clear context cache for type OTHER because the auto clear when we 775280304Sjkim * have a exact match wont work 776280304Sjkim */ 777280304Sjkim if (utype == V_ASN1_OTHER) { 778280304Sjkim asn1_tlc_clear(ctx); 779280304Sjkim } 780280304Sjkim /* SEQUENCE and SET must be constructed */ 781280304Sjkim else if (!cst) { 782280304Sjkim ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, 783280304Sjkim ASN1_R_TYPE_NOT_CONSTRUCTED); 784280304Sjkim return 0; 785280304Sjkim } 786109998Smarkm 787280304Sjkim cont = *in; 788280304Sjkim /* If indefinite length constructed find the real end */ 789280304Sjkim if (inf) { 790280304Sjkim if (!asn1_find_end(&p, plen, inf)) 791280304Sjkim goto err; 792280304Sjkim len = p - cont; 793280304Sjkim } else { 794280304Sjkim len = p - cont + plen; 795280304Sjkim p += plen; 796280304Sjkim buf.data = NULL; 797280304Sjkim } 798280304Sjkim } else if (cst) { 799280304Sjkim if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN 800280304Sjkim || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER 801280304Sjkim || utype == V_ASN1_ENUMERATED) { 802280304Sjkim ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_TYPE_NOT_PRIMITIVE); 803280304Sjkim return 0; 804280304Sjkim } 805280304Sjkim buf.length = 0; 806280304Sjkim buf.max = 0; 807280304Sjkim buf.data = NULL; 808280304Sjkim /* 809280304Sjkim * Should really check the internal tags are correct but some things 810280304Sjkim * may get this wrong. The relevant specs say that constructed string 811280304Sjkim * types should be OCTET STRINGs internally irrespective of the type. 812280304Sjkim * So instead just check for UNIVERSAL class and ignore the tag. 813280304Sjkim */ 814280304Sjkim if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) { 815280304Sjkim free_cont = 1; 816280304Sjkim goto err; 817280304Sjkim } 818280304Sjkim len = buf.length; 819280304Sjkim /* Append a final null to string */ 820280304Sjkim if (!BUF_MEM_grow_clean(&buf, len + 1)) { 821280304Sjkim ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); 822280304Sjkim return 0; 823280304Sjkim } 824280304Sjkim buf.data[len] = 0; 825280304Sjkim cont = (const unsigned char *)buf.data; 826280304Sjkim free_cont = 1; 827280304Sjkim } else { 828280304Sjkim cont = p; 829280304Sjkim len = plen; 830280304Sjkim p += plen; 831280304Sjkim } 832109998Smarkm 833280304Sjkim /* We now have content length and type: translate into a structure */ 834280304Sjkim if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it)) 835280304Sjkim goto err; 836109998Smarkm 837280304Sjkim *in = p; 838280304Sjkim ret = 1; 839280304Sjkim err: 840280304Sjkim if (free_cont && buf.data) 841280304Sjkim OPENSSL_free(buf.data); 842280304Sjkim return ret; 843280304Sjkim} 844109998Smarkm 845109998Smarkm/* Translate ASN1 content octets into a structure */ 846109998Smarkm 847160814Ssimonint asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, 848280304Sjkim int utype, char *free_cont, const ASN1_ITEM *it) 849280304Sjkim{ 850280304Sjkim ASN1_VALUE **opval = NULL; 851280304Sjkim ASN1_STRING *stmp; 852280304Sjkim ASN1_TYPE *typ = NULL; 853280304Sjkim int ret = 0; 854280304Sjkim const ASN1_PRIMITIVE_FUNCS *pf; 855280304Sjkim ASN1_INTEGER **tint; 856280304Sjkim pf = it->funcs; 857160814Ssimon 858280304Sjkim if (pf && pf->prim_c2i) 859280304Sjkim return pf->prim_c2i(pval, cont, len, utype, free_cont, it); 860280304Sjkim /* If ANY type clear type and set pointer to internal value */ 861280304Sjkim if (it->utype == V_ASN1_ANY) { 862280304Sjkim if (!*pval) { 863280304Sjkim typ = ASN1_TYPE_new(); 864280304Sjkim if (typ == NULL) 865280304Sjkim goto err; 866280304Sjkim *pval = (ASN1_VALUE *)typ; 867280304Sjkim } else 868280304Sjkim typ = (ASN1_TYPE *)*pval; 869160814Ssimon 870280304Sjkim if (utype != typ->type) 871280304Sjkim ASN1_TYPE_set(typ, utype, NULL); 872280304Sjkim opval = pval; 873280304Sjkim pval = &typ->value.asn1_value; 874280304Sjkim } 875280304Sjkim switch (utype) { 876280304Sjkim case V_ASN1_OBJECT: 877280304Sjkim if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) 878280304Sjkim goto err; 879280304Sjkim break; 880109998Smarkm 881280304Sjkim case V_ASN1_NULL: 882280304Sjkim if (len) { 883280304Sjkim ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_NULL_IS_WRONG_LENGTH); 884280304Sjkim goto err; 885280304Sjkim } 886280304Sjkim *pval = (ASN1_VALUE *)1; 887280304Sjkim break; 888109998Smarkm 889280304Sjkim case V_ASN1_BOOLEAN: 890280304Sjkim if (len != 1) { 891280304Sjkim ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); 892280304Sjkim goto err; 893280304Sjkim } else { 894280304Sjkim ASN1_BOOLEAN *tbool; 895280304Sjkim tbool = (ASN1_BOOLEAN *)pval; 896280304Sjkim *tbool = *cont; 897280304Sjkim } 898280304Sjkim break; 899109998Smarkm 900280304Sjkim case V_ASN1_BIT_STRING: 901280304Sjkim if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) 902280304Sjkim goto err; 903280304Sjkim break; 904109998Smarkm 905280304Sjkim case V_ASN1_INTEGER: 906280304Sjkim case V_ASN1_ENUMERATED: 907280304Sjkim tint = (ASN1_INTEGER **)pval; 908280304Sjkim if (!c2i_ASN1_INTEGER(tint, &cont, len)) 909280304Sjkim goto err; 910280304Sjkim /* Fixup type to match the expected form */ 911280304Sjkim (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); 912280304Sjkim break; 913109998Smarkm 914280304Sjkim case V_ASN1_OCTET_STRING: 915280304Sjkim case V_ASN1_NUMERICSTRING: 916280304Sjkim case V_ASN1_PRINTABLESTRING: 917280304Sjkim case V_ASN1_T61STRING: 918280304Sjkim case V_ASN1_VIDEOTEXSTRING: 919280304Sjkim case V_ASN1_IA5STRING: 920280304Sjkim case V_ASN1_UTCTIME: 921280304Sjkim case V_ASN1_GENERALIZEDTIME: 922280304Sjkim case V_ASN1_GRAPHICSTRING: 923280304Sjkim case V_ASN1_VISIBLESTRING: 924280304Sjkim case V_ASN1_GENERALSTRING: 925280304Sjkim case V_ASN1_UNIVERSALSTRING: 926280304Sjkim case V_ASN1_BMPSTRING: 927280304Sjkim case V_ASN1_UTF8STRING: 928280304Sjkim case V_ASN1_OTHER: 929280304Sjkim case V_ASN1_SET: 930280304Sjkim case V_ASN1_SEQUENCE: 931280304Sjkim default: 932280304Sjkim if (utype == V_ASN1_BMPSTRING && (len & 1)) { 933280304Sjkim ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BMPSTRING_IS_WRONG_LENGTH); 934280304Sjkim goto err; 935280304Sjkim } 936280304Sjkim if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) { 937280304Sjkim ASN1err(ASN1_F_ASN1_EX_C2I, 938280304Sjkim ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); 939280304Sjkim goto err; 940280304Sjkim } 941280304Sjkim /* All based on ASN1_STRING and handled the same */ 942280304Sjkim if (!*pval) { 943280304Sjkim stmp = ASN1_STRING_type_new(utype); 944280304Sjkim if (!stmp) { 945280304Sjkim ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE); 946280304Sjkim goto err; 947280304Sjkim } 948280304Sjkim *pval = (ASN1_VALUE *)stmp; 949280304Sjkim } else { 950280304Sjkim stmp = (ASN1_STRING *)*pval; 951280304Sjkim stmp->type = utype; 952280304Sjkim } 953280304Sjkim /* If we've already allocated a buffer use it */ 954280304Sjkim if (*free_cont) { 955280304Sjkim if (stmp->data) 956280304Sjkim OPENSSL_free(stmp->data); 957280304Sjkim stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */ 958280304Sjkim stmp->length = len; 959280304Sjkim *free_cont = 0; 960280304Sjkim } else { 961280304Sjkim if (!ASN1_STRING_set(stmp, cont, len)) { 962280304Sjkim ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE); 963280304Sjkim ASN1_STRING_free(stmp); 964280304Sjkim *pval = NULL; 965280304Sjkim goto err; 966280304Sjkim } 967280304Sjkim } 968280304Sjkim break; 969280304Sjkim } 970280304Sjkim /* If ASN1_ANY and NULL type fix up value */ 971280304Sjkim if (typ && (utype == V_ASN1_NULL)) 972280304Sjkim typ->value.ptr = NULL; 973109998Smarkm 974280304Sjkim ret = 1; 975280304Sjkim err: 976280304Sjkim if (!ret) { 977280304Sjkim ASN1_TYPE_free(typ); 978280304Sjkim if (opval) 979280304Sjkim *opval = NULL; 980280304Sjkim } 981280304Sjkim return ret; 982280304Sjkim} 983109998Smarkm 984280304Sjkim/* 985280304Sjkim * This function finds the end of an ASN1 structure when passed its maximum 986280304Sjkim * length, whether it is indefinite length and a pointer to the content. This 987280304Sjkim * is more efficient than calling asn1_collect because it does not recurse on 988280304Sjkim * each indefinite length header. 989160814Ssimon */ 990160814Ssimon 991160814Ssimonstatic int asn1_find_end(const unsigned char **in, long len, char inf) 992280304Sjkim{ 993280304Sjkim int expected_eoc; 994280304Sjkim long plen; 995280304Sjkim const unsigned char *p = *in, *q; 996280304Sjkim /* If not indefinite length constructed just add length */ 997280304Sjkim if (inf == 0) { 998280304Sjkim *in += len; 999280304Sjkim return 1; 1000280304Sjkim } 1001280304Sjkim expected_eoc = 1; 1002280304Sjkim /* 1003280304Sjkim * Indefinite length constructed form. Find the end when enough EOCs are 1004280304Sjkim * found. If more indefinite length constructed headers are encountered 1005280304Sjkim * increment the expected eoc count otherwise just skip to the end of the 1006280304Sjkim * data. 1007280304Sjkim */ 1008280304Sjkim while (len > 0) { 1009280304Sjkim if (asn1_check_eoc(&p, len)) { 1010280304Sjkim expected_eoc--; 1011280304Sjkim if (expected_eoc == 0) 1012280304Sjkim break; 1013280304Sjkim len -= 2; 1014280304Sjkim continue; 1015280304Sjkim } 1016280304Sjkim q = p; 1017280304Sjkim /* Just read in a header: only care about the length */ 1018280304Sjkim if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len, 1019280304Sjkim -1, 0, 0, NULL)) { 1020280304Sjkim ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR); 1021280304Sjkim return 0; 1022280304Sjkim } 1023280304Sjkim if (inf) 1024280304Sjkim expected_eoc++; 1025280304Sjkim else 1026280304Sjkim p += plen; 1027280304Sjkim len -= p - q; 1028280304Sjkim } 1029280304Sjkim if (expected_eoc) { 1030280304Sjkim ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC); 1031280304Sjkim return 0; 1032280304Sjkim } 1033280304Sjkim *in = p; 1034280304Sjkim return 1; 1035280304Sjkim} 1036280304Sjkim 1037280304Sjkim/* 1038280304Sjkim * This function collects the asn1 data from a constructred string type into 1039280304Sjkim * a buffer. The values of 'in' and 'len' should refer to the contents of the 1040280304Sjkim * constructed type and 'inf' should be set if it is indefinite length. 1041109998Smarkm */ 1042109998Smarkm 1043194206Ssimon#ifndef ASN1_MAX_STRING_NEST 1044280304Sjkim/* 1045280304Sjkim * This determines how many levels of recursion are permitted in ASN1 string 1046280304Sjkim * types. If it is not limited stack overflows can occur. If set to zero no 1047280304Sjkim * recursion is allowed at all. Although zero should be adequate examples 1048280304Sjkim * exist that require a value of 1. So 5 should be more than enough. 1049194206Ssimon */ 1050280304Sjkim# define ASN1_MAX_STRING_NEST 5 1051194206Ssimon#endif 1052194206Ssimon 1053160814Ssimonstatic int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, 1054280304Sjkim char inf, int tag, int aclass, int depth) 1055280304Sjkim{ 1056280304Sjkim const unsigned char *p, *q; 1057280304Sjkim long plen; 1058280304Sjkim char cst, ininf; 1059280304Sjkim p = *in; 1060280304Sjkim inf &= 1; 1061280304Sjkim /* 1062280304Sjkim * If no buffer and not indefinite length constructed just pass over the 1063280304Sjkim * encoded data 1064280304Sjkim */ 1065280304Sjkim if (!buf && !inf) { 1066280304Sjkim *in += len; 1067280304Sjkim return 1; 1068280304Sjkim } 1069280304Sjkim while (len > 0) { 1070280304Sjkim q = p; 1071280304Sjkim /* Check for EOC */ 1072280304Sjkim if (asn1_check_eoc(&p, len)) { 1073280304Sjkim /* 1074280304Sjkim * EOC is illegal outside indefinite length constructed form 1075280304Sjkim */ 1076280304Sjkim if (!inf) { 1077280304Sjkim ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_UNEXPECTED_EOC); 1078280304Sjkim return 0; 1079280304Sjkim } 1080280304Sjkim inf = 0; 1081280304Sjkim break; 1082280304Sjkim } 1083160814Ssimon 1084280304Sjkim if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p, 1085280304Sjkim len, tag, aclass, 0, NULL)) { 1086280304Sjkim ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR); 1087280304Sjkim return 0; 1088280304Sjkim } 1089160814Ssimon 1090280304Sjkim /* If indefinite length constructed update max length */ 1091280304Sjkim if (cst) { 1092280304Sjkim if (depth >= ASN1_MAX_STRING_NEST) { 1093280304Sjkim ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_NESTED_ASN1_STRING); 1094280304Sjkim return 0; 1095280304Sjkim } 1096280304Sjkim if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, depth + 1)) 1097280304Sjkim return 0; 1098280304Sjkim } else if (plen && !collect_data(buf, &p, plen)) 1099280304Sjkim return 0; 1100280304Sjkim len -= p - q; 1101280304Sjkim } 1102280304Sjkim if (inf) { 1103280304Sjkim ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC); 1104280304Sjkim return 0; 1105280304Sjkim } 1106280304Sjkim *in = p; 1107280304Sjkim return 1; 1108280304Sjkim} 1109109998Smarkm 1110160814Ssimonstatic int collect_data(BUF_MEM *buf, const unsigned char **p, long plen) 1111280304Sjkim{ 1112280304Sjkim int len; 1113280304Sjkim if (buf) { 1114280304Sjkim len = buf->length; 1115280304Sjkim if (!BUF_MEM_grow_clean(buf, len + plen)) { 1116280304Sjkim ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE); 1117280304Sjkim return 0; 1118280304Sjkim } 1119280304Sjkim memcpy(buf->data + len, *p, plen); 1120280304Sjkim } 1121280304Sjkim *p += plen; 1122280304Sjkim return 1; 1123280304Sjkim} 1124109998Smarkm 1125109998Smarkm/* Check for ASN1 EOC and swallow it if found */ 1126109998Smarkm 1127160814Ssimonstatic int asn1_check_eoc(const unsigned char **in, long len) 1128280304Sjkim{ 1129280304Sjkim const unsigned char *p; 1130280304Sjkim if (len < 2) 1131280304Sjkim return 0; 1132280304Sjkim p = *in; 1133280304Sjkim if (!p[0] && !p[1]) { 1134280304Sjkim *in += 2; 1135280304Sjkim return 1; 1136280304Sjkim } 1137280304Sjkim return 0; 1138280304Sjkim} 1139109998Smarkm 1140280304Sjkim/* 1141280304Sjkim * Check an ASN1 tag and length: a bit like ASN1_get_object but it sets the 1142280304Sjkim * length for indefinite length constructed form, we don't know the exact 1143280304Sjkim * length but we can set an upper bound to the amount of data available minus 1144280304Sjkim * the header length just read. 1145109998Smarkm */ 1146109998Smarkm 1147160814Ssimonstatic int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, 1148280304Sjkim char *inf, char *cst, 1149280304Sjkim const unsigned char **in, long len, 1150280304Sjkim int exptag, int expclass, char opt, ASN1_TLC *ctx) 1151280304Sjkim{ 1152280304Sjkim int i; 1153280304Sjkim int ptag, pclass; 1154280304Sjkim long plen; 1155280304Sjkim const unsigned char *p, *q; 1156280304Sjkim p = *in; 1157280304Sjkim q = p; 1158109998Smarkm 1159280304Sjkim if (ctx && ctx->valid) { 1160280304Sjkim i = ctx->ret; 1161280304Sjkim plen = ctx->plen; 1162280304Sjkim pclass = ctx->pclass; 1163280304Sjkim ptag = ctx->ptag; 1164280304Sjkim p += ctx->hdrlen; 1165280304Sjkim } else { 1166280304Sjkim i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); 1167280304Sjkim if (ctx) { 1168280304Sjkim ctx->ret = i; 1169280304Sjkim ctx->plen = plen; 1170280304Sjkim ctx->pclass = pclass; 1171280304Sjkim ctx->ptag = ptag; 1172280304Sjkim ctx->hdrlen = p - q; 1173280304Sjkim ctx->valid = 1; 1174280304Sjkim /* 1175280304Sjkim * If definite length, and no error, length + header can't exceed 1176280304Sjkim * total amount of data available. 1177280304Sjkim */ 1178280304Sjkim if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { 1179280304Sjkim ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_TOO_LONG); 1180280304Sjkim asn1_tlc_clear(ctx); 1181280304Sjkim return 0; 1182280304Sjkim } 1183280304Sjkim } 1184280304Sjkim } 1185109998Smarkm 1186280304Sjkim if (i & 0x80) { 1187280304Sjkim ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER); 1188280304Sjkim asn1_tlc_clear(ctx); 1189280304Sjkim return 0; 1190280304Sjkim } 1191280304Sjkim if (exptag >= 0) { 1192280304Sjkim if ((exptag != ptag) || (expclass != pclass)) { 1193280304Sjkim /* 1194280304Sjkim * If type is OPTIONAL, not an error: indicate missing type. 1195280304Sjkim */ 1196280304Sjkim if (opt) 1197280304Sjkim return -1; 1198280304Sjkim asn1_tlc_clear(ctx); 1199280304Sjkim ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG); 1200280304Sjkim return 0; 1201280304Sjkim } 1202280304Sjkim /* 1203280304Sjkim * We have a tag and class match: assume we are going to do something 1204280304Sjkim * with it 1205280304Sjkim */ 1206280304Sjkim asn1_tlc_clear(ctx); 1207280304Sjkim } 1208109998Smarkm 1209280304Sjkim if (i & 1) 1210280304Sjkim plen = len - (p - q); 1211109998Smarkm 1212280304Sjkim if (inf) 1213280304Sjkim *inf = i & 1; 1214109998Smarkm 1215280304Sjkim if (cst) 1216280304Sjkim *cst = i & V_ASN1_CONSTRUCTED; 1217109998Smarkm 1218280304Sjkim if (olen) 1219280304Sjkim *olen = plen; 1220109998Smarkm 1221280304Sjkim if (oclass) 1222280304Sjkim *oclass = pclass; 1223160814Ssimon 1224280304Sjkim if (otag) 1225280304Sjkim *otag = ptag; 1226160814Ssimon 1227280304Sjkim *in = p; 1228280304Sjkim return 1; 1229280304Sjkim} 1230