You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
374 lines
11 KiB
374 lines
11 KiB
diff -up libgcrypt-1.5.3/cipher/primegen.c.fips-keygen libgcrypt-1.5.3/cipher/primegen.c |
|
--- libgcrypt-1.5.3/cipher/primegen.c.fips-keygen 2014-10-21 15:05:59.434189992 +0200 |
|
+++ libgcrypt-1.5.3/cipher/primegen.c 2014-10-21 15:05:59.458190534 +0200 |
|
@@ -1189,6 +1189,22 @@ gcry_prime_check (gcry_mpi_t x, unsigned |
|
return gcry_error (err); |
|
} |
|
|
|
+/* Check whether the number X is prime according to FIPS 186-4 table C.2. */ |
|
+gpg_err_code_t |
|
+_gcry_fips186_4_prime_check (gcry_mpi_t x, unsigned int bits) |
|
+{ |
|
+ gpg_err_code_t ec = GPG_ERR_NO_ERROR; |
|
+ gcry_mpi_t val_2 = mpi_alloc_set_ui (2); /* Used by the Fermat test. */ |
|
+ |
|
+ /* We use 5 or 4 rounds as specified in table C.2 */ |
|
+ if (! check_prime (x, val_2, bits > 1024 ? 4 : 5, NULL, NULL)) |
|
+ ec = GPG_ERR_NO_PRIME; |
|
+ |
|
+ mpi_free (val_2); |
|
+ |
|
+ return ec; |
|
+} |
|
+ |
|
/* Find a generator for PRIME where the factorization of (prime-1) is |
|
in the NULL terminated array FACTORS. Return the generator as a |
|
newly allocated MPI in R_G. If START_G is not NULL, use this as s |
|
diff -up libgcrypt-1.5.3/cipher/rsa.c.fips-keygen libgcrypt-1.5.3/cipher/rsa.c |
|
--- libgcrypt-1.5.3/cipher/rsa.c.fips-keygen 2014-10-21 15:05:59.423189744 +0200 |
|
+++ libgcrypt-1.5.3/cipher/rsa.c 2014-10-21 15:12:45.200350340 +0200 |
|
@@ -328,6 +328,279 @@ generate_std (RSA_secret_key *sk, unsign |
|
} |
|
|
|
|
|
+/**************** |
|
+ * Generate a key pair with a key of size NBITS. |
|
+ * USE_E = 0 let Libcgrypt decide what exponent to use. |
|
+ * = 1 request the use of a "secure" exponent; this is required by some |
|
+ * specification to be 65537. |
|
+ * > 2 Use this public exponent. If the given exponent |
|
+ * is not odd one is internally added to it. |
|
+ * TESTPARMS: If set, do not generate but test whether the p,q is probably prime |
|
+ * Returns key with zeroes to not break code calling this function. |
|
+ * TRANSIENT_KEY: If true, generate the primes using the standard RNG. |
|
+ * Returns: 2 structures filled with all needed values |
|
+ */ |
|
+static gpg_err_code_t |
|
+generate_fips (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e, |
|
+ gcry_sexp_t testparms, int transient_key) |
|
+{ |
|
+ gcry_mpi_t p, q; /* the two primes */ |
|
+ gcry_mpi_t d; /* the private key */ |
|
+ gcry_mpi_t u; |
|
+ gcry_mpi_t p1, q1; |
|
+ gcry_mpi_t n; /* the public key */ |
|
+ gcry_mpi_t e; /* the exponent */ |
|
+ gcry_mpi_t g; |
|
+ gcry_mpi_t minp; |
|
+ gcry_mpi_t diff, mindiff; |
|
+ gcry_random_level_t random_level; |
|
+ unsigned int pbits = nbits/2; |
|
+ unsigned int i; |
|
+ int pqswitch; |
|
+ gpg_err_code_t ec = GPG_ERR_NO_PRIME; |
|
+ |
|
+ if (nbits < 1024 || (nbits & 0x1FF)) |
|
+ return GPG_ERR_INV_VALUE; |
|
+ if (_gcry_enforced_fips_mode() && nbits != 2048 && nbits != 3072) |
|
+ return GPG_ERR_INV_VALUE; |
|
+ |
|
+ /* The random quality depends on the transient_key flag. */ |
|
+ random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; |
|
+ |
|
+ if (testparms) |
|
+ { |
|
+ /* Parameters to derive the key are given. */ |
|
+ /* Note that we explicitly need to setup the values of tbl |
|
+ because some compilers (e.g. OpenWatcom, IRIX) don't allow |
|
+ to initialize a structure with automatic variables. */ |
|
+ struct { const char *name; gcry_mpi_t *value; } tbl[] = { |
|
+ { "e" }, |
|
+ { "p" }, |
|
+ { "q" }, |
|
+ { NULL } |
|
+ }; |
|
+ int idx; |
|
+ gcry_sexp_t oneparm; |
|
+ |
|
+ tbl[0].value = &e; |
|
+ tbl[1].value = &p; |
|
+ tbl[2].value = &q; |
|
+ |
|
+ for (idx=0; tbl[idx].name; idx++) |
|
+ { |
|
+ oneparm = gcry_sexp_find_token (testparms, tbl[idx].name, 0); |
|
+ if (oneparm) |
|
+ { |
|
+ *tbl[idx].value = gcry_sexp_nth_mpi (oneparm, 1, |
|
+ GCRYMPI_FMT_USG); |
|
+ gcry_sexp_release (oneparm); |
|
+ } |
|
+ } |
|
+ for (idx=0; tbl[idx].name; idx++) |
|
+ if (!*tbl[idx].value) |
|
+ break; |
|
+ if (tbl[idx].name) |
|
+ { |
|
+ /* At least one parameter is missing. */ |
|
+ for (idx=0; tbl[idx].name; idx++) |
|
+ gcry_mpi_release (*tbl[idx].value); |
|
+ return GPG_ERR_MISSING_VALUE; |
|
+ } |
|
+ } |
|
+ else |
|
+ { |
|
+ if (use_e < 65537) |
|
+ use_e = 65537; /* This is the smallest value allowed by FIPS */ |
|
+ |
|
+ e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB ); |
|
+ |
|
+ use_e |= 1; /* make sure this is odd */ |
|
+ mpi_set_ui (e, use_e); |
|
+ |
|
+ p = gcry_mpi_snew (pbits); |
|
+ q = gcry_mpi_snew (pbits); |
|
+ } |
|
+ |
|
+ n = gcry_mpi_new (nbits); |
|
+ d = gcry_mpi_snew (nbits); |
|
+ u = gcry_mpi_snew (nbits); |
|
+ |
|
+ /* prepare approximate minimum p and q */ |
|
+ minp = gcry_mpi_new (pbits); |
|
+ mpi_set_ui (minp, 0xB504F334); |
|
+ gcry_mpi_lshift (minp, minp, pbits - 32); |
|
+ |
|
+ /* prepare minimum p and q difference */ |
|
+ diff = gcry_mpi_new (pbits); |
|
+ mindiff = gcry_mpi_new (pbits - 99); |
|
+ mpi_set_ui (mindiff, 1); |
|
+ gcry_mpi_lshift (mindiff, mindiff, pbits - 100); |
|
+ |
|
+ p1 = gcry_mpi_snew (pbits); |
|
+ q1 = gcry_mpi_snew (pbits); |
|
+ g = gcry_mpi_snew (pbits); |
|
+ |
|
+retry: |
|
+ /* generate p and q */ |
|
+ for (i = 0; i < 5 * pbits; i++) |
|
+ { |
|
+ ploop: |
|
+ if (!testparms) |
|
+ { |
|
+ gcry_mpi_randomize (p, pbits, random_level); |
|
+ } |
|
+ if (mpi_cmp (p, minp) < 0) |
|
+ { |
|
+ if (testparms) goto err; |
|
+ goto ploop; |
|
+ } |
|
+ |
|
+ mpi_sub_ui (p1, p, 1); |
|
+ if (gcry_mpi_gcd (g, p1, e)) |
|
+ { |
|
+ if (_gcry_fips186_4_prime_check (p, pbits) != GPG_ERR_NO_ERROR) |
|
+ { |
|
+ /* not a prime */ |
|
+ if (testparms) goto err; |
|
+ } |
|
+ else |
|
+ break; |
|
+ } |
|
+ else if (testparms) goto err; |
|
+ } |
|
+ if (i >= 5 * pbits) |
|
+ goto err; |
|
+ |
|
+ for (i = 0; i < 5 * pbits; i++) |
|
+ { |
|
+ qloop: |
|
+ if (!testparms) |
|
+ { |
|
+ gcry_mpi_randomize (q, pbits, random_level); |
|
+ } |
|
+ if (mpi_cmp (q, minp) < 0) |
|
+ { |
|
+ if (testparms) goto err; |
|
+ goto qloop; |
|
+ } |
|
+ if (mpi_cmp (p, q) > 0) |
|
+ { |
|
+ pqswitch = 1; |
|
+ mpi_sub (diff, p, q); |
|
+ } |
|
+ else |
|
+ { |
|
+ pqswitch = 0; |
|
+ mpi_sub (diff, q, p); |
|
+ } |
|
+ if (mpi_cmp (diff, mindiff) < 0) |
|
+ { |
|
+ if (testparms) goto err; |
|
+ goto qloop; |
|
+ } |
|
+ |
|
+ mpi_sub_ui (q1, q, 1); |
|
+ if (gcry_mpi_gcd (g, q1, e)) |
|
+ { |
|
+ if (_gcry_fips186_4_prime_check (q, pbits) != GPG_ERR_NO_ERROR) |
|
+ { |
|
+ /* not a prime */ |
|
+ if (testparms) goto err; |
|
+ } |
|
+ else |
|
+ break; |
|
+ } |
|
+ else if (testparms) goto err; |
|
+ } |
|
+ if (i >= 5 * pbits) |
|
+ goto err; |
|
+ |
|
+ if (testparms) |
|
+ { |
|
+ mpi_clear (p); |
|
+ mpi_clear (q); |
|
+ } |
|
+ else |
|
+ { |
|
+ gcry_mpi_t f; |
|
+ |
|
+ if (pqswitch) |
|
+ { |
|
+ gcry_mpi_t tmp; |
|
+ |
|
+ tmp = p; |
|
+ p = q; |
|
+ q = tmp; |
|
+ } |
|
+ |
|
+ f = gcry_mpi_snew (nbits); |
|
+ |
|
+ /* calculate the modulus */ |
|
+ mpi_mul(n, p, q); |
|
+ |
|
+ /* calculate the secret key d = e^1 mod phi */ |
|
+ gcry_mpi_gcd (g, p1, q1); |
|
+ mpi_fdiv_q (f, p1, g); |
|
+ mpi_mul (f, f, q1); |
|
+ |
|
+ mpi_invm (d, e, f); |
|
+ |
|
+ gcry_mpi_release (f); |
|
+ |
|
+ if (mpi_get_nbits (d) < pbits) goto retry; |
|
+ |
|
+ /* calculate the inverse of p and q (used for chinese remainder theorem)*/ |
|
+ mpi_invm(u, p, q ); |
|
+ } |
|
+ |
|
+ ec = 0; |
|
+ |
|
+ if( DBG_CIPHER ) |
|
+ { |
|
+ log_mpidump(" p= ", p ); |
|
+ log_mpidump(" q= ", q ); |
|
+ log_mpidump(" n= ", n ); |
|
+ log_mpidump(" e= ", e ); |
|
+ log_mpidump(" d= ", d ); |
|
+ log_mpidump(" u= ", u ); |
|
+ } |
|
+ |
|
+err: |
|
+ |
|
+ gcry_mpi_release (p1); |
|
+ gcry_mpi_release (q1); |
|
+ gcry_mpi_release (g); |
|
+ gcry_mpi_release (minp); |
|
+ gcry_mpi_release (mindiff); |
|
+ gcry_mpi_release (diff); |
|
+ |
|
+ sk->n = n; |
|
+ sk->e = e; |
|
+ sk->p = p; |
|
+ sk->q = q; |
|
+ sk->d = d; |
|
+ sk->u = u; |
|
+ |
|
+ /* Now we can test our keys. */ |
|
+ if (ec || (!testparms && test_keys (sk, nbits - 64))) |
|
+ { |
|
+ gcry_mpi_release (sk->n); sk->n = NULL; |
|
+ gcry_mpi_release (sk->e); sk->e = NULL; |
|
+ gcry_mpi_release (sk->p); sk->p = NULL; |
|
+ gcry_mpi_release (sk->q); sk->q = NULL; |
|
+ gcry_mpi_release (sk->d); sk->d = NULL; |
|
+ gcry_mpi_release (sk->u); sk->u = NULL; |
|
+ if (!ec) |
|
+ { |
|
+ fips_signal_error ("self-test after key generation failed"); |
|
+ return GPG_ERR_SELFTEST_FAILED; |
|
+ } |
|
+ } |
|
+ |
|
+ return ec; |
|
+} |
|
+ |
|
+ |
|
/* Helper for generate_x931. */ |
|
static gcry_mpi_t |
|
gen_x931_parm_xp (unsigned int nbits) |
|
@@ -812,7 +1085,7 @@ rsa_generate_ext (int algo, unsigned int |
|
} |
|
} |
|
|
|
- if (deriveparms || use_x931 || fips_mode ()) |
|
+ if (deriveparms || use_x931) |
|
{ |
|
int swapped; |
|
ec = generate_x931 (&sk, nbits, evalue, deriveparms, &swapped); |
|
@@ -841,8 +1114,14 @@ rsa_generate_ext (int algo, unsigned int |
|
transient_key = 1; |
|
gcry_sexp_release (l1); |
|
} |
|
+ deriveparms = (genparms? |
|
+ gcry_sexp_find_token (genparms, "test-parms", 0) : NULL); |
|
/* Generate. */ |
|
- ec = generate_std (&sk, nbits, evalue, transient_key); |
|
+ if (deriveparms || fips_mode()) |
|
+ ec = generate_fips (&sk, nbits, evalue, deriveparms, transient_key); |
|
+ else |
|
+ ec = generate_std (&sk, nbits, evalue, transient_key); |
|
+ gcry_sexp_release (deriveparms); |
|
} |
|
|
|
if (!ec) |
|
diff -up libgcrypt-1.5.3/src/g10lib.h.fips-keygen libgcrypt-1.5.3/src/g10lib.h |
|
--- libgcrypt-1.5.3/src/g10lib.h.fips-keygen 2013-07-25 11:10:04.000000000 +0200 |
|
+++ libgcrypt-1.5.3/src/g10lib.h 2014-10-21 15:05:59.459190556 +0200 |
|
@@ -195,6 +195,9 @@ gpg_err_code_t _gcry_generate_fips186_3_ |
|
int *r_counter, |
|
void **r_seed, size_t *r_seedlen, int *r_hashalgo); |
|
|
|
+gpg_err_code_t _gcry_fips186_4_prime_check |
|
+ (const gcry_mpi_t x, unsigned int bits); |
|
+ |
|
|
|
/* Replacements of missing functions (missing-string.c). */ |
|
#ifndef HAVE_STPCPY |
|
diff -up libgcrypt-1.5.3/tests/keygen.c.fips-keygen libgcrypt-1.5.3/tests/keygen.c |
|
--- libgcrypt-1.5.3/tests/keygen.c.fips-keygen 2014-10-21 15:05:59.424189766 +0200 |
|
+++ libgcrypt-1.5.3/tests/keygen.c 2014-10-21 15:05:59.459190556 +0200 |
|
@@ -190,12 +190,12 @@ check_rsa_keys (void) |
|
|
|
|
|
if (verbose) |
|
- fprintf (stderr, "creating 1024 bit RSA key with e=257\n"); |
|
+ fprintf (stderr, "creating 1024 bit RSA key with e=65539\n"); |
|
rc = gcry_sexp_new (&keyparm, |
|
"(genkey\n" |
|
" (rsa\n" |
|
" (nbits 4:1024)\n" |
|
- " (rsa-use-e 3:257)\n" |
|
+ " (rsa-use-e 5:65539)\n" |
|
" ))", 0, 1); |
|
if (rc) |
|
die ("error creating S-expression: %s\n", gpg_strerror (rc)); |
|
@@ -204,7 +204,7 @@ check_rsa_keys (void) |
|
if (rc) |
|
die ("error generating RSA key: %s\n", gpg_strerror (rc)); |
|
|
|
- check_generated_rsa_key (key, 257); |
|
+ check_generated_rsa_key (key, 65539); |
|
gcry_sexp_release (key); |
|
|
|
if (verbose)
|
|
|