LCOV - code coverage report
Current view: top level - egg - egg-asn1x.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.2 % 2147 1979
Test Date: 2024-02-13 21:56:33 Functions: 96.5 % 170 164

            Line data    Source code
       1              : /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
       2              : /* egg-asn1x.c - ASN.1/DER parse and coding routines
       3              : 
       4              :    Copyright (C) 2009 Stefan Walter
       5              : 
       6              :    The Gnome Keyring Library is free software; you can redistribute it and/or
       7              :    modify it under the terms of the GNU Library General Public License as
       8              :    published by the Free Software Foundation; either version 2 of the
       9              :    License, or (at your option) any later version.
      10              : 
      11              :    The Gnome Keyring Library is distributed in the hope that it will be useful,
      12              :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :    Library General Public License for more details.
      15              : 
      16              :    You should have received a copy of the GNU Library General Public
      17              :    License along with the Gnome Library; see the file COPYING.LIB.  If not,
      18              :    <http://www.gnu.org/licenses/>.
      19              : 
      20              :    Author: Stef Walter <stef@memberwebs.com>
      21              : */
      22              : 
      23              : /*
      24              :  * Some portions are:
      25              :  *
      26              :  *      Copyright (C) 2004, 2006, 2008, 2009 Free Software Foundation
      27              :  *      Copyright (C) 2002 Fabio Fiorina
      28              :  *
      29              :  * This file is part of LIBTASN1.
      30              :  *
      31              :  * The LIBTASN1 library is free software; you can redistribute it
      32              :  * and/or modify it under the terms of the GNU Lesser General Public
      33              :  * License as published by the Free Software Foundation; either
      34              :  * version 2.1 of the License, or (at your option) any later version.
      35              :  *
      36              :  * This library is distributed in the hope that it will be useful, but
      37              :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      38              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      39              :  * Lesser General Public License for more details.
      40              :  *
      41              :  * You should have received a copy of the GNU Lesser General Public
      42              :  * License along with this library; if not, see
      43              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      44              :  * 02110-1301, USA
      45              :  */
      46              : 
      47              : #include "config.h"
      48              : 
      49              : #include "egg-asn1x.h"
      50              : #include "egg-asn1-defs.h"
      51              : #include "egg-timegm.h"
      52              : 
      53              : #include <stdlib.h>
      54              : #include <string.h>
      55              : 
      56              : /* From libtasn1's libtasn.h */
      57              : 
      58              : enum {
      59              :         ASN1_CLASS_UNIVERSAL = 0x00,
      60              :         ASN1_CLASS_APPLICATION = 0x40,
      61              :         ASN1_CLASS_CONTEXT_SPECIFIC = 0x80,
      62              :         ASN1_CLASS_PRIVATE = 0xC0,
      63              :         ASN1_CLASS_STRUCTURED = 0x20,
      64              : };
      65              : 
      66              : enum {
      67              :         ASN1_TAG_BOOLEAN = 0x01,
      68              :         ASN1_TAG_INTEGER = 0x02,
      69              :         ASN1_TAG_SEQUENCE = 0x10,
      70              :         ASN1_TAG_SET = 0x11,
      71              :         ASN1_TAG_OCTET_STRING = 0x04,
      72              :         ASN1_TAG_BIT_STRING = 0x03,
      73              :         ASN1_TAG_UTC_TIME = 0x17,
      74              :         ASN1_TAG_GENERALIZED_TIME = 0x18,
      75              :         ASN1_TAG_OBJECT_ID = 0x06,
      76              :         ASN1_TAG_ENUMERATED = 0x0A,
      77              :         ASN1_TAG_NULL = 0x05,
      78              :         ASN1_TAG_GENERAL_STRING = 0x1B,
      79              :         ASN1_TAG_NUMERIC_STRING = 0x12,
      80              :         ASN1_TAG_IA5_STRING = 0x16,
      81              :         ASN1_TAG_TELETEX_STRING = 0x14,
      82              :         ASN1_TAG_PRINTABLE_STRING = 0x13,
      83              :         ASN1_TAG_UNIVERSAL_STRING = 0x1C,
      84              :         ASN1_TAG_BMP_STRING = 0x1E,
      85              :         ASN1_TAG_UTF8_STRING = 0x0C,
      86              :         ASN1_TAG_VISIBLE_STRING = 0x1A,
      87              : };
      88              : 
      89              : /* From libtasn1's int.h */
      90              : 
      91              : enum {
      92              :         FLAG_UNIVERSAL = (1<<8),
      93              :         FLAG_PRIVATE = (1<<9),
      94              :         FLAG_APPLICATION = (1<<10),
      95              :         FLAG_EXPLICIT = (1<<11),
      96              :         FLAG_IMPLICIT = (1<<12),
      97              :         FLAG_TAG = (1<<13),
      98              :         FLAG_OPTION = (1<<14),
      99              :         FLAG_DEFAULT = (1<<15),
     100              :         FLAG_TRUE = (1<<16),
     101              :         FLAG_FALSE = (1<<17),
     102              :         FLAG_LIST = (1<<18),
     103              :         FLAG_MIN_MAX = (1<<19),
     104              :         FLAG_1_PARAM = (1<<20),
     105              :         FLAG_SIZE = (1<<21),
     106              :         FLAG_DEFINED_BY = (1<<22),
     107              :         FLAG_GENERALIZED = (1<<23),
     108              :         FLAG_UTC = (1<<24),
     109              :         FLAG_IMPORTS = (1<<25),
     110              :         FLAG_NOT_USED = (1<<26),
     111              :         FLAG_SET = (1<<27),
     112              :         FLAG_ASSIGN = (1<<28),
     113              :         FLAG_DOWN = (1<<29),
     114              :         FLAG_RIGHT = (1<<30),
     115              : };
     116              : 
     117              : typedef struct _Atlv Atlv;
     118              : typedef struct _Anode Anode;
     119              : 
     120              : struct _Atlv {
     121              :         guchar cls;
     122              :         gulong tag;
     123              :         gint off;
     124              :         gint len;
     125              : 
     126              :         /* An actual value here */
     127              :         GBytes *value;
     128              : 
     129              :         /* Reference to what was decoded */
     130              :         GBytes *decoded;
     131              : 
     132              :         /* Chain this into a tree */
     133              :         struct _Atlv *child;
     134              :         struct _Atlv *next;
     135              : 
     136              :         /* Used during encoding */
     137              : 
     138              :         /* Encoding: for bitstring, the number of empty bits at end */
     139              :         guint bits_empty : 3;
     140              : 
     141              :         /* Encoding: tell us whether we're dealing with a bit string */
     142              :         guint prefix_for_bit_string : 1;
     143              : 
     144              :         /* Encoding: prefix a zero byte for unsigned integers */
     145              :         guint prefix_with_zero_byte : 1;
     146              : 
     147              :         /* Encoding: sort children of this tlv (ie: SETOF) */
     148              :         guint sorted : 1;
     149              : };
     150              : 
     151              : struct _Anode {
     152              :         const EggAsn1xDef *def;
     153              :         const EggAsn1xDef *join;
     154              :         GList *opts;
     155              : 
     156              :         GBytes *value;
     157              :         Atlv *parsed;
     158              : 
     159              :         gchar* failure;
     160              : 
     161              :         /* If this node was chosen out of a choice */
     162              :         guint chosen : 1;
     163              : 
     164              :         /* For bitstring the number of empty bits */
     165              :         guint bits_empty : 3;
     166              : 
     167              :         /* Whether we need to prefix a zero byte to make unsigned */
     168              :         guint guarantee_unsigned : 1;
     169              : };
     170              : 
     171              : /* Forward Declarations */
     172              : static gboolean anode_decode_anything (GNode *, Atlv *);
     173              : static gboolean anode_decode_one (GNode *, Atlv *);
     174              : static GBytes * anode_default_boolean (GNode *node);
     175              : static GBytes * anode_default_integer (GNode *node);
     176              : static gboolean anode_validate_anything (GNode *, gboolean);
     177              : static Atlv * anode_build_anything (GNode*, gboolean want);
     178              : 
     179              : static gint
     180         3380 : atoin (const char *p, gint digits)
     181              : {
     182         3380 :         gint ret = 0, base = 1;
     183        10125 :         while(--digits >= 0) {
     184         6746 :                 if (p[digits] < '0' || p[digits] > '9')
     185            1 :                         return -1;
     186         6745 :                 ret += (p[digits] - '0') * base;
     187         6745 :                 base *= 10;
     188              :         }
     189         3379 :         return ret;
     190              : }
     191              : 
     192              : static const guchar *
     193        25292 : bytes_get_end (GBytes *data)
     194              : {
     195              :         const guchar *beg;
     196              :         gsize size;
     197        25292 :         beg = g_bytes_get_data (data, &size);
     198        25292 :         return beg + size;
     199              : }
     200              : 
     201              : typedef struct {
     202              :         EggAllocator allocator;
     203              :         gpointer allocated;
     204              : } AllocatorClosure;
     205              : 
     206              : static void
     207           26 : allocator_closure_free (gpointer data)
     208              : {
     209           26 :         AllocatorClosure *closure = data;
     210           26 :         g_assert (closure->allocator);
     211           26 :         (closure->allocator) (closure->allocated, 0);
     212           26 :         g_slice_free (AllocatorClosure, closure);
     213           26 : }
     214              : 
     215              : static GBytes *
     216          335 : bytes_new_with_allocator (EggAllocator allocator,
     217              :                           guchar **data,
     218              :                           gsize length)
     219              : {
     220              :         AllocatorClosure *closure;
     221              : 
     222          335 :         if (allocator == g_realloc)
     223            2 :                 allocator = NULL;
     224              : 
     225          335 :         if (allocator) {
     226           26 :                 *data = (allocator) (NULL, length + 1);
     227           26 :                 g_return_val_if_fail (*data != NULL, NULL);
     228           26 :                 closure = g_slice_new (AllocatorClosure);
     229           26 :                 closure->allocated = *data;
     230           26 :                 closure->allocator = allocator;
     231           26 :                 return g_bytes_new_with_free_func (*data, length,
     232              :                                                    allocator_closure_free,
     233              :                                                    closure);
     234              :         } else {
     235          309 :                 *data = g_malloc (length);
     236          309 :                 return g_bytes_new_take (*data, length);
     237              :         }
     238              : }
     239              : 
     240              : static GNode*
     241        28877 : anode_new (const EggAsn1xDef *def)
     242              : {
     243        28877 :         Anode *an = g_slice_new0 (Anode);
     244        28877 :         an->def = def;
     245        28877 :         return g_node_new (an);
     246              : }
     247              : 
     248              : static gpointer
     249        12183 : anode_copy_func (gconstpointer src, gpointer unused)
     250              : {
     251        12183 :         const Anode *san = src;
     252        12183 :         Anode *an = g_slice_new0 (Anode);
     253        12183 :         an->def = san->def;
     254        12183 :         an->join = san->join;
     255        12183 :         an->opts = g_list_copy (san->opts);
     256        12183 :         return an;
     257              : }
     258              : 
     259              : static GNode*
     260         3053 : anode_clone (GNode *node)
     261              : {
     262         3053 :         return g_node_copy_deep (node, anode_copy_func, NULL);
     263              : }
     264              : 
     265              : static int
     266       266007 : anode_def_type (GNode *node)
     267              : {
     268       266007 :         Anode *an = node->data;
     269       266007 :         gint type = an->join ? an->join->type : an->def->type;
     270       266007 :         return type & 0xFF;
     271              : }
     272              : 
     273              : static gboolean
     274        60427 : anode_def_type_is_real (GNode *node)
     275              : {
     276        60427 :         switch (anode_def_type (node)) {
     277        21073 :         case EGG_ASN1X_INTEGER:
     278              :         case EGG_ASN1X_BOOLEAN:
     279              :         case EGG_ASN1X_BIT_STRING:
     280              :         case EGG_ASN1X_OCTET_STRING:
     281              :         case EGG_ASN1X_OBJECT_ID:
     282              :         case EGG_ASN1X_TIME:
     283              :         case EGG_ASN1X_UTC_TIME:
     284              :         case EGG_ASN1X_GENERALIZED_TIME:
     285              :         case EGG_ASN1X_NULL:
     286              :         case EGG_ASN1X_ENUMERATED:
     287              :         case EGG_ASN1X_GENERAL_STRING:
     288              :         case EGG_ASN1X_NUMERIC_STRING:
     289              :         case EGG_ASN1X_IA5_STRING:
     290              :         case EGG_ASN1X_TELETEX_STRING:
     291              :         case EGG_ASN1X_PRINTABLE_STRING:
     292              :         case EGG_ASN1X_UNIVERSAL_STRING:
     293              :         case EGG_ASN1X_BMP_STRING:
     294              :         case EGG_ASN1X_UTF8_STRING:
     295              :         case EGG_ASN1X_VISIBLE_STRING:
     296        21073 :                 return TRUE;
     297        27632 :         case EGG_ASN1X_SEQUENCE:
     298              :         case EGG_ASN1X_SEQUENCE_OF:
     299              :         case EGG_ASN1X_ANY:
     300              :         case EGG_ASN1X_SET:
     301              :         case EGG_ASN1X_SET_OF:
     302              :         case EGG_ASN1X_CHOICE:
     303        27632 :                 return TRUE;
     304        11722 :         case EGG_ASN1X_CONSTANT:
     305              :         case EGG_ASN1X_IDENTIFIER:
     306              :         case EGG_ASN1X_TAG:
     307              :         case EGG_ASN1X_DEFAULT:
     308              :         case EGG_ASN1X_SIZE:
     309              :         case EGG_ASN1X_DEFINITIONS:
     310              :         case EGG_ASN1X_IMPORTS:
     311        11722 :                 return FALSE;
     312              :         }
     313              : 
     314            0 :         g_return_val_if_reached (FALSE);
     315              : }
     316              : 
     317              : static int
     318        85403 : anode_def_flags (GNode *node)
     319              : {
     320        85403 :         Anode *an = node->data;
     321        85403 :         gint type = an->def->type;
     322        85403 :         if (an->join)
     323        52062 :                 type |= an->join->type;
     324        85403 :         return type & 0xFFFFFF00;
     325              : }
     326              : 
     327              : static const gchar*
     328         6787 : anode_def_name (GNode *node)
     329              : {
     330         6787 :         Anode *an = node->data;
     331         6787 :         return an->def->name;
     332              : }
     333              : 
     334              : static const gchar*
     335            0 : anode_def_value (GNode *node)
     336              : {
     337            0 :         Anode *an = node->data;
     338            0 :         return an->def->value;
     339              : }
     340              : 
     341              : static gulong
     342         2086 : anode_def_value_as_ulong (const EggAsn1xDef *def)
     343              : {
     344         2086 :         gchar *end = NULL;
     345              :         gulong lval;
     346              : 
     347         2086 :         g_return_val_if_fail (def->value, G_MAXULONG);
     348         2086 :         lval = strtoul (def->value, &end, 10);
     349         2086 :         g_return_val_if_fail (end && !end[0], G_MAXULONG);
     350         2086 :         return lval;
     351              : }
     352              : 
     353              : static GNode*
     354         2665 : anode_child_with_name (GNode *node, const gchar *name)
     355              : {
     356              :         GNode *child;
     357              : 
     358         5706 :         for (child = node->children; child; child = child->next) {
     359         5706 :                 if (g_str_equal (name, anode_def_name (child)))
     360         2665 :                         return child;
     361              :         }
     362              : 
     363            0 :         return NULL;
     364              : }
     365              : 
     366              : static void
     367         8553 : anode_opt_add (GNode *node,
     368              :                const EggAsn1xDef *def)
     369              : {
     370         8553 :         Anode *an = node->data;
     371         8553 :         an->opts = g_list_append (an->opts, (gpointer)def);
     372         8553 : }
     373              : 
     374              : static EggAsn1xDef *
     375         5138 : anode_opt_lookup (GNode *node,
     376              :                   gint type,
     377              :                   const gchar *name)
     378              : {
     379         5138 :         Anode *an = node->data;
     380              :         EggAsn1xDef *def;
     381              :         GList *l;
     382              : 
     383         6065 :         for (l = an->opts; l; l = g_list_next (l)) {
     384         6063 :                 def = l->data;
     385         6063 :                 if (name && def->name && !g_str_equal (name, def->name))
     386            9 :                         continue;
     387         6054 :                 if ((def->type & 0xFF) == type)
     388         5136 :                         return def;
     389              :         }
     390              : 
     391            2 :         return NULL;
     392              : }
     393              : 
     394              : static EggAsn1xDef *
     395           14 : anode_opt_lookup_value (GNode *node,
     396              :                         gint type,
     397              :                         const gchar *value)
     398              : {
     399           14 :         Anode *an = node->data;
     400              :         EggAsn1xDef *def;
     401              :         GList *l;
     402              : 
     403           42 :         for (l = an->opts; l; l = g_list_next (l)) {
     404           42 :                 def = l->data;
     405           42 :                 if (value && def->value && !g_str_equal (value, def->value))
     406           28 :                         continue;
     407           14 :                 if ((def->type & 0xFF) == type)
     408           14 :                         return def;
     409              :         }
     410              : 
     411            0 :         return NULL;
     412              : }
     413              : 
     414              : static GList*
     415          329 : anode_opts_lookup (GNode *node, gint type, const gchar *name)
     416              : {
     417          329 :         Anode *an = node->data;
     418              :         EggAsn1xDef *def;
     419          329 :         GList *l, *res = NULL;
     420              : 
     421         1682 :         for (l = an->opts; l; l = g_list_next (l)) {
     422         1353 :                 def = l->data;
     423         1353 :                 if (name && def->name && !g_str_equal (name, def->name))
     424            0 :                         continue;
     425         1353 :                 if ((def->type & 0xFF) == type)
     426          883 :                         res = g_list_prepend (res, def);
     427              :         }
     428              : 
     429          329 :         return g_list_reverse (res);
     430              : }
     431              : 
     432              : static Atlv *
     433        26687 : atlv_new (void)
     434              : {
     435        26687 :         return g_slice_new0 (Atlv);
     436              : }
     437              : 
     438              : static void
     439       384109 : atlv_free (Atlv *tlv)
     440              : {
     441       384109 :         if (!tlv)
     442       237512 :                 return;
     443              : 
     444              :         /* Free attached TLVs */
     445       146597 :         atlv_free (tlv->child);
     446       146597 :         atlv_free (tlv->next);
     447              : 
     448              :         /* Free the TLV */
     449       146597 :         if (tlv->decoded)
     450       145138 :                 g_bytes_unref (tlv->decoded);
     451       146597 :         if (tlv->value)
     452        85344 :                 g_bytes_unref (tlv->value);
     453              : 
     454       146597 :         g_slice_free (Atlv, tlv);
     455              : }
     456              : 
     457              : static Atlv *
     458       239820 : atlv_dup (Atlv *tlv,
     459              :           gboolean siblings)
     460              : {
     461              :         Atlv *copy;
     462              : 
     463       239820 :         if (!tlv)
     464       119910 :                 return NULL;
     465              : 
     466       119910 :         copy = g_slice_new0 (Atlv);
     467       119910 :         memcpy (copy, tlv, sizeof (Atlv));
     468              : 
     469       119910 :         if (tlv->value != NULL)
     470        71083 :                 copy->value = g_bytes_ref (tlv->value);
     471       119910 :         if (tlv->decoded != NULL)
     472       119853 :                 copy->decoded = g_bytes_ref (tlv->decoded);
     473              : 
     474       119910 :         copy->child = atlv_dup (tlv->child, TRUE);
     475       119910 :         if (siblings)
     476        95499 :                 copy->next = atlv_dup (tlv->next, TRUE);
     477              :         else
     478        24411 :                 copy->next = NULL;
     479              : 
     480       119910 :         return copy;
     481              : }
     482              : 
     483              : static inline GBytes *
     484        24216 : anode_get_value (GNode *node)
     485              : {
     486        24216 :         Anode *an = node->data;
     487        24216 :         return an->value;
     488              : }
     489              : 
     490              : static inline void
     491        65490 : anode_clr_value (GNode *node)
     492              : {
     493        65490 :         Anode *an = node->data;
     494        65490 :         if (an->value)
     495         8855 :                 g_bytes_unref (an->value);
     496        65490 :         an->value = NULL;
     497              : 
     498        65490 :         atlv_free (an->parsed);
     499        65490 :         an->parsed = NULL;
     500        65490 : }
     501              : 
     502              : static inline void
     503         8855 : anode_take_value (GNode *node,
     504              :                   GBytes *value)
     505              : {
     506         8855 :         Anode *an = node->data;
     507         8855 :         anode_clr_value (node);
     508         8855 :         an->value = value;
     509         8855 : }
     510              : 
     511              : static inline void
     512         7963 : anode_set_value (GNode *node,
     513              :                  GBytes *value)
     514              : {
     515         7963 :         anode_take_value (node, g_bytes_ref (value));
     516         7963 : }
     517              : 
     518              : static inline Atlv *
     519        14106 : anode_get_parsed (GNode *node)
     520              : {
     521        14106 :         Anode *an = node->data;
     522        14106 :         return an->parsed;
     523              : }
     524              : 
     525              : static gboolean
     526          710 : anode_failure (GNode *node, const gchar *failure)
     527              : {
     528          710 :         Anode *an = node->data;
     529          710 :         const gchar *prefix = an->def->name;
     530          710 :         if (!prefix && an->join)
     531            0 :                 prefix = an->join->name;
     532          710 :         if (!prefix)
     533            1 :                 prefix = an->def->value;
     534          710 :         if (!prefix && an->join)
     535            0 :                 prefix = an->join->value;
     536          710 :         if (!prefix)
     537            1 :                 prefix = "unknown";
     538              : 
     539          710 :         g_free (an->failure);
     540          710 :         an->failure = g_strdup_printf ("%s: %s", prefix, failure);
     541          710 :         g_debug ("%s %s", prefix, an->failure);
     542          710 :         return FALSE; /* So this can be chained */
     543              : }
     544              : 
     545              : static const gchar*
     546           88 : anode_failure_get (GNode *node)
     547              : {
     548           88 :         Anode *an = node->data;
     549           88 :         return an->failure;
     550              : }
     551              : 
     552              : static void
     553        55178 : anode_clear (GNode *node)
     554              : {
     555        55178 :         Anode *an = node->data;
     556        55178 :         anode_clr_value (node);
     557        55178 :         g_free (an->failure);
     558        55178 :         an->failure = NULL;
     559        55178 : }
     560              : 
     561              : static gboolean
     562        41060 : anode_free_func (GNode *node, gpointer unused)
     563              : {
     564        41060 :         Anode *an = node->data;
     565        41060 :         anode_clear (node);
     566        41060 :         g_list_free (an->opts);
     567        41060 :         g_slice_free (Anode, an);
     568        41060 :         return FALSE;
     569              : }
     570              : 
     571              : static void
     572        14812 : anode_destroy (GNode *node)
     573              : {
     574        14812 :         if (!G_NODE_IS_ROOT (node))
     575           29 :                 g_node_unlink (node);
     576        14812 :         g_node_traverse (node, G_IN_ORDER, G_TRAVERSE_ALL, -1, anode_free_func, NULL);
     577        14812 :         g_node_destroy (node);
     578        14812 : }
     579              : 
     580              : static gulong
     581        30459 : anode_calc_tag_for_flags (GNode *node, gint flags)
     582              : {
     583              :         EggAsn1xDef *def;
     584              : 
     585              :         /* A context specific tag */
     586        30459 :         if (flags & FLAG_TAG) {
     587         1246 :                 def = anode_opt_lookup (node, EGG_ASN1X_TAG, NULL);
     588         1246 :                 g_return_val_if_fail (def, G_MAXULONG);
     589         1246 :                 return anode_def_value_as_ulong (def);
     590              :         }
     591              : 
     592              :         /* A tag from the universal set */
     593        29213 :         switch (anode_def_type (node)) {
     594         1162 :         case EGG_ASN1X_INTEGER:
     595         1162 :                 return ASN1_TAG_INTEGER;
     596           20 :         case EGG_ASN1X_ENUMERATED:
     597           20 :                 return ASN1_TAG_ENUMERATED;
     598          943 :         case EGG_ASN1X_BOOLEAN:
     599          943 :                 return ASN1_TAG_BOOLEAN;
     600          887 :         case EGG_ASN1X_BIT_STRING:
     601          887 :                 return ASN1_TAG_BIT_STRING;
     602         1096 :         case EGG_ASN1X_OCTET_STRING:
     603         1096 :                 return ASN1_TAG_OCTET_STRING;
     604         5077 :         case EGG_ASN1X_OBJECT_ID:
     605         5077 :                 return ASN1_TAG_OBJECT_ID;
     606           13 :         case EGG_ASN1X_NULL:
     607           13 :                 return ASN1_TAG_NULL;
     608            0 :         case EGG_ASN1X_GENERAL_STRING:
     609            0 :                 return ASN1_TAG_GENERAL_STRING;
     610            0 :         case EGG_ASN1X_NUMERIC_STRING:
     611            0 :                 return ASN1_TAG_NUMERIC_STRING;
     612            0 :         case EGG_ASN1X_IA5_STRING:
     613            0 :                 return ASN1_TAG_IA5_STRING;
     614            0 :         case EGG_ASN1X_TELETEX_STRING:
     615            0 :                 return ASN1_TAG_TELETEX_STRING;
     616            0 :         case EGG_ASN1X_PRINTABLE_STRING:
     617            0 :                 return ASN1_TAG_PRINTABLE_STRING;
     618            0 :         case EGG_ASN1X_UNIVERSAL_STRING:
     619            0 :                 return ASN1_TAG_UNIVERSAL_STRING;
     620            0 :         case EGG_ASN1X_BMP_STRING:
     621            0 :                 return ASN1_TAG_BMP_STRING;
     622            0 :         case EGG_ASN1X_UTF8_STRING:
     623            0 :                 return ASN1_TAG_UTF8_STRING;
     624            0 :         case EGG_ASN1X_VISIBLE_STRING:
     625            0 :                 return ASN1_TAG_VISIBLE_STRING;
     626         1021 :         case EGG_ASN1X_TIME:
     627         1021 :                 if (flags & FLAG_GENERALIZED)
     628          509 :                         return ASN1_TAG_GENERALIZED_TIME;
     629          512 :                 else if (flags & FLAG_UTC)
     630          512 :                         return ASN1_TAG_UTC_TIME;
     631              :                 else
     632            0 :                         g_return_val_if_reached (G_MAXULONG);
     633            0 :         case EGG_ASN1X_UTC_TIME:
     634            0 :                 return ASN1_TAG_UTC_TIME;
     635            0 :         case EGG_ASN1X_GENERALIZED_TIME:
     636            0 :                 return ASN1_TAG_GENERALIZED_TIME;
     637        10614 :         case EGG_ASN1X_SEQUENCE:
     638              :         case EGG_ASN1X_SEQUENCE_OF:
     639        10614 :                 return ASN1_TAG_SEQUENCE;
     640         3424 :         case EGG_ASN1X_SET:
     641              :         case EGG_ASN1X_SET_OF:
     642         3424 :                 return ASN1_TAG_SET;
     643              : 
     644              :         /* These should be handled specially */
     645         4956 :         case EGG_ASN1X_ANY:
     646              :         case EGG_ASN1X_CHOICE:
     647         4956 :                 return G_MAXULONG;
     648              : 
     649              :         /* These are not real nodes */
     650            0 :         case EGG_ASN1X_CONSTANT:
     651              :         case EGG_ASN1X_IDENTIFIER:
     652              :         case EGG_ASN1X_TAG:
     653              :         case EGG_ASN1X_DEFAULT:
     654              :         case EGG_ASN1X_SIZE:
     655              :         case EGG_ASN1X_DEFINITIONS:
     656              :         case EGG_ASN1X_IMPORTS:
     657            0 :                 g_return_val_if_reached (G_MAXULONG);
     658              :         }
     659              : 
     660            0 :         g_return_val_if_reached (G_MAXULONG);
     661              : }
     662              : 
     663              : static gulong
     664         3712 : anode_calc_tag (GNode *node)
     665              : {
     666         3712 :         return anode_calc_tag_for_flags (node, anode_def_flags (node));
     667              : }
     668              : 
     669              : static gboolean
     670        25744 : anode_calc_explicit_for_flags (GNode *node,
     671              :                                gint flags,
     672              :                                guchar *cls_type)
     673              : {
     674              :         const EggAsn1xDef *opt;
     675        25744 :         if ((flags & FLAG_TAG) != FLAG_TAG)
     676        25048 :                 return FALSE;
     677          696 :         opt = anode_opt_lookup (node, EGG_ASN1X_TAG, NULL);
     678          696 :         g_return_val_if_fail (opt, FALSE);
     679          696 :         if (cls_type) {
     680           91 :                 if (opt->type & FLAG_UNIVERSAL)
     681           16 :                         *cls_type = ASN1_CLASS_UNIVERSAL;
     682           75 :                 else if (opt->type & FLAG_APPLICATION)
     683            0 :                         *cls_type = ASN1_CLASS_APPLICATION;
     684           75 :                 else if (opt->type & FLAG_PRIVATE)
     685            0 :                         *cls_type = ASN1_CLASS_PRIVATE;
     686              :                 else
     687           75 :                         *cls_type = ASN1_CLASS_CONTEXT_SPECIFIC;
     688              :         }
     689          696 :         if ((opt->type & FLAG_IMPLICIT) == FLAG_IMPLICIT)
     690           47 :                 return FALSE;
     691          649 :         return TRUE;
     692              : }
     693              : 
     694              : /* -------------------------------------------------------------------------
     695              :  * PARSING
     696              :  */
     697              : 
     698              : static gboolean
     699        25349 : atlv_parse_cls_tag (const guchar *at,
     700              :                     const guchar *end,
     701              :                     guchar *cls,
     702              :                     gulong *tag,
     703              :                     gint *off)
     704              : {
     705              :         gint punt, ris, last;
     706              :         gint n_data;
     707              :         guchar val;
     708              : 
     709        25349 :         g_assert (end >= at);
     710        25349 :         g_assert (cls != NULL);
     711        25349 :         g_assert (off != NULL);
     712              : 
     713        25349 :         n_data = end - at;
     714              : 
     715        25349 :         if (n_data < 2)
     716            3 :                 return FALSE;
     717              : 
     718        25346 :         *cls = at[0] & 0xE0;
     719              : 
     720              :         /* short form */
     721        25346 :         if ((at[0] & 0x1F) != 0x1F) {
     722        25345 :                 *off = 1;
     723        25345 :                 ris = at[0] & 0x1F;
     724              : 
     725              :         /* Long form */
     726              :         } else {
     727            1 :                 punt = 1;
     728            1 :                 ris = 0;
     729            2 :                 while (punt <= n_data) {
     730            2 :                         val = at[punt++];
     731            2 :                         last = ris;
     732            2 :                         ris = ris * 128;
     733              : 
     734              :                         /* wrapper around, and no bignums... */
     735            2 :                         if (ris < last)
     736            0 :                                 return FALSE;
     737              : 
     738            2 :                         last = ris;
     739            2 :                         ris += (val & 0x7F);
     740              : 
     741              :                         /* wrapper around, and no bignums... */
     742            2 :                         if (ris < last)
     743            0 :                                 return FALSE;
     744              : 
     745            2 :                         if ((val & 0x7F) == val)
     746            1 :                                 break;
     747              :                 }
     748              : 
     749            1 :                 if (punt >= n_data)
     750            0 :                         return FALSE;
     751              : 
     752            1 :                 *off = punt;
     753              :         }
     754              : 
     755        25346 :         if (tag)
     756        25346 :                 *tag = ris;
     757              : 
     758        25346 :         return TRUE;
     759              : }
     760              : 
     761              : static gint
     762        25346 : atlv_parse_length (const guchar *at,
     763              :                    const guchar *end,
     764              :                    gint *off)
     765              : {
     766              :         gint ans;
     767              :         gint k, punt;
     768              :         gint n_data;
     769              : 
     770        25346 :         g_assert (at != NULL);
     771        25346 :         g_assert (end != NULL);
     772        25346 :         g_assert (end > at);
     773        25346 :         g_assert (off != NULL);
     774              : 
     775        25346 :         *off = 0;
     776        25346 :         n_data = end - at;
     777              : 
     778              :         /* short form */
     779        25346 :         if (!(at[0] & 128)) {
     780        22178 :                 *off = 1;
     781        22178 :                 return at[0];
     782              : 
     783              :         /* Long form */
     784              :         } else {
     785         3168 :                 k = at[0] & 0x7F;
     786         3168 :                 punt = 1;
     787              : 
     788              :                 /* definite length method */
     789         3168 :                 if (k) {
     790         3162 :                         ans = 0;
     791         7973 :                         while (punt <= k && punt < n_data) {
     792              :                                 /* we wrapped around, no bignum support... */
     793         4823 :                                 if (ans > G_MAXINT / 256)
     794           12 :                                         return -2;
     795         4811 :                                 ans = ans * 256;
     796              : 
     797              :                                 /* we wrapped around, no bignum support... */
     798         4811 :                                 if (ans > G_MAXINT - at[punt])
     799            0 :                                         return -2;
     800         4811 :                                 ans += at[punt++];
     801              :                         }
     802              : 
     803              :                 /* indefinite length method */
     804              :                 } else {
     805            6 :                         ans = -1;
     806              :                 }
     807              : 
     808         3156 :                 *off = punt;
     809         3156 :                 return ans;
     810              :         }
     811              : }
     812              : 
     813              : static gboolean
     814        25312 : atlv_parse_cls_tag_len (const guchar *at,
     815              :                         const guchar *end,
     816              :                         guchar *cls,
     817              :                         gulong *tag,
     818              :                         gint *off,
     819              :                         gint *len)
     820              : {
     821              :         gint cb1, cb2;
     822              : 
     823        25312 :         g_assert (at != NULL);
     824        25312 :         g_assert (end != NULL);
     825        25312 :         g_assert (end >= at);
     826        25312 :         g_assert (off != NULL);
     827        25312 :         g_assert (len != NULL);
     828              : 
     829        25312 :         if (!atlv_parse_cls_tag (at, end, cls, tag, &cb1))
     830            2 :                 return FALSE;
     831        25310 :         *len = atlv_parse_length (at + cb1, end, &cb2);
     832        25310 :         if (*len < -1)
     833           10 :                 return FALSE;
     834        25300 :         *off = cb1 + cb2;
     835        25300 :         if (*len >= 0 && at + *off + *len > end)
     836            4 :                 return FALSE;
     837        25296 :         return TRUE;
     838              : }
     839              : 
     840              : static const gchar *
     841        25292 : atlv_parse_der_tag (guchar cls,
     842              :                     gulong tag,
     843              :                     gint off,
     844              :                     gint len,
     845              :                     GBytes *data,
     846              :                     const guchar **at,
     847              :                     Atlv *tlv)
     848              : {
     849              :         const guchar *end;
     850              :         const gchar *ret;
     851              :         const guchar *beg;
     852              :         guchar ccls;
     853              :         gulong ctag;
     854              :         gint clen;
     855              :         gint coff;
     856              :         Atlv *child;
     857              :         Atlv *last;
     858              : 
     859        25292 :         g_assert (at != NULL);
     860        25292 :         g_assert (tlv != NULL);
     861              : 
     862        25292 :         end = bytes_get_end (data);
     863        25292 :         g_assert (*at <= end);
     864              : 
     865        25292 :         g_return_val_if_fail (*at + off + len <= end, "invalid length of tlv");
     866        25292 :         if (len < 0 && !(cls & ASN1_CLASS_STRUCTURED))
     867            1 :                 return "indefinite length on non-structured type";
     868              : 
     869        25291 :         beg = *at;
     870              : 
     871        25291 :         tlv->cls = cls;
     872        25291 :         tlv->tag = tag;
     873        25291 :         tlv->off = off;
     874        25291 :         tlv->len = len;
     875        25291 :         (*at) += off;
     876              : 
     877              :         /* Structured TLV, with further TLVs inside */
     878        25291 :         if (cls & ASN1_CLASS_STRUCTURED) {
     879              :                 /* If not indefinite length, then calculate end up front */
     880        11673 :                 if (len >= 0)
     881        11669 :                         end = (*at) + len;
     882        11673 :                 last = NULL;
     883        36076 :                 while (*at < end) {
     884        24413 :                         if (!atlv_parse_cls_tag_len (*at, end, &ccls, &ctag, &coff, &clen))
     885            5 :                                 return "content is not encoded properly";
     886              : 
     887              :                         /* End if indefinite length? */
     888        24408 :                         if (len < 0 && ccls == ASN1_CLASS_UNIVERSAL && ctag == 0 && clen == 0) {
     889            4 :                                 (*at) += coff;
     890            4 :                                 break;
     891              :                         }
     892              : 
     893              :                         /* Parse the child */
     894        24404 :                         child = atlv_new ();
     895        24404 :                         ret = atlv_parse_der_tag (ccls, ctag, coff, clen, data, at, child);
     896        24404 :                         if (ret != NULL) {
     897            1 :                                 atlv_free (child);
     898            1 :                                 return ret;
     899              :                         }
     900              : 
     901              :                         /* Add the child to the right place */
     902        24403 :                         if (last == NULL)
     903        11651 :                                 tlv->child = child;
     904              :                         else
     905        12752 :                                 last->next = child;
     906        24403 :                         last = child;
     907              :                 }
     908              : 
     909              :         /* Non-structured TLV, just a value */
     910              :         } else {
     911        13618 :                 tlv->value = g_bytes_new_with_free_func (*at, len,
     912              :                                                          (GDestroyNotify)g_bytes_unref,
     913        13618 :                                                          g_bytes_ref (data));
     914        13618 :                 (*at) += len;
     915              :         }
     916              : 
     917              :         /* Note the actual DER that we decoded */
     918        25285 :         tlv->decoded = g_bytes_new_with_free_func (beg, *at - beg,
     919              :                                                    (GDestroyNotify)g_bytes_unref,
     920        25285 :                                                    g_bytes_ref (data));
     921              : 
     922        25285 :         return NULL; /* Success */
     923              : }
     924              : 
     925              : static const gchar *
     926          899 : atlv_parse_der (GBytes *data,
     927              :                 Atlv *tlv)
     928              : {
     929              :         const guchar *end;
     930              :         const guchar *at;
     931              :         const gchar *ret;
     932              :         guchar cls;
     933              :         gulong tag;
     934              :         gint off;
     935              :         gint len;
     936              :         gsize size;
     937              : 
     938          899 :         at = g_bytes_get_data (data, &size);
     939          899 :         g_return_val_if_fail (at != NULL, FALSE);
     940          899 :         end = at + size;
     941              : 
     942          899 :         if (!atlv_parse_cls_tag_len (at, end, &cls, &tag, &off, &len))
     943           11 :                 return "content is not encoded properly";
     944              : 
     945          888 :         ret = atlv_parse_der_tag (cls, tag, off, len, data, &at, tlv);
     946          888 :         if (ret != NULL)
     947            6 :                 return ret;
     948              : 
     949          882 :         if (at != end)
     950            2 :                 return "extra unexpected trailing data";
     951              : 
     952          880 :         return NULL; /* Success */
     953              : }
     954              : 
     955              : /* -------------------------------------------------------------------------
     956              :  * DECODING
     957              :  */
     958              : 
     959              : static gboolean
     960         1088 : anode_decode_choice (GNode *node,
     961              :                      Atlv *tlv)
     962              : {
     963         1088 :         gboolean have = FALSE;
     964              :         GNode *child;
     965              :         Anode *an;
     966              : 
     967         2820 :         for (child = node->children; child; child = child->next) {
     968         1732 :                 an = (Anode*)child->data;
     969         1732 :                 if (anode_decode_one (child, tlv)) {
     970         1088 :                         an->chosen = 1;
     971         1088 :                         have = TRUE;
     972              :                 } else {
     973          644 :                         an->chosen = 0;
     974              :                 }
     975              :         }
     976              : 
     977         1088 :         if (!have)
     978            0 :                 return anode_failure (node, "no choice is present");
     979              : 
     980         1088 :         return TRUE;
     981              : }
     982              : 
     983              : static gboolean
     984         6394 : anode_decode_sequence_or_set (GNode *node,
     985              :                               Atlv *tlv)
     986              : {
     987              :         Atlv *ctlv;
     988              :         gulong tag;
     989              :         gint i;
     990              : 
     991              :         /*
     992              :          * The reason we can parse a set just like a sequence, is because in DER,
     993              :          * the order of the SET is predefined by the tags. In addition the definitions
     994              :          * we have are sorted.
     995              :          */
     996              : 
     997              :         /* Tags must be in ascending order */
     998         6394 :         if (anode_def_type (node) == EGG_ASN1X_SET) {
     999            6 :                 for (ctlv = tlv->child, i = 0; ctlv != NULL; ctlv = ctlv->next, i++) {
    1000            5 :                         if (i > 0 && tag > ctlv->tag)
    1001            1 :                                 return anode_failure (node, "content must be in ascending order");
    1002            4 :                         tag = ctlv->tag;
    1003              :                 }
    1004              :         }
    1005              : 
    1006         6393 :         return anode_decode_anything (node->children, tlv->child);
    1007              : }
    1008              : 
    1009              : static gboolean
    1010         3629 : anode_decode_sequence_or_set_of (GNode *node,
    1011              :                                  Atlv *tlv)
    1012              : {
    1013              :         Atlv *ctlv;
    1014              :         GNode *child, *other;
    1015              :         gulong tag;
    1016              :         gint i;
    1017              : 
    1018              :         /* The first child */
    1019         3629 :         child = node->children;
    1020         3629 :         g_return_val_if_fail (child, FALSE);
    1021              : 
    1022        10286 :         for (ctlv = tlv->child, i = 0; ctlv != NULL; ctlv = ctlv->next, i++) {
    1023              : 
    1024              :                 /* Tag must have same tag as top */
    1025         6659 :                 if (i == 0)
    1026         3629 :                         tag = anode_calc_tag (child);
    1027         3030 :                 else if (tag != G_MAXULONG && ctlv->tag != tag)
    1028            1 :                         return anode_failure (node, "invalid mismatched content");
    1029              : 
    1030              :                 /* TODO: Set of must be in ascending order in DER encoding */
    1031              : 
    1032         6658 :                 if (i == 0) {
    1033         3629 :                         other = child;
    1034              :                 } else {
    1035         3029 :                         other = anode_clone (child);
    1036         3029 :                         g_node_append (node, other);
    1037              :                 }
    1038              : 
    1039         6658 :                 if (!anode_decode_one (other, ctlv))
    1040            1 :                         return FALSE;
    1041              :         }
    1042              : 
    1043         3627 :         return TRUE;
    1044              : }
    1045              : 
    1046              : static gboolean
    1047          707 : anode_decode_bit_string (GNode *node,
    1048              :                          Atlv *tlv)
    1049              : {
    1050          707 :         Anode *an = node->data;
    1051              :         guchar empty, mask;
    1052              :         GBytes *value;
    1053              :         const guchar *buf;
    1054              :         gsize len;
    1055              : 
    1056          707 :         buf = g_bytes_get_data (tlv->value, &len);
    1057          707 :         if (len == 0)
    1058            1 :                 return anode_failure (node, "invalid length bit string");
    1059              : 
    1060              :         /* The first byte is the number of empty bits */
    1061          706 :         empty = buf[0];
    1062          706 :         if (empty >= 8)
    1063            1 :                 return anode_failure (node, "invalid number of empty bits");
    1064              : 
    1065              :         /* Free bits at end must be zero */
    1066          705 :         mask = 0xFF >> (8 - empty);
    1067          705 :         if (len > 1 && buf[len - 1] & mask)
    1068            1 :                 return anode_failure (node, "bit string has invalid trailing bits");
    1069              : 
    1070          704 :         value = g_bytes_new_from_bytes (tlv->value, 1, len - 1);
    1071          704 :         anode_take_value (node, value);
    1072          704 :         an = node->data;
    1073          704 :         an->bits_empty = empty;
    1074          704 :         return TRUE;
    1075              : }
    1076              : 
    1077              : static gboolean
    1078        13020 : anode_decode_primitive (GNode *node,
    1079              :                         Atlv *tlv,
    1080              :                         gint flags)
    1081              : {
    1082              :         /* Must not have any tlv children */
    1083        13020 :         g_assert (tlv->child == NULL);
    1084              : 
    1085        13020 :         switch (anode_def_type (node)) {
    1086              : 
    1087              :         /* Handle bit strings specially */
    1088          707 :         case EGG_ASN1X_BIT_STRING:
    1089          707 :                 return anode_decode_bit_string (node, tlv);
    1090              : 
    1091              :         /* The primitive value types */
    1092         7942 :         case EGG_ASN1X_INTEGER:
    1093              :         case EGG_ASN1X_ENUMERATED:
    1094              :         case EGG_ASN1X_BOOLEAN:
    1095              :         case EGG_ASN1X_OCTET_STRING:
    1096              :         case EGG_ASN1X_OBJECT_ID:
    1097              :         case EGG_ASN1X_NULL:
    1098              :         case EGG_ASN1X_TIME:
    1099              :         case EGG_ASN1X_UTC_TIME:
    1100              :         case EGG_ASN1X_GENERALIZED_TIME:
    1101              :         case EGG_ASN1X_GENERAL_STRING:
    1102              :         case EGG_ASN1X_NUMERIC_STRING:
    1103              :         case EGG_ASN1X_IA5_STRING:
    1104              :         case EGG_ASN1X_TELETEX_STRING:
    1105              :         case EGG_ASN1X_PRINTABLE_STRING:
    1106              :         case EGG_ASN1X_UNIVERSAL_STRING:
    1107              :         case EGG_ASN1X_BMP_STRING:
    1108              :         case EGG_ASN1X_UTF8_STRING:
    1109              :         case EGG_ASN1X_VISIBLE_STRING:
    1110         7942 :                 anode_set_value (node, tlv->value);
    1111         7942 :                 return TRUE;
    1112              : 
    1113              :         /* Just use the 'parsed' which is automatically set */
    1114         3821 :         case EGG_ASN1X_ANY:
    1115         3821 :                 return TRUE;
    1116              : 
    1117          550 :         case EGG_ASN1X_CHOICE:
    1118          550 :                 return anode_decode_choice (node, tlv);
    1119              :         }
    1120              : 
    1121            0 :         return anode_failure (node, "primitive value of an unexpected type"); /* UNREACHABLE: tag validation? */
    1122              : }
    1123              : 
    1124              : static gboolean
    1125        10637 : anode_decode_structured (GNode *node,
    1126              :                          Atlv *tlv,
    1127              :                          gint flags)
    1128              : {
    1129        10637 :         switch (anode_def_type (node)) {
    1130              : 
    1131              :         /* Just use the 'parsed' which is automatically set */
    1132           76 :         case EGG_ASN1X_ANY:
    1133              :         case EGG_ASN1X_GENERAL_STRING:
    1134              :         case EGG_ASN1X_OCTET_STRING:
    1135              :         case EGG_ASN1X_NUMERIC_STRING:
    1136              :         case EGG_ASN1X_IA5_STRING:
    1137              :         case EGG_ASN1X_TELETEX_STRING:
    1138              :         case EGG_ASN1X_PRINTABLE_STRING:
    1139              :         case EGG_ASN1X_UNIVERSAL_STRING:
    1140              :         case EGG_ASN1X_BMP_STRING:
    1141              :         case EGG_ASN1X_UTF8_STRING:
    1142              :         case EGG_ASN1X_VISIBLE_STRING:
    1143           76 :                 return TRUE;
    1144              : 
    1145          538 :         case EGG_ASN1X_CHOICE:
    1146          538 :                 return anode_decode_choice (node, tlv);
    1147              : 
    1148         6394 :         case EGG_ASN1X_SEQUENCE:
    1149              :         case EGG_ASN1X_SET:
    1150         6394 :                 return anode_decode_sequence_or_set (node, tlv);
    1151              : 
    1152         3629 :         case EGG_ASN1X_SEQUENCE_OF:
    1153              :         case EGG_ASN1X_SET_OF:
    1154         3629 :                 return anode_decode_sequence_or_set_of (node, tlv);
    1155              : 
    1156            0 :         default:
    1157            0 :                 return anode_failure (node, "structured value of an unexpected type"); /* UNREACHABLE: tag validation? */
    1158              :         }
    1159              : }
    1160              : 
    1161              : static gboolean
    1162        24179 : anode_decode_one_without_tag (GNode *node,
    1163              :                               Atlv *tlv,
    1164              :                               gint flags)
    1165              : {
    1166              :         gboolean ret;
    1167              :         Anode *an;
    1168              : 
    1169              :         /* An explicit, wrapped tag */
    1170        24179 :         if (anode_calc_explicit_for_flags (node, flags, NULL)) {
    1171          522 :                 if ((tlv->cls & ASN1_CLASS_CONTEXT_SPECIFIC) == 0)
    1172            1 :                         return anode_failure (node, "missing context specific tag");
    1173          521 :                 if (tlv->child == NULL)
    1174            1 :                         return anode_failure (node, "missing context specific child");
    1175          520 :                 if (tlv->child->next != NULL)
    1176            1 :                         return anode_failure (node, "multiple context specific children");
    1177          519 :                 flags &= ~FLAG_TAG;
    1178          519 :                 ret = anode_decode_one_without_tag (node, tlv->child, flags);
    1179              : 
    1180              :         /* Structured value */
    1181        23657 :         } else if (tlv->cls & ASN1_CLASS_STRUCTURED) {
    1182        10637 :                 ret = anode_decode_structured (node, tlv, flags);
    1183              : 
    1184              :         /* A primitive simple value */
    1185              :         } else {
    1186        13020 :                 ret = anode_decode_primitive (node, tlv, flags);
    1187              :         }
    1188              : 
    1189              :         /* Mark which tlv we used for this node */
    1190        24176 :         if (ret) {
    1191        24141 :                 an = node->data;
    1192        24141 :                 atlv_free (an->parsed);
    1193        24141 :                 an->parsed = atlv_dup (tlv, FALSE);
    1194              :         }
    1195              : 
    1196        24176 :         return ret;
    1197              : }
    1198              : 
    1199              : static gboolean
    1200         8390 : anode_decode_one (GNode *node,
    1201              :                   Atlv *tlv)
    1202              : {
    1203         8390 :         gint flags = anode_def_flags (node);
    1204              :         gulong tag;
    1205              : 
    1206         8390 :         tag = anode_calc_tag_for_flags (node, flags);
    1207              : 
    1208              :         /* We don't know what the tag is supposed to be */
    1209         8390 :         if (tag == G_MAXULONG)
    1210            2 :                 tag = tlv->tag;
    1211              : 
    1212              :         /* We have no match */
    1213         8390 :         if (tag != tlv->tag)
    1214          645 :                 return anode_failure (node, "decoded tag did not match expected");
    1215              : 
    1216         7745 :         return anode_decode_one_without_tag (node, tlv, flags);
    1217              : }
    1218              : 
    1219              : static gboolean
    1220         1409 : anode_decode_option_or_default (GNode *node)
    1221              : {
    1222         1409 :         gint flags = anode_def_flags (node);
    1223              : 
    1224         1409 :         if (flags & FLAG_OPTION || flags & FLAG_DEFAULT) {
    1225         1366 :                 anode_clr_value (node);
    1226         1366 :                 return TRUE;
    1227              :         }
    1228              : 
    1229           43 :         return FALSE;
    1230              : }
    1231              : 
    1232              : static gboolean
    1233         7330 : anode_decode_anything (GNode *node,
    1234              :                        Atlv *tlv)
    1235              : {
    1236         7330 :         GNode *prev = NULL;
    1237              :         GNode *next;
    1238              :         gulong tag;
    1239              :         gint flags;
    1240              : 
    1241         7330 :         g_assert (node != NULL);
    1242              : 
    1243        24362 :         while (tlv != NULL) {
    1244        17108 :                 if (node == NULL)
    1245            2 :                         return anode_failure (prev, "encountered extra tag");
    1246              : 
    1247        17106 :                 flags = anode_def_flags (node);
    1248        17106 :                 tag = anode_calc_tag_for_flags (node, flags);
    1249              : 
    1250              :                 /* We don't know what the tag is supposed to be */
    1251        17106 :                 if (tag == G_MAXULONG)
    1252         4953 :                         tag = tlv->tag;
    1253              : 
    1254              :                 /* We have no match */
    1255        17106 :                 if (tag != tlv->tag) {
    1256              : 
    1257              :                         /* See if we can skip this node */
    1258         1191 :                         if (anode_decode_option_or_default (node))
    1259         1155 :                                 next = g_node_next_sibling (node);
    1260              :                         else
    1261           36 :                                 next = NULL;
    1262              : 
    1263         1191 :                         if (next == NULL)
    1264           36 :                                 return anode_failure (node, "decoded tag did not match expected");
    1265              : 
    1266         1155 :                         prev = node;
    1267         1155 :                         node = next;
    1268         1155 :                         continue;
    1269              :                 }
    1270              : 
    1271        15915 :                 if (!anode_decode_one_without_tag (node, tlv, flags))
    1272           38 :                         return FALSE;
    1273              : 
    1274              :                 /* Next node and tag */
    1275        15877 :                 prev = node;
    1276        15877 :                 node = g_node_next_sibling (node);
    1277        15877 :                 tlv = tlv->next;
    1278              :         }
    1279              : 
    1280              :         /* We have no values for these nodes */
    1281         7465 :         while (node != NULL) {
    1282          218 :                 if (anode_decode_option_or_default (node))
    1283          211 :                         node = g_node_next_sibling (node);
    1284              :                 else
    1285            7 :                         return anode_failure (node, "no decoded value");
    1286              :         }
    1287              : 
    1288         7247 :         return TRUE;
    1289              : }
    1290              : 
    1291              : gboolean
    1292          867 : egg_asn1x_decode_full (GNode *asn,
    1293              :                        GBytes *data,
    1294              :                        gint options)
    1295              : {
    1296              :         const gchar *msg;
    1297              :         gboolean ret;
    1298              :         Anode *an;
    1299              :         Atlv *tlv;
    1300              : 
    1301          867 :         g_return_val_if_fail (asn != NULL, FALSE);
    1302          867 :         g_return_val_if_fail (data != NULL, FALSE);
    1303              : 
    1304          867 :         egg_asn1x_clear (asn);
    1305              : 
    1306          867 :         tlv = atlv_new ();
    1307          867 :         msg = atlv_parse_der (data, tlv);
    1308          867 :         if (msg == NULL) {
    1309          849 :                 ret = anode_decode_anything (asn, tlv);
    1310              : 
    1311              :         /* A failure, set the message manually so it doesn't get a prefix */
    1312              :         } else {
    1313           18 :                 an = asn->data;
    1314           18 :                 g_free (an->failure);
    1315           18 :                 an->failure = g_strdup (msg);
    1316           18 :                 ret = FALSE;
    1317              :         }
    1318              : 
    1319          867 :         atlv_free (tlv);
    1320          867 :         if (ret == FALSE)
    1321           68 :                 return FALSE;
    1322              : 
    1323          799 :         return egg_asn1x_validate (asn, !(options & EGG_ASN1X_NO_STRICT));
    1324              : }
    1325              : 
    1326              : gboolean
    1327          112 : egg_asn1x_decode (GNode *asn,
    1328              :                   GBytes *data)
    1329              : {
    1330          112 :         g_return_val_if_fail (asn != NULL, FALSE);
    1331          112 :         g_return_val_if_fail (data != NULL, FALSE);
    1332              : 
    1333          112 :         return egg_asn1x_decode_full (asn, data, 0);
    1334              : }
    1335              : 
    1336              : /* -----------------------------------------------------------------------------------
    1337              :  * UNPARSE
    1338              :  */
    1339              : 
    1340              : static void
    1341         4813 : atlv_unparse_len (gulong len,
    1342              :                   guchar *ans,
    1343              :                   gint *cb)
    1344              : {
    1345              :         guchar temp[sizeof (gulong)];
    1346              :         gint k;
    1347              : 
    1348         4813 :         g_assert (cb);
    1349              : 
    1350              :         /* short form */
    1351         4813 :         if (len < 128) {
    1352         3621 :                 if (ans != NULL)
    1353         2834 :                         ans[0] = (unsigned char)len;
    1354         3621 :                 *cb = 1;
    1355              : 
    1356              :         /* Long form */
    1357              :         } else {
    1358         1192 :                 k = 0;
    1359         2979 :                 while (len) {
    1360         1787 :                         temp[k++] = len & 0xFF;
    1361         1787 :                         len = len >> 8;
    1362              :                 }
    1363         1192 :                 *cb = k + 1;
    1364         1192 :                 if (ans != NULL) {
    1365          675 :                         ans[0] = ((unsigned char) k & 0x7F) + 128;
    1366         1675 :                         while (k--)
    1367         1000 :                                 ans[*cb - 1 - k] = temp[k];
    1368              :                 }
    1369              :         }
    1370         4813 : }
    1371              : 
    1372              : static gint
    1373         4813 : atlv_unparse_cls_tag_len (guchar *data,
    1374              :                           gsize n_data,
    1375              :                           guchar cls,
    1376              :                           gulong tag,
    1377              :                           gint len)
    1378              : {
    1379              :         guchar temp[sizeof(gulong)];
    1380              :         gint cb;
    1381         4813 :         gint off = 0;
    1382              :         gint k;
    1383              : 
    1384              :         /* Short form */
    1385         4813 :         if (tag < 31) {
    1386         4807 :                 off += 1;
    1387         4807 :                 if (data) {
    1388         3506 :                         g_assert (n_data >= off);
    1389         3506 :                         data[0] = (cls & 0xE0) + ((guchar) (tag & 0x1F));
    1390              :                 }
    1391              :         /* Long form */
    1392              :         } else {
    1393            6 :                 k = 0;
    1394           12 :                 while (tag) {
    1395            6 :                         temp[k++] = tag & 0x7F;
    1396            6 :                         tag = tag >> 7;
    1397              :                 }
    1398            6 :                 off = k + 1;
    1399            6 :                 if (data) {
    1400            3 :                         g_assert (n_data >= off);
    1401            3 :                         data[0] = (cls & 0xE0) + 31;
    1402            6 :                         while (data && k--)
    1403            3 :                                 data[off - 1 - k] = temp[k] + 128;
    1404            3 :                         data[off - 1] -= 128;
    1405              :                 }
    1406              :         }
    1407              : 
    1408              :         /* And now the length */
    1409         4813 :         cb = n_data - off;
    1410         4813 :         atlv_unparse_len (len, data ? data + off : NULL, &cb);
    1411         4813 :         off += cb;
    1412              : 
    1413         4813 :         g_assert (!data || n_data >= off);
    1414         4813 :         return off;
    1415              : }
    1416              : 
    1417              : static void
    1418         3509 : atlv_unparse_der (Atlv *tlv,
    1419              :                   guchar **at,
    1420              :                   guchar *end)
    1421              : {
    1422              :         const guchar *exp;
    1423              :         const guchar *buf;
    1424              :         guchar *p;
    1425              :         guchar mask;
    1426              :         Atlv *ctlv;
    1427              :         gint off;
    1428              :         gsize len;
    1429              : 
    1430         3509 :         g_assert (*at <= end);
    1431              : 
    1432         3509 :         off = atlv_unparse_cls_tag_len (*at, end - *at, tlv->cls,
    1433              :                                         tlv->tag, tlv->len);
    1434         3509 :         g_assert (off == tlv->off);
    1435         3509 :         (*at) += off;
    1436              : 
    1437              :         /* Write a value */
    1438         3509 :         if (tlv->value) {
    1439         1891 :                 buf = g_bytes_get_data (tlv->value, &len);
    1440         1891 :                 p = *at;
    1441              : 
    1442              :                 /* Special behavior for bit strings */
    1443         1891 :                 if (tlv->prefix_for_bit_string) {
    1444          190 :                         g_assert (len + 1 == tlv->len);
    1445          190 :                         p[0] = (guchar)tlv->bits_empty;
    1446          190 :                         memcpy (p + 1, buf, len);
    1447              : 
    1448              :                         /* Set the extra bits to zero */
    1449          190 :                         if (len && tlv->bits_empty) {
    1450            2 :                                 mask = 0xFF >> (8 - tlv->bits_empty);
    1451            2 :                                 p[len] &= ~mask;
    1452              :                         }
    1453          190 :                         p += len + 1;
    1454              : 
    1455              :                 /* Special behavior for prefixed integers */
    1456         1701 :                 } else if (tlv->prefix_with_zero_byte) {
    1457            1 :                         g_assert (len + 1 == tlv->len);
    1458            1 :                         p[0] = 0;
    1459            1 :                         memcpy (p + 1, buf, len);
    1460            1 :                         p += len + 1;
    1461              : 
    1462              :                 /* Standard behavior */
    1463              :                 } else {
    1464         1700 :                         g_assert (len == tlv->len);
    1465         1700 :                         memcpy (p, buf, len);
    1466         1700 :                         p += len;
    1467              :                 }
    1468              : 
    1469         1891 :                 *at = p;
    1470              : 
    1471              :         /* Write a bunch of child TLV's */
    1472              :         } else {
    1473         4792 :                 for (ctlv = tlv->child; ctlv != NULL; ctlv = ctlv->next) {
    1474         3174 :                         exp = *at + ctlv->len + ctlv->off;
    1475         3174 :                         atlv_unparse_der (ctlv, at, end);
    1476         3174 :                         g_assert (exp == *at);
    1477              :                 }
    1478              :         }
    1479              : 
    1480         3509 :         g_assert (*at <= end);
    1481         3509 : }
    1482              : 
    1483              : static GBytes *
    1484          335 : atlv_unparse_to_bytes (Atlv *tlv,
    1485              :                        EggAllocator allocator)
    1486              : {
    1487              :         GBytes *bytes;
    1488              :         guchar *data;
    1489              :         guchar *at;
    1490              :         gint len;
    1491              : 
    1492              :         /* Allocate enough memory for entire thingy */
    1493          335 :         len = tlv->off + tlv->len;
    1494          335 :         g_return_val_if_fail (len != 0, NULL);
    1495              : 
    1496          335 :         bytes = bytes_new_with_allocator (allocator, &data, len);
    1497          335 :         g_return_val_if_fail (bytes != NULL, NULL);
    1498              : 
    1499          335 :         at = data;
    1500          335 :         atlv_unparse_der (tlv, &at, data + len);
    1501          335 :         g_assert (at == data + len);
    1502              : 
    1503          335 :         return bytes;
    1504              : }
    1505              : 
    1506              : typedef struct {
    1507              :         GBytes *bytes;
    1508              :         Atlv *tlv;
    1509              : } SortPair;
    1510              : 
    1511              : static gint
    1512            3 : compare_sort_pair (gconstpointer a,
    1513              :                    gconstpointer b)
    1514              : {
    1515            3 :         const SortPair *sa = a;
    1516            3 :         const SortPair *sb = b;
    1517            3 :         return g_bytes_compare (sa->bytes, sb->bytes);
    1518              : }
    1519              : 
    1520              : static void
    1521         3380 : atlv_sort_perform (Atlv *tlv,
    1522              :                    EggAllocator allocator)
    1523              : {
    1524              :         GList *pairs, *l;
    1525              :         SortPair *pair;
    1526              :         GBytes *bytes;
    1527              :         Atlv *ctlv;
    1528              :         Atlv *last;
    1529              :         gboolean sort;
    1530              : 
    1531         6470 :         for (ctlv = tlv->child; ctlv != NULL; ctlv = ctlv->next)
    1532         3090 :                 atlv_sort_perform (ctlv, allocator);
    1533              : 
    1534         3380 :         if (!tlv->sorted)
    1535         3336 :                 return;
    1536              : 
    1537           44 :         pairs = NULL;
    1538           89 :         for (ctlv = tlv->child; ctlv != NULL; ctlv = ctlv->next) {
    1539           45 :                 bytes = atlv_unparse_to_bytes (ctlv, allocator);
    1540           45 :                 g_return_if_fail (bytes != NULL);
    1541              : 
    1542           45 :                 pair = g_slice_new0 (SortPair);
    1543           45 :                 pair->bytes = bytes;
    1544           45 :                 pair->tlv = ctlv;
    1545           45 :                 pairs = g_list_prepend (pairs, pair);
    1546              :         }
    1547              : 
    1548              :         /* Only sort of the above unparse completed for all */
    1549           44 :         sort = ctlv == NULL;
    1550           44 :         last = NULL;
    1551              : 
    1552           44 :         pairs = g_list_sort (pairs, compare_sort_pair);
    1553           89 :         for (l = pairs; l != NULL; l = g_list_next (l)) {
    1554           45 :                 pair = l->data;
    1555              : 
    1556              :                 /* Only if the sort completed */
    1557           45 :                 if (sort) {
    1558           45 :                         if (last == NULL)
    1559           43 :                                 tlv->child = pair->tlv;
    1560              :                         else
    1561            2 :                                 last->next = pair->tlv;
    1562           45 :                         last = pair->tlv;
    1563              :                 }
    1564              : 
    1565           45 :                 g_bytes_unref (pair->bytes);
    1566           45 :                 g_slice_free (SortPair, pair);
    1567              :         }
    1568              : 
    1569           44 :         g_list_free (pairs);
    1570              : }
    1571              : 
    1572              : static void
    1573         1251 : anode_build_cls_tag_len (GNode *node,
    1574              :                          Atlv *tlv,
    1575              :                          gint len)
    1576              : {
    1577         1251 :         gboolean explicit = FALSE;
    1578              :         guchar cls_type;
    1579              :         gint flags;
    1580              : 
    1581              :         /* One for the prefix character */
    1582         1251 :         if (tlv->prefix_for_bit_string ||
    1583              :             tlv->prefix_with_zero_byte)
    1584          191 :                 len += 1;
    1585              : 
    1586              :         /* Figure out the basis if the class */
    1587         1251 :         switch (anode_def_type (node)) {
    1588          643 :         case EGG_ASN1X_INTEGER:
    1589              :         case EGG_ASN1X_BOOLEAN:
    1590              :         case EGG_ASN1X_BIT_STRING:
    1591              :         case EGG_ASN1X_OCTET_STRING:
    1592              :         case EGG_ASN1X_OBJECT_ID:
    1593              :         case EGG_ASN1X_TIME:
    1594              :         case EGG_ASN1X_UTC_TIME:
    1595              :         case EGG_ASN1X_GENERALIZED_TIME:
    1596              :         case EGG_ASN1X_ENUMERATED:
    1597              :         case EGG_ASN1X_GENERAL_STRING:
    1598              :         case EGG_ASN1X_NUMERIC_STRING:
    1599              :         case EGG_ASN1X_IA5_STRING:
    1600              :         case EGG_ASN1X_TELETEX_STRING:
    1601              :         case EGG_ASN1X_PRINTABLE_STRING:
    1602              :         case EGG_ASN1X_UNIVERSAL_STRING:
    1603              :         case EGG_ASN1X_BMP_STRING:
    1604              :         case EGG_ASN1X_UTF8_STRING:
    1605              :         case EGG_ASN1X_VISIBLE_STRING:
    1606              :         case EGG_ASN1X_NULL:
    1607          643 :                 tlv->cls = ASN1_CLASS_UNIVERSAL;
    1608          643 :                 break;
    1609              :         /* Container types */
    1610          608 :         case EGG_ASN1X_SEQUENCE:
    1611              :         case EGG_ASN1X_SET:
    1612              :         case EGG_ASN1X_SEQUENCE_OF:
    1613              :         case EGG_ASN1X_SET_OF:
    1614          608 :                 tlv->cls = (ASN1_CLASS_STRUCTURED | ASN1_CLASS_UNIVERSAL);
    1615          608 :                 break;
    1616              : 
    1617              :         /* Transparent types shouldn't get here */
    1618            0 :         case EGG_ASN1X_ANY:
    1619              :         case EGG_ASN1X_CHOICE:
    1620              :         default:
    1621            0 :                 g_assert_not_reached ();
    1622              :         };
    1623              : 
    1624         1251 :         flags = anode_def_flags (node);
    1625              : 
    1626              :         /* Build up the class */
    1627         1251 :         if (flags & FLAG_TAG) {
    1628           29 :                 explicit = anode_calc_explicit_for_flags (node, flags, &cls_type);
    1629           29 :                 if (explicit)
    1630           20 :                         flags &= ~FLAG_TAG;
    1631              :                 else
    1632            9 :                         tlv->cls |= cls_type;
    1633              :         }
    1634              : 
    1635              :         /* Setup the class */
    1636         1251 :         tlv->tag = anode_calc_tag_for_flags (node, flags);
    1637              : 
    1638              :         /* The offset and length */
    1639         1251 :         tlv->len = len;
    1640         1251 :         tlv->off = atlv_unparse_cls_tag_len (NULL, 0, tlv->cls, tlv->tag, len);
    1641         1251 : }
    1642              : 
    1643              : static Atlv *
    1644          418 : anode_build_value (GNode *node)
    1645              : {
    1646          418 :         Anode *an = node->data;
    1647              :         Atlv *tlv;
    1648              :         gsize len;
    1649              : 
    1650              :         /* Fill this in based on the value */
    1651          418 :         if (an->value == NULL)
    1652          103 :                 return NULL;
    1653              : 
    1654          315 :         tlv = atlv_new ();
    1655          315 :         tlv->value = g_bytes_ref (an->value);
    1656              : 
    1657          315 :         len = g_bytes_get_size (an->value);
    1658          315 :         anode_build_cls_tag_len (node, tlv, len);
    1659          315 :         return tlv;
    1660              : }
    1661              : 
    1662              : static Atlv *
    1663          194 : anode_build_bit_string (GNode *node)
    1664              : {
    1665          194 :         Anode *an = node->data;
    1666              :         Atlv *tlv;
    1667              :         gsize len;
    1668              : 
    1669          194 :         if (an->value == NULL)
    1670            4 :                 return NULL;
    1671              : 
    1672          190 :         tlv = atlv_new ();
    1673          190 :         tlv->value = g_bytes_ref (an->value);
    1674          190 :         tlv->bits_empty = an->bits_empty;
    1675          190 :         tlv->prefix_for_bit_string = 1;
    1676              : 
    1677          190 :         len = g_bytes_get_size (an->value);
    1678          190 :         anode_build_cls_tag_len (node, tlv, len);
    1679          190 :         return tlv;
    1680              : }
    1681              : 
    1682              : static Atlv *
    1683          162 : anode_build_integer (GNode *node)
    1684              : {
    1685          162 :         Anode *an = node->data;
    1686              :         const guchar *buf;
    1687              :         gboolean sign;
    1688              :         gsize len;
    1689              :         Atlv *tlv;
    1690              : 
    1691          162 :         if (an->value == NULL)
    1692           24 :                 return NULL;
    1693              : 
    1694          138 :         tlv = atlv_new ();
    1695          138 :         tlv->value = g_bytes_ref (an->value);
    1696              : 
    1697          138 :         buf = g_bytes_get_data (an->value, &len);
    1698          138 :         if (an->guarantee_unsigned) {
    1699              : 
    1700              :                 /*
    1701              :                  * In two's complement (which DER is) this would be negative, add a zero
    1702              :                  * byte so that it isn't. Here we just note that the result will be one
    1703              :                  * byte longer.
    1704              :                  */
    1705            1 :                 sign = !!(buf[0] & 0x80);
    1706            1 :                 if (sign)
    1707            1 :                         tlv->prefix_with_zero_byte = 1;
    1708              :         }
    1709              : 
    1710          138 :         anode_build_cls_tag_len (node, tlv, len);
    1711          138 :         return tlv;
    1712              : }
    1713              : 
    1714              : static Atlv *
    1715          374 : anode_build_any (GNode *node)
    1716              : {
    1717              :         Atlv *parsed;
    1718              : 
    1719              :         /*
    1720              :          * Fill this in based on already parsed TLVs. It is assumed
    1721              :          * that any explicit tags are already present, and the functions
    1722              :          * for managing ANY try to enforce this.
    1723              :          */
    1724              : 
    1725          374 :         parsed = anode_get_parsed (node);
    1726          374 :         if (parsed != NULL)
    1727          270 :                 return atlv_dup (parsed, FALSE);
    1728              : 
    1729          104 :         return NULL;
    1730              : }
    1731              : 
    1732              : static Atlv *
    1733           48 : anode_build_choice (GNode *node,
    1734              :                     gboolean want)
    1735              : {
    1736              :         GNode *child;
    1737              : 
    1738           48 :         g_assert (anode_def_type (node) == EGG_ASN1X_CHOICE);
    1739              : 
    1740           48 :         child = egg_asn1x_get_choice (node);
    1741              : 
    1742              :         /* Should have been checked by a previous validate */
    1743           48 :         g_return_val_if_fail (child != NULL, NULL);
    1744              : 
    1745           48 :         return anode_build_anything (child, want);
    1746              : }
    1747              : 
    1748              : static Atlv *
    1749          688 : anode_build_structured (GNode *node,
    1750              :                         gboolean want)
    1751              : {
    1752              :         gboolean child_want;
    1753              :         Atlv *last;
    1754              :         Atlv *ctlv;
    1755              :         Atlv *tlv;
    1756              :         GNode *child;
    1757              :         gint type;
    1758              :         gint len;
    1759              : 
    1760          688 :         type = anode_def_type (node);
    1761          688 :         child_want = want;
    1762          688 :         last = NULL;
    1763          688 :         len = 0;
    1764              : 
    1765          688 :         if (type == EGG_ASN1X_SEQUENCE_OF || type == EGG_ASN1X_SET_OF)
    1766          109 :                 child_want = FALSE;
    1767          688 :         if (anode_def_flags (node) & FLAG_OPTION)
    1768           19 :                 want = FALSE;
    1769              : 
    1770          688 :         tlv = atlv_new ();
    1771         2219 :         for (child = node->children; child != NULL; child = child->next) {
    1772         1531 :                 ctlv = anode_build_anything (child, child_want);
    1773         1531 :                 if (ctlv != NULL) {
    1774         1217 :                         if (last == NULL)
    1775          581 :                                 tlv->child = ctlv;
    1776              :                         else
    1777          636 :                                 last->next = ctlv;
    1778         1217 :                         last = ctlv;
    1779         1217 :                         len += ctlv->off + ctlv->len;
    1780              :                 }
    1781              :         }
    1782              : 
    1783          688 :         if (last == NULL) {
    1784              :                 /* See if we should encode an empty set or seq of */
    1785          107 :                 if (type == EGG_ASN1X_SEQUENCE_OF || type == EGG_ASN1X_SET_OF) {
    1786           54 :                         if (!want) {
    1787           28 :                                 atlv_free (tlv);
    1788           28 :                                 return NULL;
    1789              :                         }
    1790           53 :                 } else if (!want) {
    1791           52 :                         atlv_free (tlv);
    1792           52 :                         return NULL;
    1793              :                 }
    1794              :         }
    1795              : 
    1796          608 :         anode_build_cls_tag_len (node, tlv, len);
    1797              : 
    1798          608 :         if (type == EGG_ASN1X_SET_OF)
    1799           44 :                 tlv->sorted = 1;
    1800              : 
    1801          608 :         return tlv;
    1802              : }
    1803              : 
    1804              : static Atlv *
    1805         1344 : anode_build_maybe_explicit (GNode *node,
    1806              :                             Atlv *tlv,
    1807              :                             gint flags)
    1808              : {
    1809              :         guchar cls_type;
    1810              :         Atlv *wrap;
    1811              : 
    1812              :         /* Now wrap in explicit tag if that's the case */
    1813         1344 :         if (anode_calc_explicit_for_flags (node, flags, &cls_type)) {
    1814           53 :                 wrap = atlv_new ();
    1815           53 :                 wrap->cls = (ASN1_CLASS_STRUCTURED | cls_type);
    1816           53 :                 wrap->tag = anode_calc_tag (node);
    1817           53 :                 wrap->len = tlv->off + tlv->len;
    1818           53 :                 wrap->off = atlv_unparse_cls_tag_len (NULL, 0, wrap->cls, wrap->tag, wrap->len);
    1819           53 :                 wrap->child = tlv;
    1820           53 :                 tlv = wrap;
    1821              :         }
    1822              : 
    1823         1344 :         return tlv;
    1824              : }
    1825              : 
    1826              : static Atlv *
    1827         1884 : anode_build_anything_for_flags (GNode *node,
    1828              :                                 gboolean want,
    1829              :                                 gint flags)
    1830              : {
    1831              :         Atlv *tlv;
    1832              : 
    1833         1884 :         switch (anode_def_type (node)) {
    1834          194 :         case EGG_ASN1X_BIT_STRING:
    1835          194 :                 tlv = anode_build_bit_string (node);
    1836          194 :                 break;
    1837          162 :         case EGG_ASN1X_INTEGER:
    1838          162 :                 tlv = anode_build_integer (node);
    1839          162 :                 break;
    1840          418 :         case EGG_ASN1X_BOOLEAN:
    1841              :         case EGG_ASN1X_OCTET_STRING:
    1842              :         case EGG_ASN1X_OBJECT_ID:
    1843              :         case EGG_ASN1X_TIME:
    1844              :         case EGG_ASN1X_UTC_TIME:
    1845              :         case EGG_ASN1X_GENERALIZED_TIME:
    1846              :         case EGG_ASN1X_ENUMERATED:
    1847              :         case EGG_ASN1X_GENERAL_STRING:
    1848              :         case EGG_ASN1X_NUMERIC_STRING:
    1849              :         case EGG_ASN1X_IA5_STRING:
    1850              :         case EGG_ASN1X_TELETEX_STRING:
    1851              :         case EGG_ASN1X_PRINTABLE_STRING:
    1852              :         case EGG_ASN1X_UNIVERSAL_STRING:
    1853              :         case EGG_ASN1X_BMP_STRING:
    1854              :         case EGG_ASN1X_UTF8_STRING:
    1855              :         case EGG_ASN1X_VISIBLE_STRING:
    1856              :         case EGG_ASN1X_NULL:
    1857          418 :                 tlv = anode_build_value (node);
    1858          418 :                 break;
    1859              : 
    1860              :         /* Any should already have explicit tagging, so just return */
    1861          374 :         case EGG_ASN1X_ANY:
    1862          374 :                 return anode_build_any (node);
    1863              : 
    1864          688 :         case EGG_ASN1X_SEQUENCE:
    1865              :         case EGG_ASN1X_SEQUENCE_OF:
    1866              :         case EGG_ASN1X_SET:
    1867              :         case EGG_ASN1X_SET_OF:
    1868          688 :                 tlv = anode_build_structured (node, want);
    1869          688 :                 break;
    1870              : 
    1871           48 :         case EGG_ASN1X_CHOICE:
    1872           48 :                 tlv = anode_build_choice (node, want);
    1873           48 :                 break;
    1874              : 
    1875            0 :         default:
    1876            0 :                 g_assert_not_reached ();
    1877              :         }
    1878              : 
    1879         1510 :         if (tlv == NULL)
    1880          211 :                 return NULL;
    1881              : 
    1882              :         /* Now wrap in explicit tag if that's the case */
    1883         1299 :         return anode_build_maybe_explicit (node, tlv, flags);
    1884              : }
    1885              : 
    1886              : static Atlv *
    1887         1884 : anode_build_anything (GNode *node,
    1888              :                       gboolean want)
    1889              : {
    1890         1884 :         return anode_build_anything_for_flags (node, want,
    1891              :                                                anode_def_flags (node));
    1892              : }
    1893              : 
    1894              : GBytes *
    1895          290 : egg_asn1x_encode (GNode *asn,
    1896              :                   EggAllocator allocator)
    1897              : {
    1898              :         GBytes *bytes;
    1899              :         Atlv *tlv;
    1900              : 
    1901          290 :         g_return_val_if_fail (asn != NULL, NULL);
    1902          290 :         g_return_val_if_fail (anode_def_type_is_real (asn), NULL);
    1903              : 
    1904          290 :         if (!egg_asn1x_validate (asn, TRUE))
    1905            1 :                 return NULL;
    1906              : 
    1907          289 :         tlv = anode_build_anything (asn, TRUE);
    1908              : 
    1909              :         /* The above validate should cause build not to return NULL */
    1910          289 :         g_return_val_if_fail (tlv != NULL, NULL);
    1911              : 
    1912          289 :         atlv_sort_perform (tlv, allocator);
    1913              : 
    1914          289 :         bytes = atlv_unparse_to_bytes (tlv, allocator);
    1915          289 :         atlv_free (tlv);
    1916          289 :         return bytes;
    1917              : }
    1918              : 
    1919              : /* ----------------------------------------------------------------------------
    1920              :  * VALUE READ/WRITE
    1921              :  */
    1922              : 
    1923              : static int
    1924          524 : two_to_four_digit_year (int year)
    1925              : {
    1926              :         time_t now;
    1927              :         struct tm tm;
    1928              :         int century, current;
    1929              : 
    1930          524 :         g_return_val_if_fail (year >= 0 && year <= 99, -1);
    1931              : 
    1932              :         /* Get the current year */
    1933          524 :         now = time (NULL);
    1934          524 :         g_return_val_if_fail (now >= 0, -1);
    1935          524 :         if (!gmtime_r (&now, &tm))
    1936            0 :                 g_return_val_if_reached (-1);
    1937              : 
    1938          524 :         current = (tm.tm_year % 100);
    1939          524 :         century = (tm.tm_year + 1900) - current;
    1940              : 
    1941              :         /*
    1942              :          * Check if it's within 40 years before the
    1943              :          * current date.
    1944              :          */
    1945          524 :         if (current < 40) {
    1946          524 :                 if (year < current)
    1947          314 :                         return century + year;
    1948          210 :                 if (year > 100 - (40 - current))
    1949          140 :                         return (century - 100) + year;
    1950              :         } else {
    1951            0 :                 if (year < current && year > (current - 40))
    1952            0 :                         return century + year;
    1953              :         }
    1954              : 
    1955              :         /*
    1956              :          * If it's after then adjust for overflows to
    1957              :          * the next century.
    1958              :          */
    1959           70 :         if (year < current)
    1960            0 :                 return century + 100 + year;
    1961              :         else
    1962           70 :                 return century + year;
    1963              : }
    1964              : 
    1965              : static gboolean
    1966          525 : parse_utc_time (const gchar *time, gsize n_time,
    1967              :                 struct tm* when, gint *offset)
    1968              : {
    1969              :         const char *p, *e;
    1970              :         int year;
    1971              : 
    1972          525 :         g_assert (when);
    1973          525 :         g_assert (time);
    1974          525 :         g_assert (offset);
    1975              : 
    1976              :         /* YYMMDDhhmmss.ffff Z | +0000 */
    1977          525 :         if (n_time < 6 || n_time >= 28)
    1978            1 :                 return FALSE;
    1979              : 
    1980              :         /* Reset everything to default legal values */
    1981          524 :         memset (when, 0, sizeof (*when));
    1982          524 :         *offset = 0;
    1983          524 :         when->tm_mday = 1;
    1984              : 
    1985              :         /* Select the digits part of it */
    1986          524 :         p = time;
    1987         6800 :         for (e = p; *e >= '0' && *e <= '9'; ++e);
    1988              : 
    1989          524 :         if (p + 2 <= e) {
    1990          524 :                 year = atoin (p, 2);
    1991          524 :                 p += 2;
    1992              : 
    1993              :                 /*
    1994              :                  * 40 years in the past is our century. 60 years
    1995              :                  * in the future is the next century.
    1996              :                  */
    1997          524 :                 when->tm_year = two_to_four_digit_year (year) - 1900;
    1998              :         }
    1999          524 :         if (p + 2 <= e) {
    2000          524 :                 when->tm_mon = atoin (p, 2) - 1;
    2001          524 :                 p += 2;
    2002              :         }
    2003          524 :         if (p + 2 <= e) {
    2004          524 :                 when->tm_mday = atoin (p, 2);
    2005          524 :                 p += 2;
    2006              :         }
    2007          524 :         if (p + 2 <= e) {
    2008          522 :                 when->tm_hour = atoin (p, 2);
    2009          522 :                 p += 2;
    2010              :         }
    2011          524 :         if (p + 2 <= e) {
    2012          522 :                 when->tm_min = atoin (p, 2);
    2013          522 :                 p += 2;
    2014              :         }
    2015          524 :         if (p + 2 <= e) {
    2016          522 :                 when->tm_sec = atoin (p, 2);
    2017          522 :                 p += 2;
    2018              :         }
    2019              : 
    2020          524 :         if (when->tm_year < 0 || when->tm_year > 9999 ||
    2021          524 :             when->tm_mon < 0 || when->tm_mon > 11 ||
    2022          524 :             when->tm_mday < 1 || when->tm_mday > 31 ||
    2023          524 :             when->tm_hour < 0 || when->tm_hour > 23 ||
    2024          524 :             when->tm_min < 0 || when->tm_min > 59 ||
    2025          524 :             when->tm_sec < 0 || when->tm_sec > 59)
    2026            0 :                 return FALSE;
    2027              : 
    2028              :         /* Make sure all that got parsed */
    2029          524 :         if (p != e)
    2030            0 :                 return FALSE;
    2031              : 
    2032              :         /* Now the remaining optional stuff */
    2033          524 :         e = time + n_time;
    2034              : 
    2035              :         /* See if there's a fraction, and discard it if so */
    2036          524 :         if (p < e && *p == '.' && p + 5 <= e)
    2037            1 :                 p += 5;
    2038              : 
    2039              :         /* See if it's UTC */
    2040          524 :         if (p < e && *p == 'Z') {
    2041          520 :                 p += 1;
    2042              : 
    2043              :         /* See if it has a timezone */
    2044            4 :         } else if ((*p == '-' || *p == '+') && p + 3 <= e) {
    2045              :                 int off, neg;
    2046              : 
    2047            4 :                 neg = *p == '-';
    2048            4 :                 ++p;
    2049              : 
    2050            4 :                 off = atoin (p, 2) * 3600;
    2051            4 :                 if (off < 0 || off > 86400)
    2052            0 :                         return -1;
    2053            4 :                 p += 2;
    2054              : 
    2055            4 :                 if (p + 2 <= e) {
    2056            4 :                         off += atoin (p, 2) * 60;
    2057            4 :                         p += 2;
    2058              :                 }
    2059              : 
    2060              :                 /* Use TZ offset */
    2061            4 :                 if (neg)
    2062            1 :                         *offset = 0 - off;
    2063              :                 else
    2064            3 :                         *offset = off;
    2065              :         }
    2066              : 
    2067              :         /* Make sure everything got parsed */
    2068          524 :         if (p != e)
    2069            0 :                 return FALSE;
    2070              : 
    2071          524 :         return TRUE;
    2072              : }
    2073              : 
    2074              : static gboolean
    2075           10 : parse_general_time (const gchar *time, gsize n_time,
    2076              :                     struct tm* when, gint *offset)
    2077              : {
    2078              :         const char *p, *e;
    2079              : 
    2080           10 :         g_assert (time);
    2081           10 :         g_assert (when);
    2082           10 :         g_assert (offset);
    2083              : 
    2084              :         /* YYYYMMDDhhmmss.ffff Z | +0000 */
    2085           10 :         if (n_time < 8 || n_time >= 30)
    2086            1 :                 return FALSE;
    2087              : 
    2088              :         /* Reset everything to default legal values */
    2089            9 :         memset (when, 0, sizeof (*when));
    2090            9 :         *offset = 0;
    2091            9 :         when->tm_mday = 1;
    2092              : 
    2093              :         /* Select the digits part of it */
    2094            9 :         p = time;
    2095          123 :         for (e = p; *e >= '0' && *e <= '9'; ++e);
    2096              : 
    2097            9 :         if (p + 4 <= e) {
    2098            9 :                 when->tm_year = atoin (p, 4) - 1900;
    2099            9 :                 p += 4;
    2100              :         }
    2101            9 :         if (p + 2 <= e) {
    2102            9 :                 when->tm_mon = atoin (p, 2) - 1;
    2103            9 :                 p += 2;
    2104              :         }
    2105            9 :         if (p + 2 <= e) {
    2106            9 :                 when->tm_mday = atoin (p, 2);
    2107            9 :                 p += 2;
    2108              :         }
    2109            9 :         if (p + 2 <= e) {
    2110            7 :                 when->tm_hour = atoin (p, 2);
    2111            7 :                 p += 2;
    2112              :         }
    2113            9 :         if (p + 2 <= e) {
    2114            7 :                 when->tm_min = atoin (p, 2);
    2115            7 :                 p += 2;
    2116              :         }
    2117            9 :         if (p + 2 <= e) {
    2118            7 :                 when->tm_sec = atoin (p, 2);
    2119            7 :                 p += 2;
    2120              :         }
    2121              : 
    2122            9 :         if (when->tm_year < 0 || when->tm_year > 9999 ||
    2123            9 :             when->tm_mon < 0 || when->tm_mon > 11 ||
    2124            9 :             when->tm_mday < 1 || when->tm_mday > 31 ||
    2125            9 :             when->tm_hour < 0 || when->tm_hour > 23 ||
    2126            9 :             when->tm_min < 0 || when->tm_min > 59 ||
    2127            9 :             when->tm_sec < 0 || when->tm_sec > 59)
    2128            0 :                 return FALSE;
    2129              : 
    2130              :         /* Make sure all that got parsed */
    2131            9 :         if (p != e)
    2132            0 :                 return FALSE;
    2133              : 
    2134              :         /* Now the remaining optional stuff */
    2135            9 :         e = time + n_time;
    2136              : 
    2137              :         /* See if there's a fraction, and discard it if so */
    2138            9 :         if (p < e && *p == '.' && p + 5 <= e)
    2139            1 :                 p += 5;
    2140              : 
    2141              :         /* See if it's UTC */
    2142            9 :         if (p < e && *p == 'Z') {
    2143            5 :                 p += 1;
    2144              : 
    2145              :         /* See if it has a timezone */
    2146            4 :         } else if ((*p == '-' || *p == '+') && p + 3 <= e) {
    2147              :                 int off, neg;
    2148              : 
    2149            4 :                 neg = *p == '-';
    2150            4 :                 ++p;
    2151              : 
    2152            4 :                 off = atoin (p, 2) * 3600;
    2153            4 :                 if (off < 0 || off > 86400)
    2154            0 :                         return -1;
    2155            4 :                 p += 2;
    2156              : 
    2157            4 :                 if (p + 2 <= e) {
    2158            4 :                         off += atoin (p, 2) * 60;
    2159            4 :                         p += 2;
    2160              :                 }
    2161              : 
    2162              :                 /* Use TZ offset */
    2163            4 :                 if (neg)
    2164            1 :                         *offset = 0 - off;
    2165              :                 else
    2166            3 :                         *offset = off;
    2167              :         }
    2168              : 
    2169              :         /* Make sure everything got parsed */
    2170            9 :         if (p != e)
    2171            0 :                 return FALSE;
    2172              : 
    2173            9 :         return TRUE;
    2174              : }
    2175              : 
    2176              : static gboolean
    2177          516 : anode_read_time (GNode *node,
    2178              :                  GBytes *data,
    2179              :                  struct tm *when,
    2180              :                  glong *value)
    2181              : {
    2182              :         const gchar *buf;
    2183              :         gboolean ret;
    2184          516 :         gint offset = 0;
    2185              :         gint flags;
    2186              :         gint type;
    2187              :         gsize len;
    2188              : 
    2189          516 :         g_assert (data != NULL);
    2190          516 :         g_assert (when != NULL);
    2191          516 :         g_assert (value != NULL);
    2192              : 
    2193          516 :         flags = anode_def_flags (node);
    2194          516 :         type = anode_def_type (node);
    2195          516 :         buf = g_bytes_get_data (data, &len);
    2196              : 
    2197          516 :         if (type == EGG_ASN1X_GENERALIZED_TIME)
    2198            0 :                 ret = parse_general_time (buf, len, when, &offset);
    2199          516 :         else if (type == EGG_ASN1X_UTC_TIME)
    2200            0 :                 ret = parse_utc_time (buf, len, when, &offset);
    2201          516 :         else if (flags & FLAG_GENERALIZED)
    2202            2 :                 ret = parse_general_time (buf, len, when, &offset);
    2203          514 :         else if (flags & FLAG_UTC)
    2204          514 :                 ret = parse_utc_time (buf, len, when, &offset);
    2205              :         else
    2206            0 :                 g_return_val_if_reached (FALSE);
    2207              : 
    2208          516 :         if (!ret)
    2209            0 :                 return anode_failure (node, "invalid time content");
    2210              : 
    2211              :         /* In order to work with 32 bit time_t. */
    2212              :         if (sizeof (time_t) <= 4 && when->tm_year >= 2038) {
    2213              :                 *value = (time_t)2145914603;  /* 2037-12-31 23:23:23 */
    2214              : 
    2215              :         /* Convert to seconds since epoch */
    2216              :         } else {
    2217          516 :                 *value = timegm (when);
    2218          516 :                 g_return_val_if_fail (*value >= 0, FALSE);
    2219          516 :                 *value += offset;
    2220              :         }
    2221              : 
    2222          516 :         return TRUE;
    2223              : }
    2224              : 
    2225              : static gboolean
    2226          399 : anode_read_integer_ulong (GNode *node,
    2227              :                           GBytes *data,
    2228              :                           gulong *value)
    2229              : {
    2230              :         const guchar *p;
    2231              :         gsize len;
    2232              :         gsize k;
    2233              : 
    2234          399 :         p = g_bytes_get_data (data, &len);
    2235          399 :         if (len < 1 || len > sizeof (gulong))
    2236            1 :                 return FALSE;
    2237              : 
    2238          398 :         *value = 0;
    2239          821 :         for (k = 0; k < len; ++k)
    2240          423 :                 *value |= p[k] << (8 * ((len - 1) - k));
    2241              : 
    2242          398 :         return TRUE;
    2243              : }
    2244              : 
    2245              : static void
    2246           48 : anode_write_integer_ulong (gulong value,
    2247              :                            guchar *data,
    2248              :                            gsize *n_data)
    2249              : {
    2250              :         guchar buf[sizeof (gulong)];
    2251              :         gint bytes, i, off;
    2252              :         guchar *at;
    2253              :         gboolean sign;
    2254              :         gsize len;
    2255              : 
    2256          432 :         for (i = 0; i < sizeof (gulong); ++i) {
    2257          384 :                 off = sizeof (gulong) - (i + 1);
    2258          384 :                 buf[i] = (value >> (off * 8)) & 0xFF;
    2259              :         }
    2260              : 
    2261           92 :         for (bytes = sizeof (gulong) - 1; bytes >= 0; --bytes)
    2262           92 :                 if (!buf[bytes])
    2263           48 :                         break;
    2264              : 
    2265           48 :         bytes = sizeof (gulong) - (bytes + 1);
    2266           48 :         if (bytes == 0)
    2267           18 :                 bytes = 1;
    2268              : 
    2269              :         /* If the first byte would make this negative, then add a zero */
    2270           48 :         at = buf + (sizeof (gulong) - bytes);
    2271           48 :         sign = !!(at[0] & 0x80);
    2272           48 :         len = bytes + (sign ? 1 : 0);
    2273              : 
    2274           48 :         if (data) {
    2275           45 :                 g_assert (*n_data >= len);
    2276           45 :                 if (sign) {
    2277            1 :                         data[0] = 0;
    2278            1 :                         data++;
    2279              :                 }
    2280           45 :                 memcpy (data, at, bytes);
    2281              :         }
    2282              : 
    2283           48 :         *n_data = len;
    2284           48 : }
    2285              : 
    2286              : static GBytes *
    2287           42 : anode_default_integer (GNode *node)
    2288              : {
    2289              :         const gchar *defval;
    2290              :         EggAsn1xDef *opt;
    2291              :         gchar *end;
    2292              :         gulong value;
    2293              :         guchar *data;
    2294              :         gsize len;
    2295              : 
    2296           42 :         if (!(anode_def_flags (node) & FLAG_DEFAULT))
    2297           39 :                 return NULL;
    2298              : 
    2299              :         /* Try to get a default */
    2300            3 :         opt = anode_opt_lookup (node, EGG_ASN1X_DEFAULT, NULL);
    2301            3 :         g_return_val_if_fail (opt != NULL, NULL);
    2302            3 :         g_return_val_if_fail (opt->value != NULL, NULL);
    2303            3 :         defval = opt->value;
    2304              : 
    2305            3 :         opt = anode_opt_lookup (node, EGG_ASN1X_CONSTANT, defval);
    2306            3 :         if (opt != NULL) {
    2307            1 :                 g_return_val_if_fail (opt->value != NULL, NULL);
    2308            1 :                 defval = opt->value;
    2309              :         }
    2310              : 
    2311              :         /* Parse out the default value */
    2312            3 :         value = strtoul (defval, &end, 10);
    2313            3 :         g_return_val_if_fail (end && !end[0], NULL);
    2314              : 
    2315            3 :         anode_write_integer_ulong (value, NULL, &len);
    2316            3 :         data = g_malloc (len);
    2317            3 :         anode_write_integer_ulong (value, data, &len);
    2318            3 :         return g_bytes_new_take (data, len);
    2319              : }
    2320              : 
    2321              : static gboolean
    2322            3 : anode_read_string_struct (GNode *node,
    2323              :                           Atlv *tlv,
    2324              :                           gpointer value,
    2325              :                           gsize *n_value)
    2326              : {
    2327              :         const guchar *buf;
    2328              :         gsize len;
    2329              :         Atlv *ctlv;
    2330              :         guchar *at;
    2331              :         gint remaining;
    2332              : 
    2333            3 :         g_assert (tlv != NULL);
    2334            3 :         g_assert (tlv->cls & ASN1_CLASS_STRUCTURED);
    2335            3 :         g_assert (n_value != NULL);
    2336              : 
    2337            3 :         at = value;
    2338            3 :         remaining = *n_value;
    2339            3 :         *n_value = 0;
    2340              : 
    2341            7 :         for (ctlv = tlv->child; ctlv != NULL; ctlv = ctlv->next) {
    2342            5 :                 if (ctlv->cls & ASN1_CLASS_STRUCTURED ||
    2343            4 :                     ctlv->value == NULL)
    2344            1 :                         return FALSE;
    2345            4 :                 buf = g_bytes_get_data (ctlv->value, &len);
    2346            4 :                 *n_value += len;
    2347            4 :                 if (value) {
    2348            2 :                         if (remaining >= len)
    2349            2 :                                 memcpy (at, buf, len);
    2350            2 :                         at += len;
    2351            2 :                         remaining -= len;
    2352              :                 }
    2353              :         }
    2354              : 
    2355            2 :         if (value)
    2356            1 :                 g_return_val_if_fail (remaining >= 0, FALSE);
    2357              : 
    2358            2 :         return TRUE;
    2359              : }
    2360              : 
    2361              : static gboolean
    2362         1344 : anode_read_string_simple (GNode *node,
    2363              :                           GBytes *data,
    2364              :                           gpointer value,
    2365              :                           gsize *n_value)
    2366              : {
    2367              :         const guchar *buf;
    2368              :         gsize len;
    2369              : 
    2370         1344 :         g_assert (data != NULL);
    2371         1344 :         g_assert (n_value != NULL);
    2372              : 
    2373         1344 :         buf = g_bytes_get_data (data, &len);
    2374         1344 :         if (value) {
    2375          115 :                 g_return_val_if_fail (*n_value >= len, FALSE);
    2376          115 :                 memcpy (value, buf, len);
    2377              :         }
    2378              : 
    2379         1344 :         *n_value = len;
    2380         1344 :         return TRUE;
    2381              : }
    2382              : 
    2383              : static gboolean
    2384            6 : anode_read_boolean (GNode *node,
    2385              :                     GBytes *data,
    2386              :                     gboolean *value)
    2387              : {
    2388              :         const guchar *buf;
    2389              :         gsize len;
    2390              : 
    2391            6 :         g_assert (node != NULL);
    2392            6 :         g_assert (data != NULL);
    2393            6 :         g_assert (value != NULL);
    2394              : 
    2395            6 :         buf = g_bytes_get_data (data, &len);
    2396            6 :         g_return_val_if_fail (len == 1, FALSE);
    2397            6 :         if (buf[0] == 0x00)
    2398            3 :                 *value = FALSE;
    2399            3 :         else if (buf[0] == 0xFF)
    2400            3 :                 *value = TRUE;
    2401              :         else
    2402            0 :                 g_return_val_if_reached (FALSE);
    2403            6 :         return TRUE;
    2404              : }
    2405              : 
    2406              : static void
    2407           16 : anode_write_boolean (gboolean value,
    2408              :                      guchar *data,
    2409              :                      gsize *n_data)
    2410              : {
    2411           16 :         if (data) {
    2412           11 :                 g_assert (*n_data >= 1);
    2413           11 :                 if (value)
    2414            5 :                         data[0] = 0xFF;
    2415              :                 else
    2416            6 :                         data[0] = 0x00;
    2417              :         }
    2418           16 :         *n_data = 1;
    2419           16 : }
    2420              : 
    2421              : static GBytes *
    2422           10 : anode_default_boolean (GNode *node)
    2423              : {
    2424              :         EggAsn1xDef *opt;
    2425              :         gboolean value;
    2426              :         guchar *data;
    2427              :         gsize len;
    2428              : 
    2429           10 :         if (!(anode_def_flags (node) & FLAG_DEFAULT))
    2430            5 :                 return NULL;
    2431              : 
    2432              :         /* Try to get a default */
    2433            5 :         opt = anode_opt_lookup (node, EGG_ASN1X_DEFAULT, NULL);
    2434            5 :         g_return_val_if_fail (opt != NULL, NULL);
    2435              : 
    2436              :         /* Parse out the default value */
    2437            5 :         if ((opt->type & FLAG_TRUE) == FLAG_TRUE)
    2438            1 :                 value = TRUE;
    2439            4 :         else if ((opt->type & FLAG_FALSE) == FLAG_FALSE)
    2440            4 :                 value = FALSE;
    2441              :         else
    2442            0 :                 g_return_val_if_reached (FALSE);
    2443              : 
    2444            5 :         anode_write_boolean (value, NULL, &len);
    2445            5 :         data = g_malloc (len);
    2446            5 :         anode_write_boolean (value, data, &len);
    2447            5 :         return g_bytes_new_take (data, len);
    2448              : }
    2449              : 
    2450              : static gboolean
    2451         5413 : anode_read_object_id (GNode *node,
    2452              :                       GBytes *data,
    2453              :                       gchar **oid)
    2454              : {
    2455         5413 :         GString *result = NULL;
    2456              :         const guchar *p;
    2457              :         gboolean lead;
    2458              :         guint val, pval;
    2459              :         gsize len;
    2460              :         gint k;
    2461              : 
    2462         5413 :         g_assert (data != NULL);
    2463         5413 :         p = g_bytes_get_data (data, &len);
    2464              : 
    2465         5413 :         if (oid)
    2466          337 :                 result = g_string_sized_new (32);
    2467              : 
    2468         5413 :         pval = p[0] / 40;
    2469         5413 :         val = p[0] - pval * 40;
    2470              : 
    2471         5413 :         if (result)
    2472          337 :                 g_string_append_printf (result, "%u.%u", pval, val);
    2473              : 
    2474              :         /* TODO: Validate first byte? */
    2475        28036 :         for (k = 1, lead = 1, val = 0, pval = 0; k < len; ++k) {
    2476              :                 /* X.690: the leading byte must never be 0x80 */
    2477        22624 :                 if (lead && p[k] == 0x80) {
    2478            1 :                         anode_failure (node, "object id encoding is invalid");
    2479            1 :                         break;
    2480              :                 }
    2481        22623 :                 val = val << 7;
    2482        22623 :                 val |= p[k] & 0x7F;
    2483              :                 /* Check for wrap around */
    2484        22623 :                 if (val < pval) {
    2485            0 :                         anode_failure (node, "object id encoding is invalid");
    2486            0 :                         break;
    2487              :                 }
    2488        22623 :                 pval = val;
    2489        22623 :                 if (!(p[k] & 0x80)) {
    2490        16869 :                         if (result)
    2491         1469 :                                 g_string_append_printf (result, ".%u", val);
    2492        16869 :                         pval = val = 0;
    2493        16869 :                         lead = 1;
    2494              :                 }
    2495              :         }
    2496              : 
    2497         5413 :         if (k < len) {
    2498            1 :                 if (result)
    2499            0 :                         g_string_free (result, TRUE); /* UNREACHABLE: caught by validation */
    2500            1 :                 return FALSE;
    2501              :         }
    2502              : 
    2503         5412 :         if (result)
    2504          337 :                 *oid = g_string_free (result, FALSE);
    2505         5412 :         return TRUE;
    2506              : }
    2507              : 
    2508              : static gboolean
    2509           30 : anode_write_object_id (const gchar *oid,
    2510              :                        guchar *data,
    2511              :                        gsize *n_data)
    2512              : {
    2513              :         const gchar *p, *next;
    2514              :         gint num, num1;
    2515              :         guchar bit7;
    2516              :         gboolean had;
    2517              :         gint i, k, at;
    2518              : 
    2519           30 :         at = 0;
    2520           30 :         num1 = 0;
    2521              : 
    2522          207 :         for (i = 0; oid[0]; ++i, oid = next) {
    2523          178 :                 p = strchr (oid, '.');
    2524          178 :                 if (p == NULL)
    2525           30 :                         next = p = oid + strlen (oid);
    2526              :                 else
    2527          148 :                         next = p + 1;
    2528          178 :                 if (p == oid)
    2529            0 :                         return FALSE;
    2530          178 :                 num = atoin (oid, p - oid);
    2531          178 :                 if (num < 0)
    2532            1 :                         return FALSE;
    2533          177 :                 if (i == 0) {
    2534           29 :                         num1 = num;
    2535          148 :                 } else if (i == 1) {
    2536           29 :                         if (data) {
    2537           29 :                                 g_assert (*n_data > at);
    2538           29 :                                 data[at] = 40 * num1 + num;
    2539              :                         }
    2540           29 :                         ++at;
    2541              :                 } else {
    2542          714 :                         for (had = FALSE, k = 4; k >= 0; k--) {
    2543          595 :                                 bit7 = (num >> (k * 7)) & 0x7F;
    2544          595 :                                 if (bit7 || had || !k) {
    2545          173 :                                         if (k)
    2546           54 :                                                 bit7 |= 0x80;
    2547          173 :                                         if (data) {
    2548          173 :                                                 g_assert (*n_data > at);
    2549          173 :                                                 data[at] = bit7;
    2550              :                                         }
    2551          173 :                                         ++at;
    2552          173 :                                         had = 1;
    2553              :                                 }
    2554              :                         }
    2555              :                 }
    2556              :         }
    2557              : 
    2558           29 :         if (at < 2)
    2559            0 :                 return FALSE;
    2560           29 :         if (data)
    2561           29 :                 g_assert (*n_data >= at);
    2562           29 :         *n_data = at;
    2563           29 :         return TRUE;
    2564              : }
    2565              : 
    2566              : /* -----------------------------------------------------------------------------------
    2567              :  * GETTING, SETTING
    2568              :  */
    2569              : 
    2570              : GNode*
    2571         2004 : egg_asn1x_node (GNode *asn, ...)
    2572              : {
    2573         2004 :         GNode *node = asn;
    2574              :         const gchar *name;
    2575              :         va_list va;
    2576              :         gint type;
    2577              :         gint index;
    2578              : 
    2579         2004 :         g_return_val_if_fail (asn, NULL);
    2580         2004 :         va_start (va, asn);
    2581              : 
    2582              :         for (;;) {
    2583         4913 :                 type = anode_def_type (node);
    2584              : 
    2585              :                 /* Use integer indexes for these */
    2586         4913 :                 if (type == EGG_ASN1X_SEQUENCE_OF || type == EGG_ASN1X_SET_OF) {
    2587          335 :                         index = va_arg (va, gint);
    2588          335 :                         if (index == 0)
    2589           29 :                                 return node;
    2590              : 
    2591              :                         /* Only consider nodes that have data */
    2592          306 :                         node = g_node_nth_child (node, 0);
    2593          744 :                         while (node) {
    2594          682 :                                 if (egg_asn1x_have (node)) {
    2595          682 :                                         --index;
    2596          682 :                                         if (index == 0)
    2597          244 :                                                 break;
    2598              :                                 }
    2599          438 :                                 node = g_node_next_sibling (node);
    2600              :                         }
    2601              : 
    2602          306 :                         if (node == NULL)
    2603           62 :                                 return NULL;
    2604              : 
    2605              :                 /* Use strings for these */
    2606              :                 } else {
    2607         4578 :                         name = va_arg (va, const gchar*);
    2608         4578 :                         if (name == NULL)
    2609         1913 :                                 return node;
    2610              :                         /* Warn if they're using indexes here */
    2611         2665 :                         if (name <= (const gchar*)4096) {
    2612            0 :                                 g_warning ("possible misuse of egg_asn1x_node, expected a string, but got an index");
    2613            0 :                                 return NULL;
    2614              :                         }
    2615         2665 :                         node = anode_child_with_name (node, name);
    2616         2665 :                         if (node == NULL)
    2617            0 :                                 return NULL;
    2618              :                 }
    2619              :         }
    2620              : }
    2621              : 
    2622              : const gchar*
    2623            4 : egg_asn1x_name (GNode *node)
    2624              : {
    2625            4 :         g_return_val_if_fail (node != NULL, NULL);
    2626            4 :         return anode_def_name (node);
    2627              : }
    2628              : 
    2629              : EggAsn1xType
    2630          278 : egg_asn1x_type (GNode *node)
    2631              : {
    2632          278 :         g_return_val_if_fail (node != NULL, 0);
    2633          278 :         return anode_def_type (node);
    2634              : }
    2635              : 
    2636              : guint
    2637           18 : egg_asn1x_count (GNode *node)
    2638              : {
    2639           18 :         guint result = 0;
    2640              :         GNode *child;
    2641              :         gint type;
    2642              : 
    2643           18 :         g_return_val_if_fail (node, 0);
    2644              : 
    2645           18 :         type = anode_def_type (node);
    2646           18 :         if (type != EGG_ASN1X_SEQUENCE_OF && type != EGG_ASN1X_SET_OF) {
    2647            0 :                 g_warning ("node passed to egg_asn1x_count was not a sequence of or set of");
    2648            0 :                 return 0;
    2649              :         }
    2650              : 
    2651           46 :         for (child = node->children; child; child = child->next) {
    2652           28 :                 if (egg_asn1x_have (child))
    2653           24 :                         ++result;
    2654              :         }
    2655              : 
    2656           18 :         return result;
    2657              : }
    2658              : 
    2659              : GNode*
    2660           24 : egg_asn1x_append (GNode *node)
    2661              : {
    2662              :         GNode *child;
    2663              :         gint type;
    2664              : 
    2665           24 :         g_return_val_if_fail (node, NULL);
    2666              : 
    2667           24 :         type = anode_def_type (node);
    2668           24 :         if (type != EGG_ASN1X_SEQUENCE_OF && type != EGG_ASN1X_SET_OF) {
    2669            0 :                 g_warning ("node passed to egg_asn1x_append was not a sequence of or set of");
    2670            0 :                 return NULL;
    2671              :         }
    2672              : 
    2673              :         /* There must be at least one child */
    2674           24 :         child = node->children;
    2675           24 :         g_return_val_if_fail (child, NULL);
    2676              : 
    2677           24 :         child = anode_clone (child);
    2678           24 :         anode_clear (child);
    2679           24 :         g_node_append (node, child);
    2680              : 
    2681           24 :         return child;
    2682              : }
    2683              : 
    2684              : gboolean
    2685         8158 : egg_asn1x_have (GNode *node)
    2686              : {
    2687              :         GNode *child;
    2688              : 
    2689         8158 :         g_return_val_if_fail (node, FALSE);
    2690              : 
    2691         8158 :         if (anode_get_value (node) || anode_get_parsed (node))
    2692         7524 :                 return TRUE;
    2693              : 
    2694         1062 :         for (child = node->children; child != NULL; child = child->next) {
    2695          452 :                 if (egg_asn1x_have (child))
    2696           24 :                         return TRUE;
    2697              :         }
    2698              : 
    2699          610 :         return FALSE;
    2700              : }
    2701              : 
    2702              : gboolean
    2703            8 : egg_asn1x_get_boolean (GNode *node,
    2704              :                        gboolean *value)
    2705              : {
    2706              :         gboolean ret;
    2707              :         GBytes *data;
    2708              : 
    2709            8 :         g_return_val_if_fail (node != NULL, FALSE);
    2710            8 :         g_return_val_if_fail (value != NULL, FALSE);
    2711            8 :         g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_BOOLEAN, FALSE);
    2712              : 
    2713            8 :         data = anode_get_value (node);
    2714            8 :         if (data == NULL)
    2715            4 :                 data = anode_default_boolean (node);
    2716              :         else
    2717            4 :                 g_bytes_ref (data);
    2718            8 :         if (data == NULL)
    2719            2 :                 return FALSE;
    2720              : 
    2721            6 :         ret = anode_read_boolean (node, data, value);
    2722            6 :         g_bytes_unref (data);
    2723            6 :         return ret;
    2724              : }
    2725              : 
    2726              : void
    2727            6 : egg_asn1x_set_boolean (GNode *node, gboolean value)
    2728              : {
    2729              :         GBytes *data, *def;
    2730              :         guchar *buf;
    2731              :         gsize len;
    2732              : 
    2733            6 :         g_return_if_fail (node != NULL);
    2734            6 :         g_return_if_fail (anode_def_type (node) == EGG_ASN1X_BOOLEAN);
    2735              : 
    2736            6 :         len = 1;
    2737            6 :         buf = g_malloc0 (1);
    2738            6 :         anode_write_boolean (value, buf, &len);
    2739            6 :         data = g_bytes_new_take (buf, len);
    2740              : 
    2741              :         /* If it's equal to default, then clear */
    2742            6 :         def = anode_default_boolean (node);
    2743            6 :         if (def) {
    2744            3 :                 if (g_bytes_equal (def, data)) {
    2745            2 :                         anode_clr_value (node);
    2746            2 :                         g_bytes_unref (data);
    2747            2 :                         data = NULL;
    2748              :                 }
    2749            3 :                 g_bytes_unref (def);
    2750              :         }
    2751              : 
    2752            6 :         if (data != NULL)
    2753            4 :                 anode_take_value (node, data);
    2754              : }
    2755              : 
    2756              : void
    2757            1 : egg_asn1x_set_null (GNode *node)
    2758              : {
    2759            1 :         g_return_if_fail (node != NULL);
    2760            1 :         g_return_if_fail (anode_def_type (node) == EGG_ASN1X_NULL);
    2761              : 
    2762              :         /* Encode zero characters */
    2763            1 :         anode_clr_value (node);
    2764            1 :         anode_take_value (node, g_bytes_new_static ("", 0));
    2765              : }
    2766              : 
    2767              : GQuark
    2768           15 : egg_asn1x_get_enumerated (GNode *node)
    2769              : {
    2770              :         gchar buf[sizeof (gulong) * 3];
    2771              :         EggAsn1xDef *opt;
    2772              :         gulong val;
    2773              :         GBytes *data;
    2774              : 
    2775           15 :         g_return_val_if_fail (node != NULL, 0);
    2776           15 :         g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_ENUMERATED, 0);
    2777              : 
    2778           15 :         data = anode_get_value (node);
    2779           15 :         if (data == NULL)
    2780            1 :                 return 0;
    2781              : 
    2782           14 :         if (!anode_read_integer_ulong (node, data, &val))
    2783            0 :                 g_return_val_if_reached (0);
    2784              : 
    2785              :         /* Format that as a string */
    2786           14 :         if (g_snprintf (buf, sizeof (buf), "%lu", val) < 0)
    2787            0 :                 g_return_val_if_reached (0);
    2788              : 
    2789              :         /* Lookup that value in our table */
    2790           14 :         opt = anode_opt_lookup_value (node, EGG_ASN1X_CONSTANT, buf);
    2791           14 :         if (opt == NULL || opt->name == NULL)
    2792            0 :                 return 0;
    2793              : 
    2794           14 :         return g_quark_from_static_string (opt->name);
    2795              : }
    2796              : 
    2797              : void
    2798            3 : egg_asn1x_set_enumerated (GNode *node,
    2799              :                           GQuark value)
    2800              : {
    2801              :         EggAsn1xDef *opt;
    2802              :         const gchar *name;
    2803              :         gpointer data;
    2804              :         gsize n_data;
    2805              :         gulong val;
    2806              : 
    2807            3 :         g_return_if_fail (node != NULL);
    2808            3 :         g_return_if_fail (value != 0);
    2809            3 :         g_return_if_fail (anode_def_type (node) == EGG_ASN1X_ENUMERATED);
    2810              : 
    2811            3 :         name = g_quark_to_string (value);
    2812            3 :         g_return_if_fail (name != NULL);
    2813              : 
    2814            3 :         opt = anode_opt_lookup (node, EGG_ASN1X_CONSTANT, name);
    2815            3 :         g_return_if_fail (opt && opt->value);
    2816              : 
    2817              :         /* TODO: Signed values */
    2818              : 
    2819            3 :         val = anode_def_value_as_ulong (opt);
    2820            3 :         g_return_if_fail (val != G_MAXULONG);
    2821              : 
    2822            3 :         n_data = sizeof (gulong) + 1;
    2823            3 :         data = g_malloc0 (n_data);
    2824            3 :         anode_write_integer_ulong (val, data, &n_data);
    2825              : 
    2826            3 :         anode_clr_value (node);
    2827            3 :         anode_take_value (node, g_bytes_new_take (data, n_data));
    2828              : }
    2829              : 
    2830              : gboolean
    2831           57 : egg_asn1x_get_integer_as_ulong (GNode *node,
    2832              :                                 gulong *value)
    2833              : {
    2834              :         gboolean ret;
    2835              :         GBytes *data;
    2836              : 
    2837           57 :         g_return_val_if_fail (node != NULL, FALSE);
    2838           57 :         g_return_val_if_fail (value != NULL, FALSE);
    2839           57 :         g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER, FALSE);
    2840              : 
    2841           57 :         data = anode_get_value (node);
    2842           57 :         if (data == NULL)
    2843            3 :                 data = anode_default_integer (node);
    2844              :         else
    2845           54 :                 g_bytes_ref (data);
    2846           57 :         if (data == NULL)
    2847            2 :                 return FALSE;
    2848              : 
    2849           55 :         ret = anode_read_integer_ulong (node, data, value);
    2850           55 :         g_bytes_unref (data);
    2851           55 :         return ret;
    2852              : }
    2853              : 
    2854              : void
    2855           39 : egg_asn1x_set_integer_as_ulong (GNode *node,
    2856              :                                 gulong value)
    2857              : {
    2858              :         GBytes *data, *def;
    2859              :         guchar *buf;
    2860              :         gsize len;
    2861              : 
    2862           39 :         g_return_if_fail (node != NULL);
    2863           39 :         g_return_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER);
    2864              : 
    2865           39 :         len = sizeof (gulong) + 1;
    2866           39 :         buf = g_malloc0 (len);
    2867           39 :         anode_write_integer_ulong (value, buf, &len);
    2868           39 :         data = g_bytes_new_take (buf, len);
    2869              : 
    2870              :         /* If it's equal to default, then clear */
    2871           39 :         def = anode_default_integer (node);
    2872           39 :         if (def) {
    2873            2 :                 if (g_bytes_equal (def, data)) {
    2874            1 :                         anode_clr_value (node);
    2875            1 :                         g_bytes_unref (data);
    2876            1 :                         data = NULL;
    2877              :                 }
    2878            2 :                 g_bytes_unref (def);
    2879              :         }
    2880              : 
    2881           39 :         if (data != NULL)
    2882           38 :                 anode_take_value (node, data);
    2883              : }
    2884              : 
    2885              : GBytes *
    2886          544 : egg_asn1x_get_integer_as_raw (GNode *node)
    2887              : {
    2888              :         Anode *an;
    2889              :         GBytes *raw;
    2890              : 
    2891          544 :         g_return_val_if_fail (node != NULL, NULL);
    2892          544 :         g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER, NULL);
    2893              : 
    2894          544 :         an = node->data;
    2895          544 :         if (an->guarantee_unsigned) {
    2896            0 :                 g_warning ("cannot read integer set with "        /* UNREACHABLE: */
    2897              :                            "egg_asn1x_set_integer_as_raw() "      /* UNREACHABLE: */
    2898              :                            "via egg_asn1x_get_integer_as_raw()"); /* UNREACHABLE: */
    2899            0 :                 return NULL;  /* UNREACHABLE: unreachable by coverage testing */
    2900              :         }
    2901              : 
    2902          544 :         raw = anode_get_value (node);
    2903          544 :         if (raw != NULL)
    2904          544 :                 g_bytes_ref (raw);
    2905          544 :         return raw;
    2906              : }
    2907              : 
    2908              : GBytes *
    2909            2 : egg_asn1x_get_integer_as_usg (GNode *node)
    2910              : {
    2911              :         const guchar *p;
    2912              :         Anode *an;
    2913              :         gboolean sign;
    2914              :         gsize len;
    2915              : 
    2916            2 :         g_return_val_if_fail (node != NULL, FALSE);
    2917            2 :         g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER, FALSE);
    2918              : 
    2919            2 :         an = node->data;
    2920            2 :         if (an->value == NULL)
    2921            1 :                 return NULL;
    2922              : 
    2923            1 :         p = g_bytes_get_data (an->value, &len);
    2924              : 
    2925            1 :         if (!an->guarantee_unsigned) {
    2926            1 :                 sign = !!(p[0] & 0x80);
    2927            1 :                 if (sign) {
    2928            0 :                         g_warning ("invalid two's complement integer"); /* UNREACHABLE: */
    2929            0 :                         return NULL; /* UNREACHABLE: by coverage testing */
    2930              :                 }
    2931              : 
    2932              :                 /* Strip off the extra zero byte that was preventing it from being negative */
    2933            1 :                 if (p[0] == 0 && len > 1) {
    2934            1 :                         sign = !!(p[1] & 0x80);
    2935            1 :                         if (sign) {
    2936            1 :                                 p++;
    2937            1 :                                 len--;
    2938              :                         }
    2939              :                 }
    2940              :         }
    2941              : 
    2942            1 :         return g_bytes_new_with_free_func (p, len,
    2943              :                                            (GDestroyNotify)g_bytes_unref,
    2944            1 :                                            g_bytes_ref (an->value));
    2945              : }
    2946              : 
    2947              : void
    2948           84 : egg_asn1x_set_integer_as_raw (GNode *node,
    2949              :                               GBytes *value)
    2950              : {
    2951           84 :         g_return_if_fail (value != NULL);
    2952           84 :         egg_asn1x_take_integer_as_raw (node, g_bytes_ref (value));
    2953              : }
    2954              : 
    2955              : void
    2956           84 : egg_asn1x_take_integer_as_raw (GNode *node,
    2957              :                                GBytes *value)
    2958              : {
    2959              :         gboolean sign;
    2960              :         const guchar *p;
    2961              :         Anode *an;
    2962              : 
    2963           84 :         g_return_if_fail (node != NULL);
    2964           84 :         g_return_if_fail (value != NULL);
    2965           84 :         g_return_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER);
    2966              : 
    2967              :         /* Make sure the integer is properly encoded in twos complement*/
    2968           84 :         p = g_bytes_get_data (value, NULL);
    2969           84 :         g_return_if_fail (p != NULL);
    2970              : 
    2971           84 :         sign = !!(p[0] & 0x80);
    2972           84 :         if (sign) {
    2973            0 :                 g_warning ("integer is not two's complement"); /* UNREACHABLE: */
    2974            0 :                 return; /* UNREACHABLE: unless warning */
    2975              :         }
    2976              : 
    2977           84 :         anode_clr_value (node);
    2978           84 :         anode_take_value (node, value);
    2979              : 
    2980           84 :         an = node->data;
    2981           84 :         an->guarantee_unsigned = 0;
    2982              : }
    2983              : 
    2984              : void
    2985            0 : egg_asn1x_set_integer_as_usg (GNode *node,
    2986              :                               GBytes *value)
    2987              : {
    2988            0 :         g_return_if_fail (value != NULL);
    2989            0 :         egg_asn1x_take_integer_as_usg (node, g_bytes_ref (value));
    2990              : }
    2991              : 
    2992              : void
    2993            1 : egg_asn1x_take_integer_as_usg (GNode *node,
    2994              :                                GBytes *value)
    2995              : {
    2996              :         Anode *an;
    2997              : 
    2998            1 :         g_return_if_fail (node != NULL);
    2999            1 :         g_return_if_fail (value != NULL);
    3000            1 :         g_return_if_fail (anode_def_type (node) == EGG_ASN1X_INTEGER);
    3001              : 
    3002            1 :         anode_take_value (node, value);
    3003            1 :         an = node->data;
    3004            1 :         an->guarantee_unsigned = 1;
    3005              : }
    3006              : 
    3007              : GNode *
    3008           57 : egg_asn1x_get_any_as (GNode *node,
    3009              :                       const EggAsn1xDef *defs,
    3010              :                       const gchar *type)
    3011              : {
    3012           57 :         g_return_val_if_fail (node != NULL, NULL);
    3013           57 :         g_return_val_if_fail (type != NULL, NULL);
    3014           57 :         g_return_val_if_fail (egg_asn1x_type (node) == EGG_ASN1X_ANY, NULL);
    3015              : 
    3016           57 :         return egg_asn1x_get_any_as_full (node, defs, type, 0);
    3017              : }
    3018              : 
    3019              : GNode *
    3020           57 : egg_asn1x_get_any_as_full (GNode *node,
    3021              :                            const EggAsn1xDef *defs,
    3022              :                            const gchar *type,
    3023              :                            gint options)
    3024              : {
    3025              :         GNode *asn;
    3026              : 
    3027           57 :         g_return_val_if_fail (node != NULL, NULL);
    3028           57 :         g_return_val_if_fail (type != NULL, NULL);
    3029           57 :         g_return_val_if_fail (egg_asn1x_type (node) == EGG_ASN1X_ANY, NULL);
    3030              : 
    3031           57 :         asn = egg_asn1x_create (defs, type);
    3032           57 :         g_return_val_if_fail (asn != NULL, NULL);
    3033              : 
    3034           57 :         if (!egg_asn1x_get_any_into_full (node, asn, options)) {
    3035            6 :                 egg_asn1x_destroy (asn);
    3036            6 :                 return NULL;
    3037              :         }
    3038              : 
    3039           51 :         return asn;
    3040              : }
    3041              : 
    3042              : gboolean
    3043           35 : egg_asn1x_get_any_into  (GNode *node,
    3044              :                          GNode *into)
    3045              : {
    3046           35 :         g_return_val_if_fail (node != NULL, FALSE);
    3047           35 :         g_return_val_if_fail (into != NULL, FALSE);
    3048           35 :         g_return_val_if_fail (egg_asn1x_type (node) == EGG_ASN1X_ANY, FALSE);
    3049              : 
    3050           35 :         return egg_asn1x_get_any_into_full (node, into, 0);
    3051              : }
    3052              : 
    3053              : gboolean
    3054           92 : egg_asn1x_get_any_into_full (GNode *node,
    3055              :                              GNode *into,
    3056              :                              gint options)
    3057              : {
    3058              :         Atlv *tlv;
    3059              : 
    3060           92 :         g_return_val_if_fail (node != NULL, FALSE);
    3061           92 :         g_return_val_if_fail (into != NULL, FALSE);
    3062           92 :         g_return_val_if_fail (egg_asn1x_type (node) == EGG_ASN1X_ANY, FALSE);
    3063              : 
    3064           92 :         tlv = anode_get_parsed (node);
    3065           92 :         if (tlv == NULL)
    3066            4 :                 return FALSE;
    3067              : 
    3068              :         /* If this node is explicit, then just get the contents */
    3069           88 :         if (anode_calc_explicit_for_flags (node, anode_def_flags (node), NULL)) {
    3070            1 :                 tlv = tlv->child;
    3071            1 :                 g_return_val_if_fail (tlv != NULL, FALSE);
    3072              :         }
    3073              : 
    3074           88 :         if (!anode_decode_anything (into, tlv))
    3075            4 :                 return FALSE;
    3076              : 
    3077           84 :         return egg_asn1x_validate (into, !(options & EGG_ASN1X_NO_STRICT));
    3078              : }
    3079              : 
    3080              : void
    3081           14 : egg_asn1x_set_any_from (GNode *node,
    3082              :                         GNode *from)
    3083              : {
    3084              :         Anode *an;
    3085              :         Atlv *tlv;
    3086              : 
    3087           14 :         g_return_if_fail (node != NULL);
    3088           14 :         g_return_if_fail (from != NULL);
    3089           14 :         g_return_if_fail (egg_asn1x_type (node) == EGG_ASN1X_ANY);
    3090              : 
    3091           14 :         tlv = anode_build_anything (from, TRUE);
    3092           14 :         g_return_if_fail (tlv != NULL);
    3093              : 
    3094              :         /* Wrap this in an explicit tag if necessary */
    3095           14 :         tlv = anode_build_maybe_explicit (node, tlv, anode_def_flags (node));
    3096              : 
    3097              :         /* Mark down the tlvs for this node */
    3098           14 :         an = node->data;
    3099           14 :         atlv_free (an->parsed);
    3100           14 :         an->parsed = tlv;
    3101              : }
    3102              : 
    3103              : GBytes *
    3104            2 : egg_asn1x_get_any_raw (GNode *node,
    3105              :                        EggAllocator allocator)
    3106              : {
    3107              :         GBytes *bytes;
    3108              :         Atlv *tlv;
    3109              : 
    3110            2 :         g_return_val_if_fail (node != NULL, NULL);
    3111              : 
    3112            2 :         tlv = anode_build_anything (node, TRUE);
    3113            2 :         if (tlv == NULL) {
    3114            1 :                 anode_failure (node, "missing value(s)");
    3115            1 :                 return NULL;
    3116              :         }
    3117              : 
    3118            1 :         atlv_sort_perform (tlv, allocator);
    3119              : 
    3120            1 :         bytes = atlv_unparse_to_bytes (tlv, allocator);
    3121            1 :         atlv_free (tlv);
    3122            1 :         return bytes;
    3123              : }
    3124              : 
    3125              : gboolean
    3126           32 : egg_asn1x_set_any_raw (GNode *node,
    3127              :                        GBytes *raw)
    3128              : {
    3129              :         const gchar *msg;
    3130              :         Anode *an;
    3131              :         Atlv *tlv;
    3132              : 
    3133           32 :         g_return_val_if_fail (node != NULL, FALSE);
    3134           32 :         g_return_val_if_fail (raw != NULL, FALSE);
    3135              : 
    3136           32 :         an = node->data;
    3137           32 :         tlv = atlv_new ();
    3138           32 :         msg = atlv_parse_der (raw, tlv);
    3139           32 :         if (msg == NULL) {
    3140              : 
    3141              :                 /* Wrap this in an explicit tag if necessary */
    3142           31 :                 tlv = anode_build_maybe_explicit (node, tlv, anode_def_flags (node));
    3143              : 
    3144           31 :                 atlv_free (an->parsed);
    3145           31 :                 an->parsed = tlv;
    3146           31 :                 return TRUE;
    3147              : 
    3148              :         /* A failure, set the message manually so it doesn't get a prefix */
    3149              :         } else {
    3150            1 :                 atlv_free (tlv);
    3151            1 :                 an = node->data;
    3152            1 :                 g_free (an->failure);
    3153            1 :                 an->failure = g_strdup (msg);
    3154            1 :                 return FALSE;
    3155              :         }
    3156              : }
    3157              : 
    3158              : GBytes *
    3159          111 : egg_asn1x_get_element_raw (GNode *node)
    3160              : {
    3161              :         Anode *an;
    3162              :         Atlv *tlv;
    3163              : 
    3164          111 :         g_return_val_if_fail (node != NULL, NULL);
    3165              : 
    3166          111 :         an = node->data;
    3167          111 :         tlv = an->parsed;
    3168              : 
    3169              :         /* If this node is explicit, then just get the contents */
    3170          111 :         if (tlv && anode_calc_explicit_for_flags (node, anode_def_flags (node), NULL))
    3171           53 :                 tlv = tlv->child;
    3172              : 
    3173          111 :         if (!tlv || !tlv->decoded)
    3174            7 :                 return NULL;
    3175              : 
    3176          104 :         return g_bytes_ref (tlv->decoded);
    3177              : }
    3178              : 
    3179              : GBytes *
    3180           25 : egg_asn1x_get_value_raw (GNode *node)
    3181              : {
    3182              :         GBytes *raw;
    3183              : 
    3184           25 :         g_return_val_if_fail (node != NULL, NULL);
    3185           25 :         raw = anode_get_value (node);
    3186           25 :         if (raw != NULL)
    3187           25 :                 g_bytes_ref (raw);
    3188           25 :         return raw;
    3189              : }
    3190              : 
    3191              : guchar *
    3192          121 : egg_asn1x_get_string_as_raw (GNode *node,
    3193              :                              EggAllocator allocator,
    3194              :                              gsize *n_string)
    3195              : {
    3196              :         gsize length;
    3197              :         guchar *string;
    3198              :         GBytes *data;
    3199              :         Atlv *tlv;
    3200              :         gint type;
    3201              : 
    3202          121 :         g_return_val_if_fail (node, NULL);
    3203          121 :         g_return_val_if_fail (n_string, NULL);
    3204              : 
    3205          121 :         if (!allocator)
    3206           81 :                 allocator = g_realloc;
    3207              : 
    3208          121 :         type = anode_def_type (node);
    3209          121 :         g_return_val_if_fail (type == EGG_ASN1X_OCTET_STRING ||
    3210              :                               type == EGG_ASN1X_GENERAL_STRING ||
    3211              :                               type == EGG_ASN1X_NUMERIC_STRING ||
    3212              :                               type == EGG_ASN1X_IA5_STRING ||
    3213              :                               type == EGG_ASN1X_TELETEX_STRING ||
    3214              :                               type == EGG_ASN1X_PRINTABLE_STRING ||
    3215              :                               type == EGG_ASN1X_UNIVERSAL_STRING ||
    3216              :                               type == EGG_ASN1X_BMP_STRING ||
    3217              :                               type == EGG_ASN1X_UTF8_STRING ||
    3218              :                               type == EGG_ASN1X_VISIBLE_STRING, NULL);
    3219              : 
    3220          121 :         data = anode_get_value (node);
    3221          121 :         if (data != NULL) {
    3222          115 :                 if (!anode_read_string_simple (node, data, NULL, &length))
    3223            0 :                         g_return_val_if_reached (NULL);
    3224              : 
    3225          115 :                 string = (allocator) (NULL, length + 1);
    3226          115 :                 if (string == NULL)
    3227            0 :                         return NULL; /* UNREACHABLE: unless odd allocator */
    3228              : 
    3229          115 :                 if (!anode_read_string_simple (node, data, string, &length))
    3230            0 :                         g_return_val_if_reached (NULL);
    3231              : 
    3232              :                 /* Courtesy null termination, string must however be validated! */
    3233          115 :                 string[length] = 0;
    3234          115 :                 *n_string = length;
    3235          115 :                 return string;
    3236              :         }
    3237              : 
    3238            6 :         tlv = anode_get_parsed (node);
    3239            6 :         if (tlv != NULL) {
    3240            2 :                 if (!anode_read_string_struct (node, tlv, NULL, &length))
    3241            1 :                         return NULL;
    3242              : 
    3243            1 :                 string = (allocator) (NULL, length + 1);
    3244            1 :                 if (string == NULL)
    3245            0 :                         return NULL; /* UNREACHABLE: unless odd allocator */
    3246              : 
    3247            1 :                 if (!anode_read_string_struct (node, tlv, string, &length))
    3248            0 :                         g_return_val_if_reached (NULL); /* should have failed above */
    3249              : 
    3250              :                 /* Courtesy null termination, string must however be validated! */
    3251            1 :                 string[length] = 0;
    3252            1 :                 *n_string = length;
    3253            1 :                 return string;
    3254              :         }
    3255              : 
    3256            4 :         return NULL;
    3257              : }
    3258              : 
    3259              : void
    3260           20 : egg_asn1x_set_string_as_raw (GNode *node,
    3261              :                              guchar *data,
    3262              :                              gsize n_data,
    3263              :                              GDestroyNotify destroy)
    3264              : {
    3265              :         gint type;
    3266              : 
    3267           20 :         g_return_if_fail (node != NULL);
    3268           20 :         g_return_if_fail (data != NULL);
    3269              : 
    3270           20 :         type = anode_def_type (node);
    3271           20 :         g_return_if_fail (type == EGG_ASN1X_OCTET_STRING ||
    3272              :                           type == EGG_ASN1X_GENERAL_STRING ||
    3273              :                           type == EGG_ASN1X_NUMERIC_STRING ||
    3274              :                           type == EGG_ASN1X_IA5_STRING ||
    3275              :                           type == EGG_ASN1X_TELETEX_STRING ||
    3276              :                           type == EGG_ASN1X_PRINTABLE_STRING ||
    3277              :                           type == EGG_ASN1X_UNIVERSAL_STRING ||
    3278              :                           type == EGG_ASN1X_BMP_STRING ||
    3279              :                           type == EGG_ASN1X_UTF8_STRING ||
    3280              :                           type == EGG_ASN1X_VISIBLE_STRING);
    3281              : 
    3282           20 :         anode_take_value (node, g_bytes_new_with_free_func (data, n_data,
    3283              :                                                             destroy, data));
    3284              : }
    3285              : 
    3286              : void
    3287           21 : egg_asn1x_set_string_as_bytes (GNode *node,
    3288              :                                GBytes *bytes)
    3289              : {
    3290              :         gint type;
    3291              : 
    3292           21 :         g_return_if_fail (node != NULL);
    3293           21 :         g_return_if_fail (bytes != NULL);
    3294              : 
    3295           21 :         type = anode_def_type (node);
    3296           21 :         g_return_if_fail (type == EGG_ASN1X_OCTET_STRING ||
    3297              :                           type == EGG_ASN1X_GENERAL_STRING ||
    3298              :                           type == EGG_ASN1X_NUMERIC_STRING ||
    3299              :                           type == EGG_ASN1X_IA5_STRING ||
    3300              :                           type == EGG_ASN1X_TELETEX_STRING ||
    3301              :                           type == EGG_ASN1X_PRINTABLE_STRING ||
    3302              :                           type == EGG_ASN1X_UNIVERSAL_STRING ||
    3303              :                           type == EGG_ASN1X_BMP_STRING ||
    3304              :                           type == EGG_ASN1X_UTF8_STRING ||
    3305              :                           type == EGG_ASN1X_VISIBLE_STRING);
    3306              : 
    3307           21 :         anode_set_value (node, bytes);
    3308              : }
    3309              : 
    3310              : GBytes *
    3311           77 : egg_asn1x_get_string_as_bytes (GNode *node)
    3312              : {
    3313              :         gpointer raw;
    3314              :         gsize length;
    3315              : 
    3316           77 :         g_return_val_if_fail (node != NULL, NULL);
    3317              : 
    3318           77 :         raw = egg_asn1x_get_string_as_raw (node, NULL, &length);
    3319           77 :         if (raw == NULL)
    3320            1 :                 return NULL;
    3321              : 
    3322           76 :         return g_bytes_new_take (raw, length);
    3323              : }
    3324              : 
    3325              : gchar *
    3326            1 : egg_asn1x_get_bmpstring_as_utf8 (GNode *node)
    3327              : {
    3328              :         gchar *string;
    3329              :         gsize n_string;
    3330              :         gchar *utf8;
    3331              : 
    3332            1 :         g_return_val_if_fail (node, NULL);
    3333              : 
    3334            1 :         string = (gchar*)egg_asn1x_get_string_as_raw (node, NULL, &n_string);
    3335            1 :         if (!string)
    3336            0 :                 return NULL;
    3337              : 
    3338            1 :         utf8 = g_convert (string, n_string, "UTF-8", "UTF-16BE", NULL, NULL, NULL);
    3339            1 :         g_free (string);
    3340              : 
    3341            1 :         return utf8;
    3342              : }
    3343              : 
    3344              : gchar*
    3345           20 : egg_asn1x_get_string_as_utf8 (GNode *node,
    3346              :                               EggAllocator allocator)
    3347              : {
    3348              :         gchar *string;
    3349              :         gsize n_string;
    3350              : 
    3351           20 :         g_return_val_if_fail (node, NULL);
    3352              : 
    3353           20 :         if (allocator == NULL)
    3354           20 :                 allocator = g_realloc;
    3355              : 
    3356           20 :         string = (gchar*)egg_asn1x_get_string_as_raw (node, allocator, &n_string);
    3357           20 :         if (!string)
    3358            3 :                 return NULL;
    3359              : 
    3360           17 :         if (!g_utf8_validate (string, n_string, NULL)) {
    3361            0 :                 (allocator) (string, 0);
    3362            0 :                 return NULL;
    3363              :         }
    3364              : 
    3365           17 :         return string;
    3366              : }
    3367              : 
    3368              : gboolean
    3369           13 : egg_asn1x_set_string_as_utf8 (GNode *node,
    3370              :                               gchar *data,
    3371              :                               GDestroyNotify destroy)
    3372              : {
    3373              :         gsize n_data;
    3374              : 
    3375           13 :         g_return_val_if_fail (node != NULL, FALSE);
    3376           13 :         g_return_val_if_fail (data != NULL, FALSE);
    3377              : 
    3378           13 :         n_data = strlen (data);
    3379           13 :         if (!g_utf8_validate (data, n_data, NULL))
    3380            1 :                 return FALSE;
    3381              : 
    3382           12 :         egg_asn1x_set_string_as_raw (node, (guchar*)data, n_data, destroy);
    3383           12 :         return TRUE;
    3384              : }
    3385              : 
    3386              : GBytes *
    3387          193 : egg_asn1x_get_bits_as_raw (GNode *node,
    3388              :                            guint *n_bits)
    3389              : {
    3390              :         gsize len;
    3391              :         GBytes *data;
    3392              :         Anode *an;
    3393              : 
    3394          193 :         g_return_val_if_fail (node != NULL, NULL);
    3395          193 :         g_return_val_if_fail (n_bits != NULL, NULL);
    3396          193 :         g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_BIT_STRING, NULL);
    3397              : 
    3398          193 :         data = anode_get_value (node);
    3399          193 :         if (data == NULL)
    3400            1 :                 return NULL;
    3401              : 
    3402          192 :         len = g_bytes_get_size (data);
    3403          192 :         an = node->data;
    3404              : 
    3405          192 :         *n_bits = (len * 8) - an->bits_empty;
    3406          192 :         return g_bytes_ref (data);
    3407              : }
    3408              : 
    3409              : void
    3410            6 : egg_asn1x_set_bits_as_raw (GNode *node,
    3411              :                            GBytes *value,
    3412              :                            guint n_bits)
    3413              : {
    3414            6 :         g_return_if_fail (node != NULL);
    3415            6 :         g_return_if_fail (value != NULL);
    3416              : 
    3417            6 :         egg_asn1x_take_bits_as_raw (node, g_bytes_ref (value), n_bits);
    3418              : }
    3419              : 
    3420              : void
    3421            7 : egg_asn1x_take_bits_as_raw (GNode *node,
    3422              :                             GBytes *value,
    3423              :                             guint n_bits)
    3424              : {
    3425              :         Anode *an;
    3426              :         gint type;
    3427              :         gsize len;
    3428              :         guchar empty;
    3429              : 
    3430            7 :         g_return_if_fail (node != NULL);
    3431            7 :         g_return_if_fail (value != NULL);
    3432              : 
    3433            7 :         type = anode_def_type (node);
    3434            7 :         g_return_if_fail (type == EGG_ASN1X_BIT_STRING);
    3435              : 
    3436            7 :         len = (n_bits / 8);
    3437            7 :         if (n_bits % 8)
    3438            1 :                 len += 1;
    3439              : 
    3440            7 :         empty = n_bits % 8;
    3441            7 :         if (empty > 0)
    3442            1 :                 empty = 8 - empty;
    3443              : 
    3444            7 :         anode_take_value (node, value);
    3445            7 :         an = node->data;
    3446            7 :         an->bits_empty = empty;
    3447              : }
    3448              : 
    3449              : gboolean
    3450            5 : egg_asn1x_get_bits_as_ulong (GNode *node,
    3451              :                              gulong *bits,
    3452              :                              guint *n_bits)
    3453              : {
    3454              :         GBytes *data;
    3455              :         const guchar *buf;
    3456              :         gsize len;
    3457              :         guint i, length;
    3458              :         guchar empty;
    3459              :         const guchar *p;
    3460              :         gulong value;
    3461              :         Anode *an;
    3462              : 
    3463            5 :         g_return_val_if_fail (node != NULL, FALSE);
    3464            5 :         g_return_val_if_fail (bits != NULL, FALSE);
    3465            5 :         g_return_val_if_fail (n_bits != NULL, FALSE);
    3466            5 :         g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_BIT_STRING, FALSE);
    3467              : 
    3468            5 :         data = anode_get_value (node);
    3469            5 :         if (data == NULL)
    3470            1 :                 return FALSE;
    3471              : 
    3472            4 :         buf = g_bytes_get_data (data, &len);
    3473            4 :         an = node->data;
    3474            4 :         empty = an->bits_empty;
    3475              : 
    3476            4 :         length = (len * 8) - empty;
    3477            4 :         if (length > sizeof (gulong) * 8)
    3478            1 :                 return FALSE;
    3479              : 
    3480            3 :         value = 0;
    3481            3 :         p = buf;
    3482              : 
    3483           10 :         for (i = 0; i < len; ++i)
    3484            7 :                 value = value << 8 | p[i];
    3485              : 
    3486            3 :         *bits = value >> empty;
    3487            3 :         *n_bits = length;
    3488            3 :         return TRUE;
    3489              : }
    3490              : 
    3491              : void
    3492            1 : egg_asn1x_set_bits_as_ulong (GNode *node,
    3493              :                              gulong bits,
    3494              :                              guint n_bits)
    3495              : {
    3496              :         guchar *data;
    3497              :         gulong value;
    3498              :         gsize i, len;
    3499              :         guchar empty;
    3500              :         Anode *an;
    3501              :         gint type;
    3502              : 
    3503            1 :         g_return_if_fail (node != NULL);
    3504            1 :         g_return_if_fail (n_bits <= sizeof (gulong) * 8);
    3505              : 
    3506            1 :         type = anode_def_type (node);
    3507            1 :         g_return_if_fail (type == EGG_ASN1X_BIT_STRING);
    3508              : 
    3509            1 :         empty = n_bits % 8;
    3510            1 :         if (empty > 0)
    3511            1 :                 empty = 8 - empty;
    3512            1 :         len = (n_bits / 8) + (empty ? 1 : 0);
    3513              : 
    3514            1 :         data = g_malloc0 (sizeof (gulong));
    3515            1 :         value = bits << empty;
    3516              : 
    3517            4 :         for (i = 0; i < len; ++i)
    3518            3 :                 data[len - i - 1] = (value >> i * 8) & 0xFF;
    3519              : 
    3520            1 :         an = node->data;
    3521            1 :         an->bits_empty = empty;
    3522            1 :         anode_take_value (node, g_bytes_new_take (data, len));
    3523              : }
    3524              : 
    3525              : glong
    3526            6 : egg_asn1x_get_time_as_long (GNode *node)
    3527              : {
    3528              :         struct tm when;
    3529              :         GBytes *data;
    3530              :         glong time;
    3531              :         gint type;
    3532              : 
    3533            6 :         g_return_val_if_fail (node, -1);
    3534            6 :         type = anode_def_type (node);
    3535              : 
    3536              :         /* Time is often represented as a choice, so work than in here */
    3537            6 :         if (type == EGG_ASN1X_CHOICE) {
    3538            1 :                 node = egg_asn1x_get_choice (node);
    3539            1 :                 if (node == NULL)
    3540            0 :                         return -1;
    3541            1 :                 g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_TIME ||
    3542              :                                       anode_def_type (node) == EGG_ASN1X_UTC_TIME ||
    3543              :                                       anode_def_type (node) == EGG_ASN1X_GENERALIZED_TIME, -1);
    3544            1 :                 return egg_asn1x_get_time_as_long (node);
    3545              :         }
    3546              : 
    3547            5 :         g_return_val_if_fail (type == EGG_ASN1X_TIME ||
    3548              :                               type == EGG_ASN1X_UTC_TIME ||
    3549              :                               type == EGG_ASN1X_GENERALIZED_TIME, -1);
    3550              : 
    3551            5 :         data = anode_get_value (node);
    3552            5 :         if (data == NULL)
    3553            3 :                 return -1;
    3554              : 
    3555            2 :         if (!anode_read_time (node, data, &when, &time))
    3556            0 :                 g_return_val_if_reached (-1); /* already validated */
    3557            2 :         return time;
    3558              : }
    3559              : 
    3560              : gboolean
    3561            3 : egg_asn1x_get_time_as_date (GNode *node,
    3562              :                             GDate *date)
    3563              : {
    3564              :         struct tm when;
    3565              :         GBytes *data;
    3566              :         glong time;
    3567              :         gint type;
    3568              : 
    3569            3 :         g_return_val_if_fail (node, FALSE);
    3570            3 :         type = anode_def_type (node);
    3571              : 
    3572              :         /* Time is often represented as a choice, so work than in here */
    3573            3 :         if (type == EGG_ASN1X_CHOICE) {
    3574            1 :                 node = egg_asn1x_get_choice (node);
    3575            1 :                 if (node == NULL)
    3576            0 :                         return FALSE;
    3577            1 :                 g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_TIME ||
    3578              :                                       anode_def_type (node) == EGG_ASN1X_UTC_TIME ||
    3579              :                                       anode_def_type (node) == EGG_ASN1X_GENERALIZED_TIME, FALSE);
    3580            1 :                 return egg_asn1x_get_time_as_date (node, date);
    3581              :         }
    3582              : 
    3583            2 :         g_return_val_if_fail (type == EGG_ASN1X_TIME ||
    3584              :                               type == EGG_ASN1X_UTC_TIME ||
    3585              :                               type == EGG_ASN1X_GENERALIZED_TIME, FALSE);
    3586              : 
    3587            2 :         data = anode_get_value (node);
    3588            2 :         if (data == NULL)
    3589            1 :                 return FALSE;
    3590              : 
    3591            1 :         if (!anode_read_time (node, data, &when, &time))
    3592            0 :                 g_return_val_if_reached (FALSE); /* already validated */
    3593              : 
    3594            1 :         g_date_set_dmy (date, when.tm_mday, when.tm_mon + 1, when.tm_year + 1900);
    3595            1 :         return TRUE;
    3596              : }
    3597              : 
    3598              : gchar*
    3599          338 : egg_asn1x_get_oid_as_string (GNode *node)
    3600              : {
    3601              :         GBytes *data;
    3602              :         gchar *oid;
    3603              : 
    3604          338 :         g_return_val_if_fail (node, NULL);
    3605          338 :         g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_OBJECT_ID, NULL);
    3606              : 
    3607          338 :         data = anode_get_value (node);
    3608          338 :         if (data == NULL)
    3609            1 :                 return NULL;
    3610              : 
    3611          337 :         if (!anode_read_object_id (node, data, &oid))
    3612            0 :                 g_return_val_if_reached (NULL); /* should have been validated */
    3613              : 
    3614          337 :         return oid;
    3615              : }
    3616              : 
    3617              : gboolean
    3618           30 : egg_asn1x_set_oid_as_string (GNode *node,
    3619              :                              const gchar *oid)
    3620              : {
    3621              :         guchar *data;
    3622              :         gsize n_data;
    3623              : 
    3624           30 :         g_return_val_if_fail (oid != NULL, FALSE);
    3625           30 :         g_return_val_if_fail (node != NULL, FALSE);
    3626           30 :         g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_OBJECT_ID, FALSE);
    3627              : 
    3628              :         /* Encoding will always be shorter than string */
    3629           30 :         n_data = strlen (oid);
    3630           30 :         data = g_malloc0 (n_data);
    3631              : 
    3632           30 :         if (!anode_write_object_id (oid, data, &n_data)) {
    3633            1 :                 g_free (data);
    3634            1 :                 return FALSE;
    3635              :         }
    3636              : 
    3637           29 :         anode_take_value (node, g_bytes_new_take (data, n_data));
    3638           29 :         return TRUE;
    3639              : }
    3640              : 
    3641              : GQuark
    3642          330 : egg_asn1x_get_oid_as_quark (GNode *node)
    3643              : {
    3644              :         GQuark quark;
    3645              :         gchar *oid;
    3646              : 
    3647          330 :         oid = egg_asn1x_get_oid_as_string (node);
    3648          330 :         if (!oid)
    3649            0 :                 return 0;
    3650          330 :         quark = g_quark_from_string (oid);
    3651          330 :         g_free (oid);
    3652          330 :         return quark;
    3653              : }
    3654              : 
    3655              : gboolean
    3656           28 : egg_asn1x_set_oid_as_quark (GNode *node,
    3657              :                             GQuark oid)
    3658              : {
    3659              :         const gchar *str;
    3660              : 
    3661           28 :         g_return_val_if_fail (oid != 0, FALSE);
    3662              : 
    3663           28 :         str = g_quark_to_string (oid);
    3664           28 :         g_return_val_if_fail (str != NULL, FALSE);
    3665              : 
    3666           28 :         return egg_asn1x_set_oid_as_string (node, str);
    3667              : }
    3668              : 
    3669              : GNode*
    3670         1202 : egg_asn1x_get_choice (GNode *node)
    3671              : {
    3672              :         GNode *child;
    3673              :         Anode *an;
    3674              : 
    3675         1202 :         g_return_val_if_fail (node, NULL);
    3676              : 
    3677              :         /* One and only one of the children must be set */
    3678         1292 :         for (child = node->children; child; child = child->next) {
    3679         1291 :                 an = (Anode*)child->data;
    3680         1291 :                 if (an->chosen)
    3681         1201 :                         return child;
    3682              :         }
    3683              : 
    3684            1 :         return NULL;
    3685              : }
    3686              : 
    3687              : gboolean
    3688           37 : egg_asn1x_set_choice (GNode *node,
    3689              :                       GNode *choice)
    3690              : {
    3691              :         GNode *child;
    3692              :         Anode *an;
    3693              : 
    3694           37 :         g_return_val_if_fail (node != NULL, FALSE);
    3695           37 :         g_return_val_if_fail (anode_def_type (node) == EGG_ASN1X_CHOICE, FALSE);
    3696              : 
    3697              :         /* One and only one of the children must be set */
    3698          130 :         for (child = node->children; child; child = child->next) {
    3699           93 :                 an = (Anode*)child->data;
    3700           93 :                 if (child == choice) {
    3701           37 :                         an->chosen = 1;
    3702           37 :                         choice = NULL;
    3703              :                 } else {
    3704           56 :                         an->chosen = 0;
    3705              :                 }
    3706              :         }
    3707              : 
    3708              :         /* The choice is not one of the child nodes */
    3709           37 :         g_return_val_if_fail (!choice, FALSE);
    3710              : 
    3711           37 :         return TRUE;
    3712              : }
    3713              : 
    3714              : /* -----------------------------------------------------------------------------------
    3715              :  * VALIDATION
    3716              :  */
    3717              : 
    3718              : static gboolean
    3719         6338 : anode_parse_size (GNode *node,
    3720              :                   const gchar *text,
    3721              :                   gulong *value)
    3722              : {
    3723              :         EggAsn1xDef *def;
    3724         6338 :         gchar *end = NULL;
    3725              : 
    3726         6338 :         if (text == NULL) {
    3727            0 :                 *value = 0;
    3728            0 :                 return FALSE;
    3729         6338 :         } else if (g_str_equal (text, "MAX")) {
    3730         3151 :                 *value = G_MAXULONG;
    3731         3151 :                 return TRUE;
    3732         3187 :         } else if (g_ascii_isalpha (text[0])) {
    3733            5 :                 def = anode_opt_lookup (node, EGG_ASN1X_INTEGER, text);
    3734            5 :                 g_return_val_if_fail (def, FALSE);
    3735            5 :                 return anode_parse_size (node, def->value, value);
    3736              :         }
    3737              : 
    3738         3182 :         *value = strtoul (text, &end, 10);
    3739         3182 :         g_return_val_if_fail (end && !end[0], FALSE);
    3740         3182 :         return TRUE;
    3741              : }
    3742              : 
    3743              : 
    3744              : static gboolean
    3745         4822 : anode_validate_size (GNode *node,
    3746              :                      gulong length)
    3747              : {
    3748              :         EggAsn1xDef *size;
    3749         4822 :         gulong value1 = 0;
    3750         4822 :         gulong value2 = G_MAXULONG;
    3751              : 
    3752         4822 :         if (anode_def_flags (node) & FLAG_SIZE) {
    3753         3177 :                 size = anode_opt_lookup (node, EGG_ASN1X_SIZE, NULL);
    3754         3177 :                 g_return_val_if_fail (size, FALSE);
    3755         3177 :                 if (!anode_parse_size (node, size->value, &value1))
    3756            0 :                         g_return_val_if_reached (FALSE);
    3757         3177 :                 if (size->type & FLAG_MIN_MAX) {
    3758         3156 :                         if (!anode_parse_size (node, size->name, &value2))
    3759            0 :                                 g_return_val_if_reached (FALSE);
    3760         3156 :                         if (length < value1 || length >= value2)
    3761            1 :                                 return anode_failure (node, "content size is out of bounds");
    3762              :                 } else {
    3763           21 :                         if (length != value1)
    3764            0 :                                 return anode_failure (node, "content size is not correct");
    3765              :                 }
    3766              :         }
    3767              : 
    3768         4821 :         return TRUE;
    3769              : }
    3770              : 
    3771              : static gboolean
    3772         1344 : anode_validate_integer (GNode *node,
    3773              :                         GBytes *value)
    3774              : {
    3775              :         GList *constants, *l;
    3776              :         gulong val, check;
    3777              :         gsize len;
    3778              :         gboolean found;
    3779              :         gint flags;
    3780              : 
    3781         1344 :         g_assert (value != NULL);
    3782         1344 :         len = g_bytes_get_size (value);
    3783              : 
    3784              :         /* Integers must be at least one byte long */
    3785         1344 :         if (len == 0)
    3786            1 :                 return anode_failure (node, "zero length integer");
    3787              : 
    3788         1343 :         flags = anode_def_flags (node);
    3789         1343 :         if (flags & FLAG_LIST) {
    3790              :                 /* Parse out the value, we only support small integers*/
    3791          330 :                 if (!anode_read_integer_ulong (node, value, &val))
    3792            1 :                         return anode_failure (node, "integer not part of list");
    3793              : 
    3794              :                 /* Look through the list of constants */
    3795          329 :                 found = FALSE;
    3796          329 :                 constants = anode_opts_lookup (node, EGG_ASN1X_CONSTANT, NULL);
    3797          838 :                 for (l = constants; l; l = g_list_next (l)) {
    3798          837 :                         check = anode_def_value_as_ulong (l->data);
    3799          837 :                         g_return_val_if_fail (check != G_MAXULONG, FALSE);
    3800          837 :                         if (check == val) {
    3801          328 :                                 found = TRUE;
    3802          328 :                                 break;
    3803              :                         }
    3804              :                 }
    3805          329 :                 g_list_free (constants);
    3806              : 
    3807          329 :                 if (!found)
    3808            1 :                         return anode_failure (node, "integer not part of listed set");
    3809              :         }
    3810              : 
    3811         1341 :         return TRUE;
    3812              : }
    3813              : 
    3814              : static gboolean
    3815           20 : anode_validate_enumerated (GNode *node,
    3816              :                            GBytes *value)
    3817              : {
    3818              :         const guchar *buf;
    3819              :         gsize length;
    3820              : 
    3821           20 :         g_assert (value != NULL);
    3822              : 
    3823           20 :         buf = g_bytes_get_data (value, &length);
    3824              : 
    3825              :         /* Enumerated must be positive */
    3826           20 :         if (length > 0 && (buf[0] & 0x80))
    3827            1 :                 return anode_failure (node, "enumerated must be positive");
    3828              : 
    3829           19 :         return anode_validate_integer (node, value);
    3830              : }
    3831              : 
    3832              : static gboolean
    3833          278 : anode_validate_boolean (GNode *node,
    3834              :                         GBytes *value)
    3835              : {
    3836              :         const guchar *buf;
    3837              :         gsize len;
    3838              : 
    3839          278 :         g_assert (value != NULL);
    3840          278 :         buf = g_bytes_get_data (value, &len);
    3841              : 
    3842              :         /* Must one byte, and zero or all ones */
    3843          278 :         if (len != 1)
    3844            1 :                 return anode_failure (node, "invalid length boolean");
    3845          277 :         if (buf[0] != 0x00 && buf[0] != 0xFF)
    3846            1 :                 return anode_failure (node, "boolean must be true or false");
    3847          276 :         return TRUE;
    3848              : }
    3849              : 
    3850              : static gboolean
    3851          894 : anode_validate_bit_string (GNode *node,
    3852              :                            GBytes *value)
    3853              : {
    3854          894 :         g_assert (value != NULL);
    3855              : 
    3856              :         /* All the decode validation done in anode_decode_bit_string */
    3857          894 :         return TRUE;
    3858              : }
    3859              : 
    3860              : static gboolean
    3861         1114 : anode_validate_string (GNode *node,
    3862              :                        GBytes *value)
    3863              : {
    3864              :         gsize length;
    3865              : 
    3866         1114 :         if (!anode_read_string_simple (node, value, NULL, &length))
    3867            0 :                 g_return_val_if_reached (FALSE);
    3868              : 
    3869         1114 :         return anode_validate_size (node, (gulong)length);
    3870              : }
    3871              : 
    3872              : static gboolean
    3873         5076 : anode_validate_object_id (GNode *node,
    3874              :                           GBytes *value)
    3875              : {
    3876         5076 :         return anode_read_object_id (node, value, NULL);
    3877              : }
    3878              : 
    3879              : static gboolean
    3880            2 : anode_validate_null (GNode *node,
    3881              :                      GBytes *value)
    3882              : {
    3883            2 :         g_assert (value != NULL);
    3884            2 :         return (g_bytes_get_size (value) == 0);
    3885              : }
    3886              : 
    3887              : static gboolean
    3888          513 : anode_validate_time (GNode *node,
    3889              :                      GBytes *value)
    3890              : {
    3891              :         glong time;
    3892              :         struct tm when;
    3893          513 :         return anode_read_time (node, value, &when, &time);
    3894              : }
    3895              : 
    3896              : static gboolean
    3897         1132 : anode_validate_choice (GNode *node,
    3898              :                        gboolean strict)
    3899              : {
    3900              :         GNode *child, *choice;
    3901              :         Anode *an;
    3902              : 
    3903              :         /* One and only one of the children must be set */
    3904         1132 :         choice = egg_asn1x_get_choice (node);
    3905         1132 :         if (!choice)
    3906            1 :                 return anode_failure (node, "one choice must be set");
    3907              : 
    3908         1131 :         if (!anode_validate_anything (choice, strict))
    3909            0 :                 return FALSE;
    3910              : 
    3911         2944 :         for (child = node->children; child; child = child->next) {
    3912         1813 :                 if (child != choice) {
    3913          682 :                         an = (Anode*)child->data;
    3914          682 :                         if (an->chosen)
    3915            0 :                                 return anode_failure (node, "only one choice may be set");
    3916              :                 }
    3917              :         }
    3918              : 
    3919         1131 :         return TRUE;
    3920              : }
    3921              : 
    3922              : static gboolean
    3923         6903 : anode_validate_sequence_or_set (GNode *node,
    3924              :                                 gboolean strict)
    3925              : {
    3926              :         GNode *child;
    3927              : 
    3928              :         /* If this is optional, and has no values, then that's all good */
    3929         6903 :         if (anode_def_flags (node) & FLAG_OPTION) {
    3930           14 :                 if (!egg_asn1x_have (node))
    3931           13 :                         return TRUE;
    3932              :         }
    3933              : 
    3934              :         /* All of the children must validate properly */
    3935        24399 :         for (child = node->children; child; child = child->next) {
    3936        17513 :                 if (!anode_validate_anything (child, strict))
    3937            4 :                         return FALSE;
    3938              :         }
    3939              : 
    3940         6886 :         return TRUE;
    3941              : }
    3942              : 
    3943              : static gboolean
    3944         3793 : anode_validate_sequence_or_set_of (GNode *node,
    3945              :                                    gboolean strict)
    3946              : {
    3947              :         GNode *child;
    3948              :         gulong count;
    3949              : 
    3950         3793 :         count = 0;
    3951              : 
    3952              :         /* All the children must validate properly */
    3953        10666 :         for (child = node->children; child; child = child->next) {
    3954         6874 :                 if (egg_asn1x_have (child)) {
    3955         6752 :                         if (!anode_validate_anything (child, strict))
    3956            1 :                                 return FALSE;
    3957         6751 :                         count++;
    3958              :                 }
    3959              :         }
    3960              : 
    3961         3792 :         if (count == 0 && anode_def_flags (node) & FLAG_OPTION)
    3962           84 :                 return TRUE;
    3963              : 
    3964         3708 :         return anode_validate_size (node, count);
    3965              : }
    3966              : 
    3967              : static gboolean
    3968        26573 : anode_validate_anything (GNode *node,
    3969              :                          gboolean strict)
    3970              : {
    3971              :         GBytes *value;
    3972              :         Atlv *tlv;
    3973              :         gint type;
    3974              :         gint flags;
    3975              : 
    3976        26573 :         type = anode_def_type (node);
    3977        26573 :         flags = anode_def_flags (node);
    3978              : 
    3979              :         /* Handle these specially */
    3980        26573 :         switch (type) {
    3981         1132 :         case EGG_ASN1X_CHOICE:
    3982         1132 :                 return anode_validate_choice (node, strict);
    3983              : 
    3984         6903 :         case EGG_ASN1X_SEQUENCE:
    3985              :         case EGG_ASN1X_SET:
    3986         6903 :                 return anode_validate_sequence_or_set (node, strict);
    3987              : 
    3988         3793 :         case EGG_ASN1X_SEQUENCE_OF:
    3989              :         case EGG_ASN1X_SET_OF:
    3990         3793 :                 return anode_validate_sequence_or_set_of (node, strict);
    3991              : 
    3992        14745 :         default:
    3993        14745 :                 break;
    3994              :         }
    3995              : 
    3996              :         /* Values that have been configured */
    3997        14745 :         value = anode_get_value (node);
    3998        14745 :         if (value) {
    3999         9222 :                 switch (type) {
    4000         1325 :                 case EGG_ASN1X_INTEGER:
    4001         1325 :                         return anode_validate_integer (node, value);
    4002           20 :                 case EGG_ASN1X_ENUMERATED:
    4003           20 :                         return anode_validate_enumerated (node, value);
    4004          278 :                 case EGG_ASN1X_BOOLEAN:
    4005          278 :                         return anode_validate_boolean (node, value);
    4006          894 :                 case EGG_ASN1X_BIT_STRING:
    4007          894 :                         return anode_validate_bit_string (node, value);
    4008         1114 :                 case EGG_ASN1X_OCTET_STRING:
    4009              :                 case EGG_ASN1X_GENERAL_STRING:
    4010              :                 case EGG_ASN1X_NUMERIC_STRING:
    4011              :                 case EGG_ASN1X_IA5_STRING:
    4012              :                 case EGG_ASN1X_TELETEX_STRING:
    4013              :                 case EGG_ASN1X_PRINTABLE_STRING:
    4014              :                 case EGG_ASN1X_UTF8_STRING:
    4015              :                 case EGG_ASN1X_VISIBLE_STRING:
    4016         1114 :                         return anode_validate_string (node, value);
    4017            0 :                 case EGG_ASN1X_BMP_STRING:
    4018              :                 case EGG_ASN1X_UNIVERSAL_STRING:
    4019            0 :                         return TRUE; /* TODO: Need to validate strings more completely */
    4020         5076 :                 case EGG_ASN1X_OBJECT_ID:
    4021         5076 :                         return anode_validate_object_id (node, value);
    4022            2 :                 case EGG_ASN1X_NULL:
    4023            2 :                         return anode_validate_null (node, value);
    4024          513 :                 case EGG_ASN1X_TIME:
    4025              :                 case EGG_ASN1X_UTC_TIME:
    4026              :                 case EGG_ASN1X_GENERALIZED_TIME:
    4027          513 :                         return anode_validate_time (node, value);
    4028            0 :                 default:
    4029            0 :                         g_assert_not_reached ();
    4030              :                 }
    4031              :         }
    4032              : 
    4033              :         /* See if there's a tlv parsed */
    4034         5523 :         tlv = anode_get_parsed (node);
    4035         5523 :         if (tlv) {
    4036         4166 :                 switch (type) {
    4037         4166 :                 case EGG_ASN1X_ANY:
    4038              :                 case EGG_ASN1X_GENERAL_STRING:
    4039              :                 case EGG_ASN1X_OCTET_STRING:
    4040              :                 case EGG_ASN1X_NUMERIC_STRING:
    4041              :                 case EGG_ASN1X_IA5_STRING:
    4042              :                 case EGG_ASN1X_TELETEX_STRING:
    4043              :                 case EGG_ASN1X_PRINTABLE_STRING:
    4044              :                 case EGG_ASN1X_UTF8_STRING:
    4045              :                 case EGG_ASN1X_VISIBLE_STRING:
    4046              :                 case EGG_ASN1X_BMP_STRING:
    4047              :                 case EGG_ASN1X_UNIVERSAL_STRING:
    4048         4166 :                         return TRUE;
    4049            0 :                 default:
    4050            0 :                         break; /* UNREACHABLE: fix compiler warning */
    4051              :                 }
    4052              :         }
    4053              : 
    4054         1357 :         if (flags & FLAG_OPTION)
    4055          663 :                 return TRUE;
    4056          694 :         if (flags & FLAG_DEFAULT)
    4057          692 :                 return TRUE;
    4058            2 :         return anode_failure (node, "missing value");
    4059              : }
    4060              : 
    4061              : gboolean
    4062         1177 : egg_asn1x_validate (GNode *asn,
    4063              :                     gboolean strict)
    4064              : {
    4065         1177 :         g_return_val_if_fail (asn, FALSE);
    4066         1177 :         return anode_validate_anything (asn, strict);
    4067              : }
    4068              : 
    4069              : /* -----------------------------------------------------------------------------------
    4070              :  * TREE CREATION
    4071              :  */
    4072              : 
    4073              : static gint
    4074           15 : compare_nodes_by_tag (gconstpointer a, gconstpointer b)
    4075              : {
    4076           15 :         GNode *na = (gpointer)a;
    4077           15 :         GNode *nb = (gpointer)b;
    4078              :         gulong taga, tagb;
    4079              : 
    4080           15 :         g_return_val_if_fail (anode_def_flags (na) & FLAG_TAG, 0);
    4081           15 :         g_return_val_if_fail (anode_def_flags (nb) & FLAG_TAG, 0);
    4082              : 
    4083           15 :         taga = anode_calc_tag (na);
    4084           15 :         g_return_val_if_fail (taga != G_MAXULONG, 0);
    4085              : 
    4086           15 :         tagb = anode_calc_tag (nb);
    4087           15 :         g_return_val_if_fail (tagb != G_MAXULONG, 0);
    4088              : 
    4089           15 :         if (taga == tagb)
    4090            0 :                 return 0;
    4091           15 :         return (taga < tagb) ? -1 : 1;
    4092              : }
    4093              : 
    4094              : static const EggAsn1xDef *
    4095      1224233 : adef_next_sibling (const EggAsn1xDef *def)
    4096              : {
    4097      1224233 :         int depth = 0;
    4098              : 
    4099      1224233 :         g_assert (def);
    4100      1224233 :         g_assert (def->value || def->type || def->name);
    4101              : 
    4102      1224233 :         if ((def->type & FLAG_RIGHT) == 0)
    4103         1654 :                 return NULL;
    4104              : 
    4105              :         /* Skip past any children */
    4106      1222579 :         if ((def->type & FLAG_DOWN) == FLAG_DOWN) {
    4107       947700 :                 depth += 1;
    4108      3693901 :                 while (depth > 0) {
    4109      2746201 :                         ++def;
    4110      2746201 :                         if ((def->type & FLAG_DOWN) == FLAG_DOWN)
    4111       437325 :                                 depth += 1;
    4112      2746201 :                         if ((def->type & FLAG_RIGHT) == 0)
    4113      1385025 :                                 depth -= 1;
    4114              :                 }
    4115              :         }
    4116              : 
    4117      1222579 :         ++def;
    4118      1222579 :         g_return_val_if_fail (def->value || def->type || def->name, NULL);
    4119      1222579 :         return def;
    4120              : }
    4121              : 
    4122              : static const EggAsn1xDef *
    4123        11089 : adef_first_child (const EggAsn1xDef *def)
    4124              : {
    4125        11089 :         g_assert (def);
    4126        11089 :         g_assert (def->value || def->type || def->name);
    4127              : 
    4128        11089 :         if ((def->type & FLAG_DOWN) == 0)
    4129          181 :                 return NULL;
    4130              : 
    4131        10908 :         ++def;
    4132        10908 :         g_return_val_if_fail (def->value || def->type || def->name, NULL);
    4133        10908 :         return def;
    4134              : }
    4135              : 
    4136              : static const EggAsn1xDef *
    4137           26 : lookup_def_of_type (const EggAsn1xDef *defs,
    4138              :                     const gchar *name,
    4139              :                     gint type)
    4140              : {
    4141              :         const EggAsn1xDef *def;
    4142              : 
    4143           26 :         g_assert (defs);
    4144           26 :         g_assert (defs->value || defs->type || defs->name);
    4145              : 
    4146         6941 :         for (def = adef_first_child (defs); def; def = adef_next_sibling (def)) {
    4147         6941 :                 if ((def->type & 0xFF) == type && def->name && g_str_equal (name, def->name))
    4148           26 :                         return def;
    4149              :         }
    4150              : 
    4151            0 :         return NULL;
    4152              : }
    4153              : 
    4154              : static gboolean
    4155        28877 : traverse_and_prepare (GNode *node, gpointer data)
    4156              : {
    4157        28877 :         const EggAsn1xDef *defs = data;
    4158              :         const EggAsn1xDef *def;
    4159              :         const gchar *identifier;
    4160              :         Anode *an, *anj;
    4161        28877 :         GNode *join = NULL;
    4162              :         GNode *child, *next;
    4163        28877 :         GList *list = NULL, *l;
    4164              : 
    4165              :         /* A while, because the stuff we join, could also be an identifier */
    4166        36731 :         while (anode_def_type (node) == EGG_ASN1X_IDENTIFIER) {
    4167         7854 :                 an = node->data;
    4168         7854 :                 identifier = an->join ? an->join->value : an->def->value;
    4169         7854 :                 g_return_val_if_fail (identifier, TRUE);
    4170         7854 :                 egg_asn1x_destroy (join);
    4171         7854 :                 join = egg_asn1x_create (defs, identifier);
    4172         7854 :                 g_return_val_if_fail (join, TRUE);
    4173         7854 :                 anj = join->data;
    4174         7854 :                 an->join = anj->def;
    4175              :         }
    4176              : 
    4177              :         /* Move all the children of join node into our node */
    4178        28877 :         if (join) {
    4179         7844 :                 list = NULL;
    4180        19149 :                 for (child = join->children, list = NULL; child; child = child->next)
    4181        11305 :                         list = g_list_prepend (list, child);
    4182         7844 :                 list = g_list_reverse (list);
    4183        19149 :                 for (l = list; l; l = g_list_next (l)) {
    4184        11305 :                         child = l->data;
    4185        11305 :                         g_node_unlink (child);
    4186        11305 :                         g_node_append (node, child);
    4187              :                 }
    4188         7844 :                 g_list_free (list);
    4189         7844 :                 list = NULL;
    4190              :         }
    4191              : 
    4192              :         /* Lookup the max set size */
    4193        28877 :         if (anode_def_type (node) == EGG_ASN1X_SIZE) {
    4194         1077 :                 identifier = anode_def_name (node);
    4195         1077 :                 if (identifier && !g_str_equal (identifier, "MAX") &&
    4196           54 :                     g_ascii_isalpha (identifier[0])) {
    4197           26 :                         def = lookup_def_of_type (defs, identifier, EGG_ASN1X_INTEGER);
    4198           26 :                         g_return_val_if_fail (def, TRUE);
    4199           26 :                         anode_opt_add (node, def);
    4200              :                 }
    4201              :         }
    4202              : 
    4203              :         /* Anything child not a real node, we put into opts */
    4204        28877 :         if (anode_def_type_is_real (node)) {
    4205        23016 :                 child = node->children;
    4206        54276 :                 while (child) {
    4207        31260 :                         next = child->next;
    4208        31260 :                         if (!anode_def_type_is_real (child)) {
    4209         5861 :                                 an = child->data;
    4210         5861 :                                 anode_opt_add (node, an->def);
    4211         5887 :                                 for (l = an->opts; l; l = g_list_next (l))
    4212           26 :                                         anode_opt_add (node, l->data);
    4213         5861 :                                 g_node_unlink (child);
    4214         5861 :                                 anode_destroy (child);
    4215              :                         }
    4216        31260 :                         child = next;
    4217              :                 }
    4218              :         }
    4219              : 
    4220        28877 :         if (join) {
    4221         7844 :                 an = join->data;
    4222        10484 :                 for (l = an->opts; l; l = g_list_next (l))
    4223         2640 :                         anode_opt_add (node, l->data);
    4224         7844 :                 egg_asn1x_destroy (join);
    4225              :         }
    4226              : 
    4227              :         /* Sort the children of any sets */
    4228        28877 :         if (anode_def_type (node) == EGG_ASN1X_SET) {
    4229           19 :                 for (child = node->children; child; child = child->next)
    4230           15 :                         list = g_list_prepend (list, child);
    4231            4 :                 list = g_list_sort (list, compare_nodes_by_tag);
    4232           19 :                 for (l = list; l; l = g_list_next (l))
    4233           15 :                         g_node_unlink (l->data);
    4234           19 :                 for (l = list; l; l = g_list_next (l))
    4235           15 :                         g_node_append (node, l->data);
    4236            4 :                 g_list_free (list);
    4237            4 :                 list = NULL;
    4238              :         }
    4239              : 
    4240              :         /* Continue traversal */
    4241        28877 :         return FALSE;
    4242              : }
    4243              : 
    4244              : static const EggAsn1xDef *
    4245         2138 : match_oid_in_definition (const EggAsn1xDef *def,
    4246              :                          GHashTable *names,
    4247              :                          const gchar *match,
    4248              :                          const gchar **problem)
    4249              : {
    4250         2138 :         const EggAsn1xDef *result = NULL;
    4251              :         const EggAsn1xDef *odef;
    4252              :         const gchar *value;
    4253         2138 :         GString *oid = NULL;
    4254              : 
    4255         2138 :         g_assert (match);
    4256         2138 :         g_assert (problem);
    4257         2138 :         g_assert (names);
    4258              : 
    4259         5868 :         for (odef = adef_first_child (def); odef; odef = adef_next_sibling (odef)) {
    4260         4036 :                 if ((odef->type & 0xFF) != EGG_ASN1X_CONSTANT)
    4261            0 :                         continue;
    4262              : 
    4263         4036 :                 g_return_val_if_fail (odef->value, NULL);
    4264         4036 :                 if (strspn (odef->value, "01234567890") == strlen (odef->value)) {
    4265         2237 :                         value = odef->value;
    4266              : 
    4267              :                 } else {
    4268         1799 :                         value = g_hash_table_lookup (names, odef->value);
    4269              : 
    4270              :                         /* A name resolution problem */
    4271         1799 :                         if (!value) {
    4272          306 :                                 if (oid)
    4273            0 :                                         g_string_free (oid, TRUE);
    4274          306 :                                 *problem = odef->value;
    4275          306 :                                 return NULL;
    4276              :                         }
    4277              :                 }
    4278              : 
    4279         3730 :                 if (oid) {
    4280              :                         g_string_append_c (oid, '.');
    4281              :                         g_string_append (oid, value);
    4282              :                 } else {
    4283         1651 :                         oid = g_string_new (value);
    4284              :                 }
    4285              :         }
    4286              : 
    4287         1832 :         if (oid != NULL) {
    4288         1651 :                 if (g_str_equal (oid->str, match))
    4289           34 :                         result = adef_next_sibling (def);
    4290         1651 :                 g_assert (def->name);
    4291         1651 :                 g_hash_table_insert (names, (gchar*)def->name, g_string_free (oid, FALSE));
    4292              :         }
    4293              : 
    4294         1832 :         return result;
    4295              : }
    4296              : 
    4297              : static const EggAsn1xDef *
    4298           35 : match_oid_in_definitions (const EggAsn1xDef *defs,
    4299              :                           const gchar *match)
    4300              : {
    4301              :         const EggAsn1xDef *def;
    4302              :         const EggAsn1xDef *result;
    4303              :         GHashTable *names;
    4304              :         gboolean progress;
    4305              :         const gchar *problem;
    4306              : 
    4307           35 :         names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
    4308           35 :         result = NULL;
    4309              : 
    4310              :         for (;;) {
    4311           37 :                 progress = FALSE;
    4312           37 :                 problem = NULL;
    4313              : 
    4314         5020 :                 for (def = adef_first_child (defs); def; def = adef_next_sibling (def)) {
    4315              : 
    4316              :                         /* Only work with object ids, and ones with names */
    4317         5017 :                         if ((def->type & 0xFF) != EGG_ASN1X_OBJECT_ID || !def->name)
    4318         2765 :                                 continue;
    4319              : 
    4320              :                         /* If we've already seen this one, skip */
    4321         2252 :                         if (g_hash_table_lookup (names, def->name))
    4322          114 :                                 continue;
    4323              : 
    4324         2138 :                         progress = TRUE;
    4325         2138 :                         result = match_oid_in_definition (def, names, match, &problem);
    4326         2138 :                         if (result != NULL)
    4327           34 :                                 break;
    4328              :                 }
    4329              : 
    4330           37 :                 if (!problem || result) {
    4331              :                         break;
    4332            2 :                 } else if (problem && !progress) {
    4333            0 :                         g_warning ("couldn't find oid definition in ASN.1 for: %s", problem);
    4334            0 :                         g_return_val_if_reached (NULL);
    4335              :                 }
    4336              :         }
    4337              : 
    4338           35 :         g_hash_table_destroy (names);
    4339           35 :         return result;
    4340              : }
    4341              : 
    4342              : static gboolean
    4343         8923 : is_oid_number (const gchar *p)
    4344              : {
    4345         8923 :         gboolean must = TRUE;
    4346              :         gint i;
    4347              : 
    4348         9227 :         for (i = 0; p[i] != '\0'; i++) {
    4349         9192 :                 if (g_ascii_isdigit (p[i])) {
    4350          186 :                         must = FALSE;
    4351         9006 :                 } else if (must) {
    4352         8888 :                         return FALSE;
    4353              :                 } else {
    4354          118 :                         if (p[i] != '.')
    4355            0 :                                 return FALSE;
    4356          118 :                         must = TRUE;
    4357              :                 }
    4358              :         }
    4359              : 
    4360           35 :         return !must;
    4361              : }
    4362              : 
    4363              : GNode*
    4364         8923 : egg_asn1x_create (const EggAsn1xDef *defs,
    4365              :                   const gchar *type)
    4366              : {
    4367              :         const EggAsn1xDef *def;
    4368              :         GNode *root, *parent, *node;
    4369              :         int flags;
    4370              : 
    4371         8923 :         g_return_val_if_fail (defs, NULL);
    4372         8923 :         g_return_val_if_fail (type, NULL);
    4373              : 
    4374              :         /* An OID */
    4375         8923 :         if (is_oid_number (type)) {
    4376           35 :                 def = match_oid_in_definitions (defs, type);
    4377              : 
    4378              :         /* An Identifier */
    4379              :         } else {
    4380      1217459 :                 for (def = adef_first_child (defs); def; def = adef_next_sibling (def)) {
    4381      1217459 :                         if (def->name && g_str_equal (type, def->name))
    4382         8888 :                                 break;
    4383              :                 }
    4384              :         }
    4385              : 
    4386         8923 :         if (def == NULL || !def->name || !def->type)
    4387            1 :                 return NULL;
    4388              : 
    4389              :         /* The node for this item */
    4390         8922 :         root = anode_new (def);
    4391              : 
    4392              :         /* Build up nodes for underlying level */
    4393         8922 :         if (def->type & FLAG_DOWN) {
    4394         7439 :                 node = root;
    4395              :                 for (;;) {
    4396        27394 :                         if (def->type & FLAG_DOWN) {
    4397        10377 :                                 parent = node;
    4398        17017 :                         } else if (def->type & FLAG_RIGHT) {
    4399         8189 :                                 g_assert (node->parent);
    4400         8189 :                                 parent = node->parent;
    4401              :                         } else {
    4402         8828 :                                 parent = node->parent;
    4403        10424 :                                 while (parent) {
    4404        10377 :                                         flags = anode_def_flags (parent);
    4405        10377 :                                         parent = parent->parent;
    4406        10377 :                                         if (flags & FLAG_RIGHT)
    4407         8781 :                                                 break;
    4408              :                                 }
    4409              :                         }
    4410              : 
    4411        27394 :                         if (!parent)
    4412         7439 :                                 break;
    4413              : 
    4414        19955 :                         ++def;
    4415        19955 :                         node = anode_new (def);
    4416        19955 :                         g_node_append (parent, node);
    4417              :                 }
    4418              :         }
    4419              : 
    4420              :         /* Load up sub identifiers */
    4421         8922 :         g_node_traverse (root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
    4422              :                          traverse_and_prepare, (gpointer)defs);
    4423              : 
    4424         8922 :         return root;
    4425              : }
    4426              : 
    4427              : GNode*
    4428           32 : egg_asn1x_create_quark (const EggAsn1xDef *defs,
    4429              :                         GQuark type)
    4430              : {
    4431           32 :         g_return_val_if_fail (type, NULL);
    4432           32 :         return egg_asn1x_create (defs, g_quark_to_string (type));
    4433              : }
    4434              : 
    4435              : GNode *
    4436          755 : egg_asn1x_create_and_decode_full (const EggAsn1xDef *defs,
    4437              :                                   const gchar *identifier,
    4438              :                                   GBytes *data,
    4439              :                                   gint options)
    4440              : {
    4441              :         GNode *asn;
    4442              : 
    4443          755 :         g_return_val_if_fail (defs != NULL, NULL);
    4444          755 :         g_return_val_if_fail (identifier != NULL, NULL);
    4445          755 :         g_return_val_if_fail (data != NULL, NULL);
    4446              : 
    4447          755 :         asn = egg_asn1x_create (defs, identifier);
    4448          755 :         g_return_val_if_fail (asn, NULL);
    4449              : 
    4450          755 :         if (!egg_asn1x_decode_full (asn, data, options)) {
    4451           50 :                 egg_asn1x_destroy (asn);
    4452           50 :                 return NULL;
    4453              :         }
    4454              : 
    4455          705 :         return asn;
    4456              : 
    4457              : }
    4458              : 
    4459              : GNode*
    4460          755 : egg_asn1x_create_and_decode (const EggAsn1xDef *defs,
    4461              :                              const gchar *identifier,
    4462              :                              GBytes *data)
    4463              : {
    4464          755 :         g_return_val_if_fail (defs != NULL, NULL);
    4465          755 :         g_return_val_if_fail (identifier != NULL, NULL);
    4466          755 :         g_return_val_if_fail (data != NULL, NULL);
    4467              : 
    4468          755 :         return egg_asn1x_create_and_decode_full (defs, identifier, data, 0);
    4469              : }
    4470              : 
    4471              : /* -----------------------------------------------------------------------------------
    4472              :  * DUMPING and MESSAGES
    4473              :  */
    4474              : 
    4475              : static void
    4476            0 : dump_append_type (GString *output, gint type)
    4477              : {
    4478              :         #define XX(x) if (type == EGG_ASN1X_##x) g_string_append (output, #x " ")
    4479            0 :         XX(CONSTANT); XX(IDENTIFIER); XX(INTEGER); XX(BOOLEAN); XX(SEQUENCE); XX(BIT_STRING);
    4480            0 :         XX(OCTET_STRING); XX(TAG); XX(DEFAULT); XX(SIZE); XX(SEQUENCE_OF); XX(OBJECT_ID); XX(ANY);
    4481            0 :         XX(SET); XX(SET_OF); XX(DEFINITIONS); XX(TIME); XX(UTC_TIME); XX(GENERALIZED_TIME); XX(CHOICE); XX(IMPORTS); XX(NULL);
    4482            0 :         XX(ENUMERATED); XX(GENERAL_STRING); XX(NUMERIC_STRING); XX(IA5_STRING); XX(TELETEX_STRING);
    4483            0 :         XX(PRINTABLE_STRING); XX(UNIVERSAL_STRING); XX(BMP_STRING); XX(UTF8_STRING); XX(VISIBLE_STRING);
    4484              : 
    4485            0 :         if (output->len == 0)
    4486            0 :                 g_string_printf (output, "%d ", (int)type);
    4487              :         #undef XX
    4488            0 : }
    4489              : 
    4490              : static void
    4491            0 : dump_append_flags (GString *output, gint flags)
    4492              : {
    4493              :         #define XX(x) if ((FLAG_##x & flags) == FLAG_##x) g_string_append (output, #x " ")
    4494            0 :         XX(UNIVERSAL); XX(PRIVATE); XX(APPLICATION); XX(EXPLICIT); XX(IMPLICIT); XX(TAG); XX(OPTION);
    4495            0 :         XX(DEFAULT); XX(TRUE); XX(FALSE); XX(LIST); XX(MIN_MAX); XX(1_PARAM); XX(SIZE); XX(DEFINED_BY);
    4496            0 :         XX(GENERALIZED); XX(UTC); XX(IMPORTS); XX(NOT_USED); XX(SET); XX(ASSIGN);
    4497              :         /* XX(DOWN); XX(RIGHT); */
    4498              :         #undef XX
    4499            0 : }
    4500              : 
    4501              : static gboolean
    4502            0 : traverse_and_dump (GNode *node, gpointer unused)
    4503              : {
    4504              :         EggAsn1xDef *def;
    4505              :         guint i, depth;
    4506              :         GString *output;
    4507              :         gchar *string;
    4508              :         Anode *an;
    4509              :         GList *l;
    4510              : 
    4511            0 :         depth = g_node_depth (node);
    4512            0 :         for (i = 0; i < depth - 1; ++i)
    4513            0 :                 g_print ("    ");
    4514              : 
    4515            0 :         an = node->data;
    4516            0 :         output = g_string_new ("");
    4517            0 :         dump_append_type (output, anode_def_type (node));
    4518            0 :         dump_append_flags (output, anode_def_flags (node));
    4519            0 :         string = g_utf8_casefold (output->str, output->len - 1);
    4520            0 :         g_string_free (output, TRUE);
    4521            0 :         g_print ("+ %s: %s [%s]%s\n", anode_def_name (node), anode_def_value (node),
    4522            0 :                     string, an->parsed || an->value ? " *" : "");
    4523            0 :         g_free (string);
    4524              : 
    4525              :         /* Print out all the options */
    4526            0 :         for (l = an->opts; l; l = g_list_next (l)) {
    4527            0 :                 for (i = 0; i < depth; ++i)
    4528            0 :                         g_print ("    ");
    4529              : 
    4530            0 :                 def = l->data;
    4531            0 :                 output = g_string_new ("");
    4532            0 :                 dump_append_type (output, def->type & 0xFF);
    4533            0 :                 dump_append_flags (output, def->type);
    4534            0 :                 string = g_utf8_casefold (output->str, output->len - 1);
    4535            0 :                 g_string_free (output, TRUE);
    4536            0 :                 g_print ("- %s: %s [%s]\n", def->name, (const gchar*)def->value, string);
    4537            0 :                 g_free (string);
    4538              :         }
    4539              : 
    4540            0 :         return FALSE;
    4541              : }
    4542              : 
    4543              : void
    4544            0 : egg_asn1x_dump (GNode *asn)
    4545              : {
    4546            0 :         g_return_if_fail (asn);
    4547            0 :         g_node_traverse (asn, G_PRE_ORDER, G_TRAVERSE_ALL, -1, traverse_and_dump, NULL);
    4548              : }
    4549              : 
    4550              : static gboolean
    4551           88 : traverse_and_get_failure (GNode *node, gpointer user_data)
    4552              : {
    4553           88 :         const gchar **failure = user_data;
    4554           88 :         g_assert (!*failure);
    4555           88 :         *failure = anode_failure_get (node);
    4556           88 :         return (*failure != NULL);
    4557              : }
    4558              : 
    4559              : const gchar*
    4560           28 : egg_asn1x_message (GNode *asn)
    4561              : {
    4562           28 :         const gchar *failure = NULL;
    4563           28 :         g_return_val_if_fail (asn, NULL);
    4564           28 :         g_node_traverse (asn, G_POST_ORDER, G_TRAVERSE_ALL, -1, traverse_and_get_failure, &failure);
    4565           28 :         return failure;
    4566              : }
    4567              : 
    4568              : /* -----------------------------------------------------------------------------------
    4569              :  * CLEARING and DESTROYING
    4570              :  */
    4571              : 
    4572              : static gboolean
    4573        14094 : traverse_and_clear (GNode *node, gpointer unused)
    4574              : {
    4575              :         GNode *child, *next;
    4576              :         gint type;
    4577              : 
    4578        14094 :         anode_clear (node);
    4579              : 
    4580        14094 :         type = anode_def_type (node);
    4581        14094 :         if (type == EGG_ASN1X_SET_OF || type == EGG_ASN1X_SEQUENCE_OF) {
    4582              : 
    4583              :                 /* The first 'real' child is the template */
    4584         1460 :                 child = node->children;
    4585         1460 :                 g_return_val_if_fail (child, TRUE);
    4586              : 
    4587              :                 /* And any others are extras */
    4588         1460 :                 child = child->next;
    4589         1489 :                 while (child) {
    4590           29 :                         next = child->next;
    4591           29 :                         anode_destroy (child);
    4592           29 :                         child = next;
    4593              :                 }
    4594              :         }
    4595              : 
    4596              :         /* Don't stop traversal */
    4597        14094 :         return FALSE;
    4598              : }
    4599              : 
    4600              : void
    4601          882 : egg_asn1x_clear (GNode *asn)
    4602              : {
    4603          882 :         g_return_if_fail (asn);
    4604          882 :         g_node_traverse (asn, G_POST_ORDER, G_TRAVERSE_ALL, -1, traverse_and_clear, NULL);
    4605              : }
    4606              : 
    4607              : void
    4608        16867 : egg_asn1x_destroy (gpointer data)
    4609              : {
    4610        16867 :         GNode *node = data;
    4611              : 
    4612        16867 :         if (node != NULL) {
    4613         8922 :                 g_return_if_fail (G_NODE_IS_ROOT (node));
    4614         8922 :                 anode_destroy (node);
    4615              :         }
    4616              : }
    4617              : 
    4618              : /* --------------------------------------------------------------------------------
    4619              :  * TIME PARSING
    4620              :  */
    4621              : 
    4622              : glong
    4623            8 : egg_asn1x_parse_time_general (const gchar *time, gssize n_time)
    4624              : {
    4625              :         gboolean ret;
    4626              :         glong value;
    4627              :         struct tm when;
    4628            8 :         gint offset = 0;
    4629              : 
    4630            8 :         g_return_val_if_fail (time, -1);
    4631              : 
    4632            8 :         if (n_time < 0)
    4633            8 :                 n_time = strlen (time);
    4634              : 
    4635            8 :         ret = parse_general_time (time, n_time, &when, &offset);
    4636            8 :         if (!ret)
    4637            1 :                 return -1;
    4638              : 
    4639              :         /* In order to work with 32 bit time_t. */
    4640              :         if (sizeof (time_t) <= 4 && when.tm_year >= 2038) {
    4641              :                 value = (time_t)2145914603;  /* 2037-12-31 23:23:23 */
    4642              : 
    4643              :         /* Convert to seconds since epoch */
    4644              :         } else {
    4645            7 :                 value = timegm (&when);
    4646            7 :                 g_return_val_if_fail (*time >= 0, FALSE);
    4647            7 :                 value += offset;
    4648              :         }
    4649              : 
    4650            7 :         return value;
    4651              : }
    4652              : 
    4653              : glong
    4654           11 : egg_asn1x_parse_time_utc (const gchar *time, gssize n_time)
    4655              : {
    4656              :         gboolean ret;
    4657              :         glong value;
    4658              :         struct tm when;
    4659           11 :         gint offset = 0;
    4660              : 
    4661           11 :         g_return_val_if_fail (time, -1);
    4662              : 
    4663           11 :         if (n_time < 0)
    4664           11 :                 n_time = strlen (time);
    4665              : 
    4666           11 :         ret = parse_utc_time (time, n_time, &when, &offset);
    4667           11 :         if (!ret)
    4668            1 :                 return -1;
    4669              : 
    4670              :         /* In order to work with 32 bit time_t. */
    4671              :         if (sizeof (time_t) <= 4 && when.tm_year >= 2038) {
    4672              :                 value = (time_t)2145914603;  /* 2037-12-31 23:23:23 */
    4673              : 
    4674              :         /* Convert to seconds since epoch */
    4675              :         } else {
    4676           10 :                 value = timegm (&when);
    4677           10 :                 g_return_val_if_fail (*time >= 0, FALSE);
    4678           10 :                 value += offset;
    4679              :         }
    4680              : 
    4681           10 :         return value;
    4682              : }
    4683              : 
    4684              : /* --------------------------------------------------------------------------------
    4685              :  * BASIC RAW ELEMENT INFO
    4686              :  */
    4687              : 
    4688              : gssize
    4689           33 : egg_asn1x_element_length (const guchar *data,
    4690              :                           gsize n_data)
    4691              : {
    4692              :         guchar cls;
    4693           33 :         int counter = 0;
    4694              :         int cb, len;
    4695              :         gulong tag;
    4696              : 
    4697           33 :         if (atlv_parse_cls_tag (data, data + n_data, &cls, &tag, &cb)) {
    4698           33 :                 counter += cb;
    4699           33 :                 len = atlv_parse_length (data + cb, data + n_data, &cb);
    4700           33 :                 counter += cb;
    4701           33 :                 if (len >= 0) {
    4702           31 :                         len += counter;
    4703           31 :                         if (n_data >= len)
    4704           31 :                                 return len;
    4705              :                 }
    4706              :         }
    4707              : 
    4708            2 :         return -1;
    4709              : }
    4710              : 
    4711              : gconstpointer
    4712            4 : egg_asn1x_element_content (const guchar *data,
    4713              :                            gsize n_data,
    4714              :                            gsize *n_content)
    4715              : {
    4716            4 :         int counter = 0;
    4717              :         guchar cls;
    4718              :         gulong tag;
    4719              :         int cb, len;
    4720              : 
    4721            4 :         g_return_val_if_fail (data != NULL, NULL);
    4722            4 :         g_return_val_if_fail (n_content != NULL, NULL);
    4723              : 
    4724              :         /* Now get the data out of this element */
    4725            4 :         if (!atlv_parse_cls_tag (data, data + n_data, &cls, &tag, &cb))
    4726            1 :                 return NULL;
    4727              : 
    4728            3 :         counter += cb;
    4729            3 :         len = atlv_parse_length (data + cb, data + n_data, &cb);
    4730            3 :         if (len < 0)
    4731            1 :                 return NULL;
    4732            2 :         counter += cb;
    4733              : 
    4734            2 :         *n_content = len;
    4735            2 :         return (const guchar*)data + counter;
    4736              : }
        

Generated by: LCOV version 2.0-1