[PATCH setup 0/4] Misc crypto fixes and improvements

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH setup 0/4] Misc crypto fixes and improvements

Jon TURNEY
Jon Turney (4):
  Various improvements to debug output from crypto.cc
  Increase buffer size in LogPrintf adaptors
  Provide hash to DSA as an opaque block
  Handle multiple signature packets in .sig file

 LogSingleton.cc |   8 +-
 crypto.cc       | 363 ++++++++++++++++++++++++++++--------------------
 2 files changed, 217 insertions(+), 154 deletions(-)

--
2.21.0

Reply | Threaded
Open this post in threaded view
|

[PATCH setup 1/4] Various improvements to debug output from crypto.cc

Jon TURNEY
Build an adaptor for log output from gcrypt (unfortunately complex as it
needs to gather/split lines on '\n')

Don't really need a hard breakpoint for ERRKIND, so it's the same,
irrespective of CRYPTODEBUGGING being defined.

Always debug log the pk type and hash alg in use.

Allow CRYPTODEBUGGING to be set by CPPFLAGS etc.
---
 crypto.cc | 67 +++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 58 insertions(+), 9 deletions(-)

diff --git a/crypto.cc b/crypto.cc
index 0974c6a..364ef82 100644
--- a/crypto.cc
+++ b/crypto.cc
@@ -30,15 +30,16 @@
 #include "gpg-packet.h"
 #include "geturl.h"
 
+#ifndef CRYPTODEBUGGING
 #define CRYPTODEBUGGING         (0)
+#endif
 
+#define ERRKIND note
 #if CRYPTODEBUGGING
-#define ERRKIND __asm__ __volatile__ (".byte 0xcc"); note
 #define MESSAGE LogBabblePrintf
-#else  /* !CRYPTODEBUGGING */
-#define ERRKIND note
+#else
 #define MESSAGE while (0) LogBabblePrintf
