r8302: import mini HEIMDAL into the tree
[samba.git] / source4 / heimdal / lib / asn1 / der_get.c
1 /*
2  * Copyright (c) 1997 - 2004 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 RCSID("$Id: der_get.c,v 1.39 2005/05/29 14:23:00 lha Exp $");
37
38 #include <version.h>
39
40 /* 
41  * All decoding functions take a pointer `p' to first position in
42  * which to read, from the left, `len' which means the maximum number
43  * of characters we are able to read, `ret' were the value will be
44  * returned and `size' where the number of used bytes is stored.
45  * Either 0 or an error code is returned.
46  */
47
48 static int
49 der_get_unsigned (const unsigned char *p, size_t len,
50                   unsigned *ret, size_t *size)
51 {
52     unsigned val = 0;
53     size_t oldlen = len;
54
55     while (len--)
56         val = val * 256 + *p++;
57     *ret = val;
58     if(size) *size = oldlen;
59     return 0;
60 }
61
62 int
63 der_get_int (const unsigned char *p, size_t len,
64              int *ret, size_t *size)
65 {
66     int val = 0;
67     size_t oldlen = len;
68
69     if (len > 0) {
70         val = (signed char)*p++;
71         while (--len)
72             val = val * 256 + *p++;
73     }
74     *ret = val;
75     if(size) *size = oldlen;
76     return 0;
77 }
78
79 int
80 der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size)
81 {
82     if(len < 1)
83         return ASN1_OVERRUN;
84     if(*p != 0)
85         *data = 1;
86     else
87         *data = 0;
88     *size = 1;
89     return 0;
90 }
91
92 int
93 der_get_length (const unsigned char *p, size_t len,
94                 size_t *val, size_t *size)
95 {
96     size_t v;
97
98     if (len <= 0)
99         return ASN1_OVERRUN;
100     --len;
101     v = *p++;
102     if (v < 128) {
103         *val = v;
104         if(size) *size = 1;
105     } else {
106         int e;
107         size_t l;
108         unsigned tmp;
109
110         if(v == 0x80){
111             *val = ASN1_INDEFINITE;
112             if(size) *size = 1;
113             return 0;
114         }
115         v &= 0x7F;
116         if (len < v)
117             return ASN1_OVERRUN;
118         e = der_get_unsigned (p, v, &tmp, &l);
119         if(e) return e;
120         *val = tmp;
121         if(size) *size = l + 1;
122     }
123     return 0;
124 }
125
126 int
127 der_get_general_string (const unsigned char *p, size_t len, 
128                         heim_general_string *str, size_t *size)
129 {
130     char *s;
131
132     s = malloc (len + 1);
133     if (s == NULL)
134         return ENOMEM;
135     memcpy (s, p, len);
136     s[len] = '\0';
137     *str = s;
138     if(size) *size = len;
139     return 0;
140 }
141
142 int
143 der_get_octet_string (const unsigned char *p, size_t len, 
144                       heim_octet_string *data, size_t *size)
145 {
146     data->length = len;
147     data->data = malloc(len);
148     if (data->data == NULL && data->length != 0)
149         return ENOMEM;
150     memcpy (data->data, p, len);
151     if(size) *size = len;
152     return 0;
153 }
154
155 int
156 der_get_oid (const unsigned char *p, size_t len,
157              heim_oid *data, size_t *size)
158 {
159     int n;
160     size_t oldlen = len;
161
162     if (len < 1)
163         return ASN1_OVERRUN;
164
165     data->components = malloc((len + 1) * sizeof(*data->components));
166     if (data->components == NULL)
167         return ENOMEM;
168     data->components[0] = (*p) / 40;
169     data->components[1] = (*p) % 40;
170     --len;
171     ++p;
172     for (n = 2; len > 0; ++n) {
173         unsigned u = 0;
174
175         do {
176             --len;
177             u = u * 128 + (*p++ % 128);
178         } while (len > 0 && p[-1] & 0x80);
179         data->components[n] = u;
180     }
181     if (len > 0 && p[-1] & 0x80) {
182         free_oid (data);
183         return ASN1_OVERRUN;
184     }
185     data->length = n;
186     if (size)
187         *size = oldlen;
188     return 0;
189 }
190
191 int
192 der_get_tag (const unsigned char *p, size_t len,
193              Der_class *class, Der_type *type,
194              int *tag, size_t *size)
195 {
196     if (len < 1)
197         return ASN1_OVERRUN;
198     *class = (Der_class)(((*p) >> 6) & 0x03);
199     *type = (Der_type)(((*p) >> 5) & 0x01);
200     *tag = (*p) & 0x1F;
201     if(size) *size = 1;
202     return 0;
203 }
204
205 int
206 der_match_tag (const unsigned char *p, size_t len,
207                Der_class class, Der_type type,
208                int tag, size_t *size)
209 {
210     size_t l;
211     Der_class thisclass;
212     Der_type thistype;
213     int thistag;
214     int e;
215
216     e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l);
217     if (e) return e;
218     if (class != thisclass || type != thistype)
219         return ASN1_BAD_ID;
220     if(tag > thistag)
221         return ASN1_MISPLACED_FIELD;
222     if(tag < thistag)
223         return ASN1_MISSING_FIELD;
224     if(size) *size = l;
225     return 0;
226 }
227
228 int
229 der_match_tag_and_length (const unsigned char *p, size_t len,
230                           Der_class class, Der_type type, int tag,
231                           size_t *length_ret, size_t *size)
232 {
233     size_t l, ret = 0;
234     int e;
235
236     e = der_match_tag (p, len, class, type, tag, &l);
237     if (e) return e;
238     p += l;
239     len -= l;
240     ret += l;
241
242     e = der_get_length (p, len, length_ret, &l);
243     if (e) return e;
244     p += l;
245     len -= l;
246     ret += l;
247     if(size) *size = ret;
248     return 0;
249 }
250
251 int
252 decode_boolean (const unsigned char *p, size_t len,
253                 int *num, size_t *size)
254 {
255     size_t ret = 0;
256     size_t l, reallen;
257     int e;
258
259     e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Boolean, &l);
260     if (e) return e;
261     p += l;
262     len -= l;
263     ret += l;
264
265     e = der_get_length (p, len, &reallen, &l);
266     if (e) return e;
267     p += l;
268     len -= l;
269     ret += l;
270     if (reallen > len)
271         return ASN1_OVERRUN;
272
273     e = der_get_boolean (p, reallen, num, &l);
274     if (e) return e;
275     p += l;
276     len -= l;
277     ret += l;
278     if(size) *size = ret;
279     return 0;
280 }
281
282 int
283 decode_integer (const unsigned char *p, size_t len,
284                 int *num, size_t *size)
285 {
286     size_t ret = 0;
287     size_t l, reallen;
288     int e;
289
290     e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Integer, &l);
291     if (e) return e;
292     p += l;
293     len -= l;
294     ret += l;
295
296     e = der_get_length (p, len, &reallen, &l);
297     if (e) return e;
298     p += l;
299     len -= l;
300     ret += l;
301     if (reallen > len)
302         return ASN1_OVERRUN;
303
304     e = der_get_int (p, reallen, num, &l);
305     if (e) return e;
306     p += l;
307     len -= l;
308     ret += l;
309     if(size) *size = ret;
310     return 0;
311 }
312
313 int
314 decode_unsigned (const unsigned char *p, size_t len,
315                  unsigned *num, size_t *size)
316 {
317     size_t ret = 0;
318     size_t l, reallen;
319     int e;
320
321     e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Integer, &l);
322     if (e) return e;
323     p += l;
324     len -= l;
325     ret += l;
326
327     e = der_get_length (p, len, &reallen, &l);
328     if (e) return e;
329     p += l;
330     len -= l;
331     ret += l;
332     if (reallen > len)
333         return ASN1_OVERRUN;
334
335     e = der_get_unsigned (p, reallen, num, &l);
336     if (e) return e;
337     p += l;
338     len -= l;
339     ret += l;
340     if(size) *size = ret;
341     return 0;
342 }
343
344 int
345 decode_enumerated (const unsigned char *p, size_t len,
346                    unsigned *num, size_t *size)
347 {
348     size_t ret = 0;
349     size_t l, reallen;
350     int e;
351
352     e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
353     if (e) return e;
354     p += l;
355     len -= l;
356     ret += l;
357
358     e = der_get_length (p, len, &reallen, &l);
359     if (e) return e;
360     p += l;
361     len -= l;
362     ret += l;
363     if (reallen > len)
364         return ASN1_OVERRUN;
365
366     e = der_get_int (p, reallen, num, &l);
367     if (e) return e;
368     p += l;
369     len -= l;
370     ret += l;
371     if(size) *size = ret;
372     return 0;
373 }
374
375 int
376 decode_general_string (const unsigned char *p, size_t len, 
377                        heim_general_string *str, size_t *size)
378 {
379     size_t ret = 0;
380     size_t l, reallen;
381     int e;
382
383     e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_GeneralString, &l);
384     if (e) return e;
385     p += l;
386     len -= l;
387     ret += l;
388
389     e = der_get_length (p, len, &reallen, &l);
390     if (e) return e;
391     p += l;
392     len -= l;
393     ret += l;
394     if (len < reallen)
395         return ASN1_OVERRUN;
396
397     e = der_get_general_string (p, reallen, str, &l);
398     if (e) return e;
399     p += l;
400     len -= l;
401     ret += l;
402     if(size) *size = ret;
403     return 0;
404 }
405
406 int
407 decode_octet_string (const unsigned char *p, size_t len, 
408                      heim_octet_string *k, size_t *size)
409 {
410     size_t ret = 0;
411     size_t l, reallen;
412     int e;
413
414     e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
415     if (e) return e;
416     p += l;
417     len -= l;
418     ret += l;
419
420     e = der_get_length (p, len, &reallen, &l);
421     if (e) return e;
422     p += l;
423     len -= l;
424     ret += l;
425     if (len < reallen)
426         return ASN1_OVERRUN;
427
428     e = der_get_octet_string (p, reallen, k, &l);
429     if (e) return e;
430     p += l;
431     len -= l;
432     ret += l;
433     if(size) *size = ret;
434     return 0;
435 }
436
437 int
438 decode_oid (const unsigned char *p, size_t len, 
439             heim_oid *k, size_t *size)
440 {
441     size_t ret = 0;
442     size_t l, reallen;
443     int e;
444
445     e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_OID, &l);
446     if (e) return e;
447     p += l;
448     len -= l;
449     ret += l;
450
451     e = der_get_length (p, len, &reallen, &l);
452     if (e) return e;
453     p += l;
454     len -= l;
455     ret += l;
456     if (len < reallen)
457         return ASN1_OVERRUN;
458
459     e = der_get_oid (p, reallen, k, &l);
460     if (e) return e;
461     p += l;
462     len -= l;
463     ret += l;
464     if(size) *size = ret;
465     return 0;
466 }
467
468 static void
469 generalizedtime2time (const char *s, time_t *t)
470 {
471     struct tm tm;
472
473     memset(&tm, 0, sizeof(tm));
474     sscanf (s, "%04d%02d%02d%02d%02d%02dZ",
475             &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
476             &tm.tm_min, &tm.tm_sec);
477     tm.tm_year -= 1900;
478     tm.tm_mon -= 1;
479     *t = timegm (&tm);
480 }
481
482 int
483 decode_generalized_time (const unsigned char *p, size_t len,
484                          time_t *t, size_t *size)
485 {
486     heim_octet_string k;
487     char *times;
488     size_t ret = 0;
489     size_t l, reallen;
490     int e;
491
492     e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_GeneralizedTime, &l);
493     if (e) return e;
494     p += l;
495     len -= l;
496     ret += l;
497
498     e = der_get_length (p, len, &reallen, &l);
499     if (e) return e;
500     p += l;
501     len -= l;
502     ret += l;
503     if (len < reallen)
504         return ASN1_OVERRUN;
505
506     e = der_get_octet_string (p, reallen, &k, &l);
507     if (e) return e;
508     p += l;
509     len -= l;
510     ret += l;
511     times = realloc(k.data, k.length + 1);
512     if (times == NULL){
513         free(k.data);
514         return ENOMEM;
515     }
516     times[k.length] = 0;
517     generalizedtime2time (times, t);
518     free (times);
519     if(size) *size = ret;
520     return 0;
521 }
522
523
524 int
525 fix_dce(size_t reallen, size_t *len)
526 {
527     if(reallen == ASN1_INDEFINITE)
528         return 1;
529     if(*len < reallen)
530         return -1;
531     *len = reallen;
532     return 0;
533 }