Coverage Report

Created: 2026-06-07 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/third_party/heimdal/lib/asn1/template.c
Line
Count
Source
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
_asn1_sizeofType(const struct asn1_template *t)
97
0
{
98
0
    return t->offset;
99
0
}
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
_asn1_bmember_get_bit(const unsigned char *p, void *data,
113
          unsigned int bit, size_t size)
114
0
{
115
0
    unsigned int localbit = bit % 8;
116
0
    if ((*p >> (7 - localbit)) & 1) {
117
#ifdef WORDS_BIGENDIAN
118
  *(unsigned int *)data |= (1u << ((size * 8) - bit - 1));
119
#else
120
0
  *(unsigned int *)data |= (1u << bit);
121
0
#endif
122
0
    }
123
0
}
124
125
int
126
_asn1_bmember_isset_bit(const void *data, unsigned int bit, size_t size)
127
0
{
128
#ifdef WORDS_BIGENDIAN
129
    if ((*(unsigned int *)data) & (1u << ((size * 8) - bit - 1)))
130
  return 1;
131
    return 0;
132
#else
133
0
    if ((*(unsigned int *)data) & (1u << bit))
134
0
  return 1;
135
0
    return 0;
136
0
#endif
137
0
}
138
139
void
140
_asn1_bmember_put_bit(unsigned char *p, const void *data, unsigned int bit,
141
          size_t size, unsigned int *bitset)
142
0
{
143
0
    unsigned int localbit = bit % 8;
144
145
0
    if (_asn1_bmember_isset_bit(data, bit, size)) {
146
0
  *p |= (1u << (7 - localbit));
147
0
  if (*bitset == 0)
148
0
      *bitset = (7 - localbit) + 1;
149
0
    }
150
0
}
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
is_tagged(const struct asn1_template *t)
159
0
{
160
0
    size_t elements = A1_HEADER_LEN(t);
161
162
0
    t += A1_HEADER_LEN(t);
163
0
    if (elements != 1)
164
0
        return 0;
165
0
    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
0
    case A1_OP_TAG:         return 1;
171
0
    case A1_OP_CHOICE:      return 1;
172
0
    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
0
    }
185
0
    default: abort();
186
0
    }
187
0
}
188
189
static size_t
190
inner_type_taglen(const struct asn1_template *t)
191
0
{
192
0
    size_t elements = A1_HEADER_LEN(t);
193
194
0
    t += A1_HEADER_LEN(t);
195
0
    if (elements != 1)
196
0
        return 0;
197
0
    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
0
    case A1_OP_TYPE:        return inner_type_taglen(t->ptr);
204
0
    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
0
    }
217
0
    default: abort();
218
#ifdef WIN32
219
             _exit(0); /* Quiet VC */
220
#endif
221
0
    }
222
0
}
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
typeid_int_cmp(const void *intp,
233
               int64_t i,
234
               const struct asn1_template *ttypeid)
235
0
{
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
0
    }
251
0
}
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
template4member(const struct asn1_template *t, size_t f)
264
0
{
265
0
    size_t n = (uintptr_t)t->ptr;
266
0
    size_t i;
267
268
0
    for (i = 0, t++; i < n; t++, i++) {
269
0
        switch (t->tt & A1_OP_MASK) {
270
0
        case A1_OP_TAG:
271
0
        case A1_OP_TYPE:
272
0
        case A1_OP_TYPE_EXTERN:
273
0
            if (f-- == 0)
274
0
                return t;
275
0
            continue;
276
0
        case A1_OP_OPENTYPE_OBJSET:
277
0
        case A1_OP_NAME:
278
0
            return NULL;
279
0
        default:
280
0
            continue;
281
0
        }
282
0
    }
283
0
    return NULL;
284
0
}
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
_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
0
{
370
0
    const struct asn1_template *ttypeid_univ = ttypeid;
371
0
    const struct asn1_template *tactual_type;
372
0
    const struct asn1_template *tos = t->ptr;
373
0
    size_t sz, n;
374
0
    size_t i = 0;
375
0
    unsigned int *lenp = NULL;  /* Pointer to array length field */
376
0
    unsigned int len = 1;       /* Array length */
377
0
    void **dp = NULL;           /* Decoded open type struct pointer */
378
0
    int *elementp;              /* Choice enum pointer */
379
0
    int typeid_is_oid = 0;
380
0
    int typeid_is_int = 0;
381
0
    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
0
    elementp = DPO(data, t->offset);
420
0
    *elementp = 0; /* Set the choice to choice_<type>_iosnumunknown */
421
0
    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
0
    } 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
0
        dp = DPO(data, t->offset + sizeof(*elementp));
489
0
    }
490
491
    /* Align `dp' */
492
0
    while (sizeof(void *) != sizeof(*elementp) &&
493
0
        ((uintptr_t)dp) % sizeof(void *) != 0)
494
0
        dp = (void *)(((char *)dp) + sizeof(*elementp));
495
0
    *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
0
    while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
504
0
            A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
505
0
           ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
506
0
        ttypeid_univ = ttypeid_univ->ptr;
507
0
        ttypeid_univ++;
508
0
    }
509
0
    switch (ttypeid_univ->tt & A1_OP_MASK) {
510
0
    case A1_OP_TAG:
511
0
        if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV)
512
0
            return 0;       /* Do nothing, silently */
513
0
        switch (A1_TAG_TAG(ttypeid_univ->tt)) {
514
0
        case UT_OID:
515
0
            typeid_is_oid = 1;
516
0
            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
0
        }
533
        /* It might be cool to support string types as type ID types */
534
0
        default: return 0;  /* Do nothing, silently */
535
0
        }
536
0
        break;
537
0
    default: return 0;      /* Do nothing, silently */
538
0
    }
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
0
    if (t->tt & A1_OS_IS_SORTED) {
565
0
        size_t left = 0;
566
0
        size_t right = A1_HEADER_LEN(tos);
567
0
        const void *vp = DPO(data, ttypeid->offset);
568
0
        int c = -1;
569
570
0
        while (left < right) {
571
0
            size_t mid = (left + right) >> 1;
572
573
0
            if ((tos[3 + mid * 3].tt & A1_OP_MASK) != A1_OP_OPENTYPE_ID)
574
0
                return 0;
575
0
            if (typeid_is_int)
576
0
                c = typeid_int_cmp(vp, (intptr_t)tos[3 + mid * 3].ptr,
577
0
                                   ttypeid_univ);
578
0
            else if (typeid_is_oid)
579
0
                c = der_heim_oid_cmp(vp, tos[3 + mid * 3].ptr);
580
0
            if (c < 0) {
581
0
                right = mid;
582
0
            } else if (c > 0) {
583
0
                left = mid + 1;
584
0
            } else {
585
0
                i = mid;
586
0
                break;
587
0
            }
588
0
        }
589
0
        if (c)
590
0
            return 0; /* No match */
591
0
    } 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
0
                               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
0
        }
606
0
        if (i == n)
607
0
            return 0; /* No match */
608
0
    }
609
610
    /* Match! */
611
0
    *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
0
    tactual_type = &tos[i*3 + 4];
619
620
    /* Decode the encoded open type value(s) */
621
0
    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
0
        const struct heim_base_data *d = DPOC(data, topentype->offset);
637
0
        void *o;
638
639
0
        if (d->data && d->length) {
640
0
            if ((o = calloc(1, tactual_type->offset)) == NULL)
641
0
                return ENOMEM;
642
643
            /* Re-enter to decode the encoded open type value */
644
0
            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
0
            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
0
            } else {
668
0
                *dp = o;
669
0
            }
670
0
        }
671
0
        return ret;
672
0
    } 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
0
            }
715
0
        }
716
0
        if (ret != ENOMEM)
717
0
            ret = 0; /* See above */
718
0
        *dp = val;
719
0
        return ret;
720
0
    }
721
0
}
722
723
int
724
_asn1_decode(const struct asn1_template *t, unsigned flags,
725
       const unsigned char *p, size_t len, void *data, size_t *size)
