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 86286469 : _asn1_sizeofType(const struct asn1_template *t)
97 : {
98 86286469 : 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 4255334 : _asn1_bmember_get_bit(const unsigned char *p, void *data,
113 : unsigned int bit, size_t size)
114 : {
115 4255334 : unsigned int localbit = bit % 8;
116 4255334 : if ((*p >> (7 - localbit)) & 1) {
117 : #ifdef WORDS_BIGENDIAN
118 : *(unsigned int *)data |= (1u << ((size * 8) - bit - 1));
119 : #else
120 699171 : *(unsigned int *)data |= (1u << bit);
121 : #endif
122 : }
123 4255334 : }
124 :
125 : int
126 5088271 : _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 5088271 : if ((*(unsigned int *)data) & (1u << bit))
134 820019 : return 1;
135 4268252 : return 0;
136 : #endif
137 : }
138 :
139 : void
140 5088271 : _asn1_bmember_put_bit(unsigned char *p, const void *data, unsigned int bit,
141 : size_t size, unsigned int *bitset)
142 : {
143 5088271 : unsigned int localbit = bit % 8;
144 :
145 5088271 : if (_asn1_bmember_isset_bit(data, bit, size)) {
146 820019 : *p |= (1u << (7 - localbit));
147 820019 : if (*bitset == 0)
148 308910 : *bitset = (7 - localbit) + 1;
149 : }
150 5088271 : }
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 3315 : 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 3315 : while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
504 2210 : 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 4797 : 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 36421968 : _asn1_decode(const struct asn1_template *t, unsigned flags,
725 : const unsigned char *p, size_t len, void *data, size_t *size)
726 : {
727 36421968 : const struct asn1_template *tbase = t;
728 36421968 : const struct asn1_template *tdefval = NULL;
729 36421968 : size_t elements = A1_HEADER_LEN(t);
730 36421968 : size_t oldlen = len;
731 36421968 : int ret = 0;
732 36421968 : const unsigned char *startp = NULL;
733 36421968 : 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 36421968 : t++;
760 :
761 36421968 : if (template_flags & A1_HF_PRESERVE)
762 103784 : startp = p;
763 :
764 131126669 : while (elements) {
765 58407151 : 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 14201032 : case A1_OP_NAME: break;
781 1218 : case A1_OP_DEFVAL:
782 1218 : tdefval = t;
783 1218 : break;
784 9002977 : case A1_OP_TYPE:
785 : case A1_OP_TYPE_EXTERN: {
786 : size_t newsize, elsize;
787 9002977 : void *el = DPO(data, t->offset);
788 9002977 : void **pel = (void **)el;
789 :
790 9002977 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
791 9002486 : 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 9002977 : 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 9002977 : break;
822 : }
823 : } else {
824 9002524 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
825 9002486 : 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 9002977 : 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 9002977 : p += newsize; len -= newsize;
870 :
871 9002977 : break;
872 : }
873 25010072 : case A1_OP_TAG: {
874 : Der_type dertype;
875 25010072 : size_t newsize = 0;
876 25010072 : size_t datalen, l = 0;
877 25010072 : void *olddata = data;
878 25010072 : int is_indefinite = 0;
879 25010072 : int subflags = flags;
880 25010072 : int replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
881 25010072 : void *el = data = DPO(data, t->offset);
882 25010072 : 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 25010072 : ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt),
895 25010072 : &dertype, A1_TAG_TAG(t->tt),
896 : &datalen, &l);
897 25010072 : if (ret) {
898 1313585 : if (t->tt & A1_FLAG_OPTIONAL) {
899 1188164 : data = olddata;
900 26073818 : break;
901 125421 : } else if (t->tt & A1_FLAG_DEFAULT) {
902 1003 : if (!tdefval)
903 124418 : 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 124418 : return ret; /* Error decoding required field */
937 : }
938 :
939 23696487 : 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 23696487 : 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 23696487 : 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 23696487 : } else if (datalen > len)
965 0 : return ASN1_OVERRUN;
966 :
967 23696487 : if (t->tt & A1_FLAG_OPTIONAL) {
968 1494449 : size_t ellen = _asn1_sizeofType(t->ptr);
969 :
970 1494449 : *pel = calloc(1, ellen);
971 1494449 : if (*pel == NULL)
972 0 : return ENOMEM;
973 1494449 : data = *pel;
974 : }
975 :
976 23696487 : 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 1652 : 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 23695949 : ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize);
1005 : }
1006 23696487 : if (ret == 0 && !is_indefinite && newsize != datalen)
1007 : /* Hidden data */
1008 0 : ret = ASN1_EXTRA_DATA;
1009 :
1010 23696487 : if (ret == 0) {
1011 23696487 : if (is_indefinite) {
1012 : /* If we use indefinite encoding, the newsize is the datasize. */
1013 0 : datalen = newsize;
1014 : }
1015 :
1016 23696487 : len -= datalen;
1017 23696487 : p += datalen;
1018 :
1019 : /*
1020 : * Indefinite encoding needs a trailing EndOfContent,
1021 : * check for that.
1022 : */
1023 23696487 : 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 23696487 : 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 23696487 : data = olddata;
1046 :
1047 23696487 : break;
1048 : }
1049 8280885 : case A1_OP_PARSE: {
1050 8280885 : unsigned int type = A1_PARSE_TYPE(t->tt);
1051 : size_t newsize;
1052 8280885 : 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 8280885 : if (flags & A1_PF_INDEFINTE)
1059 0 : type++;
1060 :
1061 8280885 : 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 8280885 : ret = (asn1_template_prim[type].decode)(p, len, el, &newsize);
1067 8280885 : if (ret)
1068 0 : return ret;
1069 8280885 : p += newsize; len -= newsize;
1070 :
1071 8280885 : break;
1072 : }
1073 1531816 : case A1_OP_SETOF:
1074 : case A1_OP_SEQOF: {
1075 1531816 : struct template_of *el = DPO(data, t->offset);
1076 : size_t newsize;
1077 1531816 : size_t ellen = _asn1_sizeofType(t->ptr);
1078 1531816 : size_t vallength = 0;
1079 :
1080 5577886 : while (len > 0) {
1081 : void *tmp;
1082 2514254 : size_t newlen = vallength + ellen;
1083 2514254 : if (vallength > newlen)
1084 0 : return ASN1_OVERFLOW;
1085 :
1086 : /* XXX Slow */
1087 2514254 : tmp = realloc(el->val, newlen);
1088 2514254 : if (tmp == NULL)
1089 0 : return ENOMEM;
1090 :
1091 2514254 : memset(DPO(tmp, vallength), 0, ellen);
1092 2514254 : el->val = tmp;
1093 :
1094 2514254 : el->len++;
1095 2514254 : ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len,
1096 2514254 : DPO(el->val, vallength), &newsize);
1097 2514254 : if (ret)
1098 0 : return ret;
1099 2514254 : vallength = newlen;
1100 2514254 : p += newsize; len -= newsize;
1101 : }
1102 :
1103 1531816 : break;
1104 : }
1105 311167 : case A1_OP_BMEMBER: {
1106 311167 : const struct asn1_template *bmember = t->ptr;
1107 311167 : size_t bsize = bmember->offset;
1108 311167 : size_t belements = A1_HEADER_LEN(bmember);
1109 311167 : size_t pos = 0;
1110 :
1111 311167 : bmember++;
1112 :
1113 311167 : memset(data, 0, bsize);
1114 :
1115 311167 : if (len < 1)
1116 0 : return ASN1_OVERRUN;
1117 311167 : p++; len--;
1118 :
1119 4877768 : while (belements && len) {
1120 9120330 : while (bmember->offset / 8 > pos / 8) {
1121 609462 : if (len < 1)
1122 0 : break;
1123 609462 : p++; len--;
1124 609462 : pos += 8;
1125 : }
1126 4255434 : if (len) {
1127 4255334 : _asn1_bmember_get_bit(p, data, bmember->offset, bsize);
1128 4255334 : belements--; bmember++;
1129 : }
1130 : }
1131 311167 : len = 0;
1132 311167 : break;
1133 : }
1134 66879 : case A1_OP_CHOICE: {
1135 66879 : const struct asn1_template *choice = t->ptr;
1136 66879 : 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 66879 : *element = ~0;
1147 :
1148 72377 : 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 72377 : ret = _asn1_decode(choice[i].ptr, 0, p, len,
1167 72377 : DPO(data, choice[i].offset), &datalen);
1168 72377 : if (ret == 0) {
1169 66879 : *element = i;
1170 66879 : p += datalen; len -= datalen;
1171 66879 : 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 66879 : 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 66879 : break;
1192 : }
1193 0 : default:
1194 0 : ABORT_ON_ERROR();
1195 : return ASN1_PARSE_ERROR;
1196 : }
1197 58282733 : t++;
1198 58282733 : elements--;
1199 : }
1200 : /* if we are using padding, eat up read of context */
1201 36297550 : if (template_flags & A1_HF_ELLIPSIS)
1202 127602 : len = 0;
1203 :
1204 36297550 : oldlen -= len;
1205 :
1206 36297550 : if (size)
1207 35892827 : *size = oldlen;
1208 :
1209 : /*
1210 : * saved the raw bits if asked for it, useful for signature
1211 : * verification.
1212 : */
1213 36297550 : if (startp) {
1214 103784 : heim_octet_string *save = data;
1215 :
1216 103784 : save->data = malloc(oldlen);
1217 103784 : if (save->data == NULL)
1218 0 : return ENOMEM;
1219 : else {
1220 103784 : save->length = oldlen;
1221 103784 : memcpy(save->data, startp, oldlen);
1222 : }
1223 : }
1224 36297550 : 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 39662830 : _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const void *data, size_t *size)
1405 : {
1406 39662830 : const struct asn1_template *tbase = t;
1407 39662830 : size_t elements = A1_HEADER_LEN(t);
1408 39662830 : int ret = 0;
1409 39662830 : size_t oldlen = len;
1410 :
1411 39662830 : t += A1_HEADER_LEN(t);
1412 :
1413 143265418 : while (elements) {
1414 63939758 : 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 15577096 : 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 9918894 : case A1_OP_TYPE:
1430 : case A1_OP_TYPE_EXTERN: {
1431 : size_t newsize;
1432 9918894 : const void *el = DPOC(data, t->offset);
1433 :
1434 9918894 : if (t->tt & A1_FLAG_OPTIONAL) {
1435 1386 : void **pel = (void **)el;
1436 1386 : if (*pel == NULL)
1437 9919279 : break;
1438 1001 : el = *pel;
1439 9917508 : } 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 9918509 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
1475 9915895 : 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 9918509 : if (ret)
1482 0 : return ret;
1483 9918509 : p -= newsize; len -= newsize;
1484 :
1485 9918509 : break;
1486 : }
1487 27304171 : case A1_OP_TAG: {
1488 27304171 : const void *olddata = data;
1489 27304171 : size_t l, datalen = 0;
1490 27304171 : 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 27304171 : data = DPOC(data, t->offset);
1503 :
1504 27304171 : if (t->tt & A1_FLAG_OPTIONAL) {
1505 3036926 : void **el = (void **)data;
1506 3036926 : if (*el == NULL) {
1507 1319705 : data = olddata;
1508 28623876 : break;
1509 : }
1510 1717221 : data = *el;
1511 24267245 : } 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 25984466 : replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
1553 :
1554 : /* IMPLICIT tags need special handling (see gen_encode.c) */
1555 25984466 : 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 458 : 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 25984237 : ret = _asn1_encode(t->ptr, p, len, data, &datalen);
1603 25984237 : if (ret)
1604 0 : return ret;
1605 :
1606 25984237 : len -= datalen; p -= datalen;
1607 :
1608 51968474 : ret = der_put_length_and_tag(p, len, datalen,
1609 25984237 : A1_TAG_CLASS(t->tt),
1610 25984237 : A1_TAG_TYPE(t->tt),
1611 25984237 : A1_TAG_TAG(t->tt), &l);
1612 25984237 : if (ret == 0) {
1613 25984237 : p -= l; len -= l;
1614 : }
1615 : }
1616 25984466 : if (ret)
1617 0 : return ret;
1618 :
1619 25984466 : data = olddata;
1620 :
1621 25984466 : break;
1622 : }
1623 9144832 : case A1_OP_PARSE: {
1624 9144832 : unsigned int type = A1_PARSE_TYPE(t->tt);
1625 : size_t newsize;
1626 9144832 : const void *el = DPOC(data, t->offset);
1627 :
1628 9144832 : 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 9144832 : ret = (asn1_template_prim[type].encode)(p, len, el, &newsize);
1634 9144832 : if (ret)
1635 0 : return ret;
1636 9144832 : p -= newsize; len -= newsize;
1637 :
1638 9144832 : 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 1284 : 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 1559978 : case A1_OP_SEQOF: {
1708 1559978 : struct template_of *el = DPO(data, t->offset);
1709 1559978 : size_t ellen = _asn1_sizeofType(t->ptr);
1710 : size_t newsize;
1711 : unsigned int i;
1712 1559978 : unsigned char *elptr = el->val;
1713 :
1714 1559978 : if (el->len == 0)
1715 1730816 : break;
1716 :
1717 1389140 : elptr += ellen * (el->len - 1);
1718 :
1719 4119870 : for (i = 0; i < el->len; i++) {
1720 2730730 : ret = _asn1_encode(t->ptr, p, len,
1721 : elptr,
1722 : &newsize);
1723 2730730 : if (ret)
1724 0 : return ret;
1725 2730730 : p -= newsize; len -= newsize;
1726 2730730 : elptr -= ellen;
1727 : }
1728 :
1729 1389140 : break;
1730 : }
1731 365808 : case A1_OP_BMEMBER: {
1732 365808 : const struct asn1_template *bmember = t->ptr;
1733 365808 : size_t bsize = bmember->offset;
1734 365808 : size_t belements = A1_HEADER_LEN(bmember);
1735 : size_t pos;
1736 365808 : unsigned char c = 0;
1737 365808 : unsigned int bitset = 0;
1738 365808 : int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
1739 :
1740 365808 : bmember += belements;
1741 :
1742 365808 : if (rfc1510)
1743 365808 : pos = 31;
1744 : else
1745 0 : pos = bmember->offset;
1746 :
1747 5819887 : while (belements && len) {
1748 11273966 : while (bmember->offset / 8 < pos / 8) {
1749 1097424 : if (rfc1510 || bitset || c) {
1750 1097424 : if (len < 1)
1751 0 : return ASN1_OVERFLOW;
1752 1097424 : *p-- = c; len--;
1753 : }
1754 1097424 : c = 0;
1755 1097424 : pos -= 8;
1756 : }
1757 5088271 : _asn1_bmember_put_bit(&c, data, bmember->offset, bsize, &bitset);
1758 5088271 : belements--; bmember--;
1759 : }
1760 365808 : if (rfc1510 || bitset) {
1761 365808 : if (len < 1)
1762 0 : return ASN1_OVERFLOW;
1763 365808 : *p-- = c; len--;
1764 : }
1765 :
1766 365808 : if (len < 1)
1767 0 : return ASN1_OVERFLOW;
1768 365808 : if (rfc1510 || bitset == 0)
1769 365808 : *p-- = 0;
1770 : else
1771 0 : *p-- = bitset - 1;
1772 :
1773 365808 : len--;
1774 :
1775 365808 : break;
1776 : }
1777 68427 : case A1_OP_CHOICE: {
1778 68427 : const struct asn1_template *choice = t->ptr;
1779 68427 : const unsigned int *element = DPOC(data, choice->offset);
1780 : size_t datalen;
1781 : const void *el;
1782 :
1783 68427 : if (*element > A1_HEADER_LEN(choice)) {
1784 0 : printf("element: %d\n", *element);
1785 0 : return ASN1_PARSE_ERROR;
1786 : }
1787 :
1788 68427 : if (*element == 0) {
1789 0 : ret += der_put_octet_string(p, len,
1790 0 : DPOC(data, choice->tt), &datalen);
1791 : } else {
1792 68427 : choice += *element;
1793 68427 : el = DPOC(data, choice->offset);
1794 68427 : ret = _asn1_encode(choice->ptr, p, len, el, &datalen);
1795 68427 : if (ret)
1796 0 : return ret;
1797 : }
1798 68427 : len -= datalen; p -= datalen;
1799 :
1800 68427 : break;
1801 : }
1802 0 : default:
1803 0 : ABORT_ON_ERROR();
1804 : }
1805 63939758 : t--;
1806 63939758 : elements--;
1807 : }
1808 39662830 : if (size)
1809 39662830 : *size = oldlen - len;
1810 :
1811 39662830 : 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 39665933 : _asn1_length(const struct asn1_template *t, const void *data)
1982 : {
1983 39665933 : const struct asn1_template *tbase = t;
1984 39665933 : size_t elements = A1_HEADER_LEN(t);
1985 39665933 : size_t ret = 0;
1986 :
1987 39665933 : t += A1_HEADER_LEN(t);
1988 :
1989 143276011 : while (elements) {
1990 63944145 : 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 15578059 : 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 9919934 : case A1_OP_TYPE:
2004 : case A1_OP_TYPE_EXTERN: {
2005 9919934 : const void *el = DPOC(data, t->offset);
2006 :
2007 9919934 : 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 9918548 : } 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 9919549 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
2049 9916935 : 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 9919549 : break;
2055 : }
2056 27305363 : case A1_OP_TAG: {
2057 : size_t datalen;
2058 27305363 : const void *olddata = data;
2059 27305363 : size_t oldtaglen = 0;
2060 :
2061 27305363 : data = DPO(data, t->offset);
2062 :
2063 27305363 : if (t->tt & A1_FLAG_OPTIONAL) {
2064 3036926 : void **el = (void **)data;
2065 3036926 : if (*el == NULL) {
2066 1319705 : data = olddata;
2067 1319705 : break;
2068 : }
2069 1717221 : data = *el;
2070 24268437 : } 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 25985658 : if (t->tt & A1_FLAG_IMPLICIT)
2112 229 : oldtaglen = inner_type_taglen(t->ptr);
2113 :
2114 25985658 : datalen = _asn1_length(t->ptr, data);
2115 25985658 : ret += datalen;
2116 25985658 : ret += der_length_tag(A1_TAG_TAG(t->tt));
2117 25985658 : ret += oldtaglen ? -oldtaglen : der_length_len(datalen);
2118 25985658 : data = olddata;
2119 25985658 : break;
2120 : }
2121 9145626 : case A1_OP_PARSE: {
2122 9145626 : unsigned int type = A1_PARSE_TYPE(t->tt);
2123 9145626 : const void *el = DPOC(data, t->offset);
2124 :
2125 9145626 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2126 0 : ABORT_ON_ERROR();
2127 : break;
2128 : }
2129 9145626 : ret += (asn1_template_prim[type].length)(el);
2130 9145626 : break;
2131 : }
2132 1560607 : case A1_OP_SETOF:
2133 : case A1_OP_SEQOF: {
2134 1560607 : const struct template_of *el = DPOC(data, t->offset);
2135 1560607 : size_t ellen = _asn1_sizeofType(t->ptr);
2136 1560607 : const unsigned char *element = el->val;
2137 : unsigned int i;
2138 :
2139 4291658 : for (i = 0; i < el->len; i++) {
2140 2731051 : ret += _asn1_length(t->ptr, element);
2141 2731051 : element += ellen;
2142 : }
2143 :
2144 1560607 : break;
2145 : }
2146 365808 : case A1_OP_BMEMBER: {
2147 365808 : const struct asn1_template *bmember = t->ptr;
2148 365808 : size_t size = bmember->offset;
2149 365808 : size_t belements = A1_HEADER_LEN(bmember);
2150 365808 : int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
2151 :
2152 365808 : if (rfc1510) {
2153 365808 : 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 365808 : break;
2169 : }
2170 68748 : case A1_OP_CHOICE: {
2171 68748 : const struct asn1_template *choice = t->ptr;
2172 68748 : const unsigned int *element = DPOC(data, choice->offset);
2173 :
2174 68748 : if (*element > A1_HEADER_LEN(choice))
2175 0 : break;
2176 :
2177 68748 : if (*element == 0) {
2178 0 : ret += der_length_octet_string(DPOC(data, choice->tt));
2179 : } else {
2180 68748 : choice += *element;
2181 68748 : ret += _asn1_length(choice->ptr, DPOC(data, choice->offset));
2182 : }
2183 68748 : break;
2184 : }
2185 0 : default:
2186 0 : ABORT_ON_ERROR();
2187 : break;
2188 : }
2189 0 : elements--;
2190 63944145 : t--;
2191 : }
2192 39665933 : 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 3636 : 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 258822293 : _asn1_free(const struct asn1_template *t, void *data)
2248 : {
2249 258822293 : size_t elements = A1_HEADER_LEN(t);
2250 :
2251 258822293 : if (t->tt & A1_HF_PRESERVE)
2252 277638 : der_free_octet_string(data);
2253 :
2254 258822293 : t++;
2255 :
2256 942609480 : while (elements) {
2257 424964894 : 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 105397759 : case A1_OP_NAME: break;
2263 1638 : case A1_OP_DEFVAL: break;
2264 62870216 : case A1_OP_TYPE_DECORATE_EXTERN:
2265 : case A1_OP_TYPE_DECORATE:
2266 : case A1_OP_TYPE:
2267 : case A1_OP_TYPE_EXTERN: {
2268 62870216 : void *el = DPO(data, t->offset);
2269 62870216 : void **pel = (void **)el;
2270 :
2271 62870216 : if (t->tt & A1_FLAG_OPTIONAL) {
2272 4598672 : if (*pel == NULL)
2273 3504566 : break;
2274 1094106 : el = *pel;
2275 : }
2276 :
2277 59365650 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE || (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2278 58269593 : _asn1_free(t->ptr, el);
2279 1096057 : } 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 1092427 : const struct asn1_type_func *f = t->ptr;
2285 :
2286 1092427 : if (f && f->release)
2287 0 : (f->release)(el);
2288 1092427 : else if (f)
2289 1092427 : memset(el, 0, f->size);
2290 : }
2291 59365650 : if (t->tt & A1_FLAG_OPTIONAL) {
2292 1094106 : free(el);
2293 1094106 : *pel = NULL;
2294 : }
2295 :
2296 59365650 : break;
2297 : }
2298 57491423 : case A1_OP_PARSE: {
2299 57491423 : unsigned int type = A1_PARSE_TYPE(t->tt);
2300 57491423 : void *el = DPO(data, t->offset);
2301 :
2302 57491423 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2303 0 : ABORT_ON_ERROR();
2304 : break;
2305 : }
2306 57491423 : (asn1_template_prim[type].release)(el);
2307 57491423 : break;
2308 : }
2309 181940561 : case A1_OP_TAG: {
2310 181940561 : void *el = DPO(data, t->offset);
2311 :
2312 181940561 : if (t->tt & A1_FLAG_OPTIONAL) {
2313 17665582 : void **pel = (void **)el;
2314 :
2315 17665582 : if (*pel == NULL)
2316 10044142 : break;
2317 7621440 : _asn1_free(t->ptr, *pel);
2318 7621440 : free(*pel);
2319 7621440 : *pel = NULL;
2320 : } else {
2321 164274979 : _asn1_free(t->ptr, el);
2322 : }
2323 :
2324 171896419 : break;
2325 : }
2326 14102211 : case A1_OP_SETOF:
2327 : case A1_OP_SEQOF: {
2328 14102211 : struct template_of *el = DPO(data, t->offset);
2329 14102211 : size_t ellen = _asn1_sizeofType(t->ptr);
2330 14102211 : unsigned char *element = el->val;
2331 : unsigned int i;
2332 :
2333 29603355 : for (i = 0; i < el->len; i++) {
2334 15501144 : _asn1_free(t->ptr, element);
2335 15501144 : element += ellen;
2336 : }
2337 14102211 : free(el->val);
2338 14102211 : el->val = NULL;
2339 14102211 : el->len = 0;
2340 :
2341 14102211 : break;
2342 : }
2343 1929673 : case A1_OP_BMEMBER:
2344 1929673 : break;
2345 1229663 : case A1_OP_CHOICE: {
2346 1229663 : const struct asn1_template *choice = t->ptr;
2347 1229663 : const unsigned int *element = DPOC(data, choice->offset);
2348 :
2349 1229663 : if (*element > A1_HEADER_LEN(choice))
2350 0 : break;
2351 :
2352 1229663 : if (*element == 0) {
2353 100 : der_free_octet_string(DPO(data, choice->tt));
2354 : } else {
2355 1229563 : choice += *element;
2356 1229563 : _asn1_free(choice->ptr, DPO(data, choice->offset));
2357 : }
2358 1229663 : break;
2359 : }
2360 0 : default:
2361 0 : ABORT_ON_ERROR();
2362 : break;
2363 : }
2364 424964894 : t++;
2365 424964894 : elements--;
2366 : }
2367 258822293 : }
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 : r = rk_strpoolprintf(r, ",%s\"%s\":",
2554 : indents ? indents : "",
2555 0 : (const char *)(tnames++)->ptr);
2556 0 : switch (t->tt & A1_OP_MASK) {
2557 0 : case A1_OP_OPENTYPE_OBJSET:
2558 0 : break;
2559 0 : case A1_OP_NAME: break;
2560 0 : case A1_OP_DEFVAL: break;
2561 0 : case A1_OP_TYPE_DECORATE_EXTERN: break;
2562 0 : case A1_OP_TYPE_DECORATE: break; /* We could probably print this though */
2563 0 : case A1_OP_TYPE:
2564 : case A1_OP_TYPE_EXTERN: {
2565 0 : const void *el = DPOC(data, t->offset);
2566 :
2567 0 : if (t->tt & A1_FLAG_OPTIONAL) {
2568 0 : const void * const *pel = (const void *const *)el;
2569 0 : if (*pel == NULL) {
2570 0 : r = rk_strpoolprintf(r, "null");
2571 0 : break;
2572 : }
2573 0 : el = *pel;
2574 : }
2575 :
2576 0 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
2577 0 : r = _asn1_print(t->ptr, r, flags, indent + 1, el, saved);
2578 : } else {
2579 0 : const struct asn1_type_func *f = t->ptr;
2580 0 : char *s = NULL;
2581 :
2582 0 : s = (f->print)(el, 0);
2583 0 : if (s == NULL) {
2584 0 : rk_strpoolfree(r);
2585 0 : free(indents);
2586 0 : return NULL;
2587 : }
2588 0 : r = rk_strpoolprintf(r, "%s", s);
2589 0 : free(s);
2590 : }
2591 0 : break;
2592 : }
2593 0 : case A1_OP_PARSE: {
2594 0 : unsigned int type = A1_PARSE_TYPE(t->tt);
2595 0 : const void *el = DPOC(data, t->offset);
2596 0 : char *s = NULL;
2597 :
2598 0 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2599 0 : ABORT_ON_ERROR();
2600 : break;
2601 : }
2602 :
2603 0 : if (type == A1T_IMEMBER && t->ptr) {
2604 : /* Enumeration. Use the symbolic name of this value */
2605 0 : const struct asn1_template *tenum = t->ptr;
2606 0 : size_t left = 0;
2607 0 : size_t right = A1_HEADER_LEN(tenum);
2608 : size_t mid;
2609 0 : uint32_t v = *(unsigned int *)el;
2610 0 : int c = -1;
2611 :
2612 0 : while (left <= right) {
2613 0 : mid = (left + right) >> 1;
2614 :
2615 0 : if ((tenum[mid].tt & A1_OP_MASK) != A1_OP_NAME)
2616 0 : break;
2617 0 : c = v - tenum[mid].offset;
2618 0 : if (c < 0) {
2619 0 : if (mid)
2620 0 : right = mid - 1;
2621 : else
2622 0 : break;
2623 0 : } else if (c > 0) {
2624 0 : left = mid + 1;
2625 : } else {
2626 0 : break;
2627 : }
2628 : }
2629 0 : if (c == 0) {
2630 0 : r = rk_strpoolprintf(r, "\"%s\"", (const char *)tenum[mid].ptr);
2631 0 : break;
2632 : }
2633 : }
2634 0 : s = (asn1_template_prim[type].print)(el, flags);
2635 0 : switch (type) {
2636 0 : case A1T_OID:
2637 : case A1T_IMEMBER:
2638 : case A1T_BOOLEAN:
2639 : case A1T_INTEGER:
2640 : case A1T_INTEGER64:
2641 : case A1T_UNSIGNED:
2642 : case A1T_UNSIGNED64:
2643 0 : if (s)
2644 0 : r = rk_strpoolprintf(r, "%s", s);
2645 0 : break;
2646 0 : default: {
2647 0 : char *s2 = NULL;
2648 :
2649 0 : if (s)
2650 0 : (void) rk_strasvis(&s2, s, VIS_CSTYLE|VIS_TAB|VIS_NL, "\"");
2651 0 : free(s);
2652 0 : s = s2;
2653 0 : if (s)
2654 0 : r = rk_strpoolprintf(r, "\"%s\"", s);
2655 : }
2656 : }
2657 0 : if (!s) {
2658 0 : rk_strpoolfree(r);
2659 0 : free(indents);
2660 0 : return NULL;
2661 : }
2662 0 : free(s);
2663 0 : break;
2664 : }
2665 0 : case A1_OP_TAG: {
2666 0 : const void *el = DPOC(data, t->offset);
2667 :
2668 0 : if (t->tt & A1_FLAG_OPTIONAL) {
2669 0 : const void * const *pel = (const void * const *)el;
2670 0 : if (*pel == NULL) {
2671 0 : r = rk_strpoolprintf(r, "null");
2672 0 : break;
2673 : }
2674 0 : el = *pel;
2675 : }
2676 :
2677 0 : r = _asn1_print(t->ptr, r, flags, indent + 1, el, saved);
2678 0 : break;
2679 : }
2680 0 : case A1_OP_SETOF:
2681 : case A1_OP_SEQOF: {
2682 0 : const struct template_of *el = DPOC(data, t->offset);
2683 0 : size_t ellen = _asn1_sizeofType(t->ptr);
2684 0 : const unsigned char *element = el->val;
2685 : unsigned int i;
2686 :
2687 0 : r = rk_strpoolprintf(r, "%s[", indents ? indents : "");
2688 0 : for (i = 0; r && i < el->len; i++) {
2689 0 : if (i)
2690 0 : r = rk_strpoolprintf(r, ",%s", indents ? indents : "");
2691 0 : r = _asn1_print(t->ptr, r, flags, indent + 1, element, saved);
2692 0 : element += ellen;
2693 : }
2694 0 : if (r)
2695 0 : r = rk_strpoolprintf(r, "]");
2696 0 : break;
2697 : }
2698 0 : case A1_OP_BMEMBER: {
2699 0 : const struct asn1_template *bmember = t->ptr;
2700 0 : size_t size = bmember->offset;
2701 0 : size_t belements = A1_HEADER_LEN(bmember);
2702 0 : int first = 1;
2703 :
2704 0 : bmember += belements;
2705 0 : r = rk_strpoolprintf(r, "%s[", indents ? indents : "");
2706 0 : while (r && belements) {
2707 0 : if (r && _asn1_bmember_isset_bit(data, bmember->offset, size)) {
2708 0 : if (!first)
2709 0 : r = rk_strpoolprintf(r, ",");
2710 0 : first = 0;
2711 0 : r = rk_strpoolprintf(r, "%s\"%s\"", indents ? indents : "",
2712 0 : (const char *)bmember->ptr);
2713 : }
2714 0 : belements--; bmember--;
2715 : }
2716 0 : if (r)
2717 0 : r = rk_strpoolprintf(r, "]");
2718 0 : break;
2719 : }
2720 0 : case A1_OP_CHOICE: {
2721 0 : const struct asn1_template *choice = t->ptr;
2722 0 : const unsigned int *element = DPOC(data, choice->offset);
2723 0 : unsigned int nchoices = ((uintptr_t)choice->ptr) >> 1;
2724 :
2725 0 : if (*element > A1_HEADER_LEN(choice)) {
2726 0 : r = rk_strpoolprintf(r, "null");
2727 0 : } else if (*element == 0) {
2728 0 : r = rk_strpoolprintf(r, "null");
2729 : } else {
2730 0 : choice += *element;
2731 0 : r = rk_strpoolprintf(r, "%s{\"_choice\":\"%s\",%s\"value\":",
2732 : indents ? indents : "",
2733 0 : (const char *)choice[nchoices].ptr,
2734 : indents ? indents : "");
2735 0 : if (r)
2736 0 : r = _asn1_print(choice->ptr, r, flags, indent + 1,
2737 0 : DPOC(data, choice->offset), NULL);
2738 0 : if (r)
2739 0 : r = rk_strpoolprintf(r, "}");
2740 : }
2741 0 : break;
2742 : }
2743 0 : default:
2744 0 : ABORT_ON_ERROR();
2745 : break;
2746 : }
2747 0 : t++;
2748 0 : elements--;
2749 : }
2750 0 : free(indents);
2751 0 : if (nnames && r)
2752 0 : return rk_strpoolprintf(r, "}");
2753 0 : return r;
2754 : }
2755 :
2756 : char *
2757 0 : _asn1_print_top(const struct asn1_template *t,
2758 : int flags,
2759 : const void *data)
2760 : {
2761 0 : struct rk_strpool *r = _asn1_print(t, NULL, flags, 0, data, NULL);
2762 :
2763 0 : if (r == NULL)
2764 0 : return NULL;
2765 0 : return rk_strpoolcollect(r);
2766 : }
2767 :
2768 : /* See commentary in _asn1_decode_open_type() */
2769 : static int
2770 1105 : _asn1_copy_open_type(const struct asn1_template *t, /* object set template */
2771 : const void *from,
2772 : void *to)
2773 : {
2774 : const struct asn1_template *tactual_type;
2775 1105 : const struct asn1_template *tos = t->ptr;
2776 : size_t i;
2777 : const void * const *dfromp;
2778 : const void * const *valfrom;
2779 : const unsigned int *lenfromp;
2780 : void **dtop;
2781 : void **valto;
2782 : unsigned int *lentop;
2783 : unsigned int len;
2784 1105 : const int *efromp = DPO(from, t->offset);
2785 1105 : int *etop = DPO(to, t->offset);
2786 1105 : int ret = 0;
2787 :
2788 : /* XXX We assume sizeof(enum) == sizeof(int) */
2789 1105 : if (!*efromp || *efromp >= A1_HEADER_LEN(tos) + 1) {
2790 214 : if ((t->tt & A1_OS_OT_IS_ARRAY))
2791 0 : memset(etop, 0, sizeof(int) + sizeof(unsigned int) + sizeof(void *));
2792 : else
2793 214 : memset(etop, 0, sizeof(int) + sizeof(void *));
2794 214 : return 0; /* Unknown choice -> not copied */
2795 : }
2796 891 : tactual_type = &tos[3*(*efromp - 1) + 4];
2797 :
2798 891 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
2799 891 : dfromp = DPO(from, t->offset + sizeof(*efromp));
2800 2673 : while (sizeof(void *) != sizeof(*efromp) &&
2801 1782 : ((uintptr_t)dfromp) % sizeof(void *) != 0)
2802 891 : dfromp = (void *)(((char *)dfromp) + sizeof(*efromp));
2803 891 : if (!*dfromp)
2804 0 : return 0;
2805 :
2806 891 : dtop = DPO(to, t->offset + sizeof(*etop));
2807 2673 : while (sizeof(void *) != sizeof(*etop) &&
2808 1782 : ((uintptr_t)dtop) % sizeof(void *) != 0)
2809 891 : dtop = (void *)(((char *)dtop) + sizeof(*etop));
2810 :
2811 891 : if ((*dtop = calloc(1, tactual_type->offset)) == NULL)
2812 0 : ret = ENOMEM;
2813 891 : if (ret == 0)
2814 891 : ret = _asn1_copy(tactual_type->ptr, *dfromp, *dtop);
2815 891 : if (ret == 0)
2816 891 : *etop = *efromp;
2817 891 : return ret;
2818 : }
2819 :
2820 0 : lenfromp = DPO(from, t->offset + sizeof(*efromp));
2821 0 : dfromp = DPO(from, t->offset + sizeof(*efromp) + sizeof(*lenfromp));
2822 0 : valfrom = *dfromp;
2823 0 : lentop = DPO(to, t->offset + sizeof(*etop));
2824 0 : dtop = DPO(to, t->offset + sizeof(*etop) + sizeof(*lentop));
2825 :
2826 0 : *etop = *efromp;
2827 :
2828 0 : len = *lenfromp;
2829 0 : *lentop = 0;
2830 0 : *dtop = NULL;
2831 0 : if ((valto = calloc(len, sizeof(valto[0]))) == NULL)
2832 0 : ret = ENOMEM;
2833 0 : for (i = 0, len = *lenfromp; ret == 0 && i < len; i++) {
2834 0 : if (valfrom[i] == NULL) {
2835 0 : valto[i] = NULL;
2836 0 : continue;
2837 : }
2838 0 : if ((valto[i] = calloc(1, tactual_type->offset)) == NULL)
2839 0 : ret = ENOMEM;
2840 : else
2841 0 : ret = _asn1_copy(tactual_type->ptr, valfrom[i], valto[i]);
2842 0 : (*lentop)++;
2843 : }
2844 :
2845 0 : for (i = 0; ret && i < (*lentop); i++) {
2846 0 : if (valto[i]) {
2847 0 : _asn1_free(tactual_type->ptr, valto[i]);
2848 0 : free(valto[i]);
2849 : }
2850 : }
2851 0 : if (ret) {
2852 0 : free(valto);
2853 0 : *lentop = 0;
2854 : } else
2855 0 : *dtop = valto;
2856 0 : return ret;
2857 : }
2858 :
2859 : int
2860 199833708 : _asn1_copy(const struct asn1_template *t, const void *from, void *to)
2861 : {
2862 199833708 : size_t elements = A1_HEADER_LEN(t);
2863 199833708 : int ret = 0;
2864 199833708 : int preserve = (t->tt & A1_HF_PRESERVE);
2865 :
2866 199833708 : t++;
2867 :
2868 199833708 : if (preserve) {
2869 89019 : ret = der_copy_octet_string(from, to);
2870 89019 : if (ret)
2871 0 : return ret;
2872 : }
2873 :
2874 725915324 : while (elements) {
2875 326247908 : switch (t->tt & A1_OP_MASK) {
2876 1105 : case A1_OP_OPENTYPE_OBJSET: {
2877 1105 : _asn1_copy_open_type(t, from, to);
2878 1105 : break;
2879 : }
2880 82255550 : case A1_OP_NAME: break;
2881 1218 : case A1_OP_DEFVAL: break;
2882 44404720 : case A1_OP_TYPE_DECORATE_EXTERN:
2883 : case A1_OP_TYPE_DECORATE:
2884 : case A1_OP_TYPE:
2885 : case A1_OP_TYPE_EXTERN: {
2886 44404720 : const void *fel = DPOC(from, t->offset);
2887 44404720 : void *tel = DPO(to, t->offset);
2888 44404720 : void **ptel = (void **)tel;
2889 : size_t size;
2890 :
2891 48597138 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
2892 4192418 : (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2893 43404734 : size = _asn1_sizeofType(t->ptr);
2894 : } else {
2895 999986 : const struct asn1_type_func *f = t->ptr;
2896 999986 : size = f->size;
2897 : }
2898 :
2899 44404720 : if (t->tt & A1_FLAG_OPTIONAL) {
2900 3194155 : void **pfel = (void **)fel;
2901 3194155 : if (*pfel == NULL)
2902 2194553 : break;
2903 999602 : fel = *pfel;
2904 :
2905 999602 : tel = *ptel = calloc(1, size);
2906 999602 : if (tel == NULL)
2907 0 : return ENOMEM;
2908 : }
2909 :
2910 44208032 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
2911 1997865 : (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2912 41210527 : ret = _asn1_copy(t->ptr, fel, tel);
2913 999640 : } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) {
2914 1415 : const struct asn1_type_func *f = t->ptr;
2915 1415 : ret = (f->copy)(fel, tel);
2916 : } else {
2917 998225 : const struct asn1_type_func *f = t->ptr;
2918 :
2919 : /* A1_OP_TYPE_DECORATE_EXTERN */
2920 998225 : if (f && f->copy)
2921 0 : ret = (f->copy)(fel, tel);
2922 998225 : else if (f)
2923 998225 : memset(tel, 0, f->size);
2924 : }
2925 :
2926 42210167 : if (ret) {
2927 0 : if (t->tt & A1_FLAG_OPTIONAL) {
2928 0 : free(*ptel);
2929 0 : *ptel = NULL;
2930 : }
2931 0 : return ret;
2932 : }
2933 42210167 : break;
2934 : }
2935 47509823 : case A1_OP_PARSE: {
2936 47509823 : unsigned int type = A1_PARSE_TYPE(t->tt);
2937 47509823 : const void *fel = DPOC(from, t->offset);
2938 47509823 : void *tel = DPO(to, t->offset);
2939 :
2940 47509823 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2941 0 : ABORT_ON_ERROR();
2942 : return ASN1_PARSE_ERROR;
2943 : }
2944 47509823 : ret = (asn1_template_prim[type].copy)(fel, tel);
2945 47509823 : if (ret)
2946 0 : return ret;
2947 47509823 : break;
2948 : }
2949 141254038 : case A1_OP_TAG: {
2950 141254038 : const void *oldfrom = from;
2951 141254038 : void *oldto = to;
2952 141254038 : void **tel = NULL;
2953 :
2954 141254038 : from = DPOC(from, t->offset);
2955 141254038 : to = DPO(to, t->offset);
2956 :
2957 141254038 : if (t->tt & A1_FLAG_OPTIONAL) {
2958 11155446 : void **fel = (void **)from;
2959 11155446 : tel = (void **)to;
2960 11155446 : if (*fel == NULL) {
2961 6129520 : from = oldfrom;
2962 6129520 : to = oldto;
2963 6129520 : break;
2964 : }
2965 5025926 : from = *fel;
2966 :
2967 5025926 : to = *tel = calloc(1, _asn1_sizeofType(t->ptr));
2968 5025926 : if (to == NULL)
2969 0 : return ENOMEM;
2970 : }
2971 :
2972 135124518 : ret = _asn1_copy(t->ptr, from, to);
2973 135124518 : if (ret) {
2974 0 : if (tel) {
2975 0 : free(*tel);
2976 0 : *tel = NULL;
2977 : }
2978 0 : return ret;
2979 : }
2980 :
2981 135124518 : from = oldfrom;
2982 135124518 : to = oldto;
2983 :
2984 135124518 : break;
2985 : }
2986 8603710 : case A1_OP_SETOF:
2987 : case A1_OP_SEQOF: {
2988 8603710 : const struct template_of *fel = DPOC(from, t->offset);
2989 8603710 : struct template_of *tel = DPO(to, t->offset);
2990 8603710 : size_t ellen = _asn1_sizeofType(t->ptr);
2991 : unsigned int i;
2992 :
2993 8603710 : tel->val = calloc(fel->len, ellen);
2994 8603710 : if (tel->val == NULL)
2995 0 : return ENOMEM;
2996 :
2997 8603710 : tel->len = fel->len;
2998 :
2999 19244591 : for (i = 0; i < fel->len; i++) {
3000 21281762 : ret = _asn1_copy(t->ptr,
3001 10640881 : DPOC(fel->val, (i * ellen)),
3002 10640881 : DPO(tel->val, (i *ellen)));
3003 10640881 : if (ret)
3004 0 : return ret;
3005 : }
3006 8603710 : break;
3007 : }
3008 1215621 : case A1_OP_BMEMBER: {
3009 1215621 : const struct asn1_template *bmember = t->ptr;
3010 1215621 : size_t size = bmember->offset;
3011 1215621 : memcpy(to, from, size);
3012 1215621 : break;
3013 : }
3014 1002123 : case A1_OP_CHOICE: {
3015 1002123 : const struct asn1_template *choice = t->ptr;
3016 1002123 : const unsigned int *felement = DPOC(from, choice->offset);
3017 1002123 : unsigned int *telement = DPO(to, choice->offset);
3018 :
3019 1002123 : if (*felement > A1_HEADER_LEN(choice))
3020 0 : return ASN1_PARSE_ERROR;
3021 :
3022 1002123 : *telement = *felement;
3023 :
3024 1002123 : if (*felement == 0) {
3025 0 : ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt));
3026 : } else {
3027 1002123 : choice += *felement;
3028 2004246 : ret = _asn1_copy(choice->ptr,
3029 1002123 : DPOC(from, choice->offset),
3030 1002123 : DPO(to, choice->offset));
3031 : }
3032 1002123 : if (ret)
3033 0 : return ret;
3034 1002123 : break;
3035 : }
3036 0 : default:
3037 0 : ABORT_ON_ERROR();
3038 : break;
3039 : }
3040 326247908 : t++;
3041 326247908 : elements--;
3042 : }
3043 199833708 : return 0;
3044 : }
3045 :
3046 : int
3047 1135473 : _asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size)
3048 : {
3049 : int ret;
3050 1135473 : memset(data, 0, t->offset);
3051 1135473 : ret = _asn1_decode(t, flags, p, len, data, size);
3052 1135473 : if (ret)
3053 118920 : _asn1_free_top(t, data);
3054 :
3055 1135473 : return ret;
3056 : }
3057 :
3058 : int
3059 11854768 : _asn1_copy_top(const struct asn1_template *t, const void *from, void *to)
3060 : {
3061 : int ret;
3062 11854768 : memset(to, 0, t->offset);
3063 11854768 : ret = _asn1_copy(t, from, to);
3064 11854768 : if (ret)
3065 0 : _asn1_free_top(t, to);
3066 :
3067 11854768 : return ret;
3068 : }
3069 :
3070 : void
3071 11918864 : _asn1_free_top(const struct asn1_template *t, void *data)
3072 : {
3073 11918864 : _asn1_free(t, data);
3074 11918864 : memset(data, 0, t->offset);
3075 11918864 : }
|