libgcrypt and memoryloss

Dirk Stoecker gcrypt at dstoecker.de
Wed Nov 30 15:16:48 CET 2005


Hello,

I last time tried to convince you to implement the memory patch I 
developed into the library. I did not succeed for following reasons:

a) The patch was incomplete:
--> I rechecked the complete SVN and fixed all memory stuff. The patch 
still remains valid unchanged. No additions for other parts of the 
library are needed (according to example code).

b) There should be no useless code, which makes the library vulnerable.
--> The patch are altogether 40 lines of active code, where only 16 of 
them do real work, the others are only function overhead to keep a clean 
interface. And they are in no way useless. Below are the important parts 
of the patch.

c) The examples don't use it.
--> Well, now I added all the files in tests to the patch. Each of these
also calls FINALIZE before leaving main. All of these are 100% memory-loss 
free. The main work was to fix multiple memory losses in the example code 
as well as one in the library itself (cipher/ac.c).

So to get a final note: The examples for libgcrypt and the base library 
have a memory loss problem. Without handling the one-time-allocations 
first it has been nearly impossible to track this down and fix them (as 
nobody did till now). With the fix applied there are no memory memory loss 
problems which are covered by the example programs. The fix itself does 
not change the library interface at all, but only adds the already planned 
possibility to make a finalize call.

I will release the attached patch on my website, as due the LGPL 
conditions I am required to do so. I myself no longer use the dynamic 
library, but a largely stripped link library. Nevertheless I would prefer 
the patch included in main distribution, so I need not release the patch.

Are there still any reasons to NOT apply the patch?

Below the relevant parts of the patch, which probably nobody of you ever 
had a look on. It has NOTHING to do with dll unloading or anything like 
that which was used during argumentation from your side.

src/global.c
+static void
+global_finalize (void)
+{
+  _gcry_pk_finalize();
+  _gcry_md_finalize();
+  _gcry_cipher_finalize();
+//  ath_finalize();
+  _gcry_random_finalize();
+  any_init_done = 0;
+}
--
+    case GCRYCTL_FINALIZE:
+      global_finalize();
+      break;

src/g10lib.h
+void _gcry_cipher_finalize(void);
+void _gcry_md_finalize(void);
+void _gcry_pk_finalize(void);

cipher/pubkey.c
+void
+_gcry_pk_finalize(void)
+{
+  if(default_pubkeys_registered)
+  {
+    ath_mutex_lock(&pubkeys_registered_lock);
+    while(pubkeys_registered)
+    {
+      _gcry_module_release(pubkeys_registered);
+    }
+    default_pubkeys_registered = 0;
+    ath_mutex_unlock(&pubkeys_registered_lock);
+  }
+}

cipher/md.c
+void
+_gcry_md_finalize(void)
+{
+  if(default_digests_registered)
+  {
+    ath_mutex_lock(&digests_registered_lock);
+    while(digests_registered)
+    {
+      _gcry_module_release(digests_registered);
+    }
+    default_digests_registered = 0;
+    ath_mutex_unlock(&digests_registered_lock);
+  }
+}

cipher/cipher.c
+void
+_gcry_cipher_finalize(void)
+{
+  if(default_ciphers_registered)
+  {
+    ath_mutex_lock(&ciphers_registered_lock);
+    while(ciphers_registered)
+    {
+      _gcry_module_release(ciphers_registered);
+    }
+    default_ciphers_registered = 0;
+    ath_mutex_unlock(&ciphers_registered_lock);
+  }
+}

cipher/random.c
+void
+_gcry_random_finalize(void)
+{
+  if(is_initialized)
+  {
+    gcry_free(rndpool);
+    gcry_free(keypool);
+    is_initialized = 0;
+  }
+}

cipher/random.h
+void _gcry_random_finalize(void);

Ciao
-- 
 ____  _ _  ____  _ _    _ _  ____
