[git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-350-g0bd8137

by Vitezslav Cizek cvs at cvs.gnupg.org
Fri Mar 18 16:54:53 CET 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU crypto library".

The branch, master has been updated
       via  0bd8137e68c201b6c2290710e348aaf57efa2b2e (commit)
       via  2e139456369a834cf87d983da4f61241fda76efe (commit)
       via  c690230af5a66b809f8f6fbab1a6262a5ba078cb (commit)
       via  78cec8b4754fdf774edb2d575000cb3e972e244c (commit)
       via  ce1cbe16992a7340edcf8e6576973e3508267640 (commit)
       via  c478cf175887c84dc071c4f73a7667603b354789 (commit)
       via  0f741b0704bac5c0e2d2a0c2b34b44b35baa76d6 (commit)
       via  a242e3d9185e6e2dc13902ea9331131755bbba01 (commit)
       via  e40939b2141306238cc30a340b867b60fa4dc2a3 (commit)
       via  80e9f95e6f419daa765e4876c858e3e36e808897 (commit)
       via  443bed836a4fd60217325789134f5a2dc2ec41ce (commit)
      from  4051fe7fec6ffdc7a2f5c3856665478866991ee7 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 0bd8137e68c201b6c2290710e348aaf57efa2b2e
Author: Vitezslav Cizek <vcizek at suse.com>
Date:   Fri Oct 30 17:34:04 2015 +0100

    cipher: Add option to specify salt length for PSS verification.
    
    * cipher/pubkey-util.c (_gcry_pk_util_data_to_mpi): Check for
    salt-length token.
    --
    
    Add possibility to use a different salt length for RSASSA-PSS
    verification instead of the default 20.
    
    Signed-off-by: Vitezslav Cizek <vcizek at suse.com>
    
    Additional changes by wk:
      - Detect overlong salt-length
      - Release LIST on error.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c
index 76d3923..c40ef97 100644
--- a/cipher/pubkey-util.c
+++ b/cipher/pubkey-util.c
@@ -665,7 +665,7 @@ _gcry_pk_util_free_encoding_ctx (struct pk_encoding_ctx *ctx)
 
    LABEL is specific to OAEP.
 
-   SALT-LENGTH is for PSS.
+   SALT-LENGTH is for PSS it is limited to 16384 bytes.
 
    RANDOM-OVERRIDE is used to replace random nonces for regression
    testing.  */
@@ -1068,6 +1068,31 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
             rc = GPG_ERR_DIGEST_ALGO;
 	  else
 	    {
+	      gcry_sexp_t list;
+	      /* Get SALT-LENGTH. */
+	      list = sexp_find_token (ldata, "salt-length", 0);
+	      if (list)
+		{
+                  unsigned long ul;
+
+		  s = sexp_nth_data (list, 1, &n);
+		  if (!s)
+		    {
+		      rc = GPG_ERR_NO_OBJ;
+                      sexp_release (list);
+		      goto leave;
+		    }
+		  ul = strtoul (s, NULL, 10);
+                  if (ul > 16384)
+                    {
+                      rc = GPG_ERR_TOO_LARGE;
+                      sexp_release (list);
+                      goto leave;
+                    }
+                  ctx->saltlen = ul;
+		  sexp_release (list);
+		}
+
 	      *ret_mpi = sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_USG);
 	      if (!*ret_mpi)
 		rc = GPG_ERR_INV_OBJ;

commit 2e139456369a834cf87d983da4f61241fda76efe
Author: Vitezslav Cizek <vcizek at suse.com>
Date:   Fri Oct 30 15:41:09 2015 +0100

    tests: Add support for RSA keygen tests to fipsdrv.
    
    * tests/fipsdrv.c (run_rsa_keygen): New.
    (main): Support RSA keygen and RSA keygen KAT tests.
    --
    
    In fipsdrv implement support for KeyGen_RandomProbablyPrime
    and Known Answer Test for probably primes RSA2VS tests.
    
    Signed-off-by: Vitezslav Cizek <vcizek at suse.com>

diff --git a/tests/fipsdrv.c b/tests/fipsdrv.c
index b5962cf..bcc56d1 100644
--- a/tests/fipsdrv.c
+++ b/tests/fipsdrv.c
@@ -1340,6 +1340,69 @@ run_rsa_derive (const void *data, size_t datalen)
 }
 
 
+/* Generate RSA key using the S-expression in (DATA,DATALEN).  This
+   S-expression is used directly as input to gcry_pk_genkey.  The
+   result is printed to stdout with one parameter per line in hex
+   format and in this order: e, p, q, n, d.  */
+static void
+run_rsa_keygen (const void *data, size_t datalen, int test)
+{
+  gpg_error_t err;
+  gcry_sexp_t s_keyspec, s_key, s_top, l1;
+  gcry_mpi_t mpi;
+  const char *parmlist;
+  int idx;
+
+  if (!datalen)
+    err = gpg_error (GPG_ERR_NO_DATA);
+  else
+    err = gcry_sexp_new (&s_keyspec, data, datalen, 1);
+  if (err)
+    die ("gcry_sexp_new failed for RSA key generation: %s\n",
+         gpg_strerror (err));
+
+  err = gcry_pk_genkey (&s_key, s_keyspec);
+
+  gcry_sexp_release (s_keyspec);
+
+  if (test) {
+	if (err)
+		printf("F\n");
+	else {
+		gcry_sexp_release (s_key);
+		printf("P\n");
+	}
+	return;
+  }
+
+  if (err)
+    die ("gcry_pk_genkey failed for RSA: %s\n", gpg_strerror (err));
+
+  parmlist = "epqnd";
+
+  /* Parse and print the parameters.  */
+  l1 = gcry_sexp_find_token (s_key, "private-key", 0);
+  s_top = gcry_sexp_find_token (l1, "rsa", 0);
+  gcry_sexp_release (l1);
+  if (!s_top)
+    die ("private-key part not found in result\n");
+
+  for (idx=0; parmlist[idx]; idx++)
+    {
+      l1 = gcry_sexp_find_token (s_top, parmlist+idx, 1);
+      mpi = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
+      gcry_sexp_release (l1);
+      if (!mpi)
+        die ("parameter %c missing in private-key\n", parmlist[idx]);
+      print_mpi_line (mpi, 1);
+      gcry_mpi_release (mpi);
+    }
+
+  gcry_sexp_release (s_top);
+  gcry_sexp_release (s_key);
+}
+
+
 

 static size_t
 compute_tag_length (size_t n)
@@ -2421,6 +2484,8 @@ main (int argc, char **argv)
       && !mct_server
       && strcmp (mode_string, "random")
       && strcmp (mode_string, "rsa-gen")
+      && strcmp (mode_string, "rsa-keygen")
+      && strcmp (mode_string, "rsa-keygen-kat")
       && strcmp (mode_string, "dsa-gen")
       && strcmp (mode_string, "ecdsa-gen-key") )
     {
@@ -2611,6 +2676,20 @@ main (int argc, char **argv)
         die ("no data available (do not use --chunk)\n");
       run_rsa_derive (data, datalen);
     }
+  else if (!strcmp (mode_string, "rsa-keygen"))
+    {
+      data = read_file (input, 0, &datalen);
+      if (!data)
+        die ("no data available (do not use --chunk)\n");
+      run_rsa_keygen (data, datalen, 0);
+    }
+  else if (!strcmp (mode_string, "rsa-keygen-kat"))
+    {
+      data = read_file (input, 0, &datalen);
+      if (!data)
+        die ("no data available (do not use --chunk)\n");
+      run_rsa_keygen (data, datalen, 1);
+    }
   else if (!strcmp (mode_string, "rsa-gen"))
     {
       int keysize;

commit c690230af5a66b809f8f6fbab1a6262a5ba078cb
Author: Vitezslav Cizek <vcizek at suse.com>
Date:   Fri Oct 30 15:38:13 2015 +0100

    tests: Fixes for RSA testsuite in FIPS mode
    
    * tests/basic.c (get_keys_new): Generate 2048 bit key.
    * tests/benchmark.c (rsa_bench): Skip keys of lengths different
    than 2048 and 3072 in FIPS mode.
    * tests/keygen.c (check_rsa_keys): Failure if short keys can be
    generated in FIPS mode.
    (check_dsa_keys): Ditto for DSA keys.
    * tests/pubkey.c (check_x931_derived_key): Skip keys < 2048 in FIPS.
    --
    
    Thanks to Ludwig Nussel.
    Signed-off-by: Vitezslav Cizek <vcizek at suse.com>
    
    Additional changes by wk:
      - Remove printing of "FAIL" in fail() because this is reserved for
        use by the test driver of the Makefile.
      - Move setting of IN_FIPS_MODE after gcry_check_version in keygen.c
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/tests/basic.c b/tests/basic.c
index 876ee2e..63fbcf6 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -8442,7 +8442,7 @@ get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
   if (verbose)
     fprintf (stderr, "  generating RSA key:");
   rc = gcry_sexp_new (&key_spec,
-		      in_fips_mode ? "(genkey (rsa (nbits 4:1024)))"
+		      in_fips_mode ? "(genkey (rsa (nbits 4:2048)))"
                       : "(genkey (rsa (nbits 4:1024)(transient-key)))",
                       0, 1);
   if (rc)
diff --git a/tests/benchmark.c b/tests/benchmark.c
index b6cd7a8..c748dac 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -1085,15 +1085,22 @@ rsa_bench (int iterations, int print_header, int no_blinding)
       gcry_sexp_t data;
       gcry_sexp_t sig = NULL;
       int count;
+      unsigned nbits = p_sizes[testno];
 
-      printf ("RSA %3d bit    ", p_sizes[testno]);
+      printf ("RSA %3d bit    ", nbits);
       fflush (stdout);
 
+      if (in_fips_mode && !(nbits == 2048 || nbits == 3072))
+        {
+          puts ("[skipped in fips mode]");
+          continue;
+        }
+
       err = gcry_sexp_build (&key_spec, NULL,
                              gcry_fips_mode_active ()
                              ? "(genkey (RSA (nbits %d)))"
                              : "(genkey (RSA (nbits %d)(transient-key)))",
-                             p_sizes[testno]);
+                             nbits);
       if (err)
         die ("creating S-expression failed: %s\n", gcry_strerror (err));
 
@@ -1101,7 +1108,7 @@ rsa_bench (int iterations, int print_header, int no_blinding)
       err = gcry_pk_genkey (&key_pair, key_spec);
       if (err)
         die ("creating %d bit RSA key failed: %s\n",
-             p_sizes[testno], gcry_strerror (err));
+             nbits, gcry_strerror (err));
 
       pub_key = gcry_sexp_find_token (key_pair, "public-key", 0);
       if (! pub_key)
@@ -1116,8 +1123,8 @@ rsa_bench (int iterations, int print_header, int no_blinding)
       printf ("   %s", elapsed_time (1));
       fflush (stdout);
 
-      x = gcry_mpi_new (p_sizes[testno]);
-      gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM);
+      x = gcry_mpi_new (nbits);
+      gcry_mpi_randomize (x, nbits-8, GCRY_WEAK_RANDOM);
       err = gcry_sexp_build (&data, NULL,
                              "(data (flags raw) (value %m))", x);
       gcry_mpi_release (x);
