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.16 2001/02/10 18:14:38 assar 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 TOctetString: 77 decode_primitive ("octet_string", name); 78 break; 79 case TBitString: { 80 Member *m; 81 int tag = -1; 82 int pos; 83 84 fprintf (codefile, 85 "e = der_match_tag_and_length (p, len, UNIV, PRIM, UT_BitString," 86 "&reallen, &l);\n" 87 "FORW;\n" 88 "if(len < reallen)\n" 89 "return ASN1_OVERRUN;\n" 90 "p++;\n" 91 "len--;\n" 92 "reallen--;\n" 93 "ret++;\n"); 94 pos = 0; 95 for (m = t->members; m && tag != m->val; m = m->next) { 96 while (m->val / 8 > pos / 8) { 97 fprintf (codefile, 98 "p++; len--; reallen--; ret++;\n"); 99 pos += 8; 100 } 101 fprintf (codefile, 102 "%s->%s = (*p >> %d) & 1;\n", 103 name, m->gen_name, 7 - m->val % 8); 104 if (tag == -1) 105 tag = m->val; 106 } 107 fprintf (codefile, 108 "p += reallen; len -= reallen; ret += reallen;\n"); 109 break; 110 } 111 case TSequence: { 112 Member *m; 113 int tag = -1; 114 115 if (t->members == NULL) 116 break; 117 118 fprintf (codefile, 119 "e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence," 120 "&reallen, &l);\n" 121 "FORW;\n" 122 "{\n" 123 "int dce_fix;\n" 124 "if((dce_fix = fix_dce(reallen, &len)) < 0)\n" 125 "return ASN1_BAD_FORMAT;\n"); 126 127 for (m = t->members; m && tag != m->val; m = m->next) { 128 char *s; 129 130 asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name); 131 if (0 && m->type->type == TType){ 132 if(m->optional) 133 fprintf (codefile, 134 "%s = malloc(sizeof(*%s));\n" 135 "if(%s == NULL) return ENOMEM;\n", s, s, s); 136 fprintf (codefile, 137 "e = decode_seq_%s(p, len, %d, %d, %s, &l);\n", 138 m->type->symbol->gen_name, 139 m->val, 140 m->optional, 141 s); 142 if(m->optional) 143 fprintf (codefile, 144 "if (e == ASN1_MISSING_FIELD) {\n" 145 "free(%s);\n" 146 "%s = NULL;\n" 147 "e = l = 0;\n" 148 "}\n", 149 s, s); 150 151 fprintf (codefile, "FORW;\n"); 152 153 }else{ 154 fprintf (codefile, "{\n" 155 "size_t newlen, oldlen;\n\n" 156 "e = der_match_tag (p, len, CONTEXT, CONS, %d, &l);\n", 157 m->val); 158 fprintf (codefile, 159 "if (e)\n"); 160 if(m->optional) 161 /* XXX should look at e */ 162 fprintf (codefile, 163 "%s = NULL;\n", s); 164 else 165 fprintf (codefile, 166 "return e;\n"); 167 fprintf (codefile, 168 "else {\n"); 169 fprintf (codefile, 170 "p += l;\n" 171 "len -= l;\n" 172 "ret += l;\n" 173 "e = der_get_length (p, len, &newlen, &l);\n" 174 "FORW;\n" 175 "{\n" 176 177 "int dce_fix;\n" 178 "oldlen = len;\n" 179 "if((dce_fix = fix_dce(newlen, &len)) < 0)" 180 "return ASN1_BAD_FORMAT;\n"); 181 if (m->optional) 182 fprintf (codefile, 183 "%s = malloc(sizeof(*%s));\n" 184 "if(%s == NULL) return ENOMEM;\n", s, s, s); 185 decode_type (s, m->type); 186 fprintf (codefile, 187 "if(dce_fix){\n" 188 "e = der_match_tag_and_length (p, len, " 189 "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" 190 "FORW;\n" 191 "}else \n" 192 "len = oldlen - newlen;\n" 193 "}\n" 194 "}\n"); 195 fprintf (codefile, 196 "}\n"); 197 } 198 if (tag == -1) 199 tag = m->val; 200 free (s); 201 } 202 fprintf(codefile, 203 "if(dce_fix){\n" 204 "e = der_match_tag_and_length (p, len, " 205 "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" 206 "FORW;\n" 207 "}\n" 208 "}\n"); 209 210 break; 211 } 212 case TSequenceOf: { 213 char *n; 214 215 fprintf (codefile, 216 "e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence," 217 "&reallen, &l);\n" 218 "FORW;\n" 219 "if(len < reallen)\n" 220 "return ASN1_OVERRUN;\n" 221 "len = reallen;\n"); 222 223 fprintf (codefile, 224 "{\n" 225 "size_t origlen = len;\n" 226 "int oldret = ret;\n" 227 "ret = 0;\n" 228 "(%s)->len = 0;\n" 229 "(%s)->val = NULL;\n" 230 "while(ret < origlen) {\n" 231 "(%s)->len++;\n" 232 "(%s)->val = realloc((%s)->val, sizeof(*((%s)->val)) * (%s)->len);\n", 233 name, name, name, name, name, name, name); 234 asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name); 235 decode_type (n, t->subtype); 236 fprintf (codefile, 237 "len = origlen - ret;\n" 238 "}\n" 239 "ret += oldret;\n" 240 "}\n"); 241 free (n); 242 break; 243 } 244 case TGeneralizedTime: 245 decode_primitive ("generalized_time", name); 246 break; 247 case TGeneralString: 248 decode_primitive ("general_string", name); 249 break; 250 case TApplication: 251 fprintf (codefile, 252 "e = der_match_tag_and_length (p, len, APPL, CONS, %d, " 253 "&reallen, &l);\n" 254 "FORW;\n" 255 "{\n" 256 "int dce_fix;\n" 257 "if((dce_fix = fix_dce(reallen, &len)) < 0)\n" 258 "return ASN1_BAD_FORMAT;\n", 259 t->application); 260 decode_type (name, t->subtype); 261 fprintf(codefile, 262 "if(dce_fix){\n" 263 "e = der_match_tag_and_length (p, len, " 264 "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" 265 "FORW;\n" 266 "}\n" 267 "}\n"); 268 269 break; 270 default : 271 abort (); 272 } 273 } 274 275 void 276 generate_type_decode (const Symbol *s) 277 { 278 fprintf (headerfile, 279 "int " 280 "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n", 281 s->gen_name, s->gen_name); 282 283 fprintf (codefile, "#define FORW " 284 "if(e) goto fail; " 285 "p += l; " 286 "len -= l; " 287 "ret += l\n\n"); 288 289 290 fprintf (codefile, "int\n" 291 "decode_%s(const unsigned char *p," 292 " size_t len, %s *data, size_t *size)\n" 293 "{\n", 294 s->gen_name, s->gen_name); 295 296 switch (s->type->type) { 297 case TInteger: 298 case TUInteger: 299 case TOctetString: 300 case TGeneralizedTime: 301 case TGeneralString: 302 case TBitString: 303 case TSequence: 304 case TSequenceOf: 305 case TApplication: 306 case TType: 307 fprintf (codefile, 308 "size_t ret = 0, reallen;\n" 309 "size_t l;\n" 310 "int i, e;\n\n"); 311 fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); 312 fprintf (codefile, "i = 0;\n"); /* hack to avoid `unused variable' */ 313 fprintf (codefile, "reallen = 0;\n"); /* hack to avoid `unused variable' */ 314 315 decode_type ("data", s->type); 316 fprintf (codefile, 317 "if(size) *size = ret;\n" 318 "return 0;\n"); 319 fprintf (codefile, 320 "fail:\n" 321 "free_%s(data);\n" 322 "return e;\n", 323 s->gen_name); 324 break; 325 default: 326 abort (); 327 } 328 fprintf (codefile, "}\n\n"); 329 } 330 331 void 332 generate_seq_type_decode (const Symbol *s) 333 { 334 fprintf (headerfile, 335 "int decode_seq_%s(const unsigned char *, size_t, int, int, " 336 "%s *, size_t *);\n", 337 s->gen_name, s->gen_name); 338 339 fprintf (codefile, "int\n" 340 "decode_seq_%s(const unsigned char *p, size_t len, int tag, " 341 "int optional, %s *data, size_t *size)\n" 342 "{\n", 343 s->gen_name, s->gen_name); 344 345 fprintf (codefile, 346 "size_t newlen, oldlen;\n" 347 "size_t l, ret = 0;\n" 348 "int e;\n" 349 "int dce_fix;\n"); 350 351 fprintf (codefile, 352 "e = der_match_tag(p, len, CONTEXT, CONS, tag, &l);\n" 353 "if (e)\n" 354 "return e;\n"); 355 fprintf (codefile, 356 "p += l;\n" 357 "len -= l;\n" 358 "ret += l;\n" 359 "e = der_get_length(p, len, &newlen, &l);\n" 360 "if (e)\n" 361 "return e;\n" 362 "p += l;\n" 363 "len -= l;\n" 364 "ret += l;\n" 365 "oldlen = len;\n" 366 "if ((dce_fix = fix_dce(newlen, &len)) < 0)\n" 367 "return ASN1_BAD_FORMAT;\n" 368 "e = decode_%s(p, len, data, &l);\n" 369 "if (e)\n" 370 "return e;\n" 371 "p += l;\n" 372 "len -= l;\n" 373 "ret += l;\n" 374 "if (dce_fix) {\n" 375 "size_t reallen;\n\n" 376 "e = der_match_tag_and_length(p, len, " 377 "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n" 378 "if (e)\n" 379 "return e;\n" 380 "ret += l;\n" 381 "}\n", 382 s->gen_name); 383 fprintf (codefile, 384 "if(size) *size = ret;\n" 385 "return 0;\n"); 386 387 fprintf (codefile, "}\n\n"); 388 } 389