726
0
{
727
0
    const struct asn1_template *tbase = t;
728
0
    const struct asn1_template *tdefval = NULL;
729
0
    size_t elements = A1_HEADER_LEN(t);
730
0
    size_t oldlen = len;
731
0
    int ret = 0;
732
0
    const unsigned char *startp = NULL;
733
0
    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
0
    t++;
760
761
0
    if (template_flags & A1_HF_PRESERVE)
762
0
  startp = p;
763
764
0
    while (elements) {
765
0
  switch (t->tt & A1_OP_MASK) {
766
0
        case A1_OP_OPENTYPE_OBJSET: {
767
0
            size_t opentypeid = t->tt & ((1<<10)-1);
768
0
            size_t opentype = (t->tt >> 10) & ((1<<10)-1);
769
770
            /* Note that the only error returned here would be ENOMEM */
771
0
            ret = _asn1_decode_open_type(t, flags, data,
772
0
                                         template4member(tbase, opentypeid),
773
0
                                         template4member(tbase, opentype));
774
0
            if (ret)
775
0
                return ret;
776
0
            break;
777
0
        }
778
0
  case A1_OP_TYPE_DECORATE_EXTERN: break;
779
0
  case A1_OP_TYPE_DECORATE: break;
780
0
        case A1_OP_NAME: break;
781
0
  case A1_OP_DEFVAL:
782
0
            tdefval = t;
783
0
            break;
784
0
  case A1_OP_TYPE:
785
0
  case A1_OP_TYPE_EXTERN: {
786
0
      size_t newsize, elsize;
787
0
      void *el = DPO(data, t->offset);
788
0
      void **pel = (void **)el;
789
790
0
      if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
791
0
    elsize = _asn1_sizeofType(t->ptr);
792
0
      } else {
793
0
    const struct asn1_type_func *f = t->ptr;
794
0
    elsize = f->size;
795
0
      }
796
797
0
      if (t->tt & A1_FLAG_OPTIONAL) {
798
0
    *pel = calloc(1, elsize);
799
0
    if (*pel == NULL)
800
0
        return ENOMEM;
801
0
    el = *pel;
802
0
                if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
803
0
                    ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
804
0
                } else {
805
0
                    const struct asn1_type_func *f = t->ptr;
806
0
                    ret = (f->decode)(p, len, el, &newsize);
807
0
                }
808
0
                if (ret) {
809
                    /*
810
                     * Optional field not present in encoding, presumably,
811
                     * though we should really look more carefully at `ret'.
812
                     */
813
0
                    if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
814
0
                        _asn1_free(t->ptr, el);
815
0
                    } else {
816
0
                        const struct asn1_type_func *f = t->ptr;
817
0
                        f->release(el);
818
0
                    }
819
0
        free(*pel);
820
0
        *pel = NULL;
821
0
        break;
822
0
                }
823
0
      } else {
824
0
                if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
825
0
                    ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
826
0
                } else {
827
0
                    const struct asn1_type_func *f = t->ptr;
828
0
                    ret = (f->decode)(p, len, el, &newsize);
829
0
                }
830
0
            }
831
0
      if (ret) {
832
0
    if (t->tt & A1_FLAG_OPTIONAL) {
833
0
    } else if (t->tt & A1_FLAG_DEFAULT) {
834
0
                    if (!tdefval)
835
0
                        return ASN1_PARSE_ERROR; /* Can't happen */
836
                    /*
837
                     * Defaulted field not present in encoding, presumably,
838
                     * though we should really look more carefully at `ret'.
839
                     */
840
0
                    if (tdefval->tt & A1_DV_BOOLEAN) {
841
0
                        int *i = (void *)(char *)el;
842
843
0
                        *i = tdefval->ptr ? 1 : 0;
844
0
                    } else if (tdefval->tt & A1_DV_INTEGER64) {
845
0
                        int64_t *i = (void *)(char *)el;
846
847
0
                        *i = (int64_t)(intptr_t)tdefval->ptr;
848
0
                    } else if (tdefval->tt & A1_DV_INTEGER32) {
849
0
                        int32_t *i = (void *)(char *)el;
850
851
0
                        *i = (int32_t)(intptr_t)tdefval->ptr;
852
0
                    } else if (tdefval->tt & A1_DV_INTEGER) {
853
0
                        struct heim_integer *i = (void *)(char *)el;
854
855
0
                        if ((ret = der_copy_heim_integer(tdefval->ptr, i)))
856
0
                            return ret;
857
0
                    } else if (tdefval->tt & A1_DV_UTF8STRING) {
858
0
                        char **s = el;
859
860
0
                        if ((*s = strdup(tdefval->ptr)) == NULL)
861
0
                            return ENOMEM;
862
0
                    } else {
863
0
                        abort();
864
0
                    }
865
0
                    break;
866
0
                }
867
0
    return ret; /* Error decoding required field */
868
0
      }
869
0
      p += newsize; len -= newsize;
870
871
0
      break;
872
0
  }
873
0
  case A1_OP_TAG: {
874
0
      Der_type dertype;
875
0
      size_t newsize = 0;
876
0
      size_t datalen, l = 0;
877
0
      void *olddata = data;
878
0
      int is_indefinite = 0;
879
0
      int subflags = flags;
880
0
            int replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
881
0
      void *el = data = DPO(data, t->offset);
882
0
      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
0
      ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt),
895
0
             &dertype, A1_TAG_TAG(t->tt),
896
0
             &datalen, &l);
897
0
      if (ret) {
898
0
    if (t->tt & A1_FLAG_OPTIONAL) {
899
0
                    data = olddata;
900
0
        break;
901
0
                } else if (t->tt & A1_FLAG_DEFAULT) {
902
0
                    if (!tdefval)
903
0
                        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
0
                    if (tdefval->tt & A1_DV_BOOLEAN) {
909
0
                        int *i = (void *)(char *)data;
910
911
0
                        *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
0
                    } else {
931
0
                        abort();
932
0
                    }
933
0
                    data = olddata;
934
0
                    break;
935
0
                }
936
0
    return ret; /* Error decoding required field */
937
0
      }
938
939
0
      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
0
      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
0
      }
954
955
0
      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
0
      } else if (datalen > len)
965
0
    return ASN1_OVERRUN;
966
967
0
      if (t->tt & A1_FLAG_OPTIONAL) {
968
0
    size_t ellen = _asn1_sizeofType(t->ptr);
969
970
0
    *pel = calloc(1, ellen);
971
0
    if (*pel == NULL)
972
0
        return ENOMEM;
973
0
    data = *pel;
974
0
      }
975
976
0
            if (replace_tag) {
977
0
                const struct asn1_template *subtype = t->ptr;
978
0
                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
0
                while (!have_tag) {
989
0
                    subtype++;
990
0
                    if ((subtype->tt & A1_OP_MASK) == A1_OP_TAG)
991
0
                        replace_tag = (subtype->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
992
0
                    if (replace_tag) {
993
0
                        subtype = subtype->ptr;
994
0
                        continue;
995
0
                    }
996
0
                    if ((subtype->tt & A1_OP_MASK) == A1_OP_TAG) {
997
0
                        ret = _asn1_decode(subtype->ptr, subflags, p, datalen, data, &newsize);
998
0
                        have_tag = 1;
999
0
                    } else {
1000
0
                        subtype = subtype->ptr;
1001
0
                    }
1002
0
                }
1003
0
            } else {
1004
0
                ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize);
1005
0
            }
1006
0
            if (ret == 0 && !is_indefinite && newsize != datalen)
1007
    /* Hidden data */
1008
0
                ret = ASN1_EXTRA_DATA;
1009
1010
0
            if (ret == 0) {
1011
0
                if (is_indefinite) {
1012
                    /* If we use indefinite encoding, the newsize is the datasize. */
1013
0
                    datalen = newsize;
1014
0
                }
1015
1016
0
                len -= datalen;
1017
0
                p += datalen;
1018
1019
                /*
1020
                 * Indefinite encoding needs a trailing EndOfContent,
1021
                 * check for that.
1022
                 */
1023
0
                if (is_indefinite) {
1024
0
                    ret = der_match_tag_and_length(p, len, ASN1_C_UNIV,
1025
0
                                                   &dertype, UT_EndOfContent,
1026
0
                                                   &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
0
                    }
1034
0
                }
1035
0
            }
1036
0
            if (ret) {
1037
0
                if (!(t->tt & A1_FLAG_OPTIONAL))
1038
0
                    return ret;
1039
1040
0
                _asn1_free(t->ptr, data);
1041
0
                free(data);
1042
0
                *pel = NULL;
1043
0
                return ret;
1044
0
            }
1045
0
      data = olddata;
1046
1047
0
      break;
1048
0
  }
