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 1026 : 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 1042 : 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 1010 : }
58 :
59 : static void
60 717 : find_tag (const Type *t,
61 : Der_class *cl, Der_type *ty, unsigned *tag)
62 : {
63 722 : 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 627 : case TTag:
139 627 : *cl = t->tag.tagclass;
140 1805 : *ty = !(t->tag.tagclass != ASN1_C_UNIV &&
141 551 : t->tag.tagenv == TE_EXPLICIT) &&
142 1152 : is_primitive_type(t->subtype) ? PRIM : CONS;
143 627 : *tag = t->tag.tagvalue; /* XXX is this correct? */
144 627 : break;
145 95 : case TType:
146 95 : if ((t->symbol->stype == Stype && t->symbol->type == NULL)
147 95 : || t->symbol->stype == SUndefined) {
148 0 : lex_error_message("%s is imported or still undefined, "
149 : " can't generate tag checking data in CHOICE "
150 : "without this information",
151 0 : t->symbol->name);
152 0 : exit(1);
153 : }
154 95 : find_tag(t->symbol->type, cl, ty, tag);
155 95 : return;
156 0 : case TUTCTime:
157 0 : *cl = ASN1_C_UNIV;
158 0 : *ty = PRIM;
159 0 : *tag = UT_UTCTime;
160 0 : break;
161 0 : case TUTF8String:
162 0 : *cl = ASN1_C_UNIV;
163 0 : *ty = PRIM;
164 0 : *tag = UT_UTF8String;
165 0 : break;
166 0 : case TBMPString:
167 0 : *cl = ASN1_C_UNIV;
168 0 : *ty = PRIM;
169 0 : *tag = UT_BMPString;
170 0 : break;
171 0 : case TUniversalString:
172 0 : *cl = ASN1_C_UNIV;
173 0 : *ty = PRIM;
174 0 : *tag = UT_UniversalString;
175 0 : break;
176 0 : case TVisibleString:
177 0 : *cl = ASN1_C_UNIV;
178 0 : *ty = PRIM;
179 0 : *tag = UT_VisibleString;
180 0 : break;
181 0 : default:
182 0 : abort();
183 : }
184 : }
185 :
186 : static void
187 19 : range_check(const char *name,
188 : const char *length,
189 : const char *forwstr,
190 : struct range *r)
191 : {
192 19 : if (r->min == r->max + 2 || r->min < r->max)
193 19 : fprintf (codefile,
194 : "if ((%s)->%s > %lld) {\n"
195 : "e = ASN1_MAX_CONSTRAINT; %s;\n"
196 : "}\n",
197 18 : name, length, (long long)r->max, forwstr);
198 19 : if ((r->min - 1 == r->max || r->min < r->max) && r->min > 0)
199 19 : fprintf (codefile,
200 : "if ((%s)->%s < %lld) {\n"
201 : "e = ASN1_MIN_CONSTRAINT; %s;\n"
202 : "}\n",
203 18 : name, length, (long long)r->min, forwstr);
204 19 : if (r->max == r->min)
205 0 : fprintf (codefile,
206 : "if ((%s)->%s != %lld) {\n"
207 : "e = ASN1_EXACT_CONSTRAINT; %s;\n"
208 : "}\n",
209 0 : name, length, (long long)r->min, forwstr);
210 19 : }
211 :
212 : static int
213 7486 : decode_type(const char *name, const Type *t, int optional, struct value *defval,
214 : const char *forwstr, const char *tmpstr, const char *dertype,
215 : unsigned int depth)
216 : {
217 7486 : switch (t->type) {
218 1539 : case TType: {
219 1539 : if (optional)
220 57 : fprintf(codefile,
221 : "%s = calloc(1, sizeof(*%s));\n"
222 : "if (%s == NULL) %s;\n",
223 : name, name, name, forwstr);
224 1620 : fprintf (codefile,
225 : "e = decode_%s(p, len, %s, &l);\n",
226 1539 : t->symbol->gen_name, name);
227 1539 : if (optional) {
228 57 : fprintf (codefile,
229 : "if(e == ASN1_MISSING_FIELD) {\n"
230 : "free(%s);\n"
231 : "%s = NULL;\n"
232 : "} else if (e) { %s; \n"
233 : "} else {\n"
234 : "p += l; len -= l; ret += l;\n"
235 : "}\n",
236 : name, name, forwstr);
237 1482 : } else if (defval) {
238 0 : fprintf(codefile,
239 : "if (e == ASN1_MISSING_FIELD) {\n");
240 : /*
241 : * `name' starts with an ampersand here and is not an lvalue.
242 : * We skip the ampersand and then it is an lvalue.
243 : */
244 0 : gen_assign_defval(name + 1, defval);
245 0 : fprintf(codefile,
246 : "} else if (e) { %s;\n"
247 : "} else { p += l; len -= l; ret += l; }\n",
248 : forwstr);
249 : } else {
250 1482 : fprintf (codefile,
251 : "if(e) %s;\n",
252 : forwstr);
253 1482 : fprintf (codefile,
254 : "p += l; len -= l; ret += l;\n");
255 : }
256 1458 : break;
257 : }
258 418 : case TInteger:
259 418 : if(t->members) {
260 : /*
261 : * This will produce a worning, how its hard to fix since:
262 : * if its enum to an NameType, we can add appriate
263 : * type-cast. If its not though, we have to figure out if
264 : * there is negative enum enum and use appropriate
265 : * signness and size on the intertype we cast the result
266 : * too.
267 : */
268 38 : fprintf(codefile,
269 : "{\n"
270 : "int enumint;\n");
271 38 : decode_primitive ("integer", "&enumint", forwstr);
272 38 : fprintf(codefile,
273 : "*%s = enumint;\n"
274 : "}\n",
275 : name);
276 380 : } else if (t->range == NULL) {
277 76 : decode_primitive ("heim_integer", name, forwstr);
278 304 : } else if (t->range->min < 0 &&
279 56 : (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
280 19 : decode_primitive ("integer64", name, forwstr);
281 285 : } else if (t->range->min < 0) {
282 38 : decode_primitive ("integer", name, forwstr);
283 247 : } else if (t->range->max > UINT_MAX) {
284 0 : decode_primitive ("unsigned64", name, forwstr);
285 : } else {
286 247 : decode_primitive ("unsigned", name, forwstr);
287 : }
288 396 : break;
289 36 : case TBoolean:
290 38 : decode_primitive ("boolean", name, forwstr);
291 36 : break;
292 0 : case TEnumerated:
293 0 : decode_primitive ("enumerated", name, forwstr);
294 0 : break;
295 266 : case TOctetString:
296 266 : if (dertype) {
297 0 : fprintf(codefile,
298 : "if (%s == CONS) {\n",
299 : dertype);
300 0 : decode_primitive("octet_string_ber", name, forwstr);
301 0 : fprintf(codefile,
302 : "} else {\n");
303 : }
304 266 : decode_primitive ("octet_string", name, forwstr);
305 266 : if (dertype)
306 0 : fprintf(codefile, "}\n");
307 266 : if (t->range)
308 0 : range_check(name, "length", forwstr, t->range);
309 252 : break;
310 190 : case TBitString: {
311 10 : Member *m;
312 190 : int pos = 0;
313 :
314 190 : if (HEIM_TAILQ_EMPTY(t->members)) {
315 133 : decode_primitive ("bit_string", name, forwstr);
316 126 : break;
317 : }
318 57 : fprintf(codefile,
319 : "if (len < 1) return ASN1_OVERRUN;\n"
320 : "p++; len--; ret++;\n");
321 57 : fprintf(codefile,
322 : "do {\n"
323 : "if (len < 1) break;\n");
324 741 : HEIM_TAILQ_FOREACH(m, t->members, members) {
325 741 : while (m->val / 8 > pos / 8) {
326 57 : fprintf (codefile,
327 : "p++; len--; ret++;\n"
328 : "if (len < 1) break;\n");
329 57 : pos += 8;
330 : }
331 684 : fprintf(codefile,
332 : "(%s)->%s = (*p >> %d) & 1;\n",
333 684 : name, m->gen_name, (int)(7 - m->val % 8));
334 : }
335 57 : fprintf(codefile,
336 : "} while(0);\n");
337 57 : fprintf (codefile,
338 : "p += len; ret += len;\n");
339 54 : break;
340 : }
341 551 : case TSequence: {
342 29 : Member *m;
343 :
344 551 : if (t->members == NULL)
345 0 : break;
346 :
347 2470 : HEIM_TAILQ_FOREACH(m, t->members, members) {
348 1919 : char *s = NULL;
349 :
350 1919 : if (m->ellipsis)
351 95 : continue;
352 :
353 1920 : if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&",
354 1824 : name, m->gen_name) < 0 || s == NULL)
355 0 : errx(1, "malloc");
356 1824 : decode_type(s, m->type, m->optional, m->defval, forwstr,
357 1824 : m->gen_name, NULL, depth + 1);
358 1824 : free (s);
359 : }
360 :
361 522 : break;
362 : }
363 0 : case TSet: {
364 : /*
365 : * SET { ... } is the dumbest construct in ASN.1. It's semantically
366 : * indistinguishable from SEQUENCE { ... } but in BER you can write the
367 : * fields in any order you wish, and in DER you have to write them in
368 : * lexicographic order. If you want a reason to hate ASN.1, this is
369 : * certainly one, though the real reason to hate ASN.1 is BER/DER/CER,
370 : * and, really, all tag-length-value (TLV) encodings ever invented,
371 : * including Protocol Buffers. Fortunately not all ASN.1 encoding
372 : * rules are TLV or otherwise self-describing. "Self-describing"
373 : * encoding rules other than those meant to be [somewhat] readable by
374 : * humans, such as XML and JSON, are simply dumb. But SET { ... } is a
375 : * truly special sort of dumb. The only possible use of SET { ... }
376 : * might well be for ASN.1 mappings of XML schemas(?).
377 : */
378 0 : Member *m;
379 0 : unsigned int memno;
380 :
381 0 : if(t->members == NULL)
382 0 : break;
383 :
384 0 : fprintf(codefile, "{\n");
385 0 : fprintf(codefile, "uint64_t members = 0;\n");
386 0 : fprintf(codefile, "while(len > 0) {\n");
387 0 : fprintf(codefile,
388 : "Der_class class;\n"
389 : "Der_type type;\n"
390 : "unsigned int tag;\n"
391 : "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n"
392 : "if(e) %s;\n", forwstr);
393 0 : fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n");
394 0 : memno = 0;
395 0 : HEIM_TAILQ_FOREACH(m, t->members, members) {
396 0 : Type *mst = m->type; /* Member sub-type */
397 0 : char *s;
398 :
399 0 : while (mst->type == TType) {
400 0 : assert(mst->subtype || (mst->symbol && mst->symbol->type));
401 0 : mst = mst->subtype ? mst->subtype : mst->symbol->type;
402 : }
403 0 : assert(mst->type == TTag);
404 :
405 0 : fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n",
406 0 : classname(mst->tag.tagclass),
407 0 : (mst->tag.tagclass == ASN1_C_UNIV || mst->tag.tagenv == TE_IMPLICIT) &&
408 0 : is_primitive_type(mst->subtype) ? "PRIM" : "CONS",
409 0 : valuename(mst->tag.tagclass, mst->tag.tagvalue));
410 :
411 0 : if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL)
412 0 : errx(1, "malloc");
413 0 : if(m->optional)
414 0 : fprintf(codefile,
415 : "%s = calloc(1, sizeof(*%s));\n"
416 : "if (%s == NULL) { e = ENOMEM; %s; }\n",
417 : s, s, s, forwstr);
418 0 : decode_type (s, mst, 0, NULL, forwstr, m->gen_name, NULL, depth + 1);
419 0 : free (s);
420 :
421 0 : fprintf(codefile, "members |= (1ULL << %u);\n", memno);
422 0 : memno++;
423 0 : fprintf(codefile, "break;\n");
424 : }
425 0 : fprintf(codefile,
426 : "default:\n"
427 : "return ASN1_MISPLACED_FIELD;\n"
428 : "break;\n");
429 0 : fprintf(codefile, "}\n");
430 0 : fprintf(codefile, "}\n");
431 0 : memno = 0;
432 0 : HEIM_TAILQ_FOREACH(m, t->members, members) {
433 0 : char *s;
434 :
435 0 : if (asprintf (&s, "%s->%s", name, m->gen_name) < 0 || s == NULL)
436 0 : errx(1, "malloc");
437 0 : fprintf(codefile, "if((members & (1ULL << %u)) == 0)\n", memno);
438 0 : if(m->optional)
439 0 : fprintf(codefile, "%s = NULL;\n", s);
440 0 : else if(m->defval)
441 0 : gen_assign_defval(s, m->defval);
442 : else
443 0 : fprintf(codefile, "return ASN1_MISSING_FIELD;\n");
444 0 : free(s);
445 0 : memno++;
446 : }
447 0 : fprintf(codefile, "}\n");
448 0 : break;
449 : }
450 304 : case TSetOf:
451 : case TSequenceOf: {
452 304 : char *n = NULL;
453 304 : char *sname = NULL;
454 :
455 304 : fprintf (codefile,
456 : "{\n"
457 : "size_t %s_origlen = len;\n"
458 : "size_t %s_oldret = ret;\n"
459 : "size_t %s_olen = 0;\n"
460 : "void *%s_tmp;\n"
461 : "ret = 0;\n"
462 : "(%s)->len = 0;\n"
463 : "(%s)->val = NULL;\n",
464 : tmpstr,
465 : tmpstr,
466 : tmpstr,
467 : tmpstr,
468 : name,
469 : name);
470 :
471 304 : fprintf (codefile,
472 : "while(ret < %s_origlen) {\n"
473 : "size_t %s_nlen = %s_olen + sizeof(*((%s)->val));\n"
474 : "if (%s_olen > %s_nlen) { e = ASN1_OVERFLOW; %s; }\n"
475 : "%s_olen = %s_nlen;\n"
476 : "%s_tmp = realloc((%s)->val, %s_olen);\n"
477 : "if (%s_tmp == NULL) { e = ENOMEM; %s; }\n"
478 : "(%s)->val = %s_tmp;\n",
479 : tmpstr,
480 : tmpstr, tmpstr, name,
481 : tmpstr, tmpstr, forwstr,
482 : tmpstr, tmpstr,
483 : tmpstr, name, tmpstr,
484 : tmpstr, forwstr,
485 : name, tmpstr);
486 :
487 304 : if (asprintf (&n, "&(%s)->val[(%s)->len]", name, name) < 0 || n == NULL)
488 0 : errx(1, "malloc");
489 304 : if (asprintf (&sname, "%s_s_of", tmpstr) < 0 || sname == NULL)
490 0 : errx(1, "malloc");
491 304 : decode_type(n, t->subtype, 0, NULL, forwstr, sname, NULL, depth + 1);
492 304 : fprintf (codefile,
493 : "(%s)->len++;\n"
494 : "len = %s_origlen - ret;\n"
495 : "}\n"
496 : "ret += %s_oldret;\n"
497 : "}\n",
498 : name,
499 : tmpstr, tmpstr);
500 304 : if (t->range)
501 19 : range_check(name, "len", forwstr, t->range);
502 304 : free (n);
503 304 : free (sname);
504 304 : break;
505 : }
506 0 : case TGeneralizedTime:
507 0 : decode_primitive ("generalized_time", name, forwstr);
508 0 : break;
509 18 : case TGeneralString:
510 19 : decode_primitive ("general_string", name, forwstr);
511 18 : break;
512 0 : case TTeletexString:
513 0 : decode_primitive ("general_string", name, forwstr);
514 0 : break;
515 3819 : case TTag:{
516 3819 : char *tname = NULL, *typestring = NULL;
517 3819 : char *ide = NULL;
518 3819 : int replace_tag = 0;
519 9595 : int prim = !(t->tag.tagclass != ASN1_C_UNIV &&
520 5852 : t->tag.tagenv == TE_EXPLICIT) &&
521 2033 : is_primitive_type(t->subtype);
522 :
523 : /*
524 : * XXX See the comments in gen_encode() about this.
525 : */
526 3819 : if (t->tag.tagenv == TE_IMPLICIT && !prim &&
527 114 : t->subtype->type != TSequenceOf && t->subtype->type != TSetOf &&
528 90 : t->subtype->type != TChoice) {
529 95 : if (t->subtype->symbol &&
530 57 : (t->subtype->type == TSequence ||
531 54 : t->subtype->type == TSet))
532 0 : replace_tag = 1;
533 95 : else if (t->subtype->symbol &&
534 57 : strcmp(t->subtype->symbol->name, "HEIM_ANY") != 0)
535 57 : replace_tag = 1;
536 3724 : } else if (t->tag.tagenv == TE_IMPLICIT && prim && t->subtype->symbol)
537 19 : replace_tag = is_tagged_type(t->subtype->symbol->type);
538 :
539 3819 : if (asprintf(&typestring, "%s_type", tmpstr) < 0 || typestring == NULL)
540 0 : errx(1, "malloc");
541 :
542 3819 : fprintf(codefile,
543 : "{\n"
544 : "size_t %s_datalen;\n"
545 : "Der_type %s;\n",
546 : tmpstr, typestring);
547 3819 : if (replace_tag)
548 76 : fprintf(codefile,
549 : "const unsigned char *psave%u = p;\n"
550 : "unsigned char *pcopy%u;\n"
551 : "size_t lensave%u, lsave%u;\n",
552 : depth, depth, depth, depth);
553 3743 : else if (support_ber)
554 0 : fprintf(codefile,
555 : "int is_indefinite%u;\n", depth);
556 3819 : if (!replace_tag)
557 3743 : fprintf(codefile,
558 : "size_t %s_oldlen;\n", tmpstr);
559 :
560 3819 : fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, &%s, %s, "
561 : "&%s_datalen, &l);\n",
562 3819 : classname(t->tag.tagclass),
563 : typestring,
564 3819 : valuename(t->tag.tagclass, t->tag.tagvalue),
565 : tmpstr);
566 :
567 : /* XXX hardcode for now */
568 3819 : if (!replace_tag && support_ber && t->subtype->type == TOctetString) {
569 0 : ide = typestring;
570 : } else {
571 3961 : fprintf(codefile,
572 : "if (e == 0 && %s != %s) { e = ASN1_BAD_ID; }\n",
573 : typestring,
574 : prim ? "PRIM" : "CONS");
575 : }
576 :
577 3819 : if(optional) {
578 893 : fprintf(codefile,
579 : "if(e) {\n"
580 : "%s = NULL;\n"
581 : "} else {\n"
582 : "%s = calloc(1, sizeof(*%s));\n"
583 : "if (%s == NULL) { e = ENOMEM; %s; }\n",
584 : name, name, name, name, forwstr);
585 2926 : } else if (defval) {
586 0 : char *s;
587 :
588 0 : if (asprintf(&s, "*(%s)", name) == -1 || s == NULL)
589 0 : return ENOMEM;
590 0 : fprintf(codefile, "if (e && e != ASN1_MISSING_FIELD) %s;\n", forwstr);
591 0 : fprintf(codefile, "if (e == ASN1_MISSING_FIELD) {\n");
592 0 : gen_assign_defval(s, defval);
593 0 : free(s);
594 0 : fprintf(codefile, "e = 0; l= 0;\n} else {\n");
595 : } else {
596 2926 : fprintf(codefile, "if (e) %s;\n", forwstr);
597 : }
598 :
599 3819 : if (replace_tag)
600 76 : fprintf(codefile,
601 : "lsave%u = %s_datalen + l;\n"
602 : "lensave%u = len;\n"
603 : "e = der_replace_tag(p, len, &pcopy%u, &len, asn1_tag_class_%s, %s, asn1_tag_tag_%s);\n"
604 : "if (e) %s;\n"
605 : "p = pcopy%u;\n",
606 72 : depth, tmpstr, depth, depth, t->subtype->symbol->gen_name,
607 : prim ? "PRIM" : "CONS",
608 76 : t->subtype->symbol->gen_name,
609 : forwstr, depth);
610 : else
611 3743 : fprintf(codefile,
612 : "p += l; len -= l; ret += l;\n");
613 3819 : if (!replace_tag)
614 3743 : fprintf(codefile,
615 : "%s_oldlen = len;\n",
616 : tmpstr);
617 3819 : if (support_ber && !replace_tag)
618 0 : fprintf (codefile,
619 : "if((is_indefinite%u = _heim_fix_dce(%s_datalen, &len)) < 0)\n"
620 : "{ e = ASN1_BAD_FORMAT; %s; }\n"
621 : "if (is_indefinite%u) { if (len < 2) { e = ASN1_OVERRUN; %s; } len -= 2; }",
622 : depth, tmpstr, forwstr, depth, forwstr);
623 3819 : else if (!replace_tag)
624 3743 : fprintf(codefile,
625 : "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n"
626 : "len = %s_datalen;\n", tmpstr, forwstr, tmpstr);
627 3819 : if (asprintf (&tname, "%s_Tag", tmpstr) < 0 || tname == NULL)
628 0 : errx(1, "malloc");
629 : /*
630 : * If `replace_tag' then here `p' and `len' will be the copy mutated by
631 : * der_replace_tag().
632 : */
633 3819 : decode_type(name, t->subtype, 0, NULL, forwstr, tname, ide, depth + 1);
634 3819 : if (replace_tag)
635 76 : fprintf(codefile,
636 : "p = psave%u + lsave%u;\n"
637 : "len = lensave%u - lsave%u;\n"
638 : "ret += lsave%u - l;\n"
639 : "free(pcopy%u);\n",
640 : depth, depth, depth, depth, depth, depth);
641 3743 : else if(support_ber)
642 0 : fprintf(codefile,
643 : "if(is_indefinite%u){\n"
644 : "len += 2;\n"
645 : "e = der_match_tag_and_length(p, len, "
646 : "(Der_class)0, &%s, UT_EndOfContent, "
647 : "&%s_datalen, &l);\n"
648 : "if(e) %s;\n"
649 : "p += l; len -= l; ret += l;\n"
650 : "if (%s != (Der_type)0) { e = ASN1_BAD_ID; %s; }\n"
651 : "} else \n",
652 : depth,
653 : typestring,
654 : tmpstr,
655 : forwstr,
656 : typestring, forwstr);
657 3819 : if (!replace_tag)
658 3743 : fprintf(codefile,
659 : "len = %s_oldlen - %s_datalen;\n",
660 : tmpstr, tmpstr);
661 3819 : if (optional)
662 893 : fprintf(codefile, "}\n");
663 2926 : else if (defval)
664 0 : fprintf(codefile, "}\n");
665 3819 : fprintf(codefile, "}\n");
666 3819 : free(tname);
667 3819 : free(typestring);
668 3819 : break;
669 : }
670 171 : case TChoice: {
671 171 : Member *m, *have_ellipsis = NULL;
672 171 : const char *els = "";
673 :
674 171 : if (t->members == NULL)
675 0 : break;
676 :
677 817 : HEIM_TAILQ_FOREACH(m, t->members, members) {
678 646 : const Type *tt = m->type;
679 646 : char *s = NULL;
680 34 : Der_class cl;
681 34 : Der_type ty;
682 34 : unsigned tag;
683 :
684 646 : if (m->ellipsis) {
685 19 : have_ellipsis = m;
686 19 : continue;
687 : }
688 :
689 627 : find_tag(tt, &cl, &ty, &tag);
690 :
691 1254 : fprintf(codefile,
692 : "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n",
693 : els,
694 : classname(cl),
695 627 : ty ? "CONS" : "PRIM",
696 : valuename(cl, tag));
697 627 : fprintf(codefile,
698 : "(%s)->element = %s;\n",
699 : name, m->label);
700 660 : if (asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&",
701 627 : name, m->gen_name) < 0 || s == NULL)
702 0 : errx(1, "malloc");
703 627 : decode_type(s, m->type, m->optional, NULL, forwstr, m->gen_name,
704 : NULL, depth + 1);
705 627 : free(s);
706 627 : fprintf(codefile,
707 : "}\n");
708 627 : els = "else ";
709 : }
710 171 : if (have_ellipsis) {
711 19 : fprintf(codefile,
712 : "else {\n"
713 : "(%s)->element = %s;\n"
714 : "(%s)->u.%s.data = calloc(1, len);\n"
715 : "if ((%s)->u.%s.data == NULL) {\n"
716 : "e = ENOMEM; %s;\n"
717 : "}\n"
718 : "(%s)->u.%s.length = len;\n"
719 : "memcpy((%s)->u.%s.data, p, len);\n"
720 : "p += len;\n"
721 : "ret += len;\n"
722 : "len = 0;\n"
723 : "}\n",
724 : name, have_ellipsis->label,
725 : name, have_ellipsis->gen_name,
726 : name, have_ellipsis->gen_name,
727 : forwstr,
728 : name, have_ellipsis->gen_name,
729 : name, have_ellipsis->gen_name);
730 : } else {
731 152 : fprintf(codefile,
732 : "else {\n"
733 : "e = ASN1_PARSE_ERROR;\n"
734 : "%s;\n"
735 : "}\n",
736 : forwstr);
737 : }
738 162 : break;
739 : }
740 0 : case TUTCTime:
741 0 : decode_primitive ("utctime", name, forwstr);
742 0 : break;
743 72 : case TUTF8String:
744 76 : decode_primitive ("utf8string", name, forwstr);
745 72 : break;
746 0 : case TPrintableString:
747 0 : decode_primitive ("printable_string", name, forwstr);
748 0 : break;
749 0 : case TIA5String:
750 0 : decode_primitive ("ia5_string", name, forwstr);
751 0 : break;
752 0 : case TBMPString:
753 0 : decode_primitive ("bmp_string", name, forwstr);
754 0 : break;
755 0 : case TUniversalString:
756 0 : decode_primitive ("universal_string", name, forwstr);
757 0 : break;
758 0 : case TVisibleString:
759 0 : decode_primitive ("visible_string", name, forwstr);
760 0 : break;
761 19 : case TNull:
762 19 : fprintf (codefile, "/* NULL */\n");
763 18 : break;
764 72 : case TOID:
765 76 : decode_primitive ("oid", name, forwstr);
766 72 : break;
767 0 : default :
768 0 : abort ();
769 : }
770 7092 : return 0;
771 : }
772 :
773 : void
774 912 : generate_type_decode (const Symbol *s)
775 : {
776 912 : int preserve = preserve_type(s->name) ? TRUE : FALSE;
777 :
778 960 : fprintf (codefile, "int ASN1CALL\n"
779 : "decode_%s(const unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE,"
780 : " size_t len HEIMDAL_UNUSED_ATTRIBUTE, %s *data, size_t *size)\n"
781 : "{\n",
782 912 : s->gen_name, s->gen_name);
783 :
784 912 : switch (s->type->type) {
785 912 : case TInteger:
786 : case TBoolean:
787 : case TOctetString:
788 : case TOID:
789 : case TGeneralizedTime:
790 : case TGeneralString:
791 : case TTeletexString:
792 : case TUTF8String:
793 : case TPrintableString:
794 : case TIA5String:
795 : case TBMPString:
796 : case TUniversalString:
797 : case TVisibleString:
798 : case TUTCTime:
799 : case TNull:
800 : case TEnumerated:
801 : case TBitString:
802 : case TSequence:
803 : case TSequenceOf:
804 : case TSet:
805 : case TSetOf:
806 : case TTag:
807 : case TType:
808 : case TChoice:
809 912 : fprintf (codefile,
810 : "size_t ret = 0;\n"
811 : "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n"
812 : "int e HEIMDAL_UNUSED_ATTRIBUTE;\n");
813 912 : if (preserve)
814 0 : fprintf (codefile, "const unsigned char *begin = p;\n");
815 :
816 912 : fprintf (codefile, "\n");
817 912 : fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */
818 :
819 912 : decode_type("data", s->type, 0, NULL, "goto fail", "Top", NULL, 1);
820 912 : if (preserve)
821 0 : fprintf (codefile,
822 : "data->_save.data = calloc(1, ret);\n"
823 : "if (data->_save.data == NULL) { \n"
824 : "e = ENOMEM; goto fail; \n"
825 : "}\n"
826 : "data->_save.length = ret;\n"
827 : "memcpy(data->_save.data, begin, ret);\n");
828 912 : fprintf (codefile,
829 : "if(size) *size = ret;\n"
830 : "return 0;\n");
831 960 : fprintf (codefile,
832 : "fail:\n"
833 : "free_%s(data);\n"
834 : "return e;\n",
835 912 : s->gen_name);
836 912 : break;
837 0 : default:
838 0 : abort ();
839 : }
840 912 : fprintf (codefile, "}\n\n");
841 912 : }
|