|    |  |  |    |  | \  / |  |    | the cool Gremlin from Bischofswerda
|  __   |   ____|  |  \/  |  |    | WWW: http://www.dstoecker.de/
|    |  |  |       |      |  |    | PGP key available on www page.
|____| _|_ |____| _|_    _|_ |____| I hope AMIGA never stops making fun!
-------------- next part --------------
Index: src/global.c
===================================================================
--- src/global.c	(Revision 1140)
+++ src/global.c	(Arbeitskopie)
@@ -100,6 +100,17 @@
 
 
 
+static void
+global_finalize (void)
+{
+  _gcry_pk_finalize();
+  _gcry_md_finalize();
+  _gcry_cipher_finalize();
+//  ath_finalize();
+  _gcry_random_finalize();
+  any_init_done = 0;
+}
+
 /* Version number parsing.  */
 
 /* This function parses the first portion of the version number S and
@@ -334,6 +345,10 @@
       _gcry_fast_random_poll (); 
       break;
 
+    case GCRYCTL_FINALIZE:
+      global_finalize();
+      break;
+
     default:
       err = GPG_ERR_INV_OP;
     }
Index: src/gcrypt.h
===================================================================
--- src/gcrypt.h	(Revision 1140)
+++ src/gcrypt.h	(Arbeitskopie)
@@ -1142,7 +1142,7 @@
 typedef enum gcry_ac_em
   {
     GCRY_AC_EME_PKCS_V1_5,
-    GCRY_AC_EMSA_PKCS_V1_5,
+    GCRY_AC_EMSA_PKCS_V1_5
   }
 gcry_ac_em_t;
 
@@ -1150,7 +1150,7 @@
 typedef enum gcry_ac_scheme
   {
     GCRY_AC_ES_PKCS_V1_5,
-    GCRY_AC_SSA_PKCS_V1_5,
+    GCRY_AC_SSA_PKCS_V1_5
   }
 gcry_ac_scheme_t;
 
Index: src/g10lib.h
===================================================================
--- src/g10lib.h	(Revision 1140)
+++ src/g10lib.h	(Arbeitskopie)
@@ -233,6 +233,10 @@
 gcry_err_code_t _gcry_pk_init (void);
 gcry_err_code_t _gcry_ac_init (void);
 
+void _gcry_cipher_finalize(void);
+void _gcry_md_finalize(void);
+void _gcry_pk_finalize(void);
+
 gcry_err_code_t _gcry_pk_module_lookup (int id, gcry_module_t *module);
 void _gcry_pk_module_release (gcry_module_t module);
 gcry_err_code_t _gcry_pk_get_elements (int algo, char **enc, char **sig);
Index: tests/pubkey.c
===================================================================
--- tests/pubkey.c	(Revision 1140)
+++ tests/pubkey.c	(Arbeitskopie)
@@ -90,6 +90,7 @@
   /* Extract data from plaintext.  */
   l = gcry_sexp_find_token (plain0, "value", 0);
   x0 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG);
+  gcry_sexp_release (l);
 
   /* Encrypt data.  */
   rc = gcry_pk_encrypt (&cipher, plain0, pkey);
@@ -131,6 +132,8 @@
   /* Compare.  */
   if (gcry_mpi_cmp (x0, x1))
     die ("data corrupted\n");
+  gcry_mpi_release (x0);
+  gcry_mpi_release (x1);
 }
 
 static void
@@ -164,6 +167,7 @@
 
   check_keys_crypt (pkey, skey, plain);
   gcry_sexp_release (plain);
+  gcry_mpi_release(x);
 }
 
 static void
@@ -251,5 +255,7 @@
   for (; i > 0; i--)
     check_run ();
   
+  gcry_control (GCRYCTL_FINALIZE);
+
   return 0;
 }
