1/* keygen.c  -  key generation regression tests
2 *	Copyright (C) 2003, 2005 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.h"
29
30
31
32static int verbose;
33static int debug;
34static int error_count;
35
36static void
37fail ( const char *format, ... )
38{
39    va_list arg_ptr ;
40
41    va_start( arg_ptr, format ) ;
42    vfprintf (stderr, format, arg_ptr );
43    va_end(arg_ptr);
44    error_count++;
45}
46
47static void
48die ( const char *format, ... )
49{
50    va_list arg_ptr ;
51
52    va_start( arg_ptr, format ) ;
53    vfprintf (stderr, format, arg_ptr );
54    va_end(arg_ptr);
55    exit (1);
56}
57
58
59static void
60print_mpi (const char *text, gcry_mpi_t a)
61{
62  char *buf;
63  void *bufaddr = &buf;
64  gcry_error_t rc;
65
66  rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
67  if (rc)
68    fprintf (stderr, "%s=[error printing number: %s]\n",
69             text, gpg_strerror (rc));
70  else
71    {
72      fprintf (stderr, "%s=0x%s\n", text, buf);
73      gcry_free (buf);
74    }
75}
76
77
78static void
79check_generated_rsa_key (gcry_sexp_t key, unsigned long expected_e)
80{
81  gcry_sexp_t skey, pkey, list;
82
83  pkey = gcry_sexp_find_token (key, "public-key", 0);
84  if (!pkey)
85    fail ("public part missing in return value\n");
86  else
87    {
88      gcry_mpi_t e = NULL;
89
90      list = gcry_sexp_find_token (pkey, "e", 0);
91      if (!list || !(e=gcry_sexp_nth_mpi (list, 1, 0)) )
92        fail ("public exponent not found\n");
93      else if (!expected_e)
94        {
95          if (verbose)
96            print_mpi ("e", e);
97        }
98      else if ( gcry_mpi_cmp_ui (e, expected_e))
99        {
100          print_mpi ("e", e);
101          fail ("public exponent is not %lu\n", expected_e);
102        }
103      gcry_sexp_release (list);
104      gcry_mpi_release (e);
105      gcry_sexp_release (pkey);
106    }
107
108  skey = gcry_sexp_find_token (key, "private-key", 0);
109  if (!skey)
110    fail ("private part missing in return value\n");
111  else
112    {
113      int rc = gcry_pk_testkey (skey);
114      if (rc)
115        fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc));
116      gcry_sexp_release (skey);
117    }
118
119 }
120
121static void
122check_rsa_keys (void)
123{
124  gcry_sexp_t keyparm, key;
125  int rc;
126  int i;
127
128  /* Check that DSA generation works and that it can grok the qbits
129     argument. */
130  if (verbose)
131    fprintf (stderr, "creating 5 1024 bit DSA keys\n");
132  for (i=0; i < 5; i++)
133    {
134      rc = gcry_sexp_new (&keyparm,
135                          "(genkey\n"
136                          " (dsa\n"
137                          "  (nbits 4:1024)\n"
138                          " ))", 0, 1);
139      if (rc)
140        die ("error creating S-expression: %s\n", gpg_strerror (rc));
141      rc = gcry_pk_genkey (&key, keyparm);
142      gcry_sexp_release (keyparm);
143      if (rc)
144        die ("error generating DSA key: %s\n", gpg_strerror (rc));
145      gcry_sexp_release (key);
146      if (verbose)
147        fprintf (stderr, "  done\n");
148    }
149
150  if (verbose)
151    fprintf (stderr, "creating 1536 bit DSA key\n");
152  rc = gcry_sexp_new (&keyparm,
153                      "(genkey\n"
154                      " (dsa\n"
155                      "  (nbits 4:1536)\n"
156                      "  (qbits 3:224)\n"
157                      " ))", 0, 1);
158  if (rc)
159    die ("error creating S-expression: %s\n", gpg_strerror (rc));
160  rc = gcry_pk_genkey (&key, keyparm);
161  gcry_sexp_release (keyparm);
162  if (rc)
163    die ("error generating DSA key: %s\n", gpg_strerror (rc));
164  if (debug)
165    {
166      char buffer[20000];
167      gcry_sexp_sprint (key, GCRYSEXP_FMT_ADVANCED, buffer, sizeof buffer);
168      if (verbose)
169        printf ("=============================\n%s\n"
170                "=============================\n", buffer);
171    }
172  gcry_sexp_release (key);
173
174  if (verbose)
175    fprintf (stderr, "creating 1024 bit RSA key\n");
176  rc = gcry_sexp_new (&keyparm,
177                      "(genkey\n"
178                      " (rsa\n"
179                      "  (nbits 4:1024)\n"
180                      " ))", 0, 1);
181  if (rc)
182    die ("error creating S-expression: %s\n", gpg_strerror (rc));
183  rc = gcry_pk_genkey (&key, keyparm);
184  gcry_sexp_release (keyparm);
185  if (rc)
186    die ("error generating RSA key: %s\n", gpg_strerror (rc));
187
188  check_generated_rsa_key (key, 65537);
189  gcry_sexp_release (key);
190
191
192  if (verbose)
193    fprintf (stderr, "creating 512 bit RSA key with e=257\n");
194  rc = gcry_sexp_new (&keyparm,
195                      "(genkey\n"
196                      " (rsa\n"
197                      "  (nbits 3:512)\n"
198                      "  (rsa-use-e 3:257)\n"
199                      " ))", 0, 1);
200  if (rc)
201    die ("error creating S-expression: %s\n", gpg_strerror (rc));
202  rc = gcry_pk_genkey (&key, keyparm);
203  gcry_sexp_release (keyparm);
204  if (rc)
205    die ("error generating RSA key: %s\n", gpg_strerror (rc));
206
207  check_generated_rsa_key (key, 257);
208  gcry_sexp_release (key);
209
210  if (verbose)
211    fprintf (stderr, "creating 512 bit RSA key with default e\n");
212  rc = gcry_sexp_new (&keyparm,
213                      "(genkey\n"
214                      " (rsa\n"
215                      "  (nbits 3:512)\n"
216                      "  (rsa-use-e 1:0)\n"
217                      " ))", 0, 1);
218  if (rc)
219    die ("error creating S-expression: %s\n", gpg_strerror (rc));
220  rc = gcry_pk_genkey (&key, keyparm);
221  gcry_sexp_release (keyparm);
222  if (rc)
223    die ("error generating RSA key: %s\n", gpg_strerror (rc));
224
225  check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */
226  gcry_sexp_release (key);
227
228}
229
230
231static void
232check_nonce (void)
233{
234  char a[32], b[32];
235  int i,j;
236  int oops=0;
237
238  if (verbose)
239    fprintf (stderr, "checking gcry_create_nonce\n");
240
241  gcry_create_nonce (a, sizeof a);
242  for (i=0; i < 10; i++)
243    {
244      gcry_create_nonce (b, sizeof b);
245      if (!memcmp (a, b, sizeof a))
246        die ("identical nounce found\n");
247    }
248  for (i=0; i < 10; i++)
249    {
250      gcry_create_nonce (a, sizeof a);
251      if (!memcmp (a, b, sizeof a))
252        die ("identical nounce found\n");
253    }
254
255 again:
256  for (i=1,j=0; i < sizeof a; i++)
257    if (a[0] == a[i])
258      j++;
259  if (j+1 == sizeof (a))
260    {
261      if (oops)
262        die ("impossible nonce found\n");
263      oops++;
264      gcry_create_nonce (a, sizeof a);
265      goto again;
266    }
267}
268
269
270static void
271progress_cb (void *cb_data, const char *what, int printchar,
272		  int current, int total)
273{
274  (void)cb_data;
275  (void)what;
276  (void)current;
277  (void)total;
278
279  if (printchar == '\n')
280    fputs ( "<LF>", stdout);
281  else
282    putchar (printchar);
283  fflush (stdout);
284}
285
286
287int
288main (int argc, char **argv)
289{
290  if (argc > 1 && !strcmp (argv[1], "--verbose"))
291    verbose = 1;
292  else if (argc > 1 && !strcmp (argv[1], "--debug"))
293    verbose = debug = 1;
294
295  if (!gcry_check_version (GCRYPT_VERSION))
296    die ("version mismatch\n");
297  gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
298  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
299  if (debug)
300    gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
301  /* No valuable keys are create, so we can speed up our RNG. */
302  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
303  if (verbose)
304    gcry_set_progress_handler ( progress_cb, NULL );
305
306  check_rsa_keys ();
307  check_nonce ();
308
309  return error_count? 1:0;
310}
311