@@ -1155,8 +1162,8 @@ rsa_bench (int iterations, int print_header, int no_blinding)
       if (no_blinding)
         {
           fflush (stdout);
-          x = gcry_mpi_new (p_sizes[testno]);
-          gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM);
+          x = gcry_mpi_new (nbits);
+          gcry_mpi_randomize (x, nbits-8, GCRY_WEAK_RANDOM);
           err = gcry_sexp_build (&data, NULL,
                                  "(data (flags no-blinding) (value %m))", x);
           gcry_mpi_release (x);
diff --git a/tests/keygen.c b/tests/keygen.c
index 8b9a1d5..7afa76c 100644
--- a/tests/keygen.c
+++ b/tests/keygen.c
@@ -40,6 +40,7 @@
 static int verbose;
 static int debug;
 static int error_count;
+static int in_fips_mode;
 
 
 static void
@@ -196,11 +197,11 @@ check_rsa_keys (void)
   int rc;
 
   if (verbose)
-    show ("creating 1024 bit RSA key\n");
+    show ("creating 2048 bit RSA key\n");
   rc = gcry_sexp_new (&keyparm,
                       "(genkey\n"
                       " (rsa\n"
-                      "  (nbits 4:1024)\n"
+                      "  (nbits 4:2048)\n"
                       " ))", 0, 1);
   if (rc)
     die ("error creating S-expression: %s\n", gpg_strerror (rc));
@@ -208,9 +209,29 @@ check_rsa_keys (void)
   gcry_sexp_release (keyparm);
   if (rc)
     die ("error generating RSA key: %s\n", gpg_strerror (rc));
-  if (verbose > 1)
-    show_sexp ("1024 bit RSA key:\n", key);
-  check_generated_rsa_key (key, 65537);
+
+  if (verbose)
+    show ("creating 1024 bit RSA key\n");
+  rc = gcry_sexp_new (&keyparm,
+                      "(genkey\n"
+                      " (rsa\n"
+                      "  (nbits 4:1024)\n"
+                      " ))", 0, 1);
+  if (rc)
+    die ("error creating S-expression: %s\n", gpg_strerror (rc));
+  rc = gcry_pk_genkey (&key, keyparm);
+  gcry_sexp_release (keyparm);
+  if (rc && !in_fips_mode)
+    fail ("error generating RSA key: %s\n", gpg_strerror (rc));
+  else if (!rc && in_fips_mode)
+    fail ("generating 1024 bit RSA key must not work!");
+
+  if (!rc)
+    {
+      if (verbose > 1)
+        show_sexp ("1024 bit RSA key:\n", key);
+      check_generated_rsa_key (key, 65537);
+    }
   gcry_sexp_release (key);
 
 
@@ -226,10 +247,13 @@ check_rsa_keys (void)
     die ("error creating S-expression: %s\n", gpg_strerror (rc));
   rc = gcry_pk_genkey (&key, keyparm);
   gcry_sexp_release (keyparm);
-  if (rc)
-    die ("error generating RSA key: %s\n", gpg_strerror (rc));
+  if (rc && !in_fips_mode)
+    fail ("error generating RSA key: %s\n", gpg_strerror (rc));
+  else if (!rc && in_fips_mode)
+    fail ("generating 512 bit RSA key must not work!");
 
-  check_generated_rsa_key (key, 257);
+  if (!rc)
+    check_generated_rsa_key (key, 257);
   gcry_sexp_release (key);
 
   if (verbose)
@@ -244,10 +268,13 @@ check_rsa_keys (void)
     die ("error creating S-expression: %s\n", gpg_strerror (rc));
   rc = gcry_pk_genkey (&key, keyparm);
   gcry_sexp_release (keyparm);
-  if (rc)
-    die ("error generating RSA key: %s\n", gpg_strerror (rc));
+  if (rc && !in_fips_mode)
+    fail ("error generating RSA key: %s\n", gpg_strerror (rc));
+  else if (!rc && in_fips_mode)
+    fail ("generating 512 bit RSA key must not work!");
 
-  check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */
+  if (!rc)
+    check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */
   gcry_sexp_release (key);
 }
 
@@ -299,8 +326,10 @@ check_dsa_keys (void)
         die ("error creating S-expression: %s\n", gpg_strerror (rc));
       rc = gcry_pk_genkey (&key, keyparm);
       gcry_sexp_release (keyparm);
-      if (rc)
+      if (rc && !in_fips_mode)
         die ("error generating DSA key: %s\n", gpg_strerror (rc));
+      else if (!rc && in_fips_mode)
+        die ("generating 512 bit DSA key must not work!");
       if (!i && verbose > 1)
         show_sexp ("1024 bit DSA key:\n", key);
       gcry_sexp_release (key);
@@ -318,8 +347,10 @@ check_dsa_keys (void)
     die ("error creating S-expression: %s\n", gpg_strerror (rc));
   rc = gcry_pk_genkey (&key, keyparm);
   gcry_sexp_release (keyparm);
-  if (rc)
+  if (rc && !in_fips_mode)
     die ("error generating DSA key: %s\n", gpg_strerror (rc));
+  else if (!rc && in_fips_mode)
+    die ("generating 1536 bit DSA key must not work!");
   if (verbose > 1)
     show_sexp ("1536 bit DSA key:\n", key);
   gcry_sexp_release (key);
@@ -597,6 +628,9 @@ main (int argc, char **argv)
   if (with_progress)
     gcry_set_progress_handler (progress_cb, NULL);
 
+  if ( gcry_fips_mode_active () )
+    in_fips_mode = 1;
+
   if (!argc)
     {
       check_rsa_keys ();
diff --git a/tests/pubkey.c b/tests/pubkey.c
index 62dc0d6..5ed6ca1 100644
--- a/tests/pubkey.c
+++ b/tests/pubkey.c
@@ -165,6 +165,33 @@ show_sexp (const char *prefix, gcry_sexp_t a)
   gcry_free (buf);
 }
 
+/* from ../cipher/pubkey-util.c */
+gpg_err_code_t
+_gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits)
+{
+  char buf[50];
+  const char *s;
+  size_t n;
+
+  *r_nbits = 0;
+
+  list = gcry_sexp_find_token (list, "nbits", 0);
+  if (!list)
+    return 0; /* No NBITS found.  */
+
+  s = gcry_sexp_nth_data (list, 1, &n);
+  if (!s || n >= DIM (buf) - 1 )
+    {
+      /* NBITS given without a cdr.  */
+      gcry_sexp_release (list);
+      return GPG_ERR_INV_OBJ;
+    }
+  memcpy (buf, s, n);
+  buf[n] = 0;
+  *r_nbits = (unsigned int)strtoul (buf, NULL, 0);
+  gcry_sexp_release (list);
+  return 0;
+}
 
 /* Convert STRING consisting of hex characters into its binary
    representation and return it as an allocated buffer. The valid
@@ -906,8 +933,8 @@ check_x931_derived_key (int what)
     }
   };
   gpg_error_t err;
-  gcry_sexp_t key_spec, key, pub_key, sec_key;
-  gcry_mpi_t d_expected, d_have;
+  gcry_sexp_t key_spec = NULL, key = NULL, pub_key = NULL, sec_key = NULL;
+  gcry_mpi_t d_expected = NULL, d_have = NULL;
 
   if (what < 0 && what >= sizeof testtable)
     die ("invalid WHAT value\n");
@@ -916,10 +943,25 @@ check_x931_derived_key (int what)
   if (err)
     die ("error creating S-expression [%d]: %s\n", what, gpg_strerror (err));
 
+  {
+    unsigned nbits;
+    err = _gcry_pk_util_get_nbits(key_spec, &nbits);
+    if (err)
+      die ("nbits not found\n");
+    if (gcry_fips_mode_active() && nbits < 2048)
+      {
+        info("RSA key test with %d bits skipped in fips mode\n", nbits);
+        goto leave;
+      }
+  }
+
   err = gcry_pk_genkey (&key, key_spec);
   gcry_sexp_release (key_spec);
   if (err)
-    die ("error generating RSA key [%d]: %s\n", what, gpg_strerror (err));
+    {
+      fail ("error generating RSA key [%d]: %s\n", what, gpg_strerror (err));
+      goto leave;
+    }
 
   pub_key = gcry_sexp_find_token (key, "public-key", 0);
   if (!pub_key)
@@ -945,6 +987,7 @@ check_x931_derived_key (int what)
       show_sexp (NULL, sec_key);
       die ("parameter d does match expected value [%d]\n", what);
     }
+leave:
   gcry_mpi_release (d_expected);
   gcry_mpi_release (d_have);
 

commit 78cec8b4754fdf774edb2d575000cb3e972e244c
Author: Vitezslav Cizek <vcizek at suse.com>
Date:   Fri Oct 30 13:41:41 2015 +0100

    rsa: Use 2048 bit RSA keys for selftest.
    
    * cipher/rsa.c (selftests_rsa): Use 2048 bit keys.
    (selftest_encr_1024): Replaced by selftest_encr_2048.
    (selftest_sign_1024): Replaced by selftest_sign_2048.
    (selftest_encr_2048): Add check against known ciphertext.
    (selftest_sign_2048): Add check against known signature.
    (selftest_sign_2048): Free SIG_MPI.
    * tests/pubkey.c (get_keys_new): Generate 2048 bit keys.
    --
    
    Use a 2048 bit keys for RSA selftest.
    Check against the known signature/ciphertext after signing/encryption
    in the selftests.
    Also generate 2k keys in tests/pubkey.
    
    Thanks to Ludwig Nussel.
    Signed-off-by: Vitezslav Cizek <vcizek at suse.com>
    
    Additional changes by wk:
      - Reformat some strings and comments.
      - Replace a free by xfree.
      - Free SIG_MPI.
      - Make two strings static.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/cipher/rsa.c b/cipher/rsa.c
index 45a481b..787b14a 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -62,36 +62,53 @@ static const char *rsa_names[] =
   };
 
 
-/* A sample 1024 bit RSA key used for the selftests.  */
+/* A sample 2048 bit RSA key used for the selftests.  */
 static const char sample_secret_key[] =
-"(private-key"
-" (rsa"
-"  (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
-"      2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
-"      ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
-"      891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)"
-"  (e #010001#)"
-"  (d #046129f2489d71579be0a75fe029bd6cdb574ebf57ea8a5b0fda942cab943b11"
-"      7d7bb95e5d28875e0f9fc5fcc06a72f6d502464dabded78ef6b716177b83d5bd"
-"      c543dc5d3fed932e59f5897e92e6f58a0f33424106a3b6fa2cbf877510e4ac21"
-"      c3ee47851e97d12996222ac3566d4ccb0b83d164074abf7de655fc2446da1781#)"
-"  (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213"
-"      fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)"
-"  (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9"
-"      35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)"
-"  (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e"
-"      ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)))";
-/* A sample 1024 bit RSA key used for the selftests (public only).  */
+" (private-key"
+"  (rsa"
+"  (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
+"      7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
+"      7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
+"      958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
+"      DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
+"      6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
+"      42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
+"      664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6CB#)"
+"   (e #010001#)"
+"   (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19"
+"       8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93"
+"       7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12"
+"       771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F"
+"       5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48"
+"       EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD"
+"       69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84"
+"       3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401#)"
+"   (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0"
+"       79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B"
+"       441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF"
+"       54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F1783#)"
+"   (q #00D1984135231CB243FE959C0CBEF551EDD986AD7BEDF71EDF447BE3DA27AF46"
+"       79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77"
+"       88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E"
+"       8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B919#)"
+"   (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04"
+"       479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4"
+"       A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9"
+"       AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7#)))";
+
+/* A sample 2048 bit RSA key used for the selftests (public only).  */
 static const char sample_public_key[] =
