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