c1bf804e046a336666206678cc715ee5a1f14df1
[libgcrypt.git] / src / sexp.c
1 /* sexp.c  -  S-Expression handling
2  *      Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser general Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <ctype.h>
28 #include <assert.h>
29
30 #define GCRYPT_NO_MPI_MACROS 1
31 #include "g10lib.h"
32 #include "memory.h"
33
34 typedef struct gcry_sexp *NODE;
35 typedef unsigned short DATALEN;
36
37 struct gcry_sexp {
38     byte d[1];
39 };
40
41 #define ST_STOP  0
42 #define ST_DATA  1  /* datalen follows */
43 #define ST_HINT  2  /* datalen follows */
44 #define ST_OPEN  3
45 #define ST_CLOSE 4
46
47 #define digitp(p)   (*(p) >= '0' && *(p) <= '9')
48 #define octdigitp(p) (*(p) >= '0' && *(p) <= '7')
49 #define alphap(a)    (   (*(a) >= 'A' && *(a) <= 'Z')  \
50                       || (*(a) >= 'a' && *(a) <= 'z'))
51 #define hexdigitp(a) (digitp (a)                     \
52                       || (*(a) >= 'A' && *(a) <= 'F')  \
53                       || (*(a) >= 'a' && *(a) <= 'f'))
54 /* the atoi macros assume that the buffer has only valid digits */
55 #define atoi_1(p)   (*(p) - '0' )
56 #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
57                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
58 #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
59
60 #define TOKEN_SPECIALS  "-./_:*+="
61
62
63 #if 0
64 static void
65 dump_mpi( GCRY_MPI a )
66 {
67     char buffer[1000];
68     size_t n = 1000;
69
70     if( !a )
71         fputs("[no MPI]", stderr );
72     else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) )
73         fputs("[MPI too large to print]", stderr );
74     else
75         fputs( buffer, stderr );
76 }
77 #endif
78
79 static void
80 dump_string (const byte *p, size_t n, int delim )
81 {
82   for (; n; n--, p++ )
83     {
84       if ((*p & 0x80) || iscntrl( *p ) || *p == delim ) 
85         {
86           if( *p == '\n' )
87             log_printf ("\\n");
88           else if( *p == '\r' )
89             log_printf ("\\r");
90           else if( *p == '\f' )
91             log_printf ("\\f");
92           else if( *p == '\v' )
93             log_printf ("\\v");
94             else if( *p == '\b' )
95               log_printf ("\\b");
96           else if( !*p )       
97             log_printf ("\\0");
98           else
99             log_printf ("\\x%02x", *p );
100         }
101       else
102         log_printf ("%c", *p);
103     }
104 }
105
106
107 void
108 gcry_sexp_dump (const GCRY_SEXP a)
109 {
110   const byte *p;
111   int indent = 0;
112   int type;
113
114   if (!a)
115     {
116       log_printf ( "[nil]\n");
117       return;
118     }
119
120   p = a->d;
121   while ( (type = *p) != ST_STOP )
122     {
123       p++;
124       switch ( type )
125         {
126         case ST_OPEN:
127           log_printf ("%*s[open]\n", 2*indent, "");
128           indent++;
129           break;
130         case ST_CLOSE:
131           if( indent )
132             indent--;
133           log_printf ("%*s[close]\n", 2*indent, "");
134           break;
135         case ST_DATA: {
136           DATALEN n;
137           memcpy ( &n, p, sizeof n );
138           p += sizeof n;
139           log_printf ("%*s[data=\"", 2*indent, "" );
140           dump_string (p, n, '\"' );
141           log_printf ("\"]\n");
142           p += n;
143         }
144         break;
145         default:
146           log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type);
147           break;
148         }
149     }
150 }
151
152 /****************
153  * Pass list through except when it is an empty list - in that case
154  * return NULL and release the passed list.
155  */
156 static GCRY_SEXP
157 normalize ( GCRY_SEXP list )
158 {
159     char *p;
160     if ( !list )
161         return NULL;
162     p = list->d;
163     if ( *p == ST_STOP ) {
164         /* this is "" */
165         gcry_sexp_release ( list );
166         return NULL;
167     }
168     if( *p == ST_OPEN && p[1] == ST_CLOSE ) {
169         /* this is "()" */
170         gcry_sexp_release ( list );
171         return NULL;
172     }
173
174     return list;
175 }
176
177 /****************
178  * Release resource of the given SEXP object.
179  */
180 void
181 gcry_sexp_release( GCRY_SEXP sexp )
182 {
183     gcry_free ( sexp );
184 }
185
186
187 /****************
188  * Make a pair from lists a and b, don't use a or b later on.
189  * Special behaviour:  If one is a single element list we put the
190  * element straight into the new pair.
191  */
192 GCRY_SEXP
193 gcry_sexp_cons( const GCRY_SEXP a, const GCRY_SEXP b )
194 {
195     /* NYI: Implementation should be quite easy with our new data representation */
196     BUG ();
197     return NULL;
198 }
199
200
201 /****************
202  * Make a list from all items in the array the end of the array is marked
203  * with a NULL.                                                                       y a NULL
204  */
205 GCRY_SEXP
206 gcry_sexp_alist( const GCRY_SEXP *array )
207 {
208     /* NYI: Implementaion should be quite easy with our new data representation */
209     BUG ();
210     return NULL;
211 }
212
213 /****************
214  * Make a list from all items, the end of list is indicated by a NULL
215  */
216 GCRY_SEXP
217 gcry_sexp_vlist( const GCRY_SEXP a, ... )
218 {
219     /* NYI: Implementaion should be quite easy with our new data representation */
220     BUG ();
221     return NULL;
222 }
223
224
225 /****************
226  * Append n to the list a
227  * Returns: a new ist (which maybe a)
228  */
229 GCRY_SEXP
230 gcry_sexp_append( const GCRY_SEXP a, const GCRY_SEXP n )
231 {
232     /* NYI: Implementaion should be quite easy with our new data representation */
233     BUG ();
234     return NULL;
235 }
236
237 GCRY_SEXP
238 gcry_sexp_prepend( const GCRY_SEXP a, const GCRY_SEXP n )
239 {
240     /* NYI: Implementaion should be quite easy with our new data representation */
241     BUG ();
242     return NULL;
243 }
244
245
246
247 /****************
248  * Locate token in a list. The token must be the car of a sublist.
249  * Returns: A new list with this sublist or NULL if not found.
250  */
251 GCRY_SEXP
252 gcry_sexp_find_token( const GCRY_SEXP list, const char *tok, size_t toklen )
253 {
254     const byte *p;
255     DATALEN n;
256
257     if ( !list )
258         return NULL;
259
260     if( !toklen )
261         toklen = strlen(tok);
262     p = list->d;
263     while ( *p != ST_STOP ) {
264         if ( *p == ST_OPEN && p[1] == ST_DATA ) {
265             const byte *head = p;
266
267             p += 2;
268             memcpy ( &n, p, sizeof n ); p += sizeof n;
269             if ( n == toklen && !memcmp( p, tok, toklen ) ) { /* found it */
270                 GCRY_SEXP newlist;
271                 byte *d;
272                 int level = 1;
273
274                 /* look for the end of the list */
275                 for ( p += n; level; p++ ) {
276                     if ( *p == ST_DATA ) {
277                         memcpy ( &n, ++p, sizeof n );
278                         p += sizeof n + n;
279                         p--; /* compensate for later increment */
280                     }
281                     else if ( *p == ST_OPEN ) {
282                         level++;
283                     }
284                     else if ( *p == ST_CLOSE ) {
285                         level--;
286                     }
287                     else if ( *p == ST_STOP ) {
288                         BUG ();
289                     }
290                 } while ( level );
291                 n = p - head;
292
293                 newlist = gcry_xmalloc ( sizeof *newlist + n );
294                 d = newlist->d;
295                 memcpy ( d, head, n ); d += n;
296                 *d++ = ST_STOP;
297                 return normalize ( newlist );
298             }
299             p += n;
300         }
301         else if ( *p == ST_DATA ) {
302             memcpy ( &n, ++p, sizeof n ); p += sizeof n;
303             p += n;
304         }
305         else
306             p++;
307     }
308     return NULL;
309 }
310
311 /****************
312  * return the length of the given list
313  */
314 int
315 gcry_sexp_length( const GCRY_SEXP list )
316 {
317     const byte *p;
318     DATALEN n;
319     int type;
320     int length = 0;
321     int level = 0;
322
323     if ( !list )
324         return 0;
325
326     p = list->d;
327     while ( (type=*p) != ST_STOP ) {
328         p++;
329         if ( type == ST_DATA ) {
330             memcpy ( &n, ++p, sizeof n );
331             p += sizeof n + n;
332             p--;
333             if ( !level )
334                 length++;
335         }
336         else if ( type == ST_OPEN ) {
337             if ( !level )
338                 length++;
339             level++;
340         }
341         else if ( type == ST_CLOSE ) {
342             level--;
343         }
344     }
345     return length;
346 }
347
348
349
350 /****************
351  * Extract the CAR of the given list
352  */
353 GCRY_SEXP
354 gcry_sexp_nth( const GCRY_SEXP list, int number )
355 {
356     const byte *p;
357     DATALEN n;
358     GCRY_SEXP newlist;
359     byte *d;
360     int level = 0;
361
362     if ( !list || list->d[0] != ST_OPEN )
363         return NULL;
364     p = list->d;
365
366     while ( number > 0 ) {
367         p++;
368         if ( *p == ST_DATA ) {
369             memcpy ( &n, ++p, sizeof n );
370             p += sizeof n + n;
371             p--;
372             if ( !level )
373                 number--;
374         }
375         else if ( *p == ST_OPEN ) {
376             level++;
377         }
378         else if ( *p == ST_CLOSE ) {
379             level--;
380             if ( !level )
381                 number--;
382         }
383         else if ( *p == ST_STOP ) {
384             return NULL;
385         }
386     }
387     p++;
388
389     if ( *p == ST_DATA ) {
390         memcpy ( &n, p, sizeof n ); p += sizeof n;
391         newlist = gcry_xmalloc ( sizeof *newlist + n + 1 );
392         d = newlist->d;
393         memcpy ( d, p, n ); d += n;
394         *d++ = ST_STOP;
395     }
396     else if ( *p == ST_OPEN ) {
397         const byte *head = p;
398
399         level = 1;
400         do {
401             p++;
402             if ( *p == ST_DATA ) {
403                 memcpy ( &n, ++p, sizeof n );
404                 p += sizeof n + n;
405                 p--;
406             }
407             else if ( *p == ST_OPEN ) {
408                 level++;
409             }
410             else if ( *p == ST_CLOSE ) {
411                 level--;
412             }
413             else if ( *p == ST_STOP ) {
414                 BUG ();
415             }
416         } while ( level );
417         n = p + 1 - head;
418
419         newlist = gcry_xmalloc ( sizeof *newlist + n );
420         d = newlist->d;
421         memcpy ( d, head, n ); d += n;
422         *d++ = ST_STOP;
423     }
424     else
425         newlist = NULL;
426
427     return normalize (newlist);
428 }
429
430 GCRY_SEXP
431 gcry_sexp_car( const GCRY_SEXP list )
432 {
433     return gcry_sexp_nth ( list, 0 );
434 }
435
436 /****************
437  * Get data from the car.  The returned value is valid as long as the list
438  * is not modified.
439  */
440 const char *
441 gcry_sexp_nth_data( const GCRY_SEXP list, int number, size_t *datalen )
442 {
443     const byte *p;
444     DATALEN n;
445     int level = 0;
446
447     *datalen = 0;
448     if ( !list ) {
449         return NULL;
450     }
451     p = list->d;
452     if ( *p == ST_OPEN )
453         p++;         /* yep, a list */
454     else if (number )
455         return NULL; /* not a list but an n > 0 element requested */
456
457     /* skip n elements */
458     while ( number > 0 ) {
459         if ( *p == ST_DATA ) {
460             memcpy ( &n, ++p, sizeof n );
461             p += sizeof n + n;
462             p--;
463             if ( !level )
464                 number--;
465         }
466         else if ( *p == ST_OPEN ) {
467             level++;
468         }
469         else if ( *p == ST_CLOSE ) {
470             level--;
471             if ( !level )
472                 number--;
473         }
474         else if ( *p == ST_STOP ) {
475             return NULL;
476         }
477         p++;
478     }
479
480
481     if ( *p == ST_DATA ) {
482         memcpy ( &n, ++p, sizeof n );
483         *datalen = n;
484         return p + sizeof n;
485     }
486
487     return NULL;
488 }
489
490 /****************
491  * Get a MPI from the car
492  */
493 GCRY_MPI
494 gcry_sexp_nth_mpi( GCRY_SEXP list, int number, int mpifmt )
495 {
496     const byte *p;
497     DATALEN n;
498     int level = 0;
499
500     if ( !list )
501         return NULL;
502     if ( !mpifmt )
503         mpifmt = GCRYMPI_FMT_STD;
504
505     p = list->d;
506     if ( *p == ST_OPEN )
507         p++;         /* yep, a list */
508     else if (number )
509         return NULL; /* not a list but an n > 0 element requested */
510
511     /* skip n elements */
512     while ( number > 0 ) {
513         if ( *p == ST_DATA ) {
514             memcpy ( &n, ++p, sizeof n );
515             p += sizeof n + n;
516             p--;
517             if ( !level )
518                 number--;
519         }
520         else if ( *p == ST_OPEN ) {
521             level++;
522         }
523         else if ( *p == ST_CLOSE ) {
524             level--;
525             if ( !level )
526                 number--;
527         }
528         else if ( *p == ST_STOP ) {
529             return NULL;
530         }
531         p++;
532     }
533
534     if ( *p == ST_DATA ) {
535         MPI a;
536         size_t nbytes;
537
538         memcpy ( &n, ++p, sizeof n );
539         p += sizeof n;
540         nbytes = n;
541         if( !gcry_mpi_scan( &a, mpifmt, p, &nbytes ) )
542             return a;
543     }
544
545     return NULL;
546 }
547
548
549 /****************
550  * Get the CDR
551  */
552 GCRY_SEXP
553 gcry_sexp_cdr( const GCRY_SEXP list )
554 {
555     const byte *p;
556     const byte *head;
557     DATALEN n;
558     GCRY_SEXP newlist;
559     byte *d;
560     int level = 0;
561     int skip = 1;
562
563     if ( !list || list->d[0] != ST_OPEN )
564         return NULL;
565     p = list->d;
566
567     while ( skip > 0 ) {
568         p++;
569         if ( *p == ST_DATA ) {
570             memcpy ( &n, ++p, sizeof n );
571             p += sizeof n + n;
572             p--;
573             if ( !level )
574                 skip--;
575         }
576         else if ( *p == ST_OPEN ) {
577             level++;
578         }
579         else if ( *p == ST_CLOSE ) {
580             level--;
581             if ( !level )
582                 skip--;
583         }
584         else if ( *p == ST_STOP ) {
585             return NULL;
586         }
587     }
588     p++;
589
590     head = p;
591     level = 0;
592     do {
593         if ( *p == ST_DATA ) {
594             memcpy ( &n, ++p, sizeof n );
595             p += sizeof n + n;
596             p--;
597         }
598         else if ( *p == ST_OPEN ) {
599             level++;
600         }
601         else if ( *p == ST_CLOSE ) {
602             level--;
603         }
604         else if ( *p == ST_STOP ) {
605             return NULL;
606         }
607         p++;
608     } while ( level );
609     n = p - head;
610
611     newlist = gcry_xmalloc ( sizeof *newlist + n + 2 );
612     d = newlist->d;
613     *d++ = ST_OPEN;
614     memcpy ( d, head, n ); d += n;
615     *d++ = ST_CLOSE;
616     *d++ = ST_STOP;
617
618     return normalize (newlist);
619 }
620
621 GCRY_SEXP
622 gcry_sexp_cadr ( const GCRY_SEXP list )
623 {
624     GCRY_SEXP a, b;
625
626     a = gcry_sexp_cdr ( list );
627     b = gcry_sexp_car ( a );
628     gcry_sexp_release ( a );
629     return b;
630 }
631
632
633
634 static int
635 hextobyte( const byte *s )
636 {
637     int c=0;
638
639     if( *s >= '0' && *s <= '9' )
640         c = 16 * (*s - '0');
641     else if( *s >= 'A' && *s <= 'F' )
642         c = 16 * (10 + *s - 'A');
643     else if( *s >= 'a' && *s <= 'f' ) {
644         c = 16 * (10 + *s - 'a');
645     }
646     s++;
647     if( *s >= '0' && *s <= '9' )
648         c += *s - '0';
649     else if( *s >= 'A' && *s <= 'F' )
650         c += 10 + *s - 'A';
651     else if( *s >= 'a' && *s <= 'f' ) {
652         c += 10 + *s - 'a';
653     }
654     return c;
655 }
656
657 struct make_space_ctx {
658     GCRY_SEXP sexp;
659     size_t allocated;
660     byte *pos;
661 };
662
663 static void
664 make_space ( struct make_space_ctx *c, size_t n )
665 {
666     size_t used = c->pos - c->sexp->d;
667
668     if ( used + n + sizeof(DATALEN) + 1 >= c->allocated ) {
669         GCRY_SEXP newsexp;
670         byte *newhead;
671
672         c->allocated += 2*(n+sizeof(DATALEN)+1);
673         newsexp = gcry_xrealloc ( c->sexp, sizeof *newsexp + c->allocated - 1 );
674         newhead = newsexp->d;
675         c->pos = newhead + used;
676         c->sexp = newsexp;
677     }
678 }
679
680
681 /* Unquote STRING of LENGTH and store it into BUF.  The surrounding
682    quotes are must already be removed from STRING.  We assume that the
683    quoted string is syntacillay correct.  */
684 static size_t
685 unquote_string (const unsigned char *string, size_t length, unsigned char *buf)
686 {
687   int esc = 0;
688   const unsigned char *s = string;
689   unsigned char *d = buf;
690   size_t n = length;
691
692   for (; n; n--, s++)
693     {
694       if (esc)
695         {
696           switch (*s)
697             {
698             case 'b':  *d++ = '\b'; break;
699             case 't':  *d++ = '\t'; break;
700             case 'v':  *d++ = '\v'; break;
701             case 'n':  *d++ = '\n'; break;
702             case 'f':  *d++ = '\f'; break;
703             case 'r':  *d++ = '\r'; break;
704             case '"':  *d++ = '\"'; break;
705             case '\'': *d++ = '\''; break;
706             case '\\': *d++ = '\\'; break;
707
708             case '\r':  /* ignore CR[,LF] */
709               if (n>1 && s[1] == '\n')
710                 {
711                   s++; n--;
712                 }
713               esc = 0;
714               break;
715               
716             case '\n':  /* ignore LF[,CR] */
717               if (n>1 && s[1] == '\r')
718                 {
719                   s++; n--;
720                 }
721               break;
722
723             case 'x': /* hex value */
724               if (n>2 && hexdigitp (s+1) && hexdigitp (s+2))
725                 {
726                   s++; n--;
727                   *d++ = xtoi_2 (s);
728                   s++; n--;
729                 }
730               break;
731
732             default:
733               if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
734                 {
735                   *d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
736                   s += 2;
737                   n -= 2;
738                 }
739               break;
740             }
741           esc = 0;
742         }
743       else if( *s == '\\' )
744         esc = 1;
745       else
746         *d++ = *s;
747     } 
748
749   return d - buf;
750 }
751
752 /****************
753  * Scan the provided buffer and return the S expression in our internal
754  * format.  Returns a newly allocated expression.  If erroff is not NULL and
755  * a parsing error has occured, the offset into buffer will be returned.
756  * If ARGFLAG is true, the function supports some printf like
757  * expressions.
758  *  These are:
759  *      %m - MPI
760  *      %s - string (no autoswitch to secure allocation)
761  *      %d - integer stored as string (no autoswitch to secure allocation)
762  *  all other format elements are currently not defined and return an error.
763  *  this includes the "%%" sequence becauce the percent sign is not an
764  *  allowed character.
765  * FIXME: We should find a way to store the secure-MPIS not in the string
766  * but as reference to somewhere - this can help us to save huge amounts
767  * of secure memory.  The problem is, that if only one element is secure, all
768  * other elements are automagicaly copied to secure meory too, so the most
769  * common operation gcry_sexp_cdr_mpi() will always return a secure MPI
770  * regardless whether it is needed or not.
771  */
772 static int
773 sexp_sscan( GCRY_SEXP *retsexp, size_t *erroff ,
774             const char *buffer, size_t length, va_list arg_ptr, int argflag )
775 {
776     static const char tokenchars[] = "abcdefghijklmnopqrstuvwxyz"
777                                      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
778                                      "0123456789-./_:*+=";
779     const char *p;
780     size_t n;
781     const char *digptr=NULL;
782     const char *quoted=NULL;
783     const char *tokenp=NULL;
784     const char *hexfmt=NULL;
785     const char *base64=NULL;
786     const char *disphint=NULL;
787     const char *percent=NULL;
788     int hexcount=0;
789     int quoted_esc=0;
790     int datalen=0;
791     size_t dummy_erroff;
792
793     struct make_space_ctx c;
794
795     if( !erroff )
796         erroff = &dummy_erroff;
797
798     /* FIXME: replace all the returns by a jump to the leave label
799      * and invent better error codes. Make sure that everything is cleaned up*/
800   #define MAKE_SPACE(n)  do { make_space ( &c, (n) ); } while (0)
801   #define STORE_LEN(p,n) do {                                              \
802                             DATALEN ashort = (n);                          \
803                             memcpy ( (p), &ashort, sizeof(ashort) );       \
804                             (p) += sizeof (ashort);                        \
805                         } while (0)
806
807     /* We assume that the internal representation takes less memory
808      * than the provided one.  However, we add space for one extra datalen
809      * so that the code which does the ST_CLOSE can use MAKE_SPACE */
810     c.allocated = length + sizeof(DATALEN);
811     c.sexp = gcry_xmalloc ( sizeof *c.sexp + c.allocated - 1 );
812     c.pos = c.sexp->d;
813
814     for(p=buffer,n=length; n; p++, n-- ) {
815         if( tokenp && !hexfmt ) {
816             if( strchr( tokenchars, *p ) )
817                 continue;
818             datalen = p - tokenp;
819             MAKE_SPACE ( datalen );
820             *c.pos++ = ST_DATA;
821             STORE_LEN ( c.pos, datalen );
822             memcpy ( c.pos, tokenp, datalen );
823             c.pos += datalen;
824             tokenp = NULL;
825         }
826         if( quoted ) {
827             if( quoted_esc ) {
828                 switch( *p ) {
829                   case 'b': case 't': case 'v': case 'n': case 'f':
830                   case 'r': case '"': case '\'': case '\\':
831                     quoted_esc = 0;
832                     break;
833                   case '0': case '1': case '2': case '3': case '4':
834                   case '5': case '6': case '7':
835                     if( !(n > 2 && p[1] >= '0' && p[1] <= '7'
836                                 && p[2] >= '0' && p[2] <= '7') ) {
837                         *erroff = p - buffer;
838                         return -6;   /* invalid octal value */
839                     }
840                     p += 2; n -= 2;
841                     quoted_esc = 0;
842                     break;
843                   case 'x':
844                     if( !(n > 2 && isxdigit(p[1]) && isxdigit(p[2]) ) ) {
845                         *erroff = p - buffer;
846                         return -6;   /* invalid hex value */
847                     }
848                     p += 2; n -= 2;
849                     quoted_esc = 0;
850                     break;
851                   case '\r':  /* ignore CR[,LF] */
852                     if( n && p[1] == '\n' ) {
853                         p++; n--;
854                     }
855                     quoted_esc = 0;
856                     break;
857                   case '\n':  /* ignore LF[,CR] */
858                     if( n && p[1] == '\r' ) {
859                         p++; n--;
860                     }
861                     quoted_esc = 0;
862                     break;
863                   default:
864                     *erroff = p - buffer;
865                     return -6;   /* invalid quoted string escape */
866                 }
867             }
868             else if( *p == '\\' )
869                 quoted_esc = 1;
870             else if( *p == '\"' ) {
871                 /* keep it easy - we know that the unquoted string will
872                    never be larger */
873                 char *save;
874                 size_t len;
875                 
876                 quoted++; /* skip leading quote */
877                 MAKE_SPACE (p - quoted);
878                 *c.pos++ = ST_DATA;
879                 save = c.pos;
880                 STORE_LEN (c.pos, 0); /* will be fixed up later */
881                 len = unquote_string (quoted, p - quoted, c.pos);
882                 c.pos += len;
883                 STORE_LEN (save, len);
884                 quoted = NULL;
885             }
886         }
887         else if( hexfmt ) {
888             if( isxdigit( *p ) )
889                 hexcount++;
890             else if( *p == '#' ) {
891                 if( (hexcount & 1) ) {
892                     *erroff = p - buffer;
893                     return -12;  /* odd number of hex digits */
894                 }
895
896                 datalen = hexcount/2;
897                 MAKE_SPACE (datalen);
898                 *c.pos++ = ST_DATA;
899                 STORE_LEN (c.pos, datalen);
900                 for( hexfmt++; hexfmt < p; hexfmt++ ) {
901                     if( isspace( *hexfmt ) )
902                         continue;
903                     *c.pos++ = hextobyte( hexfmt );
904                     hexfmt++;
905                 }
906                 hexfmt = NULL;
907             }
908             else if( !isspace( *p ) ) {
909                 *erroff = p - buffer;
910                 return -11;  /* invalid hex character */
911             }
912         }
913         else if( base64 ) {
914             if( *p == '|' )
915                base64 = NULL;
916         }
917         else if( digptr ) {
918             if( isdigit(*p) )
919                 ;
920             else if( *p == ':' ) {
921                 datalen = atoi( digptr ); /* fixme: check for overflow */
922                 digptr = NULL;
923                 if( datalen > n-1 ) {
924                     *erroff = p - buffer;
925                     return -2; /* buffer too short */
926                 }
927                 /* make a new list entry */
928                 MAKE_SPACE (datalen);
929                 *c.pos++ = ST_DATA;
930                 STORE_LEN (c.pos, datalen);
931                 memcpy (c.pos, p+1, datalen );
932                 c.pos += datalen;
933                 n -= datalen;
934                 p += datalen;
935             }
936             else if( *p == '\"' ) {
937                 digptr = NULL; /* we ignore the optional length */
938                 quoted = p;
939                 quoted_esc = 0;
940             }
941             else if( *p == '#' ) {
942                 digptr = NULL; /* we ignore the optional length */
943                 hexfmt = p;
944                 hexcount = 0;
945             }
946             else if( *p == '|' ) {
947                 digptr = NULL; /* we ignore the optional length */
948                 base64 = p;
949             }
950             else {
951                 *erroff = p - buffer;
952                 return -1;
953             }
954         }
955         else if ( percent ) {
956             if ( *p == 'm' ) { /* insert an MPI */
957                 GCRY_MPI m = va_arg (arg_ptr, GCRY_MPI);
958                 size_t nm;
959
960                 if ( gcry_mpi_print( GCRYMPI_FMT_STD, NULL, &nm, m ) )
961                     BUG ();
962
963                 MAKE_SPACE (nm);
964                 if ( !gcry_is_secure ( c.sexp->d )
965                      &&  gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE ) ) {
966                     /* we have to switch to secure allocation */
967                     GCRY_SEXP newsexp;
968                     byte *newhead;
969
970                     newsexp = gcry_xmalloc_secure ( sizeof *newsexp
971                                                    + c.allocated - 1 );
972                     newhead = newsexp->d;
973                     memcpy ( newhead, c.sexp->d, (c.pos - c.sexp->d) );
974                     c.pos = newhead + ( c.pos - c.sexp->d );
975                     gcry_free ( c.sexp );
976                     c.sexp = newsexp;
977                 }
978
979                 *c.pos++ = ST_DATA;
980                 STORE_LEN (c.pos, nm);
981                 if ( gcry_mpi_print( GCRYMPI_FMT_STD, c.pos, &nm, m ) )
982                     BUG ();
983                 c.pos += nm;
984             }
985             else if ( *p == 's' ) { /* insert an string */
986                 const char *astr = va_arg (arg_ptr, const char *);
987                 size_t alen = strlen ( astr );
988
989                 MAKE_SPACE (alen);
990                 *c.pos++ = ST_DATA;
991                 STORE_LEN (c.pos, alen);
992                 memcpy ( c.pos, astr, alen );
993                 c.pos += alen;
994             }
995             else if ( *p == 'd' ) { /* insert an integer as string */
996                 int aint = va_arg (arg_ptr, int);
997                 size_t alen;
998                 char buf[20];
999
1000                 sprintf ( buf, "%d", aint );
1001                 alen = strlen ( buf );
1002                 MAKE_SPACE (alen);
1003                 *c.pos++ = ST_DATA;
1004                 STORE_LEN (c.pos, alen);
1005                 memcpy ( c.pos, buf, alen );
1006                 c.pos += alen;
1007             }
1008             else {
1009                 *erroff = p - buffer;
1010                 return -1;  /* invalid format specifier */
1011             }
1012             percent = NULL;
1013         }
1014         else if( *p == '(' ) {
1015             if( disphint ) {
1016                 *erroff = p - buffer;
1017                 return -9; /* open display hint */
1018             }
1019             MAKE_SPACE (0);
1020             *c.pos++ = ST_OPEN;
1021         }
1022         else if( *p == ')' ) { /* walk up */
1023             if( disphint ) {
1024                 *erroff = p - buffer;
1025                 return -9; /* open display hint */
1026             }
1027             MAKE_SPACE (0);
1028             *c.pos++ = ST_CLOSE;
1029         }
1030         else if( *p == '\"' ) {
1031             quoted = p;
1032             quoted_esc = 0;
1033         }
1034         else if( *p == '#' ) {
1035             hexfmt = p;
1036             hexcount = 0;
1037         }
1038         else if( *p == '|' )
1039             base64 = p;
1040         else if( *p == '[' ) {
1041             if( disphint ) {
1042                 *erroff = p - buffer;
1043                 return -8; /* nested display hints */
1044             }
1045             disphint = p;
1046         }
1047         else if( *p == ']' ) {
1048             if( !disphint ) {
1049                 *erroff = p - buffer;
1050                 return -9; /* unmatched display hint close */
1051             }
1052             disphint = NULL;
1053         }
1054         else if( isdigit(*p) ) {
1055             if( *p == '0' ) { /* a length may not begin with zero */
1056                 *erroff = p - buffer;
1057                 return -7;
1058             }
1059             digptr = p;
1060         }
1061         else if( strchr( tokenchars, *p ) )
1062             tokenp = p;
1063         else if( isspace(*p) )
1064             ;
1065         else if( *p == '{' ) {
1066             /* fixme: handle rescanning:
1067              * we can do this by saving our current state
1068              * and start over at p+1 -- Hmmm. At this point here
1069              * we are in a well defined state, so we don't need to save
1070              * it.  Great.
1071              */
1072             *erroff = p - buffer;
1073             return -10; /* unexpected reserved punctuation */
1074         }
1075         else if( strchr( "&\\", *p ) ) { /*reserved punctuation*/
1076             *erroff = p - buffer;
1077             return -10; /* unexpected reserved punctuation */
1078         }
1079         else if( argflag && *p == '%' ) {
1080             percent = p;
1081         }
1082         else { /* bad or unavailable*/
1083             *erroff = p - buffer;
1084             return -5;
1085         }
1086
1087     }
1088     MAKE_SPACE (0);
1089     *c.pos++ = ST_STOP;
1090
1091     *retsexp = normalize ( c.sexp );
1092     return 0;
1093   #undef MAKE_SPACE
1094   #undef STORE_LEN
1095 }
1096
1097 int
1098 gcry_sexp_build( GCRY_SEXP *retsexp, size_t *erroff, const char *format, ... )
1099 {
1100     int rc;
1101     va_list arg_ptr ;
1102
1103     va_start( arg_ptr, format ) ;
1104     rc = sexp_sscan( retsexp, erroff, format, strlen(format), arg_ptr, 1 );
1105     va_end(arg_ptr);
1106
1107     return rc;
1108 }
1109
1110 int
1111 gcry_sexp_sscan( GCRY_SEXP *retsexp, size_t *erroff,
1112                             const char *buffer, size_t length )
1113 {
1114   /* We don't need the va_list because it is controlled by the
1115      following flag, however we have to pass it but can't initialize
1116      it as there is no portable way to do so.  volatile is needed to
1117      suppress the compiler warning */
1118   volatile va_list dummy_arg_ptr;
1119
1120   return sexp_sscan( retsexp, erroff, buffer, length, dummy_arg_ptr, 0 );
1121 }
1122
1123 \f
1124 /* Figure out a suitable encoding for BUFFER of LENGTH.
1125    Returns: 0 = Binary
1126             1 = String possible
1127             2 = Token possible
1128 */
1129 static int
1130 suitable_encoding (const unsigned char *buffer, size_t length)
1131 {
1132   const unsigned char *s;
1133   int maybe_token = 1;
1134
1135   if (!length)
1136     return 1;
1137   
1138   for (s=buffer; length; s++, length--)
1139     {
1140       if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
1141            && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
1142         return 0; /*binary*/
1143       if ( maybe_token
1144            && !alphap (s) && !digitp (s)  && !strchr (TOKEN_SPECIALS, *s))
1145         maybe_token = 0;
1146     }
1147   s = buffer;
1148   if ( maybe_token && !digitp (s) )
1149     return 2;
1150   return 1;
1151 }
1152
1153
1154 static int
1155 convert_to_hex (const unsigned char *src, size_t len, unsigned char *dest)
1156 {
1157   int i;
1158
1159   if (dest)
1160     {
1161       *dest++ = '#';
1162       for (i=0; i < len; i++, dest += 2 )
1163         sprintf (dest, "%02X", src[i]);
1164       *dest++ = '#';
1165     }
1166   return len*2+2;
1167 }
1168
1169 static int
1170 convert_to_string (const unsigned char *s, size_t len, unsigned char *dest)
1171 {
1172   if (dest)
1173     {
1174       unsigned char *p = dest;
1175       *p++ = '\"';
1176       for (; len; len--, s++ )
1177         {
1178           switch (*s)
1179             {
1180             case '\b': *p++ = '\\'; *p++ = 'b';  break;
1181             case '\t': *p++ = '\\'; *p++ = 't';  break;
1182             case '\v': *p++ = '\\'; *p++ = 'v';  break;
1183             case '\n': *p++ = '\\'; *p++ = 'n';  break;
1184             case '\f': *p++ = '\\'; *p++ = 'f';  break;
1185             case '\r': *p++ = '\\'; *p++ = 'r';  break;
1186             case '\"': *p++ = '\\'; *p++ = '\"';  break;
1187             case '\'': *p++ = '\\'; *p++ = '\'';  break;
1188             case '\\': *p++ = '\\'; *p++ = '\\';  break;
1189             default: 
1190               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1191                 {
1192                   sprintf (p, "\\x%02x", *s); 
1193                   p += 4;
1194                 }
1195               else
1196                 *p++ = *s;
1197             }
1198         }
1199       *p++ = '\"';
1200       return p - dest;
1201     }
1202   else
1203     {
1204       int count = 2;
1205       for (; len; len--, s++ )
1206         {
1207           switch (*s)
1208             {
1209             case '\b': 
1210             case '\t': 
1211             case '\v': 
1212             case '\n': 
1213             case '\f': 
1214             case '\r': 
1215             case '\"':
1216             case '\'':
1217             case '\\': count += 2; break;
1218             default: 
1219               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1220                 count += 4;
1221               else
1222                 count++;
1223             }
1224         }
1225       return count;
1226     }
1227 }
1228
1229
1230
1231 static int
1232 convert_to_token (const unsigned char *src, size_t len, unsigned char *dest)
1233 {
1234   if (dest)
1235     memcpy (dest, src, len);
1236   return len;
1237 }
1238
1239
1240 /****************
1241  * Print SEXP to buffer using the MODE.  Returns the length of the
1242  * SEXP in buffer or 0 if the buffer is too short (We have at least an
1243  * empty list consisting of 2 bytes).  If a buffer of NULL is provided,
1244  * the required length is returned.
1245  */
1246 size_t
1247 gcry_sexp_sprint( const GCRY_SEXP list, int mode,
1248                                         char *buffer, size_t maxlength )
1249 {
1250   static byte empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
1251   const byte *s;
1252   char *d;
1253   DATALEN n;
1254   char numbuf[20];
1255   size_t len = 0;
1256   int i, indent = 0;
1257   
1258   s = list? list->d : empty;
1259   d = buffer;
1260   while ( *s != ST_STOP )
1261     {
1262       switch ( *s )
1263         {
1264         case ST_OPEN:
1265           s++;
1266           if ( mode != GCRYSEXP_FMT_CANON )
1267             {
1268               if (indent)
1269                 len++; 
1270               len += indent;
1271             }
1272           len++;
1273           if ( buffer ) 
1274             {
1275               if ( len >= maxlength )
1276                 return 0;
1277               if ( mode != GCRYSEXP_FMT_CANON )
1278                 {
1279                   if (indent)
1280                     *d++ = '\n'; 
1281                   for (i=0; i < indent; i++)
1282                     *d++ = ' ';
1283                 }
1284               *d++ = '(';
1285             }
1286           indent++;
1287           break;
1288         case ST_CLOSE:
1289           s++;
1290           len++;
1291           if ( buffer ) 
1292             {
1293               if ( len >= maxlength )
1294                 return 0;
1295               *d++ = ')';
1296             }
1297           indent--;
1298           if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
1299             {
1300               len++;
1301               len += indent;
1302               if (buffer)
1303                 {
1304                   if (len >= maxlength)
1305                     return 0;
1306                   *d++ = '\n';
1307                   for (i=0; i < indent; i++)
1308                     *d++ = ' ';
1309                 }
1310             }
1311           break;
1312         case ST_DATA:
1313           s++;
1314           memcpy ( &n, s, sizeof n ); s += sizeof n;
1315           if (mode == GCRYSEXP_FMT_ADVANCED)
1316             {
1317               int type;
1318               size_t nn;
1319
1320               switch ( (type=suitable_encoding (s, n)))
1321                 {
1322                 case 1: nn = convert_to_string (s, n, NULL); break;
1323                 case 2: nn = convert_to_token (s, n, NULL); break;
1324                 default: nn = convert_to_hex (s, n, NULL); break;
1325                 }
1326               len += nn;
1327               if (buffer)
1328                 {
1329                   if (len >= maxlength)
1330                     return 0;
1331                   switch (type)
1332                     {
1333                     case 1: convert_to_string (s, n, d); break;
1334                     case 2: convert_to_token (s, n, d); break;
1335                     default: convert_to_hex (s, n, d); break;
1336                     }
1337                   d += nn;
1338                 }
1339               if (s[n] != ST_CLOSE)
1340                 {
1341                   len++;
1342                   if (buffer)
1343                     {
1344                       if (len >= maxlength)
1345                         return 0;
1346                       *d++ = ' ';
1347                     }
1348                 }
1349             }
1350           else
1351             {
1352               sprintf (numbuf, "%u:", (unsigned int)n );
1353               len += strlen (numbuf) + n;
1354               if ( buffer ) 
1355                 {
1356                   if ( len >= maxlength )
1357                     return 0;
1358                   d = stpcpy ( d, numbuf );
1359                   memcpy ( d, s, n ); d += n;
1360                 }
1361             }
1362           s += n;
1363           break;
1364         default:
1365           BUG ();
1366         }
1367     }
1368   if ( mode != GCRYSEXP_FMT_CANON )
1369     {
1370       len++;
1371       if (buffer)
1372         {
1373           if ( len >= maxlength )
1374             return 0;
1375           *d++ = '\n'; 
1376         }
1377     }
1378   if (buffer) 
1379     {
1380       if ( len >= maxlength )
1381         return 0;
1382       *d++ = 0; /* for convenience we make a C string */
1383     }
1384   else
1385     len++; /* we need one byte more for this */
1386
1387   return len;
1388 }
1389
1390
1391
1392
1393 /* Scan a cannocial encoded buffer with implicit length values and
1394    return the actual length this S-expression uses.  For a valid S-Exp
1395    it should never return 0.  If LENGTH is not zero, the maximum
1396    length to scan is given - this can be used for syntax checks of
1397    data passed from outside. erroce and erroff may both be passed as
1398    NULL
1399
1400    Errorcodes (for historic reasons they are all negative):
1401     -1 := invalid length specification
1402     -2 := string too long 
1403     -3 := unmatched parenthesis
1404     -4 := not a (canonical) S-expression
1405     -5 := bad character 
1406     -6 := invalid hex octal value or bad quotation
1407     -7 := a length may not begin with zero 
1408     -8 := nested display hints 
1409     -9 := unmatched display hint close
1410    -10 := unexpected reserved punctuation 
1411  */
1412 size_t
1413 gcry_sexp_canon_len (const unsigned char *buffer, size_t length, 
1414                      size_t *erroff, int *errcode)
1415 {
1416   const unsigned char *p;
1417   const char *disphint=NULL;
1418   unsigned int datalen = 0;
1419   size_t dummy_erroff;
1420   int    dummy_errcode;
1421   size_t count = 0;
1422   int level = 0;
1423
1424   if (!erroff)
1425     erroff = &dummy_erroff;
1426   if (!errcode)
1427     errcode = &dummy_errcode;
1428
1429   *errcode = 0;
1430   *erroff = 0;
1431   if (!buffer)
1432     return 0;
1433   if (*buffer != '(')
1434     {
1435       *errcode = -4; /* not a canonical S-expression */
1436       return 0;
1437     }
1438
1439   for (p=buffer; ; p++, count++ )
1440     {
1441       if (length && count >= length)
1442         {
1443           *erroff = count;
1444           *errcode = -2; /* string too long */
1445           return 0;
1446         }
1447       
1448       if (datalen)
1449         {
1450           if (*p == ':')
1451             {
1452               if (length && (count+datalen) >= length)
1453                 {
1454                   *erroff = count;
1455                   *errcode = -2; /* string too long */
1456                   return 0;
1457                 }
1458               count += datalen;
1459               p += datalen;
1460               datalen = 0;
1461             }
1462           else if (digitp(p))
1463             datalen = datalen*10 + atoi_1(p);
1464           else 
1465             {
1466               *erroff = count;
1467               *errcode = -1;
1468               return 0;
1469             }
1470         }
1471       else if (*p == '(')
1472         {
1473           if (disphint)
1474             {
1475               *erroff = count;
1476               *errcode = -9; /* open display hint */
1477               return 0;
1478             }
1479           level++;
1480         }
1481       else if (*p == ')')
1482         { /* walk up */
1483           if (!level)
1484             {
1485               *erroff = count;
1486               *errcode = -3; /* unmatched parenthesis */
1487               return 0;
1488             }
1489           if (disphint)
1490             {
1491               *erroff = count;
1492               *errcode = -9; /* open display hint */
1493               return 0;
1494             }
1495           if (!--level)
1496             return ++count; /* ready */
1497         }
1498       else if (*p == '[')
1499         {
1500           if (disphint) 
1501             {
1502               *erroff = count;
1503               *errcode = -8; /* nested display hints */
1504               return 0;
1505             }
1506           disphint = p;
1507         }
1508       else if (*p == ']')
1509         {
1510           if( !disphint ) 
1511             {
1512               *erroff = count;
1513               *errcode = -9; /* unmatched display hint close */
1514               return 0;
1515             }
1516           disphint = NULL;
1517         }
1518       else if (digitp (p) )
1519         {
1520           if (*p == '0')
1521             { 
1522               *erroff = count;
1523               *errcode = -7; /* a length may not begin with zero */
1524               return 0;
1525             }
1526           datalen = atoi_1 (p);
1527         }
1528       else if (*p == '&' || *p == '\\')
1529         {
1530           *erroff = count;
1531           *errcode = -10; /* unexpected reserved punctuation */
1532           return 0;
1533         }
1534       else
1535         { 
1536           *erroff = count;
1537           *errcode = -5; /* bad character */
1538           return 0;
1539         }
1540     }
1541 }
1542
1543