Use of custom memory allocators
Simon Josefsson
simon at josefsson.org
Fri Dec 5 12:04:17 CET 2008
Werner Koch <wk at gnupg.org> writes:
> On Thu, 4 Dec 2008 20:37, simon at josefsson.org said:
>
>> If I remove that code, using any application that uses the GnuTLS
>> library with some functions just dies:
>>
>> jas at mocca:~/src/gnutls/src master$ ./certtool -p
>> Generating a 2048 bit RSA private key...
>> Ohhhh jeeee: operation is not possible without initialized secure memory
>
> Right, because it is not properly initialized. We need to fix the
> application and not try to work around such problems.
Application? GnuTLS is a library. We don't want to require all
applications that use GnuTLS to call libgcrypt explicitly.
> If you don't have a need for secure memory, for example if your
> application does not use secret keys or other confidential data or it
> runs in a controlled environment where key material floating around in
> memory is not a problem, you - or weel the application - should
> initialize Libgcrypt correctly. I recently updated the manual to make
> this more clear. Here is an excerpt:
>
> | If you have to protect your keys or other information in memory
> | against being swapped out to disk and to enable an automatic overwrite
> | of used and freed memory, you need to initialize Libgcrypt this way:
> |
> | /* Version check should be the very first call because it
> | makes sure that important subsystems are intialized. */
> | if (!gcry_check_version (GCRYPT_VERSION))
> | {
> | fputs ("libgcrypt version mismatch\n", stderr);
> | exit (2);
> | }
> |
> | /* Disable secure memory. */
> | gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
> |
> | /* ... If required, other initialization goes here. */
> |
> | /* Tell Libgcrypt that initialization has completed. */
> | gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
Ok, this would argue for the following solution:
diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c
index f59a47f..2c2a91f 100644
--- a/lib/gnutls_global.c
+++ b/lib/gnutls_global.c
@@ -222,8 +222,7 @@ gnutls_global_init (void)
}
/* for gcrypt in order to be able to allocate memory */
- gcry_set_allocation_handler (gnutls_malloc, gnutls_secure_malloc,
- _gnutls_is_secure_memory, gnutls_realloc, gnutls_free);
+ gcry_control (GCRYCTL_DISABLE_SECMEM, NULL, 0);
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL, 0);
> |
> | If you have to protect your keys or other information in memory
> | against being swapped out to disk and to enable an automatic overwrite
> | of used and freed memory, you need to initialize Libgcrypt this way:
This is the exact same text as above. What is the difference between
these two modes?
> | /* Version check should be the very first call because it
> | makes sure that important subsystems are intialized. */
> | if (!gcry_check_version (GCRYPT_VERSION))
> | {
> | fputs ("libgcrypt version mismatch\n", stderr);
> | exit (2);
> | }
> |
> | /* We don't want to see any warnings, e.g. because we have not yet
> | parsed program options which might be used to suppress such
> | warnings. */
> | gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
> |
> | /* ... If required, other initialization goes here. Note that the
> | process might still be running with increased privileges and that
> | the secure memory has not been intialized. */
> |
> | /* Allocate a pool of 16k secure memory. This make the secure memory
> | available and also drops privileges where needed. */
> | gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
> |
> | /* It is now okay to let Libgcrypt complain when there was/is
> | a problem with the secure memory. */
> | gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
> |
> | /* ... If required, other initialization goes here. */
> |
> | /* Tell Libgcrypt that initialization has completed. */
> | gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
What does "increased privileges" mean? Does the application needs to be
setuid for this to work? That would also be a non-starter, we can't
require all applications using GnuTLS to be setuid.
> | It is important that these initialization steps are not done by a
> | library but by the actual application.
That seems like a non-starter for GnuTLS. If it is important for
libgcrypt that GnuTLS doesn't initialize libgcrypt, it seems we can't
really use libgcrypt in GnuTLS.
> | A library using Libgcrypt might want to check for finished
> | initialization using:
> |
> | if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P))
> | {
> | fputs ("libgcrypt has not been initialized\n", stderr);
> | abort ();
> | }
> |
> | Instead of terminating the process, the library may instead print a
> | warning and try to initialize Libgcrypt itself.
This is what GnuTLS is doing now, except it is not printing a warning.
What use is there in printing a warning?
> I am sorry that these things are a bit complicated. However I believe
> that we should better choose the safe side of things. The crypto
> library is low-level foundation code and problems there would affect a
> lot of applications. Better some applications break than applications
> requiring real security are exploitable.
The best would that things just work _and_ be secure. I don't see why
it isn't possible to reach that goal here?
/Simon
More information about the Gcrypt-devel
mailing list