1049
0
  case A1_OP_PARSE: {
1050
0
      unsigned int type = A1_PARSE_TYPE(t->tt);
1051
0
      size_t newsize;
1052
0
      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
0
      if (flags & A1_PF_INDEFINTE)
1059
0
    type++;
1060
1061
0
      if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
1062
0
    ABORT_ON_ERROR();
1063
0
    return ASN1_PARSE_ERROR;
1064
0
      }
1065
1066
0
      ret = (asn1_template_prim[type].decode)(p, len, el, &newsize);
1067
0
      if (ret)
1068
0
    return ret;
1069
0
      p += newsize; len -= newsize;
1070
1071
0
      break;
1072
0
  }
1073
0
  case A1_OP_SETOF:
1074
0
  case A1_OP_SEQOF: {
1075
0
      struct template_of *el = DPO(data, t->offset);
1076
0
      size_t newsize;
1077
0
      size_t ellen = _asn1_sizeofType(t->ptr);
1078
0
      size_t vallength = 0;
1079
1080
0
      while (len > 0) {
1081
0
    void *tmp;
1082
0
    size_t newlen = vallength + ellen;
1083
0
    if (vallength > newlen)
1084
0
        return ASN1_OVERFLOW;
1085
1086
                /* XXX Slow */
1087
0
    tmp = realloc(el->val, newlen);
1088
0
    if (tmp == NULL)
1089
0
        return ENOMEM;
1090
1091
0
    memset(DPO(tmp, vallength), 0, ellen);
1092
0
    el->val = tmp;
1093
1094
0
    el->len++;
1095
0
    ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len,
1096
0
           DPO(el->val, vallength), &newsize);
1097
0
    if (ret)
1098
0
        return ret;
1099
0
    vallength = newlen;
1100
0
    p += newsize; len -= newsize;
1101
0
      }
1102
1103
0
      break;
1104
0
  }
1105
0
  case A1_OP_BMEMBER: {
1106
0
      const struct asn1_template *bmember = t->ptr;
1107
0
      size_t bsize = bmember->offset;
1108
0
      size_t belements = A1_HEADER_LEN(bmember);
1109
0
      size_t pos = 0;
1110
1111
0
      bmember++;
1112
1113
0
      memset(data, 0, bsize);
1114
1115
0
      if (len < 1)
1116
0
    return ASN1_OVERRUN;
1117
0
      p++; len--;
1118
1119
0
      while (belements && len) {
1120
0
    while (bmember->offset / 8 > pos / 8) {
1121
0
        if (len < 1)
1122
0
      break;
1123
0
        p++; len--;
1124
0
        pos += 8;
1125
0
    }
1126
0
    if (len) {
1127
0
        _asn1_bmember_get_bit(p, data, bmember->offset, bsize);
1128
0
        belements--; bmember++;
1129
0
    }
1130
0
      }
1131
0
      len = 0;
1132
0
      break;
1133
0
  }
1134
0
  case A1_OP_CHOICE: {
1135
0
      const struct asn1_template *choice = t->ptr;
1136
0
      unsigned int *element = DPO(data, choice->offset);
1137
0
      size_t datalen;
1138
0
      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
0
      *element = ~0;
1147
1148
0
      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
0
    ret = _asn1_decode(choice[i].ptr, 0, p, len,
1167
0
           DPO(data, choice[i].offset), &datalen);
1168
0
    if (ret == 0) {
1169
0
        *element = i;
1170
0
        p += datalen; len -= datalen;
1171
0
        break;
1172
0
    }
1173
0
                _asn1_free(choice[i].ptr, DPO(data, choice[i].offset));
1174
0
                if (ret != ASN1_BAD_ID && ret != ASN1_MISPLACED_FIELD &&
1175
0
                    ret != ASN1_MISSING_FIELD)
1176
0
        return ret;
1177
0
      }
1178
0
      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
0
    if (choice->tt == 0)
1187
0
        return ASN1_BAD_ID;
1188
1189
                /* This is the ellipsis case */
1190
0
    *element = 0;
1191
0
    ret = der_get_octet_string(p, len,
1192
0
             DPO(data, choice->tt), &datalen);
1193
0
    if (ret)
1194
0
        return ret;
1195
0
    p += datalen; len -= datalen;
1196
0
      }
1197
1198
0
      break;
1199
0
  }
1200
0
  default:
1201
0
      ABORT_ON_ERROR();
1202
0
      return ASN1_PARSE_ERROR;
1203
0
  }
1204
0
  t++;
1205
0
  elements--;
1206
0
    }
1207
    /* if we are using padding, eat up read of context */
1208
0
    if (template_flags & A1_HF_ELLIPSIS)
1209
0
  len = 0;
1210
1211
0
    oldlen -= len;
1212
1213
0
    if (size)
1214
0
  *size = oldlen;
1215
1216
    /*
1217
     * saved the raw bits if asked for it, useful for signature
1218
     * verification.
1219
     */
1220
0
    if (startp) {
1221
0
  heim_octet_string *save = data;
1222
1223
0
  save->data = malloc(oldlen);
1224
0
  if (save->data == NULL)
1225
0
      return ENOMEM;
1226
0
  else {
1227
0
      save->length = oldlen;
1228
0
      memcpy(save->data, startp, oldlen);
1229
0
  }
1230
0
    }
1231
0
    return 0;
1232
0
}
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
typeid_int_copy(void *intp,
1240
                int64_t i,
1241
                const struct asn1_template *ttypeid)
1242
0
{
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
0
    }
1254
0
}
1255
1256
/* See commentary in _asn1_decode_open_type() */
1257
static int
1258
_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
0
{
1263
0
    const struct asn1_template *ttypeid_univ = ttypeid;
1264
0
    const struct asn1_template *tactual_type;
1265
0
    const struct asn1_template *tos = t->ptr;
1266
0
    size_t sz, i;
1267
0
    unsigned int *lenp = NULL;
1268
0
    unsigned int len = 1;
1269
0
    int element = *(const int *)DPOC(data, t->offset);
1270
0
    int typeid_is_oid = 0;
1271
0
    int typeid_is_int = 0;
1272
0
    int enotsup = 0;
1273
0
    int ret = 0;
1274
1275
0
    if (element == 0 || element >= A1_HEADER_LEN(tos) + 1)
1276
0
        return 0;
1277
1278
0
    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
0
    }
1285
1286
    /* Work out the type ID field's type */
1287
0
    while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
1288
0
            A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
1289
0
           ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
1290
0
        ttypeid_univ = ttypeid_univ->ptr;
1291
0
        ttypeid_univ++;
1292
0
    }
1293
0
    switch (ttypeid_univ->tt & A1_OP_MASK) {
1294
0
    case A1_OP_TAG:
1295
0
        if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV) {
1296
0
            enotsup = 1;
1297
0
            break;
1298
0
        }
1299
0
        switch (A1_TAG_TAG(ttypeid_univ->tt)) {
1300
0
        case UT_OID:
1301
0
            typeid_is_oid = 1;
1302
0
            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
0
            }
1312
0
            typeid_is_int = 1;
1313
0
            break;
1314
0
        }
1315
0
        default: enotsup = 1; break;
1316
0
        }
1317
0
        break;
1318
0
    default: enotsup = 1; break;
1319
0
    }
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
0
    if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
1327
0
        struct heim_base_data *os = DPO(data, topentype->offset);
1328
1329
0
        if (os->length && os->data)
1330
0
            return 0;
1331
0
    } 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
0
    }
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
0
    } 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
0
        }
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
0
    } 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
0
        }
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
0
        }
1405
0
        *(struct heim_base_data **)DPO(data, topentype->offset + sizeof(len)) = os;
1406
0
    }
1407
0
    return ret;
