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