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 #include <vis-extras.h>
42 /* Very old MSVC CRTs don't have ENOTSUP */
43 #define ENOTSUP EINVAL
46 struct asn1_type_func asn1_template_prim
[A1T_NUM_ENTRY
] = {
47 #define el(name, type) { \
48 (asn1_type_encode)der_put_##name, \
49 (asn1_type_decode)der_get_##name, \
50 (asn1_type_length)der_length_##name, \
51 (asn1_type_copy)der_copy_##name, \
52 (asn1_type_release)der_free_##name, \
53 (asn1_type_print)der_print_##name, \
56 #define elber(name, type) { \
57 (asn1_type_encode)der_put_##name, \
58 (asn1_type_decode)der_get_##name##_ber, \
59 (asn1_type_length)der_length_##name, \
60 (asn1_type_copy)der_copy_##name, \
61 (asn1_type_release)der_free_##name, \
62 (asn1_type_print)der_print_##name, \
66 el(heim_integer
, heim_integer
),
68 el(integer64
, int64_t),
69 el(unsigned, unsigned),
70 el(unsigned64
, uint64_t),
71 el(general_string
, heim_general_string
),
72 el(octet_string
, heim_octet_string
),
73 elber(octet_string
, heim_octet_string
),
74 el(ia5_string
, heim_ia5_string
),
75 el(bmp_string
, heim_bmp_string
),
76 el(universal_string
, heim_universal_string
),
77 el(printable_string
, heim_printable_string
),
78 el(visible_string
, heim_visible_string
),
79 el(utf8string
, heim_utf8_string
),
80 el(generalized_time
, time_t),
82 el(bit_string
, heim_bit_string
),
83 { (asn1_type_encode
)der_put_boolean
, (asn1_type_decode
)der_get_boolean
,
84 (asn1_type_length
)der_length_boolean
, (asn1_type_copy
)der_copy_integer
,
85 (asn1_type_release
)der_free_integer
, (asn1_type_print
)der_print_boolean
,
89 el(general_string
, heim_general_string
),
95 _asn1_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 _asn1_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
|= (1u << ((size
* 8) - bit
- 1));
119 *(unsigned int *)data
|= (1u << bit
);
125 _asn1_bmember_isset_bit(const void *data
, unsigned int bit
, size_t size
)
127 #ifdef WORDS_BIGENDIAN
128 if ((*(unsigned int *)data
) & (1u << ((size
* 8) - bit
- 1)))
132 if ((*(unsigned int *)data
) & (1u << bit
))
139 _asn1_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 (_asn1_bmember_isset_bit(data
, bit
, size
)) {
145 *p
|= (1u << (7 - localbit
));
147 *bitset
= (7 - localbit
) + 1;
152 * Utility function to tell us if the encoding of some type per its template
153 * will have an outer tag. This is needed when the caller wants to slap on an
154 * IMPLICIT tag: if the inner type has a tag then we need to replace it.
157 is_tagged(const struct asn1_template
*t
)
159 size_t elements
= A1_HEADER_LEN(t
);
161 t
+= A1_HEADER_LEN(t
);
164 switch (t
->tt
& A1_OP_MASK
) {
165 case A1_OP_SEQOF
: return 0;
166 case A1_OP_SETOF
: return 0;
167 case A1_OP_BMEMBER
: return 0;
168 case A1_OP_PARSE
: return 0;
169 case A1_OP_TAG
: return 1;
170 case A1_OP_CHOICE
: return 1;
171 case A1_OP_TYPE
: return 1;
172 case A1_OP_TYPE_EXTERN
: {
173 const struct asn1_type_func
*f
= t
->ptr
;
176 * XXX Add a boolean to struct asn1_type_func to tell us if the type is
177 * tagged or not. Basically, it's not tagged if it's primitive.
179 if (f
->encode
== (asn1_type_encode
)encode_heim_any
||
180 f
->encode
== (asn1_type_encode
)encode_HEIM_ANY
)
189 inner_type_taglen(const struct asn1_template
*t
)
191 size_t elements
= A1_HEADER_LEN(t
);
193 t
+= A1_HEADER_LEN(t
);
196 switch (t
->tt
& A1_OP_MASK
) {
197 case A1_OP_SEQOF
: return 0;
198 case A1_OP_SETOF
: return 0;
199 case A1_OP_BMEMBER
: return 0;
200 case A1_OP_PARSE
: return 0;
201 case A1_OP_CHOICE
: return 1;
202 case A1_OP_TYPE
: return inner_type_taglen(t
->ptr
);
203 case A1_OP_TAG
: return der_length_tag(A1_TAG_TAG(t
->tt
));
204 case A1_OP_TYPE_EXTERN
: {
205 const struct asn1_type_func
*f
= t
->ptr
;
208 * XXX Add a boolean to struct asn1_type_func to tell us if the type is
209 * tagged or not. Basically, it's not tagged if it's primitive.
211 if (f
->encode
== (asn1_type_encode
)encode_heim_any
||
212 f
->encode
== (asn1_type_encode
)encode_HEIM_ANY
)
218 _exit(0); /* Quiet VC */
224 * Compare some int of unknown size in a type ID field to the int value in
225 * some IOS object's type ID template entry.
227 * This should be called with a `A1_TAG_T(ASN1_C_UNIV, PRIM, UT_Integer)'
228 * template as the `ttypeid'.
231 typeid_int_cmp(const void *intp
,
233 const struct asn1_template
*ttypeid
)
235 const struct asn1_template
*tint
= ttypeid
->ptr
;
237 if ((tint
[1].tt
& A1_OP_MASK
) != A1_OP_PARSE
)
239 if (A1_PARSE_TYPE(tint
[1].tt
) != A1T_INTEGER
&&
240 A1_PARSE_TYPE(tint
[1].tt
) != A1T_UNSIGNED
&&
241 A1_PARSE_TYPE(tint
[1].tt
) != A1T_INTEGER64
&&
242 A1_PARSE_TYPE(tint
[1].tt
) != A1T_UNSIGNED64
&&
243 A1_PARSE_TYPE(tint
[1].tt
) != A1T_IMEMBER
)
245 switch (tint
[0].offset
) {
246 case 8: return i
- *(const int64_t *)intp
;
247 case 4: return i
- *(const int32_t *)intp
;
253 * Map a logical SET/SEQUENCE member to a template entry.
255 * This should really have been done by the compiler, but clearly it wasn't.
257 * The point is that a struct type's template may be littered with entries that
258 * don't directly correspond to a struct field (SET/SEQUENCE member), so we
259 * have to count just the ones that do to get to the one we want.
261 static const struct asn1_template
*
262 template4member(const struct asn1_template
*t
, size_t f
)
264 size_t n
= (uintptr_t)t
->ptr
;
267 for (i
= 0, t
++; i
< n
; t
++, i
++) {
268 switch (t
->tt
& A1_OP_MASK
) {
271 case A1_OP_TYPE_EXTERN
:
275 case A1_OP_OPENTYPE_OBJSET
:
286 * Attempt to decode known open type alternatives into a CHOICE-like
287 * discriminated union.
291 * - object set template
293 * - pointer to memory object (C struct) to decode into
294 * - template for type ID field of `data'
295 * - template for open type field of `data' (an octet string or HEIM_ANY)
302 * Other errors in decoding open type values are ignored, but applications can
303 * note that an error must have occurred. (Perhaps we should generate a `ret'
304 * field for the discriminated union we decode into that we could use to
305 * indicate what went wrong with decoding an open type value? The application
306 * can always try to decode itself to find out what the error was, but the
307 * whole point is to save the developer the bother of writing code to decode
308 * open type values. Then again, the specific cause of any one decode failure
309 * is not usually very important to users, so it's not very important to
310 * applications either.)
312 * Here `data' is something like this:
314 * typedef struct SingleAttribute {
315 * heim_oid type; // <--- decoded already
316 * HEIM_ANY value; // <--- decoded already
317 * // We must set this:
321 * choice_SingleAttribute_iosnumunknown = 0,
322 * choice_SingleAttribute_iosnum_id_at_name,
324 * choice_SingleAttribute_iosnum_id_at_emailAddress,
325 * } element; // <--- map type ID to enum
328 * X520name* at_surname;
330 * AliasIA5String* at_emailAddress;
331 * } u; // <--- alloc and decode val above into this
332 * } _ioschoice_value;
337 * typedef struct AttributeSet {
338 * heim_oid type; // <--- decoded already
339 * struct AttributeSet_values {
340 * unsigned int len; // <--- decoded already
341 * HEIM_ANY *val; // <--- decoded already
343 * // We must set this:
346 * enum { choice_AttributeSet_iosnumunknown = 0,
347 * choice_AttributeSet_iosnum_id_at_name,
348 * choice_AttributeSet_iosnum_id_at_surname,
350 * choice_AttributeSet_iosnum_id_at_emailAddress,
351 * } element; // <--- map type ID to enum
352 * unsigned int len; // <--- set len to len as above
355 * X520name *at_surname;
357 * AliasIA5String *at_emailAddress;
358 * } *val; // <--- alloc and decode vals above into this
359 * } _ioschoice_values;
363 _asn1_decode_open_type(const struct asn1_template
*t
,
366 const struct asn1_template
*ttypeid
,
367 const struct asn1_template
*topentype
)
369 const struct asn1_template
*ttypeid_univ
= ttypeid
;
370 const struct asn1_template
*tactual_type
;
371 const struct asn1_template
*tos
= t
->ptr
;
374 unsigned int *lenp
= NULL
; /* Pointer to array length field */
375 unsigned int len
= 1; /* Array length */
376 void **dp
= NULL
; /* Decoded open type struct pointer */
377 int *elementp
; /* Choice enum pointer */
378 int typeid_is_oid
= 0;
379 int typeid_is_int
= 0;
383 * NOTE: Here expressions like `DPO(data, t->offset + ...)' refer to parts
384 * of a _ioschoice_<fieldName> struct field of `data'.
386 * Expressions like `DPO(data, topentype->offset + ...)' refer to
387 * the open type field in `data', which is either a `heim_any', a
388 * `heim_octet_string', or an array of one of those.
390 * Expressions like `DPO(data, ttypeid->offset)' refer to the open
391 * type's type ID field in `data'.
397 * - set type choice to choice_<type>_iosnumunknown (zero).
398 * - set union value to zero
400 * We need a pointer to the choice ID:
402 * typedef struct AttributeSet {
403 * heim_oid type; // <--- decoded already
404 * struct AttributeSet_values {
405 * unsigned int len; // <--- decoded already
406 * HEIM_ANY *val; // <--- decoded already
409 * enum { choice_AttributeSet_iosnumunknown = 0,
416 * XXX NOTE: We're assuming that sizeof(enum) == sizeof(int)!
418 elementp
= DPO(data
, t
->offset
);
419 *elementp
= 0; /* Set the choice to choice_<type>_iosnumunknown */
420 if (t
->tt
& A1_OS_OT_IS_ARRAY
) {
422 * The open type is a SET OF / SEQUENCE OF -- an array.
424 * Get the number of elements to decode from:
426 * typedef struct AttributeSet {
428 * struct AttributeSet_values {
429 * ------------>unsigned int len; // HERE
435 len
= *((unsigned int *)DPO(data
, topentype
->offset
));
438 * Set the number of decoded elements to zero for now:
440 * typedef struct AttributeSet {
442 * struct AttributeSet_values {
447 * enum { ... } element;
448 * ------------>unsigned int len; // HERE
450 * } _ioschoice_values;
453 lenp
= DPO(data
, t
->offset
+ sizeof(*elementp
));
456 * Get a pointer to the place where we must put the decoded value:
458 * typedef struct AttributeSet {
460 * struct AttributeSet_values {
465 * enum { ... } element;
468 * union { SomeType *some_choice; ... } u;
469 * ------------>} *val; // HERE
470 * } _ioschoice_values;
473 dp
= DPO(data
, t
->offset
+ sizeof(*elementp
) + sizeof(*lenp
));
476 * Get a pointer to the place where we must put the decoded value:
478 * typedef struct SingleAttribute {
482 * enum { ... } element;
483 * ------------>union { SomeType *some_choice; ... } u; // HERE
484 * } _ioschoice_value;
487 dp
= DPO(data
, t
->offset
+ sizeof(*elementp
));
491 while (sizeof(void *) != sizeof(*elementp
) &&
492 ((uintptr_t)dp
) % sizeof(void *) != 0)
493 dp
= (void *)(((char *)dp
) + sizeof(*elementp
));
497 * Find out the type of the type ID member. We currently support only
500 * Chase through any tags to get to the type.
502 while (((ttypeid_univ
->tt
& A1_OP_MASK
) == A1_OP_TAG
&&
503 A1_TAG_CLASS(ttypeid_univ
->tt
) == ASN1_C_CONTEXT
) ||
504 ((ttypeid_univ
->tt
& A1_OP_MASK
) == A1_OP_TYPE
)) {
505 ttypeid_univ
= ttypeid_univ
->ptr
;
508 switch (ttypeid_univ
->tt
& A1_OP_MASK
) {
510 if (A1_TAG_CLASS(ttypeid_univ
->tt
) != ASN1_C_UNIV
)
511 return 0; /* Do nothing, silently */
512 switch (A1_TAG_TAG(ttypeid_univ
->tt
)) {
517 const struct asn1_template
*tint
= ttypeid_univ
->ptr
;
521 if ((tint
->tt
& A1_OP_MASK
) != A1_OP_PARSE
)
522 return 0; /* Do nothing, silently */
523 if (A1_PARSE_TYPE(tint
->tt
) != A1T_INTEGER
&&
524 A1_PARSE_TYPE(tint
->tt
) != A1T_UNSIGNED
&&
525 A1_PARSE_TYPE(tint
->tt
) != A1T_INTEGER64
&&
526 A1_PARSE_TYPE(tint
->tt
) != A1T_UNSIGNED64
&&
527 A1_PARSE_TYPE(tint
->tt
) != A1T_IMEMBER
)
528 return 0; /* Do nothing, silently (maybe a large int) */
532 /* It might be cool to support string types as type ID types */
533 default: return 0; /* Do nothing, silently */
536 default: return 0; /* Do nothing, silently */
540 * Find the type of the open type.
542 * An object set template looks like:
544 * const struct asn1_template asn1_ObjectSetName[] = {
545 * // Header entry (in this case it says there's 17 objects):
546 * { 0, 0, ((void*)17) },
548 * // here's the name of the object set:
549 * { A1_OP_NAME, 0, "ObjectSetName" },
551 * // then three entries per object: object name, object type ID,
553 * { A1_OP_NAME, 0, "ext-AuthorityInfoAccess" },
554 * { A1_OP_OPENTYPE_ID, 0, (const void*)&asn1_oid_oidName },
555 * { A1_OP_OPENTYPE, sizeof(SomeType), (const void*)&asn1_SomeType },
559 * `i' being a logical object offset, i*3+3 would be the index of the
560 * A1_OP_OPENTYPE_ID entry for the current object, and i*3+4 the index of
561 * the A1_OP_OPENTYPE entry for the current object.
563 if (t
->tt
& A1_OS_IS_SORTED
) {
565 size_t right
= A1_HEADER_LEN(tos
);
566 const void *vp
= DPO(data
, ttypeid
->offset
);
569 while (left
< right
) {
570 size_t mid
= (left
+ right
) >> 1;
572 if ((tos
[3 + mid
* 3].tt
& A1_OP_MASK
) != A1_OP_OPENTYPE_ID
)
575 c
= typeid_int_cmp(vp
, (intptr_t)tos
[3 + mid
* 3].ptr
,
577 else if (typeid_is_oid
)
578 c
= der_heim_oid_cmp(vp
, tos
[3 + mid
* 3].ptr
);
589 return 0; /* No match */
591 for (i
= 0, n
= A1_HEADER_LEN(tos
); i
< n
; i
++) {
592 /* We add 1 to `i' because we're skipping the header */
593 if ((tos
[3 + i
*3].tt
& A1_OP_MASK
) != A1_OP_OPENTYPE_ID
)
596 typeid_int_cmp(DPO(data
, ttypeid
->offset
),
597 (intptr_t)tos
[3 + i
*3].ptr
,
601 der_heim_oid_cmp(DPO(data
, ttypeid
->offset
), tos
[3 + i
*3].ptr
))
606 return 0; /* No match */
610 *elementp
= i
+1; /* Zero is the "unknown" choice, so add 1 */
613 * We want the A1_OP_OPENTYPE template entry. Its `offset' is the sizeof
614 * the object we'll be decoding into, and its `ptr' is the pointer to the
615 * template for decoding that type.
617 tactual_type
= &tos
[i
*3 + 4];
619 /* Decode the encoded open type value(s) */
620 if (!(t
->tt
& A1_OS_OT_IS_ARRAY
)) {
622 * Not a SET OF/SEQUENCE OF open type, just singular.
624 * We need the address of the octet string / ANY field containing the
625 * encoded open type value:
627 * typedef struct SingleAttribute {
629 * -------->HEIM_ANY value; // HERE
635 const struct heim_base_data
*d
= DPOC(data
, topentype
->offset
);
638 if (d
->data
&& d
->length
) {
639 if ((o
= calloc(1, tactual_type
->offset
)) == NULL
)
642 /* Re-enter to decode the encoded open type value */
643 ret
= _asn1_decode(tactual_type
->ptr
, flags
, d
->data
, d
->length
, o
, &sz
);
645 * Store the decoded object in the union:
647 * typedef struct SingleAttribute {
651 * enum { ... } element;
652 * ------------>union { SomeType *some_choice; ... } u; // HERE
653 * } _ioschoice_value;
656 * All the union arms are pointers.
659 _asn1_free(tactual_type
->ptr
, o
);
662 * So we failed to decode the open type -- that should not be fatal
663 * to decoding the rest of the input. Only ENOMEM should be fatal.
672 const struct heim_base_data
* const *d
;
673 void **val
; /* Array of pointers */
676 * A SET OF/SEQUENCE OF open type, plural.
678 * We need the address of the octet string / ANY array pointer field
679 * containing the encoded open type values:
681 * typedef struct AttributeSet {
683 * struct AttributeSet_values {
685 * ------------>HEIM_ANY *val; // HERE
690 * We already know the value of the `len' field.
692 d
= DPOC(data
, topentype
->offset
+ sizeof(unsigned int));
693 while (sizeof(void *) != sizeof(len
) &&
694 ((uintptr_t)d
) % sizeof(void *) != 0)
695 d
= (const void *)(((const char *)d
) + sizeof(len
));
697 if ((val
= calloc(len
, sizeof(*val
))) == NULL
)
700 /* Increment the count of decoded values as we decode */
702 for (i
= 0; ret
!= ENOMEM
&& i
< len
; i
++) {
703 if ((val
[i
] = calloc(1, tactual_type
->offset
)) == NULL
)
706 /* Re-enter to decode the encoded open type value */
707 ret
= _asn1_decode(tactual_type
->ptr
, flags
, d
[0][i
].data
,
708 d
[0][i
].length
, val
[i
], &sz
);
710 _asn1_free(tactual_type
->ptr
, val
[i
]);
716 ret
= 0; /* See above */
723 _asn1_decode(const struct asn1_template
*t
, unsigned flags
,
724 const unsigned char *p
, size_t len
, void *data
, size_t *size
)
726 const struct asn1_template
*tbase
= t
;
727 const struct asn1_template
*tdefval
= NULL
;
728 size_t elements
= A1_HEADER_LEN(t
);
731 const unsigned char *startp
= NULL
;
732 unsigned int template_flags
= t
->tt
;
737 * - by and large we don't call _asn1_free() on error, except when we're
738 * decoding optional things or choices, then we do call _asn1_free()
741 * instead we leave it to _asn1_decode_top() to call _asn1_free() on
744 * - on error all fields of whatever we didn't _asn1_free() must have been
745 * initialized to sane values because _asn1_decode_top() will call
746 * _asn1_free() on error, so we must have left everything initialized
747 * that _asn1_free() could possibly look at
749 * - so we must initialize everything
751 * FIXME? but we mostly rely on calloc() to do this...
753 * - we don't use malloc() unless we're going to write over the whole
754 * thing with memcpy() or whatever
757 /* skip over header */
760 if (template_flags
& A1_HF_PRESERVE
)
764 switch (t
->tt
& A1_OP_MASK
) {
765 case A1_OP_OPENTYPE_OBJSET
: {
766 size_t opentypeid
= t
->tt
& ((1<<10)-1);
767 size_t opentype
= (t
->tt
>> 10) & ((1<<10)-1);
769 /* Note that the only error returned here would be ENOMEM */
770 ret
= _asn1_decode_open_type(t
, flags
, data
,
771 template4member(tbase
, opentypeid
),
772 template4member(tbase
, opentype
));
777 case A1_OP_TYPE_DECORATE
: break;
778 case A1_OP_NAME
: break;
783 case A1_OP_TYPE_EXTERN
: {
784 size_t newsize
, elsize
;
785 void *el
= DPO(data
, t
->offset
);
786 void **pel
= (void **)el
;
788 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
789 elsize
= _asn1_sizeofType(t
->ptr
);
791 const struct asn1_type_func
*f
= t
->ptr
;
795 if (t
->tt
& A1_FLAG_OPTIONAL
) {
796 *pel
= calloc(1, elsize
);
800 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
801 ret
= _asn1_decode(t
->ptr
, flags
, p
, len
, el
, &newsize
);
803 const struct asn1_type_func
*f
= t
->ptr
;
804 ret
= (f
->decode
)(p
, len
, el
, &newsize
);
808 * Optional field not present in encoding, presumably,
809 * though we should really look more carefully at `ret'.
811 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
812 _asn1_free(t
->ptr
, el
);
814 const struct asn1_type_func
*f
= t
->ptr
;
822 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
823 ret
= _asn1_decode(t
->ptr
, flags
, p
, len
, el
, &newsize
);
825 const struct asn1_type_func
*f
= t
->ptr
;
826 ret
= (f
->decode
)(p
, len
, el
, &newsize
);
830 if (t
->tt
& A1_FLAG_OPTIONAL
) {
831 } else if (t
->tt
& A1_FLAG_DEFAULT
) {
833 * Defaulted field not present in encoding, presumably,
834 * though we should really look more carefully at `ret'.
836 if (tdefval
->tt
& A1_DV_BOOLEAN
) {
837 int *i
= (void *)(char *)el
;
839 *i
= tdefval
->ptr
? 1 : 0;
840 } else if (tdefval
->tt
& A1_DV_INTEGER64
) {
841 int64_t *i
= (void *)(char *)el
;
843 *i
= (int64_t)(intptr_t)tdefval
->ptr
;
844 } else if (tdefval
->tt
& A1_DV_INTEGER32
) {
845 int32_t *i
= (void *)(char *)el
;
847 *i
= (int32_t)(intptr_t)tdefval
->ptr
;
848 } else if (tdefval
->tt
& A1_DV_INTEGER
) {
849 struct heim_integer
*i
= (void *)(char *)el
;
851 if ((ret
= der_copy_heim_integer(tdefval
->ptr
, i
)))
853 } else if (tdefval
->tt
& A1_DV_UTF8STRING
) {
856 if ((*s
= strdup(tdefval
->ptr
)) == NULL
)
863 return ret
; /* Error decoding required field */
865 p
+= newsize
; len
-= newsize
;
872 size_t datalen
, l
= 0;
873 void *olddata
= data
;
874 int is_indefinite
= 0;
875 int subflags
= flags
;
876 int replace_tag
= (t
->tt
& A1_FLAG_IMPLICIT
) && is_tagged(t
->ptr
);
877 void *el
= data
= DPO(data
, t
->offset
);
878 void **pel
= (void **)el
;
881 * XXX If this type (chasing t->ptr through IMPLICIT tags, if this
882 * one is too, till we find a non-TTag) is a [UNIVERSAL SET] type,
883 * then we have to accept fields out of order. For each field tag
884 * we see we'd have to do a linear search of the SET's template
885 * because it won't be sorted (or we could sort a copy and do a
886 * binary search on that, but these SETs will always be small so it
887 * won't be worthwhile). We'll need a utility function to do all
890 ret
= der_match_tag_and_length(p
, len
, A1_TAG_CLASS(t
->tt
),
891 &dertype
, A1_TAG_TAG(t
->tt
),
894 if (t
->tt
& A1_FLAG_OPTIONAL
) {
897 } else if (t
->tt
& A1_FLAG_DEFAULT
) {
899 * Defaulted field not present in encoding, presumably,
900 * though we should really look more carefully at `ret'.
902 if (tdefval
->tt
& A1_DV_BOOLEAN
) {
903 int *i
= (void *)(char *)data
;
905 *i
= tdefval
->ptr
? 1 : 0;
906 } else if (tdefval
->tt
& A1_DV_INTEGER64
) {
907 int64_t *i
= (void *)(char *)data
;
909 *i
= (int64_t)(intptr_t)tdefval
->ptr
;
910 } else if (tdefval
->tt
& A1_DV_INTEGER32
) {
911 int32_t *i
= (void *)(char *)data
;
913 *i
= (int32_t)(intptr_t)tdefval
->ptr
;
914 } else if (tdefval
->tt
& A1_DV_INTEGER
) {
915 struct heim_integer
*i
= (void *)(char *)data
;
917 if ((ret
= der_copy_heim_integer(tdefval
->ptr
, i
)))
919 } else if (tdefval
->tt
& A1_DV_UTF8STRING
) {
922 if ((*s
= strdup(tdefval
->ptr
)) == NULL
)
930 return ret
; /* Error decoding required field */
936 * Only allow indefinite encoding for OCTET STRING and BER
937 * for now. Should handle BIT STRING too.
940 if (dertype
!= A1_TAG_TYPE(t
->tt
) && (flags
& A1_PF_ALLOW_BER
)) {
941 const struct asn1_template
*subtype
= t
->ptr
;
942 subtype
++; /* skip header */
944 if (((subtype
->tt
& A1_OP_MASK
) == A1_OP_PARSE
) &&
945 A1_PARSE_TYPE(subtype
->tt
) == A1T_OCTET_STRING
)
946 subflags
|= A1_PF_INDEFINTE
;
949 if (datalen
== ASN1_INDEFINITE
) {
950 if ((flags
& A1_PF_ALLOW_BER
) == 0)
956 /* hide EndOfContent for sub-decoder, catching it below */
958 } else if (datalen
> len
)
961 if (t
->tt
& A1_FLAG_OPTIONAL
) {
962 size_t ellen
= _asn1_sizeofType(t
->ptr
);
964 *pel
= calloc(1, ellen
);
971 const struct asn1_template
*subtype
= t
->ptr
;
975 * So, we have an IMPLICIT tag. What we want to do is find the
976 * template for the body of the type so-tagged. That's going
977 * to be a template that has a tag that isn't itself IMPLICIT.
979 * So we chase the pointer in the template until we find such a
980 * thing, then decode using that template.
984 if ((subtype
->tt
& A1_OP_MASK
) == A1_OP_TAG
)
985 replace_tag
= (subtype
->tt
& A1_FLAG_IMPLICIT
) && is_tagged(t
->ptr
);
987 subtype
= subtype
->ptr
;
990 if ((subtype
->tt
& A1_OP_MASK
) == A1_OP_TAG
) {
991 ret
= _asn1_decode(subtype
->ptr
, subflags
, p
, datalen
, data
, &newsize
);
994 subtype
= subtype
->ptr
;
998 ret
= _asn1_decode(t
->ptr
, subflags
, p
, datalen
, data
, &newsize
);
1000 if (ret
== 0 && !is_indefinite
&& newsize
!= datalen
)
1002 ret
= ASN1_EXTRA_DATA
;
1005 if (is_indefinite
) {
1006 /* If we use indefinite encoding, the newsize is the datasize. */
1014 * Indefinite encoding needs a trailing EndOfContent,
1017 if (is_indefinite
) {
1018 ret
= der_match_tag_and_length(p
, len
, ASN1_C_UNIV
,
1019 &dertype
, UT_EndOfContent
,
1021 if (ret
== 0 && dertype
!= PRIM
)
1023 else if (ret
== 0 && datalen
!= 0)
1024 ret
= ASN1_INDEF_EXTRA_DATA
;
1031 if (!(t
->tt
& A1_FLAG_OPTIONAL
))
1034 _asn1_free(t
->ptr
, data
);
1044 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
1046 void *el
= DPO(data
, t
->offset
);
1049 * INDEFINITE primitive types are one element after the
1050 * same type but non-INDEFINITE version.
1052 if (flags
& A1_PF_INDEFINTE
)
1055 if (type
>= sizeof(asn1_template_prim
)/sizeof(asn1_template_prim
[0])) {
1057 return ASN1_PARSE_ERROR
;
1060 ret
= (asn1_template_prim
[type
].decode
)(p
, len
, el
, &newsize
);
1063 p
+= newsize
; len
-= newsize
;
1069 struct template_of
*el
= DPO(data
, t
->offset
);
1071 size_t ellen
= _asn1_sizeofType(t
->ptr
);
1072 size_t vallength
= 0;
1076 size_t newlen
= vallength
+ ellen
;
1077 if (vallength
> newlen
)
1078 return ASN1_OVERFLOW
;
1081 tmp
= realloc(el
->val
, newlen
);
1085 memset(DPO(tmp
, vallength
), 0, ellen
);
1089 ret
= _asn1_decode(t
->ptr
, flags
& (~A1_PF_INDEFINTE
), p
, len
,
1090 DPO(el
->val
, vallength
), &newsize
);
1094 p
+= newsize
; len
-= newsize
;
1099 case A1_OP_BMEMBER
: {
1100 const struct asn1_template
*bmember
= t
->ptr
;
1101 size_t bsize
= bmember
->offset
;
1102 size_t belements
= A1_HEADER_LEN(bmember
);
1107 memset(data
, 0, bsize
);
1110 return ASN1_OVERRUN
;
1113 while (belements
&& len
) {
1114 while (bmember
->offset
/ 8 > pos
/ 8) {
1121 _asn1_bmember_get_bit(p
, data
, bmember
->offset
, bsize
);
1122 belements
--; bmember
++;
1128 case A1_OP_CHOICE
: {
1129 const struct asn1_template
*choice
= t
->ptr
;
1130 unsigned int *element
= DPO(data
, choice
->offset
);
1135 * CHOICE element IDs are assigned in monotonically increasing
1136 * fashion. Therefore any unrealistic value is a suitable invalid
1137 * CHOICE value. The largest binary value (or -1 if treating the
1138 * enum as signed on a twos-complement system, or...) will do.
1142 for (i
= 1; i
< A1_HEADER_LEN(choice
) + 1 && choice
[i
].tt
; i
++) {
1144 * This is more permissive than is required. CHOICE
1145 * alternatives must have different outer tags, so in principle
1146 * we should just match the tag at `p' and `len' in sequence to
1147 * the choice alternatives.
1149 * Trying every alternative instead happens to do this anyways
1150 * because each one will first match the tag at `p' and `len',
1151 * but if there are CHOICE altnernatives with the same outer
1152 * tag, then we'll allow it, and they had better be unambiguous
1153 * in their internal details, otherwise there would be some
1156 * Arguably the *compiler* should detect ambiguous CHOICE types
1157 * and raise an error, then we don't have to be concerned here
1160 ret
= _asn1_decode(choice
[i
].ptr
, 0, p
, len
,
1161 DPO(data
, choice
[i
].offset
), &datalen
);
1164 p
+= datalen
; len
-= datalen
;
1167 _asn1_free(choice
[i
].ptr
, DPO(data
, choice
[i
].offset
));
1168 if (ret
!= ASN1_BAD_ID
&& ret
!= ASN1_MISPLACED_FIELD
&&
1169 ret
!= ASN1_MISSING_FIELD
)
1172 if (i
>= A1_HEADER_LEN(choice
) + 1 || !choice
[i
].tt
) {
1173 if (choice
->tt
== 0)
1176 /* This is the ellipsis case */
1178 ret
= der_get_octet_string(p
, len
,
1179 DPO(data
, choice
->tt
), &datalen
);
1182 p
+= datalen
; len
-= datalen
;
1189 return ASN1_PARSE_ERROR
;
1194 /* if we are using padding, eat up read of context */
1195 if (template_flags
& A1_HF_ELLIPSIS
)
1204 * saved the raw bits if asked for it, useful for signature
1208 heim_octet_string
*save
= data
;
1210 save
->data
= malloc(oldlen
);
1211 if (save
->data
== NULL
)
1214 save
->length
= oldlen
;
1215 memcpy(save
->data
, startp
, oldlen
);
1222 * This should be called with a `A1_TAG_T(ASN1_C_UNIV, PRIM, UT_Integer)'
1223 * template as the `ttypeid'.
1226 typeid_int_copy(void *intp
,
1228 const struct asn1_template
*ttypeid
)
1230 const struct asn1_template
*tint
= ttypeid
->ptr
;
1232 if ((tint
[1].tt
& A1_OP_MASK
) != A1_OP_PARSE
)
1234 if (A1_PARSE_TYPE(tint
[1].tt
) != A1T_INTEGER
)
1236 switch (tint
[0].offset
) {
1237 case 8: *((int64_t *)intp
) = i
; return 0;
1238 case 4: *((int32_t *)intp
) = i
; return 0;
1239 default: memset(intp
, 0, tint
[0].offset
); return 0;
1243 /* See commentary in _asn1_decode_open_type() */
1245 _asn1_encode_open_type(const struct asn1_template
*t
,
1246 const void *data
, /* NOTE: Not really const */
1247 const struct asn1_template
*ttypeid
,
1248 const struct asn1_template
*topentype
)
1250 const struct asn1_template
*ttypeid_univ
= ttypeid
;
1251 const struct asn1_template
*tactual_type
;
1252 const struct asn1_template
*tos
= t
->ptr
;
1254 unsigned int *lenp
= NULL
;
1255 unsigned int len
= 1;
1256 int element
= *(const int *)DPOC(data
, t
->offset
);
1257 int typeid_is_oid
= 0;
1258 int typeid_is_int
= 0;
1262 if (element
== 0 || element
>= A1_HEADER_LEN(tos
) + 1)
1265 if (t
->tt
& A1_OS_OT_IS_ARRAY
) {
1266 /* The actual `len' is from the decoded open type field */
1267 len
= *(const unsigned int *)DPOC(data
, t
->offset
+ sizeof(element
));
1270 return 0; /* The app may be encoding the open type by itself */
1273 /* Work out the type ID field's type */
1274 while (((ttypeid_univ
->tt
& A1_OP_MASK
) == A1_OP_TAG
&&
1275 A1_TAG_CLASS(ttypeid_univ
->tt
) == ASN1_C_CONTEXT
) ||
1276 ((ttypeid_univ
->tt
& A1_OP_MASK
) == A1_OP_TYPE
)) {
1277 ttypeid_univ
= ttypeid_univ
->ptr
;
1280 switch (ttypeid_univ
->tt
& A1_OP_MASK
) {
1282 if (A1_TAG_CLASS(ttypeid_univ
->tt
) != ASN1_C_UNIV
) {
1286 switch (A1_TAG_TAG(ttypeid_univ
->tt
)) {
1291 const struct asn1_template
*tint
= ttypeid_univ
->ptr
;
1294 if ((tint
->tt
& A1_OP_MASK
) != A1_OP_PARSE
||
1295 A1_PARSE_TYPE(tint
->tt
) != A1T_INTEGER
) {
1302 default: enotsup
= 1; break;
1305 default: enotsup
= 1; break;
1309 * The app may not be aware of our automatic open type handling, so if the
1310 * open type already appears to have been encoded, then ignore the decoded
1313 if (!(t
->tt
& A1_OS_OT_IS_ARRAY
)) {
1314 struct heim_base_data
*os
= DPO(data
, topentype
->offset
);
1316 if (os
->length
&& os
->data
)
1319 struct heim_base_data
**os
= DPO(data
, topentype
->offset
+ sizeof(len
));
1321 while (sizeof(void *) != sizeof(unsigned int) &&
1322 ((uintptr_t)os
) % sizeof(void *) != 0)
1323 os
= (void *)(((char *)os
) + sizeof(unsigned int));
1325 lenp
= DPO(data
, topentype
->offset
);
1326 if (*lenp
== len
&& os
[0]->length
&& os
[0]->data
)
1330 if (typeid_is_int
) {
1332 * Copy the int from the type ID object field to the type ID struct
1335 ret
= typeid_int_copy(DPO(data
, ttypeid
->offset
),
1336 (intptr_t)tos
[3 + (element
-1)*3].ptr
, ttypeid_univ
);
1337 } else if (typeid_is_oid
) {
1339 * Copy the OID from the type ID object field to the type ID struct
1342 ret
= der_copy_oid(tos
[3 + (element
-1)*3].ptr
, DPO(data
, ttypeid
->offset
));
1347 * If the app did not already encode the open type, we can't help it if we
1348 * don't know what it is.
1353 tactual_type
= &tos
[(element
-1)*3 + 4];
1355 if (!(t
->tt
& A1_OS_OT_IS_ARRAY
)) {
1356 struct heim_base_data
*os
= DPO(data
, topentype
->offset
);
1357 const void * const *d
= DPOC(data
, t
->offset
+ sizeof(element
));
1359 while (sizeof(void *) != sizeof(element
) &&
1360 ((uintptr_t)d
) % sizeof(void *) != 0) {
1361 d
= (void *)(((char *)d
) + sizeof(element
));
1364 os
->length
= _asn1_length(tactual_type
->ptr
, *d
);
1365 if ((os
->data
= malloc(os
->length
)) == NULL
)
1367 ret
= _asn1_encode(tactual_type
->ptr
, (os
->length
- 1) + (unsigned char *)os
->data
, os
->length
, *d
, &sz
);
1369 struct heim_base_data
*os
;
1370 const void * const *val
=
1371 DPOC(data
, t
->offset
+ sizeof(element
) + sizeof(*lenp
));
1373 if ((os
= calloc(len
, sizeof(*os
))) == NULL
)
1377 for (i
= 0; ret
== 0 && i
< len
; i
++) {
1378 os
[i
].length
= _asn1_length(tactual_type
->ptr
, val
[i
]);
1379 if ((os
[i
].data
= malloc(os
[i
].length
)) == NULL
)
1382 ret
= _asn1_encode(tactual_type
->ptr
, (os
[i
].length
- 1) + (unsigned char *)os
[i
].data
, os
[i
].length
,
1386 for (i
= 0; i
< (*lenp
); i
++)
1392 *(struct heim_base_data
**)DPO(data
, topentype
->offset
+ sizeof(len
)) = os
;
1398 _asn1_encode(const struct asn1_template
*t
, unsigned char *p
, size_t len
, const void *data
, size_t *size
)
1400 const struct asn1_template
*tbase
= t
;
1401 size_t elements
= A1_HEADER_LEN(t
);
1403 size_t oldlen
= len
;
1405 t
+= A1_HEADER_LEN(t
);
1408 switch (t
->tt
& A1_OP_MASK
) {
1409 case A1_OP_OPENTYPE_OBJSET
: {
1410 size_t opentypeid
= t
->tt
& ((1<<10)-1);
1411 size_t opentype
= (t
->tt
>> 10) & ((1<<10)-1);
1412 ret
= _asn1_encode_open_type(t
, data
,
1413 template4member(tbase
, opentypeid
),
1414 template4member(tbase
, opentype
));
1419 case A1_OP_NAME
: break;
1420 case A1_OP_DEFVAL
: break;
1421 case A1_OP_TYPE_DECORATE
: break;
1423 case A1_OP_TYPE_EXTERN
: {
1425 const void *el
= DPOC(data
, t
->offset
);
1427 if (t
->tt
& A1_FLAG_OPTIONAL
) {
1428 void **pel
= (void **)el
;
1432 } else if ((t
->tt
& A1_FLAG_DEFAULT
) && elements
> 1) {
1433 const struct asn1_template
*tdefval
= t
- 1;
1434 /* Compare tdefval to whatever's at `el' */
1435 if (tdefval
->tt
& A1_DV_BOOLEAN
) {
1436 const int *i
= (void *)(char *)el
;
1438 if ((*i
&& tdefval
->ptr
) || (!*i
&& !tdefval
->ptr
))
1440 } else if (tdefval
->tt
& A1_DV_INTEGER64
) {
1441 const int64_t *i
= (void *)(char *)el
;
1443 if (*i
== (int64_t)(intptr_t)tdefval
->ptr
)
1445 } else if (tdefval
->tt
& A1_DV_INTEGER32
) {
1446 const int32_t *i
= (void *)(char *)el
;
1448 if ((int64_t)(intptr_t)tdefval
->ptr
<= INT_MAX
&&
1449 (int64_t)(intptr_t)tdefval
->ptr
>= INT_MIN
&&
1450 *i
== (int32_t)(intptr_t)tdefval
->ptr
)
1452 } else if (tdefval
->tt
& A1_DV_INTEGER
) {
1453 const struct heim_integer
*i
= (void *)(char *)el
;
1455 if (der_heim_integer_cmp(i
, tdefval
->ptr
) == 0)
1457 } else if (tdefval
->tt
& A1_DV_UTF8STRING
) {
1458 const char * const *s
= el
;
1460 if (*s
&& strcmp(*s
, tdefval
->ptr
) == 0)
1467 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
1468 ret
= _asn1_encode(t
->ptr
, p
, len
, el
, &newsize
);
1470 const struct asn1_type_func
*f
= t
->ptr
;
1471 ret
= (f
->encode
)(p
, len
, el
, &newsize
);
1476 p
-= newsize
; len
-= newsize
;
1481 const void *olddata
= data
;
1482 size_t l
, datalen
= 0;
1483 int replace_tag
= 0;
1486 * XXX If this type (chasing t->ptr through IMPLICIT tags, if this
1487 * one is too) till we find a non-TTag) is a [UNIVERSAL SET] type,
1488 * then we have to sort [a copy of] its template by tag, then
1489 * encode the SET using that sorted template. These SETs will
1490 * generally be small, so when they are we might want to allocate
1491 * the copy on the stack and insertion sort it. We'll need a
1492 * utility function to do all of this.
1495 data
= DPOC(data
, t
->offset
);
1497 if (t
->tt
& A1_FLAG_OPTIONAL
) {
1498 void **el
= (void **)data
;
1504 } else if ((t
->tt
& A1_FLAG_DEFAULT
) && elements
> 1) {
1505 const struct asn1_template
*tdefval
= t
- 1;
1508 /* Compare tdefval to whatever's at `data' */
1509 if (tdefval
->tt
& A1_DV_BOOLEAN
) {
1510 const int *i
= (void *)(char *)data
;
1512 if ((*i
&& tdefval
->ptr
) || (!*i
&& !tdefval
->ptr
))
1514 } else if (tdefval
->tt
& A1_DV_INTEGER64
) {
1515 const int64_t *i
= (void *)(char *)data
;
1517 if (*i
== (int64_t)(intptr_t)tdefval
->ptr
)
1519 } else if (tdefval
->tt
& A1_DV_INTEGER32
) {
1520 const int32_t *i
= (void *)(char *)data
;
1522 if ((int64_t)(intptr_t)tdefval
->ptr
<= INT_MAX
&&
1523 (int64_t)(intptr_t)tdefval
->ptr
>= INT_MIN
&&
1524 *i
== (int32_t)(intptr_t)tdefval
->ptr
)
1526 } else if (tdefval
->tt
& A1_DV_INTEGER
) {
1527 const struct heim_integer
*i
= (void *)(char *)data
;
1529 if (der_heim_integer_cmp(i
, tdefval
->ptr
) == 0)
1531 } else if (tdefval
->tt
& A1_DV_UTF8STRING
) {
1532 const char * const *s
= data
;
1534 if (*s
&& strcmp(*s
, tdefval
->ptr
) == 0)
1545 replace_tag
= (t
->tt
& A1_FLAG_IMPLICIT
) && is_tagged(t
->ptr
);
1547 /* IMPLICIT tags need special handling (see gen_encode.c) */
1549 unsigned char *pfree
, *psave
= p
;
1550 Der_class found_class
;
1551 Der_type found_type
= 0;
1552 unsigned int found_tag
;
1553 size_t lensave
= len
;
1554 size_t oldtaglen
= 0;
1555 size_t taglen
= der_length_tag(A1_TAG_TAG(t
->tt
));;
1557 /* Allocate a buffer at least as big as we need */
1558 len
= _asn1_length(t
->ptr
, data
) + taglen
;
1559 if ((p
= pfree
= malloc(len
)) == NULL
) {
1563 * Encode into it (with the wrong tag, which we'll replace
1567 ret
= _asn1_encode(t
->ptr
, p
, len
, data
, &datalen
);
1570 /* Get the old tag and, critically, its length */
1571 len
-= datalen
; p
-= datalen
;
1572 ret
= der_get_tag(p
+ 1, datalen
, &found_class
, &found_type
,
1573 &found_tag
, &oldtaglen
);
1576 /* Drop the old tag */
1577 len
+= oldtaglen
; p
+= oldtaglen
;
1578 /* Put the new tag */
1579 ret
= der_put_tag(p
, len
,
1580 A1_TAG_CLASS(t
->tt
),
1582 A1_TAG_TAG(t
->tt
), &l
);
1585 /* Copy the encoding where it belongs */
1587 psave
-= (datalen
+ l
- oldtaglen
);
1588 lensave
-= (datalen
+ l
- oldtaglen
);
1589 memcpy(psave
+ 1, p
+ 1, datalen
+ l
- oldtaglen
);
1596 ret
= _asn1_encode(t
->ptr
, p
, len
, data
, &datalen
);
1600 len
-= datalen
; p
-= datalen
;
1602 ret
= der_put_length_and_tag(p
, len
, datalen
,
1603 A1_TAG_CLASS(t
->tt
),
1605 A1_TAG_TAG(t
->tt
), &l
);
1618 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
1620 const void *el
= DPOC(data
, t
->offset
);
1622 if (type
>= sizeof(asn1_template_prim
)/sizeof(asn1_template_prim
[0])) {
1624 return ASN1_PARSE_ERROR
;
1627 ret
= (asn1_template_prim
[type
].encode
)(p
, len
, el
, &newsize
);
1630 p
-= newsize
; len
-= newsize
;
1635 const struct template_of
*el
= DPOC(data
, t
->offset
);
1636 size_t ellen
= _asn1_sizeofType(t
->ptr
);
1637 heim_octet_string
*val
;
1638 unsigned char *elptr
= el
->val
;
1644 if (el
->len
> UINT_MAX
/sizeof(val
[0]))
1647 val
= calloc(el
->len
, sizeof(val
[0]));
1651 for(totallen
= 0, i
= 0; i
< el
->len
; i
++) {
1652 unsigned char *next
;
1655 val
[i
].length
= _asn1_length(t
->ptr
, elptr
);
1656 if (val
[i
].length
) {
1657 val
[i
].data
= malloc(val
[i
].length
);
1658 if (val
[i
].data
== NULL
) {
1664 ret
= _asn1_encode(t
->ptr
, DPO(val
[i
].data
, val
[i
].length
- 1),
1665 val
[i
].length
, elptr
, &l
);
1669 next
= elptr
+ ellen
;
1671 ret
= ASN1_OVERFLOW
;
1675 totallen
+= val
[i
].length
;
1677 if (ret
== 0 && totallen
> len
)
1678 ret
= ASN1_OVERFLOW
;
1680 for (i
= 0; i
< el
->len
; i
++)
1688 qsort(val
, el
->len
, sizeof(val
[0]), _heim_der_set_sort
);
1693 memcpy(p
+ 1, val
[i
].data
, val
[i
].length
);
1702 struct template_of
*el
= DPO(data
, t
->offset
);
1703 size_t ellen
= _asn1_sizeofType(t
->ptr
);
1706 unsigned char *elptr
= el
->val
;
1711 elptr
+= ellen
* (el
->len
- 1);
1713 for (i
= 0; i
< el
->len
; i
++) {
1714 ret
= _asn1_encode(t
->ptr
, p
, len
,
1719 p
-= newsize
; len
-= newsize
;
1725 case A1_OP_BMEMBER
: {
1726 const struct asn1_template
*bmember
= t
->ptr
;
1727 size_t bsize
= bmember
->offset
;
1728 size_t belements
= A1_HEADER_LEN(bmember
);
1730 unsigned char c
= 0;
1731 unsigned int bitset
= 0;
1732 int rfc1510
= (bmember
->tt
& A1_HBF_RFC1510
);
1734 bmember
+= belements
;
1739 pos
= bmember
->offset
;
1741 while (belements
&& len
) {
1742 while (bmember
->offset
/ 8 < pos
/ 8) {
1743 if (rfc1510
|| bitset
|| c
) {
1745 return ASN1_OVERFLOW
;
1751 _asn1_bmember_put_bit(&c
, data
, bmember
->offset
, bsize
, &bitset
);
1752 belements
--; bmember
--;
1754 if (rfc1510
|| bitset
) {
1756 return ASN1_OVERFLOW
;
1761 return ASN1_OVERFLOW
;
1762 if (rfc1510
|| bitset
== 0)
1771 case A1_OP_CHOICE
: {
1772 const struct asn1_template
*choice
= t
->ptr
;
1773 const unsigned int *element
= DPOC(data
, choice
->offset
);
1777 if (*element
> A1_HEADER_LEN(choice
)) {
1778 printf("element: %d\n", *element
);
1779 return ASN1_PARSE_ERROR
;
1782 if (*element
== 0) {
1783 ret
+= der_put_octet_string(p
, len
,
1784 DPOC(data
, choice
->tt
), &datalen
);
1787 el
= DPOC(data
, choice
->offset
);
1788 ret
= _asn1_encode(choice
->ptr
, p
, len
, el
, &datalen
);
1792 len
-= datalen
; p
-= datalen
;
1803 *size
= oldlen
- len
;
1809 _asn1_length_open_type_helper(const struct asn1_template
*t
,
1812 const struct asn1_template
*tinner
= t
->ptr
;
1814 switch (t
->tt
& A1_OP_MASK
) {
1816 /* XXX Not tail-recursive :( */
1817 sz
= _asn1_length_open_type_helper(tinner
, sz
);
1818 sz
+= der_length_len(sz
);
1819 sz
+= der_length_tag(A1_TAG_TAG(t
->tt
));
1827 _asn1_length_open_type_id(const struct asn1_template
*t
,
1830 struct asn1_template pretend
[2] = {
1831 { 0, 0, ((void*)1) },
1834 while ((t
->tt
& A1_OP_MASK
) == A1_OP_TAG
)
1836 pretend
[0].offset
= t
->offset
;
1837 return _asn1_length(pretend
, data
);
1840 /* See commentary in _asn1_encode_open_type() */
1842 _asn1_length_open_type(const struct asn1_template
*tbase
,
1843 const struct asn1_template
*t
,
1845 const struct asn1_template
*ttypeid
,
1846 const struct asn1_template
*topentype
)
1848 const struct asn1_template
*ttypeid_univ
= ttypeid
;
1849 const struct asn1_template
*tactual_type
;
1850 const struct asn1_template
*tos
= t
->ptr
;
1851 const unsigned int *lenp
= NULL
;
1852 unsigned int len
= 1;
1855 int element
= *(const int *)DPOC(data
, t
->offset
);
1856 int typeid_is_oid
= 0;
1857 int typeid_is_int
= 0;
1859 /* If nothing to encode, we add nothing to the length */
1860 if (element
== 0 || element
>= A1_HEADER_LEN(tos
) + 1)
1862 if (t
->tt
& A1_OS_OT_IS_ARRAY
) {
1863 len
= *(const unsigned int *)DPOC(data
, t
->offset
+ sizeof(element
));
1868 /* Work out the type ID field's type */
1869 while (((ttypeid_univ
->tt
& A1_OP_MASK
) == A1_OP_TAG
&&
1870 A1_TAG_CLASS(ttypeid_univ
->tt
) == ASN1_C_CONTEXT
) ||
1871 ((ttypeid_univ
->tt
& A1_OP_MASK
) == A1_OP_TYPE
)) {
1872 ttypeid_univ
= ttypeid_univ
->ptr
;
1875 switch (ttypeid_univ
->tt
& A1_OP_MASK
) {
1877 if (A1_TAG_CLASS(ttypeid_univ
->tt
) != ASN1_C_UNIV
)
1879 switch (A1_TAG_TAG(ttypeid_univ
->tt
)) {
1884 const struct asn1_template
*tint
= ttypeid_univ
->ptr
;
1887 if ((tint
->tt
& A1_OP_MASK
) != A1_OP_PARSE
||
1888 A1_PARSE_TYPE(tint
->tt
) != A1T_INTEGER
)
1898 if (!typeid_is_int
&& !typeid_is_oid
)
1900 if (!(t
->tt
& A1_OS_OT_IS_ARRAY
)) {
1901 struct heim_base_data
*os
= DPO(data
, topentype
->offset
);
1903 if (os
->length
&& os
->data
)
1906 struct heim_base_data
**os
= DPO(data
, topentype
->offset
+ sizeof(len
));
1908 while (sizeof(void *) != sizeof(unsigned int) &&
1909 ((uintptr_t)os
) % sizeof(void *) != 0)
1910 os
= (void *)(((char *)os
) + sizeof(unsigned int));
1912 lenp
= DPOC(data
, topentype
->offset
);
1913 if (*lenp
== len
&& os
[0]->length
&& os
[0]->data
)
1917 /* Compute the size of the type ID field */
1918 if (typeid_is_int
) {
1922 switch (ttypeid_univ
->offset
) {
1924 i8
= (intptr_t)t
->ptr
;
1925 sz
= _asn1_length_open_type_id(ttypeid
, &i8
);
1927 sz
-= _asn1_length_open_type_id(ttypeid
, &i8
);
1930 i4
= (intptr_t)t
->ptr
;
1931 sz
= _asn1_length_open_type_id(ttypeid
, &i4
);
1933 sz
-= _asn1_length_open_type_id(ttypeid
, &i8
);
1938 } else if (typeid_is_oid
) {
1939 heim_oid no_oid
= { 0, 0 };
1941 sz
= _asn1_length_open_type_id(ttypeid
, tos
[3 + (element
- 1)*3].ptr
);
1942 sz
-= _asn1_length_open_type_id(ttypeid
, &no_oid
);
1945 tactual_type
= &tos
[(element
-1)*3 + 4];
1947 /* Compute the size of the encoded value(s) */
1948 if (!(t
->tt
& A1_OS_OT_IS_ARRAY
)) {
1949 const void * const *d
= DPOC(data
, t
->offset
+ sizeof(element
));
1951 while (sizeof(void *) != sizeof(element
) &&
1952 ((uintptr_t)d
) % sizeof(void *) != 0)
1953 d
= (void *)(((char *)d
) + sizeof(element
));
1955 sz
+= _asn1_length(tactual_type
->ptr
, *d
);
1958 const void * const * val
=
1959 DPOC(data
, t
->offset
+ sizeof(element
) + sizeof(*lenp
));
1961 /* Compute the size of the encoded SET OF / SEQUENCE OF body */
1962 for (i
= 0, bodysz
= 0; i
< len
; i
++) {
1964 bodysz
+= _asn1_length(tactual_type
->ptr
, val
[i
]);
1968 * We now know the size of the body of the SET OF or SEQUENCE OF. Now
1969 * we just need to count the length of all the TLs on the outside.
1971 sz
+= _asn1_length_open_type_helper(topentype
, bodysz
);
1977 _asn1_length(const struct asn1_template
*t
, const void *data
)
1979 const struct asn1_template
*tbase
= t
;
1980 size_t elements
= A1_HEADER_LEN(t
);
1983 t
+= A1_HEADER_LEN(t
);
1986 switch (t
->tt
& A1_OP_MASK
) {
1987 case A1_OP_OPENTYPE_OBJSET
: {
1988 size_t opentypeid
= t
->tt
& ((1<<10)-1);
1989 size_t opentype
= (t
->tt
>> 10) & ((1<<10)-1);
1990 ret
+= _asn1_length_open_type(tbase
, t
, data
,
1991 template4member(tbase
, opentypeid
),
1992 template4member(tbase
, opentype
));
1995 case A1_OP_NAME
: break;
1996 case A1_OP_DEFVAL
: break;
1997 case A1_OP_TYPE_DECORATE
: break;
1999 case A1_OP_TYPE_EXTERN
: {
2000 const void *el
= DPOC(data
, t
->offset
);
2002 if (t
->tt
& A1_FLAG_OPTIONAL
) {
2003 void **pel
= (void **)el
;
2007 } else if ((t
->tt
& A1_FLAG_DEFAULT
) && elements
> 1) {
2008 const struct asn1_template
*tdefval
= t
- 1;
2010 /* Compare tdefval to whatever's at `el' */
2011 if (tdefval
->tt
& A1_DV_BOOLEAN
) {
2012 const int *i
= (void *)(char *)el
;
2014 if ((*i
&& tdefval
->ptr
) || (!*i
&& !tdefval
->ptr
))
2016 } else if (tdefval
->tt
& A1_DV_INTEGER64
) {
2017 const int64_t *i
= (void *)(char *)el
;
2019 if (*i
== (int64_t)(intptr_t)tdefval
->ptr
)
2021 } else if (tdefval
->tt
& A1_DV_INTEGER32
) {
2022 const int32_t *i
= (void *)(char *)el
;
2024 if ((int64_t)(intptr_t)tdefval
->ptr
<= INT_MAX
&&
2025 (int64_t)(intptr_t)tdefval
->ptr
>= INT_MIN
&&
2026 *i
== (int32_t)(intptr_t)tdefval
->ptr
)
2028 } else if (tdefval
->tt
& A1_DV_INTEGER
) {
2029 const struct heim_integer
*i
= (void *)(char *)el
;
2031 if (der_heim_integer_cmp(i
, tdefval
->ptr
) == 0)
2033 } else if (tdefval
->tt
& A1_DV_UTF8STRING
) {
2034 const char * const *s
= el
;
2036 if (*s
&& strcmp(*s
, tdefval
->ptr
) == 0)
2043 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
2044 ret
+= _asn1_length(t
->ptr
, el
);
2046 const struct asn1_type_func
*f
= t
->ptr
;
2047 ret
+= (f
->length
)(el
);
2053 const void *olddata
= data
;
2054 size_t oldtaglen
= 0;
2056 data
= DPO(data
, t
->offset
);
2058 if (t
->tt
& A1_FLAG_OPTIONAL
) {
2059 void **el
= (void **)data
;
2065 } else if ((t
->tt
& A1_FLAG_DEFAULT
) && elements
> 1) {
2066 const struct asn1_template
*tdefval
= t
- 1;
2069 /* Compare tdefval to whatever's at `data' */
2070 if (tdefval
->tt
& A1_DV_BOOLEAN
) {
2071 const int *i
= (void *)(char *)data
;
2073 if ((*i
&& tdefval
->ptr
) || (!*i
&& !tdefval
->ptr
))
2075 } else if (tdefval
->tt
& A1_DV_INTEGER64
) {
2076 const int64_t *i
= (void *)(char *)data
;
2078 if (*i
== (int64_t)(intptr_t)tdefval
->ptr
)
2080 } else if (tdefval
->tt
& A1_DV_INTEGER32
) {
2081 const int32_t *i
= (void *)(char *)data
;
2083 if ((int64_t)(intptr_t)tdefval
->ptr
<= INT_MAX
&&
2084 (int64_t)(intptr_t)tdefval
->ptr
>= INT_MIN
&&
2085 *i
== (int32_t)(intptr_t)tdefval
->ptr
)
2087 } else if (tdefval
->tt
& A1_DV_INTEGER
) {
2088 const struct heim_integer
*i
= (void *)(char *)data
;
2090 if (der_heim_integer_cmp(i
, tdefval
->ptr
) == 0)
2092 } else if (tdefval
->tt
& A1_DV_UTF8STRING
) {
2093 const char * const *s
= data
;
2095 if (*s
&& strcmp(*s
, tdefval
->ptr
) == 0)
2106 if (t
->tt
& A1_FLAG_IMPLICIT
)
2107 oldtaglen
= inner_type_taglen(t
->ptr
);
2109 datalen
= _asn1_length(t
->ptr
, data
);
2111 ret
+= der_length_tag(A1_TAG_TAG(t
->tt
));
2112 ret
+= oldtaglen
? -oldtaglen
: der_length_len(datalen
);
2117 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
2118 const void *el
= DPOC(data
, t
->offset
);
2120 if (type
>= sizeof(asn1_template_prim
)/sizeof(asn1_template_prim
[0])) {
2124 ret
+= (asn1_template_prim
[type
].length
)(el
);
2129 const struct template_of
*el
= DPOC(data
, t
->offset
);
2130 size_t ellen
= _asn1_sizeofType(t
->ptr
);
2131 const unsigned char *element
= el
->val
;
2134 for (i
= 0; i
< el
->len
; i
++) {
2135 ret
+= _asn1_length(t
->ptr
, element
);
2141 case A1_OP_BMEMBER
: {
2142 const struct asn1_template
*bmember
= t
->ptr
;
2143 size_t size
= bmember
->offset
;
2144 size_t belements
= A1_HEADER_LEN(bmember
);
2145 int rfc1510
= (bmember
->tt
& A1_HBF_RFC1510
);
2153 bmember
+= belements
;
2156 if (_asn1_bmember_isset_bit(data
, bmember
->offset
, size
)) {
2157 ret
+= (bmember
->offset
/ 8) + 1;
2160 belements
--; bmember
--;
2165 case A1_OP_CHOICE
: {
2166 const struct asn1_template
*choice
= t
->ptr
;
2167 const unsigned int *element
= DPOC(data
, choice
->offset
);
2169 if (*element
> A1_HEADER_LEN(choice
))
2172 if (*element
== 0) {
2173 ret
+= der_length_octet_string(DPOC(data
, choice
->tt
));
2176 ret
+= _asn1_length(choice
->ptr
, DPOC(data
, choice
->offset
));
2190 /* See commentary in _asn1_decode_open_type() */
2192 _asn1_free_open_type(const struct asn1_template
*t
, /* object set template */
2195 const struct asn1_template
*tactual_type
;
2196 const struct asn1_template
*tos
= t
->ptr
;
2197 unsigned int *lenp
= NULL
; /* Pointer to array length field */
2198 unsigned int len
= 1; /* Array length */
2202 int *elementp
= DPO(data
, t
->offset
); /* Choice enum pointer */
2204 /* XXX We assume sizeof(enum) == sizeof(int) */
2205 if (!*elementp
|| *elementp
>= A1_HEADER_LEN(tos
) + 1)
2206 return; /* Unknown choice -> it's not decoded, nothing to free here */
2207 tactual_type
= tos
[3*(*elementp
- 1) + 4].ptr
;
2209 if (!(t
->tt
& A1_OS_OT_IS_ARRAY
)) {
2210 dp
= DPO(data
, t
->offset
+ sizeof(*elementp
));
2211 while (sizeof(void *) != sizeof(*elementp
) &&
2212 ((uintptr_t)dp
) % sizeof(void *) != 0)
2213 dp
= (void *)(((char *)dp
) + sizeof(*elementp
));
2215 _asn1_free(tactual_type
, *dp
);
2222 lenp
= DPO(data
, t
->offset
+ sizeof(*elementp
));
2224 dp
= DPO(data
, t
->offset
+ sizeof(*elementp
) + sizeof(*lenp
));
2225 while (sizeof(void *) != sizeof(*elementp
) &&
2226 ((uintptr_t)dp
) % sizeof(void *) != 0)
2227 dp
= (void *)(((char *)dp
) + sizeof(*elementp
));
2230 for (i
= 0; i
< len
; i
++) {
2232 _asn1_free(tactual_type
, val
[i
]);
2242 _asn1_free(const struct asn1_template
*t
, void *data
)
2244 size_t elements
= A1_HEADER_LEN(t
);
2246 if (t
->tt
& A1_HF_PRESERVE
)
2247 der_free_octet_string(data
);
2252 switch (t
->tt
& A1_OP_MASK
) {
2253 case A1_OP_OPENTYPE_OBJSET
: {
2254 _asn1_free_open_type(t
, data
);
2257 case A1_OP_NAME
: break;
2258 case A1_OP_DEFVAL
: break;
2259 case A1_OP_TYPE_DECORATE
:
2261 case A1_OP_TYPE_EXTERN
: {
2262 void *el
= DPO(data
, t
->offset
);
2263 void **pel
= (void **)el
;
2265 if (t
->tt
& A1_FLAG_OPTIONAL
) {
2271 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
|| (t
->tt
& A1_OP_MASK
) == A1_OP_TYPE_DECORATE
) {
2272 _asn1_free(t
->ptr
, el
);
2274 const struct asn1_type_func
*f
= t
->ptr
;
2277 if (t
->tt
& A1_FLAG_OPTIONAL
) {
2285 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
2286 void *el
= DPO(data
, t
->offset
);
2288 if (type
>= sizeof(asn1_template_prim
)/sizeof(asn1_template_prim
[0])) {
2292 (asn1_template_prim
[type
].release
)(el
);
2296 void *el
= DPO(data
, t
->offset
);
2298 if (t
->tt
& A1_FLAG_OPTIONAL
) {
2299 void **pel
= (void **)el
;
2303 _asn1_free(t
->ptr
, *pel
);
2307 _asn1_free(t
->ptr
, el
);
2314 struct template_of
*el
= DPO(data
, t
->offset
);
2315 size_t ellen
= _asn1_sizeofType(t
->ptr
);
2316 unsigned char *element
= el
->val
;
2319 for (i
= 0; i
< el
->len
; i
++) {
2320 _asn1_free(t
->ptr
, element
);
2331 case A1_OP_CHOICE
: {
2332 const struct asn1_template
*choice
= t
->ptr
;
2333 const unsigned int *element
= DPOC(data
, choice
->offset
);
2335 if (*element
> A1_HEADER_LEN(choice
))
2338 if (*element
== 0) {
2339 der_free_octet_string(DPO(data
, choice
->tt
));
2342 _asn1_free(choice
->ptr
, DPO(data
, choice
->offset
));
2356 getindent(int flags
, unsigned int i
)
2360 if (!(flags
& ASN1_PRINT_INDENT
) || i
== 0)
2364 if ((s
= malloc(i
* 2 + 2)) == NULL
)
2367 s
[i
* 2 + 1] = '\0';
2368 memset(s
+ 1, ' ', i
* 2);
2372 static struct rk_strpool
*_asn1_print(const struct asn1_template
*,
2373 struct rk_strpool
*,
2377 const heim_octet_string
*);
2379 /* See commentary in _asn1_decode_open_type() */
2380 static struct rk_strpool
*
2381 _asn1_print_open_type(const struct asn1_template
*t
, /* object set template */
2382 struct rk_strpool
*r
,
2384 unsigned int indent
,
2386 const char *opentype_name
)
2388 const struct asn1_template
*tactual_type
;
2389 const struct asn1_template
*tos
= t
->ptr
;
2390 const unsigned int *lenp
= NULL
; /* Pointer to array length field */
2391 unsigned int len
= 1; /* Array length */
2393 const void * const *dp
;
2394 const void * const *val
;
2395 const int *elementp
= DPOC(data
, t
->offset
); /* Choice enum pointer */
2396 char *indents
= getindent(flags
, indent
);
2398 /* XXX We assume sizeof(enum) == sizeof(int) */
2399 if (!*elementp
|| *elementp
>= A1_HEADER_LEN(tos
) + 1) {
2400 r
= rk_strpoolprintf(r
, ",%s\"_%s_choice\":\"_ERROR_DECODING_\"",
2401 indents
? indents
: "", opentype_name
);
2405 tactual_type
= tos
[3*(*elementp
- 1) + 4].ptr
;
2407 r
= rk_strpoolprintf(r
, ",%s\"_%s_choice\":\"%s\"",
2408 indents
? indents
: "", opentype_name
,
2409 (const char *)tos
[3*(*elementp
- 1) + 2].ptr
);
2415 if (!(t
->tt
& A1_OS_OT_IS_ARRAY
)) {
2416 dp
= DPOC(data
, t
->offset
+ sizeof(*elementp
));
2417 while (sizeof(void *) != sizeof(*elementp
) &&
2418 ((uintptr_t)dp
) % sizeof(void *) != 0)
2419 dp
= (void *)(((char *)dp
) + sizeof(*elementp
));
2421 struct rk_strpool
*r2
= NULL
;
2424 r2
= _asn1_print(tactual_type
, r2
, flags
, indent
+ 1, *dp
, NULL
);
2426 r
= rk_strpoolprintf(r
, ",%s\"_%s\":\"_ERROR_FORMATTING_\"",
2427 indents
? indents
: "", opentype_name
);
2431 s
= rk_strpoolcollect(r2
);
2433 r
= rk_strpoolprintf(r
, ",%s\"_%s\":%s",
2434 indents
? indents
: "", opentype_name
, s
);
2441 lenp
= DPOC(data
, t
->offset
+ sizeof(*elementp
));
2443 dp
= DPOC(data
, t
->offset
+ sizeof(*elementp
) + sizeof(*lenp
));
2444 while (sizeof(void *) != sizeof(*elementp
) &&
2445 ((uintptr_t)dp
) % sizeof(void *) != 0)
2446 dp
= (void *)(((char *)dp
) + sizeof(*elementp
));
2449 r
= rk_strpoolprintf(r
, ",%s\"_%s\":[", indents
? indents
: "",
2452 indents
= getindent(flags
, indent
+ 1);
2454 r
= rk_strpoolprintf(r
, "%s", indents
? indents
: "");
2455 for (i
= 0; r
&& i
< len
; i
++) {
2456 struct rk_strpool
*r2
= NULL
;
2460 r2
= _asn1_print(tactual_type
, r2
, flags
, indent
+ 2, val
[i
], NULL
);
2468 r
= rk_strpoolprintf(r
, ",%s", indents
? indents
: "");
2470 r
= rk_strpoolprintf(r
, "%s", (s
= rk_strpoolcollect(r2
)));
2474 return rk_strpoolprintf(r
, "]");
2477 static struct rk_strpool
*
2478 _asn1_print(const struct asn1_template
*t
,
2479 struct rk_strpool
*r
,
2481 unsigned int indent
,
2483 const heim_octet_string
*saved
)
2485 const struct asn1_template
*tbase
= t
;
2486 const struct asn1_template
*tnames
;
2487 size_t nelements
= A1_HEADER_LEN(t
);
2488 size_t elements
= nelements
;
2490 char *indents
= getindent(flags
, indent
);
2492 for (t
+= nelements
; t
> tbase
&& (t
->tt
& A1_OP_MASK
) == A1_OP_NAME
; t
--)
2495 tnames
= tbase
+ nelements
- nnames
+ 1;
2498 r
= rk_strpoolprintf(r
, "%s", "");
2501 r
= rk_strpoolprintf(r
, "%s{\"_type\":\"%s\"",
2502 indents
? indents
: "",
2503 (const char *)(tnames
++)->ptr
);
2505 char *s
= der_print_octet_string(data
, 0);
2512 r
= rk_strpoolprintf(r
, ",%s\"_save\":\"%s\"",
2513 indents
? indents
: "", s
);
2517 if (tbase
->tt
& A1_HF_PRESERVE
)
2521 while (r
&& elements
&& (t
->tt
& A1_OP_MASK
) != A1_OP_NAME
) {
2522 switch (t
->tt
& A1_OP_MASK
) {
2529 case A1_OP_OPENTYPE_OBJSET
: {
2530 size_t opentype
= (t
->tt
>> 10) & ((1<<10)-1);
2531 r
= _asn1_print_open_type(t
, r
, flags
, indent
+ 1, data
,
2532 tbase
[(nelements
- nnames
) + 2 + opentype
].ptr
);
2540 r
= rk_strpoolprintf(r
, ",%s\"%s\":",
2541 indents
? indents
: "",
2542 (const char *)(tnames
++)->ptr
);
2543 switch (t
->tt
& A1_OP_MASK
) {
2544 case A1_OP_OPENTYPE_OBJSET
:
2546 case A1_OP_NAME
: break;
2547 case A1_OP_DEFVAL
: break;
2548 case A1_OP_TYPE_DECORATE
: break; /* We could probably print this though */
2550 case A1_OP_TYPE_EXTERN
: {
2551 const void *el
= DPOC(data
, t
->offset
);
2553 if (t
->tt
& A1_FLAG_OPTIONAL
) {
2554 const void * const *pel
= (const void *const *)el
;
2556 r
= rk_strpoolprintf(r
, "null");
2562 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
2563 r
= _asn1_print(t
->ptr
, r
, flags
, indent
+ 1, el
, saved
);
2565 const struct asn1_type_func
*f
= t
->ptr
;
2568 s
= (f
->print
)(el
, 0);
2574 r
= rk_strpoolprintf(r
, "%s", s
);
2580 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
2581 const void *el
= DPOC(data
, t
->offset
);
2584 if (type
>= sizeof(asn1_template_prim
)/sizeof(asn1_template_prim
[0])) {
2589 if (type
== A1T_IMEMBER
&& t
->ptr
) {
2590 /* Enumeration. Use the symbolic name of this value */
2591 const struct asn1_template
*tenum
= t
->ptr
;
2593 size_t right
= A1_HEADER_LEN(tenum
);
2595 uint32_t v
= *(unsigned int *)el
;
2598 while (left
<= right
) {
2599 mid
= (left
+ right
) >> 1;
2601 if ((tenum
[mid
].tt
& A1_OP_MASK
) != A1_OP_NAME
)
2603 c
= v
- tenum
[mid
].offset
;
2616 r
= rk_strpoolprintf(r
, "\"%s\"", (const char *)tenum
[mid
].ptr
);
2620 s
= (asn1_template_prim
[type
].print
)(el
, flags
);
2628 case A1T_UNSIGNED64
:
2630 r
= rk_strpoolprintf(r
, "%s", s
);
2636 (void) rk_strasvis(&s2
, s
, VIS_CSTYLE
|VIS_TAB
|VIS_NL
, "\"");
2640 r
= rk_strpoolprintf(r
, "\"%s\"", s
);
2652 const void *el
= DPOC(data
, t
->offset
);
2654 if (t
->tt
& A1_FLAG_OPTIONAL
) {
2655 const void * const *pel
= (const void * const *)el
;
2657 r
= rk_strpoolprintf(r
, "null");
2663 r
= _asn1_print(t
->ptr
, r
, flags
, indent
+ 1, el
, saved
);
2668 const struct template_of
*el
= DPOC(data
, t
->offset
);
2669 size_t ellen
= _asn1_sizeofType(t
->ptr
);
2670 const unsigned char *element
= el
->val
;
2673 r
= rk_strpoolprintf(r
, "%s[", indents
? indents
: "");
2674 for (i
= 0; r
&& i
< el
->len
; i
++) {
2676 r
= rk_strpoolprintf(r
, ",%s", indents
? indents
: "");
2677 r
= _asn1_print(t
->ptr
, r
, flags
, indent
+ 1, element
, saved
);
2681 r
= rk_strpoolprintf(r
, "]");
2684 case A1_OP_BMEMBER
: {
2685 const struct asn1_template
*bmember
= t
->ptr
;
2686 size_t size
= bmember
->offset
;
2687 size_t belements
= A1_HEADER_LEN(bmember
);
2690 bmember
+= belements
;
2691 r
= rk_strpoolprintf(r
, "%s[", indents
? indents
: "");
2692 while (r
&& belements
) {
2693 if (r
&& _asn1_bmember_isset_bit(data
, bmember
->offset
, size
)) {
2695 r
= rk_strpoolprintf(r
, ",");
2697 r
= rk_strpoolprintf(r
, "%s\"%s\"", indents
? indents
: "",
2698 (const char *)bmember
->ptr
);
2700 belements
--; bmember
--;
2703 r
= rk_strpoolprintf(r
, "]");
2706 case A1_OP_CHOICE
: {
2707 const struct asn1_template
*choice
= t
->ptr
;
2708 const unsigned int *element
= DPOC(data
, choice
->offset
);
2709 unsigned int nchoices
= ((uintptr_t)choice
->ptr
) >> 1;
2711 if (*element
> A1_HEADER_LEN(choice
)) {
2712 r
= rk_strpoolprintf(r
, "null");
2713 } else if (*element
== 0) {
2714 r
= rk_strpoolprintf(r
, "null");
2717 r
= rk_strpoolprintf(r
, "%s{\"_choice\":\"%s\",%s\"value\":",
2718 indents
? indents
: "",
2719 (const char *)choice
[nchoices
].ptr
,
2720 indents
? indents
: "");
2722 r
= _asn1_print(choice
->ptr
, r
, flags
, indent
+ 1,
2723 DPOC(data
, choice
->offset
), NULL
);
2725 r
= rk_strpoolprintf(r
, "}");
2738 return rk_strpoolprintf(r
, "}");
2743 _asn1_print_top(const struct asn1_template
*t
,
2747 struct rk_strpool
*r
= _asn1_print(t
, NULL
, flags
, 0, data
, NULL
);
2751 return rk_strpoolcollect(r
);
2754 /* See commentary in _asn1_decode_open_type() */
2756 _asn1_copy_open_type(const struct asn1_template
*t
, /* object set template */
2760 const struct asn1_template
*tactual_type
;
2761 const struct asn1_template
*tos
= t
->ptr
;
2763 const void * const *dfromp
;
2764 const void * const *valfrom
;
2765 const unsigned int *lenfromp
;
2768 unsigned int *lentop
;
2770 const int *efromp
= DPO(from
, t
->offset
);
2771 int *etop
= DPO(to
, t
->offset
);
2774 /* XXX We assume sizeof(enum) == sizeof(int) */
2775 if (!*efromp
|| *efromp
>= A1_HEADER_LEN(tos
) + 1) {
2776 if ((t
->tt
& A1_OS_OT_IS_ARRAY
))
2777 memset(etop
, 0, sizeof(int) + sizeof(unsigned int) + sizeof(void *));
2779 memset(etop
, 0, sizeof(int) + sizeof(void *));
2780 return 0; /* Unknown choice -> not copied */
2782 tactual_type
= &tos
[3*(*efromp
- 1) + 4];
2784 if (!(t
->tt
& A1_OS_OT_IS_ARRAY
)) {
2785 dfromp
= DPO(from
, t
->offset
+ sizeof(*efromp
));
2786 while (sizeof(void *) != sizeof(*efromp
) &&
2787 ((uintptr_t)dfromp
) % sizeof(void *) != 0)
2788 dfromp
= (void *)(((char *)dfromp
) + sizeof(*efromp
));
2792 dtop
= DPO(to
, t
->offset
+ sizeof(*etop
));
2793 while (sizeof(void *) != sizeof(*etop
) &&
2794 ((uintptr_t)dtop
) % sizeof(void *) != 0)
2795 dtop
= (void *)(((char *)dtop
) + sizeof(*etop
));
2797 if ((*dtop
= calloc(1, tactual_type
->offset
)) == NULL
)
2800 ret
= _asn1_copy(tactual_type
->ptr
, *dfromp
, *dtop
);
2806 lenfromp
= DPO(from
, t
->offset
+ sizeof(*efromp
));
2807 dfromp
= DPO(from
, t
->offset
+ sizeof(*efromp
) + sizeof(*lenfromp
));
2809 lentop
= DPO(to
, t
->offset
+ sizeof(*etop
));
2810 dtop
= DPO(to
, t
->offset
+ sizeof(*etop
) + sizeof(*lentop
));
2817 if ((valto
= calloc(len
, sizeof(valto
[0]))) == NULL
)
2819 for (i
= 0, len
= *lenfromp
; ret
== 0 && i
< len
; (*lentop
)++, i
++) {
2820 if (valfrom
[i
] == NULL
) {
2824 if ((valto
[i
] = calloc(1, tactual_type
->offset
)) == NULL
)
2827 ret
= _asn1_copy(tactual_type
->ptr
, valfrom
[i
], valto
[i
]);
2830 for (i
= 0; ret
&& i
< len
; i
++) {
2832 _asn1_free(tactual_type
->ptr
, valto
[i
]);
2844 _asn1_copy(const struct asn1_template
*t
, const void *from
, void *to
)
2846 size_t elements
= A1_HEADER_LEN(t
);
2848 int preserve
= (t
->tt
& A1_HF_PRESERVE
);
2853 ret
= der_copy_octet_string(from
, to
);
2859 switch (t
->tt
& A1_OP_MASK
) {
2860 case A1_OP_OPENTYPE_OBJSET
: {
2861 _asn1_copy_open_type(t
, from
, to
);
2864 case A1_OP_NAME
: break;
2865 case A1_OP_DEFVAL
: break;
2866 case A1_OP_TYPE_DECORATE
:
2868 case A1_OP_TYPE_EXTERN
: {
2869 const void *fel
= DPOC(from
, t
->offset
);
2870 void *tel
= DPO(to
, t
->offset
);
2871 void **ptel
= (void **)tel
;
2874 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
) {
2875 size
= _asn1_sizeofType(t
->ptr
);
2877 const struct asn1_type_func
*f
= t
->ptr
;
2881 if (t
->tt
& A1_FLAG_OPTIONAL
) {
2882 void **pfel
= (void **)fel
;
2887 tel
= *ptel
= calloc(1, size
);
2892 if ((t
->tt
& A1_OP_MASK
) == A1_OP_TYPE
||
2893 (t
->tt
& A1_OP_MASK
) == A1_OP_TYPE_DECORATE
) {
2894 ret
= _asn1_copy(t
->ptr
, fel
, tel
);
2896 const struct asn1_type_func
*f
= t
->ptr
;
2897 ret
= (f
->copy
)(fel
, tel
);
2901 if (t
->tt
& A1_FLAG_OPTIONAL
) {
2910 unsigned int type
= A1_PARSE_TYPE(t
->tt
);
2911 const void *fel
= DPOC(from
, t
->offset
);
2912 void *tel
= DPO(to
, t
->offset
);
2914 if (type
>= sizeof(asn1_template_prim
)/sizeof(asn1_template_prim
[0])) {
2916 return ASN1_PARSE_ERROR
;
2918 ret
= (asn1_template_prim
[type
].copy
)(fel
, tel
);
2924 const void *oldfrom
= from
;
2928 from
= DPOC(from
, t
->offset
);
2929 to
= DPO(to
, t
->offset
);
2931 if (t
->tt
& A1_FLAG_OPTIONAL
) {
2932 void **fel
= (void **)from
;
2941 to
= *tel
= calloc(1, _asn1_sizeofType(t
->ptr
));
2946 ret
= _asn1_copy(t
->ptr
, from
, to
);
2962 const struct template_of
*fel
= DPOC(from
, t
->offset
);
2963 struct template_of
*tel
= DPO(to
, t
->offset
);
2964 size_t ellen
= _asn1_sizeofType(t
->ptr
);
2967 tel
->val
= calloc(fel
->len
, ellen
);
2968 if (tel
->val
== NULL
)
2971 tel
->len
= fel
->len
;
2973 for (i
= 0; i
< fel
->len
; i
++) {
2974 ret
= _asn1_copy(t
->ptr
,
2975 DPOC(fel
->val
, (i
* ellen
)),
2976 DPO(tel
->val
, (i
*ellen
)));
2982 case A1_OP_BMEMBER
: {
2983 const struct asn1_template
*bmember
= t
->ptr
;
2984 size_t size
= bmember
->offset
;
2985 memcpy(to
, from
, size
);
2988 case A1_OP_CHOICE
: {
2989 const struct asn1_template
*choice
= t
->ptr
;
2990 const unsigned int *felement
= DPOC(from
, choice
->offset
);
2991 unsigned int *telement
= DPO(to
, choice
->offset
);
2993 if (*felement
> A1_HEADER_LEN(choice
))
2994 return ASN1_PARSE_ERROR
;
2996 *telement
= *felement
;
2998 if (*felement
== 0) {
2999 ret
= der_copy_octet_string(DPOC(from
, choice
->tt
), DPO(to
, choice
->tt
));
3001 choice
+= *felement
;
3002 ret
= _asn1_copy(choice
->ptr
,
3003 DPOC(from
, choice
->offset
),
3004 DPO(to
, choice
->offset
));
3021 _asn1_decode_top(const struct asn1_template
*t
, unsigned flags
, const unsigned char *p
, size_t len
, void *data
, size_t *size
)
3024 memset(data
, 0, t
->offset
);
3025 ret
= _asn1_decode(t
, flags
, p
, len
, data
, size
);
3027 _asn1_free_top(t
, data
);
3033 _asn1_copy_top(const struct asn1_template
*t
, const void *from
, void *to
)
3036 memset(to
, 0, t
->offset
);
3037 ret
= _asn1_copy(t
, from
, to
);
3039 _asn1_free_top(t
, to
);
3045 _asn1_free_top(const struct asn1_template
*t
, void *data
)
3047 _asn1_free(t
, data
);
3048 memset(data
, 0, t
->offset
);