1408
0
}
1409
1410
int
1411
_asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const void *data, size_t *size)
1412
0
{
1413
0
    const struct asn1_template *tbase = t;
1414
0
    size_t elements = A1_HEADER_LEN(t);
1415
0
    int ret = 0;
1416
0
    size_t oldlen = len;
1417
1418
0
    t += A1_HEADER_LEN(t);
1419
1420
0
    while (elements) {
1421
0
  switch (t->tt & A1_OP_MASK) {
1422
0
        case A1_OP_OPENTYPE_OBJSET: {
1423
0
            size_t opentypeid = t->tt & ((1<<10)-1);
1424
0
            size_t opentype = (t->tt >> 10) & ((1<<10)-1);
1425
0
            ret = _asn1_encode_open_type(t, data,
1426
0
                                         template4member(tbase, opentypeid),
1427
0
                                         template4member(tbase, opentype));
1428
0
            if (ret)
1429
0
                return ret;
1430
0
            break;
1431
0
        }
1432
0
        case A1_OP_NAME: break;
1433
0
  case A1_OP_DEFVAL: break;
1434
0
  case A1_OP_TYPE_DECORATE_EXTERN: break;
1435
0
  case A1_OP_TYPE_DECORATE: break;
1436
0
  case A1_OP_TYPE:
1437
0
  case A1_OP_TYPE_EXTERN: {
1438
0
      size_t newsize;
1439
0
      const void *el = DPOC(data, t->offset);
1440
1441
0
      if (t->tt & A1_FLAG_OPTIONAL) {
1442
0
    void **pel = (void **)el;
1443
0
    if (*pel == NULL)
1444
0
        break;
1445
0
    el = *pel;
1446
0
            } 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
0
                        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
0
                } else {
1477
0
                    abort();
1478
0
                }
1479
0
            }
1480
1481
0
      if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
1482
0
    ret = _asn1_encode(t->ptr, p, len, el, &newsize);
1483
0
      } else {
1484
0
    const struct asn1_type_func *f = t->ptr;
1485
0
    ret = (f->encode)(p, len, el, &newsize);
1486
0
      }
1487
1488
0
      if (ret)
1489
0
    return ret;
1490
0
      p -= newsize; len -= newsize;
1491
1492
0
      break;
1493
0
  }
1494
0
  case A1_OP_TAG: {
1495
0
      const void *olddata = data;
1496
0
      size_t l, datalen = 0;
1497
0
            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
0
      data = DPOC(data, t->offset);
1510
1511
0
      if (t->tt & A1_FLAG_OPTIONAL) {
1512
0
    void **el = (void **)data;
1513
0
    if (*el == NULL) {
1514
0
        data = olddata;
1515
0
        break;
1516
0
    }
1517
0
    data = *el;
1518
0
            } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
1519
0
                const struct asn1_template *tdefval = t - 1;
1520
0
                int exclude = 0;
1521
1522
                /* Compare tdefval to whatever's at `data' */
1523
0
                if (tdefval->tt & A1_DV_BOOLEAN) {
1524
0
                    const int *i = (void *)(char *)data;
1525
1526
0
                    if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
1527
0
                        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
0
                } else {
1551
0
                    abort();
1552
0
                }
1553
0
                if (exclude) {
1554
0
                    data = olddata;
1555
0
                    break;
1556
0
                }
1557
0
            }
1558
1559
0
            replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
1560
1561
            /* IMPLICIT tags need special handling (see gen_encode.c) */
1562
0
            if (replace_tag) {
1563
0
                unsigned char *pfree, *psave = p;
1564
0
                Der_class found_class;
1565
0
                Der_type found_type = 0;
1566
0
                unsigned int found_tag;
1567
0
                size_t lensave = len;
1568
0
                size_t oldtaglen = 0;
1569
0
                size_t taglen = der_length_tag(A1_TAG_TAG(t->tt));;
1570
1571
                /* Allocate a buffer at least as big as we need */
1572
0
                len = _asn1_length(t->ptr, data) + taglen;
1573
0
                if ((p = pfree = malloc(len)) == NULL) {
1574
0
                    ret = ENOMEM;
1575
0
                } else {
1576
                    /*
1577
                     * Encode into it (with the wrong tag, which we'll replace
1578
                     * below).
1579
                     */
1580
0
                    p += len - 1;
1581
0
                    ret = _asn1_encode(t->ptr, p, len, data, &datalen);
1582
0
                }
1583
0
                if (ret == 0) {
1584
                    /* Get the old tag and, critically, its length */
1585
0
                    len -= datalen; p -= datalen;
1586
0
                    ret = der_get_tag(p + 1, datalen, &found_class, &found_type,
1587
0
                                      &found_tag, &oldtaglen);
1588
0
                }
1589
0
                if (ret == 0) {
1590
                    /* Drop the old tag */
1591
0
                    len += oldtaglen; p += oldtaglen;
1592
                    /* Put the new tag */
1593
0
                    ret = der_put_tag(p, len,
1594
0
                                      A1_TAG_CLASS(t->tt),
1595
0
                                      found_type,
1596
0
                                      A1_TAG_TAG(t->tt), &l);
1597
0
                }
1598
0
                if (ret == 0) {
1599
                    /* Copy the encoding where it belongs */
1600
0
                    psave -= (datalen + l - oldtaglen);
1601
0
                    lensave -= (datalen + l - oldtaglen);
1602
0
                    memcpy(psave + 1, p + 1 - l, datalen + l - oldtaglen);
1603
0
                    p = psave;
1604
0
                    len = lensave;
1605
0
                }
1606
0
                free(pfree);
1607
0
            } else {
1608
                /* Easy case */
1609
0
                ret = _asn1_encode(t->ptr, p, len, data, &datalen);
1610
0
                if (ret)
1611
0
                    return ret;
1612
1613
0
                len -= datalen; p -= datalen;
1614
1615
0
                ret = der_put_length_and_tag(p, len, datalen,
1616
0
                                             A1_TAG_CLASS(t->tt),
1617
0
                                             A1_TAG_TYPE(t->tt),
1618
0
                                             A1_TAG_TAG(t->tt), &l);
1619
0
                if (ret == 0) {
1620
0
                    p -= l; len -= l;
1621
0
                }
1622
0
            }
1623
0
      if (ret)
1624
0
    return ret;
1625
1626
0
      data = olddata;
1627
1628
0
      break;
1629
0
  }
1630
0
  case A1_OP_PARSE: {
1631
0
      unsigned int type = A1_PARSE_TYPE(t->tt);
1632
0
      size_t newsize;
1633
0
      const void *el = DPOC(data, t->offset);
1634
1635
0
      if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
1636
0
    ABORT_ON_ERROR();
1637
0
    return ASN1_PARSE_ERROR;
1638
0
      }
1639
1640
0
      ret = (asn1_template_prim[type].encode)(p, len, el, &newsize);
1641
0
      if (ret)
1642
0
    return ret;
1643
0
      p -= newsize; len -= newsize;
1644
1645
0
      break;
1646
0
  }
1647
0
  case A1_OP_SETOF: {
1648
0
      const struct template_of *el = DPOC(data, t->offset);
1649
0
      size_t ellen = _asn1_sizeofType(t->ptr);
1650
0
      heim_octet_string *val;
1651
0
      unsigned char *elptr = el->val;
1652
0
      size_t i, totallen;
1653
1654
0
      if (el->len == 0)
1655
0
    break;
1656
1657
0
      if (el->len > UINT_MAX/sizeof(val[0]))
1658
0
    return ERANGE;
1659
1660
0
      val = calloc(el->len, sizeof(val[0]));
1661
0
      if (val == NULL)
1662
0
    return ENOMEM;
1663
1664
0
      for(totallen = 0, i = 0; i < el->len; i++) {
1665
0
    unsigned char *next;
1666
0
    size_t l;
1667
1668
0
    val[i].length = _asn1_length(t->ptr, elptr);
1669
0
    if (val[i].length) {
1670
0
        val[i].data = malloc(val[i].length);
1671
0
        if (val[i].data == NULL) {
1672
0
      ret = ENOMEM;
1673
0
      break;
1674
0
        }
1675
0
    }
1676
1677
0
    ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1),
1678
0
           val[i].length, elptr, &l);
1679
0
    if (ret)
1680
0
        break;
1681
1682
0
    next = elptr + ellen;
1683
0
    if (next < elptr) {
1684
0
        ret = ASN1_OVERFLOW;
1685
0
        break;
1686
0
    }
1687
0
    elptr = next;
1688
0
    totallen += val[i].length;
1689
0
      }
1690
0
      if (ret == 0 && totallen > len)
1691
0
    ret = ASN1_OVERFLOW;
1692
0
      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
0
      }
1698
1699
0
      len -= totallen;
1700
1701
0
      qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort);
1702
1703
0
      i = el->len - 1;
1704
0
      do {
1705
0
    p -= val[i].length;
1706
0
    memcpy(p + 1, val[i].data, val[i].length);
1707
0
    free(val[i].data);
1708
0
      } while(i-- > 0);
1709
0
      free(val);
1710
1711
0
      break;
1712
1713
0
  }
