Use more odd chuck sizes for check_one_md
[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       if (!strcmp (curves[testno], "Ed25519"))
378         rc = gcry_sexp_build (&keyparm, NULL,
379                               "(genkey(ecc(curve %s)(flags param eddsa)))",
380                               curves[testno]);
381       else
382         rc = gcry_sexp_build (&keyparm, NULL,
383                               "(genkey(ecc(curve %s)(flags param)))",
384                               curves[testno]);
385       if (rc)
386         die ("error creating S-expression: %s\n", gpg_strerror (rc));
387       rc = gcry_pk_genkey (&key, keyparm);
388       gcry_sexp_release (keyparm);
389       if (rc)
390         die ("error generating ECC key using curve %s: %s\n",
391              curves[testno], gpg_strerror (rc));
392
393       if (verbose > 1)
394         show_sexp ("ECC key:\n", key);
395
396       check_generated_ecc_key (key);
397
398       gcry_sexp_release (key);
399     }
400
401   if (verbose)
402     show ("creating ECC key using curve Ed25519 for ECDSA\n");
403   rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve Ed25519)))");
404   if (rc)
405     die ("error creating S-expression: %s\n", gpg_strerror (rc));
406   rc = gcry_pk_genkey (&key, keyparm);
407   gcry_sexp_release (keyparm);
408   if (rc)
409     die ("error generating ECC key using curve Ed25519 for ECDSA: %s\n",
410          gpg_strerror (rc));
411
412   if (verbose > 1)
413     show_sexp ("ECC key:\n", key);
414
415   check_generated_ecc_key (key);
416   gcry_sexp_release (key);
417
418   if (verbose)
419     show ("creating ECC key using curve Ed25519 for ECDSA (nocomp)\n");
420   rc = gcry_sexp_build (&keyparm, NULL,
421                         "(genkey(ecc(curve Ed25519)(flags nocomp)))");
422   if (rc)
423     die ("error creating S-expression: %s\n", gpg_strerror (rc));
424   rc = gcry_pk_genkey (&key, keyparm);
425   gcry_sexp_release (keyparm);
426   if (rc)
427     die ("error generating ECC key using curve Ed25519 for ECDSA"
428          " (nocomp): %s\n",
429          gpg_strerror (rc));
430
431   if (verbose > 1)
432     show_sexp ("ECC key:\n", key);
433
434   check_generated_ecc_key (key);
435
436   gcry_sexp_release (key);
437 }
438
439
440 static void
441 check_nonce (void)
442 {
443   char a[32], b[32];
444   int i,j;
445   int oops=0;
446
447   if (verbose)
448     show ("checking gcry_create_nonce\n");
449
450   gcry_create_nonce (a, sizeof a);
451   for (i=0; i < 10; i++)
452     {
453       gcry_create_nonce (b, sizeof b);
454       if (!memcmp (a, b, sizeof a))
455         die ("identical nonce found\n");
456     }
457   for (i=0; i < 10; i++)
458     {
459       gcry_create_nonce (a, sizeof a);
460       if (!memcmp (a, b, sizeof a))
461         die ("identical nonce found\n");
462     }
463
464  again:
465   for (i=1,j=0; i < sizeof a; i++)
466     if (a[0] == a[i])
467       j++;
468   if (j+1 == sizeof (a))
469     {
470       if (oops)
471         die ("impossible nonce found\n");
472       oops++;
473       gcry_create_nonce (a, sizeof a);
474       goto again;
475     }
476 }
477
478
479 static void
480 progress_cb (void *cb_data, const char *what, int printchar,
481                   int current, int total)
482 {
483   (void)cb_data;
484   (void)what;
485   (void)current;
486   (void)total;
487
488   if (printchar == '\n')
489     fputs ( "<LF>", stdout);
490   else
491     putchar (printchar);
492   fflush (stdout);
493 }
494
495
496 static void
497 usage (int mode)
498 {
499   fputs ("usage: " PGM " [options] [{rsa|elg|dsa|ecc|nonce}]\n"
500          "Options:\n"
501          "  --verbose       be verbose\n"
502          "  --debug         flyswatter\n"
503          "  --progress      print progress indicators\n",
504          mode? stderr : stdout);
505   if (mode)
506     exit (1);
507 }
508
509 int
510 main (int argc, char **argv)
511 {
512   int last_argc = -1;
513   int with_progress = 0;
514
515   if (argc)
516     { argc--; argv++; }
517
518   while (argc && last_argc != argc )
519     {
520       last_argc = argc;
521       if (!strcmp (*argv, "--"))
522         {
523           argc--; argv++;
524           break;
525         }
526       else if (!strcmp (*argv, "--help"))
527         {
528           usage (0);
529           exit (0);
530         }
531       else if (!strcmp (*argv, "--verbose"))
532         {
533           verbose++;
534           argc--; argv++;
535         }
536       else if (!strcmp (*argv, "--debug"))
537         {
538           verbose += 2;
539           debug++;
540           argc--; argv++;
541         }
542       else if (!strcmp (*argv, "--progress"))
543         {
544           argc--; argv++;
545           with_progress = 1;
546         }
547       else if (!strncmp (*argv, "--", 2))
548         die ("unknown option '%s'", *argv);
549       else
550         break;
551     }
552
553   if (!gcry_check_version (GCRYPT_VERSION))
554     die ("version mismatch\n");
555   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
556   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
557   if (debug)
558     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
559   /* No valuable keys are create, so we can speed up our RNG. */
560   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
561   if (with_progress)
562     gcry_set_progress_handler (progress_cb, NULL);
563
564   if (!argc)
565     {
566       check_rsa_keys ();
567       check_elg_keys ();
568       check_dsa_keys ();
569       check_ecc_keys ();
570       check_nonce ();
571     }
572   else
573     {
574       for (; argc; argc--, argv++)
575         if (!strcmp (*argv, "rsa"))
576           check_rsa_keys ();
577         else if (!strcmp (*argv, "elg"))
578           check_elg_keys ();
579         else if (!strcmp (*argv, "dsa"))
580           check_dsa_keys ();
581         else if (!strcmp (*argv, "ecc"))
582           check_ecc_keys ();
583         else if (!strcmp (*argv, "nonce"))
584           check_nonce ();
585         else
586           usage (1);
587     }
588
589   return error_count? 1:0;
590 }