LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/asn1 - template.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 758 1668 45.4 %
Date: 2024-06-13 04:01:37 Functions: 18 28 64.3 %

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

Generated by: LCOV version 1.13