Merge branch 'master' into LIBGCRYPT-1-7-BRANCH
[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\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 /* Compare SE to the canonical formatted expression in
391  * (CANON,CANONLEN).  This is done by a converting SE to canonical
392  * format and doing a byte compare.  Returns 0 if they match.  */
393 static int
394 compare_to_canon (gcry_sexp_t se, const unsigned char *canon, size_t canonlen)
395 {
396   size_t n, n1;
397   char *p1;
398
399   n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0);
400   if (!n1)
401     {
402       fail ("get required length in compare_to_canon failed\n");
403       return -1;
404     }
405   p1 = gcry_xmalloc (n1);
406   n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
407   if (n1 != n+1)
408     {
409       fail ("length mismatch in compare_to_canon detected\n");
410       xfree (p1);
411       return -1;
412     }
413   if (n1 != canonlen || memcmp (p1, canon, canonlen))
414     {
415       xfree (p1);
416       return -1;
417     }
418   xfree (p1);
419   return 0;
420 }
421
422
423 static void
424 back_and_forth_one (int testno, const char *buffer, size_t length)
425 {
426   gcry_error_t rc;
427   gcry_sexp_t se, se1;
428   unsigned char *canon;
429   size_t canonlen;  /* Including the hidden nul suffix.  */
430   size_t n, n1;
431   char *p1;
432
433   rc = gcry_sexp_new (&se, buffer, length, 1);
434   if (rc)
435     {
436       fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc));
437       return;
438     }
439   n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0);
440   if (!n1)
441     {
442       fail ("baf %d: get required length for canon failed\n", testno);
443       return;
444     }
445   p1 = gcry_xmalloc (n1);
446   n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
447   if (n1 != n+1) /* sprints adds an extra 0 but does not return it. */
448     {
449       fail ("baf %d: length mismatch for canon\n", testno);
450       return;
451     }
452   canonlen = n1;
453   canon = gcry_malloc (canonlen);
454   memcpy (canon, p1, canonlen);
455   rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
456   if (rc)
457     {
458       fail ("baf %d: gcry_sexp_create failed: %s\n",
459             testno, gpg_strerror (rc));
460       return;
461     }
462   gcry_sexp_release (se1);
463
464   /* Again but with memory checking. */
465   p1 = gcry_xmalloc (n1+2);
466   *p1 = '\x55';
467   p1[n1+1] = '\xaa';
468   n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1+1, n1);
469   if (n1 != n+1) /* sprints adds an extra 0 but does not return it */
470     {
471       fail ("baf %d: length mismatch for canon\n", testno);
472       return;
473     }
474   if (*p1 != '\x55' || p1[n1+1] != '\xaa')
475     fail ("baf %d: memory corrupted (1)\n", testno);
476   rc = gcry_sexp_create (&se1, p1+1, n, 0, NULL);
477   if (rc)
478     {
479       fail ("baf %d: gcry_sexp_create failed: %s\n",
480             testno, gpg_strerror (rc));
481       return;
482     }
483   if (*p1 != '\x55' || p1[n1+1] != '\xaa')
484     fail ("baf %d: memory corrupted (2)\n", testno);
485   gcry_sexp_release (se1);
486   if (*p1 != '\x55' || p1[n1+1] != '\xaa')
487     fail ("baf %d: memory corrupted (3)\n", testno);
488   gcry_free (p1);
489
490   /* Check converting to advanced format.  */
491   n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_ADVANCED, NULL, 0);
492   if (!n1)
493     {
494       fail ("baf %d: get required length for advanced failed\n", testno);
495       return;
496     }
497   p1 = gcry_xmalloc (n1);
498   n = gcry_sexp_sprint (se, GCRYSEXP_FMT_ADVANCED, p1, n1);
499   if (n1 != n+1) /* sprints adds an extra 0 but does not return it */
500     {
501       fail ("baf %d: length mismatch for advanced\n", testno);
502       return;
503     }
504   rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
505   if (rc)
506     {
507       fail ("baf %d: gcry_sexp_create failed: %s\n",
508             testno, gpg_strerror (rc));
509       return;
510     }
511   if (compare_to_canon (se1, canon, canonlen))
512     {
513       fail ("baf %d: converting to advanced failed: %s\n",
514             testno, gpg_strerror (rc));
515       return;
516     }
517   gcry_sexp_release (se1);
518
519
520   /* FIXME: we need a lot more tests */
521
522   gcry_sexp_release (se);
523   xfree (canon);
524 }
525
526
527
528 static void
529 back_and_forth (void)
530 {
531   static struct { const char *buf; int len; } tests[] = {
532     { "(7:g34:fgh1::2:())", 0 },
533     { "(7:g34:fgh1::2:())", 18 },
534     {
535 "(protected-private-key \n"
536 " (rsa \n"
537 "  (n #00BE8A536204687149A48FF9F1715FF3530AD9A836D62102BF4065E5CF5953236DB94F1DF2FF4D525CD4CE7966DDC3C839968E8BAC2948934DF047CC65287CD79F6C23C93E55D7F9231E3942BD496DE383469977635A51ADF4AF747DB958CA02E9940DFC1DC0FC7FC755E7EB6618FEE6DA54B8A06E0CBF9D9257443F9992261435#)\n"
538 "  (e #010001#)\n"
539 "  (protected openpgp-s2k3-sha1-aes-cbc \n"
540 "   (\n"
541 "    (sha1 #C2A5673BD3882405# \"96\")\n"
542 "    #8D08AAF6A9209ED69D71EB7E64D78715#)\n"
543 "   #F7B0B535F8F8E22F4F3DA031224070303F82F9207D42952F1ACF21A4AB1C50304EBB25527992C7B265A9E9FF702826FB88759BDD55E4759E9FCA6C879538C9D043A9C60A326CB6681090BAA731289BD880A7D5774D9999F026E5E7963BFC8C0BDC9F061393CB734B4F259725C0A0A0B15BA39C39146EF6A1B3DC4DF30A22EBE09FD05AE6CB0C8C6532951A925F354F4E26A51964F5BBA50081690C421C8385C4074E9BAB9297D081B857756607EAE652415275A741C89E815558A50AC638EDC5F5030210B4395E3E1A40FF38DCCCB333A19EA88EFE7E4D51B54128C6DF27395646836679AC21B1B25C1DA6F0A7CE9F9BE078EFC7934FA9AE202CBB0AA06C20DFAF9A66FAB7E9073FBE96B9A7F25C3BA45EC3EECA65796AEE313BA148DE5314F30345B452B50B17C4D841A7F27397126E8C10BD0CE3B50A82C0425AAEE7798031671407B681F52916256F78CAF92A477AC27BCBE26DAFD1BCE386A853E2A036F8314BB2E8E5BB1F196434232EFB0288331C2AB16DBC5457CC295EB966CAC5CE73D5DA5D566E469F0EFA82F9A12B8693E0#)\n"
544 "  )\n"
545 " )\n", 0 },
546     { "((sha1 #8B98CBF4A9823CA7# \"2097\") #3B6FC9#)", 0 },
547     { "((4:sha18:\x8B\x98\xCB\xF4\xA9\x82\x3C\xA7""4:2097)3:\x3B\x6F\xC9)", 0},
548     { "((4:sha18:\x8B\x98\xCB\x22\xA9\x82\x3C\xA7""4:2097)3:\x3B\x6F\xC9)", 0},
549     { "((sha1 #64652267686970C9# \"2097\") #3B6FC9#)", 0 },
550     { "((4:sha18:\x64\x65\x22\x67\x68\xc3\xa4\x71""4:2097)3:\x3B\x6F\xC9)", 0},
551     { "((sha1 \"defghäq\" \"2097\") #3B6FC9#)", 0 },
552     { "((sha1 \"de\\\"ghäq\" \"2097\") #3B6FC9#)", 0 },
553     { NULL, 0 }
554   };
555   int idx;
556
557   for (idx=0; tests[idx].buf; idx++)
558     back_and_forth_one (idx, tests[idx].buf, tests[idx].len);
559 }
560
561
562 static void
563 check_sscan (void)
564 {
565   static struct {
566     const char *text;
567     gcry_error_t expected_err;
568   } values[] = {
569     /* Bug reported by Olivier L'Heureux 2003-10-07 */
570     { "(7:sig-val(3:dsa"
571       "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
572       "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
573       "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
574       "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e)))",
575       GPG_ERR_NO_ERROR },
576     { "(7:sig-val(3:dsa"
577       "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
578       "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
579       "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
580       "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))",
581       GPG_ERR_SEXP_UNMATCHED_PAREN },
582     { "(7:sig-val(3:dsa"
583       "(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
584       "\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
585       "(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
586       "\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))))",
587       GPG_ERR_SEXP_UNMATCHED_PAREN },
588     { NULL, 0 }
589   };
590   int idx;
591   gcry_error_t err;
592   gcry_sexp_t s;
593
594   info ("checking gcry_sexp_sscan\n");
595   for (idx=0; values[idx].text; idx++)
596     {
597       err = gcry_sexp_sscan (&s, NULL,
598                              values[idx].text,
599                              strlen (values[idx].text));
600       if (gpg_err_code (err) != values[idx].expected_err)
601         fail ("gcry_sexp_sscan test %d failed: %s\n", idx, gpg_strerror (err));
602       gcry_sexp_release (s);
603     }
604 }
605
606
607 static void
608 check_extract_param (void)
609 {
610   /* This sample data is a real key but with some parameters of the
611      public key modified.  */
612   static char sample1[] =
613     "(key-data"
614     " (public-key"
615     "  (ecc"
616     "   (curve Ed25519)"
617     "   (p #6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
618     "   (a #EF#)"
619     "   (b #C2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6#)"
620     "   (g #14"
621     "       216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
622     "       6666666666666666666666666666666666666666666666666666666666666658#)"
623     "   (n #0000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED#)"
624     "   (q #20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
625     "))"
626     " (private-key"
627     "  (ecc"
628     "   (curve Ed25519)"
629     "   (p #7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
630     "   (a #FF#)"
631     "   (b #D2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6#)"
632     "   (g #04"
633     "       216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
634     "       6666666666666666666666666666666666666666666666666666666666666658#)"
635     "   (n #1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED#)"
636     "   (q #30B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
637     "   (d #56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276#)"
638     ")))";
639
640   static char sample1_p[] =
641     "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED";
642   static char sample1_px[] =
643     "6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED";
644   static char sample1_a[] = "FF";
645   static char sample1_ax[] = "EF";
646   static char sample1_b[] =
647     "D2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6";
648   static char sample1_bx[] =
649     "C2036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978B6";
650   static char sample1_g[] =
651     "04"
652     "216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
653     "6666666666666666666666666666666666666666666666666666666666666658";
654   static char sample1_gx[] =
655     "14"
656     "216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A"
657     "6666666666666666666666666666666666666666666666666666666666666658";
658   static char sample1_n[] =
659     "1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
660   static char sample1_nx[] =
661     "0000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
662   static char sample1_q[] =
663     "30B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62";
664   static char sample1_qx[] =
665     "20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62";
666   static char sample1_d[] =
667     "56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276";
668
669   static struct {
670     const char *sexp_str;
671     const char *path;
672     const char *list;
673     int nparam;
674     gpg_err_code_t expected_err;
675     const char *exp_p;
676     const char *exp_a;
677     const char *exp_b;
678     const char *exp_g;
679     const char *exp_n;
680     const char *exp_q;
681     const char *exp_d;
682   } tests[] = {
683     {
684       sample1,
685       NULL,
686       "pabgnqd", 6,
687       GPG_ERR_MISSING_VALUE,
688     },
689     {
690       sample1,
691       NULL,
692       "pabgnq", 7,
693       GPG_ERR_INV_ARG
694     },
695     {
696       sample1,
697       NULL,
698       "pab'gnq", 7,
699       GPG_ERR_SYNTAX
700     },
701     {
702       sample1,
703       NULL,
704       "pab''gnq", 7,
705       GPG_ERR_SYNTAX
706     },
707     {
708       sample1,
709       NULL,
710       "pabgnqd", 7,
711       0,
712       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
713       sample1_qx, sample1_d
714     },
715     {
716       sample1,
717       NULL,
718       "  pab\tg nq\nd  ", 7,
719       0,
720       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
721       sample1_qx, sample1_d
722     },
723     {
724       sample1,
725       NULL,
726       "abg", 3,
727       0,
728       sample1_ax, sample1_bx, sample1_gx
729     },
730     {
731       sample1,
732       NULL,
733       "ab'g'", 3,
734       0,
735       sample1_ax, sample1_bx, sample1_gx
736     },
737     {
738       sample1,
739       NULL,
740       "x?abg", 4,
741       0,
742       NULL, sample1_ax, sample1_bx, sample1_gx
743     },
744     {
745       sample1,
746       NULL,
747       "p?abg", 4,
748       GPG_ERR_USER_1,
749       NULL, sample1_ax, sample1_bx, sample1_gx
750     },
751     {
752       sample1,
753       NULL,
754       "pax?gnqd", 7,
755       0,
756       sample1_px, sample1_ax, NULL, sample1_gx, sample1_nx,
757       sample1_qx, sample1_d
758     },
759     {
760       sample1,
761       "public-key",
762       "pabgnqd", 7,
763       GPG_ERR_NO_OBJ,  /* d is not in public key.  */
764       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
765       sample1_qx, sample1_d
766     },
767     {
768       sample1,
769       "private-key",
770       "pabgnqd", 7,
771       0,
772       sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
773       sample1_q, sample1_d
774     },
775     {
776       sample1,
777       "public-key!ecc",
778       "pabgnq", 6,
779       0,
780       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
781       sample1_qx
782     },
783     {
784       sample1,
785       "public-key!ecc!foo",
786       "pabgnq", 6,
787       GPG_ERR_NOT_FOUND
788     },
789     {
790       sample1,
791       "public-key!!ecc",
792       "pabgnq", 6,
793       GPG_ERR_NOT_FOUND
794     },
795     {
796       sample1,
797       "private-key",
798       "pa/bgnqd", 7,
799       0,
800       sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
801       sample1_q, sample1_d
802     },
803     {
804       sample1,
805       "private-key",
806       "p-a+bgnqd", 7,
807       0,
808       sample1_p, "-01", sample1_b, sample1_g, sample1_n,
809       sample1_q, sample1_d
810     },
811     {NULL}
812   };
813   int idx, i;
814   const char *paramstr;
815   int paramidx;
816   gpg_error_t err;
817   gcry_sexp_t sxp;
818   gcry_mpi_t mpis[7];
819   gcry_buffer_t ioarray[7];
820   char iobuffer[200];
821
822   info ("checking gcry_sexp_extract_param\n");
823   for (idx=0; tests[idx].sexp_str; idx++)
824     {
825       err = gcry_sexp_new (&sxp, tests[idx].sexp_str, 0, 1);
826       if (err)
827         die ("converting string to sexp failed: %s", gpg_strerror (err));
828
829       memset (mpis, 0, sizeof mpis);
830       switch (tests[idx].nparam)
831         {
832         case 0:
833           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
834                                          NULL);
835           break;
836         case 1:
837           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
838                                          mpis+0, NULL);
839           break;
840         case 2:
841           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
842                                          mpis+0, mpis+1, NULL);
843           break;
844         case 3:
845           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
846                                          mpis+0, mpis+1, mpis+2, NULL);
847           break;
848         case 4:
849           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
850                                          mpis+0, mpis+1, mpis+2, mpis+3, NULL);
851           break;
852         case 5:
853           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
854                                          mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
855                                          NULL);
856           break;
857         case 6:
858           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
859                                          mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
860                                          mpis+5, NULL);
861           break;
862         case 7:
863           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
864                                          mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
865                                          mpis+5, mpis+6, NULL);
866           break;
867         default:
868           die ("test %d: internal error", idx);
869         }
870
871       if (tests[idx].expected_err
872           && tests[idx].expected_err != GPG_ERR_USER_1)
873         {
874           if (tests[idx].expected_err != gpg_err_code (err))
875             fail ("gcry_sexp_extract_param test %d failed: "
876                   "expected error '%s' - got '%s'", idx,
877                   gpg_strerror (tests[idx].expected_err),gpg_strerror (err));
878
879         }
880       else if (err)
881         {
882           fail ("gcry_sexp_extract_param test %d failed: %s",
883                 idx, gpg_strerror (err));
884         }
885       else /* No error - check the extracted values.  */
886         {
887           for (paramidx=0; paramidx < DIM (mpis); paramidx++)
888             {
889               switch (paramidx)
890                 {
891                 case 0: paramstr = tests[idx].exp_p; break;
892                 case 1: paramstr = tests[idx].exp_a; break;
893                 case 2: paramstr = tests[idx].exp_b; break;
894                 case 3: paramstr = tests[idx].exp_g; break;
895                 case 4: paramstr = tests[idx].exp_n; break;
896                 case 5: paramstr = tests[idx].exp_q; break;
897                 case 6: paramstr = tests[idx].exp_d; break;
898                 default:
899                   die ("test %d: internal error: bad param %d",
900                        idx, paramidx);
901                 }
902
903               if (tests[idx].expected_err == GPG_ERR_USER_1
904                   && mpis[paramidx] && !paramstr && paramidx == 0)
905                 ; /* Okay  Special case error for param 0.  */
906               else if (!mpis[paramidx] && !paramstr)
907                 ; /* Okay.  */
908               else if (!mpis[paramidx] && paramstr)
909                 fail ("test %d: value for param %d expected but not returned",
910                       idx, paramidx);
911               else if (mpis[paramidx] && !paramstr)
912                 fail ("test %d: value for param %d not expected",
913                       idx, paramidx);
914               else if (cmp_mpihex (mpis[paramidx], paramstr))
915                 {
916                   fail ("test %d: param %d mismatch", idx, paramidx);
917                   gcry_log_debug    ("expected: %s\n", paramstr);
918                   gcry_log_debugmpi ("     got", mpis[paramidx]);
919                 }
920               else if (tests[idx].expected_err && paramidx == 0)
921                 fail ("test %d: param %d: expected error '%s' - got 'Success'",
922                       idx, paramidx, gpg_strerror (tests[idx].expected_err));
923             }
924
925         }
926
927       for (i=0; i < DIM (mpis); i++)
928         gcry_mpi_release (mpis[i]);
929       gcry_sexp_release (sxp);
930     }
931
932   info ("checking gcry_sexp_extract_param/desc\n");
933
934   memset (ioarray, 0, sizeof ioarray);
935
936   err = gcry_sexp_new (&sxp, sample1, 0, 1);
937   if (err)
938     die ("converting string to sexp failed: %s", gpg_strerror (err));
939
940   ioarray[1].size = sizeof iobuffer;
941   ioarray[1].data = iobuffer;
942   ioarray[1].off  = 0;
943   ioarray[2].size = sizeof iobuffer;
944   ioarray[2].data = iobuffer;
945   ioarray[2].off  = 50;
946   assert (ioarray[2].off < sizeof iobuffer);
947   err = gcry_sexp_extract_param (sxp, "key-data!private-key", "&pab",
948                                  ioarray+0, ioarray+1, ioarray+2, NULL);
949   if (err)
950     fail ("gcry_sexp_extract_param with desc failed: %s", gpg_strerror (err));
951   else
952     {
953       if (!ioarray[0].data)
954         fail ("gcry_sexp_extract_param/desc failed: no P");
955       else if (ioarray[0].size != 32)
956         fail ("gcry_sexp_extract_param/desc failed: P has wrong size");
957       else if (ioarray[0].len != 32)
958         fail ("gcry_sexp_extract_param/desc failed: P has wrong length");
959       else if (ioarray[0].off)
960         fail ("gcry_sexp_extract_param/desc failed: P has OFF set");
961       else if (cmp_bufhex (ioarray[0].data, ioarray[0].len, sample1_p))
962         {
963           fail ("gcry_sexp_extract_param/desc failed: P mismatch");
964           gcry_log_debug    ("expected: %s\n", sample1_p);
965           gcry_log_debughex ("     got", ioarray[0].data, ioarray[0].len);
966         }
967
968       if (!ioarray[1].data)
969         fail ("gcry_sexp_extract_param/desc failed: A buffer lost");
970       else if (ioarray[1].size != sizeof iobuffer)
971         fail ("gcry_sexp_extract_param/desc failed: A size changed");
972       else if (ioarray[1].off != 0)
973         fail ("gcry_sexp_extract_param/desc failed: A off changed");
974       else if (ioarray[1].len != 1)
975         fail ("gcry_sexp_extract_param/desc failed: A has wrong length");
976       else if (cmp_bufhex ((char *)ioarray[1].data + ioarray[1].off,
977                            ioarray[1].len, sample1_a))
978         {
979           fail ("gcry_sexp_extract_param/desc failed: A mismatch");
980           gcry_log_debug    ("expected: %s\n", sample1_a);
981           gcry_log_debughex ("     got",
982                              (char *)ioarray[1].data + ioarray[1].off,
983                              ioarray[1].len);
984         }
985
986       if (!ioarray[2].data)
987         fail ("gcry_sexp_extract_param/desc failed: B buffer lost");
988       else if (ioarray[2].size != sizeof iobuffer)
989         fail ("gcry_sexp_extract_param/desc failed: B size changed");
990       else if (ioarray[2].off != 50)
991         fail ("gcry_sexp_extract_param/desc failed: B off changed");
992       else if (ioarray[2].len != 32)
993         fail ("gcry_sexp_extract_param/desc failed: B has wrong length");
994       else if (cmp_bufhex ((char *)ioarray[2].data + ioarray[2].off,
995                            ioarray[2].len, sample1_b))
996         {
997           fail ("gcry_sexp_extract_param/desc failed: B mismatch");
998           gcry_log_debug    ("expected: %s\n", sample1_b);
999           gcry_log_debughex ("     got",
1000                              (char *)ioarray[2].data + ioarray[2].off,
1001                              ioarray[2].len);
1002         }
1003
1004       xfree (ioarray[0].data);
1005     }
1006
1007   gcry_sexp_release (sxp);
1008
1009   info ("checking gcry_sexp_extract_param long name\n");
1010
1011   memset (ioarray, 0, sizeof ioarray);
1012   memset (mpis, 0, sizeof mpis);
1013
1014   err = gcry_sexp_new (&sxp, sample1, 0, 1);
1015   if (err)
1016     die ("converting string to sexp failed: %s", gpg_strerror (err));
1017
1018   err = gcry_sexp_extract_param (sxp, "key-data!private-key",
1019                                  "&'curve'+p",
1020                                  ioarray+0, mpis+0, NULL);
1021   if (err)
1022     fail ("gcry_sexp_extract_param long name failed: %s", gpg_strerror (err));
1023
1024   if (!ioarray[0].data)
1025     fail ("gcry_sexp_extract_param long name failed: no curve");
1026   else if (ioarray[0].size != 7)
1027     fail ("gcry_sexp_extract_param long name failed: curve has wrong size");
1028   else if (ioarray[0].len != 7)
1029     fail ("gcry_sexp_extract_param long name failed: curve has wrong length");
1030   else if (ioarray[0].off)
1031     fail ("gcry_sexp_extract_param long name failed: curve has OFF set");
1032   else if (strncmp (ioarray[0].data, "Ed25519", 7))
1033     {
1034       fail ("gcry_sexp_extract_param long name failed: curve mismatch");
1035       gcry_log_debug ("expected: %s\n", "Ed25519");
1036       gcry_log_debug ("     got: %.*s\n",
1037                       (int)ioarray[0].len, (char*)ioarray[0].data);
1038     }
1039
1040   if (!mpis[0])
1041     fail ("gcry_sexp_extract_param long name failed: p not returned");
1042   else if (cmp_mpihex (mpis[0], sample1_p))
1043     {
1044       fail ("gcry_sexp_extract_param long name failed: p mismatch");
1045       gcry_log_debug    ("expected: %s\n", sample1_p);
1046       gcry_log_debugmpi ("     got", mpis[0]);
1047     }
1048
1049   gcry_free (ioarray[0].data);
1050   gcry_mpi_release (mpis[0]);
1051
1052   gcry_sexp_release (sxp);
1053
1054 }
1055
1056
1057 /* A test based on bug 1594.  */
1058 static void
1059 bug_1594 (void)
1060 {
1061 static char thing[] =
1062   "(signature"
1063   " (public-key"
1064   "  (rsa"
1065   "   (n #00A53A6B3A50BE571F805BD98ECE1FCE4CE291C3D4D3E971740E1EE6D447F526"
1066   "       6AC8973DDC82F0ADD234CC82E0A0A3F48B81ACC8B038DB8ACC3E78DC2ED2642F"
1067   "       6BA353FCA60F47C2801DEB477B37FB8B2F5508AA1C6D922780DB142DEA19B812"
1068   "       C4E64F1138AD3BD61C58DB2D2591BE0BF36A1AC588AA45763BCDFF581050ABA8"
1069   "       CA47BD9723ADD6A308AE28471EDD2B16D03C941D4F2B7E019C43AF8972880633"
1070   "       54E97B7E19F1677D84B69A26B184A77B719DD72C48E0EE36107046F786566A9D"
1071   "       13BAD724D6D78F24700FC22FC000E1B2A8C1B08ED62008395B0764CD9B55E80D"
1072   "       A0A2B61C698DC27EA98E68BB576ACFC2B91B4D7283E7D960948D049D6E3C4CB1"
1073   "       F489B460A120A4BB6C04A843FD3A67454136DE61CF68A927871EFFA9141BD372"
1074   "       A748593C703E0301F039A9E674C50301BFC385BABE5B154250E7D57B82DB31F1"
1075   "       E1AC696F870DCD8FE8DEC75608B988FCA3B484F1FD7755BF452F99597269AF02"
1076   "       E8AF87D0F93DB427291659183D077254C835BFB6DDFD87CD0B5E0738682FCD34"
1077   "       923F22551F73944E6CBE3ED6879B4414676B5DA0F30ED21DFA12BD2230C3C5D2"
1078   "       EA116A3EFEB4AEC21C58E63FAFA549A63190F01859445E9B80F427B80FD4C884"
1079   "       2AD41FE760A3E9DEDFB56CEBE8EA783838B2B392CACDDC760CCE212E388AFBC1"
1080   "       95DC6D0ED87E9091F82A82CE372738C8DE8ABD76ACD06AC8B80AA0597162DF59"
1081   "       67#)"
1082   "   (e #010001#))))";
1083   gcry_sexp_t sig, pubkey, n, n_val;
1084
1085   info ("checking fix for bug 1594\n");
1086
1087   if (gcry_sexp_new (&sig, thing, 0, 1))
1088     die ("scanning fixed string failed\n");
1089   pubkey = gcry_sexp_find_token (sig, "public-key", 0);
1090   gcry_sexp_release (sig);
1091   if (!pubkey)
1092     {
1093       fail ("'public-key' token not found");
1094       return;
1095     }
1096   n = gcry_sexp_find_token (pubkey, "n", 0);
1097   if (!n)
1098     {
1099       fail ("'n' token not found");
1100       gcry_sexp_release (pubkey);
1101       return;
1102     }
1103   n_val = gcry_sexp_nth (n, 1);
1104   /* Bug 1594 would require the following test:
1105    *   if (n_val)
1106    *     fail ("extracting 1-th of 'n' list did not fail");
1107    * However, we meanwhile modified the S-expression functions to
1108    * behave like Scheme to allow the access of any element of a list.
1109    */
1110   if (!n_val)
1111     fail ("extracting 1-th of 'n' list failed");
1112   /*gcry_log_debugsxp ("1-th", n_val); => "(#00A5...#)"  */
1113   gcry_sexp_release (n_val);
1114   n_val = gcry_sexp_nth (n, 2);
1115   if (n_val)
1116     fail ("extracting 2-th of 'n' list did not fail");
1117   n_val = gcry_sexp_nth (n, 0);
1118   if (!n_val)
1119     fail ("extracting 0-th of 'n' list failed");
1120   /*gcry_log_debugsxp ("0-th", n_val); => "(n)"  */
1121   if (gcry_sexp_nth (n_val, 1))
1122     fail ("extracting 1-th of car of 'n' list did not fail");
1123   gcry_sexp_release (n_val);
1124   gcry_sexp_release (n);
1125   gcry_sexp_release (pubkey);
1126 }
1127
1128
1129 int
1130 main (int argc, char **argv)
1131 {
1132   int last_argc = -1;
1133
1134   if (argc)
1135     {
1136       argc--; argv++;
1137     }
1138   while (argc && last_argc != argc )
1139     {
1140       last_argc = argc;
1141       if (!strcmp (*argv, "--"))
1142         {
1143           argc--; argv++;
1144           break;
1145         }
1146       else if (!strcmp (*argv, "--help"))
1147         {
1148           puts (
1149 "usage: " PGMNAME " [options]\n"
1150 "\n"
1151 "Options:\n"
1152 "  --verbose      Show what is going on\n"
1153 "  --debug        Flyswatter\n"
1154 );
1155           exit (0);
1156         }
1157       else if (!strcmp (*argv, "--verbose"))
1158         {
1159           verbose = 1;
1160           argc--; argv++;
1161         }
1162       else if (!strcmp (*argv, "--debug"))
1163         {
1164           verbose = debug = 1;
1165           argc--; argv++;
1166         }
1167       else if (!strncmp (*argv, "--", 2))
1168         die ("unknown option '%s'", *argv);
1169     }
1170
1171   if (debug)
1172     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
1173   gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
1174   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
1175   if (!gcry_check_version (GCRYPT_VERSION))
1176     die ("version mismatch");
1177   /* #include "../src/gcrypt-int.h" indicates that internal interfaces
1178      may be used; thus better do an exact version check. */
1179   if (strcmp (gcry_check_version (NULL), GCRYPT_VERSION))
1180     die ("exact version match failed");
1181   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
1182   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
1183
1184   basic ();
1185   canon_len ();
1186   back_and_forth ();
1187   check_sscan ();
1188   check_extract_param ();
1189   bug_1594 ();
1190
1191   return errorcount? 1:0;
1192 }