Hello community,

here is the log from the commit of package libgcrypt for openSUSE:Factory 
checked in at 2020-05-19 14:43:00
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libgcrypt (Old)
 and      /work/SRC/openSUSE:Factory/.libgcrypt.new.2738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libgcrypt"

Tue May 19 14:43:00 2020 rev:80 rq:805629 version:1.8.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/libgcrypt/libgcrypt.changes      2020-01-30 
09:32:02.957189834 +0100
+++ /work/SRC/openSUSE:Factory/.libgcrypt.new.2738/libgcrypt.changes    
2020-05-19 14:43:07.315382924 +0200
@@ -1,0 +2,70 @@
+Mon Apr 27 08:55:12 UTC 2020 - Pedro Monreal Gonzalez 
<pmonrealgonza...@suse.com>
+
+- FIPS: libgcrypt: Double free in test_keys() on failed signature
+  verification [bsc#1169944]
+  * Use safer gcry_mpi_release() instead of mpi_free()
+- Update patches:
+  * libgcrypt-PCT-DSA.patch
+  * libgcrypt-PCT-RSA.patch
+  * libgcrypt-PCT-ECC.patch
+
+-------------------------------------------------------------------
+Thu Apr 16 16:45:23 UTC 2020 - Vítězslav Čížek <vci...@suse.com>
+
+- Ship the FIPS checksum file in the shared library package and
+  create a separate trigger file for the FIPS selftests (bsc#1169569)
+  * add libgcrypt-fips_selftest_trigger_file.patch
+  * refresh libgcrypt-global_init-constructor.patch
+- Remove libgcrypt-binary_integrity_in_non-FIPS.patch obsoleted
+  by libgcrypt-global_init-constructor.patch
+
+-------------------------------------------------------------------
+Wed Apr 15 13:55:27 UTC 2020 - Pedro Monreal Gonzalez 
<pmonrealgonza...@suse.com>
+
+- FIPS: Verify that the generated signature and the original input
+  differ in test_keys function for RSA, DSA and ECC: [bsc#1165539]
+- Add zero-padding when qx and qy have different lengths when
+  assembling the Q point from affine coordinates.
+- Refreshed patches:
+  * libgcrypt-PCT-DSA.patch
+  * libgcrypt-PCT-RSA.patch
+  * libgcrypt-PCT-ECC.patch
+
+-------------------------------------------------------------------
+Mon Mar 30 10:48:02 UTC 2020 - Pedro Monreal Gonzalez 
<pmonrealgonza...@suse.com>
+
+- FIPS: Switch the PCT to use the new signature operation [bsc#1165539]
+  * Patches for DSA, RSA and ECDSA test_keys functions:
+    - libgcrypt-PCT-DSA.patch
+    - libgcrypt-PCT-RSA.patch
+    - libgcrypt-PCT-ECC.patch
+- Update patch: libgcrypt-FIPS-RSA-DSA-ECDSA-hashing-operation.patch
+
+-------------------------------------------------------------------
+Thu Mar 26 18:09:47 UTC 2020 - Pedro Monreal Gonzalez 
<pmonrealgonza...@suse.com>
+
+- FIPS: Run self-tests from constructor during power-on [bsc#1166748]
+  * Set up global_init as the constructor function:
+    - libgcrypt-global_init-constructor.patch
+  * Relax the entropy requirements on selftest. This is especially
+    important for virtual machines to boot properly before the RNG
+    is available:
+    - libgcrypt-random_selftests-testentropy.patch
+    - libgcrypt-rsa-no-blinding.patch
+    - libgcrypt-ecc-ecdsa-no-blinding.patch
+  * Fix benchmark regression test in FIPS mode:
+    - libgcrypt-FIPS-GMAC_AES-benckmark.patch
+
+-------------------------------------------------------------------
+Thu Mar 12 16:54:33 UTC 2020 - Pedro Monreal Gonzalez 
<pmonrealgonza...@suse.com>
+
+- Remove check not needed in _gcry_global_constructor [bsc#1164950]
+  * Update libgcrypt-Restore-self-tests-from-constructor.patch
+
+-------------------------------------------------------------------
+Tue Feb 25 22:13:24 UTC 2020 - Pedro Monreal Gonzalez 
<pmonrealgonza...@suse.com>
+
+- FIPS: Run the self-tests from the constructor [bsc#1164950]
+  * Add libgcrypt-invoke-global_init-from-constructor.patch
+
+-------------------------------------------------------------------

Old:
----
  libgcrypt-binary_integrity_in_non-FIPS.patch

New:
----
  libgcrypt-FIPS-GMAC_AES-benckmark.patch
  libgcrypt-PCT-DSA.patch
  libgcrypt-PCT-ECC.patch
  libgcrypt-PCT-RSA.patch
  libgcrypt-Restore-self-tests-from-constructor.patch
  libgcrypt-ecc-ecdsa-no-blinding.patch
  libgcrypt-fips_selftest_trigger_file.patch
  libgcrypt-global_init-constructor.patch
  libgcrypt-invoke-global_init-from-constructor.patch
  libgcrypt-random_selftests-testentropy.patch
  libgcrypt-rsa-no-blinding.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libgcrypt.spec ++++++
--- /var/tmp/diff_new_pack.ZdJnLU/_old  2020-05-19 14:43:08.959386437 +0200
+++ /var/tmp/diff_new_pack.ZdJnLU/_new  2020-05-19 14:43:08.959386437 +0200
@@ -18,7 +18,8 @@
 
 %define build_hmac256 1
 %define separate_hmac256_binary 0
-%define libsoname %{name}20
+%define libsover 20
+%define libsoname %{name}%{libsover}
 %define cavs_dir %{_libexecdir}/%{name}/cavs
 Name:           libgcrypt
 Version:        1.8.5
@@ -55,7 +56,6 @@
 #PATCH-FIX-UPSTREAM bsc#1064455 fipsdrv patch to enable --algo for dsa-verify
 Patch36:        libgcrypt-fipsdrv-enable-algo-for-dsa-verify.patch
 Patch39:        libgcrypt-1.8.3-fips-ctor.patch
-Patch41:        libgcrypt-binary_integrity_in_non-FIPS.patch
 Patch42:        libgcrypt-fips_rsa_no_enforced_mode.patch
 Patch43:        libgcrypt-1.8.4-use_xfree.patch
 Patch44:        libgcrypt-1.8.4-allow_FSM_same_state.patch
@@ -75,6 +75,20 @@
 Patch53:        libgcrypt-FIPS-RSA-DSA-ECDSA-hashing-operation.patch
 #PATCH-FIX-SUSE bsc#1161220 FIPS: libgcrypt RSA siggen/keygen: 4k not supported
 Patch54:        libgcrypt-1.8.4-fips-keygen.patch
+#PATCH-FIX-SUSE bsc#1164950 Run self-tests from the constructor
+Patch55:        libgcrypt-invoke-global_init-from-constructor.patch
+#PATCH-FIX-SUSE bsc#1164950 Restore the self-tests from the constructor
+Patch56:        libgcrypt-Restore-self-tests-from-constructor.patch
+Patch57:        libgcrypt-FIPS-GMAC_AES-benckmark.patch
+Patch58:        libgcrypt-global_init-constructor.patch
+Patch59:        libgcrypt-random_selftests-testentropy.patch
+Patch60:        libgcrypt-rsa-no-blinding.patch
+Patch61:        libgcrypt-ecc-ecdsa-no-blinding.patch
+#PATCH-FIX-SUSE bsc#1165539 FIPS: Use the new signature operation in PCT
+Patch62:        libgcrypt-PCT-RSA.patch
+Patch63:        libgcrypt-PCT-DSA.patch
+Patch64:        libgcrypt-PCT-ECC.patch
+Patch65:        libgcrypt-fips_selftest_trigger_file.patch
 BuildRequires:  automake >= 1.14
 BuildRequires:  fipscheck
 BuildRequires:  libgpg-error-devel >= 1.25
@@ -205,6 +219,11 @@
 mv %{buildroot}%{_bindir}/fipsdrv %{buildroot}%{cavs_dir}
 mv %{buildroot}%{_bindir}/drbg_test %{buildroot}%{cavs_dir}
 
+# create the FIPS "module is complete" trigger file
+%if 0%{?build_hmac256}
+touch %{buildroot}/%{_libdir}/.%{name}.so.%{libsover}.fips
+%endif
+
 %post -n %{libsoname} -p /sbin/ldconfig
 %postun -n %{libsoname} -p /sbin/ldconfig
 %post devel
@@ -216,10 +235,13 @@
 %files -n %{libsoname}
 %license COPYING.LIB
 %{_libdir}/%{name}.so.*
+%if 0%{?build_hmac256}
+%{_libdir}/.libgcrypt.so.*.hmac
+%endif # %%if 0%%{?build_hmac256}
 
 %files -n %{libsoname}-hmac
 %if 0%{?build_hmac256}
-%{_libdir}/.libgcrypt.so.*.hmac
+%{_libdir}/.libgcrypt.so.*.fips
 %endif # %%if 0%%{?build_hmac256}
 
 %files devel


++++++ libgcrypt-FIPS-GMAC_AES-benckmark.patch ++++++
Index: libgcrypt-1.8.2/tests/benchmark.c
===================================================================
--- libgcrypt-1.8.2.orig/tests/benchmark.c
+++ libgcrypt-1.8.2/tests/benchmark.c
@@ -598,7 +598,7 @@ mac_bench ( const char *algoname )
   if (!algoname)
     {
       for (i=1; i < 600; i++)
-        if (in_fips_mode && i == GCRY_MAC_HMAC_MD5)
+        if (in_fips_mode && (i == GCRY_MAC_HMAC_MD5 || i == GCRY_MAC_GMAC_AES))
           ; /* Don't use MD5 in fips mode.  */
         else if ( !gcry_mac_test_algo (i) )
           mac_bench (gcry_mac_algo_name (i));
++++++ libgcrypt-FIPS-RSA-DSA-ECDSA-hashing-operation.patch ++++++
--- /var/tmp/diff_new_pack.ZdJnLU/_old  2020-05-19 14:43:09.055386642 +0200
+++ /var/tmp/diff_new_pack.ZdJnLU/_new  2020-05-19 14:43:09.059386650 +0200
@@ -1,80 +1,13 @@
-Index: libgcrypt-1.8.2/cipher/pubkey-internal.h
-===================================================================
---- libgcrypt-1.8.2.orig/cipher/pubkey-internal.h
-+++ libgcrypt-1.8.2/cipher/pubkey-internal.h
-@@ -43,6 +43,7 @@ void _gcry_pk_util_free_encoding_ctx (st
- gcry_err_code_t _gcry_pk_util_data_to_mpi (gcry_sexp_t input,
-                                            gcry_mpi_t *ret_mpi,
-                                            struct pk_encoding_ctx *ctx);
-+gcry_err_code_t _gcry_pk_util_get_algo (gcry_sexp_t input, int *algo);
- 
- 
- 
-Index: libgcrypt-1.8.2/cipher/pubkey-util.c
-===================================================================
---- libgcrypt-1.8.2.orig/cipher/pubkey-util.c
-+++ libgcrypt-1.8.2/cipher/pubkey-util.c
-@@ -1119,3 +1119,50 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t i
- 
-   return rc;
- }
-+
-+
-+gcry_err_code_t
-+_gcry_pk_util_get_algo (gcry_sexp_t input, int *algo)
-+{
-+  gcry_err_code_t rc = 0;
-+  gcry_sexp_t ldata, list = NULL;
-+  const char *s;
-+  size_t n;
-+  int lalgo;
-+
-+  ldata = sexp_find_token (input, "data", 0);
-+  if (!ldata)
-+    {
-+      rc = GPG_ERR_INV_OBJ;
-+      goto leave;
-+    }
-+
-+  list = sexp_find_token (ldata, "hash-algo", 0);
-+  if (!list)
-+    {
-+      rc = GPG_ERR_INV_OBJ;
-+      goto leave;
-+    }
-+
-+  s = sexp_nth_data (list, 1, &n);
-+  if (!s)
-+    {
-+      rc = GPG_ERR_NO_OBJ;
-+      goto leave;
-+    }
-+
-+  lalgo = get_hash_algo (s, n);
-+  if (!lalgo)
-+    {
-+      rc = GPG_ERR_DIGEST_ALGO;
-+      goto leave;
-+    }
-+
-+  *algo = lalgo;
-+
-+ leave:
-+  sexp_release (ldata);
-+  sexp_release (list);
-+
-+  return rc;
-+}
 Index: libgcrypt-1.8.2/cipher/pubkey.c
 ===================================================================
 --- libgcrypt-1.8.2.orig/cipher/pubkey.c
 +++ libgcrypt-1.8.2/cipher/pubkey.c
-@@ -383,6 +383,33 @@ _gcry_pk_decrypt (gcry_sexp_t *r_plain,
-   return rc;
+@@ -384,6 +384,33 @@ _gcry_pk_decrypt (gcry_sexp_t *r_plain,
  }
  
+ 
 +static gcry_err_code_t
-+calculate_hash (gcry_md_hd_t hd, gcry_sexp_t s_hash)
++calculate_hash (gcry_md_hd_t hd, gcry_sexp_t* s_hash)
 +{
 +  gcry_err_code_t rc;
 +  const unsigned char *digest;
@@ -83,27 +16,27 @@
 +  if (!hd)
 +    return 0;
 +
-+  rc = _gcry_pk_util_get_algo (s_hash, &algo);
++  rc = _gcry_pk_util_get_algo (*s_hash, &algo);
 +  if (rc)
 +    return rc;
 +
 +  digest = _gcry_md_read(hd, algo);
 +  if (!digest)
-+      return GPG_ERR_DIGEST_ALGO;
++    return GPG_ERR_DIGEST_ALGO;
 +
-+  rc = _gcry_sexp_build (&s_hash, NULL,
-+       "(data (flags pkcs1)(hash %s %b))",
-+       _gcry_md_algo_name(algo), (int) _gcry_md_get_algo_dlen(algo), digest);
++  rc = _gcry_sexp_build (s_hash, NULL,
++                         "(data (flags pkcs1)(hash %s %b))",
++                         _gcry_md_algo_name(algo),
++                         (int) _gcry_md_get_algo_dlen(algo),
++                         digest);
 +
 +  return rc;
 +}
 +
-+
-+
- 
  
  /*
-@@ -414,7 +442,8 @@ _gcry_pk_decrypt (gcry_sexp_t *r_plain,
+    Create a signature.
+@@ -414,7 +441,8 @@ _gcry_pk_decrypt (gcry_sexp_t *r_plain,
    Note that (hash algo) in R_SIG is not used.
  */
  gcry_err_code_t
@@ -113,21 +46,21 @@
  {
    gcry_err_code_t rc;
    gcry_pk_spec_t *spec;
-@@ -426,6 +455,10 @@ _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_
+@@ -426,6 +454,10 @@ _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_
    if (rc)
      goto leave;
  
-+  rc = calculate_hash (hd, s_hash);
++  rc = calculate_hash (hd, &s_hash);
 +  if (rc)
 +    goto leave;
 +
    if (spec->sign)
      rc = spec->sign (r_sig, s_hash, keyparms);
    else
-@@ -436,6 +469,13 @@ _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_
-   return rc;
+@@ -437,6 +469,13 @@ _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_
  }
  
+ 
 +gcry_err_code_t
 +_gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
 +{
@@ -135,51 +68,127 @@
 +}
 +
 +
- 
  /*
     Verify a signature.
-@@ -445,7 +485,8 @@ _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_
+ 
+@@ -445,7 +484,8 @@ _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_
     as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data
     must be an S-Exp like the one in sign too.  */
  gcry_err_code_t
 -_gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
 +_gcry_pk_verify_md (gcry_sexp_t s_sig, gcry_md_hd_t hd, gcry_sexp_t s_hash,
-+                  gcry_sexp_t s_pkey)
++                    gcry_sexp_t s_pkey)
  {
    gcry_err_code_t rc;
    gcry_pk_spec_t *spec;
-@@ -455,6 +496,10 @@ _gcry_pk_verify (gcry_sexp_t s_sig, gcry
+@@ -455,6 +495,10 @@ _gcry_pk_verify (gcry_sexp_t s_sig, gcry
    if (rc)
      goto leave;
  
-+  rc = calculate_hash (hd, s_hash);
++  rc = calculate_hash (hd, &s_hash);
 +  if (rc)
 +    goto leave;
 +
    if (spec->verify)
      rc = spec->verify (s_sig, s_hash, keyparms);
    else
-@@ -465,6 +510,12 @@ _gcry_pk_verify (gcry_sexp_t s_sig, gcry
-   return rc;
+@@ -466,6 +510,13 @@ _gcry_pk_verify (gcry_sexp_t s_sig, gcry
  }
  
+ 
 +gcry_err_code_t
 +_gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
 +{
 +  return _gcry_pk_verify_md (s_sig, NULL, s_hash, s_pkey);
 +}
 +
- 
++
  /*
     Test a key.
-@@ -497,6 +548,7 @@ _gcry_pk_testkey (gcry_sexp_t s_key)
- }
+ 
+Index: libgcrypt-1.8.2/cipher/pubkey-internal.h
+===================================================================
+--- libgcrypt-1.8.2.orig/cipher/pubkey-internal.h
++++ libgcrypt-1.8.2/cipher/pubkey-internal.h
+@@ -43,6 +43,8 @@ void _gcry_pk_util_free_encoding_ctx (st
+ gcry_err_code_t _gcry_pk_util_data_to_mpi (gcry_sexp_t input,
+                                            gcry_mpi_t *ret_mpi,
+                                            struct pk_encoding_ctx *ctx);
++gcry_err_code_t _gcry_pk_util_get_algo (gcry_sexp_t input,
++                                        int *algo);
  
  
+ 
+Index: libgcrypt-1.8.2/cipher/pubkey-util.c
+===================================================================
+--- libgcrypt-1.8.2.orig/cipher/pubkey-util.c
++++ libgcrypt-1.8.2/cipher/pubkey-util.c
+@@ -1119,3 +1119,50 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t i
+ 
+   return rc;
+ }
 +
- /*
-   Create a public key pair and return it in r_key.
-   How the key is created depends on s_parms:
++
++gcry_err_code_t
++_gcry_pk_util_get_algo (gcry_sexp_t input, int *algo)
++{
++  gcry_err_code_t rc = 0;
++  gcry_sexp_t ldata, list = NULL;
++  const char *s;
++  size_t n;
++  int lalgo;
++
++  ldata = sexp_find_token (input, "data", 0);
++  if (!ldata)
++    {
++      rc = GPG_ERR_INV_OBJ;
++      goto leave;
++    }
++
++  list = sexp_find_token (ldata, "hash-algo", 0);
++  if (!list)
++    {
++      rc = GPG_ERR_INV_OBJ;
++      goto leave;
++    }
++
++  s = sexp_nth_data (list, 1, &n);
++  if (!s)
++    {
++      rc = GPG_ERR_NO_OBJ;
++      goto leave;
++    }
++
++  lalgo = get_hash_algo (s, n);
++  if (!lalgo)
++    {
++      rc = GPG_ERR_DIGEST_ALGO;
++      goto leave;
++    }
++
++  *algo = lalgo;
++
++ leave:
++  sexp_release (ldata);
++  sexp_release (list);
++
++  return rc;
++}
+Index: libgcrypt-1.8.2/src/g10lib.h
+===================================================================
+--- libgcrypt-1.8.2.orig/src/g10lib.h
++++ libgcrypt-1.8.2/src/g10lib.h
+@@ -288,6 +288,10 @@ gpg_err_code_t _gcry_generate_fips186_3_
+ gpg_err_code_t _gcry_fips186_4_prime_check (const gcry_mpi_t x,
+                                             unsigned int bits);
+ 
++gcry_err_code_t _gcry_pk_sign_md (gcry_sexp_t *r_sig, gcry_md_hd_t hd,
++                                  gcry_sexp_t s_hash, gcry_sexp_t s_skey);
++gcry_err_code_t _gcry_pk_verify_md (gcry_sexp_t s_sig, gcry_md_hd_t hd,
++                                    gcry_sexp_t s_hash, gcry_sexp_t s_pkey);
+ 
+ /* Replacements of missing functions (missing-string.c).  */
+ #ifndef HAVE_STPCPY
 Index: libgcrypt-1.8.2/src/visibility.c
 ===================================================================
 --- libgcrypt-1.8.2.orig/src/visibility.c
@@ -219,3 +228,18 @@
  gcry_pk_verify (gcry_sexp_t sigval, gcry_sexp_t data, gcry_sexp_t pkey)
  {
    if (!fips_is_operational ())
+Index: libgcrypt-1.8.2/src/visibility.h
+===================================================================
+--- libgcrypt-1.8.2.orig/src/visibility.h
++++ libgcrypt-1.8.2/src/visibility.h
+@@ -357,8 +357,10 @@ MARK_VISIBLEX (_gcry_mpi_get_const)
+ #define gcry_pk_get_param           _gcry_USE_THE_UNDERSCORED_FUNCTION
+ #define gcry_pk_get_nbits           _gcry_USE_THE_UNDERSCORED_FUNCTION
+ #define gcry_pk_map_name            _gcry_USE_THE_UNDERSCORED_FUNCTION
++#define gcry_pk_sign_md             _gcry_USE_THE_UNDERSCORED_FUNCTION
+ #define gcry_pk_sign                _gcry_USE_THE_UNDERSCORED_FUNCTION
+ #define gcry_pk_testkey             _gcry_USE_THE_UNDERSCORED_FUNCTION
++#define gcry_pk_verify_md           _gcry_USE_THE_UNDERSCORED_FUNCTION
+ #define gcry_pk_verify              _gcry_USE_THE_UNDERSCORED_FUNCTION
+ #define gcry_pubkey_get_sexp        _gcry_USE_THE_UNDERSCORED_FUNCTION
+ 

++++++ libgcrypt-PCT-DSA.patch ++++++
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;
 }
 
++++++ libgcrypt-PCT-ECC.patch ++++++
Index: libgcrypt-1.8.2/cipher/ecc.c
===================================================================
--- libgcrypt-1.8.2.orig/cipher/ecc.c
+++ libgcrypt-1.8.2/cipher/ecc.c
@@ -99,7 +99,7 @@ static void *progress_cb_data;
 
 
 /* Local prototypes. */
-static void test_keys (ECC_secret_key * sk, unsigned int nbits);
+static int test_keys (ECC_secret_key * sk, unsigned int nbits);
 static void test_ecdh_only_keys (ECC_secret_key * sk, unsigned int nbits, int 
flags);
 static unsigned int ecc_get_nbits (gcry_sexp_t parms);
 
@@ -152,6 +152,7 @@ nist_generate_key (ECC_secret_key *sk, e
   gcry_random_level_t random_level;
   gcry_mpi_t x, y;
   const unsigned int pbits = mpi_get_nbits (E->p);
+  int free_skEname = 0;
 
   point_init (&Q);
 
@@ -176,7 +177,6 @@ nist_generate_key (ECC_secret_key *sk, e
   else
     sk->d = _gcry_dsa_gen_k (E->n, random_level);
 
-
   /* Compute Q.  */
   _gcry_mpi_ec_mul_point (&Q, sk->d, &E->G, ctx);
 
@@ -190,6 +190,12 @@ nist_generate_key (ECC_secret_key *sk, e
   point_set (&sk->E.G, &E->G);
   sk->E.n = mpi_copy (E->n);
   sk->E.h = mpi_copy (E->h);
+  if (E->name)
+    {
+      free_skEname = 1;
+      sk->E.name = _gcry_xstrdup(E->name);
+    }
+
   point_init (&sk->Q);
 
   x = mpi_new (pbits);
@@ -261,10 +267,16 @@ nist_generate_key (ECC_secret_key *sk, e
   if ((flags & PUBKEY_FLAG_NO_KEYTEST))
     ; /* User requested to skip the test.  */
   else if (sk->E.model != MPI_EC_MONTGOMERY)
-    test_keys (sk, nbits - 64);
+    {
+      if (test_keys (sk, nbits - 64))
+        return GPG_ERR_BAD_SIGNATURE;
+    }
   else
     test_ecdh_only_keys (sk, nbits - 64, flags);
 
+  if (free_skEname)
+    xfree ((void*)sk->E.name);
+
   return 0;
 }
 
@@ -275,9 +287,10 @@ nist_generate_key (ECC_secret_key *sk, e
  * test if the information is recuperated.
  * Second, test with the sign and verify functions.
  */
-static void
+static int
 test_keys (ECC_secret_key *sk, unsigned int nbits)
 {
+  int result = -1; /* Default to failure. */
   ECC_public_key pk;
   gcry_mpi_t test = mpi_new (nbits);
   mpi_point_struct R_;
@@ -297,17 +310,161 @@ test_keys (ECC_secret_key *sk, unsigned
 
   _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
 
-  if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) )
-    log_fatal ("ECDSA operation: sign failed\n");
+  /* 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 r_sig = NULL;
+  gcry_sexp_t s_skey = NULL;
+  gcry_sexp_t s_pkey = NULL;
+  gcry_sexp_t s_hash = NULL;
+  gcry_mpi_t s_sig_mpi = NULL;
+  gcry_md_hd_t hd = NULL;
+  unsigned char *buf = NULL;
+  size_t buflen;
+  mpi_ec_t ctx;
+  int flags = 0;
+
+  if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0))
+    log_debug ("gcry_pk_sign failed: _gcry_md_open\n");
+
+  _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, test);
+  _gcry_md_write (hd, buf, buflen);
+
+  xfree (buf);
+
+  sexp_build (&s_hash, NULL, "(data (flags rfc6979)(hash-algo sha256))");
+
+  /* Assemble the point Q from affine coordinates by simple
+   * concatenation. */
+  gcry_mpi_t Qx = NULL;
+  gcry_mpi_t Qy = NULL;
+  Qx = mpi_new (0);
+  Qy = mpi_new (0);
+  ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.dialect, flags,
+                                     sk->E.p, sk->E.a, sk->E.b);
+  if (_gcry_mpi_ec_get_affine (Qx, Qy, &(sk->Q), ctx))
+    log_debug ("ecdh: Failed to get affine coordinates for Q\n");
+
+  unsigned char *rawqx, *rawqy;
+  unsigned int rawqxlen, rawqylen;
+  rawqx = _gcry_mpi_get_buffer (Qx, 0, &rawqxlen, NULL);
+  rawqy = _gcry_mpi_get_buffer (Qy, 0, &rawqylen, NULL);
+
+  if (rawqxlen != rawqylen)
+    {
+      // log_debug ("qx and qy size differ: %d != %d\n", rawqxlen, rawqylen);
+      if (rawqxlen < rawqylen)
+        {
+          size_t diff = rawqylen - rawqxlen;
+          unsigned char *zeros = xmalloc (rawqxlen + diff);
+          memset (zeros, 0, rawqxlen + diff);
+          memmove (zeros + diff, rawqx, rawqxlen);
+          xfree (rawqx);
+          rawqx = zeros;
+          rawqxlen += diff;
+        }
+      if (rawqylen < rawqxlen)
+        {
+          size_t diff = rawqxlen - rawqylen;
+          unsigned char *zeros = xmalloc (rawqylen + diff);
+          memset (zeros, 0, rawqylen + diff);
+          memmove (zeros + diff, rawqy, rawqylen);
+          xfree (rawqy);
+          rawqy = zeros;
+          rawqylen += diff;
+        }
+    }
+
+  unsigned char q[1 + rawqxlen + rawqxlen];
+  size_t qlen;
+  memset (&q, 0, sizeof(q));
+  *q = 4;
+  memcpy (q + 1, rawqx, rawqxlen);
+  memcpy (q + 1 + rawqxlen, rawqy, rawqylen);
+  qlen = 1 + rawqxlen + rawqylen;
+
+  _gcry_mpi_release (Qx);
+  _gcry_mpi_release (Qy);
+  xfree (rawqx);
+  xfree (rawqy);
 
-  if (_gcry_ecc_ecdsa_verify (test, &pk, r, s))
+  /* build ECC private key sexp in s_skey */
+  if (sk->E.name)
     {
-      log_fatal ("ECDSA operation: sign, verify failed\n");
+      if (sexp_build (&s_skey, NULL,
+                      "(private-key (ecc (curve %s)(d %m)(q %b)))",
+                      sk->E.name, sk->d, qlen, q))
+        log_debug ("ecc: Failed to build sexp for private key.\n");
+    }
+  else
+    {
+      if (sexp_build (&s_skey, NULL,
+                      "(private-key"
+                      " (ecc (curve %s)(d %m)(p %m)(a %m)(b %m)(n %m)(h %m)(q 
%b)))",
+                      "NIST P-512", sk->d, sk->E.p, sk->E.a, sk->E.b, sk->E.n, 
sk->E.h,
+                      qlen, q))
+        log_debug ("ecc: Failed to build sexp for private key.\n");
+    }
+
+  if (_gcry_pk_sign_md (&r_sig, hd, s_hash, s_skey))
+    {
+      log_debug ("ecc: gcry_pk_sign failed\n");
+      goto leave;
+    }
+
+  /* Check that the signature and the original test differ. */
+  if (_gcry_sexp_extract_param (r_sig, NULL, "s", &s_sig_mpi, NULL))
+    {
+      log_debug ("extracting signature data failed\n");
+      goto leave;
+    }
+
+  if (!mpi_cmp (s_sig_mpi, test))
+    {
+      log_debug ("Signature failed\n");
+      goto leave; /* Signature and test match but should not. */
+    }
+
+  /* verify */
+  /* build public key sexp in s_pkey */
+  if (pk.E.name)
+    {
+      if (sexp_build (&s_pkey, NULL,
+                      "(public-key (ecc (curve %s)(q %b)))", pk.E.name, qlen, 
q))
+        log_debug ("ecc: Failed to build sexp for public key.\n");
+    }
+  else
+    {
+      if (sexp_build (&s_pkey, NULL,
+                      "(public-key"
+                      " (ecc (curve %s)(p %m)(a %m)(b %m)(n %m)(h %m)(q %b)))",
+                      "NIST P-512", pk.E.p, pk.E.a, pk.E.b, pk.E.n, pk.E.h, 
qlen, q))
+        log_debug ("ecc: Failed to build sexp for private key.\n");
+    }
+
+  _gcry_md_close (hd);
+
+  if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0))
+    log_debug ("gcry_pk_verify failed: _gcry_md_open\n");
+
+  _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, test);
+  _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 ("ecc: gcry_pk_verify failed\n");
+      goto leave; /* Signature does not match. */
     }
 
   if (DBG_CIPHER)
     log_debug ("ECDSA operation: sign, verify ok.\n");
 
+  result = 0; /* The test succeeded. */
+
+ leave:
   point_free (&pk.Q);
   _gcry_ecc_curve_free (&pk.E);
 
@@ -317,6 +474,16 @@ test_keys (ECC_secret_key *sk, unsigned
   mpi_free (out);
   mpi_free (c);
   mpi_free (test);
+
+  _gcry_sexp_release (r_sig);
+  _gcry_sexp_release (s_skey);
+  _gcry_sexp_release (s_pkey);
+  _gcry_sexp_release (s_hash);
+  _gcry_mpi_release (s_sig_mpi);
+  _gcry_md_close (hd);
+  xfree (ctx);
+
+  return result;
 }
 
 
Index: libgcrypt-1.8.2/cipher/pubkey.c
===================================================================
--- libgcrypt-1.8.2.orig/cipher/pubkey.c
+++ libgcrypt-1.8.2/cipher/pubkey.c
@@ -390,6 +390,7 @@ calculate_hash (gcry_md_hd_t hd, gcry_se
   gcry_err_code_t rc;
   const unsigned char *digest;
   int algo;
+  const char *flags;
 
   if (!hd)
     return 0;
@@ -398,16 +399,21 @@ calculate_hash (gcry_md_hd_t hd, gcry_se
   if (rc)
     return rc;
 
+  rc = _gcry_pk_util_get_flags (*s_hash, &flags);
+  if (rc)
+    return rc;
+
   digest = _gcry_md_read(hd, algo);
   if (!digest)
     return GPG_ERR_DIGEST_ALGO;
 
   rc = _gcry_sexp_build (s_hash, NULL,
-                         "(data (flags pkcs1)(hash %s %b))",
+                         "(data (flags %s)(hash %s %b))", flags,
                          _gcry_md_algo_name(algo),
                          (int) _gcry_md_get_algo_dlen(algo),
                          digest);
 
+  xfree ((void *)flags);
   return rc;
 }
 
Index: libgcrypt-1.8.2/cipher/pubkey-internal.h
===================================================================
--- libgcrypt-1.8.2.orig/cipher/pubkey-internal.h
+++ libgcrypt-1.8.2/cipher/pubkey-internal.h
@@ -45,6 +45,8 @@ gcry_err_code_t _gcry_pk_util_data_to_mp
                                            struct pk_encoding_ctx *ctx);
 gcry_err_code_t _gcry_pk_util_get_algo (gcry_sexp_t input,
                                         int *algo);
+gcry_err_code_t _gcry_pk_util_get_flags (gcry_sexp_t input,
+                                         const char **flags);
 
 
 
Index: libgcrypt-1.8.2/cipher/pubkey-util.c
===================================================================
--- libgcrypt-1.8.2.orig/cipher/pubkey-util.c
+++ libgcrypt-1.8.2/cipher/pubkey-util.c
@@ -1120,6 +1120,40 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t i
   return rc;
 }
 
+gcry_err_code_t
+_gcry_pk_util_get_flags (gcry_sexp_t input, const char **flags)
+{
+  gcry_err_code_t rc = 0;
+  gcry_sexp_t ldata, list = NULL;
+
+  ldata = sexp_find_token (input, "data", 0);
+  if (!ldata)
+    {
+      rc = GPG_ERR_INV_OBJ;
+      goto leave;
+    }
+
+  list = sexp_find_token (ldata, "flags", 0);
+  if (!list)
+    {
+      rc = GPG_ERR_INV_OBJ;
+      goto leave;
+    }
+
+  /* FIXME: gets only the first flag */
+  *flags = sexp_nth_string (list, 1);
+  if (!*flags)
+    {
+      rc = GPG_ERR_NO_OBJ;
+      goto leave;
+    }
+
+ leave:
+  sexp_release (ldata);
+  sexp_release (list);
+
+  return rc;
+}
 
 gcry_err_code_t
 _gcry_pk_util_get_algo (gcry_sexp_t input, int *algo)
++++++ libgcrypt-PCT-RSA.patch ++++++
Index: libgcrypt-1.8.2/cipher/rsa.c
===================================================================
--- libgcrypt-1.8.2.orig/cipher/rsa.c
+++ libgcrypt-1.8.2/cipher/rsa.c
@@ -159,27 +159,93 @@ test_keys (RSA_secret_key *sk, unsigned
   /* Create another random plaintext as data for signature checking.  */
   _gcry_mpi_randomize (plaintext, nbits, GCRY_WEAK_RANDOM);
 
-  /* Use the RSA secret function to create a signature of the plaintext.  */
-  secret (signature, plaintext, sk);
+  /* 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;
+  unsigned char *buf = NULL;
+  size_t buflen;
 
-  /* Use the RSA public function to verify this signature.  */
-  public (decr_plaintext, signature, &pk);
-  if (mpi_cmp (decr_plaintext, plaintext))
-    goto leave; /* Signature does not match.  */
-
-  /* Modify the signature and check that the signing fails.  */
-  mpi_add_ui (signature, signature, 1);
-  public (decr_plaintext, signature, &pk);
-  if (!mpi_cmp (decr_plaintext, plaintext))
-    goto leave; /* Signature matches but should not.  */
+  if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0))
+    {
+      log_debug ("gcry_pk_sign failed\n");
+      goto leave_hash;
+    }
+
+  _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, plaintext);
+  _gcry_md_write (hd, buf, buflen);
+
+  xfree (buf);
+
+  /* build RSA private key sexp in s_skey */
+  sexp_build (&s_skey, NULL,
+              "(private-key (rsa(n %m)(e %m)(d %m)(p %m)(q %m)))",
+              sk->n, sk->e, sk->d, sk->p, sk->q);
+  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_hash;
+    }
+
+  /* Check that the signature and the original plaintext differ. */
+  if (_gcry_sexp_extract_param (r_sig, "sig-val!rsa", "s", &r_sig_mpi, NULL))
+    {
+      log_debug ("extracting signature data failed\n");
+      goto leave_hash;
+    }
+
+  if (!mpi_cmp (r_sig_mpi, plaintext))
+    {
+      log_debug ("Signature failed\n");
+      goto leave_hash; /* Signature and plaintext match but should not. */
+    }
+
+  _gcry_sexp_release (s_hash);
+  _gcry_md_close (hd);
+
+  /* build RSA public key sexp in s_pkey */
+  sexp_build (&s_pkey, NULL, "(public-key (rsa(n %m)(e %m)))", pk.n, pk.e);
+  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, plaintext);
+  _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_hash; /* Signature does not match. */
+    }
 
   result = 0; /* All tests succeeded.  */
 
+ leave_hash:
+  _gcry_sexp_release (s_skey);
+  _gcry_sexp_release (s_pkey);
+  _gcry_sexp_release (s_hash);
+  _gcry_sexp_release (r_sig);
+  _gcry_md_close (hd);
+  _gcry_mpi_release (r_sig_mpi);
+
  leave:
   _gcry_mpi_release (signature);
   _gcry_mpi_release (decr_plaintext);
   _gcry_mpi_release (ciphertext);
   _gcry_mpi_release (plaintext);
+
   return result;
 }
 
@@ -1903,7 +1969,7 @@ selftest_encr_2048 (gcry_sexp_t pkey, gc
   /* This sexp trickery is to prevent the use of blinding.
    * The flag doesn't get inherited by encr, so we have to
    * derive a new sexp from the ciphertext */
-  char buf[1024];
+  unsigned char buf[1024];
   memset(buf, 0, sizeof(buf));
   err = _gcry_mpi_print (GCRYMPI_FMT_STD, buf, sizeof buf, NULL, ciphertext);
   if (err)
++++++ libgcrypt-Restore-self-tests-from-constructor.patch ++++++
Index: libgcrypt-1.8.2/src/global.c
===================================================================
--- libgcrypt-1.8.2.orig/src/global.c
+++ libgcrypt-1.8.2/src/global.c
@@ -140,8 +140,9 @@ global_init (void)
   /* We always need the FSM lock to be functional. */
   _gcry_initialize_fsm_lock ();
 
-  /* Run the self-tests from the constructor. */
-  global_init ();
+  /* We run the integrity check at this point. The remaining
+     selftests are run before use of the library by application. */
+  _gcry_fips_run_selftests (0);
 }
 
 /* This function is called by the macro fips_is_operational and makes
++++++ libgcrypt-ecc-ecdsa-no-blinding.patch ++++++
Index: libgcrypt-1.8.5/cipher/ecc.c
===================================================================
--- libgcrypt-1.8.5.orig/cipher/ecc.c
+++ libgcrypt-1.8.5/cipher/ecc.c
@@ -2060,11 +2060,11 @@ selftest_sign (gcry_sexp_t pkey, gcry_se
 {
   /* Sample data from RFC 6979 section A.2.5, hash is of message "sample" */
   static const char sample_data[] =
-    "(data (flags rfc6979)"
+    "(data (flags rfc6979 no-blinding)"
     " (hash sha256 #af2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915"
     /**/           "62113d8a62add1bf#))";
   static const char sample_data_bad[] =
-    "(data (flags rfc6979)"
+    "(data (flags rfc6979 no-blinding)"
     " (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915"
     /**/           "62113d8a62add1bf#))";
   static const char signature_r[] =
Index: libgcrypt-1.8.5/cipher/ecc-ecdsa.c
===================================================================
--- libgcrypt-1.8.5.orig/cipher/ecc-ecdsa.c
+++ libgcrypt-1.8.5/cipher/ecc-ecdsa.c
@@ -52,6 +52,7 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input,
   mpi_ec_t ctx;
   gcry_mpi_t b;                /* Random number needed for blinding.  */
   gcry_mpi_t bi;               /* multiplicative inverse of B.        */
+  int with_blinding = !(flags & PUBKEY_FLAG_NO_BLINDING);
 
   if (DBG_CIPHER)
     log_mpidump ("ecdsa sign hash  ", input );
@@ -65,12 +66,15 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input,
 
   b  = mpi_snew (qbits);
   bi = mpi_snew (qbits);
-  do
+  if (with_blinding)
     {
-      _gcry_mpi_randomize (b, qbits, GCRY_WEAK_RANDOM);
-      mpi_mod (b, b, skey->E.n);
+      do
+        {
+          _gcry_mpi_randomize (b, qbits, GCRY_WEAK_RANDOM);
+          mpi_mod (b, b, skey->E.n);
+        }
+      while (!mpi_invm (bi, b, skey->E.n));
     }
-  while (!mpi_invm (bi, b, skey->E.n));
 
   k = NULL;
   dr = mpi_alloc (0);
@@ -128,15 +132,26 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input,
         }
       while (!mpi_cmp_ui (r, 0));
 
