52f645f3a36e0a09d7a7437b7f7202f8d8304562
[metze/heimdal/wip.git] / lib / asn1 / der_get.c
1 /*
2  * Copyright (c) 1997 - 2007 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 #include <vers.h>
37
38 /*
39  * All decoding functions take a pointer `p' to first position in
40  * which to read, from the left, `len' which means the maximum number
41  * of characters we are able to read, `ret' were the value will be
42  * returned and `size' where the number of used bytes is stored.
43  * Either 0 or an error code is returned.
44  */
45
46 int
47 der_get_unsigned (const unsigned char *p, size_t len,
48                   unsigned *ret, size_t *size)
49 {
50     unsigned val = 0;
51     size_t oldlen = len;
52
53     if (len == sizeof(unsigned) + 1 && p[0] == 0)
54         ;
55     else if (len > sizeof(unsigned))
56         return ASN1_OVERRUN;
57
58     while (len--)
59         val = val * 256 + *p++;
60     *ret = val;
61     if(size) *size = oldlen;
62     return 0;
63 }
64
65 int
66 der_get_integer (const unsigned char *p, size_t len,
67                  int *ret, size_t *size)
68 {
69     int val = 0;
70     size_t oldlen = len;
71
72     if (len > sizeof(int))
73         return ASN1_OVERRUN;
74
75     if (len > 0) {
76         val = (signed char)*p++;
77         while (--len)
78             val = val * 256 + *p++;
79     }
80     *ret = val;
81     if(size) *size = oldlen;
82     return 0;
83 }
84
85 int
86 der_get_length (const unsigned char *p, size_t len,
87                 size_t *val, size_t *size)
88 {
89     size_t v;
90
91     if (len <= 0)
92         return ASN1_OVERRUN;
93     --len;
94     v = *p++;
95     if (v < 128) {
96         *val = v;
97         if(size) *size = 1;
98     } else {
99         int e;
100         size_t l;
101         unsigned tmp;
102
103         if(v == 0x80){
104             *val = ASN1_INDEFINITE;
105             if(size) *size = 1;
106             return 0;
107         }
108         v &= 0x7F;
109         if (len < v)
110             return ASN1_OVERRUN;
111         e = der_get_unsigned (p, v, &tmp, &l);
112         if(e) return e;
113         *val = tmp;
114         if(size) *size = l + 1;
115     }
116     return 0;
117 }
118
119 int
120 der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size)
121 {
122     if(len < 1)
123         return ASN1_OVERRUN;
124     if(*p != 0)
125         *data = 1;
126     else
127         *data = 0;
128     *size = 1;
129     return 0;
130 }
131
132 int
133 der_get_general_string (const unsigned char *p, size_t len,
134                         heim_general_string *str, size_t *size)
135 {
136     const unsigned char *p1;
137     char *s;
138
139     p1 = memchr(p, 0, len);
140     if (p1 != NULL) {
141         /*
142          * Allow trailing NULs. We allow this since MIT Kerberos sends
143          * an strings in the NEED_PREAUTH case that includes a
144          * trailing NUL.
145          */
146         while (p1 - p < len && *p1 == '\0')
147             p1++;
148        if (p1 - p != len)
149             return ASN1_BAD_CHARACTER;
150     }
151     if (len > len + 1)
152         return ASN1_BAD_LENGTH;
153
154     s = malloc (len + 1);
155     if (s == NULL)
156         return ENOMEM;
157     memcpy (s, p, len);
158     s[len] = '\0';
159     *str = s;
160     if(size) *size = len;
161     return 0;
162 }
163
164 int
165 der_get_utf8string (const unsigned char *p, size_t len,
166                     heim_utf8_string *str, size_t *size)
167 {
168     return der_get_general_string(p, len, str, size);
169 }
170
171 int
172 der_get_printable_string (const unsigned char *p, size_t len,
173                           heim_printable_string *str, size_t *size)
174 {
175     return der_get_general_string(p, len, str, size);
176 }
177
178 int
179 der_get_ia5_string (const unsigned char *p, size_t len,
180                     heim_ia5_string *str, size_t *size)
181 {
182     return der_get_general_string(p, len, str, size);
183 }
184
185 int
186 der_get_bmp_string (const unsigned char *p, size_t len,
187                     heim_bmp_string *data, size_t *size)
188 {
189     size_t i;
190
191     if (len & 1)
192         return ASN1_BAD_FORMAT;
193     data->length = len / 2;
194     if (data->length > UINT_MAX/sizeof(data->data[0]))
195         return ERANGE;
196     data->data = malloc(data->length * sizeof(data->data[0]));
197     if (data->data == NULL && data->length != 0)
198         return ENOMEM;
199
200     for (i = 0; i < data->length; i++) {
201         data->data[i] = (p[0] << 8) | p[1];
202         p += 2;
203     }
204     if (size) *size = len;
205
206     return 0;
207 }
208
209 int
210 der_get_universal_string (const unsigned char *p, size_t len,
211                           heim_universal_string *data, size_t *size)
212 {
213     size_t i;
214
215     if (len & 3)
216         return ASN1_BAD_FORMAT;
217     data->length = len / 4;
218     if (data->length > UINT_MAX/sizeof(data->data[0]))
219         return ERANGE;
220     data->data = malloc(data->length * sizeof(data->data[0]));
221     if (data->data == NULL && data->length != 0)
222         return ENOMEM;
223
224     for (i = 0; i < data->length; i++) {
225         data->data[i] = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
226         p += 4;
227     }
228     if (size) *size = len;
229     return 0;
230 }
231
232 int
233 der_get_visible_string (const unsigned char *p, size_t len,
234                         heim_visible_string *str, size_t *size)
235 {
236     return der_get_general_string(p, len, str, size);
237 }
238
239 int
240 der_get_octet_string (const unsigned char *p, size_t len,
241                       heim_octet_string *data, size_t *size)
242 {
243     data->length = len;
244     data->data = malloc(len);
245     if (data->data == NULL && data->length != 0)
246         return ENOMEM;
247     memcpy (data->data, p, len);
248     if(size) *size = len;
249     return 0;
250 }
251
252 int
253 der_get_octet_string_ber (const unsigned char *p, size_t len,
254                           heim_octet_string *data, size_t *size)
255 {
256     int e;
257     Der_type type;
258     Der_class class;
259     unsigned int tag, depth = 0;
260     size_t l, datalen, oldlen = len;
261
262     data->length = 0;
263     data->data = NULL;
264
265     while (len) {
266         e = der_get_tag (p, len, &class, &type, &tag, &l);
267         if (e) goto out;
268         if (class != ASN1_C_UNIV) {
269             e = ASN1_BAD_ID; 
270             goto out; 
271         }
272         if (type == PRIM && tag == UT_EndOfContent) {
273             if (depth == 0)
274                 break;
275             depth--;
276         }
277         if (tag != UT_OctetString) {
278             e = ASN1_BAD_ID;
279             goto out;
280         }
281
282         p += l;
283         len -= l;
284         e = der_get_length (p, len, &datalen, &l);
285         if (e) goto out;
286         p += l;
287         len -= l;
288         
289         if (datalen > len)
290             return ASN1_OVERRUN;
291
292         if (type == PRIM) {
293             void *ptr;
294
295             ptr = realloc(data->data, data->length + datalen);
296             if (ptr == NULL) {
297                 e = ENOMEM;
298                 goto out;
299             }
300             data->data = ptr;
301             memcpy(((unsigned char *)data->data) + data->length, p, datalen);
302             data->length += datalen;
303         } else
304             depth++;
305
306         p += datalen;
307         len -= datalen;
308     }
309     if (depth != 0)
310         return ASN1_INDEF_OVERRUN;
311     if(size) *size = oldlen - len;
312     return 0;
313  out:
314     free(data->data);
315     data->data = NULL;
316     data->length = 0;
317     return e;
318 }
319
320
321 int
322 der_get_heim_integer (const unsigned char *p, size_t len,
323                       heim_integer *data, size_t *size)
324 {
325     data->length = 0;
326     data->negative = 0;
327     data->data = NULL;
328
329     if (len == 0) {
330         if (size)
331             *size = 0;
332         return 0;
333     }
334     if (p[0] & 0x80) {
335         unsigned char *q;
336         int carry = 1;
337         data->negative = 1;
338
339         data->length = len;
340
341         if (p[0] == 0xff) {
342             p++;
343             data->length--;
344         }
345         data->data = malloc(data->length);
346         if (data->data == NULL) {
347             data->length = 0;
348             if (size)
349                 *size = 0;
350             return ENOMEM;
351         }
352         q = &((unsigned char*)data->data)[data->length - 1];
353         p += data->length - 1;
354         while (q >= (unsigned char*)data->data) {
355             *q = *p ^ 0xff;
356             if (carry)
357                 carry = !++*q;
358             p--;
359             q--;
360         }
361     } else {
362         data->negative = 0;
363         data->length = len;
364
365         if (p[0] == 0) {
366             p++;
367             data->length--;
368         }
369         data->data = malloc(data->length);
370         if (data->data == NULL && data->length != 0) {
371             data->length = 0;
372             if (size)
373                 *size = 0;
374             return ENOMEM;
375         }
376         memcpy(data->data, p, data->length);
377     }
378     if (size)
379         *size = len;
380     return 0;
381 }
382
383 static int
384 generalizedtime2time (const char *s, time_t *t)
385 {
386     struct tm tm;
387
388     memset(&tm, 0, sizeof(tm));
389     if (sscanf (s, "%04d%02d%02d%02d%02d%02dZ",
390                 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
391                 &tm.tm_min, &tm.tm_sec) != 6) {
392         if (sscanf (s, "%02d%02d%02d%02d%02d%02dZ",
393                     &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
394                     &tm.tm_min, &tm.tm_sec) != 6)
395             return ASN1_BAD_TIMEFORMAT;
396         if (tm.tm_year < 50)
397             tm.tm_year += 2000;
398         else
399             tm.tm_year += 1900;
400     }
401     tm.tm_year -= 1900;
402     tm.tm_mon -= 1;
403     *t = _der_timegm (&tm);
404     return 0;
405 }
406
407 static int
408 der_get_time (const unsigned char *p, size_t len,
409               time_t *data, size_t *size)
410 {
411     char *times;
412     int e;
413
414     if (len > len + 1 || len == 0)
415         return ASN1_BAD_LENGTH;
416
417     times = malloc(len + 1);
418     if (times == NULL)
419         return ENOMEM;
420     memcpy(times, p, len);
421     times[len] = '\0';
422     e = generalizedtime2time(times, data);
423     free (times);
424     if(size) *size = len;
425     return e;
426 }
427
428 int
429 der_get_generalized_time (const unsigned char *p, size_t len,
430                           time_t *data, size_t *size)
431 {
432     return der_get_time(p, len, data, size);
433 }
434
435 int
436 der_get_utctime (const unsigned char *p, size_t len,
437                           time_t *data, size_t *size)
438 {
439     return der_get_time(p, len, data, size);
440 }
441
442 int
443 der_get_oid (const unsigned char *p, size_t len,
444              heim_oid *data, size_t *size)
445 {
446     size_t n;
447     size_t oldlen = len;
448
449     if (len < 1)
450         return ASN1_OVERRUN;
451
452     if (len > len + 1)
453         return ASN1_BAD_LENGTH;
454
455     if (len + 1 > UINT_MAX/sizeof(data->components[0]))
456         return ERANGE;
457
458     data->components = malloc((len + 1) * sizeof(data->components[0]));
459     if (data->components == NULL)
460         return ENOMEM;
461     data->components[0] = (*p) / 40;
462     data->components[1] = (*p) % 40;
463     --len;
464     ++p;
465     for (n = 2; len > 0; ++n) {
466         unsigned u = 0, u1;
467         
468         do {
469             --len;
470             u1 = u * 128 + (*p++ % 128);
471             /* check that we don't overflow the element */
472             if (u1 < u) {
473                 der_free_oid(data);
474                 return ASN1_OVERRUN;
475             }
476             u = u1;
477         } while (len > 0 && p[-1] & 0x80);
478         data->components[n] = u;
479     }
480     if (n > 2 && p[-1] & 0x80) {
481         der_free_oid (data);
482         return ASN1_OVERRUN;
483     }
484     data->length = n;
485     if (size)
486         *size = oldlen;
487     return 0;
488 }
489
490 int
491 der_get_tag (const unsigned char *p, size_t len,
492              Der_class *class, Der_type *type,
493              unsigned int *tag, size_t *size)
494 {
495     size_t ret = 0;
496     if (len < 1)
497         return ASN1_OVERRUN;
498     *class = (Der_class)(((*p) >> 6) & 0x03);
499     *type = (Der_type)(((*p) >> 5) & 0x01);
500     *tag = (*p) & 0x1f;
501     p++; len--; ret++;
502     if(*tag == 0x1f) {
503         unsigned int continuation;
504         unsigned int tag1;
505         *tag = 0;
506         do {
507             if(len < 1)
508                 return ASN1_OVERRUN;
509             continuation = *p & 128;
510             tag1 = *tag * 128 + (*p % 128);
511             /* check that we don't overflow the tag */
512             if (tag1 < *tag)
513                 return ASN1_OVERFLOW;
514             *tag = tag1;
515             p++; len--; ret++;
516         } while(continuation);
517     }
518     if(size) *size = ret;
519     return 0;
520 }
521
522 int
523 der_match_tag (const unsigned char *p, size_t len,
524                Der_class class, Der_type type,
525                unsigned int tag, size_t *size)
526 {
527     Der_type thistype;
528     int e;
529
530     e = der_match_tag2(p, len, class, &thistype, tag, size);
531     if (e) return e;
532     if (thistype != type) return ASN1_BAD_ID;
533     return 0;
534 }
535
536 int
537 der_match_tag2 (const unsigned char *p, size_t len,
538                 Der_class class, Der_type *type,
539                 unsigned int tag, size_t *size)
540 {
541     size_t l;
542     Der_class thisclass;
543     unsigned int thistag;
544     int e;
545
546     e = der_get_tag (p, len, &thisclass, type, &thistag, &l);
547     if (e) return e;
548     if (class != thisclass)
549         return ASN1_BAD_ID;
550     if(tag > thistag)
551         return ASN1_MISPLACED_FIELD;
552     if(tag < thistag)
553         return ASN1_MISSING_FIELD;
554     if(size) *size = l;
555     return 0;
556 }
557
558 int
559 der_match_tag_and_length (const unsigned char *p, size_t len,
560                           Der_class class, Der_type *type, unsigned int tag,
561                           size_t *length_ret, size_t *size)
562 {
563     size_t l, ret = 0;
564     int e;
565
566     e = der_match_tag2 (p, len, class, type, tag, &l);
567     if (e) return e;
568     p += l;
569     len -= l;
570     ret += l;
571     e = der_get_length (p, len, length_ret, &l);
572     if (e) return e;
573     p += l;
574     len -= l;
575     ret += l;
576     if(size) *size = ret;
577     return 0;
578 }
579
580
581
582 /*
583  * Old versions of DCE was based on a very early beta of the MIT code,
584  * which used MAVROS for ASN.1 encoding. MAVROS had the interesting
585  * feature that it encoded data in the forward direction, which has
586  * it's problems, since you have no idea how long the data will be
587  * until after you're done. MAVROS solved this by reserving one byte
588  * for length, and later, if the actual length was longer, it reverted
589  * to indefinite, BER style, lengths. The version of MAVROS used by
590  * the DCE people could apparently generate correct X.509 DER encodings, and
591  * did this by making space for the length after encoding, but
592  * unfortunately this feature wasn't used with Kerberos.
593  */
594
595 int
596 _heim_fix_dce(size_t reallen, size_t *len)
597 {
598     if(reallen == ASN1_INDEFINITE)
599         return 1;
600     if(*len < reallen)
601         return -1;
602     *len = reallen;
603     return 0;
604 }
605
606 int
607 der_get_bit_string (const unsigned char *p, size_t len,
608                     heim_bit_string *data, size_t *size)
609 {
610     if (len < 1)
611         return ASN1_OVERRUN;
612     if (p[0] > 7)
613         return ASN1_BAD_FORMAT;
614     if (len - 1 == 0 && p[0] != 0)
615         return ASN1_BAD_FORMAT;
616     /* check if any of the three upper bits are set
617      * any of them will cause a interger overrun */
618     if ((len - 1) >> (sizeof(len) * 8 - 3))
619         return ASN1_OVERRUN;
620     data->length = (len - 1) * 8;
621     data->data = malloc(len - 1);
622     if (data->data == NULL && (len - 1) != 0)
623         return ENOMEM;
624     /* copy data is there is data to copy */
625     if (len - 1 != 0) {
626       memcpy (data->data, p + 1, len - 1);
627       data->length -= p[0];
628     }
629     if(size) *size = len;
630     return 0;
631 }