1b528cefcSMark Murray /* 2ae771770SStanislav Sedov * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "gen_locl.h" 35c19800e8SDoug Rabson #include "lex.h" 36b528cefcSMark Murray 37ae771770SStanislav Sedov RCSID("$Id$"); 38b528cefcSMark Murray 39b528cefcSMark Murray static void 40c19800e8SDoug Rabson decode_primitive (const char *typename, const char *name, const char *forwstr) 41b528cefcSMark Murray { 42c19800e8SDoug Rabson #if 0 43b528cefcSMark Murray fprintf (codefile, 44b528cefcSMark Murray "e = decode_%s(p, len, %s, &l);\n" 45c19800e8SDoug Rabson "%s;\n", 46b528cefcSMark Murray typename, 47c19800e8SDoug Rabson name, 48c19800e8SDoug Rabson forwstr); 49c19800e8SDoug Rabson #else 50c19800e8SDoug Rabson fprintf (codefile, 51c19800e8SDoug Rabson "e = der_get_%s(p, len, %s, &l);\n" 52c19800e8SDoug Rabson "if(e) %s;\np += l; len -= l; ret += l;\n", 53c19800e8SDoug Rabson typename, 54c19800e8SDoug Rabson name, 55c19800e8SDoug Rabson forwstr); 56c19800e8SDoug Rabson #endif 57c19800e8SDoug Rabson } 58c19800e8SDoug Rabson 59b528cefcSMark Murray static void 60c19800e8SDoug Rabson find_tag (const Type *t, 61c19800e8SDoug Rabson Der_class *cl, Der_type *ty, unsigned *tag) 62b528cefcSMark Murray { 63b528cefcSMark Murray switch (t->type) { 64c19800e8SDoug Rabson case TBitString: 65c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 66c19800e8SDoug Rabson *ty = PRIM; 67c19800e8SDoug Rabson *tag = UT_BitString; 68b528cefcSMark Murray break; 69c19800e8SDoug Rabson case TBoolean: 70c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 71c19800e8SDoug Rabson *ty = PRIM; 72c19800e8SDoug Rabson *tag = UT_Boolean; 735e9cd1aeSAssar Westerlund break; 74c19800e8SDoug Rabson case TChoice: 75c19800e8SDoug Rabson errx(1, "Cannot have recursive CHOICE"); 764137ff4cSJacques Vidrine case TEnumerated: 77c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 78c19800e8SDoug Rabson *ty = PRIM; 79c19800e8SDoug Rabson *tag = UT_Enumerated; 80b528cefcSMark Murray break; 81b528cefcSMark Murray case TGeneralString: 82c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 83c19800e8SDoug Rabson *ty = PRIM; 84c19800e8SDoug Rabson *tag = UT_GeneralString; 85b528cefcSMark Murray break; 86ae771770SStanislav Sedov case TTeletexString: 87ae771770SStanislav Sedov *cl = ASN1_C_UNIV; 88ae771770SStanislav Sedov *ty = PRIM; 89ae771770SStanislav Sedov *tag = UT_TeletexString; 90ae771770SStanislav Sedov break; 91c19800e8SDoug Rabson case TGeneralizedTime: 92c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 93c19800e8SDoug Rabson *ty = PRIM; 94c19800e8SDoug Rabson *tag = UT_GeneralizedTime; 95c19800e8SDoug Rabson break; 96c19800e8SDoug Rabson case TIA5String: 97c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 98c19800e8SDoug Rabson *ty = PRIM; 99c19800e8SDoug Rabson *tag = UT_IA5String; 100c19800e8SDoug Rabson break; 101c19800e8SDoug Rabson case TInteger: 102c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 103c19800e8SDoug Rabson *ty = PRIM; 104c19800e8SDoug Rabson *tag = UT_Integer; 105c19800e8SDoug Rabson break; 106c19800e8SDoug Rabson case TNull: 107c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 108c19800e8SDoug Rabson *ty = PRIM; 109c19800e8SDoug Rabson *tag = UT_Null; 110c19800e8SDoug Rabson break; 111c19800e8SDoug Rabson case TOID: 112c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 113c19800e8SDoug Rabson *ty = PRIM; 114c19800e8SDoug Rabson *tag = UT_OID; 115c19800e8SDoug Rabson break; 116c19800e8SDoug Rabson case TOctetString: 117c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 118c19800e8SDoug Rabson *ty = PRIM; 119c19800e8SDoug Rabson *tag = UT_OctetString; 120c19800e8SDoug Rabson break; 121c19800e8SDoug Rabson case TPrintableString: 122c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 123c19800e8SDoug Rabson *ty = PRIM; 124c19800e8SDoug Rabson *tag = UT_PrintableString; 125c19800e8SDoug Rabson break; 126c19800e8SDoug Rabson case TSequence: 127c19800e8SDoug Rabson case TSequenceOf: 128c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 129c19800e8SDoug Rabson *ty = CONS; 130c19800e8SDoug Rabson *tag = UT_Sequence; 131c19800e8SDoug Rabson break; 132c19800e8SDoug Rabson case TSet: 133c19800e8SDoug Rabson case TSetOf: 134c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 135c19800e8SDoug Rabson *ty = CONS; 136c19800e8SDoug Rabson *tag = UT_Set; 137c19800e8SDoug Rabson break; 138c19800e8SDoug Rabson case TTag: 139c19800e8SDoug Rabson *cl = t->tag.tagclass; 140c19800e8SDoug Rabson *ty = is_primitive_type(t->subtype->type) ? PRIM : CONS; 141c19800e8SDoug Rabson *tag = t->tag.tagvalue; 142c19800e8SDoug Rabson break; 143c19800e8SDoug Rabson case TType: 144c19800e8SDoug Rabson if ((t->symbol->stype == Stype && t->symbol->type == NULL) 145c19800e8SDoug Rabson || t->symbol->stype == SUndefined) { 146ae771770SStanislav Sedov lex_error_message("%s is imported or still undefined, " 147c19800e8SDoug Rabson " can't generate tag checking data in CHOICE " 148c19800e8SDoug Rabson "without this information", 149c19800e8SDoug Rabson t->symbol->name); 150c19800e8SDoug Rabson exit(1); 151c19800e8SDoug Rabson } 152c19800e8SDoug Rabson find_tag(t->symbol->type, cl, ty, tag); 153c19800e8SDoug Rabson return; 154c19800e8SDoug Rabson case TUTCTime: 155c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 156c19800e8SDoug Rabson *ty = PRIM; 157c19800e8SDoug Rabson *tag = UT_UTCTime; 158c19800e8SDoug Rabson break; 159c19800e8SDoug Rabson case TUTF8String: 160c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 161c19800e8SDoug Rabson *ty = PRIM; 162c19800e8SDoug Rabson *tag = UT_UTF8String; 163c19800e8SDoug Rabson break; 164c19800e8SDoug Rabson case TBMPString: 165c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 166c19800e8SDoug Rabson *ty = PRIM; 167c19800e8SDoug Rabson *tag = UT_BMPString; 168c19800e8SDoug Rabson break; 169c19800e8SDoug Rabson case TUniversalString: 170c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 171c19800e8SDoug Rabson *ty = PRIM; 172c19800e8SDoug Rabson *tag = UT_UniversalString; 173c19800e8SDoug Rabson break; 174c19800e8SDoug Rabson case TVisibleString: 175c19800e8SDoug Rabson *cl = ASN1_C_UNIV; 176c19800e8SDoug Rabson *ty = PRIM; 177c19800e8SDoug Rabson *tag = UT_VisibleString; 178b528cefcSMark Murray break; 179b528cefcSMark Murray default: 180b528cefcSMark Murray abort(); 181b528cefcSMark Murray } 182b528cefcSMark Murray } 183b528cefcSMark Murray 184c19800e8SDoug Rabson static void 185c19800e8SDoug Rabson range_check(const char *name, 186c19800e8SDoug Rabson const char *length, 187c19800e8SDoug Rabson const char *forwstr, 188c19800e8SDoug Rabson struct range *r) 189c19800e8SDoug Rabson { 190c19800e8SDoug Rabson if (r->min == r->max + 2 || r->min < r->max) 191c19800e8SDoug Rabson fprintf (codefile, 192*1b748759SDimitry Andric "if ((%s)->%s > %" PRId64 ") {\n" 193c19800e8SDoug Rabson "e = ASN1_MAX_CONSTRAINT; %s;\n" 194c19800e8SDoug Rabson "}\n", 195c19800e8SDoug Rabson name, length, r->max, forwstr); 196c19800e8SDoug Rabson if (r->min - 1 == r->max || r->min < r->max) 197c19800e8SDoug Rabson fprintf (codefile, 198*1b748759SDimitry Andric "if ((%s)->%s < %" PRId64 ") {\n" 199c19800e8SDoug Rabson "e = ASN1_MIN_CONSTRAINT; %s;\n" 200c19800e8SDoug Rabson "}\n", 201c19800e8SDoug Rabson name, length, r->min, forwstr); 202c19800e8SDoug Rabson if (r->max == r->min) 203c19800e8SDoug Rabson fprintf (codefile, 204*1b748759SDimitry Andric "if ((%s)->%s != %" PRId64 ") {\n" 205c19800e8SDoug Rabson "e = ASN1_EXACT_CONSTRAINT; %s;\n" 206c19800e8SDoug Rabson "}\n", 207c19800e8SDoug Rabson name, length, r->min, forwstr); 208c19800e8SDoug Rabson } 209c19800e8SDoug Rabson 210c19800e8SDoug Rabson static int 211c19800e8SDoug Rabson decode_type (const char *name, const Type *t, int optional, 212ae771770SStanislav Sedov const char *forwstr, const char *tmpstr, const char *dertype, 213ae771770SStanislav Sedov unsigned int depth) 214c19800e8SDoug Rabson { 215c19800e8SDoug Rabson switch (t->type) { 216c19800e8SDoug Rabson case TType: { 217c19800e8SDoug Rabson if (optional) 218c19800e8SDoug Rabson fprintf(codefile, 219c19800e8SDoug Rabson "%s = calloc(1, sizeof(*%s));\n" 220c19800e8SDoug Rabson "if (%s == NULL) %s;\n", 221c19800e8SDoug Rabson name, name, name, forwstr); 222c19800e8SDoug Rabson fprintf (codefile, 223c19800e8SDoug Rabson "e = decode_%s(p, len, %s, &l);\n", 224c19800e8SDoug Rabson t->symbol->gen_name, name); 225c19800e8SDoug Rabson if (optional) { 226c19800e8SDoug Rabson fprintf (codefile, 227c19800e8SDoug Rabson "if(e) {\n" 228c19800e8SDoug Rabson "free(%s);\n" 229c19800e8SDoug Rabson "%s = NULL;\n" 230c19800e8SDoug Rabson "} else {\n" 231c19800e8SDoug Rabson "p += l; len -= l; ret += l;\n" 232c19800e8SDoug Rabson "}\n", 233c19800e8SDoug Rabson name, name); 234c19800e8SDoug Rabson } else { 235c19800e8SDoug Rabson fprintf (codefile, 236c19800e8SDoug Rabson "if(e) %s;\n", 237c19800e8SDoug Rabson forwstr); 238c19800e8SDoug Rabson fprintf (codefile, 239c19800e8SDoug Rabson "p += l; len -= l; ret += l;\n"); 240c19800e8SDoug Rabson } 241c19800e8SDoug Rabson break; 242c19800e8SDoug Rabson } 243c19800e8SDoug Rabson case TInteger: 244c19800e8SDoug Rabson if(t->members) { 245c19800e8SDoug Rabson fprintf(codefile, 246c19800e8SDoug Rabson "{\n" 247c19800e8SDoug Rabson "int enumint;\n"); 248c19800e8SDoug Rabson decode_primitive ("integer", "&enumint", forwstr); 249c19800e8SDoug Rabson fprintf(codefile, 250c19800e8SDoug Rabson "*%s = enumint;\n" 251c19800e8SDoug Rabson "}\n", 252c19800e8SDoug Rabson name); 253c19800e8SDoug Rabson } else if (t->range == NULL) { 254c19800e8SDoug Rabson decode_primitive ("heim_integer", name, forwstr); 255*1b748759SDimitry Andric } else if (t->range->min < INT_MIN && t->range->max <= INT64_MAX) { 256*1b748759SDimitry Andric decode_primitive ("integer64", name, forwstr); 257*1b748759SDimitry Andric } else if (t->range->min >= 0 && t->range->max > UINT_MAX) { 258*1b748759SDimitry Andric decode_primitive ("unsigned64", name, forwstr); 259*1b748759SDimitry Andric } else if (t->range->min >= INT_MIN && t->range->max <= INT_MAX) { 260c19800e8SDoug Rabson decode_primitive ("integer", name, forwstr); 261*1b748759SDimitry Andric } else if (t->range->min >= 0 && t->range->max <= UINT_MAX) { 262c19800e8SDoug Rabson decode_primitive ("unsigned", name, forwstr); 263c19800e8SDoug Rabson } else 264*1b748759SDimitry Andric errx(1, "%s: unsupported range %" PRId64 " -> %" PRId64, 265c19800e8SDoug Rabson name, t->range->min, t->range->max); 266c19800e8SDoug Rabson break; 267c19800e8SDoug Rabson case TBoolean: 268c19800e8SDoug Rabson decode_primitive ("boolean", name, forwstr); 269c19800e8SDoug Rabson break; 270c19800e8SDoug Rabson case TEnumerated: 271c19800e8SDoug Rabson decode_primitive ("enumerated", name, forwstr); 272c19800e8SDoug Rabson break; 273c19800e8SDoug Rabson case TOctetString: 274ae771770SStanislav Sedov if (dertype) { 275ae771770SStanislav Sedov fprintf(codefile, 276ae771770SStanislav Sedov "if (%s == CONS) {\n", 277ae771770SStanislav Sedov dertype); 278ae771770SStanislav Sedov decode_primitive("octet_string_ber", name, forwstr); 279ae771770SStanislav Sedov fprintf(codefile, 280ae771770SStanislav Sedov "} else {\n"); 281ae771770SStanislav Sedov } 282c19800e8SDoug Rabson decode_primitive ("octet_string", name, forwstr); 283ae771770SStanislav Sedov if (dertype) 284ae771770SStanislav Sedov fprintf(codefile, "}\n"); 285c19800e8SDoug Rabson if (t->range) 286c19800e8SDoug Rabson range_check(name, "length", forwstr, t->range); 287c19800e8SDoug Rabson break; 288c19800e8SDoug Rabson case TBitString: { 289c19800e8SDoug Rabson Member *m; 290c19800e8SDoug Rabson int pos = 0; 291c19800e8SDoug Rabson 292c19800e8SDoug Rabson if (ASN1_TAILQ_EMPTY(t->members)) { 293c19800e8SDoug Rabson decode_primitive ("bit_string", name, forwstr); 294c19800e8SDoug Rabson break; 295c19800e8SDoug Rabson } 296c19800e8SDoug Rabson fprintf(codefile, 297c19800e8SDoug Rabson "if (len < 1) return ASN1_OVERRUN;\n" 298c19800e8SDoug Rabson "p++; len--; ret++;\n"); 299c19800e8SDoug Rabson fprintf(codefile, 300c19800e8SDoug Rabson "do {\n" 301c19800e8SDoug Rabson "if (len < 1) break;\n"); 302c19800e8SDoug Rabson ASN1_TAILQ_FOREACH(m, t->members, members) { 303c19800e8SDoug Rabson while (m->val / 8 > pos / 8) { 304c19800e8SDoug Rabson fprintf (codefile, 305c19800e8SDoug Rabson "p++; len--; ret++;\n" 306c19800e8SDoug Rabson "if (len < 1) break;\n"); 307c19800e8SDoug Rabson pos += 8; 308c19800e8SDoug Rabson } 309c19800e8SDoug Rabson fprintf (codefile, 310c19800e8SDoug Rabson "(%s)->%s = (*p >> %d) & 1;\n", 311c19800e8SDoug Rabson name, m->gen_name, 7 - m->val % 8); 312c19800e8SDoug Rabson } 313c19800e8SDoug Rabson fprintf(codefile, 314c19800e8SDoug Rabson "} while(0);\n"); 315c19800e8SDoug Rabson fprintf (codefile, 316c19800e8SDoug Rabson "p += len; ret += len;\n"); 317c19800e8SDoug Rabson break; 318c19800e8SDoug Rabson } 319c19800e8SDoug Rabson case TSequence: { 320c19800e8SDoug Rabson Member *m; 321c19800e8SDoug Rabson 322c19800e8SDoug Rabson if (t->members == NULL) 323c19800e8SDoug Rabson break; 324c19800e8SDoug Rabson 325c19800e8SDoug Rabson ASN1_TAILQ_FOREACH(m, t->members, members) { 326ae771770SStanislav Sedov char *s = NULL; 327c19800e8SDoug Rabson 328c19800e8SDoug Rabson if (m->ellipsis) 329c19800e8SDoug Rabson continue; 330c19800e8SDoug Rabson 331ae771770SStanislav Sedov if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", 332ae771770SStanislav Sedov name, m->gen_name) < 0 || s == NULL) 333c19800e8SDoug Rabson errx(1, "malloc"); 334ae771770SStanislav Sedov decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL, 335ae771770SStanislav Sedov depth + 1); 336c19800e8SDoug Rabson free (s); 337c19800e8SDoug Rabson } 338c19800e8SDoug Rabson 339c19800e8SDoug Rabson break; 340c19800e8SDoug Rabson } 341c19800e8SDoug Rabson case TSet: { 342c19800e8SDoug Rabson Member *m; 343c19800e8SDoug Rabson unsigned int memno; 344c19800e8SDoug Rabson 345c19800e8SDoug Rabson if(t->members == NULL) 346c19800e8SDoug Rabson break; 347c19800e8SDoug Rabson 348c19800e8SDoug Rabson fprintf(codefile, "{\n"); 349c19800e8SDoug Rabson fprintf(codefile, "unsigned int members = 0;\n"); 350c19800e8SDoug Rabson fprintf(codefile, "while(len > 0) {\n"); 351c19800e8SDoug Rabson fprintf(codefile, 352c19800e8SDoug Rabson "Der_class class;\n" 353c19800e8SDoug Rabson "Der_type type;\n" 354c19800e8SDoug Rabson "int tag;\n" 355c19800e8SDoug Rabson "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n" 356c19800e8SDoug Rabson "if(e) %s;\n", forwstr); 357c19800e8SDoug Rabson fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n"); 358c19800e8SDoug Rabson memno = 0; 359c19800e8SDoug Rabson ASN1_TAILQ_FOREACH(m, t->members, members) { 360c19800e8SDoug Rabson char *s; 361c19800e8SDoug Rabson 362c19800e8SDoug Rabson assert(m->type->type == TTag); 363c19800e8SDoug Rabson 364c19800e8SDoug Rabson fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n", 365c19800e8SDoug Rabson classname(m->type->tag.tagclass), 366c19800e8SDoug Rabson is_primitive_type(m->type->subtype->type) ? "PRIM" : "CONS", 367c19800e8SDoug Rabson valuename(m->type->tag.tagclass, m->type->tag.tagvalue)); 368c19800e8SDoug Rabson 369ae771770SStanislav Sedov if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL) 370c19800e8SDoug Rabson errx(1, "malloc"); 371c19800e8SDoug Rabson if(m->optional) 372c19800e8SDoug Rabson fprintf(codefile, 373c19800e8SDoug Rabson "%s = calloc(1, sizeof(*%s));\n" 374c19800e8SDoug Rabson "if (%s == NULL) { e = ENOMEM; %s; }\n", 375c19800e8SDoug Rabson s, s, s, forwstr); 376ae771770SStanislav Sedov decode_type (s, m->type, 0, forwstr, m->gen_name, NULL, depth + 1); 377c19800e8SDoug Rabson free (s); 378c19800e8SDoug Rabson 379c19800e8SDoug Rabson fprintf(codefile, "members |= (1 << %d);\n", memno); 380c19800e8SDoug Rabson memno++; 381c19800e8SDoug Rabson fprintf(codefile, "break;\n"); 382c19800e8SDoug Rabson } 383c19800e8SDoug Rabson fprintf(codefile, 384c19800e8SDoug Rabson "default:\n" 385c19800e8SDoug Rabson "return ASN1_MISPLACED_FIELD;\n" 386c19800e8SDoug Rabson "break;\n"); 387c19800e8SDoug Rabson fprintf(codefile, "}\n"); 388c19800e8SDoug Rabson fprintf(codefile, "}\n"); 389c19800e8SDoug Rabson memno = 0; 390c19800e8SDoug Rabson ASN1_TAILQ_FOREACH(m, t->members, members) { 391c19800e8SDoug Rabson char *s; 392c19800e8SDoug Rabson 393ae771770SStanislav Sedov if (asprintf (&s, "%s->%s", name, m->gen_name) < 0 || s == NULL) 394c19800e8SDoug Rabson errx(1, "malloc"); 395c19800e8SDoug Rabson fprintf(codefile, "if((members & (1 << %d)) == 0)\n", memno); 396c19800e8SDoug Rabson if(m->optional) 397c19800e8SDoug Rabson fprintf(codefile, "%s = NULL;\n", s); 398c19800e8SDoug Rabson else if(m->defval) 399c19800e8SDoug Rabson gen_assign_defval(s, m->defval); 400c19800e8SDoug Rabson else 401c19800e8SDoug Rabson fprintf(codefile, "return ASN1_MISSING_FIELD;\n"); 402c19800e8SDoug Rabson free(s); 403c19800e8SDoug Rabson memno++; 404c19800e8SDoug Rabson } 405c19800e8SDoug Rabson fprintf(codefile, "}\n"); 406c19800e8SDoug Rabson break; 407c19800e8SDoug Rabson } 408c19800e8SDoug Rabson case TSetOf: 409c19800e8SDoug Rabson case TSequenceOf: { 410ae771770SStanislav Sedov char *n = NULL; 411ae771770SStanislav Sedov char *sname = NULL; 412c19800e8SDoug Rabson 413c19800e8SDoug Rabson fprintf (codefile, 414c19800e8SDoug Rabson "{\n" 415c19800e8SDoug Rabson "size_t %s_origlen = len;\n" 416c19800e8SDoug Rabson "size_t %s_oldret = ret;\n" 417c19800e8SDoug Rabson "size_t %s_olen = 0;\n" 418c19800e8SDoug Rabson "void *%s_tmp;\n" 419c19800e8SDoug Rabson "ret = 0;\n" 420c19800e8SDoug Rabson "(%s)->len = 0;\n" 421c19800e8SDoug Rabson "(%s)->val = NULL;\n", 422c19800e8SDoug Rabson tmpstr, 423c19800e8SDoug Rabson tmpstr, 424c19800e8SDoug Rabson tmpstr, 425c19800e8SDoug Rabson tmpstr, 426c19800e8SDoug Rabson name, 427c19800e8SDoug Rabson name); 428c19800e8SDoug Rabson 429c19800e8SDoug Rabson fprintf (codefile, 430c19800e8SDoug Rabson "while(ret < %s_origlen) {\n" 431c19800e8SDoug Rabson "size_t %s_nlen = %s_olen + sizeof(*((%s)->val));\n" 432c19800e8SDoug Rabson "if (%s_olen > %s_nlen) { e = ASN1_OVERFLOW; %s; }\n" 433c19800e8SDoug Rabson "%s_olen = %s_nlen;\n" 434c19800e8SDoug Rabson "%s_tmp = realloc((%s)->val, %s_olen);\n" 435c19800e8SDoug Rabson "if (%s_tmp == NULL) { e = ENOMEM; %s; }\n" 436c19800e8SDoug Rabson "(%s)->val = %s_tmp;\n", 437c19800e8SDoug Rabson tmpstr, 438c19800e8SDoug Rabson tmpstr, tmpstr, name, 439c19800e8SDoug Rabson tmpstr, tmpstr, forwstr, 440c19800e8SDoug Rabson tmpstr, tmpstr, 441c19800e8SDoug Rabson tmpstr, name, tmpstr, 442c19800e8SDoug Rabson tmpstr, forwstr, 443c19800e8SDoug Rabson name, tmpstr); 444c19800e8SDoug Rabson 445ae771770SStanislav Sedov if (asprintf (&n, "&(%s)->val[(%s)->len]", name, name) < 0 || n == NULL) 446c19800e8SDoug Rabson errx(1, "malloc"); 447ae771770SStanislav Sedov if (asprintf (&sname, "%s_s_of", tmpstr) < 0 || sname == NULL) 448c19800e8SDoug Rabson errx(1, "malloc"); 449ae771770SStanislav Sedov decode_type (n, t->subtype, 0, forwstr, sname, NULL, depth + 1); 450c19800e8SDoug Rabson fprintf (codefile, 451c19800e8SDoug Rabson "(%s)->len++;\n" 452c19800e8SDoug Rabson "len = %s_origlen - ret;\n" 453c19800e8SDoug Rabson "}\n" 454c19800e8SDoug Rabson "ret += %s_oldret;\n" 455c19800e8SDoug Rabson "}\n", 456c19800e8SDoug Rabson name, 457c19800e8SDoug Rabson tmpstr, tmpstr); 458c19800e8SDoug Rabson if (t->range) 459c19800e8SDoug Rabson range_check(name, "len", forwstr, t->range); 460c19800e8SDoug Rabson free (n); 461c19800e8SDoug Rabson free (sname); 462c19800e8SDoug Rabson break; 463c19800e8SDoug Rabson } 464c19800e8SDoug Rabson case TGeneralizedTime: 465c19800e8SDoug Rabson decode_primitive ("generalized_time", name, forwstr); 466c19800e8SDoug Rabson break; 467c19800e8SDoug Rabson case TGeneralString: 468c19800e8SDoug Rabson decode_primitive ("general_string", name, forwstr); 469c19800e8SDoug Rabson break; 470ae771770SStanislav Sedov case TTeletexString: 471ae771770SStanislav Sedov decode_primitive ("general_string", name, forwstr); 472ae771770SStanislav Sedov break; 473c19800e8SDoug Rabson case TTag:{ 474ae771770SStanislav Sedov char *tname = NULL, *typestring = NULL; 475ae771770SStanislav Sedov char *ide = NULL; 476ae771770SStanislav Sedov 477ae771770SStanislav Sedov if (asprintf(&typestring, "%s_type", tmpstr) < 0 || typestring == NULL) 478ae771770SStanislav Sedov errx(1, "malloc"); 479c19800e8SDoug Rabson 480c19800e8SDoug Rabson fprintf(codefile, 481c19800e8SDoug Rabson "{\n" 482ae771770SStanislav Sedov "size_t %s_datalen, %s_oldlen;\n" 483ae771770SStanislav Sedov "Der_type %s;\n", 484ae771770SStanislav Sedov tmpstr, tmpstr, typestring); 485ae771770SStanislav Sedov if(support_ber) 486c19800e8SDoug Rabson fprintf(codefile, 487ae771770SStanislav Sedov "int is_indefinite%u;\n", depth); 488ae771770SStanislav Sedov 489ae771770SStanislav Sedov fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, &%s, %s, " 490c19800e8SDoug Rabson "&%s_datalen, &l);\n", 491c19800e8SDoug Rabson classname(t->tag.tagclass), 492ae771770SStanislav Sedov typestring, 493c19800e8SDoug Rabson valuename(t->tag.tagclass, t->tag.tagvalue), 494c19800e8SDoug Rabson tmpstr); 495ae771770SStanislav Sedov 496ae771770SStanislav Sedov /* XXX hardcode for now */ 497ae771770SStanislav Sedov if (support_ber && t->subtype->type == TOctetString) { 498ae771770SStanislav Sedov ide = typestring; 499ae771770SStanislav Sedov } else { 500ae771770SStanislav Sedov fprintf(codefile, 501ae771770SStanislav Sedov "if (e == 0 && %s != %s) { e = ASN1_BAD_ID; }\n", 502ae771770SStanislav Sedov typestring, 503ae771770SStanislav Sedov is_primitive_type(t->subtype->type) ? "PRIM" : "CONS"); 504ae771770SStanislav Sedov } 505ae771770SStanislav Sedov 506c19800e8SDoug Rabson if(optional) { 507c19800e8SDoug Rabson fprintf(codefile, 508c19800e8SDoug Rabson "if(e) {\n" 509c19800e8SDoug Rabson "%s = NULL;\n" 510c19800e8SDoug Rabson "} else {\n" 511c19800e8SDoug Rabson "%s = calloc(1, sizeof(*%s));\n" 512c19800e8SDoug Rabson "if (%s == NULL) { e = ENOMEM; %s; }\n", 513c19800e8SDoug Rabson name, name, name, name, forwstr); 514c19800e8SDoug Rabson } else { 515c19800e8SDoug Rabson fprintf(codefile, "if(e) %s;\n", forwstr); 516c19800e8SDoug Rabson } 517c19800e8SDoug Rabson fprintf (codefile, 518c19800e8SDoug Rabson "p += l; len -= l; ret += l;\n" 519c19800e8SDoug Rabson "%s_oldlen = len;\n", 520c19800e8SDoug Rabson tmpstr); 521ae771770SStanislav Sedov if(support_ber) 522c19800e8SDoug Rabson fprintf (codefile, 523ae771770SStanislav Sedov "if((is_indefinite%u = _heim_fix_dce(%s_datalen, &len)) < 0)\n" 524ae771770SStanislav Sedov "{ e = ASN1_BAD_FORMAT; %s; }\n" 525ae771770SStanislav Sedov "if (is_indefinite%u) { if (len < 2) { e = ASN1_OVERRUN; %s; } len -= 2; }", 526ae771770SStanislav Sedov depth, tmpstr, forwstr, depth, forwstr); 527c19800e8SDoug Rabson else 528c19800e8SDoug Rabson fprintf(codefile, 529c19800e8SDoug Rabson "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n" 530c19800e8SDoug Rabson "len = %s_datalen;\n", tmpstr, forwstr, tmpstr); 531ae771770SStanislav Sedov if (asprintf (&tname, "%s_Tag", tmpstr) < 0 || tname == NULL) 532c19800e8SDoug Rabson errx(1, "malloc"); 533ae771770SStanislav Sedov decode_type (name, t->subtype, 0, forwstr, tname, ide, depth + 1); 534ae771770SStanislav Sedov if(support_ber) 535c19800e8SDoug Rabson fprintf(codefile, 536ae771770SStanislav Sedov "if(is_indefinite%u){\n" 537ae771770SStanislav Sedov "len += 2;\n" 538c19800e8SDoug Rabson "e = der_match_tag_and_length(p, len, " 539ae771770SStanislav Sedov "(Der_class)0, &%s, UT_EndOfContent, " 540c19800e8SDoug Rabson "&%s_datalen, &l);\n" 541ae771770SStanislav Sedov "if(e) %s;\n" 542ae771770SStanislav Sedov "p += l; len -= l; ret += l;\n" 543ae771770SStanislav Sedov "if (%s != (Der_type)0) { e = ASN1_BAD_ID; %s; }\n" 544ae771770SStanislav Sedov "} else \n", 545ae771770SStanislav Sedov depth, 546ae771770SStanislav Sedov typestring, 547ae771770SStanislav Sedov tmpstr, 548ae771770SStanislav Sedov forwstr, 549ae771770SStanislav Sedov typestring, forwstr); 550c19800e8SDoug Rabson fprintf(codefile, 551c19800e8SDoug Rabson "len = %s_oldlen - %s_datalen;\n", 552c19800e8SDoug Rabson tmpstr, tmpstr); 553c19800e8SDoug Rabson if(optional) 554c19800e8SDoug Rabson fprintf(codefile, 555c19800e8SDoug Rabson "}\n"); 556c19800e8SDoug Rabson fprintf(codefile, 557c19800e8SDoug Rabson "}\n"); 558c19800e8SDoug Rabson free(tname); 559ae771770SStanislav Sedov free(typestring); 560c19800e8SDoug Rabson break; 561c19800e8SDoug Rabson } 562c19800e8SDoug Rabson case TChoice: { 563c19800e8SDoug Rabson Member *m, *have_ellipsis = NULL; 564c19800e8SDoug Rabson const char *els = ""; 565c19800e8SDoug Rabson 566c19800e8SDoug Rabson if (t->members == NULL) 567c19800e8SDoug Rabson break; 568c19800e8SDoug Rabson 569c19800e8SDoug Rabson ASN1_TAILQ_FOREACH(m, t->members, members) { 570c19800e8SDoug Rabson const Type *tt = m->type; 571ae771770SStanislav Sedov char *s = NULL; 572c19800e8SDoug Rabson Der_class cl; 573c19800e8SDoug Rabson Der_type ty; 574c19800e8SDoug Rabson unsigned tag; 575c19800e8SDoug Rabson 576c19800e8SDoug Rabson if (m->ellipsis) { 577c19800e8SDoug Rabson have_ellipsis = m; 578c19800e8SDoug Rabson continue; 579c19800e8SDoug Rabson } 580c19800e8SDoug Rabson 581c19800e8SDoug Rabson find_tag(tt, &cl, &ty, &tag); 582c19800e8SDoug Rabson 583c19800e8SDoug Rabson fprintf(codefile, 584c19800e8SDoug Rabson "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n", 585c19800e8SDoug Rabson els, 586c19800e8SDoug Rabson classname(cl), 587c19800e8SDoug Rabson ty ? "CONS" : "PRIM", 588c19800e8SDoug Rabson valuename(cl, tag)); 589ed549cb0SCy Schubert fprintf(codefile, 590ed549cb0SCy Schubert "(%s)->element = %s;\n", 591ed549cb0SCy Schubert name, m->label); 592ae771770SStanislav Sedov if (asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&", 593ae771770SStanislav Sedov name, m->gen_name) < 0 || s == NULL) 594c19800e8SDoug Rabson errx(1, "malloc"); 595ae771770SStanislav Sedov decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL, 596ae771770SStanislav Sedov depth + 1); 597c19800e8SDoug Rabson free(s); 598c19800e8SDoug Rabson fprintf(codefile, 599c19800e8SDoug Rabson "}\n"); 600c19800e8SDoug Rabson els = "else "; 601c19800e8SDoug Rabson } 602c19800e8SDoug Rabson if (have_ellipsis) { 603c19800e8SDoug Rabson fprintf(codefile, 604c19800e8SDoug Rabson "else {\n" 605ed549cb0SCy Schubert "(%s)->element = %s;\n" 606c19800e8SDoug Rabson "(%s)->u.%s.data = calloc(1, len);\n" 607c19800e8SDoug Rabson "if ((%s)->u.%s.data == NULL) {\n" 608c19800e8SDoug Rabson "e = ENOMEM; %s;\n" 609c19800e8SDoug Rabson "}\n" 610c19800e8SDoug Rabson "(%s)->u.%s.length = len;\n" 611c19800e8SDoug Rabson "memcpy((%s)->u.%s.data, p, len);\n" 612c19800e8SDoug Rabson "p += len;\n" 613c19800e8SDoug Rabson "ret += len;\n" 614ae771770SStanislav Sedov "len = 0;\n" 615c19800e8SDoug Rabson "}\n", 616ed549cb0SCy Schubert name, have_ellipsis->label, 617c19800e8SDoug Rabson name, have_ellipsis->gen_name, 618c19800e8SDoug Rabson name, have_ellipsis->gen_name, 619c19800e8SDoug Rabson forwstr, 620c19800e8SDoug Rabson name, have_ellipsis->gen_name, 621ed549cb0SCy Schubert name, have_ellipsis->gen_name); 622c19800e8SDoug Rabson } else { 623c19800e8SDoug Rabson fprintf(codefile, 624c19800e8SDoug Rabson "else {\n" 625c19800e8SDoug Rabson "e = ASN1_PARSE_ERROR;\n" 626c19800e8SDoug Rabson "%s;\n" 627c19800e8SDoug Rabson "}\n", 628c19800e8SDoug Rabson forwstr); 629c19800e8SDoug Rabson } 630c19800e8SDoug Rabson break; 631c19800e8SDoug Rabson } 632c19800e8SDoug Rabson case TUTCTime: 633c19800e8SDoug Rabson decode_primitive ("utctime", name, forwstr); 634c19800e8SDoug Rabson break; 635c19800e8SDoug Rabson case TUTF8String: 636c19800e8SDoug Rabson decode_primitive ("utf8string", name, forwstr); 637c19800e8SDoug Rabson break; 638c19800e8SDoug Rabson case TPrintableString: 639c19800e8SDoug Rabson decode_primitive ("printable_string", name, forwstr); 640c19800e8SDoug Rabson break; 641c19800e8SDoug Rabson case TIA5String: 642c19800e8SDoug Rabson decode_primitive ("ia5_string", name, forwstr); 643c19800e8SDoug Rabson break; 644c19800e8SDoug Rabson case TBMPString: 645c19800e8SDoug Rabson decode_primitive ("bmp_string", name, forwstr); 646c19800e8SDoug Rabson break; 647c19800e8SDoug Rabson case TUniversalString: 648c19800e8SDoug Rabson decode_primitive ("universal_string", name, forwstr); 649c19800e8SDoug Rabson break; 650c19800e8SDoug Rabson case TVisibleString: 651c19800e8SDoug Rabson decode_primitive ("visible_string", name, forwstr); 652c19800e8SDoug Rabson break; 653c19800e8SDoug Rabson case TNull: 654c19800e8SDoug Rabson fprintf (codefile, "/* NULL */\n"); 655c19800e8SDoug Rabson break; 656c19800e8SDoug Rabson case TOID: 657c19800e8SDoug Rabson decode_primitive ("oid", name, forwstr); 658c19800e8SDoug Rabson break; 659c19800e8SDoug Rabson default : 660c19800e8SDoug Rabson abort (); 661c19800e8SDoug Rabson } 662c19800e8SDoug Rabson return 0; 663c19800e8SDoug Rabson } 664c19800e8SDoug Rabson 665b528cefcSMark Murray void 666b528cefcSMark Murray generate_type_decode (const Symbol *s) 667b528cefcSMark Murray { 668c19800e8SDoug Rabson int preserve = preserve_type(s->name) ? TRUE : FALSE; 669c19800e8SDoug Rabson 670ae771770SStanislav Sedov fprintf (codefile, "int ASN1CALL\n" 671ae771770SStanislav Sedov "decode_%s(const unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE," 672ae771770SStanislav Sedov " size_t len HEIMDAL_UNUSED_ATTRIBUTE, %s *data, size_t *size)\n" 673b528cefcSMark Murray "{\n", 674b528cefcSMark Murray s->gen_name, s->gen_name); 675b528cefcSMark Murray 676b528cefcSMark Murray switch (s->type->type) { 677b528cefcSMark Murray case TInteger: 678c19800e8SDoug Rabson case TBoolean: 679b528cefcSMark Murray case TOctetString: 6804137ff4cSJacques Vidrine case TOID: 681b528cefcSMark Murray case TGeneralizedTime: 682b528cefcSMark Murray case TGeneralString: 683ae771770SStanislav Sedov case TTeletexString: 684c19800e8SDoug Rabson case TUTF8String: 685c19800e8SDoug Rabson case TPrintableString: 686c19800e8SDoug Rabson case TIA5String: 687c19800e8SDoug Rabson case TBMPString: 688c19800e8SDoug Rabson case TUniversalString: 689c19800e8SDoug Rabson case TVisibleString: 690c19800e8SDoug Rabson case TUTCTime: 691c19800e8SDoug Rabson case TNull: 692c19800e8SDoug Rabson case TEnumerated: 693b528cefcSMark Murray case TBitString: 694b528cefcSMark Murray case TSequence: 695b528cefcSMark Murray case TSequenceOf: 696c19800e8SDoug Rabson case TSet: 697c19800e8SDoug Rabson case TSetOf: 698c19800e8SDoug Rabson case TTag: 699b528cefcSMark Murray case TType: 700c19800e8SDoug Rabson case TChoice: 701b528cefcSMark Murray fprintf (codefile, 702c19800e8SDoug Rabson "size_t ret = 0;\n" 703ae771770SStanislav Sedov "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n" 704ae771770SStanislav Sedov "int e HEIMDAL_UNUSED_ATTRIBUTE;\n"); 705c19800e8SDoug Rabson if (preserve) 706c19800e8SDoug Rabson fprintf (codefile, "const unsigned char *begin = p;\n"); 707b528cefcSMark Murray 708c19800e8SDoug Rabson fprintf (codefile, "\n"); 709c19800e8SDoug Rabson fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */ 710c19800e8SDoug Rabson 711ae771770SStanislav Sedov decode_type ("data", s->type, 0, "goto fail", "Top", NULL, 1); 712c19800e8SDoug Rabson if (preserve) 713c19800e8SDoug Rabson fprintf (codefile, 714c19800e8SDoug Rabson "data->_save.data = calloc(1, ret);\n" 715c19800e8SDoug Rabson "if (data->_save.data == NULL) { \n" 716c19800e8SDoug Rabson "e = ENOMEM; goto fail; \n" 717c19800e8SDoug Rabson "}\n" 718c19800e8SDoug Rabson "data->_save.length = ret;\n" 719c19800e8SDoug Rabson "memcpy(data->_save.data, begin, ret);\n"); 720b528cefcSMark Murray fprintf (codefile, 721b528cefcSMark Murray "if(size) *size = ret;\n" 722b528cefcSMark Murray "return 0;\n"); 723adb0ddaeSAssar Westerlund fprintf (codefile, 724adb0ddaeSAssar Westerlund "fail:\n" 725adb0ddaeSAssar Westerlund "free_%s(data);\n" 726adb0ddaeSAssar Westerlund "return e;\n", 727adb0ddaeSAssar Westerlund s->gen_name); 728b528cefcSMark Murray break; 729b528cefcSMark Murray default: 730b528cefcSMark Murray abort (); 731b528cefcSMark Murray } 732b528cefcSMark Murray fprintf (codefile, "}\n\n"); 733b528cefcSMark Murray } 734