Conf file is now in source tree
[mod_auth_kerb.cvs/.git] / spnegokrb5 / der_put.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 "der_locl.h"
35
36 #if 0
37 RCSID("$Id$");
38 #endif
39
40 /*
41  * All encoding functions take a pointer `p' to first position in
42  * which to write, from the right, `len' which means the maximum
43  * number of characters we are able to write.  The function returns
44  * the number of characters written in `size' (if non-NULL).
45  * The return value is 0 or an error.
46  */
47
48 static int
49 der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size)
50 {
51     unsigned char *base = p;
52
53     if (val) {
54         while (len > 0 && val) {
55             *p-- = val % 256;
56             val /= 256;
57             --len;
58         }
59         if (val != 0)
60             return ASN1_OVERFLOW;
61         else {
62             *size = base - p;
63             return 0;
64         }
65     } else if (len < 1)
66         return ASN1_OVERFLOW;
67     else {
68         *p    = 0;
69         *size = 1;
70         return 0;
71     }
72 }
73
74 int
75 der_put_int (unsigned char *p, size_t len, int val, size_t *size)
76 {
77     unsigned char *base = p;
78
79     if(val >= 0) {
80         do {
81             if(len < 1)
82                 return ASN1_OVERFLOW;
83             *p-- = val % 256;
84             len--;
85             val /= 256;
86         } while(val);
87         if(p[1] >= 128) {
88             if(len < 1)
89                 return ASN1_OVERFLOW;
90             *p-- = 0;
91             len--;
92         }
93     } else {
94         val = ~val;
95         do {
96             if(len < 1)
97                 return ASN1_OVERFLOW;
98             *p-- = ~(val % 256);
99             len--;
100             val /= 256;
101         } while(val);
102         if(p[1] < 128) {
103             if(len < 1)
104                 return ASN1_OVERFLOW;
105             *p-- = 0xff;
106             len--;
107         }
108     }
109     *size = base - p;
110     return 0;
111 }
112
113
114 int
115 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
116 {
117     if (len < 1)
118         return ASN1_OVERFLOW;
119     if (val < 128) {
120         *p = val;
121         *size = 1;
122         return 0;
123     } else {
124         size_t l;
125         int e;
126
127         e = der_put_unsigned (p, len - 1, val, &l);
128         if (e)
129             return e;
130         p -= l;
131         *p = 0x80 | l;
132         *size = l + 1;
133         return 0;
134     }
135 }
136
137 int
138 der_put_general_string (unsigned char *p, size_t len, 
139                         const general_string *str, size_t *size)
140 {
141     size_t slen = strlen(*str);
142
143     if (len < slen)
144         return ASN1_OVERFLOW;
145     p -= slen;
146     len -= slen;
147     memcpy (p+1, *str, slen);
148     *size = slen;
149     return 0;
150 }
151
152 int
153 der_put_octet_string (unsigned char *p, size_t len, 
154                       const octet_string *data, size_t *size)
155 {
156     if (len < data->length)
157         return ASN1_OVERFLOW;
158     p -= data->length;
159     len -= data->length;
160     memcpy (p+1, data->data, data->length);
161     *size = data->length;
162     return 0;
163 }
164
165 int
166 der_put_oid (unsigned char *p, size_t len,
167              const oid *data, size_t *size)
168 {
169     unsigned char *base = p;
170     int n;
171
172     for (n = data->length - 1; n >= 2; --n) {
173         unsigned u = data->components[n];
174
175         if (len < 1)
176             return ASN1_OVERFLOW;
177         *p-- = u % 128;
178         u /= 128;
179         --len;
180         while (u > 0) {
181             if (len < 1)
182                 return ASN1_OVERFLOW;
183             *p-- = 128 + u % 128;
184             u /= 128;
185             --len;
186         }
187     }
188     if (len < 1)
189         return ASN1_OVERFLOW;
190     *p-- = 40 * data->components[0] + data->components[1];
191     *size = base - p;
192     return 0;
193 }
194
195 int
196 der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
197              int tag, size_t *size)
198 {
199     if (len < 1)
200         return ASN1_OVERFLOW;
201     *p = (class << 6) | (type << 5) | tag; /* XXX */
202     *size = 1;
203     return 0;
204 }
205
206 int
207 der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
208                         Der_class class, Der_type type, int tag, size_t *size)
209 {
210     size_t ret = 0;
211     size_t l;
212     int e;
213
214     e = der_put_length (p, len, len_val, &l);
215     if(e)
216         return e;
217     p -= l;
218     len -= l;
219     ret += l;
220     e = der_put_tag (p, len, class, type, tag, &l);
221     if(e)
222         return e;
223     p -= l;
224     len -= l;
225     ret += l;
226     *size = ret;
227     return 0;
228 }
229
230 int
231 encode_integer (unsigned char *p, size_t len, const int *data, size_t *size)
232 {
233     int num = *data;
234     size_t ret = 0;
235     size_t l;
236     int e;
237     
238     e = der_put_int (p, len, num, &l);
239     if(e)
240         return e;
241     p -= l;
242     len -= l;
243     ret += l;
244     e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l);
245     if (e)
246         return e;
247     p -= l;
248     len -= l;
249     ret += l;
250     *size = ret;
251     return 0;
252 }
253
254 int
255 encode_unsigned (unsigned char *p, size_t len, const unsigned *data,
256                  size_t *size)
257 {
258     unsigned num = *data;
259     size_t ret = 0;
260     size_t l;
261     int e;
262     
263     e = der_put_unsigned (p, len, num, &l);
264     if(e)
265         return e;
266     p -= l;
267     len -= l;
268     ret += l;
269     e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l);
270     if (e)
271         return e;
272     p -= l;
273     len -= l;
274     ret += l;
275     *size = ret;
276     return 0;
277 }
278
279 int
280 encode_enumerated (unsigned char *p, size_t len, const unsigned *data,
281                    size_t *size)
282 {
283     unsigned num = *data;
284     size_t ret = 0;
285     size_t l;
286     int e;
287     
288     e = der_put_int (p, len, num, &l);
289     if(e)
290         return e;
291     p -= l;
292     len -= l;
293     ret += l;
294     e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Enumerated, &l);
295     if (e)
296         return e;
297     p -= l;
298     len -= l;
299     ret += l;
300     *size = ret;
301     return 0;
302 }
303
304 int
305 encode_general_string (unsigned char *p, size_t len, 
306                        const general_string *data, size_t *size)
307 {
308     size_t ret = 0;
309     size_t l;
310     int e;
311
312     e = der_put_general_string (p, len, data, &l);
313     if (e)
314         return e;
315     p -= l;
316     len -= l;
317     ret += l;
318     e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_GeneralString, &l);
319     if (e)
320         return e;
321     p -= l;
322     len -= l;
323     ret += l;
324     *size = ret;
325     return 0;
326 }
327
328 int
329 encode_octet_string (unsigned char *p, size_t len, 
330                      const octet_string *k, size_t *size)
331 {
332     size_t ret = 0;
333     size_t l;
334     int e;
335
336     e = der_put_octet_string (p, len, k, &l);
337     if (e)
338         return e;
339     p -= l;
340     len -= l;
341     ret += l;
342     e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OctetString, &l);
343     if (e)
344         return e;
345     p -= l;
346     len -= l;
347     ret += l;
348     *size = ret;
349     return 0;
350 }
351
352 int
353 encode_oid(unsigned char *p, size_t len,
354            const oid *k, size_t *size)
355 {
356     size_t ret = 0;
357     size_t l;
358     int e;
359
360     e = der_put_oid (p, len, k, &l);
361     if (e)
362         return e;
363     p -= l;
364     len -= l;
365     ret += l;
366     e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OID, &l);
367     if (e)
368         return e;
369     p -= l;
370     len -= l;
371     ret += l;
372     *size = ret;
373     return 0;
374 }
375
376 int
377 time2generalizedtime (time_t t, octet_string *s)
378 {
379      struct tm *tm;
380      size_t len;
381
382      len = 15;
383
384      s->data = malloc(len + 1);
385      if (s->data == NULL)
386          return ENOMEM;
387      s->length = len;
388      tm = gmtime (&t);
389      snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ", 
390                tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 
391                tm->tm_hour, tm->tm_min, tm->tm_sec);
392      return 0;
393 }
394
395 int
396 encode_generalized_time (unsigned char *p, size_t len,
397                          const time_t *t, size_t *size)
398 {
399     size_t ret = 0;
400     size_t l;
401     octet_string k;
402     int e;
403
404     e = time2generalizedtime (*t, &k);
405     if (e)
406         return e;
407     e = der_put_octet_string (p, len, &k, &l);
408     free (k.data);
409     if (e)
410         return e;
411     p -= l;
412     len -= l;
413     ret += l;
414     e = der_put_length_and_tag (p, len, k.length, UNIV, PRIM, 
415                                 UT_GeneralizedTime, &l);
416     if (e)
417         return e;
418     p -= l;
419     len -= l;
420     ret += l;
421     *size = ret;
422     return 0;
423 }