gcry_control(GCRYCTL_INIT_SECMEM,...)

Werner Koch wk@gnupg.org
Thu, 23 Jan 2003 17:53:07 +0100


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.


Salam-Shalom,

   Werner