1 /* 2 * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "gen_locl.h" 35 36 RCSID("$Id: gen_decode.c,v 1.18 2002/08/09 15:37:34 joda Exp $"); 37 38 static void 39 decode_primitive (const char *typename, const char *name) 40 { 41 fprintf (codefile, 42 "e = decode_%s(p, len, %s, &l);\n" 43 "FORW;\n", 44 typename, 45 name); 46 } 47 48 static void 49 decode_type (const char *name, const Type *t) 50 { 51 switch (t->type) { 52 case TType: 53 #if 0 54 decode_type (name, t->symbol->type); 55 #endif 56 fprintf (codefile, 57 "e = decode_%s(p, len, %s, &l);\n" 58 "FORW;\n", 59 t->symbol->gen_name, name); 60 break; 61 case TInteger: 62 if(t->members == NULL) 63 decode_primitive ("integer", name); 64 else { 65 char *s; 66 asprintf(&s, "(int*)%s", name); 67 if(s == NULL) 68 errx (1, "out of memory"); 69 decode_primitive ("integer", s); 70 free(s); 71 } 72 break; 73 case TUInteger: 74 decode_primitive ("unsigned", name); 75 break; 76 case TEnumerated: 77 decode_primitive ("enumerated", name); 78 break; 79 case TOctetString: 80 decode_primitive ("octet_string", name); 81 break; 82 case TOID : 83 decode_primitive ("oid", name); 84 break; 85 case TBitString: { 86 Member *m; 87 int tag = -1; 88 int pos; 89 90 fprintf (codefile, 91 "e = der_match_tag_and_length (p, len, UNIV, PRIM, UT_BitString," 92 "&reallen, &l);\n" 93 "FORW;\n" 94 "if(len < reallen)\n" 95 "return ASN1_OVERRUN;\n" 96 "p++;\n" 97 "len--;\n" 98 "reallen--;\n" 99 "ret++;\n"); 100 pos = 0; 101 for (m = t->members; m && tag != m->val; m = m->next) { 102 while (m->val / 8 > pos / 8) { 103 fprintf (codefile, 104 "p++; len--; reallen--; ret++;\n"); 105 pos += 8; 106 } 107 fprintf (codefile, 108 "%s->%s = (*p >> %d) & 1;\n", 109 name, m->gen_name, 7 - m->val % 8); 110 if (tag == -1) 111 tag = m->val; 112 } 113 fprintf (codefile, 114 "p += reallen; len -= reallen; ret += reallen;\n"); 115 break; 116 } 117 case TSequence: { 118 Member *m; 119 int tag = -1; 120 121 if (t->members == NULL) 122 break; 123 124 fprintf (codefile, 125 "e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence," 126 "&reallen, &l);\n" 127 "FORW;\n" 128 "{\n" 129 "int dce_fix;\n" 130 "if((dce_fix = fix_dce(reallen, &len)) < 0)\n" 131 "return ASN1_BAD_FORMAT;\n"); 132 133 for (m = t->members; m && tag != m->val; m = m->next) { 134 char *s; 135 136 asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name); 137 if (0 && m->type->type == TType){ 138 if(m->optional) 139 fprintf (codefile, 140 "%s = malloc(sizeof(*%s));\n" 141 "if(%s == NULL) return ENOMEM;\n", s, s, s); 142 fprintf (codefile, 143 "e = decode_seq_%s(p, len, %d, %d, %s, &l);\n", 144 m->type->symbol->gen_name, 145 m->val, 146 m->optional, 147 s); 148 if(m->optional) 149 fprintf (codefile, 150 "if (e == ASN1_MISSING_FIELD) {\n" 151 "free(%s);\n" 152 "%s = NULL;\n" 153 "e = l = 0;\n" 154 "}\n", 155 s, s); 156 157 fprintf (codefile, "FORW;\n"); 158 159 }else{ 160 fprintf (codefile, "{\n" 161 "size_t newlen, oldlen;\n\n" 162 "e = der_match_tag (p, len, CONTEXT, CONS, %d, &l);\n", 163 m->val); 164 fprintf (codefile, 165 "if (e)\n"); 166 if(m->optional) 167 /* XXX should look at e */ 168 fprintf (codefile, 169 "%s = NULL;\n", s); 170 else 171 fprintf (codefile, 172 "return e;\n"); 173 fprintf (codefile, 174 "else {\n"); 175 fprintf (codefile, 176 "p += l;\n" 177 "len -= l;\n" 178 "ret += l;\n" 179 "e = der_get_length (p, len, &newlen, &l);\n" 180 "FORW;\n" 181 "{\n" 182 183 "int dce_fix;\n" 184 "oldlen = len;\n" 185 "if((dce_fix = fix_dce(newlen, &len)) < 0)" 186 "return ASN1_BAD_FORMAT;\n"); 187 if (m->optional) 188 fprintf (codefile, 189 "%s = malloc(sizeof(*%s));\n" 190 "if(%s == NULL) return ENOMEM;\n", s, s, s); 191 decode_type (s, m->type); 192 fprintf (codefile, 193 "if(dce_fix){\n" 194 "e = der_match_tag_and_length (p, len, " 195 "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" 196 "FORW;\n" 197 "}else \n" 198 "len = oldlen - newlen;\n" 199 "}\n" 200 "}\n"); 201 fprintf (codefile, 202 "}\n"); 203 } 204 if (tag == -1) 205 tag = m->val; 206 free (s); 207 } 208 fprintf(codefile, 209 "if(dce_fix){\n" 210 "e = der_match_tag_and_length (p, len, " 211 "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" 212 "FORW;\n" 213 "}\n" 214 "}\n"); 215 216 break; 217 } 218 case TSequenceOf: { 219 char *n; 220 221 fprintf (codefile, 222 "e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence," 223 "&reallen, &l);\n" 224 "FORW;\n" 225 "if(len < reallen)\n" 226 "return ASN1_OVERRUN;\n" 227 "len = reallen;\n"); 228 229 fprintf (codefile, 230 "{\n" 231 "size_t origlen = len;\n" 232 "int oldret = ret;\n" 233 "ret = 0;\n" 234 "(%s)->len = 0;\n" 235 "(%s)->val = NULL;\n" 236 "while(ret < origlen) {\n" 237 "(%s)->len++;\n" 238 "(%s)->val = realloc((%s)->val, sizeof(*((%s)->val)) * (%s)->len);\n", 239 name, name, name, name, name, name, name); 240 asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name); 241 decode_type (n, t->subtype); 242 fprintf (codefile, 243 "len = origlen - ret;\n" 244 "}\n" 245 "ret += oldret;\n" 246 "}\n"); 247 free (n); 248 break; 249 } 250 case TGeneralizedTime: 251 decode_primitive ("generalized_time", name); 252 break; 253 case TGeneralString: 254 decode_primitive ("general_string", name); 255 break; 256 case TApplication: 257 fprintf (codefile, 258 "e = der_match_tag_and_length (p, len, APPL, CONS, %d, " 259 "&reallen, &l);\n" 260 "FORW;\n" 261 "{\n" 262 "int dce_fix;\n" 263 "if((dce_fix = fix_dce(reallen, &len)) < 0)\n" 264 "return ASN1_BAD_FORMAT;\n", 265 t->application); 266 decode_type (name, t->subtype); 267 fprintf(codefile, 268 "if(dce_fix){\n" 269 "e = der_match_tag_and_length (p, len, " 270 "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" 271 "FORW;\n" 272 "}\n" 273 "}\n"); 274 275 break; 276 default : 277 abort (); 278 } 279 } 280 281 void 282 generate_type_decode (const Symbol *s) 283 { 284 fprintf (headerfile, 285 "int " 286 "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n", 287 s->gen_name, s->gen_name); 288 289 fprintf (codefile, "#define FORW " 290 "if(e) goto fail; " 291 "p += l; " 292 "len -= l; " 293 "ret += l\n\n"); 294 295 296 fprintf (codefile, "int\n" 297 "decode_%s(const unsigned char *p," 298 " size_t len, %s *data, size_t *size)\n" 299 "{\n", 300 s->gen_name, s->gen_name); 301 302 switch (s->type->type) { 303 case TInteger: 304 case TUInteger: 305 case TOctetString: 306 case TOID: 307 case TGeneralizedTime: 308 case TGeneralString: 309 case TBitString: 310 case TSequence: 311 case TSequenceOf: 312 case TApplication: 313 case TType: 314 fprintf (codefile, 315 "size_t ret = 0, reallen;\n" 316 "size_t l;\n" 317 "int e;\n\n"); 318 fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); 319 fprintf (codefile, "reallen = 0;\n"); /* hack to avoid `unused variable' */ 320 321 decode_type ("data", s->type); 322 fprintf (codefile, 323 "if(size) *size = ret;\n" 324 "return 0;\n"); 325 fprintf (codefile, 326 "fail:\n" 327 "free_%s(data);\n" 328 "return e;\n", 329 s->gen_name); 330 break; 331 default: 332 abort (); 333 } 334 fprintf (codefile, "}\n\n"); 335 } 336 337 void 338 generate_seq_type_decode (const Symbol *s) 339 { 340 fprintf (headerfile, 341 "int decode_seq_%s(const unsigned char *, size_t, int, int, " 342 "%s *, size_t *);\n", 343 s->gen_name, s->gen_name); 344 345 fprintf (codefile, "int\n" 346 "decode_seq_%s(const unsigned char *p, size_t len, int tag, " 347 "int optional, %s *data, size_t *size)\n" 348 "{\n", 349 s->gen_name, s->gen_name); 350 351 fprintf (codefile, 352 "size_t newlen, oldlen;\n" 353 "size_t l, ret = 0;\n" 354 "int e;\n" 355 "int dce_fix;\n"); 356 357 fprintf (codefile, 358 "e = der_match_tag(p, len, CONTEXT, CONS, tag, &l);\n" 359 "if (e)\n" 360 "return e;\n"); 361 fprintf (codefile, 362 "p += l;\n" 363 "len -= l;\n" 364 "ret += l;\n" 365 "e = der_get_length(p, len, &newlen, &l);\n" 366 "if (e)\n" 367 "return e;\n" 368 "p += l;\n" 369 "len -= l;\n" 370 "ret += l;\n" 371 "oldlen = len;\n" 372 "if ((dce_fix = fix_dce(newlen, &len)) < 0)\n" 373 "return ASN1_BAD_FORMAT;\n" 374 "e = decode_%s(p, len, data, &l);\n" 375 "if (e)\n" 376 "return e;\n" 377 "p += l;\n" 378 "len -= l;\n" 379 "ret += l;\n" 380 "if (dce_fix) {\n" 381 "size_t reallen;\n\n" 382 "e = der_match_tag_and_length(p, len, " 383 "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" 384 "if (e)\n" 385 "return e;\n" 386 "ret += l;\n" 387 "}\n", 388 s->gen_name); 389 fprintf (codefile, 390 "if(size) *size = ret;\n" 391 "return 0;\n"); 392 393 fprintf (codefile, "}\n\n"); 394 } 395