-#endif /* CRYPTODEBUGGING */
+#endif
 
 /*  Command-line options for specifying and controlling extra keys.  */
 static StringArrayOption ExtraKeyOption ('K', "pubkey",
@@ -334,8 +335,8 @@ pkt_cb_resp sig_file_walker (struct packet_walker *wlk, unsigned char tag,
       sigdat->hash_alg = pkt_getch (wlk->pfile);
     }
 
-  MESSAGE ("sig type %d, pk_alg %d, hash_alg %d\n", sigdat->sig_type,
- sigdat->pk_alg, sigdat->hash_alg);
+  LogBabblePrintf("signature: sig_type %d, pk_alg %d, hash_alg %d\n",
+                  sigdat->sig_type, sigdat->pk_alg, sigdat->hash_alg);
 
   // We only handle binary file signatures
   if (sigdat->sig_type != RFC4880_ST_BINARY)
@@ -392,8 +393,7 @@ pkt_cb_resp sig_file_walker (struct packet_walker *wlk, unsigned char tag,
   // Both formats now have 16 bits of the hash value.
   int hash_first = pkt_getword (wlk->pfile);
 
-  MESSAGE ("sig type %d, pk_alg %d, hash_alg %d - first $%04x\n", sigdat->sig_type,
- sigdat->pk_alg, sigdat->hash_alg, hash_first);
+  MESSAGE ("signature: hash leftmost 2 bytes 0x%04x\n", hash_first);
 
   /*  Algorithm-Specific Fields for signatures:
 
@@ -471,6 +471,46 @@ add_key_from_sexpr (gcry_sexp_t key)
   delete [] sexprbuf;
 }
 
+#if CRYPTODEBUGGING
+static void
+gcrypt_log_adaptor(void *priv, int level, const char *fmt, va_list args)
+{
+  static std::string collected;
+
+  char buf[GPG_KEY_SEXPR_BUF_SIZE];
+  vsnprintf (buf, GPG_KEY_SEXPR_BUF_SIZE, fmt, args);
+
+  char *start = buf;
+  char *end;
+
+  do
+    {
+      if (collected.length() == 0)
+        {
+          collected = "gcrypt: ";
+        }
+
+      end = strchr(start, '\n');
+      if (end)
+        *end = '\0';
+
+      collected += start;
+
+      if (end)
+        {
+          if (level == GCRY_LOG_DEBUG)
+            Log (LOG_BABBLE) << collected << endLog;
+          else
+            Log (LOG_PLAIN) << collected << endLog;
+
+          collected.clear();
+          start = end + 1;
+        }
+    }
+  while (end);
+}
+#endif
+
 /*  Verify the signature on an ini file.  Takes care of all key-handling.  */
 bool
 verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
@@ -501,7 +541,16 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
   size_t n;
 
   /* Initialise the library.  */
-  gcry_check_version (NULL);
+  static bool gcrypt_init = false;
+  if (!gcrypt_init)
+    {
+#if CRYPTODEBUGGING
+      gcry_set_log_handler (gcrypt_log_adaptor, NULL);
+      gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
+#endif
+      gcry_check_version (NULL);
+      gcrypt_init = true;
+    }
 
   /* So first build the built-in key.  */
   gcry_sexp_t dsa_key;
--
2.21.0

Reply | Threaded
Open this post in threaded view
|

[PATCH setup 2/4] Increase buffer size in LogPrintf adaptors

Jon TURNEY
In reply to this post by Jon TURNEY
crypto.cc can now generate output lines bigger than the current buffer
size
---
 LogSingleton.cc | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/LogSingleton.cc b/LogSingleton.cc
index 73b8fb6..e08717f 100644
--- a/LogSingleton.cc
+++ b/LogSingleton.cc
@@ -81,10 +81,10 @@ void
 LogBabblePrintf(const char *fmt, ...)
 {
   int len;
-  char buf[2000];
+  char buf[8192];
   va_list args;
   va_start (args, fmt);
-  len = vsnprintf (buf, 2000, fmt, args);
+  len = vsnprintf (buf, 8192, fmt, args);
   if ((len > 0) && (buf[len-1] == '\n'))
     buf[len-1] = 0;
   Log (LOG_BABBLE) << buf << endLog;
@@ -94,10 +94,10 @@ void
 LogPlainPrintf(const char *fmt, ...)
 {
   int len;
-  char buf[2000];
+  char buf[8192];
   va_list args;
   va_start (args, fmt);
-  len = vsnprintf (buf, 2000, fmt, args);
+  len = vsnprintf (buf, 8192, fmt, args);
   if ((len > 0) && (buf[len-1] == '\n'))
     buf[len-1] = 0;
   Log (LOG_PLAIN) << buf << endLog;
--
2.21.0

Reply | Threaded
Open this post in threaded view
|

[PATCH setup 3/4] Provide hash to DSA as an opaque block

Jon TURNEY
In reply to this post by Jon TURNEY
This allows libgcrypt to truncate the hash correctly when a hash alg is
specified which produces more than the 160 bits DSA accepts.
---
 crypto.cc | 20 +++++---------------
 1 file changed, 5 insertions(+), 15 deletions(-)

diff --git a/crypto.cc b/crypto.cc
index 364ef82..428b100 100644
--- a/crypto.cc
+++ b/crypto.cc
@@ -71,7 +71,7 @@ static const char *dsa_sig_templ = "(sig-val (dsa (r %m) (s %m)))";
 static const char *rsa_sig_templ = "(sig-val (rsa (s %m)))";
 
 /*  S-expr template for data block to be signed.  */
-static const char *dsa_data_hash_templ = "(data (flags raw) (value %m))";
+static const char *dsa_data_hash_templ = "(data (flags raw) (hash %s %b))";
 
 /*  S-expr template for RSA data block to be signed.  */
 static const char *rsa_data_hash_templ = "(data (flags pkcs1) (hash %s %b))";
@@ -720,25 +720,15 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
               return false;
             }
 
-          // Make a temp mpi from the hash output, then an s-expr from that.
-          gcry_mpi_t mpi_hash = 0;
-          unsigned char *tmpbuf = gcry_md_read (sigdat.md, 0);
-          size_t dlen = gcry_md_get_algo_dlen (sigdat.algo);
-          rv = gcry_mpi_scan (&mpi_hash, GCRYMPI_FMT_USG, tmpbuf, dlen, 0UL);
-          if (rv != GPG_ERR_NO_ERROR)
-            {
-              ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating hash MPI.");
-              return false;
-            }
-
-          rv = gcry_sexp_build (&hash, &n, dsa_data_hash_templ, mpi_hash);
+          rv = gcry_sexp_build (&hash, &n, dsa_data_hash_templ,
+                                gcry_md_algo_name(sigdat.algo),
+                                gcry_md_get_algo_dlen (sigdat.algo),
+                                gcry_md_read (sigdat.md, 0));
           if (rv != GPG_ERR_NO_ERROR)
             {
               ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating hash s-expr.");
               return false;
             }
-
-          gcry_mpi_release (mpi_hash);
         }
       else if (sigdat.pk_alg == RFC4880_PK_RSA)
         {
--
2.21.0

Reply | Threaded
Open this post in threaded view
|

[PATCH setup 4/4] Handle multiple signature packets in .sig file

Jon TURNEY
In reply to this post by Jon TURNEY
Rather than stopping after the first signature packet, handle multiple
signature packets appearing in a .sig file.  If any of them is a valid
signature from a known key, then the signature is good.
---
 crypto.cc | 288 +++++++++++++++++++++++++++++-------------------------
 1 file changed, 156 insertions(+), 132 deletions(-)

diff --git a/crypto.cc b/crypto.cc
index 428b100..2f21cc1 100644
--- a/crypto.cc
+++ b/crypto.cc
@@ -76,6 +76,20 @@ static const char *dsa_data_hash_templ = "(data (flags raw) (hash %s %b))";
 /*  S-expr template for RSA data block to be signed.  */
 static const char *rsa_data_hash_templ = "(data (flags pkcs1) (hash %s %b))";
 
+/*  Information on a key to try */
+struct key_info
+{
+  key_info(std::string _name, bool _builtin, gcry_sexp_t _key, bool _owned=false) :
+    name(_name), builtin(_builtin), key(_key), owned(_owned)
+  {
+  }
+
+  std::string name;
+  bool builtin;  // if true, we don't need to retain this key with add_key_from_sexpr()
+  gcry_sexp_t key;
+  bool owned;    // if true, we own this key and should use gcry_sexp_release() on it
+};
+
 /*  User context data for sig packet walk.  */
 struct sig_data
 {
@@ -97,8 +111,11 @@ struct sig_data
   /*  Converted algo code.  */
   int algo;
 
+  /* Keys */
+  std::vector<struct key_info> *keys_to_try;
+
   /*  Final status.  */
-  bool complete;
+  bool valid;
 };
 
 /*  User context data for key packet walk.  */
@@ -259,6 +276,114 @@ fold_lfs_and_spaces (char *buf, size_t n)
   return ptr2 - buf;
 }
 
+/*  Size and allocate a temp buffer to print a representation
+  of a public key s-expr into, then add that to the extra keys
+  setting so it persists for the next run.  */
+static void
+add_key_from_sexpr (gcry_sexp_t key)
+{
+  size_t n = gcry_sexp_sprint (key, GCRYSEXP_FMT_ADVANCED, 0, ~0);
+  char *sexprbuf = new char[n];
+  n = gcry_sexp_sprint (key, GCRYSEXP_FMT_ADVANCED, sexprbuf, n);
+  // +1 because we want to include the nul-terminator.
+  n = fold_lfs_and_spaces (sexprbuf, n + 1);
+  ExtraKeysSetting::instance().add_key (sexprbuf);
+  MESSAGE ("keep:%d\n'%s'", n, sexprbuf);
+  delete [] sexprbuf;
+}
+
+static bool
+verify_sig(struct sig_data *sigdat, HWND owner)
+{
+  gcry_error_t rv;
+  size_t n;
+  {
+      /*  sig coefficients in s-expr format.  */
+      gcry_sexp_t sig;
+
+      /*  signature hash data in s-expr format.  */
+      gcry_sexp_t hash;
+
+      /* Build everything into s-exprs, and call the libgcrypt verification
+         routine. */
+
+      if (sigdat->pk_alg == RFC4880_PK_DSA)
+        {
+          rv = gcry_sexp_build (&sig, &n, dsa_sig_templ, sigdat->dsa_mpi_r,
+                                sigdat->dsa_mpi_s);
+          if (rv != GPG_ERR_NO_ERROR)
+            {
+              ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating sig s-expr.");
+              return false;
+            }
+
+          rv = gcry_sexp_build (&hash, &n, dsa_data_hash_templ,
+                                gcry_md_algo_name(sigdat->algo),
+                                gcry_md_get_algo_dlen (sigdat->algo),
+                                gcry_md_read (sigdat->md, 0));
+          if (rv != GPG_ERR_NO_ERROR)
+            {
+              ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating hash s-expr.");
+              return false;
+            }
+        }
+      else if (sigdat->pk_alg == RFC4880_PK_RSA)
+        {
+          rv = gcry_sexp_build (&sig, &n, rsa_sig_templ, sigdat->rsa_mpi_s);
+          if (rv != GPG_ERR_NO_ERROR)
+            {
+              ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating sig s-expr.");
+              return false;
+            }
+
+          rv = gcry_sexp_build (&hash, &n, rsa_data_hash_templ,
+                                gcry_md_algo_name(sigdat->algo),
+                                gcry_md_get_algo_dlen (sigdat->algo),
+                                gcry_md_read (sigdat->md, 0));
+          if (rv != GPG_ERR_NO_ERROR)
+            {
+              ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating hash s-expr.");
+              return false;
+            }
+        }
+
+#if CRYPTODEBUGGING
+      n = gcry_sexp_sprint (sig, GCRYSEXP_FMT_ADVANCED, sexprbuf,
+                            GPG_KEY_SEXPR_BUF_SIZE);
+      LogBabblePrintf ("sig:%d\n'%s'", n, sexprbuf);
+      n = gcry_sexp_sprint (hash, GCRYSEXP_FMT_ADVANCED, sexprbuf,
+                            GPG_KEY_SEXPR_BUF_SIZE);
+      LogBabblePrintf ("hash:%d\n'%s'", n, sexprbuf);
+#endif /* CRYPTODEBUGGING */
+
+      // Well, we're actually there!
+      // Try it against each key in turn
+
+      std::vector<key_info>::iterator it;
+      for (it = sigdat->keys_to_try->begin ();
+           it < sigdat->keys_to_try->end ();
+           ++it)
+        {
+          rv = gcry_pk_verify (sig, hash, it->key);
+
+          LogBabblePrintf("signature: tried key %s, returned 0x%08x %s\n",
+                          it->name.c_str(), rv, gcry_strerror(rv));
+
+          if (rv != GPG_ERR_NO_ERROR)
+            continue;
+          // Found it!  This key gets kept!
+          if (!it->builtin)
+            add_key_from_sexpr (it->key);
+          break;
+        }
+
+      gcry_sexp_release (sig);
+      gcry_sexp_release (hash);
+    }
+
+  return (rv == GPG_ERR_NO_ERROR);;
+}
+
 /*  Do-nothing stubs called by the sig file walker to
   walk over the embedded subpackets.  In the event, we don't
   actually need to do this as we aren't inspecting them.  */
@@ -287,7 +412,6 @@ pkt_cb_resp sig_file_walker (struct packet_walker *wlk, unsigned char tag,
  size_t packetsize, size_t hdrpos)
 {
   struct sig_data *sigdat = (struct sig_data *)(wlk->userdata);
-  sigdat->complete = false;
 
   if (tag != RFC4880_PT_SIGNATURE)
     return pktCONTINUE;
@@ -361,6 +485,7 @@ pkt_cb_resp sig_file_walker (struct packet_walker *wlk, unsigned char tag,
     }
 
   // Now we know hash algo, we can create md context.
+  sigdat->md = 0;
   gcry_error_t rv = gcry_md_open (&sigdat->md, sigdat->algo, 0);
   if (rv != GPG_ERR_NO_ERROR)
     {
@@ -407,6 +532,8 @@ pkt_cb_resp sig_file_walker (struct packet_walker *wlk, unsigned char tag,
       for RSA:
       - MPI of RSA value m^d mod n (aka s)
   */
+  sigdat->dsa_mpi_r = sigdat->dsa_mpi_s = 0;
+  sigdat->rsa_mpi_s = 0;
 
   if (sigdat->pk_alg == RFC4880_PK_DSA)
     {
@@ -449,26 +576,30 @@ pkt_cb_resp sig_file_walker (struct packet_walker *wlk, unsigned char tag,
       gcry_md_putc (sigdat->md, nbytes & 0xff);
     }
 
-  // Hooray, succeeded!
-  sigdat->complete = true;
+  /* So, we have hashed all the data, and found the sig coefficients. */
 
-  return pktHALT;
-}
+  // finalize the hash
+  gcry_md_final (sigdat->md);
+  MESSAGE("digest length is %d\n",gcry_md_get_algo_dlen (sigdat->algo));
 
-/*  Size and allocate a temp buffer to print a representation
-  of a public key s-expr into, then add that to the extra keys
-  setting so it persists for the next run.  */
-void
-add_key_from_sexpr (gcry_sexp_t key)
-{
-  size_t n = gcry_sexp_sprint (key, GCRYSEXP_FMT_ADVANCED, 0, ~0);
-  char *sexprbuf = new char[n];
-  n = gcry_sexp_sprint (key, GCRYSEXP_FMT_ADVANCED, sexprbuf, n);
-  // +1 because we want to include the nul-terminator.
-  n = fold_lfs_and_spaces (sexprbuf, n + 1);
-  ExtraKeysSetting::instance().add_key (sexprbuf);
-  MESSAGE ("keep:%d\n'%s'", n, sexprbuf);
-  delete [] sexprbuf;
+  // check this signature
+  if (verify_sig (sigdat, wlk->owner))
+      sigdat->valid = true;
+
+  // discard hash
+  if (sigdat->md)
+    gcry_md_close (sigdat->md);
+
+  // discard sig coefffcients
+  if (sigdat->dsa_mpi_r)
+    gcry_mpi_release (sigdat->dsa_mpi_r);
+  if (sigdat->dsa_mpi_s)
+    gcry_mpi_release (sigdat->dsa_mpi_s);
+  if (sigdat->rsa_mpi_s)
+    gcry_mpi_release (sigdat->rsa_mpi_s);
+
+  // we can stop immediately if we found a good signature
+  return sigdat->valid ? pktHALT : pktCONTINUE;
 }
 
 #if CRYPTODEBUGGING
@@ -519,18 +650,6 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
   struct sig_data sigdat;
 
   /*  Vector of keys to use.  */
-  struct key_info
-  {
-    key_info(std::string _name, bool _builtin, gcry_sexp_t _key, bool _owned=false) :
-      name(_name), builtin(_builtin), key(_key), owned(_owned)
-    {
-    }
-
-    std::string name;
-    bool builtin;  // if true, we don't need to retain this key with add_key_from_sexpr()
-    gcry_sexp_t key;
-    bool owned;    // if true, we own this key and should use gcry_sexp_release() on it
-  };
   std::vector<struct key_info> keys_to_try;
 
   /*  Overall status of signature.  */
@@ -688,110 +807,15 @@ verify_ini_file_sig (io_stream *ini_file, io_stream *ini_sig_file, HWND owner)
   // We pass in a pointer to the ini file in the user context data,
   // which the packet walker callback uses to create a new hash
   // context preloaded with all the signature-covered data.
-  sigdat.complete = false;
+  sigdat.valid = false;
   sigdat.sign_data = ini_file;
-  sigdat.dsa_mpi_r = sigdat.dsa_mpi_s = 0;
-  sigdat.rsa_mpi_s = 0;
-  sigdat.md = 0;
-  pkt_walk_packets (ini_sig_file, sig_file_walker, owner, 0,
- ini_sig_file->get_size (), &sigdat);
-  if (sigdat.complete)
-    {
-      /*  sig coefficients in s-expr format.  */
-      gcry_sexp_t sig;
-
-      /*  signature hash data in s-expr format.  */
-      gcry_sexp_t hash;
-
-      /* So, we have hashed all the data, and found the sig coefficients.
-        Next stages are to finalise the hash, build everything into
-        s-exprs, and call the libgcrypt verification routine.  */
-
-      gcry_md_final (sigdat.md);
-      MESSAGE("digest length is %d\n",gcry_md_get_algo_dlen (sigdat.algo));
-
-      if (sigdat.pk_alg == RFC4880_PK_DSA)
-        {
-          rv = gcry_sexp_build (&sig, &n, dsa_sig_templ, sigdat.dsa_mpi_r,
-                                sigdat.dsa_mpi_s);
-          if (rv != GPG_ERR_NO_ERROR)
-            {
-              ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating sig s-expr.");
-              return false;
-            }
-
-          rv = gcry_sexp_build (&hash, &n, dsa_data_hash_templ,
-                                gcry_md_algo_name(sigdat.algo),
-                                gcry_md_get_algo_dlen (sigdat.algo),
-                                gcry_md_read (sigdat.md, 0));
-          if (rv != GPG_ERR_NO_ERROR)
-            {
-              ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating hash s-expr.");
-              return false;
-            }
-        }
-      else if (sigdat.pk_alg == RFC4880_PK_RSA)
-        {
-          rv = gcry_sexp_build (&sig, &n, rsa_sig_templ, sigdat.rsa_mpi_s);
-          if (rv != GPG_ERR_NO_ERROR)
-            {
-              ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating sig s-expr.");
-              return false;
-            }
-
-          rv = gcry_sexp_build (&hash, &n, rsa_data_hash_templ,
-                                gcry_md_algo_name(sigdat.algo),
-                                gcry_md_get_algo_dlen (sigdat.algo),
-                                gcry_md_read (sigdat.md, 0));
-          if (rv != GPG_ERR_NO_ERROR)
-            {
-              ERRKIND (owner, IDS_CRYPTO_ERROR, rv, "while creating hash s-expr.");
-              return false;
-            }
-        }
-
-#if CRYPTODEBUGGING
-      n = gcry_sexp_sprint (sig, GCRYSEXP_FMT_ADVANCED, sexprbuf,
-                            GPG_KEY_SEXPR_BUF_SIZE);
-      LogBabblePrintf ("sig:%d\n'%s'", n, sexprbuf);
-      n = gcry_sexp_sprint (hash, GCRYSEXP_FMT_ADVANCED, sexprbuf,
-                            GPG_KEY_SEXPR_BUF_SIZE);
-      LogBabblePrintf ("hash:%d\n'%s'", n, sexprbuf);
-#endif /* CRYPTODEBUGGING */
-
-      // Well, we're actually there!
-      // Try it against each key in turn
-
-      std::vector<key_info>::iterator it;
-      for (it = keys_to_try.begin (); it < keys_to_try.end (); ++it)
-        {
-          rv = gcry_pk_verify (sig, hash, it->key);
-
-          LogBabblePrintf("signature: tried key %s, returned 0x%08x %s\n",
-                          it->name.c_str(), rv, gcry_strerror(rv));
+  sigdat.keys_to_try = &keys_to_try;
 
-          if (rv != GPG_ERR_NO_ERROR)
-            continue;
-          // Found it!  This key gets kept!
-          if (!it->builtin)
-            add_key_from_sexpr (it->key);
-          break;
-        }
-      sig_ok = (rv == GPG_ERR_NO_ERROR);
+  pkt_walk_packets (ini_sig_file, sig_file_walker, owner, 0,
+                    ini_sig_file->get_size (), &sigdat);
 
-      gcry_sexp_release (sig);
-      gcry_sexp_release (hash);
-    }
+  sig_ok = sigdat.valid;
 
-  // Discard the temp data then.
-  if (sigdat.dsa_mpi_r)
-    gcry_mpi_release (sigdat.dsa_mpi_r);
-  if (sigdat.dsa_mpi_s)
-    gcry_mpi_release (sigdat.dsa_mpi_s);
-  if (sigdat.rsa_mpi_s)
-    gcry_mpi_release (sigdat.rsa_mpi_s);
-  if (sigdat.md)
-    gcry_md_close (sigdat.md);
   while (keys_to_try.size ())
     {
       if (keys_to_try.back ().owned)
--
2.21.0