Line data Source code
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 :
44 :
45 : static void
46 0 : die (const char *format, ...)
47 : {
48 : va_list arg_ptr ;
49 :
50 0 : fflush (stdout);
51 0 : fprintf (stderr, "%s: ", PGM);
52 0 : va_start( arg_ptr, format ) ;
53 0 : vfprintf (stderr, format, arg_ptr );
54 0 : va_end(arg_ptr);
55 0 : if (*format && format[strlen(format)-1] != '\n')
56 0 : putc ('\n', stderr);
57 0 : exit (1);
58 : }
59 :
60 : static void
61 0 : fail (const char *format, ...)
62 : {
63 : va_list arg_ptr;
64 :
65 0 : fflush (stdout);
66 0 : fprintf (stderr, "%s: ", PGM);
67 : /* if (wherestr) */
68 : /* fprintf (stderr, "%s: ", wherestr); */
69 0 : va_start (arg_ptr, format);
70 0 : vfprintf (stderr, format, arg_ptr);
71 0 : va_end (arg_ptr);
72 0 : if (*format && format[strlen(format)-1] != '\n')
73 0 : putc ('\n', stderr);
74 0 : error_count++;
75 0 : if (error_count >= 50)
76 0 : die ("stopped after 50 errors.");
77 0 : }
78 :
79 : static void
80 0 : show (const char *format, ...)
81 : {
82 : va_list arg_ptr;
83 :
84 0 : fprintf (stderr, "%s: ", PGM);
85 0 : va_start (arg_ptr, format);
86 0 : vfprintf (stderr, format, arg_ptr);
87 0 : if (*format && format[strlen(format)-1] != '\n')
88 0 : putc ('\n', stderr);
89 0 : va_end (arg_ptr);
90 0 : }
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 0 : show_sexp (const char *prefix, gcry_sexp_t a)
112 : {
113 : char *buf;
114 : size_t size;
115 :
116 0 : fprintf (stderr, "%s: ", PGM);
117 0 : if (prefix)
118 0 : fputs (prefix, stderr);
119 0 : size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
120 0 : buf = xmalloc (size);
121 :
122 0 : gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
123 0 : fprintf (stderr, "%.*s", (int)size, buf);
124 0 : gcry_free (buf);
125 0 : }
126 :
127 :
128 : static void
129 0 : show_mpi (const char *prefix, gcry_mpi_t a)
130 : {
131 : char *buf;
132 0 : void *bufaddr = &buf;
133 : gcry_error_t rc;
134 :
135 0 : fprintf (stderr, "%s: ", PGM);
136 0 : if (prefix)
137 0 : fputs (prefix, stderr);
138 0 : rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
139 0 : if (rc)
140 0 : fprintf (stderr, "[error printing number: %s]\n", gpg_strerror (rc));
141 : else
142 : {
143 0 : fprintf (stderr, "%s\n", buf);
144 0 : gcry_free (buf);
145 : }
146 0 : }
147 :
148 :
149 : static void
150 3 : check_generated_rsa_key (gcry_sexp_t key, unsigned long expected_e)
151 : {
152 : gcry_sexp_t skey, pkey, list;
153 :
154 3 : pkey = gcry_sexp_find_token (key, "public-key", 0);
155 3 : if (!pkey)
156 0 : fail ("public part missing in return value\n");
157 : else
158 : {
159 3 : gcry_mpi_t e = NULL;
160 :
161 3 : list = gcry_sexp_find_token (pkey, "e", 0);
162 3 : if (!list || !(e=gcry_sexp_nth_mpi (list, 1, 0)) )
163 0 : fail ("public exponent not found\n");
164 3 : else if (!expected_e)
165 : {
166 1 : if (verbose)
167 0 : show_mpi ("public exponent: ", e);
168 : }
169 2 : else if ( gcry_mpi_cmp_ui (e, expected_e))
170 : {
171 0 : show_mpi ("public exponent: ", e);
172 0 : fail ("public exponent is not %lu\n", expected_e);
173 : }
174 3 : gcry_sexp_release (list);
175 3 : gcry_mpi_release (e);
176 3 : gcry_sexp_release (pkey);
177 : }
178 :
179 3 : skey = gcry_sexp_find_token (key, "private-key", 0);
180 3 : if (!skey)
181 0 : fail ("private part missing in return value\n");
182 : else
183 : {
184 3 : int rc = gcry_pk_testkey (skey);
185 3 : if (rc)
186 0 : fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc));
187 3 : gcry_sexp_release (skey);
188 : }
189 3 : }
190 :
191 :
192 : static void
193 1 : check_rsa_keys (void)
194 : {
195 : gcry_sexp_t keyparm, key;
196 : int rc;
197 :
198 1 : if (verbose)
199 0 : show ("creating 1024 bit RSA key\n");
200 1 : rc = gcry_sexp_new (&keyparm,
201 : "(genkey\n"
202 : " (rsa\n"
203 : " (nbits 4:1024)\n"
204 : " ))", 0, 1);
205 1 : if (rc)
206 0 : die ("error creating S-expression: %s\n", gpg_strerror (rc));
207 1 : rc = gcry_pk_genkey (&key, keyparm);
208 1 : gcry_sexp_release (keyparm);
209 1 : if (rc)
210 0 : die ("error generating RSA key: %s\n", gpg_strerror (rc));
211 1 : if (verbose > 1)
212 0 : show_sexp ("1024 bit RSA key:\n", key);
213 1 : check_generated_rsa_key (key, 65537);
214 1 : gcry_sexp_release (key);
215 :
216 :
217 1 : if (verbose)
218 0 : show ("creating 512 bit RSA key with e=257\n");
219 1 : 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 1 : if (rc)
226 0 : die ("error creating S-expression: %s\n", gpg_strerror (rc));
227 1 : rc = gcry_pk_genkey (&key, keyparm);
228 1 : gcry_sexp_release (keyparm);
229 1 : if (rc)
230 0 : die ("error generating RSA key: %s\n", gpg_strerror (rc));
231 :
232 1 : check_generated_rsa_key (key, 257);
233 1 : gcry_sexp_release (key);
234 :
235 1 : if (verbose)
236 0 : show ("creating 512 bit RSA key with default e\n");
237 1 : 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 1 : if (rc)
244 0 : die ("error creating S-expression: %s\n", gpg_strerror (rc));
245 1 : rc = gcry_pk_genkey (&key, keyparm);
246 1 : gcry_sexp_release (keyparm);
247 1 : if (rc)
248 0 : die ("error generating RSA key: %s\n", gpg_strerror (rc));
249 :
250 1 : check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */
251 1 : gcry_sexp_release (key);
252 1 : }
253 :
254 :
255 : static void
256 1 : check_elg_keys (void)
257 : {
258 : gcry_sexp_t keyparm, key;
259 : int rc;
260 :
261 1 : if (verbose)
262 0 : show ("creating 1024 bit Elgamal key\n");
263 1 : rc = gcry_sexp_new (&keyparm,
264 : "(genkey\n"
265 : " (elg\n"
266 : " (nbits 4:1024)\n"
267 : " ))", 0, 1);
268 1 : if (rc)
269 0 : die ("error creating S-expression: %s\n", gpg_strerror (rc));
270 1 : rc = gcry_pk_genkey (&key, keyparm);
271 1 : gcry_sexp_release (keyparm);
272 1 : if (rc)
273 0 : die ("error generating Elgamal key: %s\n", gpg_strerror (rc));
274 1 : if (verbose > 1)
275 0 : show_sexp ("1024 bit Elgamal key:\n", key);
276 1 : gcry_sexp_release (key);
277 1 : }
278 :
279 :
280 : static void
281 1 : 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 1 : if (verbose)
290 0 : show ("creating 5 1024 bit DSA keys\n");
291 6 : for (i=0; i < 5; i++)
292 : {
293 5 : rc = gcry_sexp_new (&keyparm,
294 : "(genkey\n"
295 : " (dsa\n"
296 : " (nbits 4:1024)\n"
297 : " ))", 0, 1);
298 5 : if (rc)
299 0 : die ("error creating S-expression: %s\n", gpg_strerror (rc));
300 5 : rc = gcry_pk_genkey (&key, keyparm);
301 5 : gcry_sexp_release (keyparm);
302 5 : if (rc)
303 0 : die ("error generating DSA key: %s\n", gpg_strerror (rc));
304 5 : if (!i && verbose > 1)
305 0 : show_sexp ("1024 bit DSA key:\n", key);
306 5 : gcry_sexp_release (key);
307 : }
308 :
309 1 : if (verbose)
310 0 : show ("creating 1536 bit DSA key\n");
311 1 : 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 1 : if (rc)
318 0 : die ("error creating S-expression: %s\n", gpg_strerror (rc));
319 1 : rc = gcry_pk_genkey (&key, keyparm);
320 1 : gcry_sexp_release (keyparm);
321 1 : if (rc)
322 0 : die ("error generating DSA key: %s\n", gpg_strerror (rc));
323 1 : if (verbose > 1)
324 0 : show_sexp ("1536 bit DSA key:\n", key);
325 1 : gcry_sexp_release (key);
326 1 : }
327 :
328 :
329 : static void
330 8 : check_generated_ecc_key (gcry_sexp_t key)
331 : {
332 : gcry_sexp_t skey, pkey;
333 :
334 8 : pkey = gcry_sexp_find_token (key, "public-key", 0);
335 8 : if (!pkey)
336 0 : fail ("public part missing in return value\n");
337 : else
338 : {
339 : /* Fixme: Check more stuff. */
340 8 : gcry_sexp_release (pkey);
341 : }
342 :
343 8 : skey = gcry_sexp_find_token (key, "private-key", 0);
344 8 : if (!skey)
345 0 : fail ("private part missing in return value\n");
346 : else
347 : {
348 8 : int rc = gcry_pk_testkey (skey);
349 8 : if (rc)
350 0 : fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc));
351 8 : gcry_sexp_release (skey);
352 : }
353 :
354 : /* Finally check that gcry_pk_testkey also works on the entire
355 : S-expression. */
356 : {
357 8 : int rc = gcry_pk_testkey (key);
358 8 : if (rc)
359 0 : fail ("gcry_pk_testkey failed on key pair: %s\n", gpg_strerror (rc));
360 : }
361 8 : }
362 :
363 :
364 : static void
365 1 : check_ecc_keys (void)
366 : {
367 1 : 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 5 : for (testno=0; curves[testno]; testno++)
374 : {
375 4 : if (verbose)
376 0 : show ("creating ECC key using curve %s\n", curves[testno]);
377 4 : if (!strcmp (curves[testno], "Ed25519"))
378 1 : rc = gcry_sexp_build (&keyparm, NULL,
379 : "(genkey(ecc(curve %s)(flags param eddsa)))",
380 : curves[testno]);
381 : else
382 3 : rc = gcry_sexp_build (&keyparm, NULL,
383 : "(genkey(ecc(curve %s)(flags param)))",
384 : curves[testno]);
385 4 : if (rc)
386 0 : die ("error creating S-expression: %s\n", gpg_strerror (rc));
387 4 : rc = gcry_pk_genkey (&key, keyparm);
388 4 : gcry_sexp_release (keyparm);
389 4 : if (rc)
390 0 : die ("error generating ECC key using curve %s: %s\n",
391 : curves[testno], gpg_strerror (rc));
392 :
393 4 : if (verbose > 1)
394 0 : show_sexp ("ECC key:\n", key);
395 :
396 4 : check_generated_ecc_key (key);
397 :
398 4 : gcry_sexp_release (key);
399 : }
400 :
401 1 : if (verbose)
402 0 : show ("creating ECC key using curve Ed25519 for ECDSA\n");
403 1 : rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve Ed25519)))");
404 1 : if (rc)
405 0 : die ("error creating S-expression: %s\n", gpg_strerror (rc));
406 1 : rc = gcry_pk_genkey (&key, keyparm);
407 1 : gcry_sexp_release (keyparm);
408 1 : if (rc)
409 0 : die ("error generating ECC key using curve Ed25519 for ECDSA: %s\n",
410 : gpg_strerror (rc));
411 :
412 1 : if (verbose > 1)
413 0 : show_sexp ("ECC key:\n", key);
414 :
415 1 : check_generated_ecc_key (key);
416 1 : gcry_sexp_release (key);
417 :
418 1 : if (verbose)
419 0 : show ("creating ECC key using curve Ed25519 for ECDSA (nocomp)\n");
420 1 : rc = gcry_sexp_build (&keyparm, NULL,
421 : "(genkey(ecc(curve Ed25519)(flags nocomp)))");
422 1 : if (rc)
423 0 : die ("error creating S-expression: %s\n", gpg_strerror (rc));
424 1 : rc = gcry_pk_genkey (&key, keyparm);
425 1 : gcry_sexp_release (keyparm);
426 1 : if (rc)
427 0 : die ("error generating ECC key using curve Ed25519 for ECDSA"
428 : " (nocomp): %s\n",
429 : gpg_strerror (rc));
430 :
431 1 : if (verbose > 1)
432 0 : show_sexp ("ECC key:\n", key);
433 :
434 1 : check_generated_ecc_key (key);
435 1 : gcry_sexp_release (key);
436 :
437 :
438 1 : if (verbose)
439 0 : show ("creating ECC key using curve Ed25519 for ECDSA (transient-key)\n");
440 1 : rc = gcry_sexp_build (&keyparm, NULL,
441 : "(genkey(ecc(curve Ed25519)(flags transient-key)))");
442 1 : if (rc)
443 0 : die ("error creating S-expression: %s\n", gpg_strerror (rc));
444 1 : rc = gcry_pk_genkey (&key, keyparm);
445 1 : gcry_sexp_release (keyparm);
446 1 : if (rc)
447 0 : die ("error generating ECC key using curve Ed25519 for ECDSA"
448 : " (transient-key): %s\n",
449 : gpg_strerror (rc));
450 1 : if (verbose > 1)
451 0 : show_sexp ("ECC key:\n", key);
452 1 : check_generated_ecc_key (key);
453 1 : gcry_sexp_release (key);
454 :
455 1 : if (verbose)
456 0 : show ("creating ECC key using curve Ed25519 for ECDSA "
457 : "(transient-key no-keytest)\n");
458 1 : rc = gcry_sexp_build (&keyparm, NULL,
459 : "(genkey(ecc(curve Ed25519)"
460 : "(flags transient-key no-keytest)))");
461 1 : if (rc)
462 0 : die ("error creating S-expression: %s\n", gpg_strerror (rc));
463 1 : rc = gcry_pk_genkey (&key, keyparm);
464 1 : gcry_sexp_release (keyparm);
465 1 : if (rc)
466 0 : die ("error generating ECC key using curve Ed25519 for ECDSA"
467 : " (transient-key no-keytest): %s\n",
468 : gpg_strerror (rc));
469 1 : if (verbose > 1)
470 0 : show_sexp ("ECC key:\n", key);
471 1 : check_generated_ecc_key (key);
472 1 : gcry_sexp_release (key);
473 1 : }
474 :
475 :
476 : static void
477 1 : check_nonce (void)
478 : {
479 : char a[32], b[32];
480 : int i,j;
481 1 : int oops=0;
482 :
483 1 : if (verbose)
484 0 : show ("checking gcry_create_nonce\n");
485 :
486 1 : gcry_create_nonce (a, sizeof a);
487 11 : for (i=0; i < 10; i++)
488 : {
489 10 : gcry_create_nonce (b, sizeof b);
490 10 : if (!memcmp (a, b, sizeof a))
491 0 : die ("identical nonce found\n");
492 : }
493 11 : for (i=0; i < 10; i++)
494 : {
495 10 : gcry_create_nonce (a, sizeof a);
496 10 : if (!memcmp (a, b, sizeof a))
497 0 : die ("identical nonce found\n");
498 : }
499 :
500 : again:
501 32 : for (i=1,j=0; i < sizeof a; i++)
502 31 : if (a[0] == a[i])
503 2 : j++;
504 1 : if (j+1 == sizeof (a))
505 : {
506 0 : if (oops)
507 0 : die ("impossible nonce found\n");
508 0 : oops++;
509 0 : gcry_create_nonce (a, sizeof a);
510 0 : goto again;
511 : }
512 1 : }
513 :
514 :
515 : static void
516 0 : progress_cb (void *cb_data, const char *what, int printchar,
517 : int current, int total)
518 : {
519 : (void)cb_data;
520 : (void)what;
521 : (void)current;
522 : (void)total;
523 :
524 0 : if (printchar == '\n')
525 0 : fputs ( "<LF>", stdout);
526 : else
527 0 : putchar (printchar);
528 0 : fflush (stdout);
529 0 : }
530 :
531 :
532 : static void
533 0 : usage (int mode)
534 : {
535 0 : fputs ("usage: " PGM " [options] [{rsa|elg|dsa|ecc|nonce}]\n"
536 : "Options:\n"
537 : " --verbose be verbose\n"
538 : " --debug flyswatter\n"
539 : " --progress print progress indicators\n",
540 : mode? stderr : stdout);
541 0 : if (mode)
542 0 : exit (1);
543 0 : }
544 :
545 : int
546 1 : main (int argc, char **argv)
547 : {
548 1 : int last_argc = -1;
549 1 : int with_progress = 0;
550 :
551 1 : if (argc)
552 1 : { argc--; argv++; }
553 :
554 2 : while (argc && last_argc != argc )
555 : {
556 0 : last_argc = argc;
557 0 : if (!strcmp (*argv, "--"))
558 : {
559 0 : argc--; argv++;
560 0 : break;
561 : }
562 0 : else if (!strcmp (*argv, "--help"))
563 : {
564 0 : usage (0);
565 0 : exit (0);
566 : }
567 0 : else if (!strcmp (*argv, "--verbose"))
568 : {
569 0 : verbose++;
570 0 : argc--; argv++;
571 : }
572 0 : else if (!strcmp (*argv, "--debug"))
573 : {
574 0 : verbose += 2;
575 0 : debug++;
576 0 : argc--; argv++;
577 : }
578 0 : else if (!strcmp (*argv, "--progress"))
579 : {
580 0 : argc--; argv++;
581 0 : with_progress = 1;
582 : }
583 0 : else if (!strncmp (*argv, "--", 2))
584 0 : die ("unknown option '%s'", *argv);
585 : else
586 0 : break;
587 : }
588 :
589 1 : if (!gcry_check_version (GCRYPT_VERSION))
590 0 : die ("version mismatch\n");
591 1 : gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
592 1 : gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
593 1 : if (debug)
594 0 : gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
595 : /* No valuable keys are create, so we can speed up our RNG. */
596 1 : gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
597 1 : if (with_progress)
598 0 : gcry_set_progress_handler (progress_cb, NULL);
599 :
600 1 : if (!argc)
601 : {
602 1 : check_rsa_keys ();
603 1 : check_elg_keys ();
604 1 : check_dsa_keys ();
605 1 : check_ecc_keys ();
606 1 : check_nonce ();
607 : }
608 : else
609 : {
610 0 : for (; argc; argc--, argv++)
611 0 : if (!strcmp (*argv, "rsa"))
612 0 : check_rsa_keys ();
613 0 : else if (!strcmp (*argv, "elg"))
614 0 : check_elg_keys ();
615 0 : else if (!strcmp (*argv, "dsa"))
616 0 : check_dsa_keys ();
617 0 : else if (!strcmp (*argv, "ecc"))
618 0 : check_ecc_keys ();
619 0 : else if (!strcmp (*argv, "nonce"))
620 0 : check_nonce ();
621 : else
622 0 : usage (1);
623 : }
624 :
625 1 : return error_count? 1:0;
626 : }
|