Line data Source code
1 : /*
2 : * Copyright (c) 2009 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Portions Copyright (c) 2009 - 2010 Apple Inc. All rights reserved.
7 : *
8 : * Redistribution and use in source and binary forms, with or without
9 : * modification, are permitted provided that the following conditions
10 : * are met:
11 : *
12 : * 1. Redistributions of source code must retain the above copyright
13 : * notice, this list of conditions and the following disclaimer.
14 : *
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.
18 : *
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.
22 : *
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
33 : * SUCH DAMAGE.
34 : */
35 :
36 : #include "der_locl.h"
37 : #include <com_err.h>
38 : #include <vis.h>
39 : #include <vis-extras.h>
40 : #include <heimbase.h>
41 :
42 : #ifndef ENOTSUP
43 : /* Very old MSVC CRTs don't have ENOTSUP */
44 : #define ENOTSUP EINVAL
45 : #endif
46 :
47 : struct asn1_type_func asn1_template_prim[A1T_NUM_ENTRY] = {
48 : #define el(name, type) { \
49 : (asn1_type_encode)der_put_##name, \
50 : (asn1_type_decode)der_get_##name, \
51 : (asn1_type_length)der_length_##name, \
52 : (asn1_type_copy)der_copy_##name, \
53 : (asn1_type_release)der_free_##name, \
54 : (asn1_type_print)der_print_##name, \
55 : sizeof(type) \
56 : }
57 : #define elber(name, type) { \
58 : (asn1_type_encode)der_put_##name, \
59 : (asn1_type_decode)der_get_##name##_ber, \
60 : (asn1_type_length)der_length_##name, \
61 : (asn1_type_copy)der_copy_##name, \
62 : (asn1_type_release)der_free_##name, \
63 : (asn1_type_print)der_print_##name, \
64 : sizeof(type) \
65 : }
66 : el(integer, int),
67 : el(heim_integer, heim_integer),
68 : el(integer, int),
69 : el(integer64, int64_t),
70 : el(unsigned, unsigned),
71 : el(unsigned64, uint64_t),
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),
82 : el(utctime, 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, (asn1_type_print)der_print_boolean,
87 : sizeof(int)
88 : },
89 : el(oid, heim_oid),
90 : el(general_string, heim_general_string),
91 : #undef el
92 : #undef elber
93 : };
94 :
95 : size_t
96 87144409 : _asn1_sizeofType(const struct asn1_template *t)
97 : {
98 87144409 : return t->offset;
99 : }
100 :
101 : /*
102 : * Here is abstraction to not so well evil fact of bit fields in C,
103 : * they are endian dependent, so when getting and setting bits in the
104 : * host local structure we need to know the endianness of the host.
105 : *
106 : * Its not the first time in Heimdal this have bitten us, and some day
107 : * we'll grow up and use #defined constant, but bit fields are still
108 : * so pretty and shiny.
109 : */
110 :
111 : static void
112 4278255 : _asn1_bmember_get_bit(const unsigned char *p, void *data,
113 : unsigned int bit, size_t size)
114 : {
115 4278255 : unsigned int localbit = bit % 8;
116 4278255 : if ((*p >> (7 - localbit)) & 1) {
117 : #ifdef WORDS_BIGENDIAN
118 : *(unsigned int *)data |= (1u << ((size * 8) - bit - 1));
119 : #else
120 705291 : *(unsigned int *)data |= (1u << bit);
121 : #endif
122 : }
123 4278255 : }
124 :
125 : int
126 5120202 : _asn1_bmember_isset_bit(const void *data, unsigned int bit, size_t size)
127 : {
128 : #ifdef WORDS_BIGENDIAN
129 : if ((*(unsigned int *)data) & (1u << ((size * 8) - bit - 1)))
130 : return 1;
131 : return 0;
132 : #else
133 5120202 : if ((*(unsigned int *)data) & (1u << bit))
134 827358 : return 1;
135 4292844 : return 0;
136 : #endif
137 : }
138 :
139 : void
140 5120202 : _asn1_bmember_put_bit(unsigned char *p, const void *data, unsigned int bit,
141 : size_t size, unsigned int *bitset)
142 : {
143 5120202 : unsigned int localbit = bit % 8;
144 :
145 5120202 : if (_asn1_bmember_isset_bit(data, bit, size)) {
146 827358 : *p |= (1u << (7 - localbit));
147 827358 : if (*bitset == 0)
148 310961 : *bitset = (7 - localbit) + 1;
149 : }
150 5120202 : }
151 :
152 : /*
153 : * Utility function to tell us if the encoding of some type per its template
154 : * will have an outer tag. This is needed when the caller wants to slap on an
155 : * IMPLICIT tag: if the inner type has a tag then we need to replace it.
156 : */
157 : static int
158 2007 : is_tagged(const struct asn1_template *t)
159 : {
160 2007 : size_t elements = A1_HEADER_LEN(t);
161 :
162 2007 : t += A1_HEADER_LEN(t);
163 2007 : if (elements != 1)
164 0 : return 0;
165 2007 : switch (t->tt & A1_OP_MASK) {
166 0 : case A1_OP_SEQOF: return 0;
167 0 : case A1_OP_SETOF: return 0;
168 0 : case A1_OP_BMEMBER: return 0;
169 0 : case A1_OP_PARSE: return 0;
170 1392 : case A1_OP_TAG: return 1;
171 0 : case A1_OP_CHOICE: return 1;
172 615 : case A1_OP_TYPE: return 1;
173 0 : case A1_OP_TYPE_EXTERN: {
174 0 : const struct asn1_type_func *f = t->ptr;
175 :
176 : /*
177 : * XXX Add a boolean to struct asn1_type_func to tell us if the type is
178 : * tagged or not. Basically, it's not tagged if it's primitive.
179 : */
180 0 : if (f->encode == (asn1_type_encode)encode_heim_any ||
181 0 : f->encode == (asn1_type_encode)encode_HEIM_ANY)
182 0 : return 0;
183 0 : abort(); /* XXX */
184 : }
185 0 : default: abort();
186 : }
187 : }
188 :
189 : static size_t
190 306 : inner_type_taglen(const struct asn1_template *t)
191 : {
192 306 : size_t elements = A1_HEADER_LEN(t);
193 :
194 306 : t += A1_HEADER_LEN(t);
195 306 : if (elements != 1)
196 0 : return 0;
197 306 : switch (t->tt & A1_OP_MASK) {
198 0 : case A1_OP_SEQOF: return 0;
199 0 : case A1_OP_SETOF: return 0;
200 0 : case A1_OP_BMEMBER: return 0;
201 0 : case A1_OP_PARSE: return 0;
202 0 : case A1_OP_CHOICE: return 1;
203 77 : case A1_OP_TYPE: return inner_type_taglen(t->ptr);
204 229 : case A1_OP_TAG: return der_length_tag(A1_TAG_TAG(t->tt));
205 0 : case A1_OP_TYPE_EXTERN: {
206 0 : const struct asn1_type_func *f = t->ptr;
207 :
208 : /*
209 : * XXX Add a boolean to struct asn1_type_func to tell us if the type is
210 : * tagged or not. Basically, it's not tagged if it's primitive.
211 : */
212 0 : if (f->encode == (asn1_type_encode)encode_heim_any ||
213 0 : f->encode == (asn1_type_encode)encode_HEIM_ANY)
214 0 : return 0;
215 0 : abort(); /* XXX */
216 : }
217 0 : default: abort();
218 : #ifdef WIN32
219 : _exit(0); /* Quiet VC */
220 : #endif
221 : }
222 : }
223 :
224 : /*
225 : * Compare some int of unknown size in a type ID field to the int value in
226 : * some IOS object's type ID template entry.
227 : *
228 : * This should be called with a `A1_TAG_T(ASN1_C_UNIV, PRIM, UT_Integer)'
229 : * template as the `ttypeid'.
230 : */
231 : static int
232 0 : typeid_int_cmp(const void *intp,
233 : int64_t i,
234 : const struct asn1_template *ttypeid)
235 : {
236 0 : const struct asn1_template *tint = ttypeid->ptr;
237 :
238 0 : if ((tint[1].tt & A1_OP_MASK) != A1_OP_PARSE)
239 0 : return -1;
240 0 : if (A1_PARSE_TYPE(tint[1].tt) != A1T_INTEGER &&
241 0 : A1_PARSE_TYPE(tint[1].tt) != A1T_UNSIGNED &&
242 0 : A1_PARSE_TYPE(tint[1].tt) != A1T_INTEGER64 &&
243 0 : A1_PARSE_TYPE(tint[1].tt) != A1T_UNSIGNED64 &&
244 0 : A1_PARSE_TYPE(tint[1].tt) != A1T_IMEMBER)
245 0 : return -1;
246 0 : switch (tint[0].offset) {
247 0 : case 8: return i - *(const int64_t *)intp;
248 0 : case 4: return i - *(const int32_t *)intp;
249 0 : default: return -1;
250 : }
251 : }
252 :
253 : /*
254 : * Map a logical SET/SEQUENCE member to a template entry.
255 : *
256 : * This should really have been done by the compiler, but clearly it wasn't.
257 : *
258 : * The point is that a struct type's template may be littered with entries that
259 : * don't directly correspond to a struct field (SET/SEQUENCE member), so we
260 : * have to count just the ones that do to get to the one we want.
261 : */
262 : static const struct asn1_template *
263 2210 : template4member(const struct asn1_template *t, size_t f)
264 : {
265 2210 : size_t n = (uintptr_t)t->ptr;
266 : size_t i;
267 :
268 5449 : for (i = 0, t++; i < n; t++, i++) {
269 5449 : switch (t->tt & A1_OP_MASK) {
270 4382 : case A1_OP_TAG:
271 : case A1_OP_TYPE:
272 : case A1_OP_TYPE_EXTERN:
273 4382 : if (f-- == 0)
274 2210 : return t;
275 2172 : continue;
276 0 : case A1_OP_OPENTYPE_OBJSET:
277 : case A1_OP_NAME:
278 0 : return NULL;
279 1067 : default:
280 1067 : continue;
281 : }
282 : }
283 0 : return NULL;
284 : }
285 :
286 : /*
287 : * Attempt to decode known open type alternatives into a CHOICE-like
288 : * discriminated union.
289 : *
290 : * Arguments:
291 : *
292 : * - object set template
293 : * - decoder flags
294 : * - pointer to memory object (C struct) to decode into
295 : * - template for type ID field of `data'
296 : * - template for open type field of `data' (an octet string or HEIM_ANY)
297 : *
298 : * Returns:
299 : *
300 : * - 0
301 : * - ENOMEM
302 : *
303 : * Other errors in decoding open type values are ignored, but applications can
304 : * note that an error must have occurred. (Perhaps we should generate a `ret'
305 : * field for the discriminated union we decode into that we could use to
306 : * indicate what went wrong with decoding an open type value? The application
307 : * can always try to decode itself to find out what the error was, but the
308 : * whole point is to save the developer the bother of writing code to decode
309 : * open type values. Then again, the specific cause of any one decode failure
310 : * is not usually very important to users, so it's not very important to
311 : * applications either.)
312 : *
313 : * Here `data' is something like this:
314 : *
315 : * typedef struct SingleAttribute {
316 : * heim_oid type; // <--- decoded already
317 : * HEIM_ANY value; // <--- decoded already
318 : * // We must set this:
319 : * // vvvvvvvv
320 : * struct {
321 : * enum {
322 : * choice_SingleAttribute_iosnumunknown = 0,
323 : * choice_SingleAttribute_iosnum_id_at_name,
324 : * ..
325 : * choice_SingleAttribute_iosnum_id_at_emailAddress,
326 : * } element; // <--- map type ID to enum
327 : * union {
328 : * X520name* at_name;
329 : * X520name* at_surname;
330 : * ..
331 : * AliasIA5String* at_emailAddress;
332 : * } u; // <--- alloc and decode val above into this
333 : * } _ioschoice_value;
334 : * } SingleAttribute;
335 : *
336 : * or
337 : *
338 : * typedef struct AttributeSet {
339 : * heim_oid type; // <--- decoded already
340 : * struct AttributeSet_values {
341 : * unsigned int len; // <--- decoded already
342 : * HEIM_ANY *val; // <--- decoded already
343 : * } values;
344 : * // We must set this:
345 : * // vvvvvvvv
346 : * struct {
347 : * enum { choice_AttributeSet_iosnumunknown = 0,
348 : * choice_AttributeSet_iosnum_id_at_name,
349 : * choice_AttributeSet_iosnum_id_at_surname,
350 : * ..
351 : * choice_AttributeSet_iosnum_id_at_emailAddress,
352 : * } element; // <--- map type ID to enum
353 : * unsigned int len; // <--- set len to len as above
354 : * union {
355 : * X520name *at_name;
356 : * X520name *at_surname;
357 : * ..
358 : * AliasIA5String *at_emailAddress;
359 : * } *val; // <--- alloc and decode vals above into this
360 : * } _ioschoice_values;
361 : * } AttributeSet;
362 : */
363 : static int
364 1105 : _asn1_decode_open_type(const struct asn1_template *t,
365 : unsigned flags,
366 : void *data,
367 : const struct asn1_template *ttypeid,
368 : const struct asn1_template *topentype)
369 : {
370 1105 : const struct asn1_template *ttypeid_univ = ttypeid;
371 : const struct asn1_template *tactual_type;
372 1105 : const struct asn1_template *tos = t->ptr;
373 : size_t sz, n;
374 1105 : size_t i = 0;
375 1105 : unsigned int *lenp = NULL; /* Pointer to array length field */
376 1105 : unsigned int len = 1; /* Array length */
377 1105 : void **dp = NULL; /* Decoded open type struct pointer */
378 : int *elementp; /* Choice enum pointer */
379 1105 : int typeid_is_oid = 0;
380 1105 : int typeid_is_int = 0;
381 1105 : int ret = 0;
382 :
383 : /*
384 : * NOTE: Here expressions like `DPO(data, t->offset + ...)' refer to parts
385 : * of a _ioschoice_<fieldName> struct field of `data'.
386 : *
387 : * Expressions like `DPO(data, topentype->offset + ...)' refer to
388 : * the open type field in `data', which is either a `heim_any', a
389 : * `heim_octet_string', or an array of one of those.
390 : *
391 : * Expressions like `DPO(data, ttypeid->offset)' refer to the open
392 : * type's type ID field in `data'.
393 : */
394 :
395 : /*
396 : * Minimal setup:
397 : *
398 : * - set type choice to choice_<type>_iosnumunknown (zero).
399 : * - set union value to zero
400 : *
401 : * We need a pointer to the choice ID:
402 : *
403 : * typedef struct AttributeSet {
404 : * heim_oid type; // <--- decoded already
405 : * struct AttributeSet_values {
406 : * unsigned int len; // <--- decoded already
407 : * HEIM_ANY *val; // <--- decoded already
408 : * } values;
409 : * struct {
410 : * enum { choice_AttributeSet_iosnumunknown = 0,
411 : * -----------> ...
412 : * } element; // HERE
413 : * ...
414 : * } ...
415 : * }
416 : *
417 : * XXX NOTE: We're assuming that sizeof(enum) == sizeof(int)!
418 : */
419 1105 : elementp = DPO(data, t->offset);
420 1105 : *elementp = 0; /* Set the choice to choice_<type>_iosnumunknown */
421 1105 : if (t->tt & A1_OS_OT_IS_ARRAY) {
422 : /*
423 : * The open type is a SET OF / SEQUENCE OF -- an array.
424 : *
425 : * Get the number of elements to decode from:
426 : *
427 : * typedef struct AttributeSet {
428 : * heim_oid type;
429 : * struct AttributeSet_values {
430 : * ------------>unsigned int len; // HERE
431 : * HEIM_ANY *val;
432 : * } values;
433 : * ...
434 : * }
435 : */
436 0 : len = *((unsigned int *)DPO(data, topentype->offset));
437 :
438 : /*
439 : * Set the number of decoded elements to zero for now:
440 : *
441 : * typedef struct AttributeSet {
442 : * heim_oid type;
443 : * struct AttributeSet_values {
444 : * unsigned int len;
445 : * HEIM_ANY *val;
446 : * } values;
447 : * struct {
448 : * enum { ... } element;
449 : * ------------>unsigned int len; // HERE
450 : * ...
451 : * } _ioschoice_values;
452 : * }
453 : */
454 0 : lenp = DPO(data, t->offset + sizeof(*elementp));
455 0 : *lenp = 0;
456 : /*
457 : * Get a pointer to the place where we must put the decoded value:
458 : *
459 : * typedef struct AttributeSet {
460 : * heim_oid type;
461 : * struct AttributeSet_values {
462 : * unsigned int len;
463 : * HEIM_ANY *val;
464 : * } values;
465 : * struct {
466 : * enum { ... } element;
467 : * unsigned int len;
468 : * struct {
469 : * union { SomeType *some_choice; ... } u;
470 : * ------------>} *val; // HERE
471 : * } _ioschoice_values;
472 : * } AttributeSet;
473 : */
474 0 : dp = DPO(data, t->offset + sizeof(*elementp) + sizeof(*lenp));
475 : } else {
476 : /*
477 : * Get a pointer to the place where we must put the decoded value:
478 : *
479 : * typedef struct SingleAttribute {
480 : * heim_oid type;
481 : * HEIM_ANY value;
482 : * struct {
483 : * enum { ... } element;
484 : * ------------>union { SomeType *some_choice; ... } u; // HERE
485 : * } _ioschoice_value;
486 : * } SingleAttribute;
487 : */
488 1105 : dp = DPO(data, t->offset + sizeof(*elementp));
489 : }
490 :
491 : /* Align `dp' */
492 1105 : while (sizeof(void *) != sizeof(*elementp) &&
493 2210 : ((uintptr_t)dp) % sizeof(void *) != 0)
494 1105 : dp = (void *)(((char *)dp) + sizeof(*elementp));
495 1105 : *dp = NULL;
496 :
497 : /*
498 : * Find out the type of the type ID member. We currently support only
499 : * integers and OIDs.
500 : *
501 : * Chase through any tags to get to the type.
502 : */
503 1105 : while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
504 1105 : A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
505 1105 : ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
506 0 : ttypeid_univ = ttypeid_univ->ptr;
507 0 : ttypeid_univ++;
508 : }
509 1105 : switch (ttypeid_univ->tt & A1_OP_MASK) {
510 1105 : case A1_OP_TAG:
511 1105 : if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV)
512 0 : return 0; /* Do nothing, silently */
513 1105 : switch (A1_TAG_TAG(ttypeid_univ->tt)) {
514 1105 : case UT_OID:
515 1105 : typeid_is_oid = 1;
516 1105 : break;
517 0 : case UT_Integer: {
518 0 : const struct asn1_template *tint = ttypeid_univ->ptr;
519 :
520 0 : tint++;
521 :
522 0 : if ((tint->tt & A1_OP_MASK) != A1_OP_PARSE)
523 0 : return 0; /* Do nothing, silently */
524 0 : if (A1_PARSE_TYPE(tint->tt) != A1T_INTEGER &&
525 0 : A1_PARSE_TYPE(tint->tt) != A1T_UNSIGNED &&
526 0 : A1_PARSE_TYPE(tint->tt) != A1T_INTEGER64 &&
527 0 : A1_PARSE_TYPE(tint->tt) != A1T_UNSIGNED64 &&
528 0 : A1_PARSE_TYPE(tint->tt) != A1T_IMEMBER)
529 0 : return 0; /* Do nothing, silently (maybe a large int) */
530 0 : typeid_is_int = 1;
531 0 : break;
532 : }
533 : /* It might be cool to support string types as type ID types */
534 0 : default: return 0; /* Do nothing, silently */
535 : }
536 1105 : break;
537 0 : default: return 0; /* Do nothing, silently */
538 : }
539 :
540 : /*
541 : * Find the type of the open type.
542 : *
543 : * An object set template looks like:
544 : *
545 : * const struct asn1_template asn1_ObjectSetName[] = {
546 : * // Header entry (in this case it says there's 17 objects):
547 : * { 0, 0, ((void*)17) },
548 : *
549 : * // here's the name of the object set:
550 : * { A1_OP_NAME, 0, "ObjectSetName" },
551 : *
552 : * // then three entries per object: object name, object type ID,
553 : * // object type:
554 : * { A1_OP_NAME, 0, "ext-AuthorityInfoAccess" },
555 : * { A1_OP_OPENTYPE_ID, 0, (const void*)&asn1_oid_oidName },
556 : * { A1_OP_OPENTYPE, sizeof(SomeType), (const void*)&asn1_SomeType },
557 : * ...
558 : * };
559 : *
560 : * `i' being a logical object offset, i*3+3 would be the index of the
561 : * A1_OP_OPENTYPE_ID entry for the current object, and i*3+4 the index of
562 : * the A1_OP_OPENTYPE entry for the current object.
563 : */
564 1105 : if (t->tt & A1_OS_IS_SORTED) {
565 1105 : size_t left = 0;
566 1105 : size_t right = A1_HEADER_LEN(tos);
567 1105 : const void *vp = DPO(data, ttypeid->offset);
568 1105 : int c = -1;
569 :
570 3692 : while (left < right) {
571 3478 : size_t mid = (left + right) >> 1;
572 :
573 3478 : if ((tos[3 + mid * 3].tt & A1_OP_MASK) != A1_OP_OPENTYPE_ID)
574 0 : return 0;
575 3478 : if (typeid_is_int)
576 0 : c = typeid_int_cmp(vp, (intptr_t)tos[3 + mid * 3].ptr,
577 : ttypeid_univ);
578 3478 : else if (typeid_is_oid)
579 3478 : c = der_heim_oid_cmp(vp, tos[3 + mid * 3].ptr);
580 3478 : if (c < 0) {
581 1118 : right = mid;
582 2360 : } else if (c > 0) {
583 1469 : left = mid + 1;
584 : } else {
585 891 : i = mid;
586 891 : break;
587 : }
588 : }
589 1105 : if (c)
590 214 : return 0; /* No match */
591 : } else {
592 0 : for (i = 0, n = A1_HEADER_LEN(tos); i < n; i++) {
593 : /* We add 1 to `i' because we're skipping the header */
594 0 : if ((tos[3 + i*3].tt & A1_OP_MASK) != A1_OP_OPENTYPE_ID)
595 0 : return 0;
596 0 : if (typeid_is_int &&
597 0 : typeid_int_cmp(DPO(data, ttypeid->offset),
598 0 : (intptr_t)tos[3 + i*3].ptr,
599 : ttypeid_univ))
600 0 : continue;
601 0 : if (typeid_is_oid &&
602 0 : der_heim_oid_cmp(DPO(data, ttypeid->offset), tos[3 + i*3].ptr))
603 0 : continue;
604 0 : break;
605 : }
606 0 : if (i == n)
607 0 : return 0; /* No match */
608 : }
609 :
610 : /* Match! */
611 891 : *elementp = i+1; /* Zero is the "unknown" choice, so add 1 */
612 :
613 : /*
614 : * We want the A1_OP_OPENTYPE template entry. Its `offset' is the sizeof
615 : * the object we'll be decoding into, and its `ptr' is the pointer to the
616 : * template for decoding that type.
617 : */
618 891 : tactual_type = &tos[i*3 + 4];
619 :
620 : /* Decode the encoded open type value(s) */
621 891 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
622 : /*
623 : * Not a SET OF/SEQUENCE OF open type, just singular.
624 : *
625 : * We need the address of the octet string / ANY field containing the
626 : * encoded open type value:
627 : *
628 : * typedef struct SingleAttribute {
629 : * heim_oid type;
630 : * -------->HEIM_ANY value; // HERE
631 : * struct {
632 : * ...
633 : * } ...
634 : * }
635 : */
636 891 : const struct heim_base_data *d = DPOC(data, topentype->offset);
637 : void *o;
638 :
639 891 : if (d->data && d->length) {
640 891 : if ((o = calloc(1, tactual_type->offset)) == NULL)
641 0 : return ENOMEM;
642 :
643 : /* Re-enter to decode the encoded open type value */
644 891 : ret = _asn1_decode(tactual_type->ptr, flags, d->data, d->length, o, &sz);
645 : /*
646 : * Store the decoded object in the union:
647 : *
648 : * typedef struct SingleAttribute {
649 : * heim_oid type;
650 : * HEIM_ANY value;
651 : * struct {
652 : * enum { ... } element;
653 : * ------------>union { SomeType *some_choice; ... } u; // HERE
654 : * } _ioschoice_value;
655 : * } SingleAttribute;
656 : *
657 : * All the union arms are pointers.
658 : */
659 891 : if (ret) {
660 0 : _asn1_free(tactual_type->ptr, o);
661 0 : free(o);
662 : /*
663 : * So we failed to decode the open type -- that should not be fatal
664 : * to decoding the rest of the input. Only ENOMEM should be fatal.
665 : */
666 0 : ret = 0;
667 : } else {
668 891 : *dp = o;
669 : }
670 : }
671 891 : return ret;
672 : } else {
673 : const struct heim_base_data * const *d;
674 : void **val; /* Array of pointers */
675 :
676 : /*
677 : * A SET OF/SEQUENCE OF open type, plural.
678 : *
679 : * We need the address of the octet string / ANY array pointer field
680 : * containing the encoded open type values:
681 : *
682 : * typedef struct AttributeSet {
683 : * heim_oid type;
684 : * struct AttributeSet_values {
685 : * unsigned int len;
686 : * ------------>HEIM_ANY *val; // HERE
687 : * } values;
688 : * ...
689 : * }
690 : *
691 : * We already know the value of the `len' field.
692 : */
693 0 : d = DPOC(data, topentype->offset + sizeof(unsigned int));
694 0 : while (sizeof(void *) != sizeof(len) &&
695 0 : ((uintptr_t)d) % sizeof(void *) != 0)
696 0 : d = (const void *)(((const char *)d) + sizeof(len));
697 :
698 0 : if ((val = calloc(len, sizeof(*val))) == NULL)
699 0 : ret = ENOMEM;
700 :
701 : /* Increment the count of decoded values as we decode */
702 0 : *lenp = len;
703 0 : for (i = 0; ret != ENOMEM && i < len; i++) {
704 0 : if ((val[i] = calloc(1, tactual_type->offset)) == NULL)
705 0 : ret = ENOMEM;
706 0 : if (ret == 0)
707 : /* Re-enter to decode the encoded open type value */
708 0 : ret = _asn1_decode(tactual_type->ptr, flags, d[0][i].data,
709 0 : d[0][i].length, val[i], &sz);
710 0 : if (ret) {
711 0 : _asn1_free(tactual_type->ptr, val[i]);
712 0 : free(val[i]);
713 0 : val[i] = NULL;
714 : }
715 : }
716 0 : if (ret != ENOMEM)
717 0 : ret = 0; /* See above */
718 0 : *dp = val;
719 0 : return ret;
720 : }
721 : }
722 :
723 : int
724 36625152 : _asn1_decode(const struct asn1_template *t, unsigned flags,
725 : const unsigned char *p, size_t len, void *data, size_t *size)
726 : {
727 36625152 : const struct asn1_template *tbase = t;
728 36625152 : const struct asn1_template *tdefval = NULL;
729 36625152 : size_t elements = A1_HEADER_LEN(t);
730 36625152 : size_t oldlen = len;
731 36625152 : int ret = 0;
732 36625152 : const unsigned char *startp = NULL;
733 36625152 : unsigned int template_flags = t->tt;
734 :
735 : /*
736 : * Important notes:
737 : *
738 : * - by and large we don't call _asn1_free() on error, except when we're
739 : * decoding optional things or choices, then we do call _asn1_free()
740 : * here
741 : *
742 : * instead we leave it to _asn1_decode_top() to call _asn1_free() on
743 : * error
744 : *
745 : * - on error all fields of whatever we didn't _asn1_free() must have been
746 : * initialized to sane values because _asn1_decode_top() will call
747 : * _asn1_free() on error, so we must have left everything initialized
748 : * that _asn1_free() could possibly look at
749 : *
750 : * - so we must initialize everything
751 : *
752 : * FIXME? but we mostly rely on calloc() to do this...
753 : *
754 : * - we don't use malloc() unless we're going to write over the whole
755 : * thing with memcpy() or whatever
756 : */
757 :
758 : /* skip over header */
759 36625152 : t++;
760 :
761 36625152 : if (template_flags & A1_HF_PRESERVE)
762 104073 : startp = p;
763 :
764 95228098 : while (elements) {
765 58727979 : switch (t->tt & A1_OP_MASK) {
766 1105 : case A1_OP_OPENTYPE_OBJSET: {
767 1105 : size_t opentypeid = t->tt & ((1<<10)-1);
768 1105 : size_t opentype = (t->tt >> 10) & ((1<<10)-1);
769 :
770 : /* Note that the only error returned here would be ENOMEM */
771 1105 : ret = _asn1_decode_open_type(t, flags, data,
772 : template4member(tbase, opentypeid),
773 : template4member(tbase, opentype));
774 1105 : if (ret)
775 0 : return ret;
776 1105 : break;
777 : }
778 0 : case A1_OP_TYPE_DECORATE_EXTERN: break;
779 0 : case A1_OP_TYPE_DECORATE: break;
780 14278007 : case A1_OP_NAME: break;
781 1218 : case A1_OP_DEFVAL:
782 1218 : tdefval = t;
783 1218 : break;
784 9052936 : case A1_OP_TYPE:
785 : case A1_OP_TYPE_EXTERN: {
786 : size_t newsize, elsize;
787 9052936 : void *el = DPO(data, t->offset);
788 9052936 : void **pel = (void **)el;
789 :
790 9052936 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
791 9052445 : elsize = _asn1_sizeofType(t->ptr);
792 : } else {
793 491 : const struct asn1_type_func *f = t->ptr;
794 491 : elsize = f->size;
795 : }
796 :
797 9052936 : if (t->tt & A1_FLAG_OPTIONAL) {
798 453 : *pel = calloc(1, elsize);
799 453 : if (*pel == NULL)
800 0 : return ENOMEM;
801 453 : el = *pel;
802 453 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
803 0 : ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
804 : } else {
805 453 : const struct asn1_type_func *f = t->ptr;
806 453 : ret = (f->decode)(p, len, el, &newsize);
807 : }
808 453 : if (ret) {
809 : /*
810 : * Optional field not present in encoding, presumably,
811 : * though we should really look more carefully at `ret'.
812 : */
813 0 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
814 0 : _asn1_free(t->ptr, el);
815 : } else {
816 0 : const struct asn1_type_func *f = t->ptr;
817 0 : f->release(el);
818 : }
819 0 : free(*pel);
820 0 : *pel = NULL;
821 9052936 : break;
822 : }
823 : } else {
824 9052483 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
825 9052445 : ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
826 : } else {
827 38 : const struct asn1_type_func *f = t->ptr;
828 38 : ret = (f->decode)(p, len, el, &newsize);
829 : }
830 : }
831 9052936 : if (ret) {
832 0 : if (t->tt & A1_FLAG_OPTIONAL) {
833 0 : } else if (t->tt & A1_FLAG_DEFAULT) {
834 0 : if (!tdefval)
835 0 : return ASN1_PARSE_ERROR; /* Can't happen */
836 : /*
837 : * Defaulted field not present in encoding, presumably,
838 : * though we should really look more carefully at `ret'.
839 : */
840 0 : if (tdefval->tt & A1_DV_BOOLEAN) {
841 0 : int *i = (void *)(char *)el;
842 :
843 0 : *i = tdefval->ptr ? 1 : 0;
844 0 : } else if (tdefval->tt & A1_DV_INTEGER64) {
845 0 : int64_t *i = (void *)(char *)el;
846 :
847 0 : *i = (int64_t)(intptr_t)tdefval->ptr;
848 0 : } else if (tdefval->tt & A1_DV_INTEGER32) {
849 0 : int32_t *i = (void *)(char *)el;
850 :
851 0 : *i = (int32_t)(intptr_t)tdefval->ptr;
852 0 : } else if (tdefval->tt & A1_DV_INTEGER) {
853 0 : struct heim_integer *i = (void *)(char *)el;
854 :
855 0 : if ((ret = der_copy_heim_integer(tdefval->ptr, i)))
856 0 : return ret;
857 0 : } else if (tdefval->tt & A1_DV_UTF8STRING) {
858 0 : char **s = el;
859 :
860 0 : if ((*s = strdup(tdefval->ptr)) == NULL)
861 0 : return ENOMEM;
862 : } else {
863 0 : abort();
864 : }
865 0 : break;
866 : }
867 0 : return ret; /* Error decoding required field */
868 : }
869 9052936 : p += newsize; len -= newsize;
870 :
871 9052936 : break;
872 : }
873 25147698 : case A1_OP_TAG: {
874 : Der_type dertype;
875 25147698 : size_t newsize = 0;
876 25147698 : size_t datalen, l = 0;
877 25147698 : void *olddata = data;
878 25147698 : int is_indefinite = 0;
879 25147698 : int subflags = flags;
880 25147698 : int replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
881 25147698 : void *el = data = DPO(data, t->offset);
882 25147698 : void **pel = (void **)el;
883 :
884 : /*
885 : * XXX If this type (chasing t->ptr through IMPLICIT tags, if this
886 : * one is too, till we find a non-TTag) is a [UNIVERSAL SET] type,
887 : * then we have to accept fields out of order. For each field tag
888 : * we see we'd have to do a linear search of the SET's template
889 : * because it won't be sorted (or we could sort a copy and do a
890 : * binary search on that, but these SETs will always be small so it
891 : * won't be worthwhile). We'll need a utility function to do all
892 : * of this.
893 : */
894 25147698 : ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt),
895 25147698 : &dertype, A1_TAG_TAG(t->tt),
896 : &datalen, &l);
897 25147698 : if (ret) {
898 1317879 : if (t->tt & A1_FLAG_OPTIONAL) {
899 1191843 : data = olddata;
900 25022665 : break;
901 126036 : } else if (t->tt & A1_FLAG_DEFAULT) {
902 1003 : if (!tdefval)
903 125033 : return ASN1_PARSE_ERROR; /* Can't happen */
904 : /*
905 : * Defaulted field not present in encoding, presumably,
906 : * though we should really look more carefully at `ret'.
907 : */
908 1003 : if (tdefval->tt & A1_DV_BOOLEAN) {
909 1003 : int *i = (void *)(char *)data;
910 :
911 1003 : *i = tdefval->ptr ? 1 : 0;
912 0 : } else if (tdefval->tt & A1_DV_INTEGER64) {
913 0 : int64_t *i = (void *)(char *)data;
914 :
915 0 : *i = (int64_t)(intptr_t)tdefval->ptr;
916 0 : } else if (tdefval->tt & A1_DV_INTEGER32) {
917 0 : int32_t *i = (void *)(char *)data;
918 :
919 0 : *i = (int32_t)(intptr_t)tdefval->ptr;
920 0 : } else if (tdefval->tt & A1_DV_INTEGER) {
921 0 : struct heim_integer *i = (void *)(char *)data;
922 :
923 0 : if ((ret = der_copy_heim_integer(tdefval->ptr, i)))
924 0 : return ret;
925 0 : } else if (tdefval->tt & A1_DV_UTF8STRING) {
926 0 : char **s = data;
927 :
928 0 : if ((*s = strdup(tdefval->ptr)) == NULL)
929 0 : return ENOMEM;
930 : } else {
931 0 : abort();
932 : }
933 1003 : data = olddata;
934 1003 : break;
935 : }
936 125033 : return ret; /* Error decoding required field */
937 : }
938 :
939 23829819 : p += l; len -= l;
940 :
941 : /*
942 : * Only allow indefinite encoding for OCTET STRING and BER
943 : * for now. Should handle BIT STRING too.
944 : */
945 :
946 23829819 : if (dertype != A1_TAG_TYPE(t->tt) && (flags & A1_PF_ALLOW_BER)) {
947 0 : const struct asn1_template *subtype = t->ptr;
948 0 : subtype++; /* skip header */
949 :
950 0 : if (((subtype->tt & A1_OP_MASK) == A1_OP_PARSE) &&
951 0 : A1_PARSE_TYPE(subtype->tt) == A1T_OCTET_STRING)
952 0 : subflags |= A1_PF_INDEFINTE;
953 : }
954 :
955 23829819 : if (datalen == ASN1_INDEFINITE) {
956 0 : if ((flags & A1_PF_ALLOW_BER) == 0)
957 0 : return ASN1_GOT_BER;
958 0 : is_indefinite = 1;
959 0 : datalen = len;
960 0 : if (datalen < 2)
961 0 : return ASN1_OVERRUN;
962 : /* hide EndOfContent for sub-decoder, catching it below */
963 0 : datalen -= 2;
964 23829819 : } else if (datalen > len)
965 0 : return ASN1_OVERRUN;
966 :
967 23829819 : if (t->tt & A1_FLAG_OPTIONAL) {
968 1504097 : size_t ellen = _asn1_sizeofType(t->ptr);
969 :
970 1504097 : *pel = calloc(1, ellen);
971 1504097 : if (*pel == NULL)
972 0 : return ENOMEM;
973 1504097 : data = *pel;
974 : }
975 :
976 23829819 : if (replace_tag) {
977 538 : const struct asn1_template *subtype = t->ptr;
978 538 : int have_tag = 0;
979 :
980 : /*
981 : * So, we have an IMPLICIT tag. What we want to do is find the
982 : * template for the body of the type so-tagged. That's going
983 : * to be a template that has a tag that isn't itself IMPLICIT.
984 : *
985 : * So we chase the pointer in the template until we find such a
986 : * thing, then decode using that template.
987 : */
988 1114 : while (!have_tag) {
989 576 : subtype++;
990 576 : if ((subtype->tt & A1_OP_MASK) == A1_OP_TAG)
991 538 : replace_tag = (subtype->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
992 576 : if (replace_tag) {
993 38 : subtype = subtype->ptr;
994 38 : continue;
995 : }
996 538 : if ((subtype->tt & A1_OP_MASK) == A1_OP_TAG) {
997 538 : ret = _asn1_decode(subtype->ptr, subflags, p, datalen, data, &newsize);
998 538 : have_tag = 1;
999 : } else {
1000 0 : subtype = subtype->ptr;
1001 : }
1002 : }
1003 : } else {
1004 23829281 : ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize);
1005 : }
1006 23829819 : if (ret == 0 && !is_indefinite && newsize != datalen)
1007 : /* Hidden data */
1008 0 : ret = ASN1_EXTRA_DATA;
1009 :
1010 23829819 : if (ret == 0) {
1011 23829819 : if (is_indefinite) {
1012 : /* If we use indefinite encoding, the newsize is the datasize. */
1013 0 : datalen = newsize;
1014 : }
1015 :
1016 23829819 : len -= datalen;
1017 23829819 : p += datalen;
1018 :
1019 : /*
1020 : * Indefinite encoding needs a trailing EndOfContent,
1021 : * check for that.
1022 : */
1023 23829819 : if (is_indefinite) {
1024 0 : ret = der_match_tag_and_length(p, len, ASN1_C_UNIV,
1025 : &dertype, UT_EndOfContent,
1026 : &datalen, &l);
1027 0 : if (ret == 0 && dertype != PRIM)
1028 0 : ret = ASN1_BAD_ID;
1029 0 : else if (ret == 0 && datalen != 0)
1030 0 : ret = ASN1_INDEF_EXTRA_DATA;
1031 0 : if (ret == 0) {
1032 0 : p += l; len -= l;
1033 : }
1034 : }
1035 : }
1036 23829819 : if (ret) {
1037 0 : if (!(t->tt & A1_FLAG_OPTIONAL))
1038 0 : return ret;
1039 :
1040 0 : _asn1_free(t->ptr, data);
1041 0 : free(data);
1042 0 : *pel = NULL;
1043 0 : return ret;
1044 : }
1045 23829819 : data = olddata;
1046 :
1047 23829819 : break;
1048 : }
1049 8326264 : case A1_OP_PARSE: {
1050 8326264 : unsigned int type = A1_PARSE_TYPE(t->tt);
1051 : size_t newsize;
1052 8326264 : void *el = DPO(data, t->offset);
1053 :
1054 : /*
1055 : * INDEFINITE primitive types are one element after the
1056 : * same type but non-INDEFINITE version.
1057 : */
1058 8326264 : if (flags & A1_PF_INDEFINTE)
1059 0 : type++;
1060 :
1061 8326264 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
1062 0 : ABORT_ON_ERROR();
1063 0 : return ASN1_PARSE_ERROR;
1064 : }
1065 :
1066 8326264 : ret = (asn1_template_prim[type].decode)(p, len, el, &newsize);
1067 8326264 : if (ret)
1068 0 : return ret;
1069 8326264 : p += newsize; len -= newsize;
1070 :
1071 8326264 : break;
1072 : }
1073 1540764 : case A1_OP_SETOF:
1074 : case A1_OP_SEQOF: {
1075 1540764 : struct template_of *el = DPO(data, t->offset);
1076 : size_t newsize;
1077 1540764 : size_t ellen = _asn1_sizeofType(t->ptr);
1078 1540764 : size_t vallength = 0;
1079 :
1080 4068265 : while (len > 0) {
1081 : void *tmp;
1082 2527501 : size_t newlen = vallength + ellen;
1083 2527501 : if (vallength > newlen)
1084 0 : return ASN1_OVERFLOW;
1085 :
1086 : /* XXX Slow */
1087 2527501 : tmp = realloc(el->val, newlen);
1088 2527501 : if (tmp == NULL)
1089 0 : return ENOMEM;
1090 :
1091 2527501 : memset(DPO(tmp, vallength), 0, ellen);
1092 2527501 : el->val = tmp;
1093 :
1094 2527501 : el->len++;
1095 2527501 : ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len,
1096 2527501 : DPO(el->val, vallength), &newsize);
1097 2527501 : if (ret)
1098 0 : return ret;
1099 2527501 : vallength = newlen;
1100 2527501 : p += newsize; len -= newsize;
1101 : }
1102 :
1103 1540764 : break;
1104 : }
1105 312919 : case A1_OP_BMEMBER: {
1106 312919 : const struct asn1_template *bmember = t->ptr;
1107 312919 : size_t bsize = bmember->offset;
1108 312919 : size_t belements = A1_HEADER_LEN(bmember);
1109 312919 : size_t pos = 0;
1110 :
1111 312919 : bmember++;
1112 :
1113 312919 : memset(data, 0, bsize);
1114 :
1115 312919 : if (len < 1)
1116 0 : return ASN1_OVERRUN;
1117 312919 : p++; len--;
1118 :
1119 4591325 : while (belements && len) {
1120 4890857 : while (bmember->offset / 8 > pos / 8) {
1121 612451 : if (len < 1)
1122 0 : break;
1123 612451 : p++; len--;
1124 612451 : pos += 8;
1125 : }
1126 4278406 : if (len) {
1127 4278255 : _asn1_bmember_get_bit(p, data, bmember->offset, bsize);
1128 4278255 : belements--; bmember++;
1129 : }
1130 : }
1131 312919 : len = 0;
1132 312919 : break;
1133 : }
1134 67068 : case A1_OP_CHOICE: {
1135 67068 : const struct asn1_template *choice = t->ptr;
1136 67068 : unsigned int *element = DPO(data, choice->offset);
1137 : size_t datalen;
1138 : unsigned int i;
1139 :
1140 : /*
1141 : * CHOICE element IDs are assigned in monotonically increasing
1142 : * fashion. Therefore any unrealistic value is a suitable invalid
1143 : * CHOICE value. The largest binary value (or -1 if treating the
1144 : * enum as signed on a twos-complement system, or...) will do.
1145 : */
1146 67068 : *element = ~0;
1147 :
1148 72566 : for (i = 1; i < A1_HEADER_LEN(choice) + 1 && choice[i].tt; i++) {
1149 : /*
1150 : * This is more permissive than is required. CHOICE
1151 : * alternatives must have different outer tags, so in principle
1152 : * we should just match the tag at `p' and `len' in sequence to
1153 : * the choice alternatives.
1154 : *
1155 : * Trying every alternative instead happens to do this anyways
1156 : * because each one will first match the tag at `p' and `len',
1157 : * but if there are CHOICE altnernatives with the same outer
1158 : * tag, then we'll allow it, and they had better be unambiguous
1159 : * in their internal details, otherwise there would be some
1160 : * aliasing.
1161 : *
1162 : * Arguably the *compiler* should detect ambiguous CHOICE types
1163 : * and raise an error, then we don't have to be concerned here
1164 : * at all.
1165 : */
1166 72566 : ret = _asn1_decode(choice[i].ptr, 0, p, len,
1167 72566 : DPO(data, choice[i].offset), &datalen);
1168 72566 : if (ret == 0) {
1169 67068 : *element = i;
1170 67068 : p += datalen; len -= datalen;
1171 67068 : break;
1172 : }
1173 5498 : _asn1_free(choice[i].ptr, DPO(data, choice[i].offset));
1174 5498 : if (ret != ASN1_BAD_ID && ret != ASN1_MISPLACED_FIELD &&
1175 : ret != ASN1_MISSING_FIELD)
1176 0 : return ret;
1177 : }
1178 67068 : if (i >= A1_HEADER_LEN(choice) + 1 || !choice[i].tt) {
1179 0 : if (choice->tt == 0)
1180 0 : return ASN1_BAD_ID;
1181 :
1182 : /* This is the ellipsis case */
1183 0 : *element = 0;
1184 0 : ret = der_get_octet_string(p, len,
1185 0 : DPO(data, choice->tt), &datalen);
1186 0 : if (ret)
1187 0 : return ret;
1188 0 : p += datalen; len -= datalen;
1189 : }
1190 :
1191 67068 : break;
1192 : }
1193 0 : default:
1194 0 : ABORT_ON_ERROR();
1195 : return ASN1_PARSE_ERROR;
1196 : }
1197 58602946 : t++;
1198 58602946 : elements--;
1199 : }
1200 : /* if we are using padding, eat up read of context */
1201 36500119 : if (template_flags & A1_HF_ELLIPSIS)
1202 128070 : len = 0;
1203 :
1204 36500119 : oldlen -= len;
1205 :
1206 36500119 : if (size)
1207 36092971 : *size = oldlen;
1208 :
1209 : /*
1210 : * saved the raw bits if asked for it, useful for signature
1211 : * verification.
1212 : */
1213 36500119 : if (startp) {
1214 104073 : heim_octet_string *save = data;
1215 :
1216 104073 : save->data = malloc(oldlen);
1217 104073 : if (save->data == NULL)
1218 0 : return ENOMEM;
1219 : else {
1220 104073 : save->length = oldlen;
1221 104073 : memcpy(save->data, startp, oldlen);
1222 : }
1223 : }
1224 36500119 : return 0;
1225 : }
1226 :
1227 : /*
1228 : * This should be called with a `A1_TAG_T(ASN1_C_UNIV, PRIM, UT_Integer)'
1229 : * template as the `ttypeid'.
1230 : */
1231 : static int
1232 0 : typeid_int_copy(void *intp,
1233 : int64_t i,
1234 : const struct asn1_template *ttypeid)
1235 : {
1236 0 : const struct asn1_template *tint = ttypeid->ptr;
1237 :
1238 0 : if ((tint[1].tt & A1_OP_MASK) != A1_OP_PARSE)
1239 0 : return -1;
1240 0 : if (A1_PARSE_TYPE(tint[1].tt) != A1T_INTEGER)
1241 0 : return -1;
1242 0 : switch (tint[0].offset) {
1243 0 : case 8: *((int64_t *)intp) = i; return 0;
1244 0 : case 4: *((int32_t *)intp) = i; return 0;
1245 0 : default: memset(intp, 0, tint[0].offset); return 0;
1246 : }
1247 : }
1248 :
1249 : /* See commentary in _asn1_decode_open_type() */
1250 : static int
1251 0 : _asn1_encode_open_type(const struct asn1_template *t,
1252 : const void *data, /* NOTE: Not really const */
1253 : const struct asn1_template *ttypeid,
1254 : const struct asn1_template *topentype)
1255 : {
1256 0 : const struct asn1_template *ttypeid_univ = ttypeid;
1257 : const struct asn1_template *tactual_type;
1258 0 : const struct asn1_template *tos = t->ptr;
1259 : size_t sz, i;
1260 0 : unsigned int *lenp = NULL;
1261 0 : unsigned int len = 1;
1262 0 : int element = *(const int *)DPOC(data, t->offset);
1263 0 : int typeid_is_oid = 0;
1264 0 : int typeid_is_int = 0;
1265 0 : int enotsup = 0;
1266 0 : int ret = 0;
1267 :
1268 0 : if (element == 0 || element >= A1_HEADER_LEN(tos) + 1)
1269 0 : return 0;
1270 :
1271 0 : if (t->tt & A1_OS_OT_IS_ARRAY) {
1272 : /* The actual `len' is from the decoded open type field */
1273 0 : len = *(const unsigned int *)DPOC(data, t->offset + sizeof(element));
1274 :
1275 0 : if (!len)
1276 0 : return 0; /* The app may be encoding the open type by itself */
1277 : }
1278 :
1279 : /* Work out the type ID field's type */
1280 0 : while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
1281 0 : A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
1282 0 : ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
1283 0 : ttypeid_univ = ttypeid_univ->ptr;
1284 0 : ttypeid_univ++;
1285 : }
1286 0 : switch (ttypeid_univ->tt & A1_OP_MASK) {
1287 0 : case A1_OP_TAG:
1288 0 : if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV) {
1289 0 : enotsup = 1;
1290 0 : break;
1291 : }
1292 0 : switch (A1_TAG_TAG(ttypeid_univ->tt)) {
1293 0 : case UT_OID:
1294 0 : typeid_is_oid = 1;
1295 0 : break;
1296 0 : case UT_Integer: {
1297 0 : const struct asn1_template *tint = ttypeid_univ->ptr;
1298 :
1299 0 : tint++;
1300 0 : if ((tint->tt & A1_OP_MASK) != A1_OP_PARSE ||
1301 0 : A1_PARSE_TYPE(tint->tt) != A1T_INTEGER) {
1302 0 : enotsup = 1;
1303 0 : break;
1304 : }
1305 0 : typeid_is_int = 1;
1306 0 : break;
1307 : }
1308 0 : default: enotsup = 1; break;
1309 : }
1310 0 : break;
1311 0 : default: enotsup = 1; break;
1312 : }
1313 :
1314 : /*
1315 : * The app may not be aware of our automatic open type handling, so if the
1316 : * open type already appears to have been encoded, then ignore the decoded
1317 : * values.
1318 : */
1319 0 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
1320 0 : struct heim_base_data *os = DPO(data, topentype->offset);
1321 :
1322 0 : if (os->length && os->data)
1323 0 : return 0;
1324 : } else {
1325 0 : struct heim_base_data **os = DPO(data, topentype->offset + sizeof(len));
1326 :
1327 0 : while (sizeof(void *) != sizeof(unsigned int) &&
1328 0 : ((uintptr_t)os) % sizeof(void *) != 0)
1329 0 : os = (void *)(((char *)os) + sizeof(unsigned int));
1330 :
1331 0 : lenp = DPO(data, topentype->offset);
1332 0 : if (*lenp == len && os[0]->length && os[0]->data)
1333 0 : return 0;
1334 : }
1335 :
1336 0 : if (typeid_is_int) {
1337 : /*
1338 : * Copy the int from the type ID object field to the type ID struct
1339 : * field.
1340 : */
1341 0 : ret = typeid_int_copy(DPO(data, ttypeid->offset),
1342 0 : (intptr_t)tos[3 + (element-1)*3].ptr, ttypeid_univ);
1343 0 : } else if (typeid_is_oid) {
1344 : /*
1345 : * Copy the OID from the type ID object field to the type ID struct
1346 : * field.
1347 : */
1348 0 : ret = der_copy_oid(tos[3 + (element-1)*3].ptr, DPO(data, ttypeid->offset));
1349 : } else
1350 0 : enotsup = 1;
1351 :
1352 : /*
1353 : * If the app did not already encode the open type, we can't help it if we
1354 : * don't know what it is.
1355 : */
1356 0 : if (enotsup)
1357 0 : return ENOTSUP;
1358 :
1359 0 : tactual_type = &tos[(element-1)*3 + 4];
1360 :
1361 0 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
1362 0 : struct heim_base_data *os = DPO(data, topentype->offset);
1363 0 : const void * const *d = DPOC(data, t->offset + sizeof(element));
1364 :
1365 0 : while (sizeof(void *) != sizeof(element) &&
1366 0 : ((uintptr_t)d) % sizeof(void *) != 0) {
1367 0 : d = (void *)(((char *)d) + sizeof(element));
1368 : }
1369 :
1370 0 : os->length = _asn1_length(tactual_type->ptr, *d);
1371 0 : if ((os->data = malloc(os->length)) == NULL)
1372 0 : return ENOMEM;
1373 0 : ret = _asn1_encode(tactual_type->ptr, (os->length - 1) + (unsigned char *)os->data, os->length, *d, &sz);
1374 : } else {
1375 : struct heim_base_data *os;
1376 0 : const void * const *val =
1377 0 : DPOC(data, t->offset + sizeof(element) + sizeof(*lenp));
1378 :
1379 0 : if ((os = calloc(len, sizeof(*os))) == NULL)
1380 0 : return ENOMEM;
1381 :
1382 0 : *lenp = len;
1383 0 : for (i = 0; ret == 0 && i < len; i++) {
1384 0 : os[i].length = _asn1_length(tactual_type->ptr, val[i]);
1385 0 : if ((os[i].data = malloc(os[i].length)) == NULL)
1386 0 : ret = ENOMEM;
1387 0 : if (ret == 0)
1388 0 : ret = _asn1_encode(tactual_type->ptr, (os[i].length - 1) + (unsigned char *)os[i].data, os[i].length,
1389 0 : val[i], &sz);
1390 : }
1391 0 : if (ret) {
1392 0 : for (i = 0; i < (*lenp); i++)
1393 0 : free(os[i].data);
1394 0 : free(os);
1395 0 : *lenp = 0;
1396 0 : return ret;
1397 : }
1398 0 : *(struct heim_base_data **)DPO(data, topentype->offset + sizeof(len)) = os;
1399 : }
1400 0 : return ret;
1401 : }
1402 :
1403 : int
1404 39904233 : _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const void *data, size_t *size)
1405 : {
1406 39904233 : const struct asn1_template *tbase = t;
1407 39904233 : size_t elements = A1_HEADER_LEN(t);
1408 39904233 : int ret = 0;
1409 39904233 : size_t oldlen = len;
1410 :
1411 39904233 : t += A1_HEADER_LEN(t);
1412 :
1413 104228842 : while (elements) {
1414 64324609 : switch (t->tt & A1_OP_MASK) {
1415 0 : case A1_OP_OPENTYPE_OBJSET: {
1416 0 : size_t opentypeid = t->tt & ((1<<10)-1);
1417 0 : size_t opentype = (t->tt >> 10) & ((1<<10)-1);
1418 0 : ret = _asn1_encode_open_type(t, data,
1419 : template4member(tbase, opentypeid),
1420 : template4member(tbase, opentype));
1421 0 : if (ret)
1422 0 : return ret;
1423 0 : break;
1424 : }
1425 15668998 : case A1_OP_NAME: break;
1426 0 : case A1_OP_DEFVAL: break;
1427 0 : case A1_OP_TYPE_DECORATE_EXTERN: break;
1428 0 : case A1_OP_TYPE_DECORATE: break;
1429 9979655 : case A1_OP_TYPE:
1430 : case A1_OP_TYPE_EXTERN: {
1431 : size_t newsize;
1432 9979655 : const void *el = DPOC(data, t->offset);
1433 :
1434 9979655 : if (t->tt & A1_FLAG_OPTIONAL) {
1435 1386 : void **pel = (void **)el;
1436 1386 : if (*pel == NULL)
1437 9979655 : break;
1438 1001 : el = *pel;
1439 9978269 : } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
1440 0 : const struct asn1_template *tdefval = t - 1;
1441 : /* Compare tdefval to whatever's at `el' */
1442 0 : if (tdefval->tt & A1_DV_BOOLEAN) {
1443 0 : const int *i = (void *)(char *)el;
1444 :
1445 0 : if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
1446 : break;
1447 0 : } else if (tdefval->tt & A1_DV_INTEGER64) {
1448 0 : const int64_t *i = (void *)(char *)el;
1449 :
1450 0 : if (*i == (int64_t)(intptr_t)tdefval->ptr)
1451 0 : break;
1452 0 : } else if (tdefval->tt & A1_DV_INTEGER32) {
1453 0 : const int32_t *i = (void *)(char *)el;
1454 :
1455 0 : if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
1456 0 : (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
1457 0 : *i == (int32_t)(intptr_t)tdefval->ptr)
1458 0 : break;
1459 0 : } else if (tdefval->tt & A1_DV_INTEGER) {
1460 0 : const struct heim_integer *i = (void *)(char *)el;
1461 :
1462 0 : if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
1463 0 : break;
1464 0 : } else if (tdefval->tt & A1_DV_UTF8STRING) {
1465 0 : const char * const *s = el;
1466 :
1467 0 : if (*s && strcmp(*s, tdefval->ptr) == 0)
1468 0 : break;
1469 : } else {
1470 0 : abort();
1471 : }
1472 : }
1473 :
1474 9979270 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
1475 9976656 : ret = _asn1_encode(t->ptr, p, len, el, &newsize);
1476 : } else {
1477 2614 : const struct asn1_type_func *f = t->ptr;
1478 2614 : ret = (f->encode)(p, len, el, &newsize);
1479 : }
1480 :
1481 9979270 : if (ret)
1482 0 : return ret;
1483 9979270 : p -= newsize; len -= newsize;
1484 :
1485 9979270 : break;
1486 : }
1487 27468410 : case A1_OP_TAG: {
1488 27468410 : const void *olddata = data;
1489 27468410 : size_t l, datalen = 0;
1490 27468410 : int replace_tag = 0;
1491 :
1492 : /*
1493 : * XXX If this type (chasing t->ptr through IMPLICIT tags, if this
1494 : * one is too) till we find a non-TTag) is a [UNIVERSAL SET] type,
1495 : * then we have to sort [a copy of] its template by tag, then
1496 : * encode the SET using that sorted template. These SETs will
1497 : * generally be small, so when they are we might want to allocate
1498 : * the copy on the stack and insertion sort it. We'll need a
1499 : * utility function to do all of this.
1500 : */
1501 :
1502 27468410 : data = DPOC(data, t->offset);
1503 :
1504 27468410 : if (t->tt & A1_FLAG_OPTIONAL) {
1505 3055833 : void **el = (void **)data;
1506 3055833 : if (*el == NULL) {
1507 1325967 : data = olddata;
1508 27468410 : break;
1509 : }
1510 1729866 : data = *el;
1511 24412577 : } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
1512 0 : const struct asn1_template *tdefval = t - 1;
1513 0 : int exclude = 0;
1514 :
1515 : /* Compare tdefval to whatever's at `data' */
1516 0 : if (tdefval->tt & A1_DV_BOOLEAN) {
1517 0 : const int *i = (void *)(char *)data;
1518 :
1519 0 : if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
1520 0 : exclude = 1;
1521 0 : } else if (tdefval->tt & A1_DV_INTEGER64) {
1522 0 : const int64_t *i = (void *)(char *)data;
1523 :
1524 0 : if (*i == (int64_t)(intptr_t)tdefval->ptr)
1525 0 : exclude = 1;
1526 0 : } else if (tdefval->tt & A1_DV_INTEGER32) {
1527 0 : const int32_t *i = (void *)(char *)data;
1528 :
1529 0 : if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
1530 0 : (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
1531 0 : *i == (int32_t)(intptr_t)tdefval->ptr)
1532 0 : exclude = 1;
1533 0 : } else if (tdefval->tt & A1_DV_INTEGER) {
1534 0 : const struct heim_integer *i = (void *)(char *)data;
1535 :
1536 0 : if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
1537 0 : break;
1538 0 : } else if (tdefval->tt & A1_DV_UTF8STRING) {
1539 0 : const char * const *s = data;
1540 :
1541 0 : if (*s && strcmp(*s, tdefval->ptr) == 0)
1542 0 : exclude = 1;
1543 : } else {
1544 0 : abort();
1545 : }
1546 0 : if (exclude) {
1547 0 : data = olddata;
1548 0 : break;
1549 : }
1550 : }
1551 :
1552 26142443 : replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
1553 :
1554 : /* IMPLICIT tags need special handling (see gen_encode.c) */
1555 26142443 : if (replace_tag) {
1556 229 : unsigned char *pfree, *psave = p;
1557 : Der_class found_class;
1558 229 : Der_type found_type = 0;
1559 : unsigned int found_tag;
1560 229 : size_t lensave = len;
1561 229 : size_t oldtaglen = 0;
1562 229 : size_t taglen = der_length_tag(A1_TAG_TAG(t->tt));;
1563 :
1564 : /* Allocate a buffer at least as big as we need */
1565 229 : len = _asn1_length(t->ptr, data) + taglen;
1566 229 : if ((p = pfree = malloc(len)) == NULL) {
1567 0 : ret = ENOMEM;
1568 : } else {
1569 : /*
1570 : * Encode into it (with the wrong tag, which we'll replace
1571 : * below).
1572 : */
1573 229 : p += len - 1;
1574 229 : ret = _asn1_encode(t->ptr, p, len, data, &datalen);
1575 : }
1576 229 : if (ret == 0) {
1577 : /* Get the old tag and, critically, its length */
1578 229 : len -= datalen; p -= datalen;
1579 229 : ret = der_get_tag(p + 1, datalen, &found_class, &found_type,
1580 : &found_tag, &oldtaglen);
1581 : }
1582 229 : if (ret == 0) {
1583 : /* Drop the old tag */
1584 229 : len += oldtaglen; p += oldtaglen;
1585 : /* Put the new tag */
1586 229 : ret = der_put_tag(p, len,
1587 229 : A1_TAG_CLASS(t->tt),
1588 : found_type,
1589 229 : A1_TAG_TAG(t->tt), &l);
1590 : }
1591 229 : if (ret == 0) {
1592 : /* Copy the encoding where it belongs */
1593 229 : psave -= (datalen + l - oldtaglen);
1594 229 : lensave -= (datalen + l - oldtaglen);
1595 229 : memcpy(psave + 1, p + 1 - l, datalen + l - oldtaglen);
1596 229 : p = psave;
1597 229 : len = lensave;
1598 : }
1599 229 : free(pfree);
1600 : } else {
1601 : /* Easy case */
1602 26142214 : ret = _asn1_encode(t->ptr, p, len, data, &datalen);
1603 26142214 : if (ret)
1604 0 : return ret;
1605 :
1606 26142214 : len -= datalen; p -= datalen;
1607 :
1608 26142214 : ret = der_put_length_and_tag(p, len, datalen,
1609 26142214 : A1_TAG_CLASS(t->tt),
1610 26142214 : A1_TAG_TYPE(t->tt),
1611 26142214 : A1_TAG_TAG(t->tt), &l);
1612 26142214 : if (ret == 0) {
1613 26142214 : p -= l; len -= l;
1614 : }
1615 : }
1616 26142443 : if (ret)
1617 0 : return ret;
1618 :
1619 26142443 : data = olddata;
1620 :
1621 26142443 : break;
1622 : }
1623 9200028 : case A1_OP_PARSE: {
1624 9200028 : unsigned int type = A1_PARSE_TYPE(t->tt);
1625 : size_t newsize;
1626 9200028 : const void *el = DPOC(data, t->offset);
1627 :
1628 9200028 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
1629 0 : ABORT_ON_ERROR();
1630 0 : return ASN1_PARSE_ERROR;
1631 : }
1632 :
1633 9200028 : ret = (asn1_template_prim[type].encode)(p, len, el, &newsize);
1634 9200028 : if (ret)
1635 0 : return ret;
1636 9200028 : p -= newsize; len -= newsize;
1637 :
1638 9200028 : break;
1639 : }
1640 552 : case A1_OP_SETOF: {
1641 552 : const struct template_of *el = DPOC(data, t->offset);
1642 552 : size_t ellen = _asn1_sizeofType(t->ptr);
1643 : heim_octet_string *val;
1644 552 : unsigned char *elptr = el->val;
1645 : size_t i, totallen;
1646 :
1647 552 : if (el->len == 0)
1648 231 : break;
1649 :
1650 321 : if (el->len > UINT_MAX/sizeof(val[0]))
1651 0 : return ERANGE;
1652 :
1653 321 : val = calloc(el->len, sizeof(val[0]));
1654 321 : if (val == NULL)
1655 0 : return ENOMEM;
1656 :
1657 642 : for(totallen = 0, i = 0; i < el->len; i++) {
1658 : unsigned char *next;
1659 : size_t l;
1660 :
1661 321 : val[i].length = _asn1_length(t->ptr, elptr);
1662 321 : if (val[i].length) {
1663 321 : val[i].data = malloc(val[i].length);
1664 321 : if (val[i].data == NULL) {
1665 0 : ret = ENOMEM;
1666 0 : break;
1667 : }
1668 : }
1669 :
1670 321 : ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1),
1671 321 : val[i].length, elptr, &l);
1672 321 : if (ret)
1673 0 : break;
1674 :
1675 321 : next = elptr + ellen;
1676 321 : if (next < elptr) {
1677 0 : ret = ASN1_OVERFLOW;
1678 0 : break;
1679 : }
1680 321 : elptr = next;
1681 321 : totallen += val[i].length;
1682 : }
1683 321 : if (ret == 0 && totallen > len)
1684 0 : ret = ASN1_OVERFLOW;
1685 321 : if (ret) {
1686 0 : for (i = 0; i < el->len; i++)
1687 0 : free(val[i].data);
1688 0 : free(val);
1689 0 : return ret;
1690 : }
1691 :
1692 321 : len -= totallen;
1693 :
1694 321 : qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort);
1695 :
1696 321 : i = el->len - 1;
1697 : do {
1698 321 : p -= val[i].length;
1699 321 : memcpy(p + 1, val[i].data, val[i].length);
1700 321 : free(val[i].data);
1701 321 : } while(i-- > 0);
1702 321 : free(val);
1703 :
1704 321 : break;
1705 :
1706 : }
1707 1570314 : case A1_OP_SEQOF: {
1708 1570314 : struct template_of *el = DPO(data, t->offset);
1709 1570314 : size_t ellen = _asn1_sizeofType(t->ptr);
1710 : size_t newsize;
1711 : unsigned int i;
1712 1570314 : unsigned char *elptr = el->val;
1713 :
1714 1570314 : if (el->len == 0)
1715 1570314 : break;
1716 :
1717 1397945 : elptr += ellen * (el->len - 1);
1718 :
1719 4146003 : for (i = 0; i < el->len; i++) {
1720 2748058 : ret = _asn1_encode(t->ptr, p, len,
1721 : elptr,
1722 : &newsize);
1723 2748058 : if (ret)
1724 0 : return ret;
1725 2748058 : p -= newsize; len -= newsize;
1726 2748058 : elptr -= ellen;
1727 : }
1728 :
1729 1397945 : break;
1730 : }
1731 367968 : case A1_OP_BMEMBER: {
1732 367968 : const struct asn1_template *bmember = t->ptr;
1733 367968 : size_t bsize = bmember->offset;
1734 367968 : size_t belements = A1_HEADER_LEN(bmember);
1735 : size_t pos;
1736 367968 : unsigned char c = 0;
1737 367968 : unsigned int bitset = 0;
1738 367968 : int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
1739 :
1740 367968 : bmember += belements;
1741 :
1742 367968 : if (rfc1510)
1743 367968 : pos = 31;
1744 : else
1745 0 : pos = bmember->offset;
1746 :
1747 5488170 : while (belements && len) {
1748 6224106 : while (bmember->offset / 8 < pos / 8) {
1749 1103904 : if (rfc1510 || bitset || c) {
1750 1103904 : if (len < 1)
1751 0 : return ASN1_OVERFLOW;
1752 1103904 : *p-- = c; len--;
1753 : }
1754 1103904 : c = 0;
1755 1103904 : pos -= 8;
1756 : }
1757 5120202 : _asn1_bmember_put_bit(&c, data, bmember->offset, bsize, &bitset);
1758 5120202 : belements--; bmember--;
1759 : }
1760 367968 : if (rfc1510 || bitset) {
1761 367968 : if (len < 1)
1762 0 : return ASN1_OVERFLOW;
1763 367968 : *p-- = c; len--;
1764 : }
1765 :
1766 367968 : if (len < 1)
1767 0 : return ASN1_OVERFLOW;
1768 367968 : if (rfc1510 || bitset == 0)
1769 367968 : *p-- = 0;
1770 : else
1771 0 : *p-- = bitset - 1;
1772 :
1773 367968 : len--;
1774 :
1775 367968 : break;
1776 : }
1777 68684 : case A1_OP_CHOICE: {
1778 68684 : const struct asn1_template *choice = t->ptr;
1779 68684 : const unsigned int *element = DPOC(data, choice->offset);
1780 : size_t datalen;
1781 : const void *el;
1782 :
1783 68684 : if (*element > A1_HEADER_LEN(choice)) {
1784 0 : printf("element: %d\n", *element);
1785 0 : return ASN1_PARSE_ERROR;
1786 : }
1787 :
1788 68684 : if (*element == 0) {
1789 0 : ret += der_put_octet_string(p, len,
1790 0 : DPOC(data, choice->tt), &datalen);
1791 : } else {
1792 68684 : choice += *element;
1793 68684 : el = DPOC(data, choice->offset);
1794 68684 : ret = _asn1_encode(choice->ptr, p, len, el, &datalen);
1795 68684 : if (ret)
1796 0 : return ret;
1797 : }
1798 68684 : len -= datalen; p -= datalen;
1799 :
1800 68684 : break;
1801 : }
1802 0 : default:
1803 0 : ABORT_ON_ERROR();
1804 : }
1805 64324609 : t--;
1806 64324609 : elements--;
1807 : }
1808 39904233 : if (size)
1809 39904233 : *size = oldlen - len;
1810 :
1811 39904233 : return 0;
1812 : }
1813 :
1814 : static size_t
1815 0 : _asn1_length_open_type_helper(const struct asn1_template *t,
1816 : size_t sz)
1817 : {
1818 0 : const struct asn1_template *tinner = t->ptr;
1819 :
1820 0 : switch (t->tt & A1_OP_MASK) {
1821 0 : case A1_OP_TAG:
1822 : /* XXX Not tail-recursive :( */
1823 0 : sz = _asn1_length_open_type_helper(tinner, sz);
1824 0 : sz += der_length_len(sz);
1825 0 : sz += der_length_tag(A1_TAG_TAG(t->tt));
1826 0 : return sz;
1827 0 : default:
1828 0 : return sz;
1829 : }
1830 : }
1831 :
1832 : static size_t
1833 0 : _asn1_length_open_type_id(const struct asn1_template *t,
1834 : const void *data)
1835 : {
1836 0 : struct asn1_template pretend[2] = {
1837 : { 0, 0, ((void*)(uintptr_t)1) },
1838 : };
1839 0 : pretend[1] = *t;
1840 0 : while ((t->tt & A1_OP_MASK) == A1_OP_TAG)
1841 0 : t = t->ptr;
1842 0 : pretend[0].offset = t->offset;
1843 0 : return _asn1_length(pretend, data);
1844 : }
1845 :
1846 : /* See commentary in _asn1_encode_open_type() */
1847 : static size_t
1848 0 : _asn1_length_open_type(const struct asn1_template *tbase,
1849 : const struct asn1_template *t,
1850 : const void *data,
1851 : const struct asn1_template *ttypeid,
1852 : const struct asn1_template *topentype)
1853 : {
1854 0 : const struct asn1_template *ttypeid_univ = ttypeid;
1855 : const struct asn1_template *tactual_type;
1856 0 : const struct asn1_template *tos = t->ptr;
1857 0 : const unsigned int *lenp = NULL;
1858 0 : unsigned int len = 1;
1859 0 : size_t sz = 0;
1860 : size_t i;
1861 0 : int element = *(const int *)DPOC(data, t->offset);
1862 0 : int typeid_is_oid = 0;
1863 0 : int typeid_is_int = 0;
1864 :
1865 : /* If nothing to encode, we add nothing to the length */
1866 0 : if (element == 0 || element >= A1_HEADER_LEN(tos) + 1)
1867 0 : return 0;
1868 0 : if (t->tt & A1_OS_OT_IS_ARRAY) {
1869 0 : len = *(const unsigned int *)DPOC(data, t->offset + sizeof(element));
1870 0 : if (!len)
1871 0 : return 0;
1872 : }
1873 :
1874 : /* Work out the type ID field's type */
1875 0 : while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
1876 0 : A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
1877 0 : ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
1878 0 : ttypeid_univ = ttypeid_univ->ptr;
1879 0 : ttypeid_univ++;
1880 : }
1881 0 : switch (ttypeid_univ->tt & A1_OP_MASK) {
1882 0 : case A1_OP_TAG:
1883 0 : if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV)
1884 0 : return 0;
1885 0 : switch (A1_TAG_TAG(ttypeid_univ->tt)) {
1886 0 : case UT_OID:
1887 0 : typeid_is_oid = 1;
1888 0 : break;
1889 0 : case UT_Integer: {
1890 0 : const struct asn1_template *tint = ttypeid_univ->ptr;
1891 :
1892 0 : tint++;
1893 0 : if ((tint->tt & A1_OP_MASK) != A1_OP_PARSE ||
1894 0 : A1_PARSE_TYPE(tint->tt) != A1T_INTEGER)
1895 0 : return 0;
1896 0 : typeid_is_int = 1;
1897 0 : break;
1898 : }
1899 0 : default: return 0;
1900 : }
1901 0 : break;
1902 0 : default: return 0;
1903 : }
1904 0 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
1905 0 : struct heim_base_data *os = DPO(data, topentype->offset);
1906 :
1907 0 : if (os->length && os->data)
1908 0 : return 0;
1909 : } else {
1910 0 : struct heim_base_data **os = DPO(data, topentype->offset + sizeof(len));
1911 :
1912 0 : while (sizeof(void *) != sizeof(unsigned int) &&
1913 0 : ((uintptr_t)os) % sizeof(void *) != 0)
1914 0 : os = (void *)(((char *)os) + sizeof(unsigned int));
1915 :
1916 0 : lenp = DPOC(data, topentype->offset);
1917 0 : if (*lenp == len && os[0]->length && os[0]->data)
1918 0 : return 0;
1919 : }
1920 :
1921 : /* Compute the size of the type ID field */
1922 0 : if (typeid_is_int) {
1923 : int64_t i8;
1924 : int32_t i4;
1925 :
1926 0 : switch (ttypeid_univ->offset) {
1927 0 : case 8:
1928 0 : i8 = (intptr_t)t->ptr;
1929 0 : sz = _asn1_length_open_type_id(ttypeid, &i8);
1930 0 : i8 = 0;
1931 0 : sz -= _asn1_length_open_type_id(ttypeid, &i8);
1932 0 : break;
1933 0 : case 4:
1934 0 : i4 = (intptr_t)t->ptr;
1935 0 : sz = _asn1_length_open_type_id(ttypeid, &i4);
1936 0 : i4 = 0;
1937 0 : sz -= _asn1_length_open_type_id(ttypeid, &i8);
1938 0 : break;
1939 0 : default:
1940 0 : return 0;
1941 : }
1942 0 : } else if (typeid_is_oid) {
1943 0 : heim_oid no_oid = { 0, 0 };
1944 :
1945 0 : sz = _asn1_length_open_type_id(ttypeid, tos[3 + (element - 1)*3].ptr);
1946 0 : sz -= _asn1_length_open_type_id(ttypeid, &no_oid);
1947 : }
1948 :
1949 0 : tactual_type = &tos[(element-1)*3 + 4];
1950 :
1951 : /* Compute the size of the encoded value(s) */
1952 0 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
1953 0 : const void * const *d = DPOC(data, t->offset + sizeof(element));
1954 :
1955 0 : while (sizeof(void *) != sizeof(element) &&
1956 0 : ((uintptr_t)d) % sizeof(void *) != 0)
1957 0 : d = (void *)(((char *)d) + sizeof(element));
1958 0 : if (*d)
1959 0 : sz += _asn1_length(tactual_type->ptr, *d);
1960 : } else {
1961 : size_t bodysz;
1962 0 : const void * const * val =
1963 0 : DPOC(data, t->offset + sizeof(element) + sizeof(*lenp));
1964 :
1965 : /* Compute the size of the encoded SET OF / SEQUENCE OF body */
1966 0 : for (i = 0, bodysz = 0; i < len; i++) {
1967 0 : if (val[i])
1968 0 : bodysz += _asn1_length(tactual_type->ptr, val[i]);
1969 : }
1970 :
1971 : /*
1972 : * We now know the size of the body of the SET OF or SEQUENCE OF. Now
1973 : * we just need to count the length of all the TLs on the outside.
1974 : */
1975 0 : sz += _asn1_length_open_type_helper(topentype, bodysz);
1976 : }
1977 0 : return sz;
1978 : }
1979 :
1980 : size_t
1981 39907336 : _asn1_length(const struct asn1_template *t, const void *data)
1982 : {
1983 39907336 : const struct asn1_template *tbase = t;
1984 39907336 : size_t elements = A1_HEADER_LEN(t);
1985 39907336 : size_t ret = 0;
1986 :
1987 39907336 : t += A1_HEADER_LEN(t);
1988 :
1989 104236332 : while (elements) {
1990 64328996 : switch (t->tt & A1_OP_MASK) {
1991 0 : case A1_OP_OPENTYPE_OBJSET: {
1992 0 : size_t opentypeid = t->tt & ((1<<10)-1);
1993 0 : size_t opentype = (t->tt >> 10) & ((1<<10)-1);
1994 0 : ret += _asn1_length_open_type(tbase, t, data,
1995 : template4member(tbase, opentypeid),
1996 : template4member(tbase, opentype));
1997 0 : break;
1998 : }
1999 15669961 : case A1_OP_NAME: break;
2000 0 : case A1_OP_DEFVAL: break;
2001 0 : case A1_OP_TYPE_DECORATE_EXTERN: break;
2002 0 : case A1_OP_TYPE_DECORATE: break;
2003 9980695 : case A1_OP_TYPE:
2004 : case A1_OP_TYPE_EXTERN: {
2005 9980695 : const void *el = DPOC(data, t->offset);
2006 :
2007 9980695 : if (t->tt & A1_FLAG_OPTIONAL) {
2008 1386 : void **pel = (void **)el;
2009 1386 : if (*pel == NULL)
2010 385 : break;
2011 1001 : el = *pel;
2012 9979309 : } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
2013 0 : const struct asn1_template *tdefval = t - 1;
2014 :
2015 : /* Compare tdefval to whatever's at `el' */
2016 0 : if (tdefval->tt & A1_DV_BOOLEAN) {
2017 0 : const int *i = (void *)(char *)el;
2018 :
2019 0 : if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
2020 : break;
2021 0 : } else if (tdefval->tt & A1_DV_INTEGER64) {
2022 0 : const int64_t *i = (void *)(char *)el;
2023 :
2024 0 : if (*i == (int64_t)(intptr_t)tdefval->ptr)
2025 0 : break;
2026 0 : } else if (tdefval->tt & A1_DV_INTEGER32) {
2027 0 : const int32_t *i = (void *)(char *)el;
2028 :
2029 0 : if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
2030 0 : (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
2031 0 : *i == (int32_t)(intptr_t)tdefval->ptr)
2032 0 : break;
2033 0 : } else if (tdefval->tt & A1_DV_INTEGER) {
2034 0 : const struct heim_integer *i = (void *)(char *)el;
2035 :
2036 0 : if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
2037 0 : break;
2038 0 : } else if (tdefval->tt & A1_DV_UTF8STRING) {
2039 0 : const char * const *s = el;
2040 :
2041 0 : if (*s && strcmp(*s, tdefval->ptr) == 0)
2042 0 : break;
2043 : } else {
2044 0 : abort();
2045 : }
2046 : }
2047 :
2048 9980310 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
2049 9977696 : ret += _asn1_length(t->ptr, el);
2050 : } else {
2051 2614 : const struct asn1_type_func *f = t->ptr;
2052 2614 : ret += (f->length)(el);
2053 : }
2054 9980310 : break;
2055 : }
2056 27469602 : case A1_OP_TAG: {
2057 : size_t datalen;
2058 27469602 : const void *olddata = data;
2059 27469602 : size_t oldtaglen = 0;
2060 :
2061 27469602 : data = DPO(data, t->offset);
2062 :
2063 27469602 : if (t->tt & A1_FLAG_OPTIONAL) {
2064 3055833 : void **el = (void **)data;
2065 3055833 : if (*el == NULL) {
2066 1325967 : data = olddata;
2067 1325967 : break;
2068 : }
2069 1729866 : data = *el;
2070 24413769 : } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
2071 0 : const struct asn1_template *tdefval = t - 1;
2072 0 : int exclude = 0;
2073 :
2074 : /* Compare tdefval to whatever's at `data' */
2075 0 : if (tdefval->tt & A1_DV_BOOLEAN) {
2076 0 : const int *i = (void *)(char *)data;
2077 :
2078 0 : if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
2079 0 : exclude = 1;
2080 0 : } else if (tdefval->tt & A1_DV_INTEGER64) {
2081 0 : const int64_t *i = (void *)(char *)data;
2082 :
2083 0 : if (*i == (int64_t)(intptr_t)tdefval->ptr)
2084 0 : exclude = 1;
2085 0 : } else if (tdefval->tt & A1_DV_INTEGER32) {
2086 0 : const int32_t *i = (void *)(char *)data;
2087 :
2088 0 : if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
2089 0 : (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
2090 0 : *i == (int32_t)(intptr_t)tdefval->ptr)
2091 0 : exclude = 1;
2092 0 : } else if (tdefval->tt & A1_DV_INTEGER) {
2093 0 : const struct heim_integer *i = (void *)(char *)data;
2094 :
2095 0 : if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
2096 0 : exclude = 1;
2097 0 : } else if (tdefval->tt & A1_DV_UTF8STRING) {
2098 0 : const char * const *s = data;
2099 :
2100 0 : if (*s && strcmp(*s, tdefval->ptr) == 0)
2101 0 : exclude = 1;
2102 : } else {
2103 0 : abort();
2104 : }
2105 0 : if (exclude) {
2106 0 : data = olddata;
2107 0 : break;
2108 : }
2109 : }
2110 :
2111 26143635 : if (t->tt & A1_FLAG_IMPLICIT)
2112 229 : oldtaglen = inner_type_taglen(t->ptr);
2113 :
2114 26143635 : datalen = _asn1_length(t->ptr, data);
2115 26143635 : ret += datalen;
2116 26143635 : ret += der_length_tag(A1_TAG_TAG(t->tt));
2117 26143635 : ret += oldtaglen ? -oldtaglen : der_length_len(datalen);
2118 26143635 : data = olddata;
2119 26143635 : break;
2120 : }
2121 9200822 : case A1_OP_PARSE: {
2122 9200822 : unsigned int type = A1_PARSE_TYPE(t->tt);
2123 9200822 : const void *el = DPOC(data, t->offset);
2124 :
2125 9200822 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2126 0 : ABORT_ON_ERROR();
2127 : break;
2128 : }
2129 9200822 : ret += (asn1_template_prim[type].length)(el);
2130 9200822 : break;
2131 : }
2132 1570943 : case A1_OP_SETOF:
2133 : case A1_OP_SEQOF: {
2134 1570943 : const struct template_of *el = DPOC(data, t->offset);
2135 1570943 : size_t ellen = _asn1_sizeofType(t->ptr);
2136 1570943 : const unsigned char *element = el->val;
2137 : unsigned int i;
2138 :
2139 4319322 : for (i = 0; i < el->len; i++) {
2140 2748379 : ret += _asn1_length(t->ptr, element);
2141 2748379 : element += ellen;
2142 : }
2143 :
2144 1570943 : break;
2145 : }
2146 367968 : case A1_OP_BMEMBER: {
2147 367968 : const struct asn1_template *bmember = t->ptr;
2148 367968 : size_t size = bmember->offset;
2149 367968 : size_t belements = A1_HEADER_LEN(bmember);
2150 367968 : int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
2151 :
2152 367968 : if (rfc1510) {
2153 367968 : ret += 5;
2154 : } else {
2155 :
2156 0 : ret += 1;
2157 :
2158 0 : bmember += belements;
2159 :
2160 0 : while (belements) {
2161 0 : if (_asn1_bmember_isset_bit(data, bmember->offset, size)) {
2162 0 : ret += (bmember->offset / 8) + 1;
2163 0 : break;
2164 : }
2165 0 : belements--; bmember--;
2166 : }
2167 : }
2168 367968 : break;
2169 : }
2170 69005 : case A1_OP_CHOICE: {
2171 69005 : const struct asn1_template *choice = t->ptr;
2172 69005 : const unsigned int *element = DPOC(data, choice->offset);
2173 :
2174 69005 : if (*element > A1_HEADER_LEN(choice))
2175 0 : break;
2176 :
2177 69005 : if (*element == 0) {
2178 0 : ret += der_length_octet_string(DPOC(data, choice->tt));
2179 : } else {
2180 69005 : choice += *element;
2181 69005 : ret += _asn1_length(choice->ptr, DPOC(data, choice->offset));
2182 : }
2183 69005 : break;
2184 : }
2185 0 : default:
2186 0 : ABORT_ON_ERROR();
2187 : break;
2188 : }
2189 64328996 : elements--;
2190 64328996 : t--;
2191 : }
2192 39907336 : return ret;
2193 : }
2194 :
2195 : /* See commentary in _asn1_decode_open_type() */
2196 : static void
2197 1750 : _asn1_free_open_type(const struct asn1_template *t, /* object set template */
2198 : void *data)
2199 : {
2200 : const struct asn1_template *tactual_type;
2201 1750 : const struct asn1_template *tos = t->ptr;
2202 1750 : unsigned int *lenp = NULL; /* Pointer to array length field */
2203 1750 : unsigned int len = 1; /* Array length */
2204 : size_t i;
2205 : void **dp;
2206 : void **val;
2207 1750 : int *elementp = DPO(data, t->offset); /* Choice enum pointer */
2208 :
2209 : /* XXX We assume sizeof(enum) == sizeof(int) */
2210 1750 : if (!*elementp || *elementp >= A1_HEADER_LEN(tos) + 1)
2211 538 : return; /* Unknown choice -> it's not decoded, nothing to free here */
2212 1212 : tactual_type = tos[3*(*elementp - 1) + 4].ptr;
2213 :
2214 1212 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
2215 1212 : dp = DPO(data, t->offset + sizeof(*elementp));
2216 1212 : while (sizeof(void *) != sizeof(*elementp) &&
2217 2424 : ((uintptr_t)dp) % sizeof(void *) != 0)
2218 1212 : dp = (void *)(((char *)dp) + sizeof(*elementp));
2219 1212 : if (*dp) {
2220 1212 : _asn1_free(tactual_type, *dp);
2221 1212 : free(*dp);
2222 1212 : *dp = NULL;
2223 : }
2224 1212 : return;
2225 : }
2226 :
2227 0 : lenp = DPO(data, t->offset + sizeof(*elementp));
2228 0 : len = *lenp;
2229 0 : dp = DPO(data, t->offset + sizeof(*elementp) + sizeof(*lenp));
2230 0 : while (sizeof(void *) != sizeof(*elementp) &&
2231 0 : ((uintptr_t)dp) % sizeof(void *) != 0)
2232 0 : dp = (void *)(((char *)dp) + sizeof(*elementp));
2233 0 : val = *dp;
2234 :
2235 0 : for (i = 0; i < len; i++) {
2236 0 : if (val[i]) {
2237 0 : _asn1_free(tactual_type, val[i]);
2238 0 : free(val[i]);
2239 : }
2240 : }
2241 0 : free(val);
2242 0 : *lenp = 0;
2243 0 : *dp = NULL;
2244 : }
2245 :
2246 : void
2247 261415231 : _asn1_free(const struct asn1_template *t, void *data)
2248 : {
2249 261415231 : size_t elements = A1_HEADER_LEN(t);
2250 :
2251 261415231 : if (t->tt & A1_HF_PRESERVE)
2252 279245 : der_free_octet_string(data);
2253 :
2254 261415231 : t++;
2255 :
2256 690636394 : while (elements) {
2257 429221163 : switch (t->tt & A1_OP_MASK) {
2258 1750 : case A1_OP_OPENTYPE_OBJSET: {
2259 1750 : _asn1_free_open_type(t, data);
2260 1750 : break;
2261 : }
2262 106463724 : case A1_OP_NAME: break;
2263 1638 : case A1_OP_DEFVAL: break;
2264 63475320 : case A1_OP_TYPE_DECORATE_EXTERN:
2265 : case A1_OP_TYPE_DECORATE:
2266 : case A1_OP_TYPE:
2267 : case A1_OP_TYPE_EXTERN: {
2268 63475320 : void *el = DPO(data, t->offset);
2269 63475320 : void **pel = (void **)el;
2270 :
2271 63475320 : if (t->tt & A1_FLAG_OPTIONAL) {
2272 4637223 : if (*pel == NULL)
2273 3529674 : break;
2274 1107549 : el = *pel;
2275 : }
2276 :
2277 59945646 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE || (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2278 58836146 : _asn1_free(t->ptr, el);
2279 1109500 : } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) {
2280 3630 : const struct asn1_type_func *f = t->ptr;
2281 3630 : (f->release)(el);
2282 : } else {
2283 : /* A1_OP_TYPE_DECORATE_EXTERN */
2284 1105870 : const struct asn1_type_func *f = t->ptr;
2285 :
2286 1105870 : if (f && f->release)
2287 0 : (f->release)(el);
2288 1105870 : else if (f)
2289 1105870 : memset(el, 0, f->size);
2290 : }
2291 59945646 : if (t->tt & A1_FLAG_OPTIONAL) {
2292 1107549 : free(el);
2293 1107549 : *pel = NULL;
2294 : }
2295 :
2296 59945646 : break;
2297 : }
2298 58082562 : case A1_OP_PARSE: {
2299 58082562 : unsigned int type = A1_PARSE_TYPE(t->tt);
2300 58082562 : void *el = DPO(data, t->offset);
2301 :
2302 58082562 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2303 0 : ABORT_ON_ERROR();
2304 : break;
2305 : }
2306 58082562 : (asn1_template_prim[type].release)(el);
2307 58082562 : break;
2308 : }
2309 183774850 : case A1_OP_TAG: {
2310 183774850 : void *el = DPO(data, t->offset);
2311 :
2312 183774850 : if (t->tt & A1_FLAG_OPTIONAL) {
2313 17837685 : void **pel = (void **)el;
2314 :
2315 17837685 : if (*pel == NULL)
2316 10133424 : break;
2317 7704261 : _asn1_free(t->ptr, *pel);
2318 7704261 : free(*pel);
2319 7704261 : *pel = NULL;
2320 : } else {
2321 165937165 : _asn1_free(t->ptr, el);
2322 : }
2323 :
2324 173641426 : break;
2325 : }
2326 14229785 : case A1_OP_SETOF:
2327 : case A1_OP_SEQOF: {
2328 14229785 : struct template_of *el = DPO(data, t->offset);
2329 14229785 : size_t ellen = _asn1_sizeofType(t->ptr);
2330 14229785 : unsigned char *element = el->val;
2331 : unsigned int i;
2332 :
2333 29862306 : for (i = 0; i < el->len; i++) {
2334 15632521 : _asn1_free(t->ptr, element);
2335 15632521 : element += ellen;
2336 : }
2337 14229785 : free(el->val);
2338 14229785 : el->val = NULL;
2339 14229785 : el->len = 0;
2340 :
2341 14229785 : break;
2342 : }
2343 1947982 : case A1_OP_BMEMBER:
2344 1947982 : break;
2345 1243552 : case A1_OP_CHOICE: {
2346 1243552 : const struct asn1_template *choice = t->ptr;
2347 1243552 : const unsigned int *element = DPOC(data, choice->offset);
2348 :
2349 1243552 : if (*element > A1_HEADER_LEN(choice))
2350 0 : break;
2351 :
2352 1243552 : if (*element == 0) {
2353 100 : der_free_octet_string(DPO(data, choice->tt));
2354 : } else {
2355 1243452 : choice += *element;
2356 1243452 : _asn1_free(choice->ptr, DPO(data, choice->offset));
2357 : }
2358 1243552 : break;
2359 : }
2360 0 : default:
2361 0 : ABORT_ON_ERROR();
2362 : break;
2363 : }
2364 429221163 : t++;
2365 429221163 : elements--;
2366 : }
2367 261415231 : }
2368 :
2369 : static char *
2370 0 : getindent(int flags, unsigned int i)
2371 : {
2372 : char *s;
2373 :
2374 0 : if (!(flags & ASN1_PRINT_INDENT) || i == 0)
2375 0 : return NULL;
2376 0 : if (i > 128)
2377 0 : i = 128;
2378 0 : if ((s = malloc(i * 2 + 2)) == NULL)
2379 0 : return NULL;
2380 0 : s[0] = '\n';
2381 0 : s[i * 2 + 1] = '\0';
2382 0 : memset(s + 1, ' ', i * 2);
2383 0 : return s;
2384 : }
2385 :
2386 : static struct rk_strpool *_asn1_print(const struct asn1_template *,
2387 : struct rk_strpool *,
2388 : int,
2389 : unsigned int,
2390 : const void *,
2391 : const heim_octet_string *);
2392 :
2393 : /* See commentary in _asn1_decode_open_type() */
2394 : static struct rk_strpool *
2395 0 : _asn1_print_open_type(const struct asn1_template *t, /* object set template */
2396 : struct rk_strpool *r,
2397 : int flags,
2398 : unsigned int indent,
2399 : const void *data,
2400 : const char *opentype_name)
2401 : {
2402 : const struct asn1_template *tactual_type;
2403 0 : const struct asn1_template *tos = t->ptr;
2404 0 : const unsigned int *lenp = NULL; /* Pointer to array length field */
2405 0 : unsigned int len = 1; /* Array length */
2406 : size_t i;
2407 : const void * const *dp;
2408 : const void * const *val;
2409 0 : const int *elementp = DPOC(data, t->offset); /* Choice enum pointer */
2410 0 : char *indents = getindent(flags, indent);
2411 :
2412 : /* XXX We assume sizeof(enum) == sizeof(int) */
2413 0 : if (!*elementp || *elementp >= A1_HEADER_LEN(tos) + 1) {
2414 0 : r = rk_strpoolprintf(r, ",%s\"_%s_choice\":\"_ERROR_DECODING_\"",
2415 : indents ? indents : "", opentype_name);
2416 0 : free(indents);
2417 0 : return r;
2418 : }
2419 0 : tactual_type = tos[3*(*elementp - 1) + 4].ptr;
2420 :
2421 0 : r = rk_strpoolprintf(r, ",%s\"_%s_choice\":\"%s\"",
2422 : indents ? indents : "", opentype_name,
2423 0 : (const char *)tos[3*(*elementp - 1) + 2].ptr);
2424 0 : if (!r) {
2425 0 : free(indents);
2426 0 : return r;
2427 : }
2428 :
2429 0 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
2430 0 : dp = DPOC(data, t->offset + sizeof(*elementp));
2431 0 : while (sizeof(void *) != sizeof(*elementp) &&
2432 0 : ((uintptr_t)dp) % sizeof(void *) != 0)
2433 0 : dp = (void *)(((char *)dp) + sizeof(*elementp));
2434 0 : if (*dp) {
2435 0 : struct rk_strpool *r2 = NULL;
2436 0 : char *s = NULL;
2437 :
2438 0 : r2 = _asn1_print(tactual_type, r2, flags, indent + 1, *dp, NULL);
2439 0 : if (r2 == NULL) {
2440 0 : r = rk_strpoolprintf(r, ",%s\"_%s\":\"_ERROR_FORMATTING_\"",
2441 : indents ? indents : "", opentype_name);
2442 0 : free(indents);
2443 0 : return r;
2444 : }
2445 0 : s = rk_strpoolcollect(r2);
2446 0 : if (s)
2447 0 : r = rk_strpoolprintf(r, ",%s\"_%s\":%s",
2448 : indents ? indents : "", opentype_name, s);
2449 0 : free(s);
2450 : }
2451 0 : free(indents);
2452 0 : return r;
2453 : }
2454 :
2455 0 : lenp = DPOC(data, t->offset + sizeof(*elementp));
2456 0 : len = *lenp;
2457 0 : dp = DPOC(data, t->offset + sizeof(*elementp) + sizeof(*lenp));
2458 0 : while (sizeof(void *) != sizeof(*elementp) &&
2459 0 : ((uintptr_t)dp) % sizeof(void *) != 0)
2460 0 : dp = (void *)(((char *)dp) + sizeof(*elementp));
2461 0 : val = *dp;
2462 :
2463 0 : r = rk_strpoolprintf(r, ",%s\"_%s\":[", indents ? indents : "",
2464 : opentype_name);
2465 0 : free(indents);
2466 0 : indents = getindent(flags, indent + 1);
2467 0 : r = rk_strpoolprintf(r, "%s", indents ? indents : "");
2468 0 : for (i = 0; r && i < len; i++) {
2469 0 : struct rk_strpool *r2 = NULL;
2470 0 : char *s = NULL;;
2471 :
2472 0 : if (val[i]) {
2473 0 : r2 = _asn1_print(tactual_type, r2, flags, indent + 2, val[i], NULL);
2474 0 : if (r2 == NULL) {
2475 0 : rk_strpoolfree(r);
2476 0 : free(indents);
2477 0 : return NULL;
2478 : }
2479 : }
2480 0 : if (i)
2481 0 : r = rk_strpoolprintf(r, ",%s", indents ? indents : "");
2482 0 : if (r)
2483 0 : r = rk_strpoolprintf(r, "%s", (s = rk_strpoolcollect(r2)));
2484 0 : free(s);
2485 : }
2486 0 : free(indents);
2487 0 : return rk_strpoolprintf(r, "]");
2488 : }
2489 :
2490 : static struct rk_strpool *
2491 0 : _asn1_print(const struct asn1_template *t,
2492 : struct rk_strpool *r,
2493 : int flags,
2494 : unsigned int indent,
2495 : const void *data,
2496 : const heim_octet_string *saved)
2497 : {
2498 0 : const struct asn1_template *tbase = t;
2499 : const struct asn1_template *tnames;
2500 0 : size_t nelements = A1_HEADER_LEN(t);
2501 0 : size_t elements = nelements;
2502 0 : size_t nnames = 0;
2503 0 : char *indents = getindent(flags, indent);
2504 :
2505 0 : for (t += nelements; t > tbase && (t->tt & A1_OP_MASK) == A1_OP_NAME; t--)
2506 0 : nnames++;
2507 :
2508 0 : tnames = tbase + nelements - nnames + 1;
2509 :
2510 0 : if (!r)
2511 0 : r = rk_strpoolprintf(r, "%s", "");
2512 :
2513 0 : if (nnames)
2514 0 : r = rk_strpoolprintf(r, "%s{\"_type\":\"%s\"",
2515 : indents ? indents : "",
2516 0 : (const char *)(tnames++)->ptr);
2517 0 : if (saved && r) {
2518 0 : char *s = der_print_octet_string(data, 0);
2519 :
2520 0 : if (!s) {
2521 0 : rk_strpoolfree(r);
2522 0 : free(indents);
2523 0 : return NULL;
2524 : }
2525 0 : r = rk_strpoolprintf(r, ",%s\"_save\":\"%s\"",
2526 : indents ? indents : "", s);
2527 0 : free(s);
2528 : }
2529 0 : saved = NULL;
2530 0 : if (tbase->tt & A1_HF_PRESERVE)
2531 0 : saved = data;
2532 :
2533 0 : t = tbase + 1;
2534 0 : while (r && elements && (t->tt & A1_OP_MASK) != A1_OP_NAME) {
2535 0 : switch (t->tt & A1_OP_MASK) {
2536 0 : case A1_OP_NAME:
2537 0 : continue;
2538 0 : case A1_OP_DEFVAL:
2539 0 : t++;
2540 0 : elements--;
2541 0 : continue;
2542 0 : case A1_OP_OPENTYPE_OBJSET: {
2543 0 : size_t opentype = (t->tt >> 10) & ((1<<10)-1);
2544 0 : r = _asn1_print_open_type(t, r, flags, indent + 1, data,
2545 0 : tbase[(nelements - nnames) + 2 + opentype].ptr);
2546 0 : t++;
2547 0 : elements--;
2548 0 : continue;
2549 : }
2550 0 : default: break;
2551 : }
2552 0 : if (nnames &&
2553 0 : (t->tt & A1_OP_MASK) != A1_OP_TYPE_DECORATE_EXTERN &&
2554 0 : (t->tt & A1_OP_MASK) != A1_OP_TYPE_DECORATE)
2555 0 : r = rk_strpoolprintf(r, ",%s\"%s\":",
2556 : indents ? indents : "",
2557 0 : (const char *)(tnames++)->ptr);
2558 0 : switch (t->tt & A1_OP_MASK) {
2559 0 : case A1_OP_OPENTYPE_OBJSET:
2560 0 : break;
2561 0 : case A1_OP_NAME: break;
2562 0 : case A1_OP_DEFVAL: break;
2563 0 : case A1_OP_TYPE_DECORATE_EXTERN: break;
2564 0 : case A1_OP_TYPE_DECORATE: break; /* We could probably print this though */
2565 0 : case A1_OP_TYPE:
2566 : case A1_OP_TYPE_EXTERN: {
2567 0 : const void *el = DPOC(data, t->offset);
2568 :
2569 0 : if (t->tt & A1_FLAG_OPTIONAL) {
2570 0 : const void * const *pel = (const void *const *)el;
2571 0 : if (*pel == NULL) {
2572 0 : r = rk_strpoolprintf(r, "null");
2573 0 : break;
2574 : }
2575 0 : el = *pel;
2576 : }
2577 :
2578 0 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
2579 0 : r = _asn1_print(t->ptr, r, flags, indent + 1, el, saved);
2580 : } else {
2581 0 : const struct asn1_type_func *f = t->ptr;
2582 0 : char *s = NULL;
2583 :
2584 0 : s = (f->print)(el, 0);
2585 0 : if (s == NULL) {
2586 0 : rk_strpoolfree(r);
2587 0 : free(indents);
2588 0 : return NULL;
2589 : }
2590 0 : r = rk_strpoolprintf(r, "%s", s);
2591 0 : free(s);
2592 : }
2593 0 : break;
2594 : }
2595 0 : case A1_OP_PARSE: {
2596 0 : unsigned int type = A1_PARSE_TYPE(t->tt);
2597 0 : const void *el = DPOC(data, t->offset);
2598 0 : char *s = NULL;
2599 :
2600 0 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2601 0 : ABORT_ON_ERROR();
2602 : break;
2603 : }
2604 :
2605 0 : if (type == A1T_IMEMBER && t->ptr) {
2606 : /* Enumeration. Use the symbolic name of this value */
2607 0 : const struct asn1_template *tenum = t->ptr;
2608 0 : size_t left = 0;
2609 0 : size_t right = A1_HEADER_LEN(tenum);
2610 : size_t mid;
2611 0 : uint32_t v = *(unsigned int *)el;
2612 0 : int c = -1;
2613 :
2614 0 : while (left <= right) {
2615 0 : mid = (left + right) >> 1;
2616 :
2617 0 : if ((tenum[mid].tt & A1_OP_MASK) != A1_OP_NAME)
2618 0 : break;
2619 0 : c = v - tenum[mid].offset;
2620 0 : if (c < 0) {
2621 0 : if (mid)
2622 0 : right = mid - 1;
2623 : else
2624 0 : break;
2625 0 : } else if (c > 0) {
2626 0 : left = mid + 1;
2627 : } else {
2628 0 : break;
2629 : }
2630 : }
2631 0 : if (c == 0) {
2632 0 : r = rk_strpoolprintf(r, "\"%s\"", (const char *)tenum[mid].ptr);
2633 0 : break;
2634 : }
2635 : }
2636 0 : s = (asn1_template_prim[type].print)(el, flags);
2637 : switch (type) {
2638 0 : case A1T_OID:
2639 : case A1T_IMEMBER:
2640 : case A1T_BOOLEAN:
2641 : case A1T_INTEGER:
2642 : case A1T_INTEGER64:
2643 : case A1T_UNSIGNED:
2644 : case A1T_UNSIGNED64:
2645 0 : if (s)
2646 0 : r = rk_strpoolprintf(r, "%s", s);
2647 0 : break;
2648 0 : default: {
2649 0 : char *s2 = NULL;
2650 :
2651 0 : if (s)
2652 0 : (void) rk_strasvis(&s2, s, VIS_CSTYLE|VIS_TAB|VIS_NL, "\"");
2653 0 : free(s);
2654 0 : s = s2;
2655 0 : if (s)
2656 0 : r = rk_strpoolprintf(r, "\"%s\"", s);
2657 : }
2658 : }
2659 0 : if (!s) {
2660 0 : rk_strpoolfree(r);
2661 0 : free(indents);
2662 0 : return NULL;
2663 : }
2664 0 : free(s);
2665 0 : break;
2666 : }
2667 0 : case A1_OP_TAG: {
2668 0 : const void *el = DPOC(data, t->offset);
2669 :
2670 0 : if (t->tt & A1_FLAG_OPTIONAL) {
2671 0 : const void * const *pel = (const void * const *)el;
2672 0 : if (*pel == NULL) {
2673 0 : r = rk_strpoolprintf(r, "null");
2674 0 : break;
2675 : }
2676 0 : el = *pel;
2677 : }
2678 :
2679 0 : r = _asn1_print(t->ptr, r, flags, indent + 1, el, saved);
2680 0 : break;
2681 : }
2682 0 : case A1_OP_SETOF:
2683 : case A1_OP_SEQOF: {
2684 0 : const struct template_of *el = DPOC(data, t->offset);
2685 0 : size_t ellen = _asn1_sizeofType(t->ptr);
2686 0 : const unsigned char *element = el->val;
2687 : unsigned int i;
2688 :
2689 0 : r = rk_strpoolprintf(r, "%s[", indents ? indents : "");
2690 0 : for (i = 0; r && i < el->len; i++) {
2691 0 : if (i)
2692 0 : r = rk_strpoolprintf(r, ",%s", indents ? indents : "");
2693 0 : r = _asn1_print(t->ptr, r, flags, indent + 1, element, saved);
2694 0 : element += ellen;
2695 : }
2696 0 : if (r)
2697 0 : r = rk_strpoolprintf(r, "]");
2698 0 : break;
2699 : }
2700 0 : case A1_OP_BMEMBER: {
2701 0 : const struct asn1_template *bmember = t->ptr;
2702 0 : size_t size = bmember->offset;
2703 0 : size_t belements = A1_HEADER_LEN(bmember);
2704 0 : int first = 1;
2705 :
2706 0 : bmember += belements;
2707 0 : r = rk_strpoolprintf(r, "%s[", indents ? indents : "");
2708 0 : while (r && belements) {
2709 0 : if (r && _asn1_bmember_isset_bit(data, bmember->offset, size)) {
2710 0 : if (!first)
2711 0 : r = rk_strpoolprintf(r, ",");
2712 0 : first = 0;
2713 0 : r = rk_strpoolprintf(r, "%s\"%s\"", indents ? indents : "",
2714 0 : (const char *)bmember->ptr);
2715 : }
2716 0 : belements--; bmember--;
2717 : }
2718 0 : if (r)
2719 0 : r = rk_strpoolprintf(r, "]");
2720 0 : break;
2721 : }
2722 0 : case A1_OP_CHOICE: {
2723 0 : const struct asn1_template *choice = t->ptr;
2724 0 : const unsigned int *element = DPOC(data, choice->offset);
2725 0 : unsigned int nchoices = ((uintptr_t)choice->ptr) >> 1;
2726 :
2727 0 : if (*element > A1_HEADER_LEN(choice)) {
2728 0 : r = rk_strpoolprintf(r, "null");
2729 0 : } else if (*element == 0) {
2730 0 : r = rk_strpoolprintf(r, "null");
2731 : } else {
2732 0 : choice += *element;
2733 0 : r = rk_strpoolprintf(r, "%s{\"_choice\":\"%s\",%s\"value\":",
2734 : indents ? indents : "",
2735 0 : (const char *)choice[nchoices].ptr,
2736 : indents ? indents : "");
2737 0 : if (r)
2738 0 : r = _asn1_print(choice->ptr, r, flags, indent + 1,
2739 0 : DPOC(data, choice->offset), NULL);
2740 0 : if (r)
2741 0 : r = rk_strpoolprintf(r, "}");
2742 : }
2743 0 : break;
2744 : }
2745 0 : default:
2746 0 : ABORT_ON_ERROR();
2747 : break;
2748 : }
2749 0 : t++;
2750 0 : elements--;
2751 : }
2752 0 : free(indents);
2753 0 : if (nnames && r)
2754 0 : return rk_strpoolprintf(r, "}");
2755 0 : return r;
2756 : }
2757 :
2758 : char *
2759 0 : _asn1_print_top(const struct asn1_template *t,
2760 : int flags,
2761 : const void *data)
2762 : {
2763 0 : struct rk_strpool *r = _asn1_print(t, NULL, flags, 0, data, NULL);
2764 :
2765 0 : if (r == NULL)
2766 0 : return NULL;
2767 0 : return rk_strpoolcollect(r);
2768 : }
2769 :
2770 : /* See commentary in _asn1_decode_open_type() */
2771 : static int
2772 1105 : _asn1_copy_open_type(const struct asn1_template *t, /* object set template */
2773 : const void *from,
2774 : void *to)
2775 : {
2776 : const struct asn1_template *tactual_type;
2777 1105 : const struct asn1_template *tos = t->ptr;
2778 : size_t i;
2779 : const void * const *dfromp;
2780 : const void * const *valfrom;
2781 : const unsigned int *lenfromp;
2782 : void **dtop;
2783 : void **valto;
2784 : unsigned int *lentop;
2785 : unsigned int len;
2786 1105 : const int *efromp = DPO(from, t->offset);
2787 1105 : int *etop = DPO(to, t->offset);
2788 1105 : int ret = 0;
2789 :
2790 : /* XXX We assume sizeof(enum) == sizeof(int) */
2791 1105 : if (!*efromp || *efromp >= A1_HEADER_LEN(tos) + 1) {
2792 214 : if ((t->tt & A1_OS_OT_IS_ARRAY))
2793 0 : memset(etop, 0, sizeof(int) + sizeof(unsigned int) + sizeof(void *));
2794 : else
2795 214 : memset(etop, 0, sizeof(int) + sizeof(void *));
2796 214 : return 0; /* Unknown choice -> not copied */
2797 : }
2798 891 : tactual_type = &tos[3*(*efromp - 1) + 4];
2799 :
2800 891 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
2801 891 : dfromp = DPO(from, t->offset + sizeof(*efromp));
2802 891 : while (sizeof(void *) != sizeof(*efromp) &&
2803 1782 : ((uintptr_t)dfromp) % sizeof(void *) != 0)
2804 891 : dfromp = (void *)(((char *)dfromp) + sizeof(*efromp));
2805 891 : if (!*dfromp)
2806 0 : return 0;
2807 :
2808 891 : dtop = DPO(to, t->offset + sizeof(*etop));
2809 891 : while (sizeof(void *) != sizeof(*etop) &&
2810 1782 : ((uintptr_t)dtop) % sizeof(void *) != 0)
2811 891 : dtop = (void *)(((char *)dtop) + sizeof(*etop));
2812 :
2813 891 : if ((*dtop = calloc(1, tactual_type->offset)) == NULL)
2814 0 : ret = ENOMEM;
2815 891 : if (ret == 0)
2816 891 : ret = _asn1_copy(tactual_type->ptr, *dfromp, *dtop);
2817 891 : if (ret == 0)
2818 891 : *etop = *efromp;
2819 891 : return ret;
2820 : }
2821 :
2822 0 : lenfromp = DPO(from, t->offset + sizeof(*efromp));
2823 0 : dfromp = DPO(from, t->offset + sizeof(*efromp) + sizeof(*lenfromp));
2824 0 : valfrom = *dfromp;
2825 0 : lentop = DPO(to, t->offset + sizeof(*etop));
2826 0 : dtop = DPO(to, t->offset + sizeof(*etop) + sizeof(*lentop));
2827 :
2828 0 : *etop = *efromp;
2829 :
2830 0 : len = *lenfromp;
2831 0 : *lentop = 0;
2832 0 : *dtop = NULL;
2833 0 : if ((valto = calloc(len, sizeof(valto[0]))) == NULL)
2834 0 : ret = ENOMEM;
2835 0 : for (i = 0, len = *lenfromp; ret == 0 && i < len; i++) {
2836 0 : if (valfrom[i] == NULL) {
2837 0 : valto[i] = NULL;
2838 0 : continue;
2839 : }
2840 0 : if ((valto[i] = calloc(1, tactual_type->offset)) == NULL)
2841 0 : ret = ENOMEM;
2842 : else
2843 0 : ret = _asn1_copy(tactual_type->ptr, valfrom[i], valto[i]);
2844 0 : (*lentop)++;
2845 : }
2846 :
2847 0 : for (i = 0; ret && i < (*lentop); i++) {
2848 0 : if (valto[i]) {
2849 0 : _asn1_free(tactual_type->ptr, valto[i]);
2850 0 : free(valto[i]);
2851 : }
2852 : }
2853 0 : if (ret) {
2854 0 : free(valto);
2855 0 : *lentop = 0;
2856 : } else
2857 0 : *dtop = valto;
2858 0 : return ret;
2859 : }
2860 :
2861 : int
2862 202056063 : _asn1_copy(const struct asn1_template *t, const void *from, void *to)
2863 : {
2864 202056063 : size_t elements = A1_HEADER_LEN(t);
2865 202056063 : int ret = 0;
2866 202056063 : int preserve = (t->tt & A1_HF_PRESERVE);
2867 :
2868 202056063 : t++;
2869 :
2870 202056063 : if (preserve) {
2871 89646 : ret = der_copy_octet_string(from, to);
2872 89646 : if (ret)
2873 0 : return ret;
2874 : }
2875 :
2876 531950873 : while (elements) {
2877 329894810 : switch (t->tt & A1_OP_MASK) {
2878 1105 : case A1_OP_OPENTYPE_OBJSET: {
2879 1105 : _asn1_copy_open_type(t, from, to);
2880 1105 : break;
2881 : }
2882 83180830 : case A1_OP_NAME: break;
2883 1218 : case A1_OP_DEFVAL: break;
2884 44903852 : case A1_OP_TYPE_DECORATE_EXTERN:
2885 : case A1_OP_TYPE_DECORATE:
2886 : case A1_OP_TYPE:
2887 : case A1_OP_TYPE_EXTERN: {
2888 44903852 : const void *fel = DPOC(from, t->offset);
2889 44903852 : void *tel = DPO(to, t->offset);
2890 44903852 : void **ptel = (void **)tel;
2891 : size_t size;
2892 :
2893 44903852 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
2894 4237765 : (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2895 43891111 : size = _asn1_sizeofType(t->ptr);
2896 : } else {
2897 1012741 : const struct asn1_type_func *f = t->ptr;
2898 1012741 : size = f->size;
2899 : }
2900 :
2901 44903852 : if (t->tt & A1_FLAG_OPTIONAL) {
2902 3226747 : void **pfel = (void **)fel;
2903 3226747 : if (*pfel == NULL)
2904 2214390 : break;
2905 1012357 : fel = *pfel;
2906 :
2907 1012357 : tel = *ptel = calloc(1, size);
2908 1012357 : if (tel == NULL)
2909 0 : return ENOMEM;
2910 : }
2911 :
2912 42689462 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
2913 2023375 : (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2914 41677067 : ret = _asn1_copy(t->ptr, fel, tel);
2915 1012395 : } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) {
2916 1415 : const struct asn1_type_func *f = t->ptr;
2917 1415 : ret = (f->copy)(fel, tel);
2918 : } else {
2919 1010980 : const struct asn1_type_func *f = t->ptr;
2920 :
2921 : /* A1_OP_TYPE_DECORATE_EXTERN */
2922 1010980 : if (f && f->copy)
2923 0 : ret = (f->copy)(fel, tel);
2924 1010980 : else if (f)
2925 1010980 : memset(tel, 0, f->size);
2926 : }
2927 :
2928 42689462 : if (ret) {
2929 0 : if (t->tt & A1_FLAG_OPTIONAL) {
2930 0 : free(*ptel);
2931 0 : *ptel = NULL;
2932 : }
2933 0 : return ret;
2934 : }
2935 42689462 : break;
2936 : }
2937 48035108 : case A1_OP_PARSE: {
2938 48035108 : unsigned int type = A1_PARSE_TYPE(t->tt);
2939 48035108 : const void *fel = DPOC(from, t->offset);
2940 48035108 : void *tel = DPO(to, t->offset);
2941 :
2942 48035108 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2943 0 : ABORT_ON_ERROR();
2944 : return ASN1_PARSE_ERROR;
2945 : }
2946 48035108 : ret = (asn1_template_prim[type].copy)(fel, tel);
2947 48035108 : if (ret)
2948 0 : return ret;
2949 48035108 : break;
2950 : }
2951 142832907 : case A1_OP_TAG: {
2952 142832907 : const void *oldfrom = from;
2953 142832907 : void *oldto = to;
2954 142832907 : void **tel = NULL;
2955 :
2956 142832907 : from = DPOC(from, t->offset);
2957 142832907 : to = DPO(to, t->offset);
2958 :
2959 142832907 : if (t->tt & A1_FLAG_OPTIONAL) {
2960 11285418 : void **fel = (void **)from;
2961 11285418 : tel = (void **)to;
2962 11285418 : if (*fel == NULL) {
2963 6196109 : from = oldfrom;
2964 6196109 : to = oldto;
2965 6196109 : break;
2966 : }
2967 5089309 : from = *fel;
2968 :
2969 5089309 : to = *tel = calloc(1, _asn1_sizeofType(t->ptr));
2970 5089309 : if (to == NULL)
2971 0 : return ENOMEM;
2972 : }
2973 :
2974 136636798 : ret = _asn1_copy(t->ptr, from, to);
2975 136636798 : if (ret) {
2976 0 : if (tel) {
2977 0 : free(*tel);
2978 0 : *tel = NULL;
2979 : }
2980 0 : return ret;
2981 : }
2982 :
2983 136636798 : from = oldfrom;
2984 136636798 : to = oldto;
2985 :
2986 136636798 : break;
2987 : }
2988 8695089 : case A1_OP_SETOF:
2989 : case A1_OP_SEQOF: {
2990 8695089 : const struct template_of *fel = DPOC(from, t->offset);
2991 8695089 : struct template_of *tel = DPO(to, t->offset);
2992 8695089 : size_t ellen = _asn1_sizeofType(t->ptr);
2993 : unsigned int i;
2994 :
2995 8695089 : tel->val = calloc(fel->len, ellen);
2996 8695089 : if (tel->val == NULL)
2997 0 : return ENOMEM;
2998 :
2999 8695089 : tel->len = fel->len;
3000 :
3001 19441566 : for (i = 0; i < fel->len; i++) {
3002 10746477 : ret = _asn1_copy(t->ptr,
3003 10746477 : DPOC(fel->val, (i * ellen)),
3004 10746477 : DPO(tel->val, (i *ellen)));
3005 10746477 : if (ret)
3006 0 : return ret;
3007 : }
3008 8695089 : break;
3009 : }
3010 1229823 : case A1_OP_BMEMBER: {
3011 1229823 : const struct asn1_template *bmember = t->ptr;
3012 1229823 : size_t size = bmember->offset;
3013 1229823 : memcpy(to, from, size);
3014 1229823 : break;
3015 : }
3016 1014878 : case A1_OP_CHOICE: {
3017 1014878 : const struct asn1_template *choice = t->ptr;
3018 1014878 : const unsigned int *felement = DPOC(from, choice->offset);
3019 1014878 : unsigned int *telement = DPO(to, choice->offset);
3020 :
3021 1014878 : if (*felement > A1_HEADER_LEN(choice))
3022 0 : return ASN1_PARSE_ERROR;
3023 :
3024 1014878 : *telement = *felement;
3025 :
3026 1014878 : if (*felement == 0) {
3027 0 : ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt));
3028 : } else {
3029 1014878 : choice += *felement;
3030 1014878 : ret = _asn1_copy(choice->ptr,
3031 1014878 : DPOC(from, choice->offset),
3032 1014878 : DPO(to, choice->offset));
3033 : }
3034 1014878 : if (ret)
3035 0 : return ret;
3036 1014878 : break;
3037 : }
3038 0 : default:
3039 0 : ABORT_ON_ERROR();
3040 : break;
3041 : }
3042 329894810 : t++;
3043 329894810 : elements--;
3044 : }
3045 202056063 : return 0;
3046 : }
3047 :
3048 : int
3049 1141930 : _asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size)
3050 : {
3051 : int ret;
3052 1141930 : memset(data, 0, t->offset);
3053 1141930 : ret = _asn1_decode(t, flags, p, len, data, size);
3054 1141930 : if (ret)
3055 119535 : _asn1_free_top(t, data);
3056 :
3057 1141930 : return ret;
3058 : }
3059 :
3060 : int
3061 11979952 : _asn1_copy_top(const struct asn1_template *t, const void *from, void *to)
3062 : {
3063 : int ret;
3064 11979952 : memset(to, 0, t->offset);
3065 11979952 : ret = _asn1_copy(t, from, to);
3066 11979952 : if (ret)
3067 0 : _asn1_free_top(t, to);
3068 :
3069 11979952 : return ret;
3070 : }
3071 :
3072 : void
3073 12054976 : _asn1_free_top(const struct asn1_template *t, void *data)
3074 : {
3075 12054976 : _asn1_free(t, data);
3076 12054976 : memset(data, 0, t->offset);
3077 12054976 : }
|