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