-"(public-key"
-" (rsa"
-"  (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
-"      2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
-"      ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
-"      891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)"
-"  (e #010001#)))";
-
-
+" (public-key"
+"  (rsa"
+"   (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
+"       7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
+"       7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
+"       958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
+"       DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
+"       6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
+"       42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
+"       664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6CB#)"
+"   (e #010001#)))";
 
 

 static int test_keys (RSA_secret_key *sk, unsigned nbits);
@@ -1349,20 +1366,34 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
  */
 
 static const char *
-selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
+selftest_sign_2048 (gcry_sexp_t pkey, gcry_sexp_t skey)
 {
   static const char sample_data[] =
     "(data (flags pkcs1)"
-    " (hash sha1 #11223344556677889900aabbccddeeff10203040#))";
+    " (hash sha256 #11223344556677889900aabbccddeeff"
+    /**/           "102030405060708090a0b0c0d0f01121#))";
   static const char sample_data_bad[] =
     "(data (flags pkcs1)"
-    " (hash sha1 #11223344556677889900aabbccddeeff80203040#))";
+    " (hash sha256 #11223344556677889900aabbccddeeff"
+    /**/           "802030405060708090a0b0c0d0f01121#))";
 
   const char *errtxt = NULL;
   gcry_error_t err;
   gcry_sexp_t data = NULL;
   gcry_sexp_t data_bad = NULL;
   gcry_sexp_t sig = NULL;
+  /* raw signature data reference */
+  const char ref_data[] =
+    "6252a19a11e1d5155ed9376036277193d644fa239397fff03e9b92d6f86415d6"
+    "d30da9273775f290e580d038295ff8ff89522becccfa6ae870bf76b76df402a8"
+    "54f69347e3db3de8e1e7d4dada281ec556810c7a8ecd0b5f51f9b1c0e7aa7557"
+    "61aa2b8ba5f811304acc6af0eca41fe49baf33bf34eddaf44e21e036ac7f0b68"
+    "03cdef1c60021fb7b5b97ebacdd88ab755ce29af568dbc5728cc6e6eff42618d"
+    "62a0386ca8beed46402bdeeef29b6a3feded906bace411a06a39192bf516ae10"
+    "67e4320fa8ea113968525f4574d022a3ceeaafdc41079efe1f22cc94bf59d8d3"
+    "328085da9674857db56de5978a62394aab48aa3b72e23a1b16260cfd9daafe65";
+  gcry_mpi_t ref_mpi = NULL;
+  gcry_mpi_t sig_mpi = NULL;
 
   err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data));
   if (!err)
@@ -1380,6 +1411,27 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
       errtxt = "signing failed";
       goto leave;
     }
+
+  err = _gcry_mpi_scan(&ref_mpi, GCRYMPI_FMT_HEX, ref_data, 0, NULL);
+  if (err)
+    {
+      errtxt = "converting ref_data to mpi failed";
+      goto leave;
+    }
+
+  err = _gcry_sexp_extract_param(sig, "sig-val!rsa", "s", &sig_mpi, NULL);
+  if (err)
+    {
+      errtxt = "extracting signature data failed";
+      goto leave;
+    }
+
+  if (mpi_cmp (sig_mpi, ref_mpi))
+    {
+      errtxt = "signature does not match reference data";
+      goto leave;
+    }
+
   err = _gcry_pk_verify (sig, data, pkey);
   if (err)
     {
@@ -1398,6 +1450,8 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
   sexp_release (sig);
   sexp_release (data_bad);
   sexp_release (data);
+  _gcry_mpi_release (ref_mpi);
+  _gcry_mpi_release (sig_mpi);
   return errtxt;
 }
 
@@ -1436,25 +1490,33 @@ extract_a_from_sexp (gcry_sexp_t encr_data)
 
 
 static const char *
-selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
+selftest_encr_2048 (gcry_sexp_t pkey, gcry_sexp_t skey)
 {
   const char *errtxt = NULL;
   gcry_error_t err;
-  const unsigned int nbits = 1000; /* Encrypt 1000 random bits.  */
-  gcry_mpi_t plaintext = NULL;
+  static const char plaintext[] =
+    "Jim quickly realized that the beautiful gowns are expensive.";
   gcry_sexp_t plain = NULL;
   gcry_sexp_t encr  = NULL;
   gcry_mpi_t  ciphertext = NULL;
   gcry_sexp_t decr  = NULL;
-  gcry_mpi_t  decr_plaintext = NULL;
+  char *decr_plaintext = NULL;
   gcry_sexp_t tmplist = NULL;
-
-  /* Create plaintext.  The plaintext is actually a big integer number.  */
-  plaintext = mpi_new (nbits);
-  _gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM);
+  /* expected result of encrypting the plaintext with sample_secret_key */
+  static const char ref_data[] =
+    "18022e2593a402a737caaa93b4c7e750e20ca265452980e1d6b7710fbd3e"
+    "7dce72be5c2110fb47691cb38f42170ee3b4a37f2498d4a51567d762585e"
+    "4cb81d04fbc7df4144f8e5eac2d4b8688521b64011f11d7ad53f4c874004"
+    "819856f2e2a6f83d1c9c4e73ac26089789c14482b0b8d44139133c88c4a5"
+    "2dba9dd6d6ffc622666b7d129168333d999706af30a2d7d272db7734e5ed"
+    "fb8c64ea3018af3ad20f4a013a5060cb0f5e72753967bebe294280a6ed0d"
+    "dbd3c4f11d0a8696e9d32a0dc03deb0b5e49b2cbd1503392642d4e1211f3"
+    "e8e2ee38abaa3671ccd57fcde8ca76e85fd2cb77c35706a970a213a27352"
+    "cec92a9604d543ddb5fc478ff50e0622";
+  gcry_mpi_t ref_mpi = NULL;
 
   /* Put the plaintext into an S-expression.  */
-  err = sexp_build (&plain, NULL, "(data (flags raw) (value %m))", plaintext);
+  err = sexp_build (&plain, NULL, "(data (flags raw) (value %s))", plaintext);
   if (err)
     {
       errtxt = "converting data failed";
@@ -1469,6 +1531,13 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
       goto leave;
     }
 
+  err = _gcry_mpi_scan(&ref_mpi, GCRYMPI_FMT_HEX, ref_data, 0, NULL);
+  if (err)
+    {
+      errtxt = "converting encrydata to mpi failed";
+      goto leave;
+    }
+
   /* Extraxt the ciphertext from the returned S-expression.  */
   /*sexp_dump (encr);*/
   ciphertext = extract_a_from_sexp (encr);
@@ -1481,9 +1550,9 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
   /* Check that the ciphertext does no match the plaintext.  */
   /* _gcry_log_printmpi ("plaintext", plaintext); */
   /* _gcry_log_printmpi ("ciphertxt", ciphertext); */
-  if (!mpi_cmp (plaintext, ciphertext))
+  if (mpi_cmp (ref_mpi, ciphertext))
     {
-      errtxt = "ciphertext matches plaintext";
+      errtxt = "ciphertext doesn't match reference data";
       goto leave;
     }
 
@@ -1503,9 +1572,9 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
      take care of it anyway.  */
   tmplist = sexp_find_token (decr, "value", 0);
   if (tmplist)
-    decr_plaintext = sexp_nth_mpi (tmplist, 1, GCRYMPI_FMT_USG);
+    decr_plaintext = sexp_nth_string (tmplist, 1);
   else
-    decr_plaintext = sexp_nth_mpi (decr, 0, GCRYMPI_FMT_USG);
+    decr_plaintext = sexp_nth_string (decr, 0);
   if (!decr_plaintext)
     {
       errtxt = "decrypt returned no plaintext";
@@ -1513,7 +1582,7 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
     }
 
   /* Check that the decrypted plaintext matches the original  plaintext.  */
-  if (mpi_cmp (plaintext, decr_plaintext))
+  if (strcmp (plaintext, decr_plaintext))
     {
       errtxt = "mismatch";
       goto leave;
@@ -1521,12 +1590,12 @@ selftest_encr_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
 
  leave:
   sexp_release (tmplist);
-  _gcry_mpi_release (decr_plaintext);
+  xfree (decr_plaintext);
   sexp_release (decr);
   _gcry_mpi_release (ciphertext);
+  _gcry_mpi_release (ref_mpi);
   sexp_release (encr);
   sexp_release (plain);
-  _gcry_mpi_release (plaintext);
   return errtxt;
 }
 
@@ -1561,12 +1630,12 @@ selftests_rsa (selftest_report_func_t report)
     }
 
   what = "sign";
-  errtxt = selftest_sign_1024 (pkey, skey);
+  errtxt = selftest_sign_2048 (pkey, skey);
   if (errtxt)
     goto failed;
 
   what = "encrypt";
-  errtxt = selftest_encr_1024 (pkey, skey);
+  errtxt = selftest_encr_2048 (pkey, skey);
   if (errtxt)
     goto failed;
 
diff --git a/tests/pubkey.c b/tests/pubkey.c
index 26bd9e3..62dc0d6 100644
--- a/tests/pubkey.c
+++ b/tests/pubkey.c
@@ -354,7 +354,7 @@ get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
   int rc;
 
   rc = gcry_sexp_new (&key_spec,
-		      "(genkey (rsa (nbits 4:1024)))", 0, 1);
+		      "(genkey (rsa (nbits 4:2048)))", 0, 1);
   if (rc)
     die ("error creating S-expression: %s\n", gcry_strerror (rc));
   rc = gcry_pk_genkey (&key, key_spec);
@@ -386,7 +386,7 @@ get_keys_x931_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
   int rc;
 
   rc = gcry_sexp_new (&key_spec,
-		      "(genkey (rsa (nbits 4:1024)(use-x931)))", 0, 1);
+		      "(genkey (rsa (nbits 4:2048)(use-x931)))", 0, 1);
   if (rc)
     die ("error creating S-expression: %s\n", gcry_strerror (rc));
   rc = gcry_pk_genkey (&key, key_spec);

commit ce1cbe16992a7340edcf8e6576973e3508267640
Author: Vitezslav Cizek <vcizek at suse.com>
Date:   Thu Oct 29 17:13:16 2015 +0100

    Disable non-allowed algorithms in FIPS mode
    
    * cipher/cipher.c (_gcry_cipher_init),
    * cipher/mac.c (_gcry_mac_init),
    * cipher/md.c (_gcry_md_init),
    * cipher/pubkey.c (_gcry_pk_init): In the FIPS mode, disable all the
    non-allowed ciphers.
    * cipher/md5.c: Mark MD5 as not allowed in FIPS.
    * src/g10lib.h (_gcry_mac_init): New.
    * src/global.c (global_init): Call the new _gcry_mac_init.
    * tests/basic.c (check_ciphers): Fix a typo.
    --
    
    When running in the FIPS mode, disable all the ciphers that don't have
    the fips flag set.
    Skip the non-allowed algos during testing in the FIPS mode.
    
    Thanks to Ludwig Nussel.
    Signed-off-by: Vitezslav Cizek <vcizek at suse.com>
    
    Signed-off-by: Vitezslav Cizek <vcizek at suse.com>

diff --git a/cipher/cipher.c b/cipher/cipher.c
index 802ffad..a013846 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -1514,6 +1514,17 @@ _gcry_cipher_get_algo_blklen (int algo)
 gcry_err_code_t
 _gcry_cipher_init (void)
 {
+  if (fips_mode())
+    {
+      /* disable algorithms that are disallowed in fips */
+      int idx;
+      gcry_cipher_spec_t *spec;
+
+      for (idx = 0; (spec = cipher_list[idx]); idx++)
+        if (!spec->flags.fips)
+          spec->flags.disabled = 1;
+    }
+
   return 0;
 }
 
