155682Smarkm/* 2178825Sdfr * Copyright (c) 1997 - 2006 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "gen_locl.h" 35178825Sdfr#include "lex.h" 3655682Smarkm 37178825SdfrRCSID("$Id: gen_decode.c 21503 2007-07-12 11:57:19Z lha $"); 3855682Smarkm 3955682Smarkmstatic void 40178825Sdfrdecode_primitive (const char *typename, const char *name, const char *forwstr) 4155682Smarkm{ 42178825Sdfr#if 0 4355682Smarkm fprintf (codefile, 4455682Smarkm "e = decode_%s(p, len, %s, &l);\n" 45178825Sdfr "%s;\n", 4655682Smarkm typename, 47178825Sdfr name, 48178825Sdfr forwstr); 49178825Sdfr#else 50178825Sdfr fprintf (codefile, 51178825Sdfr "e = der_get_%s(p, len, %s, &l);\n" 52178825Sdfr "if(e) %s;\np += l; len -= l; ret += l;\n", 53178825Sdfr typename, 54178825Sdfr name, 55178825Sdfr forwstr); 56178825Sdfr#endif 5755682Smarkm} 5855682Smarkm 59178825Sdfrstatic int 60178825Sdfris_primitive_type(int type) 61178825Sdfr{ 62178825Sdfr switch(type) { 63178825Sdfr case TInteger: 64178825Sdfr case TBoolean: 65178825Sdfr case TOctetString: 66178825Sdfr case TBitString: 67178825Sdfr case TEnumerated: 68178825Sdfr case TGeneralizedTime: 69178825Sdfr case TGeneralString: 70178825Sdfr case TOID: 71178825Sdfr case TUTCTime: 72178825Sdfr case TUTF8String: 73178825Sdfr case TPrintableString: 74178825Sdfr case TIA5String: 75178825Sdfr case TBMPString: 76178825Sdfr case TUniversalString: 77178825Sdfr case TVisibleString: 78178825Sdfr case TNull: 79178825Sdfr return 1; 80178825Sdfr default: 81178825Sdfr return 0; 82178825Sdfr } 83178825Sdfr} 84178825Sdfr 8555682Smarkmstatic void 86178825Sdfrfind_tag (const Type *t, 87178825Sdfr Der_class *cl, Der_type *ty, unsigned *tag) 8855682Smarkm{ 8972445Sassar switch (t->type) { 90178825Sdfr case TBitString: 91178825Sdfr *cl = ASN1_C_UNIV; 92178825Sdfr *ty = PRIM; 93178825Sdfr *tag = UT_BitString; 94178825Sdfr break; 95178825Sdfr case TBoolean: 96178825Sdfr *cl = ASN1_C_UNIV; 97178825Sdfr *ty = PRIM; 98178825Sdfr *tag = UT_Boolean; 99178825Sdfr break; 100178825Sdfr case TChoice: 101178825Sdfr errx(1, "Cannot have recursive CHOICE"); 102178825Sdfr case TEnumerated: 103178825Sdfr *cl = ASN1_C_UNIV; 104178825Sdfr *ty = PRIM; 105178825Sdfr *tag = UT_Enumerated; 106178825Sdfr break; 107178825Sdfr case TGeneralString: 108178825Sdfr *cl = ASN1_C_UNIV; 109178825Sdfr *ty = PRIM; 110178825Sdfr *tag = UT_GeneralString; 111178825Sdfr break; 112178825Sdfr case TGeneralizedTime: 113178825Sdfr *cl = ASN1_C_UNIV; 114178825Sdfr *ty = PRIM; 115178825Sdfr *tag = UT_GeneralizedTime; 116178825Sdfr break; 117178825Sdfr case TIA5String: 118178825Sdfr *cl = ASN1_C_UNIV; 119178825Sdfr *ty = PRIM; 120178825Sdfr *tag = UT_IA5String; 121178825Sdfr break; 122178825Sdfr case TInteger: 123178825Sdfr *cl = ASN1_C_UNIV; 124178825Sdfr *ty = PRIM; 125178825Sdfr *tag = UT_Integer; 126178825Sdfr break; 127178825Sdfr case TNull: 128178825Sdfr *cl = ASN1_C_UNIV; 129178825Sdfr *ty = PRIM; 130178825Sdfr *tag = UT_Null; 131178825Sdfr break; 132178825Sdfr case TOID: 133178825Sdfr *cl = ASN1_C_UNIV; 134178825Sdfr *ty = PRIM; 135178825Sdfr *tag = UT_OID; 136178825Sdfr break; 137178825Sdfr case TOctetString: 138178825Sdfr *cl = ASN1_C_UNIV; 139178825Sdfr *ty = PRIM; 140178825Sdfr *tag = UT_OctetString; 141178825Sdfr break; 142178825Sdfr case TPrintableString: 143178825Sdfr *cl = ASN1_C_UNIV; 144178825Sdfr *ty = PRIM; 145178825Sdfr *tag = UT_PrintableString; 146178825Sdfr break; 147178825Sdfr case TSequence: 148178825Sdfr case TSequenceOf: 149178825Sdfr *cl = ASN1_C_UNIV; 150178825Sdfr *ty = CONS; 151178825Sdfr *tag = UT_Sequence; 152178825Sdfr break; 153178825Sdfr case TSet: 154178825Sdfr case TSetOf: 155178825Sdfr *cl = ASN1_C_UNIV; 156178825Sdfr *ty = CONS; 157178825Sdfr *tag = UT_Set; 158178825Sdfr break; 159178825Sdfr case TTag: 160178825Sdfr *cl = t->tag.tagclass; 161178825Sdfr *ty = is_primitive_type(t->subtype->type) ? PRIM : CONS; 162178825Sdfr *tag = t->tag.tagvalue; 163178825Sdfr break; 164178825Sdfr case TType: 165178825Sdfr if ((t->symbol->stype == Stype && t->symbol->type == NULL) 166178825Sdfr || t->symbol->stype == SUndefined) { 167178825Sdfr error_message("%s is imported or still undefined, " 168178825Sdfr " can't generate tag checking data in CHOICE " 169178825Sdfr "without this information", 170178825Sdfr t->symbol->name); 171178825Sdfr exit(1); 172178825Sdfr } 173178825Sdfr find_tag(t->symbol->type, cl, ty, tag); 174178825Sdfr return; 175178825Sdfr case TUTCTime: 176178825Sdfr *cl = ASN1_C_UNIV; 177178825Sdfr *ty = PRIM; 178178825Sdfr *tag = UT_UTCTime; 179178825Sdfr break; 180178825Sdfr case TUTF8String: 181178825Sdfr *cl = ASN1_C_UNIV; 182178825Sdfr *ty = PRIM; 183178825Sdfr *tag = UT_UTF8String; 184178825Sdfr break; 185178825Sdfr case TBMPString: 186178825Sdfr *cl = ASN1_C_UNIV; 187178825Sdfr *ty = PRIM; 188178825Sdfr *tag = UT_BMPString; 189178825Sdfr break; 190178825Sdfr case TUniversalString: 191178825Sdfr *cl = ASN1_C_UNIV; 192178825Sdfr *ty = PRIM; 193178825Sdfr *tag = UT_UniversalString; 194178825Sdfr break; 195178825Sdfr case TVisibleString: 196178825Sdfr *cl = ASN1_C_UNIV; 197178825Sdfr *ty = PRIM; 198178825Sdfr *tag = UT_VisibleString; 199178825Sdfr break; 200178825Sdfr default: 201178825Sdfr abort(); 202178825Sdfr } 203178825Sdfr} 204178825Sdfr 205178825Sdfrstatic void 206178825Sdfrrange_check(const char *name, 207178825Sdfr const char *length, 208178825Sdfr const char *forwstr, 209178825Sdfr struct range *r) 210178825Sdfr{ 211178825Sdfr if (r->min == r->max + 2 || r->min < r->max) 21272445Sassar fprintf (codefile, 213178825Sdfr "if ((%s)->%s > %d) {\n" 214178825Sdfr "e = ASN1_MAX_CONSTRAINT; %s;\n" 215178825Sdfr "}\n", 216178825Sdfr name, length, r->max, forwstr); 217178825Sdfr if (r->min - 1 == r->max || r->min < r->max) 218178825Sdfr fprintf (codefile, 219178825Sdfr "if ((%s)->%s < %d) {\n" 220178825Sdfr "e = ASN1_MIN_CONSTRAINT; %s;\n" 221178825Sdfr "}\n", 222178825Sdfr name, length, r->min, forwstr); 223178825Sdfr if (r->max == r->min) 224178825Sdfr fprintf (codefile, 225178825Sdfr "if ((%s)->%s != %d) {\n" 226178825Sdfr "e = ASN1_EXACT_CONSTRAINT; %s;\n" 227178825Sdfr "}\n", 228178825Sdfr name, length, r->min, forwstr); 229178825Sdfr} 230178825Sdfr 231178825Sdfrstatic int 232178825Sdfrdecode_type (const char *name, const Type *t, int optional, 233178825Sdfr const char *forwstr, const char *tmpstr) 234178825Sdfr{ 235178825Sdfr switch (t->type) { 236178825Sdfr case TType: { 237178825Sdfr if (optional) 238178825Sdfr fprintf(codefile, 239178825Sdfr "%s = calloc(1, sizeof(*%s));\n" 240178825Sdfr "if (%s == NULL) %s;\n", 241178825Sdfr name, name, name, forwstr); 242178825Sdfr fprintf (codefile, 243178825Sdfr "e = decode_%s(p, len, %s, &l);\n", 24472445Sassar t->symbol->gen_name, name); 245178825Sdfr if (optional) { 246178825Sdfr fprintf (codefile, 247178825Sdfr "if(e) {\n" 248178825Sdfr "free(%s);\n" 249178825Sdfr "%s = NULL;\n" 250178825Sdfr "} else {\n" 251178825Sdfr "p += l; len -= l; ret += l;\n" 252178825Sdfr "}\n", 253178825Sdfr name, name); 254178825Sdfr } else { 255178825Sdfr fprintf (codefile, 256178825Sdfr "if(e) %s;\n", 257178825Sdfr forwstr); 258178825Sdfr fprintf (codefile, 259178825Sdfr "p += l; len -= l; ret += l;\n"); 260178825Sdfr } 26172445Sassar break; 262178825Sdfr } 26372445Sassar case TInteger: 264178825Sdfr if(t->members) { 265178825Sdfr fprintf(codefile, 266178825Sdfr "{\n" 267178825Sdfr "int enumint;\n"); 268178825Sdfr decode_primitive ("integer", "&enumint", forwstr); 269178825Sdfr fprintf(codefile, 270178825Sdfr "*%s = enumint;\n" 271178825Sdfr "}\n", 272178825Sdfr name); 273178825Sdfr } else if (t->range == NULL) { 274178825Sdfr decode_primitive ("heim_integer", name, forwstr); 275178825Sdfr } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { 276178825Sdfr decode_primitive ("integer", name, forwstr); 277178825Sdfr } else if (t->range->min == 0 && t->range->max == UINT_MAX) { 278178825Sdfr decode_primitive ("unsigned", name, forwstr); 279178825Sdfr } else if (t->range->min == 0 && t->range->max == INT_MAX) { 280178825Sdfr decode_primitive ("unsigned", name, forwstr); 281178825Sdfr } else 282178825Sdfr errx(1, "%s: unsupported range %d -> %d", 283178825Sdfr name, t->range->min, t->range->max); 28472445Sassar break; 285178825Sdfr case TBoolean: 286178825Sdfr decode_primitive ("boolean", name, forwstr); 287178825Sdfr break; 28890926Snectar case TEnumerated: 289178825Sdfr decode_primitive ("enumerated", name, forwstr); 29090926Snectar break; 29172445Sassar case TOctetString: 292178825Sdfr decode_primitive ("octet_string", name, forwstr); 293178825Sdfr if (t->range) 294178825Sdfr range_check(name, "length", forwstr, t->range); 29572445Sassar break; 29672445Sassar case TBitString: { 29772445Sassar Member *m; 298178825Sdfr int pos = 0; 29955682Smarkm 300178825Sdfr if (ASN1_TAILQ_EMPTY(t->members)) { 301178825Sdfr decode_primitive ("bit_string", name, forwstr); 302178825Sdfr break; 303178825Sdfr } 304178825Sdfr fprintf(codefile, 305178825Sdfr "if (len < 1) return ASN1_OVERRUN;\n" 306178825Sdfr "p++; len--; ret++;\n"); 307178825Sdfr fprintf(codefile, 308178825Sdfr "do {\n" 309178825Sdfr "if (len < 1) break;\n"); 310178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 31172445Sassar while (m->val / 8 > pos / 8) { 31272445Sassar fprintf (codefile, 313178825Sdfr "p++; len--; ret++;\n" 314178825Sdfr "if (len < 1) break;\n"); 31572445Sassar pos += 8; 31672445Sassar } 31772445Sassar fprintf (codefile, 318178825Sdfr "(%s)->%s = (*p >> %d) & 1;\n", 31972445Sassar name, m->gen_name, 7 - m->val % 8); 32072445Sassar } 321178825Sdfr fprintf(codefile, 322178825Sdfr "} while(0);\n"); 32372445Sassar fprintf (codefile, 324178825Sdfr "p += len; ret += len;\n"); 32572445Sassar break; 32655682Smarkm } 32772445Sassar case TSequence: { 32872445Sassar Member *m; 32955682Smarkm 33072445Sassar if (t->members == NULL) 33172445Sassar break; 33255682Smarkm 333178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 334178825Sdfr char *s; 33555682Smarkm 336178825Sdfr if (m->ellipsis) 337178825Sdfr continue; 338178825Sdfr 339178825Sdfr asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", 340178825Sdfr name, m->gen_name); 341178825Sdfr if (s == NULL) 342178825Sdfr errx(1, "malloc"); 343178825Sdfr decode_type (s, m->type, m->optional, forwstr, m->gen_name); 344178825Sdfr free (s); 345178825Sdfr } 346178825Sdfr 347178825Sdfr break; 348178825Sdfr } 349178825Sdfr case TSet: { 350178825Sdfr Member *m; 351178825Sdfr unsigned int memno; 352178825Sdfr 353178825Sdfr if(t->members == NULL) 354178825Sdfr break; 355178825Sdfr 356178825Sdfr fprintf(codefile, "{\n"); 357178825Sdfr fprintf(codefile, "unsigned int members = 0;\n"); 358178825Sdfr fprintf(codefile, "while(len > 0) {\n"); 359178825Sdfr fprintf(codefile, 360178825Sdfr "Der_class class;\n" 361178825Sdfr "Der_type type;\n" 362178825Sdfr "int tag;\n" 363178825Sdfr "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n" 364178825Sdfr "if(e) %s;\n", forwstr); 365178825Sdfr fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n"); 366178825Sdfr memno = 0; 367178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 36872445Sassar char *s; 36955682Smarkm 370178825Sdfr assert(m->type->type == TTag); 371178825Sdfr 372178825Sdfr fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n", 373178825Sdfr classname(m->type->tag.tagclass), 374178825Sdfr is_primitive_type(m->type->subtype->type) ? "PRIM" : "CONS", 375178825Sdfr valuename(m->type->tag.tagclass, m->type->tag.tagvalue)); 376178825Sdfr 37772445Sassar asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name); 378178825Sdfr if (s == NULL) 379178825Sdfr errx(1, "malloc"); 380178825Sdfr if(m->optional) 381178825Sdfr fprintf(codefile, 382178825Sdfr "%s = calloc(1, sizeof(*%s));\n" 383178825Sdfr "if (%s == NULL) { e = ENOMEM; %s; }\n", 384178825Sdfr s, s, s, forwstr); 385178825Sdfr decode_type (s, m->type, 0, forwstr, m->gen_name); 38672445Sassar free (s); 387178825Sdfr 388178825Sdfr fprintf(codefile, "members |= (1 << %d);\n", memno); 389178825Sdfr memno++; 390178825Sdfr fprintf(codefile, "break;\n"); 39172445Sassar } 392178825Sdfr fprintf(codefile, 393178825Sdfr "default:\n" 394178825Sdfr "return ASN1_MISPLACED_FIELD;\n" 395178825Sdfr "break;\n"); 396178825Sdfr fprintf(codefile, "}\n"); 397178825Sdfr fprintf(codefile, "}\n"); 398178825Sdfr memno = 0; 399178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 400178825Sdfr char *s; 40172445Sassar 402178825Sdfr asprintf (&s, "%s->%s", name, m->gen_name); 403178825Sdfr if (s == NULL) 404178825Sdfr errx(1, "malloc"); 405178825Sdfr fprintf(codefile, "if((members & (1 << %d)) == 0)\n", memno); 406178825Sdfr if(m->optional) 407178825Sdfr fprintf(codefile, "%s = NULL;\n", s); 408178825Sdfr else if(m->defval) 409178825Sdfr gen_assign_defval(s, m->defval); 410178825Sdfr else 411178825Sdfr fprintf(codefile, "return ASN1_MISSING_FIELD;\n"); 412178825Sdfr free(s); 413178825Sdfr memno++; 414178825Sdfr } 415178825Sdfr fprintf(codefile, "}\n"); 41672445Sassar break; 41755682Smarkm } 418178825Sdfr case TSetOf: 41972445Sassar case TSequenceOf: { 42072445Sassar char *n; 421178825Sdfr char *sname; 42255682Smarkm 42372445Sassar fprintf (codefile, 42472445Sassar "{\n" 425178825Sdfr "size_t %s_origlen = len;\n" 426178825Sdfr "size_t %s_oldret = ret;\n" 427178825Sdfr "size_t %s_olen = 0;\n" 428178825Sdfr "void *%s_tmp;\n" 42972445Sassar "ret = 0;\n" 43072445Sassar "(%s)->len = 0;\n" 431178825Sdfr "(%s)->val = NULL;\n", 432178825Sdfr tmpstr, 433178825Sdfr tmpstr, 434178825Sdfr tmpstr, 435178825Sdfr tmpstr, 436178825Sdfr name, 437178825Sdfr name); 438178825Sdfr 439178825Sdfr fprintf (codefile, 440178825Sdfr "while(ret < %s_origlen) {\n" 441178825Sdfr "size_t %s_nlen = %s_olen + sizeof(*((%s)->val));\n" 442178825Sdfr "if (%s_olen > %s_nlen) { e = ASN1_OVERFLOW; %s; }\n" 443178825Sdfr "%s_olen = %s_nlen;\n" 444178825Sdfr "%s_tmp = realloc((%s)->val, %s_olen);\n" 445178825Sdfr "if (%s_tmp == NULL) { e = ENOMEM; %s; }\n" 446178825Sdfr "(%s)->val = %s_tmp;\n", 447178825Sdfr tmpstr, 448178825Sdfr tmpstr, tmpstr, name, 449178825Sdfr tmpstr, tmpstr, forwstr, 450178825Sdfr tmpstr, tmpstr, 451178825Sdfr tmpstr, name, tmpstr, 452178825Sdfr tmpstr, forwstr, 453178825Sdfr name, tmpstr); 454178825Sdfr 455178825Sdfr asprintf (&n, "&(%s)->val[(%s)->len]", name, name); 456178825Sdfr if (n == NULL) 457178825Sdfr errx(1, "malloc"); 458178825Sdfr asprintf (&sname, "%s_s_of", tmpstr); 459178825Sdfr if (sname == NULL) 460178825Sdfr errx(1, "malloc"); 461178825Sdfr decode_type (n, t->subtype, 0, forwstr, sname); 462178825Sdfr fprintf (codefile, 46372445Sassar "(%s)->len++;\n" 464178825Sdfr "len = %s_origlen - ret;\n" 46572445Sassar "}\n" 466178825Sdfr "ret += %s_oldret;\n" 467178825Sdfr "}\n", 468178825Sdfr name, 469178825Sdfr tmpstr, tmpstr); 470178825Sdfr if (t->range) 471178825Sdfr range_check(name, "len", forwstr, t->range); 47272445Sassar free (n); 473178825Sdfr free (sname); 47472445Sassar break; 47572445Sassar } 47672445Sassar case TGeneralizedTime: 477178825Sdfr decode_primitive ("generalized_time", name, forwstr); 47872445Sassar break; 47972445Sassar case TGeneralString: 480178825Sdfr decode_primitive ("general_string", name, forwstr); 48172445Sassar break; 482178825Sdfr case TTag:{ 483178825Sdfr char *tname; 484178825Sdfr 485178825Sdfr fprintf(codefile, 486178825Sdfr "{\n" 487178825Sdfr "size_t %s_datalen, %s_oldlen;\n", 488178825Sdfr tmpstr, tmpstr); 489178825Sdfr if(dce_fix) 490178825Sdfr fprintf(codefile, 491178825Sdfr "int dce_fix;\n"); 492178825Sdfr fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, %s, %s, " 493178825Sdfr "&%s_datalen, &l);\n", 494178825Sdfr classname(t->tag.tagclass), 495178825Sdfr is_primitive_type(t->subtype->type) ? "PRIM" : "CONS", 496178825Sdfr valuename(t->tag.tagclass, t->tag.tagvalue), 497178825Sdfr tmpstr); 498178825Sdfr if(optional) { 499178825Sdfr fprintf(codefile, 500178825Sdfr "if(e) {\n" 501178825Sdfr "%s = NULL;\n" 502178825Sdfr "} else {\n" 503178825Sdfr "%s = calloc(1, sizeof(*%s));\n" 504178825Sdfr "if (%s == NULL) { e = ENOMEM; %s; }\n", 505178825Sdfr name, name, name, name, forwstr); 506178825Sdfr } else { 507178825Sdfr fprintf(codefile, "if(e) %s;\n", forwstr); 508178825Sdfr } 50972445Sassar fprintf (codefile, 510178825Sdfr "p += l; len -= l; ret += l;\n" 511178825Sdfr "%s_oldlen = len;\n", 512178825Sdfr tmpstr); 513178825Sdfr if(dce_fix) 514178825Sdfr fprintf (codefile, 515178825Sdfr "if((dce_fix = _heim_fix_dce(%s_datalen, &len)) < 0)\n" 516178825Sdfr "{ e = ASN1_BAD_FORMAT; %s; }\n", 517178825Sdfr tmpstr, forwstr); 518178825Sdfr else 519178825Sdfr fprintf(codefile, 520178825Sdfr "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n" 521178825Sdfr "len = %s_datalen;\n", tmpstr, forwstr, tmpstr); 522178825Sdfr asprintf (&tname, "%s_Tag", tmpstr); 523178825Sdfr if (tname == NULL) 524178825Sdfr errx(1, "malloc"); 525178825Sdfr decode_type (name, t->subtype, 0, forwstr, tname); 526178825Sdfr if(dce_fix) 527178825Sdfr fprintf(codefile, 528178825Sdfr "if(dce_fix){\n" 529178825Sdfr "e = der_match_tag_and_length (p, len, " 530178825Sdfr "(Der_class)0,(Der_type)0, UT_EndOfContent, " 531178825Sdfr "&%s_datalen, &l);\n" 532178825Sdfr "if(e) %s;\np += l; len -= l; ret += l;\n" 533178825Sdfr "} else \n", tmpstr, forwstr); 534178825Sdfr fprintf(codefile, 535178825Sdfr "len = %s_oldlen - %s_datalen;\n", 536178825Sdfr tmpstr, tmpstr); 537178825Sdfr if(optional) 538178825Sdfr fprintf(codefile, 539178825Sdfr "}\n"); 540178825Sdfr fprintf(codefile, 54172445Sassar "}\n"); 542178825Sdfr free(tname); 543178825Sdfr break; 544178825Sdfr } 545178825Sdfr case TChoice: { 546178825Sdfr Member *m, *have_ellipsis = NULL; 547178825Sdfr const char *els = ""; 54855682Smarkm 549178825Sdfr if (t->members == NULL) 550178825Sdfr break; 551178825Sdfr 552178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 553178825Sdfr const Type *tt = m->type; 554178825Sdfr char *s; 555178825Sdfr Der_class cl; 556178825Sdfr Der_type ty; 557178825Sdfr unsigned tag; 558178825Sdfr 559178825Sdfr if (m->ellipsis) { 560178825Sdfr have_ellipsis = m; 561178825Sdfr continue; 562178825Sdfr } 563178825Sdfr 564178825Sdfr find_tag(tt, &cl, &ty, &tag); 565178825Sdfr 566178825Sdfr fprintf(codefile, 567178825Sdfr "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n", 568178825Sdfr els, 569178825Sdfr classname(cl), 570178825Sdfr ty ? "CONS" : "PRIM", 571178825Sdfr valuename(cl, tag)); 572178825Sdfr asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&", 573178825Sdfr name, m->gen_name); 574178825Sdfr if (s == NULL) 575178825Sdfr errx(1, "malloc"); 576178825Sdfr decode_type (s, m->type, m->optional, forwstr, m->gen_name); 577178825Sdfr fprintf(codefile, 578178825Sdfr "(%s)->element = %s;\n", 579178825Sdfr name, m->label); 580178825Sdfr free(s); 581178825Sdfr fprintf(codefile, 582178825Sdfr "}\n"); 583178825Sdfr els = "else "; 584178825Sdfr } 585178825Sdfr if (have_ellipsis) { 586178825Sdfr fprintf(codefile, 587178825Sdfr "else {\n" 588178825Sdfr "(%s)->u.%s.data = calloc(1, len);\n" 589178825Sdfr "if ((%s)->u.%s.data == NULL) {\n" 590178825Sdfr "e = ENOMEM; %s;\n" 591178825Sdfr "}\n" 592178825Sdfr "(%s)->u.%s.length = len;\n" 593178825Sdfr "memcpy((%s)->u.%s.data, p, len);\n" 594178825Sdfr "(%s)->element = %s;\n" 595178825Sdfr "p += len;\n" 596178825Sdfr "ret += len;\n" 597178825Sdfr "len -= len;\n" 598178825Sdfr "}\n", 599178825Sdfr name, have_ellipsis->gen_name, 600178825Sdfr name, have_ellipsis->gen_name, 601178825Sdfr forwstr, 602178825Sdfr name, have_ellipsis->gen_name, 603178825Sdfr name, have_ellipsis->gen_name, 604178825Sdfr name, have_ellipsis->label); 605178825Sdfr } else { 606178825Sdfr fprintf(codefile, 607178825Sdfr "else {\n" 608178825Sdfr "e = ASN1_PARSE_ERROR;\n" 609178825Sdfr "%s;\n" 610178825Sdfr "}\n", 611178825Sdfr forwstr); 612178825Sdfr } 61372445Sassar break; 614178825Sdfr } 615178825Sdfr case TUTCTime: 616178825Sdfr decode_primitive ("utctime", name, forwstr); 617178825Sdfr break; 618178825Sdfr case TUTF8String: 619178825Sdfr decode_primitive ("utf8string", name, forwstr); 620178825Sdfr break; 621178825Sdfr case TPrintableString: 622178825Sdfr decode_primitive ("printable_string", name, forwstr); 623178825Sdfr break; 624178825Sdfr case TIA5String: 625178825Sdfr decode_primitive ("ia5_string", name, forwstr); 626178825Sdfr break; 627178825Sdfr case TBMPString: 628178825Sdfr decode_primitive ("bmp_string", name, forwstr); 629178825Sdfr break; 630178825Sdfr case TUniversalString: 631178825Sdfr decode_primitive ("universal_string", name, forwstr); 632178825Sdfr break; 633178825Sdfr case TVisibleString: 634178825Sdfr decode_primitive ("visible_string", name, forwstr); 635178825Sdfr break; 636178825Sdfr case TNull: 637178825Sdfr fprintf (codefile, "/* NULL */\n"); 638178825Sdfr break; 639178825Sdfr case TOID: 640178825Sdfr decode_primitive ("oid", name, forwstr); 641178825Sdfr break; 64272445Sassar default : 64372445Sassar abort (); 64472445Sassar } 645178825Sdfr return 0; 64655682Smarkm} 64755682Smarkm 64855682Smarkmvoid 64955682Smarkmgenerate_type_decode (const Symbol *s) 65055682Smarkm{ 651178825Sdfr int preserve = preserve_type(s->name) ? TRUE : FALSE; 65255682Smarkm 65355682Smarkm fprintf (headerfile, 654178825Sdfr "int " 655178825Sdfr "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n", 65655682Smarkm s->gen_name, s->gen_name); 65755682Smarkm 65855682Smarkm fprintf (codefile, "int\n" 659178825Sdfr "decode_%s(const unsigned char *p," 660178825Sdfr " size_t len, %s *data, size_t *size)\n" 66155682Smarkm "{\n", 66255682Smarkm s->gen_name, s->gen_name); 66355682Smarkm 664178825Sdfr switch (s->type->type) { 665178825Sdfr case TInteger: 666178825Sdfr case TBoolean: 667178825Sdfr case TOctetString: 668178825Sdfr case TOID: 669178825Sdfr case TGeneralizedTime: 670178825Sdfr case TGeneralString: 671178825Sdfr case TUTF8String: 672178825Sdfr case TPrintableString: 673178825Sdfr case TIA5String: 674178825Sdfr case TBMPString: 675178825Sdfr case TUniversalString: 676178825Sdfr case TVisibleString: 677178825Sdfr case TUTCTime: 678178825Sdfr case TNull: 679178825Sdfr case TEnumerated: 680178825Sdfr case TBitString: 681178825Sdfr case TSequence: 682178825Sdfr case TSequenceOf: 683178825Sdfr case TSet: 684178825Sdfr case TSetOf: 685178825Sdfr case TTag: 686178825Sdfr case TType: 687178825Sdfr case TChoice: 688178825Sdfr fprintf (codefile, 689178825Sdfr "size_t ret = 0;\n" 690178825Sdfr "size_t l;\n" 691178825Sdfr "int e;\n"); 692178825Sdfr if (preserve) 693178825Sdfr fprintf (codefile, "const unsigned char *begin = p;\n"); 69455682Smarkm 695178825Sdfr fprintf (codefile, "\n"); 696178825Sdfr fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */ 697178825Sdfr 698178825Sdfr decode_type ("data", s->type, 0, "goto fail", "Top"); 699178825Sdfr if (preserve) 700178825Sdfr fprintf (codefile, 701178825Sdfr "data->_save.data = calloc(1, ret);\n" 702178825Sdfr "if (data->_save.data == NULL) { \n" 703178825Sdfr "e = ENOMEM; goto fail; \n" 704178825Sdfr "}\n" 705178825Sdfr "data->_save.length = ret;\n" 706178825Sdfr "memcpy(data->_save.data, begin, ret);\n"); 707178825Sdfr fprintf (codefile, 708178825Sdfr "if(size) *size = ret;\n" 709178825Sdfr "return 0;\n"); 710178825Sdfr fprintf (codefile, 711178825Sdfr "fail:\n" 712178825Sdfr "free_%s(data);\n" 713178825Sdfr "return e;\n", 714178825Sdfr s->gen_name); 715178825Sdfr break; 716178825Sdfr default: 717178825Sdfr abort (); 718178825Sdfr } 71955682Smarkm fprintf (codefile, "}\n\n"); 72055682Smarkm} 721