tests: Add ECC key generation tests.
[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.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_generated_ecc_key (gcry_sexp_t key)
233 {
234   gcry_sexp_t skey, pkey;
235
236   pkey = gcry_sexp_find_token (key, "public-key", 0);
237   if (!pkey)
238     fail ("public part missing in return value\n");
239   else
240     {
241       /* Fixme: Check more stuff.  */
242       gcry_sexp_release (pkey);
243     }
244
245   skey = gcry_sexp_find_token (key, "private-key", 0);
246   if (!skey)
247     fail ("private part missing in return value\n");
248   else
249     {
250       int rc = gcry_pk_testkey (skey);
251       if (rc)
252         fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc));
253       gcry_sexp_release (skey);
254     }
255
256   /* Finally check that gcry_pk_testkey also works on the entire
257      S-expression.  */
258   {
259     int rc = gcry_pk_testkey (key);
260     if (rc)
261       fail ("gcry_pk_testkey failed on key pair: %s\n", gpg_strerror (rc));
262   }
263 }
264
265
266 static void
267 check_ecc_keys (void)
268 {
269   const char *curves[] = { "NIST P-521", "NIST P-384", "NIST P-256", NULL };
270   int testno;
271   gcry_sexp_t keyparm, key;
272   int rc;
273
274   for (testno=0; curves[testno]; testno++)
275     {
276       if (verbose)
277         fprintf (stderr, "creating ECC key using curve %s\n", curves[testno]);
278       rc = gcry_sexp_build (&keyparm, NULL,
279                             "(genkey(ecc(curve %s)))", curves[testno]);
280       if (rc)
281         die ("error creating S-expression: %s\n", gpg_strerror (rc));
282       rc = gcry_pk_genkey (&key, keyparm);
283       gcry_sexp_release (keyparm);
284       if (rc)
285         die ("error generating ECC key using curve %s: %s\n",
286              curves[testno], gpg_strerror (rc));
287
288       check_generated_ecc_key (key);
289       gcry_sexp_release (key);
290     }
291 }
292
293
294 static void
295 check_nonce (void)
296 {
297   char a[32], b[32];
298   int i,j;
299   int oops=0;
300
301   if (verbose)
302     fprintf (stderr, "checking gcry_create_nonce\n");
303
304   gcry_create_nonce (a, sizeof a);
305   for (i=0; i < 10; i++)
306     {
307       gcry_create_nonce (b, sizeof b);
308       if (!memcmp (a, b, sizeof a))
309         die ("identical nounce found\n");
310     }
311   for (i=0; i < 10; i++)
312     {
313       gcry_create_nonce (a, sizeof a);
314       if (!memcmp (a, b, sizeof a))
315         die ("identical nounce found\n");
316     }
317
318  again:
319   for (i=1,j=0; i < sizeof a; i++)
320     if (a[0] == a[i])
321       j++;
322   if (j+1 == sizeof (a))
323     {
324       if (oops)
325         die ("impossible nonce found\n");
326       oops++;
327       gcry_create_nonce (a, sizeof a);
328       goto again;
329     }
330 }
331
332
333 static void
334 progress_cb (void *cb_data, const char *what, int printchar,
335                   int current, int total)
336 {
337   (void)cb_data;
338   (void)what;
339   (void)current;
340   (void)total;
341
342   if (printchar == '\n')
343     fputs ( "<LF>", stdout);
344   else
345     putchar (printchar);
346   fflush (stdout);
347 }
348
349
350 int
351 main (int argc, char **argv)
352 {
353   if (argc > 1 && !strcmp (argv[1], "--verbose"))
354     verbose = 1;
355   else if (argc > 1 && !strcmp (argv[1], "--debug"))
356     verbose = debug = 1;
357
358   if (!gcry_check_version (GCRYPT_VERSION))
359     die ("version mismatch\n");
360   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
361   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
362   if (debug)
363     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
364   /* No valuable keys are create, so we can speed up our RNG. */
365   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
366   if (verbose)
367     gcry_set_progress_handler ( progress_cb, NULL );
368
369   check_rsa_keys ();
370   check_ecc_keys ();
371   check_nonce ();
372
373   return error_count? 1:0;
374 }