155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2006 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "gen_locl.h" 35178825Sdfr#include "lex.h" 3655682Smarkm 37233294SstasRCSID("$Id$"); 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 5955682Smarkmstatic void 60178825Sdfrfind_tag (const Type *t, 61178825Sdfr Der_class *cl, Der_type *ty, unsigned *tag) 6255682Smarkm{ 6372445Sassar switch (t->type) { 64178825Sdfr case TBitString: 65178825Sdfr *cl = ASN1_C_UNIV; 66178825Sdfr *ty = PRIM; 67178825Sdfr *tag = UT_BitString; 68178825Sdfr break; 69178825Sdfr case TBoolean: 70178825Sdfr *cl = ASN1_C_UNIV; 71178825Sdfr *ty = PRIM; 72178825Sdfr *tag = UT_Boolean; 73178825Sdfr break; 74233294Sstas case TChoice: 75178825Sdfr errx(1, "Cannot have recursive CHOICE"); 76178825Sdfr case TEnumerated: 77178825Sdfr *cl = ASN1_C_UNIV; 78178825Sdfr *ty = PRIM; 79178825Sdfr *tag = UT_Enumerated; 80178825Sdfr break; 81233294Sstas case TGeneralString: 82178825Sdfr *cl = ASN1_C_UNIV; 83178825Sdfr *ty = PRIM; 84178825Sdfr *tag = UT_GeneralString; 85178825Sdfr break; 86233294Sstas case TTeletexString: 87178825Sdfr *cl = ASN1_C_UNIV; 88178825Sdfr *ty = PRIM; 89233294Sstas *tag = UT_TeletexString; 90233294Sstas break; 91233294Sstas case TGeneralizedTime: 92233294Sstas *cl = ASN1_C_UNIV; 93233294Sstas *ty = PRIM; 94178825Sdfr *tag = UT_GeneralizedTime; 95178825Sdfr break; 96178825Sdfr case TIA5String: 97178825Sdfr *cl = ASN1_C_UNIV; 98178825Sdfr *ty = PRIM; 99178825Sdfr *tag = UT_IA5String; 100178825Sdfr break; 101233294Sstas case TInteger: 102178825Sdfr *cl = ASN1_C_UNIV; 103178825Sdfr *ty = PRIM; 104178825Sdfr *tag = UT_Integer; 105178825Sdfr break; 106178825Sdfr case TNull: 107178825Sdfr *cl = ASN1_C_UNIV; 108178825Sdfr *ty = PRIM; 109178825Sdfr *tag = UT_Null; 110178825Sdfr break; 111233294Sstas case TOID: 112178825Sdfr *cl = ASN1_C_UNIV; 113178825Sdfr *ty = PRIM; 114178825Sdfr *tag = UT_OID; 115178825Sdfr break; 116233294Sstas case TOctetString: 117178825Sdfr *cl = ASN1_C_UNIV; 118178825Sdfr *ty = PRIM; 119178825Sdfr *tag = UT_OctetString; 120178825Sdfr break; 121178825Sdfr case TPrintableString: 122178825Sdfr *cl = ASN1_C_UNIV; 123178825Sdfr *ty = PRIM; 124178825Sdfr *tag = UT_PrintableString; 125178825Sdfr break; 126233294Sstas case TSequence: 127178825Sdfr case TSequenceOf: 128178825Sdfr *cl = ASN1_C_UNIV; 129178825Sdfr *ty = CONS; 130178825Sdfr *tag = UT_Sequence; 131178825Sdfr break; 132233294Sstas case TSet: 133178825Sdfr case TSetOf: 134178825Sdfr *cl = ASN1_C_UNIV; 135178825Sdfr *ty = CONS; 136178825Sdfr *tag = UT_Set; 137178825Sdfr break; 138233294Sstas case TTag: 139178825Sdfr *cl = t->tag.tagclass; 140178825Sdfr *ty = is_primitive_type(t->subtype->type) ? PRIM : CONS; 141178825Sdfr *tag = t->tag.tagvalue; 142178825Sdfr break; 143233294Sstas case TType: 144178825Sdfr if ((t->symbol->stype == Stype && t->symbol->type == NULL) 145178825Sdfr || t->symbol->stype == SUndefined) { 146233294Sstas lex_error_message("%s is imported or still undefined, " 147233294Sstas " can't generate tag checking data in CHOICE " 148233294Sstas "without this information", 149233294Sstas t->symbol->name); 150178825Sdfr exit(1); 151178825Sdfr } 152178825Sdfr find_tag(t->symbol->type, cl, ty, tag); 153178825Sdfr return; 154233294Sstas case TUTCTime: 155178825Sdfr *cl = ASN1_C_UNIV; 156178825Sdfr *ty = PRIM; 157178825Sdfr *tag = UT_UTCTime; 158178825Sdfr break; 159178825Sdfr case TUTF8String: 160178825Sdfr *cl = ASN1_C_UNIV; 161178825Sdfr *ty = PRIM; 162178825Sdfr *tag = UT_UTF8String; 163178825Sdfr break; 164178825Sdfr case TBMPString: 165178825Sdfr *cl = ASN1_C_UNIV; 166178825Sdfr *ty = PRIM; 167178825Sdfr *tag = UT_BMPString; 168178825Sdfr break; 169178825Sdfr case TUniversalString: 170178825Sdfr *cl = ASN1_C_UNIV; 171178825Sdfr *ty = PRIM; 172178825Sdfr *tag = UT_UniversalString; 173178825Sdfr break; 174178825Sdfr case TVisibleString: 175178825Sdfr *cl = ASN1_C_UNIV; 176178825Sdfr *ty = PRIM; 177178825Sdfr *tag = UT_VisibleString; 178178825Sdfr break; 179178825Sdfr default: 180178825Sdfr abort(); 181178825Sdfr } 182178825Sdfr} 183178825Sdfr 184178825Sdfrstatic void 185178825Sdfrrange_check(const char *name, 186178825Sdfr const char *length, 187233294Sstas const char *forwstr, 188178825Sdfr struct range *r) 189178825Sdfr{ 190178825Sdfr if (r->min == r->max + 2 || r->min < r->max) 19172445Sassar fprintf (codefile, 192178825Sdfr "if ((%s)->%s > %d) {\n" 193178825Sdfr "e = ASN1_MAX_CONSTRAINT; %s;\n" 194178825Sdfr "}\n", 195178825Sdfr name, length, r->max, forwstr); 196178825Sdfr if (r->min - 1 == r->max || r->min < r->max) 197178825Sdfr fprintf (codefile, 198178825Sdfr "if ((%s)->%s < %d) {\n" 199178825Sdfr "e = ASN1_MIN_CONSTRAINT; %s;\n" 200178825Sdfr "}\n", 201178825Sdfr name, length, r->min, forwstr); 202178825Sdfr if (r->max == r->min) 203178825Sdfr fprintf (codefile, 204178825Sdfr "if ((%s)->%s != %d) {\n" 205178825Sdfr "e = ASN1_EXACT_CONSTRAINT; %s;\n" 206178825Sdfr "}\n", 207178825Sdfr name, length, r->min, forwstr); 208178825Sdfr} 209178825Sdfr 210178825Sdfrstatic int 211233294Sstasdecode_type (const char *name, const Type *t, int optional, 212233294Sstas const char *forwstr, const char *tmpstr, const char *dertype, 213233294Sstas unsigned int depth) 214178825Sdfr{ 215178825Sdfr switch (t->type) { 216178825Sdfr case TType: { 217178825Sdfr if (optional) 218233294Sstas fprintf(codefile, 219178825Sdfr "%s = calloc(1, sizeof(*%s));\n" 220178825Sdfr "if (%s == NULL) %s;\n", 221178825Sdfr name, name, name, forwstr); 222178825Sdfr fprintf (codefile, 223178825Sdfr "e = decode_%s(p, len, %s, &l);\n", 22472445Sassar t->symbol->gen_name, name); 225178825Sdfr if (optional) { 226178825Sdfr fprintf (codefile, 227178825Sdfr "if(e) {\n" 228178825Sdfr "free(%s);\n" 229178825Sdfr "%s = NULL;\n" 230178825Sdfr "} else {\n" 231178825Sdfr "p += l; len -= l; ret += l;\n" 232178825Sdfr "}\n", 233178825Sdfr name, name); 234178825Sdfr } else { 235178825Sdfr fprintf (codefile, 236178825Sdfr "if(e) %s;\n", 237178825Sdfr forwstr); 238178825Sdfr fprintf (codefile, 239178825Sdfr "p += l; len -= l; ret += l;\n"); 240178825Sdfr } 24172445Sassar break; 242178825Sdfr } 24372445Sassar case TInteger: 244178825Sdfr if(t->members) { 245178825Sdfr fprintf(codefile, 246178825Sdfr "{\n" 247178825Sdfr "int enumint;\n"); 248178825Sdfr decode_primitive ("integer", "&enumint", forwstr); 249178825Sdfr fprintf(codefile, 250178825Sdfr "*%s = enumint;\n" 251178825Sdfr "}\n", 252178825Sdfr name); 253178825Sdfr } else if (t->range == NULL) { 254178825Sdfr decode_primitive ("heim_integer", name, forwstr); 255178825Sdfr } else if (t->range->min == INT_MIN && t->range->max == INT_MAX) { 256178825Sdfr decode_primitive ("integer", name, forwstr); 257178825Sdfr } else if (t->range->min == 0 && t->range->max == UINT_MAX) { 258178825Sdfr decode_primitive ("unsigned", name, forwstr); 259178825Sdfr } else if (t->range->min == 0 && t->range->max == INT_MAX) { 260178825Sdfr decode_primitive ("unsigned", name, forwstr); 261178825Sdfr } else 262233294Sstas errx(1, "%s: unsupported range %d -> %d", 263178825Sdfr name, t->range->min, t->range->max); 26472445Sassar break; 265178825Sdfr case TBoolean: 266178825Sdfr decode_primitive ("boolean", name, forwstr); 267178825Sdfr break; 26890926Snectar case TEnumerated: 269178825Sdfr decode_primitive ("enumerated", name, forwstr); 27090926Snectar break; 27172445Sassar case TOctetString: 272233294Sstas if (dertype) { 273233294Sstas fprintf(codefile, 274233294Sstas "if (%s == CONS) {\n", 275233294Sstas dertype); 276233294Sstas decode_primitive("octet_string_ber", name, forwstr); 277233294Sstas fprintf(codefile, 278233294Sstas "} else {\n"); 279233294Sstas } 280178825Sdfr decode_primitive ("octet_string", name, forwstr); 281233294Sstas if (dertype) 282233294Sstas fprintf(codefile, "}\n"); 283178825Sdfr if (t->range) 284178825Sdfr range_check(name, "length", forwstr, t->range); 28572445Sassar break; 28672445Sassar case TBitString: { 28772445Sassar Member *m; 288178825Sdfr int pos = 0; 28955682Smarkm 290178825Sdfr if (ASN1_TAILQ_EMPTY(t->members)) { 291178825Sdfr decode_primitive ("bit_string", name, forwstr); 292178825Sdfr break; 293178825Sdfr } 294178825Sdfr fprintf(codefile, 295178825Sdfr "if (len < 1) return ASN1_OVERRUN;\n" 296178825Sdfr "p++; len--; ret++;\n"); 297178825Sdfr fprintf(codefile, 298178825Sdfr "do {\n" 299178825Sdfr "if (len < 1) break;\n"); 300178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 30172445Sassar while (m->val / 8 > pos / 8) { 30272445Sassar fprintf (codefile, 303178825Sdfr "p++; len--; ret++;\n" 304178825Sdfr "if (len < 1) break;\n"); 30572445Sassar pos += 8; 30672445Sassar } 30772445Sassar fprintf (codefile, 308178825Sdfr "(%s)->%s = (*p >> %d) & 1;\n", 30972445Sassar name, m->gen_name, 7 - m->val % 8); 31072445Sassar } 311178825Sdfr fprintf(codefile, 312178825Sdfr "} while(0);\n"); 31372445Sassar fprintf (codefile, 314178825Sdfr "p += len; ret += len;\n"); 31572445Sassar break; 31655682Smarkm } 31772445Sassar case TSequence: { 31872445Sassar Member *m; 31955682Smarkm 32072445Sassar if (t->members == NULL) 32172445Sassar break; 32255682Smarkm 323178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 324233294Sstas char *s = NULL; 32555682Smarkm 326178825Sdfr if (m->ellipsis) 327178825Sdfr continue; 328178825Sdfr 329233294Sstas if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", 330233294Sstas name, m->gen_name) < 0 || s == NULL) 331178825Sdfr errx(1, "malloc"); 332233294Sstas decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL, 333233294Sstas depth + 1); 334178825Sdfr free (s); 335178825Sdfr } 336233294Sstas 337178825Sdfr break; 338178825Sdfr } 339178825Sdfr case TSet: { 340178825Sdfr Member *m; 341178825Sdfr unsigned int memno; 342178825Sdfr 343178825Sdfr if(t->members == NULL) 344178825Sdfr break; 345178825Sdfr 346178825Sdfr fprintf(codefile, "{\n"); 347178825Sdfr fprintf(codefile, "unsigned int members = 0;\n"); 348178825Sdfr fprintf(codefile, "while(len > 0) {\n"); 349233294Sstas fprintf(codefile, 350178825Sdfr "Der_class class;\n" 351178825Sdfr "Der_type type;\n" 352178825Sdfr "int tag;\n" 353178825Sdfr "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n" 354178825Sdfr "if(e) %s;\n", forwstr); 355178825Sdfr fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n"); 356178825Sdfr memno = 0; 357178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 35872445Sassar char *s; 35955682Smarkm 360178825Sdfr assert(m->type->type == TTag); 361178825Sdfr 362178825Sdfr fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n", 363178825Sdfr classname(m->type->tag.tagclass), 364178825Sdfr is_primitive_type(m->type->subtype->type) ? "PRIM" : "CONS", 365178825Sdfr valuename(m->type->tag.tagclass, m->type->tag.tagvalue)); 366178825Sdfr 367233294Sstas if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL) 368178825Sdfr errx(1, "malloc"); 369178825Sdfr if(m->optional) 370233294Sstas fprintf(codefile, 371178825Sdfr "%s = calloc(1, sizeof(*%s));\n" 372178825Sdfr "if (%s == NULL) { e = ENOMEM; %s; }\n", 373178825Sdfr s, s, s, forwstr); 374233294Sstas decode_type (s, m->type, 0, forwstr, m->gen_name, NULL, depth + 1); 37572445Sassar free (s); 376178825Sdfr 377178825Sdfr fprintf(codefile, "members |= (1 << %d);\n", memno); 378178825Sdfr memno++; 379178825Sdfr fprintf(codefile, "break;\n"); 38072445Sassar } 381233294Sstas fprintf(codefile, 382178825Sdfr "default:\n" 383178825Sdfr "return ASN1_MISPLACED_FIELD;\n" 384178825Sdfr "break;\n"); 385178825Sdfr fprintf(codefile, "}\n"); 386178825Sdfr fprintf(codefile, "}\n"); 387178825Sdfr memno = 0; 388178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 389178825Sdfr char *s; 39072445Sassar 391233294Sstas if (asprintf (&s, "%s->%s", name, m->gen_name) < 0 || s == NULL) 392178825Sdfr errx(1, "malloc"); 393178825Sdfr fprintf(codefile, "if((members & (1 << %d)) == 0)\n", memno); 394178825Sdfr if(m->optional) 395178825Sdfr fprintf(codefile, "%s = NULL;\n", s); 396178825Sdfr else if(m->defval) 397178825Sdfr gen_assign_defval(s, m->defval); 398178825Sdfr else 399178825Sdfr fprintf(codefile, "return ASN1_MISSING_FIELD;\n"); 400178825Sdfr free(s); 401178825Sdfr memno++; 402178825Sdfr } 403178825Sdfr fprintf(codefile, "}\n"); 40472445Sassar break; 40555682Smarkm } 406178825Sdfr case TSetOf: 40772445Sassar case TSequenceOf: { 408233294Sstas char *n = NULL; 409233294Sstas char *sname = NULL; 41055682Smarkm 41172445Sassar fprintf (codefile, 41272445Sassar "{\n" 413178825Sdfr "size_t %s_origlen = len;\n" 414178825Sdfr "size_t %s_oldret = ret;\n" 415178825Sdfr "size_t %s_olen = 0;\n" 416178825Sdfr "void *%s_tmp;\n" 41772445Sassar "ret = 0;\n" 41872445Sassar "(%s)->len = 0;\n" 419178825Sdfr "(%s)->val = NULL;\n", 420178825Sdfr tmpstr, 421178825Sdfr tmpstr, 422178825Sdfr tmpstr, 423178825Sdfr tmpstr, 424178825Sdfr name, 425178825Sdfr name); 426178825Sdfr 427178825Sdfr fprintf (codefile, 428178825Sdfr "while(ret < %s_origlen) {\n" 429178825Sdfr "size_t %s_nlen = %s_olen + sizeof(*((%s)->val));\n" 430178825Sdfr "if (%s_olen > %s_nlen) { e = ASN1_OVERFLOW; %s; }\n" 431178825Sdfr "%s_olen = %s_nlen;\n" 432178825Sdfr "%s_tmp = realloc((%s)->val, %s_olen);\n" 433178825Sdfr "if (%s_tmp == NULL) { e = ENOMEM; %s; }\n" 434178825Sdfr "(%s)->val = %s_tmp;\n", 435178825Sdfr tmpstr, 436178825Sdfr tmpstr, tmpstr, name, 437178825Sdfr tmpstr, tmpstr, forwstr, 438178825Sdfr tmpstr, tmpstr, 439178825Sdfr tmpstr, name, tmpstr, 440233294Sstas tmpstr, forwstr, 441178825Sdfr name, tmpstr); 442178825Sdfr 443233294Sstas if (asprintf (&n, "&(%s)->val[(%s)->len]", name, name) < 0 || n == NULL) 444178825Sdfr errx(1, "malloc"); 445233294Sstas if (asprintf (&sname, "%s_s_of", tmpstr) < 0 || sname == NULL) 446178825Sdfr errx(1, "malloc"); 447233294Sstas decode_type (n, t->subtype, 0, forwstr, sname, NULL, depth + 1); 448233294Sstas fprintf (codefile, 44972445Sassar "(%s)->len++;\n" 450178825Sdfr "len = %s_origlen - ret;\n" 45172445Sassar "}\n" 452178825Sdfr "ret += %s_oldret;\n" 453178825Sdfr "}\n", 454178825Sdfr name, 455178825Sdfr tmpstr, tmpstr); 456178825Sdfr if (t->range) 457178825Sdfr range_check(name, "len", forwstr, t->range); 45872445Sassar free (n); 459178825Sdfr free (sname); 46072445Sassar break; 46172445Sassar } 46272445Sassar case TGeneralizedTime: 463178825Sdfr decode_primitive ("generalized_time", name, forwstr); 46472445Sassar break; 46572445Sassar case TGeneralString: 466178825Sdfr decode_primitive ("general_string", name, forwstr); 46772445Sassar break; 468233294Sstas case TTeletexString: 469233294Sstas decode_primitive ("general_string", name, forwstr); 470233294Sstas break; 471178825Sdfr case TTag:{ 472233294Sstas char *tname = NULL, *typestring = NULL; 473233294Sstas char *ide = NULL; 474178825Sdfr 475233294Sstas if (asprintf(&typestring, "%s_type", tmpstr) < 0 || typestring == NULL) 476233294Sstas errx(1, "malloc"); 477233294Sstas 478233294Sstas fprintf(codefile, 479178825Sdfr "{\n" 480233294Sstas "size_t %s_datalen, %s_oldlen;\n" 481233294Sstas "Der_type %s;\n", 482233294Sstas tmpstr, tmpstr, typestring); 483233294Sstas if(support_ber) 484233294Sstas fprintf(codefile, 485233294Sstas "int is_indefinite%u;\n", depth); 486233294Sstas 487233294Sstas fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, &%s, %s, " 488178825Sdfr "&%s_datalen, &l);\n", 489178825Sdfr classname(t->tag.tagclass), 490233294Sstas typestring, 491178825Sdfr valuename(t->tag.tagclass, t->tag.tagvalue), 492178825Sdfr tmpstr); 493233294Sstas 494233294Sstas /* XXX hardcode for now */ 495233294Sstas if (support_ber && t->subtype->type == TOctetString) { 496233294Sstas ide = typestring; 497233294Sstas } else { 498233294Sstas fprintf(codefile, 499233294Sstas "if (e == 0 && %s != %s) { e = ASN1_BAD_ID; }\n", 500233294Sstas typestring, 501233294Sstas is_primitive_type(t->subtype->type) ? "PRIM" : "CONS"); 502233294Sstas } 503233294Sstas 504178825Sdfr if(optional) { 505233294Sstas fprintf(codefile, 506178825Sdfr "if(e) {\n" 507178825Sdfr "%s = NULL;\n" 508178825Sdfr "} else {\n" 509178825Sdfr "%s = calloc(1, sizeof(*%s));\n" 510178825Sdfr "if (%s == NULL) { e = ENOMEM; %s; }\n", 511178825Sdfr name, name, name, name, forwstr); 512178825Sdfr } else { 513178825Sdfr fprintf(codefile, "if(e) %s;\n", forwstr); 514178825Sdfr } 51572445Sassar fprintf (codefile, 516178825Sdfr "p += l; len -= l; ret += l;\n" 517178825Sdfr "%s_oldlen = len;\n", 518178825Sdfr tmpstr); 519233294Sstas if(support_ber) 520178825Sdfr fprintf (codefile, 521233294Sstas "if((is_indefinite%u = _heim_fix_dce(%s_datalen, &len)) < 0)\n" 522233294Sstas "{ e = ASN1_BAD_FORMAT; %s; }\n" 523233294Sstas "if (is_indefinite%u) { if (len < 2) { e = ASN1_OVERRUN; %s; } len -= 2; }", 524233294Sstas depth, tmpstr, forwstr, depth, forwstr); 525178825Sdfr else 526233294Sstas fprintf(codefile, 527178825Sdfr "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n" 528178825Sdfr "len = %s_datalen;\n", tmpstr, forwstr, tmpstr); 529233294Sstas if (asprintf (&tname, "%s_Tag", tmpstr) < 0 || tname == NULL) 530178825Sdfr errx(1, "malloc"); 531233294Sstas decode_type (name, t->subtype, 0, forwstr, tname, ide, depth + 1); 532233294Sstas if(support_ber) 533178825Sdfr fprintf(codefile, 534233294Sstas "if(is_indefinite%u){\n" 535233294Sstas "len += 2;\n" 536233294Sstas "e = der_match_tag_and_length(p, len, " 537233294Sstas "(Der_class)0, &%s, UT_EndOfContent, " 538178825Sdfr "&%s_datalen, &l);\n" 539233294Sstas "if(e) %s;\n" 540233294Sstas "p += l; len -= l; ret += l;\n" 541233294Sstas "if (%s != (Der_type)0) { e = ASN1_BAD_ID; %s; }\n" 542233294Sstas "} else \n", 543233294Sstas depth, 544233294Sstas typestring, 545233294Sstas tmpstr, 546233294Sstas forwstr, 547233294Sstas typestring, forwstr); 548233294Sstas fprintf(codefile, 549178825Sdfr "len = %s_oldlen - %s_datalen;\n", 550178825Sdfr tmpstr, tmpstr); 551178825Sdfr if(optional) 552233294Sstas fprintf(codefile, 553178825Sdfr "}\n"); 554233294Sstas fprintf(codefile, 55572445Sassar "}\n"); 556178825Sdfr free(tname); 557233294Sstas free(typestring); 558178825Sdfr break; 559178825Sdfr } 560178825Sdfr case TChoice: { 561178825Sdfr Member *m, *have_ellipsis = NULL; 562178825Sdfr const char *els = ""; 56355682Smarkm 564178825Sdfr if (t->members == NULL) 565178825Sdfr break; 566178825Sdfr 567178825Sdfr ASN1_TAILQ_FOREACH(m, t->members, members) { 568178825Sdfr const Type *tt = m->type; 569233294Sstas char *s = NULL; 570178825Sdfr Der_class cl; 571178825Sdfr Der_type ty; 572178825Sdfr unsigned tag; 573233294Sstas 574178825Sdfr if (m->ellipsis) { 575178825Sdfr have_ellipsis = m; 576178825Sdfr continue; 577178825Sdfr } 578178825Sdfr 579178825Sdfr find_tag(tt, &cl, &ty, &tag); 580178825Sdfr 581178825Sdfr fprintf(codefile, 582178825Sdfr "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n", 583178825Sdfr els, 584178825Sdfr classname(cl), 585178825Sdfr ty ? "CONS" : "PRIM", 586178825Sdfr valuename(cl, tag)); 587233294Sstas if (asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&", 588233294Sstas name, m->gen_name) < 0 || s == NULL) 589178825Sdfr errx(1, "malloc"); 590233294Sstas decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL, 591233294Sstas depth + 1); 592178825Sdfr fprintf(codefile, 593178825Sdfr "(%s)->element = %s;\n", 594178825Sdfr name, m->label); 595178825Sdfr free(s); 596178825Sdfr fprintf(codefile, 597178825Sdfr "}\n"); 598178825Sdfr els = "else "; 599178825Sdfr } 600178825Sdfr if (have_ellipsis) { 601178825Sdfr fprintf(codefile, 602178825Sdfr "else {\n" 603178825Sdfr "(%s)->u.%s.data = calloc(1, len);\n" 604178825Sdfr "if ((%s)->u.%s.data == NULL) {\n" 605178825Sdfr "e = ENOMEM; %s;\n" 606178825Sdfr "}\n" 607178825Sdfr "(%s)->u.%s.length = len;\n" 608178825Sdfr "memcpy((%s)->u.%s.data, p, len);\n" 609178825Sdfr "(%s)->element = %s;\n" 610178825Sdfr "p += len;\n" 611178825Sdfr "ret += len;\n" 612233294Sstas "len = 0;\n" 613178825Sdfr "}\n", 614178825Sdfr name, have_ellipsis->gen_name, 615178825Sdfr name, have_ellipsis->gen_name, 616233294Sstas forwstr, 617178825Sdfr name, have_ellipsis->gen_name, 618178825Sdfr name, have_ellipsis->gen_name, 619178825Sdfr name, have_ellipsis->label); 620178825Sdfr } else { 621178825Sdfr fprintf(codefile, 622178825Sdfr "else {\n" 623178825Sdfr "e = ASN1_PARSE_ERROR;\n" 624178825Sdfr "%s;\n" 625178825Sdfr "}\n", 626178825Sdfr forwstr); 627178825Sdfr } 62872445Sassar break; 629178825Sdfr } 630178825Sdfr case TUTCTime: 631178825Sdfr decode_primitive ("utctime", name, forwstr); 632178825Sdfr break; 633178825Sdfr case TUTF8String: 634178825Sdfr decode_primitive ("utf8string", name, forwstr); 635178825Sdfr break; 636178825Sdfr case TPrintableString: 637178825Sdfr decode_primitive ("printable_string", name, forwstr); 638178825Sdfr break; 639178825Sdfr case TIA5String: 640178825Sdfr decode_primitive ("ia5_string", name, forwstr); 641178825Sdfr break; 642178825Sdfr case TBMPString: 643178825Sdfr decode_primitive ("bmp_string", name, forwstr); 644178825Sdfr break; 645178825Sdfr case TUniversalString: 646178825Sdfr decode_primitive ("universal_string", name, forwstr); 647178825Sdfr break; 648178825Sdfr case TVisibleString: 649178825Sdfr decode_primitive ("visible_string", name, forwstr); 650178825Sdfr break; 651178825Sdfr case TNull: 652178825Sdfr fprintf (codefile, "/* NULL */\n"); 653178825Sdfr break; 654178825Sdfr case TOID: 655178825Sdfr decode_primitive ("oid", name, forwstr); 656178825Sdfr break; 65772445Sassar default : 65872445Sassar abort (); 65972445Sassar } 660178825Sdfr return 0; 66155682Smarkm} 66255682Smarkm 66355682Smarkmvoid 66455682Smarkmgenerate_type_decode (const Symbol *s) 66555682Smarkm{ 666178825Sdfr int preserve = preserve_type(s->name) ? TRUE : FALSE; 66755682Smarkm 668233294Sstas fprintf (codefile, "int ASN1CALL\n" 669233294Sstas "decode_%s(const unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE," 670233294Sstas " size_t len HEIMDAL_UNUSED_ATTRIBUTE, %s *data, size_t *size)\n" 67155682Smarkm "{\n", 67255682Smarkm s->gen_name, s->gen_name); 67355682Smarkm 674178825Sdfr switch (s->type->type) { 675178825Sdfr case TInteger: 676178825Sdfr case TBoolean: 677178825Sdfr case TOctetString: 678178825Sdfr case TOID: 679178825Sdfr case TGeneralizedTime: 680178825Sdfr case TGeneralString: 681233294Sstas case TTeletexString: 682178825Sdfr case TUTF8String: 683178825Sdfr case TPrintableString: 684178825Sdfr case TIA5String: 685178825Sdfr case TBMPString: 686178825Sdfr case TUniversalString: 687178825Sdfr case TVisibleString: 688178825Sdfr case TUTCTime: 689178825Sdfr case TNull: 690178825Sdfr case TEnumerated: 691178825Sdfr case TBitString: 692178825Sdfr case TSequence: 693178825Sdfr case TSequenceOf: 694178825Sdfr case TSet: 695178825Sdfr case TSetOf: 696178825Sdfr case TTag: 697178825Sdfr case TType: 698178825Sdfr case TChoice: 699178825Sdfr fprintf (codefile, 700178825Sdfr "size_t ret = 0;\n" 701233294Sstas "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n" 702233294Sstas "int e HEIMDAL_UNUSED_ATTRIBUTE;\n"); 703178825Sdfr if (preserve) 704178825Sdfr fprintf (codefile, "const unsigned char *begin = p;\n"); 70555682Smarkm 706178825Sdfr fprintf (codefile, "\n"); 707178825Sdfr fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */ 708178825Sdfr 709233294Sstas decode_type ("data", s->type, 0, "goto fail", "Top", NULL, 1); 710178825Sdfr if (preserve) 711178825Sdfr fprintf (codefile, 712178825Sdfr "data->_save.data = calloc(1, ret);\n" 713178825Sdfr "if (data->_save.data == NULL) { \n" 714178825Sdfr "e = ENOMEM; goto fail; \n" 715178825Sdfr "}\n" 716178825Sdfr "data->_save.length = ret;\n" 717178825Sdfr "memcpy(data->_save.data, begin, ret);\n"); 718233294Sstas fprintf (codefile, 719178825Sdfr "if(size) *size = ret;\n" 720178825Sdfr "return 0;\n"); 721178825Sdfr fprintf (codefile, 722178825Sdfr "fail:\n" 723178825Sdfr "free_%s(data);\n" 724178825Sdfr "return e;\n", 725178825Sdfr s->gen_name); 726178825Sdfr break; 727178825Sdfr default: 728178825Sdfr abort (); 729178825Sdfr } 73055682Smarkm fprintf (codefile, "}\n\n"); 73155682Smarkm} 732