195b84aec835b0a686f494631ba5e925b6d910a1
[libgcrypt.git] / tests / tsexp.c
1 /* tsexp.c  -  S-expression regression tests
2  *      Copyright (C) 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 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include "../src/gcrypt.h"
26
27 #define PGMNAME "tsexp"
28
29 static int verbose;
30 static int error_count;
31
32 static void
33 info (const char *format, ...)
34 {
35   va_list arg_ptr;
36
37   if (verbose)
38     {
39       va_start( arg_ptr, format ) ;
40       vfprintf (stderr, format, arg_ptr );
41       va_end(arg_ptr);
42     }
43 }
44
45 static void
46 fail ( const char *format, ... )
47 {
48     va_list arg_ptr ;
49
50     fputs (PGMNAME ": ", stderr);
51     va_start( arg_ptr, format ) ;
52     vfprintf (stderr, format, arg_ptr );
53     va_end(arg_ptr);
54     error_count++;
55 }
56
57
58 /* fixme: we need better tests */
59 static void
60 basic (void)
61 {
62   int pass;
63   gcry_sexp_t sexp;
64   int idx;
65   char *secure_buffer;
66   size_t secure_buffer_len;
67   const char *string;
68   static struct {
69     const char *token;
70     const char *parm;
71   } values[] = {
72     { "public-key", NULL },
73     { "dsa", NULL },
74     { "dsa", "p" },
75     { "dsa", "y" },
76     { "dsa", "q" },
77     { "dsa", "g" },
78     { NULL }
79   };
80
81   info ("doing some pretty pointless tests\n"); 
82
83   secure_buffer_len = 99;
84   secure_buffer = gcry_xmalloc_secure (secure_buffer_len);
85   memset (secure_buffer, 'G', secure_buffer_len);
86
87   for (pass=0;;pass++)
88     {
89       switch (pass)
90         {
91         case 0:
92           string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
93                     "(q #61626364656667#) (g %m)))");
94           
95           if ( gcry_sexp_build (&sexp, NULL, string,
96                                 gcry_mpi_set_ui (NULL, 42)) )
97             {
98               fail (" scanning `%s' failed\n", string);
99               return;
100             }
101           break;
102           
103         case 1:
104           string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
105                     "(q %b) (g %m)))");
106       
107           if ( gcry_sexp_build (&sexp, NULL, string, 
108                                 15, "foo\0\x01\0x02789012345",
109                                 gcry_mpi_set_ui (NULL, 42)) )
110             {
111               fail (" scanning `%s' failed\n", string);
112               return;
113             }
114           break;
115
116         case 2:
117           string = ("(public-key (dsa (p #41424344#) (y silly_y_value) "
118                     "(q %b) (g %m)))");
119       
120           if ( gcry_sexp_build (&sexp, NULL, string, 
121                                 secure_buffer_len, secure_buffer,
122                                 gcry_mpi_set_ui (NULL, 17)) )
123             {
124               fail (" scanning `%s' failed\n", string);
125               return;
126             }
127           if (!gcry_is_secure (sexp))
128             fail ("gcry_sexp_build did not switch to secure memory\n");
129           break;
130           
131         default:
132           return; /* Ready. */
133         }
134
135
136       /* now find something */
137       for (idx=0; values[idx].token; idx++)
138         {
139           const char *token = values[idx].token;
140           const char *parm = values[idx].parm;
141           gcry_sexp_t s1, s2;
142           gcry_mpi_t a;
143           const char *p;
144           size_t n;
145
146           s1 = gcry_sexp_find_token (sexp, token, strlen(token) );
147           if (!s1)
148             {
149               fail ("didn't found `%s'\n", token);
150               continue;
151             }
152
153           p = gcry_sexp_nth_data (s1, 0, &n);
154           if (!p)
155             {
156               fail ("no car for `%s'\n", token);
157               continue;
158             }
159           info ("car=`%.*s'\n", (int)n, p);
160
161           s2 = gcry_sexp_cdr (s1);
162           if (!s2) 
163             {
164               fail ("no cdr for `%s'\n", token);
165               continue;
166             }
167
168           p = gcry_sexp_nth_data (s2, 0, &n);
169           if (p)
170             {
171               fail ("data at car of `%s'\n", token);
172               continue;
173             }
174
175           if (parm)
176             {
177               s2 = gcry_sexp_find_token (s1, parm, strlen (parm));
178               if (!s2)
179                 {
180                   fail ("didn't found `%s'\n", parm);
181                   continue;
182                 }
183               p = gcry_sexp_nth_data (s2, 0, &n);
184               if (!p) 
185                 {
186                   fail("no car for `%s'\n", parm );
187                   continue;
188                 }
189               info ("car=`%.*s'\n", (int)n, p);
190               p = gcry_sexp_nth_data (s2, 1, &n);
191               if (!p) 
192                 {
193                   fail("no cdr for `%s'\n", parm );
194                   continue;
195                 }
196               info ("cdr=`%.*s'\n", (int)n, p);
197           
198               a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG);
199               if (!a)
200                 {
201                   fail("failed to cdr the mpi for `%s'\n", parm);
202                   continue;
203                 }
204             }
205         }
206      
207       gcry_sexp_release (sexp);
208       sexp = NULL;
209     }
210   gcry_free (secure_buffer);
211 }
212
213
214 static void
215 canon_len (void)
216 {
217   static struct {
218     size_t textlen; /* length of the buffer */
219     size_t expected;/* expected length or 0 on error and then ... */
220     size_t erroff;  /* ... and at this offset */
221     gcry_error_t errcode;    /* ... with this error code */
222     unsigned char *text; 
223   } values[] = {
224     { 14, 13, 0, GPG_ERR_NO_ERROR, "(9:abcdefghi) " },
225     { 16, 15, 0, GPG_ERR_NO_ERROR, "(10:abcdefghix)" },
226     { 14,  0,14, GPG_ERR_SEXP_STRING_TOO_LONG, "(10:abcdefghi)" },
227     { 15,  0, 1, GPG_ERR_SEXP_ZERO_PREFIX, "(010:abcdefghi)" },
228     {  2,  0, 0, GPG_ERR_SEXP_NOT_CANONICAL, "1:"},
229     {  4,  0, 4, GPG_ERR_SEXP_STRING_TOO_LONG, "(1:)"},
230     {  5,  5, 0, GPG_ERR_NO_ERROR, "(1:x)"},
231     {  2,  2, 0, GPG_ERR_NO_ERROR, "()"},
232     {  4,  2, 0, GPG_ERR_NO_ERROR, "()()"},
233     {  4,  4, 0, GPG_ERR_NO_ERROR, "(())"},
234     {  3,  0, 3, GPG_ERR_SEXP_STRING_TOO_LONG, "(()"},
235     {  3,  0, 1, GPG_ERR_SEXP_BAD_CHARACTER, "( )"},
236     {  9,  9, 0, GPG_ERR_NO_ERROR, "(3:abc())"},
237     { 10,  0, 6, GPG_ERR_SEXP_BAD_CHARACTER, "(3:abc ())"},
238     /* fixme: we need much more cases */
239     { 0 },
240   };
241   int idx;
242   gcry_error_t errcode;
243   size_t n, erroff;
244
245   info ("checking canoncial length test function\n");
246   for (idx=0; values[idx].text; idx++)
247     {
248       n = gcry_sexp_canon_len (values[idx].text, values[idx].textlen, 
249                                &erroff, &errcode);
250       
251       if (n && n == values[idx].expected)
252         ; /* success */
253       else if (!n && !values[idx].expected)
254         { /* we expected an error - check that this is the right one */
255           if (values[idx].erroff != erroff)
256             fail ("canonical length test %d - wrong error offset %u\n",
257                   idx, (unsigned int)erroff);
258           if (gcry_err_code (errcode) != values[idx].errcode)
259             fail ("canonical length test %d - wrong error code %d\n",
260                   idx, errcode);
261         }
262       else
263         fail ("canonical length test %d failed - n=%u, off=%u, err=%d\n",
264               idx, (unsigned int)n, (unsigned int)erroff, errcode);
265     }
266 }
267
268
269 static void
270 back_and_forth_one (int testno, const char *buffer, size_t length)
271 {
272   gcry_error_t rc;
273   gcry_sexp_t se, se1;
274   size_t n, n1;
275   char *p1;
276
277   rc = gcry_sexp_new (&se, buffer, length, 1);
278   if (rc)
279     {
280       fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc));
281       return;
282     }
283   n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0);
284   if (!n1)
285     {
286       fail ("baf %d: get required length for canon failed\n", testno);
287       return;
288     }
289   p1 = gcry_xmalloc (n1);
290   n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
291   if (n1 != n+1) /* sprints adds an extra 0 but dies not return it */
292     {
293       fail ("baf %d: length mismatch for canon\n", testno);
294       return;
295     }
296   rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
297   if (rc)
298     {
299       fail ("baf %d: gcry_sexp_create failed: %s\n",
300             testno, gpg_strerror (rc));
301       return;
302     }
303   gcry_sexp_release (se1);
304   
305   /* FIXME: we need a lot more tests */
306
307   gcry_sexp_release (se);
308 }
309
310
311
312 static void
313 back_and_forth (void)
314 {
315   static struct { char *buf; int len; } tests[] = {
316     { "(7:g34:fgh1::2:())", 0 },
317     { "(7:g34:fgh1::2:())", 18 },
318     { NULL, 0 }
319   };
320   int idx;
321
322   for (idx=0; tests[idx].buf; idx++)
323     back_and_forth_one (idx, tests[idx].buf, tests[idx].len);
324 }
325
326
327 static void
328 check_sscan (void)
329 {
330   static struct {
331     const char *text;
332     gcry_error_t expected_err;  
333   } values[] = {
334     /* Bug reported by Olivier L'Heureux 2003-10-07 */
335     { "(7:sig-val(3:dsa"
336       "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
337       "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
338       "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
339       "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e)))",
340       GPG_ERR_NO_ERROR },
341     { "(7:sig-val(3:dsa"
342       "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
343       "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
344       "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
345       "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))",
346       GPG_ERR_SEXP_UNMATCHED_PAREN },
347     { "(7:sig-val(3:dsa"
348       "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
349       "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
350       "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
351       "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))))",
352       GPG_ERR_SEXP_UNMATCHED_PAREN },
353     { NULL, 0 }
354   };
355   int idx;
356   gcry_error_t err;
357   gcry_sexp_t s;
358
359   info ("checking gcry_sexp_sscan\n");
360   for (idx=0; values[idx].text; idx++)
361     {
362       err = gcry_sexp_sscan (&s, NULL,
363                              values[idx].text,
364                              strlen (values[idx].text));
365       if (gpg_err_code (err) != values[idx].expected_err)
366         fail ("gcry_sexp_sscan test %d failed: %s\n", idx, gpg_strerror (err));
367       gcry_sexp_release (s);
368     }
369 }
370
371
372
373
374 int
375 main (int argc, char **argv)
376 {
377   if (argc > 1 && !strcmp (argv[1], "-v"))
378     verbose = 1;
379
380   gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
381   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
382
383   basic ();
384   canon_len ();
385   back_and_forth ();
386   check_sscan ();
387   
388   return error_count? 1:0;
389 }
390
391
392
393
394
395