1 /* $NetBSD: template.c,v 1.1.1.2 2014/04/24 12:45:28 pettai Exp $ */
4 * Copyright (c) 2009 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the Institute nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include <krb5/com_err.h>
42 #define ABORT_ON_ERROR() abort()
44 #define ABORT_ON_ERROR() do { } while(0)
47 #define DPOC(data,offset) ((const void *)(((const unsigned char *)data) + offset))
48 #define DPO(data,offset) ((void *)(((unsigned char *)data) + offset))
51 static struct asn1_type_func prim
[] = {
52 #define el(name, type) { \
53 (asn1_type_encode)der_put_##name, \
54 (asn1_type_decode)der_get_##name, \
55 (asn1_type_length)der_length_##name, \
56 (asn1_type_copy)der_copy_##name, \
57 (asn1_type_release)der_free_##name, \
60 #define elber(name, type) { \
61 (asn1_type_encode)der_put_##name, \
62 (asn1_type_decode)der_get_##name##_ber, \
63 (asn1_type_length)der_length_##name, \
64 (asn1_type_copy)der_copy_##name, \
65 (asn1_type_release)der_free_##name, \
69 el(heim_integer
, heim_integer
),
71 el(unsigned, unsigned),
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),
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)
89 el(general_string
, heim_general_string
),
95 sizeofType(const struct asn1_template
*t
)
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.
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.
111 bmember_get_bit(const unsigned char *p
, void *data
,
112 unsigned int bit
, size_t size
)
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));
119 *(unsigned int *)data
|= (1 << bit
);
125 bmember_isset_bit(const void *data
, unsigned int bit
, size_t size
)
127 #ifdef WORDS_BIGENDIAN
128 if ((*(unsigned int *)data
) & (1 << ((size
* 8) - bit
- 1)))
132 if ((*(unsigned int *)data
) & (1 << bit
))
139 bmember_put_bit(unsigned char *p
, const void *data
, unsigned int bit
,
140 size_t size
, unsigned int *bitset
)
142 unsigned int localbit
= bit
% 8;
144 if (bmember_isset_bit(data
, bit
, size
)) {
145 *p
|= (1 << (7 - localbit
));
147 *bitset
= (7 - localbit
) + 1;
152 _asn1_decode(const struct asn1_template
*t
, unsigned flags
,
153 const unsigned char *p
, size_t len
, void *data
, size_t *size
)
155 size_t elements
= A1_HEADER_LEN(t
);
158 const unsigned char *startp
= NULL
;
159 unsigned int template_flags
= t
->tt
;
161 /* skip over header */
164 if (template_flags
& A1_HF_PRESERVE
)
168 switch (t
->tt
& A1_OP_MASK
) {
170 case A1_OP_TYPE_EXTERN
: {
171 size_t newsize
, size
;
172 void *el
= DPO(data
, t
->offset
);
173 void **pel
= (void **)el
;
175 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
176 size
= sizeofType(t
->ptr
);
178 const struct asn1_type_func
*f
= t
->ptr
;
182 if (t
->tt
& A1_FLAG_OPTIONAL
) {
183 *pel
= calloc(1, size
);
188 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
189 ret
= _asn1_decode(t
->ptr
, flags
, p
, len
, el
, &newsize
);
191 const struct asn1_type_func
*f
= t
->ptr
;
192 ret
= (f
->decode
)(p
, len
, el
, &newsize
);
195 if (t
->tt
& A1_FLAG_OPTIONAL
) {
202 p
+= newsize
; len
-= newsize
;
210 void *olddata
= data
;
211 int is_indefinite
= 0;
212 int subflags
= flags
;
214 ret
= der_match_tag_and_length(p
, len
, A1_TAG_CLASS(t
->tt
),
215 &dertype
, A1_TAG_TAG(t
->tt
),
218 if (t
->tt
& A1_FLAG_OPTIONAL
)
226 * Only allow indefinite encoding for OCTET STRING and BER
227 * for now. Should handle BIT STRING too.
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 */
234 if (((subtype
->tt
& A1_OP_MASK
) == A1_OP_PARSE
) &&
235 A1_PARSE_TYPE(subtype
->tt
) == A1T_OCTET_STRING
)
236 subflags
|= A1_PF_INDEFINTE
;
239 if (datalen
== ASN1_INDEFINITE
) {
240 if ((flags
& A1_PF_ALLOW_BER
) == 0)
246 /* hide EndOfContent for sub-decoder, catching it below */
248 } else if (datalen
> len
)
251 data
= DPO(data
, t
->offset
);
253 if (t
->tt
& A1_FLAG_OPTIONAL
) {
254 void **el
= (void **)data
;
255 size_t ellen
= sizeofType(t
->ptr
);
257 *el
= calloc(1, ellen
);
263 ret
= _asn1_decode(t
->ptr
, subflags
, p
, datalen
, data
, &newsize
);
267 if (newsize
!= datalen
)
268 return ASN1_EXTRA_DATA
;
274 * Indefinite encoding needs a trailing EndOfContent,
278 ret
= der_match_tag_and_length(p
, len
, ASN1_C_UNIV
,
279 &dertype
, UT_EndOfContent
,
286 return ASN1_INDEF_EXTRA_DATA
;
294 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
296 void *el
= DPO(data
, t
->offset
);
299 * INDEFINITE primitive types are one element after the
300 * same type but non-INDEFINITE version.
302 if (flags
& A1_PF_INDEFINTE
)
305 if (type
>= sizeof(prim
)/sizeof(prim
[0])) {
307 return ASN1_PARSE_ERROR
;
310 ret
= (prim
[type
].decode
)(p
, len
, el
, &newsize
);
313 p
+= newsize
; len
-= newsize
;
319 struct template_of
*el
= DPO(data
, t
->offset
);
321 size_t ellen
= sizeofType(t
->ptr
);
322 size_t vallength
= 0;
326 size_t newlen
= vallength
+ ellen
;
327 if (vallength
> newlen
)
328 return ASN1_OVERFLOW
;
330 tmp
= realloc(el
->val
, newlen
);
334 memset(DPO(tmp
, vallength
), 0, ellen
);
337 ret
= _asn1_decode(t
->ptr
, flags
& (~A1_PF_INDEFINTE
), p
, len
,
338 DPO(el
->val
, vallength
), &newsize
);
343 p
+= newsize
; len
-= newsize
;
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
);
356 memset(data
, 0, size
);
362 while (elements
&& len
) {
363 while (bmember
->offset
/ 8 > pos
/ 8) {
370 bmember_get_bit(p
, data
, bmember
->offset
, size
);
371 elements
--; bmember
++;
378 const struct asn1_template
*choice
= t
->ptr
;
379 unsigned int *element
= DPO(data
, choice
->offset
);
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
);
389 p
+= datalen
; len
-= datalen
;
391 } else if (ret
!= ASN1_BAD_ID
&& ret
!= ASN1_MISPLACED_FIELD
&& ret
!= ASN1_MISSING_FIELD
) {
395 if (i
>= A1_HEADER_LEN(choice
) + 1) {
400 ret
= der_get_octet_string(p
, len
,
401 DPO(data
, choice
->tt
), &datalen
);
404 p
+= datalen
; len
-= datalen
;
411 return ASN1_PARSE_ERROR
;
416 /* if we are using padding, eat up read of context */
417 if (template_flags
& A1_HF_ELLIPSIS
)
426 * saved the raw bits if asked for it, useful for signature
430 heim_octet_string
*save
= data
;
432 save
->data
= malloc(oldlen
);
433 if (save
->data
== NULL
)
436 save
->length
= oldlen
;
437 memcpy(save
->data
, startp
, oldlen
);
444 _asn1_encode(const struct asn1_template
*t
, unsigned char *p
, size_t len
, const void *data
, size_t *size
)
446 size_t elements
= A1_HEADER_LEN(t
);
450 t
+= A1_HEADER_LEN(t
);
453 switch (t
->tt
& A1_OP_MASK
) {
455 case A1_OP_TYPE_EXTERN
: {
457 const void *el
= DPOC(data
, t
->offset
);
459 if (t
->tt
& A1_FLAG_OPTIONAL
) {
460 void **pel
= (void **)el
;
466 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
467 ret
= _asn1_encode(t
->ptr
, p
, len
, el
, &newsize
);
469 const struct asn1_type_func
*f
= t
->ptr
;
470 ret
= (f
->encode
)(p
, len
, el
, &newsize
);
475 p
-= newsize
; len
-= newsize
;
480 const void *olddata
= data
;
483 data
= DPOC(data
, t
->offset
);
485 if (t
->tt
& A1_FLAG_OPTIONAL
) {
486 void **el
= (void **)data
;
494 ret
= _asn1_encode(t
->ptr
, p
, len
, data
, &datalen
);
498 len
-= datalen
; p
-= datalen
;
500 ret
= der_put_length_and_tag(p
, len
, datalen
,
503 A1_TAG_TAG(t
->tt
), &l
);
514 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
516 const void *el
= DPOC(data
, t
->offset
);
518 if (type
> sizeof(prim
)/sizeof(prim
[0])) {
520 return ASN1_PARSE_ERROR
;
523 ret
= (prim
[type
].encode
)(p
, len
, el
, &newsize
);
526 p
-= newsize
; len
-= newsize
;
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
;
540 if (el
->len
> UINT_MAX
/sizeof(val
[0]))
543 val
= malloc(sizeof(val
[0]) * el
->len
);
547 for(totallen
= 0, i
= 0; i
< el
->len
; i
++) {
551 val
[i
].length
= _asn1_length(t
->ptr
, elptr
);
552 val
[i
].data
= malloc(val
[i
].length
);
554 ret
= _asn1_encode(t
->ptr
, DPO(val
[i
].data
, val
[i
].length
- 1),
555 val
[i
].length
, elptr
, &l
);
559 next
= elptr
+ ellen
;
565 totallen
+= val
[i
].length
;
567 if (ret
== 0 && totallen
> len
)
579 qsort(val
, el
->len
, sizeof(val
[0]), _heim_der_set_sort
);
584 memcpy(p
+ 1, val
[i
].data
, val
[i
].length
);
593 struct template_of
*el
= DPO(data
, t
->offset
);
594 size_t ellen
= sizeofType(t
->ptr
);
597 unsigned char *elptr
= el
->val
;
602 elptr
+= ellen
* (el
->len
- 1);
604 for (i
= 0; i
< el
->len
; i
++) {
605 ret
= _asn1_encode(t
->ptr
, p
, len
,
610 p
-= newsize
; len
-= newsize
;
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
);
622 unsigned int bitset
= 0;
623 int rfc1510
= (bmember
->tt
& A1_HBF_RFC1510
);
630 pos
= bmember
->offset
;
632 while (elements
&& len
) {
633 while (bmember
->offset
/ 8 < pos
/ 8) {
634 if (rfc1510
|| bitset
|| c
) {
636 return ASN1_OVERFLOW
;
642 bmember_put_bit(&c
, data
, bmember
->offset
, size
, &bitset
);
643 elements
--; bmember
--;
645 if (rfc1510
|| bitset
) {
647 return ASN1_OVERFLOW
;
652 return ASN1_OVERFLOW
;
653 if (rfc1510
|| bitset
== 0)
663 const struct asn1_template
*choice
= t
->ptr
;
664 const unsigned int *element
= DPOC(data
, choice
->offset
);
668 if (*element
> A1_HEADER_LEN(choice
)) {
669 printf("element: %d\n", *element
);
670 return ASN1_PARSE_ERROR
;
674 ret
+= der_put_octet_string(p
, len
,
675 DPOC(data
, choice
->tt
), &datalen
);
678 el
= DPOC(data
, choice
->offset
);
679 ret
= _asn1_encode(choice
->ptr
, p
, len
, el
, &datalen
);
683 len
-= datalen
; p
-= datalen
;
694 *size
= oldlen
- len
;
700 _asn1_length(const struct asn1_template
*t
, const void *data
)
702 size_t elements
= A1_HEADER_LEN(t
);
705 t
+= A1_HEADER_LEN(t
);
708 switch (t
->tt
& A1_OP_MASK
) {
710 case A1_OP_TYPE_EXTERN
: {
711 const void *el
= DPOC(data
, t
->offset
);
713 if (t
->tt
& A1_FLAG_OPTIONAL
) {
714 void **pel
= (void **)el
;
720 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
721 ret
+= _asn1_length(t
->ptr
, el
);
723 const struct asn1_type_func
*f
= t
->ptr
;
724 ret
+= (f
->length
)(el
);
730 const void *olddata
= data
;
732 data
= DPO(data
, t
->offset
);
734 if (t
->tt
& A1_FLAG_OPTIONAL
) {
735 void **el
= (void **)data
;
742 datalen
= _asn1_length(t
->ptr
, data
);
743 ret
+= der_length_tag(A1_TAG_TAG(t
->tt
)) + der_length_len(datalen
);
749 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
750 const void *el
= DPOC(data
, t
->offset
);
752 if (type
> sizeof(prim
)/sizeof(prim
[0])) {
756 ret
+= (prim
[type
].length
)(el
);
761 const struct template_of
*el
= DPOC(data
, t
->offset
);
762 size_t ellen
= sizeofType(t
->ptr
);
763 const unsigned char *element
= el
->val
;
766 for (i
= 0; i
< el
->len
; i
++) {
767 ret
+= _asn1_length(t
->ptr
, element
);
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
);
788 if (bmember_isset_bit(data
, bmember
->offset
, size
)) {
789 ret
+= (bmember
->offset
/ 8) + 1;
792 elements
--; bmember
--;
798 const struct asn1_template
*choice
= t
->ptr
;
799 const unsigned int *element
= DPOC(data
, choice
->offset
);
801 if (*element
> A1_HEADER_LEN(choice
))
805 ret
+= der_length_octet_string(DPOC(data
, choice
->tt
));
808 ret
+= _asn1_length(choice
->ptr
, DPOC(data
, choice
->offset
));
823 _asn1_free(const struct asn1_template
*t
, void *data
)
825 size_t elements
= A1_HEADER_LEN(t
);
827 if (t
->tt
& A1_HF_PRESERVE
)
828 der_free_octet_string(data
);
833 switch (t
->tt
& A1_OP_MASK
) {
835 case A1_OP_TYPE_EXTERN
: {
836 void *el
= DPO(data
, t
->offset
);
838 if (t
->tt
& A1_FLAG_OPTIONAL
) {
839 void **pel
= (void **)el
;
845 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
846 _asn1_free(t
->ptr
, el
);
848 const struct asn1_type_func
*f
= t
->ptr
;
851 if (t
->tt
& A1_FLAG_OPTIONAL
)
857 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
858 void *el
= DPO(data
, t
->offset
);
860 if (type
> sizeof(prim
)/sizeof(prim
[0])) {
864 (prim
[type
].release
)(el
);
868 void *el
= DPO(data
, t
->offset
);
870 if (t
->tt
& A1_FLAG_OPTIONAL
) {
871 void **pel
= (void **)el
;
877 _asn1_free(t
->ptr
, el
);
879 if (t
->tt
& A1_FLAG_OPTIONAL
)
886 struct template_of
*el
= DPO(data
, t
->offset
);
887 size_t ellen
= sizeofType(t
->ptr
);
888 unsigned char *element
= el
->val
;
891 for (i
= 0; i
< el
->len
; i
++) {
892 _asn1_free(t
->ptr
, element
);
904 const struct asn1_template
*choice
= t
->ptr
;
905 const unsigned int *element
= DPOC(data
, choice
->offset
);
907 if (*element
> A1_HEADER_LEN(choice
))
911 der_free_octet_string(DPO(data
, choice
->tt
));
914 _asn1_free(choice
->ptr
, DPO(data
, choice
->offset
));
928 _asn1_copy(const struct asn1_template
*t
, const void *from
, void *to
)
930 size_t elements
= A1_HEADER_LEN(t
);
932 int preserve
= (t
->tt
& A1_HF_PRESERVE
);
937 ret
= der_copy_octet_string(from
, to
);
943 switch (t
->tt
& A1_OP_MASK
) {
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
;
951 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
952 size
= sizeofType(t
->ptr
);
954 const struct asn1_type_func
*f
= t
->ptr
;
958 if (t
->tt
& A1_FLAG_OPTIONAL
) {
959 void **pfel
= (void **)fel
;
964 tel
= *ptel
= calloc(1, size
);
969 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
970 ret
= _asn1_copy(t
->ptr
, fel
, tel
);
972 const struct asn1_type_func
*f
= t
->ptr
;
973 ret
= (f
->copy
)(fel
, tel
);
977 if (t
->tt
& A1_FLAG_OPTIONAL
) {
986 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
987 const void *fel
= DPOC(from
, t
->offset
);
988 void *tel
= DPO(to
, t
->offset
);
990 if (type
> sizeof(prim
)/sizeof(prim
[0])) {
992 return ASN1_PARSE_ERROR
;
994 ret
= (prim
[type
].copy
)(fel
, tel
);
1000 const void *oldfrom
= from
;
1004 from
= DPOC(from
, t
->offset
);
1005 to
= DPO(to
, t
->offset
);
1007 if (t
->tt
& A1_FLAG_OPTIONAL
) {
1008 void **fel
= (void **)from
;
1017 to
= *tel
= calloc(1, sizeofType(t
->ptr
));
1022 ret
= _asn1_copy(t
->ptr
, from
, to
);
1024 if (t
->tt
& A1_FLAG_OPTIONAL
) {
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
);
1043 tel
->val
= calloc(fel
->len
, ellen
);
1044 if (tel
->val
== NULL
)
1047 tel
->len
= fel
->len
;
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
)));
1058 case A1_OP_BMEMBER
: {
1059 const struct asn1_template
*bmember
= t
->ptr
;
1060 size_t size
= bmember
->offset
;
1061 memcpy(to
, from
, size
);
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
);
1069 if (*felement
> A1_HEADER_LEN(choice
))
1070 return ASN1_PARSE_ERROR
;
1072 *telement
= *felement
;
1074 if (*felement
== 0) {
1075 ret
= der_copy_octet_string(DPOC(from
, choice
->tt
), DPO(to
, choice
->tt
));
1077 choice
+= *felement
;
1078 ret
= _asn1_copy(choice
->ptr
,
1079 DPOC(from
, choice
->offset
),
1080 DPO(to
, choice
->offset
));
1097 _asn1_decode_top(const struct asn1_template
*t
, unsigned flags
, const unsigned char *p
, size_t len
, void *data
, size_t *size
)
1100 memset(data
, 0, t
->offset
);
1101 ret
= _asn1_decode(t
, flags
, p
, len
, data
, size
);
1103 _asn1_free(t
, data
);
1104 memset(data
, 0, t
->offset
);
1111 _asn1_copy_top(const struct asn1_template
*t
, const void *from
, void *to
)
1114 memset(to
, 0, t
->offset
);
1115 ret
= _asn1_copy(t
, from
, to
);
1118 memset(to
, 0, t
->offset
);