xref: /freebsd/crypto/heimdal/lib/asn1/der_get.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
1 /*
2  * Copyright (c) 1997, 1998, 1999 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.27 1999/12/02 17:05:01 joda 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_general_string (const unsigned char *p, size_t len,
229 		       general_string *str, size_t *size)
230 {
231     size_t ret = 0;
232     size_t l;
233     int e;
234     size_t slen;
235 
236     e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralString, &l);
237     if (e) return e;
238     p += l;
239     len -= l;
240     ret += l;
241 
242     e = der_get_length (p, len, &slen, &l);
243     if (e) return e;
244     p += l;
245     len -= l;
246     ret += l;
247     if (len < slen)
248 	return ASN1_OVERRUN;
249 
250     e = der_get_general_string (p, slen, str, &l);
251     if (e) return e;
252     p += l;
253     len -= l;
254     ret += l;
255     if(size) *size = ret;
256     return 0;
257 }
258 
259 int
260 decode_octet_string (const unsigned char *p, size_t len,
261 		     octet_string *k, size_t *size)
262 {
263     size_t ret = 0;
264     size_t l;
265     int e;
266     size_t slen;
267 
268     e = der_match_tag (p, len, UNIV, PRIM, UT_OctetString, &l);
269     if (e) return e;
270     p += l;
271     len -= l;
272     ret += l;
273 
274     e = der_get_length (p, len, &slen, &l);
275     if (e) return e;
276     p += l;
277     len -= l;
278     ret += l;
279     if (len < slen)
280 	return ASN1_OVERRUN;
281 
282     e = der_get_octet_string (p, slen, k, &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 static void
292 generalizedtime2time (const char *s, time_t *t)
293 {
294     struct tm tm;
295 
296     memset(&tm, 0, sizeof(tm));
297     sscanf (s, "%04d%02d%02d%02d%02d%02dZ",
298 	    &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
299 	    &tm.tm_min, &tm.tm_sec);
300     tm.tm_year -= 1900;
301     tm.tm_mon -= 1;
302     *t = timegm (&tm);
303 }
304 
305 int
306 decode_generalized_time (const unsigned char *p, size_t len,
307 			 time_t *t, size_t *size)
308 {
309     octet_string k;
310     char *times;
311     size_t ret = 0;
312     size_t l;
313     int e;
314     size_t slen;
315 
316     e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralizedTime, &l);
317     if (e) return e;
318     p += l;
319     len -= l;
320     ret += l;
321 
322     e = der_get_length (p, len, &slen, &l);
323     if (e) return e;
324     p += l;
325     len -= l;
326     ret += l;
327     if (len < slen)
328 	return ASN1_OVERRUN;
329     e = der_get_octet_string (p, slen, &k, &l);
330     if (e) return e;
331     p += l;
332     len -= l;
333     ret += l;
334     times = realloc(k.data, k.length + 1);
335     if (times == NULL){
336 	free(k.data);
337 	return ENOMEM;
338     }
339     times[k.length] = 0;
340     generalizedtime2time (times, t);
341     free (times);
342     if(size) *size = ret;
343     return 0;
344 }
345 
346 
347 int
348 fix_dce(size_t reallen, size_t *len)
349 {
350     if(reallen == ASN1_INDEFINITE)
351 	return 1;
352     if(*len < reallen)
353 	return -1;
354     *len = reallen;
355     return 0;
356 }
357