LCOV - code coverage report
Current view: top level - src - sexp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 683 1099 62.1 %
Date: 2015-11-05 17:08:00 Functions: 30 41 73.2 %

          Line data    Source code
       1             : /* sexp.c  -  S-Expression handling
       2             :  * Copyright (C) 1999, 2000, 2001, 2002, 2003,
       3             :  *               2004, 2006, 2007, 2008, 2011  Free Software Foundation, Inc.
       4             :  * Copyright (C) 2013, 2014 g10 Code GmbH
       5             :  *
       6             :  * This file is part of Libgcrypt.
       7             :  *
       8             :  * Libgcrypt is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU Lesser general Public License as
      10             :  * published by the Free Software Foundation; either version 2.1 of
      11             :  * the License, or (at your option) any later version.
      12             :  *
      13             :  * Libgcrypt is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with this program; if not, write to the Free Software
      20             :  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
      21             :  */
      22             : 
      23             : 
      24             : #include <config.h>
      25             : #include <stdio.h>
      26             : #include <stdlib.h>
      27             : #include <string.h>
      28             : #include <stdarg.h>
      29             : #include <ctype.h>
      30             : #include <errno.h>
      31             : 
      32             : #define GCRYPT_NO_MPI_MACROS 1
      33             : #include "g10lib.h"
      34             : 
      35             : 
      36             : /* Notes on the internal memory layout.
      37             : 
      38             :    We store an S-expression as one memory buffer with tags, length and
      39             :    value.  The simplest list would thus be:
      40             : 
      41             :    /----------+----------+---------+------+-----------+----------\
      42             :    | open_tag | data_tag | datalen | data | close_tag | stop_tag |
      43             :    \----------+----------+---------+------+-----------+----------/
      44             : 
      45             :    Expressed more compact and with an example:
      46             : 
      47             :    /----+----+----+---+----+----\
      48             :    | OT | DT | DL | D | CT | ST |  "(foo)"
      49             :    \----+----+----+---+----+----/
      50             : 
      51             :    The open tag must always be the first tag of a list as requires by
      52             :    the S-expression specs.  At least data element (data_tag, datalen,
      53             :    data) is required as well.  The close_tag finishes the list and
      54             :    would actually be sufficient.  For fail-safe reasons a final stop
      55             :    tag is always the last byte in a buffer; it has a value of 0 so
      56             :    that string function accidently applied to an S-expression will
      57             :    never access unallocated data.  We do not support display hints and
      58             :    thus don't need to represent them.  A list may have more an
      59             :    arbitrary number of data elements but at least one is required.
      60             :    The length of each data must be greater than 0 and has a current
      61             :    limit to 65535 bytes (by means of the DATALEN type).
      62             : 
      63             :    A list with two data elements:
      64             : 
      65             :    /----+----+----+---+----+----+---+----+----\
      66             :    | OT | DT | DL | D | DT | DL | D | CT | ST |  "(foo bar)"
      67             :    \----+----+----+---+----+----+---+----+----/
      68             : 
      69             :    In the above example both DL fields have a value of 3.
      70             :    A list of a list with one data element:
      71             : 
      72             :    /----+----+----+----+---+----+----+----\
      73             :    | OT | OT | DT | DL | D | CT | CT | ST |  "((foo))"
      74             :    \----+----+----+----+---+----+----+----/
      75             : 
      76             :    A list with one element followed by another list:
      77             : 
      78             :    /----+----+----+---+----+----+----+---+----+----+----\
      79             :    | OT | DT | DL | D | OT | DT | DL | D | CT | CT | ST |  "(foo (bar))"
      80             :    \----+----+----+---+----+----+----+---+----+----+----/
      81             : 
      82             :  */
      83             : 
      84             : typedef unsigned short DATALEN;
      85             : 
      86             : struct gcry_sexp
      87             : {
      88             :   byte d[1];
      89             : };
      90             : 
      91             : #define ST_STOP  0
      92             : #define ST_DATA  1  /* datalen follows */
      93             : /*#define ST_HINT  2   datalen follows (currently not used) */
      94             : #define ST_OPEN  3
      95             : #define ST_CLOSE 4
      96             : 
      97             : /* The atoi macros assume that the buffer has only valid digits.  */
      98             : #define atoi_1(p)   (*(p) - '0' )
      99             : #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
     100             :                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
     101             : #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
     102             : 
     103             : #define TOKEN_SPECIALS  "-./_:*+="
     104             : 
     105             : static gcry_err_code_t
     106             : do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
     107             :                 const char *buffer, size_t length, int argflag,
     108             :                 void **arg_list, va_list arg_ptr);
     109             : 
     110             : static gcry_err_code_t
     111             : do_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
     112             :                const char *buffer, size_t length, int argflag,
     113             :                void **arg_list, ...);
     114             : 
     115             : /* Return true if P points to a byte containing a whitespace according
     116             :    to the S-expressions definition. */
     117             : #undef whitespacep
     118             : static GPG_ERR_INLINE int
     119      213305 : whitespacep (const char *p)
     120             : {
     121      213305 :   switch (*p)
     122             :     {
     123       51968 :     case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1;
     124      161337 :     default: return 0;
     125             :     }
     126             : }
     127             : 
     128             : 
     129             : #if 0
     130             : static void
     131             : dump_mpi( gcry_mpi_t a )
     132             : {
     133             :     char buffer[1000];
     134             :     size_t n = 1000;
     135             : 
     136             :     if( !a )
     137             :         fputs("[no MPI]", stderr );
     138             :     else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) )
     139             :         fputs("[MPI too large to print]", stderr );
     140             :     else
     141             :         fputs( buffer, stderr );
     142             : }
     143             : #endif
     144             : 
     145             : static void
     146           0 : dump_string (const byte *p, size_t n, int delim )
     147             : {
     148           0 :   for (; n; n--, p++ )
     149             :     {
     150           0 :       if ((*p & 0x80) || iscntrl( *p ) || *p == delim )
     151             :         {
     152           0 :           if( *p == '\n' )
     153           0 :             log_printf ("\\n");
     154           0 :           else if( *p == '\r' )
     155           0 :             log_printf ("\\r");
     156           0 :           else if( *p == '\f' )
     157           0 :             log_printf ("\\f");
     158           0 :           else if( *p == '\v' )
     159           0 :             log_printf ("\\v");
     160           0 :             else if( *p == '\b' )
     161           0 :               log_printf ("\\b");
     162           0 :           else if( !*p )
     163           0 :             log_printf ("\\0");
     164             :           else
     165           0 :             log_printf ("\\x%02x", *p );
     166             :         }
     167             :       else
     168           0 :         log_printf ("%c", *p);
     169             :     }
     170           0 : }
     171             : 
     172             : 
     173             : void
     174           0 : _gcry_sexp_dump (const gcry_sexp_t a)
     175             : {
     176             :   const byte *p;
     177           0 :   int indent = 0;
     178             :   int type;
     179             : 
     180           0 :   if (!a)
     181             :     {
     182           0 :       log_printf ( "[nil]\n");
     183           0 :       return;
     184             :     }
     185             : 
     186           0 :   p = a->d;
     187           0 :   while ( (type = *p) != ST_STOP )
     188             :     {
     189           0 :       p++;
     190           0 :       switch ( type )
     191             :         {
     192             :         case ST_OPEN:
     193           0 :           log_printf ("%*s[open]\n", 2*indent, "");
     194           0 :           indent++;
     195           0 :           break;
     196             :         case ST_CLOSE:
     197           0 :           if( indent )
     198           0 :             indent--;
     199           0 :           log_printf ("%*s[close]\n", 2*indent, "");
     200           0 :           break;
     201             :         case ST_DATA: {
     202             :           DATALEN n;
     203           0 :           memcpy ( &n, p, sizeof n );
     204           0 :           p += sizeof n;
     205           0 :           log_printf ("%*s[data=\"", 2*indent, "" );
     206           0 :           dump_string (p, n, '\"' );
     207           0 :           log_printf ("\"]\n");
     208           0 :           p += n;
     209             :         }
     210           0 :         break;
     211             :         default:
     212           0 :           log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type);
     213           0 :           break;
     214             :         }
     215             :     }
     216             : }
     217             : 
     218             : 
     219             : /* Pass list through except when it is an empty list - in that case
     220             :  * return NULL and release the passed list.  This is used to make sure
     221             :  * that no forbidden empty lists are created.
     222             :  */
     223             : static gcry_sexp_t
     224       70681 : normalize ( gcry_sexp_t list )
     225             : {
     226             :   unsigned char *p;
     227             : 
     228       70681 :   if ( !list )
     229           2 :     return NULL;
     230       70679 :   p = list->d;
     231       70679 :   if ( *p == ST_STOP )
     232             :     {
     233             :       /* this is "" */
     234           0 :       sexp_release ( list );
     235           0 :       return NULL;
     236             :     }
     237       70679 :   if ( *p == ST_OPEN && p[1] == ST_CLOSE )
     238             :     {
     239             :       /* this is "()" */
     240           0 :       sexp_release ( list );
     241           0 :       return NULL;
     242             :     }
     243             : 
     244       70679 :   return list;
     245             : }
     246             : 
     247             : /* Create a new S-expression object by reading LENGTH bytes from
     248             :    BUFFER, assuming it is canonical encoded or autodetected encoding
     249             :    when AUTODETECT is set to 1.  With FREEFNC not NULL, ownership of
     250             :    the buffer is transferred to the newly created object.  FREEFNC
     251             :    should be the freefnc used to release BUFFER; there is no guarantee
     252             :    at which point this function is called; most likey you want to use
     253             :    free() or gcry_free().
     254             : 
     255             :    Passing LENGTH and AUTODETECT as 0 is allowed to indicate that
     256             :    BUFFER points to a valid canonical encoded S-expression.  A LENGTH
     257             :    of 0 and AUTODETECT 1 indicates that buffer points to a
     258             :    null-terminated string.
     259             : 
     260             :    This function returns 0 and and the pointer to the new object in
     261             :    RETSEXP or an error code in which case RETSEXP is set to NULL.  */
     262             : gcry_err_code_t
     263         336 : _gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length,
     264             :                   int autodetect, void (*freefnc)(void*) )
     265             : {
     266             :   gcry_err_code_t errcode;
     267             :   gcry_sexp_t se;
     268             : 
     269         336 :   if (!retsexp)
     270           0 :     return GPG_ERR_INV_ARG;
     271         336 :   *retsexp = NULL;
     272         336 :   if (autodetect < 0 || autodetect > 1 || !buffer)
     273           0 :     return GPG_ERR_INV_ARG;
     274             : 
     275         336 :   if (!length && !autodetect)
     276             :     { /* What a brave caller to assume that there is really a canonical
     277             :          encoded S-expression in buffer */
     278           0 :       length = _gcry_sexp_canon_len (buffer, 0, NULL, &errcode);
     279           0 :       if (!length)
     280           0 :         return errcode;
     281             :     }
     282         336 :   else if (!length && autodetect)
     283             :     { /* buffer is a string */
     284         159 :       length = strlen ((char *)buffer);
     285             :     }
     286             : 
     287         336 :   errcode = do_sexp_sscan (&se, NULL, buffer, length, 0, NULL);
     288         336 :   if (errcode)
     289           0 :     return errcode;
     290             : 
     291         336 :   *retsexp = se;
     292         336 :   if (freefnc)
     293             :     {
     294             :       /* For now we release the buffer immediately.  As soon as we
     295             :          have changed the internal represenation of S-expression to
     296             :          the canoncial format - which has the advantage of faster
     297             :          parsing - we will use this function as a closure in our
     298             :          GCRYSEXP object and use the BUFFER directly.  */
     299           3 :       freefnc (buffer);
     300             :     }
     301         336 :   return 0;
     302             : }
     303             : 
     304             : /* Same as gcry_sexp_create but don't transfer ownership */
     305             : gcry_err_code_t
     306         330 : _gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length,
     307             :                int autodetect)
     308             : {
     309         330 :   return _gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL);
     310             : }
     311             : 
     312             : 
     313             : /****************
     314             :  * Release resource of the given SEXP object.
     315             :  */
     316             : void
     317       85072 : _gcry_sexp_release( gcry_sexp_t sexp )
     318             : {
     319       85072 :   if (sexp)
     320             :     {
     321       70679 :       if (_gcry_is_secure (sexp))
     322             :         {
     323             :           /* Extra paranoid wiping. */
     324           2 :           const byte *p = sexp->d;
     325             :           int type;
     326             : 
     327          62 :           while ( (type = *p) != ST_STOP )
     328             :             {
     329          58 :               p++;
     330          58 :               switch ( type )
     331             :                 {
     332             :                 case ST_OPEN:
     333          16 :                   break;
     334             :                 case ST_CLOSE:
     335          16 :                   break;
     336             :                 case ST_DATA:
     337             :                   {
     338             :                     DATALEN n;
     339          26 :                     memcpy ( &n, p, sizeof n );
     340          26 :                     p += sizeof n;
     341          26 :                     p += n;
     342             :                   }
     343          26 :                   break;
     344             :                 default:
     345           0 :                   break;
     346             :                 }
     347             :             }
     348           2 :           wipememory (sexp->d, p - sexp->d);
     349             :         }
     350       70679 :       xfree ( sexp );
     351             :     }
     352       85072 : }
     353             : 
     354             : 
     355             : /****************
     356             :  * Make a pair from lists a and b, don't use a or b later on.
     357             :  * Special behaviour:  If one is a single element list we put the
     358             :  * element straight into the new pair.
     359             :  */
     360             : gcry_sexp_t
     361           0 : _gcry_sexp_cons( const gcry_sexp_t a, const gcry_sexp_t b )
     362             : {
     363             :   (void)a;
     364             :   (void)b;
     365             : 
     366             :   /* NYI: Implementation should be quite easy with our new data
     367             :      representation */
     368           0 :   BUG ();
     369             :   return NULL;
     370             : }
     371             : 
     372             : 
     373             : /****************
     374             :  * Make a list from all items in the array the end of the array is marked
     375             :  * with a NULL.
     376             :  */
     377             : gcry_sexp_t
     378           0 : _gcry_sexp_alist( const gcry_sexp_t *array )
     379             : {
     380             :   (void)array;
     381             : 
     382             :   /* NYI: Implementation should be quite easy with our new data
     383             :      representation. */
     384           0 :   BUG ();
     385             :   return NULL;
     386             : }
     387             : 
     388             : /****************
     389             :  * Make a list from all items, the end of list is indicated by a NULL
     390             :  */
     391             : gcry_sexp_t
     392           0 : _gcry_sexp_vlist( const gcry_sexp_t a, ... )
     393             : {
     394             :   (void)a;
     395             :   /* NYI: Implementation should be quite easy with our new data
     396             :      representation. */
     397           0 :   BUG ();
     398             :   return NULL;
     399             : }
     400             : 
     401             : 
     402             : /****************
     403             :  * Append n to the list a
     404             :  * Returns: a new ist (which maybe a)
     405             :  */
     406             : gcry_sexp_t
     407           0 : _gcry_sexp_append( const gcry_sexp_t a, const gcry_sexp_t n )
     408             : {
     409             :   (void)a;
     410             :   (void)n;
     411             :   /* NYI: Implementation should be quite easy with our new data
     412             :      representation. */
     413           0 :   BUG ();
     414             :   return NULL;
     415             : }
     416             : 
     417             : gcry_sexp_t
     418           0 : _gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n )
     419             : {
     420             :   (void)a;
     421             :   (void)n;
     422             :   /* NYI: Implementation should be quite easy with our new data
     423             :      representation. */
     424           0 :   BUG ();
     425             :   return NULL;
     426             : }
     427             : 
     428             : 
     429             : 
     430             : /****************
     431             :  * Locate token in a list. The token must be the car of a sublist.
     432             :  * Returns: A new list with this sublist or NULL if not found.
     433             :  */
     434             : gcry_sexp_t
     435       56717 : _gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen )
     436             : {
     437             :   const byte *p;
     438             :   DATALEN n;
     439             : 
     440       56717 :   if ( !list )
     441           0 :     return NULL;
     442             : 
     443       56717 :   if ( !toklen )
     444       32835 :     toklen = strlen(tok);
     445             : 
     446       56717 :   p = list->d;
     447      325362 :   while ( *p != ST_STOP )
     448             :     {
     449      260197 :       if ( *p == ST_OPEN && p[1] == ST_DATA )
     450       97803 :         {
     451      146072 :           const byte *head = p;
     452             : 
     453      146072 :           p += 2;
     454      146072 :           memcpy ( &n, p, sizeof n );
     455      146072 :           p += sizeof n;
     456      146072 :           if ( n == toklen && !memcmp( p, tok, toklen ) )
     457             :             { /* found it */
     458             :               gcry_sexp_t newlist;
     459             :               byte *d;
     460       48269 :               int level = 1;
     461             : 
     462             :               /* Look for the end of the list.  */
     463      304288 :               for ( p += n; level; p++ )
     464             :                 {
     465      256019 :                   if ( *p == ST_DATA )
     466             :                     {
     467      117870 :                         memcpy ( &n, ++p, sizeof n );
     468      117870 :                         p += sizeof n + n;
     469      117870 :                         p--; /* Compensate for later increment. */
     470             :                     }
     471      138149 :                   else if ( *p == ST_OPEN )
     472             :                     {
     473       44940 :                       level++;
     474             :                     }
     475       93209 :                   else if ( *p == ST_CLOSE )
     476             :                     {
     477       93209 :                       level--;
     478             :                     }
     479           0 :                   else if ( *p == ST_STOP )
     480             :                     {
     481           0 :                       BUG ();
     482             :                     }
     483             :                 }
     484       48269 :               n = p - head;
     485             : 
     486       48269 :               newlist = xtrymalloc ( sizeof *newlist + n );
     487       48269 :               if (!newlist)
     488             :                 {
     489             :                   /* No way to return an error code, so we can only
     490             :                      return Not Found. */
     491           0 :                   return NULL;
     492             :                 }
     493       48269 :               d = newlist->d;
     494       48269 :               memcpy ( d, head, n ); d += n;
     495       48269 :               *d++ = ST_STOP;
     496       48269 :               return normalize ( newlist );
     497             :             }
     498       97803 :           p += n;
     499             :         }
     500      114125 :       else if ( *p == ST_DATA )
     501             :         {
     502       52565 :           memcpy ( &n, ++p, sizeof n ); p += sizeof n;
     503       52565 :           p += n;
     504             :         }
     505             :       else
     506       61560 :         p++;
     507             :     }
     508        8448 :   return NULL;
     509             : }
     510             : 
     511             : /****************
     512             :  * Return the length of the given list
     513             :  */
     514             : int
     515        5831 : _gcry_sexp_length (const gcry_sexp_t list)
     516             : {
     517             :   const byte *p;
     518             :   DATALEN n;
     519             :   int type;
     520        5831 :   int length = 0;
     521        5831 :   int level = 0;
     522             : 
     523        5831 :   if (!list)
     524           0 :     return 0;
     525             : 
     526        5831 :   p = list->d;
     527       36027 :   while ((type=*p) != ST_STOP)
     528             :     {
     529       24365 :       p++;
     530       24365 :       if (type == ST_DATA)
     531             :         {
     532       12703 :           memcpy (&n, p, sizeof n);
     533       12703 :           p += sizeof n + n;
     534       12703 :           if (level == 1)
     535       12703 :             length++;
     536             :         }
     537       11662 :       else if (type == ST_OPEN)
     538             :         {
     539        5831 :           if (level == 1)
     540           0 :             length++;
     541        5831 :           level++;
     542             :         }
     543        5831 :       else if (type == ST_CLOSE)
     544             :         {
     545        5831 :           level--;
     546             :         }
     547             :     }
     548        5831 :   return length;
     549             : }
     550             : 
     551             : 
     552             : /* Return the internal lengths offset of LIST.  That is the size of
     553             :    the buffer from the first ST_OPEN, which is returned at R_OFF, to
     554             :    the corresponding ST_CLOSE inclusive.  */
     555             : static size_t
     556         138 : get_internal_buffer (const gcry_sexp_t list, size_t *r_off)
     557             : {
     558             :   const unsigned char *p;
     559             :   DATALEN n;
     560             :   int type;
     561         138 :   int level = 0;
     562             : 
     563         138 :   *r_off = 0;
     564         138 :   if (list)
     565             :     {
     566          92 :       p = list->d;
     567         910 :       while ( (type=*p) != ST_STOP )
     568             :         {
     569         818 :           p++;
     570         818 :           if (type == ST_DATA)
     571             :             {
     572         400 :               memcpy (&n, p, sizeof n);
     573         400 :               p += sizeof n + n;
     574             :             }
     575         418 :           else if (type == ST_OPEN)
     576             :             {
     577         209 :               if (!level)
     578          92 :                 *r_off = (p-1) - list->d;
     579         209 :               level++;
     580             :             }
     581         209 :           else if ( type == ST_CLOSE )
     582             :             {
     583         209 :               level--;
     584         209 :               if (!level)
     585          92 :                 return p - list->d;
     586             :             }
     587             :         }
     588             :     }
     589          46 :   return 0; /* Not a proper list.  */
     590             : }
     591             : 
     592             : 
     593             : 
     594             : /* Extract the n-th element of the given LIST.  Returns NULL for
     595             :    no-such-element, a corrupt list, or memory failure.  */
     596             : gcry_sexp_t
     597        8561 : _gcry_sexp_nth (const gcry_sexp_t list, int number)
     598             : {
     599             :   const byte *p;
     600             :   DATALEN n;
     601             :   gcry_sexp_t newlist;
     602             :   byte *d;
     603        8561 :   int level = 0;
     604             : 
     605        8561 :   if (!list || list->d[0] != ST_OPEN)
     606           0 :     return NULL;
     607        8561 :   p = list->d;
     608             : 
     609       30310 :   while (number > 0)
     610             :     {
     611       13188 :       p++;
     612       13188 :       if (*p == ST_DATA)
     613             :         {
     614        8410 :           memcpy (&n, ++p, sizeof n);
     615        8410 :           p += sizeof n + n;
     616        8410 :           p--;
     617        8410 :           if (!level)
     618        3632 :             number--;
     619             :         }
     620        4778 :       else if (*p == ST_OPEN)
     621             :         {
     622        2389 :           level++;
     623             :         }
     624        2389 :       else if (*p == ST_CLOSE)
     625             :         {
     626        2389 :           level--;
     627        2389 :           if ( !level )
     628        2389 :             number--;
     629             :         }
     630           0 :       else if (*p == ST_STOP)
     631             :         {
     632           0 :           return NULL;
     633             :         }
     634             :     }
     635        8561 :   p++;
     636             : 
     637        8561 :   if (*p == ST_DATA)
     638             :     {
     639           2 :       memcpy (&n, p+1, sizeof n);
     640           2 :       newlist = xtrymalloc (sizeof *newlist + 1 + 1 + sizeof n + n + 1);
     641           2 :       if (!newlist)
     642           0 :         return NULL;
     643           2 :       d = newlist->d;
     644           2 :       *d++ = ST_OPEN;
     645           2 :       memcpy (d, p, 1 + sizeof n + n);
     646           2 :       d += 1 + sizeof n + n;
     647           2 :       *d++ = ST_CLOSE;
     648           2 :       *d = ST_STOP;
     649             :     }
     650        8559 :   else if (*p == ST_OPEN)
     651             :     {
     652        8557 :       const byte *head = p;
     653             : 
     654        8557 :       level = 1;
     655             :       do {
     656       92842 :         p++;
     657       92842 :         if (*p == ST_DATA)
     658             :           {
     659       47005 :             memcpy (&n, ++p, sizeof n);
     660       47005 :             p += sizeof n + n;
     661       47005 :             p--;
     662             :           }
     663       45837 :         else if (*p == ST_OPEN)
     664             :           {
     665       18640 :             level++;
     666             :           }
     667       27197 :         else if (*p == ST_CLOSE)
     668             :           {
     669       27197 :             level--;
     670             :           }
     671           0 :         else if (*p == ST_STOP)
     672             :           {
     673           0 :             BUG ();
     674             :           }
     675       92842 :       } while (level);
     676        8557 :       n = p + 1 - head;
     677             : 
     678        8557 :       newlist = xtrymalloc (sizeof *newlist + n);
     679        8557 :       if (!newlist)
     680           0 :         return NULL;
     681        8557 :       d = newlist->d;
     682        8557 :       memcpy (d, head, n);
     683        8557 :       d += n;
     684        8557 :       *d++ = ST_STOP;
     685             :     }
     686             :   else
     687           2 :     newlist = NULL;
     688             : 
     689        8561 :   return normalize (newlist);
     690             : }
     691             : 
     692             : 
     693             : gcry_sexp_t
     694        4929 : _gcry_sexp_car (const gcry_sexp_t list)
     695             : {
     696        4929 :   return _gcry_sexp_nth (list, 0);
     697             : }
     698             : 
     699             : 
     700             : /* Helper to get data from the car.  The returned value is valid as
     701             :    long as the list is not modified. */
     702             : static const char *
     703       44817 : do_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen)
     704             : {
     705             :   const byte *p;
     706             :   DATALEN n;
     707       44817 :   int level = 0;
     708             : 
     709       44817 :   *datalen = 0;
     710       44817 :   if ( !list )
     711           0 :     return NULL;
     712             : 
     713       44817 :   p = list->d;
     714       44817 :   if ( *p == ST_OPEN )
     715       44788 :     p++;             /* Yep, a list. */
     716          29 :   else if (number)
     717           0 :     return NULL;     /* Not a list but N > 0 requested. */
     718             : 
     719             :   /* Skip over N elements. */
     720      126465 :   while (number > 0)
     721             :     {
     722       36831 :       if (*p == ST_DATA)
     723             :         {
     724       36831 :           memcpy ( &n, ++p, sizeof n );
     725       36831 :           p += sizeof n + n;
     726       36831 :           p--;
     727       36831 :           if ( !level )
     728       36831 :             number--;
     729             :         }
     730           0 :       else if (*p == ST_OPEN)
     731             :         {
     732           0 :           level++;
     733             :         }
     734           0 :       else if (*p == ST_CLOSE)
     735             :         {
     736           0 :           level--;
     737           0 :           if ( !level )
     738           0 :             number--;
     739             :         }
     740           0 :       else if (*p == ST_STOP)
     741             :         {
     742           0 :           return NULL;
     743             :         }
     744       36831 :       p++;
     745             :     }
     746             : 
     747             :   /* If this is data, return it.  */
     748       44817 :   if (*p == ST_DATA)
     749             :     {
     750       44793 :       memcpy ( &n, ++p, sizeof n );
     751       44793 :       *datalen = n;
     752       44793 :       return (const char*)p + sizeof n;
     753             :     }
     754             : 
     755          24 :   return NULL;
     756             : }
     757             : 
     758             : 
     759             : /* Get data from the car.  The returned value is valid as long as the
     760             :    list is not modified.  */
     761             : const char *
     762       12564 : _gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen )
     763             : {
     764       12564 :   return do_sexp_nth_data (list, number, datalen);
     765             : }
     766             : 
     767             : 
     768             : /* Get the nth element of a list which needs to be a simple object.
     769             :    The returned value is a malloced buffer and needs to be freed by
     770             :    the caller.  This is basically the same as gcry_sexp_nth_data but
     771             :    with an allocated result. */
     772             : void *
     773        7720 : _gcry_sexp_nth_buffer (const gcry_sexp_t list, int number, size_t *rlength)
     774             : {
     775             :   const char *s;
     776             :   size_t n;
     777             :   char *buf;
     778             : 
     779        7720 :   *rlength = 0;
     780        7720 :   s = do_sexp_nth_data (list, number, &n);
     781        7720 :   if (!s || !n)
     782           6 :     return NULL;
     783        7714 :   buf = xtrymalloc (n);
     784        7714 :   if (!buf)
     785           0 :     return NULL;
     786        7714 :   memcpy (buf, s, n);
     787        7714 :   *rlength = n;
     788        7714 :   return buf;
     789             : }
     790             : 
     791             : 
     792             : /* Get a string from the car.  The returned value is a malloced string
     793             :    and needs to be freed by the caller.  */
     794             : char *
     795       11387 : _gcry_sexp_nth_string (const gcry_sexp_t list, int number)
     796             : {
     797             :   const char *s;
     798             :   size_t n;
     799             :   char *buf;
     800             : 
     801       11387 :   s = do_sexp_nth_data (list, number, &n);
     802       11387 :   if (!s || n < 1 || (n+1) < 1)
     803           0 :     return NULL;
     804       11387 :   buf = xtrymalloc (n+1);
     805       11387 :   if (!buf)
     806           0 :     return NULL;
     807       11387 :   memcpy (buf, s, n);
     808       11387 :   buf[n] = 0;
     809       11387 :   return buf;
     810             : }
     811             : 
     812             : 
     813             : /*
     814             :  * Get a MPI from the car
     815             :  */
     816             : gcry_mpi_t
     817       16581 : _gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt)
     818             : {
     819             :   size_t n;
     820             :   gcry_mpi_t a;
     821             : 
     822       16581 :   if (mpifmt == GCRYMPI_FMT_OPAQUE)
     823             :     {
     824             :       char *p;
     825             : 
     826        3435 :       p = _gcry_sexp_nth_buffer (list, number, &n);
     827        3435 :       if (!p)
     828           0 :         return NULL;
     829             : 
     830        3435 :       a = _gcry_is_secure (list)? _gcry_mpi_snew (0) : _gcry_mpi_new (0);
     831        3435 :       if (a)
     832        3435 :         mpi_set_opaque (a, p, n*8);
     833             :       else
     834           0 :         xfree (p);
     835             :     }
     836             :   else
     837             :     {
     838             :       const char *s;
     839             : 
     840       13146 :       if (!mpifmt)
     841           6 :         mpifmt = GCRYMPI_FMT_STD;
     842             : 
     843       13146 :       s = do_sexp_nth_data (list, number, &n);
     844       13146 :       if (!s)
     845           0 :         return NULL;
     846             : 
     847       13146 :       if (_gcry_mpi_scan (&a, mpifmt, s, n, NULL))
     848           0 :         return NULL;
     849             :     }
     850             : 
     851       16581 :   return a;
     852             : }
     853             : 
     854             : 
     855             : /****************
     856             :  * Get the CDR
     857             :  */
     858             : gcry_sexp_t
     859        4953 : _gcry_sexp_cdr(const gcry_sexp_t list)
     860             : {
     861             :   const byte *p;
     862             :   const byte *head;
     863             :   DATALEN n;
     864             :   gcry_sexp_t newlist;
     865             :   byte *d;
     866        4953 :   int level = 0;
     867        4953 :   int skip = 1;
     868             : 
     869        4953 :   if (!list || list->d[0] != ST_OPEN)
     870           0 :     return NULL;
     871        4953 :   p = list->d;
     872             : 
     873       14859 :   while (skip > 0)
     874             :     {
     875        4953 :       p++;
     876        4953 :       if (*p == ST_DATA)
     877             :         {
     878        4953 :           memcpy ( &n, ++p, sizeof n );
     879        4953 :           p += sizeof n + n;
     880        4953 :           p--;
     881        4953 :           if ( !level )
     882        4953 :             skip--;
     883             :         }
     884           0 :       else if (*p == ST_OPEN)
     885             :         {
     886           0 :           level++;
     887             :         }
     888           0 :       else if (*p == ST_CLOSE)
     889             :         {
     890           0 :           level--;
     891           0 :           if ( !level )
     892           0 :             skip--;
     893             :         }
     894           0 :       else if (*p == ST_STOP)
     895             :         {
     896           0 :           return NULL;
     897             :         }
     898             :     }
     899        4953 :   p++;
     900             : 
     901        4953 :   head = p;
     902        4953 :   level = 0;
     903             :   do {
     904       74664 :     if (*p == ST_DATA)
     905             :       {
     906       34836 :         memcpy ( &n, ++p, sizeof n );
     907       34836 :         p += sizeof n + n;
     908       34836 :         p--;
     909             :       }
     910       39828 :     else if (*p == ST_OPEN)
     911             :       {
     912       19914 :         level++;
     913             :       }
     914       19914 :     else if (*p == ST_CLOSE)
     915             :       {
     916       19914 :         level--;
     917             :       }
     918           0 :     else if (*p == ST_STOP)
     919             :       {
     920           0 :         return NULL;
     921             :       }
     922       74664 :     p++;
     923       74664 :   } while (level);
     924        4953 :   n = p - head;
     925             : 
     926        4953 :   newlist = xtrymalloc (sizeof *newlist + n + 2);
     927        4953 :   if (!newlist)
     928           0 :     return NULL;
     929        4953 :   d = newlist->d;
     930        4953 :   *d++ = ST_OPEN;
     931        4953 :   memcpy (d, head, n);
     932        4953 :   d += n;
     933        4953 :   *d++ = ST_CLOSE;
     934        4953 :   *d++ = ST_STOP;
     935             : 
     936        4953 :   return normalize (newlist);
     937             : }
     938             : 
     939             : 
     940             : gcry_sexp_t
     941        4929 : _gcry_sexp_cadr ( const gcry_sexp_t list )
     942             : {
     943             :   gcry_sexp_t a, b;
     944             : 
     945        4929 :   a = _gcry_sexp_cdr (list);
     946        4929 :   b = _gcry_sexp_car (a);
     947        4929 :   sexp_release (a);
     948        4929 :   return b;
     949             : }
     950             : 
     951             : 
     952             : static GPG_ERR_INLINE int
     953      112616 : hextonibble (int s)
     954             : {
     955      112616 :   if (s >= '0' && s <= '9')
     956       73094 :     return s - '0';
     957       39522 :   else if (s >= 'A' && s <= 'F')
     958       35517 :     return 10 + s - 'A';
     959        4005 :   else if (s >= 'a' && s <= 'f')
     960        4005 :     return 10 + s - 'a';
     961             :   else
     962           0 :     return 0;
     963             : }
     964             : 
     965             : 
     966             : struct make_space_ctx
     967             : {
     968             :   gcry_sexp_t sexp;
     969             :   size_t allocated;
     970             :   byte *pos;
     971             : };
     972             : 
     973             : 
     974             : static gpg_err_code_t
     975      138626 : make_space ( struct make_space_ctx *c, size_t n )
     976             : {
     977      138626 :   size_t used = c->pos - c->sexp->d;
     978             : 
     979      138626 :   if ( used + n + sizeof(DATALEN) + 1 >= c->allocated )
     980             :     {
     981             :       gcry_sexp_t newsexp;
     982             :       byte *newhead;
     983             :       size_t newsize;
     984             : 
     985       16963 :       newsize = c->allocated + 2*(n+sizeof(DATALEN)+1);
     986       16963 :       if (newsize <= c->allocated)
     987           0 :         return GPG_ERR_TOO_LARGE;
     988       16963 :       newsexp = xtryrealloc ( c->sexp, sizeof *newsexp + newsize - 1);
     989       16963 :       if (!newsexp)
     990           0 :         return gpg_err_code_from_errno (errno);
     991       16963 :       c->allocated = newsize;
     992       16963 :       newhead = newsexp->d;
     993       16963 :       c->pos = newhead + used;
     994       16963 :       c->sexp = newsexp;
     995             :     }
     996      138626 :   return 0;
     997             : }
     998             : 
     999             : 
    1000             : /* Unquote STRING of LENGTH and store it into BUF.  The surrounding
    1001             :    quotes are must already be removed from STRING.  We assume that the
    1002             :    quoted string is syntacillay correct.  */
    1003             : static size_t
    1004        2166 : unquote_string (const char *string, size_t length, unsigned char *buf)
    1005             : {
    1006        2166 :   int esc = 0;
    1007        2166 :   const unsigned char *s = (const unsigned char*)string;
    1008        2166 :   unsigned char *d = buf;
    1009        2166 :   size_t n = length;
    1010             : 
    1011       17353 :   for (; n; n--, s++)
    1012             :     {
    1013       15187 :       if (esc)
    1014             :         {
    1015           0 :           switch (*s)
    1016             :             {
    1017           0 :             case 'b':  *d++ = '\b'; break;
    1018           0 :             case 't':  *d++ = '\t'; break;
    1019           0 :             case 'v':  *d++ = '\v'; break;
    1020           0 :             case 'n':  *d++ = '\n'; break;
    1021           0 :             case 'f':  *d++ = '\f'; break;
    1022           0 :             case 'r':  *d++ = '\r'; break;
    1023           0 :             case '"':  *d++ = '\"'; break;
    1024           0 :             case '\'': *d++ = '\''; break;
    1025           0 :             case '\\': *d++ = '\\'; break;
    1026             : 
    1027             :             case '\r':  /* ignore CR[,LF] */
    1028           0 :               if (n>1 && s[1] == '\n')
    1029             :                 {
    1030           0 :                   s++; n--;
    1031             :                 }
    1032           0 :               break;
    1033             : 
    1034             :             case '\n':  /* ignore LF[,CR] */
    1035           0 :               if (n>1 && s[1] == '\r')
    1036             :                 {
    1037           0 :                   s++; n--;
    1038             :                 }
    1039           0 :               break;
    1040             : 
    1041             :             case 'x': /* hex value */
    1042           0 :               if (n>2 && hexdigitp (s+1) && hexdigitp (s+2))
    1043             :                 {
    1044           0 :                   s++; n--;
    1045           0 :                   *d++ = xtoi_2 (s);
    1046           0 :                   s++; n--;
    1047             :                 }
    1048           0 :               break;
    1049             : 
    1050             :             default:
    1051           0 :               if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
    1052             :                 {
    1053           0 :                   *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
    1054           0 :                   s += 2;
    1055           0 :                   n -= 2;
    1056             :                 }
    1057           0 :               break;
    1058             :             }
    1059           0 :           esc = 0;
    1060             :         }
    1061       15187 :       else if( *s == '\\' )
    1062           0 :         esc = 1;
    1063             :       else
    1064       15187 :         *d++ = *s;
    1065             :     }
    1066             : 
    1067        2166 :   return d - buf;
    1068             : }
    1069             : 
    1070             : /****************
    1071             :  * Scan the provided buffer and return the S expression in our internal
    1072             :  * format.  Returns a newly allocated expression.  If erroff is not NULL and
    1073             :  * a parsing error has occurred, the offset into buffer will be returned.
    1074             :  * If ARGFLAG is true, the function supports some printf like
    1075             :  * expressions.
    1076             :  *  These are:
    1077             :  *      %m - MPI
    1078             :  *      %s - string (no autoswitch to secure allocation)
    1079             :  *      %d - integer stored as string (no autoswitch to secure allocation)
    1080             :  *      %b - memory buffer; this takes _two_ arguments: an integer with the
    1081             :  *           length of the buffer and a pointer to the buffer.
    1082             :  *      %S - Copy an gcry_sexp_t here.  The S-expression needs to be a
    1083             :  *           regular one, starting with a parenthesis.
    1084             :  *           (no autoswitch to secure allocation)
    1085             :  *  all other format elements are currently not defined and return an error.
    1086             :  *  this includes the "%%" sequence becauce the percent sign is not an
    1087             :  *  allowed character.
    1088             :  * FIXME: We should find a way to store the secure-MPIs not in the string
    1089             :  * but as reference to somewhere - this can help us to save huge amounts
    1090             :  * of secure memory.  The problem is, that if only one element is secure, all
    1091             :  * other elements are automagicaly copied to secure memory too, so the most
    1092             :  * common operation gcry_sexp_cdr_mpi() will always return a secure MPI
    1093             :  * regardless whether it is needed or not.
    1094             :  */
    1095             : static gpg_err_code_t
    1096        8900 : do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
    1097             :                 const char *buffer, size_t length, int argflag,
    1098             :                 void **arg_list, va_list arg_ptr)
    1099             : {
    1100        8900 :   gcry_err_code_t err = 0;
    1101             :   static const char tokenchars[] =
    1102             :     "abcdefghijklmnopqrstuvwxyz"
    1103             :     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    1104             :     "0123456789-./_:*+=";
    1105             :   const char *p;
    1106             :   size_t n;
    1107        8900 :   const char *digptr = NULL;
    1108        8900 :   const char *quoted = NULL;
    1109        8900 :   const char *tokenp = NULL;
    1110        8900 :   const char *hexfmt = NULL;
    1111        8900 :   const char *base64 = NULL;
    1112        8900 :   const char *disphint = NULL;
    1113        8900 :   const char *percent = NULL;
    1114        8900 :   int hexcount = 0;
    1115        8900 :   int quoted_esc = 0;
    1116        8900 :   int datalen = 0;
    1117             :   size_t dummy_erroff;
    1118             :   struct make_space_ctx c;
    1119        8900 :   int arg_counter = 0;
    1120        8900 :   int level = 0;
    1121             : 
    1122        8900 :   if (!retsexp)
    1123           0 :     return GPG_ERR_INV_ARG;
    1124        8900 :   *retsexp = NULL;
    1125             : 
    1126        8900 :   if (!buffer)
    1127           0 :     return GPG_ERR_INV_ARG;
    1128             : 
    1129        8900 :   if (!erroff)
    1130        8900 :     erroff = &dummy_erroff;
    1131             : 
    1132             :   /* Depending on whether ARG_LIST is non-zero or not, this macro gives
    1133             :      us the next argument, either from the variable argument list as
    1134             :      specified by ARG_PTR or from the argument array ARG_LIST.  */
    1135             : #define ARG_NEXT(storage, type)                          \
    1136             :   do                                                     \
    1137             :     {                                                    \
    1138             :       if (!arg_list)                                     \
    1139             :         storage = va_arg (arg_ptr, type);                \
    1140             :       else                                               \
    1141             :         storage = *((type *) (arg_list[arg_counter++])); \
    1142             :     }                                                    \
    1143             :   while (0)
    1144             : 
    1145             :   /* The MAKE_SPACE macro is used before each store operation to
    1146             :      ensure that the buffer is large enough.  It requires a global
    1147             :      context named C and jumps out to the label LEAVE on error! It
    1148             :      also sets ERROFF using the variables BUFFER and P.  */
    1149             : #define MAKE_SPACE(n)  do {                                                \
    1150             :                             gpg_err_code_t _ms_err = make_space (&c, (n)); \
    1151             :                             if (_ms_err)                                   \
    1152             :                               {                                            \
    1153             :                                 err = _ms_err;                             \
    1154             :                                 *erroff = p - buffer;                      \
    1155             :                                 goto leave;                                \
    1156             :                               }                                            \
    1157             :                        } while (0)
    1158             : 
    1159             :   /* The STORE_LEN macro is used to store the length N at buffer P. */
    1160             : #define STORE_LEN(p,n) do {                                                \
    1161             :                             DATALEN ashort = (n);                          \
    1162             :                             memcpy ( (p), &ashort, sizeof(ashort) );           \
    1163             :                             (p) += sizeof (ashort);                        \
    1164             :                         } while (0)
    1165             : 
    1166             :   /* We assume that the internal representation takes less memory than
    1167             :      the provided one.  However, we add space for one extra datalen so
    1168             :      that the code which does the ST_CLOSE can use MAKE_SPACE */
    1169        8900 :   c.allocated = length + sizeof(DATALEN);
    1170        8900 :   if (length && _gcry_is_secure (buffer))
    1171           0 :     c.sexp = xtrymalloc_secure (sizeof *c.sexp + c.allocated - 1);
    1172             :   else
    1173        8900 :     c.sexp = xtrymalloc (sizeof *c.sexp + c.allocated - 1);
    1174        8900 :   if (!c.sexp)
    1175             :     {
    1176           0 :       err = gpg_err_code_from_errno (errno);
    1177           0 :       *erroff = 0;
    1178           0 :       goto leave;
    1179             :     }
    1180        8900 :   c.pos = c.sexp->d;
    1181             : 
    1182      494210 :   for (p = buffer, n = length; n; p++, n--)
    1183             :     {
    1184      485310 :       if (tokenp && !hexfmt)
    1185             :         {
    1186      207732 :           if (strchr (tokenchars, *p))
    1187      164602 :             continue;
    1188             :           else
    1189             :             {
    1190       43130 :               datalen = p - tokenp;
    1191       43130 :               MAKE_SPACE (datalen);
    1192       43130 :               *c.pos++ = ST_DATA;
    1193       43130 :               STORE_LEN (c.pos, datalen);
    1194       43130 :               memcpy (c.pos, tokenp, datalen);
    1195       43130 :               c.pos += datalen;
    1196       43130 :               tokenp = NULL;
    1197             :             }
    1198             :         }
    1199             : 
    1200      320708 :       if (quoted)
    1201             :         {
    1202       17353 :           if (quoted_esc)
    1203             :             {
    1204           0 :               switch (*p)
    1205             :                 {
    1206             :                 case 'b': case 't': case 'v': case 'n': case 'f':
    1207             :                 case 'r': case '"': case '\'': case '\\':
    1208           0 :                   quoted_esc = 0;
    1209           0 :                   break;
    1210             : 
    1211             :                 case '0': case '1': case '2': case '3': case '4':
    1212             :                 case '5': case '6': case '7':
    1213           0 :                   if (!((n > 2)
    1214           0 :                         && (p[1] >= '0') && (p[1] <= '7')
    1215           0 :                         && (p[2] >= '0') && (p[2] <= '7')))
    1216             :                     {
    1217           0 :                       *erroff = p - buffer;
    1218             :                       /* Invalid octal value.  */
    1219           0 :                       err = GPG_ERR_SEXP_BAD_QUOTATION;
    1220           0 :                       goto leave;
    1221             :                     }
    1222           0 :                   p += 2;
    1223           0 :                   n -= 2;
    1224           0 :                   quoted_esc = 0;
    1225           0 :                   break;
    1226             : 
    1227             :                 case 'x':
    1228           0 :                   if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2)))
    1229             :                     {
    1230           0 :                       *erroff = p - buffer;
    1231             :                       /* Invalid hex value.  */
    1232           0 :                       err = GPG_ERR_SEXP_BAD_QUOTATION;
    1233           0 :                       goto leave;
    1234             :                     }
    1235           0 :                   p += 2;
    1236           0 :                   n -= 2;
    1237           0 :                   quoted_esc = 0;
    1238           0 :                   break;
    1239             : 
    1240             :                 case '\r':
    1241             :                   /* ignore CR[,LF] */
    1242           0 :                   if (n && (p[1] == '\n'))
    1243             :                     {
    1244           0 :                       p++;
    1245           0 :                       n--;
    1246             :                     }
    1247           0 :                   quoted_esc = 0;
    1248           0 :                   break;
    1249             : 
    1250             :                 case '\n':
    1251             :                   /* ignore LF[,CR] */
    1252           0 :                   if (n && (p[1] == '\r'))
    1253             :                     {
    1254           0 :                       p++;
    1255           0 :                       n--;
    1256             :                     }
    1257           0 :                   quoted_esc = 0;
    1258           0 :                   break;
    1259             : 
    1260             :                 default:
    1261           0 :                   *erroff = p - buffer;
    1262             :                   /* Invalid quoted string escape.  */
    1263           0 :                   err = GPG_ERR_SEXP_BAD_QUOTATION;
    1264           0 :                   goto leave;
    1265             :                 }
    1266             :             }
    1267       17353 :           else if (*p == '\\')
    1268           0 :             quoted_esc = 1;
    1269       17353 :           else if (*p == '\"')
    1270             :             {
    1271             :               /* Keep it easy - we know that the unquoted string will
    1272             :                  never be larger. */
    1273             :               unsigned char *save;
    1274             :               size_t len;
    1275             : 
    1276        2166 :               quoted++; /* Skip leading quote.  */
    1277        2166 :               MAKE_SPACE (p - quoted);
    1278        2166 :               *c.pos++ = ST_DATA;
    1279        2166 :               save = c.pos;
    1280        2166 :               STORE_LEN (c.pos, 0); /* Will be fixed up later.  */
    1281        2166 :               len = unquote_string (quoted, p - quoted, c.pos);
    1282        2166 :               c.pos += len;
    1283        2166 :               STORE_LEN (save, len);
    1284        2166 :               quoted = NULL;
    1285             :             }
    1286             :         }
    1287      303355 :       else if (hexfmt)
    1288             :         {
    1289      118061 :           if (isxdigit (*p))
    1290      112616 :             hexcount++;
    1291        5445 :           else if (*p == '#')
    1292             :             {
    1293        1160 :               if ((hexcount & 1))
    1294             :                 {
    1295           0 :                   *erroff = p - buffer;
    1296           0 :                   err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
    1297           0 :                   goto leave;
    1298             :                 }
    1299             : 
    1300        1160 :               datalen = hexcount / 2;
    1301        1160 :               MAKE_SPACE (datalen);
    1302        1160 :               *c.pos++ = ST_DATA;
    1303        1160 :               STORE_LEN (c.pos, datalen);
    1304       61753 :               for (hexfmt++; hexfmt < p; hexfmt++)
    1305             :                 {
    1306             :                   int tmpc;
    1307             : 
    1308       60593 :                   if (whitespacep (hexfmt))
    1309        4285 :                     continue;
    1310       56308 :                   tmpc = hextonibble (*(const unsigned char*)hexfmt);
    1311       56308 :                   for (hexfmt++; hexfmt < p && whitespacep (hexfmt); hexfmt++)
    1312             :                     ;
    1313       56308 :                   if (hexfmt < p)
    1314             :                     {
    1315       56308 :                       tmpc *= 16;
    1316       56308 :                       tmpc += hextonibble (*(const unsigned char*)hexfmt);
    1317             :                     }
    1318       56308 :                   *c.pos++ = tmpc;
    1319             :                 }
    1320        1160 :               hexfmt = NULL;
    1321             :             }
    1322        4285 :           else if (!whitespacep (p))
    1323             :             {
    1324           0 :               *erroff = p - buffer;
    1325           0 :               err = GPG_ERR_SEXP_BAD_HEX_CHAR;
    1326           0 :               goto leave;
    1327             :             }
    1328             :         }
    1329      185294 :       else if (base64)
    1330             :         {
    1331           0 :           if (*p == '|')
    1332           0 :             base64 = NULL;
    1333             :         }
    1334      185294 :       else if (digptr)
    1335             :         {
    1336         934 :           if (digitp (p))
    1337             :             ;
    1338         742 :           else if (*p == ':')
    1339             :             {
    1340         742 :               datalen = atoi (digptr); /* FIXME: check for overflow.  */
    1341         742 :               digptr = NULL;
    1342         742 :               if (datalen > n - 1)
    1343             :                 {
    1344           0 :                   *erroff = p - buffer;
    1345             :                   /* Buffer too short.  */
    1346           0 :                   err = GPG_ERR_SEXP_STRING_TOO_LONG;
    1347           0 :                   goto leave;
    1348             :                 }
    1349             :               /* Make a new list entry.  */
    1350         742 :               MAKE_SPACE (datalen);
    1351         742 :               *c.pos++ = ST_DATA;
    1352         742 :               STORE_LEN (c.pos, datalen);
    1353         742 :               memcpy (c.pos, p + 1, datalen);
    1354         742 :               c.pos += datalen;
    1355         742 :               n -= datalen;
    1356         742 :               p += datalen;
    1357             :             }
    1358           0 :           else if (*p == '\"')
    1359             :             {
    1360           0 :               digptr = NULL; /* We ignore the optional length.  */
    1361           0 :               quoted = p;
    1362           0 :               quoted_esc = 0;
    1363             :             }
    1364           0 :           else if (*p == '#')
    1365             :             {
    1366           0 :               digptr = NULL; /* We ignore the optional length.  */
    1367           0 :               hexfmt = p;
    1368           0 :               hexcount = 0;
    1369             :             }
    1370           0 :           else if (*p == '|')
    1371             :             {
    1372           0 :               digptr = NULL; /* We ignore the optional length.  */
    1373           0 :               base64 = p;
    1374             :             }
    1375             :           else
    1376             :             {
    1377           0 :               *erroff = p - buffer;
    1378           0 :               err = GPG_ERR_SEXP_INV_LEN_SPEC;
    1379           0 :               goto leave;
    1380             :             }
    1381             :         }
    1382      184360 :       else if (percent)
    1383             :         {
    1384       11204 :           if (*p == 'm' || *p == 'M')
    1385        3589 :             {
    1386             :               /* Insert an MPI.  */
    1387             :               gcry_mpi_t m;
    1388        3589 :               size_t nm = 0;
    1389        3589 :               int mpifmt = *p == 'm'? GCRYMPI_FMT_STD: GCRYMPI_FMT_USG;
    1390             : 
    1391        3589 :               ARG_NEXT (m, gcry_mpi_t);
    1392             : 
    1393        3589 :               if (mpi_get_flag (m, GCRYMPI_FLAG_OPAQUE))
    1394             :                 {
    1395             :                   void *mp;
    1396             :                   unsigned int nbits;
    1397             : 
    1398        2086 :                   mp = mpi_get_opaque (m, &nbits);
    1399        2086 :                   nm = (nbits+7)/8;
    1400        2086 :                   if (mp && nm)
    1401             :                     {
    1402        2086 :                       MAKE_SPACE (nm);
    1403        2086 :                       if (!_gcry_is_secure (c.sexp->d)
    1404        2086 :                           && mpi_get_flag (m, GCRYMPI_FLAG_SECURE))
    1405             :                         {
    1406             :                           /* We have to switch to secure allocation.  */
    1407             :                           gcry_sexp_t newsexp;
    1408             :                           byte *newhead;
    1409             : 
    1410           0 :                           newsexp = xtrymalloc_secure (sizeof *newsexp
    1411             :                                                        + c.allocated - 1);
    1412           0 :                           if (!newsexp)
    1413             :                             {
    1414           0 :                               err = gpg_err_code_from_errno (errno);
    1415           0 :                               goto leave;
    1416             :                             }
    1417           0 :                           newhead = newsexp->d;
    1418           0 :                           memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
    1419           0 :                           c.pos = newhead + (c.pos - c.sexp->d);
    1420           0 :                           xfree (c.sexp);
    1421           0 :                           c.sexp = newsexp;
    1422             :                         }
    1423             : 
    1424        2086 :                       *c.pos++ = ST_DATA;
    1425        2086 :                       STORE_LEN (c.pos, nm);
    1426        2086 :                       memcpy (c.pos, mp, nm);
    1427        2086 :                       c.pos += nm;
    1428             :                     }
    1429             :                 }
    1430             :               else
    1431             :                 {
    1432        1503 :                   if (_gcry_mpi_print (mpifmt, NULL, 0, &nm, m))
    1433           0 :                     BUG ();
    1434             : 
    1435        1503 :                   MAKE_SPACE (nm);
    1436        1503 :                   if (!_gcry_is_secure (c.sexp->d)
    1437        1501 :                       && mpi_get_flag ( m, GCRYMPI_FLAG_SECURE))
    1438             :                     {
    1439             :                       /* We have to switch to secure allocation.  */
    1440             :                       gcry_sexp_t newsexp;
    1441             :                       byte *newhead;
    1442             : 
    1443         195 :                       newsexp = xtrymalloc_secure (sizeof *newsexp
    1444             :                                                    + c.allocated - 1);
    1445         195 :                       if (!newsexp)
    1446             :                         {
    1447           0 :                           err = gpg_err_code_from_errno (errno);
    1448           0 :                           goto leave;
    1449             :                         }
    1450         195 :                       newhead = newsexp->d;
    1451         195 :                       memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
    1452         195 :                       c.pos = newhead + (c.pos - c.sexp->d);
    1453         195 :                       xfree (c.sexp);
    1454         195 :                       c.sexp = newsexp;
    1455             :                     }
    1456             : 
    1457        1503 :                   *c.pos++ = ST_DATA;
    1458        1503 :                   STORE_LEN (c.pos, nm);
    1459        1503 :                   if (_gcry_mpi_print (mpifmt, c.pos, nm, &nm, m))
    1460           0 :                     BUG ();
    1461        1503 :                   c.pos += nm;
    1462             :                 }
    1463             :             }
    1464        7615 :           else if (*p == 's')
    1465             :             {
    1466             :               /* Insert an string.  */
    1467             :               const char *astr;
    1468             :               size_t alen;
    1469             : 
    1470          94 :               ARG_NEXT (astr, const char *);
    1471          94 :               alen = strlen (astr);
    1472             : 
    1473          94 :               MAKE_SPACE (alen);
    1474          94 :               *c.pos++ = ST_DATA;
    1475          94 :               STORE_LEN (c.pos, alen);
    1476          94 :               memcpy (c.pos, astr, alen);
    1477          94 :               c.pos += alen;
    1478             :             }
    1479        7521 :           else if (*p == 'b')
    1480             :             {
    1481             :               /* Insert a memory buffer.  */
    1482             :               const char *astr;
    1483             :               int alen;
    1484             : 
    1485        7350 :               ARG_NEXT (alen, int);
    1486        7350 :               ARG_NEXT (astr, const char *);
    1487             : 
    1488        7350 :               MAKE_SPACE (alen);
    1489        7350 :               if (alen
    1490        7347 :                   && !_gcry_is_secure (c.sexp->d)
    1491        7347 :                   && _gcry_is_secure (astr))
    1492             :               {
    1493             :                   /* We have to switch to secure allocation.  */
    1494             :                   gcry_sexp_t newsexp;
    1495             :                   byte *newhead;
    1496             : 
    1497           2 :                   newsexp = xtrymalloc_secure (sizeof *newsexp
    1498             :                                                + c.allocated - 1);
    1499           2 :                   if (!newsexp)
    1500             :                     {
    1501           0 :                       err = gpg_err_code_from_errno (errno);
    1502           0 :                       goto leave;
    1503             :                     }
    1504           2 :                   newhead = newsexp->d;
    1505           2 :                   memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
    1506           2 :                   c.pos = newhead + (c.pos - c.sexp->d);
    1507           2 :                   xfree (c.sexp);
    1508           2 :                   c.sexp = newsexp;
    1509             :                 }
    1510             : 
    1511        7350 :               *c.pos++ = ST_DATA;
    1512        7350 :               STORE_LEN (c.pos, alen);
    1513        7350 :               memcpy (c.pos, astr, alen);
    1514        7350 :               c.pos += alen;
    1515             :             }
    1516         171 :           else if (*p == 'd')
    1517             :             {
    1518             :               /* Insert an integer as string.  */
    1519             :               int aint;
    1520             :               size_t alen;
    1521             :               char buf[35];
    1522             : 
    1523          33 :               ARG_NEXT (aint, int);
    1524          33 :               sprintf (buf, "%d", aint);
    1525          33 :               alen = strlen (buf);
    1526          33 :               MAKE_SPACE (alen);
    1527          33 :               *c.pos++ = ST_DATA;
    1528          33 :               STORE_LEN (c.pos, alen);
    1529          33 :               memcpy (c.pos, buf, alen);
    1530          33 :               c.pos += alen;
    1531             :             }
    1532         138 :           else if (*p == 'u')
    1533             :             {
    1534             :               /* Insert an unsigned integer as string.  */
    1535             :               unsigned int aint;
    1536             :               size_t alen;
    1537             :               char buf[35];
    1538             : 
    1539           0 :               ARG_NEXT (aint, unsigned int);
    1540           0 :               sprintf (buf, "%u", aint);
    1541           0 :               alen = strlen (buf);
    1542           0 :               MAKE_SPACE (alen);
    1543           0 :               *c.pos++ = ST_DATA;
    1544           0 :               STORE_LEN (c.pos, alen);
    1545           0 :               memcpy (c.pos, buf, alen);
    1546           0 :               c.pos += alen;
    1547             :             }
    1548         138 :           else if (*p == 'S')
    1549             :             {
    1550             :               /* Insert a gcry_sexp_t.  */
    1551             :               gcry_sexp_t asexp;
    1552             :               size_t alen, aoff;
    1553             : 
    1554         138 :               ARG_NEXT (asexp, gcry_sexp_t);
    1555         138 :               alen = get_internal_buffer (asexp, &aoff);
    1556         138 :               if (alen)
    1557             :                 {
    1558          92 :                   MAKE_SPACE (alen);
    1559          92 :                   memcpy (c.pos, asexp->d + aoff, alen);
    1560          92 :                   c.pos += alen;
    1561             :                 }
    1562             :             }
    1563             :           else
    1564             :             {
    1565           0 :               *erroff = p - buffer;
    1566             :               /* Invalid format specifier.  */
    1567           0 :               err = GPG_ERR_SEXP_INV_LEN_SPEC;
    1568           0 :               goto leave;
    1569             :             }
    1570       11204 :           percent = NULL;
    1571             :         }
    1572      173156 :       else if (*p == '(')
    1573             :         {
    1574       35685 :           if (disphint)
    1575             :             {
    1576           0 :               *erroff = p - buffer;
    1577             :               /* Open display hint.  */
    1578           0 :               err = GPG_ERR_SEXP_UNMATCHED_DH;
    1579           0 :               goto leave;
    1580             :             }
    1581       35685 :           MAKE_SPACE (0);
    1582       35685 :           *c.pos++ = ST_OPEN;
    1583       35685 :           level++;
    1584             :         }
    1585      137471 :       else if (*p == ')')
    1586             :         {
    1587             :           /* Walk up.  */
    1588       35685 :           if (disphint)
    1589             :             {
    1590           0 :               *erroff = p - buffer;
    1591             :               /* Open display hint.  */
    1592           0 :               err = GPG_ERR_SEXP_UNMATCHED_DH;
    1593           0 :               goto leave;
    1594             :             }
    1595       35685 :           MAKE_SPACE (0);
    1596       35685 :           *c.pos++ = ST_CLOSE;
    1597       35685 :           level--;
    1598             :         }
    1599      101786 :       else if (*p == '\"')
    1600             :         {
    1601        2166 :           quoted = p;
    1602        2166 :           quoted_esc = 0;
    1603             :         }
    1604       99620 :       else if (*p == '#')
    1605             :         {
    1606        1160 :           hexfmt = p;
    1607        1160 :           hexcount = 0;
    1608             :         }
    1609       98460 :       else if (*p == '|')
    1610           0 :         base64 = p;
    1611       98460 :       else if (*p == '[')
    1612             :         {
    1613           0 :           if (disphint)
    1614             :             {
    1615           0 :               *erroff = p - buffer;
    1616             :               /* Open display hint.  */
    1617           0 :               err = GPG_ERR_SEXP_NESTED_DH;
    1618           0 :               goto leave;
    1619             :             }
    1620           0 :           disphint = p;
    1621             :         }
    1622       98460 :       else if (*p == ']')
    1623             :         {
    1624           0 :           if (!disphint)
    1625             :             {
    1626           0 :               *erroff = p - buffer;
    1627             :               /* Open display hint.  */
    1628           0 :               err = GPG_ERR_SEXP_UNMATCHED_DH;
    1629           0 :               goto leave;
    1630             :             }
    1631           0 :           disphint = NULL;
    1632             :         }
    1633       98460 :       else if (digitp (p))
    1634             :         {
    1635         742 :           if (*p == '0')
    1636             :             {
    1637             :               /* A length may not begin with zero.  */
    1638           0 :               *erroff = p - buffer;
    1639           0 :               err = GPG_ERR_SEXP_ZERO_PREFIX;
    1640           0 :               goto leave;
    1641             :             }
    1642         742 :           digptr = p;
    1643             :         }
    1644       97718 :       else if (strchr (tokenchars, *p))
    1645       43130 :         tokenp = p;
    1646       54588 :       else if (whitespacep (p))
    1647             :         ;
    1648       11204 :       else if (*p == '{')
    1649             :         {
    1650             :           /* fixme: handle rescanning: we can do this by saving our
    1651             :              current state and start over at p+1 -- Hmmm. At this
    1652             :              point here we are in a well defined state, so we don't
    1653             :              need to save it.  Great.  */
    1654           0 :           *erroff = p - buffer;
    1655           0 :           err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
    1656           0 :           goto leave;
    1657             :         }
    1658       11204 :       else if (strchr ("&\\", *p))
    1659             :         {
    1660             :           /* Reserved punctuation.  */
    1661           0 :           *erroff = p - buffer;
    1662           0 :           err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
    1663           0 :           goto leave;
    1664             :         }
    1665       11204 :       else if (argflag && (*p == '%'))
    1666       11204 :         percent = p;
    1667             :       else
    1668             :         {
    1669             :           /* Bad or unavailable.  */
    1670           0 :           *erroff = p - buffer;
    1671           0 :           err = GPG_ERR_SEXP_BAD_CHARACTER;
    1672           0 :           goto leave;
    1673             :         }
    1674             :     }
    1675        8900 :   MAKE_SPACE (0);
    1676        8900 :   *c.pos++ = ST_STOP;
    1677             : 
    1678        8900 :   if (level && !err)
    1679           2 :     err = GPG_ERR_SEXP_UNMATCHED_PAREN;
    1680             : 
    1681             :  leave:
    1682        8900 :   if (err)
    1683             :     {
    1684             :       /* Error -> deallocate.  */
    1685           2 :       if (c.sexp)
    1686             :         {
    1687             :           /* Extra paranoid wipe on error. */
    1688           2 :           if (_gcry_is_secure (c.sexp))
    1689           0 :             wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
    1690           2 :           xfree (c.sexp);
    1691             :         }
    1692             :     }
    1693             :   else
    1694        8898 :     *retsexp = normalize (c.sexp);
    1695             : 
    1696        8900 :   return err;
    1697             : #undef MAKE_SPACE
    1698             : #undef STORE_LEN
    1699             : }
    1700             : 
    1701             : 
    1702             : static gpg_err_code_t
    1703         832 : do_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
    1704             :                const char *buffer, size_t length, int argflag,
    1705             :                void **arg_list, ...)
    1706             : {
    1707             :   gcry_err_code_t rc;
    1708             :   va_list arg_ptr;
    1709             : 
    1710         832 :   va_start (arg_ptr, arg_list);
    1711         832 :   rc = do_vsexp_sscan (retsexp, erroff, buffer, length, argflag,
    1712             :                        arg_list, arg_ptr);
    1713         832 :   va_end (arg_ptr);
    1714             : 
    1715         832 :   return rc;
    1716             : }
    1717             : 
    1718             : 
    1719             : gpg_err_code_t
    1720        2934 : _gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...)
    1721             : {
    1722             :   gcry_err_code_t rc;
    1723             :   va_list arg_ptr;
    1724             : 
    1725        2934 :   va_start (arg_ptr, format);
    1726        2934 :   rc = do_vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
    1727             :                        NULL, arg_ptr);
    1728        2934 :   va_end (arg_ptr);
    1729             : 
    1730        2934 :   return rc;
    1731             : }
    1732             : 
    1733             : 
    1734             : gcry_err_code_t
    1735        5134 : _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff,
    1736             :                    const char *format, va_list arg_ptr)
    1737             : {
    1738        5134 :   return do_vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
    1739             :                          NULL, arg_ptr);
    1740             : }
    1741             : 
    1742             : 
    1743             : /* Like gcry_sexp_build, but uses an array instead of variable
    1744             :    function arguments.  */
    1745             : gcry_err_code_t
    1746          33 : _gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
    1747             :                         const char *format, void **arg_list)
    1748             : {
    1749          33 :   return do_sexp_sscan (retsexp, erroff, format, strlen(format), 1, arg_list);
    1750             : }
    1751             : 
    1752             : 
    1753             : gcry_err_code_t
    1754         463 : _gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
    1755             :                   const char *buffer, size_t length)
    1756             : {
    1757         463 :   return do_sexp_sscan (retsexp, erroff, buffer, length, 0, NULL);
    1758             : }
    1759             : 
    1760             : 
    1761             : /* Figure out a suitable encoding for BUFFER of LENGTH.
    1762             :    Returns: 0 = Binary
    1763             :             1 = String possible
    1764             :             2 = Token possible
    1765             : */
    1766             : static int
    1767           0 : suitable_encoding (const unsigned char *buffer, size_t length)
    1768             : {
    1769             :   const unsigned char *s;
    1770           0 :   int maybe_token = 1;
    1771             : 
    1772           0 :   if (!length)
    1773           0 :     return 1;
    1774             : 
    1775           0 :   if (*buffer & 0x80)
    1776           0 :     return 0; /* If the MSB is set we assume that buffer represents a
    1777             :                  negative number.  */
    1778           0 :   if (!*buffer)
    1779           0 :     return 0; /* Starting with a zero is pretty much a binary string.  */
    1780             : 
    1781           0 :   for (s=buffer; length; s++, length--)
    1782             :     {
    1783           0 :       if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
    1784           0 :            && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
    1785           0 :         return 0; /*binary*/
    1786           0 :       if ( maybe_token
    1787           0 :            && !alphap (s) && !digitp (s)  && !strchr (TOKEN_SPECIALS, *s))
    1788           0 :         maybe_token = 0;
    1789             :     }
    1790           0 :   s = buffer;
    1791           0 :   if ( maybe_token && !digitp (s) )
    1792           0 :     return 2;
    1793           0 :   return 1;
    1794             : }
    1795             : 
    1796             : 
    1797             : static int
    1798           0 : convert_to_hex (const unsigned char *src, size_t len, char *dest)
    1799             : {
    1800             :   int i;
    1801             : 
    1802           0 :   if (dest)
    1803             :     {
    1804           0 :       *dest++ = '#';
    1805           0 :       for (i=0; i < len; i++, dest += 2 )
    1806           0 :         sprintf (dest, "%02X", src[i]);
    1807           0 :       *dest++ = '#';
    1808             :     }
    1809           0 :   return len*2+2;
    1810             : }
    1811             : 
    1812             : static int
    1813           0 : convert_to_string (const unsigned char *s, size_t len, char *dest)
    1814             : {
    1815           0 :   if (dest)
    1816             :     {
    1817           0 :       char *p = dest;
    1818           0 :       *p++ = '\"';
    1819           0 :       for (; len; len--, s++ )
    1820             :         {
    1821           0 :           switch (*s)
    1822             :             {
    1823           0 :             case '\b': *p++ = '\\'; *p++ = 'b';  break;
    1824           0 :             case '\t': *p++ = '\\'; *p++ = 't';  break;
    1825           0 :             case '\v': *p++ = '\\'; *p++ = 'v';  break;
    1826           0 :             case '\n': *p++ = '\\'; *p++ = 'n';  break;
    1827           0 :             case '\f': *p++ = '\\'; *p++ = 'f';  break;
    1828           0 :             case '\r': *p++ = '\\'; *p++ = 'r';  break;
    1829           0 :             case '\"': *p++ = '\\'; *p++ = '\"';  break;
    1830           0 :             case '\'': *p++ = '\\'; *p++ = '\'';  break;
    1831           0 :             case '\\': *p++ = '\\'; *p++ = '\\';  break;
    1832             :             default:
    1833           0 :               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
    1834             :                 {
    1835           0 :                   sprintf (p, "\\x%02x", *s);
    1836           0 :                   p += 4;
    1837             :                 }
    1838             :               else
    1839           0 :                 *p++ = *s;
    1840             :             }
    1841             :         }
    1842           0 :       *p++ = '\"';
    1843           0 :       return p - dest;
    1844             :     }
    1845             :   else
    1846             :     {
    1847           0 :       int count = 2;
    1848           0 :       for (; len; len--, s++ )
    1849             :         {
    1850           0 :           switch (*s)
    1851             :             {
    1852             :             case '\b':
    1853             :             case '\t':
    1854             :             case '\v':
    1855             :             case '\n':
    1856             :             case '\f':
    1857             :             case '\r':
    1858             :             case '\"':
    1859             :             case '\'':
    1860           0 :             case '\\': count += 2; break;
    1861             :             default:
    1862           0 :               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
    1863           0 :                 count += 4;
    1864             :               else
    1865           0 :                 count++;
    1866             :             }
    1867             :         }
    1868           0 :       return count;
    1869             :     }
    1870             : }
    1871             : 
    1872             : 
    1873             : 
    1874             : static int
    1875           0 : convert_to_token (const unsigned char *src, size_t len, char *dest)
    1876             : {
    1877           0 :   if (dest)
    1878           0 :     memcpy (dest, src, len);
    1879           0 :   return len;
    1880             : }
    1881             : 
    1882             : 
    1883             : /****************
    1884             :  * Print SEXP to buffer using the MODE.  Returns the length of the
    1885             :  * SEXP in buffer or 0 if the buffer is too short (We have at least an
    1886             :  * empty list consisting of 2 bytes).  If a buffer of NULL is provided,
    1887             :  * the required length is returned.
    1888             :  */
    1889             : size_t
    1890         349 : _gcry_sexp_sprint (const gcry_sexp_t list, int mode,
    1891             :                    void *buffer, size_t maxlength )
    1892             : {
    1893             :   static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
    1894             :   const unsigned char *s;
    1895             :   char *d;
    1896             :   DATALEN n;
    1897             :   char numbuf[20];
    1898         349 :   size_t len = 0;
    1899         349 :   int i, indent = 0;
    1900             : 
    1901         349 :   s = list? list->d : empty;
    1902         349 :   d = buffer;
    1903        3677 :   while ( *s != ST_STOP )
    1904             :     {
    1905        2979 :       switch ( *s )
    1906             :         {
    1907             :         case ST_OPEN:
    1908         829 :           s++;
    1909         829 :           if ( mode != GCRYSEXP_FMT_CANON )
    1910             :             {
    1911           0 :               if (indent)
    1912           0 :                 len++;
    1913           0 :               len += indent;
    1914             :             }
    1915         829 :           len++;
    1916         829 :           if ( buffer )
    1917             :             {
    1918         419 :               if ( len >= maxlength )
    1919           0 :                 return 0;
    1920         419 :               if ( mode != GCRYSEXP_FMT_CANON )
    1921             :                 {
    1922           0 :                   if (indent)
    1923           0 :                     *d++ = '\n';
    1924           0 :                   for (i=0; i < indent; i++)
    1925           0 :                     *d++ = ' ';
    1926             :                 }
    1927         419 :               *d++ = '(';
    1928             :             }
    1929         829 :           indent++;
    1930         829 :           break;
    1931             :         case ST_CLOSE:
    1932         829 :           s++;
    1933         829 :           len++;
    1934         829 :           if ( buffer )
    1935             :             {
    1936         419 :               if ( len >= maxlength )
    1937           0 :                 return 0;
    1938         419 :               *d++ = ')';
    1939             :             }
    1940         829 :           indent--;
    1941         829 :           if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
    1942             :             {
    1943           0 :               len++;
    1944           0 :               len += indent;
    1945           0 :               if (buffer)
    1946             :                 {
    1947           0 :                   if (len >= maxlength)
    1948           0 :                     return 0;
    1949           0 :                   *d++ = '\n';
    1950           0 :                   for (i=0; i < indent; i++)
    1951           0 :                     *d++ = ' ';
    1952             :                 }
    1953             :             }
    1954         829 :           break;
    1955             :         case ST_DATA:
    1956        1321 :           s++;
    1957        1321 :           memcpy ( &n, s, sizeof n ); s += sizeof n;
    1958        1321 :           if (mode == GCRYSEXP_FMT_ADVANCED)
    1959             :             {
    1960             :               int type;
    1961             :               size_t nn;
    1962             : 
    1963           0 :               switch ( (type=suitable_encoding (s, n)))
    1964             :                 {
    1965           0 :                 case 1: nn = convert_to_string (s, n, NULL); break;
    1966           0 :                 case 2: nn = convert_to_token (s, n, NULL); break;
    1967           0 :                 default: nn = convert_to_hex (s, n, NULL); break;
    1968             :                 }
    1969           0 :               len += nn;
    1970           0 :               if (buffer)
    1971             :                 {
    1972           0 :                   if (len >= maxlength)
    1973           0 :                     return 0;
    1974           0 :                   switch (type)
    1975             :                     {
    1976           0 :                     case 1: convert_to_string (s, n, d); break;
    1977           0 :                     case 2: convert_to_token (s, n, d); break;
    1978           0 :                     default: convert_to_hex (s, n, d); break;
    1979             :                     }
    1980           0 :                   d += nn;
    1981             :                 }
    1982           0 :               if (s[n] != ST_CLOSE)
    1983             :                 {
    1984           0 :                   len++;
    1985           0 :                   if (buffer)
    1986             :                     {
    1987           0 :                       if (len >= maxlength)
    1988           0 :                         return 0;
    1989           0 :                       *d++ = ' ';
    1990             :                     }
    1991             :                 }
    1992             :             }
    1993             :           else
    1994             :             {
    1995        1321 :               sprintf (numbuf, "%u:", (unsigned int)n );
    1996        1321 :               len += strlen (numbuf) + n;
    1997        1321 :               if ( buffer )
    1998             :                 {
    1999         670 :                   if ( len >= maxlength )
    2000           0 :                     return 0;
    2001         670 :                   d = stpcpy ( d, numbuf );
    2002         670 :                   memcpy ( d, s, n ); d += n;
    2003             :                 }
    2004             :             }
    2005        1321 :           s += n;
    2006        1321 :           break;
    2007             :         default:
    2008           0 :           BUG ();
    2009             :         }
    2010             :     }
    2011         349 :   if ( mode != GCRYSEXP_FMT_CANON )
    2012             :     {
    2013           0 :       len++;
    2014           0 :       if (buffer)
    2015             :         {
    2016           0 :           if ( len >= maxlength )
    2017           0 :             return 0;
    2018           0 :           *d++ = '\n';
    2019             :         }
    2020             :     }
    2021         349 :   if (buffer)
    2022             :     {
    2023         176 :       if ( len >= maxlength )
    2024           0 :         return 0;
    2025         176 :       *d++ = 0; /* for convenience we make a C string */
    2026             :     }
    2027             :   else
    2028         173 :     len++; /* we need one byte more for this */
    2029             : 
    2030         349 :   return len;
    2031             : }
    2032             : 
    2033             : 
    2034             : /* Scan a canonical encoded buffer with implicit length values and
    2035             :    return the actual length this S-expression uses.  For a valid S-Exp
    2036             :    it should never return 0.  If LENGTH is not zero, the maximum
    2037             :    length to scan is given - this can be used for syntax checks of
    2038             :    data passed from outside. errorcode and erroff may both be passed as
    2039             :    NULL.  */
    2040             : size_t
    2041          14 : _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
    2042             :                       size_t *erroff, gcry_err_code_t *errcode)
    2043             : {
    2044             :   const unsigned char *p;
    2045          14 :   const unsigned char *disphint = NULL;
    2046          14 :   unsigned int datalen = 0;
    2047             :   size_t dummy_erroff;
    2048             :   gcry_err_code_t dummy_errcode;
    2049          14 :   size_t count = 0;
    2050          14 :   int level = 0;
    2051             : 
    2052          14 :   if (!erroff)
    2053           0 :     erroff = &dummy_erroff;
    2054          14 :   if (!errcode)
    2055           0 :     errcode = &dummy_errcode;
    2056             : 
    2057          14 :   *errcode = GPG_ERR_NO_ERROR;
    2058          14 :   *erroff = 0;
    2059          14 :   if (!buffer)
    2060           0 :     return 0;
    2061          14 :   if (*buffer != '(')
    2062             :     {
    2063           1 :       *errcode = GPG_ERR_SEXP_NOT_CANONICAL;
    2064           1 :       return 0;
    2065             :     }
    2066             : 
    2067          48 :   for (p=buffer; ; p++, count++ )
    2068             :     {
    2069          48 :       if (length && count >= length)
    2070             :         {
    2071           3 :           *erroff = count;
    2072           3 :           *errcode = GPG_ERR_SEXP_STRING_TOO_LONG;
    2073           3 :           return 0;
    2074             :         }
    2075             : 
    2076          45 :       if (datalen)
    2077             :         {
    2078           9 :           if (*p == ':')
    2079             :             {
    2080           7 :               if (length && (count+datalen) >= length)
    2081             :                 {
    2082           0 :                   *erroff = count;
    2083           0 :                   *errcode = GPG_ERR_SEXP_STRING_TOO_LONG;
    2084           0 :                   return 0;
    2085             :                 }
    2086           7 :               count += datalen;
    2087           7 :               p += datalen;
    2088           7 :               datalen = 0;
    2089             :             }
    2090           2 :           else if (digitp(p))
    2091           2 :             datalen = datalen*10 + atoi_1(p);
    2092             :           else
    2093             :             {
    2094           0 :               *erroff = count;
    2095           0 :               *errcode = GPG_ERR_SEXP_INV_LEN_SPEC;
    2096           0 :               return 0;
    2097             :             }
    2098             :         }
    2099          36 :       else if (*p == '(')
    2100             :         {
    2101          16 :           if (disphint)
    2102             :             {
    2103           0 :               *erroff = count;
    2104           0 :               *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
    2105           0 :               return 0;
    2106             :             }
    2107          16 :           level++;
    2108             :         }
    2109          20 :       else if (*p == ')')
    2110             :         { /* walk up */
    2111          10 :           if (!level)
    2112             :             {
    2113           0 :               *erroff = count;
    2114           0 :               *errcode = GPG_ERR_SEXP_UNMATCHED_PAREN;
    2115           0 :               return 0;
    2116             :             }
    2117          10 :           if (disphint)
    2118             :             {
    2119           0 :               *erroff = count;
    2120           0 :               *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
    2121           0 :               return 0;
    2122             :             }
    2123          10 :           if (!--level)
    2124           7 :             return ++count; /* ready */
    2125             :         }
    2126          10 :       else if (*p == '[')
    2127             :         {
    2128           0 :           if (disphint)
    2129             :             {
    2130           0 :               *erroff = count;
    2131           0 :               *errcode = GPG_ERR_SEXP_NESTED_DH;
    2132           0 :               return 0;
    2133             :             }
    2134           0 :           disphint = p;
    2135             :         }
    2136          10 :       else if (*p == ']')
    2137             :         {
    2138           0 :           if ( !disphint )
    2139             :             {
    2140           0 :               *erroff = count;
    2141           0 :               *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
    2142           0 :               return 0;
    2143             :             }
    2144           0 :           disphint = NULL;
    2145             :         }
    2146          10 :       else if (digitp (p) )
    2147             :         {
    2148           8 :           if (*p == '0')
    2149             :             {
    2150           1 :               *erroff = count;
    2151           1 :               *errcode = GPG_ERR_SEXP_ZERO_PREFIX;
    2152           1 :               return 0;
    2153             :             }
    2154           7 :           datalen = atoi_1 (p);
    2155             :         }
    2156           2 :       else if (*p == '&' || *p == '\\')
    2157             :         {
    2158           0 :           *erroff = count;
    2159           0 :           *errcode = GPG_ERR_SEXP_UNEXPECTED_PUNC;
    2160           0 :           return 0;
    2161             :         }
    2162             :       else
    2163             :         {
    2164           2 :           *erroff = count;
    2165           2 :           *errcode = GPG_ERR_SEXP_BAD_CHARACTER;
    2166           2 :           return 0;
    2167             :         }
    2168          35 :     }
    2169             : }
    2170             : 
    2171             : 
    2172             : /* Extract MPIs from an s-expression using a list of parameters.  The
    2173             :  * names of these parameters are given by the string LIST.  Some
    2174             :  * special characters may be given to control the conversion:
    2175             :  *
    2176             :  *    + :: Switch to unsigned integer format (default).
    2177             :  *    - :: Switch to standard signed format.
    2178             :  *    / :: Switch to opaque format.
    2179             :  *    & :: Switch to buffer descriptor mode - see below.
    2180             :  *    ? :: The previous parameter is optional.
    2181             :  *
    2182             :  * In general parameter names are single letters.  To use a string for
    2183             :  * a parameter name, enclose the name in single quotes.
    2184             :  *
    2185             :  * Unless in gcry_buffer_t mode for each parameter name a pointer to
    2186             :  * an MPI variable is expected and finally a NULL is expected.
    2187             :  * Example:
    2188             :  *
    2189             :  *   _gcry_sexp_extract_param (key, NULL, "n/x+ed",
    2190             :  *                             &mpi_n, &mpi_x, &mpi_e, NULL)
    2191             :  *
    2192             :  * This stores the parameter "N" from KEY as an unsigned MPI into
    2193             :  * MPI_N, the parameter "X" as an opaque MPI into MPI_X, and the
    2194             :  * parameter "E" again as an unsigned MPI into MPI_E.
    2195             :  *
    2196             :  * If in buffer descriptor mode a pointer to gcry_buffer_t descriptor
    2197             :  * is expected instead of a pointer to an MPI.  The caller may use two
    2198             :  * different operation modes: If the DATA field of the provided buffer
    2199             :  * descriptor is NULL, the function allocates a new buffer and stores
    2200             :  * it at DATA; the other fields are set accordingly with OFF being 0.
    2201             :  * If DATA is not NULL, the function assumes that DATA, SIZE, and OFF
    2202             :  * describe a buffer where to but the data; on return the LEN field
    2203             :  * receives the number of bytes copied to that buffer; if the buffer
    2204             :  * is too small, the function immediately returns with an error code
    2205             :  * (and LEN set to 0).
    2206             :  *
    2207             :  * PATH is an optional string used to locate a token.  The exclamation
    2208             :  * mark separated tokens are used to via gcry_sexp_find_token to find
    2209             :  * a start point inside SEXP.
    2210             :  *
    2211             :  * The function returns NULL on success.  On error an error code is
    2212             :  * returned and the passed MPIs are either unchanged or set to NULL.
    2213             :  */
    2214             : gpg_err_code_t
    2215        7150 : _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
    2216             :                            const char *list, va_list arg_ptr)
    2217             : {
    2218             :   gpg_err_code_t rc;
    2219             :   const char *s, *s2;
    2220             :   gcry_mpi_t *array[20];
    2221             :   char arrayisdesc[20];
    2222             :   int idx;
    2223             :   gcry_sexp_t l1;
    2224        7150 :   int mode = '+'; /* Default to GCRYMPI_FMT_USG.  */
    2225        7150 :   gcry_sexp_t freethis = NULL;
    2226             : 
    2227        7150 :   memset (arrayisdesc, 0, sizeof arrayisdesc);
    2228             : 
    2229             :   /* First copy all the args into an array.  This is required so that
    2230             :      we are able to release already allocated MPIs if later an error
    2231             :      was found.  */
    2232       32703 :   for (s=list, idx=0; *s && idx < DIM (array); s++)
    2233             :     {
    2234       25556 :       if (*s == '&' || *s == '+' || *s == '-' || *s == '/' || *s == '?')
    2235             :         ;
    2236       16643 :       else if (whitespacep (s))
    2237             :         ;
    2238             :       else
    2239             :         {
    2240       16636 :           if (*s == '\'')
    2241             :             {
    2242           4 :               s++;
    2243           4 :               s2 = strchr (s, '\'');
    2244           4 :               if (!s2 || s2 == s)
    2245             :                 {
    2246             :                   /* Closing quote not found or empty string.  */
    2247           2 :                   return GPG_ERR_SYNTAX;
    2248             :                 }
    2249           2 :               s = s2;
    2250             :             }
    2251       16634 :           array[idx] = va_arg (arg_ptr, gcry_mpi_t *);
    2252       16634 :           if (!array[idx])
    2253           1 :             return GPG_ERR_MISSING_VALUE; /* NULL pointer given.  */
    2254       16633 :           idx++;
    2255             :         }
    2256             :     }
    2257        7147 :   if (*s)
    2258           0 :     return GPG_ERR_LIMIT_REACHED;  /* Too many list elements.  */
    2259        7147 :   if (va_arg (arg_ptr, gcry_mpi_t *))
    2260           1 :     return GPG_ERR_INV_ARG;  /* Not enough list elemends.  */
    2261             : 
    2262             :   /* Drill down.  */
    2263       14305 :   while (path && *path)
    2264             :     {
    2265             :       size_t n;
    2266             : 
    2267          15 :       s = strchr (path, '!');
    2268          15 :       if (s == path)
    2269             :         {
    2270           1 :           rc = GPG_ERR_NOT_FOUND;
    2271           1 :           goto cleanup;
    2272             :         }
    2273          14 :       n = s? s - path : 0;
    2274          14 :       l1 = _gcry_sexp_find_token (sexp, path, n);
    2275          14 :       if (!l1)
    2276             :         {
    2277           1 :           rc = GPG_ERR_NOT_FOUND;
    2278           1 :           goto cleanup;
    2279             :         }
    2280          13 :       sexp = l1; l1 = NULL;
    2281          13 :       sexp_release (freethis);
    2282          13 :       freethis = sexp;
    2283          13 :       if (n)
    2284           6 :         path += n + 1;
    2285             :       else
    2286           7 :         path = NULL;
    2287             :     }
    2288             : 
    2289             : 
    2290             :   /* Now extract all parameters.  */
    2291       32656 :   for (s=list, idx=0; *s; s++)
    2292             :     {
    2293       25517 :       if (*s == '&' || *s == '+' || *s == '-' || *s == '/')
    2294        4629 :         mode = *s;
    2295       20888 :       else if (whitespacep (s))
    2296             :         ;
    2297       20881 :       else if (*s == '?')
    2298             :         ; /* Only used via lookahead.  */
    2299             :       else
    2300             :         {
    2301       16597 :           if (*s == '\'')
    2302             :             {
    2303             :               /* Find closing quote, find token, set S to closing quote.  */
    2304           2 :               s++;
    2305           2 :               s2 = strchr (s, '\'');
    2306           2 :               if (!s2 || s2 == s)
    2307             :                 {
    2308             :                   /* Closing quote not found or empty string.  */
    2309           0 :                   rc = GPG_ERR_SYNTAX;
    2310           0 :                   goto cleanup;
    2311             :                 }
    2312           2 :               l1 = _gcry_sexp_find_token (sexp, s, s2 - s);
    2313           2 :               s = s2;
    2314             :             }
    2315             :           else
    2316       16595 :             l1 = _gcry_sexp_find_token (sexp, s, 1);
    2317             : 
    2318       16597 :           if (!l1 && s[1] == '?')
    2319             :             {
    2320             :               /* Optional element not found.  */
    2321        6414 :               if (mode == '&')
    2322             :                 {
    2323           0 :                   gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
    2324           0 :                   if (!spec->data)
    2325             :                     {
    2326           0 :                       spec->size = 0;
    2327           0 :                       spec->off = 0;
    2328             :                     }
    2329           0 :                   spec->len = 0;
    2330             :                 }
    2331             :               else
    2332        3207 :                 *array[idx] = NULL;
    2333             :             }
    2334       13390 :           else if (!l1)
    2335             :             {
    2336           5 :               rc = GPG_ERR_NO_OBJ;  /* List element not found.  */
    2337           5 :               goto cleanup;
    2338             :             }
    2339             :            else
    2340             :             {
    2341       13385 :               if (mode == '&')
    2342             :                 {
    2343           4 :                   gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
    2344             : 
    2345           4 :                   if (spec->data)
    2346             :                     {
    2347             :                       const char *pbuf;
    2348             :                       size_t nbuf;
    2349             : 
    2350           2 :                       pbuf = _gcry_sexp_nth_data (l1, 1, &nbuf);
    2351           2 :                       if (!pbuf || !nbuf)
    2352             :                         {
    2353           0 :                           rc = GPG_ERR_INV_OBJ;
    2354           0 :                           goto cleanup;
    2355             :                         }
    2356           2 :                       if (spec->off + nbuf > spec->size)
    2357             :                         {
    2358           0 :                           rc = GPG_ERR_BUFFER_TOO_SHORT;
    2359           0 :                           goto cleanup;
    2360             :                         }
    2361           2 :                       memcpy ((char*)spec->data + spec->off, pbuf, nbuf);
    2362           2 :                       spec->len = nbuf;
    2363           2 :                       arrayisdesc[idx] = 1;
    2364             :                     }
    2365             :                   else
    2366             :                     {
    2367           2 :                       spec->data = _gcry_sexp_nth_buffer (l1, 1, &spec->size);
    2368           2 :                       if (!spec->data)
    2369             :                         {
    2370           0 :                           rc = GPG_ERR_INV_OBJ; /* Or out of core.  */
    2371           0 :                           goto cleanup;
    2372             :                         }
    2373           2 :                       spec->len = spec->size;
    2374           2 :                       spec->off = 0;
    2375           2 :                       arrayisdesc[idx] = 2;
    2376             :                     }
    2377             :                 }
    2378       13381 :               else if (mode == '/')
    2379        3433 :                 *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
    2380        9948 :               else if (mode == '-')
    2381          73 :                 *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_STD);
    2382             :               else
    2383        9875 :                 *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
    2384       13385 :               sexp_release (l1); l1 = NULL;
    2385       13385 :               if (!*array[idx])
    2386             :                 {
    2387           0 :                   rc = GPG_ERR_INV_OBJ;  /* Conversion failed.  */
    2388           0 :                   goto cleanup;
    2389             :                 }
    2390             :             }
    2391       16592 :           idx++;
    2392             :         }
    2393             :     }
    2394             : 
    2395        7139 :   sexp_release (freethis);
    2396        7139 :   return 0;
    2397             : 
    2398             :  cleanup:
    2399           7 :   sexp_release (freethis);
    2400           7 :   sexp_release (l1);
    2401          46 :   while (idx--)
    2402             :     {
    2403          32 :       if (!arrayisdesc[idx])
    2404             :         {
    2405          32 :           _gcry_mpi_release (*array[idx]);
    2406          32 :           *array[idx] = NULL;
    2407             :         }
    2408           0 :       else if (arrayisdesc[idx] == 1)
    2409             :         {
    2410             :           /* Caller provided buffer.  */
    2411           0 :           gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
    2412           0 :           spec->len = 0;
    2413             :         }
    2414             :       else
    2415             :         {
    2416             :           /* We might have allocated a buffer.  */
    2417           0 :           gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
    2418           0 :           xfree (spec->data);
    2419           0 :           spec->data = NULL;
    2420           0 :           spec->size = spec->off = spec->len = 0;
    2421             :         }
    2422             :      }
    2423           7 :   return rc;
    2424             : }
    2425             : 
    2426             : gpg_err_code_t
    2427        7130 : _gcry_sexp_extract_param (gcry_sexp_t sexp, const char *path,
    2428             :                           const char *list, ...)
    2429             : {
    2430             :   gcry_err_code_t rc;
    2431             :   va_list arg_ptr;
    2432             : 
    2433        7130 :   va_start (arg_ptr, list);
    2434        7130 :   rc = _gcry_sexp_vextract_param (sexp, path, list, arg_ptr);
    2435        7130 :   va_end (arg_ptr);
    2436        7130 :   return rc;
    2437             : }

Generated by: LCOV version 1.11