diff --git a/cipher/mac.c b/cipher/mac.c
index b8a5534..46be7b7 100644
--- a/cipher/mac.c
+++ b/cipher/mac.c
@@ -116,6 +116,23 @@ static gcry_mac_spec_t *mac_list[] = {
   NULL,
 };
 
+/* Explicitly initialize this module.  */
+gcry_err_code_t
+_gcry_mac_init (void)
+{
+  if (fips_mode())
+    {
+      /* disable algorithms that are disallowed in fips */
+      int idx;
+      gcry_mac_spec_t *spec;
+
+      for (idx = 0; (spec = mac_list[idx]); idx++)
+        if (!spec->flags.fips)
+          spec->flags.disabled = 1;
+    }
+
+  return 0;
+}
 
 

 /* Return the spec structure for the MAC algorithm ALGO.  For an
diff --git a/cipher/md.c b/cipher/md.c
index 15d944d..281db12 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -1296,6 +1296,17 @@ _gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes)
 gcry_err_code_t
 _gcry_md_init (void)
 {
+  if (fips_mode())
+    {
+      /* disable algorithms that are disallowed in fips */
+      int idx;
+      gcry_md_spec_t *spec;
+
+      for (idx = 0; (spec = digest_list[idx]); idx++)
+        if (!spec->flags.fips)
+          spec->flags.disabled = 1;
+    }
+
   return 0;
 }
 
diff --git a/cipher/md5.c b/cipher/md5.c
index 66cc5f6..ed942cf 100644
--- a/cipher/md5.c
+++ b/cipher/md5.c
@@ -310,7 +310,7 @@ static gcry_md_oid_spec_t oid_spec_md5[] =
 
 gcry_md_spec_t _gcry_digest_spec_md5 =
   {
-    GCRY_MD_MD5, {0, 1},
+    GCRY_MD_MD5, {0, 0},
     "MD5", asn, DIM (asn), oid_spec_md5, 16,
     md5_init, _gcry_md_block_write, md5_final, md5_read, NULL,
     sizeof (MD5_CONTEXT)
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index b321a89..8ec15fd 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -926,6 +926,17 @@ _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx)
 gcry_err_code_t
 _gcry_pk_init (void)
 {
+  if (fips_mode())
+    {
+      /* disable algorithms that are disallowed in fips */
+      int idx;
+      gcry_pk_spec_t *spec;
+
+      for (idx = 0; (spec = pubkey_list[idx]); idx++)
+        if (!spec->flags.fips)
+          spec->flags.disabled = 1;
+    }
+
   return 0;
 }
 
diff --git a/src/g10lib.h b/src/g10lib.h
index 7352556..af68870 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -381,6 +381,7 @@ typedef struct fast_wipememory_s
 
 gcry_err_code_t _gcry_cipher_init (void);
 gcry_err_code_t _gcry_md_init (void);
+gcry_err_code_t _gcry_mac_init (void);
 gcry_err_code_t _gcry_pk_init (void);
 gcry_err_code_t _gcry_secmem_module_init (void);
 gcry_err_code_t _gcry_mpi_init (void);
diff --git a/src/global.c b/src/global.c
index 4d69b27..8669a46 100644
--- a/src/global.c
+++ b/src/global.c
@@ -105,6 +105,9 @@ global_init (void)
   err = _gcry_md_init ();
   if (err)
     goto fail;
+  err = _gcry_mac_init ();
+  if (err)
+    goto fail;
   err = _gcry_pk_init ();
   if (err)
     goto fail;
diff --git a/tests/basic.c b/tests/basic.c
index 5e7ee44..876ee2e 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -698,6 +698,14 @@ check_ctr_cipher (void)
       if (!tv[i].algo)
         continue;
 
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0);
       if (!err)
 	err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_CTR, 0);
@@ -929,6 +937,14 @@ check_cfb_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking CFB mode for %s [%i]\n",
 		 gcry_cipher_algo_name (tv[i].algo),
@@ -1100,6 +1116,14 @@ check_ofb_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking OFB mode for %s [%i]\n",
 		 gcry_cipher_algo_name (tv[i].algo),
@@ -1402,6 +1426,14 @@ _check_gcm_cipher (unsigned int step)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking GCM mode for %s [%i]\n",
                  gcry_cipher_algo_name (tv[i].algo),
@@ -2423,6 +2455,14 @@ check_ccm_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking CCM mode for %s [%i]\n",
                  gcry_cipher_algo_name (tv[i].algo),
@@ -3924,6 +3964,13 @@ check_stream_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
       if (verbose)
         fprintf (stderr, "    checking stream mode for %s [%i] (%s)\n",
 		 gcry_cipher_algo_name (tv[i].algo), tv[i].algo, tv[i].name);
@@ -4368,6 +4415,14 @@ check_stream_cipher_large_block (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+		     tv[i].algo);
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking large block stream for %s [%i] (%s)\n",
 		 gcry_cipher_algo_name (tv[i].algo), tv[i].algo, tv[i].name);
@@ -5219,11 +5274,11 @@ check_ciphers (void)
 
   for (i = 0; algos2[i]; i++)
     {
-      if (gcry_cipher_test_algo (algos[i]) && in_fips_mode)
+      if (gcry_cipher_test_algo (algos2[i]) && in_fips_mode)
         {
           if (verbose)
             fprintf (stderr, "  algorithm %d not available in fips mode\n",
-		     algos[i]);
+		     algos2[i]);
           continue;
         }
       if (verbose)
@@ -6399,8 +6454,7 @@ check_digests (void)
           show_md_not_available (algos[i].md);
           continue;
         }
