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 :
36 : /* XXX same as der_length_tag */
37 : static size_t
38 304 : length_tag(unsigned int tag)
39 : {
40 304 : size_t len = 0;
41 :
42 304 : if(tag <= 30)
43 288 : return 1;
44 0 : while(tag) {
45 0 : tag /= 128;
46 0 : len++;
47 : }
48 0 : return len + 1;
49 : }
50 :
51 : static void
52 1026 : encode_primitive (const char *typename, const char *name)
53 : {
54 1028 : fprintf (codefile,
55 : "e = der_put_%s(p, len, %s, &l);\n"
56 : "if (e) return e;\np -= l; len -= l; ret += l;\n\n",
57 : typename,
58 : name);
59 992 : }
60 :
61 : const char *
62 29849 : classname(Der_class class)
63 : {
64 29849 : const char *cn[] = { "ASN1_C_UNIV", "ASN1_C_APPL",
65 : "ASN1_C_CONTEXT", "ASN1_C_PRIV" };
66 29849 : if ((int)class >= sizeof(cn) / sizeof(cn[0]))
67 0 : return "???";
68 29849 : return cn[class];
69 : }
70 :
71 :
72 : const char *
73 29773 : valuename(Der_class class, int value)
74 : {
75 1567 : static char s[32];
76 1567 : struct {
77 : int value;
78 : const char *s;
79 29773 : } *p, values[] = {
80 : #define X(Y) { Y, #Y }
81 : X(UT_BMPString),
82 : X(UT_BitString),
83 : X(UT_Boolean),
84 : X(UT_EmbeddedPDV),
85 : X(UT_Enumerated),
86 : X(UT_External),
87 : X(UT_GeneralString),
88 : X(UT_GeneralizedTime),
89 : X(UT_GraphicString),
90 : X(UT_IA5String),
91 : X(UT_Integer),
92 : X(UT_Null),
93 : X(UT_NumericString),
94 : X(UT_OID),
95 : X(UT_ObjectDescriptor),
96 : X(UT_OctetString),
97 : X(UT_PrintableString),
98 : X(UT_Real),
99 : X(UT_RelativeOID),
100 : X(UT_Sequence),
101 : X(UT_Set),
102 : X(UT_TeletexString),
103 : X(UT_UTCTime),
104 : X(UT_UTF8String),
105 : X(UT_UniversalString),
106 : X(UT_VideotexString),
107 : X(UT_VisibleString),
108 : #undef X
109 : { -1, NULL }
110 : };
111 29773 : if(class == ASN1_C_UNIV) {
112 250059 : for(p = values; p->value != -1; p++)
113 250059 : if(p->value == value)
114 15732 : return p->s;
115 : }
116 14041 : snprintf(s, sizeof(s), "%d", value);
117 14041 : return s;
118 : }
119 :
120 : static int
121 7486 : encode_type (const char *name, const Type *t, const char *tmpstr)
122 : {
123 7486 : int constructed = 1;
124 :
125 7486 : switch (t->type) {
126 1539 : case TType:
127 : #if 0
128 : encode_type (name, t->symbol->type);
129 : #endif
130 1620 : fprintf (codefile,
131 : "e = encode_%s(p, len, %s, &l);\n"
132 : "if (e) return e;\np -= l; len -= l; ret += l;\n\n",
133 1539 : t->symbol->gen_name, name);
134 1539 : constructed = !is_primitive_type(t);
135 1539 : break;
136 418 : case TInteger:
137 418 : if(t->members) {
138 38 : fprintf(codefile,
139 : "{\n"
140 : "int enumint = (int)*%s;\n",
141 : name);
142 38 : encode_primitive("integer", "&enumint");
143 38 : fprintf(codefile, "}\n;");
144 380 : } else if (t->range == NULL) {
145 76 : encode_primitive("heim_integer", name);
146 304 : } else if (t->range->min < 0 &&
147 56 : (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
148 19 : encode_primitive("integer64", name);
149 285 : } else if (t->range->min < 0) {
150 38 : encode_primitive("integer", name);
151 247 : } else if (t->range->max > UINT_MAX) {
152 0 : encode_primitive("unsigned64", name);
153 : } else {
154 247 : encode_primitive("unsigned", name);
155 : }
156 :
157 396 : constructed = 0;
158 396 : break;
159 36 : case TBoolean:
160 38 : encode_primitive ("boolean", name);
161 38 : constructed = 0;
162 38 : break;
163 252 : case TOctetString:
164 266 : encode_primitive ("octet_string", name);
165 266 : constructed = 0;
166 266 : break;
167 190 : case TBitString: {
168 10 : Member *m;
169 10 : int pos;
170 :
171 190 : if (HEIM_TAILQ_EMPTY(t->members)) {
172 133 : encode_primitive("bit_string", name);
173 133 : constructed = 0;
174 133 : break;
175 : }
176 :
177 57 : fprintf (codefile, "{\n"
178 : "unsigned char c = 0;\n");
179 57 : if (!rfc1510_bitstring)
180 57 : fprintf (codefile,
181 : "int rest = 0;\n"
182 : "int bit_set = 0;\n");
183 : #if 0
184 : pos = t->members->prev->val;
185 : /* fix for buggy MIT (and OSF?) code */
186 : if (pos > 31)
187 : abort ();
188 : #endif
189 : /*
190 : * It seems that if we do not always set pos to 31 here, the MIT
191 : * code will do the wrong thing.
192 : *
193 : * I hate ASN.1 (and DER), but I hate it even more when everybody
194 : * has to screw it up differently.
195 : */
196 57 : pos = HEIM_TAILQ_LAST(t->members, memhead)->val;
197 57 : if (rfc1510_bitstring) {
198 0 : if (pos < 31)
199 0 : pos = 31;
200 : }
201 :
202 741 : HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
203 741 : while (m->val / 8 < pos / 8) {
204 57 : if (!rfc1510_bitstring)
205 57 : fprintf (codefile,
206 : "if (c != 0 || bit_set) {\n");
207 57 : fprintf (codefile,
208 : "if (len < 1) return ASN1_OVERFLOW;\n"
209 : "*p-- = c; len--; ret++;\n");
210 57 : if (!rfc1510_bitstring)
211 57 : fprintf (codefile,
212 : "if (!bit_set) {\n"
213 : "rest = 0;\n"
214 : "while(c) { \n"
215 : "if (c & 1) break;\n"
216 : "c = c >> 1;\n"
217 : "rest++;\n"
218 : "}\n"
219 : "bit_set = 1;\n"
220 : "}\n"
221 : "}\n");
222 57 : fprintf (codefile,
223 : "c = 0;\n");
224 57 : pos -= 8;
225 : }
226 720 : fprintf (codefile,
227 : "if((%s)->%s) {\n"
228 : "c |= 1<<%d;\n",
229 684 : name, m->gen_name, (int)(7 - m->val % 8));
230 684 : fprintf (codefile,
231 : "}\n");
232 : }
233 :
234 57 : if (!rfc1510_bitstring)
235 57 : fprintf (codefile,
236 : "if (c != 0 || bit_set) {\n");
237 57 : fprintf (codefile,
238 : "if (len < 1) return ASN1_OVERFLOW;\n"
239 : "*p-- = c; len--; ret++;\n");
240 57 : if (!rfc1510_bitstring)
241 57 : fprintf (codefile,
242 : "if (!bit_set) {\n"
243 : "rest = 0;\n"
244 : "if(c) { \n"
245 : "while(c) { \n"
246 : "if (c & 1) break;\n"
247 : "c = c >> 1;\n"
248 : "rest++;\n"
249 : "}\n"
250 : "}\n"
251 : "}\n"
252 : "}\n");
253 :
254 57 : fprintf (codefile,
255 : "if (len < 1) return ASN1_OVERFLOW;\n"
256 : "*p-- = %s;\n"
257 : "len -= 1;\n"
258 : "ret += 1;\n"
259 : "}\n\n",
260 57 : rfc1510_bitstring ? "0" : "rest");
261 57 : constructed = 0;
262 57 : break;
263 : }
264 0 : case TEnumerated : {
265 0 : encode_primitive ("enumerated", name);
266 0 : constructed = 0;
267 0 : break;
268 : }
269 :
270 551 : case TSet:
271 : case TSequence: {
272 29 : Member *m;
273 :
274 551 : if (t->members == NULL)
275 0 : break;
276 :
277 2470 : HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
278 1919 : char *s = NULL;
279 :
280 1919 : if (m->ellipsis)
281 95 : continue;
282 :
283 1920 : if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL)
284 0 : errx(1, "malloc");
285 1824 : fprintf(codefile, "/* %s */\n", m->name);
286 1824 : if (m->optional)
287 950 : fprintf (codefile,
288 : "if(%s) ",
289 : s);
290 874 : else if(m->defval)
291 0 : gen_compare_defval(s + 1, m->defval);
292 1824 : fprintf (codefile, "{\n");
293 1824 : fprintf (codefile, "size_t %s_oldret HEIMDAL_UNUSED_ATTRIBUTE = ret;\n", tmpstr);
294 1824 : fprintf (codefile, "ret = 0;\n");
295 1824 : encode_type (s, m->type, m->gen_name);
296 1824 : fprintf (codefile, "ret += %s_oldret;\n", tmpstr);
297 1824 : fprintf (codefile, "}\n");
298 1824 : free (s);
299 : }
300 522 : break;
301 : }
302 0 : case TSetOf: {
303 :
304 0 : fprintf(codefile,
305 : "{\n"
306 : "heim_octet_string *val;\n"
307 : "size_t elen = 0, totallen = 0;\n"
308 : "int eret = 0;\n");
309 :
310 0 : fprintf(codefile,
311 : "if ((%s)->len > UINT_MAX/sizeof(val[0]))\n"
312 : "return ERANGE;\n",
313 : name);
314 :
315 0 : fprintf(codefile,
316 : "val = calloc(1, sizeof(val[0]) * (%s)->len);\n"
317 : "if (val == NULL && (%s)->len != 0) return ENOMEM;\n",
318 : name, name);
319 :
320 0 : fprintf(codefile,
321 : "for(i = 0; i < (int)(%s)->len; i++) {\n",
322 : name);
323 :
324 0 : fprintf(codefile,
325 : "ASN1_MALLOC_ENCODE(%s, val[i].data, "
326 : "val[i].length, &(%s)->val[i], &elen, eret);\n",
327 0 : t->subtype->symbol->gen_name,
328 : name);
329 :
330 0 : fprintf(codefile,
331 : "if(eret) {\n"
332 : "i--;\n"
333 : "while (i >= 0) {\n"
334 : "free(val[i].data);\n"
335 : "i--;\n"
336 : "}\n"
337 : "free(val);\n"
338 : "return eret;\n"
339 : "}\n"
340 : "totallen += elen;\n"
341 : "}\n");
342 :
343 0 : fprintf(codefile,
344 : "if (totallen > len) {\n"
345 : "for (i = 0; i < (int)(%s)->len; i++) {\n"
346 : "free(val[i].data);\n"
347 : "}\n"
348 : "free(val);\n"
349 : "return ASN1_OVERFLOW;\n"
350 : "}\n",
351 : name);
352 :
353 0 : fprintf(codefile,
354 : "qsort(val, (%s)->len, sizeof(val[0]), _heim_der_set_sort);\n",
355 : name);
356 :
357 0 : fprintf (codefile,
358 : "for(i = (int)(%s)->len - 1; i >= 0; --i) {\n"
359 : "p -= val[i].length;\n"
360 : "ret += val[i].length;\n"
361 : "memcpy(p + 1, val[i].data, val[i].length);\n"
362 : "free(val[i].data);\n"
363 : "}\n"
364 : "free(val);\n"
365 : "}\n",
366 : name);
367 0 : break;
368 : }
369 304 : case TSequenceOf: {
370 304 : char *sname = NULL;
371 304 : char *n = NULL;
372 :
373 304 : fprintf (codefile,
374 : "for(i = (int)(%s)->len - 1; i >= 0; --i) {\n"
375 : "size_t %s_for_oldret = ret;\n"
376 : "ret = 0;\n",
377 : name, tmpstr);
378 304 : if (asprintf (&n, "&(%s)->val[i]", name) < 0 || n == NULL)
379 0 : errx(1, "malloc");
380 304 : if (asprintf (&sname, "%s_S_Of", tmpstr) < 0 || sname == NULL)
381 0 : errx(1, "malloc");
382 304 : encode_type (n, t->subtype, sname);
383 304 : fprintf (codefile,
384 : "ret += %s_for_oldret;\n"
385 : "}\n",
386 : tmpstr);
387 304 : free (n);
388 304 : free (sname);
389 304 : break;
390 : }
391 0 : case TGeneralizedTime:
392 0 : encode_primitive ("generalized_time", name);
393 0 : constructed = 0;
394 0 : break;
395 18 : case TGeneralString:
396 19 : encode_primitive ("general_string", name);
397 19 : constructed = 0;
398 19 : break;
399 0 : case TTeletexString:
400 0 : encode_primitive ("general_string", name);
401 0 : constructed = 0;
402 0 : break;
403 3819 : case TTag: {
404 3819 : char *tname = NULL;
405 3819 : int replace_tag = 0;
406 9595 : int prim = !(t->tag.tagclass != ASN1_C_UNIV &&
407 5852 : t->tag.tagenv == TE_EXPLICIT) &&
408 2033 : is_primitive_type(t->subtype);
409 201 : int c;
410 3819 : if (asprintf (&tname, "%s_tag", tmpstr) < 0 || tname == NULL)
411 0 : errx(1, "malloc");
412 : /*
413 : * HACK HACK HACK
414 : *
415 : * This is part of the fix to the bug where we treated IMPLICIT tags of
416 : * named types as EXPLICIT. I.e.
417 : *
418 : * Foo ::= SEQUENCE { ... }
419 : * Bar ::= SEQUENCE { foo [0] IMPLICIT Foo }
420 : *
421 : * would get a context [0] constructed tag *and* a universal sequence
422 : * constructed tag when it should get only the first tag.
423 : *
424 : * Properly fixing this would require changing the signatures of the
425 : * encode, length, and decode functions we generate to take an optional
426 : * tag to replace the one the encoder would generate / decoder would
427 : * expect. That would change the ABI, which... isn't stable, but it's
428 : * a bit soon to make that change.
429 : *
430 : * So, we're looking for IMPLICIT, and if we see any, we generate code
431 : * to replace the tag.
432 : *
433 : * On the decode side we need to know what tag to restore. For this we
434 : * generate enums in the generated header.
435 : *
436 : * NOTE: We *do* "replace" the tags of IMPLICIT-tagged primitive types,
437 : * but our primitive codec functions leave those tags out, which
438 : * is why we don't have to der_replace_tag() them here.
439 : */
440 : /*
441 : * If the tag is IMPLICIT and it's not primitive and the subtype is not
442 : * any kind of structure...
443 : */
444 3819 : if (t->tag.tagenv == TE_IMPLICIT && !prim &&
445 114 : t->subtype->type != TSequenceOf && t->subtype->type != TSetOf &&
446 90 : t->subtype->type != TChoice) {
447 : /* If it is a named type for a structured thing */
448 95 : if (t->subtype->symbol &&
449 57 : (t->subtype->type == TSequence ||
450 54 : t->subtype->type == TSet))
451 0 : replace_tag = 1;
452 95 : else if (t->subtype->symbol && strcmp(t->subtype->symbol->name, "heim_any"))
453 54 : replace_tag = 1;
454 3724 : } else if (t->tag.tagenv == TE_IMPLICIT && prim && t->subtype->symbol)
455 : /*
456 : * Because the subtype is named we are generating its codec
457 : * functions, and those will be adding their UNIVERSAL or whatever
458 : * tags unlike our raw primtive codec library.
459 : */
460 19 : replace_tag = is_tagged_type(t->subtype->symbol->type);
461 :
462 3619 : if (replace_tag)
463 277 : fprintf(codefile,
464 : "{ unsigned char *psave_%s = p, *pfree_%s = NULL;\n"
465 : "size_t l2_%s, lensave_%s = len;\n"
466 : "len = length_%s(%s);\n"
467 : /* Allocate a temp buffer for the encoder */
468 : "if ((p = pfree_%s = calloc(1, len)) == NULL) return ENOMEM;\n"
469 : /* Make p point to the last byte of the allocated buf */
470 : "p += len - 1;\n",
471 : tmpstr, tmpstr, tmpstr, tmpstr,
472 76 : t->subtype->symbol->gen_name, name, tmpstr);
473 :
474 : /* XXX Currently we generate code that leaks `pfree_%s` here. */
475 3819 : c = encode_type (name, t->subtype, tname);
476 : /* Explicit non-UNIVERSAL tags are always constructed */
477 3819 : if (!c && t->tag.tagclass != ASN1_C_UNIV && t->tag.tagenv == TE_EXPLICIT)
478 874 : c = 1;
479 3819 : if (replace_tag)
480 76 : fprintf(codefile,
481 : "if (len) { free(pfree_%s); return EINVAL; }\n"
482 : /*
483 : * Here we have `p' pointing to one byte before the buffer
484 : * we allocated above.
485 : *
486 : * [ T_wrong | LL | VVVV ] // temp buffer
487 : * ^ ^
488 : * | |
489 : * | \
490 : * \ +-- p + 1
491 : * +-- p
492 : *
493 : * psave_<fieldName> still points to the last byte in the
494 : * original buffer passed in where we should write the
495 : * encoding of <fieldName>.
496 : *
497 : * We adjust psave_<fieldName> to point to before the TLV
498 : * encoding of <fieldName> (with wrong tag) in the original
499 : * buffer (this may NOT be a valid pointer, but we won't
500 : * dereference it):
501 : *
502 : * [ ... | T_wrong | LL | VVVVV | ... ] // original buffer
503 : * ^
504 : * |
505 : * \
506 : * +-- psave_<fieldName>
507 : */
508 : "psave_%s -= l;\n"
509 : /*
510 : * We further adjust psave_<fieldName> to point to the last
511 : * byte of what should be the T(ag) of the TLV encoding of
512 : * <fieldName> (this is now a valid pointer), then...
513 : *
514 : * |<--->| (not written yet)
515 : * | | |<-------->| (not written yet)
516 : * [ ... | T_right | LL | VVVVV | ... ] // original buffer
517 : * ^
518 : * |
519 : * \
520 : * +-- psave_<fieldName>
521 : */
522 : "psave_%s += asn1_tag_length_%s;\n"
523 : /*
524 : * ...copy the L(ength)V(alue) of the TLV encoding of
525 : * <fieldName>.
526 : *
527 : * [ ... | T_right | LL | VVVVV | ... ] // original buffer
528 : * ^
529 : * |
530 : * \
531 : * +-- psave_<fieldName> + 1
532 : *
533 : * |<----->| length is
534 : * | | `l' - asn1_tag_length_<fieldName>
535 : * [ T_wrong | LL | VVVV ] // temp buffer
536 : * ^ ^
537 : * | |
538 : * | \
539 : * \ +-- p + 1 + asn1_tag_length_%s
540 : * +-- p + 1
541 : */
542 : "memcpy(psave_%s + 1, p + 1 + asn1_tag_length_%s, l - asn1_tag_length_%s);\n"
543 : /*
544 : * Encode the IMPLICIT tag. Recall that encoders like
545 : * der_put_tag() take a pointer to the last byte they
546 : * should write to, and a length of bytes to the left of
547 : * that that they are allowed to write into.
548 : *
549 : * [ ... | T_right | LL | VVVVV | ... ] // original buffer
550 : * ^
551 : * |
552 : * \
553 : * +-- psave_<fieldName>
554 : */
555 : "e = der_put_tag(psave_%s, %zu, %s, %s, %d, &l2_%s);\n"
556 : "if (e) { free(pfree_%s); return e; }\n"
557 : /* Restore `len' and adjust it (see `p' below) */
558 : "len = lensave_%s - (l + %zu - asn1_tag_length_%s);\n"
559 : /*
560 : * Adjust `ret' to account for the difference in size
561 : * between the length of the right and wrong tags.
562 : */
563 : "ret += %zu - asn1_tag_length_%s;\n"
564 : /* Free the buffer and restore `p' */
565 : "free(pfree_%s);\n"
566 : /*
567 : * Make `p' point into the original buffer again, to one
568 : * byte before the bytes we wrote:
569 : *
570 : * [ ... | T_right | LL | VVVVV | ... ] // original buffer
571 : * ^
572 : * |
573 : * \
574 : * +-- p
575 : */
576 : "p = psave_%s - (1 + %zu - asn1_tag_length_%s); }\n",
577 72 : tmpstr, tmpstr, tmpstr, t->subtype->symbol->name,
578 76 : tmpstr, t->subtype->symbol->name, t->subtype->symbol->name,
579 76 : tmpstr, length_tag(t->tag.tagvalue),
580 76 : classname(t->tag.tagclass),
581 : c ? "CONS" : "PRIM",
582 72 : t->tag.tagvalue,
583 : tmpstr,
584 :
585 72 : tmpstr, tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name,
586 72 : length_tag(t->tag.tagvalue), t->subtype->symbol->name,
587 76 : tmpstr, tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name);
588 : else
589 7486 : fprintf(codefile,
590 : "e = der_put_length_and_tag (p, len, ret, %s, %s, %s, &l);\n"
591 : "if (e) return e;\np -= l; len -= l; ret += l;\n\n",
592 3743 : classname(t->tag.tagclass),
593 : c ? "CONS" : "PRIM",
594 3743 : valuename(t->tag.tagclass, t->tag.tagvalue));
595 3819 : free(tname);
596 3819 : constructed = c;
597 3819 : break;
598 : }
599 171 : case TChoice:{
600 171 : Member *m, *have_ellipsis = NULL;
601 171 : char *s = NULL;
602 :
603 171 : if (t->members == NULL)
604 0 : break;
605 :
606 171 : fprintf(codefile, "\n");
607 :
608 171 : if (asprintf (&s, "(%s)", name) < 0 || s == NULL)
609 0 : errx(1, "malloc");
610 171 : fprintf(codefile, "switch(%s->element) {\n", s);
611 :
612 817 : HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
613 646 : char *s2 = NULL;
614 :
615 646 : if (m->ellipsis) {
616 19 : have_ellipsis = m;
617 19 : continue;
618 : }
619 :
620 627 : fprintf (codefile, "case %s: {", m->label);
621 660 : if (asprintf(&s2, "%s(%s)->u.%s", m->optional ? "" : "&",
622 627 : s, m->gen_name) < 0 || s2 == NULL)
623 0 : errx(1, "malloc");
624 627 : if (m->optional)
625 0 : fprintf (codefile, "if(%s) {\n", s2);
626 627 : fprintf (codefile, "size_t %s_oldret = ret;\n", tmpstr);
627 627 : fprintf (codefile, "ret = 0;\n");
628 627 : constructed = encode_type (s2, m->type, m->gen_name);
629 627 : fprintf (codefile, "ret += %s_oldret;\n", tmpstr);
630 627 : if(m->optional)
631 0 : fprintf (codefile, "}\n");
632 627 : fprintf(codefile, "break;\n");
633 627 : fprintf(codefile, "}\n");
634 627 : free (s2);
635 : }
636 171 : free (s);
637 171 : if (have_ellipsis) {
638 19 : fprintf(codefile,
639 : "case %s: {\n"
640 : "if (len < (%s)->u.%s.length)\n"
641 : "return ASN1_OVERFLOW;\n"
642 : "p -= (%s)->u.%s.length;\n"
643 : "ret += (%s)->u.%s.length;\n"
644 : "memcpy(p + 1, (%s)->u.%s.data, (%s)->u.%s.length);\n"
645 : "break;\n"
646 : "}\n",
647 : have_ellipsis->label,
648 : name, have_ellipsis->gen_name,
649 : name, have_ellipsis->gen_name,
650 : name, have_ellipsis->gen_name,
651 : name, have_ellipsis->gen_name,
652 : name, have_ellipsis->gen_name);
653 : }
654 171 : fprintf(codefile, "};\n");
655 162 : break;
656 : }
657 72 : case TOID:
658 76 : encode_primitive ("oid", name);
659 76 : constructed = 0;
660 76 : break;
661 0 : case TUTCTime:
662 0 : encode_primitive ("utctime", name);
663 0 : constructed = 0;
664 0 : break;
665 72 : case TUTF8String:
666 76 : encode_primitive ("utf8string", name);
667 76 : constructed = 0;
668 76 : break;
669 0 : case TPrintableString:
670 0 : encode_primitive ("printable_string", name);
671 0 : constructed = 0;
672 0 : break;
673 0 : case TIA5String:
674 0 : encode_primitive ("ia5_string", name);
675 0 : constructed = 0;
676 0 : break;
677 0 : case TBMPString:
678 0 : encode_primitive ("bmp_string", name);
679 0 : constructed = 0;
680 0 : break;
681 0 : case TUniversalString:
682 0 : encode_primitive ("universal_string", name);
683 0 : constructed = 0;
684 0 : break;
685 0 : case TVisibleString:
686 0 : encode_primitive ("visible_string", name);
687 0 : constructed = 0;
688 0 : break;
689 19 : case TNull:
690 19 : fprintf (codefile, "/* NULL */\n");
691 19 : constructed = 0;
692 19 : break;
693 0 : default:
694 0 : abort ();
695 : }
696 7486 : return constructed;
697 : }
698 :
699 : void
700 912 : generate_type_encode (const Symbol *s)
701 : {
702 960 : fprintf (codefile, "int ASN1CALL\n"
703 : "encode_%s(unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE, size_t len HEIMDAL_UNUSED_ATTRIBUTE,"
704 : " const %s *data, size_t *size)\n"
705 : "{\n",
706 912 : s->gen_name, s->gen_name);
707 :
708 912 : switch (s->type->type) {
709 912 : case TInteger:
710 : case TBoolean:
711 : case TOctetString:
712 : case TGeneralizedTime:
713 : case TGeneralString:
714 : case TTeletexString:
715 : case TUTCTime:
716 : case TUTF8String:
717 : case TPrintableString:
718 : case TIA5String:
719 : case TBMPString:
720 : case TUniversalString:
721 : case TVisibleString:
722 : case TNull:
723 : case TBitString:
724 : case TEnumerated:
725 : case TOID:
726 : case TSequence:
727 : case TSequenceOf:
728 : case TSet:
729 : case TSetOf:
730 : case TTag:
731 : case TType:
732 : case TChoice:
733 912 : fprintf (codefile,
734 : "size_t ret HEIMDAL_UNUSED_ATTRIBUTE = 0;\n"
735 : "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n"
736 : "int i HEIMDAL_UNUSED_ATTRIBUTE, e HEIMDAL_UNUSED_ATTRIBUTE;\n\n");
737 :
738 912 : encode_type("data", s->type, "Top");
739 :
740 912 : fprintf (codefile, "*size = ret;\n"
741 : "return 0;\n");
742 912 : break;
743 0 : default:
744 0 : abort ();
745 : }
746 912 : fprintf (codefile, "}\n\n");
747 912 : }
|