Index: tests/tsexp.c
===================================================================
--- tests/tsexp.c	(Revision 1140)
+++ tests/tsexp.c	(Arbeitskopie)
@@ -64,6 +64,7 @@
 {
   int pass;
   gcry_sexp_t sexp;
+  gcry_mpi_t mpi;
   int idx;
   char *secure_buffer;
   size_t secure_buffer_len;
@@ -94,39 +95,46 @@
         case 0:
           string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
                     "(q #61626364656667#) (g %m)))");
-          
-          if ( gcry_sexp_build (&sexp, NULL, string,
-                                gcry_mpi_set_ui (NULL, 42)) )
+          mpi = gcry_mpi_set_ui (NULL, 42);
+          if ( gcry_sexp_build (&sexp, NULL, string, mpi) )
             {
+              gcry_mpi_release(mpi);
               fail (" scanning `%s' failed\n", string);
               return;
             }
+          gcry_mpi_release(mpi);
           break;
           
         case 1:
           string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
                     "(q %b) (g %m)))");
       
+          mpi = gcry_mpi_set_ui (NULL, 42);
           if ( gcry_sexp_build (&sexp, NULL, string, 
                                 15, "foo\0\x01\0x02789012345",
-                                gcry_mpi_set_ui (NULL, 42)) )
+                                mpi) )
             {
+              gcry_mpi_release(mpi);
               fail (" scanning `%s' failed\n", string);
               return;
             }
+          gcry_mpi_release(mpi);
           break;
 
         case 2:
           string = ("(public-key (dsa (p #41424344#) (y silly_y_value) "
                     "(q %b) (g %m)))");
       
+          mpi = gcry_mpi_set_ui (NULL, 17);
           if ( gcry_sexp_build (&sexp, NULL, string, 
                                 secure_buffer_len, secure_buffer,
-                                gcry_mpi_set_ui (NULL, 17)) )
+                                mpi) )
             {
+              gcry_mpi_release(mpi);
               fail (" scanning `%s' failed\n", string);
               return;
             }
+          gcry_mpi_release(mpi);
           if (!gcry_is_secure (sexp))
             fail ("gcry_sexp_build did not switch to secure memory\n");
           break;
@@ -148,62 +156,58 @@
 
           s1 = gcry_sexp_find_token (sexp, token, strlen(token) );
           if (!s1)
