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