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