-      if ((gcry_md_test_algo (algos[i].md) || algos[i].md == GCRY_MD_MD5)
-          && in_fips_mode)
+      if (gcry_md_test_algo (algos[i].md) && in_fips_mode)
         {
           if (verbose)
             fprintf (stderr, "  algorithm %d not available in fips mode\n",
@@ -6832,8 +6886,7 @@ check_hmac (void)
           show_old_hmac_not_available (algos[i].md);
           continue;
         }
-      if ((gcry_md_test_algo (algos[i].md) || algos[i].md == GCRY_MD_MD5)
-          && in_fips_mode)
+      if (gcry_md_test_algo (algos[i].md) && in_fips_mode)
         {
           if (verbose)
             fprintf (stderr, "  algorithm %d not available in fips mode\n",
@@ -7809,8 +7862,7 @@ check_mac (void)
           show_mac_not_available (algos[i].algo);
           continue;
         }
-      if ((gcry_mac_test_algo (algos[i].algo)
-	   || algos[i].algo == GCRY_MAC_HMAC_MD5) && in_fips_mode)
+      if (gcry_mac_test_algo (algos[i].algo) && in_fips_mode)
         {
           if (verbose)
             fprintf (stderr, "  algorithm %d not available in fips mode\n",

commit c478cf175887c84dc071c4f73a7667603b354789
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Mar 18 15:38:26 2016 +0100

    kdf: Make PBKDF2 check work on all platforms.
    
    * cipher/kdf.c (_gcry_kdf_pkdf2): Chnage DKLEN to unsigned long.
    --
    
    The previous pacth has no effect because on almost all platformans an
    unsigned int is 32 bit and thus the 0xffffffff is anyway the largest
    value.  This patch changes the variable to an unsigned long so that at
    least on common 64 bit Unix systems (but not on 64 bit Windows) there
    is an actual check.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/cipher/kdf.c b/cipher/kdf.c
index 831edd2..27f5789 100644
--- a/cipher/kdf.c
+++ b/cipher/kdf.c
@@ -125,7 +125,7 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen,
   gpg_err_code_t ec;
   gcry_md_hd_t md;
   int secmode;
-  unsigned int dklen = keysize;
+  unsigned long dklen = keysize;
   char *dk = keybuffer;
   unsigned int hlen;   /* Output length of the digest function.  */
   unsigned int l;      /* Rounded up number of blocks.  */
@@ -151,11 +151,14 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen,
   secmode = _gcry_is_secure (passphrase) || _gcry_is_secure (keybuffer);
 
   /* Step 1 */
-  /* If dkLen > (2^32 - 1) * hLen, output "derived key too long" and stop.
-     We use a stronger inequality. */
+  /* If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
+   * stop.  We use a stronger inequality but only if our type can hold
+   * a larger value.  */
 
-  if (dklen > 4294967295U)
+#if SIZEOF_UNSIGNED_LONG > 4
+  if (dklen > 0xffffffffU)
     return GPG_ERR_INV_VALUE;
+#endif
 
 
   /* Step 2 */

commit 0f741b0704bac5c0e2d2a0c2b34b44b35baa76d6
Author: Vitezslav Cizek <vcizek at suse.com>
Date:   Thu Oct 29 14:00:26 2015 +0100

    kdf: Add upper bound for derived key length in PBKDF2.
    
    * cipher/kdf.c (_gcry_kdf_pkdf2): limit dkLen.
    --
    
    Add a missing step 1 from PBKDF specification.
    
    Signed-off-by: Vitezslav Cizek <vcizek at suse.com>

diff --git a/cipher/kdf.c b/cipher/kdf.c
index ad5c46e..831edd2 100644
--- a/cipher/kdf.c
+++ b/cipher/kdf.c
@@ -138,7 +138,7 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen,
   unsigned long iter;  /* Current iteration number.  */
   unsigned int i;
 
-  /* NWe allow for a saltlen of 0 here to support scrypt.  It is not
+  /* We allow for a saltlen of 0 here to support scrypt.  It is not
      clear whether rfc2898 allows for this this, thus we do a test on
      saltlen > 0 only in gcry_kdf_derive.  */
   if (!salt || !iterations || !dklen)
@@ -150,8 +150,13 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen,
 
   secmode = _gcry_is_secure (passphrase) || _gcry_is_secure (keybuffer);
 
-  /* We ignore step 1 from pksc5v2.1 which demands a check that dklen
-     is not larger that 0xffffffff * hlen.  */
+  /* Step 1 */
+  /* If dkLen > (2^32 - 1) * hLen, output "derived key too long" and stop.
+     We use a stronger inequality. */
+
+  if (dklen > 4294967295U)
+    return GPG_ERR_INV_VALUE;
+
 
   /* Step 2 */
   l = ((dklen - 1)/ hlen) + 1;

commit a242e3d9185e6e2dc13902ea9331131755bbba01
Author: Vitezslav Cizek <vcizek at suse.com>
Date:   Tue Oct 27 14:29:11 2015 +0100

    ecc: ECDSA adjustments for FIPS 186-4
    
    * cipher/ecc-curves.c: Unmark curve P-192 for FIPS.
    * cipher/ecc.c: Add ECDSA self test.
    * cipher/pubkey-util.c (_gcry_pk_util_init_encoding_ctx): Use SHA-2
    in FIPS mode.
    * tests/fipsdrv.c: Add support for ECDSA signatures.
    --
    
    Enable ECC in FIPS mode.
    According to NIST SP 800-131A, curve P-192 and SHA-1 are disallowed
    for key pair generation and signature generation after 2013.
    
    Thanks to Jan Matejek for the patch.
    Signed-off-by: Vitezslav Cizek <vcizek at suse.com>
    
    Minor source code re-formatting by -wk.

diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index a74501d..91f29cc 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -160,7 +160,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
 #endif /*0*/
     {
-      "NIST P-192", 192, 1,
+      "NIST P-192", 192, 0,
       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
diff --git a/cipher/ecc.c b/cipher/ecc.c
index f65203f..5b03530 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -73,6 +73,25 @@ static const char *ecc_names[] =
   };
 
 
+/* Sample NIST P-256 key from RFC 6979 A.2.5 */
+static const char sample_public_key_secp256[] =
+  "(public-key"
+  " (ecc"
+  "  (curve secp256r1)"
+  "  (q #04"
+  /**/  "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"
+  /**/  "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)))";
+
+static const char sample_secret_key_secp256[] =
+  "(private-key"
+  " (ecc"
+  "  (curve secp256r1)"
+  "  (d #C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721#)"
+  "  (q #04"
+  /**/  "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"
+  /**/  "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)))";
+
+
 /* Registered progress function and its callback value. */
 static void (*progress_cb) (void *, const char*, int, int, int);
 static void *progress_cb_data;
@@ -1956,23 +1975,165 @@ _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
      Self-test section.
  */
 
+static const char *
+selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey)
+{
+  /* Sample data from RFC 6979 section A.2.5, hash is of message "sample" */
+  static const char sample_data[] =
+    "(data (flags rfc6979)"
+    " (hash sha256 #af2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915"
+    /**/           "62113d8a62add1bf#))";
+  static const char sample_data_bad[] =
+    "(data (flags rfc6979)"
+    " (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915"
+    /**/           "62113d8a62add1bf#))";
+  static const char signature_r[] =
+    "efd48b2aacb6a8fd1140dd9cd45e81d69d2c877b56aaf991c34d0ea84eaf3716";
+  static const char signature_s[] =
+    "f7cb1c942d657c41d436c7a1b6e29f65f3e900dbb9aff4064dc4ab2f843acda8";
+
+  const char *errtxt = NULL;
+  gcry_error_t err;
+  gcry_sexp_t data = NULL;
+  gcry_sexp_t data_bad = NULL;
+  gcry_sexp_t sig = NULL;
+  gcry_sexp_t l1 = NULL;
+  gcry_sexp_t l2 = NULL;
+  gcry_mpi_t r = NULL;
+  gcry_mpi_t s = NULL;
+  gcry_mpi_t calculated_r = NULL;
+  gcry_mpi_t calculated_s = NULL;
+  int cmp;
+
+  err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data));
+  if (!err)
+    err = sexp_sscan (&data_bad, NULL,
+                      sample_data_bad, strlen (sample_data_bad));
+  if (!err)
+    err = _gcry_mpi_scan (&r, GCRYMPI_FMT_HEX, signature_r, 0, NULL);
+  if (!err)
+    err = _gcry_mpi_scan (&s, GCRYMPI_FMT_HEX, signature_s, 0, NULL);
+
+  if (err)
+    {
+      errtxt = "converting data failed";
+      goto leave;
+    }
+
+  err = _gcry_pk_sign (&sig, data, skey);
+  if (err)
+    {
+      errtxt = "signing failed";
+      goto leave;
+    }
+
+  /* check against known signature */
+  errtxt = "signature validity failed";
+  l1 = _gcry_sexp_find_token (sig, "sig-val", 0);
+  if (!l1)
+    goto leave;
+  l2 = _gcry_sexp_find_token (l1, "ecdsa", 0);
+  if (!l2)
+    goto leave;
+
+  sexp_release (l1);
+  l1 = l2;
+
+  l2 = _gcry_sexp_find_token (l1, "r", 0);
+  if (!l2)
+    goto leave;
+  calculated_r = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
+  if (!calculated_r)
+    goto leave;
+
+  l2 = _gcry_sexp_find_token (l1, "s", 0);
+  if (!l2)
+    goto leave;
+  calculated_s = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
+  if (!calculated_s)
+    goto leave;
+
+  errtxt = "known sig check failed";
+
+  cmp = _gcry_mpi_cmp (r, calculated_r);
+  if (cmp)
+    goto leave;
+  cmp = _gcry_mpi_cmp (s, calculated_s);
+  if (cmp)
+    goto leave;
+
+  errtxt = NULL;
+
+  /* verify generated signature */
+  err = _gcry_pk_verify (sig, data, pkey);
+  if (err)
+    {
+      errtxt = "verify failed";
+      goto leave;
+    }
+  err = _gcry_pk_verify (sig, data_bad, pkey);
+  if (gcry_err_code (err) != GPG_ERR_BAD_SIGNATURE)
+    {
+      errtxt = "bad signature not detected";
+      goto leave;
+    }
+
+
+ leave:
+  sexp_release (sig);
+  sexp_release (data_bad);
+  sexp_release (data);
+  sexp_release (l1);
+  sexp_release (l2);
+  mpi_release (r);
+  mpi_release (s);
+  mpi_release (calculated_r);
+  mpi_release (calculated_s);
+  return errtxt;
+}
+
 
 static gpg_err_code_t
 selftests_ecdsa (selftest_report_func_t report)
 {
   const char *what;
   const char *errtxt;
+  gcry_error_t err;
+  gcry_sexp_t skey = NULL;
+  gcry_sexp_t pkey = NULL;
+
+  what = "convert";
+  err = sexp_sscan (&skey, NULL, sample_secret_key_secp256,
+                    strlen (sample_secret_key_secp256));
+  if (!err)
+    err = sexp_sscan (&pkey, NULL, sample_public_key_secp256,
+                      strlen (sample_public_key_secp256));
+  if (err)
+    {
+      errtxt = _gcry_strerror (err);
+      goto failed;
+    }
+
+  what = "key consistency";
+  err = ecc_check_secret_key(skey);
+  if (err)
+    {
+      errtxt = _gcry_strerror (err);
+      goto failed;
+    }
 
-  what = "low-level";
-  errtxt = NULL; /*selftest ();*/
+  what = "sign";
+  errtxt = selftest_sign (pkey, skey);
   if (errtxt)
     goto failed;
 
-  /* FIXME:  need more tests.  */
-
+  sexp_release(pkey);
+  sexp_release(skey);
   return 0; /* Succeeded. */
 
  failed:
+  sexp_release(pkey);
+  sexp_release(skey);
   if (report)
     report ("pubkey", GCRY_PK_ECC, what, errtxt);
   return GPG_ERR_SELFTEST_FAILED;
@@ -1996,7 +2157,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
 

 gcry_pk_spec_t _gcry_pubkey_spec_ecc =
   {
-    GCRY_PK_ECC, { 0, 0 },
+    GCRY_PK_ECC, { 0, 1 },
     (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR),
     "ECC", ecc_names,
     "pabgnhq", "pabgnhqd", "sw", "rs", "pabgnhq",
diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c
index d0d6003..76d3923 100644
--- a/cipher/pubkey-util.c
+++ b/cipher/pubkey-util.c
@@ -617,7 +617,14 @@ _gcry_pk_util_init_encoding_ctx (struct pk_encoding_ctx *ctx,
   ctx->nbits = nbits;
   ctx->encoding = PUBKEY_ENC_UNKNOWN;
   ctx->flags = 0;
-  ctx->hash_algo = GCRY_MD_SHA1;
+  if (fips_mode ())
+    {
+      ctx->hash_algo = GCRY_MD_SHA256;
+    }
+  else
+    {
+      ctx->hash_algo = GCRY_MD_SHA1;
+    }
   ctx->label = NULL;
   ctx->labellen = 0;
   ctx->saltlen = 20;
diff --git a/src/fips.c b/src/fips.c
index edcbeac..3311ba2 100644
--- a/src/fips.c
+++ b/src/fips.c
@@ -549,7 +549,7 @@ run_pubkey_selftests (int extended)
     {
       GCRY_PK_RSA,
       GCRY_PK_DSA,
-      /* GCRY_PK_ECC is not enabled in fips mode.  */
+      GCRY_PK_ECC,
       0
     };
   int idx;
diff --git a/tests/fipsdrv.c b/tests/fipsdrv.c
index d757420..b5962cf 100644
--- a/tests/fipsdrv.c
+++ b/tests/fipsdrv.c
@@ -1721,6 +1721,33 @@ dsa_gen_with_seed (int keysize, const void *seed, size_t seedlen)
 }
 
 
+/* Generate an ECDSA key on the specified curve and return the complete
+   S-expression. */
+static gcry_sexp_t
+ecdsa_gen_key (const char *curve)
+{
+  gpg_error_t err;
+  gcry_sexp_t keyspec, key;
+
+  err = gcry_sexp_build (&keyspec, NULL,
+                         "(genkey"
+                         "  (ecc"
+                         "    (use-fips186)"
+                         "    (curve %s)))",
+                         curve);
+  if (err)
+    die ("gcry_sexp_build failed for ECDSA key generation: %s\n",
+         gpg_strerror (err));
+  err = gcry_pk_genkey (&key, keyspec);
+  if (err)
+    die ("gcry_pk_genkey failed for ECDSA: %s\n", gpg_strerror (err));
+
+  gcry_sexp_release (keyspec);
+
+  return key;
+}
+
+
 /* Print the domain parameter as well as the derive information.  KEY
    is the complete key as returned by dsa_gen.  We print to stdout
    with one parameter per line in hex format using this order: p, q,
@@ -1813,6 +1840,46 @@ print_dsa_domain_parameters (gcry_sexp_t key)
 }
 
 
+/* Print public key Q (in octet-string format) and private key d.
+   KEY is the complete key as returned by ecdsa_gen_key.
+   with one parameter per line in hex format using this order: d, Q. */
+static void
+print_ecdsa_dq (gcry_sexp_t key)
+{
+  gcry_sexp_t l1, l2;
+  gcry_mpi_t mpi;
+  int idx;
+
+  l1 = gcry_sexp_find_token (key, "private-key", 0);
+  if (!l1)
+    die ("private key not found in genkey result\n");
+
+  l2 = gcry_sexp_find_token (l1, "ecc", 0);
+  if (!l2)
+    die ("returned private key not formed as expected\n");
+  gcry_sexp_release (l1);
+  l1 = l2;
+
+  /* Extract the parameters from the S-expression and print them to stdout.  */
+  for (idx=0; "dq"[idx]; idx++)
+    {
+      l2 = gcry_sexp_find_token (l1, "dq"+idx, 1);
+      if (!l2)
+        die ("no %c parameter in returned public key\n", "dq"[idx]);
+      mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
+      if (!mpi)
+        die ("no value for %c parameter in returned private key\n","dq"[idx]);
+      gcry_sexp_release (l2);
+      if (standalone_mode)
+        printf ("%c = ", "dQ"[idx]);
+      print_mpi_line (mpi, 1);
+      gcry_mpi_release (mpi);
+    }
+
+  gcry_sexp_release (l1);
+}
+
+
 /* Generate DSA domain parameters for a modulus size of KEYSIZE.  The
    result is printed to stdout with one parameter per line in hex
    format and in this order: p, q, g, seed, counter, h.  If SEED is
@@ -1992,6 +2059,138 @@ run_dsa_verify (const void *data, size_t datalen,
 }
 
 
+

+/* Sign DATA of length DATALEN using the key taken from the S-expression
+   encoded KEYFILE. */
+static void
+run_ecdsa_sign (const void *data, size_t datalen,
+                const char *keyfile, const int algo)
+
+{
+  gpg_error_t err;
+  gcry_sexp_t s_data, s_key, s_sig, s_tmp;
+  char hash[128];
+  gcry_mpi_t tmpmpi;
+
+  s_key = read_sexp_from_file (keyfile);
+
+  gcry_md_hash_buffer (algo, hash, data, datalen);
+  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash,
+                       gcry_md_get_algo_dlen(algo), NULL);
+  if (!err)
+    {
+      err = gcry_sexp_build (&s_data, NULL,
+                             "(data (flags raw)(hash %s %M))",
+                             gcry_md_algo_name(algo), tmpmpi);
+      gcry_mpi_release (tmpmpi);
+    }
+  if (err)
+    die ("gcry_sexp_build failed for ECDSA data input: %s\n",
+         gpg_strerror (err));
+
+  err = gcry_pk_sign (&s_sig, s_data, s_key);
+  if (err)
+    {
+      die ("gcry_pk_signed failed: %s\n", gpg_strerror (err));
+    }
+  gcry_sexp_release (s_data);
+  gcry_sexp_release (s_key);
+
+  /* Now return the actual signature.  */
+  s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0);
+  if (!s_tmp)
+    die ("no sig-val element in returned S-expression\n");
+
+  gcry_sexp_release (s_sig);
+  s_sig = s_tmp;
+  s_tmp = gcry_sexp_find_token (s_sig, "ecdsa", 0);
+  if (!s_tmp)
+    die ("no ecdsa element in returned S-expression\n");
+
+  gcry_sexp_release (s_sig);
+  s_sig = s_tmp;
+
+  s_tmp = gcry_sexp_find_token (s_sig, "r", 0);
+  tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG);
+  if (!tmpmpi)
+    die ("no r parameter in returned S-expression\n");
+  print_mpi_line (tmpmpi, 1);
+  gcry_mpi_release (tmpmpi);
+  gcry_sexp_release (s_tmp);
+
+  s_tmp = gcry_sexp_find_token (s_sig, "s", 0);
+  tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG);
+  if (!tmpmpi)
+    die ("no s parameter in returned S-expression\n");
+  print_mpi_line (tmpmpi, 1);
+  gcry_mpi_release (tmpmpi);
+  gcry_sexp_release (s_tmp);
+
+  gcry_sexp_release (s_sig);
+}
+
+
+

