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