Merge from vendor branch NCURSES:
[dragonfly.git] / crypto / heimdal-0.6.3 / lib / asn1 / gen_decode.c
1 /*
2  * Copyright (c) 1997 - 2001 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 RCSID("$Id: gen_decode.c,v 1.18 2002/08/09 15:37:34 joda Exp $");
37
38 static void
39 decode_primitive (const char *typename, const char *name)
40 {
41     fprintf (codefile,
42              "e = decode_%s(p, len, %s, &l);\n"
43              "FORW;\n",
44              typename,
45              name);
46 }
47
48 static void
49 decode_type (const char *name, const Type *t)
50 {
51     switch (t->type) {
52     case TType:
53 #if 0
54         decode_type (name, t->symbol->type);
55 #endif
56         fprintf (codefile,
57                  "e = decode_%s(p, len, %s, &l);\n"
58                  "FORW;\n",
59                  t->symbol->gen_name, name);
60         break;
61     case TInteger:
62         if(t->members == NULL)
63             decode_primitive ("integer", name);
64         else {
65             char *s;
66             asprintf(&s, "(int*)%s", name);
67             if(s == NULL)
68                 errx (1, "out of memory");
69             decode_primitive ("integer", s);
70             free(s);
71         }
72         break;
73     case TUInteger:
74         decode_primitive ("unsigned", name);
75         break;
76     case TEnumerated:
77         decode_primitive ("enumerated", name);
78         break;
79     case TOctetString:
80         decode_primitive ("octet_string", name);
81         break;
82     case TOID :
83         decode_primitive ("oid", name);
84         break;
85     case TBitString: {
86         Member *m;
87         int tag = -1;
88         int pos;
89
90         fprintf (codefile,
91                  "e = der_match_tag_and_length (p, len, UNIV, PRIM, UT_BitString,"
92                  "&reallen, &l);\n"
93                  "FORW;\n"
94                  "if(len < reallen)\n"
95                  "return ASN1_OVERRUN;\n"
96                  "p++;\n"
97                  "len--;\n"
98                  "reallen--;\n"
99                  "ret++;\n");
100         pos = 0;
101         for (m = t->members; m && tag != m->val; m = m->next) {
102             while (m->val / 8 > pos / 8) {
103                 fprintf (codefile,
104                          "p++; len--; reallen--; ret++;\n");
105                 pos += 8;
106             }
107             fprintf (codefile,
108                      "%s->%s = (*p >> %d) & 1;\n",
109                      name, m->gen_name, 7 - m->val % 8);
110             if (tag == -1)
111                 tag = m->val;
112         }
113         fprintf (codefile,
114                  "p += reallen; len -= reallen; ret += reallen;\n");
115         break;
116     }
117     case TSequence: {
118         Member *m;
119         int tag = -1;
120
121         if (t->members == NULL)
122             break;
123
124         fprintf (codefile,
125                  "e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,"
126                  "&reallen, &l);\n"
127                  "FORW;\n"
128                  "{\n"
129                  "int dce_fix;\n"
130                  "if((dce_fix = fix_dce(reallen, &len)) < 0)\n"
131                  "return ASN1_BAD_FORMAT;\n");
132
133         for (m = t->members; m && tag != m->val; m = m->next) {
134             char *s;
135
136             asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name);
137             if (0 && m->type->type == TType){
138                 if(m->optional)
139                     fprintf (codefile,
140                              "%s = malloc(sizeof(*%s));\n"
141                              "if(%s == NULL) return ENOMEM;\n", s, s, s);
142                 fprintf (codefile, 
143                          "e = decode_seq_%s(p, len, %d, %d, %s, &l);\n",
144                          m->type->symbol->gen_name,
145                          m->val, 
146                          m->optional,
147                          s);
148                 if(m->optional)
149                     fprintf (codefile, 
150                              "if (e == ASN1_MISSING_FIELD) {\n"
151                              "free(%s);\n"
152                              "%s = NULL;\n"
153                              "e = l = 0;\n"
154                              "}\n",
155                              s, s);
156           
157                 fprintf (codefile, "FORW;\n");
158           
159             }else{
160                 fprintf (codefile, "{\n"
161                          "size_t newlen, oldlen;\n\n"
162                          "e = der_match_tag (p, len, CONTEXT, CONS, %d, &l);\n",
163                          m->val);
164                 fprintf (codefile,
165                          "if (e)\n");
166                 if(m->optional)
167                     /* XXX should look at e */
168                     fprintf (codefile,
169                              "%s = NULL;\n", s);
170                 else
171                     fprintf (codefile,
172                              "return e;\n");
173                 fprintf (codefile, 
174                          "else {\n");
175                 fprintf (codefile,
176                          "p += l;\n"
177                          "len -= l;\n"
178                          "ret += l;\n"
179                          "e = der_get_length (p, len, &newlen, &l);\n"
180                          "FORW;\n"
181                          "{\n"
182                
183                          "int dce_fix;\n"
184                          "oldlen = len;\n"
185                          "if((dce_fix = fix_dce(newlen, &len)) < 0)"
186                          "return ASN1_BAD_FORMAT;\n");
187                 if (m->optional)
188                     fprintf (codefile,
189                              "%s = malloc(sizeof(*%s));\n"
190                              "if(%s == NULL) return ENOMEM;\n", s, s, s);
191                 decode_type (s, m->type);
192                 fprintf (codefile,
193                          "if(dce_fix){\n"
194                          "e = der_match_tag_and_length (p, len, "
195                          "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
196                          "FORW;\n"
197                          "}else \n"
198                          "len = oldlen - newlen;\n"
199                          "}\n"
200                          "}\n");
201                 fprintf (codefile,
202                          "}\n");
203             }
204             if (tag == -1)
205                 tag = m->val;
206             free (s);
207         }
208         fprintf(codefile,
209                 "if(dce_fix){\n"
210                 "e = der_match_tag_and_length (p, len, "
211                 "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
212                 "FORW;\n"
213                 "}\n"
214                 "}\n");
215
216         break;
217     }
218     case TSequenceOf: {
219         char *n;
220
221         fprintf (codefile,
222                  "e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,"
223                  "&reallen, &l);\n"
224                  "FORW;\n"
225                  "if(len < reallen)\n"
226                  "return ASN1_OVERRUN;\n"
227                  "len = reallen;\n");
228
229         fprintf (codefile,
230                  "{\n"
231                  "size_t origlen = len;\n"
232                  "int oldret = ret;\n"
233                  "ret = 0;\n"
234                  "(%s)->len = 0;\n"
235                  "(%s)->val = NULL;\n"
236                  "while(ret < origlen) {\n"
237                  "(%s)->len++;\n"
238                  "(%s)->val = realloc((%s)->val, sizeof(*((%s)->val)) * (%s)->len);\n",
239                  name, name, name, name, name, name, name);
240         asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name);
241         decode_type (n, t->subtype);
242         fprintf (codefile, 
243                  "len = origlen - ret;\n"
244                  "}\n"
245                  "ret += oldret;\n"
246                  "}\n");
247         free (n);
248         break;
249     }
250     case TGeneralizedTime:
251         decode_primitive ("generalized_time", name);
252         break;
253     case TGeneralString:
254         decode_primitive ("general_string", name);
255         break;
256     case TApplication:
257         fprintf (codefile,
258                  "e = der_match_tag_and_length (p, len, APPL, CONS, %d, "
259                  "&reallen, &l);\n"
260                  "FORW;\n"
261                  "{\n"
262                  "int dce_fix;\n"
263                  "if((dce_fix = fix_dce(reallen, &len)) < 0)\n"
264                  "return ASN1_BAD_FORMAT;\n", 
265                  t->application);
266         decode_type (name, t->subtype);
267         fprintf(codefile,
268                 "if(dce_fix){\n"
269                 "e = der_match_tag_and_length (p, len, "
270                 "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
271                 "FORW;\n"
272                 "}\n"
273                 "}\n");
274
275         break;
276     default :
277         abort ();
278     }
279 }
280
281 void
282 generate_type_decode (const Symbol *s)
283 {
284   fprintf (headerfile,
285            "int    "
286            "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
287            s->gen_name, s->gen_name);
288
289   fprintf (codefile, "#define FORW "
290            "if(e) goto fail; "
291            "p += l; "
292            "len -= l; "
293            "ret += l\n\n");
294
295
296   fprintf (codefile, "int\n"
297            "decode_%s(const unsigned char *p,"
298            " size_t len, %s *data, size_t *size)\n"
299            "{\n",
300            s->gen_name, s->gen_name);
301
302   switch (s->type->type) {
303   case TInteger:
304   case TUInteger:
305   case TOctetString:
306   case TOID:
307   case TGeneralizedTime:
308   case TGeneralString:
309   case TBitString:
310   case TSequence:
311   case TSequenceOf:
312   case TApplication:
313   case TType:
314     fprintf (codefile,
315              "size_t ret = 0, reallen;\n"
316              "size_t l;\n"
317              "int e;\n\n");
318     fprintf (codefile, "memset(data, 0, sizeof(*data));\n");
319     fprintf (codefile, "reallen = 0;\n"); /* hack to avoid `unused variable' */
320
321     decode_type ("data", s->type);
322     fprintf (codefile, 
323              "if(size) *size = ret;\n"
324              "return 0;\n");
325     fprintf (codefile,
326              "fail:\n"
327              "free_%s(data);\n"
328              "return e;\n",
329              s->gen_name);
330     break;
331   default:
332     abort ();
333   }
334   fprintf (codefile, "}\n\n");
335 }
336
337 void
338 generate_seq_type_decode (const Symbol *s)
339 {
340     fprintf (headerfile,
341              "int decode_seq_%s(const unsigned char *, size_t, int, int, "
342              "%s *, size_t *);\n",
343              s->gen_name, s->gen_name);
344
345     fprintf (codefile, "int\n"
346              "decode_seq_%s(const unsigned char *p, size_t len, int tag, "
347              "int optional, %s *data, size_t *size)\n"
348              "{\n",
349              s->gen_name, s->gen_name);
350
351     fprintf (codefile,
352              "size_t newlen, oldlen;\n"
353              "size_t l, ret = 0;\n"
354              "int e;\n"
355              "int dce_fix;\n");
356     
357     fprintf (codefile,
358              "e = der_match_tag(p, len, CONTEXT, CONS, tag, &l);\n"
359              "if (e)\n"
360              "return e;\n");
361     fprintf (codefile, 
362              "p += l;\n"
363              "len -= l;\n"
364              "ret += l;\n"
365              "e = der_get_length(p, len, &newlen, &l);\n"
366              "if (e)\n"
367              "return e;\n"
368              "p += l;\n"
369              "len -= l;\n"
370              "ret += l;\n"
371              "oldlen = len;\n"
372              "if ((dce_fix = fix_dce(newlen, &len)) < 0)\n"
373              "return ASN1_BAD_FORMAT;\n"
374              "e = decode_%s(p, len, data, &l);\n"
375              "if (e)\n"
376              "return e;\n"
377              "p += l;\n"
378              "len -= l;\n"
379              "ret += l;\n"
380              "if (dce_fix) {\n"
381              "size_t reallen;\n\n"
382              "e = der_match_tag_and_length(p, len, "
383              "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
384              "if (e)\n"
385              "return e;\n"
386              "ret += l;\n"
387              "}\n",
388              s->gen_name);
389     fprintf (codefile, 
390              "if(size) *size = ret;\n"
391              "return 0;\n");
392
393     fprintf (codefile, "}\n\n");
394 }