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