LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/asn1 - template.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 909 1746 52.1 %
Date: 2024-04-21 15:09:00 Functions: 20 28 71.4 %

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

Generated by: LCOV version 1.14