summaryrefslogtreecommitdiff
path: root/src/global.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2012-12-03 20:41:28 +0100
committerWerner Koch <wk@gnupg.org>2012-12-03 20:47:38 +0100
commit7607ab81504ce44060ed0b331d309606f5da1e75 (patch)
tree67d02c0a5e7f2de47c0d6a5fd7b9f5437e1e49b0 /src/global.c
parentf17e4d920c8a18007a98830dd13163ff19616202 (diff)
downloadlibgcrypt-7607ab81504ce44060ed0b331d309606f5da1e75.tar.gz
random: Add a RNG selection interface and system RNG wrapper.
* random/random-system.c: New. * random/Makefile.am (librandom_la_SOURCES): Add new module. * random/random.c (struct rng_types): New. (_gcry_set_preferred_rng_type, _gcry_get_rng_type): New. (_gcry_random_initialize, gcry_random_add_bytes, do_randomize) (_gcry_set_random_seed_file, _gcry_update_random_seed_file) (_gcry_fast_random_poll): Dispatch to the actual RNG. * src/gcrypt.h.in (GCRYCTL_SET_PREFERRED_RNG_TYPE): New. GCRYCTL_GET_CURRENT_RNG_TYPE): New. (gcry_rng_types): New. * src/global.c (print_config): Print the TNG type. (global_init, _gcry_vcontrol): Implement the new control codes. * doc/gcrypt.texi (Controlling the library): Document the new control codes. * tests/benchmark.c (main): Add options to test the RNG types. * tests/random.c (main): Add new options. (print_hex): Print to stderr. (progress_cb, rng_type): New. (check_rng_type_switching, check_early_rng_type_switching): New. (run_all_rng_tests): New. -- The purpose of this change is to allow applications with moderate random requirements to use the system's RNG (e.g. /dev/urandom). The type switching logic makes sure that existing applications won't be affected by this change. A library is in almost all cases not able to degrade the quality of the RNG. The definition of "degrade" comes from our own assertion of the quality/trustworthiness of the RNGs: The most trustworthy RNG is the CSPRNG which dates back to the early GnuPG days. It is quite conservative and often requires more seeding than might be justified. GCRY_RNG_TYPE_STANDARD is the default unless the process is in FIPS mode. The second trustworthy RNG is the FIPS recommended X9.81 AES based implementation. It is seeded by the system's RNG. GCRY_RNG_TYPE_FIPS is the only available RNG if running in FIPS mode. The third trustworthy RNG is a mere wrapper around the system's native RNG. Thus there is no extra step on top of what, for example, /dev/random provides. GCRY_RNG_TYPE_SYSTEM may be used by applications which would use /dev/random or /dev/urandom instead.
Diffstat (limited to 'src/global.c')
-rw-r--r--src/global.c58
1 files changed, 56 insertions, 2 deletions
diff --git a/src/global.c b/src/global.c
index 4ce869a6..f280a7b6 100644
--- a/src/global.c
+++ b/src/global.c
@@ -1,6 +1,7 @@
/* global.c - global control functions
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
- * 2004, 2005, 2006, 2008, 2011 Free Software Foundation, Inc.
+ * 2004, 2005, 2006, 2008, 2011,
+ * 2012 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
@@ -101,6 +102,9 @@ global_init (void)
return;
any_init_done = 1;
+ /* Tell the random module that we have seen an init call. */
+ _gcry_set_preferred_rng_type (0);
+
/* Initialize our portable thread/mutex wrapper. */
err = ath_init ();
if (err)
@@ -308,6 +312,21 @@ print_config ( int (*fnc)(FILE *fp, const char *format, ...), FILE *fp)
fnc (fp, "fips-mode:%c:%c:\n",
fips_mode ()? 'y':'n',
_gcry_enforced_fips_mode ()? 'y':'n' );
+ /* The currently used RNG type. */
+ {
+ const char *s;
+
+ i = _gcry_get_rng_type (0);
+ switch (i)
+ {
+ case GCRY_RNG_TYPE_STANDARD: s = "standard"; break;
+ case GCRY_RNG_TYPE_FIPS: s = "fips"; break;
+ case GCRY_RNG_TYPE_SYSTEM: s = "system"; break;
+ default: BUG ();
+ }
+ fnc (fp, "rng-type:%s:%d:\n", s, i);
+ }
+
}
@@ -328,6 +347,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
break;
case GCRYCTL_ENABLE_QUICK_RANDOM:
+ _gcry_set_preferred_rng_type (0);
_gcry_enable_quick_random_gen ();
break;
@@ -373,16 +393,19 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
break;
case GCRYCTL_DISABLE_SECMEM_WARN:
+ _gcry_set_preferred_rng_type (0);
_gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
| GCRY_SECMEM_FLAG_NO_WARNING));
break;
case GCRYCTL_SUSPEND_SECMEM_WARN:
+ _gcry_set_preferred_rng_type (0);
_gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
| GCRY_SECMEM_FLAG_SUSPEND_WARNING));
break;
case GCRYCTL_RESUME_SECMEM_WARN:
+ _gcry_set_preferred_rng_type (0);
_gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
& ~GCRY_SECMEM_FLAG_SUSPEND_WARNING));
break;
@@ -393,15 +416,18 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
break;
case GCRYCTL_SET_RANDOM_SEED_FILE:
+ _gcry_set_preferred_rng_type (0);
_gcry_set_random_seed_file (va_arg (arg_ptr, const char *));
break;
case GCRYCTL_UPDATE_RANDOM_SEED_FILE:
+ _gcry_set_preferred_rng_type (0);
if ( fips_is_operational () )
_gcry_update_random_seed_file ();
break;
case GCRYCTL_SET_VERBOSITY:
+ _gcry_set_preferred_rng_type (0);
_gcry_set_log_verbosity (va_arg (arg_ptr, int));
break;
@@ -447,12 +473,14 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
break;
case GCRYCTL_SET_THREAD_CBS:
+ _gcry_set_preferred_rng_type (0);
err = ath_install (va_arg (arg_ptr, void *));
if (!err)
global_init ();
break;
case GCRYCTL_FAST_POLL:
+ _gcry_set_preferred_rng_type (0);
/* We need to do make sure that the random pool is really
initialized so that the poll function is not a NOP. */
_gcry_random_initialize (1);
@@ -463,6 +491,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
case GCRYCTL_SET_RNDEGD_SOCKET:
#if USE_RNDEGD
+ _gcry_set_preferred_rng_type (0);
err = _gcry_rndegd_set_socket_name (va_arg (arg_ptr, const char *));
#else
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
@@ -470,12 +499,14 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
break;
case GCRYCTL_SET_RANDOM_DAEMON_SOCKET:
+ _gcry_set_preferred_rng_type (0);
_gcry_set_random_daemon_socket (va_arg (arg_ptr, const char *));
break;
case GCRYCTL_USE_RANDOM_DAEMON:
/* We need to do make sure that the random pool is really
initialized so that the poll function is not a NOP. */
+ _gcry_set_preferred_rng_type (0);
_gcry_random_initialize (1);
_gcry_use_random_daemon (!! va_arg (arg_ptr, int));
break;
@@ -487,6 +518,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
case GCRYCTL_PRINT_CONFIG:
{
FILE *fp = va_arg (arg_ptr, FILE *);
+ _gcry_set_preferred_rng_type (0);
print_config (fp?fprintf:_gcry_log_info_with_dummy_fp, fp);
}
break;
@@ -494,6 +526,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
case GCRYCTL_OPERATIONAL_P:
/* Returns true if the library is in an operational state. This
is always true for non-fips mode. */
+ _gcry_set_preferred_rng_type (0);
if (_gcry_fips_test_operational ())
err = GPG_ERR_GENERAL; /* Used as TRUE value */
break;
@@ -510,6 +543,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
the library has already been initialized into fips mode, a
selftest is triggered. It is not possible to put the libraty
into fips mode after having passed the initialization. */
+ _gcry_set_preferred_rng_type (0);
if (!any_init_done)
{
/* Not yet intialized at all. Set a flag so that we are put
@@ -602,14 +636,34 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
case GCRYCTL_SET_ENFORCED_FIPS_FLAG:
if (!any_init_done)
{
- /* Not yet intialized at all. Set the enforced fips mode flag */
+ /* Not yet initialized at all. Set the enforced fips mode flag */
+ _gcry_set_preferred_rng_type (0);
_gcry_set_enforced_fips_mode ();
}
else
err = GPG_ERR_GENERAL;
break;
+ case GCRYCTL_SET_PREFERRED_RNG_TYPE:
+ /* This may be called before gcry_check_version. */
+ {
+ int i = va_arg (arg_ptr, int);
+ /* Note that we may not pass 0 to _gcry_set_preferred_rng_type. */
+ if (i > 0)
+ _gcry_set_preferred_rng_type (i);
+ }
+ break;
+
+ case GCRYCTL_GET_CURRENT_RNG_TYPE:
+ {
+ int *ip = va_arg (arg_ptr, int*);
+ if (ip)
+ *ip = _gcry_get_rng_type (!any_init_done);
+ }
+ break;
+
default:
+ _gcry_set_preferred_rng_type (0);
/* A call to make sure that the dummy code is linked in. */
_gcry_compat_identification ();
err = GPG_ERR_INV_OP;