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