LCOV - code coverage report
Current view: top level - src - asn1-func.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 233 641 36.3 %
Date: 2016-09-12 12:20:35 Functions: 18 32 56.2 %

          Line data    Source code
       1             : /* asn1-func.c - Fucntions for the ASN.1 data structures.
       2             :  *      Copyright (C) 2000, 2001 Fabio Fiorina
       3             :  *      Copyright (C) 2001 Free Software Foundation, Inc.
       4             :  *      Copyright (C) 2002, 2003, 2006, 2007, 2010, 2012 g10 Code GmbH
       5             :  *
       6             :  * KSBA is free software; you can redistribute it and/or modify
       7             :  * it under the terms of either
       8             :  *
       9             :  *   - the GNU Lesser General Public License as published by the Free
      10             :  *     Software Foundation; either version 3 of the License, or (at
      11             :  *     your option) any later version.
      12             :  *
      13             :  * or
      14             :  *
      15             :  *   - the GNU General Public License as published by the Free
      16             :  *     Software Foundation; either version 2 of the License, or (at
      17             :  *     your option) any later version.
      18             :  *
      19             :  * or both in parallel, as here.
      20             :  *
      21             :  * KSBA is distributed in the hope that it will be useful, but WITHOUT
      22             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      23             :  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      24             :  * License for more details.
      25             :  *
      26             :  * You should have received a copies of the GNU General Public License
      27             :  * and the GNU Lesser General Public License along with this program;
      28             :  * if not, see <http://www.gnu.org/licenses/>.
      29             :  */
      30             : 
      31             : #ifndef BUILD_GENTOOLS
      32             : #include <config.h>
      33             : #endif
      34             : 
      35             : #include <stdio.h>
      36             : #include <stdlib.h>
      37             : #include <string.h>
      38             : #include <ctype.h>
      39             : #include <assert.h>
      40             : 
      41             : #ifdef BUILD_GENTOOLS
      42             : # include "gen-help.h"
      43             : #else
      44             : # include "util.h"
      45             : # include "ksba.h"
      46             : #endif
      47             : 
      48             : #include "asn1-func.h"
      49             : 
      50             : 
      51             : static AsnNode resolve_identifier (AsnNode root, AsnNode node, int nestlevel);
      52             : 
      53             : 
      54             : static AsnNode
      55        3777 : add_node (node_type_t type)
      56             : {
      57             :   AsnNode punt;
      58             : 
      59        3777 :   punt = xmalloc (sizeof *punt);
      60             : 
      61        3777 :   punt->left = NULL;
      62        3777 :   punt->name = NULL;
      63        3777 :   punt->type = type;
      64        3777 :   punt->valuetype = VALTYPE_NULL;
      65        3777 :   punt->value.v_cstr = NULL;
      66        3777 :   punt->off = -1;
      67        3777 :   punt->nhdr = 0;
      68        3777 :   punt->len = 0;
      69        3777 :   punt->down = NULL;
      70        3777 :   punt->right = NULL;
      71        3777 :   punt->link_next = NULL;
      72        3777 :   return punt;
      73             : }
      74             : 
      75             : AsnNode
      76        3222 : _ksba_asn_new_node (node_type_t type)
      77             : {
      78        3222 :   return add_node (type);
      79             : }
      80             : 
      81             : 
      82             : int
      83         388 : _ksba_asn_is_primitive (node_type_t type)
      84             : {
      85         388 :   switch (type)
      86             :     {
      87             :     case TYPE_BOOLEAN:
      88             :     case TYPE_INTEGER:
      89             :     case TYPE_BIT_STRING:
      90             :     case TYPE_OCTET_STRING:
      91             :     case TYPE_NULL:
      92             :     case TYPE_OBJECT_ID:
      93             :     case TYPE_OBJECT_DESCRIPTOR:
      94             :     case TYPE_REAL:
      95             :     case TYPE_ENUMERATED:
      96             :     case TYPE_UTF8_STRING:
      97             :     case TYPE_REALTIVE_OID:
      98             :     case TYPE_NUMERIC_STRING:
      99             :     case TYPE_PRINTABLE_STRING:
     100             :     case TYPE_TELETEX_STRING:
     101             :     case TYPE_VIDEOTEX_STRING:
     102             :     case TYPE_IA5_STRING:
     103             :     case TYPE_UTC_TIME:
     104             :     case TYPE_GENERALIZED_TIME:
     105             :     case TYPE_GRAPHIC_STRING:
     106             :     case TYPE_VISIBLE_STRING:
     107             :     case TYPE_GENERAL_STRING:
     108             :     case TYPE_UNIVERSAL_STRING:
     109             :     case TYPE_CHARACTER_STRING:
     110             :     case TYPE_BMP_STRING:
     111             :     case TYPE_PRE_SEQUENCE:
     112         149 :       return 1;
     113             :     default:
     114         239 :       return 0;
     115             :     }
     116             : }
     117             : 
     118             : 
     119             : /* Change the value field of the node to the content of buffer value
     120             :    of size LEN.  With VALUE of NULL or LEN of 0 the value field is
     121             :    deleted */
     122             : void
     123        2544 : _ksba_asn_set_value (AsnNode node,
     124             :                      enum asn_value_type vtype, const void *value, size_t len)
     125             : {
     126        2544 :   return_if_fail (node);
     127             : 
     128        2544 :   if (node->valuetype)
     129             :     {
     130           0 :       if (node->valuetype == VALTYPE_CSTR)
     131           0 :         xfree (node->value.v_cstr);
     132           0 :       else if (node->valuetype == VALTYPE_MEM)
     133           0 :         xfree (node->value.v_mem.buf);
     134           0 :       node->valuetype = 0;
     135             :     }
     136             : 
     137        2544 :   switch (vtype)
     138             :     {
     139             :     case VALTYPE_NULL:
     140         507 :       break;
     141             :     case VALTYPE_BOOL:
     142           0 :       return_if_fail (len);
     143           0 :       node->value.v_bool = !!(const unsigned *)value;
     144           0 :       break;
     145             :     case VALTYPE_CSTR:
     146        1545 :       node->value.v_cstr = xstrdup (value);
     147        1545 :       break;
     148             :     case VALTYPE_MEM:
     149           0 :       node->value.v_mem.len = len;
     150           0 :       if (len)
     151             :         {
     152           0 :           node->value.v_mem.buf = xmalloc (len);
     153           0 :           memcpy (node->value.v_mem.buf, value, len);
     154             :         }
     155             :       else
     156           0 :           node->value.v_mem.buf = NULL;
     157           0 :       break;
     158             :     case VALTYPE_LONG:
     159           0 :       return_if_fail (sizeof (long) == len);
     160           0 :       node->value.v_long = *(long *)value;
     161           0 :       break;
     162             : 
     163             :     case VALTYPE_ULONG:
     164         492 :       return_if_fail (sizeof (unsigned long) == len);
     165         492 :       node->value.v_ulong = *(unsigned long *)value;
     166         492 :       break;
     167             : 
     168             :     default:
     169           0 :       return_if_fail (0);
     170             :     }
     171        2544 :   node->valuetype = vtype;
     172             : }
     173             : 
     174             : static void
     175         555 : copy_value (AsnNode d, const AsnNode s)
     176             : {
     177             :   char helpbuf[1];
     178         555 :   const void *buf = NULL;
     179         555 :   size_t len = 0;
     180             : 
     181         555 :   return_if_fail (d != s);
     182             : 
     183         555 :   switch (s->valuetype)
     184             :     {
     185             :     case VALTYPE_NULL:
     186         507 :       break;
     187             :     case VALTYPE_BOOL:
     188           0 :       len = 1;
     189           0 :       helpbuf[0] = s->value.v_bool;
     190           0 :       buf = helpbuf;
     191           0 :       break;
     192             :     case VALTYPE_CSTR:
     193          24 :       buf = s->value.v_cstr;
     194          24 :       break;
     195             :     case VALTYPE_MEM:
     196           0 :       len = s->value.v_mem.len;
     197           0 :       buf = len? s->value.v_mem.buf : NULL;
     198           0 :       break;
     199             :     case VALTYPE_LONG:
     200           0 :       len = sizeof (long);
     201           0 :       buf = &s->value.v_long;
     202           0 :       break;
     203             :     case VALTYPE_ULONG:
     204          24 :       len = sizeof (unsigned long);
     205          24 :       buf = &s->value.v_ulong;
     206          24 :       break;
     207             : 
     208             :     default:
     209           0 :       return_if_fail (0);
     210             :     }
     211         555 :   _ksba_asn_set_value (d, s->valuetype, buf, len);
     212         555 :   d->off = s->off;
     213         555 :   d->nhdr = s->nhdr;
     214         555 :   d->len = s->len;
     215             : }
     216             : 
     217             : static AsnNode
     218         555 : copy_node (const AsnNode s)
     219             : {
     220         555 :   AsnNode d = add_node (s->type);
     221             : 
     222         555 :   if (s->name)
     223         445 :     d->name = xstrdup (s->name);
     224         555 :   d->flags = s->flags;
     225         555 :   copy_value (d, s);
     226         555 :   return d;
     227             : }
     228             : 
     229             : 
     230             : 
     231             : 
     232             : /* Change the name field of the node to NAME.
     233             :    NAME may be NULL */
     234             : void
     235        2664 : _ksba_asn_set_name (AsnNode node, const char *name)
     236             : {
     237        5328 :   return_if_fail (node);
     238             : 
     239        2664 :   if (node->name)
     240             :     {
     241         171 :       xfree (node->name);
     242         171 :       node->name = NULL;
     243             :     }
     244             : 
     245        2664 :   if (name && *name)
     246        2604 :       node->name = xstrdup (name);
     247             : }
     248             : 
     249             : 
     250             : static AsnNode
     251           0 : set_right (AsnNode  node, AsnNode  right)
     252             : {
     253           0 :   if (node == NULL)
     254           0 :     return node;
     255             : 
     256           0 :   node->right = right;
     257           0 :   if (right)
     258           0 :     right->left = node;
     259           0 :   return node;
     260             : }
     261             : 
     262             : 
     263             : static AsnNode
     264           0 : set_down (AsnNode node, AsnNode down)
     265             : {
     266           0 :   if (node == NULL)
     267           0 :     return node;
     268             : 
     269           0 :   node->down = down;
     270           0 :   if (down)
     271           0 :     down->left = node;
     272           0 :   return node;
     273             : }
     274             : 
     275             : 
     276             : void
     277           0 : _ksba_asn_remove_node (AsnNode  node)
     278             : {
     279           0 :   if (node == NULL)
     280           0 :     return;
     281             : 
     282           0 :   xfree (node->name);
     283           0 :   if (node->valuetype == VALTYPE_CSTR)
     284           0 :     xfree (node->value.v_cstr);
     285           0 :   else if (node->valuetype == VALTYPE_MEM)
     286           0 :     xfree (node->value.v_mem.buf);
     287           0 :   xfree (node);
     288             : }
     289             : 
     290             : 
     291             : /* find the node with the given name.  A name part of "?LAST" matches
     292             :    the last element of a set of */
     293             : static AsnNode
     294         219 : find_node (AsnNode root, const char *name, int resolve)
     295             : {
     296             :   AsnNode p;
     297             :   const char *s;
     298             :   char buf[129];
     299             :   int i;
     300             : 
     301         219 :   if (!name || !name[0])
     302           0 :     return NULL;
     303             : 
     304             :   /* find the first part */
     305         219 :   s = name;
     306        1653 :   for (i=0; *s && *s != '.' && i < DIM(buf)-1; s++)
     307        1434 :     buf[i++] = *s;
     308         219 :   buf[i] = 0;
     309         219 :   return_null_if_fail (i < DIM(buf)-1);
     310             : 
     311         219 :   for (p = root; p && (!p->name || strcmp (p->name, buf)); p = p->right)
     312             :     ;
     313             : 
     314             :   /* find other parts */
     315         696 :   while (p && *s)
     316             :     {
     317         258 :       assert (*s == '.');
     318         258 :       s++; /* skip the dot */
     319             : 
     320         258 :       if (!p->down)
     321           0 :         return NULL; /* not found */
     322         258 :       p = p->down;
     323             : 
     324        3627 :       for (i=0; *s && *s != '.' && i < DIM(buf)-1; s++)
     325        3369 :         buf[i++] = *s;
     326         258 :       buf[i] = 0;
     327         258 :       return_null_if_fail (i < DIM(buf)-1);
     328             : 
     329         258 :       if (!*buf)
     330             :         {
     331             :          /* a double dot can be used to get over an unnamed sequence
     332             :             in a set - Actually a hack to workaround a bug.  We should
     333             :             rethink the entire node naming issue */
     334             :         }
     335         252 :       else if (!strcmp (buf, "?LAST"))
     336             :         {
     337           0 :           if (!p)
     338           0 :             return NULL;
     339           0 :           while (p->right)
     340           0 :             p = p->right;
     341             :         }
     342             :       else
     343             :         {
     344        2796 :           for (; p ; p = p->right)
     345             :             {
     346        2796 :               if (p->name && !strcmp (p->name, buf))
     347         252 :                 break;
     348        2544 :               if (resolve && p->name && p->type == TYPE_IDENTIFIER)
     349             :                 {
     350             :                   AsnNode p2;
     351             : 
     352           9 :                   p2 = resolve_identifier (root, p, 0);
     353           9 :                   if (p2 && p2->name && !strcmp (p2->name, buf))
     354           0 :                     break;
     355             :                 }
     356             :             }
     357             : 
     358         252 :           if (resolve && p && p->type == TYPE_IDENTIFIER)
     359           6 :             p = resolve_identifier (root, p, 0);
     360             :         }
     361             :     }
     362             : 
     363         219 :   return p;
     364             : }
     365             : 
     366             : AsnNode
     367         210 : _ksba_asn_find_node (AsnNode root, const char *name)
     368             : {
     369         210 :   return find_node (root, name, 0);
     370             : }
     371             : 
     372             : 
     373             : static AsnNode
     374           0 : _asn1_find_left (AsnNode  node)
     375             : {
     376           0 :   if ((node == NULL) || (node->left == NULL) || (node->left->down == node))
     377           0 :     return NULL;
     378             : 
     379           0 :   return node->left;
     380             : }
     381             : 
     382             : 
     383             : static AsnNode
     384        3252 : find_up (AsnNode  node)
     385             : {
     386             :   AsnNode p;
     387             : 
     388        3252 :   if (node == NULL)
     389           0 :     return NULL;
     390             : 
     391        3252 :   p = node;
     392       10726 :   while ((p->left != NULL) && (p->left->right == p))
     393        4222 :     p = p->left;
     394             : 
     395        3252 :   return p->left;
     396             : }
     397             : 
     398             : 
     399             : 
     400             : static void
     401           0 : print_value (AsnNode node, FILE *fp)
     402             : {
     403           0 :   if (!node->valuetype)
     404           0 :     return;
     405           0 :   fprintf (fp, " vt=%d val=", node->valuetype);
     406           0 :   switch (node->valuetype)
     407             :     {
     408             :     case VALTYPE_BOOL:
     409           0 :       fputs (node->value.v_bool? "True":"False", fp);
     410           0 :       break;
     411             :     case VALTYPE_CSTR:
     412           0 :       fputs (node->value.v_cstr, fp);
     413           0 :       break;
     414             :     case VALTYPE_MEM:
     415             :       {
     416             :         size_t n;
     417             :         unsigned char *p;
     418           0 :         for (p=node->value.v_mem.buf, n=node->value.v_mem.len; n; n--, p++)
     419           0 :           fprintf (fp, "%02X", *p);
     420             :       }
     421           0 :       break;
     422             :     case VALTYPE_LONG:
     423           0 :       fprintf (fp, "%ld", node->value.v_long);
     424           0 :       break;
     425             :     case VALTYPE_ULONG:
     426           0 :       fprintf (fp, "%lu", node->value.v_ulong);
     427           0 :       break;
     428             :     default:
     429           0 :       return_if_fail (0);
     430             :     }
     431             : }
     432             : 
     433             : void
     434           0 : _ksba_asn_node_dump (AsnNode p, FILE *fp)
     435             : {
     436             :   const char *typestr;
     437             : 
     438           0 :   switch (p->type)
     439             :     {
     440           0 :     case TYPE_NULL:         typestr = "NULL"; break;
     441           0 :     case TYPE_CONSTANT:     typestr = "CONST"; break;
     442           0 :     case TYPE_IDENTIFIER:   typestr = "IDENTIFIER"; break;
     443           0 :     case TYPE_INTEGER:      typestr = "INTEGER"; break;
     444           0 :     case TYPE_ENUMERATED:   typestr = "ENUMERATED"; break;
     445           0 :     case TYPE_UTC_TIME:     typestr = "UTCTIME"; break;
     446           0 :     case TYPE_GENERALIZED_TIME: typestr = "GENERALIZEDTIME"; break;
     447           0 :     case TYPE_BOOLEAN:      typestr = "BOOLEAN"; break;
     448           0 :     case TYPE_SEQUENCE:     typestr = "SEQUENCE"; break;
     449           0 :     case TYPE_PRE_SEQUENCE: typestr = "PRE_SEQUENCE"; break;
     450           0 :     case TYPE_BIT_STRING:   typestr = "BIT_STR"; break;
     451           0 :     case TYPE_OCTET_STRING: typestr = "OCT_STR"; break;
     452           0 :     case TYPE_TAG:          typestr = "TAG"; break;
     453           0 :     case TYPE_DEFAULT:      typestr = "DEFAULT"; break;
     454           0 :     case TYPE_SIZE:         typestr = "SIZE"; break;
     455           0 :     case TYPE_SEQUENCE_OF:  typestr = "SEQ_OF"; break;
     456           0 :     case TYPE_OBJECT_ID:    typestr = "OBJ_ID"; break;
     457           0 :     case TYPE_ANY:          typestr = "ANY"; break;
     458           0 :     case TYPE_SET:          typestr = "SET"; break;
     459           0 :     case TYPE_SET_OF:       typestr = "SET_OF"; break;
     460           0 :     case TYPE_CHOICE:       typestr = "CHOICE"; break;
     461           0 :     case TYPE_DEFINITIONS:  typestr = "DEFINITIONS"; break;
     462           0 :     case TYPE_UTF8_STRING:       typestr = "UTF8_STRING"; break;
     463           0 :     case TYPE_NUMERIC_STRING:    typestr = "NUMERIC_STRING"; break;
     464           0 :     case TYPE_PRINTABLE_STRING:  typestr = "PRINTABLE_STRING"; break;
     465           0 :     case TYPE_TELETEX_STRING:    typestr = "TELETEX_STRING"; break;
     466           0 :     case TYPE_IA5_STRING:        typestr = "IA5_STRING"; break;
     467           0 :     default:                typestr = "ERROR\n"; break;
     468             :     }
     469             : 
     470           0 :   fprintf (fp, "%s", typestr);
     471           0 :   if (p->name)
     472           0 :     fprintf (fp, " `%s'", p->name);
     473           0 :   print_value (p, fp);
     474           0 :   fputs ("  ", fp);
     475           0 :   switch (p->flags.class)
     476             :     {
     477           0 :     case CLASS_UNIVERSAL:   fputs ("U", fp); break;
     478           0 :     case CLASS_PRIVATE:     fputs ("P", fp); break;
     479           0 :     case CLASS_APPLICATION: fputs ("A", fp); break;
     480           0 :     case CLASS_CONTEXT:     fputs ("C", fp); break;
     481             :     }
     482             : 
     483           0 :   if (p->flags.explicit)
     484           0 :     fputs (",explicit", fp);
     485           0 :   if (p->flags.implicit)
     486           0 :     fputs (",implicit", fp);
     487           0 :   if (p->flags.is_implicit)
     488           0 :     fputs (",is_implicit", fp);
     489           0 :   if (p->flags.has_tag)
     490           0 :     fputs (",tag", fp);
     491           0 :   if (p->flags.has_default)
     492           0 :     fputs (",default", fp);
     493           0 :   if (p->flags.is_true)
     494           0 :     fputs (",true", fp);
     495           0 :   if (p->flags.is_false)
     496           0 :     fputs (",false", fp);
     497           0 :   if (p->flags.has_list)
     498           0 :     fputs (",list", fp);
     499           0 :   if (p->flags.has_min_max)
     500           0 :     fputs (",min_max", fp);
     501           0 :   if (p->flags.is_optional)
     502           0 :     fputs (",optional", fp);
     503           0 :   if (p->flags.one_param)
     504           0 :     fputs (",1_param", fp);
     505           0 :   if (p->flags.has_size)
     506           0 :     fputs (",size", fp);
     507           0 :   if (p->flags.has_defined_by)
     508           0 :     fputs (",def_by", fp);
     509           0 :   if (p->flags.has_imports)
     510           0 :     fputs (",imports", fp);
     511           0 :   if (p->flags.assignment)
     512           0 :     fputs (",assign",fp);
     513           0 :   if (p->flags.in_set)
     514           0 :     fputs (",in_set",fp);
     515           0 :   if (p->flags.in_choice)
     516           0 :     fputs (",in_choice",fp);
     517           0 :   if (p->flags.in_array)
     518           0 :     fputs (",in_array",fp);
     519           0 :   if (p->flags.not_used)
     520           0 :     fputs (",not_used",fp);
     521           0 :   if (p->flags.skip_this)
     522           0 :     fputs (",[skip]",fp);
     523           0 :   if (p->flags.is_any)
     524           0 :     fputs (",is_any",fp);
     525           0 :   if (p->off != -1 )
     526           0 :     fprintf (fp, " %d.%d.%d", p->off, p->nhdr, p->len );
     527             : 
     528           0 : }
     529             : 
     530             : void
     531           0 : _ksba_asn_node_dump_all (AsnNode root, FILE *fp)
     532             : {
     533           0 :   AsnNode p = root;
     534           0 :   int indent = 0;
     535             : 
     536           0 :   while (p)
     537             :     {
     538           0 :       fprintf (fp, "%*s", indent, "");
     539           0 :       _ksba_asn_node_dump (p, fp);
     540           0 :       putc ('\n', fp);
     541             : 
     542           0 :       if (p->down)
     543             :         {
     544           0 :           p = p->down;
     545           0 :           indent += 2;
     546             :         }
     547           0 :       else if (p == root)
     548             :         {
     549           0 :           p = NULL;
     550           0 :           break;
     551             :         }
     552           0 :       else if (p->right)
     553           0 :         p = p->right;
     554             :       else
     555             :         {
     556             :           while (1)
     557             :             {
     558           0 :               p = find_up (p);
     559           0 :               if (p == root)
     560             :                 {
     561           0 :                   p = NULL;
     562           0 :                   break;
     563             :                 }
     564           0 :               indent -= 2;
     565           0 :               if (p->right)
     566             :                 {
     567           0 :                   p = p->right;
     568           0 :                   break;
     569             :                 }
     570           0 :             }
     571             :         }
     572             :     }
     573           0 : }
     574             : 
     575             : /**
     576             :  * ksba_asn_tree_dump:
     577             :  * @tree: A Parse Tree
     578             :  * @name: Name of the element or NULL
     579             :  * @fp: dump to this stream
     580             :  *
     581             :  * If the first character of the name is a '<' the expanded version of
     582             :  * the tree will be printed.
     583             :  *
     584             :  * This function is a debugging aid.
     585             :  **/
     586             : void
     587           0 : ksba_asn_tree_dump (ksba_asn_tree_t tree, const char *name, FILE *fp)
     588             : {
     589             :   AsnNode p, root;
     590           0 :   int k, expand=0, indent = 0;
     591             : 
     592           0 :   if (!tree || !tree->parse_tree)
     593           0 :     return;
     594             : 
     595           0 :   if ( name && *name== '<')
     596             :     {
     597           0 :       expand = 1;
     598           0 :       name++;
     599           0 :       if (!*name)
     600           0 :         name = NULL;
     601             :     }
     602             : 
     603           0 :   root = name? _ksba_asn_find_node (tree->parse_tree, name) : tree->parse_tree;
     604           0 :   if (!root)
     605           0 :     return;
     606             : 
     607           0 :   if (expand)
     608           0 :     root = _ksba_asn_expand_tree (root, NULL);
     609             : 
     610           0 :   p = root;
     611           0 :   while (p)
     612             :     {
     613           0 :       for (k = 0; k < indent; k++)
     614           0 :         fprintf (fp, " ");
     615           0 :       _ksba_asn_node_dump (p, fp);
     616           0 :       putc ('\n', fp);
     617             : 
     618           0 :       if (p->down)
     619             :         {
     620           0 :           p = p->down;
     621           0 :           indent += 2;
     622             :         }
     623           0 :       else if (p == root)
     624             :         {
     625           0 :           p = NULL;
     626           0 :           break;
     627             :         }
     628           0 :       else if (p->right)
     629           0 :         p = p->right;
     630             :       else
     631             :         {
     632             :           while (1)
     633             :             {
     634           0 :               p = find_up (p);
     635           0 :               if (p == root)
     636             :                 {
     637           0 :                   p = NULL;
     638           0 :                   break;
     639             :                 }
     640           0 :               indent -= 2;
     641           0 :               if (p->right)
     642             :                 {
     643           0 :                   p = p->right;
     644           0 :                   break;
     645             :                 }
     646           0 :             }
     647             :         }
     648             :     }
     649             : 
     650           0 :   if (expand)
     651           0 :     _ksba_asn_release_nodes (root);
     652             : }
     653             : 
     654             : int
     655           0 : _ksba_asn_delete_structure (AsnNode root)
     656             : {
     657             :   AsnNode p, p2, p3;
     658             : 
     659           0 :   if (root == NULL)
     660           0 :     return gpg_error (GPG_ERR_ELEMENT_NOT_FOUND);
     661             : 
     662           0 :   p = root;
     663           0 :   while (p)
     664             :     {
     665           0 :       if (p->down)
     666             :         {
     667           0 :           p = p->down;
     668             :         }
     669             :       else
     670             :         {                       /* no down */
     671           0 :           p2 = p->right;
     672           0 :           if (p != root)
     673             :             {
     674           0 :               p3 = find_up (p);
     675           0 :               set_down (p3, p2);
     676           0 :               _ksba_asn_remove_node (p);
     677           0 :               p = p3;
     678             :             }
     679             :           else
     680             :             {                   /* p==root */
     681           0 :               p3 = _asn1_find_left (p);
     682           0 :               if (!p3)
     683             :                 {
     684           0 :                   p3 = find_up (p);
     685           0 :                   if (p3)
     686           0 :                     set_down (p3, p2);
     687             :                   else
     688             :                     {
     689           0 :                       if (p->right)
     690           0 :                         p->right->left = NULL;
     691             :                     }
     692             :                 }
     693             :               else
     694           0 :                 set_right (p3, p2);
     695           0 :               _ksba_asn_remove_node (p);
     696           0 :               p = NULL;
     697             :             }
     698             :         }
     699             :     }
     700           0 :   return 0;
     701             : }
     702             : 
     703             : 
     704             : /* check that all identifiers referenced in the tree are available */
     705             : int
     706           0 : _ksba_asn_check_identifier (AsnNode node)
     707             : {
     708             :   AsnNode p, p2;
     709             :   char name2[129];
     710             : 
     711           0 :   if (!node)
     712           0 :     return gpg_error (GPG_ERR_ELEMENT_NOT_FOUND);
     713             : 
     714           0 :   for (p = node; p; p = _ksba_asn_walk_tree (node, p))
     715             :     {
     716           0 :       if (p->type == TYPE_IDENTIFIER && p->valuetype == VALTYPE_CSTR)
     717             :         {
     718           0 :           if (strlen (node->name)+strlen(p->value.v_cstr)+2 > DIM(name2))
     719           0 :             return gpg_error (GPG_ERR_BUG); /* well identifier too long */
     720           0 :           strcpy (name2, node->name);
     721           0 :           strcat (name2, ".");
     722           0 :           strcat (name2, p->value.v_cstr);
     723           0 :           p2 = _ksba_asn_find_node (node, name2);
     724           0 :           if (!p2)
     725             :             {
     726           0 :               fprintf (stderr,"reference to `%s' not found\n", name2);
     727           0 :               return gpg_error (GPG_ERR_IDENTIFIER_NOT_FOUND);
     728             :             }
     729             : /*            fprintf (stdout,"found reference for `%s' (", name2); */
     730             : /*            print_node (p2, stdout); */
     731             : /*            fputs (")\n", stdout); */
     732             :         }
     733           0 :       else if (p->type == TYPE_OBJECT_ID && p->flags.assignment)
     734             :         { /* an object ID in an assignment */
     735           0 :           p2 = p->down;
     736           0 :           if (p2 && (p2->type == TYPE_CONSTANT))
     737             :             {
     738           0 :               if (p2->valuetype == VALTYPE_CSTR && !isdigit (p2->value.v_cstr[0]))
     739             :                 { /* the first constand below is a reference */
     740           0 :                   if (strlen (node->name)
     741           0 :                       +strlen(p->value.v_cstr)+2 > DIM(name2))
     742           0 :                     return gpg_error (GPG_ERR_BUG); /* well identifier too long */
     743           0 :                   strcpy (name2, node->name);
     744           0 :                   strcat (name2, ".");
     745           0 :                   strcat (name2, p2->value.v_cstr);
     746           0 :                   p2 = _ksba_asn_find_node (node, name2);
     747           0 :                   if (!p2)
     748             :                     {
     749           0 :                       fprintf (stderr,"object id reference `%s' not found\n",
     750             :                                name2);
     751           0 :                       return gpg_error (GPG_ERR_IDENTIFIER_NOT_FOUND);
     752             :                     }
     753           0 :                   else if ( p2->type != TYPE_OBJECT_ID
     754           0 :                             || !p2->flags.assignment )
     755             :                     {
     756           0 :                       fprintf (stderr,"`%s' is not an object id\n", name2);
     757           0 :                       return gpg_error (GPG_ERR_IDENTIFIER_NOT_FOUND);
     758             :                     }
     759             : /*                    fprintf (stdout,"found objid reference for `%s' (", name2); */
     760             : /*                    print_node (p2, stdout); */
     761             : /*                    fputs (")\n", stdout); */
     762             :                 }
     763             :             }
     764             :         }
     765             :     }
     766             : 
     767           0 :   return 0;
     768             : }
     769             : 
     770             : 
     771             : /* Get the next node until root is reached in which case NULL is
     772             :    returned */
     773             : AsnNode
     774        7605 : _ksba_asn_walk_tree (AsnNode root, AsnNode node)
     775             : {
     776        7605 :   if (!node)
     777             :     ;
     778        7605 :   else if (node->down)
     779        3252 :     node = node->down;
     780             :   else
     781             :     {
     782        4353 :       if (node == root)
     783           0 :         node = NULL;
     784        4353 :       else if (node->right)
     785        2079 :         node = node->right;
     786             :       else
     787             :         {
     788             :           for (;;)
     789             :             {
     790        3252 :               node = find_up (node);
     791        3252 :               if (node == root)
     792             :                 {
     793         131 :                   node = NULL;
     794         131 :                   break;
     795             :                 }
     796        3121 :               if (node->right)
     797             :                 {
     798        2143 :                   node = node->right;
     799        2143 :                   break;
     800             :                 }
     801         978 :             }
     802             :         }
     803             :     }
     804             : 
     805        7605 :   return node;
     806             : }
     807             : 
     808             : AsnNode
     809           0 : _ksba_asn_walk_tree_up_right (AsnNode root, AsnNode node)
     810             : {
     811           0 :   if (node)
     812             :     {
     813           0 :       if (node == root)
     814           0 :         node = NULL;
     815             :       else
     816             :         {
     817             :           for (;;)
     818             :             {
     819           0 :               node = find_up (node);
     820           0 :               if (node == root)
     821             :                 {
     822           0 :                   node = NULL;
     823           0 :                   break;
     824             :                 }
     825           0 :               if (node->right)
     826             :                 {
     827           0 :                   node = node->right;
     828           0 :                   break;
     829             :                 }
     830           0 :             }
     831             :         }
     832             :     }
     833             : 
     834           0 :   return node;
     835             : }
     836             : 
     837             : /* walk over the tree and change the value type of all integer types
     838             :    from string to long. */
     839             : int
     840           9 : _ksba_asn_change_integer_value (AsnNode node)
     841             : {
     842             :   AsnNode p;
     843             : 
     844           9 :   if (node == NULL)
     845           0 :     return gpg_error (GPG_ERR_ELEMENT_NOT_FOUND);
     846             : 
     847        3231 :   for (p = node; p; p = _ksba_asn_walk_tree (node, p))
     848             :     {
     849        3222 :       if (p->type == TYPE_INTEGER && p->flags.assignment)
     850             :         {
     851           0 :           if (p->valuetype == VALTYPE_CSTR)
     852             :             {
     853           0 :               long val = strtol (p->value.v_cstr, NULL, 10);
     854           0 :               _ksba_asn_set_value (p, VALTYPE_LONG, &val, sizeof(val));
     855             :             }
     856             :         }
     857             :     }
     858             : 
     859           9 :   return 0;
     860             : }
     861             : 
     862             : 
     863             : 
     864             : /* Expand all object ID constants */
     865             : int
     866           9 : _ksba_asn_expand_object_id (AsnNode node)
     867             : {
     868             :   AsnNode p, p2, p3, p4, p5;
     869             :   char name_root[129], name2[129*2+1];
     870             : 
     871             :   /* Fixme: Make a cleaner implementation */
     872           9 :   if (!node)
     873           0 :     return gpg_error (GPG_ERR_ELEMENT_NOT_FOUND);
     874           9 :   if (!node->name)
     875           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     876           9 :   if (strlen(node->name) >= DIM(name_root)-1)
     877           0 :     return gpg_error (GPG_ERR_GENERAL);
     878           9 :   strcpy (name_root, node->name);
     879             : 
     880             :  restart:
     881        3231 :   for (p = node; p; p = _ksba_asn_walk_tree (node, p))
     882             :     {
     883        3222 :       if (p->type == TYPE_OBJECT_ID && p->flags.assignment)
     884             :         {
     885           9 :           p2 = p->down;
     886           9 :           if (p2 && p2->type == TYPE_CONSTANT)
     887             :             {
     888           9 :               if (p2->valuetype == VALTYPE_CSTR
     889           9 :                   && !isdigit (p2->value.v_cstr[0]))
     890             :                 {
     891           0 :                   if (strlen(p2->value.v_cstr)+1+strlen(name2) >= DIM(name2)-1)
     892           0 :                     return gpg_error (GPG_ERR_GENERAL);
     893           0 :                   strcpy (name2, name_root);
     894           0 :                   strcat (name2, ".");
     895           0 :                   strcat (name2, p2->value.v_cstr);
     896           0 :                   p3 = _ksba_asn_find_node (node, name2);
     897           0 :                   if (!p3 || p3->type != TYPE_OBJECT_ID ||
     898           0 :                       !p3->flags.assignment)
     899           0 :                     return gpg_error (GPG_ERR_ELEMENT_NOT_FOUND);
     900           0 :                   set_down (p, p2->right);
     901           0 :                   _ksba_asn_remove_node (p2);
     902           0 :                   p2 = p;
     903           0 :                   p4 = p3->down;
     904           0 :                   while (p4)
     905             :                     {
     906           0 :                       if (p4->type == TYPE_CONSTANT)
     907             :                         {
     908           0 :                           p5 = add_node (TYPE_CONSTANT);
     909           0 :                           _ksba_asn_set_name (p5, p4->name);
     910           0 :                           _ksba_asn_set_value (p5, VALTYPE_CSTR,
     911           0 :                                                p4->value.v_cstr, 0);
     912           0 :                           if (p2 == p)
     913             :                             {
     914           0 :                               set_right (p5, p->down);
     915           0 :                               set_down (p, p5);
     916             :                             }
     917             :                           else
     918             :                             {
     919           0 :                               set_right (p5, p2->right);
     920           0 :                               set_right (p2, p5);
     921             :                             }
     922           0 :                           p2 = p5;
     923             :                         }
     924           0 :                       p4 = p4->right;
     925             :                     }
     926           0 :                   goto restart;  /* the most simple way to get it right ;-) */
     927             :                 }
     928             :             }
     929             :         }
     930             :     }
     931           9 :   return 0;
     932             : }
     933             : 
     934             : /* Walk the parse tree and set the default tag where appropriate.  The
     935             :    node must be of type DEFINITIONS */
     936             : void
     937           0 : _ksba_asn_set_default_tag (AsnNode node)
     938             : {
     939             :   AsnNode p;
     940             : 
     941           0 :   return_if_fail (node && node->type == TYPE_DEFINITIONS);
     942             : 
     943           0 :   for (p = node; p; p = _ksba_asn_walk_tree (node, p))
     944             :     {
     945           0 :       if ( p->type == TYPE_TAG
     946           0 :            && !p->flags.explicit && !p->flags.implicit)
     947             :         {
     948           0 :           if (node->flags.explicit)
     949           0 :             p->flags.explicit = 1;
     950             :           else
     951           0 :             p->flags.implicit = 1;
     952             :         }
     953             :     }
     954             :   /* now mark the nodes which are implicit */
     955           0 :   for (p = node; p; p = _ksba_asn_walk_tree (node, p))
     956             :     {
     957           0 :       if ( p->type == TYPE_TAG && p->flags.implicit && p->down)
     958             :         {
     959           0 :           if (p->down->type == TYPE_CHOICE)
     960             :             ; /* a CHOICE is per se implicit */
     961           0 :           else if (p->down->type != TYPE_TAG)
     962           0 :             p->down->flags.is_implicit = 1;
     963             :         }
     964             :     }
     965             : }
     966             : 
     967             : /* Walk the tree and set the is_set and not_used flags for all nodes below
     968             :    a node of type SET. */
     969             : void
     970           0 : _ksba_asn_type_set_config (AsnNode node)
     971             : {
     972             :   AsnNode p, p2;
     973             : 
     974           0 :   return_if_fail (node && node->type == TYPE_DEFINITIONS);
     975             : 
     976           0 :   for (p = node; p; p = _ksba_asn_walk_tree (node, p))
     977             :     {
     978           0 :       if (p->type == TYPE_SET)
     979             :         {
     980           0 :           for (p2 = p->down; p2; p2 = p2->right)
     981             :             {
     982           0 :               if (p2->type != TYPE_TAG)
     983             :                 {
     984           0 :                   p2->flags.in_set = 1;
     985           0 :                   p2->flags.not_used = 1;
     986             :                 }
     987             :             }
     988             :         }
     989           0 :       else if (p->type == TYPE_CHOICE)
     990             :         {
     991           0 :           for (p2 = p->down; p2; p2 = p2->right)
     992             :             {
     993           0 :                 p2->flags.in_choice = 1;
     994             :             }
     995             :         }
     996           0 :       else if (p->type == TYPE_SEQUENCE_OF || p->type == TYPE_SET_OF)
     997             :         {
     998           0 :           for (p2 = p->down; p2; p2 = p2->right)
     999           0 :             p2->flags.in_array = 1;
    1000             :         }
    1001           0 :       else if (p->type == TYPE_ANY)
    1002             :         { /* Help the DER encoder to track ANY tags */
    1003           0 :           p->flags.is_any = 1;
    1004             :         }
    1005             :     }
    1006             : }
    1007             : 
    1008             : /* Create a copy the tree at SRC_ROOT. s is a helper which should be
    1009             :    set to SRC_ROOT by the caller */
    1010             : static AsnNode
    1011         147 : copy_tree (AsnNode src_root, AsnNode s)
    1012             : {
    1013         147 :   AsnNode first=NULL, dprev=NULL, d, down, tmp;
    1014         147 :   AsnNode *link_nextp = NULL;
    1015             : 
    1016         360 :   for (; s; s=s->right )
    1017             :     {
    1018         213 :       down = s->down;
    1019         213 :       d = copy_node (s);
    1020         213 :       if (link_nextp)
    1021          66 :         *link_nextp = d;
    1022         213 :       link_nextp = &d->link_next;
    1023             : 
    1024         213 :       if (!first)
    1025         147 :         first = d;
    1026             :       else
    1027             :         {
    1028          66 :           dprev->right = d;
    1029          66 :           d->left = dprev;
    1030             :         }
    1031         213 :       dprev = d;
    1032         213 :       if (down)
    1033             :         {
    1034          98 :           tmp = copy_tree (src_root, down);
    1035          98 :           if (tmp)
    1036             :             {
    1037          98 :               if (link_nextp)
    1038          98 :                 *link_nextp = tmp;
    1039          98 :               link_nextp = &tmp->link_next;
    1040         343 :               while (*link_nextp)
    1041         147 :                 link_nextp = &(*link_nextp)->link_next;
    1042             :             }
    1043             : 
    1044          98 :           if (d->down && tmp)
    1045           0 :             { /* Need to merge it with the existing down */
    1046             :               AsnNode x;
    1047             : 
    1048           0 :               for (x=d->down; x->right; x = x->right)
    1049             :                 ;
    1050           0 :               x->right = tmp;
    1051           0 :               tmp->left = x;
    1052             :             }
    1053             :           else
    1054             :             {
    1055          98 :               d->down = tmp;
    1056          98 :               if (d->down)
    1057          98 :                 d->down->left = d;
    1058             :             }
    1059             :         }
    1060             :     }
    1061         147 :   return first;
    1062             : }
    1063             : 
    1064             : 
    1065             : 
    1066             : static AsnNode
    1067         186 : resolve_identifier (AsnNode root, AsnNode node, int nestlevel)
    1068             : {
    1069             :   char buf_space[50];
    1070             :   char *buf;
    1071             :   AsnNode n;
    1072             :   size_t bufsize;
    1073             : 
    1074         186 :   if (nestlevel > 20)
    1075           0 :     return NULL;
    1076             : 
    1077         186 :   return_null_if_fail (root);
    1078         186 :   return_null_if_fail (node->valuetype == VALTYPE_CSTR);
    1079             : 
    1080         186 :   bufsize = strlen (root->name) + strlen (node->value.v_cstr) + 2;
    1081         186 :   if (bufsize <= sizeof buf_space)
    1082         186 :     buf = buf_space;
    1083             :   else
    1084             :     {
    1085           0 :       buf = xtrymalloc (bufsize);
    1086           0 :       return_null_if_fail (buf);
    1087             :     }
    1088         186 :   strcpy (stpcpy (stpcpy (buf, root->name), "."), node->value.v_cstr);
    1089         186 :   n = _ksba_asn_find_node (root, buf);
    1090             : 
    1091             :   /* We do just a simple indirection. */
    1092         186 :   if (n && n->type == TYPE_IDENTIFIER)
    1093           0 :     n = resolve_identifier (root, n, nestlevel+1);
    1094             : 
    1095         186 :   if (buf != buf_space)
    1096           0 :     xfree (buf);
    1097             : 
    1098         186 :   return n;
    1099             : }
    1100             : 
    1101             : 
    1102             : static AsnNode
    1103         189 : do_expand_tree (AsnNode src_root, AsnNode s, int depth)
    1104             : {
    1105         189 :   AsnNode first=NULL, dprev=NULL, d, down, tmp;
    1106         189 :   AsnNode *link_nextp = NULL;
    1107             : 
    1108             :   /* On the very first level we do not follow the right pointer so that
    1109             :      we can break out a valid subtree. */
    1110         537 :   for (; s; s=depth?s->right:NULL )
    1111             :     {
    1112         348 :       if (s->type == TYPE_SIZE)
    1113           6 :         continue; /* this node gets in the way all the time.  It
    1114             :                      should be an attribute to a node */
    1115             : 
    1116         342 :       down = s->down;
    1117         342 :       if (s->type == TYPE_IDENTIFIER)
    1118             :         {
    1119             :           AsnNode s2, *dp;
    1120             : 
    1121         171 :           d = resolve_identifier (src_root, s, 0);
    1122         171 :           if (!d)
    1123             :             {
    1124           0 :               fprintf (stderr, "RESOLVING IDENTIFIER FAILED\n");
    1125           0 :               continue;
    1126             :             }
    1127         171 :           down = d->down;
    1128         171 :           d = copy_node (d);
    1129         171 :           if (link_nextp)
    1130          69 :             *link_nextp = d;
    1131         171 :           link_nextp = &d->link_next;
    1132         171 :           if (s->flags.is_optional)
    1133           0 :             d->flags.is_optional = 1;
    1134         171 :           if (s->flags.in_choice)
    1135          15 :             d->flags.in_choice = 1;
    1136         171 :           if (s->flags.in_array)
    1137          36 :             d->flags.in_array = 1;
    1138         171 :           if (s->flags.is_implicit)
    1139          12 :             d->flags.is_implicit = 1;
    1140         171 :           if (s->flags.is_any)
    1141           0 :             d->flags.is_any = 1;
    1142             :           /* we don't want the resolved name - change it back */
    1143         171 :           _ksba_asn_set_name (d, s->name);
    1144             :           /* copy the default and tag attributes */
    1145         171 :           tmp = NULL;
    1146         171 :           dp = &tmp;
    1147         171 :           for (s2=s->down; s2; s2=s2->right)
    1148             :             {
    1149             :               AsnNode x;
    1150             : 
    1151           0 :               x = copy_node (s2);
    1152           0 :               if (link_nextp)
    1153           0 :                 *link_nextp = x;
    1154           0 :               link_nextp = &x->link_next;
    1155           0 :               x->left = *dp? *dp : d;
    1156           0 :               *dp = x;
    1157           0 :               dp = &(*dp)->right;
    1158             : 
    1159           0 :               if (x->type == TYPE_TAG)
    1160           0 :                 d->flags.has_tag =1;
    1161           0 :               else if (x->type == TYPE_DEFAULT)
    1162           0 :                 d->flags.has_default =1;
    1163             :             }
    1164         171 :           d->down = tmp;
    1165             :         }
    1166             :       else
    1167             :         {
    1168         171 :           d = copy_node (s);
    1169         171 :           if (link_nextp)
    1170          84 :             *link_nextp = d;
    1171         171 :           link_nextp = &d->link_next;
    1172             :         }
    1173             : 
    1174         342 :       if (!first)
    1175         189 :         first = d;
    1176             :       else
    1177             :         {
    1178         153 :           dprev->right = d;
    1179         153 :           d->left = dprev;
    1180             :         }
    1181         342 :       dprev = d;
    1182         342 :       if (down)
    1183             :         {
    1184         180 :           if (depth >= 1000)
    1185             :             {
    1186           0 :               fprintf (stderr, "ASN.1 TREE TOO TALL!\n");
    1187           0 :               tmp = NULL;
    1188             :             }
    1189             :           else
    1190             :             {
    1191         180 :               tmp = do_expand_tree (src_root, down, depth+1);
    1192         180 :               if (tmp)
    1193             :                 {
    1194         180 :                   if (link_nextp)
    1195         180 :                     *link_nextp = tmp;
    1196         180 :                   link_nextp = &tmp->link_next;
    1197        1308 :                   while (*link_nextp)
    1198         948 :                     link_nextp = &(*link_nextp)->link_next;
    1199             :                 }
    1200             :             }
    1201         180 :           if (d->down && tmp)
    1202           0 :             { /* Need to merge it with the existing down */
    1203             :               AsnNode x;
    1204             : 
    1205           0 :               for (x=d->down; x->right; x = x->right)
    1206             :                 ;
    1207           0 :               x->right = tmp;
    1208           0 :               tmp->left = x;
    1209             :             }
    1210             :           else
    1211             :             {
    1212         180 :               d->down = tmp;
    1213         180 :               if (d->down)
    1214         180 :                 d->down->left = d;
    1215             :             }
    1216             :         }
    1217             :     }
    1218             : 
    1219         189 :   return first;
    1220             : }
    1221             : 
    1222             : 
    1223             : /* Expand the syntax tree so that all references are resolved and we
    1224             :    are able to store values right in the tree (except for set/sequence
    1225             :    of).  This expanded tree is also an requirement for doing the DER
    1226             :    decoding as the resolving of identifiers leads to a lot of
    1227             :    problems.  We use more memory of course, but this is negligible
    1228             :    because the entire code will be simpler and faster */
    1229             : AsnNode
    1230           9 : _ksba_asn_expand_tree (AsnNode parse_tree, const char *name)
    1231             : {
    1232             :   AsnNode root;
    1233             : 
    1234           9 :   root = name? find_node (parse_tree, name, 1) : parse_tree;
    1235           9 :   return do_expand_tree (parse_tree, root, 0);
    1236             : }
    1237             : 
    1238             : 
    1239             : /* Insert a copy of the entire tree at NODE as the sibling of itself
    1240             :    and return the copy */
    1241             : AsnNode
    1242          49 : _ksba_asn_insert_copy (AsnNode node)
    1243             : {
    1244             :   AsnNode n;
    1245             :   AsnNode *link_nextp;
    1246             : 
    1247          49 :   n = copy_tree (node, node);
    1248          49 :   if (!n)
    1249           0 :     return NULL; /* out of core */
    1250          49 :   return_null_if_fail (n->right == node->right);
    1251          49 :   node->right = n;
    1252          49 :   n->left = node;
    1253             : 
    1254             :   /* FIXME: Consider tail pointer for faster insertion.  */
    1255          49 :   link_nextp = &node->link_next;
    1256         592 :   while (*link_nextp)
    1257         494 :     link_nextp = &(*link_nextp)->link_next;
    1258          49 :   *link_nextp = n;
    1259             : 
    1260          49 :   return n;
    1261             : }
    1262             : 
    1263             : 
    1264             : /* Locate a type value sequence like
    1265             : 
    1266             :   SEQUENCE {
    1267             :      type    OBJECT IDENTIFIER
    1268             :      value   ANY
    1269             :   }
    1270             : 
    1271             :   below root and return the 'value' node.  OIDBUF should contain the
    1272             :   DER encoding of an OID value.  idx is the number of OIDs to skip;
    1273             :   this can be used to enumerate structures with the same OID */
    1274             : AsnNode
    1275           0 : _ksba_asn_find_type_value (const unsigned char *image, AsnNode root, int idx,
    1276             :                            const void *oidbuf, size_t oidlen)
    1277             : {
    1278             :   AsnNode n, noid;
    1279             : 
    1280           0 :   if (!image || !root)
    1281           0 :     return NULL;
    1282             : 
    1283           0 :   for (n = root; n; n = _ksba_asn_walk_tree (root, n) )
    1284             :     {
    1285           0 :       if ( n->type == TYPE_SEQUENCE
    1286           0 :            && n->down && n->down->type == TYPE_OBJECT_ID)
    1287             :         {
    1288           0 :           noid = n->down;
    1289           0 :           if (noid->off != -1 && noid->len == oidlen
    1290           0 :               && !memcmp (image + noid->off + noid->nhdr, oidbuf, oidlen)
    1291           0 :               && noid->right)
    1292             :             {
    1293           0 :               if ( !idx-- )
    1294           0 :                 return noid->right;
    1295             :             }
    1296             : 
    1297             :         }
    1298             :     }
    1299           0 :   return NULL;
    1300             : }

Generated by: LCOV version 1.11