sexp: Fix broken gcry_sexp_nth.
[libgcrypt.git] / tests / t-sexp.c
1 /* t-sexp.c  -  S-expression regression tests
2  * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
3  * Copyright (C) 2014 g10 Code GmbH
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, see <http://www.gnu.org/licenses/>.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <assert.h>
29 #include "../src/gcrypt-int.h"
30
31 #define PGMNAME "t-sexp"
32 #include "t-common.h"
33
34
35 /* Convert STRING consisting of hex characters into its binary
36    representation and return it as an allocated buffer. The valid
37    length of the buffer is returned at R_LENGTH.  The string is
38    delimited by end of string.  The function returns NULL on
39    error.  */
40 static void *
41 hex2buffer (const char *string, size_t *r_length)
42 {
43   const char *s;
44   unsigned char *buffer;
45   size_t length;
46
47   buffer = xmalloc (strlen(string)/2+1);
48   length = 0;
49   for (s=string; *s; s +=2 )
50     {
51       if (!hexdigitp (s) || !hexdigitp (s+1))
52         return NULL;           /* Invalid hex digits. */
53       ((unsigned char*)buffer)[length++] = xtoi_2 (s);
54     }
55   *r_length = length;
56   return buffer;
57 }
58
59
60 static gcry_mpi_t
61 hex2mpi (const char *string)
62 {
63   gpg_error_t err;
64   gcry_mpi_t val;
65
66   err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
67   if (err)
68     die ("hex2mpi '%s' failed: %s\n", string, gpg_strerror (err));
69   return val;
70 }
71
72 static gcry_mpi_t
73 hex2mpiopa (const char *string)
74 {
75   char *buffer;
76   size_t buflen;
77   gcry_mpi_t val;
78
79   buffer = hex2buffer (string, &buflen);
80   if (!buffer)
81     die ("hex2mpiopa '%s' failed: parser error\n", string);
82   val = gcry_mpi_set_opaque (NULL, buffer, buflen*8);
83   if (!buffer)
84     die ("hex2mpiopa '%s' failed: set_opaque error%s\n", string);
85   return val;
86 }
87
88
89 /* Compare A to B, where B is given as a hex string.  */
90 static int
91 cmp_mpihex (gcry_mpi_t a, const char *b)
92 {
93   gcry_mpi_t bval;
94   int res;
95
96   if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
97     bval = hex2mpiopa (b);
98   else
99     bval = hex2mpi (b);
100   res = gcry_mpi_cmp (a, bval);
101   gcry_mpi_release (bval);
102   return res;
103 }
104
105 /* Compare A to B, where A is a buffer and B a hex string.  */
106 static int
107 cmp_bufhex (const void *a, size_t alen, const char *b)
108 {
109   void *bbuf;
110   size_t blen;
111   int res;
112
113   if (!a && !b)
114     return 0;
115   if (a && !b)
116     return 1;
117   if (!a && b)
118     return -1;
119
120   bbuf = hex2buffer (b, &blen);
121   if (!bbuf)
122     die ("cmp_bufhex: error converting hex string\n");
123   if (alen != blen)
124     return alen < blen? -1 : 1;
125   res = memcmp (a, bbuf, alen);
126   xfree (bbuf);
127   return res;
128 }
129
130
131 \f
132 /* fixme: we need better tests */
133 static void
134 basic (void)
135 {
136   int pass;
137   gcry_sexp_t sexp;
138   int idx;
139   char *secure_buffer;
140   size_t secure_buffer_len;
141   const char *string;
142   static struct {
143     const char *token;
144     const char *parm;
145   } values[] = {
146     { "public-key", NULL },
147     { "dsa", NULL },
148     { "dsa", "p" },
149     { "dsa", "y" },
150     { "dsa", "q" },
151     { "dsa", "g" },
152     { NULL }
153   };
154
155   info ("doing some pretty pointless tests\n");
156
157   secure_buffer_len = 99;
158   secure_buffer = gcry_xmalloc_secure (secure_buffer_len);
159   memset (secure_buffer, 'G', secure_buffer_len);
160
161   for (pass=0;;pass++)
162     {
163       gcry_mpi_t m;
164
165       switch (pass)
166         {
167         case 0:
168           string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
169                     "(q #61626364656667#) (g %m)))");
170
171           m = gcry_mpi_set_ui (NULL, 42);
172           if ( gcry_sexp_build (&sexp, NULL, string, m ) )
173             {
174               gcry_mpi_release (m);
175               fail (" scanning `%s' failed\n", string);
176               return;
177             }
178           gcry_mpi_release (m);
179           break;
180
181         case 1:
182           string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
183                     "(q %b) (g %m)))");
184
185           m = gcry_mpi_set_ui (NULL, 42);
186           if ( gcry_sexp_build (&sexp, NULL, string,
187                                 15, "foo\0\x01\0x02789012345", m) )
188             {
189               gcry_mpi_release (m);
190               fail (" scanning `%s' failed\n", string);
191               return;
192             }
193           gcry_mpi_release (m);
194           break;
195
196         case 2:
197           string = ("(public-key (dsa (p #41424344#) (y silly_y_value) "
198                     "(q %b) (g %m)))");
199
200           m = gcry_mpi_set_ui (NULL, 17);
201           if ( gcry_sexp_build (&sexp, NULL, string,
202                                 secure_buffer_len, secure_buffer, m) )
203             {
204               gcry_mpi_release (m);
205               fail (" scanning `%s' failed\n", string);
206               return;
207             }
208           gcry_mpi_release (m);
209           if (!gcry_is_secure (sexp))
210             fail ("gcry_sexp_build did not switch to secure memory\n");
211           break;
212
213         case 3:
214           {
215             gcry_sexp_t help_sexp;
216
217             if (gcry_sexp_new (&help_sexp,
218                                "(foobar-parms (xp #1234#)(xq #03#))", 0, 1))
219               {
220                 fail (" scanning fixed string failed\n");
221                 return;
222               }
223
224             string = ("(public-key (dsa (p #41424344#) (parm %S) "
225                       "(y dummy)(q %b) (g %m)))");
226             m = gcry_mpi_set_ui (NULL, 17);
227             if ( gcry_sexp_build (&sexp, NULL, string, help_sexp,
228                                   secure_buffer_len, secure_buffer, m) )
229               {
230                 gcry_mpi_release (m);
231                 fail (" scanning `%s' failed\n", string);
232                 return;
233               }
234             gcry_mpi_release (m);
235             gcry_sexp_release (help_sexp);
236           }
237           break;
238
239
240         default:
241           return; /* Ready. */
242         }
243
244
245       /* now find something */
246       for (idx=0; values[idx].token; idx++)
247         {
248           const char *token = values[idx].token;
249           const char *parm = values[idx].parm;
250           gcry_sexp_t s1, s2;
251           gcry_mpi_t a;
252           const char *p;
253           size_t n;
254
255           s1 = gcry_sexp_find_token (sexp, token, strlen(token) );
256           if (!s1)
257             {
258               fail ("didn't found `%s'\n", token);
259               continue;
260             }
261
262           p = gcry_sexp_nth_data (s1, 0, &n);
263           if (!p)
264             {
265               gcry_sexp_release (s1);
266               fail ("no car for `%s'\n", token);
267               continue;
268             }
269           /* info ("car=`%.*s'\n", (int)n, p); */
270
271           s2 = gcry_sexp_cdr (s1);
272           if (!s2)
273             {
274               gcry_sexp_release (s1);
275               fail ("no cdr for `%s'\n", token);
276               continue;
277             }
278
279           p = gcry_sexp_nth_data (s2, 0, &n);
280           gcry_sexp_release (s2);
281           if (p)
282             {
283               gcry_sexp_release (s1);
284               fail ("data at car of `%s'\n", token);
285               continue;
286             }
287
288           if (parm)
289             {
290               s2 = gcry_sexp_find_token (s1, parm, strlen (parm));
291               gcry_sexp_release (s1);
292               if (!s2)
293                 {
294                   fail ("didn't found `%s'\n", parm);
295                   continue;
296                 }
297               p = gcry_sexp_nth_data (s2, 0, &n);
298               if (!p)
299                 {
300                   gcry_sexp_release (s2);
301                   fail("no car for `%s'\n", parm );
302                   continue;
303                 }
304               /* info ("car=`%.*s'\n", (int)n, p); */
305               p = gcry_sexp_nth_data (s2, 1, &n);
306               if (!p)
307                 {
308                   gcry_sexp_release (s2);
309                   fail("no cdr for `%s'\n", parm );
310                   continue;
311                 }
312               /* info ("cdr=`%.*s'\n", (int)n, p); */
313
314               a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG);
315               gcry_sexp_release (s2);
316               if (!a)
317                 {
318                   fail("failed to cdr the mpi for `%s'\n", parm);
319                   continue;
320                 }
321               gcry_mpi_release (a);
322             }
323           else
324             gcry_sexp_release (s1);
325         }
326
327       gcry_sexp_release (sexp);
328       sexp = NULL;
329     }
330   gcry_free (secure_buffer);
331 }
332
333
334 static void
335 canon_len (void)
336 {
337   static struct {
338     size_t textlen; /* length of the buffer */
339     size_t expected;/* expected length or 0 on error and then ... */
340     size_t erroff;  /* ... and at this offset */
341     gcry_error_t errcode;    /* ... with this error code */
342     const char *text;
343   } values[] = {
344     { 14, 13, 0, GPG_ERR_NO_ERROR, "(9:abcdefghi) " },
345     { 16, 15, 0, GPG_ERR_NO_ERROR, "(10:abcdefghix)" },
346     { 14,  0,14, GPG_ERR_SEXP_STRING_TOO_LONG, "(10:abcdefghi)" },
347     { 15,  0, 1, GPG_ERR_SEXP_ZERO_PREFIX, "(010:abcdefghi)" },
348     {  2,  0, 0, GPG_ERR_SEXP_NOT_CANONICAL, "1:"},
349     {  4,  0, 4, GPG_ERR_SEXP_STRING_TOO_LONG, "(1:)"},
350     {  5,  5, 0, GPG_ERR_NO_ERROR, "(1:x)"},
351     {  2,  2, 0, GPG_ERR_NO_ERROR, "()"},
352     {  4,  2, 0, GPG_ERR_NO_ERROR, "()()"},
353     {  4,  4, 0, GPG_ERR_NO_ERROR, "(())"},
354     {  3,  0, 3, GPG_ERR_SEXP_STRING_TOO_LONG, "(()"},
355     {  3,  0, 1, GPG_ERR_SEXP_BAD_CHARACTER, "( )"},
356     {  9,  9, 0, GPG_ERR_NO_ERROR, "(3:abc())"},
357     { 10,  0, 6, GPG_ERR_SEXP_BAD_CHARACTER, "(3:abc ())"},
358     /* fixme: we need much more cases */
359     { 0 },
360   };
361   int idx;
362   gcry_error_t errcode;
363   size_t n, erroff;
364
365   info ("checking canoncial length test function\n");
366   for (idx=0; values[idx].text; idx++)
367     {
368       n = gcry_sexp_canon_len ((const unsigned char*)values[idx].text,
369                                values[idx].textlen,
370                                &erroff, &errcode);
371
372       if (n && n == values[idx].expected)
373         ; /* success */
374       else if (!n && !values[idx].expected)
375         { /* we expected an error - check that this is the right one */
376           if (values[idx].erroff != erroff)
377             fail ("canonical length test %d - wrong error offset %u\n",
378                   idx, (unsigned int)erroff);
379           if (gcry_err_code (errcode) != values[idx].errcode)
380             fail ("canonical length test %d - wrong error code %d\n",
381                   idx, errcode);
382         }
383       else
384         fail ("canonical length test %d failed - n=%u, off=%u, err=%d\n",
385               idx, (unsigned int)n, (unsigned int)erroff, errcode);
386     }
387 }
388
389
390 static void
391 back_and_forth_one (int testno, const char *buffer, size_t length)
392 {
393   gcry_error_t rc;
394   gcry_sexp_t se, se1;
395   size_t n, n1;
396   char *p1;
397
398   rc = gcry_sexp_new (&se, buffer, length, 1);
399   if (rc)
400     {
401       fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc));
402       return;
403     }
404   n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0);
405   if (!n1)
406     {
407       fail ("baf %d: get required length for canon failed\n", testno);
408       return;
409     }
410   p1 = gcry_xmalloc (n1);
411   n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
412   if (n1 != n+1) /* sprints adds an extra 0 but dies not return it */
413     {
414       fail ("baf %d: length mismatch for canon\n", testno);
415       return;
416     }
417   rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
418   if (rc)
419     {
420       fail ("baf %d: gcry_sexp_create failed: %s\n",
421             testno, gpg_strerror (rc));
422       return;
423     }
424   gcry_sexp_release (se1);
425
426   /* Again but with memory checking. */
427   p1 = gcry_xmalloc (n1+2);
428   *p1 = '\x55';
429   p1[n1+1] = '\xaa';
430   n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1+1, n1);
431   if (n1 != n+1) /* sprints adds an extra 0 but does not return it */
432     {
433       fail ("baf %d: length mismatch for canon\n", testno);
434       return;
435     }
436   if (*p1 != '\x55' || p1[n1+1] != '\xaa')
437     fail ("baf %d: memory corrupted (1)\n", testno);
438   rc = gcry_sexp_create (&se1, p1+1, n, 0, NULL);
439   if (rc)
440     {
441       fail ("baf %d: gcry_sexp_create failed: %s\n",
442             testno, gpg_strerror (rc));
443       return;
444     }
445   if (*p1 != '\x55' || p1[n1+1] != '\xaa')
446     fail ("baf %d: memory corrupted (2)\n", testno);
447   gcry_sexp_release (se1);
448   if (*p1 != '\x55' || p1[n1+1] != '\xaa')
449     fail ("baf %d: memory corrupted (3)\n", testno);
450   gcry_free (p1);
451
452   /* FIXME: we need a lot more tests */
453
454   gcry_sexp_release (se);
455 }
456
457
458
459 static void
460 back_and_forth (void)
461 {
462   static struct { const char *buf; int len; } tests[] = {
463     { "(7:g34:fgh1::2:())", 0 },
464     { "(7:g34:fgh1::2:())", 18 },
465     {
466 "(protected-private-key \n"
467 " (rsa \n"
468 "  (n #00BE8A536204687149A48FF9F1715FF3530AD9A836D62102BF4065E5CF5953236DB94F1DF2FF4D525CD4CE7966DDC3C839968E8BAC2948934DF047CC65287CD79F6C23C93E55D7F9231E3942BD496DE383469977635A51ADF4AF747DB958CA02E9940DFC1DC0FC7FC755E7EB6618FEE6DA54B8A06E0CBF9D9257443F9992261435#)\n"
469 "  (e #010001#)\n"
470 "  (protected openpgp-s2k3-sha1-aes-cbc \n"
471 "   (\n"
472 "    (sha1 #C2A5673BD3882405# \"96\")\n"
473 "    #8D08AAF6A9209ED69D71EB7E64D78715#)\n"
474 "   #F7B0B535F8F8E22F4F3DA031224070303F82F9207D42952F1ACF21A4AB1C50304EBB25527992C7B265A9E9FF702826FB88759BDD55E4759E9FCA6C879538C9D043A9C60A326CB6681090BAA731289BD880A7D5774D9999F026E5E7963BFC8C0BDC9F061393CB734B4F259725C0A0A0B15BA39C39146EF6A1B3DC4DF30A22EBE09FD05AE6CB0C8C6532951A925F354F4E26A51964F5BBA50081690C421C8385C4074E9BAB9297D081B857756607EAE652415275A741C89E815558A50AC638EDC5F5030210B4395E3E1A40FF38DCCCB333A19EA88EFE7E4D51B54128C6DF27395646836679AC21B1B25C1DA6F0A7CE9F9BE078EFC7934FA9AE202CBB0AA06C20DFAF9A66FAB7E9073FBE96B9A7F25C3BA45EC3EECA65796AEE313BA148DE5314F30345B452B50B17C4D841A7F27397126E8C10BD0CE3B50A82C0425AAEE7798031671407B681F52916256F78CAF92A477AC27BCBE26DAFD1BCE386A853E2A036F8314BB2E8E5BB1F196434232EFB0288331C2AB16DBC5457CC295EB966CAC5CE73D5DA5D566E469F0EFA82F9A12B8693E0#)\n"
475 "  )\n"
476 " )\n", 0 },
477     { NULL, 0 }
478   };
479   int idx;
480
481   for (idx=0; tests[idx].buf; idx++)
482     back_and_forth_one (idx, tests[idx].buf, tests[idx].len);
483 }
484
485
486 static void
487 check_sscan (void)
488 {
489   static struct {
490     const char *text;
491     gcry_error_t expected_err;
492   } values[] = {
493     /* Bug reported by Olivier L'Heureux 2003-10-07 */
494     { "(7:sig-val(3:dsa"
495       "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
496       "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
497       "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
498       "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e)))",
499       GPG_ERR_NO_ERROR },
500     { "(7:sig-val(3:dsa"
501       "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
502       "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
503       "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
504       "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))",
505       GPG_ERR_SEXP_UNMATCHED_PAREN },
506     { "(7:sig-val(3:dsa"
507       "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
508       "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
509       "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
510       "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))))",
511       GPG_ERR_SEXP_UNMATCHED_PAREN },
512     { NULL, 0 }
513   };
514   int idx;
515   gcry_error_t err;
516   gcry_sexp_t s;
517
518   info ("checking gcry_sexp_sscan\n");
519   for (idx=0; values[idx].text; idx++)
520     {
521       err = gcry_sexp_sscan (&s, NULL,
522                              values[idx].text,
523                              strlen (values[idx].text));
524       if (gpg_err_code (err) != values[idx].expected_err)
525         fail ("gcry_sexp_sscan test %d failed: %s\n", idx, gpg_strerror (err));
526       gcry_sexp_release (s);
527     }
528 }
529
530
531 static void
532 check_extract_param (void)
533 {
534   /* This sample data is a real key but with some parameters of the
535      public key modified.  */
536   static char sample1[] =
537     "(key-data"
538     " (public-key"
539     "  (ecc"
540     "   (curve Ed25519)"
541     "   (p #6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
542     "   (a #EF#)"
543     "   (b #C2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6#)"
544     "   (g #14"
545     "       216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
546     "       6666666666666666666666666666666666666666666666666666666666666658#)"
547     "   (n #0000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED#)"
548     "   (q #20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
549     "))"
550     " (private-key"
551     "  (ecc"
552     "   (curve Ed25519)"
553     "   (p #7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
554     "   (a #FF#)"
555     "   (b #D2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6#)"
556     "   (g #04"
557     "       216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
558     "       6666666666666666666666666666666666666666666666666666666666666658#)"
559     "   (n #1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED#)"
560     "   (q #30B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
561     "   (d #56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276#)"
562     ")))";
563
564   static char sample1_p[] =
565     "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED";
566   static char sample1_px[] =
567     "6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED";
568   static char sample1_a[] = "FF";
569   static char sample1_ax[] = "EF";
570   static char sample1_b[] =
571     "D2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6";
572   static char sample1_bx[] =
573     "C2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6";
574   static char sample1_g[] =
575     "04"
576     "216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
577     "6666666666666666666666666666666666666666666666666666666666666658";
578   static char sample1_gx[] =
579     "14"
580     "216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
581     "6666666666666666666666666666666666666666666666666666666666666658";
582   static char sample1_n[] =
583     "1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
584   static char sample1_nx[] =
585     "0000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
586   static char sample1_q[] =
587     "30B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62";
588   static char sample1_qx[] =
589     "20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62";
590   static char sample1_d[] =
591     "56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276";
592
593   static struct {
594     const char *sexp_str;
595     const char *path;
596     const char *list;
597     int nparam;
598     gpg_err_code_t expected_err;
599     const char *exp_p;
600     const char *exp_a;
601     const char *exp_b;
602     const char *exp_g;
603     const char *exp_n;
604     const char *exp_q;
605     const char *exp_d;
606   } tests[] = {
607     {
608       sample1,
609       NULL,
610       "pabgnqd", 6,
611       GPG_ERR_MISSING_VALUE,
612     },
613     {
614       sample1,
615       NULL,
616       "pabgnq", 7,
617       GPG_ERR_INV_ARG
618     },
619     {
620       sample1,
621       NULL,
622       "pab'gnq", 7,
623       GPG_ERR_SYNTAX
624     },
625     {
626       sample1,
627       NULL,
628       "pab''gnq", 7,
629       GPG_ERR_SYNTAX
630     },
631     {
632       sample1,
633       NULL,
634       "pabgnqd", 7,
635       0,
636       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
637       sample1_qx, sample1_d
638     },
639     {
640       sample1,
641       NULL,
642       "  pab\tg nq\nd  ", 7,
643       0,
644       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
645       sample1_qx, sample1_d
646     },
647     {
648       sample1,
649       NULL,
650       "abg", 3,
651       0,
652       sample1_ax, sample1_bx, sample1_gx
653     },
654     {
655       sample1,
656       NULL,
657       "ab'g'", 3,
658       0,
659       sample1_ax, sample1_bx, sample1_gx
660     },
661     {
662       sample1,
663       NULL,
664       "x?abg", 4,
665       0,
666       NULL, sample1_ax, sample1_bx, sample1_gx
667     },
668     {
669       sample1,
670       NULL,
671       "p?abg", 4,
672       GPG_ERR_USER_1,
673       NULL, sample1_ax, sample1_bx, sample1_gx
674     },
675     {
676       sample1,
677       NULL,
678       "pax?gnqd", 7,
679       0,
680       sample1_px, sample1_ax, NULL, sample1_gx, sample1_nx,
681       sample1_qx, sample1_d
682     },
683     {
684       sample1,
685       "public-key",
686       "pabgnqd", 7,
687       GPG_ERR_NO_OBJ,  /* d is not in public key.  */
688       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
689       sample1_qx, sample1_d
690     },
691     {
692       sample1,
693       "private-key",
694       "pabgnqd", 7,
695       0,
696       sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
697       sample1_q, sample1_d
698     },
699     {
700       sample1,
701       "public-key!ecc",
702       "pabgnq", 6,
703       0,
704       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
705       sample1_qx
706     },
707     {
708       sample1,
709       "public-key!ecc!foo",
710       "pabgnq", 6,
711       GPG_ERR_NOT_FOUND
712     },
713     {
714       sample1,
715       "public-key!!ecc",
716       "pabgnq", 6,
717       GPG_ERR_NOT_FOUND
718     },
719     {
720       sample1,
721       "private-key",
722       "pa/bgnqd", 7,
723       0,
724       sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
725       sample1_q, sample1_d
726     },
727     {
728       sample1,
729       "private-key",
730       "p-a+bgnqd", 7,
731       0,
732       sample1_p, "-01", sample1_b, sample1_g, sample1_n,
733       sample1_q, sample1_d
734     },
735     {NULL}
736   };
737   int idx, i;
738   const char *paramstr;
739   int paramidx;
740   gpg_error_t err;
741   gcry_sexp_t sxp;
742   gcry_mpi_t mpis[7];
743   gcry_buffer_t ioarray[7];
744   char iobuffer[200];
745
746   info ("checking gcry_sexp_extract_param\n");
747   for (idx=0; tests[idx].sexp_str; idx++)
748     {
749       err = gcry_sexp_new (&sxp, tests[idx].sexp_str, 0, 1);
750       if (err)
751         die ("converting string to sexp failed: %s", gpg_strerror (err));
752
753       memset (mpis, 0, sizeof mpis);
754       switch (tests[idx].nparam)
755         {
756         case 0:
757           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
758                                          NULL);
759           break;
760         case 1:
761           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
762                                          mpis+0, NULL);
763           break;
764         case 2:
765           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
766                                          mpis+0, mpis+1, NULL);
767           break;
768         case 3:
769           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
770                                          mpis+0, mpis+1, mpis+2, NULL);
771           break;
772         case 4:
773           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
774                                          mpis+0, mpis+1, mpis+2, mpis+3, NULL);
775           break;
776         case 5:
777           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
778                                          mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
779                                          NULL);
780           break;
781         case 6:
782           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
783                                          mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
784                                          mpis+5, NULL);
785           break;
786         case 7:
787           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
788                                          mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
789                                          mpis+5, mpis+6, NULL);
790           break;
791         default:
792           die ("test %d: internal error", idx);
793         }
794
795       if (tests[idx].expected_err
796           && tests[idx].expected_err != GPG_ERR_USER_1)
797         {
798           if (tests[idx].expected_err != gpg_err_code (err))
799             fail ("gcry_sexp_extract_param test %d failed: "
800                   "expected error '%s' - got '%s'", idx,
801                   gpg_strerror (tests[idx].expected_err),gpg_strerror (err));
802
803         }
804       else if (err)
805         {
806           fail ("gcry_sexp_extract_param test %d failed: %s",
807                 idx, gpg_strerror (err));
808         }
809       else /* No error - check the extracted values.  */
810         {
811           for (paramidx=0; paramidx < DIM (mpis); paramidx++)
812             {
813               switch (paramidx)
814                 {
815                 case 0: paramstr = tests[idx].exp_p; break;
816                 case 1: paramstr = tests[idx].exp_a; break;
817                 case 2: paramstr = tests[idx].exp_b; break;
818                 case 3: paramstr = tests[idx].exp_g; break;
819                 case 4: paramstr = tests[idx].exp_n; break;
820                 case 5: paramstr = tests[idx].exp_q; break;
821                 case 6: paramstr = tests[idx].exp_d; break;
822                 default:
823                   die ("test %d: internal error: bad param %d",
824                        idx, paramidx);
825                 }
826
827               if (tests[idx].expected_err == GPG_ERR_USER_1
828                   && mpis[paramidx] && !paramstr && paramidx == 0)
829                 ; /* Okay  Special case error for param 0.  */
830               else if (!mpis[paramidx] && !paramstr)
831                 ; /* Okay.  */
832               else if (!mpis[paramidx] && paramstr)
833                 fail ("test %d: value for param %d expected but not returned",
834                       idx, paramidx);
835               else if (mpis[paramidx] && !paramstr)
836                 fail ("test %d: value for param %d not expected",
837                       idx, paramidx);
838               else if (cmp_mpihex (mpis[paramidx], paramstr))
839                 {
840                   fail ("test %d: param %d mismatch", idx, paramidx);
841                   gcry_log_debug    ("expected: %s\n", paramstr);
842                   gcry_log_debugmpi ("     got", mpis[paramidx]);
843                 }
844               else if (tests[idx].expected_err && paramidx == 0)
845                 fail ("test %d: param %d: expected error '%s' - got 'Success'",
846                       idx, paramidx, gpg_strerror (tests[idx].expected_err));
847             }
848
849         }
850
851       for (i=0; i < DIM (mpis); i++)
852         gcry_mpi_release (mpis[i]);
853       gcry_sexp_release (sxp);
854     }
855
856   info ("checking gcry_sexp_extract_param/desc\n");
857
858   memset (ioarray, 0, sizeof ioarray);
859
860   err = gcry_sexp_new (&sxp, sample1, 0, 1);
861   if (err)
862     die ("converting string to sexp failed: %s", gpg_strerror (err));
863
864   ioarray[1].size = sizeof iobuffer;
865   ioarray[1].data = iobuffer;
866   ioarray[1].off  = 0;
867   ioarray[2].size = sizeof iobuffer;
868   ioarray[2].data = iobuffer;
869   ioarray[2].off  = 50;
870   assert (ioarray[2].off < sizeof iobuffer);
871   err = gcry_sexp_extract_param (sxp, "key-data!private-key", "&pab",
872                                  ioarray+0, ioarray+1, ioarray+2, NULL);
873   if (err)
874     fail ("gcry_sexp_extract_param with desc failed: %s", gpg_strerror (err));
875   else
876     {
877       if (!ioarray[0].data)
878         fail ("gcry_sexp_extract_param/desc failed: no P");
879       else if (ioarray[0].size != 32)
880         fail ("gcry_sexp_extract_param/desc failed: P has wrong size");
881       else if (ioarray[0].len != 32)
882         fail ("gcry_sexp_extract_param/desc failed: P has wrong length");
883       else if (ioarray[0].off)
884         fail ("gcry_sexp_extract_param/desc failed: P has OFF set");
885       else if (cmp_bufhex (ioarray[0].data, ioarray[0].len, sample1_p))
886         {
887           fail ("gcry_sexp_extract_param/desc failed: P mismatch");
888           gcry_log_debug    ("expected: %s\n", sample1_p);
889           gcry_log_debughex ("     got", ioarray[0].data, ioarray[0].len);
890         }
891
892       if (!ioarray[1].data)
893         fail ("gcry_sexp_extract_param/desc failed: A buffer lost");
894       else if (ioarray[1].size != sizeof iobuffer)
895         fail ("gcry_sexp_extract_param/desc failed: A size changed");
896       else if (ioarray[1].off != 0)
897         fail ("gcry_sexp_extract_param/desc failed: A off changed");
898       else if (ioarray[1].len != 1)
899         fail ("gcry_sexp_extract_param/desc failed: A has wrong length");
900       else if (cmp_bufhex ((char *)ioarray[1].data + ioarray[1].off,
901                            ioarray[1].len, sample1_a))
902         {
903           fail ("gcry_sexp_extract_param/desc failed: A mismatch");
904           gcry_log_debug    ("expected: %s\n", sample1_a);
905           gcry_log_debughex ("     got",
906                              (char *)ioarray[1].data + ioarray[1].off,
907                              ioarray[1].len);
908         }
909
910       if (!ioarray[2].data)
911         fail ("gcry_sexp_extract_param/desc failed: B buffer lost");
912       else if (ioarray[2].size != sizeof iobuffer)
913         fail ("gcry_sexp_extract_param/desc failed: B size changed");
914       else if (ioarray[2].off != 50)
915         fail ("gcry_sexp_extract_param/desc failed: B off changed");
916       else if (ioarray[2].len != 32)
917         fail ("gcry_sexp_extract_param/desc failed: B has wrong length");
918       else if (cmp_bufhex ((char *)ioarray[2].data + ioarray[2].off,
919                            ioarray[2].len, sample1_b))
920         {
921           fail ("gcry_sexp_extract_param/desc failed: B mismatch");
922           gcry_log_debug    ("expected: %s\n", sample1_b);
923           gcry_log_debughex ("     got",
924                              (char *)ioarray[2].data + ioarray[2].off,
925                              ioarray[2].len);
926         }
927
928       xfree (ioarray[0].data);
929     }
930
931   gcry_sexp_release (sxp);
932
933   info ("checking gcry_sexp_extract_param long name\n");
934
935   memset (ioarray, 0, sizeof ioarray);
936   memset (mpis, 0, sizeof mpis);
937
938   err = gcry_sexp_new (&sxp, sample1, 0, 1);
939   if (err)
940     die ("converting string to sexp failed: %s", gpg_strerror (err));
941
942   err = gcry_sexp_extract_param (sxp, "key-data!private-key",
943                                  "&'curve'+p",
944                                  ioarray+0, mpis+0, NULL);
945   if (err)
946     fail ("gcry_sexp_extract_param long name failed: %s", gpg_strerror (err));
947
948   if (!ioarray[0].data)
949     fail ("gcry_sexp_extract_param long name failed: no curve");
950   else if (ioarray[0].size != 7)
951     fail ("gcry_sexp_extract_param long name failed: curve has wrong size");
952   else if (ioarray[0].len != 7)
953     fail ("gcry_sexp_extract_param long name failed: curve has wrong length");
954   else if (ioarray[0].off)
955     fail ("gcry_sexp_extract_param long name failed: curve has OFF set");
956   else if (strncmp (ioarray[0].data, "Ed25519", 7))
957     {
958       fail ("gcry_sexp_extract_param long name failed: curve mismatch");
959       gcry_log_debug ("expected: %s\n", "Ed25519");
960       gcry_log_debug ("     got: %.*s\n",
961                       (int)ioarray[0].len, (char*)ioarray[0].data);
962     }
963
964   if (!mpis[0])
965     fail ("gcry_sexp_extract_param long name failed: p not returned");
966   else if (cmp_mpihex (mpis[0], sample1_p))
967     {
968       fail ("gcry_sexp_extract_param long name failed: p mismatch");
969       gcry_log_debug    ("expected: %s\n", sample1_p);
970       gcry_log_debugmpi ("     got", mpis[0]);
971     }
972
973   gcry_free (ioarray[0].data);
974   gcry_mpi_release (mpis[0]);
975
976   gcry_sexp_release (sxp);
977
978 }
979
980
981 /* A test based on bug 1594.  */
982 static void
983 bug_1594 (void)
984 {
985 static char thing[] =
986   "(signature"
987   " (public-key"
988   "  (rsa"
989   "   (n #00A53A6B3A50BE571F805BD98ECE1FCE4CE291C3D4D3E971740E1EE6D447F526"
990   "       6AC8973DDC82F0ADD234CC82E0A0A3F48B81ACC8B038DB8ACC3E78DC2ED2642F"
991   "       6BA353FCA60F47C2801DEB477B37FB8B2F5508AA1C6D922780DB142DEA19B812"
992   "       C4E64F1138AD3BD61C58DB2D2591BE0BF36A1AC588AA45763BCDFF581050ABA8"
993   "       CA47BD9723ADD6A308AE28471EDD2B16D03C941D4F2B7E019C43AF8972880633"
994   "       54E97B7E19F1677D84B69A26B184A77B719DD72C48E0EE36107046F786566A9D"
995   "       13BAD724D6D78F24700FC22FC000E1B2A8C1B08ED62008395B0764CD9B55E80D"
996   "       A0A2B61C698DC27EA98E68BB576ACFC2B91B4D7283E7D960948D049D6E3C4CB1"
997   "       F489B460A120A4BB6C04A843FD3A67454136DE61CF68A927871EFFA9141BD372"
998   "       A748593C703E0301F039A9E674C50301BFC385BABE5B154250E7D57B82DB31F1"
999   "       E1AC696F870DCD8FE8DEC75608B988FCA3B484F1FD7755BF452F99597269AF02"
1000   "       E8AF87D0F93DB427291659183D077254C835BFB6DDFD87CD0B5E0738682FCD34"
1001   "       923F22551F73944E6CBE3ED6879B4414676B5DA0F30ED21DFA12BD2230C3C5D2"
1002   "       EA116A3EFEB4AEC21C58E63FAFA549A63190F01859445E9B80F427B80FD4C884"
1003   "       2AD41FE760A3E9DEDFB56CEBE8EA783838B2B392CACDDC760CCE212E388AFBC1"
1004   "       95DC6D0ED87E9091F82A82CE372738C8DE8ABD76ACD06AC8B80AA0597162DF59"
1005   "       67#)"
1006   "   (e #010001#))))";
1007   gcry_sexp_t sig, pubkey, n, n_val;
1008
1009   info ("checking fix for bug 1594\n");
1010
1011   if (gcry_sexp_new (&sig, thing, 0, 1))
1012     die ("scanning fixed string failed\n");
1013   pubkey = gcry_sexp_find_token (sig, "public-key", 0);
1014   gcry_sexp_release (sig);
1015   if (!pubkey)
1016     {
1017       fail ("'public-key' token not found");
1018       return;
1019     }
1020   n = gcry_sexp_find_token (pubkey, "n", 0);
1021   if (!n)
1022     {
1023       fail ("'n' token not found");
1024       gcry_sexp_release (pubkey);
1025       return;
1026     }
1027   n_val = gcry_sexp_nth (n, 1);
1028   /* Bug 1594 would require the following test:
1029    *   if (n_val)
1030    *     fail ("extracting 1-th of 'n' list did not fail");
1031    * However, we meanwhile modified the S-expression functions to
1032    * behave like Scheme to allow the access of any element of a list.
1033    */
1034   if (!n_val)
1035     fail ("extracting 1-th of 'n' list failed");
1036   /*gcry_log_debugsxp ("1-th", n_val); => "(#00A5...#)"  */
1037   gcry_sexp_release (n_val);
1038   n_val = gcry_sexp_nth (n, 2);
1039   if (n_val)
1040     fail ("extracting 2-th of 'n' list did not fail");
1041   n_val = gcry_sexp_nth (n, 0);
1042   if (!n_val)
1043     fail ("extracting 0-th of 'n' list failed");
1044   /*gcry_log_debugsxp ("0-th", n_val); => "(n)"  */
1045   if (gcry_sexp_nth (n_val, 1))
1046     fail ("extracting 1-th of car of 'n' list did not fail");
1047   gcry_sexp_release (n_val);
1048 }
1049
1050
1051 int
1052 main (int argc, char **argv)
1053 {
1054   int last_argc = -1;
1055
1056   if (argc)
1057     {
1058       argc--; argv++;
1059     }
1060   while (argc && last_argc != argc )
1061     {
1062       last_argc = argc;
1063       if (!strcmp (*argv, "--"))
1064         {
1065           argc--; argv++;
1066           break;
1067         }
1068       else if (!strcmp (*argv, "--help"))
1069         {
1070           puts (
1071 "usage: " PGMNAME " [options]\n"
1072 "\n"
1073 "Options:\n"
1074 "  --verbose      Show what is going on\n"
1075 "  --debug        Flyswatter\n"
1076 );
1077           exit (0);
1078         }
1079       else if (!strcmp (*argv, "--verbose"))
1080         {
1081           verbose = 1;
1082           argc--; argv++;
1083         }
1084       else if (!strcmp (*argv, "--debug"))
1085         {
1086           verbose = debug = 1;
1087           argc--; argv++;
1088         }
1089       else if (!strncmp (*argv, "--", 2))
1090         die ("unknown option '%s'", *argv);
1091     }
1092
1093   if (debug)
1094     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
1095   gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
1096   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
1097   if (!gcry_check_version (GCRYPT_VERSION))
1098     die ("version mismatch");
1099   /* #include "../src/gcrypt-int.h" indicates that internal interfaces
1100      may be used; thus better do an exact version check. */
1101   if (strcmp (gcry_check_version (NULL), GCRYPT_VERSION))
1102     die ("exact version match failed");
1103   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
1104   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
1105
1106   basic ();
1107   canon_len ();
1108   back_and_forth ();
1109   check_sscan ();
1110   check_extract_param ();
1111   bug_1594 ();
1112
1113   return errorcount? 1:0;
1114 }