tests: Beautify some diagnostics.
[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
399
400 static void
401 check_nonce (void)
402 {
403   char a[32], b[32];
404   int i,j;
405   int oops=0;
406
407   if (verbose)
408     show ("checking gcry_create_nonce\n");
409
410   gcry_create_nonce (a, sizeof a);
411   for (i=0; i < 10; i++)
412     {
413       gcry_create_nonce (b, sizeof b);
414       if (!memcmp (a, b, sizeof a))
415         die ("identical nonce found\n");
416     }
417   for (i=0; i < 10; i++)
418     {
419       gcry_create_nonce (a, sizeof a);
420       if (!memcmp (a, b, sizeof a))
421         die ("identical nonce found\n");
422     }
423
424  again:
425   for (i=1,j=0; i < sizeof a; i++)
426     if (a[0] == a[i])
427       j++;
428   if (j+1 == sizeof (a))
429     {
430       if (oops)
431         die ("impossible nonce found\n");
432       oops++;
433       gcry_create_nonce (a, sizeof a);
434       goto again;
435     }
436 }
437
438
439 static void
440 progress_cb (void *cb_data, const char *what, int printchar,
441                   int current, int total)
442 {
443   (void)cb_data;
444   (void)what;
445   (void)current;
446   (void)total;
447
448   if (printchar == '\n')
449     fputs ( "<LF>", stdout);
450   else
451     putchar (printchar);
452   fflush (stdout);
453 }
454
455
456 int
457 main (int argc, char **argv)
458 {
459   int last_argc = -1;
460   int with_progress = 0;
461
462   if (argc)
463     { argc--; argv++; }
464
465   while (argc && last_argc != argc )
466     {
467       last_argc = argc;
468       if (!strcmp (*argv, "--"))
469         {
470           argc--; argv++;
471           break;
472         }
473       else if (!strcmp (*argv, "--help"))
474         {
475           fputs ("usage: " PGM " [options]\n"
476                  "Options:\n"
477                  "  --verbose       be verbose\n"
478                  "  --debug         flyswatter\n"
479                  "  --progress      print progress indicators\n",
480                  stdout);
481           exit (0);
482         }
483       else if (!strcmp (*argv, "--verbose"))
484         {
485           verbose++;
486           argc--; argv++;
487         }
488       else if (!strcmp (*argv, "--debug"))
489         {
490           verbose += 2;
491           debug++;
492           argc--; argv++;
493         }
494       else if (!strcmp (*argv, "--progress"))
495         {
496           argc--; argv++;
497           with_progress = 1;
498         }
499       else if (!strncmp (*argv, "--", 2))
500         die ("unknown option '%s'", *argv);
501     }
502
503   if (!gcry_check_version (GCRYPT_VERSION))
504     die ("version mismatch\n");
505   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
506   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
507   if (debug)
508     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
509   /* No valuable keys are create, so we can speed up our RNG. */
510   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
511   if (with_progress)
512     gcry_set_progress_handler (progress_cb, NULL);
513
514   check_rsa_keys ();
515   check_elg_keys ();
516   check_dsa_keys ();
517   check_ecc_keys ();
518   check_nonce ();
519
520   return error_count? 1:0;
521 }