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