tests: Prevent rare failure of gcry_pk_decrypt test.
[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       "pab'gnq", 7,
688       GPG_ERR_SYNTAX
689     },
690     {
691       sample1,
692       NULL,
693       "pab''gnq", 7,
694       GPG_ERR_SYNTAX
695     },
696     {
697       sample1,
698       NULL,
699       "pabgnqd", 7,
700       0,
701       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
702       sample1_qx, sample1_d
703     },
704     {
705       sample1,
706       NULL,
707       "  pab\tg nq\nd  ", 7,
708       0,
709       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
710       sample1_qx, sample1_d
711     },
712     {
713       sample1,
714       NULL,
715       "abg", 3,
716       0,
717       sample1_ax, sample1_bx, sample1_gx
718     },
719     {
720       sample1,
721       NULL,
722       "ab'g'", 3,
723       0,
724       sample1_ax, sample1_bx, sample1_gx
725     },
726     {
727       sample1,
728       NULL,
729       "x?abg", 4,
730       0,
731       NULL, sample1_ax, sample1_bx, sample1_gx
732     },
733     {
734       sample1,
735       NULL,
736       "p?abg", 4,
737       GPG_ERR_USER_1,
738       NULL, sample1_ax, sample1_bx, sample1_gx
739     },
740     {
741       sample1,
742       NULL,
743       "pax?gnqd", 7,
744       0,
745       sample1_px, sample1_ax, NULL, sample1_gx, sample1_nx,
746       sample1_qx, sample1_d
747     },
748     {
749       sample1,
750       "public-key",
751       "pabgnqd", 7,
752       GPG_ERR_NO_OBJ,  /* d is not in public key.  */
753       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
754       sample1_qx, sample1_d
755     },
756     {
757       sample1,
758       "private-key",
759       "pabgnqd", 7,
760       0,
761       sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
762       sample1_q, sample1_d
763     },
764     {
765       sample1,
766       "public-key!ecc",
767       "pabgnq", 6,
768       0,
769       sample1_px, sample1_ax, sample1_bx, sample1_gx, sample1_nx,
770       sample1_qx
771     },
772     {
773       sample1,
774       "public-key!ecc!foo",
775       "pabgnq", 6,
776       GPG_ERR_NOT_FOUND
777     },
778     {
779       sample1,
780       "public-key!!ecc",
781       "pabgnq", 6,
782       GPG_ERR_NOT_FOUND
783     },
784     {
785       sample1,
786       "private-key",
787       "pa/bgnqd", 7,
788       0,
789       sample1_p, sample1_a, sample1_b, sample1_g, sample1_n,
790       sample1_q, sample1_d
791     },
792     {
793       sample1,
794       "private-key",
795       "p-a+bgnqd", 7,
796       0,
797       sample1_p, "-01", sample1_b, sample1_g, sample1_n,
798       sample1_q, sample1_d
799     },
800     {NULL}
801   };
802   int idx, i;
803   const char *paramstr;
804   int paramidx;
805   gpg_error_t err;
806   gcry_sexp_t sxp;
807   gcry_mpi_t mpis[7];
808   gcry_buffer_t ioarray[7];
809   char iobuffer[200];
810
811   info ("checking gcry_sexp_extract_param\n");
812   for (idx=0; tests[idx].sexp_str; idx++)
813     {
814       err = gcry_sexp_new (&sxp, tests[idx].sexp_str, 0, 1);
815       if (err)
816         die ("converting string to sexp failed: %s", gpg_strerror (err));
817
818       memset (mpis, 0, sizeof mpis);
819       switch (tests[idx].nparam)
820         {
821         case 0:
822           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
823                                          NULL);
824           break;
825         case 1:
826           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
827                                          mpis+0, NULL);
828           break;
829         case 2:
830           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
831                                          mpis+0, mpis+1, NULL);
832           break;
833         case 3:
834           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
835                                          mpis+0, mpis+1, mpis+2, NULL);
836           break;
837         case 4:
838           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
839                                          mpis+0, mpis+1, mpis+2, mpis+3, NULL);
840           break;
841         case 5:
842           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
843                                          mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
844                                          NULL);
845           break;
846         case 6:
847           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
848                                          mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
849                                          mpis+5, NULL);
850           break;
851         case 7:
852           err = gcry_sexp_extract_param (sxp, tests[idx].path, tests[idx].list,
853                                          mpis+0, mpis+1, mpis+2, mpis+3, mpis+4,
854                                          mpis+5, mpis+6, NULL);
855           break;
856         default:
857           die ("test %d: internal error", idx);
858         }
859
860       if (tests[idx].expected_err
861           && tests[idx].expected_err != GPG_ERR_USER_1)
862         {
863           if (tests[idx].expected_err != gpg_err_code (err))
864             fail ("gcry_sexp_extract_param test %d failed: "
865                   "expected error '%s' - got '%s'", idx,
866                   gpg_strerror (tests[idx].expected_err),gpg_strerror (err));
867
868         }
869       else if (err)
870         {
871           fail ("gcry_sexp_extract_param test %d failed: %s",
872                 idx, gpg_strerror (err));
873         }
874       else /* No error - check the extracted values.  */
875         {
876           for (paramidx=0; paramidx < DIM (mpis); paramidx++)
877             {
878               switch (paramidx)
879                 {
880                 case 0: paramstr = tests[idx].exp_p; break;
881                 case 1: paramstr = tests[idx].exp_a; break;
882                 case 2: paramstr = tests[idx].exp_b; break;
883                 case 3: paramstr = tests[idx].exp_g; break;
884                 case 4: paramstr = tests[idx].exp_n; break;
885                 case 5: paramstr = tests[idx].exp_q; break;
886                 case 6: paramstr = tests[idx].exp_d; break;
887                 default:
888                   die ("test %d: internal error: bad param %d",
889                        idx, paramidx);
890                 }
891
892               if (tests[idx].expected_err == GPG_ERR_USER_1
893                   && mpis[paramidx] && !paramstr && paramidx == 0)
894                 ; /* Okay  Special case error for param 0.  */
895               else if (!mpis[paramidx] && !paramstr)
896                 ; /* Okay.  */
897               else if (!mpis[paramidx] && paramstr)
898                 fail ("test %d: value for param %d expected but not returned",
899                       idx, paramidx);
900               else if (mpis[paramidx] && !paramstr)
901                 fail ("test %d: value for param %d not expected",
902                       idx, paramidx);
903               else if (cmp_mpihex (mpis[paramidx], paramstr))
904                 {
905                   fail ("test %d: param %d mismatch", idx, paramidx);
906                   gcry_log_debug    ("expected: %s\n", paramstr);
907                   gcry_log_debugmpi ("     got", mpis[paramidx]);
908                 }
909               else if (tests[idx].expected_err && paramidx == 0)
910                 fail ("test %d: param %d: expected error '%s' - got 'Success'",
911                       idx, paramidx, gpg_strerror (tests[idx].expected_err));
912             }
913
914         }
915
916       for (i=0; i < DIM (mpis); i++)
917         gcry_mpi_release (mpis[i]);
918       gcry_sexp_release (sxp);
919     }
920
921   info ("checking gcry_sexp_extract_param/desc\n");
922
923   memset (ioarray, 0, sizeof ioarray);
924
925   err = gcry_sexp_new (&sxp, sample1, 0, 1);
926   if (err)
927     die ("converting string to sexp failed: %s", gpg_strerror (err));
928
929   ioarray[1].size = sizeof iobuffer;
930   ioarray[1].data = iobuffer;
931   ioarray[1].off  = 0;
932   ioarray[2].size = sizeof iobuffer;
933   ioarray[2].data = iobuffer;
934   ioarray[2].off  = 50;
935   assert (ioarray[2].off < sizeof iobuffer);
936   err = gcry_sexp_extract_param (sxp, "key-data!private-key", "&pab",
937                                  ioarray+0, ioarray+1, ioarray+2, NULL);
938   if (err)
939     fail ("gcry_sexp_extract_param with desc failed: %s", gpg_strerror (err));
940   else
941     {
942       if (!ioarray[0].data)
943         fail ("gcry_sexp_extract_param/desc failed: no P");
944       else if (ioarray[0].size != 32)
945         fail ("gcry_sexp_extract_param/desc failed: P has wrong size");
946       else if (ioarray[0].len != 32)
947         fail ("gcry_sexp_extract_param/desc failed: P has wrong length");
948       else if (ioarray[0].off)
949         fail ("gcry_sexp_extract_param/desc failed: P has OFF set");
950       else if (cmp_bufhex (ioarray[0].data, ioarray[0].len, sample1_p))
951         {
952           fail ("gcry_sexp_extract_param/desc failed: P mismatch");
953           gcry_log_debug    ("expected: %s\n", sample1_p);
954           gcry_log_debughex ("     got", ioarray[0].data, ioarray[0].len);
955         }
956
957       if (!ioarray[1].data)
958         fail ("gcry_sexp_extract_param/desc failed: A buffer lost");
959       else if (ioarray[1].size != sizeof iobuffer)
960         fail ("gcry_sexp_extract_param/desc failed: A size changed");
961       else if (ioarray[1].off != 0)
962         fail ("gcry_sexp_extract_param/desc failed: A off changed");
963       else if (ioarray[1].len != 1)
964         fail ("gcry_sexp_extract_param/desc failed: A has wrong length");
965       else if (cmp_bufhex ((char *)ioarray[1].data + ioarray[1].off,
966                            ioarray[1].len, sample1_a))
967         {
968           fail ("gcry_sexp_extract_param/desc failed: A mismatch");
969           gcry_log_debug    ("expected: %s\n", sample1_a);
970           gcry_log_debughex ("     got",
971                              (char *)ioarray[1].data + ioarray[1].off,
972                              ioarray[1].len);
973         }
974
975       if (!ioarray[2].data)
976         fail ("gcry_sexp_extract_param/desc failed: B buffer lost");
977       else if (ioarray[2].size != sizeof iobuffer)
978         fail ("gcry_sexp_extract_param/desc failed: B size changed");
979       else if (ioarray[2].off != 50)
980         fail ("gcry_sexp_extract_param/desc failed: B off changed");
981       else if (ioarray[2].len != 32)
982         fail ("gcry_sexp_extract_param/desc failed: B has wrong length");
983       else if (cmp_bufhex ((char *)ioarray[2].data + ioarray[2].off,
984                            ioarray[2].len, sample1_b))
985         {
986           fail ("gcry_sexp_extract_param/desc failed: B mismatch");
987           gcry_log_debug    ("expected: %s\n", sample1_b);
988           gcry_log_debughex ("     got",
989                              (char *)ioarray[2].data + ioarray[2].off,
990                              ioarray[2].len);
991         }
992
993       xfree (ioarray[0].data);
994     }
995
996   gcry_sexp_release (sxp);
997
998   info ("checking gcry_sexp_extract_param long name\n");
999
1000   memset (ioarray, 0, sizeof ioarray);
1001   memset (mpis, 0, sizeof mpis);
1002
1003   err = gcry_sexp_new (&sxp, sample1, 0, 1);
1004   if (err)
1005     die ("converting string to sexp failed: %s", gpg_strerror (err));
1006
1007   err = gcry_sexp_extract_param (sxp, "key-data!private-key",
1008                                  "&'curve'+p",
1009                                  ioarray+0, mpis+0, NULL);
1010   if (err)
1011     fail ("gcry_sexp_extract_param long name failed: %s", gpg_strerror (err));
1012
1013   if (!ioarray[0].data)
1014     fail ("gcry_sexp_extract_param long name failed: no curve");
1015   else if (ioarray[0].size != 7)
1016     fail ("gcry_sexp_extract_param long name failed: curve has wrong size");
1017   else if (ioarray[0].len != 7)
1018     fail ("gcry_sexp_extract_param long name failed: curve has wrong length");
1019   else if (ioarray[0].off)
1020     fail ("gcry_sexp_extract_param long name failed: curve has OFF set");
1021   else if (strncmp (ioarray[0].data, "Ed25519", 7))
1022     {
1023       fail ("gcry_sexp_extract_param long name failed: curve mismatch");
1024       gcry_log_debug ("expected: %s\n", "Ed25519");
1025       gcry_log_debug ("     got: %.*s\n",
1026                       (int)ioarray[0].len, (char*)ioarray[0].data);
1027     }
1028
1029   if (!mpis[0])
1030     fail ("gcry_sexp_extract_param long name failed: p not returned");
1031   else if (cmp_mpihex (mpis[0], sample1_p))
1032     {
1033       fail ("gcry_sexp_extract_param long name failed: p mismatch");
1034       gcry_log_debug    ("expected: %s\n", sample1_p);
1035       gcry_log_debugmpi ("     got", mpis[0]);
1036     }
1037
1038   gcry_mpi_release (mpis[0]);
1039
1040   gcry_sexp_release (sxp);
1041
1042 }
1043
1044
1045 int
1046 main (int argc, char **argv)
1047 {
1048   if (argc > 1 && !strcmp (argv[1], "--verbose"))
1049     verbose = 1;
1050
1051   gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
1052   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
1053
1054   basic ();
1055   canon_len ();
1056   back_and_forth ();
1057   check_sscan ();
1058   check_extract_param ();
1059
1060   return error_count? 1:0;
1061 }