xref: /freebsd/crypto/heimdal/lib/asn1/der_get.c (revision 5e9cd1ae3e10592ed70e7575551cba1bbab04d84)
1 /*
2  * Copyright (c) 1997 - 2000 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.28 2000/04/06 17:19:53 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_tag (const unsigned char *p, size_t len,
143 	     Der_class *class, Der_type *type,
144 	     int *tag, size_t *size)
145 {
146     if (len < 1)
147 	return ASN1_OVERRUN;
148     *class = (Der_class)(((*p) >> 6) & 0x03);
149     *type = (Der_type)(((*p) >> 5) & 0x01);
150     *tag = (*p) & 0x1F;
151     if(size) *size = 1;
152     return 0;
153 }
154 
155 int
156 der_match_tag (const unsigned char *p, size_t len,
157 	       Der_class class, Der_type type,
158 	       int tag, size_t *size)
159 {
160     size_t l;
161     Der_class thisclass;
162     Der_type thistype;
163     int thistag;
164     int e;
165 
166     e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l);
167     if (e) return e;
168     if (class != thisclass || type != thistype)
169 	return ASN1_BAD_ID;
170     if(tag > thistag)
171 	return ASN1_MISPLACED_FIELD;
172     if(tag < thistag)
173 	return ASN1_MISSING_FIELD;
174     if(size) *size = l;
175     return 0;
176 }
177 
178 int
179 der_match_tag_and_length (const unsigned char *p, size_t len,
180 			  Der_class class, Der_type type, int tag,
181 			  size_t *length_ret, size_t *size)
182 {
183     size_t l, ret = 0;
184     int e;
185 
186     e = der_match_tag (p, len, class, type, tag, &l);
187     if (e) return e;
188     p += l;
189     len -= l;
190     ret += l;
191     e = der_get_length (p, len, length_ret, &l);
192     if (e) return e;
193     p += l;
194     len -= l;
195     ret += l;
196     if(size) *size = ret;
197     return 0;
198 }
199 
200 int
201 decode_integer (const unsigned char *p, size_t len,
202 		int *num, size_t *size)
203 {
204     size_t ret = 0;
205     size_t l, reallen;
206     int e;
207 
208     e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l);
209     if (e) return e;
210     p += l;
211     len -= l;
212     ret += l;
213     e = der_get_length (p, len, &reallen, &l);
214     if (e) return e;
215     p += l;
216     len -= l;
217     ret += l;
218     e = der_get_int (p, reallen, num, &l);
219     if (e) return e;
220     p += l;
221     len -= l;
222     ret += l;
223     if(size) *size = ret;
224     return 0;
225 }
226 
227 int
228 decode_unsigned (const unsigned char *p, size_t len,
229 		 unsigned *num, size_t *size)
230 {
231     size_t ret = 0;
232     size_t l, reallen;
233     int e;
234 
235     e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l);
236     if (e) return e;
237     p += l;
238     len -= l;
239     ret += l;
240     e = der_get_length (p, len, &reallen, &l);
241     if (e) return e;
242     p += l;
243     len -= l;
244     ret += l;
245     e = der_get_unsigned (p, reallen, num, &l);
246     if (e) return e;
247     p += l;
248     len -= l;
249     ret += l;
250     if(size) *size = ret;
251     return 0;
252 }
253 
254 int
255 decode_general_string (const unsigned char *p, size_t len,
256 		       general_string *str, size_t *size)
257 {
258     size_t ret = 0;
259     size_t l;
260     int e;
261     size_t slen;
262 
263     e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralString, &l);
264     if (e) return e;
265     p += l;
266     len -= l;
267     ret += l;
268 
269     e = der_get_length (p, len, &slen, &l);
270     if (e) return e;
271     p += l;
272     len -= l;
273     ret += l;
274     if (len < slen)
275 	return ASN1_OVERRUN;
276 
277     e = der_get_general_string (p, slen, str, &l);
278     if (e) return e;
279     p += l;
280     len -= l;
281     ret += l;
282     if(size) *size = ret;
283     return 0;
284 }
285 
286 int
287 decode_octet_string (const unsigned char *p, size_t len,
288 		     octet_string *k, size_t *size)
289 {
290     size_t ret = 0;
291     size_t l;
292     int e;
293     size_t slen;
294 
295     e = der_match_tag (p, len, UNIV, PRIM, UT_OctetString, &l);
296     if (e) return e;
297     p += l;
298     len -= l;
299     ret += l;
300 
301     e = der_get_length (p, len, &slen, &l);
302     if (e) return e;
303     p += l;
304     len -= l;
305     ret += l;
306     if (len < slen)
307 	return ASN1_OVERRUN;
308 
309     e = der_get_octet_string (p, slen, k, &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 static void
319 generalizedtime2time (const char *s, time_t *t)
320 {
321     struct tm tm;
322 
323     memset(&tm, 0, sizeof(tm));
324     sscanf (s, "%04d%02d%02d%02d%02d%02dZ",
325 	    &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
326 	    &tm.tm_min, &tm.tm_sec);
327     tm.tm_year -= 1900;
328     tm.tm_mon -= 1;
329     *t = timegm (&tm);
330 }
331 
332 int
333 decode_generalized_time (const unsigned char *p, size_t len,
334 			 time_t *t, size_t *size)
335 {
336     octet_string k;
337     char *times;
338     size_t ret = 0;
339     size_t l;
340     int e;
341     size_t slen;
342 
343     e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralizedTime, &l);
344     if (e) return e;
345     p += l;
346     len -= l;
347     ret += l;
348 
349     e = der_get_length (p, len, &slen, &l);
350     if (e) return e;
351     p += l;
352     len -= l;
353     ret += l;
354     if (len < slen)
355 	return ASN1_OVERRUN;
356     e = der_get_octet_string (p, slen, &k, &l);
357     if (e) return e;
358     p += l;
359     len -= l;
360     ret += l;
361     times = realloc(k.data, k.length + 1);
362     if (times == NULL){
363 	free(k.data);
364 	return ENOMEM;
365     }
366     times[k.length] = 0;
367     generalizedtime2time (times, t);
368     free (times);
369     if(size) *size = ret;
370     return 0;
371 }
372 
373 
374 int
375 fix_dce(size_t reallen, size_t *len)
376 {
377     if(reallen == ASN1_INDEFINITE)
378 	return 1;
379     if(*len < reallen)
380 	return -1;
381     *len = reallen;
382     return 0;
383 }
384