* sexp.c (suitable_encoding,convert_to_hex,convert_to_string)
[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 General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (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 General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * 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     va_list dummy_arg_ptr = 0;
1115
1116     return sexp_sscan( retsexp, erroff, buffer, length, dummy_arg_ptr, 0 );
1117 }
1118
1119 \f
1120 /* Figure out a suitable encoding for BUFFER of LENGTH.
1121    Returns: 0 = Binary
1122             1 = String possible
1123             2 = Token possible
1124 */
1125 static int
1126 suitable_encoding (const unsigned char *buffer, size_t length)
1127 {
1128   const unsigned char *s;
1129   int maybe_token = 1;
1130
1131   if (!length)
1132     return 1;
1133   
1134   for (s=buffer; length; s++, length--)
1135     {
1136       if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
1137            && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
1138         return 0; /*binary*/
1139       if ( maybe_token
1140            && !alphap (s) && !digitp (s)  && !strchr (TOKEN_SPECIALS, *s))
1141         maybe_token = 0;
1142     }
1143   s = buffer;
1144   if ( maybe_token && !digitp (s) )
1145     return 2;
1146   return 1;
1147 }
1148
1149
1150 static int
1151 convert_to_hex (const unsigned char *src, size_t len, unsigned char *dest)
1152 {
1153   int i;
1154
1155   if (dest)
1156     {
1157       *dest++ = '#';
1158       for (i=0; i < len; i++, dest += 2 )
1159         sprintf (dest, "%02X", src[i]);
1160       *dest++ = '#';
1161     }
1162   return len*2+2;
1163 }
1164
1165 static int
1166 convert_to_string (const unsigned char *s, size_t len, unsigned char *dest)
1167 {
1168   if (dest)
1169     {
1170       unsigned char *p = dest;
1171       *p++ = '\"';
1172       for (; len; len--, s++ )
1173         {
1174           switch (*s)
1175             {
1176             case '\b': *p++ = '\\'; *p++ = 'b';  break;
1177             case '\t': *p++ = '\\'; *p++ = 't';  break;
1178             case '\v': *p++ = '\\'; *p++ = 'v';  break;
1179             case '\n': *p++ = '\\'; *p++ = 'n';  break;
1180             case '\f': *p++ = '\\'; *p++ = 'f';  break;
1181             case '\r': *p++ = '\\'; *p++ = 'r';  break;
1182             case '\"': *p++ = '\\'; *p++ = '\"';  break;
1183             case '\'': *p++ = '\\'; *p++ = '\'';  break;
1184             case '\\': *p++ = '\\'; *p++ = '\\';  break;
1185             default: 
1186               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1187                 {
1188                   sprintf (p, "\\x%02x", *s); 
1189                   p += 4;
1190                 }
1191               else
1192                 *p++ = *s;
1193             }
1194         }
1195       *p++ = '\"';
1196       return p - dest;
1197     }
1198   else
1199     {
1200       int count = 2;
1201       for (; len; len--, s++ )
1202         {
1203           switch (*s)
1204             {
1205             case '\b': 
1206             case '\t': 
1207             case '\v': 
1208             case '\n': 
1209             case '\f': 
1210             case '\r': 
1211             case '\"':
1212             case '\'':
1213             case '\\': count += 2; break;
1214             default: 
1215               if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
1216                 count += 4;
1217               else
1218                 count++;
1219             }
1220         }
1221       return count;
1222     }
1223 }
1224
1225
1226
1227 static int
1228 convert_to_token (const unsigned char *src, size_t len, unsigned char *dest)
1229 {
1230   if (dest)
1231     memcpy (dest, src, len);
1232   return len;
1233 }
1234
1235
1236 /****************
1237  * Print SEXP to buffer using the MODE.  Returns the length of the
1238  * SEXP in buffer or 0 if the buffer is too short (We have at least an
1239  * empty list consisting of 2 bytes).  If a buffer of NULL is provided,
1240  * the required length is returned.
1241  */
1242 size_t
1243 gcry_sexp_sprint( const GCRY_SEXP list, int mode,
1244                                         char *buffer, size_t maxlength )
1245 {
1246   static byte empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
1247   const byte *s;
1248   char *d;
1249   DATALEN n;
1250   char numbuf[20];
1251   size_t len = 0;
1252   int i, indent = 0;
1253   
1254   s = list? list->d : empty;
1255   d = buffer;
1256   while ( *s != ST_STOP )
1257     {
1258       switch ( *s )
1259         {
1260         case ST_OPEN:
1261           s++;
1262           if ( mode != GCRYSEXP_FMT_CANON )
1263             {
1264               if (indent)
1265                 len++; 
1266               len += indent;
1267             }
1268           len++;
1269           if ( buffer ) 
1270             {
1271               if ( len >= maxlength )
1272                 return 0;
1273               if ( mode != GCRYSEXP_FMT_CANON )
1274                 {
1275                   if (indent)
1276                     *d++ = '\n'; 
1277                   for (i=0; i < indent; i++)
1278                     *d++ = ' ';
1279                 }
1280               *d++ = '(';
1281             }
1282           indent++;
1283           break;
1284         case ST_CLOSE:
1285           s++;
1286           len++;
1287           if ( buffer ) 
1288             {
1289               if ( len >= maxlength )
1290                 return 0;
1291               *d++ = ')';
1292             }
1293           indent--;
1294           if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
1295             {
1296               len++;
1297               len += indent;
1298               if (buffer)
1299                 {
1300                   if (len >= maxlength)
1301                     return 0;
1302                   *d++ = '\n';
1303                   for (i=0; i < indent; i++)
1304                     *d++ = ' ';
1305                 }
1306             }
1307           break;
1308         case ST_DATA:
1309           s++;
1310           memcpy ( &n, s, sizeof n ); s += sizeof n;
1311           if (mode == GCRYSEXP_FMT_ADVANCED)
1312             {
1313               int type;
1314               size_t nn;
1315
1316               switch ( (type=suitable_encoding (s, n)))
1317                 {
1318                 case 1: nn = convert_to_string (s, n, NULL); break;
1319                 case 2: nn = convert_to_token (s, n, NULL); break;
1320                 default: nn = convert_to_hex (s, n, NULL); break;
1321                 }
1322               len += nn;
1323               if (buffer)
1324                 {
1325                   if (len >= maxlength)
1326                     return 0;
1327                   switch (type)
1328                     {
1329                     case 1: convert_to_string (s, n, d); break;
1330                     case 2: convert_to_token (s, n, d); break;
1331                     default: convert_to_hex (s, n, d); break;
1332                     }
1333                   d += nn;
1334                 }
1335               if (s[n] != ST_CLOSE)
1336                 {
1337                   len++;
1338                   if (buffer)
1339                     {
1340                       if (len >= maxlength)
1341                         return 0;
1342                       *d++ = ' ';
1343                     }
1344                 }
1345             }
1346           else
1347             {
1348               sprintf (numbuf, "%u:", (unsigned int)n );
1349               len += strlen (numbuf) + n;
1350               if ( buffer ) 
1351                 {
1352                   if ( len >= maxlength )
1353                     return 0;
1354                   d = stpcpy ( d, numbuf );
1355                   memcpy ( d, s, n ); d += n;
1356                 }
1357             }
1358           s += n;
1359           break;
1360         default:
1361           BUG ();
1362         }
1363     }
1364   if ( mode != GCRYSEXP_FMT_CANON )
1365     {
1366       len++;
1367       if (buffer)
1368         {
1369           if ( len >= maxlength )
1370             return 0;
1371           *d++ = '\n'; 
1372         }
1373     }
1374   if (buffer) 
1375     {
1376       if ( len >= maxlength )
1377         return 0;
1378       *d++ = 0; /* for convenience we make a C string */
1379     }
1380   else
1381     len++; /* we need one byte more for this */
1382
1383   return len;
1384 }
1385
1386
1387
1388
1389 /* Scan a cannocial encoded buffer with implicit length values and
1390    return the actual length this S-expression uses.  For a valid S-Exp
1391    it should never return 0.  If LENGTH is not zero, the maximum
1392    length to scan is given - this can be used for syntax checks of
1393    data passed from outside. erroce and erroff may both be passed as
1394    NULL
1395
1396    Errorcodes (for historic reasons they are all negative):
1397     -1 := invalid length specification
1398     -2 := string too long 
1399     -3 := unmatched parenthesis
1400     -4 := not a (canonical) S-expression
1401     -5 := bad character 
1402     -6 := invalid hex octal value or bad quotation
1403     -7 := a length may not begin with zero 
1404     -8 := nested display hints 
1405     -9 := unmatched display hint close
1406    -10 := unexpected reserved punctuation 
1407  */
1408 size_t
1409 gcry_sexp_canon_len (const unsigned char *buffer, size_t length, 
1410                      size_t *erroff, int *errcode)
1411 {
1412   const unsigned char *p;
1413   const char *disphint=NULL;
1414   unsigned int datalen = 0;
1415   size_t dummy_erroff;
1416   int    dummy_errcode;
1417   size_t count = 0;
1418   int level = 0;
1419
1420   if (!erroff)
1421     erroff = &dummy_erroff;
1422   if (!errcode)
1423     errcode = &dummy_errcode;
1424
1425   *errcode = 0;
1426   *erroff = 0;
1427   if (!buffer)
1428     return 0;
1429   if (*buffer != '(')
1430     {
1431       *errcode = -4; /* not a canonical S-expression */
1432       return 0;
1433     }
1434
1435   for (p=buffer; ; p++, count++ )
1436     {
1437       if (length && count >= length)
1438         {
1439           *erroff = count;
1440           *errcode = -2; /* string too long */
1441           return 0;
1442         }
1443       
1444       if (datalen)
1445         {
1446           if (*p == ':')
1447             {
1448               if (length && (count+datalen) >= length)
1449                 {
1450                   *erroff = count;
1451                   *errcode = -2; /* string too long */
1452                   return 0;
1453                 }
1454               count += datalen;
1455               p += datalen;
1456               datalen = 0;
1457             }
1458           else if (digitp(p))
1459             datalen = datalen*10 + atoi_1(p);
1460           else 
1461             {
1462               *erroff = count;
1463               *errcode = -1;
1464               return 0;
1465             }
1466         }
1467       else if (*p == '(')
1468         {
1469           if (disphint)
1470             {
1471               *erroff = count;
1472               *errcode = -9; /* open display hint */
1473               return 0;
1474             }
1475           level++;
1476         }
1477       else if (*p == ')')
1478         { /* walk up */
1479           if (!level)
1480             {
1481               *erroff = count;
1482               *errcode = -3; /* unmatched parenthesis */
1483               return 0;
1484             }
1485           if (disphint)
1486             {
1487               *erroff = count;
1488               *errcode = -9; /* open display hint */
1489               return 0;
1490             }
1491           if (!--level)
1492             return ++count; /* ready */
1493         }
1494       else if (*p == '[')
1495         {
1496           if (disphint) 
1497             {
1498               *erroff = count;
1499               *errcode = -8; /* nested display hints */
1500               return 0;
1501             }
1502           disphint = p;
1503         }
1504       else if (*p == ']')
1505         {
1506           if( !disphint ) 
1507             {
1508               *erroff = count;
1509               *errcode = -9; /* unmatched display hint close */
1510               return 0;
1511             }
1512           disphint = NULL;
1513         }
1514       else if (digitp (p) )
1515         {
1516           if (*p == '0')
1517             { 
1518               *erroff = count;
1519               *errcode = -7; /* a length may not begin with zero */
1520               return 0;
1521             }
1522           datalen = atoi_1 (p);
1523         }
1524       else if (*p == '&' || *p == '\\')
1525         {
1526           *erroff = count;
1527           *errcode = -10; /* unexpected reserved punctuation */
1528           return 0;
1529         }
1530       else
1531         { 
1532           *erroff = count;
1533           *errcode = -5; /* bad character */
1534           return 0;
1535         }
1536     }
1537 }
1538
1539