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