Add heimdal-0.6.3
[dragonfly.git] / crypto / heimdal-0.6.3 / lib / asn1 / gen_encode.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_encode.c,v 1.12 2001/09/25 13:39:26 assar Exp $");
37
38 static void
39 encode_primitive (const char *typename, const char *name)
40 {
41     fprintf (codefile,
42              "e = encode_%s(p, len, %s, &l);\n"
43              "BACK;\n",
44              typename,
45              name);
46 }
47
48 static void
49 encode_type (const char *name, const Type *t)
50 {
51     switch (t->type) {
52     case TType:
53 #if 0
54         encode_type (name, t->symbol->type);
55 #endif
56         fprintf (codefile,
57                  "e = encode_%s(p, len, %s, &l);\n"
58                  "BACK;\n",
59                  t->symbol->gen_name, name);
60         break;
61     case TInteger:
62         if(t->members == NULL)
63             encode_primitive ("integer", name);
64         else {
65             char *s;
66             asprintf(&s, "(const int*)%s", name);
67             if(s == NULL)
68                 errx(1, "out of memory");
69             encode_primitive ("integer", s);
70             free(s);
71         }
72         break;
73     case TUInteger:
74         encode_primitive ("unsigned", name);
75         break;
76     case TOctetString:
77         encode_primitive ("octet_string", name);
78         break;
79     case TOID :
80         encode_primitive ("oid", name);
81         break;
82     case TBitString: {
83         Member *m;
84         int pos;
85         int rest;
86         int tag = -1;
87
88         if (t->members == NULL)
89             break;
90
91         fprintf (codefile, "{\n"
92                  "unsigned char c = 0;\n");
93         pos = t->members->prev->val;
94         /* fix for buggy MIT (and OSF?) code */
95         if (pos > 31)
96             abort ();
97         /*
98          * It seems that if we do not always set pos to 31 here, the MIT
99          * code will do the wrong thing.
100          *
101          * I hate ASN.1 (and DER), but I hate it even more when everybody
102          * has to screw it up differently.
103          */
104         pos = 31;
105         rest = 7 - (pos % 8);
106
107         for (m = t->members->prev; m && tag != m->val; m = m->prev) {
108             while (m->val / 8 < pos / 8) {
109                 fprintf (codefile,
110                          "*p-- = c; len--; ret++;\n"
111                          "c = 0;\n");
112                 pos -= 8;
113             }
114             fprintf (codefile,
115                      "if(%s->%s) c |= 1<<%d;\n", name, m->gen_name,
116                      7 - m->val % 8);
117
118             if (tag == -1)
119                 tag = m->val;
120         }
121
122         fprintf (codefile, 
123                  "*p-- = c;\n"
124                  "*p-- = %d;\n"
125                  "len -= 2;\n"
126                  "ret += 2;\n"
127                  "}\n\n"
128                  "e = der_put_length_and_tag (p, len, ret, UNIV, PRIM,"
129                  "UT_BitString, &l);\n"
130                  "BACK;\n",
131                  rest);
132         break;
133     }
134     case TEnumerated : {
135         encode_primitive ("enumerated", name);
136         break;
137     }
138     case TSequence: {
139         Member *m;
140         int tag = -1;
141
142         if (t->members == NULL)
143             break;
144
145         for (m = t->members->prev; m && tag != m->val; m = m->prev) {
146             char *s;
147
148             asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name);
149             if (m->optional)
150                 fprintf (codefile,
151                          "if(%s)\n",
152                          s);
153 #if 1
154             fprintf (codefile, "{\n"
155                      "int oldret = ret;\n"
156                      "ret = 0;\n");
157 #endif
158             encode_type (s, m->type);
159             fprintf (codefile,
160                      "e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, "
161                      "%d, &l);\n"
162                      "BACK;\n",
163                      m->val);
164 #if 1
165             fprintf (codefile,
166                      "ret += oldret;\n"
167                      "}\n");
168 #endif
169             if (tag == -1)
170                 tag = m->val;
171             free (s);
172         }
173         fprintf (codefile,
174                  "e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l);\n"
175                  "BACK;\n");
176         break;
177     }
178     case TSequenceOf: {
179         char *n;
180
181         fprintf (codefile,
182                  "for(i = (%s)->len - 1; i >= 0; --i) {\n"
183 #if 1
184                  "int oldret = ret;\n"
185                  "ret = 0;\n",
186 #else
187                  ,
188 #endif
189                  name);
190         asprintf (&n, "&(%s)->val[i]", name);
191         encode_type (n, t->subtype);
192         fprintf (codefile,
193 #if 1
194                  "ret += oldret;\n"
195 #endif
196                  "}\n"
197                  "e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l);\n"
198                  "BACK;\n");
199         free (n);
200         break;
201     }
202     case TGeneralizedTime:
203         encode_primitive ("generalized_time", name);
204         break;
205     case TGeneralString:
206         encode_primitive ("general_string", name);
207         break;
208     case TApplication:
209         encode_type (name, t->subtype);
210         fprintf (codefile,
211                  "e = der_put_length_and_tag (p, len, ret, APPL, CONS, %d, &l);\n"
212                  "BACK;\n",
213                  t->application);
214         break;
215     default:
216         abort ();
217     }
218 }
219
220 void
221 generate_type_encode (const Symbol *s)
222 {
223   fprintf (headerfile,
224            "int    "
225            "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
226            s->gen_name, s->gen_name);
227
228   fprintf (codefile, "#define BACK if (e) return e; p -= l; len -= l; ret += l\n\n");
229
230
231   fprintf (codefile, "int\n"
232            "encode_%s(unsigned char *p, size_t len,"
233            " const %s *data, size_t *size)\n"
234            "{\n",
235            s->gen_name, s->gen_name);
236
237   switch (s->type->type) {
238   case TInteger:
239   case TUInteger:
240   case TOctetString:
241   case TGeneralizedTime:
242   case TGeneralString:
243   case TBitString:
244   case TEnumerated:
245   case TOID:
246   case TSequence:
247   case TSequenceOf:
248   case TApplication:
249   case TType:
250     fprintf (codefile,
251              "size_t ret = 0;\n"
252              "size_t l;\n"
253              "int i, e;\n\n");
254     fprintf(codefile, "i = 0;\n"); /* hack to avoid `unused variable' */
255     
256       encode_type("data", s->type);
257
258     fprintf (codefile, "*size = ret;\n"
259              "return 0;\n");
260     break;
261   default:
262     abort ();
263   }
264   fprintf (codefile, "}\n\n");
265 }