tests: Add options --fips to keygen for manual tests.
[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   rc = gcry_pk_genkey (&key, keyparm);
223   gcry_sexp_release (keyparm);
224   if (rc && !in_fips_mode)
225     fail ("error generating RSA key: %s\n", gpg_strerror (rc));
226   else if (!rc && in_fips_mode)
227     fail ("generating 1024 bit RSA key must not work!");
228
229   if (!rc)
230     {
231       if (verbose > 1)
232         show_sexp ("1024 bit RSA key:\n", key);
233       check_generated_rsa_key (key, 65537);
234     }
235   gcry_sexp_release (key);
236
237   if (verbose)
238     show ("creating 2048 bit RSA key with e=65539\n");
239   rc = gcry_sexp_new (&keyparm,
240                       "(genkey\n"
241                       " (rsa\n"
242                       "  (nbits 4:2048)\n"
243                       "  (rsa-use-e 5:65539)\n"
244                       " ))", 0, 1);
245   if (rc)
246     die ("error creating S-expression: %s\n", gpg_strerror (rc));
247   rc = gcry_pk_genkey (&key, keyparm);
248   gcry_sexp_release (keyparm);
249   if (rc)
250     fail ("error generating RSA key: %s\n", gpg_strerror (rc));
251
252   if (!rc)
253     check_generated_rsa_key (key, 65539);
254   gcry_sexp_release (key);
255
256
257   if (verbose)
258     show ("creating 512 bit RSA key with e=257\n");
259   rc = gcry_sexp_new (&keyparm,
260                       "(genkey\n"
261                       " (rsa\n"
262                       "  (nbits 3:512)\n"
263                       "  (rsa-use-e 3:257)\n"
264                       " ))", 0, 1);
265   if (rc)
266     die ("error creating S-expression: %s\n", gpg_strerror (rc));
267   rc = gcry_pk_genkey (&key, keyparm);
268   gcry_sexp_release (keyparm);
269   if (rc && !in_fips_mode)
270     fail ("error generating RSA key: %s\n", gpg_strerror (rc));
271   else if (!rc && in_fips_mode)
272     fail ("generating 512 bit RSA key must not work!");
273
274   if (verbose && rc && in_fips_mode)
275     show ("... correctly rejected key creation in FIPS mode (%s)\n",
276           gpg_strerror (rc));
277
278   if (!rc)
279     check_generated_rsa_key (key, 257);
280   gcry_sexp_release (key);
281
282   if (verbose)
283     show ("creating 512 bit RSA key with default e\n");
284   rc = gcry_sexp_new (&keyparm,
285                       "(genkey\n"
286                       " (rsa\n"
287                       "  (nbits 3:512)\n"
288                       "  (rsa-use-e 1:0)\n"
289                       " ))", 0, 1);
290   if (rc)
291     die ("error creating S-expression: %s\n", gpg_strerror (rc));
292   rc = gcry_pk_genkey (&key, keyparm);
293   gcry_sexp_release (keyparm);
294   if (rc && !in_fips_mode)
295     fail ("error generating RSA key: %s\n", gpg_strerror (rc));
296   else if (!rc && in_fips_mode)
297     fail ("generating 512 bit RSA key must not work!");
298
299   if (verbose && rc && in_fips_mode)
300     show ("... correctly rejected key creation in FIPS mode (%s)\n",
301           gpg_strerror (rc));
302
303
304   if (!rc)
305     check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */
306   gcry_sexp_release (key);
307 }
308
309
310 static void
311 check_elg_keys (void)
312 {
313   gcry_sexp_t keyparm, key;
314   int rc;
315
316   if (verbose)
317     show ("creating 1024 bit Elgamal key\n");
318   rc = gcry_sexp_new (&keyparm,
319                       "(genkey\n"
320                       " (elg\n"
321                       "  (nbits 4:1024)\n"
322                       " ))", 0, 1);
323   if (rc)
324     die ("error creating S-expression: %s\n", gpg_strerror (rc));
325   rc = gcry_pk_genkey (&key, keyparm);
326   gcry_sexp_release (keyparm);
327   if (rc)
328     die ("error generating Elgamal key: %s\n", gpg_strerror (rc));
329   if (verbose > 1)
330     show_sexp ("1024 bit Elgamal key:\n", key);
331   gcry_sexp_release (key);
332 }
333
334
335 static void
336 check_dsa_keys (void)
337 {
338   gcry_sexp_t keyparm, key;
339   int rc;
340   int i;
341
342   /* Check that DSA generation works and that it can grok the qbits
343      argument. */
344   if (verbose)
345     show ("creating 5 1024 bit DSA keys\n");
346   for (i=0; i < 5; i++)
347     {
348       rc = gcry_sexp_new (&keyparm,
349                           "(genkey\n"
350                           " (dsa\n"
351                           "  (nbits 4:1024)\n"
352                           " ))", 0, 1);
353       if (rc)
354         die ("error creating S-expression: %s\n", gpg_strerror (rc));
355       rc = gcry_pk_genkey (&key, keyparm);
356       gcry_sexp_release (keyparm);
357       if (rc && !in_fips_mode)
358         die ("error generating DSA key: %s\n", gpg_strerror (rc));
359       else if (!rc && in_fips_mode)
360         die ("generating 1024 bit DSA key must not work!");
361       if (!i && verbose > 1)
362         show_sexp ("1024 bit DSA key:\n", key);
363       gcry_sexp_release (key);
364     }
365
366   if (verbose)
367     show ("creating 1536 bit DSA key\n");
368   rc = gcry_sexp_new (&keyparm,
369                       "(genkey\n"
370                       " (dsa\n"
371                       "  (nbits 4:1536)\n"
372                       "  (qbits 3:224)\n"
373                       " ))", 0, 1);
374   if (rc)
375     die ("error creating S-expression: %s\n", gpg_strerror (rc));
376   rc = gcry_pk_genkey (&key, keyparm);
377   gcry_sexp_release (keyparm);
378   if (rc && !in_fips_mode)
379     die ("error generating DSA key: %s\n", gpg_strerror (rc));
380   else if (!rc && in_fips_mode)
381     die ("generating 1536 bit DSA key must not work!");
382   if (verbose > 1)
383     show_sexp ("1536 bit DSA key:\n", key);
384   gcry_sexp_release (key);
385
386   if (verbose)
387     show ("creating 3072 bit DSA key\n");
388   rc = gcry_sexp_new (&keyparm,
389                       "(genkey\n"
390                       " (dsa\n"
391                       "  (nbits 4:3072)\n"
392                       "  (qbits 3:256)\n"
393                       " ))", 0, 1);
394   if (rc)
395     die ("error creating S-expression: %s\n", gpg_strerror (rc));
396   rc = gcry_pk_genkey (&key, keyparm);
397   gcry_sexp_release (keyparm);
398   if (rc)
399     die ("error generating DSA key: %s\n", gpg_strerror (rc));
400   if (verbose > 1)
401     show_sexp ("3072 bit DSA key:\n", key);
402   gcry_sexp_release (key);
403
404   if (verbose)
405     show ("creating 2048/256 bit DSA key\n");
406   rc = gcry_sexp_new (&keyparm,
407                       "(genkey\n"
408                       " (dsa\n"
409                       "  (nbits 4:2048)\n"
410                       "  (qbits 3:256)\n"
411                       " ))", 0, 1);
412   if (rc)
413     die ("error creating S-expression: %s\n", gpg_strerror (rc));
414   rc = gcry_pk_genkey (&key, keyparm);
415   gcry_sexp_release (keyparm);
416   if (rc)
417     die ("error generating DSA key: %s\n", gpg_strerror (rc));
418   if (verbose > 1)
419     show_sexp ("2048 bit DSA key:\n", key);
420   gcry_sexp_release (key);
421
422   if (verbose)
423     show ("creating 2048/224 bit DSA key\n");
424   rc = gcry_sexp_new (&keyparm,
425                       "(genkey\n"
426                       " (dsa\n"
427                       "  (nbits 4:2048)\n"
428                       "  (qbits 3:224)\n"
429                       " ))", 0, 1);
430   if (rc)
431     die ("error creating S-expression: %s\n", gpg_strerror (rc));
432   rc = gcry_pk_genkey (&key, keyparm);
433   gcry_sexp_release (keyparm);
434   if (rc)
435     die ("error generating DSA key: %s\n", gpg_strerror (rc));
436   if (verbose > 1)
437     show_sexp ("2048 bit DSA key:\n", key);
438   gcry_sexp_release (key);
439 }
440
441
442 static void
443 check_generated_ecc_key (gcry_sexp_t key)
444 {
445   gcry_sexp_t skey, pkey;
446
447   pkey = gcry_sexp_find_token (key, "public-key", 0);
448   if (!pkey)
449     fail ("public part missing in return value\n");
450   else
451     {
452       /* Fixme: Check more stuff.  */
453       gcry_sexp_release (pkey);
454     }
455
456   skey = gcry_sexp_find_token (key, "private-key", 0);
457   if (!skey)
458     fail ("private part missing in return value\n");
459   else
460     {
461       int rc = gcry_pk_testkey (skey);
462       if (rc)
463         fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc));
464       gcry_sexp_release (skey);
465     }
466
467   /* Finally check that gcry_pk_testkey also works on the entire
468      S-expression.  */
469   {
470     int rc = gcry_pk_testkey (key);
471     if (rc)
472       fail ("gcry_pk_testkey failed on key pair: %s\n", gpg_strerror (rc));
473   }
474 }
475
476
477 static void
478 check_ecc_keys (void)
479 {
480   const char *curves[] = { "NIST P-521", "NIST P-384", "NIST P-256",
481                            "Ed25519", NULL };
482   int testno;
483   gcry_sexp_t keyparm, key;
484   int rc;
485
486   for (testno=0; curves[testno]; testno++)
487     {
488       if (verbose)
489         show ("creating ECC key using curve %s\n", curves[testno]);
490       if (!strcmp (curves[testno], "Ed25519"))
491         {
492           /* Ed25519 isn't allowed in fips mode */
493           if (in_fips_mode)
494             continue;
495           rc = gcry_sexp_build (&keyparm, NULL,
496                                 "(genkey(ecc(curve %s)(flags param eddsa)))",
497                                 curves[testno]);
498         }
499       else
500         rc = gcry_sexp_build (&keyparm, NULL,
501                               "(genkey(ecc(curve %s)(flags param)))",
502                               curves[testno]);
503       if (rc)
504         die ("error creating S-expression: %s\n", gpg_strerror (rc));
505       rc = gcry_pk_genkey (&key, keyparm);
506       gcry_sexp_release (keyparm);
507       if (rc)
508         die ("error generating ECC key using curve %s: %s\n",
509              curves[testno], gpg_strerror (rc));
510
511       if (verbose > 1)
512         show_sexp ("ECC key:\n", key);
513
514       check_generated_ecc_key (key);
515
516       gcry_sexp_release (key);
517     }
518
519   if (verbose)
520     show ("creating ECC key using curve Ed25519 for ECDSA\n");
521   rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve Ed25519)))");
522   if (rc)
523     die ("error creating S-expression: %s\n", gpg_strerror (rc));
524   rc = gcry_pk_genkey (&key, keyparm);
525   gcry_sexp_release (keyparm);
526   if (rc && !in_fips_mode)
527     die ("error generating ECC key using curve Ed25519 for ECDSA: %s\n",
528          gpg_strerror (rc));
529   else if (!rc && in_fips_mode)
530     fail ("generating Ed25519 key must not work!");
531
532   if (verbose && rc && in_fips_mode)
533     show ("... correctly rejected key creation in FIPS mode (%s)\n",
534           gpg_strerror (rc));
535
536   if (!rc)
537     {
538       if (verbose > 1)
539         show_sexp ("ECC key:\n", key);
540
541       check_generated_ecc_key (key);
542     }
543   gcry_sexp_release (key);
544
545   if (verbose)
546     show ("creating ECC key using curve Ed25519 for ECDSA (nocomp)\n");
547   rc = gcry_sexp_build (&keyparm, NULL,
548                         "(genkey(ecc(curve Ed25519)(flags nocomp)))");
549   if (rc)
550     die ("error creating S-expression: %s\n", gpg_strerror (rc));
551   rc = gcry_pk_genkey (&key, keyparm);
552   gcry_sexp_release (keyparm);
553   if (rc && !in_fips_mode)
554     die ("error generating ECC key using curve Ed25519 for ECDSA"
555          " (nocomp): %s\n",
556          gpg_strerror (rc));
557   else if (!rc && in_fips_mode)
558     fail ("generating Ed25519 key must not work in FIPS mode!");
559
560   if (verbose && rc && in_fips_mode)
561     show ("... correctly rejected key creation in FIPS mode (%s)\n",
562           gpg_strerror (rc));
563
564   if (verbose)
565     show ("creating ECC key using curve NIST P-384 for ECDSA\n");
566
567   /* Must be specified as nistp384 (one word), because ecc_generate
568    * uses _gcry_sexp_nth_string which takes the first word of the name
569    * and thus libgcrypt can't find it later in its curves table.  */
570   rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve nistp384)))");
571   if (rc)
572     die ("error creating S-expression: %s\n", gpg_strerror (rc));
573   rc = gcry_pk_genkey (&key, keyparm);
574   gcry_sexp_release (keyparm);
575   if (rc)
576     die ("error generating ECC key using curve NIST P-384 for ECDSA: %s\n",
577          gpg_strerror (rc));
578
579   if (verbose > 1)
580     show_sexp ("ECC key:\n", key);
581
582   check_generated_ecc_key (key);
583   gcry_sexp_release (key);
584
585   if (verbose)
586     show ("creating ECC key using curve NIST P-384 for ECDSA (nocomp)\n");
587   rc = gcry_sexp_build (&keyparm, NULL,
588                         "(genkey(ecc(curve nistp384)(flags nocomp)))");
589   if (rc)
590     die ("error creating S-expression: %s\n", gpg_strerror (rc));
591   rc = gcry_pk_genkey (&key, keyparm);
592   gcry_sexp_release (keyparm);
593   if (rc)
594     die ("error generating ECC key using curve NIST P-384 for ECDSA"
595          " (nocomp): %s\n",
596          gpg_strerror (rc));
597
598   if (verbose > 1)
599     show_sexp ("ECC key:\n", key);
600
601   check_generated_ecc_key (key);
602   gcry_sexp_release (key);
603
604
605   if (verbose)
606     show ("creating ECC key using curve Ed25519 for ECDSA (transient-key)\n");
607   rc = gcry_sexp_build (&keyparm, NULL,
608                         "(genkey(ecc(curve Ed25519)(flags transient-key)))");
609   if (rc)
610     die ("error creating S-expression: %s\n", gpg_strerror (rc));
611   rc = gcry_pk_genkey (&key, keyparm);
612   gcry_sexp_release (keyparm);
613   if (rc && !in_fips_mode)
614     die ("error generating ECC key using curve Ed25519 for ECDSA"
615          " (transient-key): %s\n",
616          gpg_strerror (rc));
617   else if (!rc && in_fips_mode)
618     fail ("generating Ed25519 key must not work in FIPS mode!");
619
620   if (verbose && rc && in_fips_mode)
621     show ("... correctly rejected key creation in FIPS mode (%s)\n",
622           gpg_strerror (rc));
623
624   if (!rc)
625     {
626       if (verbose > 1)
627         show_sexp ("ECC key:\n", key);
628       check_generated_ecc_key (key);
629     }
630   gcry_sexp_release (key);
631
632   if (verbose)
633     show ("creating ECC key using curve Ed25519 for ECDSA "
634           "(transient-key no-keytest)\n");
635   rc = gcry_sexp_build (&keyparm, NULL,
636                         "(genkey(ecc(curve Ed25519)"
637                         "(flags transient-key no-keytest)))");
638   if (rc)
639     die ("error creating S-expression: %s\n", gpg_strerror (rc));
640   rc = gcry_pk_genkey (&key, keyparm);
641   gcry_sexp_release (keyparm);
642   if (rc && !in_fips_mode)
643     die ("error generating ECC key using curve Ed25519 for ECDSA"
644          " (transient-key no-keytest): %s\n",
645          gpg_strerror (rc));
646   else if (!rc && in_fips_mode)
647     fail ("generating Ed25519 key must not work in FIPS mode!");
648
649   if (verbose && rc && in_fips_mode)
650     show ("... correctly rejected key creation in FIPS mode (%s)\n",
651           gpg_strerror (rc));
652
653   if (!rc)
654     {
655       if (verbose > 1)
656         show_sexp ("ECC key:\n", key);
657       check_generated_ecc_key (key);
658     }
659   gcry_sexp_release (key);
660 }
661
662
663 static void
664 check_nonce (void)
665 {
666   char a[32], b[32];
667   int i,j;
668   int oops=0;
669
670   if (verbose)
671     show ("checking gcry_create_nonce\n");
672
673   gcry_create_nonce (a, sizeof a);
674   for (i=0; i < 10; i++)
675     {
676       gcry_create_nonce (b, sizeof b);
677       if (!memcmp (a, b, sizeof a))
678         die ("identical nonce found\n");
679     }
680   for (i=0; i < 10; i++)
681     {
682       gcry_create_nonce (a, sizeof a);
683       if (!memcmp (a, b, sizeof a))
684         die ("identical nonce found\n");
685     }
686
687  again:
688   for (i=1,j=0; i < sizeof a; i++)
689     if (a[0] == a[i])
690       j++;
691   if (j+1 == sizeof (a))
692     {
693       if (oops)
694         die ("impossible nonce found\n");
695       oops++;
696       gcry_create_nonce (a, sizeof a);
697       goto again;
698     }
699 }
700
701
702 static void
703 progress_cb (void *cb_data, const char *what, int printchar,
704                   int current, int total)
705 {
706   (void)cb_data;
707   (void)what;
708   (void)current;
709   (void)total;
710
711   if (printchar == '\n')
712     fputs ( "<LF>", stdout);
713   else
714     putchar (printchar);
715   fflush (stdout);
716 }
717
718
719 static void
720 usage (int mode)
721 {
722   fputs ("usage: " PGM " [options] [{rsa|elg|dsa|ecc|nonce}]\n"
723          "Options:\n"
724          "  --verbose       be verbose\n"
725          "  --debug         flyswatter\n"
726          "  --fips          run in FIPS mode\n"
727          "  --progress      print progress indicators\n",
728          mode? stderr : stdout);
729   if (mode)
730     exit (1);
731 }
732
733 int
734 main (int argc, char **argv)
735 {
736   int last_argc = -1;
737   int opt_fips = 0;
738   int with_progress = 0;
739
740   if (argc)
741     { argc--; argv++; }
742
743   while (argc && last_argc != argc )
744     {
745       last_argc = argc;
746       if (!strcmp (*argv, "--"))
747         {
748           argc--; argv++;
749           break;
750         }
751       else if (!strcmp (*argv, "--help"))
752         {
753           usage (0);
754           exit (0);
755         }
756       else if (!strcmp (*argv, "--verbose"))
757         {
758           verbose++;
759           argc--; argv++;
760         }
761       else if (!strcmp (*argv, "--debug"))
762         {
763           verbose += 2;
764           debug++;
765           argc--; argv++;
766         }
767       else if (!strcmp (*argv, "--fips"))
768         {
769           argc--; argv++;
770           opt_fips = 1;
771         }
772       else if (!strcmp (*argv, "--progress"))
773         {
774           argc--; argv++;
775           with_progress = 1;
776         }
777       else if (!strncmp (*argv, "--", 2))
778         die ("unknown option '%s'", *argv);
779       else
780         break;
781     }
782
783   gcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
784   if (opt_fips)
785     gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
786
787   if (!gcry_check_version (GCRYPT_VERSION))
788     die ("version mismatch\n");
789
790   if (!opt_fips)
791     gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
792
793   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
794   if (debug)
795     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
796   /* No valuable keys are create, so we can speed up our RNG. */
797   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
798   if (with_progress)
799     gcry_set_progress_handler (progress_cb, NULL);
800
801   if ( gcry_fips_mode_active () )
802     in_fips_mode = 1;
803
804   if (opt_fips && !in_fips_mode)
805     die ("failed to switch into FIPS mode\n");
806
807   if (!argc)
808     {
809       check_rsa_keys ();
810       check_elg_keys ();
811       check_dsa_keys ();
812       check_ecc_keys ();
813       check_nonce ();
814     }
815   else
816     {
817       for (; argc; argc--, argv++)
818         if (!strcmp (*argv, "rsa"))
819           check_rsa_keys ();
820         else if (!strcmp (*argv, "elg"))
821           check_elg_keys ();
822         else if (!strcmp (*argv, "dsa"))
823           check_dsa_keys ();
824         else if (!strcmp (*argv, "ecc"))
825           check_ecc_keys ();
826         else if (!strcmp (*argv, "nonce"))
827           check_nonce ();
828         else
829           usage (1);
830     }
831
832   return error_count? 1:0;
833 }