-      /* Computation of dr, sum, and s are blinded with b.  */
-      mpi_mulm (dr, b, skey->d, skey->E.n);
-      mpi_mulm (dr, dr, r, skey->E.n);      /* dr = d*r mod n */
-      mpi_mulm (sum, b, hash, skey->E.n);
-      mpi_addm (sum, sum, dr, skey->E.n);   /* sum = hash + (d*r) mod n */
+      if (!with_blinding)
+        {
+          mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n  */
+          mpi_addm (sum, hash, dr, skey->E.n);  /* sum = hash + (d*r) mod n  */
+       }
+      else
+        {
+          /* Computation of dr, sum, and s are blinded with b.  */
+          mpi_mulm (dr, b, skey->d, skey->E.n);
+          mpi_mulm (dr, dr, r, skey->E.n);      /* dr = d*r mod n */
+          mpi_mulm (sum, b, hash, skey->E.n);
+          mpi_addm (sum, sum, dr, skey->E.n);   /* sum = hash + (d*r) mod n */
+       }
       mpi_invm (k_1, k, skey->E.n);         /* k_1 = k^(-1) mod n  */
       mpi_mulm (s, k_1, sum, skey->E.n);    /* s = k^(-1)*(hash+(d*r)) mod n */
-      /* Undo blinding by b^-1 */
-      mpi_mulm (s, bi, s, skey->E.n);
+      if (with_blinding)
+        {
+          /* Undo blinding by b^-1 */
+          mpi_mulm (s, bi, s, skey->E.n);
+       }
     }
   while (!mpi_cmp_ui (s, 0));
 