+            fail ("didn't found `%s'\n", token);
+          else
             {
-              fail ("didn't found `%s'\n", token);
-              continue;
-            }
+              p = gcry_sexp_nth_data (s1, 0, &n);
+              if (!p)
+                fail ("no car for `%s'\n", token);
+              else
+                {
+                  info ("car=`%.*s'\n", (int)n, p);
 
-          p = gcry_sexp_nth_data (s1, 0, &n);
-          if (!p)
-            {
-              fail ("no car for `%s'\n", token);
-              continue;
-            }
-          info ("car=`%.*s'\n", (int)n, p);
+                  s2 = gcry_sexp_cdr (s1);
+                  if (!s2) 
+                    fail ("no cdr for `%s'\n", token);
+                  else
+                    {
+                      p = gcry_sexp_nth_data (s2, 0, &n);
+                      if (p)
+                        fail ("data at car of `%s'\n", token);
+                      else if (parm)
+                        {
+                          gcry_sexp_release (s2);
+                          s2 = gcry_sexp_find_token (s1, parm, strlen (parm));
+                          if (!s2)
+                            fail ("didn't found `%s'\n", parm);
+                          else
+                            {
+                              p = gcry_sexp_nth_data (s2, 0, &n);
+                              if (!p) 
+                                fail("no car for `%s'\n", parm );
+                              else
+                                {
+                                  info ("car=`%.*s'\n", (int)n, p);
+                                  p = gcry_sexp_nth_data (s2, 1, &n);
+                                  if (!p) 
+                                    fail("no cdr for `%s'\n", parm );
+                                  else
+                                    {
+                                      info ("cdr=`%.*s'\n", (int)n, p);
 
-          s2 = gcry_sexp_cdr (s1);
-          if (!s2) 
-            {
-              fail ("no cdr for `%s'\n", token);
-              continue;
-            }
-
-          p = gcry_sexp_nth_data (s2, 0, &n);
-          if (p)
-            {
-              fail ("data at car of `%s'\n", token);
-              continue;
-            }
-
-          if (parm)
-            {
-              s2 = gcry_sexp_find_token (s1, parm, strlen (parm));
-              if (!s2)
-                {
-                  fail ("didn't found `%s'\n", parm);
-                  continue;
+                                      a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG);
+                                      if (!a)
+                                        fail("failed to cdr the mpi for `%s'\n", parm);
+                                      gcry_mpi_release (a);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                  if (s2)
+                    gcry_sexp_release (s2);
                 }
-              p = gcry_sexp_nth_data (s2, 0, &n);
-              if (!p) 
-                {
-                  fail("no car for `%s'\n", parm );
-                  continue;
-                }
-              info ("car=`%.*s'\n", (int)n, p);
-              p = gcry_sexp_nth_data (s2, 1, &n);
-              if (!p) 
-                {
-                  fail("no cdr for `%s'\n", parm );
-                  continue;
-                }
-              info ("cdr=`%.*s'\n", (int)n, p);
-          
-              a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG);
-              if (!a)
-                {
-                  fail("failed to cdr the mpi for `%s'\n", parm);
-                  continue;
-                }
+              gcry_sexp_release (s1);
             }
         }
      
@@ -387,6 +391,8 @@
   canon_len ();
   back_and_forth ();
   check_sscan ();
+
+  gcry_control (GCRYCTL_FINALIZE);
   
   return error_count? 1:0;
 }
Index: tests/ac-schemes.c
===================================================================
--- tests/ac-schemes.c	(Revision 1140)
+++ tests/ac-schemes.c	(Arbeitskopie)
@@ -318,6 +318,14 @@
       es_checks (handle, key_public, key_secret);
       ssa_checks (handle, key_public, key_secret);
     }
+
+  if(handle)
+    gcry_ac_close (handle);
+
+  if(key_secret)
+    gcry_ac_key_destroy (key_secret);
+  if(key_public)
+    gcry_ac_key_destroy (key_public);
   
   assert (! err);
 }
@@ -340,6 +348,8 @@
     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
 
   check_run ();
+
+  gcry_control (GCRYCTL_FINALIZE);
   
   return 0;
 }
Index: tests/hmac.c
===================================================================
--- tests/hmac.c	(Revision 1140)
+++ tests/hmac.c	(Arbeitskopie)
@@ -167,5 +167,7 @@
     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
   check_hmac ();
 
+  gcry_control (GCRYCTL_FINALIZE);
+
   return error_count ? 1 : 0;
 }
Index: tests/testapi.c
===================================================================
--- tests/testapi.c	(Revision 1140)
+++ tests/testapi.c	(Arbeitskopie)
@@ -108,5 +108,7 @@
 	return 1;
     }
 
+    gcry_control (GCRYCTL_FINALIZE);
+
     return 0;
 }
Index: tests/keygrip.c
===================================================================
--- tests/keygrip.c	(Revision 1140)
+++ tests/keygrip.c	(Arbeitskopie)
@@ -135,5 +135,7 @@
 
   check ();
 
+  gcry_control (GCRYCTL_FINALIZE);
+
   return 0;
 }
Index: tests/pkbench.c
===================================================================
--- tests/pkbench.c	(Revision 1140)
+++ tests/pkbench.c	(Arbeitskopie)
@@ -359,5 +359,7 @@
 	process_key_pair_file (argv[i]);
     }
 
+  gcry_control (GCRYCTL_FINALIZE);
+
   return EXIT_SUCCESS;
 }
Index: tests/prime.c
===================================================================
--- tests/prime.c	(Revision 1140)
+++ tests/prime.c	(Arbeitskopie)
@@ -95,6 +95,7 @@
       gcry_mpi_add_ui (prime, prime, 1);
       err = gcry_prime_check (prime, 0);
       assert (err);