+/* Verify DATA of length DATALEN using the public key taken from the
+   S-expression in KEYFILE against the S-expression formatted
+   signature in SIGFILE.  */
+static void
+run_ecdsa_verify (const void *data, size_t datalen,
+                const char *keyfile, const int algo, const char *sigfile)
+
+{
+  gpg_error_t err;
+  gcry_sexp_t s_data, s_key, s_sig;
+  char hash[128];
+  gcry_mpi_t tmpmpi;
+
+  s_key = read_sexp_from_file (keyfile);
+
+  gcry_md_hash_buffer (algo, hash, data, datalen);
+  /* Note that we can't simply use %b with HASH to build the
+     S-expression, because that might yield a negative value.  */
+  err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash,
+                       gcry_md_get_algo_dlen(algo), NULL);
+  if (!err)
+    {
+      err = gcry_sexp_build (&s_data, NULL,
+                             "(data (flags raw)(hash %s %M))",
+                             gcry_md_algo_name(algo), tmpmpi);
+      gcry_mpi_release (tmpmpi);
+    }
+  if (err)
+    die ("gcry_sexp_build failed for DSA data input: %s\n",
+         gpg_strerror (err));
+
+  s_sig = read_sexp_from_file (sigfile);
+
+  err = gcry_pk_verify (s_sig, s_data, s_key);
+  if (!err)
+    puts ("GOOD signature");
+  else if (gpg_err_code (err) == GPG_ERR_BAD_SIGNATURE)
+    puts ("BAD signature");
+  else
+    printf ("ERROR (%s)\n", gpg_strerror (err));
+
+  gcry_sexp_release (s_sig);
+  gcry_sexp_release (s_key);
+  gcry_sexp_release (s_data);
+}
+
+
+/* Generate an ECDSA key with specified domain parameters
+   and print the d and Q values, in the standard octet-string format. */
+static void
+run_ecdsa_gen_key (const char *curve)
+{
+  gcry_sexp_t key;
+
+  key = ecdsa_gen_key (curve);
+  print_ecdsa_dq (key);
+
+  gcry_sexp_release (key);
+}
+
 
 

 static void
@@ -2008,7 +2207,8 @@ usage (int show_help)
      "Run a crypto operation using hex encoded input and output.\n"
      "MODE:\n"
      "  encrypt, decrypt, digest, random, hmac-sha,\n"
-     "  rsa-{derive,gen,sign,verify}, dsa-{pqg-gen,gen,sign,verify}\n"
+     "  rsa-{derive,gen,sign,verify},\n"
+     "  dsa-{pqg-gen,gen,sign,verify}, ecdsa-{gen-key,sign,verify}\n"
      "OPTIONS:\n"
      "  --verbose        Print additional information\n"
      "  --binary         Input and output is in binary form\n"
@@ -2017,6 +2217,7 @@ usage (int show_help)
      "  --iv IV          Use the hex encoded IV\n"
      "  --dt DT          Use the hex encoded DT for the RNG\n"
      "  --algo NAME      Use algorithm NAME\n"
+     "  --curve NAME     Select ECC curve spec NAME\n"
      "  --keysize N      Use a keysize of N bits\n"
      "  --signature NAME Take signature from file NAME\n"
      "  --chunk N        Read in chunks of N bytes (implies --binary)\n"
@@ -2039,6 +2240,7 @@ main (int argc, char **argv)
   int progress = 0;
   int use_pkcs1 = 0;
   const char *mode_string;
+  const char *curve_string = NULL;
   const char *key_string = NULL;
   const char *iv_string = NULL;
   const char *dt_string = NULL;
@@ -2154,6 +2356,14 @@ main (int argc, char **argv)
           binary_input = binary_output = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--curve"))
+        {
+          argc--; argv++;
+          if (!argc)
+            usage (0);
+          curve_string = *argv;
+          argc--; argv++;
+        }
       else if (!strcmp (*argv, "--pkcs1"))
         {
           use_pkcs1 = 1;
@@ -2211,7 +2421,8 @@ main (int argc, char **argv)
       && !mct_server
       && strcmp (mode_string, "random")
       && strcmp (mode_string, "rsa-gen")
-      && strcmp (mode_string, "dsa-gen") )
+      && strcmp (mode_string, "dsa-gen")
+      && strcmp (mode_string, "ecdsa-gen-key") )
     {
       data = read_file (input, !binary_input, &datalen);
       if (!data)
@@ -2501,6 +2712,53 @@ main (int argc, char **argv)
 
       run_dsa_verify (data, datalen, key_string, signature_string);
     }
+  else if (!strcmp (mode_string, "ecdsa-gen-key"))
+    {
+      if (!curve_string)
+        die ("option --curve containing name of the specified curve is required in this mode\n");
+      run_ecdsa_gen_key (curve_string);
+    }
+  else if (!strcmp (mode_string, "ecdsa-sign"))
+    {
+      int algo;
+
+      if (!key_string)
+        die ("option --key is required in this mode\n");
+      if (access (key_string, R_OK))
+        die ("option --key needs to specify an existing keyfile\n");
+      if (!algo_string)
+        die ("use --algo to specify the digest algorithm\n");
+      algo = gcry_md_map_name (algo_string);
+      if (!algo)
+        die ("digest algorithm `%s' is not supported\n", algo_string);
+
+      if (!data)
+        die ("no data available (do not use --chunk)\n");
+
+      run_ecdsa_sign (data, datalen, key_string, algo);
+    }
+  else if (!strcmp (mode_string, "ecdsa-verify"))
+    {
+      int algo;
+
+      if (!key_string)
+        die ("option --key is required in this mode\n");
+      if (access (key_string, R_OK))
+        die ("option --key needs to specify an existing keyfile\n");
+      if (!algo_string)
+        die ("use --algo to specify the digest algorithm\n");
+      algo = gcry_md_map_name (algo_string);
+      if (!algo)
+        die ("digest algorithm `%s' is not supported\n", algo_string);
+      if (!data)
+        die ("no data available (do not use --chunk)\n");
+      if (!signature_string)
+        die ("option --signature is required in this mode\n");
+      if (access (signature_string, R_OK))
+        die ("option --signature needs to specify an existing file\n");
+
+      run_ecdsa_verify (data, datalen, key_string, algo, signature_string);
+    }
   else
     usage (0);
 

commit e40939b2141306238cc30a340b867b60fa4dc2a3
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Mar 18 15:11:31 2016 +0100

    dsa: Make regression tests work.
    
    * cipher/dsa.c (sample_secret_key_1024): Comment out unused constant.
    (ogenerate_fips186): Make it work with use-fips183-2 flag.
    * cipher/primegen.c (_gcry_generate_fips186_3_prime): Use Emacs
    standard comment out format.
    * tests/fips186-dsa.c (check_dsa_gen_186_3): New dummy fucntion.
    (main): Call it.
    (main): Compare against current version.
    * tests/pubkey.c (get_dsa_key_fips186_new): Create 2048 bit key.
    (get_dsa_key_fips186_with_seed_new): Ditto.
    (get_dsa_key_fips186_with_domain_new): Comment out.
    (check_run): Do not call that function.
    --
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/cipher/dsa.c b/cipher/dsa.c
index 37c1b18..909a8ca 100644
--- a/cipher/dsa.c
+++ b/cipher/dsa.c
@@ -66,7 +66,9 @@ static const char *dsa_names[] =
   };
 
 
-/* A sample 1024 bit DSA key used for the selftests.  */
+/* A sample 1024 bit DSA key used for the selftests.  Not anymore
+ * used, kept only for reference.  */
+#if 0
 static const char sample_secret_key_1024[] =
 "(private-key"
 " (dsa"
@@ -101,6 +103,7 @@ static const char sample_public_key_1024[] =
 "      A1816A724C34F87330FC9E187C5D66897A04535CC2AC9164A7150ABFA8179827"
 "      6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20"
 "      42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)))";
+#endif /*0*/
 
 /* 2048 DSA key from RFC 6979 A.2.2 */
 static const char sample_public_key_2048[] =
@@ -412,7 +415,9 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
 
   /* Check that QBITS and NBITS match the standard.  Note that FIPS
      186-3 uses N for QBITS and L for NBITS.  */
-  if (nbits == 2048 && qbits == 224)
+  if (nbits == 1024 && qbits == 160 && use_fips186_2)
+    ; /* Allowed in FIPS 186-2 mode.  */
+  else if (nbits == 2048 && qbits == 224)
     ;
   else if (nbits == 2048 && qbits == 256)
     ;
@@ -442,27 +447,28 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
           initial_seed.sexp = sexp_find_token (deriveparms, "seed", 0);
           if (initial_seed.sexp)
             initial_seed.seed = sexp_nth_data (initial_seed.sexp, 1,
-                                                    &initial_seed.seedlen);
+                                               &initial_seed.seedlen);
         }
 
       if (use_fips186_2)
         ec = _gcry_generate_fips186_2_prime (nbits, qbits,
-                                           initial_seed.seed,
-                                           initial_seed.seedlen,
-                                           &prime_q, &prime_p,
-                                           r_counter,
-                                           r_seed, r_seedlen);
+                                             initial_seed.seed,
+                                             initial_seed.seedlen,
+                                             &prime_q, &prime_p,
+                                             r_counter,
+                                             r_seed, r_seedlen);
       else
         ec = _gcry_generate_fips186_3_prime (nbits, qbits, NULL, 0,
-                                           &prime_q, &prime_p,
-                                           r_counter,
-                                           r_seed, r_seedlen, NULL);
+                                             &prime_q, &prime_p,
+                                             r_counter,
+                                             r_seed, r_seedlen, NULL);
       sexp_release (initial_seed.sexp);
       if (ec)
         goto leave;
 
       /* Find a generator g (h and e are helpers).
-         e = (p-1)/q */
+       *    e = (p-1)/q
+       */
       value_e = mpi_alloc_like (prime_p);
       mpi_sub_ui (value_e, prime_p, 1);
       mpi_fdiv_q (value_e, value_e, prime_q );
