tests: Add test options to keygen.
[libgcrypt.git] / tests / keygen.c
1 /* keygen.c  -  key generation regression tests
2  * Copyright (C) 2003, 2005, 2012 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 "../src/gcrypt-int.h"
29
30
31 #define PGM "keygen"
32
33 #define xmalloc(a)    gcry_xmalloc ((a))
34 #define xcalloc(a,b)  gcry_xcalloc ((a),(b))
35 #define xstrdup(a)    gcry_xstrdup ((a))
36 #define xfree(a)      gcry_free ((a))
37 #define pass()        do { ; } while (0)
38
39
40 static int verbose;
41 static int debug;
42 static int error_count;
43
44
45 static void
46 die (const char *format, ...)
47 {
48   va_list arg_ptr ;
49
50   fflush (stdout);
51   fprintf (stderr, "%s: ", PGM);
52   va_start( arg_ptr, format ) ;
53   vfprintf (stderr, format, arg_ptr );
54   va_end(arg_ptr);
55   if (*format && format[strlen(format)-1] != '\n')
56     putc ('\n', stderr);
57   exit (1);
58 }
59
60 static void
61 fail (const char *format, ...)
62 {
63   va_list arg_ptr;
64
65   fflush (stdout);
66   fprintf (stderr, "%s: ", PGM);
67   /* if (wherestr) */
68   /*   fprintf (stderr, "%s: ", wherestr); */
69   va_start (arg_ptr, format);
70   vfprintf (stderr, format, arg_ptr);
71   va_end (arg_ptr);
72   if (*format && format[strlen(format)-1] != '\n')
73     putc ('\n', stderr);
74   error_count++;
75   if (error_count >= 50)
76     die ("stopped after 50 errors.");
77 }
78
79 static void
80 show (const char *format, ...)
81 {
82   va_list arg_ptr;
83
84   fprintf (stderr, "%s: ", PGM);
85   va_start (arg_ptr, format);
86   vfprintf (stderr, format, arg_ptr);
87   if (*format && format[strlen(format)-1] != '\n')
88     putc ('\n', stderr);
89   va_end (arg_ptr);
90 }
91
92
93 static void
94 show_note (const char *format, ...)
95 {
96   va_list arg_ptr;
97
98   if (!verbose && getenv ("srcdir"))
99     fputs ("      ", stderr);  /* To align above "PASS: ".  */
100   else
101     fprintf (stderr, "%s: ", PGM);
102   va_start (arg_ptr, format);
103   vfprintf (stderr, format, arg_ptr);
104   if (*format && format[strlen(format)-1] != '\n')
105     putc ('\n', stderr);
106   va_end (arg_ptr);
107 }
108
109
110 static void
111 show_sexp (const char *prefix, gcry_sexp_t a)
112 {
113   char *buf;
114   size_t size;
115
116   fprintf (stderr, "%s: ", PGM);
117   if (prefix)
118     fputs (prefix, stderr);
119   size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
120   buf = xmalloc (size);
121
122   gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
123   fprintf (stderr, "%.*s", (int)size, buf);
124   gcry_free (buf);
125 }
126
127
128 static void
129 show_mpi (const char *prefix, gcry_mpi_t a)
130 {
131   char *buf;
132   void *bufaddr = &buf;
133   gcry_error_t rc;
134
135   fprintf (stderr, "%s: ", PGM);
136   if (prefix)
137     fputs (prefix, stderr);
138   rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
139   if (rc)
140     fprintf (stderr, "[error printing number: %s]\n",  gpg_strerror (rc));
141   else
142     {
143       fprintf (stderr, "%s\n", buf);
144       gcry_free (buf);
145     }
146 }
147
148
149 static void
150 check_generated_rsa_key (gcry_sexp_t key, unsigned long expected_e)
151 {
152   gcry_sexp_t skey, pkey, list;
153
154   pkey = gcry_sexp_find_token (key, "public-key", 0);
155   if (!pkey)
156     fail ("public part missing in return value\n");
157   else
158     {
159       gcry_mpi_t e = NULL;
160
161       list = gcry_sexp_find_token (pkey, "e", 0);
162       if (!list || !(e=gcry_sexp_nth_mpi (list, 1, 0)) )
163         fail ("public exponent not found\n");
164       else if (!expected_e)
165         {
166           if (verbose)
167             show_mpi ("public exponent: ", e);
168         }
169       else if ( gcry_mpi_cmp_ui (e, expected_e))
170         {
171           show_mpi ("public exponent: ", e);
172           fail ("public exponent is not %lu\n", expected_e);
173         }
174       gcry_sexp_release (list);
175       gcry_mpi_release (e);
176       gcry_sexp_release (pkey);
177     }
178
179   skey = gcry_sexp_find_token (key, "private-key", 0);
180   if (!skey)
181     fail ("private part missing in return value\n");
182   else
183     {
184       int rc = gcry_pk_testkey (skey);
185       if (rc)
186         fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc));
187       gcry_sexp_release (skey);
188     }
189 }
190
191
192 static void
193 check_rsa_keys (void)
194 {
195   gcry_sexp_t keyparm, key;
196   int rc;
197
198   if (verbose)
199     show ("creating 1024 bit RSA key\n");
200   rc = gcry_sexp_new (&keyparm,
201                       "(genkey\n"
202                       " (rsa\n"
203                       "  (nbits 4:1024)\n"
204                       " ))", 0, 1);
205   if (rc)
206     die ("error creating S-expression: %s\n", gpg_strerror (rc));
207   rc = gcry_pk_genkey (&key, keyparm);
208   gcry_sexp_release (keyparm);
209   if (rc)
210     die ("error generating RSA key: %s\n", gpg_strerror (rc));
211   if (verbose > 1)
212     show_sexp ("1024 bit RSA key:\n", key);
213   check_generated_rsa_key (key, 65537);
214   gcry_sexp_release (key);
215
216
217   if (verbose)
218     show ("creating 512 bit RSA key with e=257\n");
219   rc = gcry_sexp_new (&keyparm,
220                       "(genkey\n"
221                       " (rsa\n"
222                       "  (nbits 3:512)\n"
223                       "  (rsa-use-e 3:257)\n"
224                       " ))", 0, 1);
225   if (rc)
226     die ("error creating S-expression: %s\n", gpg_strerror (rc));
227   rc = gcry_pk_genkey (&key, keyparm);
228   gcry_sexp_release (keyparm);
229   if (rc)
230     die ("error generating RSA key: %s\n", gpg_strerror (rc));
231
232   check_generated_rsa_key (key, 257);
233   gcry_sexp_release (key);
234
235   if (verbose)
236     show ("creating 512 bit RSA key with default e\n");
237   rc = gcry_sexp_new (&keyparm,
238                       "(genkey\n"
239                       " (rsa\n"
240                       "  (nbits 3:512)\n"
241                       "  (rsa-use-e 1:0)\n"
242                       " ))", 0, 1);
243   if (rc)
244     die ("error creating S-expression: %s\n", gpg_strerror (rc));
245   rc = gcry_pk_genkey (&key, keyparm);
246   gcry_sexp_release (keyparm);
247   if (rc)
248     die ("error generating RSA key: %s\n", gpg_strerror (rc));
249
250   check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */
251   gcry_sexp_release (key);
252 }
253
254
255 static void
256 check_elg_keys (void)
257 {
258   gcry_sexp_t keyparm, key;
259   int rc;
260
261   if (verbose)
262     show ("creating 1024 bit Elgamal key\n");
263   rc = gcry_sexp_new (&keyparm,
264                       "(genkey\n"
265                       " (elg\n"
266                       "  (nbits 4:1024)\n"
267                       " ))", 0, 1);
268   if (rc)
269     die ("error creating S-expression: %s\n", gpg_strerror (rc));
270   rc = gcry_pk_genkey (&key, keyparm);
271   gcry_sexp_release (keyparm);
272   if (rc)
273     die ("error generating Elgamal key: %s\n", gpg_strerror (rc));
274   if (verbose > 1)
275     show_sexp ("1024 bit Elgamal key:\n", key);
276   gcry_sexp_release (key);
277 }
278
279
280 static void
281 check_dsa_keys (void)
282 {
283   gcry_sexp_t keyparm, key;
284   int rc;
285   int i;
286
287   /* Check that DSA generation works and that it can grok the qbits
288      argument. */
289   if (verbose)
290     show ("creating 5 1024 bit DSA keys\n");
291   for (i=0; i < 5; i++)
292     {
293       rc = gcry_sexp_new (&keyparm,
294                           "(genkey\n"
295                           " (dsa\n"
296                           "  (nbits 4:1024)\n"
297                           " ))", 0, 1);
298       if (rc)
299         die ("error creating S-expression: %s\n", gpg_strerror (rc));
300       rc = gcry_pk_genkey (&key, keyparm);
301       gcry_sexp_release (keyparm);
302       if (rc)
303         die ("error generating DSA key: %s\n", gpg_strerror (rc));
304       if (!i && verbose > 1)
305         show_sexp ("1024 bit DSA key:\n", key);
306       gcry_sexp_release (key);
307     }
308
309   if (verbose)
310     show ("creating 1536 bit DSA key\n");
311   rc = gcry_sexp_new (&keyparm,
312                       "(genkey\n"
313                       " (dsa\n"
314                       "  (nbits 4:1536)\n"
315                       "  (qbits 3:224)\n"
316                       " ))", 0, 1);
317   if (rc)
318     die ("error creating S-expression: %s\n", gpg_strerror (rc));
319   rc = gcry_pk_genkey (&key, keyparm);
320   gcry_sexp_release (keyparm);
321   if (rc)
322     die ("error generating DSA key: %s\n", gpg_strerror (rc));
323   if (verbose > 1)
324     show_sexp ("1536 bit DSA key:\n", key);
325   gcry_sexp_release (key);
326 }
327
328
329 static void
330 check_generated_ecc_key (gcry_sexp_t key)
331 {
332   gcry_sexp_t skey, pkey;
333
334   pkey = gcry_sexp_find_token (key, "public-key", 0);
335   if (!pkey)
336     fail ("public part missing in return value\n");
337   else
338     {
339       /* Fixme: Check more stuff.  */
340       gcry_sexp_release (pkey);
341     }
342
343   skey = gcry_sexp_find_token (key, "private-key", 0);
344   if (!skey)
345     fail ("private part missing in return value\n");
346   else
347     {
348       int rc = gcry_pk_testkey (skey);
349       if (rc)
350         fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc));
351       gcry_sexp_release (skey);
352     }
353
354   /* Finally check that gcry_pk_testkey also works on the entire
355      S-expression.  */
356   {
357     int rc = gcry_pk_testkey (key);
358     if (rc)
359       fail ("gcry_pk_testkey failed on key pair: %s\n", gpg_strerror (rc));
360   }
361 }
362
363
364 static void
365 check_ecc_keys (void)
366 {
367   const char *curves[] = { "NIST P-521", "NIST P-384", "NIST P-256",
368                            "Ed25519", NULL };
369   int testno;
370   gcry_sexp_t keyparm, key;
371   int rc;
372
373   for (testno=0; curves[testno]; testno++)
374     {
375       if (verbose)
376         show ("creating ECC key using curve %s\n", curves[testno]);
377       rc = gcry_sexp_build (&keyparm, NULL,
378                             "(genkey(ecc(curve %s)))", curves[testno]);
379       if (rc)
380         die ("error creating S-expression: %s\n", gpg_strerror (rc));
381       rc = gcry_pk_genkey (&key, keyparm);
382       gcry_sexp_release (keyparm);
383       if (rc)
384         die ("error generating ECC key using curve %s: %s\n",
385              curves[testno], gpg_strerror (rc));
386
387       if (verbose > 1)
388         show_sexp ("ECC key:\n", key);
389
390       if (!strcmp (curves[testno], "Ed25519"))
391         show_note ("note: gcry_pk_testkey does not yet work for Ed25519\n");
392       else
393         check_generated_ecc_key (key);
394
395       gcry_sexp_release (key);
396     }
397
398   if (verbose)
399     show ("creating ECC key using curve Ed25519 for ECDSA\n");
400   rc = gcry_sexp_build (&keyparm, NULL,
401                         "(genkey(ecc(curve Ed25519)(flags ecdsa)))");
402   if (rc)
403     die ("error creating S-expression: %s\n", gpg_strerror (rc));
404   rc = gcry_pk_genkey (&key, keyparm);
405   gcry_sexp_release (keyparm);
406   if (rc)
407     die ("error generating ECC key using curve Ed25519 for ECDSA: %s\n",
408          gpg_strerror (rc));
409
410   if (verbose > 1)
411     show_sexp ("ECC key:\n", key);
412
413   gcry_sexp_release (key);
414 }
415
416
417 static void
418 check_nonce (void)
419 {
420   char a[32], b[32];
421   int i,j;
422   int oops=0;
423
424   if (verbose)
425     show ("checking gcry_create_nonce\n");
426
427   gcry_create_nonce (a, sizeof a);
428   for (i=0; i < 10; i++)
429     {
430       gcry_create_nonce (b, sizeof b);
431       if (!memcmp (a, b, sizeof a))
432         die ("identical nonce found\n");
433     }
434   for (i=0; i < 10; i++)
435     {
436       gcry_create_nonce (a, sizeof a);
437       if (!memcmp (a, b, sizeof a))
438         die ("identical nonce found\n");
439     }
440
441  again:
442   for (i=1,j=0; i < sizeof a; i++)
443     if (a[0] == a[i])
444       j++;
445   if (j+1 == sizeof (a))
446     {
447       if (oops)
448         die ("impossible nonce found\n");
449       oops++;
450       gcry_create_nonce (a, sizeof a);
451       goto again;
452     }
453 }
454
455
456 static void
457 progress_cb (void *cb_data, const char *what, int printchar,
458                   int current, int total)
459 {
460   (void)cb_data;
461   (void)what;
462   (void)current;
463   (void)total;
464
465   if (printchar == '\n')
466     fputs ( "<LF>", stdout);
467   else
468     putchar (printchar);
469   fflush (stdout);
470 }
471
472
473 static void
474 usage (int mode)
475 {
476   fputs ("usage: " PGM " [options] [{rsa|elg|dsa|ecc|nonce}]\n"
477          "Options:\n"
478          "  --verbose       be verbose\n"
479          "  --debug         flyswatter\n"
480          "  --progress      print progress indicators\n",
481          mode? stderr : stdout);
482   if (mode)
483     exit (1);
484 }
485
486 int
487 main (int argc, char **argv)
488 {
489   int last_argc = -1;
490   int with_progress = 0;
491
492   if (argc)
493     { argc--; argv++; }
494
495   while (argc && last_argc != argc )
496     {
497       last_argc = argc;
498       if (!strcmp (*argv, "--"))
499         {
500           argc--; argv++;
501           break;
502         }
503       else if (!strcmp (*argv, "--help"))
504         {
505           usage (0);
506           exit (0);
507         }
508       else if (!strcmp (*argv, "--verbose"))
509         {
510           verbose++;
511           argc--; argv++;
512         }
513       else if (!strcmp (*argv, "--debug"))
514         {
515           verbose += 2;
516           debug++;
517           argc--; argv++;
518         }
519       else if (!strcmp (*argv, "--progress"))
520         {
521           argc--; argv++;
522           with_progress = 1;
523         }
524       else if (!strncmp (*argv, "--", 2))
525         die ("unknown option '%s'", *argv);
526       else
527         break;
528     }
529
530   if (!gcry_check_version (GCRYPT_VERSION))
531     die ("version mismatch\n");
532   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
533   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
534   if (debug)
535     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
536   /* No valuable keys are create, so we can speed up our RNG. */
537   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
538   if (with_progress)
539     gcry_set_progress_handler (progress_cb, NULL);
540
541   if (!argc)
542     {
543       check_rsa_keys ();
544       check_elg_keys ();
545       check_dsa_keys ();
546       check_ecc_keys ();
547       check_nonce ();
548     }
549   else
550     {
551       for (; argc; argc--, argv++)
552         if (!strcmp (*argv, "rsa"))
553           check_rsa_keys ();
554         else if (!strcmp (*argv, "elg"))
555           check_elg_keys ();
556         else if (!strcmp (*argv, "dsa"))
557           check_dsa_keys ();
558         else if (!strcmp (*argv, "ecc"))
559           check_ecc_keys ();
560         else if (!strcmp (*argv, "nonce"))
561           check_nonce ();
562         else
563           usage (1);
564     }
565
566   return error_count? 1:0;
567 }