2 * Copyright (c) 2009 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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.
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.
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
40 #define ABORT_ON_ERROR() abort()
42 #define ABORT_ON_ERROR() do { } while(0)
45 #define DPOC(data,offset) ((const void *)(((const unsigned char *)data) + offset))
46 #define DPO(data,offset) ((void *)(((unsigned char *)data) + offset))
49 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, \
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, \
67 el(heim_integer
, heim_integer
),
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),
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)
87 el(general_string
, heim_general_string
),
93 sizeofType(const struct asn1_template
*t
)
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.
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.
109 bmember_get_bit(const unsigned char *p
, void *data
,
110 unsigned int bit
, size_t size
)
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));
117 *(unsigned int *)data
|= (1 << bit
);
123 bmember_isset_bit(const void *data
, unsigned int bit
, size_t size
)
125 #ifdef WORDS_BIGENDIAN
126 if ((*(unsigned int *)data
) & (1 << ((size
* 8) - bit
- 1)))
130 if ((*(unsigned int *)data
) & (1 << bit
))
137 bmember_put_bit(unsigned char *p
, const void *data
, unsigned int bit
,
138 size_t size
, unsigned int *bitset
)
140 unsigned int localbit
= bit
% 8;
142 if (bmember_isset_bit(data
, bit
, size
)) {
143 *p
|= (1 << (7 - localbit
));
145 *bitset
= (7 - localbit
) + 1;
150 _asn1_decode(const struct asn1_template
*t
, unsigned flags
,
151 const unsigned char *p
, size_t len
, void *data
, size_t *size
)
153 size_t elements
= A1_HEADER_LEN(t
);
156 const unsigned char *startp
= NULL
;
157 unsigned int template_flags
= t
->tt
;
159 /* skip over header */
162 if (template_flags
& A1_HF_PRESERVE
)
166 switch (t
->tt
& A1_OP_MASK
) {
168 case A1_OP_TYPE_EXTERN
: {
169 size_t newsize
, size
;
170 void *el
= DPO(data
, t
->offset
);
171 void **pel
= (void **)el
;
173 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
174 size
= sizeofType(t
->ptr
);
176 const struct asn1_type_func
*f
= t
->ptr
;
180 if (t
->tt
& A1_FLAG_OPTIONAL
) {
181 *pel
= calloc(1, size
);
186 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
187 ret
= _asn1_decode(t
->ptr
, flags
, p
, len
, el
, &newsize
);
189 const struct asn1_type_func
*f
= t
->ptr
;
190 ret
= (f
->decode
)(p
, len
, el
, &newsize
);
193 if (t
->tt
& A1_FLAG_OPTIONAL
) {
200 p
+= newsize
; len
-= newsize
;
208 void *olddata
= data
;
209 int is_indefinite
= 0;
210 int subflags
= flags
;
212 ret
= der_match_tag_and_length(p
, len
, A1_TAG_CLASS(t
->tt
),
213 &dertype
, A1_TAG_TAG(t
->tt
),
216 if (t
->tt
& A1_FLAG_OPTIONAL
)
224 * Only allow indefinite encoding for OCTET STRING and BER
225 * for now. Should handle BIT STRING too.
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 */
232 if (((subtype
->tt
& A1_OP_MASK
) == A1_OP_PARSE
) &&
233 A1_PARSE_TYPE(subtype
->tt
) == A1T_OCTET_STRING
)
234 subflags
|= A1_PF_INDEFINTE
;
237 if (datalen
== ASN1_INDEFINITE
) {
238 if ((flags
& A1_PF_ALLOW_BER
) == 0)
244 /* hide EndOfContent for sub-decoder, catching it below */
246 } else if (datalen
> len
)
249 data
= DPO(data
, t
->offset
);
251 if (t
->tt
& A1_FLAG_OPTIONAL
) {
252 void **el
= (void **)data
;
253 size_t ellen
= sizeofType(t
->ptr
);
255 *el
= calloc(1, ellen
);
261 ret
= _asn1_decode(t
->ptr
, subflags
, p
, datalen
, data
, &newsize
);
265 if (newsize
!= datalen
)
266 return ASN1_EXTRA_DATA
;
272 * Indefinite encoding needs a trailing EndOfContent,
276 ret
= der_match_tag_and_length(p
, len
, ASN1_C_UNIV
,
277 &dertype
, UT_EndOfContent
,
284 return ASN1_INDEF_EXTRA_DATA
;
292 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
294 void *el
= DPO(data
, t
->offset
);
297 * INDEFINITE primitive types are one element after the
298 * same type but non-INDEFINITE version.
300 if (flags
& A1_PF_INDEFINTE
)
303 if (type
>= sizeof(prim
)/sizeof(prim
[0])) {
305 return ASN1_PARSE_ERROR
;
308 ret
= (prim
[type
].decode
)(p
, len
, el
, &newsize
);
311 p
+= newsize
; len
-= newsize
;
317 struct template_of
*el
= DPO(data
, t
->offset
);
319 size_t ellen
= sizeofType(t
->ptr
);
320 size_t vallength
= 0;
324 size_t newlen
= vallength
+ ellen
;
325 if (vallength
> newlen
)
326 return ASN1_OVERFLOW
;
328 tmp
= realloc(el
->val
, newlen
);
332 memset(DPO(tmp
, vallength
), 0, ellen
);
335 ret
= _asn1_decode(t
->ptr
, flags
& (~A1_PF_INDEFINTE
), p
, len
,
336 DPO(el
->val
, vallength
), &newsize
);
341 p
+= newsize
; len
-= newsize
;
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
);
354 memset(data
, 0, size
);
360 while (elements
&& len
) {
361 while (bmember
->offset
/ 8 > pos
/ 8) {
368 bmember_get_bit(p
, data
, bmember
->offset
, size
);
369 elements
--; bmember
++;
376 const struct asn1_template
*choice
= t
->ptr
;
377 unsigned int *element
= DPO(data
, choice
->offset
);
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
);
387 p
+= datalen
; len
-= datalen
;
389 } else if (ret
!= ASN1_BAD_ID
&& ret
!= ASN1_MISPLACED_FIELD
&& ret
!= ASN1_MISSING_FIELD
) {
393 if (i
>= A1_HEADER_LEN(choice
) + 1) {
398 ret
= der_get_octet_string(p
, len
,
399 DPO(data
, choice
->tt
), &datalen
);
402 p
+= datalen
; len
-= datalen
;
409 return ASN1_PARSE_ERROR
;
414 /* if we are using padding, eat up read of context */
415 if (template_flags
& A1_HF_ELLIPSIS
)
424 * saved the raw bits if asked for it, useful for signature
428 heim_octet_string
*save
= data
;
430 save
->data
= malloc(oldlen
);
431 if (save
->data
== NULL
)
434 save
->length
= oldlen
;
435 memcpy(save
->data
, startp
, oldlen
);
442 _asn1_encode(const struct asn1_template
*t
, unsigned char *p
, size_t len
, const void *data
, size_t *size
)
444 size_t elements
= A1_HEADER_LEN(t
);
448 t
+= A1_HEADER_LEN(t
);
451 switch (t
->tt
& A1_OP_MASK
) {
453 case A1_OP_TYPE_EXTERN
: {
455 const void *el
= DPOC(data
, t
->offset
);
457 if (t
->tt
& A1_FLAG_OPTIONAL
) {
458 void **pel
= (void **)el
;
464 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
465 ret
= _asn1_encode(t
->ptr
, p
, len
, el
, &newsize
);
467 const struct asn1_type_func
*f
= t
->ptr
;
468 ret
= (f
->encode
)(p
, len
, el
, &newsize
);
473 p
-= newsize
; len
-= newsize
;
478 const void *olddata
= data
;
481 data
= DPOC(data
, t
->offset
);
483 if (t
->tt
& A1_FLAG_OPTIONAL
) {
484 void **el
= (void **)data
;
492 ret
= _asn1_encode(t
->ptr
, p
, len
, data
, &datalen
);
496 len
-= datalen
; p
-= datalen
;
498 ret
= der_put_length_and_tag(p
, len
, datalen
,
501 A1_TAG_TAG(t
->tt
), &l
);
512 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
514 const void *el
= DPOC(data
, t
->offset
);
516 if (type
> sizeof(prim
)/sizeof(prim
[0])) {
518 return ASN1_PARSE_ERROR
;
521 ret
= (prim
[type
].encode
)(p
, len
, el
, &newsize
);
524 p
-= newsize
; len
-= newsize
;
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
;
538 if (el
->len
> UINT_MAX
/sizeof(val
[0]))
541 val
= malloc(sizeof(val
[0]) * el
->len
);
545 for(totallen
= 0, i
= 0; i
< el
->len
; i
++) {
549 val
[i
].length
= _asn1_length(t
->ptr
, elptr
);
550 val
[i
].data
= malloc(val
[i
].length
);
552 ret
= _asn1_encode(t
->ptr
, DPO(val
[i
].data
, val
[i
].length
- 1),
553 val
[i
].length
, elptr
, &l
);
557 next
= elptr
+ ellen
;
563 totallen
+= val
[i
].length
;
565 if (ret
== 0 && totallen
> len
)
577 qsort(val
, el
->len
, sizeof(val
[0]), _heim_der_set_sort
);
582 memcpy(p
+ 1, val
[i
].data
, val
[i
].length
);
591 struct template_of
*el
= DPO(data
, t
->offset
);
592 size_t ellen
= sizeofType(t
->ptr
);
595 unsigned char *elptr
= el
->val
;
600 elptr
+= ellen
* (el
->len
- 1);
602 for (i
= 0; i
< el
->len
; i
++) {
603 ret
= _asn1_encode(t
->ptr
, p
, len
,
608 p
-= newsize
; len
-= newsize
;
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
);
620 unsigned int bitset
= 0;
621 int rfc1510
= (bmember
->tt
& A1_HBF_RFC1510
);
628 pos
= bmember
->offset
;
630 while (elements
&& len
) {
631 while (bmember
->offset
/ 8 < pos
/ 8) {
632 if (rfc1510
|| bitset
|| c
) {
634 return ASN1_OVERFLOW
;
640 bmember_put_bit(&c
, data
, bmember
->offset
, size
, &bitset
);
641 elements
--; bmember
--;
643 if (rfc1510
|| bitset
) {
645 return ASN1_OVERFLOW
;
650 return ASN1_OVERFLOW
;
651 if (rfc1510
|| bitset
== 0)
661 const struct asn1_template
*choice
= t
->ptr
;
662 const unsigned int *element
= DPOC(data
, choice
->offset
);
666 if (*element
> A1_HEADER_LEN(choice
)) {
667 printf("element: %d\n", *element
);
668 return ASN1_PARSE_ERROR
;
672 ret
+= der_put_octet_string(p
, len
,
673 DPOC(data
, choice
->tt
), &datalen
);
676 el
= DPOC(data
, choice
->offset
);
677 ret
= _asn1_encode(choice
->ptr
, p
, len
, el
, &datalen
);
681 len
-= datalen
; p
-= datalen
;
692 *size
= oldlen
- len
;
698 _asn1_length(const struct asn1_template
*t
, const void *data
)
700 size_t elements
= A1_HEADER_LEN(t
);
703 t
+= A1_HEADER_LEN(t
);
706 switch (t
->tt
& A1_OP_MASK
) {
708 case A1_OP_TYPE_EXTERN
: {
709 const void *el
= DPOC(data
, t
->offset
);
711 if (t
->tt
& A1_FLAG_OPTIONAL
) {
712 void **pel
= (void **)el
;
718 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
719 ret
+= _asn1_length(t
->ptr
, el
);
721 const struct asn1_type_func
*f
= t
->ptr
;
722 ret
+= (f
->length
)(el
);
728 const void *olddata
= data
;
730 data
= DPO(data
, t
->offset
);
732 if (t
->tt
& A1_FLAG_OPTIONAL
) {
733 void **el
= (void **)data
;
740 datalen
= _asn1_length(t
->ptr
, data
);
741 ret
+= der_length_tag(A1_TAG_TAG(t
->tt
)) + der_length_len(datalen
);
747 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
748 const void *el
= DPOC(data
, t
->offset
);
750 if (type
> sizeof(prim
)/sizeof(prim
[0])) {
754 ret
+= (prim
[type
].length
)(el
);
759 const struct template_of
*el
= DPOC(data
, t
->offset
);
760 size_t ellen
= sizeofType(t
->ptr
);
761 const unsigned char *element
= el
->val
;
764 for (i
= 0; i
< el
->len
; i
++) {
765 ret
+= _asn1_length(t
->ptr
, element
);
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
);
786 if (bmember_isset_bit(data
, bmember
->offset
, size
)) {
787 ret
+= (bmember
->offset
/ 8) + 1;
790 elements
--; bmember
--;
796 const struct asn1_template
*choice
= t
->ptr
;
797 const unsigned int *element
= DPOC(data
, choice
->offset
);
799 if (*element
> A1_HEADER_LEN(choice
))
803 ret
+= der_length_octet_string(DPOC(data
, choice
->tt
));
806 ret
+= _asn1_length(choice
->ptr
, DPOC(data
, choice
->offset
));
821 _asn1_free(const struct asn1_template
*t
, void *data
)
823 size_t elements
= A1_HEADER_LEN(t
);
825 if (t
->tt
& A1_HF_PRESERVE
)
826 der_free_octet_string(data
);
831 switch (t
->tt
& A1_OP_MASK
) {
833 case A1_OP_TYPE_EXTERN
: {
834 void *el
= DPO(data
, t
->offset
);
836 if (t
->tt
& A1_FLAG_OPTIONAL
) {
837 void **pel
= (void **)el
;
843 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
844 _asn1_free(t
->ptr
, el
);
846 const struct asn1_type_func
*f
= t
->ptr
;
849 if (t
->tt
& A1_FLAG_OPTIONAL
)
855 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
856 void *el
= DPO(data
, t
->offset
);
858 if (type
> sizeof(prim
)/sizeof(prim
[0])) {
862 (prim
[type
].release
)(el
);
866 void *el
= DPO(data
, t
->offset
);
868 if (t
->tt
& A1_FLAG_OPTIONAL
) {
869 void **pel
= (void **)el
;
875 _asn1_free(t
->ptr
, el
);
877 if (t
->tt
& A1_FLAG_OPTIONAL
)
884 struct template_of
*el
= DPO(data
, t
->offset
);
885 size_t ellen
= sizeofType(t
->ptr
);
886 unsigned char *element
= el
->val
;
889 for (i
= 0; i
< el
->len
; i
++) {
890 _asn1_free(t
->ptr
, element
);
902 const struct asn1_template
*choice
= t
->ptr
;
903 const unsigned int *element
= DPOC(data
, choice
->offset
);
905 if (*element
> A1_HEADER_LEN(choice
))
909 der_free_octet_string(DPO(data
, choice
->tt
));
912 _asn1_free(choice
->ptr
, DPO(data
, choice
->offset
));
926 _asn1_copy(const struct asn1_template
*t
, const void *from
, void *to
)
928 size_t elements
= A1_HEADER_LEN(t
);
930 int preserve
= (t
->tt
& A1_HF_PRESERVE
);
935 ret
= der_copy_octet_string(from
, to
);
941 switch (t
->tt
& A1_OP_MASK
) {
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
;
949 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
950 size
= sizeofType(t
->ptr
);
952 const struct asn1_type_func
*f
= t
->ptr
;
956 if (t
->tt
& A1_FLAG_OPTIONAL
) {
957 void **pfel
= (void **)fel
;
962 tel
= *ptel
= calloc(1, size
);
967 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
968 ret
= _asn1_copy(t
->ptr
, fel
, tel
);
970 const struct asn1_type_func
*f
= t
->ptr
;
971 ret
= (f
->copy
)(fel
, tel
);
975 if (t
->tt
& A1_FLAG_OPTIONAL
) {
984 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
985 const void *fel
= DPOC(from
, t
->offset
);
986 void *tel
= DPO(to
, t
->offset
);
988 if (type
> sizeof(prim
)/sizeof(prim
[0])) {
990 return ASN1_PARSE_ERROR
;
992 ret
= (prim
[type
].copy
)(fel
, tel
);
998 const void *oldfrom
= from
;
1002 from
= DPOC(from
, t
->offset
);
1003 to
= DPO(to
, t
->offset
);
1005 if (t
->tt
& A1_FLAG_OPTIONAL
) {
1006 void **fel
= (void **)from
;
1015 to
= *tel
= calloc(1, sizeofType(t
->ptr
));
1020 ret
= _asn1_copy(t
->ptr
, from
, to
);
1022 if (t
->tt
& A1_FLAG_OPTIONAL
) {
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
);
1041 tel
->val
= calloc(fel
->len
, ellen
);
1042 if (tel
->val
== NULL
)
1045 tel
->len
= fel
->len
;
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
)));
1056 case A1_OP_BMEMBER
: {
1057 const struct asn1_template
*bmember
= t
->ptr
;
1058 size_t size
= bmember
->offset
;
1059 memcpy(to
, from
, size
);
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
);
1067 if (*felement
> A1_HEADER_LEN(choice
))
1068 return ASN1_PARSE_ERROR
;
1070 *telement
= *felement
;
1072 if (*felement
== 0) {
1073 ret
= der_copy_octet_string(DPOC(from
, choice
->tt
), DPO(to
, choice
->tt
));
1075 choice
+= *felement
;
1076 ret
= _asn1_copy(choice
->ptr
,
1077 DPOC(from
, choice
->offset
),
1078 DPO(to
, choice
->offset
));
1095 _asn1_decode_top(const struct asn1_template
*t
, unsigned flags
, const unsigned char *p
, size_t len
, void *data
, size_t *size
)
1098 memset(data
, 0, t
->offset
);
1099 ret
= _asn1_decode(t
, flags
, p
, len
, data
, size
);
1101 _asn1_free(t
, data
);
1102 memset(data
, 0, t
->offset
);
1109 _asn1_copy_top(const struct asn1_template
*t
, const void *from
, void *to
)
1112 memset(to
, 0, t
->offset
);
1113 ret
= _asn1_copy(t
, from
, to
);
1116 memset(to
, 0, t
->offset
);