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