Do not ship generated header file in tarball.
[libgcrypt.git] / src / sexp.c
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 accidentally 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 whitespacep (const char *p)
120 {
121   switch (*p)
122     {
123     case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1;
124     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 dump_string (const byte *p, size_t n, int delim )
147 {
148   for (; n; n--, p++ )
149     {
150       if ((*p & 0x80) || iscntrl( *p ) || *p == delim )
151         {
152           if( *p == '\n' )
153             log_printf ("\\n");
154           else if( *p == '\r' )
155             log_printf ("\\r");
156           else if( *p == '\f' )
157             log_printf ("\\f");
158           else if( *p == '\v' )
159             log_printf ("\\v");
160             else if( *p == '\b' )
161               log_printf ("\\b");
162           else if( !*p )
163             log_printf ("\\0");
164           else
165             log_printf ("\\x%02x", *p );
166         }
167       else
168         log_printf ("%c", *p);
169     }
170 }
171
172
173 void
174 _gcry_sexp_dump (const gcry_sexp_t a)
175 {
176   const byte *p;
177   int indent = 0;
178   int type;
179
180   if (!a)
181     {
182       log_printf ( "[nil]\n");
183       return;
184     }
185
186   p = a->d;
187   while ( (type = *p) != ST_STOP )
188     {
189       p++;
190       switch ( type )
191         {
192         case ST_OPEN:
193           log_printf ("%*s[open]\n", 2*indent, "");
194           indent++;
195           break;
196         case ST_CLOSE:
197           if( indent )
198             indent--;
199           log_printf ("%*s[close]\n", 2*indent, "");
200           break;
201         case ST_DATA: {
202           DATALEN n;
203           memcpy ( &n, p, sizeof n );
204           p += sizeof n;
205           log_printf ("%*s[data=\"", 2*indent, "" );
206           dump_string (p, n, '\"' );
207           log_printf ("\"]\n");
208           p += n;
209         }
210         break;
211         default:
212           log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type);
213           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 normalize ( gcry_sexp_t list )
225 {
226   unsigned char *p;
227
228   if ( !list )
229     return NULL;
230   p = list->d;
231   if ( *p == ST_STOP )
232     {
233       /* this is "" */
234       sexp_release ( list );
235       return NULL;
236     }
237   if ( *p == ST_OPEN && p[1] == ST_CLOSE )
238     {
239       /* this is "()" */
240       sexp_release ( list );
241       return NULL;
242     }
243
244   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 _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   if (!retsexp)
270     return GPG_ERR_INV_ARG;
271   *retsexp = NULL;
272   if (autodetect < 0 || autodetect > 1 || !buffer)
273     return GPG_ERR_INV_ARG;
274
275   if (!length && !autodetect)
276     { /* What a brave caller to assume that there is really a canonical
277          encoded S-expression in buffer */
278       length = _gcry_sexp_canon_len (buffer, 0, NULL, &errcode);
279       if (!length)
280         return errcode;
281     }
282   else if (!length && autodetect)
283     { /* buffer is a string */
284       length = strlen ((char *)buffer);
285     }
286
287   errcode = do_sexp_sscan (&se, NULL, buffer, length, 0, NULL);
288   if (errcode)
289     return errcode;
290
291   *retsexp = se;
292   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       freefnc (buffer);
300     }
301   return 0;
302 }
303
304 /* Same as gcry_sexp_create but don't transfer ownership */
305 gcry_err_code_t
306 _gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length,
307                int autodetect)
308 {
309   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 _gcry_sexp_release( gcry_sexp_t sexp )
318 {
319   if (sexp)
320     {
321       if (_gcry_is_secure (sexp))
322         {
323           /* Extra paranoid wiping. */
324           const byte *p = sexp->d;
325           int type;
326
327           while ( (type = *p) != ST_STOP )
328             {
329               p++;
330               switch ( type )
331                 {
332                 case ST_OPEN:
333                   break;
334                 case ST_CLOSE:
335                   break;
336                 case ST_DATA:
337                   {
338                     DATALEN n;
339                     memcpy ( &n, p, sizeof n );
340                     p += sizeof n;
341                     p += n;
342                   }
343                   break;
344                 default:
345                   break;
346                 }
347             }
348           wipememory (sexp->d, p - sexp->d);
349         }
350       xfree ( sexp );
351     }
352 }
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 _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   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 _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   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 _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   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 _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   BUG ();
414   return NULL;
415 }
416
417 gcry_sexp_t
418 _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   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 _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   if ( !list )
441     return NULL;
442
443   if ( !toklen )
444     toklen = strlen(tok);
445
446   p = list->d;
447   while ( *p != ST_STOP )
448     {
449       if ( *p == ST_OPEN && p[1] == ST_DATA )
450         {
451           const byte *head = p;
452
453           p += 2;
454           memcpy ( &n, p, sizeof n );
455           p += sizeof n;
456           if ( n == toklen && !memcmp( p, tok, toklen ) )
457             { /* found it */
458               gcry_sexp_t newlist;
459               byte *d;
460               int level = 1;
461
462               /* Look for the end of the list.  */
463               for ( p += n; level; p++ )
464                 {
465                   if ( *p == ST_DATA )
466                     {
467                         memcpy ( &n, ++p, sizeof n );
468                         p += sizeof n + n;
469                         p--; /* Compensate for later increment. */
470                     }
471                   else if ( *p == ST_OPEN )
472                     {
473                       level++;
474                     }
475                   else if ( *p == ST_CLOSE )
476                     {
477                       level--;
478                     }
479                   else if ( *p == ST_STOP )
480                     {
481                       BUG ();
482                     }
483                 }
484               n = p - head;
485
486               newlist = xtrymalloc ( sizeof *newlist + n );
487               if (!newlist)
488                 {
489                   /* No way to return an error code, so we can only
490                      return Not Found. */
491                   return NULL;
492                 }
493               d = newlist->d;
494               memcpy ( d, head, n ); d += n;
495               *d++ = ST_STOP;
496               return normalize ( newlist );
497             }
498           p += n;
499         }
500       else if ( *p == ST_DATA )
501         {
502           memcpy ( &n, ++p, sizeof n ); p += sizeof n;
503           p += n;
504         }
505       else
506         p++;
507     }
508   return NULL;
509 }
510
511 /****************
512  * Return the length of the given list
513  */
514 int
515 _gcry_sexp_length (const gcry_sexp_t list)
516 {
517   const byte *p;
518   DATALEN n;
519   int type;
520   int length = 0;
521   int level = 0;
522
523   if (!list)
524     return 0;
525
526   p = list->d;
527   while ((type=*p) != ST_STOP)
528     {
529       p++;
530       if (type == ST_DATA)
531         {
532           memcpy (&n, p, sizeof n);
533           p += sizeof n + n;
534           if (level == 1)
535             length++;
536         }
537       else if (type == ST_OPEN)
538         {
539           if (level == 1)
540             length++;
541           level++;
542         }
543       else if (type == ST_CLOSE)
544         {
545           level--;
546         }
547     }
548   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 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   int level = 0;
562
563   *r_off = 0;
564   if (list)
565     {
566       p = list->d;
567       while ( (type=*p) != ST_STOP )
568         {
569           p++;
570           if (type == ST_DATA)
571             {
572               memcpy (&n, p, sizeof n);
573               p += sizeof n + n;
574             }
575           else if (type == ST_OPEN)
576             {
577               if (!level)
578                 *r_off = (p-1) - list->d;
579               level++;
580             }
581           else if ( type == ST_CLOSE )
582             {
583               level--;
584               if (!level)
585                 return p - list->d;
586             }
587         }
588     }
589   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 _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   int level = 0;
604
605   if (!list || list->d[0] != ST_OPEN)
606     return NULL;
607   p = list->d;
608
609   while (number > 0)
610     {
611       p++;
612       if (*p == ST_DATA)
613         {
614           memcpy (&n, ++p, sizeof n);
615           p += sizeof n + n;
616           p--;
617           if (!level)
618             number--;
619         }
620       else if (*p == ST_OPEN)
621         {
622           level++;
623         }
624       else if (*p == ST_CLOSE)
625         {
626           level--;
627           if ( !level )
628             number--;
629         }
630       else if (*p == ST_STOP)
631         {
632           return NULL;
633         }
634     }
635   p++;
636
637   if (*p == ST_DATA)
638     {
639       memcpy (&n, p+1, sizeof n);
640       newlist = xtrymalloc (sizeof *newlist + 1 + 1 + sizeof n + n + 1);
641       if (!newlist)
642         return NULL;
643       d = newlist->d;
644       *d++ = ST_OPEN;
645       memcpy (d, p, 1 + sizeof n + n);
646       d += 1 + sizeof n + n;
647       *d++ = ST_CLOSE;
648       *d = ST_STOP;
649     }
650   else if (*p == ST_OPEN)
651     {
652       const byte *head = p;
653
654       level = 1;
655       do {
656         p++;
657         if (*p == ST_DATA)
658           {
659             memcpy (&n, ++p, sizeof n);
660             p += sizeof n + n;
661             p--;
662           }
663         else if (*p == ST_OPEN)
664           {
665             level++;
666           }
667         else if (*p == ST_CLOSE)
668           {
669             level--;
670           }
671         else if (*p == ST_STOP)
672           {
673             BUG ();
674           }
675       } while (level);
676       n = p + 1 - head;
677
678       newlist = xtrymalloc (sizeof *newlist + n);
679       if (!newlist)
680         return NULL;
681       d = newlist->d;
682       memcpy (d, head, n);
683       d += n;
684       *d++ = ST_STOP;
685     }
686   else
687     newlist = NULL;
688
689   return normalize (newlist);
690 }
691
692
693 gcry_sexp_t
694 _gcry_sexp_car (const gcry_sexp_t list)
695 {
696   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 do_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen)
704 {
705   const byte *p;
706   DATALEN n;
707   int level = 0;
708
709   *datalen = 0;
710   if ( !list )
711     return NULL;
712
713   p = list->d;
714   if ( *p == ST_OPEN )
715     p++;             /* Yep, a list. */
716   else if (number)
717     return NULL;     /* Not a list but N > 0 requested. */
718
719   /* Skip over N elements. */
720   while (number > 0)
721     {
722       if (*p == ST_DATA)
723         {
724           memcpy ( &n, ++p, sizeof n );
725           p += sizeof n + n;
726           p--;
727           if ( !level )
728             number--;
729         }
730       else if (*p == ST_OPEN)
731         {
732           level++;
733         }
734       else if (*p == ST_CLOSE)
735         {
736           level--;
737           if ( !level )
738             number--;
739         }
740       else if (*p == ST_STOP)
741         {
742           return NULL;
743         }
744       p++;
745     }
746
747   /* If this is data, return it.  */
748   if (*p == ST_DATA)
749     {
750       memcpy ( &n, ++p, sizeof n );
751       *datalen = n;
752       return (const char*)p + sizeof n;
753     }
754
755   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 _gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen )
763 {
764   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 _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   *rlength = 0;
780   s = do_sexp_nth_data (list, number, &n);
781   if (!s || !n)
782     return NULL;
783   buf = xtrymalloc (n);
784   if (!buf)
785     return NULL;
786   memcpy (buf, s, n);
787   *rlength = n;
788   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 _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   s = do_sexp_nth_data (list, number, &n);
802   if (!s || n < 1 || (n+1) < 1)
803     return NULL;
804   buf = xtrymalloc (n+1);
805   if (!buf)
806     return NULL;
807   memcpy (buf, s, n);
808   buf[n] = 0;
809   return buf;
810 }
811
812
813 /*
814  * Get a MPI from the car
815  */
816 gcry_mpi_t
817 _gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt)
818 {
819   size_t n;
820   gcry_mpi_t a;
821
822   if (mpifmt == GCRYMPI_FMT_OPAQUE)
823     {
824       char *p;
825
826       p = _gcry_sexp_nth_buffer (list, number, &n);
827       if (!p)
828         return NULL;
829
830       a = _gcry_is_secure (list)? _gcry_mpi_snew (0) : _gcry_mpi_new (0);
831       if (a)
832         mpi_set_opaque (a, p, n*8);
833       else
834         xfree (p);
835     }
836   else
837     {
838       const char *s;
839
840       if (!mpifmt)
841         mpifmt = GCRYMPI_FMT_STD;
842
843       s = do_sexp_nth_data (list, number, &n);
844       if (!s)
845         return NULL;
846
847       if (_gcry_mpi_scan (&a, mpifmt, s, n, NULL))
848         return NULL;
849     }
850
851   return a;
852 }
853
854
855 /****************
856  * Get the CDR
857  */
858 gcry_sexp_t
859 _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   int level = 0;
867   int skip = 1;
868
869   if (!list || list->d[0] != ST_OPEN)
870     return NULL;
871   p = list->d;
872
873   while (skip > 0)
874     {
875       p++;
876       if (*p == ST_DATA)
877         {
878           memcpy ( &n, ++p, sizeof n );
879           p += sizeof n + n;
880           p--;
881           if ( !level )
882             skip--;
883         }
884       else if (*p == ST_OPEN)
885         {
886           level++;
887         }
888       else if (*p == ST_CLOSE)
889         {
890           level--;
891           if ( !level )
892             skip--;
893         }
894       else if (*p == ST_STOP)
895         {
896           return NULL;
897         }
898     }
899   p++;
900
901   head = p;
902   level = 0;
903   do {
904     if (*p == ST_DATA)
905       {
906         memcpy ( &n, ++p, sizeof n );
907         p += sizeof n + n;
908         p--;
909       }
910     else if (*p == ST_OPEN)
911       {
912         level++;
913       }
914     else if (*p == ST_CLOSE)
915       {
916         level--;
917       }
918     else if (*p == ST_STOP)
919       {
920         return NULL;
921       }
922     p++;
923   } while (level);
924   n = p - head;
925
926   newlist = xtrymalloc (sizeof *newlist + n + 2);
927   if (!newlist)
928     return NULL;
929   d = newlist->d;
930   *d++ = ST_OPEN;
931   memcpy (d, head, n);
932   d += n;
933   *d++ = ST_CLOSE;
934   *d++ = ST_STOP;
935
936   return normalize (newlist);
937 }
938
939
940 gcry_sexp_t
941 _gcry_sexp_cadr ( const gcry_sexp_t list )
942 {
943   gcry_sexp_t a, b;
944
945   a = _gcry_sexp_cdr (list);
946   b = _gcry_sexp_car (a);
947   sexp_release (a);
948   return b;
949 }
950
951
952 static GPG_ERR_INLINE int
953 hextonibble (int s)
954 {
955   if (s >= '0' && s <= '9')
956     return s - '0';
957   else if (s >= 'A' && s <= 'F')
958     return 10 + s - 'A';
959   else if (s >= 'a' && s <= 'f')
960     return 10 + s - 'a';
961   else
962     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 make_space ( struct make_space_ctx *c, size_t n )
976 {
977   size_t used = c->pos - c->sexp->d;
978
979   if ( used + n + sizeof(DATALEN) + 1 >= c->allocated )
980     {
981       gcry_sexp_t newsexp;
982       byte *newhead;
983       size_t newsize;
984
985       newsize = c->allocated + 2*(n+sizeof(DATALEN)+1);
986       if (newsize <= c->allocated)
987         return GPG_ERR_TOO_LARGE;
988       newsexp = xtryrealloc ( c->sexp, sizeof *newsexp + newsize - 1);
989       if (!newsexp)
990         return gpg_err_code_from_errno (errno);
991       c->allocated = newsize;
992       newhead = newsexp->d;
993       c->pos = newhead + used;
994       c->sexp = newsexp;
995     }
996   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 unquote_string (const char *string, size_t length, unsigned char *buf)
1005 {
1006   int esc = 0;
1007   const unsigned char *s = (const unsigned char*)string;
1008   unsigned char *d = buf;
1009   size_t n = length;
1010
1011   for (; n; n--, s++)
1012     {
1013       if (esc)
1014         {
1015           switch (*s)
1016             {
1017             case 'b':  *d++ = '\b'; break;
1018             case 't':  *d++ = '\t'; break;
1019             case 'v':  *d++ = '\v'; break;
1020             case 'n':  *d++ = '\n'; break;
1021             case 'f':  *d++ = '\f'; break;
1022             case 'r':  *d++ = '\r'; break;
1023             case '"':  *d++ = '\"'; break;
1024             case '\'': *d++ = '\''; break;
1025             case '\\': *d++ = '\\'; break;
1026
1027             case '\r':  /* ignore CR[,LF] */
1028               if (n>1 && s[1] == '\n')
1029                 {
1030                   s++; n--;
1031                 }
1032               break;
1033
1034             case '\n':  /* ignore LF[,CR] */
1035               if (n>1 && s[1] == '\r')
1036                 {
1037                   s++; n--;
1038                 }
1039               break;
1040
1041             case 'x': /* hex value */
1042               if (n>2 && hexdigitp (s+1) && hexdigitp (s+2))
1043                 {
1044                   s++; n--;
1045                   *d++ = xtoi_2 (s);
1046                   s++; n--;
1047                 }
1048               break;
1049
1050             default:
1051               if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
1052                 {
1053                   *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
1054                   s += 2;
1055                   n -= 2;
1056                 }
1057               break;
1058             }
1059           esc = 0;
1060         }
1061       else if( *s == '\\' )
1062         esc = 1;
1063       else
1064         *d++ = *s;
1065     }
1066
1067   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 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   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   const char *digptr = NULL;
1108   const char *quoted = NULL;
1109   const char *tokenp = NULL;
1110   const char *hexfmt = NULL;
1111   const char *base64 = NULL;
1112   const char *disphint = NULL;
1113   const char *percent = NULL;
1114   int hexcount = 0;
1115   int quoted_esc = 0;
1116   int datalen = 0;
1117   size_t dummy_erroff;
1118   struct make_space_ctx c;
1119   int arg_counter = 0;
1120   int level = 0;
1121
1122   if (!retsexp)
1123     return GPG_ERR_INV_ARG;
1124   *retsexp = NULL;
1125
1126   if (!buffer)
1127     return GPG_ERR_INV_ARG;
1128
1129   if (!erroff)
1130     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   c.allocated = length + sizeof(DATALEN);
1170   if (length && _gcry_is_secure (buffer))
1171     c.sexp = xtrymalloc_secure (sizeof *c.sexp + c.allocated - 1);
1172   else
1173     c.sexp = xtrymalloc (sizeof *c.sexp + c.allocated - 1);
1174   if (!c.sexp)
1175     {
1176       err = gpg_err_code_from_errno (errno);
1177       *erroff = 0;
1178       goto leave;
1179     }
1180   c.pos = c.sexp->d;
1181
1182   for (p = buffer, n = length; n; p++, n--)
1183     {
1184       if (tokenp && !hexfmt)
1185         {
1186           if (strchr (tokenchars, *p))
1187             continue;
1188           else
1189             {
1190               datalen = p - tokenp;
1191               MAKE_SPACE (datalen);
1192               *c.pos++ = ST_DATA;
1193               STORE_LEN (c.pos, datalen);
1194               memcpy (c.pos, tokenp, datalen);
1195               c.pos += datalen;
1196               tokenp = NULL;
1197             }
1198         }
1199
1200       if (quoted)
1201         {
1202           if (quoted_esc)
1203             {
1204               switch (*p)
1205                 {
1206                 case 'b': case 't': case 'v': case 'n': case 'f':
1207                 case 'r': case '"': case '\'': case '\\':
1208                   quoted_esc = 0;
1209                   break;
1210
1211                 case '0': case '1': case '2': case '3': case '4':
1212                 case '5': case '6': case '7':
1213                   if (!((n > 2)
1214                         && (p[1] >= '0') && (p[1] <= '7')
1215                         && (p[2] >= '0') && (p[2] <= '7')))
1216                     {
1217                       *erroff = p - buffer;
1218                       /* Invalid octal value.  */
1219                       err = GPG_ERR_SEXP_BAD_QUOTATION;
1220                       goto leave;
1221                     }
1222                   p += 2;
1223                   n -= 2;
1224                   quoted_esc = 0;
1225                   break;
1226
1227                 case 'x':
1228                   if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2)))
1229                     {
1230                       *erroff = p - buffer;
1231                       /* Invalid hex value.  */
1232                       err = GPG_ERR_SEXP_BAD_QUOTATION;
1233                       goto leave;
1234                     }
1235                   p += 2;
1236                   n -= 2;
1237                   quoted_esc = 0;
1238                   break;
1239
1240                 case '\r':
1241                   /* ignore CR[,LF] */
1242                   if (n && (p[1] == '\n'))
1243                     {
1244                       p++;
1245                       n--;
1246                     }
1247                   quoted_esc = 0;
1248                   break;
1249
1250                 case '\n':
1251                   /* ignore LF[,CR] */
1252                   if (n && (p[1] == '\r'))
1253                     {
1254                       p++;
1255                       n--;
1256                     }
1257                   quoted_esc = 0;
1258                   break;
1259
1260                 default:
1261                   *erroff = p - buffer;
1262                   /* Invalid quoted string escape.  */
1263                   err = GPG_ERR_SEXP_BAD_QUOTATION;
1264                   goto leave;
1265                 }
1266             }
1267           else if (*p == '\\')
1268             quoted_esc = 1;
1269           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               quoted++; /* Skip leading quote.  */
1277               MAKE_SPACE (p - quoted);
1278               *c.pos++ = ST_DATA;
1279               save = c.pos;
1280               STORE_LEN (c.pos, 0); /* Will be fixed up later.  */
1281               len = unquote_string (quoted, p - quoted, c.pos);
1282               c.pos += len;
1283               STORE_LEN (save, len);
1284               quoted = NULL;
1285             }
1286         }
1287       else if (hexfmt)
1288         {
1289           if (isxdigit (*p))
1290             hexcount++;
1291           else if (*p == '#')
1292             {
1293               if ((hexcount & 1))
1294                 {
1295                   *erroff = p - buffer;
1296                   err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
1297                   goto leave;
1298                 }
1299
1300               datalen = hexcount / 2;
1301               MAKE_SPACE (datalen);
1302               *c.pos++ = ST_DATA;
1303               STORE_LEN (c.pos, datalen);
1304               for (hexfmt++; hexfmt < p; hexfmt++)
1305                 {
1306                   int tmpc;
1307
1308                   if (whitespacep (hexfmt))
1309                     continue;
1310                   tmpc = hextonibble (*(const unsigned char*)hexfmt);
1311                   for (hexfmt++; hexfmt < p && whitespacep (hexfmt); hexfmt++)
1312                     ;
1313                   if (hexfmt < p)
1314                     {
1315                       tmpc *= 16;
1316                       tmpc += hextonibble (*(const unsigned char*)hexfmt);
1317                     }
1318                   *c.pos++ = tmpc;
1319                 }
1320               hexfmt = NULL;
1321             }
1322           else if (!whitespacep (p))
1323             {
1324               *erroff = p - buffer;
1325               err = GPG_ERR_SEXP_BAD_HEX_CHAR;
1326               goto leave;
1327             }
1328         }
1329       else if (base64)
1330         {
1331           if (*p == '|')
1332             base64 = NULL;
1333         }
1334       else if (digptr)
1335         {
1336           if (digitp (p))
1337             ;
1338           else if (*p == ':')
1339             {
1340               datalen = atoi (digptr); /* FIXME: check for overflow.  */
1341               digptr = NULL;
1342               if (datalen > n - 1)
1343                 {
1344                   *erroff = p - buffer;
1345                   /* Buffer too short.  */
1346                   err = GPG_ERR_SEXP_STRING_TOO_LONG;
1347                   goto leave;
1348                 }
1349               /* Make a new list entry.  */
1350               MAKE_SPACE (datalen);
1351               *c.pos++ = ST_DATA;
1352               STORE_LEN (c.pos, datalen);
1353               memcpy (c.pos, p + 1, datalen);
1354               c.pos += datalen;
1355               n -= datalen;
1356               p += datalen;
1357             }
1358           else if (*p == '\"')
1359             {
1360               digptr = NULL; /* We ignore the optional length.  */
1361               quoted = p;
1362               quoted_esc = 0;
1363             }
1364           else if (*p == '#')
1365             {
1366               digptr = NULL; /* We ignore the optional length.  */
1367               hexfmt = p;
1368               hexcount = 0;
1369             }
1370           else if (*p == '|')
1371             {
1372               digptr = NULL; /* We ignore the optional length.  */
1373               base64 = p;
1374             }
1375           else
1376             {
1377               *erroff = p - buffer;
1378               err = GPG_ERR_SEXP_INV_LEN_SPEC;
1379               goto leave;
1380             }
1381         }
1382       else if (percent)
1383         {
1384           if (*p == 'm' || *p == 'M')
1385             {
1386               /* Insert an MPI.  */
1387               gcry_mpi_t m;
1388               size_t nm = 0;
1389               int mpifmt = *p == 'm'? GCRYMPI_FMT_STD: GCRYMPI_FMT_USG;
1390
1391               ARG_NEXT (m, gcry_mpi_t);
1392
1393               if (mpi_get_flag (m, GCRYMPI_FLAG_OPAQUE))
1394                 {
1395                   void *mp;
1396                   unsigned int nbits;
1397
1398                   mp = mpi_get_opaque (m, &nbits);
1399                   nm = (nbits+7)/8;
1400                   if (mp && nm)
1401                     {
1402                       MAKE_SPACE (nm);
1403                       if (!_gcry_is_secure (c.sexp->d)
1404                           && 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                           newsexp = xtrymalloc_secure (sizeof *newsexp
1411                                                        + c.allocated - 1);
1412                           if (!newsexp)
1413                             {
1414                               err = gpg_err_code_from_errno (errno);
1415                               goto leave;
1416                             }
1417                           newhead = newsexp->d;
1418                           memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
1419                           c.pos = newhead + (c.pos - c.sexp->d);
1420                           xfree (c.sexp);
1421                           c.sexp = newsexp;
1422                         }
1423
1424                       *c.pos++ = ST_DATA;
1425                       STORE_LEN (c.pos, nm);
1426                       memcpy (c.pos, mp, nm);
1427                       c.pos += nm;
1428                     }
1429                 }
1430               else
1431                 {
1432                   if (_gcry_mpi_print (mpifmt, NULL, 0, &nm, m))
1433                     BUG ();
1434
1435                   MAKE_SPACE (nm);
1436                   if (!_gcry_is_secure (c.sexp->d)
1437                       && 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                       newsexp = xtrymalloc_secure (sizeof *newsexp
1444                                                    + c.allocated - 1);
1445                       if (!newsexp)
1446                         {
1447                           err = gpg_err_code_from_errno (errno);
1448                           goto leave;
1449                         }
1450                       newhead = newsexp->d;
1451                       memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
1452                       c.pos = newhead + (c.pos - c.sexp->d);
1453                       xfree (c.sexp);
1454                       c.sexp = newsexp;
1455                     }
1456
1457                   *c.pos++ = ST_DATA;
1458                   STORE_LEN (c.pos, nm);
1459                   if (_gcry_mpi_print (mpifmt, c.pos, nm, &nm, m))
1460                     BUG ();
1461                   c.pos += nm;
1462                 }
1463             }
1464           else if (*p == 's')
1465             {
1466               /* Insert an string.  */
1467               const char *astr;
1468               size_t alen;
1469
1470               ARG_NEXT (astr, const char *);
1471               alen = strlen (astr);
1472
1473               MAKE_SPACE (alen);
1474               *c.pos++ = ST_DATA;
1475               STORE_LEN (c.pos, alen);
1476               memcpy (c.pos, astr, alen);
1477               c.pos += alen;
1478             }
1479           else if (*p == 'b')
1480             {
1481               /* Insert a memory buffer.  */
1482               const char *astr;
1483               int alen;
1484
1485               ARG_NEXT (alen, int);
1486               ARG_NEXT (astr, const char *);
1487
1488               MAKE_SPACE (alen);
1489               if (alen
1490                   && !_gcry_is_secure (c.sexp->d)
1491                   && _gcry_is_secure (astr))
1492               {
1493                   /* We have to switch to secure allocation.  */
1494                   gcry_sexp_t newsexp;
1495                   byte *newhead;
1496
1497                   newsexp = xtrymalloc_secure (sizeof *newsexp
1498                                                + c.allocated - 1);
1499                   if (!newsexp)
1500                     {
1501                       err = gpg_err_code_from_errno (errno);
1502                       goto leave;
1503                     }
1504                   newhead = newsexp->d;
1505                   memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
1506                   c.pos = newhead + (c.pos - c.sexp->d);
1507                   xfree (c.sexp);
1508                   c.sexp = newsexp;
1509                 }
1510
1511               *c.pos++ = ST_DATA;
1512               STORE_LEN (c.pos, alen);
1513               memcpy (c.pos, astr, alen);
1514               c.pos += alen;
1515             }
1516           else if (*p == 'd')
1517             {
1518               /* Insert an integer as string.  */
1519               int aint;
1520               size_t alen;
1521               char buf[35];
1522
1523               ARG_NEXT (aint, int);
1524               sprintf (buf, "%d", aint);
1525               alen = strlen (buf);
1526               MAKE_SPACE (alen);
1527               *c.pos++ = ST_DATA;
1528               STORE_LEN (c.pos, alen);
1529               memcpy (c.pos, buf, alen);
1530               c.pos += alen;
1531             }
1532           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               ARG_NEXT (aint, unsigned int);
1540               sprintf (buf, "%u", aint);
1541               alen = strlen (buf);
1542               MAKE_SPACE (alen);
1543               *c.pos++ = ST_DATA;
1544               STORE_LEN (c.pos, alen);
1545               memcpy (c.pos, buf, alen);
1546               c.pos += alen;
1547             }
1548           else if (*p == 'S')
1549             {
1550               /* Insert a gcry_sexp_t.  */
1551               gcry_sexp_t asexp;
1552               size_t alen, aoff;
1553
1554               ARG_NEXT (asexp, gcry_sexp_t);
1555               alen = get_internal_buffer (asexp, &aoff);
1556               if (alen)
1557                 {
1558                   MAKE_SPACE (alen);
1559                   memcpy (c.pos, asexp->d + aoff, alen);
1560                   c.pos += alen;
1561                 }
1562             }
1563           else
1564             {
1565               *erroff = p - buffer;
1566               /* Invalid format specifier.  */
1567               err = GPG_ERR_SEXP_INV_LEN_SPEC;
1568               goto leave;
1569             }
1570           percent = NULL;
1571         }
1572       else if (*p == '(')
1573         {
1574           if (disphint)
1575             {
1576               *erroff = p - buffer;
1577               /* Open display hint.  */
1578               err = GPG_ERR_SEXP_UNMATCHED_DH;
1579               goto leave;
1580             }
1581           MAKE_SPACE (0);
1582           *c.pos++ = ST_OPEN;
1583           level++;
1584         }
1585       else if (*p == ')')
1586         {
1587           /* Walk up.  */
1588           if (disphint)
1589             {
1590               *erroff = p - buffer;
1591               /* Open display hint.  */
1592               err = GPG_ERR_SEXP_UNMATCHED_DH;
1593               goto leave;
1594             }
1595           MAKE_SPACE (0);
1596           *c.pos++ = ST_CLOSE;
1597           level--;
1598         }
1599       else if (*p == '\"')
1600         {
1601           quoted = p;
1602           quoted_esc = 0;
1603         }
1604       else if (*p == '#')
1605         {
1606           hexfmt = p;
1607           hexcount = 0;
1608         }
1609       else if (*p == '|')
1610         base64 = p;
1611       else if (*p == '[')
1612         {
1613           if (disphint)
1614             {
1615               *erroff = p - buffer;
1616               /* Open display hint.  */
1617               err = GPG_ERR_SEXP_NESTED_DH;
1618               goto leave;
1619             }
1620           disphint = p;
1621         }
1622       else if (*p == ']')
1623         {
1624           if (!disphint)
1625             {
1626               *erroff = p - buffer;
1627               /* Open display hint.  */
1628               err = GPG_ERR_SEXP_UNMATCHED_DH;
1629               goto leave;
1630             }
1631           disphint = NULL;
1632         }
1633       else if (digitp (p))
1634         {
1635           if (*p == '0')
1636             {
1637               /* A length may not begin with zero.  */
1638               *erroff = p - buffer;
1639               err = GPG_ERR_SEXP_ZERO_PREFIX;
1640               goto leave;
1641             }
1642           digptr = p;
1643         }
1644       else if (strchr (tokenchars, *p))
1645         tokenp = p;
1646       else if (whitespacep (p))
1647         ;
1648       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           *erroff = p - buffer;
1655           err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
1656           goto leave;
1657         }
1658       else if (strchr ("&\\", *p))
1659         {
1660           /* Reserved punctuation.  */
1661           *erroff = p - buffer;
1662           err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
1663           goto leave;
1664         }
1665       else if (argflag && (*p == '%'))
1666         percent = p;
1667       else
1668         {
1669           /* Bad or unavailable.  */
1670           *erroff = p - buffer;
1671           err = GPG_ERR_SEXP_BAD_CHARACTER;
1672           goto leave;
1673         }
1674     }
1675   MAKE_SPACE (0);
1676   *c.pos++ = ST_STOP;
1677
1678   if (level && !err)
1679     err = GPG_ERR_SEXP_UNMATCHED_PAREN;
1680
1681  leave:
1682   if (err)
1683     {
1684       /* Error -> deallocate.  */
1685       if (c.sexp)
1686         {
1687           /* Extra paranoid wipe on error. */
1688           if (_gcry_is_secure (c.sexp))
1689             wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
1690           xfree (c.sexp);
1691         }
1692     }
1693   else
1694     *retsexp = normalize (c.sexp);
1695
1696   return err;
1697 #undef MAKE_SPACE
1698 #undef STORE_LEN
1699 }
1700
1701
1702 static gpg_err_code_t
1703 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   va_start (arg_ptr, arg_list);
1711   rc = do_vsexp_sscan (retsexp, erroff, buffer, length, argflag,
1712                        arg_list, arg_ptr);
1713   va_end (arg_ptr);
1714
1715   return rc;
1716 }
1717
1718
1719 gpg_err_code_t
1720 _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   va_start (arg_ptr, format);
1726   rc = do_vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
1727                        NULL, arg_ptr);
1728   va_end (arg_ptr);
1729
1730   return rc;
1731 }
1732
1733
1734 gcry_err_code_t
1735 _gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff,
1736                    const char *format, va_list arg_ptr)
1737 {
1738   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 _gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
1747                         const char *format, void **arg_list)
1748 {
1749   return do_sexp_sscan (retsexp, erroff, format, strlen(format), 1, arg_list);
1750 }
1751
1752
1753 gcry_err_code_t
1754 _gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
1755                   const char *buffer, size_t length)
1756 {
1757   return do_sexp_sscan (retsexp, erroff, buffer, length, 0, NULL);
1758 }
1759
1760 \f
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 suitable_encoding (const unsigned char *buffer, size_t length)
1768 {
1769   const unsigned char *s;
1770   int maybe_token = 1;
1771
1772   if (!length)
1773     return 1;
1774
1775   if (*buffer & 0x80)
1776     return 0; /* If the MSB is set we assume that buffer represents a
1777                  negative number.  */
1778   if (!*buffer)
1779     return 0; /* Starting with a zero is pretty much a binary string.  */
1780
1781   for (s=buffer; length; s++, length--)
1782     {
1783       if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
1784            && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
1785         return 0; /*binary*/
1786       if ( maybe_token
1787            && !alphap (s) && !digitp (s)  && !strchr (TOKEN_SPECIALS, *s))
1788         maybe_token = 0;
1789     }
1790   s = buffer;
1791   if ( maybe_token && !digitp (s) )
1792     return 2;
1793   return 1;
1794 }
1795
1796
1797 static int
1798 convert_to_hex (const unsigned char *src, size_t len, char *dest)
1799 {
1800   int i;
1801
1802   if (dest)
1803     {
1804       *dest++ = '#';
1805       for (i=0; i < len; i++, dest += 2 )
1806         sprintf (dest, "%02X", src[i]);
1807       *dest++ = '#';
1808     }
1809   return len*2+2;
1810 }
1811
1812 static int
1813 convert_to_string (const unsigned char *s, size_t len, char *dest)
1814 {
1815   if (dest)
1816     {
1817       char *p = dest;
1818       *p++ = '\"';
1819       for (; len; len--, s++ )
1820         {
1821           switch (*s)
1822             {
1823             case '\b': *p++ = '\\'; *p++ = 'b';  break;
1824             case '\t': *p++ = '\\'; *p++ = 't';  break;
1825             case '\v': *p++ = '\\'; *p++ = 'v';  break;
1826             case '\n': *p++ = '\\'; *p++ = 'n';  break;
1827             case '\f': *p++ = '\\'; *p++ = 'f';  break;
1828             case '\r': *p++ = '\\'; *p++ = 'r';  break;
1829             case '\"': *p++ = '\\'; *p++ = '\"';  break;
1830             case '\'': *p++ = '\\'; *p++ = '\'';  break;
1831             case '\\': *p++ = '\\'; *p++ = '\\';  break;
1832             default:
1833               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1834                 {
1835                   sprintf (p, "\\x%02x", *s);
1836                   p += 4;
1837                 }
1838               else
1839                 *p++ = *s;
1840             }
1841         }
1842       *p++ = '\"';
1843       return p - dest;
1844     }
1845   else
1846     {
1847       int count = 2;
1848       for (; len; len--, s++ )
1849         {
1850           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             case '\\': count += 2; break;
1861             default:
1862               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1863                 count += 4;
1864               else
1865                 count++;
1866             }
1867         }
1868       return count;
1869     }
1870 }
1871
1872
1873
1874 static int
1875 convert_to_token (const unsigned char *src, size_t len, char *dest)
1876 {
1877   if (dest)
1878     memcpy (dest, src, len);
1879   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 _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   size_t len = 0;
1899   int i, indent = 0;
1900
1901   s = list? list->d : empty;
1902   d = buffer;
1903   while ( *s != ST_STOP )
1904     {
1905       switch ( *s )
1906         {
1907         case ST_OPEN:
1908           s++;
1909           if ( mode != GCRYSEXP_FMT_CANON )
1910             {
1911               if (indent)
1912                 len++;
1913               len += indent;
1914             }
1915           len++;
1916           if ( buffer )
1917             {
1918               if ( len >= maxlength )
1919                 return 0;
1920               if ( mode != GCRYSEXP_FMT_CANON )
1921                 {
1922                   if (indent)
1923                     *d++ = '\n';
1924                   for (i=0; i < indent; i++)
1925                     *d++ = ' ';
1926                 }
1927               *d++ = '(';
1928             }
1929           indent++;
1930           break;
1931         case ST_CLOSE:
1932           s++;
1933           len++;
1934           if ( buffer )
1935             {
1936               if ( len >= maxlength )
1937                 return 0;
1938               *d++ = ')';
1939             }
1940           indent--;
1941           if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
1942             {
1943               len++;
1944               len += indent;
1945               if (buffer)
1946                 {
1947                   if (len >= maxlength)
1948                     return 0;
1949                   *d++ = '\n';
1950                   for (i=0; i < indent; i++)
1951                     *d++ = ' ';
1952                 }
1953             }
1954           break;
1955         case ST_DATA:
1956           s++;
1957           memcpy ( &n, s, sizeof n ); s += sizeof n;
1958           if (mode == GCRYSEXP_FMT_ADVANCED)
1959             {
1960               int type;
1961               size_t nn;
1962
1963               switch ( (type=suitable_encoding (s, n)))
1964                 {
1965                 case 1: nn = convert_to_string (s, n, NULL); break;
1966                 case 2: nn = convert_to_token (s, n, NULL); break;
1967                 default: nn = convert_to_hex (s, n, NULL); break;
1968                 }
1969               len += nn;
1970               if (buffer)
1971                 {
1972                   if (len >= maxlength)
1973                     return 0;
1974                   switch (type)
1975                     {
1976                     case 1: convert_to_string (s, n, d); break;
1977                     case 2: convert_to_token (s, n, d); break;
1978                     default: convert_to_hex (s, n, d); break;
1979                     }
1980                   d += nn;
1981                 }
1982               if (s[n] != ST_CLOSE)
1983                 {
1984                   len++;
1985                   if (buffer)
1986                     {
1987                       if (len >= maxlength)
1988                         return 0;
1989                       *d++ = ' ';
1990                     }
1991                 }
1992             }
1993           else
1994             {
1995               sprintf (numbuf, "%u:", (unsigned int)n );
1996               len += strlen (numbuf) + n;
1997               if ( buffer )
1998                 {
1999                   if ( len >= maxlength )
2000                     return 0;
2001                   d = stpcpy ( d, numbuf );
2002                   memcpy ( d, s, n ); d += n;
2003                 }
2004             }
2005           s += n;
2006           break;
2007         default:
2008           BUG ();
2009         }
2010     }
2011   if ( mode != GCRYSEXP_FMT_CANON )
2012     {
2013       len++;
2014       if (buffer)
2015         {
2016           if ( len >= maxlength )
2017             return 0;
2018           *d++ = '\n';
2019         }
2020     }
2021   if (buffer)
2022     {
2023       if ( len >= maxlength )
2024         return 0;
2025       *d++ = 0; /* for convenience we make a C string */
2026     }
2027   else
2028     len++; /* we need one byte more for this */
2029
2030   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 _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   const unsigned char *disphint = NULL;
2046   unsigned int datalen = 0;
2047   size_t dummy_erroff;
2048   gcry_err_code_t dummy_errcode;
2049   size_t count = 0;
2050   int level = 0;
2051
2052   if (!erroff)
2053     erroff = &dummy_erroff;
2054   if (!errcode)
2055     errcode = &dummy_errcode;
2056
2057   *errcode = GPG_ERR_NO_ERROR;
2058   *erroff = 0;
2059   if (!buffer)
2060     return 0;
2061   if (*buffer != '(')
2062     {
2063       *errcode = GPG_ERR_SEXP_NOT_CANONICAL;
2064       return 0;
2065     }
2066
2067   for (p=buffer; ; p++, count++ )
2068     {
2069       if (length && count >= length)
2070         {
2071           *erroff = count;
2072           *errcode = GPG_ERR_SEXP_STRING_TOO_LONG;
2073           return 0;
2074         }
2075
2076       if (datalen)
2077         {
2078           if (*p == ':')
2079             {
2080               if (length && (count+datalen) >= length)
2081                 {
2082                   *erroff = count;
2083                   *errcode = GPG_ERR_SEXP_STRING_TOO_LONG;
2084                   return 0;
2085                 }
2086               count += datalen;
2087               p += datalen;
2088               datalen = 0;
2089             }
2090           else if (digitp(p))
2091             datalen = datalen*10 + atoi_1(p);
2092           else
2093             {
2094               *erroff = count;
2095               *errcode = GPG_ERR_SEXP_INV_LEN_SPEC;
2096               return 0;
2097             }
2098         }
2099       else if (*p == '(')
2100         {
2101           if (disphint)
2102             {
2103               *erroff = count;
2104               *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
2105               return 0;
2106             }
2107           level++;
2108         }
2109       else if (*p == ')')
2110         { /* walk up */
2111           if (!level)
2112             {
2113               *erroff = count;
2114               *errcode = GPG_ERR_SEXP_UNMATCHED_PAREN;
2115               return 0;
2116             }
2117           if (disphint)
2118             {
2119               *erroff = count;
2120               *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
2121               return 0;
2122             }
2123           if (!--level)
2124             return ++count; /* ready */
2125         }
2126       else if (*p == '[')
2127         {
2128           if (disphint)
2129             {
2130               *erroff = count;
2131               *errcode = GPG_ERR_SEXP_NESTED_DH;
2132               return 0;
2133             }
2134           disphint = p;
2135         }
2136       else if (*p == ']')
2137         {
2138           if ( !disphint )
2139             {
2140               *erroff = count;
2141               *errcode = GPG_ERR_SEXP_UNMATCHED_DH;
2142               return 0;
2143             }
2144           disphint = NULL;
2145         }
2146       else if (digitp (p) )
2147         {
2148           if (*p == '0')
2149             {
2150               *erroff = count;
2151               *errcode = GPG_ERR_SEXP_ZERO_PREFIX;
2152               return 0;
2153             }
2154           datalen = atoi_1 (p);
2155         }
2156       else if (*p == '&' || *p == '\\')
2157         {
2158           *erroff = count;
2159           *errcode = GPG_ERR_SEXP_UNEXPECTED_PUNC;
2160           return 0;
2161         }
2162       else
2163         {
2164           *erroff = count;
2165           *errcode = GPG_ERR_SEXP_BAD_CHARACTER;
2166           return 0;
2167         }
2168     }
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 _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   int mode = '+'; /* Default to GCRYMPI_FMT_USG.  */
2225   gcry_sexp_t freethis = NULL;
2226
2227   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   for (s=list, idx=0; *s && idx < DIM (array); s++)
2233     {
2234       if (*s == '&' || *s == '+' || *s == '-' || *s == '/' || *s == '?')
2235         ;
2236       else if (whitespacep (s))
2237         ;
2238       else
2239         {
2240           if (*s == '\'')
2241             {
2242               s++;
2243               s2 = strchr (s, '\'');
2244               if (!s2 || s2 == s)
2245                 {
2246                   /* Closing quote not found or empty string.  */
2247                   return GPG_ERR_SYNTAX;
2248                 }
2249               s = s2;
2250             }
2251           array[idx] = va_arg (arg_ptr, gcry_mpi_t *);
2252           if (!array[idx])
2253             return GPG_ERR_MISSING_VALUE; /* NULL pointer given.  */
2254           idx++;
2255         }
2256     }
2257   if (*s)
2258     return GPG_ERR_LIMIT_REACHED;  /* Too many list elements.  */
2259   if (va_arg (arg_ptr, gcry_mpi_t *))
2260     return GPG_ERR_INV_ARG;  /* Not enough list elemends.  */
2261
2262   /* Drill down.  */
2263   while (path && *path)
2264     {
2265       size_t n;
2266
2267       s = strchr (path, '!');
2268       if (s == path)
2269         {
2270           rc = GPG_ERR_NOT_FOUND;
2271           goto cleanup;
2272         }
2273       n = s? s - path : 0;
2274       l1 = _gcry_sexp_find_token (sexp, path, n);
2275       if (!l1)
2276         {
2277           rc = GPG_ERR_NOT_FOUND;
2278           goto cleanup;
2279         }
2280       sexp = l1; l1 = NULL;
2281       sexp_release (freethis);
2282       freethis = sexp;
2283       if (n)
2284         path += n + 1;
2285       else
2286         path = NULL;
2287     }
2288
2289
2290   /* Now extract all parameters.  */
2291   for (s=list, idx=0; *s; s++)
2292     {
2293       if (*s == '&' || *s == '+' || *s == '-' || *s == '/')
2294         mode = *s;
2295       else if (whitespacep (s))
2296         ;
2297       else if (*s == '?')
2298         ; /* Only used via lookahead.  */
2299       else
2300         {
2301           if (*s == '\'')
2302             {
2303               /* Find closing quote, find token, set S to closing quote.  */
2304               s++;
2305               s2 = strchr (s, '\'');
2306               if (!s2 || s2 == s)
2307                 {
2308                   /* Closing quote not found or empty string.  */
2309                   rc = GPG_ERR_SYNTAX;
2310                   goto cleanup;
2311                 }
2312               l1 = _gcry_sexp_find_token (sexp, s, s2 - s);
2313               s = s2;
2314             }
2315           else
2316             l1 = _gcry_sexp_find_token (sexp, s, 1);
2317
2318           if (!l1 && s[1] == '?')
2319             {
2320               /* Optional element not found.  */
2321               if (mode == '&')
2322                 {
2323                   gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2324                   if (!spec->data)
2325                     {
2326                       spec->size = 0;
2327                       spec->off = 0;
2328                     }
2329                   spec->len = 0;
2330                 }
2331               else
2332                 *array[idx] = NULL;
2333             }
2334           else if (!l1)
2335             {
2336               rc = GPG_ERR_NO_OBJ;  /* List element not found.  */
2337               goto cleanup;
2338             }
2339            else
2340             {
2341               if (mode == '&')
2342                 {
2343                   gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2344
2345                   if (spec->data)
2346                     {
2347                       const char *pbuf;
2348                       size_t nbuf;
2349
2350                       pbuf = _gcry_sexp_nth_data (l1, 1, &nbuf);
2351                       if (!pbuf || !nbuf)
2352                         {
2353                           rc = GPG_ERR_INV_OBJ;
2354                           goto cleanup;
2355                         }
2356                       if (spec->off + nbuf > spec->size)
2357                         {
2358                           rc = GPG_ERR_BUFFER_TOO_SHORT;
2359                           goto cleanup;
2360                         }
2361                       memcpy ((char*)spec->data + spec->off, pbuf, nbuf);
2362                       spec->len = nbuf;
2363                       arrayisdesc[idx] = 1;
2364                     }
2365                   else
2366                     {
2367                       spec->data = _gcry_sexp_nth_buffer (l1, 1, &spec->size);
2368                       if (!spec->data)
2369                         {
2370                           rc = GPG_ERR_INV_OBJ; /* Or out of core.  */
2371                           goto cleanup;
2372                         }
2373                       spec->len = spec->size;
2374                       spec->off = 0;
2375                       arrayisdesc[idx] = 2;
2376                     }
2377                 }
2378               else if (mode == '/')
2379                 *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
2380               else if (mode == '-')
2381                 *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_STD);
2382               else
2383                 *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
2384               sexp_release (l1); l1 = NULL;
2385               if (!*array[idx])
2386                 {
2387                   rc = GPG_ERR_INV_OBJ;  /* Conversion failed.  */
2388                   goto cleanup;
2389                 }
2390             }
2391           idx++;
2392         }
2393     }
2394
2395   sexp_release (freethis);
2396   return 0;
2397
2398  cleanup:
2399   sexp_release (freethis);
2400   sexp_release (l1);
2401   while (idx--)
2402     {
2403       if (!arrayisdesc[idx])
2404         {
2405           _gcry_mpi_release (*array[idx]);
2406           *array[idx] = NULL;
2407         }
2408       else if (arrayisdesc[idx] == 1)
2409         {
2410           /* Caller provided buffer.  */
2411           gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2412           spec->len = 0;
2413         }
2414       else
2415         {
2416           /* We might have allocated a buffer.  */
2417           gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
2418           xfree (spec->data);
2419           spec->data = NULL;
2420           spec->size = spec->off = spec->len = 0;
2421         }
2422      }
2423   return rc;
2424 }
2425
2426 gpg_err_code_t
2427 _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   va_start (arg_ptr, list);
2434   rc = _gcry_sexp_vextract_param (sexp, path, list, arg_ptr);
2435   va_end (arg_ptr);
2436   return rc;
2437 }