• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/libgcrypt-1.5.1/src/
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 *
5 * This file is part of Libgcrypt.
6 *
7 * Libgcrypt is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser general Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * Libgcrypt is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 */
21
22
23#include <config.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <stdarg.h>
28#include <ctype.h>
29#include <errno.h>
30
31#define GCRYPT_NO_MPI_MACROS 1
32#include "g10lib.h"
33
34typedef struct gcry_sexp *NODE;
35typedef unsigned short DATALEN;
36
37struct gcry_sexp
38{
39  byte d[1];
40};
41
42#define ST_STOP  0
43#define ST_DATA  1  /* datalen follows */
44#define ST_HINT  2  /* datalen follows */
45#define ST_OPEN  3
46#define ST_CLOSE 4
47
48/* the atoi macros assume that the buffer has only valid digits */
49#define atoi_1(p)   (*(p) - '0' )
50#define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
51                     *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
52#define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
53
54#define TOKEN_SPECIALS  "-./_:*+="
55
56static gcry_error_t
57vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
58	     const char *buffer, size_t length, int argflag,
59	     void **arg_list, va_list arg_ptr);
60
61static gcry_error_t
62sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
63	    const char *buffer, size_t length, int argflag,
64	    void **arg_list, ...);
65
66/* Return true if P points to a byte containing a whitespace according
67   to the S-expressions definition. */
68#undef whitespacep
69static GPG_ERR_INLINE int
70whitespacep (const char *p)
71{
72  switch (*p)
73    {
74    case ' ': case '\t': case '\v': case '\f': case '\r': case '\n': return 1;
75    default: return 0;
76    }
77}
78
79
80#if 0
81static void
82dump_mpi( gcry_mpi_t a )
83{
84    char buffer[1000];
85    size_t n = 1000;
86
87    if( !a )
88	fputs("[no MPI]", stderr );
89    else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) )
90	fputs("[MPI too large to print]", stderr );
91    else
92	fputs( buffer, stderr );
93}
94#endif
95
96static void
97dump_string (const byte *p, size_t n, int delim )
98{
99  for (; n; n--, p++ )
100    {
101      if ((*p & 0x80) || iscntrl( *p ) || *p == delim )
102        {
103          if( *p == '\n' )
104            log_printf ("\\n");
105          else if( *p == '\r' )
106            log_printf ("\\r");
107          else if( *p == '\f' )
108            log_printf ("\\f");
109          else if( *p == '\v' )
110            log_printf ("\\v");
111	    else if( *p == '\b' )
112              log_printf ("\\b");
113          else if( !*p )
114            log_printf ("\\0");
115          else
116            log_printf ("\\x%02x", *p );
117	}
118      else
119        log_printf ("%c", *p);
120    }
121}
122
123
124void
125gcry_sexp_dump (const gcry_sexp_t a)
126{
127  const byte *p;
128  int indent = 0;
129  int type;
130
131  if (!a)
132    {
133      log_printf ( "[nil]\n");
134      return;
135    }
136
137  p = a->d;
138  while ( (type = *p) != ST_STOP )
139    {
140      p++;
141      switch ( type )
142        {
143        case ST_OPEN:
144          log_printf ("%*s[open]\n", 2*indent, "");
145          indent++;
146          break;
147        case ST_CLOSE:
148          if( indent )
149            indent--;
150          log_printf ("%*s[close]\n", 2*indent, "");
151          break;
152        case ST_DATA: {
153          DATALEN n;
154          memcpy ( &n, p, sizeof n );
155          p += sizeof n;
156          log_printf ("%*s[data=\"", 2*indent, "" );
157          dump_string (p, n, '\"' );
158          log_printf ("\"]\n");
159          p += n;
160        }
161        break;
162        default:
163          log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type);
164          break;
165	}
166    }
167}
168
169/****************
170 * Pass list through except when it is an empty list - in that case
171 * return NULL and release the passed list.
172 */
173static gcry_sexp_t
174normalize ( gcry_sexp_t list )
175{
176  unsigned char *p;
177
178  if ( !list )
179    return NULL;
180  p = list->d;
181  if ( *p == ST_STOP )
182    {
183      /* this is "" */
184      gcry_sexp_release ( list );
185      return NULL;
186    }
187  if ( *p == ST_OPEN && p[1] == ST_CLOSE )
188    {
189      /* this is "()" */
190      gcry_sexp_release ( list );
191      return NULL;
192    }
193
194  return list;
195}
196
197/* Create a new S-expression object by reading LENGTH bytes from
198   BUFFER, assuming it is canonical encoded or autodetected encoding
199   when AUTODETECT is set to 1.  With FREEFNC not NULL, ownership of
200   the buffer is transferred to the newly created object.  FREEFNC
201   should be the freefnc used to release BUFFER; there is no guarantee
202   at which point this function is called; most likey you want to use
203   free() or gcry_free().
204
205   Passing LENGTH and AUTODETECT as 0 is allowed to indicate that
206   BUFFER points to a valid canonical encoded S-expression.  A LENGTH
207   of 0 and AUTODETECT 1 indicates that buffer points to a
208   null-terminated string.
209
210   This function returns 0 and and the pointer to the new object in
211   RETSEXP or an error code in which case RETSEXP is set to NULL.  */
212gcry_error_t
213gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length,
214                  int autodetect, void (*freefnc)(void*) )
215{
216  gcry_error_t errcode;
217  gcry_sexp_t se;
218
219  if (!retsexp)
220    return gcry_error (GPG_ERR_INV_ARG);
221  *retsexp = NULL;
222  if (autodetect < 0 || autodetect > 1 || !buffer)
223    return gcry_error (GPG_ERR_INV_ARG);
224
225  if (!length && !autodetect)
226    { /* What a brave caller to assume that there is really a canonical
227         encoded S-expression in buffer */
228      length = gcry_sexp_canon_len (buffer, 0, NULL, &errcode);
229      if (!length)
230        return errcode;
231    }
232  else if (!length && autodetect)
233    { /* buffer is a string */
234      length = strlen ((char *)buffer);
235    }
236
237  errcode = sexp_sscan (&se, NULL, buffer, length, 0, NULL);
238  if (errcode)
239    return errcode;
240
241  *retsexp = se;
242  if (freefnc)
243    {
244      /* For now we release the buffer immediately.  As soon as we
245         have changed the internal represenation of S-expression to
246         the canoncial format - which has the advantage of faster
247         parsing - we will use this function as a closure in our
248         GCRYSEXP object and use the BUFFER directly.  */
249      freefnc (buffer);
250    }
251  return gcry_error (GPG_ERR_NO_ERROR);
252}
253
254/* Same as gcry_sexp_create but don't transfer ownership */
255gcry_error_t
256gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length,
257               int autodetect)
258{
259  return gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL);
260}
261
262
263/****************
264 * Release resource of the given SEXP object.
265 */
266void
267gcry_sexp_release( gcry_sexp_t sexp )
268{
269  if (sexp)
270    {
271      if (gcry_is_secure (sexp))
272        {
273          /* Extra paranoid wiping. */
274          const byte *p = sexp->d;
275          int type;
276
277          while ( (type = *p) != ST_STOP )
278            {
279              p++;
280              switch ( type )
281                {
282                case ST_OPEN:
283                  break;
284                case ST_CLOSE:
285                  break;
286                case ST_DATA:
287                  {
288                    DATALEN n;
289                    memcpy ( &n, p, sizeof n );
290                    p += sizeof n;
291                    p += n;
292                  }
293                  break;
294                default:
295                  break;
296                }
297            }
298          wipememory (sexp->d, p - sexp->d);
299        }
300      gcry_free ( sexp );
301    }
302}
303
304
305/****************
306 * Make a pair from lists a and b, don't use a or b later on.
307 * Special behaviour:  If one is a single element list we put the
308 * element straight into the new pair.
309 */
310gcry_sexp_t
311gcry_sexp_cons( const gcry_sexp_t a, const gcry_sexp_t b )
312{
313  (void)a;
314  (void)b;
315
316  /* NYI: Implementation should be quite easy with our new data
317     representation */
318  BUG ();
319  return NULL;
320}
321
322
323/****************
324 * Make a list from all items in the array the end of the array is marked
325 * with a NULL.
326 */
327gcry_sexp_t
328gcry_sexp_alist( const gcry_sexp_t *array )
329{
330  (void)array;
331
332  /* NYI: Implementation should be quite easy with our new data
333     representation. */
334  BUG ();
335  return NULL;
336}
337
338/****************
339 * Make a list from all items, the end of list is indicated by a NULL
340 */
341gcry_sexp_t
342gcry_sexp_vlist( const gcry_sexp_t a, ... )
343{
344  (void)a;
345  /* NYI: Implementation should be quite easy with our new data
346     representation. */
347  BUG ();
348  return NULL;
349}
350
351
352/****************
353 * Append n to the list a
354 * Returns: a new ist (which maybe a)
355 */
356gcry_sexp_t
357gcry_sexp_append( const gcry_sexp_t a, const gcry_sexp_t n )
358{
359  (void)a;
360  (void)n;
361  /* NYI: Implementation should be quite easy with our new data
362     representation. */
363  BUG ();
364  return NULL;
365}
366
367gcry_sexp_t
368gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n )
369{
370  (void)a;
371  (void)n;
372  /* NYI: Implementation should be quite easy with our new data
373     representation. */
374  BUG ();
375  return NULL;
376}
377
378
379
380/****************
381 * Locate token in a list. The token must be the car of a sublist.
382 * Returns: A new list with this sublist or NULL if not found.
383 */
384gcry_sexp_t
385gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen )
386{
387  const byte *p;
388  DATALEN n;
389
390  if ( !list )
391    return NULL;
392
393  if ( !toklen )
394    toklen = strlen(tok);
395
396  p = list->d;
397  while ( *p != ST_STOP )
398    {
399      if ( *p == ST_OPEN && p[1] == ST_DATA )
400        {
401          const byte *head = p;
402
403          p += 2;
404          memcpy ( &n, p, sizeof n );
405          p += sizeof n;
406          if ( n == toklen && !memcmp( p, tok, toklen ) )
407            { /* found it */
408              gcry_sexp_t newlist;
409              byte *d;
410              int level = 1;
411
412              /* Look for the end of the list.  */
413              for ( p += n; level; p++ )
414                {
415                  if ( *p == ST_DATA )
416                    {
417			memcpy ( &n, ++p, sizeof n );
418			p += sizeof n + n;
419			p--; /* Compensate for later increment. */
420		    }
421                  else if ( *p == ST_OPEN )
422                    {
423                      level++;
424		    }
425                  else if ( *p == ST_CLOSE )
426                    {
427                      level--;
428		    }
429                  else if ( *p == ST_STOP )
430                    {
431                      BUG ();
432		    }
433		}
434              n = p - head;
435
436              newlist = gcry_malloc ( sizeof *newlist + n );
437              if (!newlist)
438                {
439                  /* No way to return an error code, so we can only
440                     return Not Found. */
441                  return NULL;
442                }
443              d = newlist->d;
444              memcpy ( d, head, n ); d += n;
445              *d++ = ST_STOP;
446              return normalize ( newlist );
447	    }
448          p += n;
449	}
450      else if ( *p == ST_DATA )
451        {
452          memcpy ( &n, ++p, sizeof n ); p += sizeof n;
453          p += n;
454	}
455      else
456        p++;
457    }
458  return NULL;
459}
460
461/****************
462 * Return the length of the given list
463 */
464int
465gcry_sexp_length( const gcry_sexp_t list )
466{
467    const byte *p;
468    DATALEN n;
469    int type;
470    int length = 0;
471    int level = 0;
472
473    if ( !list )
474	return 0;
475
476    p = list->d;
477    while ( (type=*p) != ST_STOP ) {
478	p++;
479	if ( type == ST_DATA ) {
480	    memcpy ( &n, p, sizeof n );
481	    p += sizeof n + n;
482	    if ( level == 1 )
483		length++;
484	}
485	else if ( type == ST_OPEN ) {
486	    if ( level == 1 )
487		length++;
488	    level++;
489	}
490	else if ( type == ST_CLOSE ) {
491	    level--;
492	}
493    }
494    return length;
495}
496
497
498/* Return the internal lengths offset of LIST.  That is the size of
499   the buffer from the first ST_OPEN, which is retruned at R_OFF, to
500   the corresponding ST_CLOSE inclusive.  */
501static size_t
502get_internal_buffer (const gcry_sexp_t list, size_t *r_off)
503{
504  const unsigned char *p;
505  DATALEN n;
506  int type;
507  int level = 0;
508
509  *r_off = 0;
510  if (list)
511    {
512      p = list->d;
513      while ( (type=*p) != ST_STOP )
514        {
515          p++;
516          if (type == ST_DATA)
517            {
518              memcpy (&n, p, sizeof n);
519              p += sizeof n + n;
520            }
521          else if (type == ST_OPEN)
522            {
523              if (!level)
524                *r_off = (p-1) - list->d;
525              level++;
526            }
527          else if ( type == ST_CLOSE )
528            {
529              level--;
530              if (!level)
531                return p - list->d;
532            }
533        }
534    }
535  return 0; /* Not a proper list.  */
536}
537
538
539
540/* Extract the CAR of the given list.  May return NULL for bad lists
541   or memory failure.  */
542gcry_sexp_t
543gcry_sexp_nth( const gcry_sexp_t list, int number )
544{
545    const byte *p;
546    DATALEN n;
547    gcry_sexp_t newlist;
548    byte *d;
549    int level = 0;
550
551    if ( !list || list->d[0] != ST_OPEN )
552	return NULL;
553    p = list->d;
554
555    while ( number > 0 ) {
556	p++;
557	if ( *p == ST_DATA ) {
558	    memcpy ( &n, ++p, sizeof n );
559	    p += sizeof n + n;
560	    p--;
561	    if ( !level )
562		number--;
563	}
564	else if ( *p == ST_OPEN ) {
565	    level++;
566	}
567	else if ( *p == ST_CLOSE ) {
568	    level--;
569	    if ( !level )
570		number--;
571	}
572	else if ( *p == ST_STOP ) {
573	    return NULL;
574	}
575    }
576    p++;
577
578    if ( *p == ST_DATA ) {
579        memcpy ( &n, p, sizeof n );
580        /* Allocate 1 (=sizeof *newlist) byte for ST_OPEN
581                    1 byte for ST_DATA
582                    sizeof n byte for n
583                    n byte for the data
584                    1 byte for ST_CLOSE
585                    1 byte for ST_STOP */
586        newlist = gcry_malloc ( sizeof *newlist + 1 + sizeof n + n + 2 );
587        if (!newlist)
588            return NULL;
589        d = newlist->d;
590        *d = ST_OPEN;   /* Put the ST_OPEN flag */
591        d++;            /* Move forward */
592        /* Copy ST_DATA, n and the data from p to d */
593        memcpy ( d, p, 1 + sizeof n + n );
594        d += 1 + sizeof n + n;  /* Move after the data copied */
595        *d = ST_CLOSE;          /* Put the ST_CLOSE flag */
596        d++;                    /* Move forward */
597        *d = ST_STOP;           /* Put the ST_STOP flag */
598    }
599    else if ( *p == ST_OPEN ) {
600	const byte *head = p;
601
602	level = 1;
603	do {
604	    p++;
605	    if ( *p == ST_DATA ) {
606		memcpy ( &n, ++p, sizeof n );
607		p += sizeof n + n;
608		p--;
609	    }
610	    else if ( *p == ST_OPEN ) {
611		level++;
612	    }
613	    else if ( *p == ST_CLOSE ) {
614		level--;
615	    }
616	    else if ( *p == ST_STOP ) {
617		BUG ();
618	    }
619	} while ( level );
620	n = p + 1 - head;
621
622	newlist = gcry_malloc ( sizeof *newlist + n );
623        if (!newlist)
624          return NULL;
625	d = newlist->d;
626	memcpy ( d, head, n ); d += n;
627	*d++ = ST_STOP;
628    }
629    else
630	newlist = NULL;
631
632    return normalize (newlist);
633}
634
635gcry_sexp_t
636gcry_sexp_car( const gcry_sexp_t list )
637{
638    return gcry_sexp_nth ( list, 0 );
639}
640
641
642/* Helper to get data from the car.  The returned value is valid as
643   long as the list is not modified. */
644static const char *
645sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen)
646{
647  const byte *p;
648  DATALEN n;
649  int level = 0;
650
651  *datalen = 0;
652  if ( !list )
653    return NULL;
654
655  p = list->d;
656  if ( *p == ST_OPEN )
657    p++;	     /* Yep, a list. */
658  else if (number)
659    return NULL;     /* Not a list but N > 0 requested. */
660
661  /* Skip over N elements. */
662  while ( number > 0 )
663    {
664      if ( *p == ST_DATA )
665        {
666          memcpy ( &n, ++p, sizeof n );
667          p += sizeof n + n;
668          p--;
669          if ( !level )
670            number--;
671	}
672      else if ( *p == ST_OPEN )
673        {
674          level++;
675	}
676      else if ( *p == ST_CLOSE )
677        {
678          level--;
679          if ( !level )
680            number--;
681	}
682      else if ( *p == ST_STOP )
683        {
684          return NULL;
685	}
686      p++;
687    }
688
689  /* If this is data, return it.  */
690  if ( *p == ST_DATA )
691    {
692      memcpy ( &n, ++p, sizeof n );
693      *datalen = n;
694      return (const char*)p + sizeof n;
695    }
696
697  return NULL;
698}
699
700
701/* Get data from the car.  The returned value is valid as long as the
702   list is not modified.  */
703const char *
704gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen )
705{
706  return sexp_nth_data (list, number, datalen);
707}
708
709
710/* Get a string from the car.  The returned value is a malloced string
711   and needs to be freed by the caller.  */
712char *
713gcry_sexp_nth_string (const gcry_sexp_t list, int number)
714{
715  const char *s;
716  size_t n;
717  char *buf;
718
719  s = sexp_nth_data (list, number, &n);
720  if (!s || n < 1 || (n+1) < 1)
721    return NULL;
722  buf = gcry_malloc (n+1);
723  if (!buf)
724    return NULL;
725  memcpy (buf, s, n);
726  buf[n] = 0;
727  return buf;
728}
729
730/*
731 * Get a MPI from the car
732 */
733gcry_mpi_t
734gcry_sexp_nth_mpi( gcry_sexp_t list, int number, int mpifmt )
735{
736  const char *s;
737  size_t n;
738  gcry_mpi_t a;
739
740  if ( !mpifmt )
741    mpifmt = GCRYMPI_FMT_STD;
742
743  s = sexp_nth_data (list, number, &n);
744  if (!s)
745    return NULL;
746
747  if ( gcry_mpi_scan ( &a, mpifmt, s, n, NULL ) )
748    return NULL;
749
750  return a;
751}
752
753
754/****************
755 * Get the CDR
756 */
757gcry_sexp_t
758gcry_sexp_cdr( const gcry_sexp_t list )
759{
760    const byte *p;
761    const byte *head;
762    DATALEN n;
763    gcry_sexp_t newlist;
764    byte *d;
765    int level = 0;
766    int skip = 1;
767
768    if ( !list || list->d[0] != ST_OPEN )
769	return NULL;
770    p = list->d;
771
772    while ( skip > 0 ) {
773	p++;
774	if ( *p == ST_DATA ) {
775	    memcpy ( &n, ++p, sizeof n );
776	    p += sizeof n + n;
777	    p--;
778	    if ( !level )
779		skip--;
780	}
781	else if ( *p == ST_OPEN ) {
782	    level++;
783	}
784	else if ( *p == ST_CLOSE ) {
785	    level--;
786	    if ( !level )
787		skip--;
788	}
789	else if ( *p == ST_STOP ) {
790	    return NULL;
791	}
792    }
793    p++;
794
795    head = p;
796    level = 0;
797    do {
798	if ( *p == ST_DATA ) {
799	    memcpy ( &n, ++p, sizeof n );
800	    p += sizeof n + n;
801	    p--;
802	}
803	else if ( *p == ST_OPEN ) {
804	    level++;
805	}
806	else if ( *p == ST_CLOSE ) {
807	    level--;
808	}
809	else if ( *p == ST_STOP ) {
810	    return NULL;
811	}
812	p++;
813    } while ( level );
814    n = p - head;
815
816    newlist = gcry_malloc ( sizeof *newlist + n + 2 );
817    if (!newlist)
818      return NULL;
819    d = newlist->d;
820    *d++ = ST_OPEN;
821    memcpy ( d, head, n ); d += n;
822    *d++ = ST_CLOSE;
823    *d++ = ST_STOP;
824
825    return normalize (newlist);
826}
827
828gcry_sexp_t
829gcry_sexp_cadr ( const gcry_sexp_t list )
830{
831    gcry_sexp_t a, b;
832
833    a = gcry_sexp_cdr ( list );
834    b = gcry_sexp_car ( a );
835    gcry_sexp_release ( a );
836    return b;
837}
838
839
840
841static int
842hextobyte( const byte *s )
843{
844    int c=0;
845
846    if( *s >= '0' && *s <= '9' )
847	c = 16 * (*s - '0');
848    else if( *s >= 'A' && *s <= 'F' )
849	c = 16 * (10 + *s - 'A');
850    else if( *s >= 'a' && *s <= 'f' ) {
851	c = 16 * (10 + *s - 'a');
852    }
853    s++;
854    if( *s >= '0' && *s <= '9' )
855	c += *s - '0';
856    else if( *s >= 'A' && *s <= 'F' )
857	c += 10 + *s - 'A';
858    else if( *s >= 'a' && *s <= 'f' ) {
859	c += 10 + *s - 'a';
860    }
861    return c;
862}
863
864struct make_space_ctx {
865    gcry_sexp_t sexp;
866    size_t allocated;
867    byte *pos;
868};
869
870static gpg_err_code_t
871make_space ( struct make_space_ctx *c, size_t n )
872{
873  size_t used = c->pos - c->sexp->d;
874
875  if ( used + n + sizeof(DATALEN) + 1 >= c->allocated )
876    {
877      gcry_sexp_t newsexp;
878      byte *newhead;
879      size_t newsize;
880
881      newsize = c->allocated + 2*(n+sizeof(DATALEN)+1);
882      if (newsize <= c->allocated)
883        return GPG_ERR_TOO_LARGE;
884      newsexp = gcry_realloc ( c->sexp, sizeof *newsexp + newsize - 1);
885      if (!newsexp)
886        return gpg_err_code_from_errno (errno);
887      c->allocated = newsize;
888      newhead = newsexp->d;
889      c->pos = newhead + used;
890      c->sexp = newsexp;
891    }
892  return 0;
893}
894
895
896/* Unquote STRING of LENGTH and store it into BUF.  The surrounding
897   quotes are must already be removed from STRING.  We assume that the
898   quoted string is syntacillay correct.  */
899static size_t
900unquote_string (const char *string, size_t length, unsigned char *buf)
901{
902  int esc = 0;
903  const unsigned char *s = (const unsigned char*)string;
904  unsigned char *d = buf;
905  size_t n = length;
906
907  for (; n; n--, s++)
908    {
909      if (esc)
910        {
911          switch (*s)
912            {
913            case 'b':  *d++ = '\b'; break;
914            case 't':  *d++ = '\t'; break;
915            case 'v':  *d++ = '\v'; break;
916            case 'n':  *d++ = '\n'; break;
917            case 'f':  *d++ = '\f'; break;
918            case 'r':  *d++ = '\r'; break;
919            case '"':  *d++ = '\"'; break;
920            case '\'': *d++ = '\''; break;
921            case '\\': *d++ = '\\'; break;
922
923            case '\r':  /* ignore CR[,LF] */
924              if (n>1 && s[1] == '\n')
925                {
926                  s++; n--;
927                }
928              break;
929
930            case '\n':  /* ignore LF[,CR] */
931              if (n>1 && s[1] == '\r')
932                {
933                  s++; n--;
934                }
935              break;
936
937            case 'x': /* hex value */
938              if (n>2 && hexdigitp (s+1) && hexdigitp (s+2))
939                {
940                  s++; n--;
941                  *d++ = xtoi_2 (s);
942                  s++; n--;
943                }
944              break;
945
946            default:
947              if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
948                {
949                  *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
950                  s += 2;
951                  n -= 2;
952                }
953              break;
954	    }
955          esc = 0;
956        }
957      else if( *s == '\\' )
958        esc = 1;
959      else
960        *d++ = *s;
961    }
962
963  return d - buf;
964}
965
966/****************
967 * Scan the provided buffer and return the S expression in our internal
968 * format.  Returns a newly allocated expression.  If erroff is not NULL and
969 * a parsing error has occurred, the offset into buffer will be returned.
970 * If ARGFLAG is true, the function supports some printf like
971 * expressions.
972 *  These are:
973 *	%m - MPI
974 *	%s - string (no autoswitch to secure allocation)
975 *	%d - integer stored as string (no autoswitch to secure allocation)
976 *      %b - memory buffer; this takes _two_ arguments: an integer with the
977 *           length of the buffer and a pointer to the buffer.
978 *      %S - Copy an gcry_sexp_t here.  The S-expression needs to be a
979 *           regular one, starting with a parenthesis.
980 *           (no autoswitch to secure allocation)
981 *  all other format elements are currently not defined and return an error.
982 *  this includes the "%%" sequence becauce the percent sign is not an
983 *  allowed character.
984 * FIXME: We should find a way to store the secure-MPIs not in the string
985 * but as reference to somewhere - this can help us to save huge amounts
986 * of secure memory.  The problem is, that if only one element is secure, all
987 * other elements are automagicaly copied to secure memory too, so the most
988 * common operation gcry_sexp_cdr_mpi() will always return a secure MPI
989 * regardless whether it is needed or not.
990 */
991static gcry_error_t
992vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
993	     const char *buffer, size_t length, int argflag,
994	     void **arg_list, va_list arg_ptr)
995{
996  gcry_err_code_t err = 0;
997  static const char tokenchars[] =
998    "abcdefghijklmnopqrstuvwxyz"
999    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1000    "0123456789-./_:*+=";
1001  const char *p;
1002  size_t n;
1003  const char *digptr = NULL;
1004  const char *quoted = NULL;
1005  const char *tokenp = NULL;
1006  const char *hexfmt = NULL;
1007  const char *base64 = NULL;
1008  const char *disphint = NULL;
1009  const char *percent = NULL;
1010  int hexcount = 0;
1011  int quoted_esc = 0;
1012  int datalen = 0;
1013  size_t dummy_erroff;
1014  struct make_space_ctx c;
1015  int arg_counter = 0;
1016  int level = 0;
1017
1018  if (!erroff)
1019    erroff = &dummy_erroff;
1020
1021  /* Depending on whether ARG_LIST is non-zero or not, this macro gives
1022     us the next argument, either from the variable argument list as
1023     specified by ARG_PTR or from the argument array ARG_LIST.  */
1024#define ARG_NEXT(storage, type)                          \
1025  do                                                     \
1026    {                                                    \
1027      if (!arg_list)                                     \
1028	storage = va_arg (arg_ptr, type);                \
1029      else                                               \
1030	storage = *((type *) (arg_list[arg_counter++])); \
1031    }                                                    \
1032  while (0)
1033
1034  /* The MAKE_SPACE macro is used before each store operation to
1035     ensure that the buffer is large enough.  It requires a global
1036     context named C and jumps out to the label LEAVE on error! It
1037     also sets ERROFF using the variables BUFFER and P.  */
1038#define MAKE_SPACE(n)  do {                                                \
1039                            gpg_err_code_t _ms_err = make_space (&c, (n)); \
1040                            if (_ms_err)                                   \
1041                              {                                            \
1042                                err = _ms_err;                             \
1043                                *erroff = p - buffer;                      \
1044                                goto leave;                                \
1045                              }                                            \
1046                       } while (0)
1047
1048  /* The STORE_LEN macro is used to store the length N at buffer P. */
1049#define STORE_LEN(p,n) do {						   \
1050			    DATALEN ashort = (n);			   \
1051			    memcpy ( (p), &ashort, sizeof(ashort) );	   \
1052			    (p) += sizeof (ashort);			   \
1053			} while (0)
1054
1055  /* We assume that the internal representation takes less memory than
1056     the provided one.  However, we add space for one extra datalen so
1057     that the code which does the ST_CLOSE can use MAKE_SPACE */
1058  c.allocated = length + sizeof(DATALEN);
1059  if (buffer && length && gcry_is_secure (buffer))
1060    c.sexp = gcry_malloc_secure (sizeof *c.sexp + c.allocated - 1);
1061  else
1062    c.sexp = gcry_malloc (sizeof *c.sexp + c.allocated - 1);
1063  if (!c.sexp)
1064    {
1065      err = gpg_err_code_from_errno (errno);
1066      *erroff = 0;
1067      goto leave;
1068    }
1069  c.pos = c.sexp->d;
1070
1071  for (p = buffer, n = length; n; p++, n--)
1072    {
1073      if (tokenp && !hexfmt)
1074	{
1075	  if (strchr (tokenchars, *p))
1076	    continue;
1077	  else
1078	    {
1079	      datalen = p - tokenp;
1080	      MAKE_SPACE (datalen);
1081	      *c.pos++ = ST_DATA;
1082	      STORE_LEN (c.pos, datalen);
1083	      memcpy (c.pos, tokenp, datalen);
1084	      c.pos += datalen;
1085	      tokenp = NULL;
1086	    }
1087	}
1088
1089      if (quoted)
1090	{
1091	  if (quoted_esc)
1092	    {
1093	      switch (*p)
1094		{
1095		case 'b': case 't': case 'v': case 'n': case 'f':
1096		case 'r': case '"': case '\'': case '\\':
1097		  quoted_esc = 0;
1098		  break;
1099
1100		case '0': case '1': case '2': case '3': case '4':
1101		case '5': case '6': case '7':
1102		  if (!((n > 2)
1103                        && (p[1] >= '0') && (p[1] <= '7')
1104                        && (p[2] >= '0') && (p[2] <= '7')))
1105		    {
1106		      *erroff = p - buffer;
1107		      /* Invalid octal value.  */
1108		      err = GPG_ERR_SEXP_BAD_QUOTATION;
1109                      goto leave;
1110		    }
1111		  p += 2;
1112		  n -= 2;
1113		  quoted_esc = 0;
1114		  break;
1115
1116		case 'x':
1117		  if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2)))
1118		    {
1119		      *erroff = p - buffer;
1120		      /* Invalid hex value.  */
1121		      err = GPG_ERR_SEXP_BAD_QUOTATION;
1122                      goto leave;
1123		    }
1124		  p += 2;
1125		  n -= 2;
1126		  quoted_esc = 0;
1127		  break;
1128
1129		case '\r':
1130		  /* ignore CR[,LF] */
1131		  if (n && (p[1] == '\n'))
1132		    {
1133		      p++;
1134		      n--;
1135		    }
1136		  quoted_esc = 0;
1137		  break;
1138
1139		case '\n':
1140		  /* ignore LF[,CR] */
1141		  if (n && (p[1] == '\r'))
1142		    {
1143		      p++;
1144		      n--;
1145		    }
1146		  quoted_esc = 0;
1147		  break;
1148
1149		default:
1150		  *erroff = p - buffer;
1151		  /* Invalid quoted string escape.  */
1152		  err = GPG_ERR_SEXP_BAD_QUOTATION;
1153                  goto leave;
1154		}
1155	    }
1156	  else if (*p == '\\')
1157	    quoted_esc = 1;
1158	  else if (*p == '\"')
1159	    {
1160	      /* Keep it easy - we know that the unquoted string will
1161		 never be larger. */
1162	      unsigned char *save;
1163	      size_t len;
1164
1165	      quoted++; /* Skip leading quote.  */
1166	      MAKE_SPACE (p - quoted);
1167	      *c.pos++ = ST_DATA;
1168	      save = c.pos;
1169	      STORE_LEN (c.pos, 0); /* Will be fixed up later.  */
1170	      len = unquote_string (quoted, p - quoted, c.pos);
1171	      c.pos += len;
1172	      STORE_LEN (save, len);
1173	      quoted = NULL;
1174	    }
1175	}
1176      else if (hexfmt)
1177	{
1178	  if (isxdigit (*p))
1179	    hexcount++;
1180	  else if (*p == '#')
1181	    {
1182	      if ((hexcount & 1))
1183		{
1184		  *erroff = p - buffer;
1185		  err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
1186                  goto leave;
1187		}
1188
1189	      datalen = hexcount / 2;
1190	      MAKE_SPACE (datalen);
1191	      *c.pos++ = ST_DATA;
1192	      STORE_LEN (c.pos, datalen);
1193	      for (hexfmt++; hexfmt < p; hexfmt++)
1194		{
1195		  if (whitespacep (hexfmt))
1196		    continue;
1197		  *c.pos++ = hextobyte ((const unsigned char*)hexfmt);
1198		  hexfmt++;
1199		}
1200	      hexfmt = NULL;
1201	    }
1202	  else if (!whitespacep (p))
1203	    {
1204	      *erroff = p - buffer;
1205	      err = GPG_ERR_SEXP_BAD_HEX_CHAR;
1206              goto leave;
1207	    }
1208	}
1209      else if (base64)
1210	{
1211	  if (*p == '|')
1212	    base64 = NULL;
1213	}
1214      else if (digptr)
1215	{
1216	  if (digitp (p))
1217	    ;
1218	  else if (*p == ':')
1219	    {
1220	      datalen = atoi (digptr); /* FIXME: check for overflow.  */
1221	      digptr = NULL;
1222	      if (datalen > n - 1)
1223		{
1224		  *erroff = p - buffer;
1225		  /* Buffer too short.  */
1226		  err = GPG_ERR_SEXP_STRING_TOO_LONG;
1227                  goto leave;
1228		}
1229	      /* Make a new list entry.  */
1230	      MAKE_SPACE (datalen);
1231	      *c.pos++ = ST_DATA;
1232	      STORE_LEN (c.pos, datalen);
1233	      memcpy (c.pos, p + 1, datalen);
1234	      c.pos += datalen;
1235	      n -= datalen;
1236	      p += datalen;
1237	    }
1238	  else if (*p == '\"')
1239	    {
1240	      digptr = NULL; /* We ignore the optional length.  */
1241	      quoted = p;
1242	      quoted_esc = 0;
1243	    }
1244	  else if (*p == '#')
1245	    {
1246	      digptr = NULL; /* We ignore the optional length.  */
1247	      hexfmt = p;
1248	      hexcount = 0;
1249	    }
1250	  else if (*p == '|')
1251	    {
1252	      digptr = NULL; /* We ignore the optional length.  */
1253	      base64 = p;
1254	    }
1255	  else
1256	    {
1257	      *erroff = p - buffer;
1258	      err = GPG_ERR_SEXP_INV_LEN_SPEC;
1259              goto leave;
1260	    }
1261	}
1262      else if (percent)
1263	{
1264	  if (*p == 'm' || *p == 'M')
1265	    {
1266	      /* Insert an MPI.  */
1267	      gcry_mpi_t m;
1268	      size_t nm = 0;
1269              int mpifmt = *p == 'm'? GCRYMPI_FMT_STD: GCRYMPI_FMT_USG;
1270
1271	      ARG_NEXT (m, gcry_mpi_t);
1272
1273              if (gcry_mpi_get_flag (m, GCRYMPI_FLAG_OPAQUE))
1274                {
1275                  void *mp;
1276                  unsigned int nbits;
1277
1278                  mp = gcry_mpi_get_opaque (m, &nbits);
1279                  nm = (nbits+7)/8;
1280                  if (mp && nm)
1281                    {
1282                      MAKE_SPACE (nm);
1283                      if (!gcry_is_secure (c.sexp->d)
1284                          && gcry_mpi_get_flag (m, GCRYMPI_FLAG_SECURE))
1285                        {
1286                          /* We have to switch to secure allocation.  */
1287                          gcry_sexp_t newsexp;
1288                          byte *newhead;
1289
1290                          newsexp = gcry_malloc_secure (sizeof *newsexp
1291                                                        + c.allocated - 1);
1292                          if (!newsexp)
1293                            {
1294                              err = gpg_err_code_from_errno (errno);
1295                              goto leave;
1296                            }
1297                          newhead = newsexp->d;
1298                          memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
1299                          c.pos = newhead + (c.pos - c.sexp->d);
1300                          gcry_free (c.sexp);
1301                          c.sexp = newsexp;
1302                        }
1303
1304                      *c.pos++ = ST_DATA;
1305                      STORE_LEN (c.pos, nm);
1306                      memcpy (c.pos, mp, nm);
1307                      c.pos += nm;
1308                    }
1309                }
1310              else
1311                {
1312                  if (gcry_mpi_print (mpifmt, NULL, 0, &nm, m))
1313                    BUG ();
1314
1315                  MAKE_SPACE (nm);
1316                  if (!gcry_is_secure (c.sexp->d)
1317                      && gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE))
1318                    {
1319                      /* We have to switch to secure allocation.  */
1320                      gcry_sexp_t newsexp;
1321                      byte *newhead;
1322
1323                      newsexp = gcry_malloc_secure (sizeof *newsexp
1324                                                    + c.allocated - 1);
1325                      if (!newsexp)
1326                        {
1327                          err = gpg_err_code_from_errno (errno);
1328                          goto leave;
1329                        }
1330                      newhead = newsexp->d;
1331                      memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
1332                      c.pos = newhead + (c.pos - c.sexp->d);
1333                      gcry_free (c.sexp);
1334                      c.sexp = newsexp;
1335                    }
1336
1337                  *c.pos++ = ST_DATA;
1338                  STORE_LEN (c.pos, nm);
1339                  if (gcry_mpi_print (mpifmt, c.pos, nm, &nm, m))
1340                    BUG ();
1341                  c.pos += nm;
1342                }
1343	    }
1344	  else if (*p == 's')
1345	    {
1346	      /* Insert an string.  */
1347	      const char *astr;
1348	      size_t alen;
1349
1350	      ARG_NEXT (astr, const char *);
1351	      alen = strlen (astr);
1352
1353	      MAKE_SPACE (alen);
1354	      *c.pos++ = ST_DATA;
1355	      STORE_LEN (c.pos, alen);
1356	      memcpy (c.pos, astr, alen);
1357	      c.pos += alen;
1358	    }
1359	  else if (*p == 'b')
1360	    {
1361	      /* Insert a memory buffer.  */
1362	      const char *astr;
1363	      int alen;
1364
1365	      ARG_NEXT (alen, int);
1366	      ARG_NEXT (astr, const char *);
1367
1368	      MAKE_SPACE (alen);
1369	      if (alen
1370                  && !gcry_is_secure (c.sexp->d)
1371		  && gcry_is_secure (astr))
1372              {
1373		  /* We have to switch to secure allocation.  */
1374		  gcry_sexp_t newsexp;
1375		  byte *newhead;
1376
1377		  newsexp = gcry_malloc_secure (sizeof *newsexp
1378                                                + c.allocated - 1);
1379                  if (!newsexp)
1380                    {
1381                      err = gpg_err_code_from_errno (errno);
1382                      goto leave;
1383                    }
1384		  newhead = newsexp->d;
1385		  memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
1386		  c.pos = newhead + (c.pos - c.sexp->d);
1387		  gcry_free (c.sexp);
1388		  c.sexp = newsexp;
1389		}
1390
1391	      *c.pos++ = ST_DATA;
1392	      STORE_LEN (c.pos, alen);
1393	      memcpy (c.pos, astr, alen);
1394	      c.pos += alen;
1395	    }
1396	  else if (*p == 'd')
1397	    {
1398	      /* Insert an integer as string.  */
1399	      int aint;
1400	      size_t alen;
1401	      char buf[35];
1402
1403	      ARG_NEXT (aint, int);
1404	      sprintf (buf, "%d", aint);
1405	      alen = strlen (buf);
1406	      MAKE_SPACE (alen);
1407	      *c.pos++ = ST_DATA;
1408	      STORE_LEN (c.pos, alen);
1409	      memcpy (c.pos, buf, alen);
1410	      c.pos += alen;
1411	    }
1412	  else if (*p == 'u')
1413	    {
1414	      /* Insert an unsigned integer as string.  */
1415	      unsigned int aint;
1416	      size_t alen;
1417	      char buf[35];
1418
1419	      ARG_NEXT (aint, unsigned int);
1420	      sprintf (buf, "%u", aint);
1421	      alen = strlen (buf);
1422	      MAKE_SPACE (alen);
1423	      *c.pos++ = ST_DATA;
1424	      STORE_LEN (c.pos, alen);
1425	      memcpy (c.pos, buf, alen);
1426	      c.pos += alen;
1427	    }
1428	  else if (*p == 'S')
1429	    {
1430	      /* Insert a gcry_sexp_t.  */
1431	      gcry_sexp_t asexp;
1432	      size_t alen, aoff;
1433
1434	      ARG_NEXT (asexp, gcry_sexp_t);
1435              alen = get_internal_buffer (asexp, &aoff);
1436              if (alen)
1437                {
1438                  MAKE_SPACE (alen);
1439                  memcpy (c.pos, asexp->d + aoff, alen);
1440                  c.pos += alen;
1441                }
1442	    }
1443	  else
1444	    {
1445	      *erroff = p - buffer;
1446	      /* Invalid format specifier.  */
1447	      err = GPG_ERR_SEXP_INV_LEN_SPEC;
1448              goto leave;
1449	    }
1450	  percent = NULL;
1451	}
1452      else if (*p == '(')
1453	{
1454	  if (disphint)
1455	    {
1456	      *erroff = p - buffer;
1457	      /* Open display hint.  */
1458	      err = GPG_ERR_SEXP_UNMATCHED_DH;
1459              goto leave;
1460	    }
1461	  MAKE_SPACE (0);
1462	  *c.pos++ = ST_OPEN;
1463	  level++;
1464	}
1465      else if (*p == ')')
1466	{
1467	  /* Walk up.  */
1468	  if (disphint)
1469	    {
1470	      *erroff = p - buffer;
1471	      /* Open display hint.  */
1472	      err = GPG_ERR_SEXP_UNMATCHED_DH;
1473              goto leave;
1474	    }
1475	  MAKE_SPACE (0);
1476	  *c.pos++ = ST_CLOSE;
1477	  level--;
1478	}
1479      else if (*p == '\"')
1480	{
1481	  quoted = p;
1482	  quoted_esc = 0;
1483	}
1484      else if (*p == '#')
1485	{
1486	  hexfmt = p;
1487	  hexcount = 0;
1488	}
1489      else if (*p == '|')
1490	base64 = p;
1491      else if (*p == '[')
1492	{
1493	  if (disphint)
1494	    {
1495	      *erroff = p - buffer;
1496	      /* Open display hint.  */
1497	      err = GPG_ERR_SEXP_NESTED_DH;
1498              goto leave;
1499	    }
1500	  disphint = p;
1501	}
1502      else if (*p == ']')
1503	{
1504	  if (!disphint)
1505	    {
1506	      *erroff = p - buffer;
1507	      /* Open display hint.  */
1508	      err = GPG_ERR_SEXP_UNMATCHED_DH;
1509              goto leave;
1510	    }
1511	  disphint = NULL;
1512	}
1513      else if (digitp (p))
1514	{
1515	  if (*p == '0')
1516	    {
1517	      /* A length may not begin with zero.  */
1518	      *erroff = p - buffer;
1519	      err = GPG_ERR_SEXP_ZERO_PREFIX;
1520              goto leave;
1521	    }
1522	  digptr = p;
1523	}
1524      else if (strchr (tokenchars, *p))
1525	tokenp = p;
1526      else if (whitespacep (p))
1527	;
1528      else if (*p == '{')
1529	{
1530	  /* fixme: handle rescanning: we can do this by saving our
1531	     current state and start over at p+1 -- Hmmm. At this
1532	     point here we are in a well defined state, so we don't
1533	     need to save it.  Great.  */
1534	  *erroff = p - buffer;
1535	  err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
1536          goto leave;
1537	}
1538      else if (strchr ("&\\", *p))
1539	{
1540	  /* Reserved punctuation.  */
1541	  *erroff = p - buffer;
1542	  err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
1543          goto leave;
1544	}
1545      else if (argflag && (*p == '%'))
1546	percent = p;
1547      else
1548	{
1549	  /* Bad or unavailable.  */
1550	  *erroff = p - buffer;
1551	  err = GPG_ERR_SEXP_BAD_CHARACTER;
1552          goto leave;
1553	}
1554    }
1555  MAKE_SPACE (0);
1556  *c.pos++ = ST_STOP;
1557
1558  if (level && !err)
1559    err = GPG_ERR_SEXP_UNMATCHED_PAREN;
1560
1561 leave:
1562  if (err)
1563    {
1564      /* Error -> deallocate.  */
1565      if (c.sexp)
1566        {
1567          /* Extra paranoid wipe on error. */
1568          if (gcry_is_secure (c.sexp))
1569            wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
1570          gcry_free (c.sexp);
1571        }
1572      /* This might be expected by existing code...  */
1573      *retsexp = NULL;
1574    }
1575  else
1576    *retsexp = normalize (c.sexp);
1577
1578  return gcry_error (err);
1579#undef MAKE_SPACE
1580#undef STORE_LEN
1581}
1582
1583
1584static gcry_error_t
1585sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
1586	    const char *buffer, size_t length, int argflag,
1587	    void **arg_list, ...)
1588{
1589  gcry_error_t rc;
1590  va_list arg_ptr;
1591
1592  va_start (arg_ptr, arg_list);
1593  rc = vsexp_sscan (retsexp, erroff, buffer, length, argflag,
1594		    arg_list, arg_ptr);
1595  va_end (arg_ptr);
1596
1597  return rc;
1598}
1599
1600
1601gcry_error_t
1602gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...)
1603{
1604  gcry_error_t rc;
1605  va_list arg_ptr;
1606
1607  va_start (arg_ptr, format);
1608  rc = vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
1609		    NULL, arg_ptr);
1610  va_end (arg_ptr);
1611
1612  return rc;
1613}
1614
1615
1616gcry_error_t
1617_gcry_sexp_vbuild (gcry_sexp_t *retsexp, size_t *erroff,
1618                   const char *format, va_list arg_ptr)
1619{
1620  return vsexp_sscan (retsexp, erroff, format, strlen(format), 1,
1621		      NULL, arg_ptr);
1622}
1623
1624
1625/* Like gcry_sexp_build, but uses an array instead of variable
1626   function arguments.  */
1627gcry_error_t
1628gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
1629		       const char *format, void **arg_list)
1630{
1631  return sexp_sscan (retsexp, erroff, format, strlen(format), 1, arg_list);
1632}
1633
1634
1635gcry_error_t
1636gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
1637		 const char *buffer, size_t length)
1638{
1639  return sexp_sscan (retsexp, erroff, buffer, length, 0, NULL);
1640}
1641
1642
1643/* Figure out a suitable encoding for BUFFER of LENGTH.
1644   Returns: 0 = Binary
1645            1 = String possible
1646            2 = Token possible
1647*/
1648static int
1649suitable_encoding (const unsigned char *buffer, size_t length)
1650{
1651  const unsigned char *s;
1652  int maybe_token = 1;
1653
1654  if (!length)
1655    return 1;
1656
1657  for (s=buffer; length; s++, length--)
1658    {
1659      if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
1660           && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
1661        return 0; /*binary*/
1662      if ( maybe_token
1663           && !alphap (s) && !digitp (s)  && !strchr (TOKEN_SPECIALS, *s))
1664        maybe_token = 0;
1665    }
1666  s = buffer;
1667  if ( maybe_token && !digitp (s) )
1668    return 2;
1669  return 1;
1670}
1671
1672
1673static int
1674convert_to_hex (const unsigned char *src, size_t len, char *dest)
1675{
1676  int i;
1677
1678  if (dest)
1679    {
1680      *dest++ = '#';
1681      for (i=0; i < len; i++, dest += 2 )
1682        sprintf (dest, "%02X", src[i]);
1683      *dest++ = '#';
1684    }
1685  return len*2+2;
1686}
1687
1688static int
1689convert_to_string (const unsigned char *s, size_t len, char *dest)
1690{
1691  if (dest)
1692    {
1693      char *p = dest;
1694      *p++ = '\"';
1695      for (; len; len--, s++ )
1696        {
1697          switch (*s)
1698            {
1699            case '\b': *p++ = '\\'; *p++ = 'b';  break;
1700            case '\t': *p++ = '\\'; *p++ = 't';  break;
1701            case '\v': *p++ = '\\'; *p++ = 'v';  break;
1702            case '\n': *p++ = '\\'; *p++ = 'n';  break;
1703            case '\f': *p++ = '\\'; *p++ = 'f';  break;
1704            case '\r': *p++ = '\\'; *p++ = 'r';  break;
1705            case '\"': *p++ = '\\'; *p++ = '\"';  break;
1706            case '\'': *p++ = '\\'; *p++ = '\'';  break;
1707            case '\\': *p++ = '\\'; *p++ = '\\';  break;
1708            default:
1709              if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1710                {
1711                  sprintf (p, "\\x%02x", *s);
1712                  p += 4;
1713                }
1714              else
1715                *p++ = *s;
1716            }
1717        }
1718      *p++ = '\"';
1719      return p - dest;
1720    }
1721  else
1722    {
1723      int count = 2;
1724      for (; len; len--, s++ )
1725        {
1726          switch (*s)
1727            {
1728            case '\b':
1729            case '\t':
1730            case '\v':
1731            case '\n':
1732            case '\f':
1733            case '\r':
1734            case '\"':
1735            case '\'':
1736            case '\\': count += 2; break;
1737            default:
1738              if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1739                count += 4;
1740              else
1741                count++;
1742            }
1743        }
1744      return count;
1745    }
1746}
1747
1748
1749
1750static int
1751convert_to_token (const unsigned char *src, size_t len, char *dest)
1752{
1753  if (dest)
1754    memcpy (dest, src, len);
1755  return len;
1756}
1757
1758
1759/****************
1760 * Print SEXP to buffer using the MODE.  Returns the length of the
1761 * SEXP in buffer or 0 if the buffer is too short (We have at least an
1762 * empty list consisting of 2 bytes).  If a buffer of NULL is provided,
1763 * the required length is returned.
1764 */
1765size_t
1766gcry_sexp_sprint (const gcry_sexp_t list, int mode,
1767                  void *buffer, size_t maxlength )
1768{
1769  static unsigned char empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
1770  const unsigned char *s;
1771  char *d;
1772  DATALEN n;
1773  char numbuf[20];
1774  size_t len = 0;
1775  int i, indent = 0;
1776
1777  s = list? list->d : empty;
1778  d = buffer;
1779  while ( *s != ST_STOP )
1780    {
1781      switch ( *s )
1782        {
1783        case ST_OPEN:
1784          s++;
1785          if ( mode != GCRYSEXP_FMT_CANON )
1786            {
1787              if (indent)
1788                len++;
1789              len += indent;
1790            }
1791          len++;
1792          if ( buffer )
1793            {
1794              if ( len >= maxlength )
1795                return 0;
1796              if ( mode != GCRYSEXP_FMT_CANON )
1797                {
1798                  if (indent)
1799                    *d++ = '\n';
1800                  for (i=0; i < indent; i++)
1801                    *d++ = ' ';
1802                }
1803              *d++ = '(';
1804	    }
1805          indent++;
1806          break;
1807        case ST_CLOSE:
1808          s++;
1809          len++;
1810          if ( buffer )
1811            {
1812              if ( len >= maxlength )
1813                return 0;
1814              *d++ = ')';
1815	    }
1816          indent--;
1817          if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
1818            {
1819              len++;
1820              len += indent;
1821              if (buffer)
1822                {
1823                  if (len >= maxlength)
1824                    return 0;
1825                  *d++ = '\n';
1826                  for (i=0; i < indent; i++)
1827                    *d++ = ' ';
1828                }
1829            }
1830          break;
1831        case ST_DATA:
1832          s++;
1833          memcpy ( &n, s, sizeof n ); s += sizeof n;
1834          if (mode == GCRYSEXP_FMT_ADVANCED)
1835            {
1836              int type;
1837              size_t nn;
1838
1839              switch ( (type=suitable_encoding (s, n)))
1840                {
1841                case 1: nn = convert_to_string (s, n, NULL); break;
1842                case 2: nn = convert_to_token (s, n, NULL); break;
1843                default: nn = convert_to_hex (s, n, NULL); break;
1844                }
1845              len += nn;
1846              if (buffer)
1847                {
1848                  if (len >= maxlength)
1849                    return 0;
1850                  switch (type)
1851                    {
1852                    case 1: convert_to_string (s, n, d); break;
1853                    case 2: convert_to_token (s, n, d); break;
1854                    default: convert_to_hex (s, n, d); break;
1855                    }
1856                  d += nn;
1857                }
1858              if (s[n] != ST_CLOSE)
1859                {
1860                  len++;
1861                  if (buffer)
1862                    {
1863                      if (len >= maxlength)
1864                        return 0;
1865                      *d++ = ' ';
1866                    }
1867                }
1868            }
1869          else
1870            {
1871              sprintf (numbuf, "%u:", (unsigned int)n );
1872              len += strlen (numbuf) + n;
1873              if ( buffer )
1874                {
1875                  if ( len >= maxlength )
1876		    return 0;
1877                  d = stpcpy ( d, numbuf );
1878                  memcpy ( d, s, n ); d += n;
1879                }
1880            }
1881          s += n;
1882          break;
1883        default:
1884          BUG ();
1885	}
1886    }
1887  if ( mode != GCRYSEXP_FMT_CANON )
1888    {
1889      len++;
1890      if (buffer)
1891        {
1892          if ( len >= maxlength )
1893            return 0;
1894          *d++ = '\n';
1895        }
1896    }
1897  if (buffer)
1898    {
1899      if ( len >= maxlength )
1900        return 0;
1901      *d++ = 0; /* for convenience we make a C string */
1902    }
1903  else
1904    len++; /* we need one byte more for this */
1905
1906  return len;
1907}
1908
1909
1910/* Scan a canonical encoded buffer with implicit length values and
1911   return the actual length this S-expression uses.  For a valid S-Exp
1912   it should never return 0.  If LENGTH is not zero, the maximum
1913   length to scan is given - this can be used for syntax checks of
1914   data passed from outside. errorcode and erroff may both be passed as
1915   NULL.  */
1916size_t
1917gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
1918                     size_t *erroff, gcry_error_t *errcode)
1919{
1920  const unsigned char *p;
1921  const unsigned char *disphint = NULL;
1922  unsigned int datalen = 0;
1923  size_t dummy_erroff;
1924  gcry_error_t dummy_errcode;
1925  size_t count = 0;
1926  int level = 0;
1927
1928  if (!erroff)
1929    erroff = &dummy_erroff;
1930  if (!errcode)
1931    errcode = &dummy_errcode;
1932
1933  *errcode = gcry_error (GPG_ERR_NO_ERROR);
1934  *erroff = 0;
1935  if (!buffer)
1936    return 0;
1937  if (*buffer != '(')
1938    {
1939      *errcode = gcry_error (GPG_ERR_SEXP_NOT_CANONICAL);
1940      return 0;
1941    }
1942
1943  for (p=buffer; ; p++, count++ )
1944    {
1945      if (length && count >= length)
1946        {
1947          *erroff = count;
1948          *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
1949          return 0;
1950        }
1951
1952      if (datalen)
1953        {
1954          if (*p == ':')
1955            {
1956              if (length && (count+datalen) >= length)
1957                {
1958                  *erroff = count;
1959                  *errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
1960                  return 0;
1961                }
1962              count += datalen;
1963              p += datalen;
1964              datalen = 0;
1965	    }
1966          else if (digitp(p))
1967            datalen = datalen*10 + atoi_1(p);
1968          else
1969            {
1970              *erroff = count;
1971              *errcode = gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC);
1972              return 0;
1973	    }
1974	}
1975      else if (*p == '(')
1976        {
1977          if (disphint)
1978            {
1979              *erroff = count;
1980              *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1981              return 0;
1982	    }
1983          level++;
1984	}
1985      else if (*p == ')')
1986        { /* walk up */
1987          if (!level)
1988            {
1989              *erroff = count;
1990              *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_PAREN);
1991              return 0;
1992	    }
1993          if (disphint)
1994            {
1995              *erroff = count;
1996              *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
1997              return 0;
1998	    }
1999          if (!--level)
2000            return ++count; /* ready */
2001	}
2002      else if (*p == '[')
2003        {
2004          if (disphint)
2005            {
2006              *erroff = count;
2007              *errcode = gcry_error (GPG_ERR_SEXP_NESTED_DH);
2008              return 0;
2009            }
2010          disphint = p;
2011	}
2012      else if (*p == ']')
2013        {
2014          if ( !disphint )
2015            {
2016              *erroff = count;
2017              *errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
2018              return 0;
2019	    }
2020          disphint = NULL;
2021	}
2022      else if (digitp (p) )
2023        {
2024          if (*p == '0')
2025            {
2026              *erroff = count;
2027              *errcode = gcry_error (GPG_ERR_SEXP_ZERO_PREFIX);
2028              return 0;
2029	    }
2030          datalen = atoi_1 (p);
2031	}
2032      else if (*p == '&' || *p == '\\')
2033        {
2034          *erroff = count;
2035          *errcode = gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
2036          return 0;
2037	}
2038      else
2039        {
2040          *erroff = count;
2041          *errcode = gcry_error (GPG_ERR_SEXP_BAD_CHARACTER);
2042          return 0;
2043	}
2044    }
2045}
2046