1714
0
  case A1_OP_SEQOF: {
1715
0
      struct template_of *el = DPO(data, t->offset);
1716
0
      size_t ellen = _asn1_sizeofType(t->ptr);
1717
0
      size_t newsize;
1718
0
      unsigned int i;
1719
0
      unsigned char *elptr = el->val;
1720
1721
0
      if (el->len == 0)
1722
0
    break;
1723
1724
0
      elptr += ellen * (el->len - 1);
1725
1726
0
      for (i = 0; i < el->len; i++) {
1727
0
    ret = _asn1_encode(t->ptr, p, len,
1728
0
           elptr,
1729
0
           &newsize);
1730
0
    if (ret)
1731
0
        return ret;
1732
0
    p -= newsize; len -= newsize;
1733
0
    elptr -= ellen;
1734
0
      }
1735
1736
0
      break;
1737
0
  }
1738
0
  case A1_OP_BMEMBER: {
1739
0
      const struct asn1_template *bmember = t->ptr;
1740
0
      size_t bsize = bmember->offset;
1741
0
      size_t belements = A1_HEADER_LEN(bmember);
1742
0
      size_t pos;
1743
0
      unsigned char c = 0;
1744
0
      unsigned int bitset = 0;
1745
0
      int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
1746
1747
0
      bmember += belements;
1748
1749
0
      if (rfc1510)
1750
0
    pos = 31;
1751
0
      else
1752
0
    pos = bmember->offset;
1753
1754
0
      while (belements && len) {
1755
0
    while (bmember->offset / 8 < pos / 8) {
1756
0
        if (rfc1510 || bitset || c) {
1757
0
      if (len < 1)
1758
0
          return ASN1_OVERFLOW;
1759
0
      *p-- = c; len--;
1760
0
        }
1761
0
        c = 0;
1762
0
        pos -= 8;
1763
0
    }
1764
0
    _asn1_bmember_put_bit(&c, data, bmember->offset, bsize, &bitset);
1765
0
    belements--; bmember--;
1766
0
      }
1767
0
      if (rfc1510 || bitset) {
1768
0
    if (len < 1)
1769
0
        return ASN1_OVERFLOW;
1770
0
    *p-- = c; len--;
1771
0
      }
1772
1773
0
      if (len < 1)
1774
0
    return ASN1_OVERFLOW;
1775
0
      if (rfc1510 || bitset == 0)
1776
0
    *p-- = 0;
1777
0
      else
1778
0
    *p-- = bitset - 1;
1779
1780
0
      len--;
1781
1782
0
      break;
1783
0
  }
1784
0
  case A1_OP_CHOICE: {
1785
0
      const struct asn1_template *choice = t->ptr;
1786
0
      const unsigned int *element = DPOC(data, choice->offset);
1787
0
      size_t datalen;
1788
0
      const void *el;
1789
1790
0
      if (*element > A1_HEADER_LEN(choice)) {
1791
0
    printf("element: %d\n", *element);
1792
0
    return ASN1_PARSE_ERROR;
1793
0
      }
1794
1795
0
      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
0
                } /* else this is really an error -- XXX what to do? */
1802
0
      } else {
1803
0
    choice += *element;
1804
0
    el = DPOC(data, choice->offset);
1805
0
    ret = _asn1_encode(choice->ptr, p, len, el, &datalen);
1806
0
    if (ret)
1807
0
        return ret;
1808
0
                len -= datalen; p -= datalen;
1809
0
      }
1810
1811
0
      break;
1812
0
  }
1813
0
  default:
1814
0
      ABORT_ON_ERROR();
1815
0
  }
1816
0
  t--;
1817
0
  elements--;
1818
0
    }
1819
0
    if (size)
1820
0
  *size = oldlen - len;
1821
1822
0
    return 0;
1823
0
}
1824
1825
static size_t
1826
_asn1_length_open_type_helper(const struct asn1_template *t,
1827
                              size_t sz)
1828
0
{
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
0
    }
1841
0
}
1842
1843
static size_t
1844
_asn1_length_open_type_id(const struct asn1_template *t,
1845
                          const void *data)
1846
0
{
1847
0
    struct asn1_template pretend[2] = {
1848
0
  { 0, 0, ((void*)(uintptr_t)1) },
1849
0
    };
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
0
}
1856
1857
/* See commentary in _asn1_encode_open_type() */
1858
static size_t
1859
_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
0
{
1865
0
    const struct asn1_template *ttypeid_univ = ttypeid;
1866
0
    const struct asn1_template *tactual_type;
1867
0
    const struct asn1_template *tos = t->ptr;
1868
0
    const unsigned int *lenp = NULL;
1869
0
    unsigned int len = 1;
1870
0
    size_t sz = 0;
1871
0
    size_t i;
1872
0
    int element = *(const int *)DPOC(data, t->offset);
1873
0
    int typeid_is_oid = 0;
1874
0
    int typeid_is_int = 0;
1875
1876
    /* If nothing to encode, we add nothing to the length */
1877
0
    if (element == 0 || element >= A1_HEADER_LEN(tos) + 1)
1878
0
        return 0;
1879
0
    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
0
    }
1884
1885
    /* Work out the type ID field's type */
1886
0
    while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
1887
0
            A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
1888
0
           ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
1889
0
        ttypeid_univ = ttypeid_univ->ptr;
1890
0
        ttypeid_univ++;
1891
0
    }
1892
0
    switch (ttypeid_univ->tt & A1_OP_MASK) {
1893
0
    case A1_OP_TAG:
1894
0
        if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV)
1895
0
            return 0;
1896
0
        switch (A1_TAG_TAG(ttypeid_univ->tt)) {
1897
0
        case UT_OID:
1898
0
            typeid_is_oid = 1;
1899
0
            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
0
        }
1910
0
        default: return 0;
1911
0
        }
1912
0
        break;
1913
0
    default: return 0;
1914
0
    }
1915
0
    if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
1916
0
        struct heim_base_data *os = DPO(data, topentype->offset);
1917
1918
0
        if (os->length && os->data)
1919
0
            return 0;
1920
0
    } 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
0
    }
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, &i4);
1949
0
            break;
1950
0
        default:
1951
0
            return 0;
1952
0
        }
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
0
    }
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
0
    } 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
0
        }
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
0
    }
1988
0
    return sz;
1989
0
}
1990
1991
size_t
1992
_asn1_length(const struct asn1_template *t, const void *data)
1993
0
{
1994
0
    const struct asn1_template *tbase = t;
1995
0
    size_t elements = A1_HEADER_LEN(t);
1996
0
    size_t ret = 0;
1997
1998
0
    t += A1_HEADER_LEN(t);
1999
2000
0
    while (elements) {
2001
0
  switch (t->tt & A1_OP_MASK) {
2002
0
        case A1_OP_OPENTYPE_OBJSET: {
2003
0
            size_t opentypeid = t->tt & ((1<<10)-1);
2004
0
            size_t opentype = (t->tt >> 10) & ((1<<10)-1);
2005
0
            ret += _asn1_length_open_type(tbase, t, data,
2006
0
                                          template4member(tbase, opentypeid),
2007
0
                                          template4member(tbase, opentype));
2008
0
            break;
2009
0
        }
2010
0
        case A1_OP_NAME: break;
2011
0
  case A1_OP_DEFVAL: break;
2012
0
  case A1_OP_TYPE_DECORATE_EXTERN: break;
2013
0
  case A1_OP_TYPE_DECORATE: break;
2014
0
  case A1_OP_TYPE:
2015
0
  case A1_OP_TYPE_EXTERN: {
2016
0
      const void *el = DPOC(data, t->offset);
2017
2018
0
      if (t->tt & A1_FLAG_OPTIONAL) {
2019
0
    void **pel = (void **)el;
2020
0
    if (*pel == NULL)
2021
0
        break;
2022
0
    el = *pel;
2023
0
            } 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
0
                        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
0
                } else {
2055
0
                    abort();
2056
0
                }
2057
0
            }
2058
2059
0
      if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
2060
0
    ret += _asn1_length(t->ptr, el);
2061
0
      } else {
2062
0
    const struct asn1_type_func *f = t->ptr;
2063
0
    ret += (f->length)(el);
2064
0
      }
2065
0
      break;
2066
0
  }
