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 115697212 : _asn1_sizeofType(const struct asn1_template *t)
97 : {
98 115697212 : 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 5963645 : _asn1_bmember_get_bit(const unsigned char *p, void *data,
113 : unsigned int bit, size_t size)
114 : {
115 5963645 : unsigned int localbit = bit % 8;
116 5963645 : if ((*p >> (7 - localbit)) & 1) {
117 : #ifdef WORDS_BIGENDIAN
118 : *(unsigned int *)data |= (1u << ((size * 8) - bit - 1));
119 : #else
120 987382 : *(unsigned int *)data |= (1u << bit);
121 : #endif
122 : }
123 5755970 : }
124 :
125 : int
126 7231483 : _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 7231483 : if ((*(unsigned int *)data) & (1u << bit))
134 1200728 : return 1;
135 5824635 : return 0;
136 : #endif
137 : }
138 :
139 : void
140 7231483 : _asn1_bmember_put_bit(unsigned char *p, const void *data, unsigned int bit,
141 : size_t size, unsigned int *bitset)
142 : {
143 7231483 : unsigned int localbit = bit % 8;
144 :
145 7231483 : if (_asn1_bmember_isset_bit(data, bit, size)) {
146 1200728 : *p |= (1u << (7 - localbit));
147 1200728 : if (*bitset == 0)
148 442877 : *bitset = (7 - localbit) + 1;
149 : }
150 7231483 : }
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 5457 : is_tagged(const struct asn1_template *t)
159 : {
160 5457 : size_t elements = A1_HEADER_LEN(t);
161 :
162 5457 : t += A1_HEADER_LEN(t);
163 5457 : if (elements != 1)
164 0 : return 0;
165 5457 : 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 3512 : case A1_OP_TAG: return 1;
171 0 : case A1_OP_CHOICE: return 1;
172 1945 : 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 893 : inner_type_taglen(const struct asn1_template *t)
191 : {
192 893 : size_t elements = A1_HEADER_LEN(t);
193 :
194 893 : t += A1_HEADER_LEN(t);
195 893 : if (elements != 1)
196 0 : return 0;
197 893 : 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 291 : case A1_OP_TYPE: return inner_type_taglen(t->ptr);
204 602 : 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 8692 : template4member(const struct asn1_template *t, size_t f)
264 : {
265 8692 : size_t n = (uintptr_t)t->ptr;
266 368 : size_t i;
267 :
268 21246 : for (i = 0, t++; i < n; t++, i++) {
269 21246 : switch (t->tt & A1_OP_MASK) {
270 17142 : case A1_OP_TAG:
271 : case A1_OP_TYPE:
272 : case A1_OP_TYPE_EXTERN:
273 17142 : if (f-- == 0)
274 8692 : return t;
275 8450 : continue;
276 0 : case A1_OP_OPENTYPE_OBJSET:
277 : case A1_OP_NAME:
278 0 : return NULL;
279 4104 : default:
280 4104 : 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 2916 : _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 2916 : const struct asn1_template *ttypeid_univ = ttypeid;
371 184 : const struct asn1_template *tactual_type;
372 2916 : const struct asn1_template *tos = t->ptr;
373 184 : size_t sz, n;
374 2916 : size_t i = 0;
375 2916 : unsigned int *lenp = NULL; /* Pointer to array length field */
376 2916 : unsigned int len = 1; /* Array length */
377 2916 : void **dp = NULL; /* Decoded open type struct pointer */
378 184 : int *elementp; /* Choice enum pointer */
379 2916 : int typeid_is_oid = 0;
380 2916 : int typeid_is_int = 0;
381 2916 : 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 2916 : elementp = DPO(data, t->offset);
420 2916 : *elementp = 0; /* Set the choice to choice_<type>_iosnumunknown */
421 2916 : 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 2916 : dp = DPO(data, t->offset + sizeof(*elementp));
489 : }
490 :
491 : /* Align `dp' */
492 3100 : while (sizeof(void *) != sizeof(*elementp) &&
493 5832 : ((uintptr_t)dp) % sizeof(void *) != 0)
494 2916 : dp = (void *)(((char *)dp) + sizeof(*elementp));
495 2916 : *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 2916 : while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
504 2916 : A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
505 2732 : ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
506 0 : ttypeid_univ = ttypeid_univ->ptr;
507 0 : ttypeid_univ++;
508 : }
509 2916 : switch (ttypeid_univ->tt & A1_OP_MASK) {
510 2916 : case A1_OP_TAG:
511 2916 : if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV)
512 0 : return 0; /* Do nothing, silently */
513 2916 : switch (A1_TAG_TAG(ttypeid_univ->tt)) {
514 2732 : case UT_OID:
515 2732 : typeid_is_oid = 1;
516 2732 : 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 2916 : 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 2916 : if (t->tt & A1_OS_IS_SORTED) {
565 2916 : size_t left = 0;
566 2916 : size_t right = A1_HEADER_LEN(tos);
567 2916 : const void *vp = DPO(data, ttypeid->offset);
568 2916 : int c = -1;
569 :
570 10011 : while (left < right) {
571 9419 : size_t mid = (left + right) >> 1;
572 :
573 9419 : if ((tos[3 + mid * 3].tt & A1_OP_MASK) != A1_OP_OPENTYPE_ID)
574 0 : return 0;
575 9419 : if (typeid_is_int)
576 0 : c = typeid_int_cmp(vp, (intptr_t)tos[3 + mid * 3].ptr,
577 : ttypeid_univ);
578 9419 : else if (typeid_is_oid)
579 9419 : c = der_heim_oid_cmp(vp, tos[3 + mid * 3].ptr);
580 9419 : if (c < 0) {
581 3119 : right = mid;
582 6108 : } else if (c > 0) {
583 3504 : left = mid + 1;
584 : } else {
585 2188 : i = mid;
586 2188 : break;
587 : }
588 : }
589 2916 : if (c)
590 544 : 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 2324 : *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 2324 : tactual_type = &tos[i*3 + 4];
619 :
620 : /* Decode the encoded open type value(s) */
621 2324 : 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 2324 : const struct heim_base_data *d = DPOC(data, topentype->offset);
637 136 : void *o;
638 :
639 2324 : if (d->data && d->length) {
640 2324 : if ((o = calloc(1, tactual_type->offset)) == NULL)
641 0 : return ENOMEM;
642 :
643 : /* Re-enter to decode the encoded open type value */
644 2324 : 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 2324 : 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 2324 : *dp = o;
669 : }
670 : }
671 2324 : return ret;
672 : } else {
673 0 : const struct heim_base_data * const *d;
674 0 : 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 50550725 : _asn1_decode(const struct asn1_template *t, unsigned flags,
725 : const unsigned char *p, size_t len, void *data, size_t *size)
726 : {
727 50550725 : const struct asn1_template *tbase = t;
728 50550725 : const struct asn1_template *tdefval = NULL;
729 50550725 : size_t elements = A1_HEADER_LEN(t);
730 50550725 : size_t oldlen = len;
731 50550725 : int ret = 0;
732 50550725 : const unsigned char *startp = NULL;
733 50550725 : 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 50550725 : t++;
760 :
761 50550725 : if (template_flags & A1_HF_PRESERVE)
762 150744 : startp = p;
763 :
764 131399938 : while (elements) {
765 81062856 : switch (t->tt & A1_OP_MASK) {
766 2916 : case A1_OP_OPENTYPE_OBJSET: {
767 2916 : size_t opentypeid = t->tt & ((1<<10)-1);
768 2916 : size_t opentype = (t->tt >> 10) & ((1<<10)-1);
769 :
770 : /* Note that the only error returned here would be ENOMEM */
771 2916 : ret = _asn1_decode_open_type(t, flags, data,
772 : template4member(tbase, opentypeid),
773 : template4member(tbase, opentype));
774 2916 : if (ret)
775 0 : return ret;
776 2732 : break;
777 : }
778 0 : case A1_OP_TYPE_DECORATE_EXTERN: break;
779 0 : case A1_OP_TYPE_DECORATE: break;
780 18987429 : case A1_OP_NAME: break;
781 3145 : case A1_OP_DEFVAL:
782 3145 : tdefval = t;
783 3145 : break;
784 12487659 : case A1_OP_TYPE:
785 : case A1_OP_TYPE_EXTERN: {
786 444995 : size_t newsize, elsize;
787 12487659 : void *el = DPO(data, t->offset);
788 12487659 : void **pel = (void **)el;
789 :
790 12487659 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
791 12484618 : elsize = _asn1_sizeofType(t->ptr);
792 : } else {
793 3041 : const struct asn1_type_func *f = t->ptr;
794 3041 : elsize = f->size;
795 : }
796 :
797 12487659 : if (t->tt & A1_FLAG_OPTIONAL) {
798 1987 : *pel = calloc(1, elsize);
799 1987 : if (*pel == NULL)
800 74 : return ENOMEM;
801 1987 : el = *pel;
802 1987 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
803 149 : ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
804 : } else {
805 1838 : const struct asn1_type_func *f = t->ptr;
806 1838 : ret = (f->decode)(p, len, el, &newsize);
807 : }
808 1987 : if (ret) {
809 : /*
810 : * Optional field not present in encoding, presumably,
811 : * though we should really look more carefully at `ret'.
812 : */
813 269 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
814 35 : _asn1_free(t->ptr, el);
815 : } else {
816 234 : const struct asn1_type_func *f = t->ptr;
817 234 : f->release(el);
818 : }
819 269 : free(*pel);
820 269 : *pel = NULL;
821 12487585 : break;
822 : }
823 : } else {
824 12485672 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
825 12484469 : ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
826 : } else {
827 1203 : const struct asn1_type_func *f = t->ptr;
828 1203 : ret = (f->decode)(p, len, el, &newsize);
829 : }
830 : }
831 12487390 : if (ret) {
832 74 : if (t->tt & A1_FLAG_OPTIONAL) {
833 74 : } 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 74 : return ret; /* Error decoding required field */
868 : }
869 12487316 : p += newsize; len -= newsize;
870 :
871 12487316 : break;
872 : }
873 34719825 : case A1_OP_TAG: {
874 1234303 : Der_type dertype;
875 34719825 : size_t newsize = 0;
876 34719825 : size_t datalen, l = 0;
877 34719825 : void *olddata = data;
878 34719825 : int is_indefinite = 0;
879 34719825 : int subflags = flags;
880 34719825 : int replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
881 34719825 : void *el = data = DPO(data, t->offset);
882 34719825 : 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 34719825 : ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt),
895 33485522 : &dertype, A1_TAG_TAG(t->tt),
896 : &datalen, &l);
897 34719825 : if (ret) {
898 1872412 : if (t->tt & A1_FLAG_OPTIONAL) {
899 1614506 : data = olddata;
900 34506256 : break;
901 200192 : } else if (t->tt & A1_FLAG_DEFAULT) {
902 2640 : if (!tdefval)
903 213569 : 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 2640 : if (tdefval->tt & A1_DV_BOOLEAN) {
909 2640 : int *i = (void *)(char *)data;
910 :
911 2640 : *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 2456 : data = olddata;
934 2456 : break;
935 : }
936 197552 : return ret; /* Error decoding required field */
937 : }
938 :
939 32847413 : 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 32847413 : 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 32847413 : 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 32847413 : } else if (datalen > len)
965 0 : return ASN1_OVERRUN;
966 :
967 32847413 : if (t->tt & A1_FLAG_OPTIONAL) {
968 2104682 : size_t ellen = _asn1_sizeofType(t->ptr);
969 :
970 2104682 : *pel = calloc(1, ellen);
971 2104682 : if (*pel == NULL)
972 0 : return ENOMEM;
973 2028586 : data = *pel;
974 : }
975 :
976 32847413 : if (replace_tag) {
977 1695 : const struct asn1_template *subtype = t->ptr;
978 1695 : 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 3734 : while (!have_tag) {
989 2039 : subtype++;
990 2039 : if ((subtype->tt & A1_OP_MASK) == A1_OP_TAG)
991 1695 : replace_tag = (subtype->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
992 1935 : if (replace_tag) {
993 344 : subtype = subtype->ptr;
994 344 : continue;
995 : }
996 1695 : if ((subtype->tt & A1_OP_MASK) == A1_OP_TAG) {
997 1695 : ret = _asn1_decode(subtype->ptr, subflags, p, datalen, data, &newsize);
998 1695 : have_tag = 1;
999 : } else {
1000 0 : subtype = subtype->ptr;
1001 : }
1002 : }
1003 : } else {
1004 32845718 : ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize);
1005 : }
1006 32847413 : if (ret == 0 && !is_indefinite && newsize != datalen)
1007 : /* Hidden data */
1008 0 : ret = ASN1_EXTRA_DATA;
1009 :
1010 32847413 : if (ret == 0) {
1011 32831396 : if (is_indefinite) {
1012 : /* If we use indefinite encoding, the newsize is the datasize. */
1013 0 : datalen = newsize;
1014 : }
1015 :
1016 32831396 : len -= datalen;
1017 32831396 : p += datalen;
1018 :
1019 : /*
1020 : * Indefinite encoding needs a trailing EndOfContent,
1021 : * check for that.
1022 : */
1023 32831396 : 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 32847413 : if (ret) {
1037 16017 : if (!(t->tt & A1_FLAG_OPTIONAL))
1038 15432 : return ret;
1039 :
1040 0 : _asn1_free(t->ptr, data);
1041 0 : free(data);
1042 0 : *pel = NULL;
1043 0 : return ret;
1044 : }
1045 31663265 : data = olddata;
1046 :
1047 31663265 : break;
1048 : }
1049 11494937 : case A1_OP_PARSE: {
1050 11494937 : unsigned int type = A1_PARSE_TYPE(t->tt);
1051 410549 : size_t newsize;
1052 11494937 : 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 11494937 : if (flags & A1_PF_INDEFINTE)
1059 0 : type++;
1060 :
1061 11494937 : 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 11494937 : ret = (asn1_template_prim[type].decode)(p, len, el, &newsize);
1067 11494937 : if (ret)
1068 0 : return ret;
1069 11494937 : p += newsize; len -= newsize;
1070 :
1071 11494937 : break;
1072 : }
1073 2139030 : case A1_OP_SETOF:
1074 : case A1_OP_SEQOF: {
1075 2139030 : struct template_of *el = DPO(data, t->offset);
1076 76730 : size_t newsize;
1077 2139030 : size_t ellen = _asn1_sizeofType(t->ptr);
1078 2139030 : size_t vallength = 0;
1079 :
1080 5646983 : while (len > 0) {
1081 126949 : void *tmp;
1082 3507953 : size_t newlen = vallength + ellen;
1083 3507953 : if (vallength > newlen)
1084 0 : return ASN1_OVERFLOW;
1085 :
1086 : /* XXX Slow */
1087 3507953 : tmp = realloc(el->val, newlen);
1088 3507953 : if (tmp == NULL)
1089 0 : return ENOMEM;
1090 :
1091 3507953 : memset(DPO(tmp, vallength), 0, ellen);
1092 3507953 : el->val = tmp;
1093 :
1094 3507953 : el->len++;
1095 3507953 : ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len,
1096 3381004 : DPO(el->val, vallength), &newsize);
1097 3507953 : if (ret)
1098 0 : return ret;
1099 3507953 : vallength = newlen;
1100 3507953 : p += newsize; len -= newsize;
1101 : }
1102 :
1103 2139030 : break;
1104 : }
1105 434063 : case A1_OP_BMEMBER: {
1106 434063 : const struct asn1_template *bmember = t->ptr;
1107 434063 : size_t bsize = bmember->offset;
1108 434063 : size_t belements = A1_HEADER_LEN(bmember);
1109 434063 : size_t pos = 0;
1110 :
1111 434063 : bmember++;
1112 :
1113 434063 : memset(data, 0, bsize);
1114 :
1115 434063 : if (len < 1)
1116 0 : return ASN1_OVERRUN;
1117 434063 : p++; len--;
1118 :
1119 6398233 : while (belements && len) {
1120 6824169 : while (bmember->offset / 8 > pos / 8) {
1121 859999 : if (len < 1)
1122 0 : break;
1123 859999 : p++; len--;
1124 859999 : pos += 8;
1125 : }
1126 5964170 : if (len) {
1127 5963645 : _asn1_bmember_get_bit(p, data, bmember->offset, bsize);
1128 5963645 : belements--; bmember++;
1129 : }
1130 : }
1131 419116 : len = 0;
1132 419116 : break;
1133 : }
1134 95685 : case A1_OP_CHOICE: {
1135 95685 : const struct asn1_template *choice = t->ptr;
1136 95685 : unsigned int *element = DPO(data, choice->offset);
1137 3756 : size_t datalen;
1138 3756 : 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 95685 : *element = ~0;
1147 :
1148 110538 : 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 115253 : ret = _asn1_decode(choice[i].ptr, 0, p, len,
1167 110537 : DPO(data, choice[i].offset), &datalen);
1168 110537 : if (ret == 0) {
1169 95684 : *element = i;
1170 95684 : p += datalen; len -= datalen;
1171 95684 : break;
1172 : }
1173 14853 : _asn1_free(choice[i].ptr, DPO(data, choice[i].offset));
1174 14853 : if (ret != ASN1_BAD_ID && ret != ASN1_MISPLACED_FIELD &&
1175 : ret != ASN1_MISSING_FIELD)
1176 0 : return ret;
1177 : }
1178 95685 : if (i >= A1_HEADER_LEN(choice) + 1 || !choice[i].tt) {
1179 : /*
1180 : * If this is an extensible CHOICE, then choice->tt will be the
1181 : * offset to u.ellipsis. If it's not, then this "extension" is
1182 : * an error and must stop parsing it. (We could be permissive
1183 : * and throw away the extension, though one might as well just
1184 : * mark such a CHOICE as extensible.)
1185 : */
1186 1 : if (choice->tt == 0)
1187 0 : return ASN1_BAD_ID;
1188 :
1189 : /* This is the ellipsis case */
1190 1 : *element = 0;
1191 1 : ret = der_get_octet_string(p, len,
1192 1 : DPO(data, choice->tt), &datalen);
1193 1 : if (ret)
1194 0 : return ret;
1195 1 : p += datalen; len -= datalen;
1196 : }
1197 :
1198 95685 : break;
1199 : }
1200 0 : default:
1201 0 : ABORT_ON_ERROR();
1202 : return ASN1_PARSE_ERROR;
1203 : }
1204 80849213 : t++;
1205 80849213 : elements--;
1206 : }
1207 : /* if we are using padding, eat up read of context */
1208 50337082 : if (template_flags & A1_HF_ELLIPSIS)
1209 176958 : len = 0;
1210 :
1211 50337082 : oldlen -= len;
1212 :
1213 50337082 : if (size)
1214 49780040 : *size = oldlen;
1215 :
1216 : /*
1217 : * saved the raw bits if asked for it, useful for signature
1218 : * verification.
1219 : */
1220 50337082 : if (startp) {
1221 150744 : heim_octet_string *save = data;
1222 :
1223 150744 : save->data = malloc(oldlen);
1224 150744 : if (save->data == NULL)
1225 0 : return ENOMEM;
1226 : else {
1227 150744 : save->length = oldlen;
1228 150744 : memcpy(save->data, startp, oldlen);
1229 : }
1230 : }
1231 48542965 : return 0;
1232 : }
1233 :
1234 : /*
1235 : * This should be called with a `A1_TAG_T(ASN1_C_UNIV, PRIM, UT_Integer)'
1236 : * template as the `ttypeid'.
1237 : */
1238 : static int
1239 0 : typeid_int_copy(void *intp,
1240 : int64_t i,
1241 : const struct asn1_template *ttypeid)
1242 : {
1243 0 : const struct asn1_template *tint = ttypeid->ptr;
1244 :
1245 0 : if ((tint[1].tt & A1_OP_MASK) != A1_OP_PARSE)
1246 0 : return -1;
1247 0 : if (A1_PARSE_TYPE(tint[1].tt) != A1T_INTEGER)
1248 0 : return -1;
1249 0 : switch (tint[0].offset) {
1250 0 : case 8: *((int64_t *)intp) = i; return 0;
1251 0 : case 4: *((int32_t *)intp) = i; return 0;
1252 0 : default: memset(intp, 0, tint[0].offset); return 0;
1253 : }
1254 : }
1255 :
1256 : /* See commentary in _asn1_decode_open_type() */
1257 : static int
1258 715 : _asn1_encode_open_type(const struct asn1_template *t,
1259 : const void *data, /* NOTE: Not really const */
1260 : const struct asn1_template *ttypeid,
1261 : const struct asn1_template *topentype)
1262 : {
1263 715 : const struct asn1_template *ttypeid_univ = ttypeid;
1264 0 : const struct asn1_template *tactual_type;
1265 715 : const struct asn1_template *tos = t->ptr;
1266 0 : size_t sz, i;
1267 715 : unsigned int *lenp = NULL;
1268 715 : unsigned int len = 1;
1269 715 : int element = *(const int *)DPOC(data, t->offset);
1270 715 : int typeid_is_oid = 0;
1271 715 : int typeid_is_int = 0;
1272 715 : int enotsup = 0;
1273 715 : int ret = 0;
1274 :
1275 715 : if (element == 0 || element >= A1_HEADER_LEN(tos) + 1)
1276 195 : return 0;
1277 :
1278 520 : if (t->tt & A1_OS_OT_IS_ARRAY) {
1279 : /* The actual `len' is from the decoded open type field */
1280 0 : len = *(const unsigned int *)DPOC(data, t->offset + sizeof(element));
1281 :
1282 0 : if (!len)
1283 0 : return 0; /* The app may be encoding the open type by itself */
1284 : }
1285 :
1286 : /* Work out the type ID field's type */
1287 520 : while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
1288 520 : A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
1289 520 : ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
1290 0 : ttypeid_univ = ttypeid_univ->ptr;
1291 0 : ttypeid_univ++;
1292 : }
1293 520 : switch (ttypeid_univ->tt & A1_OP_MASK) {
1294 520 : case A1_OP_TAG:
1295 520 : if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV) {
1296 0 : enotsup = 1;
1297 0 : break;
1298 : }
1299 520 : switch (A1_TAG_TAG(ttypeid_univ->tt)) {
1300 520 : case UT_OID:
1301 520 : typeid_is_oid = 1;
1302 520 : break;
1303 0 : case UT_Integer: {
1304 0 : const struct asn1_template *tint = ttypeid_univ->ptr;
1305 :
1306 0 : tint++;
1307 0 : if ((tint->tt & A1_OP_MASK) != A1_OP_PARSE ||
1308 0 : A1_PARSE_TYPE(tint->tt) != A1T_INTEGER) {
1309 0 : enotsup = 1;
1310 0 : break;
1311 : }
1312 0 : typeid_is_int = 1;
1313 0 : break;
1314 : }
1315 0 : default: enotsup = 1; break;
1316 : }
1317 520 : break;
1318 0 : default: enotsup = 1; break;
1319 : }
1320 :
1321 : /*
1322 : * The app may not be aware of our automatic open type handling, so if the
1323 : * open type already appears to have been encoded, then ignore the decoded
1324 : * values.
1325 : */
1326 520 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
1327 520 : struct heim_base_data *os = DPO(data, topentype->offset);
1328 :
1329 520 : if (os->length && os->data)
1330 520 : return 0;
1331 : } else {
1332 0 : struct heim_base_data **os = DPO(data, topentype->offset + sizeof(len));
1333 :
1334 0 : while (sizeof(void *) != sizeof(unsigned int) &&
1335 0 : ((uintptr_t)os) % sizeof(void *) != 0)
1336 0 : os = (void *)(((char *)os) + sizeof(unsigned int));
1337 :
1338 0 : lenp = DPO(data, topentype->offset);
1339 0 : if (*lenp == len && os[0]->length && os[0]->data)
1340 0 : return 0;
1341 : }
1342 :
1343 0 : if (typeid_is_int) {
1344 : /*
1345 : * Copy the int from the type ID object field to the type ID struct
1346 : * field.
1347 : */
1348 0 : ret = typeid_int_copy(DPO(data, ttypeid->offset),
1349 0 : (intptr_t)tos[3 + (element-1)*3].ptr, ttypeid_univ);
1350 0 : } else if (typeid_is_oid) {
1351 : /*
1352 : * Copy the OID from the type ID object field to the type ID struct
1353 : * field.
1354 : */
1355 0 : ret = der_copy_oid(tos[3 + (element-1)*3].ptr, DPO(data, ttypeid->offset));
1356 : } else
1357 0 : enotsup = 1;
1358 :
1359 : /*
1360 : * If the app did not already encode the open type, we can't help it if we
1361 : * don't know what it is.
1362 : */
1363 0 : if (enotsup)
1364 0 : return ENOTSUP;
1365 :
1366 0 : tactual_type = &tos[(element-1)*3 + 4];
1367 :
1368 0 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
1369 0 : struct heim_base_data *os = DPO(data, topentype->offset);
1370 0 : const void * const *d = DPOC(data, t->offset + sizeof(element));
1371 :
1372 0 : while (sizeof(void *) != sizeof(element) &&
1373 0 : ((uintptr_t)d) % sizeof(void *) != 0) {
1374 0 : d = (void *)(((char *)d) + sizeof(element));
1375 : }
1376 :
1377 0 : os->length = _asn1_length(tactual_type->ptr, *d);
1378 0 : if ((os->data = malloc(os->length)) == NULL)
1379 0 : return ENOMEM;
1380 0 : ret = _asn1_encode(tactual_type->ptr, (os->length - 1) + (unsigned char *)os->data, os->length, *d, &sz);
1381 : } else {
1382 0 : struct heim_base_data *os;
1383 0 : const void * const *val =
1384 0 : DPOC(data, t->offset + sizeof(element) + sizeof(*lenp));
1385 :
1386 0 : if ((os = calloc(len, sizeof(*os))) == NULL)
1387 0 : return ENOMEM;
1388 :
1389 0 : *lenp = len;
1390 0 : for (i = 0; ret == 0 && i < len; i++) {
1391 0 : os[i].length = _asn1_length(tactual_type->ptr, val[i]);
1392 0 : if ((os[i].data = malloc(os[i].length)) == NULL)
1393 0 : ret = ENOMEM;
1394 0 : if (ret == 0)
1395 0 : ret = _asn1_encode(tactual_type->ptr, (os[i].length - 1) + (unsigned char *)os[i].data, os[i].length,
1396 0 : val[i], &sz);
1397 : }
1398 0 : if (ret) {
1399 0 : for (i = 0; i < (*lenp); i++)
1400 0 : free(os[i].data);
1401 0 : free(os);
1402 0 : *lenp = 0;
1403 0 : return ret;
1404 : }
1405 0 : *(struct heim_base_data **)DPO(data, topentype->offset + sizeof(len)) = os;
1406 : }
1407 0 : return ret;
1408 : }
1409 :
1410 : int
1411 56043429 : _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const void *data, size_t *size)
1412 : {
1413 56043429 : const struct asn1_template *tbase = t;
1414 56043429 : size_t elements = A1_HEADER_LEN(t);
1415 56043429 : int ret = 0;
1416 56043429 : size_t oldlen = len;
1417 :
1418 56043429 : t += A1_HEADER_LEN(t);
1419 :
1420 146317882 : while (elements) {
1421 90274453 : switch (t->tt & A1_OP_MASK) {
1422 715 : case A1_OP_OPENTYPE_OBJSET: {
1423 715 : size_t opentypeid = t->tt & ((1<<10)-1);
1424 715 : size_t opentype = (t->tt >> 10) & ((1<<10)-1);
1425 715 : ret = _asn1_encode_open_type(t, data,
1426 : template4member(tbase, opentypeid),
1427 : template4member(tbase, opentype));
1428 715 : if (ret)
1429 0 : return ret;
1430 715 : break;
1431 : }
1432 21166215 : case A1_OP_NAME: break;
1433 715 : case A1_OP_DEFVAL: break;
1434 0 : case A1_OP_TYPE_DECORATE_EXTERN: break;
1435 0 : case A1_OP_TYPE_DECORATE: break;
1436 14025808 : case A1_OP_TYPE:
1437 : case A1_OP_TYPE_EXTERN: {
1438 500316 : size_t newsize;
1439 14025808 : const void *el = DPOC(data, t->offset);
1440 :
1441 14025808 : if (t->tt & A1_FLAG_OPTIONAL) {
1442 2729 : void **pel = (void **)el;
1443 2729 : if (*pel == NULL)
1444 13525492 : break;
1445 2088 : el = *pel;
1446 14023079 : } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
1447 0 : const struct asn1_template *tdefval = t - 1;
1448 : /* Compare tdefval to whatever's at `el' */
1449 0 : if (tdefval->tt & A1_DV_BOOLEAN) {
1450 0 : const int *i = (void *)(char *)el;
1451 :
1452 0 : if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
1453 : break;
1454 0 : } else if (tdefval->tt & A1_DV_INTEGER64) {
1455 0 : const int64_t *i = (void *)(char *)el;
1456 :
1457 0 : if (*i == (int64_t)(intptr_t)tdefval->ptr)
1458 0 : break;
1459 0 : } else if (tdefval->tt & A1_DV_INTEGER32) {
1460 0 : const int32_t *i = (void *)(char *)el;
1461 :
1462 0 : if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
1463 0 : (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
1464 0 : *i == (int32_t)(intptr_t)tdefval->ptr)
1465 0 : break;
1466 0 : } else if (tdefval->tt & A1_DV_INTEGER) {
1467 0 : const struct heim_integer *i = (void *)(char *)el;
1468 :
1469 0 : if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
1470 0 : break;
1471 0 : } else if (tdefval->tt & A1_DV_UTF8STRING) {
1472 0 : const char * const *s = el;
1473 :
1474 0 : if (*s && strcmp(*s, tdefval->ptr) == 0)
1475 0 : break;
1476 : } else {
1477 0 : abort();
1478 : }
1479 : }
1480 :
1481 14025167 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
1482 14019402 : ret = _asn1_encode(t->ptr, p, len, el, &newsize);
1483 : } else {
1484 5765 : const struct asn1_type_func *f = t->ptr;
1485 5765 : ret = (f->encode)(p, len, el, &newsize);
1486 : }
1487 :
1488 14025167 : if (ret)
1489 0 : return ret;
1490 14025167 : p -= newsize; len -= newsize;
1491 :
1492 14025167 : break;
1493 : }
1494 38530334 : case A1_OP_TAG: {
1495 38530334 : const void *olddata = data;
1496 38530334 : size_t l, datalen = 0;
1497 38530334 : int replace_tag = 0;
1498 :
1499 : /*
1500 : * XXX If this type (chasing t->ptr through IMPLICIT tags, if this
1501 : * one is too) till we find a non-TTag) is a [UNIVERSAL SET] type,
1502 : * then we have to sort [a copy of] its template by tag, then
1503 : * encode the SET using that sorted template. These SETs will
1504 : * generally be small, so when they are we might want to allocate
1505 : * the copy on the stack and insertion sort it. We'll need a
1506 : * utility function to do all of this.
1507 : */
1508 :
1509 38530334 : data = DPOC(data, t->offset);
1510 :
1511 38530334 : if (t->tt & A1_FLAG_OPTIONAL) {
1512 4305569 : void **el = (void **)data;
1513 4305569 : if (*el == NULL) {
1514 1794946 : data = olddata;
1515 38530334 : break;
1516 : }
1517 2358540 : data = *el;
1518 34224765 : } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
1519 715 : const struct asn1_template *tdefval = t - 1;
1520 715 : int exclude = 0;
1521 :
1522 : /* Compare tdefval to whatever's at `data' */
1523 715 : if (tdefval->tt & A1_DV_BOOLEAN) {
1524 715 : const int *i = (void *)(char *)data;
1525 :
1526 715 : if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
1527 715 : exclude = 1;
1528 0 : } else if (tdefval->tt & A1_DV_INTEGER64) {
1529 0 : const int64_t *i = (void *)(char *)data;
1530 :
1531 0 : if (*i == (int64_t)(intptr_t)tdefval->ptr)
1532 0 : exclude = 1;
1533 0 : } else if (tdefval->tt & A1_DV_INTEGER32) {
1534 0 : const int32_t *i = (void *)(char *)data;
1535 :
1536 0 : if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
1537 0 : (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
1538 0 : *i == (int32_t)(intptr_t)tdefval->ptr)
1539 0 : exclude = 1;
1540 0 : } else if (tdefval->tt & A1_DV_INTEGER) {
1541 0 : const struct heim_integer *i = (void *)(char *)data;
1542 :
1543 0 : if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
1544 0 : break;
1545 0 : } else if (tdefval->tt & A1_DV_UTF8STRING) {
1546 0 : const char * const *s = data;
1547 :
1548 0 : if (*s && strcmp(*s, tdefval->ptr) == 0)
1549 0 : exclude = 1;
1550 : } else {
1551 0 : abort();
1552 : }
1553 715 : if (exclude) {
1554 715 : data = olddata;
1555 715 : break;
1556 : }
1557 : }
1558 :
1559 36671605 : replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
1560 :
1561 : /* IMPLICIT tags need special handling (see gen_encode.c) */
1562 36671605 : if (replace_tag) {
1563 541 : unsigned char *pfree, *psave = p;
1564 0 : Der_class found_class;
1565 541 : Der_type found_type = 0;
1566 0 : unsigned int found_tag;
1567 541 : size_t lensave = len;
1568 541 : size_t oldtaglen = 0;
1569 541 : size_t taglen = der_length_tag(A1_TAG_TAG(t->tt));;
1570 :
1571 : /* Allocate a buffer at least as big as we need */
1572 541 : len = _asn1_length(t->ptr, data) + taglen;
1573 541 : if ((p = pfree = malloc(len)) == NULL) {
1574 0 : ret = ENOMEM;
1575 : } else {
1576 : /*
1577 : * Encode into it (with the wrong tag, which we'll replace
1578 : * below).
1579 : */
1580 541 : p += len - 1;
1581 541 : ret = _asn1_encode(t->ptr, p, len, data, &datalen);
1582 : }
1583 541 : if (ret == 0) {
1584 : /* Get the old tag and, critically, its length */
1585 541 : len -= datalen; p -= datalen;
1586 541 : ret = der_get_tag(p + 1, datalen, &found_class, &found_type,
1587 : &found_tag, &oldtaglen);
1588 : }
1589 541 : if (ret == 0) {
1590 : /* Drop the old tag */
1591 541 : len += oldtaglen; p += oldtaglen;
1592 : /* Put the new tag */
1593 541 : ret = der_put_tag(p, len,
1594 541 : A1_TAG_CLASS(t->tt),
1595 : found_type,
1596 541 : A1_TAG_TAG(t->tt), &l);
1597 : }
1598 541 : if (ret == 0) {
1599 : /* Copy the encoding where it belongs */
1600 541 : psave -= (datalen + l - oldtaglen);
1601 541 : lensave -= (datalen + l - oldtaglen);
1602 541 : memcpy(psave + 1, p + 1 - l, datalen + l - oldtaglen);
1603 541 : p = psave;
1604 541 : len = lensave;
1605 : }
1606 541 : free(pfree);
1607 : } else {
1608 : /* Easy case */
1609 36671064 : ret = _asn1_encode(t->ptr, p, len, data, &datalen);
1610 36671064 : if (ret)
1611 0 : return ret;
1612 :
1613 36671064 : len -= datalen; p -= datalen;
1614 :
1615 37981241 : ret = der_put_length_and_tag(p, len, datalen,
1616 36671064 : A1_TAG_CLASS(t->tt),
1617 36671064 : A1_TAG_TYPE(t->tt),
1618 36671064 : A1_TAG_TAG(t->tt), &l);
1619 36671064 : if (ret == 0) {
1620 36671064 : p -= l; len -= l;
1621 : }
1622 : }
1623 36671605 : if (ret)
1624 0 : return ret;
1625 :
1626 35361428 : data = olddata;
1627 :
1628 35361428 : break;
1629 : }
1630 12931540 : case A1_OP_PARSE: {
1631 12931540 : unsigned int type = A1_PARSE_TYPE(t->tt);
1632 462162 : size_t newsize;
1633 12931540 : const void *el = DPOC(data, t->offset);
1634 :
1635 12931540 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
1636 0 : ABORT_ON_ERROR();
1637 0 : return ASN1_PARSE_ERROR;
1638 : }
1639 :
1640 12931540 : ret = (asn1_template_prim[type].encode)(p, len, el, &newsize);
1641 12931540 : if (ret)
1642 0 : return ret;
1643 12931540 : p -= newsize; len -= newsize;
1644 :
1645 12931540 : break;
1646 : }
1647 2434 : case A1_OP_SETOF: {
1648 2434 : const struct template_of *el = DPOC(data, t->offset);
1649 2434 : size_t ellen = _asn1_sizeofType(t->ptr);
1650 0 : heim_octet_string *val;
1651 2434 : unsigned char *elptr = el->val;
1652 0 : size_t i, totallen;
1653 :
1654 2434 : if (el->len == 0)
1655 312 : break;
1656 :
1657 2122 : if (el->len > UINT_MAX/sizeof(val[0]))
1658 0 : return ERANGE;
1659 :
1660 2122 : val = calloc(el->len, sizeof(val[0]));
1661 2122 : if (val == NULL)
1662 0 : return ENOMEM;
1663 :
1664 4394 : for(totallen = 0, i = 0; i < el->len; i++) {
1665 0 : unsigned char *next;
1666 0 : size_t l;
1667 :
1668 2272 : val[i].length = _asn1_length(t->ptr, elptr);
1669 2272 : if (val[i].length) {
1670 2272 : val[i].data = malloc(val[i].length);
1671 2272 : if (val[i].data == NULL) {
1672 0 : ret = ENOMEM;
1673 0 : break;
1674 : }
1675 : }
1676 :
1677 2272 : ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1),
1678 2272 : val[i].length, elptr, &l);
1679 2272 : if (ret)
1680 0 : break;
1681 :
1682 2272 : next = elptr + ellen;
1683 2272 : if (next < elptr) {
1684 0 : ret = ASN1_OVERFLOW;
1685 0 : break;
1686 : }
1687 2272 : elptr = next;
1688 2272 : totallen += val[i].length;
1689 : }
1690 2122 : if (ret == 0 && totallen > len)
1691 0 : ret = ASN1_OVERFLOW;
1692 2122 : if (ret) {
1693 0 : for (i = 0; i < el->len; i++)
1694 0 : free(val[i].data);
1695 0 : free(val);
1696 0 : return ret;
1697 : }
1698 :
1699 2122 : len -= totallen;
1700 :
1701 2122 : qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort);
1702 :
1703 2122 : i = el->len - 1;
1704 0 : do {
1705 2272 : p -= val[i].length;
1706 2272 : memcpy(p + 1, val[i].data, val[i].length);
1707 2272 : free(val[i].data);
1708 2272 : } while(i-- > 0);
1709 2122 : free(val);
1710 :
1711 2122 : break;
1712 :
1713 : }
1714 2229402 : case A1_OP_SEQOF: {
1715 2229402 : struct template_of *el = DPO(data, t->offset);
1716 2229402 : size_t ellen = _asn1_sizeofType(t->ptr);
1717 80717 : size_t newsize;
1718 80717 : unsigned int i;
1719 2229402 : unsigned char *elptr = el->val;
1720 :
1721 2229402 : if (el->len == 0)
1722 2148685 : break;
1723 :
1724 2000764 : elptr += ellen * (el->len - 1);
1725 :
1726 5896889 : for (i = 0; i < el->len; i++) {
1727 3896125 : ret = _asn1_encode(t->ptr, p, len,
1728 : elptr,
1729 : &newsize);
1730 3896125 : if (ret)
1731 0 : return ret;
1732 3896125 : p -= newsize; len -= newsize;
1733 3896125 : elptr -= ellen;
1734 : }
1735 :
1736 1929573 : break;
1737 : }
1738 512829 : case A1_OP_BMEMBER: {
1739 512829 : const struct asn1_template *bmember = t->ptr;
1740 512829 : size_t bsize = bmember->offset;
1741 512829 : size_t belements = A1_HEADER_LEN(bmember);
1742 17809 : size_t pos;
1743 512829 : unsigned char c = 0;
1744 512829 : unsigned int bitset = 0;
1745 512829 : int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
1746 :
1747 512829 : bmember += belements;
1748 :
1749 512829 : if (rfc1510)
1750 495020 : pos = 31;
1751 : else
1752 0 : pos = bmember->offset;
1753 :
1754 7744312 : while (belements && len) {
1755 8769970 : while (bmember->offset / 8 < pos / 8) {
1756 1538487 : if (rfc1510 || bitset || c) {
1757 1538487 : if (len < 1)
1758 0 : return ASN1_OVERFLOW;
1759 1538487 : *p-- = c; len--;
1760 : }
1761 1538487 : c = 0;
1762 1538487 : pos -= 8;
1763 : }
1764 7231483 : _asn1_bmember_put_bit(&c, data, bmember->offset, bsize, &bitset);
1765 7231483 : belements--; bmember--;
1766 : }
1767 512829 : if (rfc1510 || bitset) {
1768 512829 : if (len < 1)
1769 0 : return ASN1_OVERFLOW;
1770 512829 : *p-- = c; len--;
1771 : }
1772 :
1773 512829 : if (len < 1)
1774 0 : return ASN1_OVERFLOW;
1775 512829 : if (rfc1510 || bitset == 0)
1776 512829 : *p-- = 0;
1777 : else
1778 0 : *p-- = bitset - 1;
1779 :
1780 512829 : len--;
1781 :
1782 512829 : break;
1783 : }
1784 94684 : case A1_OP_CHOICE: {
1785 94684 : const struct asn1_template *choice = t->ptr;
1786 94684 : const unsigned int *element = DPOC(data, choice->offset);
1787 3316 : size_t datalen;
1788 3316 : const void *el;
1789 :
1790 94684 : if (*element > A1_HEADER_LEN(choice)) {
1791 0 : printf("element: %d\n", *element);
1792 0 : return ASN1_PARSE_ERROR;
1793 : }
1794 :
1795 94684 : if (*element == 0) {
1796 0 : if (choice->tt) {
1797 : /* This is an extensible CHOICE */
1798 0 : ret += der_put_octet_string(p, len,
1799 0 : DPOC(data, choice->tt), &datalen);
1800 0 : len -= datalen; p -= datalen;
1801 : } /* else this is really an error -- XXX what to do? */
1802 : } else {
1803 94684 : choice += *element;
1804 94684 : el = DPOC(data, choice->offset);
1805 94684 : ret = _asn1_encode(choice->ptr, p, len, el, &datalen);
1806 94684 : if (ret)
1807 0 : return ret;
1808 94684 : len -= datalen; p -= datalen;
1809 : }
1810 :
1811 94684 : break;
1812 : }
1813 0 : default:
1814 0 : ABORT_ON_ERROR();
1815 : }
1816 90274453 : t--;
1817 90274453 : elements--;
1818 : }
1819 56043429 : if (size)
1820 56043429 : *size = oldlen - len;
1821 :
1822 54040597 : return 0;
1823 : }
1824 :
1825 : static size_t
1826 0 : _asn1_length_open_type_helper(const struct asn1_template *t,
1827 : size_t sz)
1828 : {
1829 0 : const struct asn1_template *tinner = t->ptr;
1830 :
1831 0 : switch (t->tt & A1_OP_MASK) {
1832 0 : case A1_OP_TAG:
1833 : /* XXX Not tail-recursive :( */
1834 0 : sz = _asn1_length_open_type_helper(tinner, sz);
1835 0 : sz += der_length_len(sz);
1836 0 : sz += der_length_tag(A1_TAG_TAG(t->tt));
1837 0 : return sz;
1838 0 : default:
1839 0 : return sz;
1840 : }
1841 : }
1842 :
1843 : static size_t
1844 0 : _asn1_length_open_type_id(const struct asn1_template *t,
1845 : const void *data)
1846 : {
1847 0 : struct asn1_template pretend[2] = {
1848 : { 0, 0, ((void*)(uintptr_t)1) },
1849 : };
1850 0 : pretend[1] = *t;
1851 0 : while ((t->tt & A1_OP_MASK) == A1_OP_TAG)
1852 0 : t = t->ptr;
1853 0 : pretend[0].offset = t->offset;
1854 0 : return _asn1_length(pretend, data);
1855 : }
1856 :
1857 : /* See commentary in _asn1_encode_open_type() */
1858 : static size_t
1859 715 : _asn1_length_open_type(const struct asn1_template *tbase,
1860 : const struct asn1_template *t,
1861 : const void *data,
1862 : const struct asn1_template *ttypeid,
1863 : const struct asn1_template *topentype)
1864 : {
1865 715 : const struct asn1_template *ttypeid_univ = ttypeid;
1866 0 : const struct asn1_template *tactual_type;
1867 715 : const struct asn1_template *tos = t->ptr;
1868 715 : const unsigned int *lenp = NULL;
1869 715 : unsigned int len = 1;
1870 715 : size_t sz = 0;
1871 0 : size_t i;
1872 715 : int element = *(const int *)DPOC(data, t->offset);
1873 715 : int typeid_is_oid = 0;
1874 715 : int typeid_is_int = 0;
1875 :
1876 : /* If nothing to encode, we add nothing to the length */
1877 715 : if (element == 0 || element >= A1_HEADER_LEN(tos) + 1)
1878 195 : return 0;
1879 520 : if (t->tt & A1_OS_OT_IS_ARRAY) {
1880 0 : len = *(const unsigned int *)DPOC(data, t->offset + sizeof(element));
1881 0 : if (!len)
1882 0 : return 0;
1883 : }
1884 :
1885 : /* Work out the type ID field's type */
1886 520 : while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
1887 520 : A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
1888 520 : ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
1889 0 : ttypeid_univ = ttypeid_univ->ptr;
1890 0 : ttypeid_univ++;
1891 : }
1892 520 : switch (ttypeid_univ->tt & A1_OP_MASK) {
1893 520 : case A1_OP_TAG:
1894 520 : if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV)
1895 0 : return 0;
1896 520 : switch (A1_TAG_TAG(ttypeid_univ->tt)) {
1897 520 : case UT_OID:
1898 520 : typeid_is_oid = 1;
1899 520 : break;
1900 0 : case UT_Integer: {
1901 0 : const struct asn1_template *tint = ttypeid_univ->ptr;
1902 :
1903 0 : tint++;
1904 0 : if ((tint->tt & A1_OP_MASK) != A1_OP_PARSE ||
1905 0 : A1_PARSE_TYPE(tint->tt) != A1T_INTEGER)
1906 0 : return 0;
1907 0 : typeid_is_int = 1;
1908 0 : break;
1909 : }
1910 0 : default: return 0;
1911 : }
1912 520 : break;
1913 0 : default: return 0;
1914 : }
1915 520 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
1916 520 : struct heim_base_data *os = DPO(data, topentype->offset);
1917 :
1918 520 : if (os->length && os->data)
1919 520 : return 0;
1920 : } else {
1921 0 : struct heim_base_data **os = DPO(data, topentype->offset + sizeof(len));
1922 :
1923 0 : while (sizeof(void *) != sizeof(unsigned int) &&
1924 0 : ((uintptr_t)os) % sizeof(void *) != 0)
1925 0 : os = (void *)(((char *)os) + sizeof(unsigned int));
1926 :
1927 0 : lenp = DPOC(data, topentype->offset);
1928 0 : if (*lenp == len && os[0]->length && os[0]->data)
1929 0 : return 0;
1930 : }
1931 :
1932 : /* Compute the size of the type ID field */
1933 0 : if (typeid_is_int) {
1934 0 : int64_t i8;
1935 0 : int32_t i4;
1936 :
1937 0 : switch (ttypeid_univ->offset) {
1938 0 : case 8:
1939 0 : i8 = (intptr_t)t->ptr;
1940 0 : sz = _asn1_length_open_type_id(ttypeid, &i8);
1941 0 : i8 = 0;
1942 0 : sz -= _asn1_length_open_type_id(ttypeid, &i8);
1943 0 : break;
1944 0 : case 4:
1945 0 : i4 = (intptr_t)t->ptr;
1946 0 : sz = _asn1_length_open_type_id(ttypeid, &i4);
1947 0 : i4 = 0;
1948 0 : sz -= _asn1_length_open_type_id(ttypeid, &i8);
1949 0 : break;
1950 0 : default:
1951 0 : return 0;
1952 : }
1953 0 : } else if (typeid_is_oid) {
1954 0 : heim_oid no_oid = { 0, 0 };
1955 :
1956 0 : sz = _asn1_length_open_type_id(ttypeid, tos[3 + (element - 1)*3].ptr);
1957 0 : sz -= _asn1_length_open_type_id(ttypeid, &no_oid);
1958 : }
1959 :
1960 0 : tactual_type = &tos[(element-1)*3 + 4];
1961 :
1962 : /* Compute the size of the encoded value(s) */
1963 0 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
1964 0 : const void * const *d = DPOC(data, t->offset + sizeof(element));
1965 :
1966 0 : while (sizeof(void *) != sizeof(element) &&
1967 0 : ((uintptr_t)d) % sizeof(void *) != 0)
1968 0 : d = (void *)(((char *)d) + sizeof(element));
1969 0 : if (*d)
1970 0 : sz += _asn1_length(tactual_type->ptr, *d);
1971 : } else {
1972 0 : size_t bodysz;
1973 0 : const void * const * val =
1974 0 : DPOC(data, t->offset + sizeof(element) + sizeof(*lenp));
1975 :
1976 : /* Compute the size of the encoded SET OF / SEQUENCE OF body */
1977 0 : for (i = 0, bodysz = 0; i < len; i++) {
1978 0 : if (val[i])
1979 0 : bodysz += _asn1_length(tactual_type->ptr, val[i]);
1980 : }
1981 :
1982 : /*
1983 : * We now know the size of the body of the SET OF or SEQUENCE OF. Now
1984 : * we just need to count the length of all the TLs on the outside.
1985 : */
1986 0 : sz += _asn1_length_open_type_helper(topentype, bodysz);
1987 : }
1988 0 : return sz;
1989 : }
1990 :
1991 : size_t
1992 56064352 : _asn1_length(const struct asn1_template *t, const void *data)
1993 : {
1994 56064352 : const struct asn1_template *tbase = t;
1995 56064352 : size_t elements = A1_HEADER_LEN(t);
1996 56064352 : size_t ret = 0;
1997 :
1998 56064352 : t += A1_HEADER_LEN(t);
1999 :
2000 146369670 : while (elements) {
2001 90305318 : switch (t->tt & A1_OP_MASK) {
2002 715 : case A1_OP_OPENTYPE_OBJSET: {
2003 715 : size_t opentypeid = t->tt & ((1<<10)-1);
2004 715 : size_t opentype = (t->tt >> 10) & ((1<<10)-1);
2005 715 : ret += _asn1_length_open_type(tbase, t, data,
2006 : template4member(tbase, opentypeid),
2007 : template4member(tbase, opentype));
2008 715 : break;
2009 : }
2010 21173488 : case A1_OP_NAME: break;
2011 715 : case A1_OP_DEFVAL: break;
2012 0 : case A1_OP_TYPE_DECORATE_EXTERN: break;
2013 0 : case A1_OP_TYPE_DECORATE: break;
2014 14035188 : case A1_OP_TYPE:
2015 : case A1_OP_TYPE_EXTERN: {
2016 14035188 : const void *el = DPOC(data, t->offset);
2017 :
2018 14035188 : if (t->tt & A1_FLAG_OPTIONAL) {
2019 2945 : void **pel = (void **)el;
2020 2945 : if (*pel == NULL)
2021 662 : break;
2022 2283 : el = *pel;
2023 14032243 : } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
2024 0 : const struct asn1_template *tdefval = t - 1;
2025 :
2026 : /* Compare tdefval to whatever's at `el' */
2027 0 : if (tdefval->tt & A1_DV_BOOLEAN) {
2028 0 : const int *i = (void *)(char *)el;
2029 :
2030 0 : if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
2031 : break;
2032 0 : } else if (tdefval->tt & A1_DV_INTEGER64) {
2033 0 : const int64_t *i = (void *)(char *)el;
2034 :
2035 0 : if (*i == (int64_t)(intptr_t)tdefval->ptr)
2036 0 : break;
2037 0 : } else if (tdefval->tt & A1_DV_INTEGER32) {
2038 0 : const int32_t *i = (void *)(char *)el;
2039 :
2040 0 : if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
2041 0 : (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
2042 0 : *i == (int32_t)(intptr_t)tdefval->ptr)
2043 0 : break;
2044 0 : } else if (tdefval->tt & A1_DV_INTEGER) {
2045 0 : const struct heim_integer *i = (void *)(char *)el;
2046 :
2047 0 : if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
2048 0 : break;
2049 0 : } else if (tdefval->tt & A1_DV_UTF8STRING) {
2050 0 : const char * const *s = el;
2051 :
2052 0 : if (*s && strcmp(*s, tdefval->ptr) == 0)
2053 0 : break;
2054 : } else {
2055 0 : abort();
2056 : }
2057 : }
2058 :
2059 14034526 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
2060 14026746 : ret += _asn1_length(t->ptr, el);
2061 : } else {
2062 7780 : const struct asn1_type_func *f = t->ptr;
2063 7780 : ret += (f->length)(el);
2064 : }
2065 13534210 : break;
2066 : }
2067 38537928 : case A1_OP_TAG: {
2068 1373245 : size_t datalen;
2069 38537928 : const void *olddata = data;
2070 38537928 : size_t oldtaglen = 0;
2071 :
2072 38537928 : data = DPO(data, t->offset);
2073 :
2074 38537928 : if (t->tt & A1_FLAG_OPTIONAL) {
2075 4305699 : void **el = (void **)data;
2076 4305699 : if (*el == NULL) {
2077 1795015 : data = olddata;
2078 1795015 : break;
2079 : }
2080 2358601 : data = *el;
2081 34232229 : } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
2082 715 : const struct asn1_template *tdefval = t - 1;
2083 715 : int exclude = 0;
2084 :
2085 : /* Compare tdefval to whatever's at `data' */
2086 715 : if (tdefval->tt & A1_DV_BOOLEAN) {
2087 715 : const int *i = (void *)(char *)data;
2088 :
2089 715 : if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
2090 715 : exclude = 1;
2091 0 : } else if (tdefval->tt & A1_DV_INTEGER64) {
2092 0 : const int64_t *i = (void *)(char *)data;
2093 :
2094 0 : if (*i == (int64_t)(intptr_t)tdefval->ptr)
2095 0 : exclude = 1;
2096 0 : } else if (tdefval->tt & A1_DV_INTEGER32) {
2097 0 : const int32_t *i = (void *)(char *)data;
2098 :
2099 0 : if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
2100 0 : (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
2101 0 : *i == (int32_t)(intptr_t)tdefval->ptr)
2102 0 : exclude = 1;
2103 0 : } else if (tdefval->tt & A1_DV_INTEGER) {
2104 0 : const struct heim_integer *i = (void *)(char *)data;
2105 :
2106 0 : if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
2107 0 : exclude = 1;
2108 0 : } else if (tdefval->tt & A1_DV_UTF8STRING) {
2109 0 : const char * const *s = data;
2110 :
2111 0 : if (*s && strcmp(*s, tdefval->ptr) == 0)
2112 0 : exclude = 1;
2113 : } else {
2114 0 : abort();
2115 : }
2116 715 : if (exclude) {
2117 715 : data = olddata;
2118 715 : break;
2119 : }
2120 : }
2121 :
2122 36679130 : if (t->tt & A1_FLAG_IMPLICIT)
2123 602 : oldtaglen = inner_type_taglen(t->ptr);
2124 :
2125 36679130 : datalen = _asn1_length(t->ptr, data);
2126 36679130 : ret += datalen;
2127 36679130 : ret += der_length_tag(A1_TAG_TAG(t->tt));
2128 36679130 : ret += oldtaglen ? -oldtaglen : der_length_len(datalen);
2129 36679130 : data = olddata;
2130 36679130 : break;
2131 : }
2132 12935781 : case A1_OP_PARSE: {
2133 12935781 : unsigned int type = A1_PARSE_TYPE(t->tt);
2134 12935781 : const void *el = DPOC(data, t->offset);
2135 :
2136 12935781 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2137 0 : ABORT_ON_ERROR();
2138 462162 : break;
2139 : }
2140 12935781 : ret += (asn1_template_prim[type].length)(el);
2141 12935781 : break;
2142 : }
2143 2232671 : case A1_OP_SETOF:
2144 : case A1_OP_SEQOF: {
2145 2232671 : const struct template_of *el = DPOC(data, t->offset);
2146 2232671 : size_t ellen = _asn1_sizeofType(t->ptr);
2147 2232671 : const unsigned char *element = el->val;
2148 80717 : unsigned int i;
2149 :
2150 6131921 : for (i = 0; i < el->len; i++) {
2151 3899250 : ret += _asn1_length(t->ptr, element);
2152 3899250 : element += ellen;
2153 : }
2154 :
2155 2151954 : break;
2156 : }
2157 512829 : case A1_OP_BMEMBER: {
2158 512829 : const struct asn1_template *bmember = t->ptr;
2159 512829 : size_t size = bmember->offset;
2160 512829 : size_t belements = A1_HEADER_LEN(bmember);
2161 512829 : int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
2162 :
2163 512829 : if (rfc1510) {
2164 512829 : ret += 5;
2165 : } else {
2166 :
2167 0 : ret += 1;
2168 :
2169 0 : bmember += belements;
2170 :
2171 0 : while (belements) {
2172 0 : if (_asn1_bmember_isset_bit(data, bmember->offset, size)) {
2173 0 : ret += (bmember->offset / 8) + 1;
2174 0 : break;
2175 : }
2176 0 : belements--; bmember--;
2177 : }
2178 : }
2179 495020 : break;
2180 : }
2181 96226 : case A1_OP_CHOICE: {
2182 96226 : const struct asn1_template *choice = t->ptr;
2183 96226 : const unsigned int *element = DPOC(data, choice->offset);
2184 :
2185 96226 : if (*element > A1_HEADER_LEN(choice))
2186 0 : break;
2187 :
2188 96226 : if (*element == 0) {
2189 0 : if (choice->tt)
2190 0 : ret += der_length_octet_string(DPOC(data, choice->tt));
2191 : } else {
2192 96226 : choice += *element;
2193 96226 : ret += _asn1_length(choice->ptr, DPOC(data, choice->offset));
2194 : }
2195 92910 : break;
2196 : }
2197 0 : default:
2198 0 : ABORT_ON_ERROR();
2199 3217342 : break;
2200 : }
2201 90305318 : elements--;
2202 90305318 : t--;
2203 : }
2204 56064352 : return ret;
2205 : }
2206 :
2207 : /* See commentary in _asn1_decode_open_type() */
2208 : static void
2209 5066 : _asn1_free_open_type(const struct asn1_template *t, /* object set template */
2210 : void *data)
2211 : {
2212 216 : const struct asn1_template *tactual_type;
2213 5066 : const struct asn1_template *tos = t->ptr;
2214 5066 : unsigned int *lenp = NULL; /* Pointer to array length field */
2215 5066 : unsigned int len = 1; /* Array length */
2216 216 : size_t i;
2217 216 : void **dp;
2218 216 : void **val;
2219 5066 : int *elementp = DPO(data, t->offset); /* Choice enum pointer */
2220 :
2221 : /* XXX We assume sizeof(enum) == sizeof(int) */
2222 5066 : if (!*elementp || *elementp >= A1_HEADER_LEN(tos) + 1)
2223 1448 : return; /* Unknown choice -> it's not decoded, nothing to free here */
2224 3522 : tactual_type = tos[3*(*elementp - 1) + 4].ptr;
2225 :
2226 3522 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
2227 3522 : dp = DPO(data, t->offset + sizeof(*elementp));
2228 3522 : while (sizeof(void *) != sizeof(*elementp) &&
2229 7044 : ((uintptr_t)dp) % sizeof(void *) != 0)
2230 3522 : dp = (void *)(((char *)dp) + sizeof(*elementp));
2231 3522 : if (*dp) {
2232 3522 : _asn1_free(tactual_type, *dp);
2233 3522 : free(*dp);
2234 3522 : *dp = NULL;
2235 : }
2236 3522 : return;
2237 : }
2238 :
2239 0 : lenp = DPO(data, t->offset + sizeof(*elementp));
2240 0 : len = *lenp;
2241 0 : dp = DPO(data, t->offset + sizeof(*elementp) + sizeof(*lenp));
2242 0 : while (sizeof(void *) != sizeof(*elementp) &&
2243 0 : ((uintptr_t)dp) % sizeof(void *) != 0)
2244 0 : dp = (void *)(((char *)dp) + sizeof(*elementp));
2245 0 : val = *dp;
2246 :
2247 0 : for (i = 0; i < len; i++) {
2248 0 : if (val[i]) {
2249 0 : _asn1_free(tactual_type, val[i]);
2250 0 : free(val[i]);
2251 : }
2252 : }
2253 0 : free(val);
2254 0 : *lenp = 0;
2255 0 : *dp = NULL;
2256 : }
2257 :
2258 : void
2259 350238532 : _asn1_free(const struct asn1_template *t, void *data)
2260 : {
2261 350238532 : size_t elements = A1_HEADER_LEN(t);
2262 :
2263 350238532 : if (t->tt & A1_HF_PRESERVE)
2264 407209 : der_free_octet_string(data);
2265 :
2266 350238532 : t++;
2267 :
2268 924561942 : while (elements) {
2269 574323410 : switch (t->tt & A1_OP_MASK) {
2270 5066 : case A1_OP_OPENTYPE_OBJSET: {
2271 5066 : _asn1_free_open_type(t, data);
2272 5066 : break;
2273 : }
2274 137476293 : case A1_OP_NAME: break;
2275 4507 : case A1_OP_DEFVAL: break;
2276 85112642 : case A1_OP_TYPE_DECORATE_EXTERN:
2277 : case A1_OP_TYPE_DECORATE:
2278 : case A1_OP_TYPE:
2279 : case A1_OP_TYPE_EXTERN: {
2280 85112642 : void *el = DPO(data, t->offset);
2281 85112642 : void **pel = (void **)el;
2282 :
2283 85112642 : if (t->tt & A1_FLAG_OPTIONAL) {
2284 6241027 : if (*pel == NULL)
2285 4669447 : break;
2286 1357593 : el = *pel;
2287 : }
2288 :
2289 80276819 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE || (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2290 78866114 : _asn1_free(t->ptr, el);
2291 1410705 : } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) {
2292 9855 : const struct asn1_type_func *f = t->ptr;
2293 9855 : (f->release)(el);
2294 : } else {
2295 : /* A1_OP_TYPE_DECORATE_EXTERN */
2296 1400850 : const struct asn1_type_func *f = t->ptr;
2297 :
2298 1400850 : if (f && f->release)
2299 0 : (f->release)(el);
2300 1400850 : else if (f)
2301 1400850 : memset(el, 0, f->size);
2302 : }
2303 80276819 : if (t->tt & A1_FLAG_OPTIONAL) {
2304 1405204 : free(el);
2305 1405204 : *pel = NULL;
2306 : }
2307 :
2308 77528570 : break;
2309 : }
2310 77824829 : case A1_OP_PARSE: {
2311 77824829 : unsigned int type = A1_PARSE_TYPE(t->tt);
2312 77824829 : void *el = DPO(data, t->offset);
2313 :
2314 77824829 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2315 0 : ABORT_ON_ERROR();
2316 2635401 : break;
2317 : }
2318 77824829 : (asn1_template_prim[type].release)(el);
2319 77824829 : break;
2320 : }
2321 245814084 : case A1_OP_TAG: {
2322 245814084 : void *el = DPO(data, t->offset);
2323 :
2324 245814084 : if (t->tt & A1_FLAG_OPTIONAL) {
2325 23720326 : void **pel = (void **)el;
2326 :
2327 23720326 : if (*pel == NULL)
2328 12979021 : break;
2329 10289566 : _asn1_free(t->ptr, *pel);
2330 10289566 : free(*pel);
2331 10289566 : *pel = NULL;
2332 : } else {
2333 222093758 : _asn1_free(t->ptr, el);
2334 : }
2335 :
2336 224490115 : break;
2337 : }
2338 19070384 : case A1_OP_SETOF:
2339 : case A1_OP_SEQOF: {
2340 19070384 : struct template_of *el = DPO(data, t->offset);
2341 19070384 : size_t ellen = _asn1_sizeofType(t->ptr);
2342 19070384 : unsigned char *element = el->val;
2343 657950 : unsigned int i;
2344 :
2345 40230893 : for (i = 0; i < el->len; i++) {
2346 21160509 : _asn1_free(t->ptr, element);
2347 21160509 : element += ellen;
2348 : }
2349 19070384 : free(el->val);
2350 19070384 : el->val = NULL;
2351 19070384 : el->len = 0;
2352 :
2353 19070384 : break;
2354 : }
2355 2508549 : case A1_OP_BMEMBER:
2356 2508549 : break;
2357 1596012 : case A1_OP_CHOICE: {
2358 1596012 : const struct asn1_template *choice = t->ptr;
2359 1596012 : const unsigned int *element = DPOC(data, choice->offset);
2360 :
2361 1596012 : if (*element > A1_HEADER_LEN(choice))
2362 0 : break;
2363 :
2364 1596012 : if (*element == 0) {
2365 : /*
2366 : * If choice->tt != 0 then this is an extensible choice, and
2367 : * the offset choice->tt is the offset to u.ellipsis.
2368 : */
2369 368 : if (choice->tt != 0)
2370 2 : der_free_octet_string(DPO(data, choice->tt));
2371 : /*
2372 : * Else this was a not-fully initialized CHOICE. We could
2373 : * stand to memset clear the rest of it though...
2374 : */
2375 : } else {
2376 1595644 : choice += *element;
2377 1595644 : _asn1_free(choice->ptr, DPO(data, choice->offset));
2378 : }
2379 1541449 : break;
2380 : }
2381 0 : default:
2382 0 : ABORT_ON_ERROR();
2383 19518747 : break;
2384 : }
2385 574323410 : t++;
2386 574323410 : elements--;
2387 : }
2388 350238532 : }
2389 :
2390 : static char *
2391 0 : getindent(int flags, unsigned int i)
2392 : {
2393 0 : char *s;
2394 :
2395 0 : if (!(flags & ASN1_PRINT_INDENT) || i == 0)
2396 0 : return NULL;
2397 0 : if (i > 128)
2398 0 : i = 128;
2399 0 : if ((s = malloc(i * 2 + 2)) == NULL)
2400 0 : return NULL;
2401 0 : s[0] = '\n';
2402 0 : s[i * 2 + 1] = '\0';
2403 0 : memset(s + 1, ' ', i * 2);
2404 0 : return s;
2405 : }
2406 :
2407 : static struct rk_strpool *_asn1_print(const struct asn1_template *,
2408 : struct rk_strpool *,
2409 : int,
2410 : unsigned int,
2411 : const void *,
2412 : const heim_octet_string *);
2413 :
2414 : /* See commentary in _asn1_decode_open_type() */
2415 : static struct rk_strpool *
2416 0 : _asn1_print_open_type(const struct asn1_template *t, /* object set template */
2417 : struct rk_strpool *r,
2418 : int flags,
2419 : unsigned int indent,
2420 : const void *data,
2421 : const char *opentype_name)
2422 : {
2423 0 : const struct asn1_template *tactual_type;
2424 0 : const struct asn1_template *tos = t->ptr;
2425 0 : const unsigned int *lenp = NULL; /* Pointer to array length field */
2426 0 : unsigned int len = 1; /* Array length */
2427 0 : size_t i;
2428 0 : const void * const *dp;
2429 0 : const void * const *val;
2430 0 : const int *elementp = DPOC(data, t->offset); /* Choice enum pointer */
2431 0 : char *indents = getindent(flags, indent);
2432 :
2433 : /* XXX We assume sizeof(enum) == sizeof(int) */
2434 0 : if (!*elementp || *elementp >= A1_HEADER_LEN(tos) + 1) {
2435 0 : r = rk_strpoolprintf(r, ",%s\"_%s_choice\":\"_ERROR_DECODING_\"",
2436 : indents ? indents : "", opentype_name);
2437 0 : free(indents);
2438 0 : return r;
2439 : }
2440 0 : tactual_type = tos[3*(*elementp - 1) + 4].ptr;
2441 :
2442 0 : r = rk_strpoolprintf(r, ",%s\"_%s_choice\":\"%s\"",
2443 : indents ? indents : "", opentype_name,
2444 0 : (const char *)tos[3*(*elementp - 1) + 2].ptr);
2445 0 : if (!r) {
2446 0 : free(indents);
2447 0 : return r;
2448 : }
2449 :
2450 0 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
2451 0 : dp = DPOC(data, t->offset + sizeof(*elementp));
2452 0 : while (sizeof(void *) != sizeof(*elementp) &&
2453 0 : ((uintptr_t)dp) % sizeof(void *) != 0)
2454 0 : dp = (void *)(((char *)dp) + sizeof(*elementp));
2455 0 : if (*dp) {
2456 0 : struct rk_strpool *r2 = NULL;
2457 0 : char *s = NULL;
2458 :
2459 0 : r2 = _asn1_print(tactual_type, r2, flags, indent + 1, *dp, NULL);
2460 0 : if (r2 == NULL) {
2461 0 : r = rk_strpoolprintf(r, ",%s\"_%s\":\"_ERROR_FORMATTING_\"",
2462 : indents ? indents : "", opentype_name);
2463 0 : free(indents);
2464 0 : return r;
2465 : }
2466 0 : s = rk_strpoolcollect(r2);
2467 0 : if (s)
2468 0 : r = rk_strpoolprintf(r, ",%s\"_%s\":%s",
2469 : indents ? indents : "", opentype_name, s);
2470 0 : free(s);
2471 : }
2472 0 : free(indents);
2473 0 : return r;
2474 : }
2475 :
2476 0 : lenp = DPOC(data, t->offset + sizeof(*elementp));
2477 0 : len = *lenp;
2478 0 : dp = DPOC(data, t->offset + sizeof(*elementp) + sizeof(*lenp));
2479 0 : while (sizeof(void *) != sizeof(*elementp) &&
2480 0 : ((uintptr_t)dp) % sizeof(void *) != 0)
2481 0 : dp = (void *)(((char *)dp) + sizeof(*elementp));
2482 0 : val = *dp;
2483 :
2484 0 : r = rk_strpoolprintf(r, ",%s\"_%s\":[", indents ? indents : "",
2485 : opentype_name);
2486 0 : free(indents);
2487 0 : indents = getindent(flags, indent + 1);
2488 0 : r = rk_strpoolprintf(r, "%s", indents ? indents : "");
2489 0 : for (i = 0; r && i < len; i++) {
2490 0 : struct rk_strpool *r2 = NULL;
2491 0 : char *s = NULL;;
2492 :
2493 0 : if (val[i]) {
2494 0 : r2 = _asn1_print(tactual_type, r2, flags, indent + 2, val[i], NULL);
2495 0 : if (r2 == NULL) {
2496 0 : rk_strpoolfree(r);
2497 0 : free(indents);
2498 0 : return NULL;
2499 : }
2500 : }
2501 0 : if (i)
2502 0 : r = rk_strpoolprintf(r, ",%s", indents ? indents : "");
2503 0 : if (r)
2504 0 : r = rk_strpoolprintf(r, "%s", (s = rk_strpoolcollect(r2)));
2505 0 : free(s);
2506 : }
2507 0 : free(indents);
2508 0 : return rk_strpoolprintf(r, "]");
2509 : }
2510 :
2511 : static struct rk_strpool *
2512 0 : _asn1_print(const struct asn1_template *t,
2513 : struct rk_strpool *r,
2514 : int flags,
2515 : unsigned int indent,
2516 : const void *data,
2517 : const heim_octet_string *saved)
2518 : {
2519 0 : const struct asn1_template *tbase = t;
2520 0 : const struct asn1_template *tnames;
2521 0 : size_t nelements = A1_HEADER_LEN(t);
2522 0 : size_t elements = nelements;
2523 0 : size_t nnames = 0;
2524 0 : char *indents = getindent(flags, indent);
2525 :
2526 0 : for (t += nelements; t > tbase && (t->tt & A1_OP_MASK) == A1_OP_NAME; t--)
2527 0 : nnames++;
2528 :
2529 0 : tnames = tbase + nelements - nnames + 1;
2530 :
2531 0 : if (!r)
2532 0 : r = rk_strpoolprintf(r, "%s", "");
2533 :
2534 0 : if (nnames)
2535 0 : r = rk_strpoolprintf(r, "%s{\"_type\":\"%s\"",
2536 : indents ? indents : "",
2537 0 : (const char *)(tnames++)->ptr);
2538 0 : if (saved && r) {
2539 0 : char *s = der_print_octet_string(data, 0);
2540 :
2541 0 : if (!s) {
2542 0 : rk_strpoolfree(r);
2543 0 : free(indents);
2544 0 : return NULL;
2545 : }
2546 0 : r = rk_strpoolprintf(r, ",%s\"_save\":\"%s\"",
2547 : indents ? indents : "", s);
2548 0 : free(s);
2549 : }
2550 0 : saved = NULL;
2551 0 : if (tbase->tt & A1_HF_PRESERVE)
2552 0 : saved = data;
2553 :
2554 0 : t = tbase + 1;
2555 0 : while (r && elements && (t->tt & A1_OP_MASK) != A1_OP_NAME) {
2556 0 : switch (t->tt & A1_OP_MASK) {
2557 0 : case A1_OP_NAME:
2558 0 : continue;
2559 0 : case A1_OP_DEFVAL:
2560 0 : t++;
2561 0 : elements--;
2562 0 : continue;
2563 0 : case A1_OP_OPENTYPE_OBJSET: {
2564 0 : size_t opentype = (t->tt >> 10) & ((1<<10)-1);
2565 0 : r = _asn1_print_open_type(t, r, flags, indent + 1, data,
2566 0 : tbase[(nelements - nnames) + 2 + opentype].ptr);
2567 0 : t++;
2568 0 : elements--;
2569 0 : continue;
2570 : }
2571 0 : default: break;
2572 : }
2573 0 : if (nnames &&
2574 0 : (t->tt & A1_OP_MASK) != A1_OP_TYPE_DECORATE_EXTERN &&
2575 0 : (t->tt & A1_OP_MASK) != A1_OP_TYPE_DECORATE)
2576 0 : r = rk_strpoolprintf(r, ",%s\"%s\":",
2577 : indents ? indents : "",
2578 0 : (const char *)(tnames++)->ptr);
2579 0 : switch (t->tt & A1_OP_MASK) {
2580 0 : case A1_OP_OPENTYPE_OBJSET:
2581 0 : break;
2582 0 : case A1_OP_NAME: break;
2583 0 : case A1_OP_DEFVAL: break;
2584 0 : case A1_OP_TYPE_DECORATE_EXTERN: break;
2585 0 : case A1_OP_TYPE_DECORATE: break; /* We could probably print this though */
2586 0 : case A1_OP_TYPE:
2587 : case A1_OP_TYPE_EXTERN: {
2588 0 : const void *el = DPOC(data, t->offset);
2589 :
2590 0 : if (t->tt & A1_FLAG_OPTIONAL) {
2591 0 : const void * const *pel = (const void *const *)el;
2592 0 : if (*pel == NULL) {
2593 0 : r = rk_strpoolprintf(r, "null");
2594 0 : break;
2595 : }
2596 0 : el = *pel;
2597 : }
2598 :
2599 0 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
2600 0 : r = _asn1_print(t->ptr, r, flags, indent + 1, el, saved);
2601 : } else {
2602 0 : const struct asn1_type_func *f = t->ptr;
2603 0 : char *s = NULL;
2604 :
2605 0 : s = (f->print)(el, 0);
2606 0 : if (s == NULL) {
2607 0 : rk_strpoolfree(r);
2608 0 : free(indents);
2609 0 : return NULL;
2610 : }
2611 0 : r = rk_strpoolprintf(r, "%s", s);
2612 0 : free(s);
2613 : }
2614 0 : break;
2615 : }
2616 0 : case A1_OP_PARSE: {
2617 0 : unsigned int type = A1_PARSE_TYPE(t->tt);
2618 0 : const void *el = DPOC(data, t->offset);
2619 0 : char *s = NULL;
2620 :
2621 0 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2622 0 : ABORT_ON_ERROR();
2623 0 : break;
2624 : }
2625 :
2626 0 : if (type == A1T_IMEMBER && t->ptr) {
2627 : /* Enumeration. Use the symbolic name of this value */
2628 0 : const struct asn1_template *tenum = t->ptr;
2629 0 : size_t left = 0;
2630 0 : size_t right = A1_HEADER_LEN(tenum);
2631 0 : size_t mid;
2632 0 : uint32_t v = *(unsigned int *)el;
2633 0 : int c = -1;
2634 :
2635 0 : while (left <= right) {
2636 0 : mid = (left + right) >> 1;
2637 :
2638 0 : if ((tenum[mid].tt & A1_OP_MASK) != A1_OP_NAME)
2639 0 : break;
2640 0 : c = v - tenum[mid].offset;
2641 0 : if (c < 0) {
2642 0 : if (mid)
2643 0 : right = mid - 1;
2644 : else
2645 0 : break;
2646 0 : } else if (c > 0) {
2647 0 : left = mid + 1;
2648 : } else {
2649 0 : break;
2650 : }
2651 : }
2652 0 : if (c == 0) {
2653 0 : r = rk_strpoolprintf(r, "\"%s\"", (const char *)tenum[mid].ptr);
2654 0 : break;
2655 : }
2656 : }
2657 0 : s = (asn1_template_prim[type].print)(el, flags);
2658 0 : switch (type) {
2659 0 : case A1T_OID:
2660 : case A1T_IMEMBER:
2661 : case A1T_BOOLEAN:
2662 : case A1T_INTEGER:
2663 : case A1T_INTEGER64:
2664 : case A1T_UNSIGNED:
2665 : case A1T_UNSIGNED64:
2666 0 : if (s)
2667 0 : r = rk_strpoolprintf(r, "%s", s);
2668 0 : break;
2669 0 : default: {
2670 0 : char *s2 = NULL;
2671 :
2672 0 : if (s)
2673 0 : (void) rk_strasvis(&s2, s, VIS_CSTYLE|VIS_TAB|VIS_NL, "\"");
2674 0 : free(s);
2675 0 : s = s2;
2676 0 : if (s)
2677 0 : r = rk_strpoolprintf(r, "\"%s\"", s);
2678 : }
2679 : }
2680 0 : if (!s) {
2681 0 : rk_strpoolfree(r);
2682 0 : free(indents);
2683 0 : return NULL;
2684 : }
2685 0 : free(s);
2686 0 : break;
2687 : }
2688 0 : case A1_OP_TAG: {
2689 0 : const void *el = DPOC(data, t->offset);
2690 :
2691 0 : if (t->tt & A1_FLAG_OPTIONAL) {
2692 0 : const void * const *pel = (const void * const *)el;
2693 0 : if (*pel == NULL) {
2694 0 : r = rk_strpoolprintf(r, "null");
2695 0 : break;
2696 : }
2697 0 : el = *pel;
2698 : }
2699 :
2700 0 : r = _asn1_print(t->ptr, r, flags, indent + 1, el, saved);
2701 0 : break;
2702 : }
2703 0 : case A1_OP_SETOF:
2704 : case A1_OP_SEQOF: {
2705 0 : const struct template_of *el = DPOC(data, t->offset);
2706 0 : size_t ellen = _asn1_sizeofType(t->ptr);
2707 0 : const unsigned char *element = el->val;
2708 0 : unsigned int i;
2709 :
2710 0 : r = rk_strpoolprintf(r, "%s[", indents ? indents : "");
2711 0 : for (i = 0; r && i < el->len; i++) {
2712 0 : if (i)
2713 0 : r = rk_strpoolprintf(r, ",%s", indents ? indents : "");
2714 0 : r = _asn1_print(t->ptr, r, flags, indent + 1, element, saved);
2715 0 : element += ellen;
2716 : }
2717 0 : if (r)
2718 0 : r = rk_strpoolprintf(r, "]");
2719 0 : break;
2720 : }
2721 0 : case A1_OP_BMEMBER: {
2722 0 : const struct asn1_template *bmember = t->ptr;
2723 0 : size_t size = bmember->offset;
2724 0 : size_t belements = A1_HEADER_LEN(bmember);
2725 0 : int first = 1;
2726 :
2727 0 : bmember += belements;
2728 0 : r = rk_strpoolprintf(r, "%s[", indents ? indents : "");
2729 0 : while (r && belements) {
2730 0 : if (r && _asn1_bmember_isset_bit(data, bmember->offset, size)) {
2731 0 : if (!first)
2732 0 : r = rk_strpoolprintf(r, ",");
2733 0 : first = 0;
2734 0 : r = rk_strpoolprintf(r, "%s\"%s\"", indents ? indents : "",
2735 0 : (const char *)bmember->ptr);
2736 : }
2737 0 : belements--; bmember--;
2738 : }
2739 0 : if (r)
2740 0 : r = rk_strpoolprintf(r, "]");
2741 0 : break;
2742 : }
2743 0 : case A1_OP_CHOICE: {
2744 0 : const struct asn1_template *choice = t->ptr;
2745 0 : const unsigned int *element = DPOC(data, choice->offset);
2746 0 : unsigned int nchoices = ((uintptr_t)choice->ptr) >> 1;
2747 :
2748 0 : if (*element > A1_HEADER_LEN(choice)) {
2749 0 : r = rk_strpoolprintf(r, "null");
2750 0 : } else if (*element == 0) {
2751 : /* XXX If choice->tt then we should print the u.ellipsis */
2752 0 : r = rk_strpoolprintf(r, "null");
2753 : } else {
2754 0 : choice += *element;
2755 0 : r = rk_strpoolprintf(r, "%s{\"_choice\":\"%s\",%s\"value\":",
2756 : indents ? indents : "",
2757 0 : (const char *)choice[nchoices].ptr,
2758 : indents ? indents : "");
2759 0 : if (r)
2760 0 : r = _asn1_print(choice->ptr, r, flags, indent + 1,
2761 0 : DPOC(data, choice->offset), NULL);
2762 0 : if (r)
2763 0 : r = rk_strpoolprintf(r, "}");
2764 : }
2765 0 : break;
2766 : }
2767 0 : default:
2768 0 : ABORT_ON_ERROR();
2769 0 : break;
2770 : }
2771 0 : t++;
2772 0 : elements--;
2773 : }
2774 0 : free(indents);
2775 0 : if (nnames && r)
2776 0 : return rk_strpoolprintf(r, "}");
2777 0 : return r;
2778 : }
2779 :
2780 : char *
2781 0 : _asn1_print_top(const struct asn1_template *t,
2782 : int flags,
2783 : const void *data)
2784 : {
2785 0 : struct rk_strpool *r = _asn1_print(t, NULL, flags, 0, data, NULL);
2786 :
2787 0 : if (r == NULL)
2788 0 : return NULL;
2789 0 : return rk_strpoolcollect(r);
2790 : }
2791 :
2792 : /* See commentary in _asn1_decode_open_type() */
2793 : static int
2794 2651 : _asn1_copy_open_type(const struct asn1_template *t, /* object set template */
2795 : const void *from,
2796 : void *to)
2797 : {
2798 160 : const struct asn1_template *tactual_type;
2799 2651 : const struct asn1_template *tos = t->ptr;
2800 160 : size_t i;
2801 160 : const void * const *dfromp;
2802 160 : const void * const *valfrom;
2803 160 : const unsigned int *lenfromp;
2804 160 : void **dtop;
2805 160 : void **valto;
2806 160 : unsigned int *lentop;
2807 160 : unsigned int len;
2808 2651 : const int *efromp = DPO(from, t->offset);
2809 2651 : int *etop = DPO(to, t->offset);
2810 2651 : int ret = 0;
2811 :
2812 : /* XXX We assume sizeof(enum) == sizeof(int) */
2813 2651 : if (!*efromp || *efromp >= A1_HEADER_LEN(tos) + 1) {
2814 535 : if ((t->tt & A1_OS_OT_IS_ARRAY))
2815 0 : memset(etop, 0, sizeof(int) + sizeof(unsigned int) + sizeof(void *));
2816 : else
2817 535 : memset(etop, 0, sizeof(int) + sizeof(void *));
2818 535 : return 0; /* Unknown choice -> not copied */
2819 : }
2820 2116 : tactual_type = &tos[3*(*efromp - 1) + 4];
2821 :
2822 2116 : if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
2823 2116 : dfromp = DPO(from, t->offset + sizeof(*efromp));
2824 2116 : while (sizeof(void *) != sizeof(*efromp) &&
2825 4232 : ((uintptr_t)dfromp) % sizeof(void *) != 0)
2826 2116 : dfromp = (void *)(((char *)dfromp) + sizeof(*efromp));
2827 2116 : if (!*dfromp)
2828 0 : return 0;
2829 :
2830 2116 : dtop = DPO(to, t->offset + sizeof(*etop));
2831 2116 : while (sizeof(void *) != sizeof(*etop) &&
2832 4232 : ((uintptr_t)dtop) % sizeof(void *) != 0)
2833 2116 : dtop = (void *)(((char *)dtop) + sizeof(*etop));
2834 :
2835 2116 : if ((*dtop = calloc(1, tactual_type->offset)) == NULL)
2836 0 : ret = ENOMEM;
2837 2116 : if (ret == 0)
2838 2116 : ret = _asn1_copy(tactual_type->ptr, *dfromp, *dtop);
2839 2116 : if (ret == 0)
2840 2116 : *etop = *efromp;
2841 2116 : return ret;
2842 : }
2843 :
2844 0 : lenfromp = DPO(from, t->offset + sizeof(*efromp));
2845 0 : dfromp = DPO(from, t->offset + sizeof(*efromp) + sizeof(*lenfromp));
2846 0 : valfrom = *dfromp;
2847 0 : lentop = DPO(to, t->offset + sizeof(*etop));
2848 0 : dtop = DPO(to, t->offset + sizeof(*etop) + sizeof(*lentop));
2849 :
2850 0 : *etop = *efromp;
2851 :
2852 0 : len = *lenfromp;
2853 0 : *lentop = 0;
2854 0 : *dtop = NULL;
2855 0 : if ((valto = calloc(len, sizeof(valto[0]))) == NULL)
2856 0 : ret = ENOMEM;
2857 0 : for (i = 0, len = *lenfromp; ret == 0 && i < len; i++) {
2858 0 : if (valfrom[i] == NULL) {
2859 0 : valto[i] = NULL;
2860 0 : continue;
2861 : }
2862 0 : if ((valto[i] = calloc(1, tactual_type->offset)) == NULL)
2863 0 : ret = ENOMEM;
2864 : else
2865 0 : ret = _asn1_copy(tactual_type->ptr, valfrom[i], valto[i]);
2866 0 : (*lentop)++;
2867 : }
2868 :
2869 0 : for (i = 0; ret && i < (*lentop); i++) {
2870 0 : if (valto[i]) {
2871 0 : _asn1_free(tactual_type->ptr, valto[i]);
2872 0 : free(valto[i]);
2873 : }
2874 : }
2875 0 : if (ret) {
2876 0 : free(valto);
2877 0 : *lentop = 0;
2878 : } else
2879 0 : *dtop = valto;
2880 0 : return ret;
2881 : }
2882 :
2883 : int
2884 265571779 : _asn1_copy(const struct asn1_template *t, const void *from, void *to)
2885 : {
2886 265571779 : size_t elements = A1_HEADER_LEN(t);
2887 265571779 : int ret = 0;
2888 265571779 : int preserve = (t->tt & A1_HF_PRESERVE);
2889 :
2890 265571779 : t++;
2891 :
2892 265571779 : if (preserve) {
2893 132634 : ret = der_copy_octet_string(from, to);
2894 132634 : if (ret)
2895 0 : return ret;
2896 : }
2897 :
2898 698041236 : while (elements) {
2899 432469457 : switch (t->tt & A1_OP_MASK) {
2900 2651 : case A1_OP_OPENTYPE_OBJSET: {
2901 2651 : _asn1_copy_open_type(t, from, to);
2902 2651 : break;
2903 : }
2904 105184305 : case A1_OP_NAME: break;
2905 2658 : case A1_OP_DEFVAL: break;
2906 58702163 : case A1_OP_TYPE_DECORATE_EXTERN:
2907 : case A1_OP_TYPE_DECORATE:
2908 : case A1_OP_TYPE:
2909 : case A1_OP_TYPE_EXTERN: {
2910 58702163 : const void *fel = DPOC(from, t->offset);
2911 58702163 : void *tel = DPO(to, t->offset);
2912 58702163 : void **ptel = (void **)tel;
2913 2006343 : size_t size;
2914 :
2915 58702163 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
2916 5303050 : (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2917 57427901 : size = _asn1_sizeofType(t->ptr);
2918 : } else {
2919 1274262 : const struct asn1_type_func *f = t->ptr;
2920 1274262 : size = f->size;
2921 : }
2922 :
2923 58702163 : if (t->tt & A1_FLAG_OPTIONAL) {
2924 4217812 : void **pfel = (void **)fel;
2925 4217812 : if (*pfel == NULL)
2926 2844852 : break;
2927 1273355 : fel = *pfel;
2928 :
2929 1273355 : tel = *ptel = calloc(1, size);
2930 1273355 : if (tel == NULL)
2931 0 : return ENOMEM;
2932 : }
2933 :
2934 55757706 : if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
2935 2458198 : (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2936 54484138 : ret = _asn1_copy(t->ptr, fel, tel);
2937 1273568 : } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) {
2938 3114 : const struct asn1_type_func *f = t->ptr;
2939 3114 : ret = (f->copy)(fel, tel);
2940 : } else {
2941 1270454 : const struct asn1_type_func *f = t->ptr;
2942 :
2943 : /* A1_OP_TYPE_DECORATE_EXTERN */
2944 1270454 : if (f && f->copy)
2945 0 : ret = (f->copy)(fel, tel);
2946 1270454 : else if (f)
2947 1270454 : memset(tel, 0, f->size);
2948 : }
2949 :
2950 55757706 : if (ret) {
2951 0 : if (t->tt & A1_FLAG_OPTIONAL) {
2952 0 : free(*ptel);
2953 0 : *ptel = NULL;
2954 : }
2955 0 : return ret;
2956 : }
2957 53850968 : break;
2958 : }
2959 63272251 : case A1_OP_PARSE: {
2960 63272251 : unsigned int type = A1_PARSE_TYPE(t->tt);
2961 63272251 : const void *fel = DPOC(from, t->offset);
2962 63272251 : void *tel = DPO(to, t->offset);
2963 :
2964 63272251 : if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2965 0 : ABORT_ON_ERROR();
2966 : return ASN1_PARSE_ERROR;
2967 : }
2968 63272251 : ret = (asn1_template_prim[type].copy)(fel, tel);
2969 63272251 : if (ret)
2970 0 : return ret;
2971 61110771 : break;
2972 : }
2973 187321564 : case A1_OP_TAG: {
2974 187321564 : const void *oldfrom = from;
2975 187321564 : void *oldto = to;
2976 187321564 : void **tel = NULL;
2977 :
2978 187321564 : from = DPOC(from, t->offset);
2979 187321564 : to = DPO(to, t->offset);
2980 :
2981 187321564 : if (t->tt & A1_FLAG_OPTIONAL) {
2982 14427531 : void **fel = (void **)from;
2983 14427531 : tel = (void **)to;
2984 14427531 : if (*fel == NULL) {
2985 7568098 : from = oldfrom;
2986 7568098 : to = oldto;
2987 7568098 : break;
2988 : }
2989 6599309 : from = *fel;
2990 :
2991 6599309 : to = *tel = calloc(1, _asn1_sizeofType(t->ptr));
2992 6599309 : if (to == NULL)
2993 0 : return ENOMEM;
2994 : }
2995 :
2996 179493342 : ret = _asn1_copy(t->ptr, from, to);
2997 179493342 : if (ret) {
2998 0 : if (tel) {
2999 0 : free(*tel);
3000 0 : *tel = NULL;
3001 : }
3002 0 : return ret;
3003 : }
3004 :
3005 173354128 : from = oldfrom;
3006 173354128 : to = oldto;
3007 :
3008 173354128 : break;
3009 : }
3010 11406781 : case A1_OP_SETOF:
3011 : case A1_OP_SEQOF: {
3012 11406781 : const struct template_of *fel = DPOC(from, t->offset);
3013 11406781 : struct template_of *tel = DPO(to, t->offset);
3014 11406781 : size_t ellen = _asn1_sizeofType(t->ptr);
3015 390251 : unsigned int i;
3016 :
3017 11406781 : tel->val = calloc(fel->len, ellen);
3018 11406781 : if (tel->val == NULL && fel->len > 0)
3019 0 : return ENOMEM;
3020 :
3021 11406781 : tel->len = fel->len;
3022 :
3023 25644417 : for (i = 0; i < fel->len; i++) {
3024 14725818 : ret = _asn1_copy(t->ptr,
3025 14237636 : DPOC(fel->val, (i * ellen)),
3026 14237636 : DPO(tel->val, (i *ellen)));
3027 14237636 : if (ret)
3028 0 : return ret;
3029 : }
3030 11016530 : break;
3031 : }
3032 1578528 : case A1_OP_BMEMBER: {
3033 1578528 : const struct asn1_template *bmember = t->ptr;
3034 1578528 : size_t size = bmember->offset;
3035 1578528 : memcpy(to, from, size);
3036 1524894 : break;
3037 : }
3038 1279690 : case A1_OP_CHOICE: {
3039 1279690 : const struct asn1_template *choice = t->ptr;
3040 1279690 : const unsigned int *felement = DPOC(from, choice->offset);
3041 1279690 : unsigned int *telement = DPO(to, choice->offset);
3042 :
3043 1279690 : if (*felement > A1_HEADER_LEN(choice))
3044 0 : return ASN1_PARSE_ERROR;
3045 :
3046 1279690 : *telement = *felement;
3047 :
3048 1279690 : if (*felement == 0) {
3049 0 : if (choice->tt)
3050 0 : ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt));
3051 : /*
3052 : * Else we should really memset clear the rest of this choice,
3053 : * but we don't really know its size.
3054 : */
3055 : } else {
3056 1279690 : choice += *felement;
3057 1279690 : ret = _asn1_copy(choice->ptr,
3058 1236454 : DPOC(from, choice->offset),
3059 1279690 : DPO(to, choice->offset));
3060 : }
3061 1279690 : if (ret)
3062 0 : return ret;
3063 1236454 : break;
3064 : }
3065 0 : default:
3066 0 : ABORT_ON_ERROR();
3067 14773308 : break;
3068 : }
3069 432469457 : t++;
3070 432469457 : elements--;
3071 : }
3072 256487958 : return 0;
3073 : }
3074 :
3075 : int
3076 1597880 : _asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size)
3077 : {
3078 56951 : int ret;
3079 1597880 : memset(data, 0, t->offset);
3080 1597880 : ret = _asn1_decode(t, flags, p, len, data, size);
3081 1597880 : if (ret)
3082 182664 : _asn1_free_top(t, data);
3083 :
3084 1597880 : return ret;
3085 : }
3086 :
3087 : int
3088 16074857 : _asn1_copy_top(const struct asn1_template *t, const void *from, void *to)
3089 : {
3090 549271 : int ret;
3091 16074857 : memset(to, 0, t->offset);
3092 16074857 : ret = _asn1_copy(t, from, to);
3093 16074857 : if (ret)
3094 0 : _asn1_free_top(t, to);
3095 :
3096 16074857 : return ret;
3097 : }
3098 :
3099 : void
3100 16214531 : _asn1_free_top(const struct asn1_template *t, void *data)
3101 : {
3102 16214531 : _asn1_free(t, data);
3103 16214531 : memset(data, 0, t->offset);
3104 16214531 : }
|