File libgcrypt-PCT-DSA.patch of Package libgcrypt.14858

Index: libgcrypt-1.8.2/cipher/dsa.c
===================================================================
--- libgcrypt-1.8.2.orig/cipher/dsa.c
+++ libgcrypt-1.8.2/cipher/dsa.c
@@ -181,24 +181,91 @@ test_keys (DSA_secret_key *sk, unsigned
   /* Create a random plaintext.  */
   _gcry_mpi_randomize (data, qbits, GCRY_WEAK_RANDOM);
 
-  /* Sign DATA using the secret key.  */
-  sign (sig_a, sig_b, data, sk, 0, 0);
+  /* Use the gcry_pk_sign_md API in order to comply with FIPS 140-2,
+   * which requires full signature operation for PCT (hashing +
+   * asymmetric operation) */
+  gcry_sexp_t s_skey = NULL;
+  gcry_sexp_t s_pkey = NULL;
+  gcry_sexp_t r_sig = NULL;
+  gcry_sexp_t s_hash = NULL;
+  gcry_md_hd_t hd = NULL;
+  gcry_mpi_t r_sig_mpi = NULL;
+  gcry_mpi_t s_sig_mpi = NULL;
+  unsigned char *buf = NULL;
+  size_t buflen;
+
+  if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0))
+    {
+      log_debug ("gcry_pk_sign failed\n");
+      goto leave;
+    }
+
+  _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, data);
+  _gcry_md_write (hd, buf, buflen);
+
+  xfree (buf);
+
+  /* build DSA private key sexp in s_skey */
+  sexp_build (&s_skey, NULL, "(private-key (dsa(p %m)(q %m)(g %m)(y %m)(x %m)))",
+                             sk->p, sk->q, sk->g, sk->y, sk->x);
+  sexp_build (&s_hash, NULL, "(data (flags pkcs1)(hash-algo sha256))");
+  if (_gcry_pk_sign_md (&r_sig, hd, s_hash, s_skey))
+    {
+      log_debug ("gcry_pk_sign failed\n");
+      goto leave;
+    }
+
+  /* Check that the signature and the original plaintext differ. */
+  if (_gcry_sexp_extract_param (r_sig, NULL, "rs", &r_sig_mpi, &s_sig_mpi, NULL))
+    {
+      log_debug ("extracting signature data failed\n");
+      goto leave;
+    }
+
+  if ( !verify (r_sig_mpi, s_sig_mpi, data, &pk))
+    {
+      log_debug ("Signature failed\n");
+      goto leave; /* Signature matches but should not. */
+    }
+
+  _gcry_sexp_release (s_hash);
+  _gcry_md_close (hd);
+
+  /* build DSA public key sexp in s_pkey */
+  sexp_build (&s_pkey, NULL, "(public-key (dsa(p %m)(q %m)(g %m)(y %m)))",
+                             pk.p, pk.q, pk.g, pk.y);
+  sexp_build (&s_hash, NULL, "(data (flags pkcs1)(hash-algo sha256))");
+
+  if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0))
+    log_debug ("gcry_md_open failed\n");
+
+  _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, data);
+  _gcry_md_write (hd, buf, buflen);
+
+  xfree (buf);
+
+  /* verify the signature */
+  if (_gcry_pk_verify_md (r_sig, hd, s_hash, s_pkey))
+    {
+      log_debug ("gcry_pk_verify failed\n");
+      goto leave; /* Signature does not match. */
+    }
 
-  /* Verify the signature using the public key.  */
-  if ( verify (sig_a, sig_b, data, &pk) )
-    goto leave; /* Signature does not match.  */
-
-  /* Modify the data and check that the signing fails.  */
-  mpi_add_ui (data, data, 1);
-  if ( !verify (sig_a, sig_b, data, &pk) )
-    goto leave; /* Signature matches but should not.  */
-
-  result = 0; /* The test succeeded.  */
+  result = 0; /* The test succeeded. */
 
  leave:
   _gcry_mpi_release (sig_b);
   _gcry_mpi_release (sig_a);
   _gcry_mpi_release (data);
+
+  _gcry_sexp_release (s_skey);
+  _gcry_sexp_release (s_pkey);
+  _gcry_sexp_release (s_hash);
+  _gcry_sexp_release (r_sig);
+  _gcry_mpi_release (r_sig_mpi);
+  _gcry_mpi_release (s_sig_mpi);
+  _gcry_md_close (hd);
+
   return result;
 }