2067
0
  case A1_OP_TAG: {
2068
0
      size_t datalen;
2069
0
      const void *olddata = data;
2070
0
            size_t oldtaglen = 0;
2071
2072
0
      data = DPO(data, t->offset);
2073
2074
0
      if (t->tt & A1_FLAG_OPTIONAL) {
2075
0
    void **el = (void **)data;
2076
0
    if (*el == NULL) {
2077
0
        data = olddata;
2078
0
        break;
2079
0
    }
2080
0
    data = *el;
2081
0
      } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
2082
0
                const struct asn1_template *tdefval = t - 1;
2083
0
                int exclude = 0;
2084
2085
                /* Compare tdefval to whatever's at `data' */
2086
0
                if (tdefval->tt & A1_DV_BOOLEAN) {
2087
0
                    const int *i = (void *)(char *)data;
2088
2089
0
                    if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
2090
0
                        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
0
                } else {
2114
0
                    abort();
2115
0
                }
2116
0
                if (exclude) {
2117
0
                    data = olddata;
2118
0
                    break;
2119
0
                }
2120
0
            }
2121
2122
0
            if (t->tt & A1_FLAG_IMPLICIT)
2123
0
                oldtaglen = inner_type_taglen(t->ptr);
2124
2125
0
      datalen = _asn1_length(t->ptr, data);
2126
0
      ret += datalen;
2127
0
      ret += der_length_tag(A1_TAG_TAG(t->tt));
2128
0
            ret += oldtaglen ? -oldtaglen : der_length_len(datalen);
2129
0
      data = olddata;
2130
0
      break;
2131
0
  }
2132
0
  case A1_OP_PARSE: {
2133
0
      unsigned int type = A1_PARSE_TYPE(t->tt);
2134
0
      const void *el = DPOC(data, t->offset);
2135
2136
0
      if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2137
0
    ABORT_ON_ERROR();
2138
0
    break;
2139
0
      }
2140
0
      ret += (asn1_template_prim[type].length)(el);
2141
0
      break;
2142
0
  }
2143
0
  case A1_OP_SETOF:
2144
0
  case A1_OP_SEQOF: {
2145
0
      const struct template_of *el = DPOC(data, t->offset);
2146
0
      size_t ellen = _asn1_sizeofType(t->ptr);
2147
0
      const unsigned char *element = el->val;
2148
0
      unsigned int i;
2149
2150
0
      for (i = 0; i < el->len; i++) {
2151
0
    ret += _asn1_length(t->ptr, element);
2152
0
    element += ellen;
2153
0
      }
2154
2155
0
      break;
2156
0
  }
2157
0
  case A1_OP_BMEMBER: {
2158
0
      const struct asn1_template *bmember = t->ptr;
2159
0
      size_t size = bmember->offset;
2160
0
      size_t belements = A1_HEADER_LEN(bmember);
2161
0
      int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
2162
2163
0
      if (rfc1510) {
2164
0
    ret += 5;
2165
0
      } 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
0
        }
2176
0
        belements--; bmember--;
2177
0
    }
2178
0
      }
2179
0
      break;
2180
0
  }
2181
0
  case A1_OP_CHOICE: {
2182
0
      const struct asn1_template *choice = t->ptr;
2183
0
      const unsigned int *element = DPOC(data, choice->offset);
2184
2185
0
      if (*element > A1_HEADER_LEN(choice))
2186
0
    break;
2187
2188
0
      if (*element == 0) {
2189
0
                if (choice->tt)
2190
0
                    ret += der_length_octet_string(DPOC(data, choice->tt));
2191
0
      } else {
2192
0
    choice += *element;
2193
0
    ret += _asn1_length(choice->ptr, DPOC(data, choice->offset));
2194
0
      }
2195
0
      break;
2196
0
  }
2197
0
  default:
2198
0
      ABORT_ON_ERROR();
2199
0
      break;
2200
0
  }
2201
0
  elements--;
2202
0
  t--;
2203
0
    }
2204
0
    return ret;
2205
0
}
2206
2207
/* See commentary in _asn1_decode_open_type() */
2208
static void
2209
_asn1_free_open_type(const struct asn1_template *t, /* object set template */
2210
                     void *data)
2211
0
{
2212
0
    const struct asn1_template *tactual_type;
2213
0
    const struct asn1_template *tos = t->ptr;
2214
0
    unsigned int *lenp = NULL;  /* Pointer to array length field */
2215
0
    unsigned int len = 1;       /* Array length */
2216
0
    size_t i;
2217
0
    void **dp;
2218
0
    void **val;
2219
0
    int *elementp = DPO(data, t->offset);   /* Choice enum pointer */
2220
2221
    /* XXX We assume sizeof(enum) == sizeof(int) */
2222
0
    if (!*elementp || *elementp >= A1_HEADER_LEN(tos) + 1)
2223
0
        return; /* Unknown choice -> it's not decoded, nothing to free here */
2224
0
    tactual_type = tos[3*(*elementp - 1) + 4].ptr;
2225
2226
0
    if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
2227
0
        dp = DPO(data, t->offset + sizeof(*elementp));
2228
0
        while (sizeof(void *) != sizeof(*elementp) &&
2229
0
               ((uintptr_t)dp) % sizeof(void *) != 0)
2230
0
            dp = (void *)(((char *)dp) + sizeof(*elementp));
2231
0
        if (*dp) {
2232
0
            _asn1_free(tactual_type, *dp);
2233
0
            free(*dp);
2234
0
            *dp = NULL;
2235
0
        }
2236
0
        return;
2237
0
    }
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
0
        }
2252
0
    }
2253
0
    free(val);
2254
0
    *lenp = 0;
2255
0
    *dp = NULL;
2256
0
}
2257
2258
void
2259
_asn1_free(const struct asn1_template *t, void *data)
2260
0
{
2261
0
    size_t elements = A1_HEADER_LEN(t);
2262
2263
0
    if (t->tt & A1_HF_PRESERVE)
2264
0
  der_free_octet_string(data);
2265
2266
0
    t++;
2267
2268
0
    while (elements) {
2269
0
  switch (t->tt & A1_OP_MASK) {
2270
0
        case A1_OP_OPENTYPE_OBJSET: {
2271
0
            _asn1_free_open_type(t, data);
2272
0
            break;
2273
0
        }
2274
0
        case A1_OP_NAME: break;
2275
0
  case A1_OP_DEFVAL: break;
2276
0
  case A1_OP_TYPE_DECORATE_EXTERN:
2277
0
  case A1_OP_TYPE_DECORATE:
2278
0
  case A1_OP_TYPE:
2279
0
  case A1_OP_TYPE_EXTERN: {
2280
0
      void *el = DPO(data, t->offset);
2281
0
            void **pel = (void **)el;
2282
2283
0
      if (t->tt & A1_FLAG_OPTIONAL) {
2284
0
    if (*pel == NULL)
2285
0
        break;
2286
0
    el = *pel;
2287
0
      }
2288
2289
0
      if ((t->tt & A1_OP_MASK) == A1_OP_TYPE || (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2290
0
    _asn1_free(t->ptr, el);
2291
0
      } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) {
2292
0
    const struct asn1_type_func *f = t->ptr;
2293
0
    (f->release)(el);
2294
0
      } else {
2295
                /* A1_OP_TYPE_DECORATE_EXTERN */
2296
0
    const struct asn1_type_func *f = t->ptr;
2297
2298
0
                if (f && f->release)
2299
0
                    (f->release)(el);
2300
0
                else if (f)
2301
0
                    memset(el, 0, f->size);
2302
0
      }
2303
0
      if (t->tt & A1_FLAG_OPTIONAL) {
2304
0
    free(el);
2305
0
                *pel = NULL;
2306
0
            }
2307
2308
0
      break;
2309
0
  }
2310
0
  case A1_OP_PARSE: {
2311
0
      unsigned int type = A1_PARSE_TYPE(t->tt);
2312
0
      void *el = DPO(data, t->offset);
2313
2314
0
      if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2315
0
    ABORT_ON_ERROR();
2316
0
    break;
2317
0
      }
2318
0
      (asn1_template_prim[type].release)(el);
2319
0
      break;
2320
0
  }
2321
0
  case A1_OP_TAG: {
2322
0
      void *el = DPO(data, t->offset);
2323
2324
0
      if (t->tt & A1_FLAG_OPTIONAL) {
2325
0
                void **pel = (void **)el;
2326
2327
0
    if (*pel == NULL)
2328
0
        break;
2329
0
                _asn1_free(t->ptr, *pel);
2330
0
    free(*pel);
2331
0
                *pel = NULL;
2332
0
            } else {
2333
0
                _asn1_free(t->ptr, el);
2334
0
            }
2335
2336
0
      break;
2337
0
  }
2338
0
  case A1_OP_SETOF:
2339
0
  case A1_OP_SEQOF: {
2340
0
      struct template_of *el = DPO(data, t->offset);
2341
0
      size_t ellen = _asn1_sizeofType(t->ptr);
2342
0
      unsigned char *element = el->val;
2343
0
      unsigned int i;
2344
2345
0
      for (i = 0; i < el->len; i++) {
2346
0
    _asn1_free(t->ptr, element);
2347
0
    element += ellen;
2348
0
      }
2349
0
      free(el->val);
2350
0
      el->val = NULL;
2351
0
      el->len = 0;
2352
2353
0
      break;
2354
0
  }
2355
0
  case A1_OP_BMEMBER:
2356
0
      break;
2357
0
  case A1_OP_CHOICE: {
2358
0
      const struct asn1_template *choice = t->ptr;
2359
0
      const unsigned int *element = DPOC(data, choice->offset);
2360
2361
0
      if (*element > A1_HEADER_LEN(choice))
2362
0
    break;
2363
2364
0
      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
0
                if (choice->tt != 0)
2370
0
                    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
0
      } else {
2376
0
    choice += *element;
2377
0
    _asn1_free(choice->ptr, DPO(data, choice->offset));
2378
0
      }
2379
0
      break;
2380
0
  }
2381
0
  default:
2382
0
      ABORT_ON_ERROR();
2383
0
      break;
2384
0
  }
