xref: /freebsd/crypto/heimdal/lib/asn1/der_get.c (revision 8373020d34ceb1ac55d8f43333c1ca3680185b39)
1 /*
2  * Copyright (c) 1997 - 2002 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.32 2002/08/22 19:11:07 assar 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_length (const unsigned char *p, size_t len,
81 		size_t *val, size_t *size)
82 {
83     size_t v;
84 
85     if (len <= 0)
86 	return ASN1_OVERRUN;
87     --len;
88     v = *p++;
89     if (v < 128) {
90 	*val = v;
91 	if(size) *size = 1;
92     } else {
93 	int e;
94 	size_t l;
95 	unsigned tmp;
96 
97 	if(v == 0x80){
98 	    *val = ASN1_INDEFINITE;
99 	    if(size) *size = 1;
100 	    return 0;
101 	}
102 	v &= 0x7F;
103 	if (len < v)
104 	    return ASN1_OVERRUN;
105 	e = der_get_unsigned (p, v, &tmp, &l);
106 	if(e) return e;
107 	*val = tmp;
108 	if(size) *size = l + 1;
109     }
110     return 0;
111 }
112 
113 int
114 der_get_general_string (const unsigned char *p, size_t len,
115 			general_string *str, size_t *size)
116 {
117     char *s;
118 
119     s = malloc (len + 1);
120     if (s == NULL)
121 	return ENOMEM;
122     memcpy (s, p, len);
123     s[len] = '\0';
124     *str = s;
125     if(size) *size = len;
126     return 0;
127 }
128 
129 int
130 der_get_octet_string (const unsigned char *p, size_t len,
131 		      octet_string *data, size_t *size)
132 {
133     data->length = len;
134     data->data = malloc(len);
135     if (data->data == NULL && data->length != 0)
136 	return ENOMEM;
137     memcpy (data->data, p, len);
138     if(size) *size = len;
139     return 0;
140 }
141 
142 int
143 der_get_oid (const unsigned char *p, size_t len,
144 	     oid *data, size_t *size)
145 {
146     int n;
147     size_t oldlen = len;
148 
149     if (len < 1)
150 	return ASN1_OVERRUN;
151 
152     data->components = malloc(len * sizeof(*data->components));
153     if (data->components == NULL && len != 0)
154 	return ENOMEM;
155     data->components[0] = (*p) / 40;
156     data->components[1] = (*p) % 40;
157     --len;
158     ++p;
159     for (n = 2; len > 0; ++n) {
160 	unsigned u = 0;
161 
162 	do {
163 	    --len;
164 	    u = u * 128 + (*p++ % 128);
165 	} while (len > 0 && p[-1] & 0x80);
166 	data->components[n] = u;
167     }
168     if (p[-1] & 0x80) {
169 	free_oid (data);
170 	return ASN1_OVERRUN;
171     }
172     data->length = n;
173     if (size)
174 	*size = oldlen;
175     return 0;
176 }
177 
178 int
179 der_get_tag (const unsigned char *p, size_t len,
180 	     Der_class *class, Der_type *type,
181 	     int *tag, size_t *size)
182 {
183     if (len < 1)
184 	return ASN1_OVERRUN;
185     *class = (Der_class)(((*p) >> 6) & 0x03);
186     *type = (Der_type)(((*p) >> 5) & 0x01);
187     *tag = (*p) & 0x1F;
188     if(size) *size = 1;
189     return 0;
190 }
191 
192 int
193 der_match_tag (const unsigned char *p, size_t len,
194 	       Der_class class, Der_type type,
195 	       int tag, size_t *size)
196 {
197     size_t l;
198     Der_class thisclass;
199     Der_type thistype;
200     int thistag;
201     int e;
202 
203     e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l);
204     if (e) return e;
205     if (class != thisclass || type != thistype)
206 	return ASN1_BAD_ID;
207     if(tag > thistag)
208 	return ASN1_MISPLACED_FIELD;
209     if(tag < thistag)
210 	return ASN1_MISSING_FIELD;
211     if(size) *size = l;
212     return 0;
213 }
214 
215 int
216 der_match_tag_and_length (const unsigned char *p, size_t len,
217 			  Der_class class, Der_type type, int tag,
218 			  size_t *length_ret, size_t *size)
219 {
220     size_t l, ret = 0;
221     int e;
222 
223     e = der_match_tag (p, len, class, type, tag, &l);
224     if (e) return e;
225     p += l;
226     len -= l;
227     ret += l;
228     e = der_get_length (p, len, length_ret, &l);
229     if (e) return e;
230     p += l;
231     len -= l;
232     ret += l;
233     if(size) *size = ret;
234     return 0;
235 }
236 
237 int
238 decode_integer (const unsigned char *p, size_t len,
239 		int *num, size_t *size)
240 {
241     size_t ret = 0;
242     size_t l, reallen;
243     int e;
244 
245     e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l);
246     if (e) return e;
247     p += l;
248     len -= l;
249     ret += l;
250     e = der_get_length (p, len, &reallen, &l);
251     if (e) return e;
252     p += l;
253     len -= l;
254     ret += l;
255     e = der_get_int (p, reallen, num, &l);
256     if (e) return e;
257     p += l;
258     len -= l;
259     ret += l;
260     if(size) *size = ret;
261     return 0;
262 }
263 
264 int
265 decode_unsigned (const unsigned char *p, size_t len,
266 		 unsigned *num, size_t *size)
267 {
268     size_t ret = 0;
269     size_t l, reallen;
270     int e;
271 
272     e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l);
273     if (e) return e;
274     p += l;
275     len -= l;
276     ret += l;
277     e = der_get_length (p, len, &reallen, &l);
278     if (e) return e;
279     p += l;
280     len -= l;
281     ret += l;
282     e = der_get_unsigned (p, reallen, num, &l);
283     if (e) return e;
284     p += l;
285     len -= l;
286     ret += l;
287     if(size) *size = ret;
288     return 0;
289 }
290 
291 int
292 decode_enumerated (const unsigned char *p, size_t len,
293 		   unsigned *num, size_t *size)
294 {
295     size_t ret = 0;
296     size_t l, reallen;
297     int e;
298 
299     e = der_match_tag (p, len, UNIV, PRIM, UT_Enumerated, &l);
300     if (e) return e;
301     p += l;
302     len -= l;
303     ret += l;
304     e = der_get_length (p, len, &reallen, &l);
305     if (e) return e;
306     p += l;
307     len -= l;
308     ret += l;
309     e = der_get_int (p, reallen, num, &l);
310     if (e) return e;
311     p += l;
312     len -= l;
313     ret += l;
314     if(size) *size = ret;
315     return 0;
316 }
317 
318 int
319 decode_general_string (const unsigned char *p, size_t len,
320 		       general_string *str, size_t *size)
321 {
322     size_t ret = 0;
323     size_t l;
324     int e;
325     size_t slen;
326 
327     e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralString, &l);
328     if (e) return e;
329     p += l;
330     len -= l;
331     ret += l;
332 
333     e = der_get_length (p, len, &slen, &l);
334     if (e) return e;
335     p += l;
336     len -= l;
337     ret += l;
338     if (len < slen)
339 	return ASN1_OVERRUN;
340 
341     e = der_get_general_string (p, slen, str, &l);
342     if (e) return e;
343     p += l;
344     len -= l;
345     ret += l;
346     if(size) *size = ret;
347     return 0;
348 }
349 
350 int
351 decode_octet_string (const unsigned char *p, size_t len,
352 		     octet_string *k, size_t *size)
353 {
354     size_t ret = 0;
355     size_t l;
356     int e;
357     size_t slen;
358 
359     e = der_match_tag (p, len, UNIV, PRIM, UT_OctetString, &l);
360     if (e) return e;
361     p += l;
362     len -= l;
363     ret += l;
364 
365     e = der_get_length (p, len, &slen, &l);
366     if (e) return e;
367     p += l;
368     len -= l;
369     ret += l;
370     if (len < slen)
371 	return ASN1_OVERRUN;
372 
373     e = der_get_octet_string (p, slen, k, &l);
374     if (e) return e;
375     p += l;
376     len -= l;
377     ret += l;
378     if(size) *size = ret;
379     return 0;
380 }
381 
382 int
383 decode_oid (const unsigned char *p, size_t len,
384 	    oid *k, size_t *size)
385 {
386     size_t ret = 0;
387     size_t l;
388     int e;
389     size_t slen;
390 
391     e = der_match_tag (p, len, UNIV, PRIM, UT_OID, &l);
392     if (e) return e;
393     p += l;
394     len -= l;
395     ret += l;
396 
397     e = der_get_length (p, len, &slen, &l);
398     if (e) return e;
399     p += l;
400     len -= l;
401     ret += l;
402     if (len < slen)
403 	return ASN1_OVERRUN;
404 
405     e = der_get_oid (p, slen, k, &l);
406     if (e) return e;
407     p += l;
408     len -= l;
409     ret += l;
410     if(size) *size = ret;
411     return 0;
412 }
413 
414 static void
415 generalizedtime2time (const char *s, time_t *t)
416 {
417     struct tm tm;
418 
419     memset(&tm, 0, sizeof(tm));
420     sscanf (s, "%04d%02d%02d%02d%02d%02dZ",
421 	    &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
422 	    &tm.tm_min, &tm.tm_sec);
423     tm.tm_year -= 1900;
424     tm.tm_mon -= 1;
425     *t = timegm (&tm);
426 }
427 
428 int
429 decode_generalized_time (const unsigned char *p, size_t len,
430 			 time_t *t, size_t *size)
431 {
432     octet_string k;
433     char *times;
434     size_t ret = 0;
435     size_t l;
436     int e;
437     size_t slen;
438 
439     e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralizedTime, &l);
440     if (e) return e;
441     p += l;
442     len -= l;
443     ret += l;
444 
445     e = der_get_length (p, len, &slen, &l);
446     if (e) return e;
447     p += l;
448     len -= l;
449     ret += l;
450     if (len < slen)
451 	return ASN1_OVERRUN;
452     e = der_get_octet_string (p, slen, &k, &l);
453     if (e) return e;
454     p += l;
455     len -= l;
456     ret += l;
457     times = realloc(k.data, k.length + 1);
458     if (times == NULL){
459 	free(k.data);
460 	return ENOMEM;
461     }
462     times[k.length] = 0;
463     generalizedtime2time (times, t);
464     free (times);
465     if(size) *size = ret;
466     return 0;
467 }
468 
469 
470 int
471 fix_dce(size_t reallen, size_t *len)
472 {
473     if(reallen == ASN1_INDEFINITE)
474 	return 1;
475     if(*len < reallen)
476 	return -1;
477     *len = reallen;
478     return 0;
479 }
480