c4520e92d50b2574955b88c1a6fa33e98efa7dfa
[libgcrypt.git] / tests / keygen.c
1 /* keygen.c  -  key generation regression tests
2  * Copyright (C) 2003, 2005, 2012 Free Software Foundation, Inc.
3  * Copyright (C) 2013, 2015 g10 Code GmbH
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include "../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 static int in_fips_mode;
44
45
46 static void
47 die (const char *format, ...)
48 {
49   va_list arg_ptr ;
50
51   fflush (stdout);
52   fprintf (stderr, "%s: ", PGM);
53   va_start( arg_ptr, format ) ;
54   vfprintf (stderr, format, arg_ptr );
55   va_end(arg_ptr);
56   if (*format && format[strlen(format)-1] != '\n')
57     putc ('\n', stderr);
58   exit (1);
59 }
60
61 static void
62 fail (const char *format, ...)
63 {
64   va_list arg_ptr;
65
66   fflush (stdout);
67   fprintf (stderr, "%s: ", PGM);
68   /* if (wherestr) */
69   /*   fprintf (stderr, "%s: ", wherestr); */
70   va_start (arg_ptr, format);
71   vfprintf (stderr, format, arg_ptr);
72   va_end (arg_ptr);
73   if (*format && format[strlen(format)-1] != '\n')
74     putc ('\n', stderr);
75   error_count++;
76   if (error_count >= 50)
77     die ("stopped after 50 errors.");
78 }
79
80 static void
81 show (const char *format, ...)
82 {
83   va_list arg_ptr;
84
85   fprintf (stderr, "%s: ", PGM);
86   va_start (arg_ptr, format);
87   vfprintf (stderr, format, arg_ptr);
88   if (*format && format[strlen(format)-1] != '\n')
89     putc ('\n', stderr);
90   va_end (arg_ptr);
91 }
92
93
94 /* static void */
95 /* show_note (const char *format, ...) */
96 /* { */
97 /*   va_list arg_ptr; */
98
99 /*   if (!verbose && getenv ("srcdir")) */
100 /*     fputs ("      ", stderr);  /\* To align above "PASS: ".  *\/ */
101 /*   else */
102 /*     fprintf (stderr, "%s: ", PGM); */
103 /*   va_start (arg_ptr, format); */
104 /*   vfprintf (stderr, format, arg_ptr); */
105 /*   if (*format && format[strlen(format)-1] != '\n') */
106 /*     putc ('\n', stderr); */
107 /*   va_end (arg_ptr); */
108 /* } */
109
110
111 static void
112 show_sexp (const char *prefix, gcry_sexp_t a)
113 {
114   char *buf;
115   size_t size;
116
117   fprintf (stderr, "%s: ", PGM);
118   if (prefix)
119     fputs (prefix, stderr);
120   size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
121   buf = xmalloc (size);
122
123   gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
124   fprintf (stderr, "%.*s", (int)size, buf);
125   gcry_free (buf);
126 }
127
128
129 static void
130 show_mpi (const char *prefix, gcry_mpi_t a)
131 {
132   char *buf;
133   void *bufaddr = &buf;
134   gcry_error_t rc;
135
136   fprintf (stderr, "%s: ", PGM);
137   if (prefix)
138     fputs (prefix, stderr);
139   rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
140   if (rc)
141     fprintf (stderr, "[error printing number: %s]\n",  gpg_strerror (rc));
142   else
143     {
144       fprintf (stderr, "%s\n", buf);
145       gcry_free (buf);
146     }
147 }
148
149
150 static void
151 check_generated_rsa_key (gcry_sexp_t key, unsigned long expected_e)
152 {
153   gcry_sexp_t skey, pkey, list;
154
155   pkey = gcry_sexp_find_token (key, "public-key", 0);
156   if (!pkey)
157     fail ("public part missing in return value\n");
158   else
159     {
160       gcry_mpi_t e = NULL;
161
162       list = gcry_sexp_find_token (pkey, "e", 0);
163       if (!list || !(e=gcry_sexp_nth_mpi (list, 1, 0)) )
164         fail ("public exponent not found\n");
165       else if (!expected_e)
166         {
167           if (verbose)
168             show_mpi ("public exponent: ", e);
169         }
170       else if ( gcry_mpi_cmp_ui (e, expected_e))
171         {
172           show_mpi ("public exponent: ", e);
173           fail ("public exponent is not %lu\n", expected_e);
174         }
175       gcry_sexp_release (list);
176       gcry_mpi_release (e);
177       gcry_sexp_release (pkey);
178     }
179
180   skey = gcry_sexp_find_token (key, "private-key", 0);
181   if (!skey)
182     fail ("private part missing in return value\n");
183   else
184     {
185       int rc = gcry_pk_testkey (skey);
186       if (rc)
187         fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc));
188       gcry_sexp_release (skey);
189     }
190 }
191
192
193 static void
194 check_rsa_keys (void)
195 {
196   gcry_sexp_t keyparm, key;
197   int rc;
198
199   if (verbose)
200     show ("creating 2048 bit RSA key\n");
201   rc = gcry_sexp_new (&keyparm,
202                       "(genkey\n"
203                       " (rsa\n"
204                       "  (nbits 4:2048)\n"
205                       " ))", 0, 1);
206   if (rc)
207     die ("error creating S-expression: %s\n", gpg_strerror (rc));
208   rc = gcry_pk_genkey (&key, keyparm);
209   gcry_sexp_release (keyparm);
210   if (rc)
211     die ("error generating RSA key: %s\n", gpg_strerror (rc));
212
213   if (verbose)
214     show ("creating 1024 bit RSA key\n");
215   rc = gcry_sexp_new (&keyparm,
216                       "(genkey\n"
217                       " (rsa\n"
218                       "  (nbits 4:1024)\n"
219                       " ))", 0, 1);
220   if (rc)
221     die ("error creating S-expression: %s\n", gpg_strerror (rc));
222
223   gcry_sexp_release (key);
224   rc = gcry_pk_genkey (&key, keyparm);
225   gcry_sexp_release (keyparm);
226   if (rc && !in_fips_mode)
227     fail ("error generating RSA key: %s\n", gpg_strerror (rc));
228   else if (!rc && in_fips_mode)
229     fail ("generating 1024 bit RSA key must not work!");
230
231   if (!rc)
232     {
233       if (verbose > 1)
234         show_sexp ("1024 bit RSA key:\n", key);
235       check_generated_rsa_key (key, 65537);
236     }
237   gcry_sexp_release (key);
238
239   if (verbose)
240     show ("creating 2048 bit RSA key with e=65539\n");
241   rc = gcry_sexp_new (&keyparm,
242                       "(genkey\n"
243                       " (rsa\n"
244                       "  (nbits 4:2048)\n"
245                       "  (rsa-use-e 5:65539)\n"
246                       " ))", 0, 1);
247   if (rc)
248     die ("error creating S-expression: %s\n", gpg_strerror (rc));
249   rc = gcry_pk_genkey (&key, keyparm);
250   gcry_sexp_release (keyparm);
251   if (rc)
252     fail ("error generating RSA key: %s\n", gpg_strerror (rc));
253
254   if (!rc)
255     check_generated_rsa_key (key, 65539);
256   gcry_sexp_release (key);
257
258
259   if (verbose)
260     show ("creating 512 bit RSA key with e=257\n");
261   rc = gcry_sexp_new (&keyparm,
262                       "(genkey\n"
263                       " (rsa\n"
264                       "  (nbits 3:512)\n"
265                       "  (rsa-use-e 3:257)\n"
266                       " ))", 0, 1);
267   if (rc)
268     die ("error creating S-expression: %s\n", gpg_strerror (rc));
269   rc = gcry_pk_genkey (&key, keyparm);
270   gcry_sexp_release (keyparm);
271   if (rc && !in_fips_mode)
272     fail ("error generating RSA key: %s\n", gpg_strerror (rc));
273   else if (!rc && in_fips_mode)
274     fail ("generating 512 bit RSA key must not work!");
275
276   if (verbose && rc && in_fips_mode)
277     show ("... correctly rejected key creation in FIPS mode (%s)\n",
278           gpg_strerror (rc));
279
280   if (!rc)
281     check_generated_rsa_key (key, 257);
282   gcry_sexp_release (key);
283
284   if (verbose)
285     show ("creating 512 bit RSA key with default e\n");
286   rc = gcry_sexp_new (&keyparm,
287                       "(genkey\n"
288                       " (rsa\n"
289                       "  (nbits 3:512)\n"
290                       "  (rsa-use-e 1:0)\n"
291                       " ))", 0, 1);
292   if (rc)
293     die ("error creating S-expression: %s\n", gpg_strerror (rc));
294   rc = gcry_pk_genkey (&key, keyparm);
295   gcry_sexp_release (keyparm);
296   if (rc && !in_fips_mode)
297     fail ("error generating RSA key: %s\n", gpg_strerror (rc));
298   else if (!rc && in_fips_mode)
299     fail ("generating 512 bit RSA key must not work!");
300
301   if (verbose && rc && in_fips_mode)
302     show ("... correctly rejected key creation in FIPS mode (%s)\n",
303           gpg_strerror (rc));
304
305
306   if (!rc)
307     check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */
308   gcry_sexp_release (key);
309 }
310
311
312 static void
313 check_elg_keys (void)
314 {
315   gcry_sexp_t keyparm, key;
316   int rc;
317
318   if (verbose)
319     show ("creating 1024 bit Elgamal key\n");
320   rc = gcry_sexp_new (&keyparm,
321                       "(genkey\n"
322                       " (elg\n"
323                       "  (nbits 4:1024)\n"
324                       " ))", 0, 1);
325   if (rc)
326     die ("error creating S-expression: %s\n", gpg_strerror (rc));
327   rc = gcry_pk_genkey (&key, keyparm);
328   gcry_sexp_release (keyparm);
329   if (rc)
330     die ("error generating Elgamal key: %s\n", gpg_strerror (rc));
331   if (verbose > 1)
332     show_sexp ("1024 bit Elgamal key:\n", key);
333   gcry_sexp_release (key);
334 }
335
336
337 static void
338 check_dsa_keys (void)
339 {
340   gcry_sexp_t keyparm, key;
341   int rc;
342   int i;
343
344   /* Check that DSA generation works and that it can grok the qbits
345      argument. */
346   if (verbose)
347     show ("creating 5 1024 bit DSA keys\n");
348   for (i=0; i < 5; i++)
349     {
350       rc = gcry_sexp_new (&keyparm,
351                           "(genkey\n"
352                           " (dsa\n"
353                           "  (nbits 4:1024)\n"
354                           " ))", 0, 1);
355       if (rc)
356         die ("error creating S-expression: %s\n", gpg_strerror (rc));
357       rc = gcry_pk_genkey (&key, keyparm);
358       gcry_sexp_release (keyparm);
359       if (rc && !in_fips_mode)
360         die ("error generating DSA key: %s\n", gpg_strerror (rc));
361       else if (!rc && in_fips_mode)
362         die ("generating 1024 bit DSA key must not work!");
363       if (!i && verbose > 1)
364         show_sexp ("1024 bit DSA key:\n", key);
365       gcry_sexp_release (key);
366     }
367
368   if (verbose)
369     show ("creating 1536 bit DSA key\n");
370   rc = gcry_sexp_new (&keyparm,
371                       "(genkey\n"
372                       " (dsa\n"
373                       "  (nbits 4:1536)\n"
374                       "  (qbits 3:224)\n"
375                       " ))", 0, 1);
376   if (rc)
377     die ("error creating S-expression: %s\n", gpg_strerror (rc));
378   rc = gcry_pk_genkey (&key, keyparm);
379   gcry_sexp_release (keyparm);
380   if (rc && !in_fips_mode)
381     die ("error generating DSA key: %s\n", gpg_strerror (rc));
382   else if (!rc && in_fips_mode)
383     die ("generating 1536 bit DSA key must not work!");
384   if (verbose > 1)
385     show_sexp ("1536 bit DSA key:\n", key);
386   gcry_sexp_release (key);
387
388   if (verbose)
389     show ("creating 3072 bit DSA key\n");
390   rc = gcry_sexp_new (&keyparm,
391                       "(genkey\n"
392                       " (dsa\n"
393                       "  (nbits 4:3072)\n"
394                       "  (qbits 3:256)\n"
395                       " ))", 0, 1);
396   if (rc)
397     die ("error creating S-expression: %s\n", gpg_strerror (rc));
398   rc = gcry_pk_genkey (&key, keyparm);
399   gcry_sexp_release (keyparm);
400   if (rc)
401     die ("error generating DSA key: %s\n", gpg_strerror (rc));
402   if (verbose > 1)
403     show_sexp ("3072 bit DSA key:\n", key);
404   gcry_sexp_release (key);
405
406   if (verbose)
407     show ("creating 2048/256 bit DSA key\n");
408   rc = gcry_sexp_new (&keyparm,
409                       "(genkey\n"
410                       " (dsa\n"
411                       "  (nbits 4:2048)\n"
412                       "  (qbits 3:256)\n"
413                       " ))", 0, 1);
414   if (rc)
415     die ("error creating S-expression: %s\n", gpg_strerror (rc));
416   rc = gcry_pk_genkey (&key, keyparm);
417   gcry_sexp_release (keyparm);
418   if (rc)
419     die ("error generating DSA key: %s\n", gpg_strerror (rc));
420   if (verbose > 1)
421     show_sexp ("2048 bit DSA key:\n", key);
422   gcry_sexp_release (key);
423
424   if (verbose)
425     show ("creating 2048/224 bit DSA key\n");
426   rc = gcry_sexp_new (&keyparm,
427                       "(genkey\n"
428                       " (dsa\n"
429                       "  (nbits 4:2048)\n"
430                       "  (qbits 3:224)\n"
431                       " ))", 0, 1);
432   if (rc)
433     die ("error creating S-expression: %s\n", gpg_strerror (rc));
434   rc = gcry_pk_genkey (&key, keyparm);
435   gcry_sexp_release (keyparm);
436   if (rc)
437     die ("error generating DSA key: %s\n", gpg_strerror (rc));
438   if (verbose > 1)
439     show_sexp ("2048 bit DSA key:\n", key);
440   gcry_sexp_release (key);
441 }
442
443
444 static void
445 check_generated_ecc_key (gcry_sexp_t key)
446 {
447   gcry_sexp_t skey, pkey;
448
449   pkey = gcry_sexp_find_token (key, "public-key", 0);
450   if (!pkey)
451     fail ("public part missing in return value\n");
452   else
453     {
454       /* Fixme: Check more stuff.  */
455       gcry_sexp_release (pkey);
456     }
457
458   skey = gcry_sexp_find_token (key, "private-key", 0);
459   if (!skey)
460     fail ("private part missing in return value\n");
461   else
462     {
463       int rc = gcry_pk_testkey (skey);
464       if (rc)
465         fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc));
466       gcry_sexp_release (skey);
467     }
468
469   /* Finally check that gcry_pk_testkey also works on the entire
470      S-expression.  */
471   {
472     int rc = gcry_pk_testkey (key);
473     if (rc)
474       fail ("gcry_pk_testkey failed on key pair: %s\n", gpg_strerror (rc));
475   }
476 }
477
478
479 static void
480 check_ecc_keys (void)
481 {
482   const char *curves[] = { "NIST P-521", "NIST P-384", "NIST P-256",
483                            "Ed25519", NULL };
484   int testno;
485   gcry_sexp_t keyparm, key;
486   int rc;
487
488   for (testno=0; curves[testno]; testno++)
489     {
490       if (verbose)
491         show ("creating ECC key using curve %s\n", curves[testno]);
492       if (!strcmp (curves[testno], "Ed25519"))
493         {
494           /* Ed25519 isn't allowed in fips mode */
495           if (in_fips_mode)
496             continue;
497           rc = gcry_sexp_build (&keyparm, NULL,
498                                 "(genkey(ecc(curve %s)(flags param eddsa)))",
499                                 curves[testno]);
500         }
501       else
502         rc = gcry_sexp_build (&keyparm, NULL,
503                               "(genkey(ecc(curve %s)(flags param)))",
504                               curves[testno]);
505       if (rc)
506         die ("error creating S-expression: %s\n", gpg_strerror (rc));
507       rc = gcry_pk_genkey (&key, keyparm);
508       gcry_sexp_release (keyparm);
509       if (rc)
510         die ("error generating ECC key using curve %s: %s\n",
511              curves[testno], gpg_strerror (rc));
512
513       if (verbose > 1)
514         show_sexp ("ECC key:\n", key);
515
516       check_generated_ecc_key (key);
517
518       gcry_sexp_release (key);
519     }
520
521   if (verbose)
522     show ("creating ECC key using curve Ed25519 for ECDSA\n");
523   rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve Ed25519)))");
524   if (rc)
525     die ("error creating S-expression: %s\n", gpg_strerror (rc));
526   rc = gcry_pk_genkey (&key, keyparm);
527   gcry_sexp_release (keyparm);
528   if (rc && !in_fips_mode)
529     die ("error generating ECC key using curve Ed25519 for ECDSA: %s\n",
530          gpg_strerror (rc));
531   else if (!rc && in_fips_mode)
532     fail ("generating Ed25519 key must not work!");
533
534   if (verbose && rc && in_fips_mode)
535     show ("... correctly rejected key creation in FIPS mode (%s)\n",
536           gpg_strerror (rc));
537
538   if (!rc)
539     {
540       if (verbose > 1)
541         show_sexp ("ECC key:\n", key);
542
543       check_generated_ecc_key (key);
544     }
545   gcry_sexp_release (key);
546
547   if (verbose)
548     show ("creating ECC key using curve Ed25519 for ECDSA (nocomp)\n");
549   rc = gcry_sexp_build (&keyparm, NULL,
550                         "(genkey(ecc(curve Ed25519)(flags nocomp)))");
551   if (rc)
552     die ("error creating S-expression: %s\n", gpg_strerror (rc));
553   rc = gcry_pk_genkey (&key, keyparm);
554   gcry_sexp_release (keyparm);
555   if (rc && !in_fips_mode)
556     die ("error generating ECC key using curve Ed25519 for ECDSA"
557          " (nocomp): %s\n",
558          gpg_strerror (rc));
559   else if (!rc && in_fips_mode)
560     fail ("generating Ed25519 key must not work in FIPS mode!");
561
562   if (verbose && rc && in_fips_mode)
563     show ("... correctly rejected key creation in FIPS mode (%s)\n",
564           gpg_strerror (rc));
565   gcry_sexp_release (key);
566
567   if (verbose)
568     show ("creating ECC key using curve NIST P-384 for ECDSA\n");
569
570   /* Must be specified as nistp384 (one word), because ecc_generate
571    * uses _gcry_sexp_nth_string which takes the first word of the name
572    * and thus libgcrypt can't find it later in its curves table.  */
573   rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve nistp384)))");
574   if (rc)
575     die ("error creating S-expression: %s\n", gpg_strerror (rc));
576   rc = gcry_pk_genkey (&key, keyparm);
577   gcry_sexp_release (keyparm);
578   if (rc)
579     die ("error generating ECC key using curve NIST P-384 for ECDSA: %s\n",
580          gpg_strerror (rc));
581
582   if (verbose > 1)
583     show_sexp ("ECC key:\n", key);
584
585   check_generated_ecc_key (key);
586   gcry_sexp_release (key);
587
588   if (verbose)
589     show ("creating ECC key using curve NIST P-384 for ECDSA (nocomp)\n");
590   rc = gcry_sexp_build (&keyparm, NULL,
591                         "(genkey(ecc(curve nistp384)(flags nocomp)))");
592   if (rc)
593     die ("error creating S-expression: %s\n", gpg_strerror (rc));
594   rc = gcry_pk_genkey (&key, keyparm);
595   gcry_sexp_release (keyparm);
596   if (rc)
597     die ("error generating ECC key using curve NIST P-384 for ECDSA"
598          " (nocomp): %s\n",
599          gpg_strerror (rc));
600
601   if (verbose > 1)
602     show_sexp ("ECC key:\n", key);
603
604   check_generated_ecc_key (key);
605   gcry_sexp_release (key);
606
607
608   if (verbose)
609     show ("creating ECC key using curve Ed25519 for ECDSA (transient-key)\n");
610   rc = gcry_sexp_build (&keyparm, NULL,
611                         "(genkey(ecc(curve Ed25519)(flags transient-key)))");
612   if (rc)
613     die ("error creating S-expression: %s\n", gpg_strerror (rc));
614   rc = gcry_pk_genkey (&key, keyparm);
615   gcry_sexp_release (keyparm);
616   if (rc && !in_fips_mode)
617     die ("error generating ECC key using curve Ed25519 for ECDSA"
618          " (transient-key): %s\n",
619          gpg_strerror (rc));
620   else if (!rc && in_fips_mode)
621     fail ("generating Ed25519 key must not work in FIPS mode!");
622
623   if (verbose && rc && in_fips_mode)
624     show ("... correctly rejected key creation in FIPS mode (%s)\n",
625           gpg_strerror (rc));
626
627   if (!rc)
628     {
629       if (verbose > 1)
630         show_sexp ("ECC key:\n", key);
631       check_generated_ecc_key (key);
632     }
633   gcry_sexp_release (key);
634
635   if (verbose)
636     show ("creating ECC key using curve Ed25519 for ECDSA "
637           "(transient-key no-keytest)\n");
638   rc = gcry_sexp_build (&keyparm, NULL,
639                         "(genkey(ecc(curve Ed25519)"
640                         "(flags transient-key no-keytest)))");
641   if (rc)
642     die ("error creating S-expression: %s\n", gpg_strerror (rc));
643   rc = gcry_pk_genkey (&key, keyparm);
644   gcry_sexp_release (keyparm);
645   if (rc && !in_fips_mode)
646     die ("error generating ECC key using curve Ed25519 for ECDSA"
647          " (transient-key no-keytest): %s\n",
648          gpg_strerror (rc));
649   else if (!rc && in_fips_mode)
650     fail ("generating Ed25519 key must not work in FIPS mode!");
651
652   if (verbose && rc && in_fips_mode)
653     show ("... correctly rejected key creation in FIPS mode (%s)\n",
654           gpg_strerror (rc));
655
656   if (!rc)
657     {
658       if (verbose > 1)
659         show_sexp ("ECC key:\n", key);
660       check_generated_ecc_key (key);
661     }
662   gcry_sexp_release (key);
663 }
664
665
666 static void
667 check_nonce (void)
668 {
669   char a[32], b[32];
670   int i,j;
671   int oops=0;
672
673   if (verbose)
674     show ("checking gcry_create_nonce\n");
675
676   gcry_create_nonce (a, sizeof a);
677   for (i=0; i < 10; i++)
678     {
679       gcry_create_nonce (b, sizeof b);
680       if (!memcmp (a, b, sizeof a))
681         die ("identical nonce found\n");
682     }
683   for (i=0; i < 10; i++)
684     {
685       gcry_create_nonce (a, sizeof a);
686       if (!memcmp (a, b, sizeof a))
687         die ("identical nonce found\n");
688     }
689
690  again:
691   for (i=1,j=0; i < sizeof a; i++)
692     if (a[0] == a[i])
693       j++;
694   if (j+1 == sizeof (a))
695     {
696       if (oops)
697         die ("impossible nonce found\n");
698       oops++;
699       gcry_create_nonce (a, sizeof a);
700       goto again;
701     }
702 }
703
704
705 static void
706 progress_cb (void *cb_data, const char *what, int printchar,
707                   int current, int total)
708 {
709   (void)cb_data;
710   (void)what;
711   (void)current;
712   (void)total;
713
714   if (printchar == '\n')
715     fputs ( "<LF>", stdout);
716   else
717     putchar (printchar);
718   fflush (stdout);
719 }
720
721
722 static void
723 usage (int mode)
724 {
725   fputs ("usage: " PGM " [options] [{rsa|elg|dsa|ecc|nonce}]\n"
726          "Options:\n"
727          "  --verbose       be verbose\n"
728          "  --debug         flyswatter\n"
729          "  --fips          run in FIPS mode\n"
730          "  --progress      print progress indicators\n",
731          mode? stderr : stdout);
732   if (mode)
733     exit (1);
734 }
735
736 int
737 main (int argc, char **argv)
738 {
739   int last_argc = -1;
740   int opt_fips = 0;
741   int with_progress = 0;
742
743   if (argc)
744     { argc--; argv++; }
745
746   while (argc && last_argc != argc )
747     {
748       last_argc = argc;
749       if (!strcmp (*argv, "--"))
750         {
751           argc--; argv++;
752           break;
753         }
754       else if (!strcmp (*argv, "--help"))
755         {
756           usage (0);
757           exit (0);
758         }
759       else if (!strcmp (*argv, "--verbose"))
760         {
761           verbose++;
762           argc--; argv++;
763         }
764       else if (!strcmp (*argv, "--debug"))
765         {
766           verbose += 2;
767           debug++;
768           argc--; argv++;
769         }
770       else if (!strcmp (*argv, "--fips"))
771         {
772           argc--; argv++;
773           opt_fips = 1;
774         }
775       else if (!strcmp (*argv, "--progress"))
776         {
777           argc--; argv++;
778           with_progress = 1;
779         }
780       else if (!strncmp (*argv, "--", 2))
781         die ("unknown option '%s'", *argv);
782       else
783         break;
784     }
785
786   gcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
787   if (opt_fips)
788     gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
789
790   if (!gcry_check_version (GCRYPT_VERSION))
791     die ("version mismatch\n");
792
793   if (!opt_fips)
794     gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
795
796   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
797   if (debug)
798     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
799   /* No valuable keys are create, so we can speed up our RNG. */
800   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
801   if (with_progress)
802     gcry_set_progress_handler (progress_cb, NULL);
803
804   if ( gcry_fips_mode_active () )
805     in_fips_mode = 1;
806
807   if (opt_fips && !in_fips_mode)
808     die ("failed to switch into FIPS mode\n");
809
810   if (!argc)
811     {
812       check_rsa_keys ();
813       check_elg_keys ();
814       check_dsa_keys ();
815       check_ecc_keys ();
816       check_nonce ();
817     }
818   else
819     {
820       for (; argc; argc--, argv++)
821         if (!strcmp (*argv, "rsa"))
822           check_rsa_keys ();
823         else if (!strcmp (*argv, "elg"))
824           check_elg_keys ();
825         else if (!strcmp (*argv, "dsa"))
826           check_dsa_keys ();
827         else if (!strcmp (*argv, "ecc"))
828           check_ecc_keys ();
829         else if (!strcmp (*argv, "nonce"))
830           check_nonce ();
831         else
832           usage (1);
833     }
834
835   return error_count? 1:0;
836 }