2385
0
  t++;
2386
0
  elements--;
2387
0
    }
2388
0
}
2389
2390
static char *
2391
getindent(int flags, unsigned int i)
2392
0
{
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
0
}
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
_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
0
{
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
0
                             indents ? indents : "", opentype_name);
2437
0
        free(indents);
2438
0
        return r;
2439
0
    }
2440
0
    tactual_type = tos[3*(*elementp - 1) + 4].ptr;
2441
2442
0
    r = rk_strpoolprintf(r, ",%s\"_%s_choice\":\"%s\"",
2443
0
                         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
0
    }
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
0
                                     indents ? indents : "", opentype_name);
2463
0
                free(indents);
2464
0
                return r;
2465
0
            }
2466
0
            s = rk_strpoolcollect(r2);
2467
0
            if (s)
2468
0
                r = rk_strpoolprintf(r, ",%s\"_%s\":%s",
2469
0
                                     indents ? indents : "", opentype_name, s);
2470
0
            free(s);
2471
0
        }
2472
0
  free(indents);
2473
0
        return r;
2474
0
    }
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
0
                         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
0
            }
2500
0
        }
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
0
    }
2507
0
    free(indents);
2508
0
    return rk_strpoolprintf(r, "]");
2509
0
}
2510
2511
static struct rk_strpool *
2512
_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
0
{
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
0
                             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
0
        }
2546
0
        r = rk_strpoolprintf(r, ",%s\"_save\":\"%s\"",
2547
0
                             indents ? indents : "", s);
2548
0
        free(s);
2549
0
    }
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
0
        }
2571
0
        default: break;
2572
0
        }
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
0
                                 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
0
  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
0
                }
2596
0
    el = *pel;
2597
0
      }
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
0
      } 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
0
                }
2611
0
    r = rk_strpoolprintf(r, "%s", s);
2612
0
                free(s);
2613
0
      }
2614
0
      break;
2615
0
  }
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
0
      }
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
0
                        else
2645
0
                            break;
2646
0
                    } else if (c > 0) {
2647
0
                        left = mid + 1;
2648
0
                    } else {
2649
0
                        break;
2650
0
                    }
2651
0
                }
2652
0
                if (c == 0) {
2653
0
                    r = rk_strpoolprintf(r, "\"%s\"", (const char *)tenum[mid].ptr);
2654
0
                    break;
2655
0
                }
2656
0
            }
2657
0
      s = (asn1_template_prim[type].print)(el, flags);
2658
0
            switch (type) {
2659
0
            case A1T_OID:
2660
0
            case A1T_IMEMBER:
2661
0
            case A1T_BOOLEAN:
2662
0
            case A1T_INTEGER:
2663
0
            case A1T_INTEGER64:
2664
0
            case A1T_UNSIGNED:
2665
0
            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
0
            }
2679
0
            }
2680
0
            if (!s) {
2681
0
                rk_strpoolfree(r);
2682
0
                free(indents);
2683
0
                return NULL;
2684
0
            }
2685
0
            free(s);
2686
0
      break;
2687
0
  }
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
0
                }
2697
0
    el = *pel;
2698
0
      }
2699
2700
0
      r = _asn1_print(t->ptr, r, flags, indent + 1, el, saved);
2701
0
      break;
2702
0
  }
2703
0
  case A1_OP_SETOF:
2704
0
  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
0
      }
2717
0
            if (r)
2718
0
                r = rk_strpoolprintf(r, "]");
2719
0
      break;
2720
0
  }
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
0
                }
2737
0
                belements--; bmember--;
2738
0
      }
2739
0
            if (r)
2740
0
                r = rk_strpoolprintf(r, "]");
2741
0
      break;
2742
0
  }
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
0
      } else {
2754
0
    choice += *element;
2755
0
                r = rk_strpoolprintf(r, "%s{\"_choice\":\"%s\",%s\"value\":",
2756
0
                                     indents ? indents : "",
2757
0
                                     (const char *)choice[nchoices].ptr,
2758
0
                                     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
0
      }
2765
0
      break;
2766
0
  }
2767
0
  default:
2768
0
      ABORT_ON_ERROR();
2769
0
      break;
2770
0
  }
2771
0
  t++;
2772
0
  elements--;
2773
0
    }
2774
0
    free(indents);
2775
0
    if (nnames && r)
2776
0
        return rk_strpoolprintf(r, "}");
2777
0
    return r;
2778
0
}
2779
2780
char *
2781
_asn1_print_top(const struct asn1_template *t,
2782
                int flags,
2783
                const void *data)
2784
0
{
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
0
}
2791
2792
/* See commentary in _asn1_decode_open_type() */
2793
static int
2794
_asn1_copy_open_type(const struct asn1_template *t, /* object set template */
2795
                     const void *from,
2796
                     void *to)
2797
0
{
2798
0
    const struct asn1_template *tactual_type;
2799
0
    const struct asn1_template *tos = t->ptr;
2800
0
    size_t i;
2801
0
    const void * const *dfromp;
2802
0
    const void * const *valfrom;
2803
0
    const unsigned int *lenfromp;
2804
0
    void **dtop;
2805
0
    void **valto;
2806
0
    unsigned int *lentop;
2807
0
    unsigned int len;
2808
0
    const int *efromp = DPO(from, t->offset);
2809
0
    int *etop = DPO(to, t->offset);
2810
0
    int ret = 0;
2811
2812
    /* XXX We assume sizeof(enum) == sizeof(int) */
2813
0
    if (!*efromp || *efromp >= A1_HEADER_LEN(tos) + 1) {
2814
0
        if ((t->tt & A1_OS_OT_IS_ARRAY))
2815
0
            memset(etop, 0, sizeof(int) + sizeof(unsigned int) + sizeof(void *));
2816
0
        else
2817
0
            memset(etop, 0, sizeof(int) + sizeof(void *));
2818
0
        return 0; /* Unknown choice -> not copied */
2819
0
    }
2820
0
    tactual_type = &tos[3*(*efromp - 1) + 4];
2821
2822
0
    if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
2823
0
        dfromp = DPO(from, t->offset + sizeof(*efromp));
2824
0
        while (sizeof(void *) != sizeof(*efromp) &&
2825
0
               ((uintptr_t)dfromp) % sizeof(void *) != 0)
2826
0
            dfromp = (void *)(((char *)dfromp) + sizeof(*efromp));
2827
0
        if (!*dfromp)
2828
0
            return 0;
2829
2830
0
        dtop = DPO(to, t->offset + sizeof(*etop));
2831
0
        while (sizeof(void *) != sizeof(*etop) &&
2832
0
               ((uintptr_t)dtop) % sizeof(void *) != 0)
2833
0
            dtop = (void *)(((char *)dtop) + sizeof(*etop));
2834
2835
0
        if ((*dtop = calloc(1, tactual_type->offset)) == NULL)
2836
0
            ret = ENOMEM;
2837
0
        if (ret == 0)
2838
0
            ret = _asn1_copy(tactual_type->ptr, *dfromp, *dtop);
2839
0
        if (ret == 0)
2840
0
            *etop = *efromp;
2841
0
        return ret;
2842
0
    }
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
0
        }
