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