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