xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/asn1/template.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1 /*	$NetBSD: template.c,v 1.2 2017/01/28 21:31:45 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2009 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Portions Copyright (c) 2009 - 2010 Apple Inc. All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * 3. Neither the name of the Institute nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include "der_locl.h"
39 #include <krb5/com_err.h>
40 
41 struct asn1_type_func asn1_template_prim[A1T_NUM_ENTRY] = {
42 #define el(name, type) {				\
43 	(asn1_type_encode)der_put_##name,		\
44 	(asn1_type_decode)der_get_##name,		\
45 	(asn1_type_length)der_length_##name,		\
46 	(asn1_type_copy)der_copy_##name,		\
47 	(asn1_type_release)der_free_##name,		\
48 	sizeof(type)					\
49     }
50 #define elber(name, type) {				\
51 	(asn1_type_encode)der_put_##name,		\
52 	(asn1_type_decode)der_get_##name##_ber,		\
53 	(asn1_type_length)der_length_##name,		\
54 	(asn1_type_copy)der_copy_##name,		\
55 	(asn1_type_release)der_free_##name,		\
56 	sizeof(type)					\
57     }
58     el(integer, int),
59     el(heim_integer, heim_integer),
60     el(integer, int),
61     el(integer64, int64_t),
62     el(unsigned, unsigned),
63     el(unsigned64, uint64_t),
64     el(general_string, heim_general_string),
65     el(octet_string, heim_octet_string),
66     elber(octet_string, heim_octet_string),
67     el(ia5_string, heim_ia5_string),
68     el(bmp_string, heim_bmp_string),
69     el(universal_string, heim_universal_string),
70     el(printable_string, heim_printable_string),
71     el(visible_string, heim_visible_string),
72     el(utf8string, heim_utf8_string),
73     el(generalized_time, time_t),
74     el(utctime, time_t),
75     el(bit_string, heim_bit_string),
76     { (asn1_type_encode)der_put_boolean, (asn1_type_decode)der_get_boolean,
77       (asn1_type_length)der_length_boolean, (asn1_type_copy)der_copy_integer,
78       (asn1_type_release)der_free_integer, sizeof(int)
79     },
80     el(oid, heim_oid),
81     el(general_string, heim_general_string),
82 #undef el
83 #undef elber
84 };
85 
86 size_t
_asn1_sizeofType(const struct asn1_template * t)87 _asn1_sizeofType(const struct asn1_template *t)
88 {
89     return t->offset;
90 }
91 
92 /*
93  * Here is abstraction to not so well evil fact of bit fields in C,
94  * they are endian dependent, so when getting and setting bits in the
95  * host local structure we need to know the endianness of the host.
96  *
97  * Its not the first time in Heimdal this have bitten us, and some day
98  * we'll grow up and use #defined constant, but bit fields are still
99  * so pretty and shiny.
100  */
101 
102 static void
_asn1_bmember_get_bit(const unsigned char * p,void * data,unsigned int bit,size_t size)103 _asn1_bmember_get_bit(const unsigned char *p, void *data,
104 		      unsigned int bit, size_t size)
105 {
106     unsigned int localbit = bit % 8;
107     if ((*p >> (7 - localbit)) & 1) {
108 #ifdef WORDS_BIGENDIAN
109 	*(unsigned int *)data |= (1 << ((size * 8) - bit - 1));
110 #else
111 	*(unsigned int *)data |= (1 << bit);
112 #endif
113     }
114 }
115 
116 int
_asn1_bmember_isset_bit(const void * data,unsigned int bit,size_t size)117 _asn1_bmember_isset_bit(const void *data, unsigned int bit, size_t size)
118 {
119 #ifdef WORDS_BIGENDIAN
120     if ((*(unsigned int *)data) & (1 << ((size * 8) - bit - 1)))
121 	return 1;
122     return 0;
123 #else
124     if ((*(unsigned int *)data) & (1 << bit))
125 	return 1;
126     return 0;
127 #endif
128 }
129 
130 void
_asn1_bmember_put_bit(unsigned char * p,const void * data,unsigned int bit,size_t size,unsigned int * bitset)131 _asn1_bmember_put_bit(unsigned char *p, const void *data, unsigned int bit,
132 		      size_t size, unsigned int *bitset)
133 {
134     unsigned int localbit = bit % 8;
135 
136     if (_asn1_bmember_isset_bit(data, bit, size)) {
137 	*p |= (1 << (7 - localbit));
138 	if (*bitset == 0)
139 	    *bitset = (7 - localbit) + 1;
140     }
141 }
142 
143 int
_asn1_decode(const struct asn1_template * t,unsigned flags,const unsigned char * p,size_t len,void * data,size_t * size)144 _asn1_decode(const struct asn1_template *t, unsigned flags,
145 	     const unsigned char *p, size_t len, void *data, size_t *size)
146 {
147     size_t elements = A1_HEADER_LEN(t);
148     size_t oldlen = len;
149     int ret = 0;
150     const unsigned char *startp = NULL;
151     unsigned int template_flags = t->tt;
152 
153     /* skip over header */
154     t++;
155 
156     if (template_flags & A1_HF_PRESERVE)
157 	startp = p;
158 
159     while (elements) {
160 	switch (t->tt & A1_OP_MASK) {
161 	case A1_OP_TYPE:
162 	case A1_OP_TYPE_EXTERN: {
163 	    size_t newsize, elsize;
164 	    void *el = DPO(data, t->offset);
165 	    void **pel = (void **)el;
166 
167 	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
168 		elsize = _asn1_sizeofType(t->ptr);
169 	    } else {
170 		const struct asn1_type_func *f = t->ptr;
171 		elsize = f->size;
172 	    }
173 
174 	    if (t->tt & A1_FLAG_OPTIONAL) {
175 		*pel = calloc(1, elsize);
176 		if (*pel == NULL)
177 		    return ENOMEM;
178 		el = *pel;
179 	    }
180 	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
181 		ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
182 	    } else {
183 		const struct asn1_type_func *f = t->ptr;
184 		ret = (f->decode)(p, len, el, &newsize);
185 	    }
186 	    if (ret) {
187 		if (t->tt & A1_FLAG_OPTIONAL) {
188 		    free(*pel);
189 		    *pel = NULL;
190 		    break;
191 		}
192 		return ret;
193 	    }
194 	    p += newsize; len -= newsize;
195 
196 	    break;
197 	}
198 	case A1_OP_TAG: {
199 	    Der_type dertype;
200 	    size_t newsize;
201 	    size_t datalen, l;
202 	    void *olddata = data;
203 	    int is_indefinite = 0;
204 	    int subflags = flags;
205 
206 	    ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt),
207 					   &dertype, A1_TAG_TAG(t->tt),
208 					   &datalen, &l);
209 	    if (ret) {
210 		if (t->tt & A1_FLAG_OPTIONAL)
211 		    break;
212 		return ret;
213 	    }
214 
215 	    p += l; len -= l;
216 
217 	    /*
218 	     * Only allow indefinite encoding for OCTET STRING and BER
219 	     * for now. Should handle BIT STRING too.
220 	     */
221 
222 	    if (dertype != A1_TAG_TYPE(t->tt) && (flags & A1_PF_ALLOW_BER)) {
223 		const struct asn1_template *subtype = t->ptr;
224 		subtype++; /* skip header */
225 
226 		if (((subtype->tt & A1_OP_MASK) == A1_OP_PARSE) &&
227 		    A1_PARSE_TYPE(subtype->tt) == A1T_OCTET_STRING)
228 		    subflags |= A1_PF_INDEFINTE;
229 	    }
230 
231 	    if (datalen == ASN1_INDEFINITE) {
232 		if ((flags & A1_PF_ALLOW_BER) == 0)
233 		    return ASN1_GOT_BER;
234 		is_indefinite = 1;
235 		datalen = len;
236 		if (datalen < 2)
237 		    return ASN1_OVERRUN;
238 		/* hide EndOfContent for sub-decoder, catching it below */
239 		datalen -= 2;
240 	    } else if (datalen > len)
241 		return ASN1_OVERRUN;
242 
243 	    data = DPO(data, t->offset);
244 
245 	    if (t->tt & A1_FLAG_OPTIONAL) {
246 		void **el = (void **)data;
247 		size_t ellen = _asn1_sizeofType(t->ptr);
248 
249 		*el = calloc(1, ellen);
250 		if (*el == NULL)
251 		    return ENOMEM;
252 		data = *el;
253 	    }
254 
255 	    ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize);
256 	    if (ret)
257 		return ret;
258 
259 	    if (is_indefinite) {
260 		/* If we use indefinite encoding, the newsize is the datasize. */
261 		datalen = newsize;
262 	    } else if (newsize != datalen) {
263 		/* Check for hidden data that might be after the real tag */
264 		return ASN1_EXTRA_DATA;
265 	    }
266 
267 	    len -= datalen;
268 	    p += datalen;
269 
270 	    /*
271 	     * Indefinite encoding needs a trailing EndOfContent,
272 	     * check for that.
273 	     */
274 	    if (is_indefinite) {
275 		ret = der_match_tag_and_length(p, len, ASN1_C_UNIV,
276 					       &dertype, UT_EndOfContent,
277 					       &datalen, &l);
278 		if (ret)
279 		    return ret;
280 		if (dertype != PRIM)
281 		    return ASN1_BAD_ID;
282 		if (datalen != 0)
283 		    return ASN1_INDEF_EXTRA_DATA;
284 		p += l; len -= l;
285 	    }
286 	    data = olddata;
287 
288 	    break;
289 	}
290 	case A1_OP_PARSE: {
291 	    unsigned int type = A1_PARSE_TYPE(t->tt);
292 	    size_t newsize;
293 	    void *el = DPO(data, t->offset);
294 
295 	    /*
296 	     * INDEFINITE primitive types are one element after the
297 	     * same type but non-INDEFINITE version.
298 	    */
299 	    if (flags & A1_PF_INDEFINTE)
300 		type++;
301 
302 	    if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
303 		ABORT_ON_ERROR();
304 		return ASN1_PARSE_ERROR;
305 	    }
306 
307 	    ret = (asn1_template_prim[type].decode)(p, len, el, &newsize);
308 	    if (ret)
309 		return ret;
310 	    p += newsize; len -= newsize;
311 
312 	    break;
313 	}
314 	case A1_OP_SETOF:
315 	case A1_OP_SEQOF: {
316 	    struct template_of *el = DPO(data, t->offset);
317 	    size_t newsize;
318 	    size_t ellen = _asn1_sizeofType(t->ptr);
319 	    size_t vallength = 0;
320 
321 	    while (len > 0) {
322 		void *tmp;
323 		size_t newlen = vallength + ellen;
324 		if (vallength > newlen)
325 		    return ASN1_OVERFLOW;
326 
327 		tmp = realloc(el->val, newlen);
328 		if (tmp == NULL)
329 		    return ENOMEM;
330 
331 		memset(DPO(tmp, vallength), 0, ellen);
332 		el->val = tmp;
333 
334 		ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len,
335 				   DPO(el->val, vallength), &newsize);
336 		if (ret)
337 		    return ret;
338 		vallength = newlen;
339 		el->len++;
340 		p += newsize; len -= newsize;
341 	    }
342 
343 	    break;
344 	}
345 	case A1_OP_BMEMBER: {
346 	    const struct asn1_template *bmember = t->ptr;
347 	    size_t bsize = bmember->offset;
348 	    size_t belements = A1_HEADER_LEN(bmember);
349 	    size_t pos = 0;
350 
351 	    bmember++;
352 
353 	    memset(data, 0, bsize);
354 
355 	    if (len < 1)
356 		return ASN1_OVERRUN;
357 	    p++; len--;
358 
359 	    while (belements && len) {
360 		while (bmember->offset / 8 > pos / 8) {
361 		    if (len < 1)
362 			break;
363 		    p++; len--;
364 		    pos += 8;
365 		}
366 		if (len) {
367 		    _asn1_bmember_get_bit(p, data, bmember->offset, bsize);
368 		    belements--; bmember++;
369 		}
370 	    }
371 	    len = 0;
372 	    break;
373 	}
374 	case A1_OP_CHOICE: {
375 	    const struct asn1_template *choice = t->ptr;
376 	    unsigned int *element = DPO(data, choice->offset);
377 	    size_t datalen;
378 	    unsigned int i;
379 
380 	    /* provide a saner value as default, we should have a NO element value */
381 	    *element = 1;
382 
383 	    for (i = 1; i < A1_HEADER_LEN(choice) + 1; i++) {
384 		/* should match first tag instead, store it in choice.tt */
385 		ret = _asn1_decode(choice[i].ptr, 0, p, len,
386 				   DPO(data, choice[i].offset), &datalen);
387 		if (ret == 0) {
388 		    *element = i;
389 		    p += datalen; len -= datalen;
390 		    break;
391 		} else if (ret != ASN1_BAD_ID && ret != ASN1_MISPLACED_FIELD && ret != ASN1_MISSING_FIELD) {
392 		    return ret;
393 		}
394 	    }
395 	    if (i >= A1_HEADER_LEN(choice) + 1) {
396 		if (choice->tt == 0)
397 		    return ASN1_BAD_ID;
398 
399 		*element = 0;
400 		ret = der_get_octet_string(p, len,
401 					   DPO(data, choice->tt), &datalen);
402 		if (ret)
403 		    return ret;
404 		p += datalen; len -= datalen;
405 	    }
406 
407 	    break;
408 	}
409 	default:
410 	    ABORT_ON_ERROR();
411 	    return ASN1_PARSE_ERROR;
412 	}
413 	t++;
414 	elements--;
415     }
416     /* if we are using padding, eat up read of context */
417     if (template_flags & A1_HF_ELLIPSIS)
418 	len = 0;
419 
420     oldlen -= len;
421 
422     if (size)
423 	*size = oldlen;
424 
425     /*
426      * saved the raw bits if asked for it, useful for signature
427      * verification.
428      */
429     if (startp) {
430 	heim_octet_string *save = data;
431 
432 	save->data = malloc(oldlen);
433 	if (save->data == NULL)
434 	    return ENOMEM;
435 	else {
436 	    save->length = oldlen;
437 	    memcpy(save->data, startp, oldlen);
438 	}
439     }
440     return 0;
441 }
442 
443 int
_asn1_encode(const struct asn1_template * t,unsigned char * p,size_t len,const void * data,size_t * size)444 _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const void *data, size_t *size)
445 {
446     size_t elements = A1_HEADER_LEN(t);
447     int ret = 0;
448     size_t oldlen = len;
449 
450     t += A1_HEADER_LEN(t);
451 
452     while (elements) {
453 	switch (t->tt & A1_OP_MASK) {
454 	case A1_OP_TYPE:
455 	case A1_OP_TYPE_EXTERN: {
456 	    size_t newsize;
457 	    const void *el = DPOC(data, t->offset);
458 
459 	    if (t->tt & A1_FLAG_OPTIONAL) {
460 		void **pel = (void **)el;
461 		if (*pel == NULL)
462 		    break;
463 		el = *pel;
464 	    }
465 
466 	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
467 		ret = _asn1_encode(t->ptr, p, len, el, &newsize);
468 	    } else {
469 		const struct asn1_type_func *f = t->ptr;
470 		ret = (f->encode)(p, len, el, &newsize);
471 	    }
472 
473 	    if (ret)
474 		return ret;
475 	    p -= newsize; len -= newsize;
476 
477 	    break;
478 	}
479 	case A1_OP_TAG: {
480 	    const void *olddata = data;
481 	    size_t l, datalen;
482 
483 	    data = DPOC(data, t->offset);
484 
485 	    if (t->tt & A1_FLAG_OPTIONAL) {
486 		void **el = (void **)data;
487 		if (*el == NULL) {
488 		    data = olddata;
489 		    break;
490 		}
491 		data = *el;
492 	    }
493 
494 	    ret = _asn1_encode(t->ptr, p, len, data, &datalen);
495 	    if (ret)
496 		return ret;
497 
498 	    len -= datalen; p -= datalen;
499 
500 	    ret = der_put_length_and_tag(p, len, datalen,
501 					 A1_TAG_CLASS(t->tt),
502 					 A1_TAG_TYPE(t->tt),
503 					 A1_TAG_TAG(t->tt), &l);
504 	    if (ret)
505 		return ret;
506 
507 	    p -= l; len -= l;
508 
509 	    data = olddata;
510 
511 	    break;
512 	}
513 	case A1_OP_PARSE: {
514 	    unsigned int type = A1_PARSE_TYPE(t->tt);
515 	    size_t newsize;
516 	    const void *el = DPOC(data, t->offset);
517 
518 	    if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
519 		ABORT_ON_ERROR();
520 		return ASN1_PARSE_ERROR;
521 	    }
522 
523 	    ret = (asn1_template_prim[type].encode)(p, len, el, &newsize);
524 	    if (ret)
525 		return ret;
526 	    p -= newsize; len -= newsize;
527 
528 	    break;
529 	}
530 	case A1_OP_SETOF: {
531 	    const struct template_of *el = DPOC(data, t->offset);
532 	    size_t ellen = _asn1_sizeofType(t->ptr);
533 	    heim_octet_string *val;
534 	    unsigned char *elptr = el->val;
535 	    size_t i, totallen;
536 
537 	    if (el->len == 0)
538 		break;
539 
540 	    if (el->len > UINT_MAX/sizeof(val[0]))
541 		return ERANGE;
542 
543 	    val = calloc(el->len, sizeof(val[0]));
544 	    if (val == NULL)
545 		return ENOMEM;
546 
547 	    for(totallen = 0, i = 0; i < el->len; i++) {
548 		unsigned char *next;
549 		size_t l;
550 
551 		val[i].length = _asn1_length(t->ptr, elptr);
552 		if (val[i].length) {
553 		    val[i].data = malloc(val[i].length);
554 		    if (val[i].data == NULL) {
555 			ret = ENOMEM;
556 			break;
557 		    }
558 		}
559 
560 		ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1),
561 				   val[i].length, elptr, &l);
562 		if (ret)
563 		    break;
564 
565 		next = elptr + ellen;
566 		if (next < elptr) {
567 		    ret = ASN1_OVERFLOW;
568 		    break;
569 		}
570 		elptr = next;
571 		totallen += val[i].length;
572 	    }
573 	    if (ret == 0 && totallen > len)
574 		ret = ASN1_OVERFLOW;
575 	    if (ret) {
576 		for (i = 0; i < el->len; i++)
577 		    free(val[i].data);
578 		free(val);
579 		return ret;
580 	    }
581 
582 	    len -= totallen;
583 
584 	    qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort);
585 
586 	    i = el->len - 1;
587 	    do {
588 		p -= val[i].length;
589 		memcpy(p + 1, val[i].data, val[i].length);
590 		free(val[i].data);
591 	    } while(i-- > 0);
592 	    free(val);
593 
594 	    break;
595 
596 	}
597 	case A1_OP_SEQOF: {
598 	    struct template_of *el = DPO(data, t->offset);
599 	    size_t ellen = _asn1_sizeofType(t->ptr);
600 	    size_t newsize;
601 	    unsigned int i;
602 	    unsigned char *elptr = el->val;
603 
604 	    if (el->len == 0)
605 		break;
606 
607 	    elptr += ellen * (el->len - 1);
608 
609 	    for (i = 0; i < el->len; i++) {
610 		ret = _asn1_encode(t->ptr, p, len,
611 				   elptr,
612 				   &newsize);
613 		if (ret)
614 		    return ret;
615 		p -= newsize; len -= newsize;
616 		elptr -= ellen;
617 	    }
618 
619 	    break;
620 	}
621 	case A1_OP_BMEMBER: {
622 	    const struct asn1_template *bmember = t->ptr;
623 	    size_t bsize = bmember->offset;
624 	    size_t belements = A1_HEADER_LEN(bmember);
625 	    size_t pos;
626 	    unsigned char c = 0;
627 	    unsigned int bitset = 0;
628 	    int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
629 
630 	    bmember += belements;
631 
632 	    if (rfc1510)
633 		pos = 31;
634 	    else
635 		pos = bmember->offset;
636 
637 	    while (belements && len) {
638 		while (bmember->offset / 8 < pos / 8) {
639 		    if (rfc1510 || bitset || c) {
640 			if (len < 1)
641 			    return ASN1_OVERFLOW;
642 			*p-- = c; len--;
643 		    }
644 		    c = 0;
645 		    pos -= 8;
646 		}
647 		_asn1_bmember_put_bit(&c, data, bmember->offset, bsize, &bitset);
648 		belements--; bmember--;
649 	    }
650 	    if (rfc1510 || bitset) {
651 		if (len < 1)
652 		    return ASN1_OVERFLOW;
653 		*p-- = c; len--;
654 	    }
655 
656 	    if (len < 1)
657 		return ASN1_OVERFLOW;
658 	    if (rfc1510 || bitset == 0)
659 		*p-- = 0;
660 	    else
661 		*p-- = bitset - 1;
662 
663 	    len--;
664 
665 	    break;
666 	}
667 	case A1_OP_CHOICE: {
668 	    const struct asn1_template *choice = t->ptr;
669 	    const unsigned int *element = DPOC(data, choice->offset);
670 	    size_t datalen;
671 	    const void *el;
672 
673 	    if (*element > A1_HEADER_LEN(choice)) {
674 		printf("element: %d\n", *element);
675 		return ASN1_PARSE_ERROR;
676 	    }
677 
678 	    if (*element == 0) {
679 		ret += der_put_octet_string(p, len,
680 					    DPOC(data, choice->tt), &datalen);
681 	    } else {
682 		choice += *element;
683 		el = DPOC(data, choice->offset);
684 		ret = _asn1_encode(choice->ptr, p, len, el, &datalen);
685 		if (ret)
686 		    return ret;
687 	    }
688 	    len -= datalen; p -= datalen;
689 
690 	    break;
691 	}
692 	default:
693 	    ABORT_ON_ERROR();
694 	}
695 	t--;
696 	elements--;
697     }
698     if (size)
699 	*size = oldlen - len;
700 
701     return 0;
702 }
703 
704 size_t
_asn1_length(const struct asn1_template * t,const void * data)705 _asn1_length(const struct asn1_template *t, const void *data)
706 {
707     size_t elements = A1_HEADER_LEN(t);
708     size_t ret = 0;
709 
710     t += A1_HEADER_LEN(t);
711 
712     while (elements) {
713 	switch (t->tt & A1_OP_MASK) {
714 	case A1_OP_TYPE:
715 	case A1_OP_TYPE_EXTERN: {
716 	    const void *el = DPOC(data, t->offset);
717 
718 	    if (t->tt & A1_FLAG_OPTIONAL) {
719 		void **pel = (void **)el;
720 		if (*pel == NULL)
721 		    break;
722 		el = *pel;
723 	    }
724 
725 	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
726 		ret += _asn1_length(t->ptr, el);
727 	    } else {
728 		const struct asn1_type_func *f = t->ptr;
729 		ret += (f->length)(el);
730 	    }
731 	    break;
732 	}
733 	case A1_OP_TAG: {
734 	    size_t datalen;
735 	    const void *olddata = data;
736 
737 	    data = DPO(data, t->offset);
738 
739 	    if (t->tt & A1_FLAG_OPTIONAL) {
740 		void **el = (void **)data;
741 		if (*el == NULL) {
742 		    data = olddata;
743 		    break;
744 		}
745 		data = *el;
746 	    }
747 	    datalen = _asn1_length(t->ptr, data);
748 	    ret += der_length_tag(A1_TAG_TAG(t->tt)) + der_length_len(datalen);
749 	    ret += datalen;
750 	    data = olddata;
751 	    break;
752 	}
753 	case A1_OP_PARSE: {
754 	    unsigned int type = A1_PARSE_TYPE(t->tt);
755 	    const void *el = DPOC(data, t->offset);
756 
757 	    if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
758 		ABORT_ON_ERROR();
759 		break;
760 	    }
761 	    ret += (asn1_template_prim[type].length)(el);
762 	    break;
763 	}
764 	case A1_OP_SETOF:
765 	case A1_OP_SEQOF: {
766 	    const struct template_of *el = DPOC(data, t->offset);
767 	    size_t ellen = _asn1_sizeofType(t->ptr);
768 	    const unsigned char *element = el->val;
769 	    unsigned int i;
770 
771 	    for (i = 0; i < el->len; i++) {
772 		ret += _asn1_length(t->ptr, element);
773 		element += ellen;
774 	    }
775 
776 	    break;
777 	}
778 	case A1_OP_BMEMBER: {
779 	    const struct asn1_template *bmember = t->ptr;
780 	    size_t size = bmember->offset;
781 	    size_t belements = A1_HEADER_LEN(bmember);
782 	    int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
783 
784 	    if (rfc1510) {
785 		ret += 5;
786 	    } else {
787 
788 		ret += 1;
789 
790 		bmember += belements;
791 
792 		while (belements) {
793 		    if (_asn1_bmember_isset_bit(data, bmember->offset, size)) {
794 			ret += (bmember->offset / 8) + 1;
795 			break;
796 		    }
797 		    belements--; bmember--;
798 		}
799 	    }
800 	    break;
801 	}
802 	case A1_OP_CHOICE: {
803 	    const struct asn1_template *choice = t->ptr;
804 	    const unsigned int *element = DPOC(data, choice->offset);
805 
806 	    if (*element > A1_HEADER_LEN(choice))
807 		break;
808 
809 	    if (*element == 0) {
810 		ret += der_length_octet_string(DPOC(data, choice->tt));
811 	    } else {
812 		choice += *element;
813 		ret += _asn1_length(choice->ptr, DPOC(data, choice->offset));
814 	    }
815 	    break;
816 	}
817 	default:
818 	    ABORT_ON_ERROR();
819 	    break;
820 	}
821 	elements--;
822 	t--;
823     }
824     return ret;
825 }
826 
827 void
_asn1_free(const struct asn1_template * t,void * data)828 _asn1_free(const struct asn1_template *t, void *data)
829 {
830     size_t elements = A1_HEADER_LEN(t);
831 
832     if (t->tt & A1_HF_PRESERVE)
833 	der_free_octet_string(data);
834 
835     t++;
836 
837     while (elements) {
838 	switch (t->tt & A1_OP_MASK) {
839 	case A1_OP_TYPE:
840 	case A1_OP_TYPE_EXTERN: {
841 	    void *el = DPO(data, t->offset);
842 
843 	    if (t->tt & A1_FLAG_OPTIONAL) {
844 		void **pel = (void **)el;
845 		if (*pel == NULL)
846 		    break;
847 		el = *pel;
848 	    }
849 
850 	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
851 		_asn1_free(t->ptr, el);
852 	    } else {
853 		const struct asn1_type_func *f = t->ptr;
854 		(f->release)(el);
855 	    }
856 	    if (t->tt & A1_FLAG_OPTIONAL)
857 		free(el);
858 
859 	    break;
860 	}
861 	case A1_OP_PARSE: {
862 	    unsigned int type = A1_PARSE_TYPE(t->tt);
863 	    void *el = DPO(data, t->offset);
864 
865 	    if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
866 		ABORT_ON_ERROR();
867 		break;
868 	    }
869 	    (asn1_template_prim[type].release)(el);
870 	    break;
871 	}
872 	case A1_OP_TAG: {
873 	    void *el = DPO(data, t->offset);
874 
875 	    if (t->tt & A1_FLAG_OPTIONAL) {
876 		void **pel = (void **)el;
877 		if (*pel == NULL)
878 		    break;
879 		el = *pel;
880 	    }
881 
882 	    _asn1_free(t->ptr, el);
883 
884 	    if (t->tt & A1_FLAG_OPTIONAL)
885 		free(el);
886 
887 	    break;
888 	}
889 	case A1_OP_SETOF:
890 	case A1_OP_SEQOF: {
891 	    struct template_of *el = DPO(data, t->offset);
892 	    size_t ellen = _asn1_sizeofType(t->ptr);
893 	    unsigned char *element = el->val;
894 	    unsigned int i;
895 
896 	    for (i = 0; i < el->len; i++) {
897 		_asn1_free(t->ptr, element);
898 		element += ellen;
899 	    }
900 	    free(el->val);
901 	    el->val = NULL;
902 	    el->len = 0;
903 
904 	    break;
905 	}
906 	case A1_OP_BMEMBER:
907 	    break;
908 	case A1_OP_CHOICE: {
909 	    const struct asn1_template *choice = t->ptr;
910 	    const unsigned int *element = DPOC(data, choice->offset);
911 
912 	    if (*element > A1_HEADER_LEN(choice))
913 		break;
914 
915 	    if (*element == 0) {
916 		der_free_octet_string(DPO(data, choice->tt));
917 	    } else {
918 		choice += *element;
919 		_asn1_free(choice->ptr, DPO(data, choice->offset));
920 	    }
921 	    break;
922 	}
923 	default:
924 	    ABORT_ON_ERROR();
925 	    break;
926 	}
927 	t++;
928 	elements--;
929     }
930 }
931 
932 int
_asn1_copy(const struct asn1_template * t,const void * from,void * to)933 _asn1_copy(const struct asn1_template *t, const void *from, void *to)
934 {
935     size_t elements = A1_HEADER_LEN(t);
936     int ret = 0;
937     int preserve = (t->tt & A1_HF_PRESERVE);
938 
939     t++;
940 
941     if (preserve) {
942 	ret = der_copy_octet_string(from, to);
943 	if (ret)
944 	    return ret;
945     }
946 
947     while (elements) {
948 	switch (t->tt & A1_OP_MASK) {
949 	case A1_OP_TYPE:
950 	case A1_OP_TYPE_EXTERN: {
951 	    const void *fel = DPOC(from, t->offset);
952 	    void *tel = DPO(to, t->offset);
953 	    void **ptel = (void **)tel;
954 	    size_t size;
955 
956 	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
957 		size = _asn1_sizeofType(t->ptr);
958 	    } else {
959 		const struct asn1_type_func *f = t->ptr;
960 		size = f->size;
961 	    }
962 
963 	    if (t->tt & A1_FLAG_OPTIONAL) {
964 		void **pfel = (void **)fel;
965 		if (*pfel == NULL)
966 		    break;
967 		fel = *pfel;
968 
969 		tel = *ptel = calloc(1, size);
970 		if (tel == NULL)
971 		    return ENOMEM;
972 	    }
973 
974 	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
975 		ret = _asn1_copy(t->ptr, fel, tel);
976 	    } else {
977 		const struct asn1_type_func *f = t->ptr;
978 		ret = (f->copy)(fel, tel);
979 	    }
980 
981 	    if (ret) {
982 		if (t->tt & A1_FLAG_OPTIONAL) {
983 		    free(*ptel);
984 		    *ptel = NULL;
985 		}
986 		return ret;
987 	    }
988 	    break;
989 	}
990 	case A1_OP_PARSE: {
991 	    unsigned int type = A1_PARSE_TYPE(t->tt);
992 	    const void *fel = DPOC(from, t->offset);
993 	    void *tel = DPO(to, t->offset);
994 
995 	    if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
996 		ABORT_ON_ERROR();
997 		return ASN1_PARSE_ERROR;
998 	    }
999 	    ret = (asn1_template_prim[type].copy)(fel, tel);
1000 	    if (ret)
1001 		return ret;
1002 	    break;
1003 	}
1004 	case A1_OP_TAG: {
1005 	    const void *oldfrom = from;
1006 	    void *oldto = to;
1007 	    void **tel = NULL;
1008 
1009 	    from = DPOC(from, t->offset);
1010 	    to = DPO(to, t->offset);
1011 
1012 	    if (t->tt & A1_FLAG_OPTIONAL) {
1013 		void **fel = (void **)from;
1014 		tel = (void **)to;
1015 		if (*fel == NULL) {
1016 		    from = oldfrom;
1017 		    to = oldto;
1018 		    break;
1019 		}
1020 		from = *fel;
1021 
1022 		to = *tel = calloc(1, _asn1_sizeofType(t->ptr));
1023 		if (to == NULL)
1024 		    return ENOMEM;
1025 	    }
1026 
1027 	    ret = _asn1_copy(t->ptr, from, to);
1028 	    if (ret) {
1029 		if (tel) {
1030 		    free(*tel);
1031 		    *tel = NULL;
1032 		}
1033 		return ret;
1034 	    }
1035 
1036 	    from = oldfrom;
1037 	    to = oldto;
1038 
1039 	    break;
1040 	}
1041 	case A1_OP_SETOF:
1042 	case A1_OP_SEQOF: {
1043 	    const struct template_of *fel = DPOC(from, t->offset);
1044 	    struct template_of *tel = DPO(to, t->offset);
1045 	    size_t ellen = _asn1_sizeofType(t->ptr);
1046 	    unsigned int i;
1047 
1048 	    tel->val = calloc(fel->len, ellen);
1049 	    if (tel->val == NULL)
1050 		return ENOMEM;
1051 
1052 	    tel->len = fel->len;
1053 
1054 	    for (i = 0; i < fel->len; i++) {
1055 		ret = _asn1_copy(t->ptr,
1056 				 DPOC(fel->val, (i * ellen)),
1057 				 DPO(tel->val, (i *ellen)));
1058 		if (ret)
1059 		    return ret;
1060 	    }
1061 	    break;
1062 	}
1063 	case A1_OP_BMEMBER: {
1064 	    const struct asn1_template *bmember = t->ptr;
1065 	    size_t size = bmember->offset;
1066 	    memcpy(to, from, size);
1067 	    break;
1068 	}
1069 	case A1_OP_CHOICE: {
1070 	    const struct asn1_template *choice = t->ptr;
1071 	    const unsigned int *felement = DPOC(from, choice->offset);
1072 	    unsigned int *telement = DPO(to, choice->offset);
1073 
1074 	    if (*felement > A1_HEADER_LEN(choice))
1075 		return ASN1_PARSE_ERROR;
1076 
1077 	    *telement = *felement;
1078 
1079 	    if (*felement == 0) {
1080 		ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt));
1081 	    } else {
1082 		choice += *felement;
1083 		ret = _asn1_copy(choice->ptr,
1084 				 DPOC(from, choice->offset),
1085 				 DPO(to, choice->offset));
1086 	    }
1087 	    if (ret)
1088 		return ret;
1089 	    break;
1090 	}
1091 	default:
1092 	    ABORT_ON_ERROR();
1093 	    break;
1094 	}
1095 	t++;
1096 	elements--;
1097     }
1098     return 0;
1099 }
1100 
1101 int
_asn1_decode_top(const struct asn1_template * t,unsigned flags,const unsigned char * p,size_t len,void * data,size_t * size)1102 _asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size)
1103 {
1104     int ret;
1105     memset(data, 0, t->offset);
1106     ret = _asn1_decode(t, flags, p, len, data, size);
1107     if (ret)
1108 	_asn1_free_top(t, data);
1109 
1110     return ret;
1111 }
1112 
1113 int
_asn1_copy_top(const struct asn1_template * t,const void * from,void * to)1114 _asn1_copy_top(const struct asn1_template *t, const void *from, void *to)
1115 {
1116     int ret;
1117     memset(to, 0, t->offset);
1118     ret = _asn1_copy(t, from, to);
1119     if (ret)
1120 	_asn1_free_top(t, to);
1121 
1122     return ret;
1123 }
1124 
1125 void
_asn1_free_top(const struct asn1_template * t,void * data)1126 _asn1_free_top(const struct asn1_template *t, void *data)
1127 {
1128     _asn1_free(t, data);
1129     memset(data, 0, t->offset);
1130 }
1131