diff --git a/cipher/primegen.c b/cipher/primegen.c
index 9fd58d2..3ed432b 100644
--- a/cipher/primegen.c
+++ b/cipher/primegen.c
@@ -1612,23 +1612,21 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits,
 
 
 

-/* WARNING: The code below has not yet been tested!  However, it is
-   not yet used.  We need to wait for FIPS 186-3 final and for test
-   vectors.
-
-   Generate the two prime used for DSA using the algorithm specified
-   in FIPS 186-3, A.1.1.2.  PBITS is the desired length of the prime P
-   and a QBITS the length of the prime Q.  If SEED is not supplied and
-   SEEDLEN is 0 the function generates an appropriate SEED.  On
-   success the generated primes are stored at R_Q and R_P, the counter
-   value is stored at R_COUNTER and the seed actually used for
-   generation is stored at R_SEED and R_SEEDVALUE.  The hash algorithm
-   used is stored at R_HASHALGO.
-
-   Note that this function is very similar to the fips186_2 code.  Due
-   to the minor differences, other buffer sizes and for documentarion,
-   we use a separate function.
-*/
+/* WARNING: The code below has not yet been tested!
+ *
+ * Generate the two prime used for DSA using the algorithm specified
+ * in FIPS 186-3, A.1.1.2.  PBITS is the desired length of the prime P
+ * and a QBITS the length of the prime Q.  If SEED is not supplied and
+ * SEEDLEN is 0 the function generates an appropriate SEED.  On
+ * success the generated primes are stored at R_Q and R_P, the counter
+ * value is stored at R_COUNTER and the seed actually used for
+ * generation is stored at R_SEED and R_SEEDVALUE.  The hash algorithm
+ * used is stored at R_HASHALGO.
+ *
+ * Note that this function is very similar to the fips186_2 code.  Due
+ * to the minor differences, other buffer sizes and for documentarion,
+ * we use a separate function.
+ */
 gpg_err_code_t
 _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits,
                                 const void *seed, size_t seedlen,
@@ -1813,13 +1811,12 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits,
     }
 
   /* Step 12:  Save p, q, counter and seed.  */
-/*
-  log_debug ("fips186-3 pbits p=%u q=%u counter=%d\n",
-             mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter);
-  log_printhex ("fips186-3 seed", seed, seedlen);
-  log_printmpi ("fips186-3    p", prime_p);
-  log_printmpi ("fips186-3    q", prime_q);
-*/
+  /* log_debug ("fips186-3 pbits p=%u q=%u counter=%d\n", */
+  /*            mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter); */
+  /* log_printhex ("fips186-3 seed", seed, seedlen); */
+  /* log_printmpi ("fips186-3    p", prime_p); */
+  /* log_printmpi ("fips186-3    q", prime_q); */
+
   if (r_q)
     {
       *r_q = prime_q;
diff --git a/tests/fips186-dsa.c b/tests/fips186-dsa.c
index 10b18ab..5ee829e 100644
--- a/tests/fips186-dsa.c
+++ b/tests/fips186-dsa.c
@@ -434,6 +434,14 @@ check_dsa_gen_186_2 (void)
 }
 
 
+static void
+check_dsa_gen_186_3 (void)
+{
+  /* FIXME: Needs to be implemented.  */
+  if (verbose)
+    info ("generating FIPS 186-3 test keys - skipped\n");
+}
+
 
 int
 main (int argc, char **argv)
@@ -449,7 +457,7 @@ main (int argc, char **argv)
     }
 
   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  if (!gcry_check_version ("1.4.4"))
+  if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
   if (debug)
@@ -459,6 +467,7 @@ main (int argc, char **argv)
 
 
   check_dsa_gen_186_2 ();
+  check_dsa_gen_186_3 ();
 
 
   return error_count ? 1 : 0;
diff --git a/tests/pubkey.c b/tests/pubkey.c
index ae5eea2..26bd9e3 100644
--- a/tests/pubkey.c
+++ b/tests/pubkey.c
@@ -490,7 +490,7 @@ get_dsa_key_fips186_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
   int rc;
 
   rc = gcry_sexp_new
-    (&key_spec, "(genkey (dsa (nbits 4:1024)(use-fips186)))",  0, 1);
+    (&key_spec, "(genkey (dsa (nbits 4:2048)(use-fips186)))",  0, 1);
   if (rc)
     die ("error creating S-expression: %s\n", gcry_strerror (rc));
   rc = gcry_pk_genkey (&key, key_spec);
@@ -557,6 +557,7 @@ get_dsa_key_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
   *skey = sec_key;
 }
 
+#if 0
 static void
 get_dsa_key_fips186_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
 {
@@ -598,7 +599,7 @@ get_dsa_key_fips186_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
   *pkey = pub_key;
   *skey = sec_key;
 }
-
+#endif /*0*/
 
 static void
 get_dsa_key_fips186_with_seed_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
@@ -610,7 +611,7 @@ get_dsa_key_fips186_with_seed_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
     (&key_spec,
      "(genkey"
      "  (dsa"
-     "    (nbits 4:1024)"
+     "    (nbits 4:2048)"
      "    (use-fips186)"
      "    (transient-key)"
      "    (derive-parms"
@@ -722,12 +723,14 @@ check_run (void)
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
 
+  /* We need new test vectors for get_dsa_key_fips186_with_domain_new.  */
   if (verbose)
-    fprintf (stderr, "Generating DSA key with given domain (FIPS 186).\n");
-  get_dsa_key_fips186_with_domain_new (&pkey, &skey);
-  /* Fixme:  Add a check function for DSA keys.  */
-  gcry_sexp_release (pkey);
-  gcry_sexp_release (skey);
+    fprintf (stderr, "Generating DSA key with given domain (FIPS 186)"
+             " - skipped.\n");
+  /* get_dsa_key_fips186_with_domain_new (&pkey, &skey); */
+  /* /\* Fixme:  Add a check function for DSA keys.  *\/ */
+  /* gcry_sexp_release (pkey); */
+  /* gcry_sexp_release (skey); */
 
   if (verbose)
     fprintf (stderr, "Generating DSA key with given seed (FIPS 186).\n");

commit 80e9f95e6f419daa765e4876c858e3e36e808897
Author: Vitezslav Cizek <vcizek at suse.com>
Date:   Tue Oct 27 12:46:30 2015 +0100

    dsa: Adjustments to conform with FIPS 186-4.
    
    * cipher/dsa.c (generate_fips186): FIPS 186-4 adjustments.
    * cipher/primegen.c (_gcry_generate_fips186_3_prime): Fix incorrect
      buflen passed to _gcry_mpi_scan.
    --
    
    Generate the DSA keypair by testing candidates. (FIPS 186-4 B.1.2)
    Use 2048 bit key for the selftest.
    Allow only 2048 and 3072 as pbits size.
    
    Signed-off-by: Vitezslav Cizek <vcizek at suse.com>

diff --git a/cipher/dsa.c b/cipher/dsa.c
index 01d153f..37c1b18 100644
--- a/cipher/dsa.c
+++ b/cipher/dsa.c
@@ -67,7 +67,7 @@ static const char *dsa_names[] =
 
 
 /* A sample 1024 bit DSA key used for the selftests.  */
-static const char sample_secret_key[] =
+static const char sample_secret_key_1024[] =
 "(private-key"
 " (dsa"
 "  (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB"
@@ -85,7 +85,7 @@ static const char sample_secret_key[] =
 "      42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)"
 "  (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))";
 /* A sample 1024 bit DSA key used for the selftests (public only).  */
-static const char sample_public_key[] =
+static const char sample_public_key_1024[] =
 "(public-key"
 " (dsa"
 "  (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB"
@@ -102,6 +102,23 @@ static const char sample_public_key[] =
 "      6E45831AB811EEE848EBB24D9F5F2883B6E5DDC4C659DEF944DCFD80BF4D0A20"
 "      42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)))";
 
+/* 2048 DSA key from RFC 6979 A.2.2 */
+static const char sample_public_key_2048[] =
+"(public-key"
+" (dsa"
+"  (p #9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44FFE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE235567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA153E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B#)"
+"  (q #F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F#)"
+"  (g #5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C46A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7#)"
+"  (y #667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD949F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA611728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADECB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D123AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF#)))";
+
+static const char sample_secret_key_2048[] =
+"(private-key"
+" (dsa"
+"  (p #9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44FFE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE235567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA153E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B#)"
+"  (q #F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F#)"
+"  (g #5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C46A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7#)"
+"  (y #667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD949F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA611728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADECB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D123AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF#)"
+"  (x #69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC#)))";
 
 
 

@@ -373,6 +390,8 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
   gcry_mpi_t value_x = NULL; /* The secret exponent. */
   gcry_mpi_t value_h = NULL; /* Helper.  */
   gcry_mpi_t value_e = NULL; /* Helper.  */
+  gcry_mpi_t value_c = NULL; /* helper for x */
+  gcry_mpi_t value_qm2 = NULL; /* q - 2 */
 
   /* Preset return values.  */
   *r_counter = 0;
@@ -393,9 +412,7 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
 
   /* Check that QBITS and NBITS match the standard.  Note that FIPS
      186-3 uses N for QBITS and L for NBITS.  */
-  if (nbits == 1024 && qbits == 160)
-    ;
-  else if (nbits == 2048 && qbits == 224)
+  if (nbits == 2048 && qbits == 224)
     ;
   else if (nbits == 2048 && qbits == 256)
     ;
@@ -428,21 +445,18 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
                                                     &initial_seed.seedlen);
         }
 
-      /* Fixme: Enable 186-3 after it has been approved and after fixing
-         the generation function.  */
-      /*   if (use_fips186_2) */
-      (void)use_fips186_2;
-      ec = _gcry_generate_fips186_2_prime (nbits, qbits,
+      if (use_fips186_2)
+        ec = _gcry_generate_fips186_2_prime (nbits, qbits,
                                            initial_seed.seed,
                                            initial_seed.seedlen,
                                            &prime_q, &prime_p,
                                            r_counter,
                                            r_seed, r_seedlen);
-      /*   else */
-      /*     ec = _gcry_generate_fips186_3_prime (nbits, qbits, NULL, 0, */
-      /*                                          &prime_q, &prime_p, */
-      /*                                          r_counter, */
-      /*                                          r_seed, r_seedlen, NULL); */
+      else
+        ec = _gcry_generate_fips186_3_prime (nbits, qbits, NULL, 0,
+                                           &prime_q, &prime_p,
+                                           r_counter,
+                                           r_seed, r_seedlen, NULL);
       sexp_release (initial_seed.sexp);
       if (ec)
         goto leave;
@@ -463,17 +477,24 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
       while (!mpi_cmp_ui (value_g, 1));  /* Continue until g != 1.  */
     }
 