+      gcry_mpi_release(prime);
     }
 }
 
@@ -118,5 +119,7 @@
 
   check_primes ();
 
+  gcry_control (GCRYCTL_FINALIZE);
+
   return 0;
 }
Index: tests/basic.c
===================================================================
--- tests/basic.c	(Revision 1140)
+++ tests/basic.c	(Arbeitskopie)
@@ -974,6 +974,8 @@
 
   get_keys_new (&pkey, &skey);
   do_check_one_pubkey (n, skey, pkey, NULL, FLAG_SIGN | FLAG_CRYPT);
+  gcry_sexp_release (pkey);
+  gcry_sexp_release (skey);
 }
 
 /* Run all tests for the public key fucntions. */
@@ -1120,5 +1122,6 @@
   check_digests ();
   check_pubkey ();
 
+  gcry_control (GCRYCTL_FINALIZE, 0);
   return error_count ? 1 : 0;
 }
Index: tests/keygen.c
===================================================================
--- tests/keygen.c	(Revision 1140)
+++ tests/keygen.c	(Arbeitskopie)
@@ -238,6 +238,8 @@
 
   check_rsa_keys ();
   check_nonce ();
+
+  gcry_control (GCRYCTL_FINALIZE);
   
   return error_count? 1:0;
 }
Index: tests/ac.c
===================================================================
--- tests/ac.c	(Revision 1140)
+++ tests/ac.c	(Arbeitskopie)
@@ -75,6 +75,8 @@
   err = gcry_ac_key_pair_generate (handle, 1024, &rsa_spec, &key_pair, NULL);
   assert (! err);
 
+  gcry_mpi_release(rsa_spec.e);
+
   key_sec = gcry_ac_key_pair_extract (key_pair, GCRY_AC_KEY_SECRET);
   key_copy (handle, GCRY_AC_KEY_SECRET, &key_sec_cp, key_sec);
 
@@ -120,6 +122,11 @@
   }
 
   gcry_ac_close (handle);
+  gcry_ac_data_destroy (data);
+  gcry_mpi_release(x2);
+  gcry_ac_key_destroy(key_sec_cp);
+  gcry_ac_key_destroy(key_pub_cp);
+  gcry_ac_key_pair_destroy(key_pair);
 }
 
 void
@@ -156,5 +163,7 @@
   for (; i > 0; i--)
     check_run ();
   
+  gcry_control (GCRYCTL_FINALIZE);
+
   return 0;
 }
Index: tests/register.c
===================================================================
--- tests/register.c	(Revision 1140)
+++ tests/register.c	(Arbeitskopie)
@@ -92,6 +92,8 @@
     if (list[i] == algorithm)
       ret = 1;
 
+  free(list);
+
   return ret;
 }
 
@@ -158,5 +160,7 @@
   for (; i > 0; i--)
     check_run ();
   
+  gcry_control (GCRYCTL_FINALIZE);
+
   return 0;
 }
Index: tests/benchmark.c
===================================================================
--- tests/benchmark.c	(Revision 1140)
+++ tests/benchmark.c	(Arbeitskopie)
@@ -424,6 +424,8 @@
       return 1;
     }
   
+  gcry_control (GCRYCTL_FINALIZE);
+
   return 0;
 }
 
Index: tests/ac-data.c
===================================================================
--- tests/ac-data.c	(Revision 1140)
+++ tests/ac-data.c	(Arbeitskopie)
@@ -174,7 +174,8 @@
  
   gcry_ac_data_destroy (data);
  
-
+  gcry_mpi_release (mpi0);
+  gcry_mpi_release (mpi2);
 }
 
 int
@@ -198,5 +199,7 @@
   for (; i > 0; i--)
     check_run ();
   
+  gcry_control (GCRYCTL_FINALIZE);
+
   return 0;
 }
