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(integer64, int64_t),
70    el(unsigned, unsigned),
71    el(unsigned64, uint64_t),
72    el(general_string, heim_general_string),
73    el(octet_string, heim_octet_string),
74    elber(octet_string, heim_octet_string),
75    el(ia5_string, heim_ia5_string),
76    el(bmp_string, heim_bmp_string),
77    el(universal_string, heim_universal_string),
78    el(printable_string, heim_printable_string),
79    el(visible_string, heim_visible_string),
80    el(utf8string, heim_utf8_string),
81    el(generalized_time, time_t),
82    el(utctime, time_t),
83    el(bit_string, heim_bit_string),
84    { (asn1_type_encode)der_put_boolean, (asn1_type_decode)der_get_boolean,
85      (asn1_type_length)der_length_boolean, (asn1_type_copy)der_copy_integer,
86      (asn1_type_release)der_free_integer, sizeof(int)
87    },
88    el(oid, heim_oid),
89    el(general_string, heim_general_string),
90#undef el
91#undef elber
92};
93
94static size_t
95sizeofType(const struct asn1_template *t)
96{
97    return t->offset;
98}
99
100/*
101 * Here is abstraction to not so well evil fact of bit fields in C,
102 * they are endian dependent, so when getting and setting bits in the
103 * host local structure we need to know the endianness of the host.
104 *
105 * Its not the first time in Heimdal this have bitten us, and some day
106 * we'll grow up and use #defined constant, but bit fields are still
107 * so pretty and shiny.
108 */
109
110static void
111bmember_get_bit(const unsigned char *p, void *data,
112		unsigned int bit, size_t size)
113{
114    unsigned int localbit = bit % 8;
115    if ((*p >> (7 - localbit)) & 1) {
116#ifdef WORDS_BIGENDIAN
117	*(unsigned int *)data |= (1 << ((size * 8) - bit - 1));
118#else
119	*(unsigned int *)data |= (1 << bit);
120#endif
121    }
122}
123
124static int
125bmember_isset_bit(const void *data, unsigned int bit, size_t size)
126{
127#ifdef WORDS_BIGENDIAN
128    if ((*(unsigned int *)data) & (1 << ((size * 8) - bit - 1)))
129	return 1;
130    return 0;
131#else
132    if ((*(unsigned int *)data) & (1 << bit))
133	return 1;
134    return 0;
135#endif
136}
137
138static void
139bmember_put_bit(unsigned char *p, const void *data, unsigned int bit,
140		size_t size, unsigned int *bitset)
141{
142    unsigned int localbit = bit % 8;
143
144    if (bmember_isset_bit(data, bit, size)) {
145	*p |= (1 << (7 - localbit));
146	if (*bitset == 0)
147	    *bitset = (7 - localbit) + 1;
148    }
149}
150
151int
152_asn1_decode(const struct asn1_template *t, unsigned flags,
153	     const unsigned char *p, size_t len, void *data, size_t *size)
154{
155    size_t elements = A1_HEADER_LEN(t);
156    size_t oldlen = len;
157    int ret = 0;
158    const unsigned char *startp = NULL;
159    unsigned int template_flags = t->tt;
160
161    /* skip over header */
162    t++;
163
164    if (template_flags & A1_HF_PRESERVE)
165	startp = p;
166
167    while (elements) {
168	switch (t->tt & A1_OP_MASK) {
169	case A1_OP_TYPE:
170	case A1_OP_TYPE_EXTERN: {
171	    size_t newsize, size;
172	    void *el = DPO(data, t->offset);
173	    void **pel = (void **)el;
174
175	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
176		size = sizeofType(t->ptr);
177	    } else {
178		const struct asn1_type_func *f = t->ptr;
179		size = f->size;
180	    }
181
182	    if (t->tt & A1_FLAG_OPTIONAL) {
183		*pel = calloc(1, size);
184		if (*pel == NULL)
185		    return ENOMEM;
186		el = *pel;
187	    }
188	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
189		ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
190	    } else {
191		const struct asn1_type_func *f = t->ptr;
192		ret = (f->decode)(p, len, el, &newsize);
193	    }
194	    if (ret) {
195		if (t->tt & A1_FLAG_OPTIONAL) {
196		    free(*pel);
197		    *pel = NULL;
198		    break;
199		}
200		return ret;
201	    }
202	    p += newsize; len -= newsize;
203
204	    break;
205	}
206	case A1_OP_TAG: {
207	    Der_type dertype;
208	    size_t newsize;
209	    size_t datalen, l;
210	    void *olddata = data;
211	    int is_indefinite = 0;
212	    int subflags = flags;
213
214	    ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt),
215					   &dertype, A1_TAG_TAG(t->tt),
216					   &datalen, &l);
217	    if (ret) {
218		if (t->tt & A1_FLAG_OPTIONAL)
219		    break;
220		return ret;
221	    }
222
223	    p += l; len -= l;
224
225	    /*
226	     * Only allow indefinite encoding for OCTET STRING and BER
227	     * for now. Should handle BIT STRING too.
228	     */
229
230	    if (dertype != A1_TAG_TYPE(t->tt) && (flags & A1_PF_ALLOW_BER)) {
231		const struct asn1_template *subtype = t->ptr;
232		subtype++; /* skip header */
233
234		if (((subtype->tt & A1_OP_MASK) == A1_OP_PARSE) &&
235		    A1_PARSE_TYPE(subtype->tt) == A1T_OCTET_STRING)
236		    subflags |= A1_PF_INDEFINTE;
237	    }
238
239	    if (datalen == ASN1_INDEFINITE) {
240		if ((flags & A1_PF_ALLOW_BER) == 0)
241		    return ASN1_GOT_BER;
242		is_indefinite = 1;
243		datalen = len;
244		if (datalen < 2)
245		    return ASN1_OVERRUN;
246		/* hide EndOfContent for sub-decoder, catching it below */
247		datalen -= 2;
248	    } else if (datalen > len)
249		return ASN1_OVERRUN;
250
251	    data = DPO(data, t->offset);
252
253	    if (t->tt & A1_FLAG_OPTIONAL) {
254		void **el = (void **)data;
255		size_t ellen = sizeofType(t->ptr);
256
257		*el = calloc(1, ellen);
258		if (*el == NULL)
259		    return ENOMEM;
260		data = *el;
261	    }
262
263	    ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize);
264	    if (ret)
265		return ret;
266
267	    if (newsize != datalen)
268		return ASN1_EXTRA_DATA;
269
270	    len -= datalen;
271	    p += datalen;
272
273	    /*
274	     * Indefinite encoding needs a trailing EndOfContent,
275	     * check for that.
276	     */
277	    if (is_indefinite) {
278		ret = der_match_tag_and_length(p, len, ASN1_C_UNIV,
279					       &dertype, UT_EndOfContent,
280					       &datalen, &l);
281		if (ret)
282		    return ret;
283		if (dertype != PRIM)
284		    return ASN1_BAD_ID;
285		if (datalen != 0)
286		    return ASN1_INDEF_EXTRA_DATA;
287		p += l; len -= l;
288	    }
289	    data = olddata;
290
291	    break;
292	}
293	case A1_OP_PARSE: {
294	    unsigned int type = A1_PARSE_TYPE(t->tt);
295	    size_t newsize;
296	    void *el = DPO(data, t->offset);
297
298	    /*
299	     * INDEFINITE primitive types are one element after the
300	     * same type but non-INDEFINITE version.
301	    */
302	    if (flags & A1_PF_INDEFINTE)
303		type++;
304
305	    if (type >= sizeof(prim)/sizeof(prim[0])) {
306		ABORT_ON_ERROR();
307		return ASN1_PARSE_ERROR;
308	    }
309
310	    ret = (prim[type].decode)(p, len, el, &newsize);
311	    if (ret)
312		return ret;
313	    p += newsize; len -= newsize;
314
315	    break;
316	}
317	case A1_OP_SETOF:
318	case A1_OP_SEQOF: {
319	    struct template_of *el = DPO(data, t->offset);
320	    size_t newsize;
321	    size_t ellen = sizeofType(t->ptr);
322	    size_t vallength = 0;
323
324	    while (len > 0) {
325		void *tmp;
326		size_t newlen = vallength + ellen;
327		if (vallength > newlen)
328		    return ASN1_OVERFLOW;
329
330		tmp = realloc(el->val, newlen);
331		if (tmp == NULL)
332		    return ENOMEM;
333
334		memset(DPO(tmp, vallength), 0, ellen);
335		el->val = tmp;
336
337		ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len,
338				   DPO(el->val, vallength), &newsize);
339		if (ret)
340		    return ret;
341		vallength = newlen;
342		el->len++;
343		p += newsize; len -= newsize;
344	    }
345
346	    break;
347	}
348	case A1_OP_BMEMBER: {
349	    const struct asn1_template *bmember = t->ptr;
350	    size_t size = bmember->offset;
351	    size_t elements = A1_HEADER_LEN(bmember);
352	    size_t pos = 0;
353
354	    bmember++;
355
356	    memset(data, 0, size);
357
358	    if (len < 1)
359		return ASN1_OVERRUN;
360	    p++; len--;
361
362	    while (elements && len) {
363		while (bmember->offset / 8 > pos / 8) {
364		    if (len < 1)
365			break;
366		    p++; len--;
367		    pos += 8;
368		}
369		if (len) {
370		    bmember_get_bit(p, data, bmember->offset, size);
371		    elements--; bmember++;
372		}
373	    }
374	    len = 0;
375	    break;
376	}
377	case A1_OP_CHOICE: {
378	    const struct asn1_template *choice = t->ptr;
379	    unsigned int *element = DPO(data, choice->offset);
380	    size_t datalen;
381	    unsigned int i;
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
443int
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(prim)/sizeof(prim[0])) {
519		ABORT_ON_ERROR();
520		return ASN1_PARSE_ERROR;
521	    }
522
523	    ret = (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 = sizeofType(t->ptr);
533	    struct 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 = malloc(sizeof(val[0]) * el->len);
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		val[i].data = malloc(val[i].length);
553
554		ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1),
555				   val[i].length, elptr, &l);
556		if (ret)
557		    break;
558
559		next = elptr + ellen;
560		if (next < elptr) {
561		    ret = ASN1_OVERFLOW;
562		    break;
563		}
564		elptr = next;
565		totallen += val[i].length;
566	    }
567	    if (ret == 0 && totallen > len)
568		ret = ASN1_OVERFLOW;
569	    if (ret) {
570		do {
571		    free(val[i].data);
572		} while(i-- > 0);
573		free(val);
574		return ret;
575	    }
576
577	    len -= totallen;
578
579	    qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort);
580
581	    i = el->len - 1;
582	    do {
583		p -= val[i].length;
584		memcpy(p + 1, val[i].data, val[i].length);
585		free(val[i].data);
586	    } while(i-- > 0);
587	    free(val);
588
589	    break;
590
591	}
592	case A1_OP_SEQOF: {
593	    struct template_of *el = DPO(data, t->offset);
594	    size_t ellen = sizeofType(t->ptr);
595	    size_t newsize;
596	    unsigned int i;
597	    unsigned char *elptr = el->val;
598
599	    if (el->len == 0)
600		break;
601
602	    elptr += ellen * (el->len - 1);
603
604	    for (i = 0; i < el->len; i++) {
605		ret = _asn1_encode(t->ptr, p, len,
606				   elptr,
607				   &newsize);
608		if (ret)
609		    return ret;
610		p -= newsize; len -= newsize;
611		elptr -= ellen;
612	    }
613
614	    break;
615	}
616	case A1_OP_BMEMBER: {
617	    const struct asn1_template *bmember = t->ptr;
618	    size_t size = bmember->offset;
619	    size_t elements = A1_HEADER_LEN(bmember);
620	    size_t pos;
621	    unsigned char c = 0;
622	    unsigned int bitset = 0;
623	    int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
624
625	    bmember += elements;
626
627	    if (rfc1510)
628		pos = 31;
629	    else
630		pos = bmember->offset;
631
632	    while (elements && len) {
633		while (bmember->offset / 8 < pos / 8) {
634		    if (rfc1510 || bitset || c) {
635			if (len < 1)
636			    return ASN1_OVERFLOW;
637			*p-- = c; len--;
638		    }
639		    c = 0;
640		    pos -= 8;
641		}
642		bmember_put_bit(&c, data, bmember->offset, size, &bitset);
643		elements--; bmember--;
644	    }
645	    if (rfc1510 || bitset) {
646		if (len < 1)
647		    return ASN1_OVERFLOW;
648		*p-- = c; len--;
649	    }
650
651	    if (len < 1)
652		return ASN1_OVERFLOW;
653	    if (rfc1510 || bitset == 0)
654		*p-- = 0;
655	    else
656		*p-- = bitset - 1;
657
658	    len--;
659
660	    break;
661	}
662	case A1_OP_CHOICE: {
663	    const struct asn1_template *choice = t->ptr;
664	    const unsigned int *element = DPOC(data, choice->offset);
665	    size_t datalen;
666	    const void *el;
667
668	    if (*element > A1_HEADER_LEN(choice)) {
669		printf("element: %d\n", *element);
670		return ASN1_PARSE_ERROR;
671	    }
672
673	    if (*element == 0) {
674		ret += der_put_octet_string(p, len,
675					    DPOC(data, choice->tt), &datalen);
676	    } else {
677		choice += *element;
678		el = DPOC(data, choice->offset);
679		ret = _asn1_encode(choice->ptr, p, len, el, &datalen);
680		if (ret)
681		    return ret;
682	    }
683	    len -= datalen; p -= datalen;
684
685	    break;
686	}
687	default:
688	    ABORT_ON_ERROR();
689	}
690	t--;
691	elements--;
692    }
693    if (size)
694	*size = oldlen - len;
695
696    return 0;
697}
698
699size_t
700_asn1_length(const struct asn1_template *t, const void *data)
701{
702    size_t elements = A1_HEADER_LEN(t);
703    size_t ret = 0;
704
705    t += A1_HEADER_LEN(t);
706
707    while (elements) {
708	switch (t->tt & A1_OP_MASK) {
709	case A1_OP_TYPE:
710	case A1_OP_TYPE_EXTERN: {
711	    const void *el = DPOC(data, t->offset);
712
713	    if (t->tt & A1_FLAG_OPTIONAL) {
714		void **pel = (void **)el;
715		if (*pel == NULL)
716		    break;
717		el = *pel;
718	    }
719
720	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
721		ret += _asn1_length(t->ptr, el);
722	    } else {
723		const struct asn1_type_func *f = t->ptr;
724		ret += (f->length)(el);
725	    }
726	    break;
727	}
728	case A1_OP_TAG: {
729	    size_t datalen;
730	    const void *olddata = data;
731
732	    data = DPO(data, t->offset);
733
734	    if (t->tt & A1_FLAG_OPTIONAL) {
735		void **el = (void **)data;
736		if (*el == NULL) {
737		    data = olddata;
738		    break;
739		}
740		data = *el;
741	    }
742	    datalen = _asn1_length(t->ptr, data);
743	    ret += der_length_tag(A1_TAG_TAG(t->tt)) + der_length_len(datalen);
744	    ret += datalen;
745	    data = olddata;
746	    break;
747	}
748	case A1_OP_PARSE: {
749	    unsigned int type = A1_PARSE_TYPE(t->tt);
750	    const void *el = DPOC(data, t->offset);
751
752	    if (type > sizeof(prim)/sizeof(prim[0])) {
753		ABORT_ON_ERROR();
754		break;
755	    }
756	    ret += (prim[type].length)(el);
757	    break;
758	}
759	case A1_OP_SETOF:
760	case A1_OP_SEQOF: {
761	    const struct template_of *el = DPOC(data, t->offset);
762	    size_t ellen = sizeofType(t->ptr);
763	    const unsigned char *element = el->val;
764	    unsigned int i;
765
766	    for (i = 0; i < el->len; i++) {
767		ret += _asn1_length(t->ptr, element);
768		element += ellen;
769	    }
770
771	    break;
772	}
773	case A1_OP_BMEMBER: {
774	    const struct asn1_template *bmember = t->ptr;
775	    size_t size = bmember->offset;
776	    size_t elements = A1_HEADER_LEN(bmember);
777	    int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
778
779	    if (rfc1510) {
780		ret += 5;
781	    } else {
782
783		ret += 1;
784
785		bmember += elements;
786
787		while (elements) {
788		    if (bmember_isset_bit(data, bmember->offset, size)) {
789			ret += (bmember->offset / 8) + 1;
790			break;
791		    }
792		    elements--; bmember--;
793		}
794	    }
795	    break;
796	}
797	case A1_OP_CHOICE: {
798	    const struct asn1_template *choice = t->ptr;
799	    const unsigned int *element = DPOC(data, choice->offset);
800
801	    if (*element > A1_HEADER_LEN(choice))
802		break;
803
804	    if (*element == 0) {
805		ret += der_length_octet_string(DPOC(data, choice->tt));
806	    } else {
807		choice += *element;
808		ret += _asn1_length(choice->ptr, DPOC(data, choice->offset));
809	    }
810	    break;
811	}
812	default:
813	    ABORT_ON_ERROR();
814	    break;
815	}
816	elements--;
817	t--;
818    }
819    return ret;
820}
821
822void
823_asn1_free(const struct asn1_template *t, void *data)
824{
825    size_t elements = A1_HEADER_LEN(t);
826
827    if (t->tt & A1_HF_PRESERVE)
828	der_free_octet_string(data);
829
830    t++;
831
832    while (elements) {
833	switch (t->tt & A1_OP_MASK) {
834	case A1_OP_TYPE:
835	case A1_OP_TYPE_EXTERN: {
836	    void *el = DPO(data, t->offset);
837
838	    if (t->tt & A1_FLAG_OPTIONAL) {
839		void **pel = (void **)el;
840		if (*pel == NULL)
841		    break;
842		el = *pel;
843	    }
844
845	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
846		_asn1_free(t->ptr, el);
847	    } else {
848		const struct asn1_type_func *f = t->ptr;
849		(f->release)(el);
850	    }
851	    if (t->tt & A1_FLAG_OPTIONAL)
852		free(el);
853
854	    break;
855	}
856	case A1_OP_PARSE: {
857	    unsigned int type = A1_PARSE_TYPE(t->tt);
858	    void *el = DPO(data, t->offset);
859
860	    if (type > sizeof(prim)/sizeof(prim[0])) {
861		ABORT_ON_ERROR();
862		break;
863	    }
864	    (prim[type].release)(el);
865	    break;
866	}
867	case A1_OP_TAG: {
868	    void *el = DPO(data, t->offset);
869
870	    if (t->tt & A1_FLAG_OPTIONAL) {
871		void **pel = (void **)el;
872		if (*pel == NULL)
873		    break;
874		el = *pel;
875	    }
876
877	    _asn1_free(t->ptr, el);
878
879	    if (t->tt & A1_FLAG_OPTIONAL)
880		free(el);
881
882	    break;
883	}
884	case A1_OP_SETOF:
885	case A1_OP_SEQOF: {
886	    struct template_of *el = DPO(data, t->offset);
887	    size_t ellen = sizeofType(t->ptr);
888	    unsigned char *element = el->val;
889	    unsigned int i;
890
891	    for (i = 0; i < el->len; i++) {
892		_asn1_free(t->ptr, element);
893		element += ellen;
894	    }
895	    free(el->val);
896	    el->val = NULL;
897	    el->len = 0;
898
899	    break;
900	}
901	case A1_OP_BMEMBER:
902	    break;
903	case A1_OP_CHOICE: {
904	    const struct asn1_template *choice = t->ptr;
905	    const unsigned int *element = DPOC(data, choice->offset);
906
907	    if (*element > A1_HEADER_LEN(choice))
908		break;
909
910	    if (*element == 0) {
911		der_free_octet_string(DPO(data, choice->tt));
912	    } else {
913		choice += *element;
914		_asn1_free(choice->ptr, DPO(data, choice->offset));
915	    }
916	    break;
917	}
918	default:
919	    ABORT_ON_ERROR();
920	    break;
921	}
922	t++;
923	elements--;
924    }
925}
926
927int
928_asn1_copy(const struct asn1_template *t, const void *from, void *to)
929{
930    size_t elements = A1_HEADER_LEN(t);
931    int ret = 0;
932    int preserve = (t->tt & A1_HF_PRESERVE);
933
934    t++;
935
936    if (preserve) {
937	ret = der_copy_octet_string(from, to);
938	if (ret)
939	    return ret;
940    }
941
942    while (elements) {
943	switch (t->tt & A1_OP_MASK) {
944	case A1_OP_TYPE:
945	case A1_OP_TYPE_EXTERN: {
946	    const void *fel = DPOC(from, t->offset);
947	    void *tel = DPO(to, t->offset);
948	    void **ptel = (void **)tel;
949	    size_t size;
950
951	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
952		size = sizeofType(t->ptr);
953	    } else {
954		const struct asn1_type_func *f = t->ptr;
955		size = f->size;
956	    }
957
958	    if (t->tt & A1_FLAG_OPTIONAL) {
959		void **pfel = (void **)fel;
960		if (*pfel == NULL)
961		    break;
962		fel = *pfel;
963
964		tel = *ptel = calloc(1, size);
965		if (tel == NULL)
966		    return ENOMEM;
967	    }
968
969	    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
970		ret = _asn1_copy(t->ptr, fel, tel);
971	    } else {
972		const struct asn1_type_func *f = t->ptr;
973		ret = (f->copy)(fel, tel);
974	    }
975
976	    if (ret) {
977		if (t->tt & A1_FLAG_OPTIONAL) {
978		    free(*ptel);
979		    *ptel = NULL;
980		}
981		return ret;
982	    }
983	    break;
984	}
985	case A1_OP_PARSE: {
986	    unsigned int type = A1_PARSE_TYPE(t->tt);
987	    const void *fel = DPOC(from, t->offset);
988	    void *tel = DPO(to, t->offset);
989
990	    if (type > sizeof(prim)/sizeof(prim[0])) {
991		ABORT_ON_ERROR();
992		return ASN1_PARSE_ERROR;
993	    }
994	    ret = (prim[type].copy)(fel, tel);
995	    if (ret)
996		return ret;
997	    break;
998	}
999	case A1_OP_TAG: {
1000	    const void *oldfrom = from;
1001	    void *oldto = to;
1002	    void **tel = NULL;
1003
1004	    from = DPOC(from, t->offset);
1005	    to = DPO(to, t->offset);
1006
1007	    if (t->tt & A1_FLAG_OPTIONAL) {
1008		void **fel = (void **)from;
1009		tel = (void **)to;
1010		if (*fel == NULL) {
1011		    from = oldfrom;
1012		    to = oldto;
1013		    break;
1014		}
1015		from = *fel;
1016
1017		to = *tel = calloc(1, sizeofType(t->ptr));
1018		if (to == NULL)
1019		    return ENOMEM;
1020	    }
1021
1022	    ret = _asn1_copy(t->ptr, from, to);
1023	    if (ret) {
1024		if (t->tt & A1_FLAG_OPTIONAL) {
1025		    free(*tel);
1026		    *tel = NULL;
1027		}
1028		return ret;
1029	    }
1030
1031	    from = oldfrom;
1032	    to = oldto;
1033
1034	    break;
1035	}
1036	case A1_OP_SETOF:
1037	case A1_OP_SEQOF: {
1038	    const struct template_of *fel = DPOC(from, t->offset);
1039	    struct template_of *tel = DPO(to, t->offset);
1040	    size_t ellen = sizeofType(t->ptr);
1041	    unsigned int i;
1042
1043	    tel->val = calloc(fel->len, ellen);
1044	    if (tel->val == NULL)
1045		return ENOMEM;
1046
1047	    tel->len = fel->len;
1048
1049	    for (i = 0; i < fel->len; i++) {
1050		ret = _asn1_copy(t->ptr,
1051				 DPOC(fel->val, (i * ellen)),
1052				 DPO(tel->val, (i *ellen)));
1053		if (ret)
1054		    return ret;
1055	    }
1056	    break;
1057	}
1058	case A1_OP_BMEMBER: {
1059	    const struct asn1_template *bmember = t->ptr;
1060	    size_t size = bmember->offset;
1061	    memcpy(to, from, size);
1062	    break;
1063	}
1064	case A1_OP_CHOICE: {
1065	    const struct asn1_template *choice = t->ptr;
1066	    const unsigned int *felement = DPOC(from, choice->offset);
1067	    unsigned int *telement = DPO(to, choice->offset);
1068
1069	    if (*felement > A1_HEADER_LEN(choice))
1070		return ASN1_PARSE_ERROR;
1071
1072	    *telement = *felement;
1073
1074	    if (*felement == 0) {
1075		ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt));
1076	    } else {
1077		choice += *felement;
1078		ret = _asn1_copy(choice->ptr,
1079				 DPOC(from, choice->offset),
1080				 DPO(to, choice->offset));
1081	    }
1082	    if (ret)
1083		return ret;
1084	    break;
1085	}
1086	default:
1087	    ABORT_ON_ERROR();
1088	    break;
1089	}
1090	t++;
1091	elements--;
1092    }
1093    return 0;
1094}
1095
1096int
1097_asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size)
1098{
1099    int ret;
1100    memset(data, 0, t->offset);
1101    ret = _asn1_decode(t, flags, p, len, data, size);
1102    if (ret) {
1103	_asn1_free(t, data);
1104	memset(data, 0, t->offset);
1105    }
1106
1107    return ret;
1108}
1109
1110int
1111_asn1_copy_top(const struct asn1_template *t, const void *from, void *to)
1112{
1113    int ret;
1114    memset(to, 0, t->offset);
1115    ret = _asn1_copy(t, from, to);
1116    if (ret) {
1117	_asn1_free(t, to);
1118	memset(to, 0, t->offset);
1119    }
1120    return ret;
1121}
1122