2862
0
        if ((valto[i] = calloc(1, tactual_type->offset)) == NULL)
2863
0
            ret = ENOMEM;
2864
0
        else
2865
0
            ret = _asn1_copy(tactual_type->ptr, valfrom[i], valto[i]);
2866
0
        (*lentop)++;
2867
0
    }
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
0
        }
2874
0
    }
2875
0
    if (ret) {
2876
0
        free(valto);
2877
0
        *lentop = 0;
2878
0
    } else
2879
0
        *dtop = valto;
2880
0
    return ret;
2881
0
}
2882
2883
int
2884
_asn1_copy(const struct asn1_template *t, const void *from, void *to)
2885
0
{
2886
0
    size_t elements = A1_HEADER_LEN(t);
2887
0
    int ret = 0;
2888
0
    int preserve = (t->tt & A1_HF_PRESERVE);
2889
2890
0
    t++;
2891
2892
0
    if (preserve) {
2893
0
  ret = der_copy_octet_string(from, to);
2894
0
  if (ret)
2895
0
      return ret;
2896
0
    }
2897
2898
0
    while (elements) {
2899
0
  switch (t->tt & A1_OP_MASK) {
2900
0
        case A1_OP_OPENTYPE_OBJSET: {
2901
0
            _asn1_copy_open_type(t, from, to);
2902
0
            break;
2903
0
        }
2904
0
        case A1_OP_NAME: break;
2905
0
  case A1_OP_DEFVAL: break;
2906
0
  case A1_OP_TYPE_DECORATE_EXTERN:
2907
0
  case A1_OP_TYPE_DECORATE:
2908
0
  case A1_OP_TYPE:
2909
0
  case A1_OP_TYPE_EXTERN: {
2910
0
      const void *fel = DPOC(from, t->offset);
2911
0
      void *tel = DPO(to, t->offset);
2912
0
      void **ptel = (void **)tel;
2913
0
      size_t size;
2914
2915
0
      if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
2916
0
                (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2917
0
    size = _asn1_sizeofType(t->ptr);
2918
0
      } else {
2919
0
    const struct asn1_type_func *f = t->ptr;
2920
0
    size = f->size;
2921
0
      }
2922
2923
0
      if (t->tt & A1_FLAG_OPTIONAL) {
2924
0
    void **pfel = (void **)fel;
2925
0
    if (*pfel == NULL)
2926
0
        break;
2927
0
    fel = *pfel;
2928
2929
0
    tel = *ptel = calloc(1, size);
2930
0
    if (tel == NULL)
2931
0
        return ENOMEM;
2932
0
      }
2933
2934
0
      if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
2935
0
                (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
2936
0
    ret = _asn1_copy(t->ptr, fel, tel);
2937
0
      } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) {
2938
0
    const struct asn1_type_func *f = t->ptr;
2939
0
                ret = (f->copy)(fel, tel);
2940
0
      } else {
2941
0
    const struct asn1_type_func *f = t->ptr;
2942
2943
                /* A1_OP_TYPE_DECORATE_EXTERN */
2944
0
                if (f && f->copy)
2945
0
                    ret = (f->copy)(fel, tel);
2946
0
                else if (f)
2947
0
                    memset(tel, 0, f->size);
2948
0
      }
2949
2950
0
      if (ret) {
2951
0
    if (t->tt & A1_FLAG_OPTIONAL) {
2952
0
        free(*ptel);
2953
0
        *ptel = NULL;
2954
0
    }
2955
0
    return ret;
2956
0
      }
2957
0
      break;
2958
0
  }
2959
0
  case A1_OP_PARSE: {
2960
0
      unsigned int type = A1_PARSE_TYPE(t->tt);
2961
0
      const void *fel = DPOC(from, t->offset);
2962
0
      void *tel = DPO(to, t->offset);
2963
2964
0
      if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
2965
0
    ABORT_ON_ERROR();
2966
0
    return ASN1_PARSE_ERROR;
2967
0
      }
2968
0
      ret = (asn1_template_prim[type].copy)(fel, tel);
2969
0
      if (ret)
2970
0
    return ret;
2971
0
      break;
2972
0
  }
2973
0
  case A1_OP_TAG: {
2974
0
      const void *oldfrom = from;
2975
0
      void *oldto = to;
2976
0
      void **tel = NULL;
2977
2978
0
      from = DPOC(from, t->offset);
2979
0
      to = DPO(to, t->offset);
2980
2981
0
      if (t->tt & A1_FLAG_OPTIONAL) {
2982
0
    void **fel = (void **)from;
2983
0
    tel = (void **)to;
2984
0
    if (*fel == NULL) {
2985
0
        from = oldfrom;
2986
0
        to = oldto;
2987
0
        break;
2988
0
    }
2989
0
    from = *fel;
2990
2991
0
    to = *tel = calloc(1, _asn1_sizeofType(t->ptr));
2992
0
    if (to == NULL)
2993
0
        return ENOMEM;
2994
0
      }
2995
2996
0
      ret = _asn1_copy(t->ptr, from, to);
2997
0
      if (ret) {
2998
0
    if (tel) {
2999
0
        free(*tel);
3000
0
        *tel = NULL;
3001
0
    }
3002
0
    return ret;
3003
0
      }
3004
3005
0
      from = oldfrom;
3006
0
      to = oldto;
3007
3008
0
      break;
3009
0
  }
3010
0
  case A1_OP_SETOF:
3011
0
  case A1_OP_SEQOF: {
3012
0
      const struct template_of *fel = DPOC(from, t->offset);
3013
0
      struct template_of *tel = DPO(to, t->offset);
3014
0
      size_t ellen = _asn1_sizeofType(t->ptr);
3015
0
      unsigned int i;
3016
3017
0
      tel->val = calloc(fel->len, ellen);
3018
0
      if (tel->val == NULL && fel->len > 0)
3019
0
    return ENOMEM;
3020
3021
0
      tel->len = fel->len;
3022
3023
0
      for (i = 0; i < fel->len; i++) {
3024
0
    ret = _asn1_copy(t->ptr,
3025
0
         DPOC(fel->val, (i * ellen)),
3026
0
         DPO(tel->val, (i *ellen)));
3027
0
    if (ret)
3028
0
        return ret;
3029
0
      }
3030
0
      break;
3031
0
  }
3032
0
  case A1_OP_BMEMBER: {
3033
0
      const struct asn1_template *bmember = t->ptr;
3034
0
      size_t size = bmember->offset;
3035
0
      memcpy(to, from, size);
3036
0
      break;
3037
0
  }
3038
0
  case A1_OP_CHOICE: {
3039
0
      const struct asn1_template *choice = t->ptr;
3040
0
      const unsigned int *felement = DPOC(from, choice->offset);
3041
0
      unsigned int *telement = DPO(to, choice->offset);
3042
3043
0
      if (*felement > A1_HEADER_LEN(choice))
3044
0
    return ASN1_PARSE_ERROR;
3045
3046
0
      *telement = *felement;
3047
3048
0
      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
0
      } else {
3056
0
    choice += *felement;
3057
0
    ret = _asn1_copy(choice->ptr,
3058
0
         DPOC(from, choice->offset),
3059
0
         DPO(to, choice->offset));
3060
0
      }
3061
0
      if (ret)
3062
0
    return ret;
3063
0
      break;
3064
0
  }
3065
0
  default:
3066
0
      ABORT_ON_ERROR();
3067
0
      break;
3068
0
  }
3069
0
  t++;
3070
0
  elements--;
3071
0
    }
3072
0
    return 0;
3073
0
}
3074
3075
int
3076
_asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size)
3077
0
{
3078
0
    int ret;
3079
0
    memset(data, 0, t->offset);
3080
0
    ret = _asn1_decode(t, flags, p, len, data, size);
3081
0
    if (ret)
3082
0
  _asn1_free_top(t, data);
3083
3084
0
    return ret;
3085
0
}
3086
3087
int
3088
_asn1_copy_top(const struct asn1_template *t, const void *from, void *to)
3089
0
{
3090
0
    int ret;
3091
0
    memset(to, 0, t->offset);
3092
0
    ret = _asn1_copy(t, from, to);
3093
0
    if (ret)
3094
0
  _asn1_free_top(t, to);
3095
3096
0
    return ret;
3097
0
}
3098
3099
void
3100
_asn1_free_top(const struct asn1_template *t, void *data)
3101
0
{
3102
0
    _asn1_free(t, data);
3103
0
    memset(data, 0, t->offset);
3104
0
}