Index: doc/Makefile.am
===================================================================
--- doc/Makefile.am	(Revision 1140)
+++ doc/Makefile.am	(Arbeitskopie)
@@ -22,3 +22,4 @@
 info_TEXINFOS = gcrypt.texi
 gcrypt_TEXINFOS = lgpl.texi gpl.texi
 
+gcrypt.info: version.texi
Index: cipher/pubkey.c
===================================================================
--- cipher/pubkey.c	(Revision 1140)
+++ cipher/pubkey.c	(Arbeitskopie)
@@ -2310,6 +2310,20 @@
   return err;
 }
 
+void
+_gcry_pk_finalize(void)
+{
+  if(default_pubkeys_registered)
+  {
+    ath_mutex_lock(&pubkeys_registered_lock);
+    while(pubkeys_registered)
+    {
+      _gcry_module_release(pubkeys_registered);
+    }
+    default_pubkeys_registered = 0;
+    ath_mutex_unlock(&pubkeys_registered_lock);
+  }
+}
 
 gcry_err_code_t
 _gcry_pk_module_lookup (int algorithm, gcry_module_t *module)
Index: cipher/md.c
===================================================================
--- cipher/md.c	(Revision 1140)
+++ cipher/md.c	(Arbeitskopie)
@@ -1212,6 +1212,20 @@
   return err;
 }
 
+void
+_gcry_md_finalize(void)
+{
+  if(default_digests_registered)
+  {
+    ath_mutex_lock(&digests_registered_lock);
+    while(digests_registered)
+    {
+      _gcry_module_release(digests_registered);
+    }
+    default_digests_registered = 0;
+    ath_mutex_unlock(&digests_registered_lock);
+  }
+}
 
 int
 gcry_md_is_secure (gcry_md_hd_t a) 
Index: cipher/cipher.c
===================================================================
--- cipher/cipher.c	(Revision 1140)
+++ cipher/cipher.c	(Arbeitskopie)
@@ -1380,6 +1380,21 @@
   return err;
 }
 
+void
+_gcry_cipher_finalize(void)
+{
+  if(default_ciphers_registered)
+  {
+    ath_mutex_lock(&ciphers_registered_lock);
+    while(ciphers_registered)
+    {
+      _gcry_module_release(ciphers_registered);
+    }
+    default_ciphers_registered = 0;
+    ath_mutex_unlock(&ciphers_registered_lock);
+  }
+}
+
 /* Get a list consisting of the IDs of the loaded cipher modules.  If
    LIST is zero, write the number of loaded cipher modules to
    LIST_LENGTH and return.  If LIST is non-zero, the first
Index: cipher/random.c
===================================================================
--- cipher/random.c	(Revision 1140)
+++ cipher/random.c	(Arbeitskopie)
@@ -168,10 +168,8 @@
   keypool = secure_alloc ? gcry_xcalloc_secure(1,POOLSIZE+BLOCKLEN)
                          : gcry_xcalloc(1,POOLSIZE+BLOCKLEN);
   is_initialized = 1;
-
 }
 
-
 /* Used to register a progress callback. */
 void
 _gcry_register_random_progress (void (*cb)(void *,const char*,int,int,int),
@@ -206,6 +204,17 @@
 }
 
 void
