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