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