2 * Copyright (c) 2009 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Portions Copyright (c) 2009 - 2010 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
39 struct asn1_type_func asn1_template_prim
[A1T_NUM_ENTRY
] = {
40 #define el(name, type) { \
41 (asn1_type_encode)der_put_##name, \
42 (asn1_type_decode)der_get_##name, \
43 (asn1_type_length)der_length_##name, \
44 (asn1_type_copy)der_copy_##name, \
45 (asn1_type_release)der_free_##name, \
48 #define elber(name, type) { \
49 (asn1_type_encode)der_put_##name, \
50 (asn1_type_decode)der_get_##name##_ber, \
51 (asn1_type_length)der_length_##name, \
52 (asn1_type_copy)der_copy_##name, \
53 (asn1_type_release)der_free_##name, \
57 el(heim_integer
, heim_integer
),
59 el(integer64
, int64_t),
60 el(unsigned, unsigned),
61 el(unsigned64
, uint64_t),
62 el(general_string
, heim_general_string
),
63 el(octet_string
, heim_octet_string
),
64 elber(octet_string
, heim_octet_string
),
65 el(ia5_string
, heim_ia5_string
),
66 el(bmp_string
, heim_bmp_string
),
67 el(universal_string
, heim_universal_string
),
68 el(printable_string
, heim_printable_string
),
69 el(visible_string
, heim_visible_string
),
70 el(utf8string
, heim_utf8_string
),
71 el(generalized_time
, time_t),
73 el(bit_string
, heim_bit_string
),
74 { (asn1_type_encode
)der_put_boolean
, (asn1_type_decode
)der_get_boolean
,
75 (asn1_type_length
)der_length_boolean
, (asn1_type_copy
)der_copy_integer
,
76 (asn1_type_release
)der_free_integer
, sizeof(int)
79 el(general_string
, heim_general_string
),
85 _asn1_sizeofType(const struct asn1_template
*t
)
91 * Here is abstraction to not so well evil fact of bit fields in C,
92 * they are endian dependent, so when getting and setting bits in the
93 * host local structure we need to know the endianness of the host.
95 * Its not the first time in Heimdal this have bitten us, and some day
96 * we'll grow up and use #defined constant, but bit fields are still
97 * so pretty and shiny.
101 _asn1_bmember_get_bit(const unsigned char *p
, void *data
,
102 unsigned int bit
, size_t size
)
104 unsigned int localbit
= bit
% 8;
105 if ((*p
>> (7 - localbit
)) & 1) {
106 #ifdef WORDS_BIGENDIAN
107 *(unsigned int *)data
|= (1 << ((size
* 8) - bit
- 1));
109 *(unsigned int *)data
|= (1 << bit
);
115 _asn1_bmember_isset_bit(const void *data
, unsigned int bit
, size_t size
)
117 #ifdef WORDS_BIGENDIAN
118 if ((*(unsigned int *)data
) & (1 << ((size
* 8) - bit
- 1)))
122 if ((*(unsigned int *)data
) & (1 << bit
))
129 _asn1_bmember_put_bit(unsigned char *p
, const void *data
, unsigned int bit
,
130 size_t size
, unsigned int *bitset
)
132 unsigned int localbit
= bit
% 8;
134 if (_asn1_bmember_isset_bit(data
, bit
, size
)) {
135 *p
|= (1 << (7 - localbit
));
137 *bitset
= (7 - localbit
) + 1;
142 _asn1_decode(const struct asn1_template
*t
, unsigned flags
,
143 const unsigned char *p
, size_t len
, void *data
, size_t *size
)
145 size_t elements
= A1_HEADER_LEN(t
);
148 const unsigned char *startp
= NULL
;
149 unsigned int template_flags
= t
->tt
;
151 /* skip over header */
154 if (template_flags
& A1_HF_PRESERVE
)
158 switch (t
->tt
& A1_OP_MASK
) {
160 case A1_OP_TYPE_EXTERN
: {
161 size_t newsize
, elsize
;
162 void *el
= DPO(data
, t
->offset
);
163 void **pel
= (void **)el
;
165 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
166 elsize
= _asn1_sizeofType(t
->ptr
);
168 const struct asn1_type_func
*f
= t
->ptr
;
172 if (t
->tt
& A1_FLAG_OPTIONAL
) {
173 *pel
= calloc(1, elsize
);
178 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
179 ret
= _asn1_decode(t
->ptr
, flags
, p
, len
, el
, &newsize
);
181 const struct asn1_type_func
*f
= t
->ptr
;
182 ret
= (f
->decode
)(p
, len
, el
, &newsize
);
185 if (t
->tt
& A1_FLAG_OPTIONAL
) {
192 p
+= newsize
; len
-= newsize
;
200 void *olddata
= data
;
201 int is_indefinite
= 0;
202 int subflags
= flags
;
204 ret
= der_match_tag_and_length(p
, len
, A1_TAG_CLASS(t
->tt
),
205 &dertype
, A1_TAG_TAG(t
->tt
),
208 if (t
->tt
& A1_FLAG_OPTIONAL
)
216 * Only allow indefinite encoding for OCTET STRING and BER
217 * for now. Should handle BIT STRING too.
220 if (dertype
!= A1_TAG_TYPE(t
->tt
) && (flags
& A1_PF_ALLOW_BER
)) {
221 const struct asn1_template
*subtype
= t
->ptr
;
222 subtype
++; /* skip header */
224 if (((subtype
->tt
& A1_OP_MASK
) == A1_OP_PARSE
) &&
225 A1_PARSE_TYPE(subtype
->tt
) == A1T_OCTET_STRING
)
226 subflags
|= A1_PF_INDEFINTE
;
229 if (datalen
== ASN1_INDEFINITE
) {
230 if ((flags
& A1_PF_ALLOW_BER
) == 0)
236 /* hide EndOfContent for sub-decoder, catching it below */
238 } else if (datalen
> len
)
241 data
= DPO(data
, t
->offset
);
243 if (t
->tt
& A1_FLAG_OPTIONAL
) {
244 void **el
= (void **)data
;
245 size_t ellen
= _asn1_sizeofType(t
->ptr
);
247 *el
= calloc(1, ellen
);
253 ret
= _asn1_decode(t
->ptr
, subflags
, p
, datalen
, data
, &newsize
);
258 /* If we use indefinite encoding, the newsize is the datasize. */
260 } else if (newsize
!= datalen
) {
261 /* Check for hidden data that might be after the real tag */
262 return ASN1_EXTRA_DATA
;
269 * Indefinite encoding needs a trailing EndOfContent,
273 ret
= der_match_tag_and_length(p
, len
, ASN1_C_UNIV
,
274 &dertype
, UT_EndOfContent
,
281 return ASN1_INDEF_EXTRA_DATA
;
289 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
291 void *el
= DPO(data
, t
->offset
);
294 * INDEFINITE primitive types are one element after the
295 * same type but non-INDEFINITE version.
297 if (flags
& A1_PF_INDEFINTE
)
300 if (type
>= sizeof(asn1_template_prim
)/sizeof(asn1_template_prim
[0])) {
302 return ASN1_PARSE_ERROR
;
305 ret
= (asn1_template_prim
[type
].decode
)(p
, len
, el
, &newsize
);
308 p
+= newsize
; len
-= newsize
;
314 struct template_of
*el
= DPO(data
, t
->offset
);
316 size_t ellen
= _asn1_sizeofType(t
->ptr
);
317 size_t vallength
= 0;
321 size_t newlen
= vallength
+ ellen
;
322 if (vallength
> newlen
)
323 return ASN1_OVERFLOW
;
325 tmp
= realloc(el
->val
, newlen
);
329 memset(DPO(tmp
, vallength
), 0, ellen
);
332 ret
= _asn1_decode(t
->ptr
, flags
& (~A1_PF_INDEFINTE
), p
, len
,
333 DPO(el
->val
, vallength
), &newsize
);
338 p
+= newsize
; len
-= newsize
;
343 case A1_OP_BMEMBER
: {
344 const struct asn1_template
*bmember
= t
->ptr
;
345 size_t bsize
= bmember
->offset
;
346 size_t belements
= A1_HEADER_LEN(bmember
);
351 memset(data
, 0, bsize
);
357 while (belements
&& len
) {
358 while (bmember
->offset
/ 8 > pos
/ 8) {
365 _asn1_bmember_get_bit(p
, data
, bmember
->offset
, bsize
);
366 belements
--; bmember
++;
373 const struct asn1_template
*choice
= t
->ptr
;
374 unsigned int *element
= DPO(data
, choice
->offset
);
378 /* provide a saner value as default, we should have a NO element value */
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(asn1_template_prim
)/sizeof(asn1_template_prim
[0])) {
518 return ASN1_PARSE_ERROR
;
521 ret
= (asn1_template_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
= _asn1_sizeofType(t
->ptr
);
531 heim_octet_string
*val
;
532 unsigned char *elptr
= el
->val
;
538 if (el
->len
> UINT_MAX
/sizeof(val
[0]))
541 val
= calloc(el
->len
, sizeof(val
[0]));
545 for(totallen
= 0, i
= 0; i
< el
->len
; i
++) {
549 val
[i
].length
= _asn1_length(t
->ptr
, elptr
);
551 val
[i
].data
= malloc(val
[i
].length
);
552 if (val
[i
].data
== NULL
) {
558 ret
= _asn1_encode(t
->ptr
, DPO(val
[i
].data
, val
[i
].length
- 1),
559 val
[i
].length
, elptr
, &l
);
563 next
= elptr
+ ellen
;
569 totallen
+= val
[i
].length
;
571 if (ret
== 0 && totallen
> len
)
574 for (i
= 0; i
< el
->len
; i
++)
582 qsort(val
, el
->len
, sizeof(val
[0]), _heim_der_set_sort
);
587 memcpy(p
+ 1, val
[i
].data
, val
[i
].length
);
596 struct template_of
*el
= DPO(data
, t
->offset
);
597 size_t ellen
= _asn1_sizeofType(t
->ptr
);
600 unsigned char *elptr
= el
->val
;
605 elptr
+= ellen
* (el
->len
- 1);
607 for (i
= 0; i
< el
->len
; i
++) {
608 ret
= _asn1_encode(t
->ptr
, p
, len
,
613 p
-= newsize
; len
-= newsize
;
619 case A1_OP_BMEMBER
: {
620 const struct asn1_template
*bmember
= t
->ptr
;
621 size_t bsize
= bmember
->offset
;
622 size_t belements
= A1_HEADER_LEN(bmember
);
625 unsigned int bitset
= 0;
626 int rfc1510
= (bmember
->tt
& A1_HBF_RFC1510
);
628 bmember
+= belements
;
633 pos
= bmember
->offset
;
635 while (belements
&& len
) {
636 while (bmember
->offset
/ 8 < pos
/ 8) {
637 if (rfc1510
|| bitset
|| c
) {
639 return ASN1_OVERFLOW
;
645 _asn1_bmember_put_bit(&c
, data
, bmember
->offset
, bsize
, &bitset
);
646 belements
--; bmember
--;
648 if (rfc1510
|| bitset
) {
650 return ASN1_OVERFLOW
;
655 return ASN1_OVERFLOW
;
656 if (rfc1510
|| bitset
== 0)
666 const struct asn1_template
*choice
= t
->ptr
;
667 const unsigned int *element
= DPOC(data
, choice
->offset
);
671 if (*element
> A1_HEADER_LEN(choice
)) {
672 printf("element: %d\n", *element
);
673 return ASN1_PARSE_ERROR
;
677 ret
+= der_put_octet_string(p
, len
,
678 DPOC(data
, choice
->tt
), &datalen
);
681 el
= DPOC(data
, choice
->offset
);
682 ret
= _asn1_encode(choice
->ptr
, p
, len
, el
, &datalen
);
686 len
-= datalen
; p
-= datalen
;
697 *size
= oldlen
- len
;
703 _asn1_length(const struct asn1_template
*t
, const void *data
)
705 size_t elements
= A1_HEADER_LEN(t
);
708 t
+= A1_HEADER_LEN(t
);
711 switch (t
->tt
& A1_OP_MASK
) {
713 case A1_OP_TYPE_EXTERN
: {
714 const void *el
= DPOC(data
, t
->offset
);
716 if (t
->tt
& A1_FLAG_OPTIONAL
) {
717 void **pel
= (void **)el
;
723 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
724 ret
+= _asn1_length(t
->ptr
, el
);
726 const struct asn1_type_func
*f
= t
->ptr
;
727 ret
+= (f
->length
)(el
);
733 const void *olddata
= data
;
735 data
= DPO(data
, t
->offset
);
737 if (t
->tt
& A1_FLAG_OPTIONAL
) {
738 void **el
= (void **)data
;
745 datalen
= _asn1_length(t
->ptr
, data
);
746 ret
+= der_length_tag(A1_TAG_TAG(t
->tt
)) + der_length_len(datalen
);
752 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
753 const void *el
= DPOC(data
, t
->offset
);
755 if (type
>= sizeof(asn1_template_prim
)/sizeof(asn1_template_prim
[0])) {
759 ret
+= (asn1_template_prim
[type
].length
)(el
);
764 const struct template_of
*el
= DPOC(data
, t
->offset
);
765 size_t ellen
= _asn1_sizeofType(t
->ptr
);
766 const unsigned char *element
= el
->val
;
769 for (i
= 0; i
< el
->len
; i
++) {
770 ret
+= _asn1_length(t
->ptr
, element
);
776 case A1_OP_BMEMBER
: {
777 const struct asn1_template
*bmember
= t
->ptr
;
778 size_t size
= bmember
->offset
;
779 size_t belements
= A1_HEADER_LEN(bmember
);
780 int rfc1510
= (bmember
->tt
& A1_HBF_RFC1510
);
788 bmember
+= belements
;
791 if (_asn1_bmember_isset_bit(data
, bmember
->offset
, size
)) {
792 ret
+= (bmember
->offset
/ 8) + 1;
795 belements
--; bmember
--;
801 const struct asn1_template
*choice
= t
->ptr
;
802 const unsigned int *element
= DPOC(data
, choice
->offset
);
804 if (*element
> A1_HEADER_LEN(choice
))
808 ret
+= der_length_octet_string(DPOC(data
, choice
->tt
));
811 ret
+= _asn1_length(choice
->ptr
, DPOC(data
, choice
->offset
));
826 _asn1_free(const struct asn1_template
*t
, void *data
)
828 size_t elements
= A1_HEADER_LEN(t
);
830 if (t
->tt
& A1_HF_PRESERVE
)
831 der_free_octet_string(data
);
836 switch (t
->tt
& A1_OP_MASK
) {
838 case A1_OP_TYPE_EXTERN
: {
839 void *el
= DPO(data
, t
->offset
);
841 if (t
->tt
& A1_FLAG_OPTIONAL
) {
842 void **pel
= (void **)el
;
848 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
849 _asn1_free(t
->ptr
, el
);
851 const struct asn1_type_func
*f
= t
->ptr
;
854 if (t
->tt
& A1_FLAG_OPTIONAL
)
860 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
861 void *el
= DPO(data
, t
->offset
);
863 if (type
>= sizeof(asn1_template_prim
)/sizeof(asn1_template_prim
[0])) {
867 (asn1_template_prim
[type
].release
)(el
);
871 void *el
= DPO(data
, t
->offset
);
873 if (t
->tt
& A1_FLAG_OPTIONAL
) {
874 void **pel
= (void **)el
;
880 _asn1_free(t
->ptr
, el
);
882 if (t
->tt
& A1_FLAG_OPTIONAL
)
889 struct template_of
*el
= DPO(data
, t
->offset
);
890 size_t ellen
= _asn1_sizeofType(t
->ptr
);
891 unsigned char *element
= el
->val
;
894 for (i
= 0; i
< el
->len
; i
++) {
895 _asn1_free(t
->ptr
, element
);
907 const struct asn1_template
*choice
= t
->ptr
;
908 const unsigned int *element
= DPOC(data
, choice
->offset
);
910 if (*element
> A1_HEADER_LEN(choice
))
914 der_free_octet_string(DPO(data
, choice
->tt
));
917 _asn1_free(choice
->ptr
, DPO(data
, choice
->offset
));
931 _asn1_copy(const struct asn1_template
*t
, const void *from
, void *to
)
933 size_t elements
= A1_HEADER_LEN(t
);
935 int preserve
= (t
->tt
& A1_HF_PRESERVE
);
940 ret
= der_copy_octet_string(from
, to
);
946 switch (t
->tt
& A1_OP_MASK
) {
948 case A1_OP_TYPE_EXTERN
: {
949 const void *fel
= DPOC(from
, t
->offset
);
950 void *tel
= DPO(to
, t
->offset
);
951 void **ptel
= (void **)tel
;
954 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
955 size
= _asn1_sizeofType(t
->ptr
);
957 const struct asn1_type_func
*f
= t
->ptr
;
961 if (t
->tt
& A1_FLAG_OPTIONAL
) {
962 void **pfel
= (void **)fel
;
967 tel
= *ptel
= calloc(1, size
);
972 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
973 ret
= _asn1_copy(t
->ptr
, fel
, tel
);
975 const struct asn1_type_func
*f
= t
->ptr
;
976 ret
= (f
->copy
)(fel
, tel
);
980 if (t
->tt
& A1_FLAG_OPTIONAL
) {
989 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
990 const void *fel
= DPOC(from
, t
->offset
);
991 void *tel
= DPO(to
, t
->offset
);
993 if (type
>= sizeof(asn1_template_prim
)/sizeof(asn1_template_prim
[0])) {
995 return ASN1_PARSE_ERROR
;
997 ret
= (asn1_template_prim
[type
].copy
)(fel
, tel
);
1003 const void *oldfrom
= from
;
1007 from
= DPOC(from
, t
->offset
);
1008 to
= DPO(to
, t
->offset
);
1010 if (t
->tt
& A1_FLAG_OPTIONAL
) {
1011 void **fel
= (void **)from
;
1020 to
= *tel
= calloc(1, _asn1_sizeofType(t
->ptr
));
1025 ret
= _asn1_copy(t
->ptr
, from
, to
);
1041 const struct template_of
*fel
= DPOC(from
, t
->offset
);
1042 struct template_of
*tel
= DPO(to
, t
->offset
);
1043 size_t ellen
= _asn1_sizeofType(t
->ptr
);
1046 tel
->val
= calloc(fel
->len
, ellen
);
1047 if (tel
->val
== NULL
)
1050 tel
->len
= fel
->len
;
1052 for (i
= 0; i
< fel
->len
; i
++) {
1053 ret
= _asn1_copy(t
->ptr
,
1054 DPOC(fel
->val
, (i
* ellen
)),
1055 DPO(tel
->val
, (i
*ellen
)));
1061 case A1_OP_BMEMBER
: {
1062 const struct asn1_template
*bmember
= t
->ptr
;
1063 size_t size
= bmember
->offset
;
1064 memcpy(to
, from
, size
);
1067 case A1_OP_CHOICE
: {
1068 const struct asn1_template
*choice
= t
->ptr
;
1069 const unsigned int *felement
= DPOC(from
, choice
->offset
);
1070 unsigned int *telement
= DPO(to
, choice
->offset
);
1072 if (*felement
> A1_HEADER_LEN(choice
))
1073 return ASN1_PARSE_ERROR
;
1075 *telement
= *felement
;
1077 if (*felement
== 0) {
1078 ret
= der_copy_octet_string(DPOC(from
, choice
->tt
), DPO(to
, choice
->tt
));
1080 choice
+= *felement
;
1081 ret
= _asn1_copy(choice
->ptr
,
1082 DPOC(from
, choice
->offset
),
1083 DPO(to
, choice
->offset
));
1100 _asn1_decode_top(const struct asn1_template
*t
, unsigned flags
, const unsigned char *p
, size_t len
, void *data
, size_t *size
)
1103 memset(data
, 0, t
->offset
);
1104 ret
= _asn1_decode(t
, flags
, p
, len
, data
, size
);
1106 _asn1_free_top(t
, data
);
1112 _asn1_copy_top(const struct asn1_template
*t
, const void *from
, void *to
)
1115 memset(to
, 0, t
->offset
);
1116 ret
= _asn1_copy(t
, from
, to
);
1118 _asn1_free_top(t
, to
);
1124 _asn1_free_top(const struct asn1_template
*t
, void *data
)
1126 _asn1_free(t
, data
);
1127 memset(data
, 0, t
->offset
);