* rndlinux.c (set_cloexec_flag): New.
[libgcrypt.git] / tests / keygen.c
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
32 static int verbose;
33 static int debug;
34 static int error_count;
35
36 static void
37 fail ( 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
47 static void
48 die ( 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
59 static void
60 print_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
78 static void
79 check_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
121 static void
122 check_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
231 static void
232 check_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
270 static void
271 progress_cb (void *cb_data, const char *what, int printchar,
272                   int current, int total)
273 {
274   putchar (printchar);
275   fflush (stdout);
276 }
277
278
279 int
280 main (int argc, char **argv)
281 {
282   if (argc > 1 && !strcmp (argv[1], "--verbose"))
283     verbose = 1;
284   else if (argc > 1 && !strcmp (argv[1], "--debug"))
285     verbose = debug = 1;
286
287   if (!gcry_check_version (GCRYPT_VERSION))
288     die ("version mismatch\n");
289   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
290   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
291   if (debug)
292     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
293   /* No valuable keys are create, so we can speed up our RNG. */
294   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
295   if (verbose)
296     gcry_set_progress_handler ( progress_cb, NULL );
297
298   check_rsa_keys ();
299   check_nonce ();
300   
301   return error_count? 1:0;
302 }
303