+_gcry_random_finalize(void)
+{
+  if(is_initialized)
+  {
+    gcry_free(rndpool);
+    gcry_free(keypool);
+    is_initialized = 0;
+  }
+}
+
+void
 _gcry_random_dump_stats()
 {
   /* FIXME: don't we need proper locking here? -mo */
Index: cipher/ac.c
===================================================================
--- cipher/ac.c	(Revision 1140)
+++ cipher/ac.c	(Arbeitskopie)
@@ -726,14 +726,14 @@
 
   for (i = 0; i < sexp_n; i++)
     {
-      sexp_tmp = gcry_sexp_nth (sexp_cur, i);
-      if (! sexp_tmp)
+      gcry_sexp_t sexp_tmp2 = gcry_sexp_nth (sexp_cur, i);
+      if (! sexp_tmp2)
 	{
 	  err = gcry_error (GPG_ERR_INV_SEXP);
 	  break;
 	}
 
-      data = gcry_sexp_nth_data (sexp_tmp, 0, &data_n);
+      data = gcry_sexp_nth_data (sexp_tmp2, 0, &data_n);
       string = gcry_malloc (data_n + 1);
       if (! string)
 	{
@@ -743,22 +743,24 @@
       memcpy (string, data, data_n);
       string[data_n] = 0;
 
-      mpi = gcry_sexp_nth_mpi (sexp_tmp, 1, 0);
+      mpi = gcry_sexp_nth_mpi (sexp_tmp2, 1, 0);
       if (! mpi)
 	{
 	  err = gcry_error (GPG_ERR_INV_SEXP); /* FIXME? */
 	  break;
 	}
 
-      err = gcry_ac_data_set (data_set_new, GCRY_AC_FLAG_DEALLOC, string, mpi);
+      err = gcry_ac_data_set (data_set_new, GCRY_AC_FLAG_COPY |
+                              GCRY_AC_FLAG_DEALLOC, string, mpi);
       if (err)
 	break;
 
+      gcry_free (string);
+      gcry_mpi_release (mpi);
       string = NULL;
       mpi = NULL;
 
-      gcry_sexp_release (sexp_tmp);
-      sexp_tmp = NULL;
+      gcry_sexp_release (sexp_tmp2);
     }
   if (err)
     goto out;
@@ -1180,11 +1182,14 @@
       strncpy (value_name, data_raw, data_raw_n);
       value_name[data_raw_n] = 0;
 
-      err = _gcry_ac_data_set (data_new, GCRY_AC_FLAG_DEALLOC, value_name, value_mpi);
+      err = _gcry_ac_data_set (data_new, GCRY_AC_FLAG_DEALLOC |
+                               GCRY_AC_FLAG_COPY, value_name, value_mpi);
       if (err)
 	break;
 
       gcry_sexp_release (value_sexp);
+      gcry_mpi_release (value_mpi);
+      gcry_free (value_name);
       value_sexp = NULL;
       value_name = NULL;
       value_mpi = NULL;
@@ -1480,7 +1485,7 @@
   gcry_ac_key_pair_t key_pair_new;
   gcry_ac_key_t key_secret;
   gcry_ac_key_t key_public;
-  gcry_sexp_t key_sexp;
+  gcry_sexp_t key_sexp = NULL;
   gcry_error_t err;
   char *genkey_format;
   size_t genkey_format_n;
@@ -1630,6 +1635,7 @@
   
   gcry_free (genkey_format);
   gcry_free (arg_list);
+  gcry_sexp_release (key_sexp);
   gcry_sexp_release (genkey_sexp_request);
   gcry_sexp_release (genkey_sexp_reply);
   if (err)
@@ -1693,17 +1699,10 @@
 void
 _gcry_ac_key_destroy (gcry_ac_key_t key)
 {
-  unsigned int i;
-
   if (key)
     {
       if (key->data)
-        {
-          for (i = 0; i < key->data->data_n; i++)
-            if (key->data->data[i].mpi != NULL)
-              gcry_mpi_release (key->data->data[i].mpi);
-          gcry_free (key->data);
-        }
+        gcry_ac_data_destroy (key->data);
       gcry_free (key);
     }
 }
Index: cipher/random.h
===================================================================
--- cipher/random.h	(Revision 1140)
+++ cipher/random.h	(Arbeitskopie)
@@ -23,6 +23,7 @@
 #include "types.h"
 
 void _gcry_random_initialize (int full);
+void _gcry_random_finalize(void);
 void _gcry_register_random_progress (void (*cb)(void *,const char*,int,int,int),
                                      void *cb_data );
 void _gcry_random_dump_stats(void);


More information about the Gcrypt-devel mailing list