-
-  /* Select a random number x with:  0 < x < q  */
+  value_c = mpi_snew (qbits);
   value_x = mpi_snew (qbits);
+  value_qm2 = mpi_snew (qbits);
+  mpi_sub_ui (value_qm2, prime_q, 2);
+
+  /* FIPS 186-4 B.1.2 steps 4-6 */
   do
     {
       if( DBG_CIPHER )
         progress('.');
-      _gcry_mpi_randomize (value_x, qbits, GCRY_VERY_STRONG_RANDOM);
-      mpi_clear_highbit (value_x, qbits+1);
+      _gcry_mpi_randomize (value_c, qbits, GCRY_VERY_STRONG_RANDOM);
+      mpi_clear_highbit (value_c, qbits+1);
     }
-  while (!(mpi_cmp_ui (value_x, 0) > 0 && mpi_cmp (value_x, prime_q) < 0));
+  while (!(mpi_cmp_ui (value_c, 0) > 0 && mpi_cmp (value_c, value_qm2) < 0));
+  /* while (mpi_cmp (value_c, value_qm2) > 0); */
+
+  /* x = c + 1 */
+  mpi_add_ui(value_x, value_c, 1);
 
   /* y = g^x mod p */
   value_y = mpi_alloc_like (prime_p);
@@ -506,6 +527,8 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
   _gcry_mpi_release (value_x);
   _gcry_mpi_release (value_h);
   _gcry_mpi_release (value_e);
+  _gcry_mpi_release (value_c);
+  _gcry_mpi_release (value_qm2);
 
   /* As a last step test this keys (this should never fail of course). */
   if (!ec && test_keys (sk, qbits) )
@@ -1158,25 +1181,42 @@ dsa_get_nbits (gcry_sexp_t parms)
  */
 
 static const char *
-selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
+selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey)
 {
+  /* Sample data from RFC 6979 section A.2.2, hash is of message "sample" */
   static const char sample_data[] =
-    "(data (flags raw)"
-    " (value #a0b1c2d3e4f500102030405060708090a1b2c3d4#))";
+    "(data (flags rfc6979)"
+    " (hash sha256 #af2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e9891562113d8a62add1bf#))";
   static const char sample_data_bad[] =
-    "(data (flags raw)"
-    " (value #a0b1c2d3e4f510102030405060708090a1b2c3d4#))";
+    "(data (flags rfc6979)"
+    " (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e9891562113d8a62add1bf#))";
+  static const char signature_r[] =
+    "eace8bdbbe353c432a795d9ec556c6d021f7a03f42c36e9bc87e4ac7932cc809";
+  static const char signature_s[] =
+    "7081e175455f9247b812b74583e9e94f9ea79bd640dc962533b0680793a38d53";
 
   const char *errtxt = NULL;
   gcry_error_t err;
   gcry_sexp_t data = NULL;
   gcry_sexp_t data_bad = NULL;
   gcry_sexp_t sig = NULL;
+  gcry_sexp_t l1 = NULL;
+  gcry_sexp_t l2 = NULL;
+  gcry_mpi_t r = NULL;
+  gcry_mpi_t s = NULL;
+  gcry_mpi_t calculated_r = NULL;
+  gcry_mpi_t calculated_s = NULL;
+  int cmp;
 
   err = sexp_sscan (&data, NULL, sample_data, strlen (sample_data));
   if (!err)
     err = sexp_sscan (&data_bad, NULL,
                       sample_data_bad, strlen (sample_data_bad));
+  if (!err)
+    err = _gcry_mpi_scan (&r, GCRYMPI_FMT_HEX, signature_r, 0, NULL);
+  if (!err)
+    err = _gcry_mpi_scan (&s, GCRYMPI_FMT_HEX, signature_s, 0, NULL);
+
   if (err)
     {
       errtxt = "converting data failed";
@@ -1189,6 +1229,45 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
       errtxt = "signing failed";
       goto leave;
     }
+
+  /* check against known signature */
+  errtxt = "signature validity failed";
+  l1 = _gcry_sexp_find_token (sig, "sig-val", 0);
+  if (!l1)
+    goto leave;
+  l2 = _gcry_sexp_find_token (l1, "dsa", 0);
+  if (!l2)
+    goto leave;
+
+  sexp_release (l1);
+  l1 = l2;
+
+  l2 = _gcry_sexp_find_token (l1, "r", 0);
+  if (!l2)
+    goto leave;
+  calculated_r = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
+  if (!calculated_r)
+    goto leave;
+
+  l2 = _gcry_sexp_find_token (l1, "s", 0);
+  if (!l2)
+    goto leave;
+  calculated_s = _gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
+  if (!calculated_s)
+    goto leave;
+
+  errtxt = "known sig check failed";
+
+  cmp = _gcry_mpi_cmp (r, calculated_r);
+  if (cmp)
+    goto leave;
+  cmp = _gcry_mpi_cmp (s, calculated_s);
+  if (cmp)
+    goto leave;
+
+  errtxt = NULL;
+
+
   err = _gcry_pk_verify (sig, data, pkey);
   if (err)
     {
@@ -1212,7 +1291,7 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey)
 
 
 static gpg_err_code_t
-selftests_dsa (selftest_report_func_t report)
+selftests_dsa_2048 (selftest_report_func_t report)
 {
   const char *what;
   const char *errtxt;
@@ -1222,10 +1301,10 @@ selftests_dsa (selftest_report_func_t report)
 
   /* Convert the S-expressions into the internal representation.  */
   what = "convert";
-  err = sexp_sscan (&skey, NULL, sample_secret_key, strlen (sample_secret_key));
+  err = sexp_sscan (&skey, NULL, sample_secret_key_2048, strlen (sample_secret_key_2048));
   if (!err)
     err = sexp_sscan (&pkey, NULL,
-                      sample_public_key, strlen (sample_public_key));
+                      sample_public_key_2048, strlen (sample_public_key_2048));
   if (err)
     {
       errtxt = _gcry_strerror (err);
@@ -1241,7 +1320,7 @@ selftests_dsa (selftest_report_func_t report)
     }
 
   what = "sign";
-  errtxt = selftest_sign_1024 (pkey, skey);
+  errtxt = selftest_sign (pkey, skey);
   if (errtxt)
     goto failed;
 
@@ -1269,7 +1348,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
   switch (algo)
     {
     case GCRY_PK_DSA:
-      ec = selftests_dsa (report);
+      ec = selftests_dsa_2048 (report);
       break;
     default:
       ec = GPG_ERR_PUBKEY_ALGO;
@@ -1280,7 +1359,6 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
 }
 
 
-
 

 gcry_pk_spec_t _gcry_pubkey_spec_dsa =
   {
diff --git a/cipher/primegen.c b/cipher/primegen.c
index 2a702a7..9fd58d2 100644
--- a/cipher/primegen.c
+++ b/cipher/primegen.c
@@ -1640,7 +1640,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits,
   gpg_err_code_t ec;
   unsigned char seed_help_buffer[256/8];  /* Used to hold a generated SEED. */
   unsigned char *seed_plus;     /* Malloced buffer to hold SEED+x.  */
-  unsigned char digest[256/8];  /* Helper buffer for SHA-1 digest.  */
+  unsigned char digest[256/8];  /* Helper buffer for SHA-2 digest.  */
   gcry_mpi_t val_2 = NULL;      /* Helper for the prime test.  */
   gcry_mpi_t tmpval = NULL;     /* Helper variable.  */
   int hashalgo;                 /* The id of the Approved Hash Function.  */
@@ -1659,9 +1659,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits,
 
   /* Step 1:  Check the requested prime lengths.  */
   /* Note that due to the size of our buffers QBITS is limited to 256.  */
-  if (pbits == 1024 && qbits == 160)
-    hashalgo = GCRY_MD_SHA1;
-  else if (pbits == 2048 && qbits == 224)
+  if (pbits == 2048 && qbits == 224)
     hashalgo = GCRY_MD_SHA224;
   else if (pbits == 2048 && qbits == 256)
     hashalgo = GCRY_MD_SHA256;
@@ -1730,7 +1728,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits,
         }
       _gcry_mpi_release (prime_q); prime_q = NULL;
       ec = _gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG,
-                           value_u, sizeof value_u, NULL);
+                           value_u, qbits/8, NULL);
       if (ec)
         goto leave;
       mpi_set_highbit (prime_q, qbits-1 );
@@ -1775,11 +1773,11 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits,
               if (seed_plus[i])
                 break;
             }
-          _gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen);
+          _gcry_md_hash_buffer (hashalgo, digest, seed_plus, seedlen);
 
           _gcry_mpi_release (tmpval); tmpval = NULL;
           ec = _gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG,
-                               digest, sizeof digest, NULL);
+                               digest, qbits/8, NULL);
           if (ec)
             goto leave;
           if (value_j == value_n)
@@ -1815,11 +1813,13 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits,
     }
 
   /* Step 12:  Save p, q, counter and seed.  */
+/*
   log_debug ("fips186-3 pbits p=%u q=%u counter=%d\n",
              mpi_get_nbits (prime_p), mpi_get_nbits (prime_q), counter);
   log_printhex ("fips186-3 seed", seed, seedlen);
   log_printmpi ("fips186-3    p", prime_p);
   log_printmpi ("fips186-3    q", prime_q);
+*/
   if (r_q)
     {
       *r_q = prime_q;

commit 443bed836a4fd60217325789134f5a2dc2ec41ce
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Mar 18 13:05:34 2016 +0100

    Register DCO for Vitezslav Cizek.
    
    --
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/AUTHORS b/AUTHORS
index 42d5ee6..b19612b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -180,6 +180,9 @@ Stephan Mueller <smueller at chronox.de>
 Tomáš Mráz <tm at t8m.info>
 2012-04-16:1334571250.5056.52.camel at vespa.frost.loc:
 
+Vitezslav Cizek <vcizek at suse.com>
+2015-11-05:20151105131424.GA32700 at kolac.suse.cz:
+
 Werner Koch <wk at gnupg.org> (g10 Code GmbH)
 2012-12-05:87obi8u4h2.fsf at vigenere.g10code.de:
 

-----------------------------------------------------------------------

Summary of changes:
 AUTHORS              |   3 +
 cipher/cipher.c      |  11 ++
 cipher/dsa.c         | 160 ++++++++++++++++++------
 cipher/ecc-curves.c  |   2 +-
 cipher/ecc.c         | 171 +++++++++++++++++++++++++-
 cipher/kdf.c         |  16 ++-
 cipher/mac.c         |  17 +++
 cipher/md.c          |  11 ++
 cipher/md5.c         |   2 +-
 cipher/primegen.c    |  55 ++++-----
 cipher/pubkey-util.c |  36 +++++-
 cipher/pubkey.c      |  11 ++
 cipher/rsa.c         | 167 +++++++++++++++++--------
 src/fips.c           |   2 +-
 src/g10lib.h         |   1 +
 src/global.c         |   3 +
 tests/basic.c        |  70 +++++++++--
 tests/benchmark.c    |  21 ++--
 tests/fips186-dsa.c  |  11 +-
 tests/fipsdrv.c      | 341 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 tests/keygen.c       |  60 +++++++--
 tests/pubkey.c       |  72 +++++++++--
 22 files changed, 1068 insertions(+), 175 deletions(-)


hooks/post-receive
-- 
The GNU crypto library
http://git.gnupg.org


_______________________________________________
Gnupg-commits mailing list
Gnupg-commits at gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-commits


More information about the Gcrypt-devel mailing list