++++++ libgcrypt-fips_selftest_trigger_file.patch ++++++
Index: libgcrypt-1.8.2/src/fips.c
===================================================================
--- libgcrypt-1.8.2.orig/src/fips.c     2020-04-16 21:15:01.633217969 +0200
+++ libgcrypt-1.8.2/src/fips.c  2020-04-16 21:21:44.279376166 +0200
@@ -651,7 +651,7 @@ get_library_path(const char *libname, co
 }
 
 static gpg_error_t
-get_hmac_path(char **fname)
+get_hmac_path(char **fname, char *suffix)
 {
   char libpath[4096];
   gpg_error_t err;
@@ -676,7 +676,7 @@ get_hmac_path(char **fname)
            p = *fname;
          memmove (p+1, p, strlen (p)+1);
          *p = '.';
-         strcat (*fname, ".hmac");
+         strcat (*fname, suffix);
          err = 0;
        }
     }
@@ -708,7 +708,7 @@ check_binary_integrity (void)
       else
         {
           FILE *fp;
-         err = get_hmac_path(&fname);
+         err = get_hmac_path(&fname, ".hmac");
          if (!err)
            {
               /* Open the file.  */
@@ -769,7 +769,7 @@ can_skip_selftests(void)
   if (fips_mode())
     return 0;
 
-  if (get_hmac_path(&fname))
+  if (get_hmac_path(&fname, ".fips"))
     return 0;
 
   /* check the hmac presence */
++++++ libgcrypt-global_init-constructor.patch ++++++
Index: libgcrypt-1.8.2/src/global.c
===================================================================
--- libgcrypt-1.8.2.orig/src/global.c   2020-04-16 21:13:28.252717330 +0200
+++ libgcrypt-1.8.2/src/global.c        2020-04-16 21:13:47.960822991 +0200
@@ -86,7 +86,7 @@ static gpg_err_code_t external_lock_test
    likely to be called at startup.  The suggested way for an
    application to make sure that this has been called is by using
    gcry_check_version. */
-static void
+static void __attribute__((constructor))
 global_init (void)
 {
   gcry_error_t err = 0;
@@ -134,6 +134,16 @@ global_init (void)
   if (err)
     goto fail;
 
+  int no_secmem_save;
+  /* it should be always 0 at this point but let's keep on the safe side */
+  no_secmem_save = no_secure_memory;
+  no_secure_memory = 1;
+  err = _gcry_fips_run_selftests (0);
+  no_secure_memory = no_secmem_save;
+
+  if (err)
+    goto fail;
+
   return;
 
  fail:
@@ -141,16 +151,6 @@ global_init (void)
 }
 
 
-void __attribute__ ((constructor)) _gcry_global_constructor (void)
-{
-  /* We always need the FSM lock to be functional. */
-  _gcry_initialize_fsm_lock ();
-
-  /* We run the integrity check at this point. The remaining
-     selftests are run before use of the library by application. */
-  _gcry_fips_run_selftests (0);
-}
-
 /* This function is called by the macro fips_is_operational and makes
    sure that the minimal initialization has been done.  This is far
    from a perfect solution and hides problems with an improper
Index: libgcrypt-1.8.2/src/fips.c
===================================================================
--- libgcrypt-1.8.2.orig/src/fips.c     2020-04-16 21:13:28.252717330 +0200
+++ libgcrypt-1.8.2/src/fips.c  2020-04-16 21:14:44.781127616 +0200
@@ -125,6 +125,7 @@ void
 _gcry_initialize_fips_mode (int force)
 {
   static int done;
+  gpg_error_t err;
 
   /* Make sure we are not accidentally called twice.  */
   if (done)
@@ -214,6 +215,23 @@ _gcry_initialize_fips_mode (int force)
       /* Yes, we are in FIPS mode.  */
       FILE *fp;
 
+      /* Intitialize the lock to protect the FSM.  */
+      err = gpgrt_lock_init (&fsm_lock);
+      if (err)
+       {
+         /* If that fails we can't do anything but abort the
+             process. We need to use log_info so that the FSM won't
+             get involved.  */
+         log_info ("FATAL: failed to create the FSM lock in libgcrypt: %s\n",
+                   gpg_strerror (err));
+#ifdef HAVE_SYSLOG
+         syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
+                 "creating FSM lock failed: %s - abort",
+                 gpg_strerror (err));
+#endif /*HAVE_SYSLOG*/
+         abort ();
+       }
+
       /* If the FIPS force files exists, is readable and has a number
          != 0 on its first line, we enable the enforced fips mode.  */
       fp = fopen (FIPS_FORCE_FILE, "r");
@@ -614,10 +632,10 @@ get_library_path(const char *libname, co
     void *dl, *sym;
     int rv = -1;
 
-        dl = dlopen(libname, RTLD_LAZY);
-        if (dl == NULL) {
-            return -1;
-        }       
+    dl = dlopen(libname, RTLD_LAZY);
+    if (dl == NULL) {
+        return -1;
+    }
 
     sym = dlsym(dl, symbolname);
 
@@ -632,6 +650,39 @@ get_library_path(const char *libname, co
     return rv;
 }
 
+static gpg_error_t
+get_hmac_path(char **fname)
+{
+  char libpath[4096];
+  gpg_error_t err;
+
+  if (get_library_path ("libgcrypt.so.20", "gcry_check_version", libpath, 
sizeof(libpath)))
+    err = gpg_error_from_syserror ();
+  else
+    {
+      *fname = _gcry_malloc (strlen (libpath) + 1 + 5 + 1 );
+      if (!*fname)
+       err = gpg_error_from_syserror ();
+      else
+       {
+          char *p;
+
+         /* Prefix the basename with a dot.  */
+         strcpy (*fname, libpath);
+         p = strrchr (*fname, '/');
+         if (p)
+            p++;
+         else
+           p = *fname;
+         memmove (p+1, p, strlen (p)+1);
+         *p = '.';
+         strcat (*fname, ".hmac");
+         err = 0;
+       }
+    }
+  return err;
+}
+
 /* Run an integrity check on the binary.  Returns 0 on success.  */
 static int
 check_binary_integrity (void)
@@ -656,25 +707,10 @@ check_binary_integrity (void)
         err = gpg_error (GPG_ERR_INTERNAL);
       else
         {
-          fname = xtrymalloc (strlen (libpath) + 1 + 5 + 1 );
-          if (!fname)
-            err = gpg_error_from_syserror ();
-          else
-            {
-              FILE *fp;
-              char *p;
-
-              /* Prefix the basename with a dot.  */
-              strcpy (fname, libpath);
-              p = strrchr (fname, '/');
-              if (p)
-                p++;
-              else
-                p = fname;
-              memmove (p+1, p, strlen (p)+1);
-              *p = '.';
-              strcat (fname, ".hmac");
-
+          FILE *fp;
+         err = get_hmac_path(&fname);
+         if (!err)
+           {
               /* Open the file.  */
               fp = fopen (fname, "r");
               if (!fp)
@@ -725,6 +761,33 @@ check_binary_integrity (void)
 #endif
 }
 
+int
+can_skip_selftests(void)
+{
+  char *fname = NULL;
+  int ret = 0;
+
+  if (fips_mode())
+    return 0;
+
+  if (get_hmac_path(&fname))
+    return 0;
+
+  /* check the hmac presence */
+  if (access(fname, F_OK))
+    /* no hmac file is present, don't run the tests */
+    if (errno == ENOENT)
+      ret = 1;
+  /* otherwise one of these events happened:
+   * access() returned 0
+   *   -> run the tests
+   * some error other than ENOENT occurred
+   *   -> run the tests anyway and let them fail
+   */
+
+  xfree(fname);
+  return ret;
+}
 
 /* Run the self-tests.  If EXTENDED is true, extended versions of the
    selftest are run, that is more tests than required by FIPS.  */
@@ -733,26 +795,13 @@ _gcry_fips_run_selftests (int extended)
 {
   enum module_states result = STATE_ERROR;
   gcry_err_code_t ec = GPG_ERR_SELFTEST_FAILED;
-  int in_poweron;
 
-  lock_fsm ();
-  in_poweron = (current_state == STATE_POWERON);
-  unlock_fsm ();
-
-  fips_new_state (STATE_SELFTEST);
-
-  /* We first check the integrity of the binary.
-     If run from the constructor we are in POWERON state,
-     we return and finish the remaining selftests before
-     real use of the library. It will be in the POWERON
-     state meanwhile.  */
-  if (in_poweron)
-    if (check_binary_integrity ())
-      goto leave;
-
-  if (in_poweron)
+  if (can_skip_selftests())
     return 0;
 
+  if (fips_mode ())
+    fips_new_state (STATE_SELFTEST);
+
   if (run_cipher_selftests (extended))
     goto leave;
 
@@ -762,6 +811,9 @@ _gcry_fips_run_selftests (int extended)
   if (run_mac_selftests (extended))
     goto leave;
 
+  if (check_binary_integrity ())
+    goto leave;
+
   /* Run random tests before the pubkey tests because the latter
      require random.  */
   if (run_random_selftests ())
@@ -775,7 +827,8 @@ _gcry_fips_run_selftests (int extended)
   ec = 0;
 
  leave:
-  fips_new_state (result);
+  if (fips_mode ())
+    fips_new_state (result);
 
   return ec;
 }
@@ -831,7 +884,6 @@ fips_new_state (enum module_states new_s
     {
     case STATE_POWERON:
       if (new_state == STATE_INIT
-          || new_state == STATE_SELFTEST
           || new_state == STATE_ERROR
           || new_state == STATE_FATALERROR)
         ok = 1;
@@ -846,8 +898,6 @@ fips_new_state (enum module_states new_s
 
     case STATE_SELFTEST:
       if (new_state == STATE_OPERATIONAL
-          || new_state == STATE_INIT
-          || new_state == STATE_SELFTEST
           || new_state == STATE_ERROR
           || new_state == STATE_FATALERROR)
         ok = 1;
++++++ libgcrypt-invoke-global_init-from-constructor.patch ++++++
Index: libgcrypt-1.8.2/src/global.c
===================================================================
--- libgcrypt-1.8.2.orig/src/global.c
+++ libgcrypt-1.8.2/src/global.c
@@ -145,6 +145,9 @@ void __attribute__ ((constructor)) _gcry
 {
   /* We always need the FSM lock to be functional. */
   _gcry_initialize_fsm_lock ();
+
+  /* Run the self-tests from the constructor. */
+  global_init ();
 }
 
 /* This function is called by the macro fips_is_operational and makes
++++++ libgcrypt-random_selftests-testentropy.patch ++++++
Index: libgcrypt-1.8.2/random/random-drbg.c
===================================================================
--- libgcrypt-1.8.2.orig/random/random-drbg.c
+++ libgcrypt-1.8.2/random/random-drbg.c
@@ -2428,6 +2428,10 @@ drbg_healthcheck_sanity (struct gcry_drb
 
   /* if the following tests fail, it is likely that there is a buffer
    * overflow and we get a SIGSEV */
+  test_data.testentropy = &testentropy;
+  test_data.fail_seed_source = 0;
+  drbg_string_fill (&testentropy, test->entropy, test->entropylen);
+  drbg->test_data = &test_data;
   ret = drbg_instantiate (drbg, NULL, coreref, 1);
   if (ret)
     goto outbuf;
++++++ libgcrypt-rsa-no-blinding.patch ++++++
--- libgcrypt-1.8.2.orig/cipher/rsa.c   2020-03-26 07:23:17.392861551 +0100
+++ libgcrypt-1.8.2.orig/cipher/rsa.c   2020-03-26 15:43:29.556282072 +0100
@@ -91,10 +91,16 @@ static const char sample_secret_key[] =
 "       79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77"
 "       88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E"
 "       8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B919#)"
+"))";
+/* We need to get rid of the u value, in order to end in
+ * secret_core_std when called from secret. It's not used anyway. */
+
+/*
 "   (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04"
 "       479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4"
 "       A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9"
 "       AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7#)))";
+*/
 
 /* A sample 2048 bit RSA key used for the selftests (public only).  */
 static const char sample_public_key[] =
@@ -1252,8 +1258,8 @@ rsa_check_secret_key (gcry_sexp_t keypar
   RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL};
 
   /* To check the key we need the optional parameters. */
-  rc = sexp_extract_param (keyparms, NULL, "nedpqu",
-                           &sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
+  rc = sexp_extract_param (keyparms, NULL, "npq",
+                           &sk.n, &sk.p, &sk.q,
                            NULL);
   if (rc)
     goto leave;
@@ -1263,11 +1269,8 @@ rsa_check_secret_key (gcry_sexp_t keypar
 
  leave:
   _gcry_mpi_release (sk.n);
-  _gcry_mpi_release (sk.e);
-  _gcry_mpi_release (sk.d);
   _gcry_mpi_release (sk.p);
   _gcry_mpi_release (sk.q);
-  _gcry_mpi_release (sk.u);
   if (DBG_CIPHER)
     log_debug ("rsa_testkey    => %s\n", gpg_strerror (rc));
   return rc;
@@ -1710,11 +1713,11 @@ static const char *
 selftest_sign_2048 (gcry_sexp_t pkey, gcry_sexp_t skey)
 {
   static const char sample_data[] =
-    "(data (flags pkcs1)"
+    "(data (flags pkcs1 no-blinding)"
     " (hash sha256 #11223344556677889900aabbccddeeff"
     /**/           "102030405060708090a0b0c0d0f01121#))";
   static const char sample_data_bad[] =
-    "(data (flags pkcs1)"
+    "(data (flags pkcs1 no-blinding)"
     " (hash sha256 #11223344556677889900aabbccddeeff"
     /**/           "802030405060708090a0b0c0d0f01121#))";
 
@@ -1857,7 +1860,7 @@ selftest_encr_2048 (gcry_sexp_t pkey, gc
   gcry_mpi_t ref_mpi = NULL;
 
   /* Put the plaintext into an S-expression.  */
-  err = sexp_build (&plain, NULL, "(data (flags raw) (value %s))", plaintext);
+  err = sexp_build (&plain, NULL, "(data (flags raw no-blinding) (value %s))", 
plaintext);
   if (err)
     {
       errtxt = "converting data failed";
@@ -1897,6 +1900,26 @@ selftest_encr_2048 (gcry_sexp_t pkey, gc
       goto leave;
     }
 
+  /* This sexp trickery is to prevent the use of blinding.
+   * The flag doesn't get inherited by encr, so we have to
+   * derive a new sexp from the ciphertext */
+  char buf[1024];
+  memset(buf, 0, sizeof(buf));
+  err = _gcry_mpi_print (GCRYMPI_FMT_STD, buf, sizeof buf, NULL, ciphertext);
+  if (err)
+    {
+      errtxt = "Dumping ciphertext mpi to buffer failed";
+      goto leave;
+    }
+
+  sexp_release (encr);
+  err = sexp_build (&encr, NULL, "(enc-val (flags no-blinding) (rsa (a %s)))", 
buf);
+  if (err)
+    {
+      errtxt = "Adding no-blinding flag to ciphertext failed";
+      goto leave;
+    }
+
   /* Decrypt.  */
   err = _gcry_pk_decrypt (&decr, encr, skey);
   if (err)

Reply via email to