gcry_control(GCRYCTL_INIT_SECMEM,...)

Simon Josefsson jas@extundo.com
Thu, 23 Jan 2003 18:31:21 +0100


Werner Koch <wk@gnupg.org> writes:

> On Thu, 23 Jan 2003 15:14:17 +0100, Simon Josefsson said:
>
>> gcry_control() prints warnings to stderr if called multiple times,
>> which isn't always possible to avoid (consider two shared libraries
>> each using libgcrypt without knowing about each other, linked into the
>> same application).  Would disabling the error message cause any
>> problems?
>
> No.
>
> However you should never see this message because libgcrypt should
> make sure that it is initialized only once - as early as possible and
> definitely before you create another thread.  The application must
> decide whether secure memory is required or not.  If there is no need
> for it; the following code should be used:
>
>   /* Version check should be the very first gcry call because it
>      makes sure that constructor functrions are run. */
>   if (!gcry_check_version (GCRYPT_VERSION))
>     die ("version mismatch\n");
>   /* Many applications don't require secure memory, so they should
>      disable it right away.  There won't be a problem unless one makes
>      use of a feature which requires secure memoery - in that case the
>      process would abort becuase the secmem is not initialized. */
>   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
>
>   /* .. add whatever initialization you want, but better don't make calls
>         to libgcrypt from more than one thread ... */
>
>   /* Tell Libgcrypt that initialization has completed. */
>   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
>
>
> If you require secure memory, this code should be used: 
>
>   if (!gcry_check_version (GCRYPT_VERSION))
>     die ("version mismatch\n");
>   /* We don't want to see any warnings, e.g. because we have not yet
>     parsed options which might be used to suppress such warnings */
>   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
>
>   /* ... */
>
>   /* Allocate a pool of 16k secure memory.  This also drops priviliges
>      on some systems. */
>   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);
>
>   /* Tell Libgcrypt that initialization has completed. */
>   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
>
>
> This sounds a bit complicated but has the advantage that the caller
> must decide whether he wants secure memory or not - there is no
> default.
>
> It is important that this initialization is not done by a library but
> in the application.  The library might want to check for finished
> initialization using:
>
>   if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P))
>     return MYLIB_ERROR_LIBGCRYPT_NOT_INITIALIZED;
>
> or as GNUTLS does it (while still single-threaded):
>
>   if (gcry_control( GCRYCTL_ANY_INITIALIZATION_P) == 0) {
>       /* 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_INITIALIZATION_FINISHED, NULL,0);
>   }
>
>
> So the bottom line is that IMHO the message is useful.

It gets complex when 1) the library that uses libgcrypt only
optionally links with libgcrypt (compile time check) and 2) the
library using libgcrypt decides at runtime whether libgcrypt, and in
particular secure memory, is needed at all, and 3) the application
implements a network protocol where the stderr print will confuse the
implementation at the other end and cause it to drop the connection.

I'd prefer to hide these details in the library and not have libgcrypt
print anything to stdout or stderr.  The
MYLIB_ERROR_LIBGCRYPT_NOT_INITIALIZED approach is closest to working,
but it requires all applications using my library to set up autoconf
tests and code for libgcrypt, even though it might not be needed.  The
application would have to ask my library for how much secure memory it
should request as well.

Maybe introducing a GCRYCTL_DISABLE_ALREADY_INIT_SECMEM_WARN gcryctl()
flag would solve it without putting requirements on applications?

Perhaps there is another easier solution.

(I'm having a deja vu about this, perhaps it has been discussed
already.)