xref: /freebsd/crypto/heimdal/lib/asn1/gen_decode.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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 
36 RCSID("$Id: gen_decode.c,v 1.11 1999/12/02 17:05:02 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     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 
262 void
263 generate_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 
318 void
319 generate_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